Back to index

lightning-sunbird  0.9+nobinonly
crsa.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Red Hat, Inc.
00018  * Portions created by the Initial Developer are Copyright (C) 2005
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Bob Relyea (rrelyea@redhat.com)
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #ifdef DEBUG
00039 static const char CVS_ID[] = "@(#) $RCSfile: crsa.c,v $ $Revision: 1.3 $ $Date: 2005/11/15 00:13:58 $";
00040 #endif /* DEBUG */
00041 
00042 #include "ckcapi.h"
00043 #include "secdert.h"
00044 
00045 #define SSL3_SHAMD5_HASH_SIZE  36 /* LEN_MD5 (16) + LEN_SHA1 (20) */
00046 
00047 /*
00048  * ckcapi/crsa.c
00049  *
00050  * This file implements the NSSCKMDMechnaism and NSSCKMDCryptoOperation objects
00051  * for the RSA operation on the CAPI cryptoki module.
00052  */
00053 
00054 /*
00055  * write a Decimal value to a string
00056  */
00057 
00058 static char *
00059 putDecimalString(char *cstr, unsigned long value)
00060 {
00061   unsigned long tenpower;
00062   int first = 1;
00063 
00064   for (tenpower=10000000; tenpower; tenpower /= 10) {
00065     unsigned char digit = (unsigned char )(value/tenpower);
00066     value = value % tenpower;
00067 
00068     /* drop leading zeros */
00069     if (first && (0 == digit)) {
00070       continue;
00071     }
00072     first = 0;
00073     *cstr++ = digit + '0';
00074   }
00075 
00076   /* if value was zero, put one of them out */
00077   if (first) {
00078     *cstr++ = '0';
00079   }
00080   return cstr;
00081 }
00082 
00083 
00084 /*
00085  * Create a Capi OID string value from a DER OID
00086  */
00087 static char *
00088 nss_ckcapi_GetOidString
00089 (
00090   unsigned char *oidTag,
00091   int oidTagSize,
00092   CK_RV *pError
00093 )
00094 {
00095   unsigned char *oid;
00096   char *oidStr;
00097   char *cstr;
00098   unsigned long value;
00099   int oidSize;
00100 
00101   if (DER_OBJECT_ID != *oidTag) {
00102     /* wasn't an oid */
00103     *pError = CKR_DATA_INVALID;
00104     return NULL;
00105   }
00106   oid = nss_ckcapi_DERUnwrap(oidTag, oidTagSize, &oidSize, NULL);
00107 
00108   if (oidSize < 2) {
00109     *pError = CKR_DATA_INVALID;
00110     return NULL;
00111   }
00112 
00113   oidStr = nss_ZNEWARRAY( NULL, char, oidSize*4 );
00114   if ((char *)NULL == oidStr) {
00115     *pError = CKR_HOST_MEMORY;
00116     return NULL;
00117   }
00118   cstr = oidStr;
00119   cstr = putDecimalString(cstr, (*oid) / 40);
00120   *cstr++ = '.';
00121   cstr = putDecimalString(cstr, (*oid) % 40);
00122   oidSize--;
00123 
00124   value = 0;
00125   while (oidSize--) {
00126     oid++;
00127     value = (value << 7) + (*oid & 0x7f);
00128     if (0 == (*oid & 0x80)) {
00129       *cstr++ = '.';
00130       cstr = putDecimalString(cstr, value);
00131       value = 0;
00132     }
00133   }
00134 
00135   *cstr = 0; /* NULL terminate */
00136 
00137   if (value != 0) {
00138     nss_ZFreeIf(oidStr);
00139     *pError = CKR_DATA_INVALID;
00140     return NULL;
00141   }
00142   return oidStr;
00143 }
00144 
00145 
00146 /*
00147  * PKCS #11 sign for RSA expects to take a fully DER-encoded hash value, 
00148  * which includes the hash OID. CAPI expects to take a Hash Context. While 
00149  * CAPI does have the capability of setting a raw hash value, it does not 
00150  * have the ability to sign an arbitrary value. This function tries to
00151  * reduce the passed in data into something that CAPI could actually sign.
00152  */
00153 static CK_RV
00154 ckcapi_GetRawHash
00155 (
00156   const NSSItem *input,
00157   NSSItem *hash, 
00158   ALG_ID *hashAlg
00159 )
00160 {
00161    unsigned char *current;
00162    unsigned char *algid;
00163    unsigned char *oid;
00164    unsigned char *hashData;
00165    char *oidStr;
00166    CK_RV error;
00167    int oidSize;
00168    int size;
00169    /*
00170     * there are 2 types of hashes NSS typically tries to sign, regular
00171     * RSA signature format (with encoded DER_OIDS), and SSL3 Signed hashes.
00172     * CAPI knows not to add any oids to SSL3_Signed hashes, so if we have any
00173     * random hash that is exactly the same size as an SSL3 hash, then we can
00174     * just pass the data through. CAPI has know way of knowing if the value
00175     * is really a combined hash or some other arbitrary data, so it's safe to
00176     * handle this case first.
00177     */
00178   if (SSL3_SHAMD5_HASH_SIZE == input->size) {
00179     hash->data = input->data;
00180     hash->size = input->size;
00181     *hashAlg = CALG_SSL3_SHAMD5;
00182     return CKR_OK;
00183   }
00184 
00185   current = (unsigned char *)input->data;
00186 
00187   /* make sure we have a sequence tag */
00188   if ((DER_SEQUENCE|DER_CONSTRUCTED) != *current) {
00189     return CKR_DATA_INVALID;
00190   }
00191 
00192   /* parse the input block to get 1) the hash oid, and 2) the raw hash value.
00193    * unfortunatly CAPI doesn't have a builtin function to do this work, so
00194    * we go ahead and do it by hand here.
00195    *
00196    * format is:
00197    *  SEQUENCE {
00198    *     SECQUENCE { // algid
00199    *       OID {}    // oid
00200    *       ANY {}    // optional params 
00201    *     }
00202    *     OCTECT {}   // hash
00203    */
00204 
00205   /* unwrap */
00206   algid = nss_ckcapi_DERUnwrap(current,input->size, &size, NULL);
00207   
00208   if (algid+size != current+input->size) {
00209     /* make sure there is not extra data at the end */
00210     return CKR_DATA_INVALID;
00211   }
00212 
00213   if ((DER_SEQUENCE|DER_CONSTRUCTED) != *algid) {
00214     /* wasn't an algid */
00215     return CKR_DATA_INVALID;
00216   }
00217   oid = nss_ckcapi_DERUnwrap(algid, size, &oidSize, &hashData);
00218 
00219   if (DER_OCTET_STRING != *hashData) {
00220     /* wasn't a hash */
00221     return CKR_DATA_INVALID;
00222   }
00223 
00224   /* get the real hash */
00225   current = hashData;
00226   size = size - (hashData-algid);
00227   hash->data = nss_ckcapi_DERUnwrap(current, size, &hash->size, NULL);
00228 
00229   /* get the real oid as a string. Again, Microsoft does not
00230    * export anything that does this for us */
00231   oidStr = nss_ckcapi_GetOidString(oid, oidSize, &error);
00232   if ((char *)NULL == oidStr ) {
00233     return error;
00234   }
00235 
00236   /* look up the hash alg from the oid (fortunately CAPI does to this) */ 
00237   *hashAlg = CertOIDToAlgId(oidStr);
00238   nss_ZFreeIf(oidStr);
00239   if (0 == *hashAlg) {
00240     return CKR_HOST_MEMORY;
00241   }
00242 
00243   /* hash looks reasonably consistent, we should be able to sign it now */
00244   return CKR_OK;
00245 }
00246 
00247 /*
00248  * So everyone else in the worlds stores their bignum data MSB first, but not
00249  * Microsoft, we need to byte swap everything coming into and out of CAPI.
00250  */
00251 void
00252 ckcapi_ReverseData(NSSItem *item)
00253 {
00254   int end = (item->size)-1;
00255   int middle = (item->size)/2;
00256   unsigned char *buf = item->data;
00257   int i;
00258 
00259   for (i=0; i < middle; i++) {
00260     unsigned char  tmp = buf[i];
00261     buf[i] = buf[end-i];
00262     buf[end-i] = tmp;
00263   }
00264   return;
00265 }
00266 
00267 typedef struct ckcapiInternalCryptoOperationRSAPrivStr 
00268                ckcapiInternalCryptoOperationRSAPriv;
00269 struct ckcapiInternalCryptoOperationRSAPrivStr
00270 {
00271   NSSCKMDCryptoOperation mdOperation;
00272   NSSCKMDMechanism     *mdMechanism;
00273   ckcapiInternalObject *iKey;
00274   HCRYPTPROV           hProv;
00275   DWORD                keySpec;
00276   HCRYPTKEY            hKey;
00277   NSSItem            *buffer;
00278 };
00279 
00280 /*
00281  * ckcapi_mdCryptoOperationRSAPriv_Create
00282  */
00283 static NSSCKMDCryptoOperation *
00284 ckcapi_mdCryptoOperationRSAPriv_Create
00285 (
00286   const NSSCKMDCryptoOperation *proto,
00287   NSSCKMDMechanism *mdMechanism,
00288   NSSCKMDObject *mdKey,
00289   CK_RV *pError
00290 )
00291 {
00292   ckcapiInternalObject *iKey = (ckcapiInternalObject *)mdKey->etc;
00293   const NSSItem *classItem = nss_ckcapi_FetchAttribute(iKey, CKA_CLASS);
00294   const NSSItem *keyType = nss_ckcapi_FetchAttribute(iKey, CKA_KEY_TYPE);
00295   ckcapiInternalCryptoOperationRSAPriv *iOperation;
00296   CK_RV   error;
00297   HCRYPTPROV  hProv;
00298   DWORD       keySpec;
00299   HCRYPTKEY   hKey;
00300 
00301   /* make sure we have the right objects */
00302   if (((const NSSItem *)NULL == classItem) ||
00303       (sizeof(CK_OBJECT_CLASS) != classItem->size) ||
00304       (CKO_PRIVATE_KEY != *(CK_OBJECT_CLASS *)classItem->data) ||
00305       ((const NSSItem *)NULL == keyType) ||
00306       (sizeof(CK_KEY_TYPE) != keyType->size) ||
00307       (CKK_RSA != *(CK_KEY_TYPE *)keyType->data)) {
00308     *pError =  CKR_KEY_TYPE_INCONSISTENT;
00309     return (NSSCKMDCryptoOperation *)NULL;
00310   }
00311 
00312   error = nss_ckcapi_FetchKeyContainer(iKey, &hProv, &keySpec, &hKey);
00313   if (error != CKR_OK) {
00314     *pError = error;
00315     return (NSSCKMDCryptoOperation *)NULL;
00316   }
00317 
00318   iOperation = nss_ZNEW(NULL, ckcapiInternalCryptoOperationRSAPriv);
00319   if ((ckcapiInternalCryptoOperationRSAPriv *)NULL == iOperation) {
00320     *pError = CKR_HOST_MEMORY;
00321     return (NSSCKMDCryptoOperation *)NULL;
00322   }
00323   iOperation->mdMechanism = mdMechanism;
00324   iOperation->iKey = iKey;
00325   iOperation->hProv = hProv;
00326   iOperation->keySpec = keySpec;
00327   iOperation->hKey = hKey;
00328 
00329   nsslibc_memcpy(&iOperation->mdOperation, 
00330                  proto, sizeof(NSSCKMDCryptoOperation));
00331   iOperation->mdOperation.etc = iOperation;
00332 
00333   return &iOperation->mdOperation;
00334 }
00335 
00336 static CK_RV
00337 ckcapi_mdCryptoOperationRSAPriv_Destroy
00338 (
00339   NSSCKMDCryptoOperation *mdOperation,
00340   NSSCKFWCryptoOperation *fwOperation,
00341   NSSCKMDInstance *mdInstance,
00342   NSSCKFWInstance *fwInstance
00343 )
00344 {
00345   ckcapiInternalCryptoOperationRSAPriv *iOperation =
00346        (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc;
00347 
00348   if (iOperation->hKey) {
00349     CryptDestroyKey(iOperation->hKey);
00350   }
00351   if (iOperation->buffer) {
00352     nssItem_Destroy(iOperation->buffer);
00353   }
00354   nss_ZFreeIf(iOperation);
00355   return CKR_OK;
00356 }
00357 
00358 static CK_ULONG
00359 ckcapi_mdCryptoOperationRSA_GetFinalLength
00360 (
00361   NSSCKMDCryptoOperation *mdOperation,
00362   NSSCKFWCryptoOperation *fwOperation,
00363   NSSCKMDSession *mdSession,
00364   NSSCKFWSession *fwSession,
00365   NSSCKMDToken *mdToken,
00366   NSSCKFWToken *fwToken,
00367   NSSCKMDInstance *mdInstance,
00368   NSSCKFWInstance *fwInstance,
00369   CK_RV *pError
00370 )
00371 {
00372   ckcapiInternalCryptoOperationRSAPriv *iOperation =
00373        (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc;
00374   const NSSItem *modulus = 
00375        nss_ckcapi_FetchAttribute(iOperation->iKey, CKA_MODULUS);
00376 
00377   return modulus->size;
00378 }
00379 
00380 
00381 /*
00382  * ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength
00383  * we won't know the length until we actually decrypt the
00384  * input block. Since we go to all the work to decrypt the
00385  * the block, we'll save if for when the block is asked for
00386  */
00387 static CK_ULONG
00388 ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength
00389 (
00390   NSSCKMDCryptoOperation *mdOperation,
00391   NSSCKFWCryptoOperation *fwOperation,
00392   NSSCKMDSession *mdSession,
00393   NSSCKFWSession *fwSession,
00394   NSSCKMDToken *mdToken,
00395   NSSCKFWToken *fwToken,
00396   NSSCKMDInstance *mdInstance,
00397   NSSCKFWInstance *fwInstance,
00398   const NSSItem *input,
00399   CK_RV *pError
00400 )
00401 {
00402   ckcapiInternalCryptoOperationRSAPriv *iOperation =
00403        (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc;
00404   BOOL rc;
00405 
00406   /* Microsoft's Decrypt operation works in place. Since we don't want
00407    * to trash our input buffer, we make a copy of it */
00408   iOperation->buffer = nssItem_Duplicate((NSSItem *)input, NULL, NULL);
00409   if ((NSSItem *) NULL == iOperation->buffer) {
00410     *pError = CKR_HOST_MEMORY;
00411     return 0;
00412   }
00413   /* Sigh, reverse it */
00414   ckcapi_ReverseData(iOperation->buffer);
00415   
00416   rc = CryptDecrypt(iOperation->hKey, 0, TRUE, 0, 
00417                   iOperation->buffer->data, &iOperation->buffer->size);
00418   if (!rc) {
00419     DWORD msError = GetLastError();
00420     switch (msError) {
00421     case NTE_BAD_DATA:
00422       *pError = CKR_ENCRYPTED_DATA_INVALID;
00423       break;
00424     case NTE_FAIL:
00425     case NTE_BAD_UID:
00426       *pError = CKR_DEVICE_ERROR;
00427       break;
00428     default:
00429       *pError = CKR_GENERAL_ERROR; 
00430     }
00431     return 0;
00432   }
00433 
00434   return iOperation->buffer->size;
00435 }
00436 
00437 /*
00438  * ckcapi_mdCryptoOperationRSADecrypt_UpdateFinal
00439  *
00440  * NOTE: ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength is presumed to 
00441  * have been called previously.
00442  */
00443 static CK_RV
00444 ckcapi_mdCryptoOperationRSADecrypt_UpdateFinal
00445 (
00446   NSSCKMDCryptoOperation *mdOperation,
00447   NSSCKFWCryptoOperation *fwOperation,
00448   NSSCKMDSession *mdSession,
00449   NSSCKFWSession *fwSession,
00450   NSSCKMDToken *mdToken,
00451   NSSCKFWToken *fwToken,
00452   NSSCKMDInstance *mdInstance,
00453   NSSCKFWInstance *fwInstance,
00454   const NSSItem *input,
00455   NSSItem *output
00456 )
00457 {
00458   ckcapiInternalCryptoOperationRSAPriv *iOperation =
00459        (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc;
00460   NSSItem *buffer = iOperation->buffer;
00461 
00462   if ((NSSItem *)NULL == buffer) {
00463     return CKR_GENERAL_ERROR;
00464   }
00465   nsslibc_memcpy(output->data, buffer->data, buffer->size);
00466   output->size = buffer->size;
00467   return CKR_OK;
00468 }
00469 
00470 /*
00471  * ckcapi_mdCryptoOperationRSASign_UpdateFinal
00472  *
00473  */
00474 static CK_RV
00475 ckcapi_mdCryptoOperationRSASign_UpdateFinal
00476 (
00477   NSSCKMDCryptoOperation *mdOperation,
00478   NSSCKFWCryptoOperation *fwOperation,
00479   NSSCKMDSession *mdSession,
00480   NSSCKFWSession *fwSession,
00481   NSSCKMDToken *mdToken,
00482   NSSCKFWToken *fwToken,
00483   NSSCKMDInstance *mdInstance,
00484   NSSCKFWInstance *fwInstance,
00485   const NSSItem *input,
00486   NSSItem *output
00487 )
00488 {
00489   ckcapiInternalCryptoOperationRSAPriv *iOperation =
00490        (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc;
00491   CK_RV error = CKR_OK;
00492   DWORD msError;
00493   NSSItem hash;
00494   HCRYPTHASH hHash = 0;
00495   ALG_ID  hashAlg;
00496   DWORD  hashSize;
00497   DWORD  len; /* temp length value we throw away */
00498   BOOL   rc;
00499 
00500   /*
00501    * PKCS #11 sign for RSA expects to take a fully DER-encoded hash value, 
00502    * which includes the hash OID. CAPI expects to take a Hash Context. While 
00503    * CAPI does have the capability of setting a raw hash value, it does not 
00504    * have the ability to sign an arbitrary value. This function tries to
00505    * reduce the passed in data into something that CAPI could actually sign.
00506    */
00507   error = ckcapi_GetRawHash(input, &hash, &hashAlg);
00508   if (CKR_OK != error) {
00509     goto loser;
00510   }
00511 
00512   rc = CryptCreateHash(iOperation->hProv, hashAlg, 0, 0, &hHash);
00513   if (!rc) {
00514     goto loser;
00515   }
00516 
00517   /* make sure the hash lens match before we set it */
00518   len = sizeof(DWORD);
00519   rc = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&hashSize, &len, 0);
00520   if (!rc) {
00521     goto loser;
00522   }
00523 
00524   if (hash.size != hashSize) {
00525     /* The input must have been bad for this to happen */
00526     error = CKR_DATA_INVALID;
00527     goto loser;
00528   }
00529 
00530   /* we have an explicit hash, set it, note that the length is
00531    * implicit by the hashAlg used in create */
00532   rc = CryptSetHashParam(hHash, HP_HASHVAL, hash.data, 0);
00533   if (!rc) {
00534     goto loser;
00535   }
00536 
00537   /* OK, we have the data in a hash structure, sign it! */
00538   rc = CryptSignHash(hHash, iOperation->keySpec, NULL, 0,
00539                      output->data, &output->size);
00540   if (!rc) {
00541     goto loser;
00542   }
00543 
00544   /* Don't return a signature that might have been broken because of a cosmic
00545    * ray, or a broken processor, verify that it is valid... */
00546   rc = CryptVerifySignature(hHash, output->data, output->size, 
00547                             iOperation->hKey, NULL, 0);
00548   if (!rc) {
00549     goto loser;
00550   }
00551 
00552   /* OK, Microsoft likes to do things completely differently than anyone
00553    * else. We need to reverse the data we recieved here */
00554   ckcapi_ReverseData(output);
00555   CryptDestroyHash(hHash);
00556   return CKR_OK;
00557 
00558 loser:
00559   /* map the microsoft error */
00560   if (CKR_OK == error) {
00561     msError = GetLastError();
00562     switch (msError) {
00563     case ERROR_NOT_ENOUGH_MEMORY:
00564       error = CKR_HOST_MEMORY;
00565       break;
00566     case NTE_NO_MEMORY:
00567       error = CKR_DEVICE_MEMORY;
00568       break;
00569     case ERROR_MORE_DATA:
00570       return CKR_BUFFER_TOO_SMALL;
00571     case ERROR_INVALID_PARAMETER: /* these params were derived from the */
00572     case ERROR_INVALID_HANDLE:    /* inputs, so if they are bad, the input */ 
00573     case NTE_BAD_ALGID:           /* data is bad */
00574     case NTE_BAD_HASH:
00575       error = CKR_DATA_INVALID;
00576       break;
00577     case ERROR_BUSY:
00578     case NTE_FAIL:
00579     case NTE_BAD_UID:
00580       error = CKR_DEVICE_ERROR;
00581       break;
00582     default:
00583       error = CKR_GENERAL_ERROR;
00584       break;
00585     }
00586   }
00587   if (hHash) {
00588     CryptDestroyHash(hHash);
00589   }
00590   return error;
00591 }
00592   
00593 
00594 NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation
00595 ckcapi_mdCryptoOperationRSADecrypt_proto = {
00596   NULL, /* etc */
00597   ckcapi_mdCryptoOperationRSAPriv_Destroy,
00598   NULL, /* GetFinalLengh - not needed for one shot Decrypt/Encrypt */
00599   ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength,
00600   NULL, /* Final - not needed for one shot operation */
00601   NULL, /* Update - not needed for one shot operation */
00602   NULL, /* DigetUpdate - not needed for one shot operation */
00603   ckcapi_mdCryptoOperationRSADecrypt_UpdateFinal,
00604   NULL, /* UpdateCombo - not needed for one shot operation */
00605   NULL, /* DigetKey - not needed for one shot operation */
00606   (void *)NULL /* null terminator */
00607 };
00608 
00609 NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation
00610 ckcapi_mdCryptoOperationRSASign_proto = {
00611   NULL, /* etc */
00612   ckcapi_mdCryptoOperationRSAPriv_Destroy,
00613   ckcapi_mdCryptoOperationRSA_GetFinalLength,
00614   NULL, /* GetOperationLengh - not needed for one shot Sign/Verify */
00615   NULL, /* Final - not needed for one shot operation */
00616   NULL, /* Update - not needed for one shot operation */
00617   NULL, /* DigetUpdate - not needed for one shot operation */
00618   ckcapi_mdCryptoOperationRSASign_UpdateFinal,
00619   NULL, /* UpdateCombo - not needed for one shot operation */
00620   NULL, /* DigetKey - not needed for one shot operation */
00621   (void *)NULL /* null terminator */
00622 };
00623 
00624 /********** NSSCKMDMechansim functions ***********************/
00625 /*
00626  * ckcapi_mdMechanismRSA_Destroy
00627  */
00628 static void
00629 ckcapi_mdMechanismRSA_Destroy
00630 (
00631   NSSCKMDMechanism *mdMechanism,
00632   NSSCKFWMechanism *fwMechanism,
00633   NSSCKMDInstance *mdInstance,
00634   NSSCKFWInstance *fwInstance
00635 )
00636 {
00637   nss_ZFreeIf(fwMechanism);
00638 }
00639 
00640 /*
00641  * ckcapi_mdMechanismRSA_GetMinKeySize
00642  */
00643 static CK_ULONG
00644 ckcapi_mdMechanismRSA_GetMinKeySize
00645 (
00646   NSSCKMDMechanism *mdMechanism,
00647   NSSCKFWMechanism *fwMechanism,
00648   NSSCKMDToken *mdToken,
00649   NSSCKFWToken *fwToken,
00650   NSSCKMDInstance *mdInstance,
00651   NSSCKFWInstance *fwInstance,
00652   CK_RV *pError
00653 )
00654 {
00655   return 384;
00656 }
00657 
00658 /*
00659  * ckcapi_mdMechanismRSA_GetMaxKeySize
00660  */
00661 static CK_ULONG
00662 ckcapi_mdMechanismRSA_GetMaxKeySize
00663 (
00664   NSSCKMDMechanism *mdMechanism,
00665   NSSCKFWMechanism *fwMechanism,
00666   NSSCKMDToken *mdToken,
00667   NSSCKFWToken *fwToken,
00668   NSSCKMDInstance *mdInstance,
00669   NSSCKFWInstance *fwInstance,
00670   CK_RV *pError
00671 )
00672 {
00673   return 16384;
00674 }
00675 
00676 /*
00677  * ckcapi_mdMechanismRSA_DecryptInit
00678  */
00679 static NSSCKMDCryptoOperation * 
00680 ckcapi_mdMechanismRSA_DecryptInit
00681 (
00682   NSSCKMDMechanism *mdMechanism,
00683   NSSCKFWMechanism *fwMechanism,
00684   CK_MECHANISM     *pMechanism,
00685   NSSCKMDSession *mdSession,
00686   NSSCKFWSession *fwSession,
00687   NSSCKMDToken *mdToken,
00688   NSSCKFWToken *fwToken,
00689   NSSCKMDInstance *mdInstance,
00690   NSSCKFWInstance *fwInstance,
00691   NSSCKMDObject *mdKey,
00692   NSSCKFWObject *fwKey,
00693   CK_RV *pError
00694 )
00695 {
00696   return ckcapi_mdCryptoOperationRSAPriv_Create(
00697               &ckcapi_mdCryptoOperationRSADecrypt_proto,
00698               mdMechanism, mdKey, pError);
00699 }
00700 
00701 /*
00702  * ckcapi_mdMechanismRSA_SignInit
00703  */
00704 static NSSCKMDCryptoOperation * 
00705 ckcapi_mdMechanismRSA_SignInit
00706 (
00707   NSSCKMDMechanism *mdMechanism,
00708   NSSCKFWMechanism *fwMechanism,
00709   CK_MECHANISM     *pMechanism,
00710   NSSCKMDSession *mdSession,
00711   NSSCKFWSession *fwSession,
00712   NSSCKMDToken *mdToken,
00713   NSSCKFWToken *fwToken,
00714   NSSCKMDInstance *mdInstance,
00715   NSSCKFWInstance *fwInstance,
00716   NSSCKMDObject *mdKey,
00717   NSSCKFWObject *fwKey,
00718   CK_RV *pError
00719 )
00720 {
00721   return ckcapi_mdCryptoOperationRSAPriv_Create(
00722               &ckcapi_mdCryptoOperationRSASign_proto,
00723               mdMechanism, mdKey, pError);
00724 }
00725 
00726 
00727 NSS_IMPLEMENT_DATA const NSSCKMDMechanism
00728 nss_ckcapi_mdMechanismRSA = {
00729   (void *)NULL, /* etc */
00730   ckcapi_mdMechanismRSA_Destroy,
00731   ckcapi_mdMechanismRSA_GetMinKeySize,
00732   ckcapi_mdMechanismRSA_GetMaxKeySize,
00733   NULL, /* GetInHardware - default false */
00734   NULL, /* EncryptInit - default errs */
00735   ckcapi_mdMechanismRSA_DecryptInit,
00736   NULL, /* DigestInit - default errs*/
00737   ckcapi_mdMechanismRSA_SignInit,
00738   NULL, /* VerifyInit - default errs */
00739   ckcapi_mdMechanismRSA_SignInit,  /* SignRecoverInit */
00740   NULL, /* VerifyRecoverInit - default errs */
00741   NULL, /* GenerateKey - default errs */
00742   NULL, /* GenerateKeyPair - default errs */
00743   NULL, /* GetWrapKeyLength - default errs */
00744   NULL, /* WrapKey - default errs */
00745   NULL, /* UnwrapKey - default errs */
00746   NULL, /* DeriveKey - default errs */
00747   (void *)NULL /* null terminator */
00748 };