michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "ckcapi.h" michael@0: #include "secdert.h" michael@0: michael@0: #define SSL3_SHAMD5_HASH_SIZE 36 /* LEN_MD5 (16) + LEN_SHA1 (20) */ michael@0: michael@0: /* michael@0: * ckcapi/crsa.c michael@0: * michael@0: * This file implements the NSSCKMDMechnaism and NSSCKMDCryptoOperation objects michael@0: * for the RSA operation on the CAPI cryptoki module. michael@0: */ michael@0: michael@0: /* michael@0: * write a Decimal value to a string michael@0: */ michael@0: michael@0: static char * michael@0: putDecimalString(char *cstr, unsigned long value) michael@0: { michael@0: unsigned long tenpower; michael@0: int first = 1; michael@0: michael@0: for (tenpower=10000000; tenpower; tenpower /= 10) { michael@0: unsigned char digit = (unsigned char )(value/tenpower); michael@0: value = value % tenpower; michael@0: michael@0: /* drop leading zeros */ michael@0: if (first && (0 == digit)) { michael@0: continue; michael@0: } michael@0: first = 0; michael@0: *cstr++ = digit + '0'; michael@0: } michael@0: michael@0: /* if value was zero, put one of them out */ michael@0: if (first) { michael@0: *cstr++ = '0'; michael@0: } michael@0: return cstr; michael@0: } michael@0: michael@0: michael@0: /* michael@0: * Create a Capi OID string value from a DER OID michael@0: */ michael@0: static char * michael@0: nss_ckcapi_GetOidString michael@0: ( michael@0: unsigned char *oidTag, michael@0: unsigned int oidTagSize, michael@0: CK_RV *pError michael@0: ) michael@0: { michael@0: unsigned char *oid; michael@0: char *oidStr; michael@0: char *cstr; michael@0: unsigned long value; michael@0: unsigned int oidSize; michael@0: michael@0: if (DER_OBJECT_ID != *oidTag) { michael@0: /* wasn't an oid */ michael@0: *pError = CKR_DATA_INVALID; michael@0: return NULL; michael@0: } michael@0: oid = nss_ckcapi_DERUnwrap(oidTag, oidTagSize, &oidSize, NULL); michael@0: michael@0: if (oidSize < 2) { michael@0: *pError = CKR_DATA_INVALID; michael@0: return NULL; michael@0: } michael@0: michael@0: oidStr = nss_ZNEWARRAY( NULL, char, oidSize*4 ); michael@0: if ((char *)NULL == oidStr) { michael@0: *pError = CKR_HOST_MEMORY; michael@0: return NULL; michael@0: } michael@0: cstr = oidStr; michael@0: cstr = putDecimalString(cstr, (*oid) / 40); michael@0: *cstr++ = '.'; michael@0: cstr = putDecimalString(cstr, (*oid) % 40); michael@0: oidSize--; michael@0: michael@0: value = 0; michael@0: while (oidSize--) { michael@0: oid++; michael@0: value = (value << 7) + (*oid & 0x7f); michael@0: if (0 == (*oid & 0x80)) { michael@0: *cstr++ = '.'; michael@0: cstr = putDecimalString(cstr, value); michael@0: value = 0; michael@0: } michael@0: } michael@0: michael@0: *cstr = 0; /* NULL terminate */ michael@0: michael@0: if (value != 0) { michael@0: nss_ZFreeIf(oidStr); michael@0: *pError = CKR_DATA_INVALID; michael@0: return NULL; michael@0: } michael@0: return oidStr; michael@0: } michael@0: michael@0: michael@0: /* michael@0: * PKCS #11 sign for RSA expects to take a fully DER-encoded hash value, michael@0: * which includes the hash OID. CAPI expects to take a Hash Context. While michael@0: * CAPI does have the capability of setting a raw hash value, it does not michael@0: * have the ability to sign an arbitrary value. This function tries to michael@0: * reduce the passed in data into something that CAPI could actually sign. michael@0: */ michael@0: static CK_RV michael@0: ckcapi_GetRawHash michael@0: ( michael@0: const NSSItem *input, michael@0: NSSItem *hash, michael@0: ALG_ID *hashAlg michael@0: ) michael@0: { michael@0: unsigned char *current; michael@0: unsigned char *algid; michael@0: unsigned char *oid; michael@0: unsigned char *hashData; michael@0: char *oidStr; michael@0: CK_RV error; michael@0: unsigned int oidSize; michael@0: unsigned int size; michael@0: /* michael@0: * there are 2 types of hashes NSS typically tries to sign, regular michael@0: * RSA signature format (with encoded DER_OIDS), and SSL3 Signed hashes. michael@0: * CAPI knows not to add any oids to SSL3_Signed hashes, so if we have any michael@0: * random hash that is exactly the same size as an SSL3 hash, then we can michael@0: * just pass the data through. CAPI has know way of knowing if the value michael@0: * is really a combined hash or some other arbitrary data, so it's safe to michael@0: * handle this case first. michael@0: */ michael@0: if (SSL3_SHAMD5_HASH_SIZE == input->size) { michael@0: hash->data = input->data; michael@0: hash->size = input->size; michael@0: *hashAlg = CALG_SSL3_SHAMD5; michael@0: return CKR_OK; michael@0: } michael@0: michael@0: current = (unsigned char *)input->data; michael@0: michael@0: /* make sure we have a sequence tag */ michael@0: if ((DER_SEQUENCE|DER_CONSTRUCTED) != *current) { michael@0: return CKR_DATA_INVALID; michael@0: } michael@0: michael@0: /* parse the input block to get 1) the hash oid, and 2) the raw hash value. michael@0: * unfortunatly CAPI doesn't have a builtin function to do this work, so michael@0: * we go ahead and do it by hand here. michael@0: * michael@0: * format is: michael@0: * SEQUENCE { michael@0: * SECQUENCE { // algid michael@0: * OID {} // oid michael@0: * ANY {} // optional params michael@0: * } michael@0: * OCTECT {} // hash michael@0: */ michael@0: michael@0: /* unwrap */ michael@0: algid = nss_ckcapi_DERUnwrap(current,input->size, &size, NULL); michael@0: michael@0: if (algid+size != current+input->size) { michael@0: /* make sure there is not extra data at the end */ michael@0: return CKR_DATA_INVALID; michael@0: } michael@0: michael@0: if ((DER_SEQUENCE|DER_CONSTRUCTED) != *algid) { michael@0: /* wasn't an algid */ michael@0: return CKR_DATA_INVALID; michael@0: } michael@0: oid = nss_ckcapi_DERUnwrap(algid, size, &oidSize, &hashData); michael@0: michael@0: if (DER_OCTET_STRING != *hashData) { michael@0: /* wasn't a hash */ michael@0: return CKR_DATA_INVALID; michael@0: } michael@0: michael@0: /* get the real hash */ michael@0: current = hashData; michael@0: size = size - (hashData-algid); michael@0: hash->data = nss_ckcapi_DERUnwrap(current, size, &hash->size, NULL); michael@0: michael@0: /* get the real oid as a string. Again, Microsoft does not michael@0: * export anything that does this for us */ michael@0: oidStr = nss_ckcapi_GetOidString(oid, oidSize, &error); michael@0: if ((char *)NULL == oidStr ) { michael@0: return error; michael@0: } michael@0: michael@0: /* look up the hash alg from the oid (fortunately CAPI does to this) */ michael@0: *hashAlg = CertOIDToAlgId(oidStr); michael@0: nss_ZFreeIf(oidStr); michael@0: if (0 == *hashAlg) { michael@0: return CKR_HOST_MEMORY; michael@0: } michael@0: michael@0: /* hash looks reasonably consistent, we should be able to sign it now */ michael@0: return CKR_OK; michael@0: } michael@0: michael@0: /* michael@0: * So everyone else in the worlds stores their bignum data MSB first, but not michael@0: * Microsoft, we need to byte swap everything coming into and out of CAPI. michael@0: */ michael@0: void michael@0: ckcapi_ReverseData(NSSItem *item) michael@0: { michael@0: int end = (item->size)-1; michael@0: int middle = (item->size)/2; michael@0: unsigned char *buf = item->data; michael@0: int i; michael@0: michael@0: for (i=0; i < middle; i++) { michael@0: unsigned char tmp = buf[i]; michael@0: buf[i] = buf[end-i]; michael@0: buf[end-i] = tmp; michael@0: } michael@0: return; michael@0: } michael@0: michael@0: typedef struct ckcapiInternalCryptoOperationRSAPrivStr michael@0: ckcapiInternalCryptoOperationRSAPriv; michael@0: struct ckcapiInternalCryptoOperationRSAPrivStr michael@0: { michael@0: NSSCKMDCryptoOperation mdOperation; michael@0: NSSCKMDMechanism *mdMechanism; michael@0: ckcapiInternalObject *iKey; michael@0: HCRYPTPROV hProv; michael@0: DWORD keySpec; michael@0: HCRYPTKEY hKey; michael@0: NSSItem *buffer; michael@0: }; michael@0: michael@0: /* michael@0: * ckcapi_mdCryptoOperationRSAPriv_Create michael@0: */ michael@0: static NSSCKMDCryptoOperation * michael@0: ckcapi_mdCryptoOperationRSAPriv_Create michael@0: ( michael@0: const NSSCKMDCryptoOperation *proto, michael@0: NSSCKMDMechanism *mdMechanism, michael@0: NSSCKMDObject *mdKey, michael@0: CK_RV *pError michael@0: ) michael@0: { michael@0: ckcapiInternalObject *iKey = (ckcapiInternalObject *)mdKey->etc; michael@0: const NSSItem *classItem = nss_ckcapi_FetchAttribute(iKey, CKA_CLASS); michael@0: const NSSItem *keyType = nss_ckcapi_FetchAttribute(iKey, CKA_KEY_TYPE); michael@0: ckcapiInternalCryptoOperationRSAPriv *iOperation; michael@0: CK_RV error; michael@0: HCRYPTPROV hProv; michael@0: DWORD keySpec; michael@0: HCRYPTKEY hKey; michael@0: michael@0: /* make sure we have the right objects */ michael@0: if (((const NSSItem *)NULL == classItem) || michael@0: (sizeof(CK_OBJECT_CLASS) != classItem->size) || michael@0: (CKO_PRIVATE_KEY != *(CK_OBJECT_CLASS *)classItem->data) || michael@0: ((const NSSItem *)NULL == keyType) || michael@0: (sizeof(CK_KEY_TYPE) != keyType->size) || michael@0: (CKK_RSA != *(CK_KEY_TYPE *)keyType->data)) { michael@0: *pError = CKR_KEY_TYPE_INCONSISTENT; michael@0: return (NSSCKMDCryptoOperation *)NULL; michael@0: } michael@0: michael@0: error = nss_ckcapi_FetchKeyContainer(iKey, &hProv, &keySpec, &hKey); michael@0: if (error != CKR_OK) { michael@0: *pError = error; michael@0: return (NSSCKMDCryptoOperation *)NULL; michael@0: } michael@0: michael@0: iOperation = nss_ZNEW(NULL, ckcapiInternalCryptoOperationRSAPriv); michael@0: if ((ckcapiInternalCryptoOperationRSAPriv *)NULL == iOperation) { michael@0: *pError = CKR_HOST_MEMORY; michael@0: return (NSSCKMDCryptoOperation *)NULL; michael@0: } michael@0: iOperation->mdMechanism = mdMechanism; michael@0: iOperation->iKey = iKey; michael@0: iOperation->hProv = hProv; michael@0: iOperation->keySpec = keySpec; michael@0: iOperation->hKey = hKey; michael@0: michael@0: nsslibc_memcpy(&iOperation->mdOperation, michael@0: proto, sizeof(NSSCKMDCryptoOperation)); michael@0: iOperation->mdOperation.etc = iOperation; michael@0: michael@0: return &iOperation->mdOperation; michael@0: } michael@0: michael@0: static CK_RV michael@0: ckcapi_mdCryptoOperationRSAPriv_Destroy michael@0: ( michael@0: NSSCKMDCryptoOperation *mdOperation, michael@0: NSSCKFWCryptoOperation *fwOperation, michael@0: NSSCKMDInstance *mdInstance, michael@0: NSSCKFWInstance *fwInstance michael@0: ) michael@0: { michael@0: ckcapiInternalCryptoOperationRSAPriv *iOperation = michael@0: (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc; michael@0: michael@0: if (iOperation->hKey) { michael@0: CryptDestroyKey(iOperation->hKey); michael@0: } michael@0: if (iOperation->buffer) { michael@0: nssItem_Destroy(iOperation->buffer); michael@0: } michael@0: nss_ZFreeIf(iOperation); michael@0: return CKR_OK; michael@0: } michael@0: michael@0: static CK_ULONG michael@0: ckcapi_mdCryptoOperationRSA_GetFinalLength michael@0: ( michael@0: NSSCKMDCryptoOperation *mdOperation, michael@0: NSSCKFWCryptoOperation *fwOperation, michael@0: NSSCKMDSession *mdSession, michael@0: NSSCKFWSession *fwSession, michael@0: NSSCKMDToken *mdToken, michael@0: NSSCKFWToken *fwToken, michael@0: NSSCKMDInstance *mdInstance, michael@0: NSSCKFWInstance *fwInstance, michael@0: CK_RV *pError michael@0: ) michael@0: { michael@0: ckcapiInternalCryptoOperationRSAPriv *iOperation = michael@0: (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc; michael@0: const NSSItem *modulus = michael@0: nss_ckcapi_FetchAttribute(iOperation->iKey, CKA_MODULUS); michael@0: michael@0: return modulus->size; michael@0: } michael@0: michael@0: michael@0: /* michael@0: * ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength michael@0: * we won't know the length until we actually decrypt the michael@0: * input block. Since we go to all the work to decrypt the michael@0: * the block, we'll save if for when the block is asked for michael@0: */ michael@0: static CK_ULONG michael@0: ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength michael@0: ( michael@0: NSSCKMDCryptoOperation *mdOperation, michael@0: NSSCKFWCryptoOperation *fwOperation, michael@0: NSSCKMDSession *mdSession, michael@0: NSSCKFWSession *fwSession, michael@0: NSSCKMDToken *mdToken, michael@0: NSSCKFWToken *fwToken, michael@0: NSSCKMDInstance *mdInstance, michael@0: NSSCKFWInstance *fwInstance, michael@0: const NSSItem *input, michael@0: CK_RV *pError michael@0: ) michael@0: { michael@0: ckcapiInternalCryptoOperationRSAPriv *iOperation = michael@0: (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc; michael@0: BOOL rc; michael@0: michael@0: /* Microsoft's Decrypt operation works in place. Since we don't want michael@0: * to trash our input buffer, we make a copy of it */ michael@0: iOperation->buffer = nssItem_Duplicate((NSSItem *)input, NULL, NULL); michael@0: if ((NSSItem *) NULL == iOperation->buffer) { michael@0: *pError = CKR_HOST_MEMORY; michael@0: return 0; michael@0: } michael@0: /* Sigh, reverse it */ michael@0: ckcapi_ReverseData(iOperation->buffer); michael@0: michael@0: rc = CryptDecrypt(iOperation->hKey, 0, TRUE, 0, michael@0: iOperation->buffer->data, &iOperation->buffer->size); michael@0: if (!rc) { michael@0: DWORD msError = GetLastError(); michael@0: switch (msError) { michael@0: case NTE_BAD_DATA: michael@0: *pError = CKR_ENCRYPTED_DATA_INVALID; michael@0: break; michael@0: case NTE_FAIL: michael@0: case NTE_BAD_UID: michael@0: *pError = CKR_DEVICE_ERROR; michael@0: break; michael@0: default: michael@0: *pError = CKR_GENERAL_ERROR; michael@0: } michael@0: return 0; michael@0: } michael@0: michael@0: return iOperation->buffer->size; michael@0: } michael@0: michael@0: /* michael@0: * ckcapi_mdCryptoOperationRSADecrypt_UpdateFinal michael@0: * michael@0: * NOTE: ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength is presumed to michael@0: * have been called previously. michael@0: */ michael@0: static CK_RV michael@0: ckcapi_mdCryptoOperationRSADecrypt_UpdateFinal michael@0: ( michael@0: NSSCKMDCryptoOperation *mdOperation, michael@0: NSSCKFWCryptoOperation *fwOperation, michael@0: NSSCKMDSession *mdSession, michael@0: NSSCKFWSession *fwSession, michael@0: NSSCKMDToken *mdToken, michael@0: NSSCKFWToken *fwToken, michael@0: NSSCKMDInstance *mdInstance, michael@0: NSSCKFWInstance *fwInstance, michael@0: const NSSItem *input, michael@0: NSSItem *output michael@0: ) michael@0: { michael@0: ckcapiInternalCryptoOperationRSAPriv *iOperation = michael@0: (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc; michael@0: NSSItem *buffer = iOperation->buffer; michael@0: michael@0: if ((NSSItem *)NULL == buffer) { michael@0: return CKR_GENERAL_ERROR; michael@0: } michael@0: nsslibc_memcpy(output->data, buffer->data, buffer->size); michael@0: output->size = buffer->size; michael@0: return CKR_OK; michael@0: } michael@0: michael@0: /* michael@0: * ckcapi_mdCryptoOperationRSASign_UpdateFinal michael@0: * michael@0: */ michael@0: static CK_RV michael@0: ckcapi_mdCryptoOperationRSASign_UpdateFinal michael@0: ( michael@0: NSSCKMDCryptoOperation *mdOperation, michael@0: NSSCKFWCryptoOperation *fwOperation, michael@0: NSSCKMDSession *mdSession, michael@0: NSSCKFWSession *fwSession, michael@0: NSSCKMDToken *mdToken, michael@0: NSSCKFWToken *fwToken, michael@0: NSSCKMDInstance *mdInstance, michael@0: NSSCKFWInstance *fwInstance, michael@0: const NSSItem *input, michael@0: NSSItem *output michael@0: ) michael@0: { michael@0: ckcapiInternalCryptoOperationRSAPriv *iOperation = michael@0: (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc; michael@0: CK_RV error = CKR_OK; michael@0: DWORD msError; michael@0: NSSItem hash; michael@0: HCRYPTHASH hHash = 0; michael@0: ALG_ID hashAlg; michael@0: DWORD hashSize; michael@0: DWORD len; /* temp length value we throw away */ michael@0: BOOL rc; michael@0: michael@0: /* michael@0: * PKCS #11 sign for RSA expects to take a fully DER-encoded hash value, michael@0: * which includes the hash OID. CAPI expects to take a Hash Context. While michael@0: * CAPI does have the capability of setting a raw hash value, it does not michael@0: * have the ability to sign an arbitrary value. This function tries to michael@0: * reduce the passed in data into something that CAPI could actually sign. michael@0: */ michael@0: error = ckcapi_GetRawHash(input, &hash, &hashAlg); michael@0: if (CKR_OK != error) { michael@0: goto loser; michael@0: } michael@0: michael@0: rc = CryptCreateHash(iOperation->hProv, hashAlg, 0, 0, &hHash); michael@0: if (!rc) { michael@0: goto loser; michael@0: } michael@0: michael@0: /* make sure the hash lens match before we set it */ michael@0: len = sizeof(DWORD); michael@0: rc = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&hashSize, &len, 0); michael@0: if (!rc) { michael@0: goto loser; michael@0: } michael@0: michael@0: if (hash.size != hashSize) { michael@0: /* The input must have been bad for this to happen */ michael@0: error = CKR_DATA_INVALID; michael@0: goto loser; michael@0: } michael@0: michael@0: /* we have an explicit hash, set it, note that the length is michael@0: * implicit by the hashAlg used in create */ michael@0: rc = CryptSetHashParam(hHash, HP_HASHVAL, hash.data, 0); michael@0: if (!rc) { michael@0: goto loser; michael@0: } michael@0: michael@0: /* OK, we have the data in a hash structure, sign it! */ michael@0: rc = CryptSignHash(hHash, iOperation->keySpec, NULL, 0, michael@0: output->data, &output->size); michael@0: if (!rc) { michael@0: goto loser; michael@0: } michael@0: michael@0: /* Don't return a signature that might have been broken because of a cosmic michael@0: * ray, or a broken processor, verify that it is valid... */ michael@0: rc = CryptVerifySignature(hHash, output->data, output->size, michael@0: iOperation->hKey, NULL, 0); michael@0: if (!rc) { michael@0: goto loser; michael@0: } michael@0: michael@0: /* OK, Microsoft likes to do things completely differently than anyone michael@0: * else. We need to reverse the data we received here */ michael@0: ckcapi_ReverseData(output); michael@0: CryptDestroyHash(hHash); michael@0: return CKR_OK; michael@0: michael@0: loser: michael@0: /* map the microsoft error */ michael@0: if (CKR_OK == error) { michael@0: msError = GetLastError(); michael@0: switch (msError) { michael@0: case ERROR_NOT_ENOUGH_MEMORY: michael@0: error = CKR_HOST_MEMORY; michael@0: break; michael@0: case NTE_NO_MEMORY: michael@0: error = CKR_DEVICE_MEMORY; michael@0: break; michael@0: case ERROR_MORE_DATA: michael@0: return CKR_BUFFER_TOO_SMALL; michael@0: case ERROR_INVALID_PARAMETER: /* these params were derived from the */ michael@0: case ERROR_INVALID_HANDLE: /* inputs, so if they are bad, the input */ michael@0: case NTE_BAD_ALGID: /* data is bad */ michael@0: case NTE_BAD_HASH: michael@0: error = CKR_DATA_INVALID; michael@0: break; michael@0: case ERROR_BUSY: michael@0: case NTE_FAIL: michael@0: case NTE_BAD_UID: michael@0: error = CKR_DEVICE_ERROR; michael@0: break; michael@0: default: michael@0: error = CKR_GENERAL_ERROR; michael@0: break; michael@0: } michael@0: } michael@0: if (hHash) { michael@0: CryptDestroyHash(hHash); michael@0: } michael@0: return error; michael@0: } michael@0: michael@0: michael@0: NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation michael@0: ckcapi_mdCryptoOperationRSADecrypt_proto = { michael@0: NULL, /* etc */ michael@0: ckcapi_mdCryptoOperationRSAPriv_Destroy, michael@0: NULL, /* GetFinalLengh - not needed for one shot Decrypt/Encrypt */ michael@0: ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength, michael@0: NULL, /* Final - not needed for one shot operation */ michael@0: NULL, /* Update - not needed for one shot operation */ michael@0: NULL, /* DigetUpdate - not needed for one shot operation */ michael@0: ckcapi_mdCryptoOperationRSADecrypt_UpdateFinal, michael@0: NULL, /* UpdateCombo - not needed for one shot operation */ michael@0: NULL, /* DigetKey - not needed for one shot operation */ michael@0: (void *)NULL /* null terminator */ michael@0: }; michael@0: michael@0: NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation michael@0: ckcapi_mdCryptoOperationRSASign_proto = { michael@0: NULL, /* etc */ michael@0: ckcapi_mdCryptoOperationRSAPriv_Destroy, michael@0: ckcapi_mdCryptoOperationRSA_GetFinalLength, michael@0: NULL, /* GetOperationLengh - not needed for one shot Sign/Verify */ michael@0: NULL, /* Final - not needed for one shot operation */ michael@0: NULL, /* Update - not needed for one shot operation */ michael@0: NULL, /* DigetUpdate - not needed for one shot operation */ michael@0: ckcapi_mdCryptoOperationRSASign_UpdateFinal, michael@0: NULL, /* UpdateCombo - not needed for one shot operation */ michael@0: NULL, /* DigetKey - not needed for one shot operation */ michael@0: (void *)NULL /* null terminator */ michael@0: }; michael@0: michael@0: /********** NSSCKMDMechansim functions ***********************/ michael@0: /* michael@0: * ckcapi_mdMechanismRSA_Destroy michael@0: */ michael@0: static void michael@0: ckcapi_mdMechanismRSA_Destroy michael@0: ( michael@0: NSSCKMDMechanism *mdMechanism, michael@0: NSSCKFWMechanism *fwMechanism, michael@0: NSSCKMDInstance *mdInstance, michael@0: NSSCKFWInstance *fwInstance michael@0: ) michael@0: { michael@0: nss_ZFreeIf(fwMechanism); michael@0: } michael@0: michael@0: /* michael@0: * ckcapi_mdMechanismRSA_GetMinKeySize michael@0: */ michael@0: static CK_ULONG michael@0: ckcapi_mdMechanismRSA_GetMinKeySize michael@0: ( michael@0: NSSCKMDMechanism *mdMechanism, michael@0: NSSCKFWMechanism *fwMechanism, michael@0: NSSCKMDToken *mdToken, michael@0: NSSCKFWToken *fwToken, michael@0: NSSCKMDInstance *mdInstance, michael@0: NSSCKFWInstance *fwInstance, michael@0: CK_RV *pError michael@0: ) michael@0: { michael@0: return 384; michael@0: } michael@0: michael@0: /* michael@0: * ckcapi_mdMechanismRSA_GetMaxKeySize michael@0: */ michael@0: static CK_ULONG michael@0: ckcapi_mdMechanismRSA_GetMaxKeySize michael@0: ( michael@0: NSSCKMDMechanism *mdMechanism, michael@0: NSSCKFWMechanism *fwMechanism, michael@0: NSSCKMDToken *mdToken, michael@0: NSSCKFWToken *fwToken, michael@0: NSSCKMDInstance *mdInstance, michael@0: NSSCKFWInstance *fwInstance, michael@0: CK_RV *pError michael@0: ) michael@0: { michael@0: return 16384; michael@0: } michael@0: michael@0: /* michael@0: * ckcapi_mdMechanismRSA_DecryptInit michael@0: */ michael@0: static NSSCKMDCryptoOperation * michael@0: ckcapi_mdMechanismRSA_DecryptInit michael@0: ( michael@0: NSSCKMDMechanism *mdMechanism, michael@0: NSSCKFWMechanism *fwMechanism, michael@0: CK_MECHANISM *pMechanism, michael@0: NSSCKMDSession *mdSession, michael@0: NSSCKFWSession *fwSession, michael@0: NSSCKMDToken *mdToken, michael@0: NSSCKFWToken *fwToken, michael@0: NSSCKMDInstance *mdInstance, michael@0: NSSCKFWInstance *fwInstance, michael@0: NSSCKMDObject *mdKey, michael@0: NSSCKFWObject *fwKey, michael@0: CK_RV *pError michael@0: ) michael@0: { michael@0: return ckcapi_mdCryptoOperationRSAPriv_Create( michael@0: &ckcapi_mdCryptoOperationRSADecrypt_proto, michael@0: mdMechanism, mdKey, pError); michael@0: } michael@0: michael@0: /* michael@0: * ckcapi_mdMechanismRSA_SignInit michael@0: */ michael@0: static NSSCKMDCryptoOperation * michael@0: ckcapi_mdMechanismRSA_SignInit michael@0: ( michael@0: NSSCKMDMechanism *mdMechanism, michael@0: NSSCKFWMechanism *fwMechanism, michael@0: CK_MECHANISM *pMechanism, michael@0: NSSCKMDSession *mdSession, michael@0: NSSCKFWSession *fwSession, michael@0: NSSCKMDToken *mdToken, michael@0: NSSCKFWToken *fwToken, michael@0: NSSCKMDInstance *mdInstance, michael@0: NSSCKFWInstance *fwInstance, michael@0: NSSCKMDObject *mdKey, michael@0: NSSCKFWObject *fwKey, michael@0: CK_RV *pError michael@0: ) michael@0: { michael@0: return ckcapi_mdCryptoOperationRSAPriv_Create( michael@0: &ckcapi_mdCryptoOperationRSASign_proto, michael@0: mdMechanism, mdKey, pError); michael@0: } michael@0: michael@0: michael@0: NSS_IMPLEMENT_DATA const NSSCKMDMechanism michael@0: nss_ckcapi_mdMechanismRSA = { michael@0: (void *)NULL, /* etc */ michael@0: ckcapi_mdMechanismRSA_Destroy, michael@0: ckcapi_mdMechanismRSA_GetMinKeySize, michael@0: ckcapi_mdMechanismRSA_GetMaxKeySize, michael@0: NULL, /* GetInHardware - default false */ michael@0: NULL, /* EncryptInit - default errs */ michael@0: ckcapi_mdMechanismRSA_DecryptInit, michael@0: NULL, /* DigestInit - default errs*/ michael@0: ckcapi_mdMechanismRSA_SignInit, michael@0: NULL, /* VerifyInit - default errs */ michael@0: ckcapi_mdMechanismRSA_SignInit, /* SignRecoverInit */ michael@0: NULL, /* VerifyRecoverInit - default errs */ michael@0: NULL, /* GenerateKey - default errs */ michael@0: NULL, /* GenerateKeyPair - default errs */ michael@0: NULL, /* GetWrapKeyLength - default errs */ michael@0: NULL, /* WrapKey - default errs */ michael@0: NULL, /* UnwrapKey - default errs */ michael@0: NULL, /* DeriveKey - default errs */ michael@0: (void *)NULL /* null terminator */ michael@0: };