Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
5 #include "ckcapi.h"
6 #include "secdert.h"
8 #define SSL3_SHAMD5_HASH_SIZE 36 /* LEN_MD5 (16) + LEN_SHA1 (20) */
10 /*
11 * ckcapi/crsa.c
12 *
13 * This file implements the NSSCKMDMechnaism and NSSCKMDCryptoOperation objects
14 * for the RSA operation on the CAPI cryptoki module.
15 */
17 /*
18 * write a Decimal value to a string
19 */
21 static char *
22 putDecimalString(char *cstr, unsigned long value)
23 {
24 unsigned long tenpower;
25 int first = 1;
27 for (tenpower=10000000; tenpower; tenpower /= 10) {
28 unsigned char digit = (unsigned char )(value/tenpower);
29 value = value % tenpower;
31 /* drop leading zeros */
32 if (first && (0 == digit)) {
33 continue;
34 }
35 first = 0;
36 *cstr++ = digit + '0';
37 }
39 /* if value was zero, put one of them out */
40 if (first) {
41 *cstr++ = '0';
42 }
43 return cstr;
44 }
47 /*
48 * Create a Capi OID string value from a DER OID
49 */
50 static char *
51 nss_ckcapi_GetOidString
52 (
53 unsigned char *oidTag,
54 unsigned int oidTagSize,
55 CK_RV *pError
56 )
57 {
58 unsigned char *oid;
59 char *oidStr;
60 char *cstr;
61 unsigned long value;
62 unsigned int oidSize;
64 if (DER_OBJECT_ID != *oidTag) {
65 /* wasn't an oid */
66 *pError = CKR_DATA_INVALID;
67 return NULL;
68 }
69 oid = nss_ckcapi_DERUnwrap(oidTag, oidTagSize, &oidSize, NULL);
71 if (oidSize < 2) {
72 *pError = CKR_DATA_INVALID;
73 return NULL;
74 }
76 oidStr = nss_ZNEWARRAY( NULL, char, oidSize*4 );
77 if ((char *)NULL == oidStr) {
78 *pError = CKR_HOST_MEMORY;
79 return NULL;
80 }
81 cstr = oidStr;
82 cstr = putDecimalString(cstr, (*oid) / 40);
83 *cstr++ = '.';
84 cstr = putDecimalString(cstr, (*oid) % 40);
85 oidSize--;
87 value = 0;
88 while (oidSize--) {
89 oid++;
90 value = (value << 7) + (*oid & 0x7f);
91 if (0 == (*oid & 0x80)) {
92 *cstr++ = '.';
93 cstr = putDecimalString(cstr, value);
94 value = 0;
95 }
96 }
98 *cstr = 0; /* NULL terminate */
100 if (value != 0) {
101 nss_ZFreeIf(oidStr);
102 *pError = CKR_DATA_INVALID;
103 return NULL;
104 }
105 return oidStr;
106 }
109 /*
110 * PKCS #11 sign for RSA expects to take a fully DER-encoded hash value,
111 * which includes the hash OID. CAPI expects to take a Hash Context. While
112 * CAPI does have the capability of setting a raw hash value, it does not
113 * have the ability to sign an arbitrary value. This function tries to
114 * reduce the passed in data into something that CAPI could actually sign.
115 */
116 static CK_RV
117 ckcapi_GetRawHash
118 (
119 const NSSItem *input,
120 NSSItem *hash,
121 ALG_ID *hashAlg
122 )
123 {
124 unsigned char *current;
125 unsigned char *algid;
126 unsigned char *oid;
127 unsigned char *hashData;
128 char *oidStr;
129 CK_RV error;
130 unsigned int oidSize;
131 unsigned int size;
132 /*
133 * there are 2 types of hashes NSS typically tries to sign, regular
134 * RSA signature format (with encoded DER_OIDS), and SSL3 Signed hashes.
135 * CAPI knows not to add any oids to SSL3_Signed hashes, so if we have any
136 * random hash that is exactly the same size as an SSL3 hash, then we can
137 * just pass the data through. CAPI has know way of knowing if the value
138 * is really a combined hash or some other arbitrary data, so it's safe to
139 * handle this case first.
140 */
141 if (SSL3_SHAMD5_HASH_SIZE == input->size) {
142 hash->data = input->data;
143 hash->size = input->size;
144 *hashAlg = CALG_SSL3_SHAMD5;
145 return CKR_OK;
146 }
148 current = (unsigned char *)input->data;
150 /* make sure we have a sequence tag */
151 if ((DER_SEQUENCE|DER_CONSTRUCTED) != *current) {
152 return CKR_DATA_INVALID;
153 }
155 /* parse the input block to get 1) the hash oid, and 2) the raw hash value.
156 * unfortunatly CAPI doesn't have a builtin function to do this work, so
157 * we go ahead and do it by hand here.
158 *
159 * format is:
160 * SEQUENCE {
161 * SECQUENCE { // algid
162 * OID {} // oid
163 * ANY {} // optional params
164 * }
165 * OCTECT {} // hash
166 */
168 /* unwrap */
169 algid = nss_ckcapi_DERUnwrap(current,input->size, &size, NULL);
171 if (algid+size != current+input->size) {
172 /* make sure there is not extra data at the end */
173 return CKR_DATA_INVALID;
174 }
176 if ((DER_SEQUENCE|DER_CONSTRUCTED) != *algid) {
177 /* wasn't an algid */
178 return CKR_DATA_INVALID;
179 }
180 oid = nss_ckcapi_DERUnwrap(algid, size, &oidSize, &hashData);
182 if (DER_OCTET_STRING != *hashData) {
183 /* wasn't a hash */
184 return CKR_DATA_INVALID;
185 }
187 /* get the real hash */
188 current = hashData;
189 size = size - (hashData-algid);
190 hash->data = nss_ckcapi_DERUnwrap(current, size, &hash->size, NULL);
192 /* get the real oid as a string. Again, Microsoft does not
193 * export anything that does this for us */
194 oidStr = nss_ckcapi_GetOidString(oid, oidSize, &error);
195 if ((char *)NULL == oidStr ) {
196 return error;
197 }
199 /* look up the hash alg from the oid (fortunately CAPI does to this) */
200 *hashAlg = CertOIDToAlgId(oidStr);
201 nss_ZFreeIf(oidStr);
202 if (0 == *hashAlg) {
203 return CKR_HOST_MEMORY;
204 }
206 /* hash looks reasonably consistent, we should be able to sign it now */
207 return CKR_OK;
208 }
210 /*
211 * So everyone else in the worlds stores their bignum data MSB first, but not
212 * Microsoft, we need to byte swap everything coming into and out of CAPI.
213 */
214 void
215 ckcapi_ReverseData(NSSItem *item)
216 {
217 int end = (item->size)-1;
218 int middle = (item->size)/2;
219 unsigned char *buf = item->data;
220 int i;
222 for (i=0; i < middle; i++) {
223 unsigned char tmp = buf[i];
224 buf[i] = buf[end-i];
225 buf[end-i] = tmp;
226 }
227 return;
228 }
230 typedef struct ckcapiInternalCryptoOperationRSAPrivStr
231 ckcapiInternalCryptoOperationRSAPriv;
232 struct ckcapiInternalCryptoOperationRSAPrivStr
233 {
234 NSSCKMDCryptoOperation mdOperation;
235 NSSCKMDMechanism *mdMechanism;
236 ckcapiInternalObject *iKey;
237 HCRYPTPROV hProv;
238 DWORD keySpec;
239 HCRYPTKEY hKey;
240 NSSItem *buffer;
241 };
243 /*
244 * ckcapi_mdCryptoOperationRSAPriv_Create
245 */
246 static NSSCKMDCryptoOperation *
247 ckcapi_mdCryptoOperationRSAPriv_Create
248 (
249 const NSSCKMDCryptoOperation *proto,
250 NSSCKMDMechanism *mdMechanism,
251 NSSCKMDObject *mdKey,
252 CK_RV *pError
253 )
254 {
255 ckcapiInternalObject *iKey = (ckcapiInternalObject *)mdKey->etc;
256 const NSSItem *classItem = nss_ckcapi_FetchAttribute(iKey, CKA_CLASS);
257 const NSSItem *keyType = nss_ckcapi_FetchAttribute(iKey, CKA_KEY_TYPE);
258 ckcapiInternalCryptoOperationRSAPriv *iOperation;
259 CK_RV error;
260 HCRYPTPROV hProv;
261 DWORD keySpec;
262 HCRYPTKEY hKey;
264 /* make sure we have the right objects */
265 if (((const NSSItem *)NULL == classItem) ||
266 (sizeof(CK_OBJECT_CLASS) != classItem->size) ||
267 (CKO_PRIVATE_KEY != *(CK_OBJECT_CLASS *)classItem->data) ||
268 ((const NSSItem *)NULL == keyType) ||
269 (sizeof(CK_KEY_TYPE) != keyType->size) ||
270 (CKK_RSA != *(CK_KEY_TYPE *)keyType->data)) {
271 *pError = CKR_KEY_TYPE_INCONSISTENT;
272 return (NSSCKMDCryptoOperation *)NULL;
273 }
275 error = nss_ckcapi_FetchKeyContainer(iKey, &hProv, &keySpec, &hKey);
276 if (error != CKR_OK) {
277 *pError = error;
278 return (NSSCKMDCryptoOperation *)NULL;
279 }
281 iOperation = nss_ZNEW(NULL, ckcapiInternalCryptoOperationRSAPriv);
282 if ((ckcapiInternalCryptoOperationRSAPriv *)NULL == iOperation) {
283 *pError = CKR_HOST_MEMORY;
284 return (NSSCKMDCryptoOperation *)NULL;
285 }
286 iOperation->mdMechanism = mdMechanism;
287 iOperation->iKey = iKey;
288 iOperation->hProv = hProv;
289 iOperation->keySpec = keySpec;
290 iOperation->hKey = hKey;
292 nsslibc_memcpy(&iOperation->mdOperation,
293 proto, sizeof(NSSCKMDCryptoOperation));
294 iOperation->mdOperation.etc = iOperation;
296 return &iOperation->mdOperation;
297 }
299 static CK_RV
300 ckcapi_mdCryptoOperationRSAPriv_Destroy
301 (
302 NSSCKMDCryptoOperation *mdOperation,
303 NSSCKFWCryptoOperation *fwOperation,
304 NSSCKMDInstance *mdInstance,
305 NSSCKFWInstance *fwInstance
306 )
307 {
308 ckcapiInternalCryptoOperationRSAPriv *iOperation =
309 (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc;
311 if (iOperation->hKey) {
312 CryptDestroyKey(iOperation->hKey);
313 }
314 if (iOperation->buffer) {
315 nssItem_Destroy(iOperation->buffer);
316 }
317 nss_ZFreeIf(iOperation);
318 return CKR_OK;
319 }
321 static CK_ULONG
322 ckcapi_mdCryptoOperationRSA_GetFinalLength
323 (
324 NSSCKMDCryptoOperation *mdOperation,
325 NSSCKFWCryptoOperation *fwOperation,
326 NSSCKMDSession *mdSession,
327 NSSCKFWSession *fwSession,
328 NSSCKMDToken *mdToken,
329 NSSCKFWToken *fwToken,
330 NSSCKMDInstance *mdInstance,
331 NSSCKFWInstance *fwInstance,
332 CK_RV *pError
333 )
334 {
335 ckcapiInternalCryptoOperationRSAPriv *iOperation =
336 (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc;
337 const NSSItem *modulus =
338 nss_ckcapi_FetchAttribute(iOperation->iKey, CKA_MODULUS);
340 return modulus->size;
341 }
344 /*
345 * ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength
346 * we won't know the length until we actually decrypt the
347 * input block. Since we go to all the work to decrypt the
348 * the block, we'll save if for when the block is asked for
349 */
350 static CK_ULONG
351 ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength
352 (
353 NSSCKMDCryptoOperation *mdOperation,
354 NSSCKFWCryptoOperation *fwOperation,
355 NSSCKMDSession *mdSession,
356 NSSCKFWSession *fwSession,
357 NSSCKMDToken *mdToken,
358 NSSCKFWToken *fwToken,
359 NSSCKMDInstance *mdInstance,
360 NSSCKFWInstance *fwInstance,
361 const NSSItem *input,
362 CK_RV *pError
363 )
364 {
365 ckcapiInternalCryptoOperationRSAPriv *iOperation =
366 (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc;
367 BOOL rc;
369 /* Microsoft's Decrypt operation works in place. Since we don't want
370 * to trash our input buffer, we make a copy of it */
371 iOperation->buffer = nssItem_Duplicate((NSSItem *)input, NULL, NULL);
372 if ((NSSItem *) NULL == iOperation->buffer) {
373 *pError = CKR_HOST_MEMORY;
374 return 0;
375 }
376 /* Sigh, reverse it */
377 ckcapi_ReverseData(iOperation->buffer);
379 rc = CryptDecrypt(iOperation->hKey, 0, TRUE, 0,
380 iOperation->buffer->data, &iOperation->buffer->size);
381 if (!rc) {
382 DWORD msError = GetLastError();
383 switch (msError) {
384 case NTE_BAD_DATA:
385 *pError = CKR_ENCRYPTED_DATA_INVALID;
386 break;
387 case NTE_FAIL:
388 case NTE_BAD_UID:
389 *pError = CKR_DEVICE_ERROR;
390 break;
391 default:
392 *pError = CKR_GENERAL_ERROR;
393 }
394 return 0;
395 }
397 return iOperation->buffer->size;
398 }
400 /*
401 * ckcapi_mdCryptoOperationRSADecrypt_UpdateFinal
402 *
403 * NOTE: ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength is presumed to
404 * have been called previously.
405 */
406 static CK_RV
407 ckcapi_mdCryptoOperationRSADecrypt_UpdateFinal
408 (
409 NSSCKMDCryptoOperation *mdOperation,
410 NSSCKFWCryptoOperation *fwOperation,
411 NSSCKMDSession *mdSession,
412 NSSCKFWSession *fwSession,
413 NSSCKMDToken *mdToken,
414 NSSCKFWToken *fwToken,
415 NSSCKMDInstance *mdInstance,
416 NSSCKFWInstance *fwInstance,
417 const NSSItem *input,
418 NSSItem *output
419 )
420 {
421 ckcapiInternalCryptoOperationRSAPriv *iOperation =
422 (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc;
423 NSSItem *buffer = iOperation->buffer;
425 if ((NSSItem *)NULL == buffer) {
426 return CKR_GENERAL_ERROR;
427 }
428 nsslibc_memcpy(output->data, buffer->data, buffer->size);
429 output->size = buffer->size;
430 return CKR_OK;
431 }
433 /*
434 * ckcapi_mdCryptoOperationRSASign_UpdateFinal
435 *
436 */
437 static CK_RV
438 ckcapi_mdCryptoOperationRSASign_UpdateFinal
439 (
440 NSSCKMDCryptoOperation *mdOperation,
441 NSSCKFWCryptoOperation *fwOperation,
442 NSSCKMDSession *mdSession,
443 NSSCKFWSession *fwSession,
444 NSSCKMDToken *mdToken,
445 NSSCKFWToken *fwToken,
446 NSSCKMDInstance *mdInstance,
447 NSSCKFWInstance *fwInstance,
448 const NSSItem *input,
449 NSSItem *output
450 )
451 {
452 ckcapiInternalCryptoOperationRSAPriv *iOperation =
453 (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc;
454 CK_RV error = CKR_OK;
455 DWORD msError;
456 NSSItem hash;
457 HCRYPTHASH hHash = 0;
458 ALG_ID hashAlg;
459 DWORD hashSize;
460 DWORD len; /* temp length value we throw away */
461 BOOL rc;
463 /*
464 * PKCS #11 sign for RSA expects to take a fully DER-encoded hash value,
465 * which includes the hash OID. CAPI expects to take a Hash Context. While
466 * CAPI does have the capability of setting a raw hash value, it does not
467 * have the ability to sign an arbitrary value. This function tries to
468 * reduce the passed in data into something that CAPI could actually sign.
469 */
470 error = ckcapi_GetRawHash(input, &hash, &hashAlg);
471 if (CKR_OK != error) {
472 goto loser;
473 }
475 rc = CryptCreateHash(iOperation->hProv, hashAlg, 0, 0, &hHash);
476 if (!rc) {
477 goto loser;
478 }
480 /* make sure the hash lens match before we set it */
481 len = sizeof(DWORD);
482 rc = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&hashSize, &len, 0);
483 if (!rc) {
484 goto loser;
485 }
487 if (hash.size != hashSize) {
488 /* The input must have been bad for this to happen */
489 error = CKR_DATA_INVALID;
490 goto loser;
491 }
493 /* we have an explicit hash, set it, note that the length is
494 * implicit by the hashAlg used in create */
495 rc = CryptSetHashParam(hHash, HP_HASHVAL, hash.data, 0);
496 if (!rc) {
497 goto loser;
498 }
500 /* OK, we have the data in a hash structure, sign it! */
501 rc = CryptSignHash(hHash, iOperation->keySpec, NULL, 0,
502 output->data, &output->size);
503 if (!rc) {
504 goto loser;
505 }
507 /* Don't return a signature that might have been broken because of a cosmic
508 * ray, or a broken processor, verify that it is valid... */
509 rc = CryptVerifySignature(hHash, output->data, output->size,
510 iOperation->hKey, NULL, 0);
511 if (!rc) {
512 goto loser;
513 }
515 /* OK, Microsoft likes to do things completely differently than anyone
516 * else. We need to reverse the data we received here */
517 ckcapi_ReverseData(output);
518 CryptDestroyHash(hHash);
519 return CKR_OK;
521 loser:
522 /* map the microsoft error */
523 if (CKR_OK == error) {
524 msError = GetLastError();
525 switch (msError) {
526 case ERROR_NOT_ENOUGH_MEMORY:
527 error = CKR_HOST_MEMORY;
528 break;
529 case NTE_NO_MEMORY:
530 error = CKR_DEVICE_MEMORY;
531 break;
532 case ERROR_MORE_DATA:
533 return CKR_BUFFER_TOO_SMALL;
534 case ERROR_INVALID_PARAMETER: /* these params were derived from the */
535 case ERROR_INVALID_HANDLE: /* inputs, so if they are bad, the input */
536 case NTE_BAD_ALGID: /* data is bad */
537 case NTE_BAD_HASH:
538 error = CKR_DATA_INVALID;
539 break;
540 case ERROR_BUSY:
541 case NTE_FAIL:
542 case NTE_BAD_UID:
543 error = CKR_DEVICE_ERROR;
544 break;
545 default:
546 error = CKR_GENERAL_ERROR;
547 break;
548 }
549 }
550 if (hHash) {
551 CryptDestroyHash(hHash);
552 }
553 return error;
554 }
557 NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation
558 ckcapi_mdCryptoOperationRSADecrypt_proto = {
559 NULL, /* etc */
560 ckcapi_mdCryptoOperationRSAPriv_Destroy,
561 NULL, /* GetFinalLengh - not needed for one shot Decrypt/Encrypt */
562 ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength,
563 NULL, /* Final - not needed for one shot operation */
564 NULL, /* Update - not needed for one shot operation */
565 NULL, /* DigetUpdate - not needed for one shot operation */
566 ckcapi_mdCryptoOperationRSADecrypt_UpdateFinal,
567 NULL, /* UpdateCombo - not needed for one shot operation */
568 NULL, /* DigetKey - not needed for one shot operation */
569 (void *)NULL /* null terminator */
570 };
572 NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation
573 ckcapi_mdCryptoOperationRSASign_proto = {
574 NULL, /* etc */
575 ckcapi_mdCryptoOperationRSAPriv_Destroy,
576 ckcapi_mdCryptoOperationRSA_GetFinalLength,
577 NULL, /* GetOperationLengh - not needed for one shot Sign/Verify */
578 NULL, /* Final - not needed for one shot operation */
579 NULL, /* Update - not needed for one shot operation */
580 NULL, /* DigetUpdate - not needed for one shot operation */
581 ckcapi_mdCryptoOperationRSASign_UpdateFinal,
582 NULL, /* UpdateCombo - not needed for one shot operation */
583 NULL, /* DigetKey - not needed for one shot operation */
584 (void *)NULL /* null terminator */
585 };
587 /********** NSSCKMDMechansim functions ***********************/
588 /*
589 * ckcapi_mdMechanismRSA_Destroy
590 */
591 static void
592 ckcapi_mdMechanismRSA_Destroy
593 (
594 NSSCKMDMechanism *mdMechanism,
595 NSSCKFWMechanism *fwMechanism,
596 NSSCKMDInstance *mdInstance,
597 NSSCKFWInstance *fwInstance
598 )
599 {
600 nss_ZFreeIf(fwMechanism);
601 }
603 /*
604 * ckcapi_mdMechanismRSA_GetMinKeySize
605 */
606 static CK_ULONG
607 ckcapi_mdMechanismRSA_GetMinKeySize
608 (
609 NSSCKMDMechanism *mdMechanism,
610 NSSCKFWMechanism *fwMechanism,
611 NSSCKMDToken *mdToken,
612 NSSCKFWToken *fwToken,
613 NSSCKMDInstance *mdInstance,
614 NSSCKFWInstance *fwInstance,
615 CK_RV *pError
616 )
617 {
618 return 384;
619 }
621 /*
622 * ckcapi_mdMechanismRSA_GetMaxKeySize
623 */
624 static CK_ULONG
625 ckcapi_mdMechanismRSA_GetMaxKeySize
626 (
627 NSSCKMDMechanism *mdMechanism,
628 NSSCKFWMechanism *fwMechanism,
629 NSSCKMDToken *mdToken,
630 NSSCKFWToken *fwToken,
631 NSSCKMDInstance *mdInstance,
632 NSSCKFWInstance *fwInstance,
633 CK_RV *pError
634 )
635 {
636 return 16384;
637 }
639 /*
640 * ckcapi_mdMechanismRSA_DecryptInit
641 */
642 static NSSCKMDCryptoOperation *
643 ckcapi_mdMechanismRSA_DecryptInit
644 (
645 NSSCKMDMechanism *mdMechanism,
646 NSSCKFWMechanism *fwMechanism,
647 CK_MECHANISM *pMechanism,
648 NSSCKMDSession *mdSession,
649 NSSCKFWSession *fwSession,
650 NSSCKMDToken *mdToken,
651 NSSCKFWToken *fwToken,
652 NSSCKMDInstance *mdInstance,
653 NSSCKFWInstance *fwInstance,
654 NSSCKMDObject *mdKey,
655 NSSCKFWObject *fwKey,
656 CK_RV *pError
657 )
658 {
659 return ckcapi_mdCryptoOperationRSAPriv_Create(
660 &ckcapi_mdCryptoOperationRSADecrypt_proto,
661 mdMechanism, mdKey, pError);
662 }
664 /*
665 * ckcapi_mdMechanismRSA_SignInit
666 */
667 static NSSCKMDCryptoOperation *
668 ckcapi_mdMechanismRSA_SignInit
669 (
670 NSSCKMDMechanism *mdMechanism,
671 NSSCKFWMechanism *fwMechanism,
672 CK_MECHANISM *pMechanism,
673 NSSCKMDSession *mdSession,
674 NSSCKFWSession *fwSession,
675 NSSCKMDToken *mdToken,
676 NSSCKFWToken *fwToken,
677 NSSCKMDInstance *mdInstance,
678 NSSCKFWInstance *fwInstance,
679 NSSCKMDObject *mdKey,
680 NSSCKFWObject *fwKey,
681 CK_RV *pError
682 )
683 {
684 return ckcapi_mdCryptoOperationRSAPriv_Create(
685 &ckcapi_mdCryptoOperationRSASign_proto,
686 mdMechanism, mdKey, pError);
687 }
690 NSS_IMPLEMENT_DATA const NSSCKMDMechanism
691 nss_ckcapi_mdMechanismRSA = {
692 (void *)NULL, /* etc */
693 ckcapi_mdMechanismRSA_Destroy,
694 ckcapi_mdMechanismRSA_GetMinKeySize,
695 ckcapi_mdMechanismRSA_GetMaxKeySize,
696 NULL, /* GetInHardware - default false */
697 NULL, /* EncryptInit - default errs */
698 ckcapi_mdMechanismRSA_DecryptInit,
699 NULL, /* DigestInit - default errs*/
700 ckcapi_mdMechanismRSA_SignInit,
701 NULL, /* VerifyInit - default errs */
702 ckcapi_mdMechanismRSA_SignInit, /* SignRecoverInit */
703 NULL, /* VerifyRecoverInit - default errs */
704 NULL, /* GenerateKey - default errs */
705 NULL, /* GenerateKeyPair - default errs */
706 NULL, /* GetWrapKeyLength - default errs */
707 NULL, /* WrapKey - default errs */
708 NULL, /* UnwrapKey - default errs */
709 NULL, /* DeriveKey - default errs */
710 (void *)NULL /* null terminator */
711 };