diff options
Diffstat (limited to 'security/nss/lib/ckfw/capi/cobject.c')
-rw-r--r-- | security/nss/lib/ckfw/capi/cobject.c | 2226 |
1 files changed, 0 insertions, 2226 deletions
diff --git a/security/nss/lib/ckfw/capi/cobject.c b/security/nss/lib/ckfw/capi/cobject.c deleted file mode 100644 index c4b77d27ae..0000000000 --- a/security/nss/lib/ckfw/capi/cobject.c +++ /dev/null @@ -1,2226 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ckcapi.h" -#include "nssbase.h" - -/* - * ckcapi/cobject.c - * - * This file implements the NSSCKMDObject object for the - * "nss to capi objects" cryptoki module. - */ - -const CK_ATTRIBUTE_TYPE certAttrs[] = { - CKA_CLASS, - CKA_TOKEN, - CKA_PRIVATE, - CKA_MODIFIABLE, - CKA_LABEL, - CKA_CERTIFICATE_TYPE, - CKA_SUBJECT, - CKA_ISSUER, - CKA_SERIAL_NUMBER, - CKA_VALUE -}; -const PRUint32 certAttrsCount = NSS_CKCAPI_ARRAY_SIZE(certAttrs); - -/* private keys, for now only support RSA */ -const CK_ATTRIBUTE_TYPE privKeyAttrs[] = { - CKA_CLASS, - CKA_TOKEN, - CKA_PRIVATE, - CKA_MODIFIABLE, - CKA_LABEL, - CKA_KEY_TYPE, - CKA_DERIVE, - CKA_LOCAL, - CKA_SUBJECT, - CKA_SENSITIVE, - CKA_DECRYPT, - CKA_SIGN, - CKA_SIGN_RECOVER, - CKA_UNWRAP, - CKA_EXTRACTABLE, - CKA_ALWAYS_SENSITIVE, - CKA_NEVER_EXTRACTABLE, - CKA_MODULUS, - CKA_PUBLIC_EXPONENT, -}; -const PRUint32 privKeyAttrsCount = NSS_CKCAPI_ARRAY_SIZE(privKeyAttrs); - -/* public keys, for now only support RSA */ -const CK_ATTRIBUTE_TYPE pubKeyAttrs[] = { - CKA_CLASS, - CKA_TOKEN, - CKA_PRIVATE, - CKA_MODIFIABLE, - CKA_LABEL, - CKA_KEY_TYPE, - CKA_DERIVE, - CKA_LOCAL, - CKA_SUBJECT, - CKA_ENCRYPT, - CKA_VERIFY, - CKA_VERIFY_RECOVER, - CKA_WRAP, - CKA_MODULUS, - CKA_PUBLIC_EXPONENT, -}; -const PRUint32 pubKeyAttrsCount = NSS_CKCAPI_ARRAY_SIZE(pubKeyAttrs); -static const CK_BBOOL ck_true = CK_TRUE; -static const CK_BBOOL ck_false = CK_FALSE; -static const CK_CERTIFICATE_TYPE ckc_x509 = CKC_X_509; -static const CK_KEY_TYPE ckk_rsa = CKK_RSA; -static const CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE; -static const CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY; -static const CK_OBJECT_CLASS cko_public_key = CKO_PUBLIC_KEY; -static const NSSItem ckcapi_trueItem = { - (void *)&ck_true, (PRUint32)sizeof(CK_BBOOL) -}; -static const NSSItem ckcapi_falseItem = { - (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL) -}; -static const NSSItem ckcapi_x509Item = { - (void *)&ckc_x509, (PRUint32)sizeof(CK_CERTIFICATE_TYPE) -}; -static const NSSItem ckcapi_rsaItem = { - (void *)&ckk_rsa, (PRUint32)sizeof(CK_KEY_TYPE) -}; -static const NSSItem ckcapi_certClassItem = { - (void *)&cko_certificate, (PRUint32)sizeof(CK_OBJECT_CLASS) -}; -static const NSSItem ckcapi_privKeyClassItem = { - (void *)&cko_private_key, (PRUint32)sizeof(CK_OBJECT_CLASS) -}; -static const NSSItem ckcapi_pubKeyClassItem = { - (void *)&cko_public_key, (PRUint32)sizeof(CK_OBJECT_CLASS) -}; -static const NSSItem ckcapi_emptyItem = { - (void *)&ck_true, 0 -}; - -/* - * these are utilities. The chould be moved to a new utilities file. - */ - -/* - * unwrap a single DER value - */ -unsigned char * -nss_ckcapi_DERUnwrap( - unsigned char *src, - unsigned int size, - unsigned int *outSize, - unsigned char **next) -{ - unsigned char *start = src; - unsigned char *end = src + size; - unsigned int len = 0; - - /* initialize error condition return values */ - *outSize = 0; - if (next) { - *next = src; - } - - if (size < 2) { - return start; - } - src++; /* skip the tag -- should check it against an expected value! */ - len = (unsigned)*src++; - if (len & 0x80) { - unsigned int count = len & 0x7f; - len = 0; - - if (count + 2 > size) { - return start; - } - while (count-- > 0) { - len = (len << 8) | (unsigned)*src++; - } - } - if (len + (src - start) > size) { - return start; - } - if (next) { - *next = src + len; - } - *outSize = len; - - return src; -} - -/* - * convert a PKCS #11 bytestrin into a CK_ULONG, the byte stream must be - * less than sizeof (CK_ULONG). - */ -CK_ULONG -nss_ckcapi_DataToInt( - NSSItem *data, - CK_RV *pError) -{ - CK_ULONG value = 0; - unsigned long count = data->size; - unsigned char *dataPtr = data->data; - unsigned long size = 0; - - *pError = CKR_OK; - - while (count--) { - value = value << 8; - value = value + *dataPtr++; - if (size || value) { - size++; - } - } - if (size > sizeof(CK_ULONG)) { - *pError = CKR_ATTRIBUTE_VALUE_INVALID; - } - return value; -} - -/* - * convert a CK_ULONG to a bytestream. Data is stored in the buffer 'buf' - * and must be at least CK_ULONG. Caller must provide buf. - */ -CK_ULONG -nss_ckcapi_IntToData( - CK_ULONG value, - NSSItem *data, - unsigned char *dataPtr, - CK_RV *pError) -{ - unsigned long count = 0; - unsigned long i; -#define SHIFT ((sizeof(CK_ULONG) - 1) * 8) - PRBool first = 0; - - *pError = CKR_OK; - - data->data = dataPtr; - for (i = 0; i < sizeof(CK_ULONG); i++) { - unsigned char digit = (unsigned char)((value >> SHIFT) & 0xff); - - value = value << 8; - - /* drop leading zero bytes */ - if (first && (0 == digit)) { - continue; - } - *dataPtr++ = digit; - count++; - } - data->size = count; - return count; -} - -/* - * get an attribute from a template. Value is returned in NSS item. - * data for the item is owned by the template. - */ -CK_RV -nss_ckcapi_GetAttribute( - CK_ATTRIBUTE_TYPE type, - CK_ATTRIBUTE *template, - CK_ULONG templateSize, - NSSItem *item) -{ - CK_ULONG i; - - for (i = 0; i < templateSize; i++) { - if (template[i].type == type) { - item->data = template[i].pValue; - item->size = template[i].ulValueLen; - return CKR_OK; - } - } - return CKR_TEMPLATE_INCOMPLETE; -} - -/* - * get an attribute which is type CK_ULONG. - */ -CK_ULONG -nss_ckcapi_GetULongAttribute( - CK_ATTRIBUTE_TYPE type, - CK_ATTRIBUTE *template, - CK_ULONG templateSize, - CK_RV *pError) -{ - NSSItem item; - - *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item); - if (CKR_OK != *pError) { - return (CK_ULONG)0; - } - if (item.size != sizeof(CK_ULONG)) { - *pError = CKR_ATTRIBUTE_VALUE_INVALID; - return (CK_ULONG)0; - } - return *(CK_ULONG *)item.data; -} - -/* - * get an attribute which is type CK_BBOOL. - */ -CK_BBOOL -nss_ckcapi_GetBoolAttribute( - CK_ATTRIBUTE_TYPE type, - CK_ATTRIBUTE *template, - CK_ULONG templateSize, - CK_RV *pError) -{ - NSSItem item; - - *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item); - if (CKR_OK != *pError) { - return (CK_BBOOL)0; - } - if (item.size != sizeof(CK_BBOOL)) { - *pError = CKR_ATTRIBUTE_VALUE_INVALID; - return (CK_BBOOL)0; - } - return *(CK_BBOOL *)item.data; -} - -/* - * get an attribute which is type CK_BBOOL. - */ -char * -nss_ckcapi_GetStringAttribute( - CK_ATTRIBUTE_TYPE type, - CK_ATTRIBUTE *template, - CK_ULONG templateSize, - CK_RV *pError) -{ - NSSItem item; - char *str; - - /* get the attribute */ - *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item); - if (CKR_OK != *pError) { - return (char *)NULL; - } - /* make sure it is null terminated */ - str = nss_ZNEWARRAY(NULL, char, item.size + 1); - if ((char *)NULL == str) { - *pError = CKR_HOST_MEMORY; - return (char *)NULL; - } - - nsslibc_memcpy(str, item.data, item.size); - str[item.size] = 0; - - return str; -} - -/* - * Return the size in bytes of a wide string, including the terminating null - * character - */ -int -nss_ckcapi_WideSize( - LPCWSTR wide) -{ - DWORD size; - - if ((LPWSTR)NULL == wide) { - return 0; - } - size = wcslen(wide) + 1; - return size * sizeof(WCHAR); -} - -/* - * Covert a Unicode wide character string to a UTF8 string - */ -char * -nss_ckcapi_WideToUTF8( - LPCWSTR wide) -{ - DWORD size; - char *buf; - - if ((LPWSTR)NULL == wide) { - return (char *)NULL; - } - - size = WideCharToMultiByte(CP_UTF8, 0, wide, -1, NULL, 0, NULL, 0); - if (size == 0) { - return (char *)NULL; - } - buf = nss_ZNEWARRAY(NULL, char, size); - size = WideCharToMultiByte(CP_UTF8, 0, wide, -1, buf, size, NULL, 0); - if (size == 0) { - nss_ZFreeIf(buf); - return (char *)NULL; - } - return buf; -} - -/* - * Return a Wide String duplicated with nss allocated memory. - */ -LPWSTR -nss_ckcapi_WideDup( - LPCWSTR wide) -{ - DWORD len; - LPWSTR buf; - - if ((LPWSTR)NULL == wide) { - return (LPWSTR)NULL; - } - - len = wcslen(wide) + 1; - - buf = nss_ZNEWARRAY(NULL, WCHAR, len); - if ((LPWSTR)NULL == buf) { - return buf; - } - nsslibc_memcpy(buf, wide, len * sizeof(WCHAR)); - return buf; -} - -/* - * Covert a UTF8 string to Unicode wide character - */ -LPWSTR -nss_ckcapi_UTF8ToWide( - char *buf) -{ - DWORD size; - LPWSTR wide; - - if ((char *)NULL == buf) { - return (LPWSTR)NULL; - } - - size = MultiByteToWideChar(CP_UTF8, 0, buf, -1, NULL, 0); - if (size == 0) { - return (LPWSTR)NULL; - } - wide = nss_ZNEWARRAY(NULL, WCHAR, size); - size = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wide, size); - if (size == 0) { - nss_ZFreeIf(wide); - return (LPWSTR)NULL; - } - return wide; -} - -/* - * keep all the knowlege of how the internalObject is laid out in this function - * - * nss_ckcapi_FetchKeyContainer - * - * fetches the Provider container and info as well as a key handle for a - * private key. If something other than a private key is passed in, - * this function fails with CKR_KEY_TYPE_INCONSISTENT - */ -NSS_EXTERN CK_RV -nss_ckcapi_FetchKeyContainer( - ckcapiInternalObject *iKey, - HCRYPTPROV *hProv, - DWORD *keySpec, - HCRYPTKEY *hKey) -{ - ckcapiCertObject *co; - ckcapiKeyObject *ko; - BOOL rc, dummy; - DWORD msError; - - switch (iKey->type) { - default: - case ckcapiRaw: - /* can't have raw private keys */ - return CKR_KEY_TYPE_INCONSISTENT; - case ckcapiCert: - if (iKey->objClass != CKO_PRIVATE_KEY) { - /* Only private keys have private key provider handles */ - return CKR_KEY_TYPE_INCONSISTENT; - } - co = &iKey->u.cert; - - /* OK, get the Provider */ - rc = CryptAcquireCertificatePrivateKey(co->certContext, - CRYPT_ACQUIRE_CACHE_FLAG | - CRYPT_ACQUIRE_COMPARE_KEY_FLAG, - NULL, hProv, - keySpec, &dummy); - if (!rc) { - goto loser; - } - break; - case ckcapiBareKey: - if (iKey->objClass != CKO_PRIVATE_KEY) { - /* Only private keys have private key provider handles */ - return CKR_KEY_TYPE_INCONSISTENT; - } - ko = &iKey->u.key; - - /* OK, get the Provider */ - if (0 == ko->hProv) { - rc = - CryptAcquireContext(hProv, - ko->containerName, - ko->provName, - ko->provInfo.dwProvType, 0); - if (!rc) { - goto loser; - } - } else { - *hProv = - ko->hProv; - } - *keySpec = ko->provInfo.dwKeySpec; - break; - } - - /* and get the crypto handle */ - rc = CryptGetUserKey(*hProv, *keySpec, hKey); - if (!rc) { - goto loser; - } - return CKR_OK; -loser: - /* map the microsoft error before leaving */ - msError = GetLastError(); - switch (msError) { - case ERROR_INVALID_HANDLE: - case ERROR_INVALID_PARAMETER: - case NTE_BAD_KEY: - case NTE_NO_KEY: - case NTE_BAD_PUBLIC_KEY: - case NTE_BAD_KEYSET: - case NTE_KEYSET_NOT_DEF: - return CKR_KEY_TYPE_INCONSISTENT; - case NTE_BAD_UID: - case NTE_KEYSET_ENTRY_BAD: - return CKR_DEVICE_ERROR; - } - return CKR_GENERAL_ERROR; -} - -/* - * take a DER PUBLIC Key block and return the modulus and exponent - */ -static void -ckcapi_CertPopulateModulusExponent( - ckcapiInternalObject *io) -{ - ckcapiKeyParams *kp = &io->u.cert.key; - PCCERT_CONTEXT certContext = io->u.cert.certContext; - unsigned char *pkData = - certContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData; - unsigned int size = - certContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData; - unsigned int newSize; - unsigned char *ptr, *newptr; - - /* find the start of the modulus -- this will not give good results if - * the key isn't an rsa key! */ - ptr = nss_ckcapi_DERUnwrap(pkData, size, &newSize, NULL); - kp->modulus.data = nss_ckcapi_DERUnwrap(ptr, newSize, - &kp->modulus.size, &newptr); - /* changed from signed to unsigned int */ - if (0 == *(char *)kp->modulus.data) { - kp->modulus.data = ((char *)kp->modulus.data) + 1; - kp->modulus.size = kp->modulus.size - 1; - } - /* changed from signed to unsigned int */ - kp->exponent.data = nss_ckcapi_DERUnwrap(newptr, (newptr - ptr) + newSize, - &kp->exponent.size, NULL); - if (0 == *(char *)kp->exponent.data) { - kp->exponent.data = ((char *)kp->exponent.data) + 1; - kp->exponent.size = kp->exponent.size - 1; - } - return; -} - -typedef struct _CAPI_RSA_KEY_BLOB { - PUBLICKEYSTRUC header; - RSAPUBKEY rsa; - char data[1]; -} CAPI_RSA_KEY_BLOB; - -#define CAPI_MODULUS_OFFSET(modSize) 0 -#define CAPI_PRIME_1_OFFSET(modSize) (modSize) -#define CAPI_PRIME_2_OFFSET(modSize) ((modSize) + (modSize) / 2) -#define CAPI_EXPONENT_1_OFFSET(modSize) ((modSize)*2) -#define CAPI_EXPONENT_2_OFFSET(modSize) ((modSize)*2 + (modSize) / 2) -#define CAPI_COEFFICIENT_OFFSET(modSize) ((modSize)*3) -#define CAPI_PRIVATE_EXP_OFFSET(modSize) ((modSize)*3 + (modSize) / 2) - -void -ckcapi_FetchPublicKey( - ckcapiInternalObject *io) -{ - ckcapiKeyParams *kp; - HCRYPTPROV hProv; - DWORD keySpec; - HCRYPTKEY hKey = 0; - CK_RV error; - DWORD bufLen; - BOOL rc; - unsigned long modulus; - char *buf = NULL; - CAPI_RSA_KEY_BLOB *blob; - - error = nss_ckcapi_FetchKeyContainer(io, &hProv, &keySpec, &hKey); - if (CKR_OK != error) { - goto loser; - } - kp = (ckcapiCert == io->type) ? &io->u.cert.key : &io->u.key.key; - - rc = CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, buf, &bufLen); - if (!rc) { - goto loser; - } - buf = nss_ZNEWARRAY(NULL, char, bufLen); - rc = CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, buf, &bufLen); - if (!rc) { - goto loser; - } - /* validate the blob */ - blob = (CAPI_RSA_KEY_BLOB *)buf; - if ((PUBLICKEYBLOB != blob->header.bType) || - (0x02 != blob->header.bVersion) || - (0x31415352 != blob->rsa.magic)) { - goto loser; - } - modulus = blob->rsa.bitlen / 8; - kp->pubKey = buf; - buf = NULL; - - kp->modulus.data = &blob->data[CAPI_MODULUS_OFFSET(modulus)]; - kp->modulus.size = modulus; - ckcapi_ReverseData(&kp->modulus); - nss_ckcapi_IntToData(blob->rsa.pubexp, &kp->exponent, - kp->publicExponentData, &error); - -loser: - nss_ZFreeIf(buf); - if (0 != hKey) { - CryptDestroyKey(hKey); - } - return; -} - -void -ckcapi_FetchPrivateKey( - ckcapiInternalObject *io) -{ - ckcapiKeyParams *kp; - HCRYPTPROV hProv; - DWORD keySpec; - HCRYPTKEY hKey = 0; - CK_RV error; - DWORD bufLen; - BOOL rc; - unsigned long modulus; - char *buf = NULL; - CAPI_RSA_KEY_BLOB *blob; - - error = nss_ckcapi_FetchKeyContainer(io, &hProv, &keySpec, &hKey); - if (CKR_OK != error) { - goto loser; - } - kp = (ckcapiCert == io->type) ? &io->u.cert.key : &io->u.key.key; - - rc = CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, buf, &bufLen); - if (!rc) { - goto loser; - } - buf = nss_ZNEWARRAY(NULL, char, bufLen); - rc = CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, buf, &bufLen); - if (!rc) { - goto loser; - } - /* validate the blob */ - blob = (CAPI_RSA_KEY_BLOB *)buf; - if ((PRIVATEKEYBLOB != blob->header.bType) || - (0x02 != blob->header.bVersion) || - (0x32415352 != blob->rsa.magic)) { - goto loser; - } - modulus = blob->rsa.bitlen / 8; - kp->privateKey = buf; - buf = NULL; - - kp->privateExponent.data = &blob->data[CAPI_PRIVATE_EXP_OFFSET(modulus)]; - kp->privateExponent.size = modulus; - ckcapi_ReverseData(&kp->privateExponent); - kp->prime1.data = &blob->data[CAPI_PRIME_1_OFFSET(modulus)]; - kp->prime1.size = modulus / 2; - ckcapi_ReverseData(&kp->prime1); - kp->prime2.data = &blob->data[CAPI_PRIME_2_OFFSET(modulus)]; - kp->prime2.size = modulus / 2; - ckcapi_ReverseData(&kp->prime2); - kp->exponent1.data = &blob->data[CAPI_EXPONENT_1_OFFSET(modulus)]; - kp->exponent1.size = modulus / 2; - ckcapi_ReverseData(&kp->exponent1); - kp->exponent2.data = &blob->data[CAPI_EXPONENT_2_OFFSET(modulus)]; - kp->exponent2.size = modulus / 2; - ckcapi_ReverseData(&kp->exponent2); - kp->coefficient.data = &blob->data[CAPI_COEFFICIENT_OFFSET(modulus)]; - kp->coefficient.size = modulus / 2; - ckcapi_ReverseData(&kp->coefficient); - -loser: - nss_ZFreeIf(buf); - if (0 != hKey) { - CryptDestroyKey(hKey); - } - return; -} - -void -ckcapi_PopulateModulusExponent( - ckcapiInternalObject *io) -{ - if (ckcapiCert == io->type) { - ckcapi_CertPopulateModulusExponent(io); - } else { - ckcapi_FetchPublicKey(io); - } - return; -} - -/* - * fetch the friendly name attribute. - * can only be called with ckcapiCert type objects! - */ -void -ckcapi_FetchLabel( - ckcapiInternalObject *io) -{ - ckcapiCertObject *co = &io->u.cert; - char *label; - PCCERT_CONTEXT certContext = io->u.cert.certContext; - char labelDataUTF16[128]; - DWORD size = sizeof(labelDataUTF16); - DWORD size8 = sizeof(co->labelData); - BOOL rv; - - rv = CertGetCertificateContextProperty(certContext, - CERT_FRIENDLY_NAME_PROP_ID, labelDataUTF16, &size); - if (rv) { - co->labelData = nss_ckcapi_WideToUTF8((LPCWSTR)labelDataUTF16); - if ((CHAR *)NULL == co->labelData) { - rv = 0; - } else { - size = strlen(co->labelData); - } - } - label = co->labelData; - /* we are presuming a user cert, make sure it has a nickname, even if - * Microsoft never gave it one */ - if (!rv && co->hasID) { - DWORD mserror = GetLastError(); -#define DEFAULT_NICKNAME "no Microsoft nickname" - label = DEFAULT_NICKNAME; - size = sizeof(DEFAULT_NICKNAME); - rv = 1; - } - - if (rv) { - co->label.data = label; - co->label.size = size; - } - return; -} - -void -ckcapi_FetchSerial( - ckcapiInternalObject *io) -{ - ckcapiCertObject *co = &io->u.cert; - PCCERT_CONTEXT certContext = io->u.cert.certContext; - DWORD size = sizeof(co->derSerial); - - BOOL rc = CryptEncodeObject(X509_ASN_ENCODING, - X509_MULTI_BYTE_INTEGER, - &certContext->pCertInfo->SerialNumber, - co->derSerial, - &size); - if (rc) { - co->serial.data = co->derSerial; - co->serial.size = size; - } - return; -} - -/* - * fetch the key ID. - */ -void -ckcapi_FetchID( - ckcapiInternalObject *io) -{ - PCCERT_CONTEXT certContext = io->u.cert.certContext; - DWORD size = 0; - BOOL rc; - - rc = CertGetCertificateContextProperty(certContext, - CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size); - if (!rc) { - return; - } - io->idData = nss_ZNEWARRAY(NULL, char, size); - if (io->idData == NULL) { - return; - } - - rc = CertGetCertificateContextProperty(certContext, - CERT_KEY_IDENTIFIER_PROP_ID, io->idData, &size); - if (!rc) { - nss_ZFreeIf(io->idData); - io->idData = NULL; - return; - } - io->id.data = io->idData; - io->id.size = size; - return; -} - -/* - * fetch the hash key. - */ -void -ckcapi_CertFetchHashKey( - ckcapiInternalObject *io) -{ - ckcapiCertObject *co = &io->u.cert; - PCCERT_CONTEXT certContext = io->u.cert.certContext; - DWORD size = certContext->cbCertEncoded; - DWORD max = sizeof(io->hashKeyData) - 1; - DWORD offset = 0; - - /* make sure we don't over flow. NOTE: cutting the top of a cert is - * not a big issue because the signature for will be unique for the cert */ - if (size > max) { - offset = size - max; - size = max; - } - - nsslibc_memcpy(io->hashKeyData, certContext->pbCertEncoded + offset, size); - io->hashKeyData[size] = (char)(io->objClass & 0xff); - - io->hashKey.data = io->hashKeyData; - io->hashKey.size = size + 1; - return; -} - -/* - * fetch the hash key. - */ -void -ckcapi_KeyFetchHashKey( - ckcapiInternalObject *io) -{ - ckcapiKeyObject *ko = &io->u.key; - DWORD size; - DWORD max = sizeof(io->hashKeyData) - 2; - DWORD offset = 0; - DWORD provLen = strlen(ko->provName); - DWORD containerLen = strlen(ko->containerName); - - size = provLen + containerLen; - - /* make sure we don't overflow, try to keep things unique */ - if (size > max) { - DWORD diff = ((size - max) + 1) / 2; - provLen -= diff; - containerLen -= diff; - size = provLen + containerLen; - } - - nsslibc_memcpy(io->hashKeyData, ko->provName, provLen); - nsslibc_memcpy(&io->hashKeyData[provLen], - ko->containerName, - containerLen); - io->hashKeyData[size] = (char)(io->objClass & 0xff); - io->hashKeyData[size + 1] = (char)(ko->provInfo.dwKeySpec & 0xff); - - io->hashKey.data = io->hashKeyData; - io->hashKey.size = size + 2; - return; -} - -/* - * fetch the hash key. - */ -void -ckcapi_FetchHashKey( - ckcapiInternalObject *io) -{ - if (ckcapiCert == io->type) { - ckcapi_CertFetchHashKey(io); - } else { - ckcapi_KeyFetchHashKey(io); - } - return; -} - -const NSSItem * -ckcapi_FetchCertAttribute( - ckcapiInternalObject *io, - CK_ATTRIBUTE_TYPE type) -{ - PCCERT_CONTEXT certContext = io->u.cert.certContext; - switch (type) { - case CKA_CLASS: - return &ckcapi_certClassItem; - case CKA_TOKEN: - return &ckcapi_trueItem; - case CKA_MODIFIABLE: - case CKA_PRIVATE: - return &ckcapi_falseItem; - case CKA_CERTIFICATE_TYPE: - return &ckcapi_x509Item; - case CKA_LABEL: - if (0 == io->u.cert.label.size) { - ckcapi_FetchLabel(io); - } - return &io->u.cert.label; - case CKA_SUBJECT: - if (0 == io->u.cert.subject.size) { - io->u.cert.subject.data = - certContext->pCertInfo->Subject.pbData; - io->u.cert.subject.size = - certContext->pCertInfo->Subject.cbData; - } - return &io->u.cert.subject; - case CKA_ISSUER: - if (0 == io->u.cert.issuer.size) { - io->u.cert.issuer.data = - certContext->pCertInfo->Issuer.pbData; - io->u.cert.issuer.size = - certContext->pCertInfo->Issuer.cbData; - } - return &io->u.cert.issuer; - case CKA_SERIAL_NUMBER: - if (0 == io->u.cert.serial.size) { - /* not exactly right. This should be the encoded serial number, but - * it's the decoded serial number! */ - ckcapi_FetchSerial(io); - } - return &io->u.cert.serial; - case CKA_VALUE: - if (0 == io->u.cert.derCert.size) { - io->u.cert.derCert.data = - io->u.cert.certContext->pbCertEncoded; - io->u.cert.derCert.size = - io->u.cert.certContext->cbCertEncoded; - } - return &io->u.cert.derCert; - case CKA_ID: - if (!io->u.cert.hasID) { - return NULL; - } - if (0 == io->id.size) { - ckcapi_FetchID(io); - } - return &io->id; - default: - break; - } - return NULL; -} - -const NSSItem * -ckcapi_FetchPubKeyAttribute( - ckcapiInternalObject *io, - CK_ATTRIBUTE_TYPE type) -{ - PRBool isCertType = (ckcapiCert == io->type); - ckcapiKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key; - - switch (type) { - case CKA_CLASS: - return &ckcapi_pubKeyClassItem; - case CKA_TOKEN: - case CKA_LOCAL: - case CKA_ENCRYPT: - case CKA_VERIFY: - case CKA_VERIFY_RECOVER: - return &ckcapi_trueItem; - case CKA_PRIVATE: - case CKA_MODIFIABLE: - case CKA_DERIVE: - case CKA_WRAP: - return &ckcapi_falseItem; - case CKA_KEY_TYPE: - return &ckcapi_rsaItem; - case CKA_LABEL: - if (!isCertType) { - return &ckcapi_emptyItem; - } - if (0 == io->u.cert.label.size) { - ckcapi_FetchLabel(io); - } - return &io->u.cert.label; - case CKA_SUBJECT: - if (!isCertType) { - return &ckcapi_emptyItem; - } - if (0 == io->u.cert.subject.size) { - PCCERT_CONTEXT certContext = - io->u.cert.certContext; - io->u.cert.subject.data = - certContext->pCertInfo->Subject.pbData; - io->u.cert.subject.size = - certContext->pCertInfo->Subject.cbData; - } - return &io->u.cert.subject; - case CKA_MODULUS: - if (0 == kp->modulus.size) { - ckcapi_PopulateModulusExponent(io); - } - return &kp->modulus; - case CKA_PUBLIC_EXPONENT: - if (0 == kp->modulus.size) { - ckcapi_PopulateModulusExponent(io); - } - return &kp->exponent; - case CKA_ID: - if (0 == io->id.size) { - ckcapi_FetchID(io); - } - return &io->id; - default: - break; - } - return NULL; -} - -const NSSItem * -ckcapi_FetchPrivKeyAttribute( - ckcapiInternalObject *io, - CK_ATTRIBUTE_TYPE type) -{ - PRBool isCertType = (ckcapiCert == io->type); - ckcapiKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key; - - switch (type) { - case CKA_CLASS: - return &ckcapi_privKeyClassItem; - case CKA_TOKEN: - case CKA_LOCAL: - case CKA_SIGN: - case CKA_DECRYPT: - case CKA_SIGN_RECOVER: - return &ckcapi_trueItem; - case CKA_SENSITIVE: - case CKA_PRIVATE: /* should move in the future */ - case CKA_MODIFIABLE: - case CKA_DERIVE: - case CKA_UNWRAP: - case CKA_EXTRACTABLE: /* will probably move in the future */ - case CKA_ALWAYS_SENSITIVE: - case CKA_NEVER_EXTRACTABLE: - return &ckcapi_falseItem; - case CKA_KEY_TYPE: - return &ckcapi_rsaItem; - case CKA_LABEL: - if (!isCertType) { - return &ckcapi_emptyItem; - } - if (0 == io->u.cert.label.size) { - ckcapi_FetchLabel(io); - } - return &io->u.cert.label; - case CKA_SUBJECT: - if (!isCertType) { - return &ckcapi_emptyItem; - } - if (0 == io->u.cert.subject.size) { - PCCERT_CONTEXT certContext = - io->u.cert.certContext; - io->u.cert.subject.data = - certContext->pCertInfo->Subject.pbData; - io->u.cert.subject.size = - certContext->pCertInfo->Subject.cbData; - } - return &io->u.cert.subject; - case CKA_MODULUS: - if (0 == kp->modulus.size) { - ckcapi_PopulateModulusExponent(io); - } - return &kp->modulus; - case CKA_PUBLIC_EXPONENT: - if (0 == kp->modulus.size) { - ckcapi_PopulateModulusExponent(io); - } - return &kp->exponent; - case CKA_PRIVATE_EXPONENT: - if (0 == kp->privateExponent.size) { - ckcapi_FetchPrivateKey(io); - } - return &kp->privateExponent; - case CKA_PRIME_1: - if (0 == kp->privateExponent.size) { - ckcapi_FetchPrivateKey(io); - } - return &kp->prime1; - case CKA_PRIME_2: - if (0 == kp->privateExponent.size) { - ckcapi_FetchPrivateKey(io); - } - return &kp->prime2; - case CKA_EXPONENT_1: - if (0 == kp->privateExponent.size) { - ckcapi_FetchPrivateKey(io); - } - return &kp->exponent1; - case CKA_EXPONENT_2: - if (0 == kp->privateExponent.size) { - ckcapi_FetchPrivateKey(io); - } - return &kp->exponent2; - case CKA_COEFFICIENT: - if (0 == kp->privateExponent.size) { - ckcapi_FetchPrivateKey(io); - } - return &kp->coefficient; - case CKA_ID: - if (0 == io->id.size) { - ckcapi_FetchID(io); - } - return &io->id; - default: - return NULL; - } -} - -const NSSItem * -nss_ckcapi_FetchAttribute( - ckcapiInternalObject *io, - CK_ATTRIBUTE_TYPE type) -{ - CK_ULONG i; - - if (io->type == ckcapiRaw) { - for (i = 0; i < io->u.raw.n; i++) { - if (type == io->u.raw.types[i]) { - return &io->u.raw.items[i]; - } - } - return NULL; - } - /* deal with the common attributes */ - switch (io->objClass) { - case CKO_CERTIFICATE: - return ckcapi_FetchCertAttribute(io, type); - case CKO_PRIVATE_KEY: - return ckcapi_FetchPrivKeyAttribute(io, type); - case CKO_PUBLIC_KEY: - return ckcapi_FetchPubKeyAttribute(io, type); - } - return NULL; -} - -/* - * check to see if the certificate already exists - */ -static PRBool -ckcapi_cert_exists( - NSSItem *value, - ckcapiInternalObject **io) -{ - int count, i; - PRUint32 size = 0; - ckcapiInternalObject **listp = NULL; - CK_ATTRIBUTE myTemplate[2]; - CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; - CK_ULONG templateCount = 2; - CK_RV error; - PRBool found = PR_FALSE; - - myTemplate[0].type = CKA_CLASS; - myTemplate[0].pValue = &cert_class; - myTemplate[0].ulValueLen = sizeof(cert_class); - myTemplate[1].type = CKA_VALUE; - myTemplate[1].pValue = value->data; - myTemplate[1].ulValueLen = value->size; - - count = nss_ckcapi_collect_all_certs(myTemplate, templateCount, &listp, - &size, 0, &error); - - /* free them */ - if (count > 1) { - *io = listp[0]; - found = PR_TRUE; - } - - for (i = 1; i < count; i++) { - nss_ckcapi_DestroyInternalObject(listp[i]); - } - nss_ZFreeIf(listp); - return found; -} - -static PRBool -ckcapi_cert_hasEmail( - PCCERT_CONTEXT certContext) -{ - int count; - - count = CertGetNameString(certContext, CERT_NAME_EMAIL_TYPE, - 0, NULL, NULL, 0); - - return count > 1 ? PR_TRUE : PR_FALSE; -} - -static PRBool -ckcapi_cert_isRoot( - PCCERT_CONTEXT certContext) -{ - return CertCompareCertificateName(certContext->dwCertEncodingType, - &certContext->pCertInfo->Issuer, &certContext->pCertInfo->Subject); -} - -static PRBool -ckcapi_cert_isCA( - PCCERT_CONTEXT certContext) -{ - PCERT_EXTENSION extension; - CERT_BASIC_CONSTRAINTS2_INFO basicInfo; - DWORD size = sizeof(basicInfo); - BOOL rc; - - extension = CertFindExtension(szOID_BASIC_CONSTRAINTS, - certContext->pCertInfo->cExtension, - certContext->pCertInfo->rgExtension); - if ((PCERT_EXTENSION)NULL == extension) { - return PR_FALSE; - } - rc = CryptDecodeObject(X509_ASN_ENCODING, szOID_BASIC_CONSTRAINTS2, - extension->Value.pbData, extension->Value.cbData, - 0, &basicInfo, &size); - if (!rc) { - return PR_FALSE; - } - return (PRBool)basicInfo.fCA; -} - -static CRYPT_KEY_PROV_INFO * -ckcapi_cert_getPrivateKeyInfo( - PCCERT_CONTEXT certContext, - NSSItem *keyID) -{ - BOOL rc; - CRYPT_HASH_BLOB msKeyID; - DWORD size = 0; - CRYPT_KEY_PROV_INFO *prov = NULL; - - msKeyID.cbData = keyID->size; - msKeyID.pbData = keyID->data; - - rc = CryptGetKeyIdentifierProperty( - &msKeyID, - CERT_KEY_PROV_INFO_PROP_ID, - 0, NULL, NULL, NULL, &size); - if (!rc) { - return (CRYPT_KEY_PROV_INFO *)NULL; - } - prov = (CRYPT_KEY_PROV_INFO *)nss_ZAlloc(NULL, size); - if ((CRYPT_KEY_PROV_INFO *)prov == NULL) { - return (CRYPT_KEY_PROV_INFO *)NULL; - } - rc = CryptGetKeyIdentifierProperty( - &msKeyID, - CERT_KEY_PROV_INFO_PROP_ID, - 0, NULL, NULL, prov, &size); - if (!rc) { - nss_ZFreeIf(prov); - return (CRYPT_KEY_PROV_INFO *)NULL; - } - - return prov; -} - -static CRYPT_KEY_PROV_INFO * -ckcapi_cert_getProvInfo( - ckcapiInternalObject *io) -{ - BOOL rc; - DWORD size = 0; - CRYPT_KEY_PROV_INFO *prov = NULL; - - rc = CertGetCertificateContextProperty( - io->u.cert.certContext, - CERT_KEY_PROV_INFO_PROP_ID, - NULL, &size); - if (!rc) { - return (CRYPT_KEY_PROV_INFO *)NULL; - } - prov = (CRYPT_KEY_PROV_INFO *)nss_ZAlloc(NULL, size); - if ((CRYPT_KEY_PROV_INFO *)prov == NULL) { - return (CRYPT_KEY_PROV_INFO *)NULL; - } - rc = CertGetCertificateContextProperty( - io->u.cert.certContext, - CERT_KEY_PROV_INFO_PROP_ID, - prov, &size); - if (!rc) { - nss_ZFreeIf(prov); - return (CRYPT_KEY_PROV_INFO *)NULL; - } - - return prov; -} - -/* forward declaration */ -static void -ckcapi_removeObjectFromHash( - ckcapiInternalObject *io); - -/* - * Finalize - unneeded - * Destroy - * IsTokenObject - CK_TRUE - * GetAttributeCount - * GetAttributeTypes - * GetAttributeSize - * GetAttribute - * SetAttribute - * GetObjectSize - */ - -static CK_RV -ckcapi_mdObject_Destroy( - NSSCKMDObject *mdObject, - NSSCKFWObject *fwObject, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; - CK_OBJECT_CLASS objClass; - BOOL rc; - DWORD provType; - DWORD msError; - PRBool isCertType = (PRBool)(ckcapiCert == io->type); - HCERTSTORE hStore = 0; - - if (ckcapiRaw == io->type) { - /* there is not 'object write protected' error, use the next best thing */ - return CKR_TOKEN_WRITE_PROTECTED; - } - - objClass = io->objClass; - if (CKO_CERTIFICATE == objClass) { - PCCERT_CONTEXT certContext; - - /* get the store */ - hStore = CertOpenSystemStore(0, io->u.cert.certStore); - if (0 == hStore) { - rc = 0; - goto loser; - } - certContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING, 0, - CERT_FIND_EXISTING, io->u.cert.certContext, NULL); - if ((PCCERT_CONTEXT)NULL == certContext) { - rc = 0; - goto loser; - } - rc = CertDeleteCertificateFromStore(certContext); - } else { - char *provName = NULL; - char *containerName = NULL; - HCRYPTPROV hProv; - CRYPT_HASH_BLOB msKeyID; - - if (0 == io->id.size) { - ckcapi_FetchID(io); - } - - if (isCertType) { - CRYPT_KEY_PROV_INFO *provInfo = ckcapi_cert_getProvInfo(io); - provName = nss_ckcapi_WideToUTF8(provInfo->pwszProvName); - containerName = nss_ckcapi_WideToUTF8(provInfo->pwszContainerName); - provType = provInfo->dwProvType; - nss_ZFreeIf(provInfo); - } else { - provName = io->u.key.provName; - containerName = io->u.key.containerName; - provType = io->u.key.provInfo.dwProvType; - io->u.key.provName = NULL; - io->u.key.containerName = NULL; - } - /* first remove the key id pointer */ - msKeyID.cbData = io->id.size; - msKeyID.pbData = io->id.data; - rc = CryptSetKeyIdentifierProperty(&msKeyID, - CERT_KEY_PROV_INFO_PROP_ID, CRYPT_KEYID_DELETE_FLAG, NULL, NULL, NULL); - if (rc) { - rc = CryptAcquireContext(&hProv, containerName, provName, provType, - CRYPT_DELETEKEYSET); - } - nss_ZFreeIf(provName); - nss_ZFreeIf(containerName); - } -loser: - - if (hStore) { - CertCloseStore(hStore, 0); - } - if (!rc) { - msError = GetLastError(); - return CKR_GENERAL_ERROR; - } - - /* remove it from the hash */ - ckcapi_removeObjectFromHash(io); - - /* free the puppy.. */ - nss_ckcapi_DestroyInternalObject(io); - return CKR_OK; -} - -static CK_BBOOL -ckcapi_mdObject_IsTokenObject( - NSSCKMDObject *mdObject, - NSSCKFWObject *fwObject, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance) -{ - return CK_TRUE; -} - -static CK_ULONG -ckcapi_mdObject_GetAttributeCount( - NSSCKMDObject *mdObject, - NSSCKFWObject *fwObject, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; - - if (ckcapiRaw == io->type) { - return io->u.raw.n; - } - switch (io->objClass) { - case CKO_CERTIFICATE: - return certAttrsCount; - case CKO_PUBLIC_KEY: - return pubKeyAttrsCount; - case CKO_PRIVATE_KEY: - return privKeyAttrsCount; - default: - break; - } - return 0; -} - -static CK_RV -ckcapi_mdObject_GetAttributeTypes( - NSSCKMDObject *mdObject, - NSSCKFWObject *fwObject, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_ATTRIBUTE_TYPE_PTR typeArray, - CK_ULONG ulCount) -{ - ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; - CK_ULONG i; - CK_RV error = CKR_OK; - const CK_ATTRIBUTE_TYPE *attrs = NULL; - CK_ULONG size = ckcapi_mdObject_GetAttributeCount( - mdObject, fwObject, mdSession, fwSession, - mdToken, fwToken, mdInstance, fwInstance, &error); - - if (size != ulCount) { - return CKR_BUFFER_TOO_SMALL; - } - if (io->type == ckcapiRaw) { - attrs = io->u.raw.types; - } else - switch (io->objClass) { - case CKO_CERTIFICATE: - attrs = - certAttrs; - break; - case CKO_PUBLIC_KEY: - attrs = - pubKeyAttrs; - break; - case CKO_PRIVATE_KEY: - attrs = - privKeyAttrs; - break; - default: - return CKR_OK; - } - - for (i = 0; i < size; i++) { - typeArray[i] = attrs[i]; - } - - return CKR_OK; -} - -static CK_ULONG -ckcapi_mdObject_GetAttributeSize( - NSSCKMDObject *mdObject, - NSSCKFWObject *fwObject, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_ATTRIBUTE_TYPE attribute, - CK_RV *pError) -{ - ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; - - const NSSItem *b; - - b = nss_ckcapi_FetchAttribute(io, attribute); - - if ((const NSSItem *)NULL == b) { - *pError = CKR_ATTRIBUTE_TYPE_INVALID; - return 0; - } - return b->size; -} - -static CK_RV -ckcapi_mdObject_SetAttribute( - NSSCKMDObject *mdObject, - NSSCKFWObject *fwObject, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_ATTRIBUTE_TYPE attribute, - NSSItem *value) -{ - return CKR_OK; -} - -static NSSCKFWItem -ckcapi_mdObject_GetAttribute( - NSSCKMDObject *mdObject, - NSSCKFWObject *fwObject, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_ATTRIBUTE_TYPE attribute, - CK_RV *pError) -{ - NSSCKFWItem mdItem; - ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; - - mdItem.needsFreeing = PR_FALSE; - mdItem.item = (NSSItem *)nss_ckcapi_FetchAttribute(io, attribute); - - if ((NSSItem *)NULL == mdItem.item) { - *pError = CKR_ATTRIBUTE_TYPE_INVALID; - } - - return mdItem; -} - -static CK_ULONG -ckcapi_mdObject_GetObjectSize( - NSSCKMDObject *mdObject, - NSSCKFWObject *fwObject, - NSSCKMDSession *mdSession, - NSSCKFWSession *fwSession, - NSSCKMDToken *mdToken, - NSSCKFWToken *fwToken, - NSSCKMDInstance *mdInstance, - NSSCKFWInstance *fwInstance, - CK_RV *pError) -{ - ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; - CK_ULONG rv = 1; - - /* size is irrelevant to this token */ - return rv; -} - -static const NSSCKMDObject - ckcapi_prototype_mdObject = { - (void *)NULL, /* etc */ - NULL, /* Finalize */ - ckcapi_mdObject_Destroy, - ckcapi_mdObject_IsTokenObject, - ckcapi_mdObject_GetAttributeCount, - ckcapi_mdObject_GetAttributeTypes, - ckcapi_mdObject_GetAttributeSize, - ckcapi_mdObject_GetAttribute, - NULL, /* FreeAttribute */ - ckcapi_mdObject_SetAttribute, - ckcapi_mdObject_GetObjectSize, - (void *)NULL /* null terminator */ - }; - -static nssHash *ckcapiInternalObjectHash = NULL; - -NSS_IMPLEMENT NSSCKMDObject * -nss_ckcapi_CreateMDObject( - NSSArena *arena, - ckcapiInternalObject *io, - CK_RV *pError) -{ - if ((nssHash *)NULL == ckcapiInternalObjectHash) { - ckcapiInternalObjectHash = nssHash_CreateItem(NULL, 10); - } - if (ckcapiCert == io->type) { - /* the hash key, not a cryptographic key */ - NSSItem *key = &io->hashKey; - ckcapiInternalObject *old_o = NULL; - - if (key->size == 0) { - ckcapi_FetchHashKey(io); - } - old_o = (ckcapiInternalObject *) - nssHash_Lookup(ckcapiInternalObjectHash, key); - if (!old_o) { - nssHash_Add(ckcapiInternalObjectHash, key, io); - } else if (old_o != io) { - nss_ckcapi_DestroyInternalObject(io); - io = old_o; - } - } - - if ((void *)NULL == io->mdObject.etc) { - (void)nsslibc_memcpy(&io->mdObject, &ckcapi_prototype_mdObject, - sizeof(ckcapi_prototype_mdObject)); - io->mdObject.etc = (void *)io; - } - return &io->mdObject; -} - -static void -ckcapi_removeObjectFromHash( - ckcapiInternalObject *io) -{ - NSSItem *key = &io->hashKey; - - if ((nssHash *)NULL == ckcapiInternalObjectHash) { - return; - } - if (key->size == 0) { - ckcapi_FetchHashKey(io); - } - nssHash_Remove(ckcapiInternalObjectHash, key); - return; -} - -void -nss_ckcapi_DestroyInternalObject( - ckcapiInternalObject *io) -{ - switch (io->type) { - case ckcapiRaw: - return; - case ckcapiCert: - CertFreeCertificateContext(io->u.cert.certContext); - nss_ZFreeIf(io->u.cert.labelData); - nss_ZFreeIf(io->u.cert.key.privateKey); - nss_ZFreeIf(io->u.cert.key.pubKey); - nss_ZFreeIf(io->idData); - break; - case ckcapiBareKey: - nss_ZFreeIf(io->u.key.provInfo.pwszContainerName); - nss_ZFreeIf(io->u.key.provInfo.pwszProvName); - nss_ZFreeIf(io->u.key.provName); - nss_ZFreeIf(io->u.key.containerName); - nss_ZFreeIf(io->u.key.key.privateKey); - nss_ZFreeIf(io->u.key.key.pubKey); - if (0 != io->u.key.hProv) { - CryptReleaseContext(io->u.key.hProv, 0); - } - nss_ZFreeIf(io->idData); - break; - } - nss_ZFreeIf(io); - return; -} - -static ckcapiInternalObject * -nss_ckcapi_CreateCertificate( - NSSCKFWSession *fwSession, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - CK_RV *pError) -{ - NSSItem value; - NSSItem keyID; - char *storeStr; - ckcapiInternalObject *io = NULL; - PCCERT_CONTEXT certContext = NULL; - PCCERT_CONTEXT storedCertContext = NULL; - CRYPT_KEY_PROV_INFO *prov_info = NULL; - char *nickname = NULL; - HCERTSTORE hStore = 0; - DWORD msError = 0; - PRBool hasID; - CK_RV dummy; - BOOL rc; - - *pError = nss_ckcapi_GetAttribute(CKA_VALUE, pTemplate, - ulAttributeCount, &value); - - if (CKR_OK != *pError) { - return (ckcapiInternalObject *)NULL; - } - - *pError = nss_ckcapi_GetAttribute(CKA_ID, pTemplate, - ulAttributeCount, &keyID); - - if (CKR_OK != *pError) { - return (ckcapiInternalObject *)NULL; - } - - if (ckcapi_cert_exists(&value, &io)) { - return io; - } - - /* OK, we are creating a new one, figure out what store it belongs to.. - * first get a certContext handle.. */ - certContext = CertCreateCertificateContext(X509_ASN_ENCODING, - value.data, value.size); - if ((PCCERT_CONTEXT)NULL == certContext) { - msError = GetLastError(); - *pError = CKR_ATTRIBUTE_VALUE_INVALID; - goto loser; - } - - /* do we have a private key laying around... */ - prov_info = ckcapi_cert_getPrivateKeyInfo(certContext, &keyID); - if (prov_info) { - CRYPT_DATA_BLOB msKeyID; - storeStr = "My"; - hasID = PR_TRUE; - rc = CertSetCertificateContextProperty(certContext, - CERT_KEY_PROV_INFO_PROP_ID, - 0, prov_info); - nss_ZFreeIf(prov_info); - if (!rc) { - msError = GetLastError(); - *pError = CKR_DEVICE_ERROR; - goto loser; - } - msKeyID.cbData = keyID.size; - msKeyID.pbData = keyID.data; - rc = CertSetCertificateContextProperty(certContext, - CERT_KEY_IDENTIFIER_PROP_ID, - 0, &msKeyID); - if (!rc) { - msError = GetLastError(); - *pError = CKR_DEVICE_ERROR; - goto loser; - } - - /* does it look like a CA */ - } else if (ckcapi_cert_isCA(certContext)) { - storeStr = ckcapi_cert_isRoot(certContext) ? "CA" : "Root"; - /* does it look like an S/MIME cert */ - } else if (ckcapi_cert_hasEmail(certContext)) { - storeStr = "AddressBook"; - } else { - /* just pick a store */ - storeStr = "CA"; - } - - /* get the nickname, not an error if we can't find it */ - nickname = nss_ckcapi_GetStringAttribute(CKA_LABEL, pTemplate, - ulAttributeCount, &dummy); - if (nickname) { - LPWSTR nicknameUTF16 = NULL; - CRYPT_DATA_BLOB nicknameBlob; - - nicknameUTF16 = nss_ckcapi_UTF8ToWide(nickname); - nss_ZFreeIf(nickname); - nickname = NULL; - if ((LPWSTR)NULL == nicknameUTF16) { - *pError = CKR_HOST_MEMORY; - goto loser; - } - nicknameBlob.cbData = nss_ckcapi_WideSize(nicknameUTF16); - nicknameBlob.pbData = (BYTE *)nicknameUTF16; - rc = CertSetCertificateContextProperty(certContext, - CERT_FRIENDLY_NAME_PROP_ID, 0, &nicknameBlob); - nss_ZFreeIf(nicknameUTF16); - if (!rc) { - msError = GetLastError(); - *pError = CKR_DEVICE_ERROR; - goto loser; - } - } - - hStore = CertOpenSystemStore((HCRYPTPROV)NULL, storeStr); - if (0 == hStore) { - msError = GetLastError(); - *pError = CKR_DEVICE_ERROR; - goto loser; - } - - rc = CertAddCertificateContextToStore(hStore, certContext, - CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES, &storedCertContext); - CertFreeCertificateContext(certContext); - certContext = NULL; - CertCloseStore(hStore, 0); - hStore = 0; - if (!rc) { - msError = GetLastError(); - *pError = CKR_DEVICE_ERROR; - goto loser; - } - - io = nss_ZNEW(NULL, ckcapiInternalObject); - if ((ckcapiInternalObject *)NULL == io) { - *pError = CKR_HOST_MEMORY; - goto loser; - } - io->type = ckcapiCert; - io->objClass = CKO_CERTIFICATE; - io->u.cert.certContext = storedCertContext; - io->u.cert.hasID = hasID; - return io; - -loser: - if (certContext) { - CertFreeCertificateContext(certContext); - certContext = NULL; - } - if (storedCertContext) { - CertFreeCertificateContext(storedCertContext); - storedCertContext = NULL; - } - if (0 != hStore) { - CertCloseStore(hStore, 0); - } - return (ckcapiInternalObject *)NULL; -} - -static char * -ckcapi_getDefaultProvider( - CK_RV *pError) -{ - char *name = NULL; - BOOL rc; - DWORD nameLength = 0; - - rc = CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_USER_DEFAULT, NULL, - &nameLength); - if (!rc) { - return (char *)NULL; - } - - name = nss_ZNEWARRAY(NULL, char, nameLength); - if ((char *)NULL == name) { - return (char *)NULL; - } - rc = CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_USER_DEFAULT, name, - &nameLength); - if (!rc) { - nss_ZFreeIf(name); - return (char *)NULL; - } - - return name; -} - -static char * -ckcapi_getContainer( - CK_RV *pError, - NSSItem *id) -{ - RPC_STATUS rstat; - UUID uuid; - char *uuidStr; - char *container; - - rstat = UuidCreate(&uuid); - rstat = UuidToString(&uuid, &uuidStr); - - /* convert it from rcp memory to our own */ - container = nssUTF8_Duplicate(uuidStr, NULL); - RpcStringFree(&uuidStr); - - return container; -} - -static CK_RV -ckcapi_buildPrivateKeyBlob( - NSSItem *keyBlob, - NSSItem *modulus, - NSSItem *publicExponent, - NSSItem *privateExponent, - NSSItem *prime1, - NSSItem *prime2, - NSSItem *exponent1, - NSSItem *exponent2, - NSSItem *coefficient, - PRBool isKeyExchange) -{ - CAPI_RSA_KEY_BLOB *keyBlobData = NULL; - unsigned char *target; - unsigned long modSize = modulus->size; - unsigned long dataSize; - CK_RV error = CKR_OK; - - /* validate extras */ - if (privateExponent->size != modSize) { - error = CKR_ATTRIBUTE_VALUE_INVALID; - goto loser; - } - if (prime1->size != modSize / 2) { - error = CKR_ATTRIBUTE_VALUE_INVALID; - goto loser; - } - if (prime2->size != modSize / 2) { - error = CKR_ATTRIBUTE_VALUE_INVALID; - goto loser; - } - if (exponent1->size != modSize / 2) { - error = CKR_ATTRIBUTE_VALUE_INVALID; - goto loser; - } - if (exponent2->size != modSize / 2) { - error = CKR_ATTRIBUTE_VALUE_INVALID; - goto loser; - } - if (coefficient->size != modSize / 2) { - error = CKR_ATTRIBUTE_VALUE_INVALID; - goto loser; - } - dataSize = (modSize * 4) + (modSize / 2) + sizeof(CAPI_RSA_KEY_BLOB); - keyBlobData = (CAPI_RSA_KEY_BLOB *)nss_ZAlloc(NULL, dataSize); - if ((CAPI_RSA_KEY_BLOB *)NULL == keyBlobData) { - error = CKR_HOST_MEMORY; - goto loser; - } - - keyBlobData->header.bType = PRIVATEKEYBLOB; - keyBlobData->header.bVersion = 0x02; - keyBlobData->header.reserved = 0x00; - keyBlobData->header.aiKeyAlg = isKeyExchange ? CALG_RSA_KEYX : CALG_RSA_SIGN; - keyBlobData->rsa.magic = 0x32415352; - keyBlobData->rsa.bitlen = modSize * 8; - keyBlobData->rsa.pubexp = nss_ckcapi_DataToInt(publicExponent, &error); - if (CKR_OK != error) { - goto loser; - } - - target = &keyBlobData->data[CAPI_MODULUS_OFFSET(modSize)]; - nsslibc_memcpy(target, modulus->data, modulus->size); - modulus->data = target; - ckcapi_ReverseData(modulus); - - target = &keyBlobData->data[CAPI_PRIVATE_EXP_OFFSET(modSize)]; - nsslibc_memcpy(target, privateExponent->data, privateExponent->size); - privateExponent->data = target; - ckcapi_ReverseData(privateExponent); - - target = &keyBlobData->data[CAPI_PRIME_1_OFFSET(modSize)]; - nsslibc_memcpy(target, prime1->data, prime1->size); - prime1->data = target; - ckcapi_ReverseData(prime1); - - target = &keyBlobData->data[CAPI_PRIME_2_OFFSET(modSize)]; - nsslibc_memcpy(target, prime2->data, prime2->size); - prime2->data = target; - ckcapi_ReverseData(prime2); - - target = &keyBlobData->data[CAPI_EXPONENT_1_OFFSET(modSize)]; - nsslibc_memcpy(target, exponent1->data, exponent1->size); - exponent1->data = target; - ckcapi_ReverseData(exponent1); - - target = &keyBlobData->data[CAPI_EXPONENT_2_OFFSET(modSize)]; - nsslibc_memcpy(target, exponent2->data, exponent2->size); - exponent2->data = target; - ckcapi_ReverseData(exponent2); - - target = &keyBlobData->data[CAPI_COEFFICIENT_OFFSET(modSize)]; - nsslibc_memcpy(target, coefficient->data, coefficient->size); - coefficient->data = target; - ckcapi_ReverseData(coefficient); - - keyBlob->data = keyBlobData; - keyBlob->size = dataSize; - - return CKR_OK; - -loser: - nss_ZFreeIf(keyBlobData); - return error; -} - -static ckcapiInternalObject * -nss_ckcapi_CreatePrivateKey( - NSSCKFWSession *fwSession, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - CK_RV *pError) -{ - NSSItem modulus; - NSSItem publicExponent; - NSSItem privateExponent; - NSSItem exponent1; - NSSItem exponent2; - NSSItem prime1; - NSSItem prime2; - NSSItem coefficient; - NSSItem keyID; - NSSItem keyBlob; - ckcapiInternalObject *io = NULL; - char *providerName = NULL; - char *containerName = NULL; - char *idData = NULL; - CRYPT_KEY_PROV_INFO provInfo; - CRYPT_HASH_BLOB msKeyID; - CK_KEY_TYPE keyType; - HCRYPTPROV hProv = 0; - HCRYPTKEY hKey = 0; - PRBool decrypt; - DWORD keySpec; - DWORD msError; - BOOL rc; - - keyType = nss_ckcapi_GetULongAttribute(CKA_KEY_TYPE, pTemplate, ulAttributeCount, pError); - if (CKR_OK != *pError) { - return (ckcapiInternalObject *)NULL; - } - if (CKK_RSA != keyType) { - *pError = CKR_ATTRIBUTE_VALUE_INVALID; - return (ckcapiInternalObject *)NULL; - } - - decrypt = nss_ckcapi_GetBoolAttribute(CKA_DECRYPT, - pTemplate, ulAttributeCount, pError); - if (CKR_TEMPLATE_INCOMPLETE == *pError) { - decrypt = PR_TRUE; /* default to true */ - } - decrypt = decrypt || nss_ckcapi_GetBoolAttribute(CKA_UNWRAP, - pTemplate, ulAttributeCount, pError); - if (CKR_TEMPLATE_INCOMPLETE == *pError) { - decrypt = PR_TRUE; /* default to true */ - } - keySpec = decrypt ? AT_KEYEXCHANGE : AT_SIGNATURE; - - *pError = nss_ckcapi_GetAttribute(CKA_MODULUS, pTemplate, - ulAttributeCount, &modulus); - if (CKR_OK != *pError) { - return (ckcapiInternalObject *)NULL; - } - *pError = nss_ckcapi_GetAttribute(CKA_PUBLIC_EXPONENT, pTemplate, - ulAttributeCount, &publicExponent); - if (CKR_OK != *pError) { - return (ckcapiInternalObject *)NULL; - } - *pError = nss_ckcapi_GetAttribute(CKA_PRIVATE_EXPONENT, pTemplate, - ulAttributeCount, &privateExponent); - if (CKR_OK != *pError) { - return (ckcapiInternalObject *)NULL; - } - *pError = nss_ckcapi_GetAttribute(CKA_PRIME_1, pTemplate, - ulAttributeCount, &prime1); - if (CKR_OK != *pError) { - return (ckcapiInternalObject *)NULL; - } - *pError = nss_ckcapi_GetAttribute(CKA_PRIME_2, pTemplate, - ulAttributeCount, &prime2); - if (CKR_OK != *pError) { - return (ckcapiInternalObject *)NULL; - } - *pError = nss_ckcapi_GetAttribute(CKA_EXPONENT_1, pTemplate, - ulAttributeCount, &exponent1); - if (CKR_OK != *pError) { - return (ckcapiInternalObject *)NULL; - } - *pError = nss_ckcapi_GetAttribute(CKA_EXPONENT_2, pTemplate, - ulAttributeCount, &exponent2); - if (CKR_OK != *pError) { - return (ckcapiInternalObject *)NULL; - } - *pError = nss_ckcapi_GetAttribute(CKA_COEFFICIENT, pTemplate, - ulAttributeCount, &coefficient); - if (CKR_OK != *pError) { - return (ckcapiInternalObject *)NULL; - } - *pError = nss_ckcapi_GetAttribute(CKA_ID, pTemplate, - ulAttributeCount, &keyID); - if (CKR_OK != *pError) { - return (ckcapiInternalObject *)NULL; - } - providerName = ckcapi_getDefaultProvider(pError); - if ((char *)NULL == providerName) { - return (ckcapiInternalObject *)NULL; - } - containerName = ckcapi_getContainer(pError, &keyID); - if ((char *)NULL == containerName) { - goto loser; - } - rc = CryptAcquireContext(&hProv, containerName, providerName, - PROV_RSA_FULL, CRYPT_NEWKEYSET); - if (!rc) { - msError = GetLastError(); - *pError = CKR_DEVICE_ERROR; - goto loser; - } - - *pError = ckcapi_buildPrivateKeyBlob( - &keyBlob, - &modulus, - &publicExponent, - &privateExponent, - &prime1, - &prime2, - &exponent1, - &exponent2, - &coefficient, - decrypt); - if (CKR_OK != *pError) { - goto loser; - } - - rc = CryptImportKey(hProv, keyBlob.data, keyBlob.size, - 0, CRYPT_EXPORTABLE, &hKey); - if (!rc) { - msError = GetLastError(); - *pError = CKR_DEVICE_ERROR; - goto loser; - } - - idData = nss_ZNEWARRAY(NULL, char, keyID.size); - if ((void *)NULL == idData) { - *pError = CKR_HOST_MEMORY; - goto loser; - } - nsslibc_memcpy(idData, keyID.data, keyID.size); - - provInfo.pwszContainerName = nss_ckcapi_UTF8ToWide(containerName); - provInfo.pwszProvName = nss_ckcapi_UTF8ToWide(providerName); - provInfo.dwProvType = PROV_RSA_FULL; - provInfo.dwFlags = 0; - provInfo.cProvParam = 0; - provInfo.rgProvParam = NULL; - provInfo.dwKeySpec = keySpec; - - msKeyID.cbData = keyID.size; - msKeyID.pbData = keyID.data; - - rc = CryptSetKeyIdentifierProperty(&msKeyID, CERT_KEY_PROV_INFO_PROP_ID, - 0, NULL, NULL, &provInfo); - if (!rc) { - goto loser; - } - - /* handle error here */ - io = nss_ZNEW(NULL, ckcapiInternalObject); - if ((ckcapiInternalObject *)NULL == io) { - *pError = CKR_HOST_MEMORY; - goto loser; - } - io->type = ckcapiBareKey; - io->objClass = CKO_PRIVATE_KEY; - io->u.key.provInfo = provInfo; - io->u.key.provName = providerName; - io->u.key.containerName = containerName; - io->u.key.hProv = hProv; /* save the handle */ - io->idData = idData; - io->id.data = idData; - io->id.size = keyID.size; - /* done with the key handle */ - CryptDestroyKey(hKey); - return io; - -loser: - nss_ZFreeIf(containerName); - nss_ZFreeIf(providerName); - nss_ZFreeIf(idData); - if (0 != hProv) { - CryptReleaseContext(hProv, 0); - } - if (0 != hKey) { - CryptDestroyKey(hKey); - } - return (ckcapiInternalObject *)NULL; -} - -NSS_EXTERN NSSCKMDObject * -nss_ckcapi_CreateObject( - NSSCKFWSession *fwSession, - CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulAttributeCount, - CK_RV *pError) -{ - CK_OBJECT_CLASS objClass; - ckcapiInternalObject *io = NULL; - CK_BBOOL isToken; - - /* - * only create token objects - */ - isToken = nss_ckcapi_GetBoolAttribute(CKA_TOKEN, pTemplate, - ulAttributeCount, pError); - if (CKR_OK != *pError) { - return (NSSCKMDObject *)NULL; - } - if (!isToken) { - *pError = CKR_ATTRIBUTE_VALUE_INVALID; - return (NSSCKMDObject *)NULL; - } - - /* - * only create keys and certs. - */ - objClass = nss_ckcapi_GetULongAttribute(CKA_CLASS, pTemplate, - ulAttributeCount, pError); - if (CKR_OK != *pError) { - return (NSSCKMDObject *)NULL; - } -#ifdef notdef - if (objClass == CKO_PUBLIC_KEY) { - return CKR_OK; /* fake public key creation, happens as a side effect of - * private key creation */ - } -#endif - if (objClass == CKO_CERTIFICATE) { - io = nss_ckcapi_CreateCertificate(fwSession, pTemplate, - ulAttributeCount, pError); - } else if (objClass == CKO_PRIVATE_KEY) { - io = nss_ckcapi_CreatePrivateKey(fwSession, pTemplate, - ulAttributeCount, pError); - } else { - *pError = CKR_ATTRIBUTE_VALUE_INVALID; - } - - if ((ckcapiInternalObject *)NULL == io) { - return (NSSCKMDObject *)NULL; - } - return nss_ckcapi_CreateMDObject(NULL, io, pError); -} |