security/nss/lib/ckfw/capi/cobject.c

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:d2c854fd87ec
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include "ckcapi.h"
6 #include "nssbase.h"
7
8 /*
9 * ckcapi/cobject.c
10 *
11 * This file implements the NSSCKMDObject object for the
12 * "nss to capi objects" cryptoki module.
13 */
14
15 const CK_ATTRIBUTE_TYPE certAttrs[] = {
16 CKA_CLASS,
17 CKA_TOKEN,
18 CKA_PRIVATE,
19 CKA_MODIFIABLE,
20 CKA_LABEL,
21 CKA_CERTIFICATE_TYPE,
22 CKA_SUBJECT,
23 CKA_ISSUER,
24 CKA_SERIAL_NUMBER,
25 CKA_VALUE
26 };
27 const PRUint32 certAttrsCount = NSS_CKCAPI_ARRAY_SIZE(certAttrs);
28
29 /* private keys, for now only support RSA */
30 const CK_ATTRIBUTE_TYPE privKeyAttrs[] = {
31 CKA_CLASS,
32 CKA_TOKEN,
33 CKA_PRIVATE,
34 CKA_MODIFIABLE,
35 CKA_LABEL,
36 CKA_KEY_TYPE,
37 CKA_DERIVE,
38 CKA_LOCAL,
39 CKA_SUBJECT,
40 CKA_SENSITIVE,
41 CKA_DECRYPT,
42 CKA_SIGN,
43 CKA_SIGN_RECOVER,
44 CKA_UNWRAP,
45 CKA_EXTRACTABLE,
46 CKA_ALWAYS_SENSITIVE,
47 CKA_NEVER_EXTRACTABLE,
48 CKA_MODULUS,
49 CKA_PUBLIC_EXPONENT,
50 };
51 const PRUint32 privKeyAttrsCount = NSS_CKCAPI_ARRAY_SIZE(privKeyAttrs);
52
53 /* public keys, for now only support RSA */
54 const CK_ATTRIBUTE_TYPE pubKeyAttrs[] = {
55 CKA_CLASS,
56 CKA_TOKEN,
57 CKA_PRIVATE,
58 CKA_MODIFIABLE,
59 CKA_LABEL,
60 CKA_KEY_TYPE,
61 CKA_DERIVE,
62 CKA_LOCAL,
63 CKA_SUBJECT,
64 CKA_ENCRYPT,
65 CKA_VERIFY,
66 CKA_VERIFY_RECOVER,
67 CKA_WRAP,
68 CKA_MODULUS,
69 CKA_PUBLIC_EXPONENT,
70 };
71 const PRUint32 pubKeyAttrsCount = NSS_CKCAPI_ARRAY_SIZE(pubKeyAttrs);
72 static const CK_BBOOL ck_true = CK_TRUE;
73 static const CK_BBOOL ck_false = CK_FALSE;
74 static const CK_CERTIFICATE_TYPE ckc_x509 = CKC_X_509;
75 static const CK_KEY_TYPE ckk_rsa = CKK_RSA;
76 static const CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE;
77 static const CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY;
78 static const CK_OBJECT_CLASS cko_public_key = CKO_PUBLIC_KEY;
79 static const NSSItem ckcapi_trueItem = {
80 (void *)&ck_true, (PRUint32)sizeof(CK_BBOOL) };
81 static const NSSItem ckcapi_falseItem = {
82 (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL) };
83 static const NSSItem ckcapi_x509Item = {
84 (void *)&ckc_x509, (PRUint32)sizeof(CK_CERTIFICATE_TYPE) };
85 static const NSSItem ckcapi_rsaItem = {
86 (void *)&ckk_rsa, (PRUint32)sizeof(CK_KEY_TYPE) };
87 static const NSSItem ckcapi_certClassItem = {
88 (void *)&cko_certificate, (PRUint32)sizeof(CK_OBJECT_CLASS) };
89 static const NSSItem ckcapi_privKeyClassItem = {
90 (void *)&cko_private_key, (PRUint32)sizeof(CK_OBJECT_CLASS) };
91 static const NSSItem ckcapi_pubKeyClassItem = {
92 (void *)&cko_public_key, (PRUint32)sizeof(CK_OBJECT_CLASS) };
93 static const NSSItem ckcapi_emptyItem = {
94 (void *)&ck_true, 0};
95
96 /*
97 * these are utilities. The chould be moved to a new utilities file.
98 */
99
100 /*
101 * unwrap a single DER value
102 */
103 unsigned char *
104 nss_ckcapi_DERUnwrap
105 (
106 unsigned char *src,
107 unsigned int size,
108 unsigned int *outSize,
109 unsigned char **next
110 )
111 {
112 unsigned char *start = src;
113 unsigned char *end = src+size;
114 unsigned int len = 0;
115
116 /* initialize error condition return values */
117 *outSize = 0;
118 if (next) {
119 *next = src;
120 }
121
122 if (size < 2) {
123 return start;
124 }
125 src++; /* skip the tag -- should check it against an expected value! */
126 len = (unsigned) *src++;
127 if (len & 0x80) {
128 unsigned int count = len & 0x7f;
129 len = 0;
130
131 if (count+2 > size) {
132 return start;
133 }
134 while (count-- > 0) {
135 len = (len << 8) | (unsigned) *src++;
136 }
137 }
138 if (len + (src-start) > size) {
139 return start;
140 }
141 if (next) {
142 *next = src+len;
143 }
144 *outSize = len;
145
146 return src;
147 }
148
149 /*
150 * convert a PKCS #11 bytestrin into a CK_ULONG, the byte stream must be
151 * less than sizeof (CK_ULONG).
152 */
153 CK_ULONG
154 nss_ckcapi_DataToInt
155 (
156 NSSItem *data,
157 CK_RV *pError
158 )
159 {
160 CK_ULONG value = 0;
161 unsigned long count = data->size;
162 unsigned char *dataPtr = data->data;
163 unsigned long size = 0;
164
165 *pError = CKR_OK;
166
167 while (count--) {
168 value = value << 8;
169 value = value + *dataPtr++;
170 if (size || value) {
171 size++;
172 }
173 }
174 if (size > sizeof(CK_ULONG)) {
175 *pError = CKR_ATTRIBUTE_VALUE_INVALID;
176 }
177 return value;
178 }
179
180 /*
181 * convert a CK_ULONG to a bytestream. Data is stored in the buffer 'buf'
182 * and must be at least CK_ULONG. Caller must provide buf.
183 */
184 CK_ULONG
185 nss_ckcapi_IntToData
186 (
187 CK_ULONG value,
188 NSSItem *data,
189 unsigned char *dataPtr,
190 CK_RV *pError
191 )
192 {
193 unsigned long count = 0;
194 unsigned long i;
195 #define SHIFT ((sizeof(CK_ULONG)-1)*8)
196 PRBool first = 0;
197
198 *pError = CKR_OK;
199
200 data->data = dataPtr;
201 for (i=0; i < sizeof(CK_ULONG); i++) {
202 unsigned char digit = (unsigned char)((value >> SHIFT) & 0xff);
203
204 value = value << 8;
205
206 /* drop leading zero bytes */
207 if (first && (0 == digit)) {
208 continue;
209 }
210 *dataPtr++ = digit;
211 count++;
212 }
213 data->size = count;
214 return count;
215 }
216
217 /*
218 * get an attribute from a template. Value is returned in NSS item.
219 * data for the item is owned by the template.
220 */
221 CK_RV
222 nss_ckcapi_GetAttribute
223 (
224 CK_ATTRIBUTE_TYPE type,
225 CK_ATTRIBUTE *template,
226 CK_ULONG templateSize,
227 NSSItem *item
228 )
229 {
230 CK_ULONG i;
231
232 for (i=0; i < templateSize; i++) {
233 if (template[i].type == type) {
234 item->data = template[i].pValue;
235 item->size = template[i].ulValueLen;
236 return CKR_OK;
237 }
238 }
239 return CKR_TEMPLATE_INCOMPLETE;
240 }
241
242 /*
243 * get an attribute which is type CK_ULONG.
244 */
245 CK_ULONG
246 nss_ckcapi_GetULongAttribute
247 (
248 CK_ATTRIBUTE_TYPE type,
249 CK_ATTRIBUTE *template,
250 CK_ULONG templateSize,
251 CK_RV *pError
252 )
253 {
254 NSSItem item;
255
256 *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item);
257 if (CKR_OK != *pError) {
258 return (CK_ULONG) 0;
259 }
260 if (item.size != sizeof(CK_ULONG)) {
261 *pError = CKR_ATTRIBUTE_VALUE_INVALID;
262 return (CK_ULONG) 0;
263 }
264 return *(CK_ULONG *)item.data;
265 }
266
267 /*
268 * get an attribute which is type CK_BBOOL.
269 */
270 CK_BBOOL
271 nss_ckcapi_GetBoolAttribute
272 (
273 CK_ATTRIBUTE_TYPE type,
274 CK_ATTRIBUTE *template,
275 CK_ULONG templateSize,
276 CK_RV *pError
277 )
278 {
279 NSSItem item;
280
281 *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item);
282 if (CKR_OK != *pError) {
283 return (CK_BBOOL) 0;
284 }
285 if (item.size != sizeof(CK_BBOOL)) {
286 *pError = CKR_ATTRIBUTE_VALUE_INVALID;
287 return (CK_BBOOL) 0;
288 }
289 return *(CK_BBOOL *)item.data;
290 }
291
292 /*
293 * get an attribute which is type CK_BBOOL.
294 */
295 char *
296 nss_ckcapi_GetStringAttribute
297 (
298 CK_ATTRIBUTE_TYPE type,
299 CK_ATTRIBUTE *template,
300 CK_ULONG templateSize,
301 CK_RV *pError
302 )
303 {
304 NSSItem item;
305 char *str;
306
307 /* get the attribute */
308 *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item);
309 if (CKR_OK != *pError) {
310 return (char *)NULL;
311 }
312 /* make sure it is null terminated */
313 str = nss_ZNEWARRAY(NULL, char, item.size+1);
314 if ((char *)NULL == str) {
315 *pError = CKR_HOST_MEMORY;
316 return (char *)NULL;
317 }
318
319 nsslibc_memcpy(str, item.data, item.size);
320 str[item.size] = 0;
321
322 return str;
323 }
324
325 /*
326 * Return the size in bytes of a wide string, including the terminating null
327 * character
328 */
329 int
330 nss_ckcapi_WideSize
331 (
332 LPCWSTR wide
333 )
334 {
335 DWORD size;
336
337 if ((LPWSTR)NULL == wide) {
338 return 0;
339 }
340 size = wcslen(wide)+1;
341 return size*sizeof(WCHAR);
342 }
343
344 /*
345 * Covert a Unicode wide character string to a UTF8 string
346 */
347 char *
348 nss_ckcapi_WideToUTF8
349 (
350 LPCWSTR wide
351 )
352 {
353 DWORD size;
354 char *buf;
355
356 if ((LPWSTR)NULL == wide) {
357 return (char *)NULL;
358 }
359
360 size = WideCharToMultiByte(CP_UTF8, 0, wide, -1, NULL, 0, NULL, 0);
361 if (size == 0) {
362 return (char *)NULL;
363 }
364 buf = nss_ZNEWARRAY(NULL, char, size);
365 size = WideCharToMultiByte(CP_UTF8, 0, wide, -1, buf, size, NULL, 0);
366 if (size == 0) {
367 nss_ZFreeIf(buf);
368 return (char *)NULL;
369 }
370 return buf;
371 }
372
373 /*
374 * Return a Wide String duplicated with nss allocated memory.
375 */
376 LPWSTR
377 nss_ckcapi_WideDup
378 (
379 LPCWSTR wide
380 )
381 {
382 DWORD len;
383 LPWSTR buf;
384
385 if ((LPWSTR)NULL == wide) {
386 return (LPWSTR)NULL;
387 }
388
389 len = wcslen(wide)+1;
390
391 buf = nss_ZNEWARRAY(NULL, WCHAR, len);
392 if ((LPWSTR) NULL == buf) {
393 return buf;
394 }
395 nsslibc_memcpy(buf, wide, len*sizeof(WCHAR));
396 return buf;
397 }
398
399 /*
400 * Covert a UTF8 string to Unicode wide character
401 */
402 LPWSTR
403 nss_ckcapi_UTF8ToWide
404 (
405 char *buf
406 )
407 {
408 DWORD size;
409 LPWSTR wide;
410
411 if ((char *)NULL == buf) {
412 return (LPWSTR) NULL;
413 }
414
415 size = MultiByteToWideChar(CP_UTF8, 0, buf, -1, NULL, 0);
416 if (size == 0) {
417 return (LPWSTR) NULL;
418 }
419 wide = nss_ZNEWARRAY(NULL, WCHAR, size);
420 size = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wide, size);
421 if (size == 0) {
422 nss_ZFreeIf(wide);
423 return (LPWSTR) NULL;
424 }
425 return wide;
426 }
427
428
429 /*
430 * keep all the knowlege of how the internalObject is laid out in this function
431 *
432 * nss_ckcapi_FetchKeyContainer
433 *
434 * fetches the Provider container and info as well as a key handle for a
435 * private key. If something other than a private key is passed in,
436 * this function fails with CKR_KEY_TYPE_INCONSISTENT
437 */
438 NSS_EXTERN CK_RV
439 nss_ckcapi_FetchKeyContainer
440 (
441 ckcapiInternalObject *iKey,
442 HCRYPTPROV *hProv,
443 DWORD *keySpec,
444 HCRYPTKEY *hKey
445 )
446 {
447 ckcapiCertObject *co;
448 ckcapiKeyObject *ko;
449 BOOL rc, dummy;
450 DWORD msError;
451
452
453 switch (iKey->type) {
454 default:
455 case ckcapiRaw:
456 /* can't have raw private keys */
457 return CKR_KEY_TYPE_INCONSISTENT;
458 case ckcapiCert:
459 if (iKey->objClass != CKO_PRIVATE_KEY) {
460 /* Only private keys have private key provider handles */
461 return CKR_KEY_TYPE_INCONSISTENT;
462 }
463 co = &iKey->u.cert;
464
465 /* OK, get the Provider */
466 rc = CryptAcquireCertificatePrivateKey(co->certContext,
467 CRYPT_ACQUIRE_CACHE_FLAG|CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, hProv,
468 keySpec, &dummy);
469 if (!rc) {
470 goto loser;
471 }
472 break;
473 case ckcapiBareKey:
474 if (iKey->objClass != CKO_PRIVATE_KEY) {
475 /* Only private keys have private key provider handles */
476 return CKR_KEY_TYPE_INCONSISTENT;
477 }
478 ko = &iKey->u.key;
479
480 /* OK, get the Provider */
481 if (0 == ko->hProv) {
482 rc = CryptAcquireContext(hProv,
483 ko->containerName,
484 ko->provName,
485 ko->provInfo.dwProvType , 0);
486 if (!rc) {
487 goto loser;
488 }
489 } else {
490 *hProv = ko->hProv;
491 }
492 *keySpec = ko->provInfo.dwKeySpec;
493 break;
494 }
495
496 /* and get the crypto handle */
497 rc = CryptGetUserKey(*hProv, *keySpec, hKey);
498 if (!rc) {
499 goto loser;
500 }
501 return CKR_OK;
502 loser:
503 /* map the microsoft error before leaving */
504 msError = GetLastError();
505 switch (msError) {
506 case ERROR_INVALID_HANDLE:
507 case ERROR_INVALID_PARAMETER:
508 case NTE_BAD_KEY:
509 case NTE_NO_KEY:
510 case NTE_BAD_PUBLIC_KEY:
511 case NTE_BAD_KEYSET:
512 case NTE_KEYSET_NOT_DEF:
513 return CKR_KEY_TYPE_INCONSISTENT;
514 case NTE_BAD_UID:
515 case NTE_KEYSET_ENTRY_BAD:
516 return CKR_DEVICE_ERROR;
517 }
518 return CKR_GENERAL_ERROR;
519 }
520
521
522 /*
523 * take a DER PUBLIC Key block and return the modulus and exponent
524 */
525 static void
526 ckcapi_CertPopulateModulusExponent
527 (
528 ckcapiInternalObject *io
529 )
530 {
531 ckcapiKeyParams *kp = &io->u.cert.key;
532 PCCERT_CONTEXT certContext = io->u.cert.certContext;
533 unsigned char *pkData =
534 certContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData;
535 unsigned int size=
536 certContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData;
537 unsigned int newSize;
538 unsigned char *ptr, *newptr;
539
540 /* find the start of the modulus -- this will not give good results if
541 * the key isn't an rsa key! */
542 ptr = nss_ckcapi_DERUnwrap(pkData, size, &newSize, NULL);
543 kp->modulus.data = nss_ckcapi_DERUnwrap(ptr, newSize,
544 &kp->modulus.size, &newptr);
545 /* changed from signed to unsigned int */
546 if (0 == *(char *)kp->modulus.data) {
547 kp->modulus.data = ((char *)kp->modulus.data)+1;
548 kp->modulus.size = kp->modulus.size - 1;
549 }
550 /* changed from signed to unsigned int */
551 kp->exponent.data = nss_ckcapi_DERUnwrap(newptr, (newptr-ptr)+newSize,
552 &kp->exponent.size, NULL);
553 if (0 == *(char *)kp->exponent.data) {
554 kp->exponent.data = ((char *)kp->exponent.data)+1;
555 kp->exponent.size = kp->exponent.size - 1;
556 }
557 return;
558 }
559
560 typedef struct _CAPI_RSA_KEY_BLOB {
561 PUBLICKEYSTRUC header;
562 RSAPUBKEY rsa;
563 char data[1];
564 } CAPI_RSA_KEY_BLOB;
565
566 #define CAPI_MODULUS_OFFSET(modSize) 0
567 #define CAPI_PRIME_1_OFFSET(modSize) (modSize)
568 #define CAPI_PRIME_2_OFFSET(modSize) ((modSize)+(modSize)/2)
569 #define CAPI_EXPONENT_1_OFFSET(modSize) ((modSize)*2)
570 #define CAPI_EXPONENT_2_OFFSET(modSize) ((modSize)*2+(modSize)/2)
571 #define CAPI_COEFFICIENT_OFFSET(modSize) ((modSize)*3)
572 #define CAPI_PRIVATE_EXP_OFFSET(modSize) ((modSize)*3+(modSize)/2)
573
574 void
575 ckcapi_FetchPublicKey
576 (
577 ckcapiInternalObject *io
578 )
579 {
580 ckcapiKeyParams *kp;
581 HCRYPTPROV hProv;
582 DWORD keySpec;
583 HCRYPTKEY hKey = 0;
584 CK_RV error;
585 DWORD bufLen;
586 BOOL rc;
587 unsigned long modulus;
588 char *buf = NULL;
589 CAPI_RSA_KEY_BLOB *blob;
590
591 error = nss_ckcapi_FetchKeyContainer(io, &hProv, &keySpec, &hKey);
592 if (CKR_OK != error) {
593 goto loser;
594 }
595 kp = (ckcapiCert == io->type) ? &io->u.cert.key : &io->u.key.key;
596
597 rc = CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, buf, &bufLen);
598 if (!rc) {
599 goto loser;
600 }
601 buf = nss_ZNEWARRAY(NULL, char, bufLen);
602 rc = CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, buf, &bufLen);
603 if (!rc) {
604 goto loser;
605 }
606 /* validate the blob */
607 blob = (CAPI_RSA_KEY_BLOB *)buf;
608 if ((PUBLICKEYBLOB != blob->header.bType) ||
609 (0x02 != blob->header.bVersion) ||
610 (0x31415352 != blob->rsa.magic)) {
611 goto loser;
612 }
613 modulus = blob->rsa.bitlen/8;
614 kp->pubKey = buf;
615 buf = NULL;
616
617 kp->modulus.data = &blob->data[CAPI_MODULUS_OFFSET(modulus)];
618 kp->modulus.size = modulus;
619 ckcapi_ReverseData(&kp->modulus);
620 nss_ckcapi_IntToData(blob->rsa.pubexp, &kp->exponent,
621 kp->publicExponentData, &error);
622
623 loser:
624 nss_ZFreeIf(buf);
625 if (0 != hKey) {
626 CryptDestroyKey(hKey);
627 }
628 return;
629 }
630
631 void
632 ckcapi_FetchPrivateKey
633 (
634 ckcapiInternalObject *io
635 )
636 {
637 ckcapiKeyParams *kp;
638 HCRYPTPROV hProv;
639 DWORD keySpec;
640 HCRYPTKEY hKey = 0;
641 CK_RV error;
642 DWORD bufLen;
643 BOOL rc;
644 unsigned long modulus;
645 char *buf = NULL;
646 CAPI_RSA_KEY_BLOB *blob;
647
648 error = nss_ckcapi_FetchKeyContainer(io, &hProv, &keySpec, &hKey);
649 if (CKR_OK != error) {
650 goto loser;
651 }
652 kp = (ckcapiCert == io->type) ? &io->u.cert.key : &io->u.key.key;
653
654 rc = CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, buf, &bufLen);
655 if (!rc) {
656 goto loser;
657 }
658 buf = nss_ZNEWARRAY(NULL, char, bufLen);
659 rc = CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, buf, &bufLen);
660 if (!rc) {
661 goto loser;
662 }
663 /* validate the blob */
664 blob = (CAPI_RSA_KEY_BLOB *)buf;
665 if ((PRIVATEKEYBLOB != blob->header.bType) ||
666 (0x02 != blob->header.bVersion) ||
667 (0x32415352 != blob->rsa.magic)) {
668 goto loser;
669 }
670 modulus = blob->rsa.bitlen/8;
671 kp->privateKey = buf;
672 buf = NULL;
673
674 kp->privateExponent.data = &blob->data[CAPI_PRIVATE_EXP_OFFSET(modulus)];
675 kp->privateExponent.size = modulus;
676 ckcapi_ReverseData(&kp->privateExponent);
677 kp->prime1.data = &blob->data[CAPI_PRIME_1_OFFSET(modulus)];
678 kp->prime1.size = modulus/2;
679 ckcapi_ReverseData(&kp->prime1);
680 kp->prime2.data = &blob->data[CAPI_PRIME_2_OFFSET(modulus)];
681 kp->prime2.size = modulus/2;
682 ckcapi_ReverseData(&kp->prime2);
683 kp->exponent1.data = &blob->data[CAPI_EXPONENT_1_OFFSET(modulus)];
684 kp->exponent1.size = modulus/2;
685 ckcapi_ReverseData(&kp->exponent1);
686 kp->exponent2.data = &blob->data[CAPI_EXPONENT_2_OFFSET(modulus)];
687 kp->exponent2.size = modulus/2;
688 ckcapi_ReverseData(&kp->exponent2);
689 kp->coefficient.data = &blob->data[CAPI_COEFFICIENT_OFFSET(modulus)];
690 kp->coefficient.size = modulus/2;
691 ckcapi_ReverseData(&kp->coefficient);
692
693 loser:
694 nss_ZFreeIf(buf);
695 if (0 != hKey) {
696 CryptDestroyKey(hKey);
697 }
698 return;
699 }
700
701
702 void
703 ckcapi_PopulateModulusExponent
704 (
705 ckcapiInternalObject *io
706 )
707 {
708 if (ckcapiCert == io->type) {
709 ckcapi_CertPopulateModulusExponent(io);
710 } else {
711 ckcapi_FetchPublicKey(io);
712 }
713 return;
714 }
715
716 /*
717 * fetch the friendly name attribute.
718 * can only be called with ckcapiCert type objects!
719 */
720 void
721 ckcapi_FetchLabel
722 (
723 ckcapiInternalObject *io
724 )
725 {
726 ckcapiCertObject *co = &io->u.cert;
727 char *label;
728 PCCERT_CONTEXT certContext = io->u.cert.certContext;
729 char labelDataUTF16[128];
730 DWORD size = sizeof(labelDataUTF16);
731 DWORD size8 = sizeof(co->labelData);
732 BOOL rv;
733
734 rv = CertGetCertificateContextProperty(certContext,
735 CERT_FRIENDLY_NAME_PROP_ID, labelDataUTF16, &size);
736 if (rv) {
737 co->labelData = nss_ckcapi_WideToUTF8((LPCWSTR)labelDataUTF16);
738 if ((CHAR *)NULL == co->labelData) {
739 rv = 0;
740 } else {
741 size = strlen(co->labelData);
742 }
743 }
744 label = co->labelData;
745 /* we are presuming a user cert, make sure it has a nickname, even if
746 * Microsoft never gave it one */
747 if (!rv && co->hasID) {
748 DWORD mserror = GetLastError();
749 #define DEFAULT_NICKNAME "no Microsoft nickname"
750 label = DEFAULT_NICKNAME;
751 size = sizeof(DEFAULT_NICKNAME);
752 rv = 1;
753 }
754
755 if (rv) {
756 co->label.data = label;
757 co->label.size = size;
758 }
759 return;
760 }
761
762 void
763 ckcapi_FetchSerial
764 (
765 ckcapiInternalObject *io
766 )
767 {
768 ckcapiCertObject *co = &io->u.cert;
769 PCCERT_CONTEXT certContext = io->u.cert.certContext;
770 DWORD size = sizeof(co->derSerial);
771
772 BOOL rc = CryptEncodeObject(X509_ASN_ENCODING,
773 X509_MULTI_BYTE_INTEGER,
774 &certContext->pCertInfo->SerialNumber,
775 co->derSerial,
776 &size);
777 if (rc) {
778 co->serial.data = co->derSerial;
779 co->serial.size = size;
780 }
781 return;
782 }
783
784 /*
785 * fetch the key ID.
786 */
787 void
788 ckcapi_FetchID
789 (
790 ckcapiInternalObject *io
791 )
792 {
793 PCCERT_CONTEXT certContext = io->u.cert.certContext;
794 DWORD size = 0;
795 BOOL rc;
796
797 rc = CertGetCertificateContextProperty(certContext,
798 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
799 if (!rc) {
800 return;
801 }
802 io->idData = nss_ZNEWARRAY(NULL, char, size);
803 if (io->idData == NULL) {
804 return;
805 }
806
807 rc = CertGetCertificateContextProperty(certContext,
808 CERT_KEY_IDENTIFIER_PROP_ID, io->idData, &size);
809 if (!rc) {
810 nss_ZFreeIf(io->idData);
811 io->idData = NULL;
812 return;
813 }
814 io->id.data = io->idData;
815 io->id.size = size;
816 return;
817 }
818
819 /*
820 * fetch the hash key.
821 */
822 void
823 ckcapi_CertFetchHashKey
824 (
825 ckcapiInternalObject *io
826 )
827 {
828 ckcapiCertObject *co = &io->u.cert;
829 PCCERT_CONTEXT certContext = io->u.cert.certContext;
830 DWORD size = certContext->cbCertEncoded;
831 DWORD max = sizeof(io->hashKeyData)-1;
832 DWORD offset = 0;
833
834 /* make sure we don't over flow. NOTE: cutting the top of a cert is
835 * not a big issue because the signature for will be unique for the cert */
836 if (size > max) {
837 offset = size - max;
838 size = max;
839 }
840
841 nsslibc_memcpy(io->hashKeyData,certContext->pbCertEncoded+offset, size);
842 io->hashKeyData[size] = (char)(io->objClass & 0xff);
843
844 io->hashKey.data = io->hashKeyData;
845 io->hashKey.size = size+1;
846 return;
847 }
848
849 /*
850 * fetch the hash key.
851 */
852 void
853 ckcapi_KeyFetchHashKey
854 (
855 ckcapiInternalObject *io
856 )
857 {
858 ckcapiKeyObject *ko = &io->u.key;
859 DWORD size;
860 DWORD max = sizeof(io->hashKeyData)-2;
861 DWORD offset = 0;
862 DWORD provLen = strlen(ko->provName);
863 DWORD containerLen = strlen(ko->containerName);
864
865
866 size = provLen + containerLen;
867
868 /* make sure we don't overflow, try to keep things unique */
869 if (size > max) {
870 DWORD diff = ((size - max)+1)/2;
871 provLen -= diff;
872 containerLen -= diff;
873 size = provLen+containerLen;
874 }
875
876 nsslibc_memcpy(io->hashKeyData, ko->provName, provLen);
877 nsslibc_memcpy(&io->hashKeyData[provLen],
878 ko->containerName,
879 containerLen);
880 io->hashKeyData[size] = (char)(io->objClass & 0xff);
881 io->hashKeyData[size+1] = (char)(ko->provInfo.dwKeySpec & 0xff);
882
883 io->hashKey.data = io->hashKeyData;
884 io->hashKey.size = size+2;
885 return;
886 }
887
888 /*
889 * fetch the hash key.
890 */
891 void
892 ckcapi_FetchHashKey
893 (
894 ckcapiInternalObject *io
895 )
896 {
897 if (ckcapiCert == io->type) {
898 ckcapi_CertFetchHashKey(io);
899 } else {
900 ckcapi_KeyFetchHashKey(io);
901 }
902 return;
903 }
904
905 const NSSItem *
906 ckcapi_FetchCertAttribute
907 (
908 ckcapiInternalObject *io,
909 CK_ATTRIBUTE_TYPE type
910 )
911 {
912 PCCERT_CONTEXT certContext = io->u.cert.certContext;
913 switch(type) {
914 case CKA_CLASS:
915 return &ckcapi_certClassItem;
916 case CKA_TOKEN:
917 return &ckcapi_trueItem;
918 case CKA_MODIFIABLE:
919 case CKA_PRIVATE:
920 return &ckcapi_falseItem;
921 case CKA_CERTIFICATE_TYPE:
922 return &ckcapi_x509Item;
923 case CKA_LABEL:
924 if (0 == io->u.cert.label.size) {
925 ckcapi_FetchLabel(io);
926 }
927 return &io->u.cert.label;
928 case CKA_SUBJECT:
929 if (0 == io->u.cert.subject.size) {
930 io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData;
931 io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData;
932 }
933 return &io->u.cert.subject;
934 case CKA_ISSUER:
935 if (0 == io->u.cert.issuer.size) {
936 io->u.cert.issuer.data = certContext->pCertInfo->Issuer.pbData;
937 io->u.cert.issuer.size = certContext->pCertInfo->Issuer.cbData;
938 }
939 return &io->u.cert.issuer;
940 case CKA_SERIAL_NUMBER:
941 if (0 == io->u.cert.serial.size) {
942 /* not exactly right. This should be the encoded serial number, but
943 * it's the decoded serial number! */
944 ckcapi_FetchSerial(io);
945 }
946 return &io->u.cert.serial;
947 case CKA_VALUE:
948 if (0 == io->u.cert.derCert.size) {
949 io->u.cert.derCert.data = io->u.cert.certContext->pbCertEncoded;
950 io->u.cert.derCert.size = io->u.cert.certContext->cbCertEncoded;
951 }
952 return &io->u.cert.derCert;
953 case CKA_ID:
954 if (!io->u.cert.hasID) {
955 return NULL;
956 }
957 if (0 == io->id.size) {
958 ckcapi_FetchID(io);
959 }
960 return &io->id;
961 default:
962 break;
963 }
964 return NULL;
965 }
966
967 const NSSItem *
968 ckcapi_FetchPubKeyAttribute
969 (
970 ckcapiInternalObject *io,
971 CK_ATTRIBUTE_TYPE type
972 )
973 {
974 PRBool isCertType = (ckcapiCert == io->type);
975 ckcapiKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key;
976
977 switch(type) {
978 case CKA_CLASS:
979 return &ckcapi_pubKeyClassItem;
980 case CKA_TOKEN:
981 case CKA_LOCAL:
982 case CKA_ENCRYPT:
983 case CKA_VERIFY:
984 case CKA_VERIFY_RECOVER:
985 return &ckcapi_trueItem;
986 case CKA_PRIVATE:
987 case CKA_MODIFIABLE:
988 case CKA_DERIVE:
989 case CKA_WRAP:
990 return &ckcapi_falseItem;
991 case CKA_KEY_TYPE:
992 return &ckcapi_rsaItem;
993 case CKA_LABEL:
994 if (!isCertType) {
995 return &ckcapi_emptyItem;
996 }
997 if (0 == io->u.cert.label.size) {
998 ckcapi_FetchLabel(io);
999 }
1000 return &io->u.cert.label;
1001 case CKA_SUBJECT:
1002 if (!isCertType) {
1003 return &ckcapi_emptyItem;
1004 }
1005 if (0 == io->u.cert.subject.size) {
1006 PCCERT_CONTEXT certContext= io->u.cert.certContext;
1007 io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData;
1008 io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData;
1009 }
1010 return &io->u.cert.subject;
1011 case CKA_MODULUS:
1012 if (0 == kp->modulus.size) {
1013 ckcapi_PopulateModulusExponent(io);
1014 }
1015 return &kp->modulus;
1016 case CKA_PUBLIC_EXPONENT:
1017 if (0 == kp->modulus.size) {
1018 ckcapi_PopulateModulusExponent(io);
1019 }
1020 return &kp->exponent;
1021 case CKA_ID:
1022 if (0 == io->id.size) {
1023 ckcapi_FetchID(io);
1024 }
1025 return &io->id;
1026 default:
1027 break;
1028 }
1029 return NULL;
1030 }
1031
1032 const NSSItem *
1033 ckcapi_FetchPrivKeyAttribute
1034 (
1035 ckcapiInternalObject *io,
1036 CK_ATTRIBUTE_TYPE type
1037 )
1038 {
1039 PRBool isCertType = (ckcapiCert == io->type);
1040 ckcapiKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key;
1041
1042 switch(type) {
1043 case CKA_CLASS:
1044 return &ckcapi_privKeyClassItem;
1045 case CKA_TOKEN:
1046 case CKA_LOCAL:
1047 case CKA_SIGN:
1048 case CKA_DECRYPT:
1049 case CKA_SIGN_RECOVER:
1050 return &ckcapi_trueItem;
1051 case CKA_SENSITIVE:
1052 case CKA_PRIVATE: /* should move in the future */
1053 case CKA_MODIFIABLE:
1054 case CKA_DERIVE:
1055 case CKA_UNWRAP:
1056 case CKA_EXTRACTABLE: /* will probably move in the future */
1057 case CKA_ALWAYS_SENSITIVE:
1058 case CKA_NEVER_EXTRACTABLE:
1059 return &ckcapi_falseItem;
1060 case CKA_KEY_TYPE:
1061 return &ckcapi_rsaItem;
1062 case CKA_LABEL:
1063 if (!isCertType) {
1064 return &ckcapi_emptyItem;
1065 }
1066 if (0 == io->u.cert.label.size) {
1067 ckcapi_FetchLabel(io);
1068 }
1069 return &io->u.cert.label;
1070 case CKA_SUBJECT:
1071 if (!isCertType) {
1072 return &ckcapi_emptyItem;
1073 }
1074 if (0 == io->u.cert.subject.size) {
1075 PCCERT_CONTEXT certContext= io->u.cert.certContext;
1076 io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData;
1077 io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData;
1078 }
1079 return &io->u.cert.subject;
1080 case CKA_MODULUS:
1081 if (0 == kp->modulus.size) {
1082 ckcapi_PopulateModulusExponent(io);
1083 }
1084 return &kp->modulus;
1085 case CKA_PUBLIC_EXPONENT:
1086 if (0 == kp->modulus.size) {
1087 ckcapi_PopulateModulusExponent(io);
1088 }
1089 return &kp->exponent;
1090 case CKA_PRIVATE_EXPONENT:
1091 if (0 == kp->privateExponent.size) {
1092 ckcapi_FetchPrivateKey(io);
1093 }
1094 return &kp->privateExponent;
1095 case CKA_PRIME_1:
1096 if (0 == kp->privateExponent.size) {
1097 ckcapi_FetchPrivateKey(io);
1098 }
1099 return &kp->prime1;
1100 case CKA_PRIME_2:
1101 if (0 == kp->privateExponent.size) {
1102 ckcapi_FetchPrivateKey(io);
1103 }
1104 return &kp->prime2;
1105 case CKA_EXPONENT_1:
1106 if (0 == kp->privateExponent.size) {
1107 ckcapi_FetchPrivateKey(io);
1108 }
1109 return &kp->exponent1;
1110 case CKA_EXPONENT_2:
1111 if (0 == kp->privateExponent.size) {
1112 ckcapi_FetchPrivateKey(io);
1113 }
1114 return &kp->exponent2;
1115 case CKA_COEFFICIENT:
1116 if (0 == kp->privateExponent.size) {
1117 ckcapi_FetchPrivateKey(io);
1118 }
1119 return &kp->coefficient;
1120 case CKA_ID:
1121 if (0 == io->id.size) {
1122 ckcapi_FetchID(io);
1123 }
1124 return &io->id;
1125 default:
1126 return NULL;
1127 }
1128 }
1129
1130 const NSSItem *
1131 nss_ckcapi_FetchAttribute
1132 (
1133 ckcapiInternalObject *io,
1134 CK_ATTRIBUTE_TYPE type
1135 )
1136 {
1137 CK_ULONG i;
1138
1139 if (io->type == ckcapiRaw) {
1140 for( i = 0; i < io->u.raw.n; i++ ) {
1141 if( type == io->u.raw.types[i] ) {
1142 return &io->u.raw.items[i];
1143 }
1144 }
1145 return NULL;
1146 }
1147 /* deal with the common attributes */
1148 switch (io->objClass) {
1149 case CKO_CERTIFICATE:
1150 return ckcapi_FetchCertAttribute(io, type);
1151 case CKO_PRIVATE_KEY:
1152 return ckcapi_FetchPrivKeyAttribute(io, type);
1153 case CKO_PUBLIC_KEY:
1154 return ckcapi_FetchPubKeyAttribute(io, type);
1155 }
1156 return NULL;
1157 }
1158
1159 /*
1160 * check to see if the certificate already exists
1161 */
1162 static PRBool
1163 ckcapi_cert_exists(
1164 NSSItem *value,
1165 ckcapiInternalObject **io
1166 )
1167 {
1168 int count,i;
1169 PRUint32 size = 0;
1170 ckcapiInternalObject **listp = NULL;
1171 CK_ATTRIBUTE myTemplate[2];
1172 CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE;
1173 CK_ULONG templateCount = 2;
1174 CK_RV error;
1175 PRBool found = PR_FALSE;
1176
1177 myTemplate[0].type = CKA_CLASS;
1178 myTemplate[0].pValue = &cert_class;
1179 myTemplate[0].ulValueLen = sizeof(cert_class);
1180 myTemplate[1].type = CKA_VALUE;
1181 myTemplate[1].pValue = value->data;
1182 myTemplate[1].ulValueLen = value->size;
1183
1184 count = nss_ckcapi_collect_all_certs(myTemplate, templateCount, &listp,
1185 &size, 0, &error);
1186
1187 /* free them */
1188 if (count > 1) {
1189 *io = listp[0];
1190 found = PR_TRUE;
1191 }
1192
1193 for (i=1; i < count; i++) {
1194 nss_ckcapi_DestroyInternalObject(listp[i]);
1195 }
1196 nss_ZFreeIf(listp);
1197 return found;
1198 }
1199
1200 static PRBool
1201 ckcapi_cert_hasEmail
1202 (
1203 PCCERT_CONTEXT certContext
1204 )
1205 {
1206 int count;
1207
1208 count = CertGetNameString(certContext, CERT_NAME_EMAIL_TYPE,
1209 0, NULL, NULL, 0);
1210
1211 return count > 1 ? PR_TRUE : PR_FALSE;
1212 }
1213
1214 static PRBool
1215 ckcapi_cert_isRoot
1216 (
1217 PCCERT_CONTEXT certContext
1218 )
1219 {
1220 return CertCompareCertificateName(certContext->dwCertEncodingType,
1221 &certContext->pCertInfo->Issuer, &certContext->pCertInfo->Subject);
1222 }
1223
1224 static PRBool
1225 ckcapi_cert_isCA
1226 (
1227 PCCERT_CONTEXT certContext
1228 )
1229 {
1230 PCERT_EXTENSION extension;
1231 CERT_BASIC_CONSTRAINTS2_INFO basicInfo;
1232 DWORD size = sizeof(basicInfo);
1233 BOOL rc;
1234
1235 extension = CertFindExtension (szOID_BASIC_CONSTRAINTS,
1236 certContext->pCertInfo->cExtension,
1237 certContext->pCertInfo->rgExtension);
1238 if ((PCERT_EXTENSION) NULL == extension ) {
1239 return PR_FALSE;
1240 }
1241 rc = CryptDecodeObject(X509_ASN_ENCODING, szOID_BASIC_CONSTRAINTS2,
1242 extension->Value.pbData, extension->Value.cbData,
1243 0, &basicInfo, &size);
1244 if (!rc) {
1245 return PR_FALSE;
1246 }
1247 return (PRBool) basicInfo.fCA;
1248 }
1249
1250 static CRYPT_KEY_PROV_INFO *
1251 ckcapi_cert_getPrivateKeyInfo
1252 (
1253 PCCERT_CONTEXT certContext,
1254 NSSItem *keyID
1255 )
1256 {
1257 BOOL rc;
1258 CRYPT_HASH_BLOB msKeyID;
1259 DWORD size = 0;
1260 CRYPT_KEY_PROV_INFO *prov = NULL;
1261
1262 msKeyID.cbData = keyID->size;
1263 msKeyID.pbData = keyID->data;
1264
1265 rc = CryptGetKeyIdentifierProperty(
1266 &msKeyID,
1267 CERT_KEY_PROV_INFO_PROP_ID,
1268 0, NULL, NULL, NULL, &size);
1269 if (!rc) {
1270 return (CRYPT_KEY_PROV_INFO *)NULL;
1271 }
1272 prov = (CRYPT_KEY_PROV_INFO *)nss_ZAlloc(NULL, size);
1273 if ((CRYPT_KEY_PROV_INFO *)prov == NULL) {
1274 return (CRYPT_KEY_PROV_INFO *) NULL;
1275 }
1276 rc = CryptGetKeyIdentifierProperty(
1277 &msKeyID,
1278 CERT_KEY_PROV_INFO_PROP_ID,
1279 0, NULL, NULL, prov, &size);
1280 if (!rc) {
1281 nss_ZFreeIf(prov);
1282 return (CRYPT_KEY_PROV_INFO *)NULL;
1283 }
1284
1285 return prov;
1286 }
1287
1288 static CRYPT_KEY_PROV_INFO *
1289 ckcapi_cert_getProvInfo
1290 (
1291 ckcapiInternalObject *io
1292 )
1293 {
1294 BOOL rc;
1295 DWORD size = 0;
1296 CRYPT_KEY_PROV_INFO *prov = NULL;
1297
1298 rc = CertGetCertificateContextProperty(
1299 io->u.cert.certContext,
1300 CERT_KEY_PROV_INFO_PROP_ID,
1301 NULL, &size);
1302 if (!rc) {
1303 return (CRYPT_KEY_PROV_INFO *)NULL;
1304 }
1305 prov = (CRYPT_KEY_PROV_INFO *)nss_ZAlloc(NULL, size);
1306 if ((CRYPT_KEY_PROV_INFO *)prov == NULL) {
1307 return (CRYPT_KEY_PROV_INFO *) NULL;
1308 }
1309 rc = CertGetCertificateContextProperty(
1310 io->u.cert.certContext,
1311 CERT_KEY_PROV_INFO_PROP_ID,
1312 prov, &size);
1313 if (!rc) {
1314 nss_ZFreeIf(prov);
1315 return (CRYPT_KEY_PROV_INFO *)NULL;
1316 }
1317
1318 return prov;
1319 }
1320
1321 /* forward declaration */
1322 static void
1323 ckcapi_removeObjectFromHash
1324 (
1325 ckcapiInternalObject *io
1326 );
1327
1328 /*
1329 * Finalize - unneeded
1330 * Destroy
1331 * IsTokenObject - CK_TRUE
1332 * GetAttributeCount
1333 * GetAttributeTypes
1334 * GetAttributeSize
1335 * GetAttribute
1336 * SetAttribute
1337 * GetObjectSize
1338 */
1339
1340 static CK_RV
1341 ckcapi_mdObject_Destroy
1342 (
1343 NSSCKMDObject *mdObject,
1344 NSSCKFWObject *fwObject,
1345 NSSCKMDSession *mdSession,
1346 NSSCKFWSession *fwSession,
1347 NSSCKMDToken *mdToken,
1348 NSSCKFWToken *fwToken,
1349 NSSCKMDInstance *mdInstance,
1350 NSSCKFWInstance *fwInstance
1351 )
1352 {
1353 ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
1354 CK_OBJECT_CLASS objClass;
1355 BOOL rc;
1356 DWORD provType;
1357 DWORD msError;
1358 PRBool isCertType = (PRBool)(ckcapiCert == io->type);
1359 HCERTSTORE hStore = 0;
1360
1361 if (ckcapiRaw == io->type) {
1362 /* there is not 'object write protected' error, use the next best thing */
1363 return CKR_TOKEN_WRITE_PROTECTED;
1364 }
1365
1366 objClass = io->objClass;
1367 if (CKO_CERTIFICATE == objClass) {
1368 PCCERT_CONTEXT certContext;
1369
1370 /* get the store */
1371 hStore = CertOpenSystemStore(0, io->u.cert.certStore);
1372 if (0 == hStore) {
1373 rc = 0;
1374 goto loser;
1375 }
1376 certContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING, 0,
1377 CERT_FIND_EXISTING, io->u.cert.certContext, NULL);
1378 if ((PCCERT_CONTEXT)NULL == certContext) {
1379 rc = 0;
1380 goto loser;
1381 }
1382 rc = CertDeleteCertificateFromStore(certContext);
1383 } else {
1384 char *provName = NULL;
1385 char *containerName = NULL;
1386 HCRYPTPROV hProv;
1387 CRYPT_HASH_BLOB msKeyID;
1388
1389 if (0 == io->id.size) {
1390 ckcapi_FetchID(io);
1391 }
1392
1393 if (isCertType) {
1394 CRYPT_KEY_PROV_INFO * provInfo = ckcapi_cert_getProvInfo(io);
1395 provName = nss_ckcapi_WideToUTF8(provInfo->pwszProvName);
1396 containerName = nss_ckcapi_WideToUTF8(provInfo->pwszContainerName);
1397 provType = provInfo->dwProvType;
1398 nss_ZFreeIf(provInfo);
1399 } else {
1400 provName = io->u.key.provName;
1401 containerName = io->u.key.containerName;
1402 provType = io->u.key.provInfo.dwProvType;
1403 io->u.key.provName = NULL;
1404 io->u.key.containerName = NULL;
1405 }
1406 /* first remove the key id pointer */
1407 msKeyID.cbData = io->id.size;
1408 msKeyID.pbData = io->id.data;
1409 rc = CryptSetKeyIdentifierProperty(&msKeyID,
1410 CERT_KEY_PROV_INFO_PROP_ID, CRYPT_KEYID_DELETE_FLAG, NULL, NULL, NULL);
1411 if (rc) {
1412 rc = CryptAcquireContext(&hProv, containerName, provName, provType,
1413 CRYPT_DELETEKEYSET);
1414 }
1415 nss_ZFreeIf(provName);
1416 nss_ZFreeIf(containerName);
1417 }
1418 loser:
1419
1420 if (hStore) {
1421 CertCloseStore(hStore, 0);
1422 }
1423 if (!rc) {
1424 msError = GetLastError();
1425 return CKR_GENERAL_ERROR;
1426 }
1427
1428 /* remove it from the hash */
1429 ckcapi_removeObjectFromHash(io);
1430
1431 /* free the puppy.. */
1432 nss_ckcapi_DestroyInternalObject(io);
1433 return CKR_OK;
1434 }
1435
1436 static CK_BBOOL
1437 ckcapi_mdObject_IsTokenObject
1438 (
1439 NSSCKMDObject *mdObject,
1440 NSSCKFWObject *fwObject,
1441 NSSCKMDSession *mdSession,
1442 NSSCKFWSession *fwSession,
1443 NSSCKMDToken *mdToken,
1444 NSSCKFWToken *fwToken,
1445 NSSCKMDInstance *mdInstance,
1446 NSSCKFWInstance *fwInstance
1447 )
1448 {
1449 return CK_TRUE;
1450 }
1451
1452 static CK_ULONG
1453 ckcapi_mdObject_GetAttributeCount
1454 (
1455 NSSCKMDObject *mdObject,
1456 NSSCKFWObject *fwObject,
1457 NSSCKMDSession *mdSession,
1458 NSSCKFWSession *fwSession,
1459 NSSCKMDToken *mdToken,
1460 NSSCKFWToken *fwToken,
1461 NSSCKMDInstance *mdInstance,
1462 NSSCKFWInstance *fwInstance,
1463 CK_RV *pError
1464 )
1465 {
1466 ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
1467
1468 if (ckcapiRaw == io->type) {
1469 return io->u.raw.n;
1470 }
1471 switch (io->objClass) {
1472 case CKO_CERTIFICATE:
1473 return certAttrsCount;
1474 case CKO_PUBLIC_KEY:
1475 return pubKeyAttrsCount;
1476 case CKO_PRIVATE_KEY:
1477 return privKeyAttrsCount;
1478 default:
1479 break;
1480 }
1481 return 0;
1482 }
1483
1484 static CK_RV
1485 ckcapi_mdObject_GetAttributeTypes
1486 (
1487 NSSCKMDObject *mdObject,
1488 NSSCKFWObject *fwObject,
1489 NSSCKMDSession *mdSession,
1490 NSSCKFWSession *fwSession,
1491 NSSCKMDToken *mdToken,
1492 NSSCKFWToken *fwToken,
1493 NSSCKMDInstance *mdInstance,
1494 NSSCKFWInstance *fwInstance,
1495 CK_ATTRIBUTE_TYPE_PTR typeArray,
1496 CK_ULONG ulCount
1497 )
1498 {
1499 ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
1500 CK_ULONG i;
1501 CK_RV error = CKR_OK;
1502 const CK_ATTRIBUTE_TYPE *attrs = NULL;
1503 CK_ULONG size = ckcapi_mdObject_GetAttributeCount(
1504 mdObject, fwObject, mdSession, fwSession,
1505 mdToken, fwToken, mdInstance, fwInstance, &error);
1506
1507 if( size != ulCount ) {
1508 return CKR_BUFFER_TOO_SMALL;
1509 }
1510 if (io->type == ckcapiRaw) {
1511 attrs = io->u.raw.types;
1512 } else switch(io->objClass) {
1513 case CKO_CERTIFICATE:
1514 attrs = certAttrs;
1515 break;
1516 case CKO_PUBLIC_KEY:
1517 attrs = pubKeyAttrs;
1518 break;
1519 case CKO_PRIVATE_KEY:
1520 attrs = privKeyAttrs;
1521 break;
1522 default:
1523 return CKR_OK;
1524 }
1525
1526 for( i = 0; i < size; i++) {
1527 typeArray[i] = attrs[i];
1528 }
1529
1530 return CKR_OK;
1531 }
1532
1533 static CK_ULONG
1534 ckcapi_mdObject_GetAttributeSize
1535 (
1536 NSSCKMDObject *mdObject,
1537 NSSCKFWObject *fwObject,
1538 NSSCKMDSession *mdSession,
1539 NSSCKFWSession *fwSession,
1540 NSSCKMDToken *mdToken,
1541 NSSCKFWToken *fwToken,
1542 NSSCKMDInstance *mdInstance,
1543 NSSCKFWInstance *fwInstance,
1544 CK_ATTRIBUTE_TYPE attribute,
1545 CK_RV *pError
1546 )
1547 {
1548 ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
1549
1550 const NSSItem *b;
1551
1552 b = nss_ckcapi_FetchAttribute(io, attribute);
1553
1554 if ((const NSSItem *)NULL == b) {
1555 *pError = CKR_ATTRIBUTE_TYPE_INVALID;
1556 return 0;
1557 }
1558 return b->size;
1559 }
1560
1561 static CK_RV
1562 ckcapi_mdObject_SetAttribute
1563 (
1564 NSSCKMDObject *mdObject,
1565 NSSCKFWObject *fwObject,
1566 NSSCKMDSession *mdSession,
1567 NSSCKFWSession *fwSession,
1568 NSSCKMDToken *mdToken,
1569 NSSCKFWToken *fwToken,
1570 NSSCKMDInstance *mdInstance,
1571 NSSCKFWInstance *fwInstance,
1572 CK_ATTRIBUTE_TYPE attribute,
1573 NSSItem *value
1574 )
1575 {
1576 return CKR_OK;
1577 }
1578
1579 static NSSCKFWItem
1580 ckcapi_mdObject_GetAttribute
1581 (
1582 NSSCKMDObject *mdObject,
1583 NSSCKFWObject *fwObject,
1584 NSSCKMDSession *mdSession,
1585 NSSCKFWSession *fwSession,
1586 NSSCKMDToken *mdToken,
1587 NSSCKFWToken *fwToken,
1588 NSSCKMDInstance *mdInstance,
1589 NSSCKFWInstance *fwInstance,
1590 CK_ATTRIBUTE_TYPE attribute,
1591 CK_RV *pError
1592 )
1593 {
1594 NSSCKFWItem mdItem;
1595 ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
1596
1597 mdItem.needsFreeing = PR_FALSE;
1598 mdItem.item = (NSSItem*)nss_ckcapi_FetchAttribute(io, attribute);
1599
1600 if ((NSSItem *)NULL == mdItem.item) {
1601 *pError = CKR_ATTRIBUTE_TYPE_INVALID;
1602 }
1603
1604 return mdItem;
1605 }
1606
1607 static CK_ULONG
1608 ckcapi_mdObject_GetObjectSize
1609 (
1610 NSSCKMDObject *mdObject,
1611 NSSCKFWObject *fwObject,
1612 NSSCKMDSession *mdSession,
1613 NSSCKFWSession *fwSession,
1614 NSSCKMDToken *mdToken,
1615 NSSCKFWToken *fwToken,
1616 NSSCKMDInstance *mdInstance,
1617 NSSCKFWInstance *fwInstance,
1618 CK_RV *pError
1619 )
1620 {
1621 ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
1622 CK_ULONG rv = 1;
1623
1624 /* size is irrelevant to this token */
1625 return rv;
1626 }
1627
1628 static const NSSCKMDObject
1629 ckcapi_prototype_mdObject = {
1630 (void *)NULL, /* etc */
1631 NULL, /* Finalize */
1632 ckcapi_mdObject_Destroy,
1633 ckcapi_mdObject_IsTokenObject,
1634 ckcapi_mdObject_GetAttributeCount,
1635 ckcapi_mdObject_GetAttributeTypes,
1636 ckcapi_mdObject_GetAttributeSize,
1637 ckcapi_mdObject_GetAttribute,
1638 NULL, /* FreeAttribute */
1639 ckcapi_mdObject_SetAttribute,
1640 ckcapi_mdObject_GetObjectSize,
1641 (void *)NULL /* null terminator */
1642 };
1643
1644 static nssHash *ckcapiInternalObjectHash = NULL;
1645
1646 NSS_IMPLEMENT NSSCKMDObject *
1647 nss_ckcapi_CreateMDObject
1648 (
1649 NSSArena *arena,
1650 ckcapiInternalObject *io,
1651 CK_RV *pError
1652 )
1653 {
1654 if ((nssHash *)NULL == ckcapiInternalObjectHash) {
1655 ckcapiInternalObjectHash = nssHash_CreateItem(NULL, 10);
1656 }
1657 if (ckcapiCert == io->type) {
1658 /* the hash key, not a cryptographic key */
1659 NSSItem *key = &io->hashKey;
1660 ckcapiInternalObject *old_o = NULL;
1661
1662 if (key->size == 0) {
1663 ckcapi_FetchHashKey(io);
1664 }
1665 old_o = (ckcapiInternalObject *)
1666 nssHash_Lookup(ckcapiInternalObjectHash, key);
1667 if (!old_o) {
1668 nssHash_Add(ckcapiInternalObjectHash, key, io);
1669 } else if (old_o != io) {
1670 nss_ckcapi_DestroyInternalObject(io);
1671 io = old_o;
1672 }
1673 }
1674
1675 if ( (void*)NULL == io->mdObject.etc) {
1676 (void) nsslibc_memcpy(&io->mdObject,&ckcapi_prototype_mdObject,
1677 sizeof(ckcapi_prototype_mdObject));
1678 io->mdObject.etc = (void *)io;
1679 }
1680 return &io->mdObject;
1681 }
1682
1683 static void
1684 ckcapi_removeObjectFromHash
1685 (
1686 ckcapiInternalObject *io
1687 )
1688 {
1689 NSSItem *key = &io->hashKey;
1690
1691 if ((nssHash *)NULL == ckcapiInternalObjectHash) {
1692 return;
1693 }
1694 if (key->size == 0) {
1695 ckcapi_FetchHashKey(io);
1696 }
1697 nssHash_Remove(ckcapiInternalObjectHash, key);
1698 return;
1699 }
1700
1701 void
1702 nss_ckcapi_DestroyInternalObject
1703 (
1704 ckcapiInternalObject *io
1705 )
1706 {
1707 switch (io->type) {
1708 case ckcapiRaw:
1709 return;
1710 case ckcapiCert:
1711 CertFreeCertificateContext(io->u.cert.certContext);
1712 nss_ZFreeIf(io->u.cert.labelData);
1713 nss_ZFreeIf(io->u.cert.key.privateKey);
1714 nss_ZFreeIf(io->u.cert.key.pubKey);
1715 nss_ZFreeIf(io->idData);
1716 break;
1717 case ckcapiBareKey:
1718 nss_ZFreeIf(io->u.key.provInfo.pwszContainerName);
1719 nss_ZFreeIf(io->u.key.provInfo.pwszProvName);
1720 nss_ZFreeIf(io->u.key.provName);
1721 nss_ZFreeIf(io->u.key.containerName);
1722 nss_ZFreeIf(io->u.key.key.privateKey);
1723 nss_ZFreeIf(io->u.key.key.pubKey);
1724 if (0 != io->u.key.hProv) {
1725 CryptReleaseContext(io->u.key.hProv, 0);
1726 }
1727 nss_ZFreeIf(io->idData);
1728 break;
1729 }
1730 nss_ZFreeIf(io);
1731 return;
1732 }
1733
1734 static ckcapiInternalObject *
1735 nss_ckcapi_CreateCertificate
1736 (
1737 NSSCKFWSession *fwSession,
1738 CK_ATTRIBUTE_PTR pTemplate,
1739 CK_ULONG ulAttributeCount,
1740 CK_RV *pError
1741 )
1742 {
1743 NSSItem value;
1744 NSSItem keyID;
1745 char *storeStr;
1746 ckcapiInternalObject *io = NULL;
1747 PCCERT_CONTEXT certContext = NULL;
1748 PCCERT_CONTEXT storedCertContext = NULL;
1749 CRYPT_KEY_PROV_INFO *prov_info = NULL;
1750 char *nickname = NULL;
1751 HCERTSTORE hStore = 0;
1752 DWORD msError = 0;
1753 PRBool hasID;
1754 CK_RV dummy;
1755 BOOL rc;
1756
1757 *pError = nss_ckcapi_GetAttribute(CKA_VALUE, pTemplate,
1758 ulAttributeCount, &value);
1759
1760 if (CKR_OK != *pError) {
1761 return (ckcapiInternalObject *)NULL;
1762 }
1763
1764 *pError = nss_ckcapi_GetAttribute(CKA_ID, pTemplate,
1765 ulAttributeCount, &keyID);
1766
1767 if (CKR_OK != *pError) {
1768 return (ckcapiInternalObject *)NULL;
1769 }
1770
1771 if (ckcapi_cert_exists(&value, &io)) {
1772 return io;
1773 }
1774
1775 /* OK, we are creating a new one, figure out what store it belongs to..
1776 * first get a certContext handle.. */
1777 certContext = CertCreateCertificateContext(X509_ASN_ENCODING,
1778 value.data, value.size);
1779 if ((PCCERT_CONTEXT) NULL == certContext) {
1780 msError = GetLastError();
1781 *pError = CKR_ATTRIBUTE_VALUE_INVALID;
1782 goto loser;
1783 }
1784
1785 /* do we have a private key laying around... */
1786 prov_info = ckcapi_cert_getPrivateKeyInfo(certContext, &keyID);
1787 if (prov_info) {
1788 CRYPT_DATA_BLOB msKeyID;
1789 storeStr = "My";
1790 hasID = PR_TRUE;
1791 rc = CertSetCertificateContextProperty(certContext,
1792 CERT_KEY_PROV_INFO_PROP_ID,
1793 0, prov_info);
1794 nss_ZFreeIf(prov_info);
1795 if (!rc) {
1796 msError = GetLastError();
1797 *pError = CKR_DEVICE_ERROR;
1798 goto loser;
1799 }
1800 msKeyID.cbData = keyID.size;
1801 msKeyID.pbData = keyID.data;
1802 rc = CertSetCertificateContextProperty(certContext,
1803 CERT_KEY_IDENTIFIER_PROP_ID,
1804 0, &msKeyID);
1805 if (!rc) {
1806 msError = GetLastError();
1807 *pError = CKR_DEVICE_ERROR;
1808 goto loser;
1809 }
1810
1811 /* does it look like a CA */
1812 } else if (ckcapi_cert_isCA(certContext)) {
1813 storeStr = ckcapi_cert_isRoot(certContext) ? "CA" : "Root";
1814 /* does it look like an S/MIME cert */
1815 } else if (ckcapi_cert_hasEmail(certContext)) {
1816 storeStr = "AddressBook";
1817 } else {
1818 /* just pick a store */
1819 storeStr = "CA";
1820 }
1821
1822 /* get the nickname, not an error if we can't find it */
1823 nickname = nss_ckcapi_GetStringAttribute(CKA_LABEL, pTemplate,
1824 ulAttributeCount, &dummy);
1825 if (nickname) {
1826 LPWSTR nicknameUTF16 = NULL;
1827 CRYPT_DATA_BLOB nicknameBlob;
1828
1829 nicknameUTF16 = nss_ckcapi_UTF8ToWide(nickname);
1830 nss_ZFreeIf(nickname);
1831 nickname = NULL;
1832 if ((LPWSTR)NULL == nicknameUTF16) {
1833 *pError = CKR_HOST_MEMORY;
1834 goto loser;
1835 }
1836 nicknameBlob.cbData = nss_ckcapi_WideSize(nicknameUTF16);
1837 nicknameBlob.pbData = (BYTE *)nicknameUTF16;
1838 rc = CertSetCertificateContextProperty(certContext,
1839 CERT_FRIENDLY_NAME_PROP_ID, 0, &nicknameBlob);
1840 nss_ZFreeIf(nicknameUTF16);
1841 if (!rc) {
1842 msError = GetLastError();
1843 *pError = CKR_DEVICE_ERROR;
1844 goto loser;
1845 }
1846 }
1847
1848 hStore = CertOpenSystemStore((HCRYPTPROV) NULL, storeStr);
1849 if (0 == hStore) {
1850 msError = GetLastError();
1851 *pError = CKR_DEVICE_ERROR;
1852 goto loser;
1853 }
1854
1855 rc = CertAddCertificateContextToStore(hStore, certContext,
1856 CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES, &storedCertContext);
1857 CertFreeCertificateContext(certContext);
1858 certContext = NULL;
1859 CertCloseStore(hStore, 0);
1860 hStore = 0;
1861 if (!rc) {
1862 msError = GetLastError();
1863 *pError = CKR_DEVICE_ERROR;
1864 goto loser;
1865 }
1866
1867 io = nss_ZNEW(NULL, ckcapiInternalObject);
1868 if ((ckcapiInternalObject *)NULL == io) {
1869 *pError = CKR_HOST_MEMORY;
1870 goto loser;
1871 }
1872 io->type = ckcapiCert;
1873 io->objClass = CKO_CERTIFICATE;
1874 io->u.cert.certContext = storedCertContext;
1875 io->u.cert.hasID = hasID;
1876 return io;
1877
1878 loser:
1879 if (certContext) {
1880 CertFreeCertificateContext(certContext);
1881 certContext = NULL;
1882 }
1883 if (storedCertContext) {
1884 CertFreeCertificateContext(storedCertContext);
1885 storedCertContext = NULL;
1886 }
1887 if (0 != hStore) {
1888 CertCloseStore(hStore, 0);
1889 }
1890 return (ckcapiInternalObject *)NULL;
1891
1892 }
1893
1894 static char *
1895 ckcapi_getDefaultProvider
1896 (
1897 CK_RV *pError
1898 )
1899 {
1900 char *name = NULL;
1901 BOOL rc;
1902 DWORD nameLength = 0;
1903
1904 rc = CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_USER_DEFAULT, NULL,
1905 &nameLength);
1906 if (!rc) {
1907 return (char *)NULL;
1908 }
1909
1910 name = nss_ZNEWARRAY(NULL, char, nameLength);
1911 if ((char *)NULL == name ) {
1912 return (char *)NULL;
1913 }
1914 rc = CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_USER_DEFAULT, name,
1915 &nameLength);
1916 if (!rc) {
1917 nss_ZFreeIf(name);
1918 return (char *)NULL;
1919 }
1920
1921 return name;
1922 }
1923
1924 static char *
1925 ckcapi_getContainer
1926 (
1927 CK_RV *pError,
1928 NSSItem *id
1929 )
1930 {
1931 RPC_STATUS rstat;
1932 UUID uuid;
1933 char *uuidStr;
1934 char *container;
1935
1936 rstat = UuidCreate(&uuid);
1937 rstat = UuidToString(&uuid, &uuidStr);
1938
1939 /* convert it from rcp memory to our own */
1940 container = nssUTF8_Duplicate(uuidStr, NULL);
1941 RpcStringFree(&uuidStr);
1942
1943 return container;
1944 }
1945
1946 static CK_RV
1947 ckcapi_buildPrivateKeyBlob
1948 (
1949 NSSItem *keyBlob,
1950 NSSItem *modulus,
1951 NSSItem *publicExponent,
1952 NSSItem *privateExponent,
1953 NSSItem *prime1,
1954 NSSItem *prime2,
1955 NSSItem *exponent1,
1956 NSSItem *exponent2,
1957 NSSItem *coefficient,
1958 PRBool isKeyExchange
1959 )
1960 {
1961 CAPI_RSA_KEY_BLOB *keyBlobData = NULL;
1962 unsigned char *target;
1963 unsigned long modSize = modulus->size;
1964 unsigned long dataSize;
1965 CK_RV error = CKR_OK;
1966
1967 /* validate extras */
1968 if (privateExponent->size != modSize) {
1969 error = CKR_ATTRIBUTE_VALUE_INVALID;
1970 goto loser;
1971 }
1972 if (prime1->size != modSize/2) {
1973 error = CKR_ATTRIBUTE_VALUE_INVALID;
1974 goto loser;
1975 }
1976 if (prime2->size != modSize/2) {
1977 error = CKR_ATTRIBUTE_VALUE_INVALID;
1978 goto loser;
1979 }
1980 if (exponent1->size != modSize/2) {
1981 error = CKR_ATTRIBUTE_VALUE_INVALID;
1982 goto loser;
1983 }
1984 if (exponent2->size != modSize/2) {
1985 error = CKR_ATTRIBUTE_VALUE_INVALID;
1986 goto loser;
1987 }
1988 if (coefficient->size != modSize/2) {
1989 error = CKR_ATTRIBUTE_VALUE_INVALID;
1990 goto loser;
1991 }
1992 dataSize = (modSize*4)+(modSize/2) + sizeof(CAPI_RSA_KEY_BLOB);
1993 keyBlobData = (CAPI_RSA_KEY_BLOB *)nss_ZAlloc(NULL, dataSize);
1994 if ((CAPI_RSA_KEY_BLOB *)NULL == keyBlobData) {
1995 error = CKR_HOST_MEMORY;
1996 goto loser;
1997 }
1998
1999 keyBlobData->header.bType = PRIVATEKEYBLOB;
2000 keyBlobData->header.bVersion = 0x02;
2001 keyBlobData->header.reserved = 0x00;
2002 keyBlobData->header.aiKeyAlg = isKeyExchange ? CALG_RSA_KEYX:CALG_RSA_SIGN;
2003 keyBlobData->rsa.magic = 0x32415352;
2004 keyBlobData->rsa.bitlen = modSize * 8;
2005 keyBlobData->rsa.pubexp = nss_ckcapi_DataToInt(publicExponent,&error);
2006 if (CKR_OK != error) {
2007 goto loser;
2008 }
2009
2010 target = &keyBlobData->data[CAPI_MODULUS_OFFSET(modSize)];
2011 nsslibc_memcpy(target, modulus->data, modulus->size);
2012 modulus->data = target;
2013 ckcapi_ReverseData(modulus);
2014
2015 target = &keyBlobData->data[CAPI_PRIVATE_EXP_OFFSET(modSize)];
2016 nsslibc_memcpy(target, privateExponent->data, privateExponent->size);
2017 privateExponent->data = target;
2018 ckcapi_ReverseData(privateExponent);
2019
2020 target = &keyBlobData->data[CAPI_PRIME_1_OFFSET(modSize)];
2021 nsslibc_memcpy(target, prime1->data, prime1->size);
2022 prime1->data = target;
2023 ckcapi_ReverseData(prime1);
2024
2025 target = &keyBlobData->data[CAPI_PRIME_2_OFFSET(modSize)];
2026 nsslibc_memcpy(target, prime2->data, prime2->size);
2027 prime2->data = target;
2028 ckcapi_ReverseData(prime2);
2029
2030 target = &keyBlobData->data[CAPI_EXPONENT_1_OFFSET(modSize)];
2031 nsslibc_memcpy(target, exponent1->data, exponent1->size);
2032 exponent1->data = target;
2033 ckcapi_ReverseData(exponent1);
2034
2035 target = &keyBlobData->data[CAPI_EXPONENT_2_OFFSET(modSize)];
2036 nsslibc_memcpy(target, exponent2->data, exponent2->size);
2037 exponent2->data = target;
2038 ckcapi_ReverseData(exponent2);
2039
2040 target = &keyBlobData->data[CAPI_COEFFICIENT_OFFSET(modSize)];
2041 nsslibc_memcpy(target, coefficient->data, coefficient->size);
2042 coefficient->data = target;
2043 ckcapi_ReverseData(coefficient);
2044
2045 keyBlob->data = keyBlobData;
2046 keyBlob->size = dataSize;
2047
2048 return CKR_OK;
2049
2050 loser:
2051 nss_ZFreeIf(keyBlobData);
2052 return error;
2053 }
2054
2055 static ckcapiInternalObject *
2056 nss_ckcapi_CreatePrivateKey
2057 (
2058 NSSCKFWSession *fwSession,
2059 CK_ATTRIBUTE_PTR pTemplate,
2060 CK_ULONG ulAttributeCount,
2061 CK_RV *pError
2062 )
2063 {
2064 NSSItem modulus;
2065 NSSItem publicExponent;
2066 NSSItem privateExponent;
2067 NSSItem exponent1;
2068 NSSItem exponent2;
2069 NSSItem prime1;
2070 NSSItem prime2;
2071 NSSItem coefficient;
2072 NSSItem keyID;
2073 NSSItem keyBlob;
2074 ckcapiInternalObject *io = NULL;
2075 char *providerName = NULL;
2076 char *containerName = NULL;
2077 char *idData = NULL;
2078 CRYPT_KEY_PROV_INFO provInfo;
2079 CRYPT_HASH_BLOB msKeyID;
2080 CK_KEY_TYPE keyType;
2081 HCRYPTPROV hProv = 0;
2082 HCRYPTKEY hKey = 0;
2083 PRBool decrypt;
2084 DWORD keySpec;
2085 DWORD msError;
2086 BOOL rc;
2087
2088 keyType = nss_ckcapi_GetULongAttribute
2089 (CKA_KEY_TYPE, pTemplate, ulAttributeCount, pError);
2090 if (CKR_OK != *pError) {
2091 return (ckcapiInternalObject *)NULL;
2092 }
2093 if (CKK_RSA != keyType) {
2094 *pError = CKR_ATTRIBUTE_VALUE_INVALID;
2095 return (ckcapiInternalObject *)NULL;
2096 }
2097
2098 decrypt = nss_ckcapi_GetBoolAttribute(CKA_DECRYPT,
2099 pTemplate, ulAttributeCount, pError);
2100 if (CKR_TEMPLATE_INCOMPLETE == *pError) {
2101 decrypt = PR_TRUE; /* default to true */
2102 }
2103 decrypt = decrypt || nss_ckcapi_GetBoolAttribute(CKA_UNWRAP,
2104 pTemplate, ulAttributeCount, pError);
2105 if (CKR_TEMPLATE_INCOMPLETE == *pError) {
2106 decrypt = PR_TRUE; /* default to true */
2107 }
2108 keySpec = decrypt ? AT_KEYEXCHANGE : AT_SIGNATURE;
2109
2110 *pError = nss_ckcapi_GetAttribute(CKA_MODULUS, pTemplate,
2111 ulAttributeCount, &modulus);
2112 if (CKR_OK != *pError) {
2113 return (ckcapiInternalObject *)NULL;
2114 }
2115 *pError = nss_ckcapi_GetAttribute(CKA_PUBLIC_EXPONENT, pTemplate,
2116 ulAttributeCount, &publicExponent);
2117 if (CKR_OK != *pError) {
2118 return (ckcapiInternalObject *)NULL;
2119 }
2120 *pError = nss_ckcapi_GetAttribute(CKA_PRIVATE_EXPONENT, pTemplate,
2121 ulAttributeCount, &privateExponent);
2122 if (CKR_OK != *pError) {
2123 return (ckcapiInternalObject *)NULL;
2124 }
2125 *pError = nss_ckcapi_GetAttribute(CKA_PRIME_1, pTemplate,
2126 ulAttributeCount, &prime1);
2127 if (CKR_OK != *pError) {
2128 return (ckcapiInternalObject *)NULL;
2129 }
2130 *pError = nss_ckcapi_GetAttribute(CKA_PRIME_2, pTemplate,
2131 ulAttributeCount, &prime2);
2132 if (CKR_OK != *pError) {
2133 return (ckcapiInternalObject *)NULL;
2134 }
2135 *pError = nss_ckcapi_GetAttribute(CKA_EXPONENT_1, pTemplate,
2136 ulAttributeCount, &exponent1);
2137 if (CKR_OK != *pError) {
2138 return (ckcapiInternalObject *)NULL;
2139 }
2140 *pError = nss_ckcapi_GetAttribute(CKA_EXPONENT_2, pTemplate,
2141 ulAttributeCount, &exponent2);
2142 if (CKR_OK != *pError) {
2143 return (ckcapiInternalObject *)NULL;
2144 }
2145 *pError = nss_ckcapi_GetAttribute(CKA_COEFFICIENT, pTemplate,
2146 ulAttributeCount, &coefficient);
2147 if (CKR_OK != *pError) {
2148 return (ckcapiInternalObject *)NULL;
2149 }
2150 *pError = nss_ckcapi_GetAttribute(CKA_ID, pTemplate,
2151 ulAttributeCount, &keyID);
2152 if (CKR_OK != *pError) {
2153 return (ckcapiInternalObject *)NULL;
2154 }
2155 providerName = ckcapi_getDefaultProvider(pError);
2156 if ((char *)NULL == providerName ) {
2157 return (ckcapiInternalObject *)NULL;
2158 }
2159 containerName = ckcapi_getContainer(pError, &keyID);
2160 if ((char *)NULL == containerName) {
2161 goto loser;
2162 }
2163 rc = CryptAcquireContext(&hProv, containerName, providerName,
2164 PROV_RSA_FULL, CRYPT_NEWKEYSET);
2165 if (!rc) {
2166 msError = GetLastError();
2167 *pError = CKR_DEVICE_ERROR;
2168 goto loser;
2169 }
2170
2171 *pError = ckcapi_buildPrivateKeyBlob(
2172 &keyBlob,
2173 &modulus,
2174 &publicExponent,
2175 &privateExponent,
2176 &prime1,
2177 &prime2,
2178 &exponent1,
2179 &exponent2,
2180 &coefficient,
2181 decrypt);
2182 if (CKR_OK != *pError) {
2183 goto loser;
2184 }
2185
2186 rc = CryptImportKey(hProv, keyBlob.data, keyBlob.size,
2187 0, CRYPT_EXPORTABLE, &hKey);
2188 if (!rc) {
2189 msError = GetLastError();
2190 *pError = CKR_DEVICE_ERROR;
2191 goto loser;
2192 }
2193
2194 idData = nss_ZNEWARRAY(NULL, char, keyID.size);
2195 if ((void *)NULL == idData) {
2196 *pError = CKR_HOST_MEMORY;
2197 goto loser;
2198 }
2199 nsslibc_memcpy(idData, keyID.data, keyID.size);
2200
2201 provInfo.pwszContainerName = nss_ckcapi_UTF8ToWide(containerName);
2202 provInfo.pwszProvName = nss_ckcapi_UTF8ToWide(providerName);
2203 provInfo.dwProvType = PROV_RSA_FULL;
2204 provInfo.dwFlags = 0;
2205 provInfo.cProvParam = 0;
2206 provInfo.rgProvParam = NULL;
2207 provInfo.dwKeySpec = keySpec;
2208
2209 msKeyID.cbData = keyID.size;
2210 msKeyID.pbData = keyID.data;
2211
2212 rc = CryptSetKeyIdentifierProperty(&msKeyID, CERT_KEY_PROV_INFO_PROP_ID,
2213 0, NULL, NULL, &provInfo);
2214 if (!rc) {
2215 goto loser;
2216 }
2217
2218 /* handle error here */
2219 io = nss_ZNEW(NULL, ckcapiInternalObject);
2220 if ((ckcapiInternalObject *)NULL == io) {
2221 *pError = CKR_HOST_MEMORY;
2222 goto loser;
2223 }
2224 io->type = ckcapiBareKey;
2225 io->objClass = CKO_PRIVATE_KEY;
2226 io->u.key.provInfo = provInfo;
2227 io->u.key.provName = providerName;
2228 io->u.key.containerName = containerName;
2229 io->u.key.hProv = hProv; /* save the handle */
2230 io->idData = idData;
2231 io->id.data = idData;
2232 io->id.size = keyID.size;
2233 /* done with the key handle */
2234 CryptDestroyKey(hKey);
2235 return io;
2236
2237 loser:
2238 nss_ZFreeIf(containerName);
2239 nss_ZFreeIf(providerName);
2240 nss_ZFreeIf(idData);
2241 if (0 != hProv) {
2242 CryptReleaseContext(hProv, 0);
2243 }
2244 if (0 != hKey) {
2245 CryptDestroyKey(hKey);
2246 }
2247 return (ckcapiInternalObject *)NULL;
2248 }
2249
2250
2251 NSS_EXTERN NSSCKMDObject *
2252 nss_ckcapi_CreateObject
2253 (
2254 NSSCKFWSession *fwSession,
2255 CK_ATTRIBUTE_PTR pTemplate,
2256 CK_ULONG ulAttributeCount,
2257 CK_RV *pError
2258 )
2259 {
2260 CK_OBJECT_CLASS objClass;
2261 ckcapiInternalObject *io = NULL;
2262 CK_BBOOL isToken;
2263
2264 /*
2265 * only create token objects
2266 */
2267 isToken = nss_ckcapi_GetBoolAttribute(CKA_TOKEN, pTemplate,
2268 ulAttributeCount, pError);
2269 if (CKR_OK != *pError) {
2270 return (NSSCKMDObject *) NULL;
2271 }
2272 if (!isToken) {
2273 *pError = CKR_ATTRIBUTE_VALUE_INVALID;
2274 return (NSSCKMDObject *) NULL;
2275 }
2276
2277 /*
2278 * only create keys and certs.
2279 */
2280 objClass = nss_ckcapi_GetULongAttribute(CKA_CLASS, pTemplate,
2281 ulAttributeCount, pError);
2282 if (CKR_OK != *pError) {
2283 return (NSSCKMDObject *) NULL;
2284 }
2285 #ifdef notdef
2286 if (objClass == CKO_PUBLIC_KEY) {
2287 return CKR_OK; /* fake public key creation, happens as a side effect of
2288 * private key creation */
2289 }
2290 #endif
2291 if (objClass == CKO_CERTIFICATE) {
2292 io = nss_ckcapi_CreateCertificate(fwSession, pTemplate,
2293 ulAttributeCount, pError);
2294 } else if (objClass == CKO_PRIVATE_KEY) {
2295 io = nss_ckcapi_CreatePrivateKey(fwSession, pTemplate,
2296 ulAttributeCount, pError);
2297 } else {
2298 *pError = CKR_ATTRIBUTE_VALUE_INVALID;
2299 }
2300
2301 if ((ckcapiInternalObject *)NULL == io) {
2302 return (NSSCKMDObject *) NULL;
2303 }
2304 return nss_ckcapi_CreateMDObject(NULL, io, pError);
2305 }

mercurial