mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-14 11:40:13 +01:00
511 lines
14 KiB
C
511 lines
14 KiB
C
/* 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 */
|
|
};
|