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