summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/ckfw/nssmkey/mrsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/ckfw/nssmkey/mrsa.c')
-rw-r--r--security/nss/lib/ckfw/nssmkey/mrsa.c479
1 files changed, 479 insertions, 0 deletions
diff --git a/security/nss/lib/ckfw/nssmkey/mrsa.c b/security/nss/lib/ckfw/nssmkey/mrsa.c
new file mode 100644
index 000000000..00175b47a
--- /dev/null
+++ b/security/nss/lib/ckfw/nssmkey/mrsa.c
@@ -0,0 +1,479 @@
+/* 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 "ckmk.h"
+
+/* Sigh, For all the talk about 'ease of use', apple has hidden the interfaces
+ * needed to be able to truly use CSSM. These came from their modification
+ * to NSS's S/MIME code. The following two functions currently are not
+ * part of the SecKey.h interface.
+ */
+OSStatus
+SecKeyGetCredentials(
+ SecKeyRef keyRef,
+ CSSM_ACL_AUTHORIZATION_TAG authTag,
+ int type,
+ const CSSM_ACCESS_CREDENTIALS **creds);
+
+/* this function could be implemented using 'SecKeychainItemCopyKeychain' and
+ * 'SecKeychainGetCSPHandle' */
+OSStatus
+SecKeyGetCSPHandle(
+ SecKeyRef keyRef,
+ CSSM_CSP_HANDLE *cspHandle);
+
+typedef struct ckmkInternalCryptoOperationRSAPrivStr
+ ckmkInternalCryptoOperationRSAPriv;
+struct ckmkInternalCryptoOperationRSAPrivStr {
+ NSSCKMDCryptoOperation mdOperation;
+ NSSCKMDMechanism *mdMechanism;
+ ckmkInternalObject *iKey;
+ NSSItem *buffer;
+ CSSM_CC_HANDLE cssmContext;
+};
+
+typedef enum {
+ CKMK_DECRYPT,
+ CKMK_SIGN
+} ckmkRSAOpType;
+
+/*
+ * ckmk_mdCryptoOperationRSAPriv_Create
+ */
+static NSSCKMDCryptoOperation *
+ckmk_mdCryptoOperationRSAPriv_Create(
+ const NSSCKMDCryptoOperation *proto,
+ NSSCKMDMechanism *mdMechanism,
+ NSSCKMDObject *mdKey,
+ ckmkRSAOpType type,
+ CK_RV *pError)
+{
+ ckmkInternalObject *iKey = (ckmkInternalObject *)mdKey->etc;
+ const NSSItem *classItem = nss_ckmk_FetchAttribute(iKey, CKA_CLASS, pError);
+ const NSSItem *keyType = nss_ckmk_FetchAttribute(iKey, CKA_KEY_TYPE, pError);
+ ckmkInternalCryptoOperationRSAPriv *iOperation;
+ SecKeyRef privateKey;
+ OSStatus macErr;
+ CSSM_RETURN cssmErr;
+ const CSSM_KEY *cssmKey;
+ CSSM_CSP_HANDLE cspHandle;
+ const CSSM_ACCESS_CREDENTIALS *creds = NULL;
+ CSSM_CC_HANDLE cssmContext;
+ CSSM_ACL_AUTHORIZATION_TAG authType;
+
+ /* make sure we have the right objects */
+ if (((const NSSItem *)NULL == classItem) ||
+ (sizeof(CK_OBJECT_CLASS) != classItem->size) ||
+ (CKO_PRIVATE_KEY != *(CK_OBJECT_CLASS *)classItem->data) ||
+ ((const NSSItem *)NULL == keyType) ||
+ (sizeof(CK_KEY_TYPE) != keyType->size) ||
+ (CKK_RSA != *(CK_KEY_TYPE *)keyType->data)) {
+ *pError = CKR_KEY_TYPE_INCONSISTENT;
+ return (NSSCKMDCryptoOperation *)NULL;
+ }
+
+ privateKey = (SecKeyRef)iKey->u.item.itemRef;
+ macErr = SecKeyGetCSSMKey(privateKey, &cssmKey);
+ if (noErr != macErr) {
+ CKMK_MACERR("Getting CSSM Key", macErr);
+ *pError = CKR_KEY_HANDLE_INVALID;
+ return (NSSCKMDCryptoOperation *)NULL;
+ }
+ macErr = SecKeyGetCSPHandle(privateKey, &cspHandle);
+ if (noErr != macErr) {
+ CKMK_MACERR("Getting CSP for Key", macErr);
+ *pError = CKR_KEY_HANDLE_INVALID;
+ return (NSSCKMDCryptoOperation *)NULL;
+ }
+ switch (type) {
+ case CKMK_DECRYPT:
+ authType = CSSM_ACL_AUTHORIZATION_DECRYPT;
+ break;
+ case CKMK_SIGN:
+ authType = CSSM_ACL_AUTHORIZATION_SIGN;
+ break;
+ default:
+ *pError = CKR_GENERAL_ERROR;
+#ifdef DEBUG
+ fprintf(stderr, "RSAPriv_Create: bad type = %d\n", type);
+#endif
+ return (NSSCKMDCryptoOperation *)NULL;
+ }
+
+ macErr = SecKeyGetCredentials(privateKey, authType, 0, &creds);
+ if (noErr != macErr) {
+ CKMK_MACERR("Getting Credentials for Key", macErr);
+ *pError = CKR_KEY_HANDLE_INVALID;
+ return (NSSCKMDCryptoOperation *)NULL;
+ }
+
+ switch (type) {
+ case CKMK_DECRYPT:
+ cssmErr = CSSM_CSP_CreateAsymmetricContext(cspHandle, CSSM_ALGID_RSA,
+ creds, cssmKey, CSSM_PADDING_PKCS1, &cssmContext);
+ break;
+ case CKMK_SIGN:
+ cssmErr = CSSM_CSP_CreateSignatureContext(cspHandle, CSSM_ALGID_RSA,
+ creds, cssmKey, &cssmContext);
+ break;
+ default:
+ *pError = CKR_GENERAL_ERROR;
+#ifdef DEBUG
+ fprintf(stderr, "RSAPriv_Create: bad type = %d\n", type);
+#endif
+ return (NSSCKMDCryptoOperation *)NULL;
+ }
+ if (noErr != cssmErr) {
+ CKMK_MACERR("Getting Context for Key", cssmErr);
+ *pError = CKR_GENERAL_ERROR;
+ return (NSSCKMDCryptoOperation *)NULL;
+ }
+
+ iOperation = nss_ZNEW(NULL, ckmkInternalCryptoOperationRSAPriv);
+ if ((ckmkInternalCryptoOperationRSAPriv *)NULL == iOperation) {
+ *pError = CKR_HOST_MEMORY;
+ return (NSSCKMDCryptoOperation *)NULL;
+ }
+ iOperation->mdMechanism = mdMechanism;
+ iOperation->iKey = iKey;
+ iOperation->cssmContext = cssmContext;
+
+ nsslibc_memcpy(&iOperation->mdOperation,
+ proto, sizeof(NSSCKMDCryptoOperation));
+ iOperation->mdOperation.etc = iOperation;
+
+ return &iOperation->mdOperation;
+}
+
+static void
+ckmk_mdCryptoOperationRSAPriv_Destroy(
+ NSSCKMDCryptoOperation *mdOperation,
+ NSSCKFWCryptoOperation *fwOperation,
+ NSSCKMDInstance *mdInstance,
+ NSSCKFWInstance *fwInstance)
+{
+ ckmkInternalCryptoOperationRSAPriv *iOperation =
+ (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc;
+
+ if (iOperation->buffer) {
+ nssItem_Destroy(iOperation->buffer);
+ }
+ if (iOperation->cssmContext) {
+ CSSM_DeleteContext(iOperation->cssmContext);
+ }
+ nss_ZFreeIf(iOperation);
+ return;
+}
+
+static CK_ULONG
+ckmk_mdCryptoOperationRSA_GetFinalLength(
+ NSSCKMDCryptoOperation *mdOperation,
+ NSSCKFWCryptoOperation *fwOperation,
+ NSSCKMDSession *mdSession,
+ NSSCKFWSession *fwSession,
+ NSSCKMDToken *mdToken,
+ NSSCKFWToken *fwToken,
+ NSSCKMDInstance *mdInstance,
+ NSSCKFWInstance *fwInstance,
+ CK_RV *pError)
+{
+ ckmkInternalCryptoOperationRSAPriv *iOperation =
+ (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc;
+ const NSSItem *modulus =
+ nss_ckmk_FetchAttribute(iOperation->iKey, CKA_MODULUS, pError);
+
+ return modulus->size;
+}
+
+/*
+ * ckmk_mdCryptoOperationRSADecrypt_GetOperationLength
+ * we won't know the length until we actually decrypt the
+ * input block. Since we go to all the work to decrypt the
+ * the block, we'll save if for when the block is asked for
+ */
+static CK_ULONG
+ckmk_mdCryptoOperationRSADecrypt_GetOperationLength(
+ NSSCKMDCryptoOperation *mdOperation,
+ NSSCKFWCryptoOperation *fwOperation,
+ NSSCKMDSession *mdSession,
+ NSSCKFWSession *fwSession,
+ NSSCKMDToken *mdToken,
+ NSSCKFWToken *fwToken,
+ NSSCKMDInstance *mdInstance,
+ NSSCKFWInstance *fwInstance,
+ const NSSItem *input,
+ CK_RV *pError)
+{
+ ckmkInternalCryptoOperationRSAPriv *iOperation =
+ (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc;
+ CSSM_DATA cssmInput;
+ CSSM_DATA cssmOutput = { 0, NULL };
+ PRUint32 bytesDecrypted;
+ CSSM_DATA remainder = { 0, NULL };
+ NSSItem output;
+ CSSM_RETURN cssmErr;
+
+ if (iOperation->buffer) {
+ return iOperation->buffer->size;
+ }
+
+ cssmInput.Data = input->data;
+ cssmInput.Length = input->size;
+
+ cssmErr = CSSM_DecryptData(iOperation->cssmContext,
+ &cssmInput, 1, &cssmOutput, 1,
+ &bytesDecrypted, &remainder);
+ if (CSSM_OK != cssmErr) {
+ CKMK_MACERR("Decrypt Failed", cssmErr);
+ *pError = CKR_DATA_INVALID;
+ return 0;
+ }
+ /* we didn't suppy any buffers, so it should all be in remainder */
+ output.data = nss_ZNEWARRAY(NULL, char, bytesDecrypted + remainder.Length);
+ if (NULL == output.data) {
+ free(cssmOutput.Data);
+ free(remainder.Data);
+ *pError = CKR_HOST_MEMORY;
+ return 0;
+ }
+ output.size = bytesDecrypted + remainder.Length;
+
+ if (0 != bytesDecrypted) {
+ nsslibc_memcpy(output.data, cssmOutput.Data, bytesDecrypted);
+ free(cssmOutput.Data);
+ }
+ if (0 != remainder.Length) {
+ nsslibc_memcpy(((char *)output.data) + bytesDecrypted,
+ remainder.Data, remainder.Length);
+ free(remainder.Data);
+ }
+
+ iOperation->buffer = nssItem_Duplicate(&output, NULL, NULL);
+ nss_ZFreeIf(output.data);
+ if ((NSSItem *)NULL == iOperation->buffer) {
+ *pError = CKR_HOST_MEMORY;
+ return 0;
+ }
+
+ return iOperation->buffer->size;
+}
+
+/*
+ * ckmk_mdCryptoOperationRSADecrypt_UpdateFinal
+ *
+ * NOTE: ckmk_mdCryptoOperationRSADecrypt_GetOperationLength is presumed to
+ * have been called previously.
+ */
+static CK_RV
+ckmk_mdCryptoOperationRSADecrypt_UpdateFinal(
+ NSSCKMDCryptoOperation *mdOperation,
+ NSSCKFWCryptoOperation *fwOperation,
+ NSSCKMDSession *mdSession,
+ NSSCKFWSession *fwSession,
+ NSSCKMDToken *mdToken,
+ NSSCKFWToken *fwToken,
+ NSSCKMDInstance *mdInstance,
+ NSSCKFWInstance *fwInstance,
+ const NSSItem *input,
+ NSSItem *output)
+{
+ ckmkInternalCryptoOperationRSAPriv *iOperation =
+ (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc;
+ NSSItem *buffer = iOperation->buffer;
+
+ if ((NSSItem *)NULL == buffer) {
+ return CKR_GENERAL_ERROR;
+ }
+ nsslibc_memcpy(output->data, buffer->data, buffer->size);
+ output->size = buffer->size;
+ return CKR_OK;
+}
+
+/*
+ * ckmk_mdCryptoOperationRSASign_UpdateFinal
+ *
+ */
+static CK_RV
+ckmk_mdCryptoOperationRSASign_UpdateFinal(
+ NSSCKMDCryptoOperation *mdOperation,
+ NSSCKFWCryptoOperation *fwOperation,
+ NSSCKMDSession *mdSession,
+ NSSCKFWSession *fwSession,
+ NSSCKMDToken *mdToken,
+ NSSCKFWToken *fwToken,
+ NSSCKMDInstance *mdInstance,
+ NSSCKFWInstance *fwInstance,
+ const NSSItem *input,
+ NSSItem *output)
+{
+ ckmkInternalCryptoOperationRSAPriv *iOperation =
+ (ckmkInternalCryptoOperationRSAPriv *)mdOperation->etc;
+ CSSM_DATA cssmInput;
+ CSSM_DATA cssmOutput = { 0, NULL };
+ CSSM_RETURN cssmErr;
+
+ cssmInput.Data = input->data;
+ cssmInput.Length = input->size;
+
+ cssmErr = CSSM_SignData(iOperation->cssmContext, &cssmInput, 1,
+ CSSM_ALGID_NONE, &cssmOutput);
+ if (CSSM_OK != cssmErr) {
+ CKMK_MACERR("Signed Failed", cssmErr);
+ return CKR_FUNCTION_FAILED;
+ }
+ if (cssmOutput.Length > output->size) {
+ free(cssmOutput.Data);
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ nsslibc_memcpy(output->data, cssmOutput.Data, cssmOutput.Length);
+ free(cssmOutput.Data);
+ output->size = cssmOutput.Length;
+
+ return CKR_OK;
+}
+
+NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation
+ ckmk_mdCryptoOperationRSADecrypt_proto = {
+ NULL, /* etc */
+ ckmk_mdCryptoOperationRSAPriv_Destroy,
+ NULL, /* GetFinalLengh - not needed for one shot Decrypt/Encrypt */
+ ckmk_mdCryptoOperationRSADecrypt_GetOperationLength,
+ NULL, /* Final - not needed for one shot operation */
+ NULL, /* Update - not needed for one shot operation */
+ NULL, /* DigetUpdate - not needed for one shot operation */
+ ckmk_mdCryptoOperationRSADecrypt_UpdateFinal,
+ NULL, /* UpdateCombo - not needed for one shot operation */
+ NULL, /* DigetKey - not needed for one shot operation */
+ (void *)NULL /* null terminator */
+ };
+
+NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation
+ ckmk_mdCryptoOperationRSASign_proto = {
+ NULL, /* etc */
+ ckmk_mdCryptoOperationRSAPriv_Destroy,
+ ckmk_mdCryptoOperationRSA_GetFinalLength,
+ NULL, /* GetOperationLengh - not needed for one shot Sign/Verify */
+ NULL, /* Final - not needed for one shot operation */
+ NULL, /* Update - not needed for one shot operation */
+ NULL, /* DigetUpdate - not needed for one shot operation */
+ ckmk_mdCryptoOperationRSASign_UpdateFinal,
+ NULL, /* UpdateCombo - not needed for one shot operation */
+ NULL, /* DigetKey - not needed for one shot operation */
+ (void *)NULL /* null terminator */
+ };
+
+/********** NSSCKMDMechansim functions ***********************/
+/*
+ * ckmk_mdMechanismRSA_Destroy
+ */
+static void
+ckmk_mdMechanismRSA_Destroy(
+ NSSCKMDMechanism *mdMechanism,
+ NSSCKFWMechanism *fwMechanism,
+ NSSCKMDInstance *mdInstance,
+ NSSCKFWInstance *fwInstance)
+{
+ nss_ZFreeIf(fwMechanism);
+}
+
+/*
+ * ckmk_mdMechanismRSA_GetMinKeySize
+ */
+static CK_ULONG
+ckmk_mdMechanismRSA_GetMinKeySize(
+ NSSCKMDMechanism *mdMechanism,
+ NSSCKFWMechanism *fwMechanism,
+ NSSCKMDToken *mdToken,
+ NSSCKFWToken *fwToken,
+ NSSCKMDInstance *mdInstance,
+ NSSCKFWInstance *fwInstance,
+ CK_RV *pError)
+{
+ return 384;
+}
+
+/*
+ * ckmk_mdMechanismRSA_GetMaxKeySize
+ */
+static CK_ULONG
+ckmk_mdMechanismRSA_GetMaxKeySize(
+ NSSCKMDMechanism *mdMechanism,
+ NSSCKFWMechanism *fwMechanism,
+ NSSCKMDToken *mdToken,
+ NSSCKFWToken *fwToken,
+ NSSCKMDInstance *mdInstance,
+ NSSCKFWInstance *fwInstance,
+ CK_RV *pError)
+{
+ return 16384;
+}
+
+/*
+ * ckmk_mdMechanismRSA_DecryptInit
+ */
+static NSSCKMDCryptoOperation *
+ckmk_mdMechanismRSA_DecryptInit(
+ NSSCKMDMechanism *mdMechanism,
+ NSSCKFWMechanism *fwMechanism,
+ CK_MECHANISM *pMechanism,
+ NSSCKMDSession *mdSession,
+ NSSCKFWSession *fwSession,
+ NSSCKMDToken *mdToken,
+ NSSCKFWToken *fwToken,
+ NSSCKMDInstance *mdInstance,
+ NSSCKFWInstance *fwInstance,
+ NSSCKMDObject *mdKey,
+ NSSCKFWObject *fwKey,
+ CK_RV *pError)
+{
+ return ckmk_mdCryptoOperationRSAPriv_Create(
+ &ckmk_mdCryptoOperationRSADecrypt_proto,
+ mdMechanism, mdKey, CKMK_DECRYPT, pError);
+}
+
+/*
+ * ckmk_mdMechanismRSA_SignInit
+ */
+static NSSCKMDCryptoOperation *
+ckmk_mdMechanismRSA_SignInit(
+ NSSCKMDMechanism *mdMechanism,
+ NSSCKFWMechanism *fwMechanism,
+ CK_MECHANISM *pMechanism,
+ NSSCKMDSession *mdSession,
+ NSSCKFWSession *fwSession,
+ NSSCKMDToken *mdToken,
+ NSSCKFWToken *fwToken,
+ NSSCKMDInstance *mdInstance,
+ NSSCKFWInstance *fwInstance,
+ NSSCKMDObject *mdKey,
+ NSSCKFWObject *fwKey,
+ CK_RV *pError)
+{
+ return ckmk_mdCryptoOperationRSAPriv_Create(
+ &ckmk_mdCryptoOperationRSASign_proto,
+ mdMechanism, mdKey, CKMK_SIGN, pError);
+}
+
+NSS_IMPLEMENT_DATA const NSSCKMDMechanism
+ nss_ckmk_mdMechanismRSA = {
+ (void *)NULL, /* etc */
+ ckmk_mdMechanismRSA_Destroy,
+ ckmk_mdMechanismRSA_GetMinKeySize,
+ ckmk_mdMechanismRSA_GetMaxKeySize,
+ NULL, /* GetInHardware - default false */
+ NULL, /* EncryptInit - default errs */
+ ckmk_mdMechanismRSA_DecryptInit,
+ NULL, /* DigestInit - default errs*/
+ ckmk_mdMechanismRSA_SignInit,
+ NULL, /* VerifyInit - default errs */
+ ckmk_mdMechanismRSA_SignInit, /* SignRecoverInit */
+ NULL, /* VerifyRecoverInit - default errs */
+ NULL, /* GenerateKey - default errs */
+ NULL, /* GenerateKeyPair - default errs */
+ NULL, /* GetWrapKeyLength - default errs */
+ NULL, /* WrapKey - default errs */
+ NULL, /* UnwrapKey - default errs */
+ NULL, /* DeriveKey - default errs */
+ (void *)NULL /* null terminator */
+ };