1 /*
2  * COPYRIGHT (c) International Business Machines Corp. 2001-2017
3  *
4  * This program is provided under the terms of the Common Public License,
5  * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
6  * software constitutes recipient's acceptance of CPL-1.0 terms which can be
7  * found in the file LICENSE file or at
8  * https://opensource.org/licenses/cpl1.0.php
9  */
10 
11 // loadsave.c
12 //
13 // routines associated with loading/saving files
14 //
15 //
16 #define _GNU_SOURCE
17 #include <pthread.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <strings.h>
22 #include <unistd.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <sys/ipc.h>
26 #include <errno.h>
27 #include <syslog.h>
28 #include <pwd.h>
29 #include <grp.h>
30 #include "pkcs11types.h"
31 #include "defs.h"
32 #include "host_defs.h"
33 #include "h_extern.h"
34 #include "tok_spec_struct.h"
35 #include "pkcs32.h"
36 #include "sw_crypt.h"
37 #include "trace.h"
38 #include "ock_syslog.h"
39 
40 /* #include "../api/apiproto.h" */
41 
42 char *pk_dir;
43 
get_pk_dir(char * fname)44 char *get_pk_dir(char *fname)
45 {
46     struct passwd *pw = NULL;
47 
48     if (token_specific.data_store.per_user && (pw = getpwuid(getuid())) != NULL)
49         sprintf(fname, "%s/%s", pk_dir, pw->pw_name);
50     else
51         sprintf(fname, "%s", pk_dir);
52 
53     return fname;
54 }
55 
get_encryption_info_for_clear_key(CK_ULONG * p_key_len,CK_ULONG * p_block_size)56 static CK_RV get_encryption_info_for_clear_key(CK_ULONG *p_key_len,
57                                                CK_ULONG *p_block_size)
58 {
59     CK_ULONG key_len = 0L;
60     CK_ULONG block_size = 0L;
61 
62     switch (token_specific.data_store.encryption_algorithm) {
63     case CKM_DES3_CBC:
64         key_len = 3 * DES_KEY_SIZE;
65         block_size = DES_BLOCK_SIZE;
66         break;
67     case CKM_AES_CBC:
68         key_len = AES_KEY_SIZE_256;
69         block_size = AES_BLOCK_SIZE;
70         break;
71     default:
72         TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
73         return ERR_MECHANISM_INVALID;
74     }
75 
76     if (p_key_len)
77         *p_key_len = key_len;
78     if (p_block_size)
79         *p_block_size = block_size;
80 
81     return CKR_OK;
82 }
83 
get_encryption_info(CK_ULONG * p_key_len,CK_ULONG * p_block_size)84 static CK_RV get_encryption_info(CK_ULONG *p_key_len, CK_ULONG *p_block_size)
85 {
86     CK_RV rc;
87 
88     rc = get_encryption_info_for_clear_key(p_key_len, p_block_size);
89     if (rc != CKR_OK)
90         return rc;
91 
92     /* Tokens that use a secure key have a different size for key because
93      * it's just an indentifier not a real key.
94      */
95     if (is_secure_key_token()) {
96         if (p_key_len)
97             *p_key_len = token_specific.token_keysize;
98     }
99 
100     return CKR_OK;
101 }
102 
duplicate_initial_vector(const CK_BYTE * iv)103 static CK_BYTE *duplicate_initial_vector(const CK_BYTE *iv)
104 {
105     CK_ULONG block_size = 0L;
106     CK_BYTE *initial_vector = NULL;
107 
108     if (iv == NULL)
109         goto done;
110 
111     if (get_encryption_info(NULL, &block_size) != CKR_OK)
112         goto done;
113 
114     initial_vector = malloc(block_size);
115     if (initial_vector == NULL) {
116         goto done;
117     }
118     memcpy(initial_vector, iv, block_size);
119 
120 done:
121     return initial_vector;
122 }
123 
encrypt_data(STDLL_TokData_t * tokdata,CK_BYTE * key,CK_ULONG keylen,const CK_BYTE * iv,CK_BYTE * clear,CK_ULONG clear_len,CK_BYTE * cipher,CK_ULONG * p_cipher_len)124 static CK_RV encrypt_data(STDLL_TokData_t *tokdata, CK_BYTE *key,
125                           CK_ULONG keylen, const CK_BYTE *iv,
126                           CK_BYTE *clear, CK_ULONG clear_len,
127                           CK_BYTE *cipher, CK_ULONG *p_cipher_len)
128 {
129 #ifndef  CLEARTEXT
130     CK_RV rc = CKR_OK;
131     CK_BYTE *initial_vector = NULL;
132     OBJECT *keyobj = NULL;
133     CK_KEY_TYPE keyType;
134     CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
135     CK_ATTRIBUTE key_tmpl[] = {
136         {CKA_CLASS, &keyClass, sizeof(keyClass)}
137         ,
138         {CKA_KEY_TYPE, &keyType, sizeof(keyType)}
139         ,
140         {CKA_VALUE, key, keylen}
141     };
142 
143     switch (token_specific.data_store.encryption_algorithm) {
144     case CKM_DES3_CBC:
145         keyType = CKK_DES3;
146         break;
147     case CKM_AES_CBC:
148         keyType = CKK_AES;
149         break;
150     default:
151         TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
152         return ERR_MECHANISM_INVALID;
153     }
154     rc = object_create_skel(tokdata, key_tmpl, 3, MODE_CREATE,
155                             CKO_SECRET_KEY, keyType, &keyobj);
156     if (rc != CKR_OK) {
157         TRACE_DEVEL("object_create_skel failed.\n");
158         return rc;
159     }
160 
161     initial_vector = duplicate_initial_vector(iv);
162     if (initial_vector == NULL) {
163         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
164         return ERR_HOST_MEMORY;
165     }
166 
167     switch (token_specific.data_store.encryption_algorithm) {
168     case CKM_DES3_CBC:
169         rc = ckm_des3_cbc_encrypt(tokdata, clear, clear_len,
170                                   cipher, p_cipher_len, initial_vector, keyobj);
171         break;
172     case CKM_AES_CBC:
173         rc = ckm_aes_cbc_encrypt(tokdata, clear, clear_len,
174                                  cipher, p_cipher_len, initial_vector, keyobj);
175         break;
176     default:
177         TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
178         rc = ERR_MECHANISM_INVALID;
179     }
180 
181     if (initial_vector)
182         free(initial_vector);
183 
184     return rc;
185 
186 #else
187     memcpy(cipher, clear, clear_len);
188     return CKR_OK;
189 #endif
190 }
191 
encrypt_data_with_clear_key(STDLL_TokData_t * tokdata,CK_BYTE * key,CK_ULONG keylen,const CK_BYTE * iv,CK_BYTE * clear,CK_ULONG clear_len,CK_BYTE * cipher,CK_ULONG * p_cipher_len)192 static CK_RV encrypt_data_with_clear_key(STDLL_TokData_t *tokdata,
193                                          CK_BYTE *key, CK_ULONG keylen,
194                                          const CK_BYTE *iv,
195                                          CK_BYTE *clear, CK_ULONG clear_len,
196                                          CK_BYTE *cipher,
197                                          CK_ULONG *p_cipher_len)
198 {
199 #ifndef CLEARTEXT
200     CK_RV rc = CKR_OK;
201     CK_BYTE *initial_vector = NULL;
202 
203     if (!is_secure_key_token() &&
204         token_specific.data_store.encryption_algorithm != CKM_DES3_CBC) {
205         return encrypt_data(tokdata, key, keylen, iv, clear, clear_len,
206                             cipher, p_cipher_len);
207     }
208 
209     /* Fall back to a software alternative if key is secure, or
210      * if token's data store encryption algorithm is 3DES_CBC */
211     initial_vector = duplicate_initial_vector(iv);
212     if (initial_vector == NULL) {
213         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
214         return ERR_HOST_MEMORY;
215     }
216 
217     switch (token_specific.data_store.encryption_algorithm) {
218     case CKM_DES3_CBC:
219         rc = sw_des3_cbc_encrypt(clear, clear_len,
220                                  cipher, p_cipher_len, initial_vector, key);
221         break;
222     case CKM_AES_CBC:
223         rc = sw_aes_cbc_encrypt(clear, clear_len, cipher, p_cipher_len,
224                                 initial_vector, key, keylen);
225         break;
226     default:
227         TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
228         rc = ERR_MECHANISM_INVALID;
229     }
230 
231     if (initial_vector)
232         free(initial_vector);
233 
234     return rc;
235 
236 #else
237     memcpy(cipher, clear, clear_len);
238     return CKR_OK;
239 #endif
240 }
241 
decrypt_data(STDLL_TokData_t * tokdata,CK_BYTE * key,CK_ULONG keylen,const CK_BYTE * iv,CK_BYTE * cipher,CK_ULONG cipher_len,CK_BYTE * clear,CK_ULONG * p_clear_len)242 static CK_RV decrypt_data(STDLL_TokData_t *tokdata,
243                           CK_BYTE *key, CK_ULONG keylen, const CK_BYTE *iv,
244                           CK_BYTE *cipher, CK_ULONG cipher_len,
245                           CK_BYTE *clear, CK_ULONG *p_clear_len)
246 {
247 #ifndef  CLEARTEXT
248     CK_RV rc = CKR_OK;
249     CK_BYTE *initial_vector = NULL;
250     OBJECT *keyobj = NULL;
251     CK_KEY_TYPE keyType;
252     CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
253     CK_ATTRIBUTE key_tmpl[] = {
254         { CKA_CLASS, &keyClass, sizeof(keyClass) },
255         { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
256         { CKA_VALUE, key, keylen }
257     };
258 
259     switch (token_specific.data_store.encryption_algorithm) {
260     case CKM_DES3_CBC:
261         keyType = CKK_DES3;
262         break;
263     case CKM_AES_CBC:
264         keyType = CKK_AES;
265         break;
266     default:
267         TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
268         return ERR_MECHANISM_INVALID;
269     }
270     rc = object_create_skel(tokdata, key_tmpl, 3, MODE_CREATE,
271                             CKO_SECRET_KEY, keyType, &keyobj);
272     if (rc != CKR_OK) {
273         TRACE_DEVEL("object_create_skel failed.\n");
274         return rc;
275     }
276 
277     initial_vector = duplicate_initial_vector(iv);
278     if (initial_vector == NULL) {
279         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
280         return ERR_HOST_MEMORY;
281     }
282 
283     switch (token_specific.data_store.encryption_algorithm) {
284     case CKM_DES3_CBC:
285         rc = ckm_des3_cbc_decrypt(tokdata, cipher, cipher_len,
286                                   clear, p_clear_len, initial_vector, keyobj);
287         break;
288     case CKM_AES_CBC:
289         rc = ckm_aes_cbc_decrypt(tokdata, cipher, cipher_len,
290                                  clear, p_clear_len, initial_vector, keyobj);
291         break;
292     default:
293         TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
294         rc = ERR_MECHANISM_INVALID;
295     }
296 
297     if (initial_vector)
298         free(initial_vector);
299 
300     return rc;
301 
302 #else
303     memcpy(clear, cipher, cipher_len);
304     return CKR_OK;
305 #endif
306 }
307 
decrypt_data_with_clear_key(STDLL_TokData_t * tokdata,CK_BYTE * key,CK_ULONG keylen,const CK_BYTE * iv,CK_BYTE * cipher,CK_ULONG cipher_len,CK_BYTE * clear,CK_ULONG * p_clear_len)308 static CK_RV decrypt_data_with_clear_key(STDLL_TokData_t *tokdata,
309                                          CK_BYTE *key, CK_ULONG keylen,
310                                          const CK_BYTE *iv,
311                                          CK_BYTE *cipher, CK_ULONG cipher_len,
312                                          CK_BYTE *clear,
313                                          CK_ULONG *p_clear_len)
314 {
315 #ifndef CLEARTEXT
316     CK_RV rc = CKR_OK;
317     CK_BYTE *initial_vector = NULL;
318 
319     if (!is_secure_key_token() &&
320         token_specific.data_store.encryption_algorithm != CKM_DES3_CBC) {
321         return decrypt_data(tokdata, key, keylen, iv, cipher,
322                             cipher_len, clear, p_clear_len);
323     }
324 
325     /* Fall back to a software alternative if key is secure, or
326      * if token's data store encryption algorithm is 3DES_CBC */
327     initial_vector = duplicate_initial_vector(iv);
328     if (initial_vector == NULL) {
329         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
330         return ERR_HOST_MEMORY;
331     }
332 
333     switch (token_specific.data_store.encryption_algorithm) {
334     case CKM_DES3_CBC:
335         rc = sw_des3_cbc_decrypt(cipher, cipher_len, clear, p_clear_len,
336                                  initial_vector, key);
337         break;
338     case CKM_AES_CBC:
339         rc = sw_aes_cbc_decrypt(cipher, cipher_len, clear, p_clear_len,
340                                  initial_vector, key, keylen);
341         break;
342     default:
343         TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
344         rc = ERR_MECHANISM_INVALID;
345     }
346 
347     if (initial_vector)
348         free(initial_vector);
349 
350     return rc;
351 
352 #else
353     memcpy(clear, cipher, cipher_len);
354     return CKR_OK;
355 #endif
356 }
357 
set_perm(int file)358 void set_perm(int file)
359 {
360     struct group *grp;
361 
362     if (token_specific.data_store.per_user) {
363         /* In the TPM token, with per user data stores, we don't share
364          * the token object amongst a group. In fact, we want to
365          * restrict access to a single user */
366         fchmod(file, S_IRUSR | S_IWUSR);
367     } else {
368         // Set absolute permissions or rw-rw----
369         fchmod(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
370 
371         grp = getgrnam(PKCS11GROUP);       // Obtain the group id
372         if (grp) {
373             // set ownership to root, and pkcs11 group
374             if (fchown(file, getuid(), grp->gr_gid) != 0) {
375                 goto error;
376             }
377         } else {
378             goto error;
379         }
380     }
381 
382     return;
383 
384 error:
385     TRACE_DEVEL("Unable to set permissions on file.\n");
386 }
387 
388 //
389 //
load_token_data(STDLL_TokData_t * tokdata,CK_SLOT_ID slot_id)390 CK_RV load_token_data(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id)
391 {
392     FILE *fp = NULL;
393     char fname[PATH_MAX];
394     TOKEN_DATA td;
395     CK_RV rc;
396 
397     rc = XProcLock(tokdata);
398     if (rc != CKR_OK) {
399         TRACE_ERROR("Failed to get Process Lock.\n");
400         goto out_nolock;
401     }
402 
403     sprintf(fname, "%s/%s", tokdata->data_store, PK_LITE_NV);
404     fp = fopen(fname, "r");
405     if (!fp) {
406         /* Better error checking added */
407         if (errno == ENOENT) {
408             /* init_token_data may call save_token_data, which
409              * grabs the lock, so we must release it around this
410              * call */
411             rc = XProcUnLock(tokdata);
412             if (rc != CKR_OK) {
413                 TRACE_ERROR("Failed to release Process Lock.\n");
414                 goto out_nolock;
415             }
416 
417             init_token_data(tokdata, slot_id);
418 
419             rc = XProcLock(tokdata);
420             if (rc != CKR_OK) {
421                 TRACE_ERROR("Failed to get Process Lock.\n");
422                 goto out_nolock;
423             }
424 
425             fp = fopen(fname, "r");
426             if (!fp) {
427                 // were really hosed here since the created
428                 // did not occur
429                 TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
430                 rc = CKR_FUNCTION_FAILED;
431                 goto out_unlock;
432             }
433         } else {
434             /* Could not open file for some unknown reason */
435             TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
436             rc = CKR_FUNCTION_FAILED;
437             goto out_unlock;
438         }
439     }
440     set_perm(fileno(fp));
441 
442     /* Load generic token data */
443     if (!fread(&td, sizeof(TOKEN_DATA), 1, fp)) {
444         TRACE_ERROR("fread(%s): %s\n", fname,
445                     ferror(fp) ? strerror(errno) : "failed");
446         rc = CKR_FUNCTION_FAILED;
447         goto out_unlock;
448     }
449     memcpy(tokdata->nv_token_data, &td, sizeof(TOKEN_DATA));
450 
451     /* Load token-specific data */
452     if (token_specific.t_load_token_data) {
453         rc = token_specific.t_load_token_data(tokdata, slot_id, fp);
454         if (rc)
455             goto out_unlock;
456     }
457 
458     rc = CKR_OK;
459 
460 out_unlock:
461     if (fp)
462         fclose(fp);
463 
464     if (rc == CKR_OK) {
465         rc = XProcUnLock(tokdata);
466         if (rc != CKR_OK)
467             TRACE_ERROR("Failed to release Process Lock.\n");
468     } else {
469         /* return error that occurred first */
470         XProcUnLock(tokdata);
471     }
472 
473 out_nolock:
474     return rc;
475 }
476 
477 //
478 //
save_token_data(STDLL_TokData_t * tokdata,CK_SLOT_ID slot_id)479 CK_RV save_token_data(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id)
480 {
481     FILE *fp = NULL;
482     TOKEN_DATA td;
483     CK_RV rc;
484     char fname[PATH_MAX];
485 
486     rc = XProcLock(tokdata);
487     if (rc != CKR_OK) {
488         TRACE_ERROR("Failed to get Process Lock.\n");
489         goto out_nolock;
490     }
491 
492     sprintf(fname, "%s/%s", tokdata->data_store, PK_LITE_NV);
493     fp = fopen(fname, "w");
494     if (!fp) {
495         TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
496         rc = CKR_FUNCTION_FAILED;
497         goto done;
498     }
499     set_perm(fileno(fp));
500 
501     /* Write generic token data */
502     memcpy(&td, tokdata->nv_token_data, sizeof(TOKEN_DATA));
503     if (!fwrite(&td, sizeof(TOKEN_DATA), 1, fp)) {
504         TRACE_ERROR("fwrite(%s): %s\n", fname,
505                     ferror(fp) ? strerror(errno) : "failed");
506         rc = CKR_FUNCTION_FAILED;
507         goto done;
508     }
509 
510     /* Write token-specific data */
511     if (token_specific.t_save_token_data) {
512         rc = token_specific.t_save_token_data(tokdata, slot_id, fp);
513         if (rc)
514             goto done;
515     }
516 
517     rc = CKR_OK;
518 
519 done:
520     if (fp)
521         fclose(fp);
522 
523     if (rc == CKR_OK) {
524         rc = XProcUnLock(tokdata);
525         if (rc != CKR_OK)
526             TRACE_ERROR("Failed to release Process Lock.\n");
527     } else {
528         /* return error that occurred first */
529         XProcUnLock(tokdata);
530     }
531 
532 out_nolock:
533     return rc;
534 }
535 
536 //
537 // Note: The token lock (XProcLock) must be held when calling this function.
538 //
save_token_object(STDLL_TokData_t * tokdata,OBJECT * obj)539 CK_RV save_token_object(STDLL_TokData_t *tokdata, OBJECT *obj)
540 {
541     FILE *fp = NULL;
542     char line[256];
543     char fname[PATH_MAX];
544     CK_RV rc;
545 
546     if (object_is_private(obj) == TRUE)
547         rc = save_private_token_object(tokdata, obj);
548     else
549         rc = save_public_token_object(tokdata, obj);
550 
551     if (rc != CKR_OK)
552         return rc;
553 
554     // update the index file if it exists
555     sprintf(fname, "%s/%s/%s", tokdata->data_store, PK_LITE_OBJ_DIR,
556             PK_LITE_OBJ_IDX);
557     fp = fopen(fname, "r");
558     if (fp) {
559         set_perm(fileno(fp));
560         while (fgets(line, 50, fp)) {
561             line[strlen(line) - 1] = 0;
562             if (strcmp(line, (char *)obj->name) == 0) {
563                 fclose(fp);
564                 // object is already in the list
565                 return CKR_OK;
566             }
567         }
568         fclose(fp);
569     }
570     // we didn't find it...either the index file doesn't exist or this
571     // is a new object...
572     //
573     fp = fopen(fname, "a");
574     if (!fp) {
575         TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
576         return CKR_FUNCTION_FAILED;
577     }
578 
579     set_perm(fileno(fp));
580     fprintf(fp, "%s\n", obj->name);
581     fclose(fp);
582 
583     return CKR_OK;
584 }
585 
586 // this is the same as the old version.  public token objects are stored in the
587 // clear
588 // Note: The token lock (XProcLock) must be held when calling this function.
589 //
save_public_token_object(STDLL_TokData_t * tokdata,OBJECT * obj)590 CK_RV save_public_token_object(STDLL_TokData_t *tokdata, OBJECT * obj)
591 {
592     FILE *fp = NULL;
593     CK_BYTE *clear = NULL;
594     char fname[PATH_MAX];
595     CK_ULONG clear_len;
596     CK_BBOOL flag = FALSE;
597     CK_RV rc;
598     CK_ULONG_32 total_len;
599     rc = object_flatten(obj, &clear, &clear_len);
600     if (rc != CKR_OK) {
601         goto error;
602     }
603 
604     sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR);
605     strncat(fname, (char *) obj->name, 8);
606     fp = fopen(fname, "w");
607     if (!fp) {
608         TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
609         rc = CKR_FUNCTION_FAILED;
610         goto error;
611     }
612 
613     set_perm(fileno(fp));
614 
615     total_len = clear_len + sizeof(CK_ULONG_32) + sizeof(CK_BBOOL);
616 
617     (void) fwrite(&total_len, sizeof(CK_ULONG_32), 1, fp);
618     (void) fwrite(&flag, sizeof(CK_BBOOL), 1, fp);
619     (void) fwrite(clear, clear_len, 1, fp);
620 
621     fclose(fp);
622     free(clear);
623 
624     return CKR_OK;
625 
626 error:
627     if (fp)
628         fclose(fp);
629     if (clear)
630         free(clear);
631 
632     return rc;
633 }
634 
635 //
636 // Note: The token lock (XProcLock) must be held when calling this function.
637 //
save_private_token_object(STDLL_TokData_t * tokdata,OBJECT * obj)638 CK_RV save_private_token_object(STDLL_TokData_t *tokdata, OBJECT *obj)
639 {
640     FILE *fp = NULL;
641     CK_BYTE *obj_data = NULL;
642     CK_BYTE *clear = NULL;
643     CK_BYTE *cipher = NULL;
644     CK_BYTE *ptr = NULL;
645     char fname[PATH_MAX];
646     CK_BYTE hash_sha[SHA1_HASH_SIZE];
647     CK_BYTE *key = NULL;
648     CK_ULONG key_len = 0L;
649     CK_ULONG block_size = 0L;
650     CK_ULONG obj_data_len, clear_len, cipher_len;
651     CK_ULONG padded_len;
652     CK_BBOOL flag;
653     CK_RV rc;
654     CK_ULONG_32 obj_data_len_32;
655     CK_ULONG_32 total_len;
656 
657     rc = object_flatten(obj, &obj_data, &obj_data_len);
658     obj_data_len_32 = obj_data_len;
659     if (rc != CKR_OK) {
660         goto error;
661     }
662     //
663     // format for the object file:
664     //    private flag
665     //    ---- begin encrypted part        <--+
666     //       length of object data            |
667     //       object data                      +---- sensitive part
668     //       SHA of (object data)             |
669     //    ---- end encrypted part          <--+
670     //
671     compute_sha1(tokdata, obj_data, obj_data_len, hash_sha);
672 
673     // encrypt the sensitive object data.  need to be careful.
674     // if I use the normal high-level encryption routines I'll need to
675     // create a tepmorary key object containing the master key, perform the
676     // encryption, then destroy the key object.  There is a race condition
677     // here if the application is multithreaded (if a thread-switch occurs,
678     // the other application thread could do a FindObject and be able to
679     // access the master key object.
680     //
681     // So I have to use the low-level encryption routines.
682     //
683 
684     if ((rc = get_encryption_info(&key_len, &block_size)) != CKR_OK)
685         goto error;
686 
687     // Duplicate key
688     key = malloc(key_len);
689     if (!key)
690         goto oom_error;
691     memcpy(key, tokdata->master_key, key_len);
692 
693 
694     clear_len = sizeof(CK_ULONG_32) + obj_data_len_32 + SHA1_HASH_SIZE;
695     cipher_len = padded_len = block_size * (clear_len / block_size + 1);
696 
697     clear = malloc(padded_len);
698     cipher = malloc(padded_len);
699     if (!clear || !cipher)
700         goto oom_error;
701 
702     // Build data that will be encrypted
703     ptr = clear;
704     memcpy(ptr, &obj_data_len_32, sizeof(CK_ULONG_32));
705     ptr += sizeof(CK_ULONG_32);
706     memcpy(ptr, obj_data, obj_data_len_32);
707     ptr += obj_data_len_32;
708     memcpy(ptr, hash_sha, SHA1_HASH_SIZE);
709 
710     add_pkcs_padding(clear + clear_len, block_size, clear_len, padded_len);
711 
712     rc = encrypt_data_with_clear_key(tokdata, key, key_len,
713                                      token_specific.data_store.
714                                      obj_initial_vector, clear, padded_len,
715                                      cipher, &cipher_len);
716     if (rc != CKR_OK) {
717         goto error;
718     }
719 
720     sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR);
721     strncat(fname, (char *) obj->name, 8);
722     fp = fopen(fname, "w");
723     if (!fp) {
724         TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
725         rc = CKR_FUNCTION_FAILED;
726         goto error;
727     }
728 
729     set_perm(fileno(fp));
730 
731     total_len = sizeof(CK_ULONG_32) + sizeof(CK_BBOOL) + cipher_len;
732 
733     flag = TRUE;
734 
735     (void) fwrite(&total_len, sizeof(CK_ULONG_32), 1, fp);
736     (void) fwrite(&flag, sizeof(CK_BBOOL), 1, fp);
737     (void) fwrite(cipher, cipher_len, 1, fp);
738 
739     fclose(fp);
740     free(obj_data);
741     free(clear);
742     free(cipher);
743     free(key);
744 
745     return CKR_OK;
746 
747 oom_error:
748     rc = CKR_HOST_MEMORY;
749 
750 error:
751     if (fp)
752         fclose(fp);
753     if (obj_data)
754         free(obj_data);
755     if (clear)
756         free(clear);
757     if (cipher)
758         free(cipher);
759     if (key)
760         free(key);
761 
762     return rc;
763 }
764 
765 //
766 // Note: The token lock (XProcLock) must be held when calling this function.
767 //
load_public_token_objects(STDLL_TokData_t * tokdata)768 CK_RV load_public_token_objects(STDLL_TokData_t *tokdata)
769 {
770     FILE *fp1 = NULL, *fp2 = NULL;
771     CK_BYTE *buf = NULL;
772     char tmp[PATH_MAX];
773     char iname[PATH_MAX];
774     char fname[PATH_MAX];
775     CK_BBOOL priv;
776     CK_ULONG_32 size;
777     size_t read_size;
778 
779     sprintf(iname, "%s/%s/%s", tokdata->data_store, PK_LITE_OBJ_DIR,
780             PK_LITE_OBJ_IDX);
781 
782     fp1 = fopen(iname, "r");
783     if (!fp1)
784         return CKR_OK;          // no token objects
785 
786     while (fgets(tmp, 50, fp1)) {
787         tmp[strlen(tmp) - 1] = 0;
788 
789         sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR);
790         strcat(fname, tmp);
791 
792         fp2 = fopen(fname, "r");
793         if (!fp2)
794             continue;
795 
796         if (!fread(&size, sizeof(CK_ULONG_32), 1, fp2)) {
797             fclose(fp2);
798             OCK_SYSLOG(LOG_ERR, "Cannot read size\n");
799             continue;
800         }
801         if (!fread(&priv, sizeof(CK_BBOOL), 1, fp2)) {
802             fclose(fp2);
803             OCK_SYSLOG(LOG_ERR, "Cannot read boolean\n");
804             continue;
805         }
806         if (priv == TRUE) {
807             fclose(fp2);
808             continue;
809         }
810         // size--;
811         size = size - sizeof(CK_ULONG_32) - sizeof(CK_BBOOL);
812         buf = (CK_BYTE *) malloc(size);
813         if (!buf) {
814             fclose(fp2);
815             OCK_SYSLOG(LOG_ERR,
816                        "Cannot malloc %u bytes to read in "
817                        "token object %s (ignoring it)", size, fname);
818             continue;
819         }
820 
821         read_size = fread(buf, 1, size, fp2);
822         if (read_size != size) {
823             fclose(fp2);
824             free(buf);
825             OCK_SYSLOG(LOG_ERR,
826                        "Cannot read token object %s " "(ignoring it)", fname);
827             continue;
828         }
829         // ... grab object mutex here.
830         if (object_mgr_restore_obj_withSize(tokdata,
831                                             buf, NULL, size) != CKR_OK) {
832             OCK_SYSLOG(LOG_ERR,
833                        "Cannot restore token object %s "
834                        "(ignoring it)", fname);
835         }
836         free(buf);
837         fclose(fp2);
838     }
839 
840     fclose(fp1);
841 
842     return CKR_OK;
843 }
844 
845 //
846 // Note: The token lock (XProcLock) must be held when calling this function.
847 //
load_private_token_objects(STDLL_TokData_t * tokdata)848 CK_RV load_private_token_objects(STDLL_TokData_t *tokdata)
849 {
850     FILE *fp1 = NULL, *fp2 = NULL;
851     CK_BYTE *buf = NULL;
852     char tmp[PATH_MAX];
853     char iname[PATH_MAX];
854     char fname[PATH_MAX];
855     CK_BBOOL priv;
856     CK_ULONG_32 size;
857     CK_RV rc;
858     size_t read_size;
859 
860     sprintf(iname, "%s/%s/%s", tokdata->data_store, PK_LITE_OBJ_DIR,
861             PK_LITE_OBJ_IDX);
862 
863     fp1 = fopen(iname, "r");
864     if (!fp1)
865         return CKR_OK;          // no token objects
866 
867     while (fgets(tmp, 50, fp1)) {
868         tmp[strlen(tmp) - 1] = 0;
869 
870         sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR);
871         strcat(fname, tmp);
872 
873         fp2 = fopen(fname, "r");
874         if (!fp2)
875             continue;
876 
877         if (!fread(&size, sizeof(CK_ULONG_32), 1, fp2)) {
878             fclose(fp2);
879             OCK_SYSLOG(LOG_ERR, "Cannot read size\n");
880             continue;
881         }
882         if (!fread(&priv, sizeof(CK_BBOOL), 1, fp2)) {
883             fclose(fp2);
884             OCK_SYSLOG(LOG_ERR, "Cannot read boolean\n");
885             continue;
886         }
887         if (priv == FALSE) {
888             fclose(fp2);
889             continue;
890         }
891         //size--;
892         size = size - sizeof(CK_ULONG_32) - sizeof(CK_BBOOL);
893         buf = (CK_BYTE *) malloc(size);
894         if (!buf) {
895             fclose(fp2);
896             OCK_SYSLOG(LOG_ERR,
897                        "Cannot malloc %u bytes to read in "
898                        "token object %s (ignoring it)", size, fname);
899             continue;
900         }
901 
902         read_size = fread(buf, 1, size, fp2);
903         if (read_size != size) {
904             free(buf);
905             fclose(fp2);
906             OCK_SYSLOG(LOG_ERR,
907                        "Cannot read token object %s " "(ignoring it)", fname);
908             continue;
909         }
910         // Grab object list  mutex
911         MY_LockMutex(&obj_list_mutex);
912         rc = restore_private_token_object(tokdata, buf, size, NULL);
913         MY_UnlockMutex(&obj_list_mutex);
914         if (rc != CKR_OK)
915             goto error;
916 
917         free(buf);
918         fclose(fp2);
919     }
920 
921     fclose(fp1);
922 
923     return CKR_OK;
924 
925 error:
926     if (buf)
927         free(buf);
928     if (fp1)
929         fclose(fp1);
930     if (fp2)
931         fclose(fp2);
932 
933     return rc;
934 }
935 
936 //
937 //
restore_private_token_object(STDLL_TokData_t * tokdata,CK_BYTE * data,CK_ULONG len,OBJECT * pObj)938 CK_RV restore_private_token_object(STDLL_TokData_t *tokdata, CK_BYTE *data,
939                                    CK_ULONG len, OBJECT *pObj)
940 {
941     CK_BYTE *clear = NULL;
942     CK_BYTE *obj_data = NULL;
943     CK_BYTE *ptr = NULL;
944     CK_BYTE *key = NULL;
945     CK_ULONG key_len;
946     CK_ULONG block_size;
947     CK_BYTE hash_sha[SHA1_HASH_SIZE];
948     CK_ULONG clear_len, obj_data_len;
949     CK_RV rc;
950 
951     // format for the object data:
952     //    (private flag has already been read at this point)
953     //    ---- begin encrypted part
954     //       length of object data
955     //       object data
956     //       SHA of object data
957     //    ---- end encrypted part
958     //
959 
960     clear_len = len;
961 
962     clear = (CK_BYTE *) malloc(len);
963     if (!clear) {
964         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
965         rc = CKR_HOST_MEMORY;
966         goto done;
967     }
968 
969     if ((rc = get_encryption_info(&key_len, &block_size)) != CKR_OK)
970         goto done;
971 
972     // decrypt the encrypted chunk
973     key = malloc(key_len);
974     if (!key) {
975         rc = ERR_HOST_MEMORY;
976         goto done;
977     }
978     memcpy(key, tokdata->master_key, key_len);
979 
980     rc = decrypt_data_with_clear_key(tokdata, key, key_len,
981                                      token_specific.data_store.
982                                      obj_initial_vector, data, len, clear,
983                                      &clear_len);
984     if (rc != CKR_OK) {
985         goto done;
986     }
987 
988     rc = strip_pkcs_padding(clear, len, &clear_len);
989 
990     // if the padding extraction didn't work it means the object was
991     // tampered with or the key was incorrect
992     //
993     if (rc != CKR_OK || (clear_len > len)) {
994         TRACE_DEVEL("strip_pkcs_padding failed.\n");
995         rc = CKR_FUNCTION_FAILED;
996         goto done;
997     }
998 
999     ptr = clear;
1000 
1001     obj_data_len = *(CK_ULONG_32 *) ptr;
1002 
1003     // prevent buffer overflow in sha_update
1004     if (obj_data_len > clear_len) {
1005         TRACE_ERROR("stripped length is greater than clear length\n");
1006         rc = CKR_FUNCTION_FAILED;
1007         goto done;
1008     }
1009 
1010     ptr += sizeof(CK_ULONG_32);
1011     obj_data = ptr;
1012 
1013     // check the hash
1014     //
1015     rc = compute_sha1(tokdata, ptr, obj_data_len, hash_sha);
1016     if (rc != CKR_OK) {
1017         goto done;
1018     }
1019     ptr += obj_data_len;
1020 
1021     if (memcmp(ptr, hash_sha, SHA1_HASH_SIZE) != 0) {
1022         TRACE_ERROR("stored hash does not match restored data hash.\n");
1023         rc = CKR_FUNCTION_FAILED;
1024         goto done;
1025     }
1026     // okay.  at this point, we're satisfied that nobody has tampered with
1027     // the token object...
1028     //
1029 
1030     rc = object_mgr_restore_obj(tokdata, obj_data, pObj);
1031     if (rc != CKR_OK) {
1032         goto done;
1033     }
1034     rc = CKR_OK;
1035 
1036 done:
1037     if (clear)
1038         free(clear);
1039     if (key)
1040         free(key);
1041 
1042     return rc;
1043 }
1044 
1045 //
1046 //
load_masterkey_so(STDLL_TokData_t * tokdata)1047 CK_RV load_masterkey_so(STDLL_TokData_t *tokdata)
1048 {
1049     FILE *fp = NULL;
1050     CK_BYTE hash_sha[SHA1_HASH_SIZE];
1051     CK_BYTE *cipher = NULL;
1052     CK_BYTE *clear = NULL;
1053     CK_BYTE *key = NULL;
1054     CK_ULONG data_len;
1055     CK_ULONG cipher_len, clear_len;
1056     CK_RV rc;
1057     char fname[PATH_MAX];
1058     CK_ULONG key_len = 0L;
1059     CK_ULONG master_key_len = 0L;
1060     CK_ULONG block_size = 0L;
1061 
1062     if ((rc = get_encryption_info_for_clear_key(&key_len,
1063                                                 &block_size)) != CKR_OK)
1064         goto done;
1065 
1066     if ((rc = get_encryption_info(&master_key_len, NULL)) != CKR_OK)
1067         goto done;
1068 
1069     memset(tokdata->master_key, 0x0, master_key_len);
1070 
1071     data_len = master_key_len + SHA1_HASH_SIZE;
1072     clear_len = cipher_len = (data_len + block_size - 1)
1073         & ~(block_size - 1);
1074 
1075     key = malloc(key_len);
1076     cipher = malloc(cipher_len);
1077     clear = malloc(clear_len);
1078     if (key == NULL || cipher == NULL || clear == NULL) {
1079         rc = ERR_HOST_MEMORY;
1080         goto done;
1081     }
1082     // this file gets created on C_InitToken so we can assume that it always
1083     // exists
1084     //
1085     sprintf(fname, "%s/MK_SO", tokdata->data_store);
1086     fp = fopen(fname, "r");
1087     if (!fp) {
1088         TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
1089         rc = CKR_FUNCTION_FAILED;
1090         goto done;
1091     }
1092     set_perm(fileno(fp));
1093 
1094     rc = fread(cipher, cipher_len, 1, fp);
1095     if (rc != 1) {
1096         TRACE_ERROR("fread() failed.\n");
1097         rc = CKR_FUNCTION_FAILED;
1098         goto done;
1099     }
1100     // decrypt the master key data using the MD5 of the SO key
1101     // (we can't use the SHA of the SO key since the SHA of the key is
1102     // stored in the token data file).
1103     memcpy(key, tokdata->so_pin_md5, MD5_HASH_SIZE);
1104     memcpy(key + MD5_HASH_SIZE, tokdata->so_pin_md5, key_len - MD5_HASH_SIZE);
1105 
1106     rc = decrypt_data_with_clear_key(tokdata, key, key_len,
1107                                      token_specific.data_store.
1108                                      pin_initial_vector, cipher, cipher_len,
1109                                      clear, &clear_len);
1110     if (rc != CKR_OK) {
1111         TRACE_DEVEL("decrypt_data_with_clear_key failed.\n");
1112         goto done;
1113     }
1114     //
1115     // technically should strip PKCS padding here but since I already know
1116     // what the length should be, I don't bother.
1117     //
1118 
1119     // compare the hashes
1120     //
1121     rc = compute_sha1(tokdata, clear, master_key_len, hash_sha);
1122     if (rc != CKR_OK) {
1123         goto done;
1124     }
1125 
1126     if (memcmp(hash_sha, clear + master_key_len, SHA1_HASH_SIZE) != 0) {
1127         TRACE_ERROR("masterkey hashes do not match\n");
1128         rc = CKR_FUNCTION_FAILED;
1129         goto done;
1130     }
1131 
1132     memcpy(tokdata->master_key, clear, master_key_len);
1133     rc = CKR_OK;
1134 
1135 done:
1136     if (fp)
1137         fclose(fp);
1138     if (clear)
1139         free(clear);
1140     if (cipher)
1141         free(cipher);
1142     if (key)
1143         free(key);
1144 
1145     return rc;
1146 }
1147 
1148 //
1149 //
load_masterkey_user(STDLL_TokData_t * tokdata)1150 CK_RV load_masterkey_user(STDLL_TokData_t *tokdata)
1151 {
1152     FILE *fp = NULL;
1153     CK_BYTE hash_sha[SHA1_HASH_SIZE];
1154     CK_BYTE *cipher = NULL;
1155     CK_BYTE *clear = NULL;
1156     CK_BYTE *key = NULL;
1157     CK_ULONG data_len;
1158     CK_ULONG cipher_len, clear_len;
1159     CK_RV rc;
1160     char fname[PATH_MAX];
1161     CK_ULONG key_len = 0L;
1162     CK_ULONG master_key_len = 0L;
1163     CK_ULONG block_size = 0L;
1164 
1165     if ((rc =
1166          get_encryption_info_for_clear_key(&key_len, &block_size)) != CKR_OK)
1167         goto done;
1168 
1169     if ((rc = get_encryption_info(&master_key_len, NULL)) != CKR_OK)
1170         goto done;
1171 
1172     memset(tokdata->master_key, 0x0, master_key_len);
1173 
1174     data_len = master_key_len + SHA1_HASH_SIZE;
1175     clear_len = cipher_len = (data_len + block_size - 1)
1176         & ~(block_size - 1);
1177 
1178     key = malloc(key_len);
1179     cipher = malloc(cipher_len);
1180     clear = malloc(clear_len);
1181     if (key == NULL || cipher == NULL || clear == NULL) {
1182         rc = ERR_HOST_MEMORY;
1183         goto done;
1184     }
1185     // this file gets created on C_InitToken so we can assume that it always
1186     // exists
1187     //
1188     sprintf(fname, "%s/MK_USER", tokdata->data_store);
1189     fp = fopen(fname, "r");
1190     if (!fp) {
1191         TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
1192         rc = CKR_FUNCTION_FAILED;
1193         goto done;
1194     }
1195     set_perm(fileno(fp));
1196 
1197     rc = fread(cipher, cipher_len, 1, fp);
1198     if (rc != 1) {
1199         TRACE_ERROR("fread failed.\n");
1200         rc = CKR_FUNCTION_FAILED;
1201         goto done;
1202     }
1203     // decrypt the master key data using the MD5 of the SO key
1204     // (we can't use the SHA of the SO key since the SHA of the key is
1205     // stored in the token data file).
1206     memcpy(key, tokdata->user_pin_md5, MD5_HASH_SIZE);
1207     memcpy(key + MD5_HASH_SIZE, tokdata->user_pin_md5, key_len - MD5_HASH_SIZE);
1208 
1209     rc = decrypt_data_with_clear_key(tokdata, key, key_len,
1210                                      token_specific.data_store.
1211                                      pin_initial_vector, cipher, cipher_len,
1212                                      clear, &clear_len);
1213     if (rc != CKR_OK) {
1214         TRACE_DEVEL("decrypt_data_with_clear_key failed.\n");
1215         goto done;
1216     }
1217     //
1218     // technically should strip PKCS padding here but since I already know
1219     // what the length should be, I don't bother.
1220     //
1221 
1222     // compare the hashes
1223     //
1224     rc = compute_sha1(tokdata, clear, master_key_len, hash_sha);
1225     if (rc != CKR_OK) {
1226         goto done;
1227     }
1228 
1229     if (memcmp(hash_sha, clear + master_key_len, SHA1_HASH_SIZE) != 0) {
1230         TRACE_ERROR("User's masterkey hashes do not match.\n");
1231         rc = CKR_FUNCTION_FAILED;
1232         goto done;
1233     }
1234 
1235     memcpy(tokdata->master_key, clear, master_key_len);
1236     rc = CKR_OK;
1237 
1238 done:
1239     if (fp)
1240         fclose(fp);
1241     if (key)
1242         free(key);
1243     if (clear)
1244         free(clear);
1245     if (cipher)
1246         free(cipher);
1247 
1248     return rc;
1249 }
1250 
1251 //
1252 //
save_masterkey_so(STDLL_TokData_t * tokdata)1253 CK_RV save_masterkey_so(STDLL_TokData_t *tokdata)
1254 {
1255     FILE *fp = NULL;
1256     CK_BYTE *clear = NULL;
1257     CK_ULONG clear_len = 0L;
1258     CK_BYTE *cipher = NULL;
1259     CK_ULONG cipher_len = 0L;
1260     CK_BYTE *key = NULL;
1261     CK_ULONG key_len = 0L;
1262     CK_ULONG master_key_len = 0L;
1263     CK_ULONG block_size = 0L;
1264     CK_ULONG data_len = 0L;
1265     char fname[PATH_MAX];
1266     CK_RV rc;
1267 
1268     /* Skip it if master key is not needed. */
1269     if (!token_specific.data_store.use_master_key)
1270         return CKR_OK;
1271 
1272     if ((rc = get_encryption_info_for_clear_key(&key_len,
1273                                                 &block_size)) != CKR_OK)
1274         goto done;
1275 
1276     if ((rc = get_encryption_info(&master_key_len, NULL)) != CKR_OK)
1277         goto done;
1278 
1279     data_len = master_key_len + SHA1_HASH_SIZE;
1280     cipher_len = clear_len = block_size * (data_len / block_size + 1);
1281 
1282     key = malloc(key_len);
1283     clear = malloc(clear_len);
1284     cipher = malloc(cipher_len);
1285     if (key == NULL || clear == NULL || cipher == NULL) {
1286         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
1287         rc = ERR_HOST_MEMORY;
1288         goto done;
1289     }
1290     // Copy data to buffer (key+hash)
1291     memcpy(clear, tokdata->master_key, master_key_len);
1292     if ((rc = compute_sha1(tokdata, tokdata->master_key,
1293                            master_key_len, clear + master_key_len)) != CKR_OK)
1294         goto done;
1295     add_pkcs_padding(clear + data_len, block_size, data_len, clear_len);
1296 
1297     // encrypt the key data
1298     memcpy(key, tokdata->so_pin_md5, MD5_HASH_SIZE);
1299     memcpy(key + MD5_HASH_SIZE, tokdata->so_pin_md5, key_len - MD5_HASH_SIZE);
1300 
1301     rc = encrypt_data_with_clear_key(tokdata, key, key_len,
1302                                      token_specific.data_store.
1303                                      pin_initial_vector, clear, clear_len,
1304                                      cipher, &cipher_len);
1305     if (rc != CKR_OK) {
1306         goto done;
1307     }
1308     // write the file
1309     //
1310     // probably ought to ensure the permissions are correct
1311     //
1312     sprintf(fname, "%s/MK_SO", tokdata->data_store);
1313     fp = fopen(fname, "w");
1314     if (!fp) {
1315         TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
1316         rc = CKR_FUNCTION_FAILED;
1317         goto done;
1318     }
1319     set_perm(fileno(fp));
1320 
1321     rc = fwrite(cipher, cipher_len, 1, fp);
1322     if (rc != 1) {
1323         TRACE_ERROR("fwrite failed.\n");
1324         rc = CKR_FUNCTION_FAILED;
1325         goto done;
1326     }
1327 
1328     rc = CKR_OK;
1329 
1330 done:
1331     if (fp)
1332         fclose(fp);
1333     if (key)
1334         free(key);
1335     if (clear)
1336         free(clear);
1337     if (cipher)
1338         free(cipher);
1339 
1340     return rc;
1341 }
1342 
1343 //
1344 //
save_masterkey_user(STDLL_TokData_t * tokdata)1345 CK_RV save_masterkey_user(STDLL_TokData_t *tokdata)
1346 {
1347     FILE *fp = NULL;
1348     CK_BYTE *clear = NULL;
1349     CK_ULONG clear_len = 0L;
1350     CK_BYTE *cipher = NULL;
1351     CK_ULONG cipher_len = 0L;
1352     CK_BYTE *key = NULL;
1353     CK_ULONG key_len = 0L;
1354     CK_ULONG master_key_len = 0L;
1355     CK_ULONG block_size = 0L;
1356     CK_ULONG data_len = 0L;
1357     char fname[PATH_MAX];
1358     CK_RV rc;
1359 
1360     if ((rc = get_encryption_info_for_clear_key(&key_len,
1361                                                 &block_size)) != CKR_OK)
1362         goto done;
1363 
1364     if ((rc = get_encryption_info(&master_key_len, NULL)) != CKR_OK)
1365         goto done;
1366 
1367     data_len = master_key_len + SHA1_HASH_SIZE;
1368     cipher_len = clear_len = block_size * (data_len / block_size + 1);
1369 
1370     key = malloc(key_len);
1371     clear = malloc(clear_len);
1372     cipher = malloc(cipher_len);
1373     if (key == NULL || clear == NULL || cipher == NULL) {
1374         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
1375         rc = ERR_HOST_MEMORY;
1376         goto done;
1377     }
1378     // Copy data to buffer (key+hash)
1379     memcpy(clear, tokdata->master_key, master_key_len);
1380     if ((rc = compute_sha1(tokdata, tokdata->master_key,
1381                            master_key_len, clear + master_key_len)) != CKR_OK)
1382         goto done;
1383     add_pkcs_padding(clear + data_len, block_size, data_len, clear_len);
1384 
1385     // encrypt the key data
1386     memcpy(key, tokdata->user_pin_md5, MD5_HASH_SIZE);
1387     memcpy(key + MD5_HASH_SIZE, tokdata->user_pin_md5, key_len - MD5_HASH_SIZE);
1388 
1389     rc = encrypt_data_with_clear_key(tokdata, key, key_len,
1390                                      token_specific.data_store.
1391                                      pin_initial_vector, clear, clear_len,
1392                                      cipher, &cipher_len);
1393     if (rc != CKR_OK) {
1394         goto done;
1395     }
1396     // write the file
1397     //
1398     // probably ought to ensure the permissions are correct
1399     //
1400     sprintf(fname, "%s/MK_USER", tokdata->data_store);
1401     fp = fopen(fname, "w");
1402     if (!fp) {
1403         TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
1404         rc = CKR_FUNCTION_FAILED;
1405         goto done;
1406     }
1407 
1408     set_perm(fileno(fp));
1409     rc = fwrite(cipher, cipher_len, 1, fp);
1410     if (rc != 1) {
1411         TRACE_ERROR("fwrite failed.\n");
1412         rc = CKR_FUNCTION_FAILED;
1413         goto done;
1414     }
1415 
1416     rc = CKR_OK;
1417 
1418 done:
1419     if (fp)
1420         fclose(fp);
1421     if (key)
1422         free(key);
1423     if (clear)
1424         free(clear);
1425     if (cipher)
1426         free(cipher);
1427 
1428     return rc;
1429 }
1430 
1431 //
1432 //
reload_token_object(STDLL_TokData_t * tokdata,OBJECT * obj)1433 CK_RV reload_token_object(STDLL_TokData_t *tokdata, OBJECT *obj)
1434 {
1435     FILE *fp = NULL;
1436     CK_BYTE *buf = NULL;
1437     char fname[PATH_MAX];
1438     CK_BBOOL priv;
1439     CK_ULONG_32 size;
1440     CK_ULONG size_64;
1441     CK_RV rc;
1442     size_t read_size;
1443 
1444     memset(fname, 0x0, sizeof(fname));
1445 
1446     sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR);
1447 
1448     strncat(fname, (char *) obj->name, 8);
1449 
1450     fp = fopen(fname, "r");
1451     if (!fp) {
1452         TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
1453         rc = CKR_FUNCTION_FAILED;
1454         goto done;
1455     }
1456 
1457     set_perm(fileno(fp));
1458 
1459     if (!fread(&size, sizeof(CK_ULONG_32), 1, fp)) {
1460         OCK_SYSLOG(LOG_ERR, "Cannot read size\n");
1461         rc = CKR_FUNCTION_FAILED;
1462         goto done;
1463     }
1464 
1465     if (!fread(&priv, sizeof(CK_BBOOL), 1, fp)) {
1466         OCK_SYSLOG(LOG_ERR, "Cannot read boolean\n");
1467         rc = CKR_FUNCTION_FAILED;
1468         goto done;
1469     }
1470 
1471     size = size - sizeof(CK_ULONG_32) - sizeof(CK_BBOOL);       // SAB
1472 
1473     buf = (CK_BYTE *) malloc(size);
1474     if (!buf) {
1475         rc = CKR_HOST_MEMORY;
1476         OCK_SYSLOG(LOG_ERR,
1477                    "Cannot malloc %u bytes to read in token object %s "
1478                    "(ignoring it)", size, fname);
1479         goto done;
1480     }
1481 
1482     read_size = fread(buf, 1, size, fp);
1483     if (read_size != size) {
1484         OCK_SYSLOG(LOG_ERR,
1485                    "Token object %s appears corrupted (ignoring it)", fname);
1486         rc = CKR_FUNCTION_FAILED;
1487         goto done;
1488     }
1489 
1490     size_64 = size;
1491 
1492     if (priv)
1493         rc = restore_private_token_object(tokdata, buf, size_64, obj);
1494     else
1495         rc = object_mgr_restore_obj(tokdata, buf, obj);
1496 
1497 done:
1498     if (fp)
1499         fclose(fp);
1500     if (buf)
1501         free(buf);
1502 
1503     return rc;
1504 }
1505 
1506 extern void set_perm(int);
1507 
1508 //
1509 // Note: The token lock (XProcLock) must be held when calling this function.
1510 //
delete_token_object(STDLL_TokData_t * tokdata,OBJECT * obj)1511 CK_RV delete_token_object(STDLL_TokData_t *tokdata, OBJECT *obj)
1512 {
1513     FILE *fp1, *fp2;
1514     char objidx[PATH_MAX], idxtmp[PATH_MAX], fname[PATH_MAX], line[256];
1515 
1516     sprintf(objidx, "%s/%s/%s", tokdata->data_store,
1517             PK_LITE_OBJ_DIR, PK_LITE_OBJ_IDX);
1518     sprintf(idxtmp, "%s/%s/%s", tokdata->data_store,
1519             PK_LITE_OBJ_DIR, "IDX.TMP");
1520 
1521     // FIXME:  on UNIX, we need to make sure these guys aren't symlinks
1522     //         before we blindly write to these files...
1523     //
1524 
1525     // remove the object from the index file
1526     //
1527 
1528     fp1 = fopen(objidx, "r");
1529     fp2 = fopen(idxtmp, "w");
1530     if (!fp1 || !fp2) {
1531         if (fp1)
1532             fclose(fp1);
1533         if (fp2)
1534             fclose(fp2);
1535         TRACE_ERROR("fopen failed\n");
1536         return CKR_FUNCTION_FAILED;
1537     }
1538 
1539     set_perm(fileno(fp2));
1540 
1541     while (fgets(line, 50, fp1)) {
1542         line[strlen(line) - 1] = 0;
1543         if (strcmp(line, (char *)obj->name) == 0)
1544             continue;
1545         else
1546             fprintf(fp2, "%s\n", line);
1547     }
1548 
1549     fclose(fp1);
1550     fclose(fp2);
1551     fp2 = fopen(objidx, "w");
1552     fp1 = fopen(idxtmp, "r");
1553     if (!fp1 || !fp2) {
1554         if (fp1)
1555             fclose(fp1);
1556         if (fp2)
1557             fclose(fp2);
1558         TRACE_ERROR("fopen failed\n");
1559         return CKR_FUNCTION_FAILED;
1560     }
1561 
1562     set_perm(fileno(fp2));
1563 
1564     while (fgets(line, 50, fp1)) {
1565         fprintf(fp2, "%s", line);
1566     }
1567 
1568     fclose(fp1);
1569     fclose(fp2);
1570 
1571     sprintf(fname, "%s/%s/%s", tokdata->data_store,
1572             PK_LITE_OBJ_DIR, (char *) obj->name);
1573     unlink(fname);
1574 
1575     return CKR_OK;
1576 }
1577 
delete_token_data(STDLL_TokData_t * tokdata)1578 CK_RV delete_token_data(STDLL_TokData_t *tokdata)
1579 {
1580     CK_RV rc = CKR_OK;
1581     char *cmd = NULL;
1582 
1583     // Construct a string to delete the token objects.
1584     //
1585     // META This should be fine since the open session checking
1586     // should occur at the API not the STDLL
1587     //
1588     // TODO: Implement delete_all_files_in_dir() */
1589     if (asprintf(&cmd, "%s %s/%s/* > /dev/null 2>&1", DEL_CMD,
1590                  tokdata->data_store, PK_LITE_OBJ_DIR) < 0) {
1591         rc = CKR_HOST_MEMORY;
1592         goto done;
1593     }
1594 
1595     if (system(cmd))
1596         TRACE_ERROR("system() failed.\n");
1597 
1598 done:
1599     free(cmd);
1600 
1601     return rc;
1602 }
1603 
generate_master_key(STDLL_TokData_t * tokdata,CK_BYTE * key)1604 CK_RV generate_master_key(STDLL_TokData_t *tokdata, CK_BYTE *key)
1605 {
1606     CK_RV rc = CKR_OK;
1607     CK_ULONG key_len = 0L;
1608     CK_ULONG master_key_len = 0L;
1609 
1610     /* Skip it if master key is not needed. */
1611     if (!token_specific.data_store.use_master_key)
1612         return CKR_OK;
1613 
1614     if ((rc = get_encryption_info_for_clear_key(&key_len, NULL)) != CKR_OK ||
1615         (rc = get_encryption_info(&master_key_len, NULL)) != CKR_OK)
1616         return ERR_FUNCTION_FAILED;
1617 
1618     /* For secure key tokens, object encrypt/decrypt uses
1619      * software(openssl), not token. So generate masterkey via RNG.
1620      */
1621     if (is_secure_key_token())
1622         return rng_generate(tokdata, key, key_len);
1623 
1624     /* For clear key tokens, let token generate masterkey
1625      * since token will also encrypt/decrypt the objects.
1626      */
1627     switch (token_specific.data_store.encryption_algorithm) {
1628     case CKM_DES3_CBC:
1629         return token_specific.t_des_key_gen(tokdata, key,
1630                                             master_key_len, key_len);
1631     case CKM_AES_CBC:
1632         return token_specific.t_aes_key_gen(tokdata, key,
1633                                             master_key_len, key_len);
1634     }
1635 
1636     return ERR_MECHANISM_INVALID;
1637 }
1638 
init_data_store(char * directory,char * data_store)1639 void init_data_store(char *directory, char *data_store)
1640 {
1641     char *pkdir;
1642 
1643     if (pk_dir != NULL) {
1644         free(pk_dir);
1645         pk_dir = NULL;
1646     }
1647 
1648     if ((pkdir = getenv("PKCS_APP_STORE")) != NULL) {
1649         pk_dir = (char *) malloc(strlen(pkdir) + 1024);
1650         memset(pk_dir, 0, strlen(pkdir) + 1024);
1651         sprintf(pk_dir, "%s/%s", pkdir, SUB_DIR);
1652         return;
1653     }
1654 
1655     if (directory) {
1656         pk_dir = (char *) malloc(strlen(directory) + 25);
1657         memset(pk_dir, 0, strlen(directory) + 25);
1658         sprintf(pk_dir, "%s", directory);
1659         memcpy(data_store, pk_dir, strlen(directory) + 25);
1660     } else {
1661         pk_dir = (char *) malloc(strlen(PK_DIR) + 25);
1662         memset(pk_dir, 0, strlen(PK_DIR) + 25);
1663         sprintf(pk_dir, "%s", PK_DIR);
1664         memcpy(data_store, pk_dir, strlen(PK_DIR) + 25);
1665     }
1666 
1667     return;
1668 }
1669 
final_data_store(void)1670 void final_data_store(void)
1671 {
1672     if (pk_dir != NULL) {
1673         free(pk_dir);
1674         pk_dir = NULL;
1675     }
1676 }
1677 
1678