1 /*
2 * The Initial Developer of the Original Code is International
3 * Business Machines Corporation. Portions created by IBM
4 * Corporation are Copyright (C) 2005 International Business
5 * Machines Corporation. All Rights Reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the Common Public License as published by
9 * IBM Corporation; either version 1 of the License, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * Common Public License for more details.
16 *
17 * You should have received a copy of the Common Public License
18 * along with this program; if not, a copy can be viewed at
19 * http://www.opensource.org/licenses/cpl1.0.php.
20 */
21
22 /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */
23 /*
24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 #include "tpmtok_int.h"
29
30 static CK_SLOT_INFO slot_info;
31
32 // Function: dlist_add_as_first()
33 //
34 // Adds the specified node to the start of the list
35 //
36 // Returns: pointer to the start of the list
37 //
38 DL_NODE *
dlist_add_as_first(DL_NODE * list,void * data)39 dlist_add_as_first(DL_NODE *list, void *data)
40 {
41 DL_NODE *node = NULL;
42
43 if (! data)
44 return (list);
45 node = (DL_NODE *)malloc(sizeof (DL_NODE));
46 if (! node)
47 return (NULL);
48 node->data = data;
49 node->prev = NULL;
50 node->next = list;
51 if (list)
52 list->prev = node;
53
54 return (node);
55 }
56
57
58 // Function: dlist_add_as_last()
59 //
60 // Adds the specified node to the end of the list
61 //
62 // Returns: pointer to the start of the list
63 //
64 DL_NODE *
dlist_add_as_last(DL_NODE * list,void * data)65 dlist_add_as_last(DL_NODE *list, void *data) {
66 DL_NODE *node = NULL;
67
68 if (! data)
69 return (list);
70 node = (DL_NODE *)malloc(sizeof (DL_NODE));
71 if (! node)
72 return (NULL);
73 node->data = data;
74 node->next = NULL;
75
76 if (! list) {
77 node->prev = NULL;
78 return (node);
79 } else {
80 DL_NODE *temp = dlist_get_last(list);
81 temp->next = node;
82 node->prev = temp;
83
84 return (list);
85 }
86 }
87
88
89 // Function: dlist_find()
90 //
91 DL_NODE *
dlist_find(DL_NODE * list,void * data)92 dlist_find(DL_NODE *list, void *data)
93 {
94 DL_NODE *node = list;
95
96 while (node && node->data != data)
97 node = node->next;
98
99 return (node);
100 }
101
102
103 // Function: dlist_get_first()
104 //
105 // Returns the last node in the list or NULL if list is empty
106 //
107 DL_NODE *
dlist_get_first(DL_NODE * list)108 dlist_get_first(DL_NODE *list) {
109 DL_NODE *temp = list;
110
111 if (! list)
112 return (NULL);
113 while (temp->prev != NULL)
114 temp = temp->prev;
115
116 return (temp);
117 }
118
119
120 // Function: dlist_get_last()
121 //
122 // Returns the last node in the list or NULL if list is empty
123 //
124 DL_NODE *
dlist_get_last(DL_NODE * list)125 dlist_get_last(DL_NODE *list) {
126 DL_NODE *temp = list;
127
128 if (! list)
129 return (NULL);
130 while (temp->next != NULL)
131 temp = temp->next;
132
133 return (temp);
134 }
135
136
137 //
138 //
139 CK_ULONG
dlist_length(DL_NODE * list)140 dlist_length(DL_NODE *list) {
141 DL_NODE *temp = list;
142 CK_ULONG len = 0;
143
144 while (temp) {
145 len++;
146 temp = temp->next;
147 }
148
149 return (len);
150 }
151
152
153 //
154 //
155 DL_NODE *
dlist_next(DL_NODE * node)156 dlist_next(DL_NODE *node)
157 {
158 if (! node)
159 return (NULL);
160 return (node->next);
161 }
162
163
164 //
165 //
166 DL_NODE *
dlist_prev(DL_NODE * node)167 dlist_prev(DL_NODE *node) {
168 if (! node)
169 return (NULL);
170 return (node->prev);
171 }
172
173
174 //
175 //
176 void
dlist_purge(DL_NODE * list)177 dlist_purge(DL_NODE *list) {
178 DL_NODE *node;
179
180 if (! list)
181 return;
182 do {
183 node = list->next;
184 free(list);
185 list = node;
186 } while (list);
187 }
188
189 // Function: dlist_remove_node()
190 //
191 // Attempts to remove the specified node from the list. The caller is
192 // responsible for freeing the data associated with the node prior to
193 // calling this routine
194 //
195 DL_NODE *
dlist_remove_node(DL_NODE * list,DL_NODE * node)196 dlist_remove_node(DL_NODE *list, DL_NODE *node) {
197 DL_NODE *temp = list;
198
199 if (! list || ! node)
200 return (NULL);
201 // special case: removing head of the list
202 //
203 if (list == node) {
204 temp = list->next;
205 if (temp)
206 temp->prev = NULL;
207
208 free(list);
209 return (temp);
210 }
211
212 // we have no guarantee that the node is in the list
213 // so search through the list to find it
214 //
215 while ((temp != NULL) && (temp->next != node))
216 temp = temp->next;
217
218 if (temp != NULL) {
219 DL_NODE *next = node->next;
220
221 temp->next = next;
222 if (next)
223 next->prev = temp;
224
225 free(node);
226 }
227
228 return (list);
229 }
230
231 extern void set_perm(int);
232
233 void
CreateXProcLock(void * xproc)234 CreateXProcLock(void *xproc)
235 {
236 pthread_mutexattr_t mtxattr;
237
238 (void) pthread_mutexattr_init(&mtxattr);
239 (void) pthread_mutexattr_setpshared(&mtxattr, PTHREAD_PROCESS_SHARED);
240 (void) pthread_mutex_init((pthread_mutex_t *)xproc, &mtxattr);
241 }
242
243 int
DestroyXProcLock(void * xproc)244 DestroyXProcLock(void *xproc)
245 {
246 return (pthread_mutex_destroy((pthread_mutex_t *)xproc));
247 }
248
249 int
XProcLock(void * xproc)250 XProcLock(void *xproc)
251 {
252 return (pthread_mutex_lock((pthread_mutex_t *)xproc));
253 }
254
255 int
XProcUnLock(void * xproc)256 XProcUnLock(void *xproc)
257 {
258 return (pthread_mutex_unlock((pthread_mutex_t *)xproc));
259 }
260
261 //
262 //
263 // is_attribute_defined()
264 //
265 // determine whether the specified attribute is defined by Cryptoki
266 //
267 CK_BBOOL
is_attribute_defined(CK_ATTRIBUTE_TYPE type)268 is_attribute_defined(CK_ATTRIBUTE_TYPE type)
269 {
270 if (type >= CKA_VENDOR_DEFINED)
271 return (TRUE);
272 switch (type) {
273 case CKA_CLASS:
274 case CKA_TOKEN:
275 case CKA_PRIVATE:
276 case CKA_LABEL:
277 case CKA_APPLICATION:
278 case CKA_VALUE:
279 case CKA_CERTIFICATE_TYPE:
280 case CKA_ISSUER:
281 case CKA_SERIAL_NUMBER:
282 case CKA_KEY_TYPE:
283 case CKA_SUBJECT:
284 case CKA_ID:
285 case CKA_SENSITIVE:
286 case CKA_ENCRYPT:
287 case CKA_DECRYPT:
288 case CKA_WRAP:
289 case CKA_UNWRAP:
290 case CKA_SIGN:
291 case CKA_SIGN_RECOVER:
292 case CKA_VERIFY:
293 case CKA_VERIFY_RECOVER:
294 case CKA_DERIVE:
295 case CKA_START_DATE:
296 case CKA_END_DATE:
297 case CKA_MODULUS:
298 case CKA_MODULUS_BITS:
299 case CKA_PUBLIC_EXPONENT:
300 case CKA_PRIVATE_EXPONENT:
301 case CKA_PRIME_1:
302 case CKA_PRIME_2:
303 case CKA_EXPONENT_1:
304 case CKA_EXPONENT_2:
305 case CKA_COEFFICIENT:
306 case CKA_PRIME:
307 case CKA_SUBPRIME:
308 case CKA_BASE:
309 case CKA_VALUE_BITS:
310 case CKA_VALUE_LEN:
311 case CKA_EXTRACTABLE:
312 case CKA_LOCAL:
313 case CKA_NEVER_EXTRACTABLE:
314 case CKA_ALWAYS_SENSITIVE:
315 case CKA_MODIFIABLE:
316 case CKA_ECDSA_PARAMS:
317 case CKA_EC_POINT:
318 case CKA_HW_FEATURE_TYPE:
319 case CKA_HAS_RESET:
320 case CKA_RESET_ON_INIT:
321 case CKA_KEY_GEN_MECHANISM:
322 case CKA_PRIME_BITS:
323 case CKA_SUBPRIME_BITS:
324 case CKA_OBJECT_ID:
325 case CKA_AC_ISSUER:
326 case CKA_OWNER:
327 case CKA_ATTR_TYPES:
328 case CKA_TRUSTED:
329 return (TRUE);
330 }
331
332 return (FALSE);
333 }
334
335 void
init_slot_info(TOKEN_DATA * td)336 init_slot_info(TOKEN_DATA *td)
337 {
338 /*
339 * Much of the token info is pulled from the TPM itself when
340 * C_Initialize is called.
341 */
342 (void) (void) memset(&slot_info.slotDescription, ' ',
343 sizeof (slot_info.slotDescription) - 1);
344 (void) (void) memset(&slot_info.manufacturerID, ' ',
345 sizeof (slot_info.manufacturerID) - 1);
346
347 (void) (void) memcpy(&slot_info.slotDescription,
348 "PKCS#11 Interface for TPM",
349 strlen("PKCS#11 Interface for TPM"));
350
351 (void) (void) memcpy(&slot_info.manufacturerID,
352 td->token_info.manufacturerID,
353 strlen((char *)td->token_info.manufacturerID));
354
355 slot_info.hardwareVersion = nv_token_data->token_info.hardwareVersion;
356 slot_info.firmwareVersion = nv_token_data->token_info.firmwareVersion;
357 slot_info.flags = CKF_TOKEN_PRESENT | CKF_HW_SLOT;
358 }
359
360 /*ARGSUSED*/
361 void
copy_slot_info(CK_SLOT_ID slotID,CK_SLOT_INFO_PTR sinfo)362 copy_slot_info(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR sinfo)
363 {
364 if (sinfo != NULL)
365 (void) memcpy(sinfo, &slot_info, sizeof (slot_info));
366 }
367
368 static void
init_token_info(TOKEN_DATA * td)369 init_token_info(TOKEN_DATA *td)
370 {
371 CK_TOKEN_INFO *token_info = NULL;
372
373 token_info = &td->token_info;
374
375 (void) memset(token_info->model, ' ',
376 sizeof (token_info->model));
377 (void) memset(token_info->serialNumber, ' ',
378 sizeof (token_info->serialNumber));
379
380 //
381 // I don't see any API support for changing the clock so
382 // we will use the system clock for the token's clock.
383 //
384 token_info->flags = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_CLOCK_ON_TOKEN |
385 CKF_SO_PIN_TO_BE_CHANGED;
386
387 if (memcmp(td->user_pin_sha, "00000000000000000000",
388 SHA1_DIGEST_LENGTH) != 0)
389 token_info->flags |= CKF_USER_PIN_INITIALIZED;
390 else
391 token_info->flags |= CKF_USER_PIN_TO_BE_CHANGED;
392
393 // For the release, we made these
394 // values as CK_UNAVAILABLE_INFORMATION
395 //
396 token_info->ulMaxSessionCount = (CK_ULONG)CK_UNAVAILABLE_INFORMATION;
397 token_info->ulSessionCount = (CK_ULONG)CK_UNAVAILABLE_INFORMATION;
398 token_info->ulMaxRwSessionCount = (CK_ULONG)CK_UNAVAILABLE_INFORMATION;
399 token_info->ulRwSessionCount = (CK_ULONG)CK_UNAVAILABLE_INFORMATION;
400 token_info->ulMaxPinLen = MAX_PIN_LEN;
401 token_info->ulMinPinLen = MIN_PIN_LEN;
402 token_info->ulTotalPublicMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION;
403 token_info->ulFreePublicMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION;
404 token_info->ulTotalPrivateMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION;
405 token_info->ulFreePrivateMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION;
406
407 (void) memset(token_info->utcTime, ' ', sizeof (token_info->utcTime));
408 }
409
410 CK_RV
init_token_data(TSS_HCONTEXT hContext,TOKEN_DATA * td)411 init_token_data(TSS_HCONTEXT hContext, TOKEN_DATA *td) {
412 CK_RV rc;
413
414 (void) memset((char *)td, 0, sizeof (nv_token_data));
415 //
416 // the normal USER pin is not set when the token is initialized
417 //
418 (void) memcpy(td->user_pin_sha, "00000000000000000000",
419 SHA1_DIGEST_LENGTH);
420 (void) memcpy(td->so_pin_sha, default_so_pin_sha,
421 SHA1_DIGEST_LENGTH);
422
423 (void) memset(user_pin_md5, 0x0, MD5_DIGEST_LENGTH);
424 (void) memcpy(so_pin_md5, default_so_pin_md5, MD5_DIGEST_LENGTH);
425
426 (void) memcpy(td->next_token_object_name, "00000000", 8);
427
428 td->tweak_vector.allow_key_mods = TRUE;
429
430 init_token_info(td);
431
432 rc = token_get_tpm_info(hContext, td);
433 if (rc != CKR_OK)
434 return (rc);
435
436 rc = save_token_data(td);
437
438 return (rc);
439 }
440
441 // Function: compute_next_token_obj_name()
442 //
443 // Given a token object name (8 bytes in the range [0 - 9A - Z])
444 // increment by one adjusting as necessary
445 //
446 // This gives us a namespace of 36^8 = 2, 821, 109, 907, 456
447 // objects before wrapping around.
448 //
449 CK_RV
compute_next_token_obj_name(CK_BYTE * current,CK_BYTE * next)450 compute_next_token_obj_name(CK_BYTE *current, CK_BYTE *next) {
451 int val[8];
452 int i;
453
454 if (! current || ! next) {
455 return (CKR_FUNCTION_FAILED);
456 }
457 // Convert to integral base 36
458 //
459 for (i = 0; i < 8; i++) {
460 if (current[i] >= '0' && current[i] <= '9')
461 val[i] = current[i] - '0';
462
463 if (current[i] >= 'A' && current[i] <= 'Z')
464 val[i] = current[i] - 'A' + 10;
465 }
466
467 val[0]++;
468
469 i = 0;
470
471 while (val[i] > 35) {
472 val[i] = 0;
473
474 if (i + 1 < 8) {
475 val[i + 1]++;
476 i++;
477 } else {
478 val[0]++;
479 i = 0; // start pass 2
480 }
481 }
482
483 // now, convert back to [0 - 9A - Z]
484 //
485 for (i = 0; i < 8; i++) {
486 if (val[i] < 10)
487 next[i] = '0' + val[i];
488 else
489 next[i] = 'A' + val[i] - 10;
490 }
491
492 return (CKR_OK);
493 }
494
495
496 //
497 //
498 CK_RV
build_attribute(CK_ATTRIBUTE_TYPE type,CK_BYTE * data,CK_ULONG data_len,CK_ATTRIBUTE ** attrib)499 build_attribute(CK_ATTRIBUTE_TYPE type,
500 CK_BYTE *data,
501 CK_ULONG data_len,
502 CK_ATTRIBUTE **attrib) {
503 CK_ATTRIBUTE *attr = NULL;
504
505 attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + data_len);
506 if (! attr) {
507 return (CKR_DEVICE_MEMORY);
508 }
509 attr->type = type;
510 attr->ulValueLen = data_len;
511
512 if (data_len > 0) {
513 attr->pValue = (CK_BYTE *)attr + sizeof (CK_ATTRIBUTE);
514 (void) memcpy(attr->pValue, data, data_len);
515 }
516 else
517 attr->pValue = NULL;
518
519 *attrib = attr;
520
521 return (CKR_OK);
522 }
523
524 CK_RV
add_pkcs_padding(CK_BYTE * ptr,UINT32 block_size,UINT32 data_len,UINT32 total_len)525 add_pkcs_padding(CK_BYTE * ptr,
526 UINT32 block_size,
527 UINT32 data_len,
528 UINT32 total_len)
529 {
530 UINT32 i, pad_len;
531 CK_BYTE pad_value;
532
533 pad_len = block_size - (data_len % block_size);
534 pad_value = (CK_BYTE)pad_len;
535
536 if (data_len + pad_len > total_len) {
537 return (CKR_FUNCTION_FAILED);
538 }
539 for (i = 0; i < pad_len; i++)
540 ptr[i] = pad_value;
541
542 return (CKR_OK);
543 }
544
545 CK_RV
strip_pkcs_padding(CK_BYTE * ptr,UINT32 total_len,UINT32 * data_len)546 strip_pkcs_padding(
547 CK_BYTE *ptr,
548 UINT32 total_len,
549 UINT32 *data_len)
550 {
551 CK_BYTE pad_value;
552
553 pad_value = ptr[total_len - 1];
554
555 /* We have 'pad_value' bytes of 'pad_value' appended to the end */
556 *data_len = total_len - pad_value;
557
558 return (CKR_OK);
559 }
560
561 CK_RV
remove_leading_zeros(CK_ATTRIBUTE * attr)562 remove_leading_zeros(CK_ATTRIBUTE *attr)
563 {
564 CK_BYTE *ptr = NULL;
565 CK_ULONG new_len, i;
566
567 ptr = attr->pValue;
568
569 for (i = 0; i < attr->ulValueLen; i++) {
570 if (ptr[i] != 0x0)
571 break;
572 }
573
574 new_len = attr->ulValueLen - i;
575
576 (void) memcpy(ptr, ptr + i, new_len);
577 attr->ulValueLen = new_len;
578
579 return (CKR_OK);
580 }
581
582 CK_RV
parity_is_odd(CK_BYTE b)583 parity_is_odd(CK_BYTE b) {
584 b = ((b >> 4) ^ b) & 0x0f;
585 b = ((b >> 2) ^ b) & 0x03;
586 b = ((b >> 1) ^ b) & 0x01;
587
588 if (b == 1)
589 return (TRUE);
590 else
591 return (FALSE);
592 }
593
594 CK_RV
attach_shm()595 attach_shm() {
596 if (global_shm != NULL)
597 return (CKR_OK);
598
599 global_shm = (LW_SHM_TYPE *)calloc(1, sizeof (LW_SHM_TYPE));
600 if (global_shm == NULL) {
601 return (CKR_HOST_MEMORY);
602 }
603 CreateXProcLock(&global_shm->mutex);
604
605 xproclock = (void *)&global_shm->mutex;
606
607 return (CKR_OK);
608 }
609
610 CK_RV
detach_shm()611 detach_shm()
612 {
613 if (global_shm != NULL) {
614 free(global_shm);
615 global_shm = NULL;
616 }
617
618 return (CKR_OK);
619 }
620
621 CK_RV
compute_sha(CK_BYTE * data,CK_ULONG_32 len,CK_BYTE * hash)622 compute_sha(CK_BYTE *data,
623 CK_ULONG_32 len,
624 CK_BYTE * hash)
625 {
626 SHA1_CTX ctx;
627
628 SHA1Init(&ctx);
629
630 SHA1Update(&ctx, data, len);
631
632 SHA1Final(hash, &ctx);
633 return (CKR_OK);
634 }
635