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