diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-01-04 14:24:24 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-01-04 14:24:24 +0000 |
commit | dc1565216a5d20ae0d75872151523252309a1292 (patch) | |
tree | d57454ba9a40386552179eddf60d28bd1e8f3d54 /nss/lib/softoken/pkcs11c.c | |
parent | 26c046fbc57d53136b4fb3b5e0d18298318125d4 (diff) | |
download | nss-dc1565216a5d20ae0d75872151523252309a1292.tar.gz |
nss-3.28.1nss-3.28.1
Diffstat (limited to 'nss/lib/softoken/pkcs11c.c')
-rw-r--r-- | nss/lib/softoken/pkcs11c.c | 9709 |
1 files changed, 5013 insertions, 4696 deletions
diff --git a/nss/lib/softoken/pkcs11c.c b/nss/lib/softoken/pkcs11c.c index 8755f24..d7b4bb9 100644 --- a/nss/lib/softoken/pkcs11c.c +++ b/nss/lib/softoken/pkcs11c.c @@ -6,11 +6,11 @@ * * For more information about PKCS 11 See PKCS 11 Token Inteface Standard. * This implementation has two slots: - * slot 1 is our generic crypto support. It does not require login. - * It supports Public Key ops, and all they bulk ciphers and hashes. - * It can also support Private Key ops for imported Private keys. It does + * slot 1 is our generic crypto support. It does not require login. + * It supports Public Key ops, and all they bulk ciphers and hashes. + * It can also support Private Key ops for imported Private keys. It does * not have any token storage. - * slot 2 is our private key support. It requires a login before use. It + * slot 2 is our private key support. It requires a login before use. It * can store Private Keys and Certs as token objects. Currently only private * keys and their associated Certificates are saved on the token. * @@ -27,7 +27,7 @@ #include "lowkeyi.h" #include "secder.h" #include "secdig.h" -#include "lowpbe.h" /* We do PBE below */ +#include "lowpbe.h" /* We do PBE below */ #include "pkcs11t.h" #include "secoid.h" #include "alghmac.h" @@ -36,21 +36,22 @@ #include "secerr.h" #include "prprf.h" +#include "prenv.h" -#define __PASTE(x,y) x##y +#define __PASTE(x, y) x##y /* * we renamed all our internal functions, get the correct * definitions for them... - */ + */ #undef CK_PKCS11_FUNCTION_INFO #undef CK_NEED_ARG_LIST #define CK_EXTERN extern #define CK_PKCS11_FUNCTION_INFO(func) \ - CK_RV __PASTE(NS,func) -#define CK_NEED_ARG_LIST 1 - + CK_RV __PASTE(NS, func) +#define CK_NEED_ARG_LIST 1 + #include "pkcs11f.h" typedef struct { @@ -58,23 +59,24 @@ typedef struct { PRUint8 random[46]; } SSL3RSAPreMasterSecret; -static void sftk_Null(void *data, PRBool freeit) +static void +sftk_Null(void *data, PRBool freeit) { return; -} +} #ifndef NSS_DISABLE_ECC #ifdef EC_DEBUG -#define SEC_PRINT(str1, str2, num, sitem) \ +#define SEC_PRINT(str1, str2, num, sitem) \ printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \ - str1, str2, num, sitem->len); \ - for (i = 0; i < sitem->len; i++) { \ - printf("%02x:", sitem->data[i]); \ - } \ - printf("\n") + str1, str2, num, sitem->len); \ + for (i = 0; i < sitem->len; i++) { \ + printf("%02x:", sitem->data[i]); \ + } \ + printf("\n") #else #undef EC_DEBUG -#define SEC_PRINT(a, b, c, d) +#define SEC_PRINT(a, b, c, d) #endif #endif /* NSS_DISABLE_ECC */ @@ -92,7 +94,7 @@ static void sftk_Space(void *data, PRBool freeit) { PORT_Free(data); -} +} /* * map all the SEC_ERROR_xxx error codes that may be returned by freebl @@ -103,33 +105,33 @@ static CK_RV sftk_MapCryptError(int error) { switch (error) { - case SEC_ERROR_INVALID_ARGS: - case SEC_ERROR_BAD_DATA: /* MP_RANGE gets mapped to this */ - return CKR_ARGUMENTS_BAD; - case SEC_ERROR_INPUT_LEN: - return CKR_DATA_LEN_RANGE; - case SEC_ERROR_OUTPUT_LEN: - return CKR_BUFFER_TOO_SMALL; - case SEC_ERROR_LIBRARY_FAILURE: - return CKR_GENERAL_ERROR; - case SEC_ERROR_NO_MEMORY: - return CKR_HOST_MEMORY; - case SEC_ERROR_BAD_SIGNATURE: - return CKR_SIGNATURE_INVALID; - case SEC_ERROR_INVALID_KEY: - return CKR_KEY_SIZE_RANGE; - case SEC_ERROR_BAD_KEY: /* an EC public key that fails validation */ - return CKR_KEY_SIZE_RANGE; /* the closest error code */ - case SEC_ERROR_UNSUPPORTED_EC_POINT_FORM: - return CKR_TEMPLATE_INCONSISTENT; - /* EC functions set this error if NSS_DISABLE_ECC is defined */ - case SEC_ERROR_UNSUPPORTED_KEYALG: - return CKR_MECHANISM_INVALID; - case SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE: - return CKR_DOMAIN_PARAMS_INVALID; - /* key pair generation failed after max number of attempts */ - case SEC_ERROR_NEED_RANDOM: - return CKR_FUNCTION_FAILED; + case SEC_ERROR_INVALID_ARGS: + case SEC_ERROR_BAD_DATA: /* MP_RANGE gets mapped to this */ + return CKR_ARGUMENTS_BAD; + case SEC_ERROR_INPUT_LEN: + return CKR_DATA_LEN_RANGE; + case SEC_ERROR_OUTPUT_LEN: + return CKR_BUFFER_TOO_SMALL; + case SEC_ERROR_LIBRARY_FAILURE: + return CKR_GENERAL_ERROR; + case SEC_ERROR_NO_MEMORY: + return CKR_HOST_MEMORY; + case SEC_ERROR_BAD_SIGNATURE: + return CKR_SIGNATURE_INVALID; + case SEC_ERROR_INVALID_KEY: + return CKR_KEY_SIZE_RANGE; + case SEC_ERROR_BAD_KEY: /* an EC public key that fails validation */ + return CKR_KEY_SIZE_RANGE; /* the closest error code */ + case SEC_ERROR_UNSUPPORTED_EC_POINT_FORM: + return CKR_TEMPLATE_INCONSISTENT; + /* EC functions set this error if NSS_DISABLE_ECC is defined */ + case SEC_ERROR_UNSUPPORTED_KEYALG: + return CKR_MECHANISM_INVALID; + case SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE: + return CKR_DOMAIN_PARAMS_INVALID; + /* key pair generation failed after max number of attempts */ + case SEC_ERROR_NEED_RANDOM: + return CKR_FUNCTION_FAILED; } return CKR_DEVICE_ERROR; } @@ -139,10 +141,10 @@ static CK_RV sftk_MapDecryptError(int error) { switch (error) { - case SEC_ERROR_BAD_DATA: - return CKR_ENCRYPTED_DATA_INVALID; - default: - return sftk_MapCryptError(error); + case SEC_ERROR_BAD_DATA: + return CKR_ENCRYPTED_DATA_INVALID; + default: + return sftk_MapCryptError(error); } } @@ -155,11 +157,10 @@ sftk_MapVerifyError(int error) { CK_RV crv = sftk_MapCryptError(error); if (crv == CKR_DEVICE_ERROR) - crv = CKR_SIGNATURE_INVALID; + crv = CKR_SIGNATURE_INVALID; return crv; } - /* * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by * Deprecating a full des key to 40 bit key strenth. @@ -171,45 +172,47 @@ sftk_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey) unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 }; unsigned char enc_src[8]; unsigned char enc_dest[8]; - unsigned int leng,i; + unsigned int leng, i; DESContext *descx; SECStatus rv; - - + /* zero the parity bits */ - for (i=0; i < 8; i++) { - enc_src[i] = cdmfkey[i] & 0xfe; + for (i = 0; i < 8; i++) { + enc_src[i] = cdmfkey[i] & 0xfe; } /* encrypt with key 1 */ descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE); - if (descx == NULL) return CKR_HOST_MEMORY; + if (descx == NULL) + return CKR_HOST_MEMORY; rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8); - DES_DestroyContext(descx,PR_TRUE); - if (rv != SECSuccess) return sftk_MapCryptError(PORT_GetError()); + DES_DestroyContext(descx, PR_TRUE); + if (rv != SECSuccess) + return sftk_MapCryptError(PORT_GetError()); /* xor source with des, zero the parity bits and deprecate the key*/ - for (i=0; i < 8; i++) { - if (i & 1) { - enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe; - } else { - enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e; - } + for (i = 0; i < 8; i++) { + if (i & 1) { + enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe; + } else { + enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e; + } } /* encrypt with key 2 */ descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE); - if (descx == NULL) return CKR_HOST_MEMORY; + if (descx == NULL) + return CKR_HOST_MEMORY; rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8); - DES_DestroyContext(descx,PR_TRUE); - if (rv != SECSuccess) return sftk_MapCryptError(PORT_GetError()); + DES_DestroyContext(descx, PR_TRUE); + if (rv != SECSuccess) + return sftk_MapCryptError(PORT_GetError()); - /* set the corret parity on our new des key */ + /* set the corret parity on our new des key */ sftk_FormatDESKey(deskey, 8); return CKR_OK; } - /* NSC_DestroyObject destroys an object. */ CK_RV NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) @@ -222,7 +225,7 @@ NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) CHECK_FORK(); if (slot == NULL) { - return CKR_SESSION_HANDLE_INVALID; + return CKR_SESSION_HANDLE_INVALID; } /* * This whole block just makes sure we really can destroy the @@ -233,30 +236,30 @@ NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) return CKR_SESSION_HANDLE_INVALID; } - object = sftk_ObjectFromHandle(hObject,session); + object = sftk_ObjectFromHandle(hObject, session); if (object == NULL) { - sftk_FreeSession(session); - return CKR_OBJECT_HANDLE_INVALID; + sftk_FreeSession(session); + return CKR_OBJECT_HANDLE_INVALID; } /* don't destroy a private object if we aren't logged in */ if ((!slot->isLoggedIn) && (slot->needLogin) && - (sftk_isTrue(object,CKA_PRIVATE))) { - sftk_FreeSession(session); - sftk_FreeObject(object); - return CKR_USER_NOT_LOGGED_IN; + (sftk_isTrue(object, CKA_PRIVATE))) { + sftk_FreeSession(session); + sftk_FreeObject(object); + return CKR_USER_NOT_LOGGED_IN; } /* don't destroy a token object if we aren't in a rw session */ if (((session->info.flags & CKF_RW_SESSION) == 0) && - (sftk_isTrue(object,CKA_TOKEN))) { - sftk_FreeSession(session); - sftk_FreeObject(object); - return CKR_SESSION_READ_ONLY; + (sftk_isTrue(object, CKA_TOKEN))) { + sftk_FreeSession(session); + sftk_FreeObject(object); + return CKR_SESSION_READ_ONLY; } - sftk_DeleteObject(session,object); + sftk_DeleteObject(session, object); sftk_FreeSession(session); @@ -272,7 +275,6 @@ NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR; } - /* ************** Crypto Functions: Utilities ************************ */ @@ -344,48 +346,48 @@ sftk_ValidateOaepParams(const CK_RSA_PKCS_OAEP_PARAMS *params) return PR_TRUE; } -/* +/* * return a context based on the SFTKContext type. */ SFTKSessionContext * sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type) { switch (type) { - case SFTK_ENCRYPT: - case SFTK_DECRYPT: - return session->enc_context; - case SFTK_HASH: - return session->hash_context; - case SFTK_SIGN: - case SFTK_SIGN_RECOVER: - case SFTK_VERIFY: - case SFTK_VERIFY_RECOVER: - return session->hash_context; + case SFTK_ENCRYPT: + case SFTK_DECRYPT: + return session->enc_context; + case SFTK_HASH: + return session->hash_context; + case SFTK_SIGN: + case SFTK_SIGN_RECOVER: + case SFTK_VERIFY: + case SFTK_VERIFY_RECOVER: + return session->hash_context; } return NULL; } -/* +/* * change a context based on the SFTKContext type. */ void -sftk_SetContextByType(SFTKSession *session, SFTKContextType type, - SFTKSessionContext *context) +sftk_SetContextByType(SFTKSession *session, SFTKContextType type, + SFTKSessionContext *context) { switch (type) { - case SFTK_ENCRYPT: - case SFTK_DECRYPT: - session->enc_context = context; - break; - case SFTK_HASH: - session->hash_context = context; - break; - case SFTK_SIGN: - case SFTK_SIGN_RECOVER: - case SFTK_VERIFY: - case SFTK_VERIFY_RECOVER: - session->hash_context = context; - break; + case SFTK_ENCRYPT: + case SFTK_DECRYPT: + session->enc_context = context; + break; + case SFTK_HASH: + session->hash_context = context; + break; + case SFTK_SIGN: + case SFTK_SIGN_RECOVER: + case SFTK_VERIFY: + case SFTK_VERIFY_RECOVER: + session->hash_context = context; + break; } return; } @@ -398,25 +400,26 @@ sftk_SetContextByType(SFTKSession *session, SFTKContextType type, * pointer is returned, the caller is responsible for freeing it. */ static CK_RV -sftk_GetContext(CK_SESSION_HANDLE handle,SFTKSessionContext **contextPtr, - SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr) +sftk_GetContext(CK_SESSION_HANDLE handle, SFTKSessionContext **contextPtr, + SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr) { SFTKSession *session; SFTKSessionContext *context; session = sftk_SessionFromHandle(handle); - if (session == NULL) return CKR_SESSION_HANDLE_INVALID; - context = sftk_ReturnContextByType(session,type); + if (session == NULL) + return CKR_SESSION_HANDLE_INVALID; + context = sftk_ReturnContextByType(session, type); /* make sure the context is valid */ - if((context==NULL)||(context->type!=type)||(needMulti&&!(context->multi))){ + if ((context == NULL) || (context->type != type) || (needMulti && !(context->multi))) { sftk_FreeSession(session); - return CKR_OPERATION_NOT_INITIALIZED; + return CKR_OPERATION_NOT_INITIALIZED; } *contextPtr = context; if (sessionPtr != NULL) { - *sessionPtr = session; + *sessionPtr = session; } else { - sftk_FreeSession(session); + sftk_FreeSession(session); } return CKR_OK; } @@ -425,11 +428,11 @@ sftk_GetContext(CK_SESSION_HANDLE handle,SFTKSessionContext **contextPtr, * Intuitive name for FreeContext/SetNullContext pair. */ static void -sftk_TerminateOp( SFTKSession *session, SFTKContextType ctype, - SFTKSessionContext *context ) +sftk_TerminateOp(SFTKSession *session, SFTKContextType ctype, + SFTKSessionContext *context) { - sftk_FreeContext( context ); - sftk_SetContextByType( session, ctype, NULL ); + sftk_FreeContext(context); + sftk_SetContextByType(session, ctype, NULL); } /* @@ -441,55 +444,55 @@ sftk_TerminateOp( SFTKSession *session, SFTKContextType ctype, * all need to do at the beginning. This is done here. */ static CK_RV -sftk_InitGeneric(SFTKSession *session,SFTKSessionContext **contextPtr, - SFTKContextType ctype,SFTKObject **keyPtr, - CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr, - CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation) +sftk_InitGeneric(SFTKSession *session, SFTKSessionContext **contextPtr, + SFTKContextType ctype, SFTKObject **keyPtr, + CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr, + CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation) { SFTKObject *key = NULL; SFTKAttribute *att; SFTKSessionContext *context; /* We can only init if there is not current context active */ - if (sftk_ReturnContextByType(session,ctype) != NULL) { - return CKR_OPERATION_ACTIVE; + if (sftk_ReturnContextByType(session, ctype) != NULL) { + return CKR_OPERATION_ACTIVE; } /* find the key */ if (keyPtr) { - key = sftk_ObjectFromHandle(hKey,session); + key = sftk_ObjectFromHandle(hKey, session); if (key == NULL) { - return CKR_KEY_HANDLE_INVALID; - } - - /* make sure it's a valid key for this operation */ - if (((key->objclass != CKO_SECRET_KEY) && (key->objclass != pubKeyType)) - || !sftk_isTrue(key,operation)) { - sftk_FreeObject(key); - return CKR_KEY_TYPE_INCONSISTENT; - } - /* get the key type */ - att = sftk_FindAttribute(key,CKA_KEY_TYPE); - if (att == NULL) { - sftk_FreeObject(key); - return CKR_KEY_TYPE_INCONSISTENT; - } - PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE)); - if (att->attrib.ulValueLen != sizeof(CK_KEY_TYPE)) { - sftk_FreeAttribute(att); - sftk_FreeObject(key); - return CKR_ATTRIBUTE_VALUE_INVALID; - } - PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE)); - sftk_FreeAttribute(att); - *keyPtr = key; + return CKR_KEY_HANDLE_INVALID; + } + + /* make sure it's a valid key for this operation */ + if (((key->objclass != CKO_SECRET_KEY) && (key->objclass != pubKeyType)) || !sftk_isTrue(key, operation)) { + sftk_FreeObject(key); + return CKR_KEY_TYPE_INCONSISTENT; + } + /* get the key type */ + att = sftk_FindAttribute(key, CKA_KEY_TYPE); + if (att == NULL) { + sftk_FreeObject(key); + return CKR_KEY_TYPE_INCONSISTENT; + } + PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE)); + if (att->attrib.ulValueLen != sizeof(CK_KEY_TYPE)) { + sftk_FreeAttribute(att); + sftk_FreeObject(key); + return CKR_ATTRIBUTE_VALUE_INVALID; + } + PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE)); + sftk_FreeAttribute(att); + *keyPtr = key; } /* allocate the context structure */ context = (SFTKSessionContext *)PORT_Alloc(sizeof(SFTKSessionContext)); if (context == NULL) { - if (key) sftk_FreeObject(key); - return CKR_HOST_MEMORY; + if (key) + sftk_FreeObject(key); + return CKR_HOST_MEMORY; } context->type = ctype; context->multi = PR_TRUE; @@ -510,17 +513,17 @@ static int sftk_aes_mode(CK_MECHANISM_TYPE mechanism) { switch (mechanism) { - case CKM_AES_CBC_PAD: - case CKM_AES_CBC: - return NSS_AES_CBC; - case CKM_AES_ECB: - return NSS_AES; - case CKM_AES_CTS: - return NSS_AES_CTS; - case CKM_AES_CTR: - return NSS_AES_CTR; - case CKM_AES_GCM: - return NSS_AES_GCM; + case CKM_AES_CBC_PAD: + case CKM_AES_CBC: + return NSS_AES_CBC; + case CKM_AES_ECB: + return NSS_AES; + case CKM_AES_CTS: + return NSS_AES_CTS; + case CKM_AES_CTR: + return NSS_AES_CTR; + case CKM_AES_GCM: + return NSS_AES_GCM; } return -1; } @@ -631,7 +634,7 @@ sftk_RSAEncryptOAEP(SFTKOAEPEncryptInfo *info, unsigned char *output, maskHashAlg = GetHashTypeFromMechanism(info->params->mgf); return RSA_EncryptOAEP(&info->key->u.rsa, hashAlg, maskHashAlg, - (const unsigned char*)info->params->pSourceData, + (const unsigned char *)info->params->pSourceData, info->params->ulSourceDataLen, NULL, 0, output, outputLen, maxLen, input, inputLen); } @@ -655,15 +658,111 @@ sftk_RSADecryptOAEP(SFTKOAEPDecryptInfo *info, unsigned char *output, maskHashAlg = GetHashTypeFromMechanism(info->params->mgf); rv = RSA_DecryptOAEP(&info->key->u.rsa, hashAlg, maskHashAlg, - (const unsigned char*)info->params->pSourceData, + (const unsigned char *)info->params->pSourceData, info->params->ulSourceDataLen, output, outputLen, maxLen, input, inputLen); - if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { sftk_fatalError = PR_TRUE; } return rv; } +static SFTKChaCha20Poly1305Info * +sftk_ChaCha20Poly1305_CreateContext(const unsigned char *key, + unsigned int keyLen, + const CK_NSS_AEAD_PARAMS *params) +{ + SFTKChaCha20Poly1305Info *ctx; + + if (params->ulNonceLen != sizeof(ctx->nonce)) { + PORT_SetError(SEC_ERROR_INPUT_LEN); + return NULL; + } + + ctx = PORT_New(SFTKChaCha20Poly1305Info); + if (ctx == NULL) { + return NULL; + } + + if (ChaCha20Poly1305_InitContext(&ctx->freeblCtx, key, keyLen, + params->ulTagLen) != SECSuccess) { + PORT_Free(ctx); + return NULL; + } + + PORT_Memcpy(ctx->nonce, params->pNonce, sizeof(ctx->nonce)); + + /* AAD data and length must both be null, or both non-null. */ + PORT_Assert((params->pAAD == NULL) == (params->ulAADLen == 0)); + + if (params->ulAADLen > sizeof(ctx->ad)) { + /* Need to allocate an overflow buffer for the additional data. */ + ctx->adOverflow = (unsigned char *)PORT_Alloc(params->ulAADLen); + if (!ctx->adOverflow) { + PORT_Free(ctx); + return NULL; + } + PORT_Memcpy(ctx->adOverflow, params->pAAD, params->ulAADLen); + } else { + ctx->adOverflow = NULL; + if (params->pAAD) { + PORT_Memcpy(ctx->ad, params->pAAD, params->ulAADLen); + } + } + ctx->adLen = params->ulAADLen; + + return ctx; +} + +static void +sftk_ChaCha20Poly1305_DestroyContext(SFTKChaCha20Poly1305Info *ctx, + PRBool freeit) +{ + ChaCha20Poly1305_DestroyContext(&ctx->freeblCtx, PR_FALSE); + if (ctx->adOverflow != NULL) { + PORT_Free(ctx->adOverflow); + ctx->adOverflow = NULL; + } + ctx->adLen = 0; + if (freeit) { + PORT_Free(ctx); + } +} + +static SECStatus +sftk_ChaCha20Poly1305_Encrypt(const SFTKChaCha20Poly1305Info *ctx, + unsigned char *output, unsigned int *outputLen, + unsigned int maxOutputLen, + const unsigned char *input, unsigned int inputLen) +{ + const unsigned char *ad = ctx->adOverflow; + + if (ad == NULL) { + ad = ctx->ad; + } + + return ChaCha20Poly1305_Seal(&ctx->freeblCtx, output, outputLen, + maxOutputLen, input, inputLen, ctx->nonce, + sizeof(ctx->nonce), ad, ctx->adLen); +} + +static SECStatus +sftk_ChaCha20Poly1305_Decrypt(const SFTKChaCha20Poly1305Info *ctx, + unsigned char *output, unsigned int *outputLen, + unsigned int maxOutputLen, + const unsigned char *input, unsigned int inputLen) +{ + const unsigned char *ad = ctx->adOverflow; + + if (ad == NULL) { + ad = ctx->ad; + } + + return ChaCha20Poly1305_Open(&ctx->freeblCtx, output, outputLen, + maxOutputLen, input, inputLen, ctx->nonce, + sizeof(ctx->nonce), ad, ctx->adLen); +} + /** NSC_CryptInit initializes an encryption/Decryption operation. * * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey. @@ -672,9 +771,9 @@ sftk_RSADecryptOAEP(SFTKOAEPDecryptInfo *info, unsigned char *output, */ static CK_RV sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hKey, - CK_ATTRIBUTE_TYPE mechUsage, CK_ATTRIBUTE_TYPE keyUsage, - SFTKContextType contextType, PRBool isEncrypt) + CK_OBJECT_HANDLE hKey, + CK_ATTRIBUTE_TYPE mechUsage, CK_ATTRIBUTE_TYPE keyUsage, + SFTKContextType contextType, PRBool isEncrypt) { SFTKSession *session; SFTKObject *key; @@ -689,412 +788,439 @@ sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_RV crv = CKR_OK; unsigned effectiveKeyLength; unsigned char newdeskey[24]; - PRBool useNewKey=PR_FALSE; + PRBool useNewKey = PR_FALSE; int t; - crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage ); - if (crv != CKR_OK) - return crv; + crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage); + if (crv != CKR_OK) + return crv; session = sftk_SessionFromHandle(hSession); - if (session == NULL) return CKR_SESSION_HANDLE_INVALID; + if (session == NULL) + return CKR_SESSION_HANDLE_INVALID; + + crv = sftk_InitGeneric(session, &context, contextType, &key, hKey, &key_type, + isEncrypt ? CKO_PUBLIC_KEY : CKO_PRIVATE_KEY, keyUsage); - crv = sftk_InitGeneric(session,&context,contextType,&key,hKey,&key_type, - isEncrypt ?CKO_PUBLIC_KEY:CKO_PRIVATE_KEY, keyUsage); - if (crv != CKR_OK) { - sftk_FreeSession(session); - return crv; + sftk_FreeSession(session); + return crv; } context->doPad = PR_FALSE; - switch(pMechanism->mechanism) { - case CKM_RSA_PKCS: - case CKM_RSA_X_509: - if (key_type != CKK_RSA) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - context->multi = PR_FALSE; - context->rsa = PR_TRUE; - if (isEncrypt) { - NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key,CKK_RSA,&crv); - if (pubKey == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - context->maxLen = nsslowkey_PublicModulusLen(pubKey); - context->cipherInfo = (void *)pubKey; - context->update = (SFTKCipher) - (pMechanism->mechanism == CKM_RSA_X_509 - ? sftk_RSAEncryptRaw : sftk_RSAEncrypt); - } else { - NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key,CKK_RSA,&crv); - if (privKey == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - context->maxLen = nsslowkey_PrivateModulusLen(privKey); - context->cipherInfo = (void *)privKey; - context->update = (SFTKCipher) - (pMechanism->mechanism == CKM_RSA_X_509 - ? sftk_RSADecryptRaw : sftk_RSADecrypt); - } - context->destroy = sftk_Null; - break; - case CKM_RSA_PKCS_OAEP: - if (key_type != CKK_RSA) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS) || - !sftk_ValidateOaepParams((CK_RSA_PKCS_OAEP_PARAMS*)pMechanism->pParameter)) { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - context->multi = PR_FALSE; - context->rsa = PR_TRUE; - if (isEncrypt) { - SFTKOAEPEncryptInfo *info = PORT_New(SFTKOAEPEncryptInfo); - if (info == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - info->params = pMechanism->pParameter; - info->key = sftk_GetPubKey(key, CKK_RSA, &crv); - if (info->key == NULL) { - PORT_Free(info); - crv = CKR_KEY_HANDLE_INVALID; - break; - } - context->update = (SFTKCipher) sftk_RSAEncryptOAEP; - context->maxLen = nsslowkey_PublicModulusLen(info->key); - context->cipherInfo = info; - } else { - SFTKOAEPDecryptInfo *info = PORT_New(SFTKOAEPDecryptInfo); - if (info == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - info->params = pMechanism->pParameter; - info->key = sftk_GetPrivKey(key, CKK_RSA, &crv); - if (info->key == NULL) { - PORT_Free(info); - crv = CKR_KEY_HANDLE_INVALID; - break; - } - context->update = (SFTKCipher) sftk_RSADecryptOAEP; - context->maxLen = nsslowkey_PrivateModulusLen(info->key); - context->cipherInfo = info; - } - context->destroy = (SFTKDestroy) sftk_Space; - break; - case CKM_RC2_CBC_PAD: - context->doPad = PR_TRUE; - /* fall thru */ - case CKM_RC2_ECB: - case CKM_RC2_CBC: - context->blockSize = 8; - if (key_type != CKK_RC2) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - att = sftk_FindAttribute(key,CKA_VALUE); - if (att == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter; - effectiveKeyLength = (rc2_param->ulEffectiveBits+7)/8; - context->cipherInfo = - RC2_CreateContext((unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen, rc2_param->iv, - pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 : - NSS_RC2_CBC,effectiveKeyLength); - sftk_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (SFTKCipher) (isEncrypt ? RC2_Encrypt : RC2_Decrypt); - context->destroy = (SFTKDestroy) RC2_DestroyContext; - break; + switch (pMechanism->mechanism) { + case CKM_RSA_PKCS: + case CKM_RSA_X_509: + if (key_type != CKK_RSA) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + context->multi = PR_FALSE; + context->rsa = PR_TRUE; + if (isEncrypt) { + NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key, CKK_RSA, &crv); + if (pubKey == NULL) { + crv = CKR_KEY_HANDLE_INVALID; + break; + } + context->maxLen = nsslowkey_PublicModulusLen(pubKey); + context->cipherInfo = (void *)pubKey; + context->update = (SFTKCipher)(pMechanism->mechanism == CKM_RSA_X_509 + ? sftk_RSAEncryptRaw + : sftk_RSAEncrypt); + } else { + NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key, CKK_RSA, &crv); + if (privKey == NULL) { + crv = CKR_KEY_HANDLE_INVALID; + break; + } + context->maxLen = nsslowkey_PrivateModulusLen(privKey); + context->cipherInfo = (void *)privKey; + context->update = (SFTKCipher)(pMechanism->mechanism == CKM_RSA_X_509 + ? sftk_RSADecryptRaw + : sftk_RSADecrypt); + } + context->destroy = sftk_Null; + break; + case CKM_RSA_PKCS_OAEP: + if (key_type != CKK_RSA) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS) || + !sftk_ValidateOaepParams((CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter)) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + context->multi = PR_FALSE; + context->rsa = PR_TRUE; + if (isEncrypt) { + SFTKOAEPEncryptInfo *info = PORT_New(SFTKOAEPEncryptInfo); + if (info == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + info->params = pMechanism->pParameter; + info->key = sftk_GetPubKey(key, CKK_RSA, &crv); + if (info->key == NULL) { + PORT_Free(info); + crv = CKR_KEY_HANDLE_INVALID; + break; + } + context->update = (SFTKCipher)sftk_RSAEncryptOAEP; + context->maxLen = nsslowkey_PublicModulusLen(info->key); + context->cipherInfo = info; + } else { + SFTKOAEPDecryptInfo *info = PORT_New(SFTKOAEPDecryptInfo); + if (info == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + info->params = pMechanism->pParameter; + info->key = sftk_GetPrivKey(key, CKK_RSA, &crv); + if (info->key == NULL) { + PORT_Free(info); + crv = CKR_KEY_HANDLE_INVALID; + break; + } + context->update = (SFTKCipher)sftk_RSADecryptOAEP; + context->maxLen = nsslowkey_PrivateModulusLen(info->key); + context->cipherInfo = info; + } + context->destroy = (SFTKDestroy)sftk_Space; + break; + case CKM_RC2_CBC_PAD: + context->doPad = PR_TRUE; + /* fall thru */ + case CKM_RC2_ECB: + case CKM_RC2_CBC: + context->blockSize = 8; + if (key_type != CKK_RC2) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + att = sftk_FindAttribute(key, CKA_VALUE); + if (att == NULL) { + crv = CKR_KEY_HANDLE_INVALID; + break; + } + rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter; + effectiveKeyLength = (rc2_param->ulEffectiveBits + 7) / 8; + context->cipherInfo = + RC2_CreateContext((unsigned char *)att->attrib.pValue, + att->attrib.ulValueLen, rc2_param->iv, + pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 : NSS_RC2_CBC, effectiveKeyLength); + sftk_FreeAttribute(att); + if (context->cipherInfo == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + context->update = (SFTKCipher)(isEncrypt ? RC2_Encrypt : RC2_Decrypt); + context->destroy = (SFTKDestroy)RC2_DestroyContext; + break; #if NSS_SOFTOKEN_DOES_RC5 - case CKM_RC5_CBC_PAD: - context->doPad = PR_TRUE; - /* fall thru */ - case CKM_RC5_ECB: - case CKM_RC5_CBC: - if (key_type != CKK_RC5) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - att = sftk_FindAttribute(key,CKA_VALUE); - if (att == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter; - context->blockSize = rc5_param->ulWordsize*2; - rc5Key.data = (unsigned char*)att->attrib.pValue; - rc5Key.len = att->attrib.ulValueLen; - context->cipherInfo = RC5_CreateContext(&rc5Key,rc5_param->ulRounds, - rc5_param->ulWordsize,rc5_param->pIv, - pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC); - sftk_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (SFTKCipher) (isEncrypt ? RC5_Encrypt : RC5_Decrypt); - context->destroy = (SFTKDestroy) RC5_DestroyContext; - break; + case CKM_RC5_CBC_PAD: + context->doPad = PR_TRUE; + /* fall thru */ + case CKM_RC5_ECB: + case CKM_RC5_CBC: + if (key_type != CKK_RC5) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + att = sftk_FindAttribute(key, CKA_VALUE); + if (att == NULL) { + crv = CKR_KEY_HANDLE_INVALID; + break; + } + rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter; + context->blockSize = rc5_param->ulWordsize * 2; + rc5Key.data = (unsigned char *)att->attrib.pValue; + rc5Key.len = att->attrib.ulValueLen; + context->cipherInfo = RC5_CreateContext(&rc5Key, rc5_param->ulRounds, + rc5_param->ulWordsize, rc5_param->pIv, + pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC); + sftk_FreeAttribute(att); + if (context->cipherInfo == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + context->update = (SFTKCipher)(isEncrypt ? RC5_Encrypt : RC5_Decrypt); + context->destroy = (SFTKDestroy)RC5_DestroyContext; + break; #endif - case CKM_RC4: - if (key_type != CKK_RC4) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - att = sftk_FindAttribute(key,CKA_VALUE); - if (att == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - context->cipherInfo = - RC4_CreateContext((unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen); - sftk_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; /* WRONG !!! */ - break; - } - context->update = (SFTKCipher) (isEncrypt ? RC4_Encrypt : RC4_Decrypt); - context->destroy = (SFTKDestroy) RC4_DestroyContext; - break; - case CKM_CDMF_CBC_PAD: - context->doPad = PR_TRUE; - /* fall thru */ - case CKM_CDMF_ECB: - case CKM_CDMF_CBC: - if (key_type != CKK_CDMF) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC; - if (crv != CKR_OK) break; - goto finish_des; - case CKM_DES_ECB: - if (key_type != CKK_DES) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - t = NSS_DES; - goto finish_des; - case CKM_DES_CBC_PAD: - context->doPad = PR_TRUE; - /* fall thru */ - case CKM_DES_CBC: - if (key_type != CKK_DES) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - t = NSS_DES_CBC; - goto finish_des; - case CKM_DES3_ECB: - if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - t = NSS_DES_EDE3; - goto finish_des; - case CKM_DES3_CBC_PAD: - context->doPad = PR_TRUE; - /* fall thru */ - case CKM_DES3_CBC: - if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - t = NSS_DES_EDE3_CBC; -finish_des: - context->blockSize = 8; - att = sftk_FindAttribute(key,CKA_VALUE); - if (att == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - if (key_type == CKK_DES2 && - (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) { - /* extend DES2 key to DES3 key. */ - memcpy(newdeskey, att->attrib.pValue, 16); - memcpy(newdeskey + 16, newdeskey, 8); - useNewKey=PR_TRUE; - } else if (key_type == CKK_CDMF) { - crv = sftk_cdmf2des((unsigned char*)att->attrib.pValue,newdeskey); - if (crv != CKR_OK) { - sftk_FreeAttribute(att); - break; - } - useNewKey=PR_TRUE; - } - context->cipherInfo = DES_CreateContext( - useNewKey ? newdeskey : (unsigned char*)att->attrib.pValue, - (unsigned char*)pMechanism->pParameter,t, isEncrypt); - if (useNewKey) - memset(newdeskey, 0, sizeof newdeskey); - sftk_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (SFTKCipher) (isEncrypt ? DES_Encrypt : DES_Decrypt); - context->destroy = (SFTKDestroy) DES_DestroyContext; - break; - case CKM_SEED_CBC_PAD: - context->doPad = PR_TRUE; - /* fall thru */ - case CKM_SEED_CBC: - if (!pMechanism->pParameter || - pMechanism->ulParameterLen != 16) { - crv = CKR_MECHANISM_PARAM_INVALID; + case CKM_RC4: + if (key_type != CKK_RC4) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + att = sftk_FindAttribute(key, CKA_VALUE); + if (att == NULL) { + crv = CKR_KEY_HANDLE_INVALID; + break; + } + context->cipherInfo = + RC4_CreateContext((unsigned char *)att->attrib.pValue, + att->attrib.ulValueLen); + sftk_FreeAttribute(att); + if (context->cipherInfo == NULL) { + crv = CKR_HOST_MEMORY; /* WRONG !!! */ + break; + } + context->update = (SFTKCipher)(isEncrypt ? RC4_Encrypt : RC4_Decrypt); + context->destroy = (SFTKDestroy)RC4_DestroyContext; break; - } + case CKM_CDMF_CBC_PAD: + context->doPad = PR_TRUE; /* fall thru */ - case CKM_SEED_ECB: - context->blockSize = 16; - if (key_type != CKK_SEED) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - att = sftk_FindAttribute(key,CKA_VALUE); - if (att == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - context->cipherInfo = SEED_CreateContext( - (unsigned char*)att->attrib.pValue, - (unsigned char*)pMechanism->pParameter, - pMechanism->mechanism == CKM_SEED_ECB ? NSS_SEED : NSS_SEED_CBC, - isEncrypt); - sftk_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (SFTKCipher)(isEncrypt ? SEED_Encrypt : SEED_Decrypt); - context->destroy = (SFTKDestroy) SEED_DestroyContext; - break; - - case CKM_CAMELLIA_CBC_PAD: - context->doPad = PR_TRUE; - /* fall thru */ - case CKM_CAMELLIA_CBC: - if (!pMechanism->pParameter || - pMechanism->ulParameterLen != 16) { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - /* fall thru */ - case CKM_CAMELLIA_ECB: - context->blockSize = 16; - if (key_type != CKK_CAMELLIA) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - att = sftk_FindAttribute(key,CKA_VALUE); - if (att == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - context->cipherInfo = Camellia_CreateContext( - (unsigned char*)att->attrib.pValue, - (unsigned char*)pMechanism->pParameter, - pMechanism->mechanism == - CKM_CAMELLIA_ECB ? NSS_CAMELLIA : NSS_CAMELLIA_CBC, - isEncrypt, att->attrib.ulValueLen); - sftk_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (SFTKCipher) (isEncrypt ? - Camellia_Encrypt : Camellia_Decrypt); - context->destroy = (SFTKDestroy) Camellia_DestroyContext; - break; - - case CKM_AES_CBC_PAD: - context->doPad = PR_TRUE; - /* fall thru */ - case CKM_AES_ECB: - case CKM_AES_CBC: - context->blockSize = 16; - case CKM_AES_CTS: - case CKM_AES_CTR: - case CKM_AES_GCM: - if (pMechanism->mechanism == CKM_AES_GCM) { - context->multi = PR_FALSE; - } - if (key_type != CKK_AES) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - att = sftk_FindAttribute(key,CKA_VALUE); - if (att == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - context->cipherInfo = AES_CreateContext( - (unsigned char*)att->attrib.pValue, - (unsigned char*)pMechanism->pParameter, - sftk_aes_mode(pMechanism->mechanism), - isEncrypt, att->attrib.ulValueLen, 16); - sftk_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (SFTKCipher) (isEncrypt ? AES_Encrypt : AES_Decrypt); - context->destroy = (SFTKDestroy) AES_DestroyContext; - break; - - case CKM_NETSCAPE_AES_KEY_WRAP_PAD: - context->doPad = PR_TRUE; - /* fall thru */ - case CKM_NETSCAPE_AES_KEY_WRAP: - context->multi = PR_FALSE; - context->blockSize = 8; - if (key_type != CKK_AES) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - att = sftk_FindAttribute(key,CKA_VALUE); - if (att == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - context->cipherInfo = AESKeyWrap_CreateContext( - (unsigned char*)att->attrib.pValue, - (unsigned char*)pMechanism->pParameter, - isEncrypt, att->attrib.ulValueLen); - sftk_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (SFTKCipher) (isEncrypt ? AESKeyWrap_Encrypt - : AESKeyWrap_Decrypt); - context->destroy = (SFTKDestroy) AESKeyWrap_DestroyContext; - break; - - default: - crv = CKR_MECHANISM_INVALID; - break; + case CKM_CDMF_ECB: + case CKM_CDMF_CBC: + if (key_type != CKK_CDMF) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC; + goto finish_des; + case CKM_DES_ECB: + if (key_type != CKK_DES) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + t = NSS_DES; + goto finish_des; + case CKM_DES_CBC_PAD: + context->doPad = PR_TRUE; + /* fall thru */ + case CKM_DES_CBC: + if (key_type != CKK_DES) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + t = NSS_DES_CBC; + goto finish_des; + case CKM_DES3_ECB: + if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + t = NSS_DES_EDE3; + goto finish_des; + case CKM_DES3_CBC_PAD: + context->doPad = PR_TRUE; + /* fall thru */ + case CKM_DES3_CBC: + if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + t = NSS_DES_EDE3_CBC; + finish_des: + context->blockSize = 8; + att = sftk_FindAttribute(key, CKA_VALUE); + if (att == NULL) { + crv = CKR_KEY_HANDLE_INVALID; + break; + } + if (key_type == CKK_DES2 && + (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) { + /* extend DES2 key to DES3 key. */ + memcpy(newdeskey, att->attrib.pValue, 16); + memcpy(newdeskey + 16, newdeskey, 8); + useNewKey = PR_TRUE; + } else if (key_type == CKK_CDMF) { + crv = sftk_cdmf2des((unsigned char *)att->attrib.pValue, newdeskey); + if (crv != CKR_OK) { + sftk_FreeAttribute(att); + break; + } + useNewKey = PR_TRUE; + } + context->cipherInfo = DES_CreateContext( + useNewKey ? newdeskey : (unsigned char *)att->attrib.pValue, + (unsigned char *)pMechanism->pParameter, t, isEncrypt); + if (useNewKey) + memset(newdeskey, 0, sizeof newdeskey); + sftk_FreeAttribute(att); + if (context->cipherInfo == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + context->update = (SFTKCipher)(isEncrypt ? DES_Encrypt : DES_Decrypt); + context->destroy = (SFTKDestroy)DES_DestroyContext; + break; + case CKM_SEED_CBC_PAD: + context->doPad = PR_TRUE; + /* fall thru */ + case CKM_SEED_CBC: + if (!pMechanism->pParameter || + pMechanism->ulParameterLen != 16) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + /* fall thru */ + case CKM_SEED_ECB: + context->blockSize = 16; + if (key_type != CKK_SEED) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + att = sftk_FindAttribute(key, CKA_VALUE); + if (att == NULL) { + crv = CKR_KEY_HANDLE_INVALID; + break; + } + context->cipherInfo = SEED_CreateContext( + (unsigned char *)att->attrib.pValue, + (unsigned char *)pMechanism->pParameter, + pMechanism->mechanism == CKM_SEED_ECB ? NSS_SEED : NSS_SEED_CBC, + isEncrypt); + sftk_FreeAttribute(att); + if (context->cipherInfo == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + context->update = (SFTKCipher)(isEncrypt ? SEED_Encrypt : SEED_Decrypt); + context->destroy = (SFTKDestroy)SEED_DestroyContext; + break; + + case CKM_CAMELLIA_CBC_PAD: + context->doPad = PR_TRUE; + /* fall thru */ + case CKM_CAMELLIA_CBC: + if (!pMechanism->pParameter || + pMechanism->ulParameterLen != 16) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + /* fall thru */ + case CKM_CAMELLIA_ECB: + context->blockSize = 16; + if (key_type != CKK_CAMELLIA) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + att = sftk_FindAttribute(key, CKA_VALUE); + if (att == NULL) { + crv = CKR_KEY_HANDLE_INVALID; + break; + } + context->cipherInfo = Camellia_CreateContext( + (unsigned char *)att->attrib.pValue, + (unsigned char *)pMechanism->pParameter, + pMechanism->mechanism == + CKM_CAMELLIA_ECB + ? NSS_CAMELLIA + : NSS_CAMELLIA_CBC, + isEncrypt, att->attrib.ulValueLen); + sftk_FreeAttribute(att); + if (context->cipherInfo == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + context->update = (SFTKCipher)(isEncrypt ? Camellia_Encrypt : Camellia_Decrypt); + context->destroy = (SFTKDestroy)Camellia_DestroyContext; + break; + + case CKM_AES_CBC_PAD: + context->doPad = PR_TRUE; + /* fall thru */ + case CKM_AES_ECB: + case CKM_AES_CBC: + context->blockSize = 16; + case CKM_AES_CTS: + case CKM_AES_CTR: + case CKM_AES_GCM: + if (pMechanism->mechanism == CKM_AES_GCM) { + context->multi = PR_FALSE; + } + if (key_type != CKK_AES) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + att = sftk_FindAttribute(key, CKA_VALUE); + if (att == NULL) { + crv = CKR_KEY_HANDLE_INVALID; + break; + } + context->cipherInfo = AES_CreateContext( + (unsigned char *)att->attrib.pValue, + (unsigned char *)pMechanism->pParameter, + sftk_aes_mode(pMechanism->mechanism), + isEncrypt, att->attrib.ulValueLen, 16); + sftk_FreeAttribute(att); + if (context->cipherInfo == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + context->update = (SFTKCipher)(isEncrypt ? AES_Encrypt : AES_Decrypt); + context->destroy = (SFTKDestroy)AES_DestroyContext; + break; + + case CKM_NSS_CHACHA20_POLY1305: + if (pMechanism->ulParameterLen != sizeof(CK_NSS_AEAD_PARAMS)) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + context->multi = PR_FALSE; + if (key_type != CKK_NSS_CHACHA20) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + att = sftk_FindAttribute(key, CKA_VALUE); + if (att == NULL) { + crv = CKR_KEY_HANDLE_INVALID; + break; + } + context->cipherInfo = sftk_ChaCha20Poly1305_CreateContext( + (unsigned char *)att->attrib.pValue, att->attrib.ulValueLen, + (CK_NSS_AEAD_PARAMS *)pMechanism->pParameter); + sftk_FreeAttribute(att); + if (context->cipherInfo == NULL) { + crv = sftk_MapCryptError(PORT_GetError()); + break; + } + context->update = (SFTKCipher)(isEncrypt ? sftk_ChaCha20Poly1305_Encrypt : sftk_ChaCha20Poly1305_Decrypt); + context->destroy = (SFTKDestroy)sftk_ChaCha20Poly1305_DestroyContext; + break; + + case CKM_NSS_AES_KEY_WRAP_PAD: + context->doPad = PR_TRUE; + /* fall thru */ + case CKM_NSS_AES_KEY_WRAP: + context->multi = PR_FALSE; + context->blockSize = 8; + if (key_type != CKK_AES) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + att = sftk_FindAttribute(key, CKA_VALUE); + if (att == NULL) { + crv = CKR_KEY_HANDLE_INVALID; + break; + } + context->cipherInfo = AESKeyWrap_CreateContext( + (unsigned char *)att->attrib.pValue, + (unsigned char *)pMechanism->pParameter, + isEncrypt, att->attrib.ulValueLen); + sftk_FreeAttribute(att); + if (context->cipherInfo == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + context->update = (SFTKCipher)(isEncrypt ? AESKeyWrap_Encrypt + : AESKeyWrap_Decrypt); + context->destroy = (SFTKDestroy)AESKeyWrap_DestroyContext; + break; + + default: + crv = CKR_MECHANISM_INVALID; + break; } if (crv != CKR_OK) { sftk_FreeContext(context); - sftk_FreeSession(session); - return crv; + sftk_FreeSession(session); + return crv; } sftk_SetContextByType(session, contextType, context); sftk_FreeSession(session); @@ -1102,21 +1228,23 @@ finish_des: } /* NSC_EncryptInit initializes an encryption operation. */ -CK_RV NSC_EncryptInit(CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) +CK_RV +NSC_EncryptInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CHECK_FORK(); return sftk_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, CKA_ENCRYPT, - SFTK_ENCRYPT, PR_TRUE); + SFTK_ENCRYPT, PR_TRUE); } /* NSC_EncryptUpdate continues a multiple-part encryption operation. */ -CK_RV NSC_EncryptUpdate(CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, - CK_ULONG_PTR pulEncryptedPartLen) +CK_RV +NSC_EncryptUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen) { SFTKSessionContext *context; - unsigned int outlen,i; + unsigned int outlen, i; unsigned int padoutlen = 0; unsigned int maxout = *pulEncryptedPartLen; CK_RV crv; @@ -1125,79 +1253,79 @@ CK_RV NSC_EncryptUpdate(CK_SESSION_HANDLE hSession, CHECK_FORK(); /* make sure we're legal */ - crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_TRUE,NULL); - if (crv != CKR_OK) return crv; + crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, NULL); + if (crv != CKR_OK) + return crv; if (!pEncryptedPart) { - if (context->doPad) { - CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength; - CK_ULONG blocksToSend = totalDataAvailable/context->blockSize; + if (context->doPad) { + CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength; + CK_ULONG blocksToSend = totalDataAvailable / context->blockSize; - *pulEncryptedPartLen = blocksToSend * context->blockSize; - return CKR_OK; - } - *pulEncryptedPartLen = ulPartLen; - return CKR_OK; + *pulEncryptedPartLen = blocksToSend * context->blockSize; + return CKR_OK; + } + *pulEncryptedPartLen = ulPartLen; + return CKR_OK; } /* do padding */ if (context->doPad) { - /* deal with previous buffered data */ - if (context->padDataLength != 0) { - /* fill in the padded to a full block size */ - for (i=context->padDataLength; - (ulPartLen != 0) && i < context->blockSize; i++) { - context->padBuf[i] = *pPart++; - ulPartLen--; - context->padDataLength++; - } - - /* not enough data to encrypt yet? then return */ - if (context->padDataLength != context->blockSize) { - *pulEncryptedPartLen = 0; - return CKR_OK; - } - /* encrypt the current padded data */ - rv = (*context->update)(context->cipherInfo, pEncryptedPart, - &padoutlen, context->blockSize, context->padBuf, - context->blockSize); - if (rv != SECSuccess) { - return sftk_MapCryptError(PORT_GetError()); - } - pEncryptedPart += padoutlen; - maxout -= padoutlen; - } - /* save the residual */ - context->padDataLength = ulPartLen % context->blockSize; - if (context->padDataLength) { - PORT_Memcpy(context->padBuf, - &pPart[ulPartLen-context->padDataLength], - context->padDataLength); - ulPartLen -= context->padDataLength; - } - /* if we've exhausted our new buffer, we're done */ - if (ulPartLen == 0) { - *pulEncryptedPartLen = padoutlen; - return CKR_OK; - } - } + /* deal with previous buffered data */ + if (context->padDataLength != 0) { + /* fill in the padded to a full block size */ + for (i = context->padDataLength; + (ulPartLen != 0) && i < context->blockSize; i++) { + context->padBuf[i] = *pPart++; + ulPartLen--; + context->padDataLength++; + } + /* not enough data to encrypt yet? then return */ + if (context->padDataLength != context->blockSize) { + *pulEncryptedPartLen = 0; + return CKR_OK; + } + /* encrypt the current padded data */ + rv = (*context->update)(context->cipherInfo, pEncryptedPart, + &padoutlen, context->blockSize, context->padBuf, + context->blockSize); + if (rv != SECSuccess) { + return sftk_MapCryptError(PORT_GetError()); + } + pEncryptedPart += padoutlen; + maxout -= padoutlen; + } + /* save the residual */ + context->padDataLength = ulPartLen % context->blockSize; + if (context->padDataLength) { + PORT_Memcpy(context->padBuf, + &pPart[ulPartLen - context->padDataLength], + context->padDataLength); + ulPartLen -= context->padDataLength; + } + /* if we've exhausted our new buffer, we're done */ + if (ulPartLen == 0) { + *pulEncryptedPartLen = padoutlen; + return CKR_OK; + } + } /* do it: NOTE: this assumes buf size in is >= buf size out! */ - rv = (*context->update)(context->cipherInfo,pEncryptedPart, - &outlen, maxout, pPart, ulPartLen); - *pulEncryptedPartLen = (CK_ULONG) (outlen + padoutlen); + rv = (*context->update)(context->cipherInfo, pEncryptedPart, + &outlen, maxout, pPart, ulPartLen); + *pulEncryptedPartLen = (CK_ULONG)(outlen + padoutlen); return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); } - /* NSC_EncryptFinal finishes a multiple-part encryption operation. */ -CK_RV NSC_EncryptFinal(CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) +CK_RV +NSC_EncryptFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) { SFTKSession *session; SFTKSessionContext *context; - unsigned int outlen,i; + unsigned int outlen, i; unsigned int maxout = *pulLastEncryptedPartLen; CK_RV crv; SECStatus rv = SECSuccess; @@ -1206,43 +1334,45 @@ CK_RV NSC_EncryptFinal(CK_SESSION_HANDLE hSession, CHECK_FORK(); /* make sure we're legal */ - crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_TRUE,&session); - if (crv != CKR_OK) return crv; + crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, &session); + if (crv != CKR_OK) + return crv; *pulLastEncryptedPartLen = 0; if (!pLastEncryptedPart) { - /* caller is checking the amount of remaining data */ - if (context->blockSize > 0 && context->doPad) { - *pulLastEncryptedPartLen = context->blockSize; - contextFinished = PR_FALSE; /* still have padding to go */ - } - goto finish; + /* caller is checking the amount of remaining data */ + if (context->blockSize > 0 && context->doPad) { + *pulLastEncryptedPartLen = context->blockSize; + contextFinished = PR_FALSE; /* still have padding to go */ + } + goto finish; } /* do padding */ if (context->doPad) { - unsigned char padbyte = (unsigned char) - (context->blockSize - context->padDataLength); - /* fill out rest of pad buffer with pad magic*/ - for (i=context->padDataLength; i < context->blockSize; i++) { - context->padBuf[i] = padbyte; - } - rv = (*context->update)(context->cipherInfo,pLastEncryptedPart, - &outlen, maxout, context->padBuf, context->blockSize); - if (rv == SECSuccess) *pulLastEncryptedPartLen = (CK_ULONG) outlen; + unsigned char padbyte = (unsigned char)(context->blockSize - context->padDataLength); + /* fill out rest of pad buffer with pad magic*/ + for (i = context->padDataLength; i < context->blockSize; i++) { + context->padBuf[i] = padbyte; + } + rv = (*context->update)(context->cipherInfo, pLastEncryptedPart, + &outlen, maxout, context->padBuf, context->blockSize); + if (rv == SECSuccess) + *pulLastEncryptedPartLen = (CK_ULONG)outlen; } finish: if (contextFinished) - sftk_TerminateOp( session, SFTK_ENCRYPT, context ); + sftk_TerminateOp(session, SFTK_ENCRYPT, context); sftk_FreeSession(session); return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); } /* NSC_Encrypt encrypts single-part data. */ -CK_RV NSC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, - CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, - CK_ULONG_PTR pulEncryptedDataLen) +CK_RV +NSC_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, + CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, + CK_ULONG_PTR pulEncryptedDataLen) { SFTKSession *session; SFTKSessionContext *context; @@ -1251,94 +1381,95 @@ CK_RV NSC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_RV crv; CK_RV crv2; SECStatus rv = SECSuccess; - SECItem pText; + SECItem pText; pText.type = siBuffer; pText.data = pData; - pText.len = ulDataLen; + pText.len = ulDataLen; CHECK_FORK(); /* make sure we're legal */ - crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_FALSE,&session); - if (crv != CKR_OK) return crv; + crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, &session); + if (crv != CKR_OK) + return crv; if (!pEncryptedData) { - *pulEncryptedDataLen = context->rsa ? context->maxLen : - ulDataLen + 2 * context->blockSize; - goto finish; + *pulEncryptedDataLen = context->rsa ? context->maxLen : ulDataLen + 2 * context->blockSize; + goto finish; } if (context->doPad) { - if (context->multi) { - CK_ULONG finalLen; - /* padding is fairly complicated, have the update and final - * code deal with it */ - sftk_FreeSession(session); - crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData, - pulEncryptedDataLen); - if (crv != CKR_OK) - *pulEncryptedDataLen = 0; - maxoutlen -= *pulEncryptedDataLen; - pEncryptedData += *pulEncryptedDataLen; - finalLen = maxoutlen; - crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen); - if (crv2 == CKR_OK) - *pulEncryptedDataLen += finalLen; - return crv == CKR_OK ? crv2 : crv; - } - /* doPad without multi means that padding must be done on the first - ** and only update. There will be no final. - */ - PORT_Assert(context->blockSize > 1); - if (context->blockSize > 1) { - CK_ULONG remainder = ulDataLen % context->blockSize; - CK_ULONG padding = context->blockSize - remainder; - pText.len += padding; - pText.data = PORT_ZAlloc(pText.len); - if (pText.data) { - memcpy(pText.data, pData, ulDataLen); - memset(pText.data + ulDataLen, padding, padding); - } else { - crv = CKR_HOST_MEMORY; - goto fail; - } - } + if (context->multi) { + CK_ULONG finalLen; + /* padding is fairly complicated, have the update and final + * code deal with it */ + sftk_FreeSession(session); + crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData, + pulEncryptedDataLen); + if (crv != CKR_OK) + *pulEncryptedDataLen = 0; + maxoutlen -= *pulEncryptedDataLen; + pEncryptedData += *pulEncryptedDataLen; + finalLen = maxoutlen; + crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen); + if (crv2 == CKR_OK) + *pulEncryptedDataLen += finalLen; + return crv == CKR_OK ? crv2 : crv; + } + /* doPad without multi means that padding must be done on the first + ** and only update. There will be no final. + */ + PORT_Assert(context->blockSize > 1); + if (context->blockSize > 1) { + CK_ULONG remainder = ulDataLen % context->blockSize; + CK_ULONG padding = context->blockSize - remainder; + pText.len += padding; + pText.data = PORT_ZAlloc(pText.len); + if (pText.data) { + memcpy(pText.data, pData, ulDataLen); + memset(pText.data + ulDataLen, padding, padding); + } else { + crv = CKR_HOST_MEMORY; + goto fail; + } + } } /* do it: NOTE: this assumes buf size is big enough. */ - rv = (*context->update)(context->cipherInfo, pEncryptedData, - &outlen, maxoutlen, pText.data, pText.len); + rv = (*context->update)(context->cipherInfo, pEncryptedData, + &outlen, maxoutlen, pText.data, pText.len); crv = (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError()); - *pulEncryptedDataLen = (CK_ULONG) outlen; + *pulEncryptedDataLen = (CK_ULONG)outlen; if (pText.data != pData) - PORT_ZFree(pText.data, pText.len); + PORT_ZFree(pText.data, pText.len); fail: - sftk_TerminateOp( session, SFTK_ENCRYPT, context ); + sftk_TerminateOp(session, SFTK_ENCRYPT, context); finish: sftk_FreeSession(session); return crv; } - /* ************** Crypto Functions: Decrypt ************************ */ /* NSC_DecryptInit initializes a decryption operation. */ -CK_RV NSC_DecryptInit( CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) +CK_RV +NSC_DecryptInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CHECK_FORK(); return sftk_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, CKA_DECRYPT, - SFTK_DECRYPT, PR_FALSE); + SFTK_DECRYPT, PR_FALSE); } /* NSC_DecryptUpdate continues a multiple-part decryption operation. */ -CK_RV NSC_DecryptUpdate(CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, - CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) +CK_RV +NSC_DecryptUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { SFTKSessionContext *context; unsigned int padoutlen = 0; @@ -1350,69 +1481,70 @@ CK_RV NSC_DecryptUpdate(CK_SESSION_HANDLE hSession, CHECK_FORK(); /* make sure we're legal */ - crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_TRUE,NULL); - if (crv != CKR_OK) return crv; + crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, NULL); + if (crv != CKR_OK) + return crv; /* this can only happen on an NSS programming error */ - PORT_Assert((context->padDataLength == 0) - || context->padDataLength == context->blockSize); - + PORT_Assert((context->padDataLength == 0) || context->padDataLength == context->blockSize); if (context->doPad) { - /* Check the data length for block ciphers. If we are padding, - * then we must be using a block cipher. In the non-padding case - * the error will be returned by the underlying decryption - * function when we do the actual decrypt. We need to do the - * check here to avoid returning a negative length to the caller - * or reading before the beginning of the pEncryptedPart buffer. - */ - if ((ulEncryptedPartLen == 0) || - (ulEncryptedPartLen % context->blockSize) != 0) { - return CKR_ENCRYPTED_DATA_LEN_RANGE; - } + /* Check the data length for block ciphers. If we are padding, + * then we must be using a block cipher. In the non-padding case + * the error will be returned by the underlying decryption + * function when we do the actual decrypt. We need to do the + * check here to avoid returning a negative length to the caller + * or reading before the beginning of the pEncryptedPart buffer. + */ + if ((ulEncryptedPartLen == 0) || + (ulEncryptedPartLen % context->blockSize) != 0) { + return CKR_ENCRYPTED_DATA_LEN_RANGE; + } } if (!pPart) { - if (context->doPad) { - *pulPartLen = - ulEncryptedPartLen + context->padDataLength - context->blockSize; - return CKR_OK; - } - /* for stream ciphers there is are no constraints on ulEncryptedPartLen. - * for block ciphers, it must be a multiple of blockSize. The error is - * detected when this function is called again do decrypt the output. - */ - *pulPartLen = ulEncryptedPartLen; - return CKR_OK; + if (context->doPad) { + *pulPartLen = + ulEncryptedPartLen + context->padDataLength - context->blockSize; + return CKR_OK; + } + /* for stream ciphers there is are no constraints on ulEncryptedPartLen. + * for block ciphers, it must be a multiple of blockSize. The error is + * detected when this function is called again do decrypt the output. + */ + *pulPartLen = ulEncryptedPartLen; + return CKR_OK; } if (context->doPad) { - /* first decrypt our saved buffer */ - if (context->padDataLength != 0) { - rv = (*context->update)(context->cipherInfo, pPart, &padoutlen, - maxout, context->padBuf, context->blockSize); - if (rv != SECSuccess) return sftk_MapDecryptError(PORT_GetError()); - pPart += padoutlen; - maxout -= padoutlen; - } - /* now save the final block for the next decrypt or the final */ - PORT_Memcpy(context->padBuf,&pEncryptedPart[ulEncryptedPartLen - - context->blockSize], context->blockSize); - context->padDataLength = context->blockSize; - ulEncryptedPartLen -= context->padDataLength; + /* first decrypt our saved buffer */ + if (context->padDataLength != 0) { + rv = (*context->update)(context->cipherInfo, pPart, &padoutlen, + maxout, context->padBuf, context->blockSize); + if (rv != SECSuccess) + return sftk_MapDecryptError(PORT_GetError()); + pPart += padoutlen; + maxout -= padoutlen; + } + /* now save the final block for the next decrypt or the final */ + PORT_Memcpy(context->padBuf, &pEncryptedPart[ulEncryptedPartLen - + context->blockSize], + context->blockSize); + context->padDataLength = context->blockSize; + ulEncryptedPartLen -= context->padDataLength; } /* do it: NOTE: this assumes buf size in is >= buf size out! */ - rv = (*context->update)(context->cipherInfo,pPart, &outlen, - maxout, pEncryptedPart, ulEncryptedPartLen); - *pulPartLen = (CK_ULONG) (outlen + padoutlen); - return (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError()); + rv = (*context->update)(context->cipherInfo, pPart, &outlen, + maxout, pEncryptedPart, ulEncryptedPartLen); + *pulPartLen = (CK_ULONG)(outlen + padoutlen); + return (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError()); } - /* NSC_DecryptFinal finishes a multiple-part decryption operation. */ -CK_RV NSC_DecryptFinal(CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen) +CK_RV +NSC_DecryptFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen) { SFTKSession *session; SFTKSessionContext *context; @@ -1424,60 +1556,62 @@ CK_RV NSC_DecryptFinal(CK_SESSION_HANDLE hSession, CHECK_FORK(); /* make sure we're legal */ - crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_TRUE,&session); - if (crv != CKR_OK) return crv; + crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, &session); + if (crv != CKR_OK) + return crv; *pulLastPartLen = 0; if (!pLastPart) { - /* caller is checking the amount of remaining data */ - if (context->padDataLength > 0) { - *pulLastPartLen = context->padDataLength; - } - goto finish; + /* caller is checking the amount of remaining data */ + if (context->padDataLength > 0) { + *pulLastPartLen = context->padDataLength; + } + goto finish; } if (context->doPad) { - /* decrypt our saved buffer */ - if (context->padDataLength != 0) { - /* this assumes that pLastPart is big enough to hold the *whole* - * buffer!!! */ - rv = (*context->update)(context->cipherInfo, pLastPart, &outlen, - maxout, context->padBuf, context->blockSize); - if (rv != SECSuccess) { - crv = sftk_MapDecryptError(PORT_GetError()); - } else { - unsigned int padSize = - (unsigned int) pLastPart[context->blockSize-1]; - if ((padSize > context->blockSize) || (padSize == 0)) { - crv = CKR_ENCRYPTED_DATA_INVALID; - } else { - unsigned int i; - unsigned int badPadding = 0; /* used as a boolean */ - for (i = 0; i < padSize; i++) { - badPadding |= - (unsigned int) pLastPart[context->blockSize-1-i] ^ - padSize; - } - if (badPadding) { - crv = CKR_ENCRYPTED_DATA_INVALID; - } else { - *pulLastPartLen = outlen - padSize; - } - } - } - } - } - - sftk_TerminateOp( session, SFTK_DECRYPT, context ); + /* decrypt our saved buffer */ + if (context->padDataLength != 0) { + /* this assumes that pLastPart is big enough to hold the *whole* + * buffer!!! */ + rv = (*context->update)(context->cipherInfo, pLastPart, &outlen, + maxout, context->padBuf, context->blockSize); + if (rv != SECSuccess) { + crv = sftk_MapDecryptError(PORT_GetError()); + } else { + unsigned int padSize = + (unsigned int)pLastPart[context->blockSize - 1]; + if ((padSize > context->blockSize) || (padSize == 0)) { + crv = CKR_ENCRYPTED_DATA_INVALID; + } else { + unsigned int i; + unsigned int badPadding = 0; /* used as a boolean */ + for (i = 0; i < padSize; i++) { + badPadding |= + (unsigned int)pLastPart[context->blockSize - 1 - i] ^ + padSize; + } + if (badPadding) { + crv = CKR_ENCRYPTED_DATA_INVALID; + } else { + *pulLastPartLen = outlen - padSize; + } + } + } + } + } + + sftk_TerminateOp(session, SFTK_DECRYPT, context); finish: sftk_FreeSession(session); return crv; } /* NSC_Decrypt decrypts encrypted data in a single part. */ -CK_RV NSC_Decrypt(CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData, - CK_ULONG_PTR pulDataLen) +CK_RV +NSC_Decrypt(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, + CK_ULONG_PTR pulDataLen) { SFTKSession *session; SFTKSessionContext *context; @@ -1490,69 +1624,69 @@ CK_RV NSC_Decrypt(CK_SESSION_HANDLE hSession, CHECK_FORK(); /* make sure we're legal */ - crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_FALSE,&session); - if (crv != CKR_OK) return crv; + crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_FALSE, &session); + if (crv != CKR_OK) + return crv; if (!pData) { - *pulDataLen = ulEncryptedDataLen + context->blockSize; - goto finish; + *pulDataLen = ulEncryptedDataLen + context->blockSize; + goto finish; } if (context->doPad && context->multi) { - CK_ULONG finalLen; - /* padding is fairly complicated, have the update and final - * code deal with it */ - sftk_FreeSession(session); - crv = NSC_DecryptUpdate(hSession,pEncryptedData,ulEncryptedDataLen, - pData, pulDataLen); - if (crv != CKR_OK) - *pulDataLen = 0; - maxoutlen -= *pulDataLen; - pData += *pulDataLen; - finalLen = maxoutlen; - crv2 = NSC_DecryptFinal(hSession, pData, &finalLen); - if (crv2 == CKR_OK) - *pulDataLen += finalLen; - return crv == CKR_OK ? crv2 : crv; - } - - rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, - pEncryptedData, ulEncryptedDataLen); + CK_ULONG finalLen; + /* padding is fairly complicated, have the update and final + * code deal with it */ + sftk_FreeSession(session); + crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen, + pData, pulDataLen); + if (crv != CKR_OK) + *pulDataLen = 0; + maxoutlen -= *pulDataLen; + pData += *pulDataLen; + finalLen = maxoutlen; + crv2 = NSC_DecryptFinal(hSession, pData, &finalLen); + if (crv2 == CKR_OK) + *pulDataLen += finalLen; + return crv == CKR_OK ? crv2 : crv; + } + + rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, + pEncryptedData, ulEncryptedDataLen); /* XXX need to do MUCH better error mapping than this. */ crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError()); if (rv == SECSuccess && context->doPad) { - unsigned int padding = pData[outlen - 1]; - if (padding > context->blockSize || !padding) { - crv = CKR_ENCRYPTED_DATA_INVALID; - } else { - unsigned int i; - unsigned int badPadding = 0; /* used as a boolean */ - for (i = 0; i < padding; i++) { - badPadding |= (unsigned int) pData[outlen - 1 - i] ^ padding; - } - if (badPadding) { - crv = CKR_ENCRYPTED_DATA_INVALID; - } else { - outlen -= padding; - } - } - } - *pulDataLen = (CK_ULONG) outlen; - sftk_TerminateOp( session, SFTK_DECRYPT, context ); + unsigned int padding = pData[outlen - 1]; + if (padding > context->blockSize || !padding) { + crv = CKR_ENCRYPTED_DATA_INVALID; + } else { + unsigned int i; + unsigned int badPadding = 0; /* used as a boolean */ + for (i = 0; i < padding; i++) { + badPadding |= (unsigned int)pData[outlen - 1 - i] ^ padding; + } + if (badPadding) { + crv = CKR_ENCRYPTED_DATA_INVALID; + } else { + outlen -= padding; + } + } + } + *pulDataLen = (CK_ULONG)outlen; + sftk_TerminateOp(session, SFTK_DECRYPT, context); finish: sftk_FreeSession(session); return crv; } - - /* ************** Crypto Functions: Digest (HASH) ************************ */ /* NSC_DigestInit initializes a message-digesting operation. */ -CK_RV NSC_DigestInit(CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism) +CK_RV +NSC_DigestInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism) { SFTKSession *session; SFTKSessionContext *context; @@ -1561,61 +1695,60 @@ CK_RV NSC_DigestInit(CK_SESSION_HANDLE hSession, CHECK_FORK(); session = sftk_SessionFromHandle(hSession); - if (session == NULL) - return CKR_SESSION_HANDLE_INVALID; - crv = sftk_InitGeneric(session,&context,SFTK_HASH,NULL,0,NULL, 0, 0); + if (session == NULL) + return CKR_SESSION_HANDLE_INVALID; + crv = sftk_InitGeneric(session, &context, SFTK_HASH, NULL, 0, NULL, 0, 0); if (crv != CKR_OK) { - sftk_FreeSession(session); - return crv; - } - - -#define INIT_MECH(mech,mmm) \ - case mech: { \ - mmm ## Context * mmm ## _ctx = mmm ## _NewContext(); \ - context->cipherInfo = (void *)mmm ## _ctx; \ - context->cipherInfoLen = mmm ## _FlattenSize(mmm ## _ctx); \ - context->currentMech = mech; \ - context->hashUpdate = (SFTKHash) mmm ## _Update; \ - context->end = (SFTKEnd) mmm ## _End; \ - context->destroy = (SFTKDestroy) mmm ## _DestroyContext; \ - context->maxLen = mmm ## _LENGTH; \ - if (mmm ## _ctx) \ - mmm ## _Begin(mmm ## _ctx); \ - else \ - crv = CKR_HOST_MEMORY; \ - break; \ - } - - switch(pMechanism->mechanism) { - INIT_MECH(CKM_MD2, MD2) - INIT_MECH(CKM_MD5, MD5) - INIT_MECH(CKM_SHA_1, SHA1) - INIT_MECH(CKM_SHA224, SHA224) - INIT_MECH(CKM_SHA256, SHA256) - INIT_MECH(CKM_SHA384, SHA384) - INIT_MECH(CKM_SHA512, SHA512) - - default: - crv = CKR_MECHANISM_INVALID; - break; + sftk_FreeSession(session); + return crv; + } + +#define INIT_MECH(mech, mmm) \ + case mech: { \ + mmm##Context *mmm##_ctx = mmm##_NewContext(); \ + context->cipherInfo = (void *)mmm##_ctx; \ + context->cipherInfoLen = mmm##_FlattenSize(mmm##_ctx); \ + context->currentMech = mech; \ + context->hashUpdate = (SFTKHash)mmm##_Update; \ + context->end = (SFTKEnd)mmm##_End; \ + context->destroy = (SFTKDestroy)mmm##_DestroyContext; \ + context->maxLen = mmm##_LENGTH; \ + if (mmm##_ctx) \ + mmm##_Begin(mmm##_ctx); \ + else \ + crv = CKR_HOST_MEMORY; \ + break; \ + } + + switch (pMechanism->mechanism) { + INIT_MECH(CKM_MD2, MD2) + INIT_MECH(CKM_MD5, MD5) + INIT_MECH(CKM_SHA_1, SHA1) + INIT_MECH(CKM_SHA224, SHA224) + INIT_MECH(CKM_SHA256, SHA256) + INIT_MECH(CKM_SHA384, SHA384) + INIT_MECH(CKM_SHA512, SHA512) + + default: + crv = CKR_MECHANISM_INVALID; + break; } if (crv != CKR_OK) { sftk_FreeContext(context); - sftk_FreeSession(session); - return crv; + sftk_FreeSession(session); + return crv; } sftk_SetContextByType(session, SFTK_HASH, context); sftk_FreeSession(session); return CKR_OK; } - /* NSC_Digest digests data in a single part. */ -CK_RV NSC_Digest(CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, - CK_ULONG_PTR pulDigestLen) +CK_RV +NSC_Digest(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, + CK_ULONG_PTR pulDigestLen) { SFTKSession *session; SFTKSessionContext *context; @@ -1626,30 +1759,31 @@ CK_RV NSC_Digest(CK_SESSION_HANDLE hSession, CHECK_FORK(); /* make sure we're legal */ - crv = sftk_GetContext(hSession,&context,SFTK_HASH,PR_FALSE,&session); - if (crv != CKR_OK) return crv; + crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_FALSE, &session); + if (crv != CKR_OK) + return crv; if (pDigest == NULL) { - *pulDigestLen = context->maxLen; - goto finish; + *pulDigestLen = context->maxLen; + goto finish; } /* do it: */ (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen); /* NOTE: this assumes buf size is bigenough for the algorithm */ - (*context->end)(context->cipherInfo, pDigest, &digestLen,maxout); + (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout); *pulDigestLen = digestLen; - sftk_TerminateOp( session, SFTK_HASH, context ); + sftk_TerminateOp(session, SFTK_HASH, context); finish: sftk_FreeSession(session); return CKR_OK; } - /* NSC_DigestUpdate continues a multiple-part message-digesting operation. */ -CK_RV NSC_DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart, - CK_ULONG ulPartLen) +CK_RV +NSC_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, + CK_ULONG ulPartLen) { SFTKSessionContext *context; CK_RV crv; @@ -1657,17 +1791,18 @@ CK_RV NSC_DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart, CHECK_FORK(); /* make sure we're legal */ - crv = sftk_GetContext(hSession,&context,SFTK_HASH,PR_TRUE,NULL); - if (crv != CKR_OK) return crv; + crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, NULL); + if (crv != CKR_OK) + return crv; /* do it: */ (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen); return CKR_OK; } - /* NSC_DigestFinal finishes a multiple-part message-digesting operation. */ -CK_RV NSC_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest, - CK_ULONG_PTR pulDigestLen) +CK_RV +NSC_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, + CK_ULONG_PTR pulDigestLen) { SFTKSession *session; SFTKSessionContext *context; @@ -1679,14 +1814,15 @@ CK_RV NSC_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest, /* make sure we're legal */ crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session); - if (crv != CKR_OK) return crv; + if (crv != CKR_OK) + return crv; if (pDigest != NULL) { (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout); *pulDigestLen = digestLen; - sftk_TerminateOp( session, SFTK_HASH, context ); + sftk_TerminateOp(session, SFTK_HASH, context); } else { - *pulDigestLen = context->maxLen; + *pulDigestLen = context->maxLen; } sftk_FreeSession(session); @@ -1695,22 +1831,23 @@ CK_RV NSC_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest, /* * these helper functions are used by Generic Macing and Signing functions - * that use hashes as part of their operations. + * that use hashes as part of their operations. */ -#define DOSUB(mmm) \ -static CK_RV \ -sftk_doSub ## mmm(SFTKSessionContext *context) { \ - mmm ## Context * mmm ## _ctx = mmm ## _NewContext(); \ - context->hashInfo = (void *) mmm ## _ctx; \ - context->hashUpdate = (SFTKHash) mmm ## _Update; \ - context->end = (SFTKEnd) mmm ## _End; \ - context->hashdestroy = (SFTKDestroy) mmm ## _DestroyContext; \ - if (!context->hashInfo) { \ - return CKR_HOST_MEMORY; \ - } \ - mmm ## _Begin( mmm ## _ctx ); \ - return CKR_OK; \ -} +#define DOSUB(mmm) \ + static CK_RV \ + sftk_doSub##mmm(SFTKSessionContext *context) \ + { \ + mmm##Context *mmm##_ctx = mmm##_NewContext(); \ + context->hashInfo = (void *)mmm##_ctx; \ + context->hashUpdate = (SFTKHash)mmm##_Update; \ + context->end = (SFTKEnd)mmm##_End; \ + context->hashdestroy = (SFTKDestroy)mmm##_DestroyContext; \ + if (!context->hashInfo) { \ + return CKR_HOST_MEMORY; \ + } \ + mmm##_Begin(mmm##_ctx); \ + return CKR_OK; \ + } DOSUB(MD2) DOSUB(MD5) @@ -1722,40 +1859,40 @@ DOSUB(SHA512) static SECStatus sftk_SignCopy( - CK_ULONG *copyLen, - void *out, unsigned int *outLength, - unsigned int maxLength, - const unsigned char *hashResult, - unsigned int hashResultLength) + CK_ULONG *copyLen, + void *out, unsigned int *outLength, + unsigned int maxLength, + const unsigned char *hashResult, + unsigned int hashResultLength) { unsigned int toCopy = *copyLen; if (toCopy > maxLength) { - toCopy = maxLength; + toCopy = maxLength; } if (toCopy > hashResultLength) { - toCopy = hashResultLength; + toCopy = hashResultLength; } memcpy(out, hashResult, toCopy); if (outLength) { - *outLength = toCopy; + *outLength = toCopy; } return SECSuccess; } /* Verify is just a compare for HMAC */ static SECStatus -sftk_HMACCmp(CK_ULONG *copyLen,unsigned char *sig,unsigned int sigLen, - unsigned char *hash, unsigned int hashLen) +sftk_HMACCmp(CK_ULONG *copyLen, unsigned char *sig, unsigned int sigLen, + unsigned char *hash, unsigned int hashLen) { - return (PORT_Memcmp(sig,hash,*copyLen) == 0) ? SECSuccess : SECFailure ; + return (PORT_Memcmp(sig, hash, *copyLen) == 0) ? SECSuccess : SECFailure; } /* * common HMAC initalization routine */ static CK_RV -sftk_doHMACInit(SFTKSessionContext *context,HASH_HashType hash, - SFTKObject *key, CK_ULONG mac_size) +sftk_doHMACInit(SFTKSessionContext *context, HASH_HashType hash, + SFTKObject *key, CK_ULONG mac_size) { SFTKAttribute *keyval; HMACContext *HMACcontext; @@ -1764,38 +1901,39 @@ sftk_doHMACInit(SFTKSessionContext *context,HASH_HashType hash, PRBool isFIPS = (key->slot->slotID == FIPS_SLOT_ID); /* required by FIPS 198 Section 4 */ - if (isFIPS && (mac_size < 4 || mac_size < hashObj->length/2)) { - return CKR_BUFFER_TOO_SMALL; + if (isFIPS && (mac_size < 4 || mac_size < hashObj->length / 2)) { + return CKR_BUFFER_TOO_SMALL; } - keyval = sftk_FindAttribute(key,CKA_VALUE); - if (keyval == NULL) return CKR_KEY_SIZE_RANGE; + keyval = sftk_FindAttribute(key, CKA_VALUE); + if (keyval == NULL) + return CKR_KEY_SIZE_RANGE; - HMACcontext = HMAC_Create(hashObj, - (const unsigned char*)keyval->attrib.pValue, - keyval->attrib.ulValueLen, isFIPS); + HMACcontext = HMAC_Create(hashObj, + (const unsigned char *)keyval->attrib.pValue, + keyval->attrib.ulValueLen, isFIPS); context->hashInfo = HMACcontext; context->multi = PR_TRUE; sftk_FreeAttribute(keyval); if (context->hashInfo == NULL) { - if (PORT_GetError() == SEC_ERROR_INVALID_ARGS) { - return CKR_KEY_SIZE_RANGE; - } - return CKR_HOST_MEMORY; + if (PORT_GetError() == SEC_ERROR_INVALID_ARGS) { + return CKR_KEY_SIZE_RANGE; + } + return CKR_HOST_MEMORY; } - context->hashUpdate = (SFTKHash) HMAC_Update; - context->end = (SFTKEnd) HMAC_Finish; + context->hashUpdate = (SFTKHash)HMAC_Update; + context->end = (SFTKEnd)HMAC_Finish; - context->hashdestroy = (SFTKDestroy) HMAC_Destroy; + context->hashdestroy = (SFTKDestroy)HMAC_Destroy; intpointer = PORT_New(CK_ULONG); if (intpointer == NULL) { - return CKR_HOST_MEMORY; + return CKR_HOST_MEMORY; } *intpointer = mac_size; context->cipherInfo = intpointer; - context->destroy = (SFTKDestroy) sftk_Space; - context->update = (SFTKCipher) sftk_SignCopy; - context->verify = (SFTKVerify) sftk_HMACCmp; + context->destroy = (SFTKDestroy)sftk_Space; + context->update = (SFTKCipher)sftk_SignCopy; + context->verify = (SFTKVerify)sftk_HMACCmp; context->maxLen = hashObj->length; HMAC_Begin(HMACcontext); return CKR_OK; @@ -1812,7 +1950,7 @@ sftk_doHMACInit(SFTKSessionContext *context,HASH_HashType hash, * We probably should have one copy of this table. We still need this table * in ssl to 'sign' the handshake hashes. */ -static unsigned char ssl_pad_1 [60] = { +static unsigned char ssl_pad_1[60] = { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, @@ -1822,7 +1960,7 @@ static unsigned char ssl_pad_1 [60] = { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 }; -static unsigned char ssl_pad_2 [60] = { +static unsigned char ssl_pad_2[60] = { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, @@ -1834,44 +1972,43 @@ static unsigned char ssl_pad_2 [60] = { }; static SECStatus -sftk_SSLMACSign(SFTKSSLMACInfo *info,unsigned char *sig,unsigned int *sigLen, - unsigned int maxLen,unsigned char *hash, unsigned int hashLen) +sftk_SSLMACSign(SFTKSSLMACInfo *info, unsigned char *sig, unsigned int *sigLen, + unsigned int maxLen, unsigned char *hash, unsigned int hashLen) { unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH]; unsigned int out; info->begin(info->hashContext); - info->update(info->hashContext,info->key,info->keySize); - info->update(info->hashContext,ssl_pad_2,info->padSize); - info->update(info->hashContext,hash,hashLen); - info->end(info->hashContext,tmpBuf,&out,SFTK_MAX_MAC_LENGTH); - PORT_Memcpy(sig,tmpBuf,info->macSize); + info->update(info->hashContext, info->key, info->keySize); + info->update(info->hashContext, ssl_pad_2, info->padSize); + info->update(info->hashContext, hash, hashLen); + info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH); + PORT_Memcpy(sig, tmpBuf, info->macSize); *sigLen = info->macSize; return SECSuccess; } static SECStatus -sftk_SSLMACVerify(SFTKSSLMACInfo *info,unsigned char *sig,unsigned int sigLen, - unsigned char *hash, unsigned int hashLen) +sftk_SSLMACVerify(SFTKSSLMACInfo *info, unsigned char *sig, unsigned int sigLen, + unsigned char *hash, unsigned int hashLen) { unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH]; unsigned int out; info->begin(info->hashContext); - info->update(info->hashContext,info->key,info->keySize); - info->update(info->hashContext,ssl_pad_2,info->padSize); - info->update(info->hashContext,hash,hashLen); - info->end(info->hashContext,tmpBuf,&out,SFTK_MAX_MAC_LENGTH); - return (PORT_Memcmp(sig,tmpBuf,info->macSize) == 0) ? - SECSuccess : SECFailure; + info->update(info->hashContext, info->key, info->keySize); + info->update(info->hashContext, ssl_pad_2, info->padSize); + info->update(info->hashContext, hash, hashLen); + info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH); + return (PORT_Memcmp(sig, tmpBuf, info->macSize) == 0) ? SECSuccess : SECFailure; } /* * common HMAC initalization routine */ static CK_RV -sftk_doSSLMACInit(SFTKSessionContext *context,SECOidTag oid, - SFTKObject *key, CK_ULONG mac_size) +sftk_doSSLMACInit(SFTKSessionContext *context, SECOidTag oid, + SFTKObject *key, CK_ULONG mac_size) { SFTKAttribute *keyval; SFTKBegin begin; @@ -1880,43 +2017,46 @@ sftk_doSSLMACInit(SFTKSessionContext *context,SECOidTag oid, CK_RV crv = CKR_MECHANISM_INVALID; if (oid == SEC_OID_SHA1) { - crv = sftk_doSubSHA1(context); - if (crv != CKR_OK) return crv; - begin = (SFTKBegin) SHA1_Begin; - padSize = 40; + crv = sftk_doSubSHA1(context); + if (crv != CKR_OK) + return crv; + begin = (SFTKBegin)SHA1_Begin; + padSize = 40; } else { - crv = sftk_doSubMD5(context); - if (crv != CKR_OK) return crv; - begin = (SFTKBegin) MD5_Begin; - padSize = 48; + crv = sftk_doSubMD5(context); + if (crv != CKR_OK) + return crv; + begin = (SFTKBegin)MD5_Begin; + padSize = 48; } context->multi = PR_TRUE; - keyval = sftk_FindAttribute(key,CKA_VALUE); - if (keyval == NULL) return CKR_KEY_SIZE_RANGE; + keyval = sftk_FindAttribute(key, CKA_VALUE); + if (keyval == NULL) + return CKR_KEY_SIZE_RANGE; - context->hashUpdate(context->hashInfo,keyval->attrib.pValue, - keyval->attrib.ulValueLen); - context->hashUpdate(context->hashInfo,ssl_pad_1,padSize); - sslmacinfo = (SFTKSSLMACInfo *) PORT_Alloc(sizeof(SFTKSSLMACInfo)); + context->hashUpdate(context->hashInfo, keyval->attrib.pValue, + keyval->attrib.ulValueLen); + context->hashUpdate(context->hashInfo, ssl_pad_1, padSize); + sslmacinfo = (SFTKSSLMACInfo *)PORT_Alloc(sizeof(SFTKSSLMACInfo)); if (sslmacinfo == NULL) { sftk_FreeAttribute(keyval); - return CKR_HOST_MEMORY; + return CKR_HOST_MEMORY; } sslmacinfo->macSize = mac_size; sslmacinfo->hashContext = context->hashInfo; - PORT_Memcpy(sslmacinfo->key,keyval->attrib.pValue, - keyval->attrib.ulValueLen); + PORT_Memcpy(sslmacinfo->key, keyval->attrib.pValue, + keyval->attrib.ulValueLen); sslmacinfo->keySize = keyval->attrib.ulValueLen; sslmacinfo->begin = begin; sslmacinfo->end = context->end; sslmacinfo->update = context->hashUpdate; sslmacinfo->padSize = padSize; sftk_FreeAttribute(keyval); - context->cipherInfo = (void *) sslmacinfo; - context->destroy = (SFTKDestroy) sftk_Space; - context->update = (SFTKCipher) sftk_SSLMACSign; - context->verify = (SFTKVerify) sftk_SSLMACVerify; + context->cipherInfo = (void *)sslmacinfo; + context->destroy = (SFTKDestroy)sftk_Space; + context->update = (SFTKCipher)sftk_SSLMACSign; + context->verify = (SFTKVerify)sftk_SSLMACVerify; context->maxLen = mac_size; return CKR_OK; } @@ -1925,16 +2065,16 @@ sftk_doSSLMACInit(SFTKSessionContext *context,SECOidTag oid, ************** Crypto Functions: Sign ************************ */ -/** +/** * Check if We're using CBCMacing and initialize the session context if we are. * @param contextType SFTK_SIGN or SFTK_VERIFY * @param keyUsage check whether key allows this usage */ static CK_RV sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, - CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage, - SFTKContextType contextType) - + CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage, + SFTKContextType contextType) + { CK_MECHANISM cbc_mechanism; CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE; @@ -1949,105 +2089,109 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, unsigned int blockSize; switch (pMechanism->mechanism) { - case CKM_RC2_MAC_GENERAL: - mac_bytes = - ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; - /* fall through */ - case CKM_RC2_MAC: - /* this works because ulEffectiveBits is in the same place in both the - * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */ - rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *) - pMechanism->pParameter)->ulEffectiveBits; - PORT_Memset(rc2_params.iv,0,sizeof(rc2_params.iv)); - cbc_mechanism.mechanism = CKM_RC2_CBC; - cbc_mechanism.pParameter = &rc2_params; - cbc_mechanism.ulParameterLen = sizeof(rc2_params); - blockSize = 8; - break; + case CKM_RC2_MAC_GENERAL: + if (!pMechanism->pParameter) { + return CKR_MECHANISM_PARAM_INVALID; + } + mac_bytes = + ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; + /* fall through */ + case CKM_RC2_MAC: + /* this works because ulEffectiveBits is in the same place in both the + * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */ + rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *) + pMechanism->pParameter) + ->ulEffectiveBits; + PORT_Memset(rc2_params.iv, 0, sizeof(rc2_params.iv)); + cbc_mechanism.mechanism = CKM_RC2_CBC; + cbc_mechanism.pParameter = &rc2_params; + cbc_mechanism.ulParameterLen = sizeof(rc2_params); + blockSize = 8; + break; #if NSS_SOFTOKEN_DOES_RC5 - case CKM_RC5_MAC_GENERAL: - mac_bytes = - ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; - /* fall through */ - case CKM_RC5_MAC: - /* this works because ulEffectiveBits is in the same place in both the - * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */ - rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter; - rc5_params.ulWordsize = rc5_mac->ulWordsize; - rc5_params.ulRounds = rc5_mac->ulRounds; - rc5_params.pIv = ivBlock; - if( (blockSize = rc5_mac->ulWordsize*2) > SFTK_MAX_BLOCK_SIZE ) - return CKR_MECHANISM_PARAM_INVALID; - rc5_params.ulIvLen = blockSize; - PORT_Memset(ivBlock,0,blockSize); - cbc_mechanism.mechanism = CKM_RC5_CBC; - cbc_mechanism.pParameter = &rc5_params; - cbc_mechanism.ulParameterLen = sizeof(rc5_params); - break; + case CKM_RC5_MAC_GENERAL: + mac_bytes = + ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; + /* fall through */ + case CKM_RC5_MAC: + /* this works because ulEffectiveBits is in the same place in both the + * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */ + rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter; + rc5_params.ulWordsize = rc5_mac->ulWordsize; + rc5_params.ulRounds = rc5_mac->ulRounds; + rc5_params.pIv = ivBlock; + if ((blockSize = rc5_mac->ulWordsize * 2) > SFTK_MAX_BLOCK_SIZE) + return CKR_MECHANISM_PARAM_INVALID; + rc5_params.ulIvLen = blockSize; + PORT_Memset(ivBlock, 0, blockSize); + cbc_mechanism.mechanism = CKM_RC5_CBC; + cbc_mechanism.pParameter = &rc5_params; + cbc_mechanism.ulParameterLen = sizeof(rc5_params); + break; #endif - /* add cast and idea later */ - case CKM_DES_MAC_GENERAL: - mac_bytes = *(CK_ULONG *)pMechanism->pParameter; - /* fall through */ - case CKM_DES_MAC: - blockSize = 8; - PORT_Memset(ivBlock,0,blockSize); - cbc_mechanism.mechanism = CKM_DES_CBC; - cbc_mechanism.pParameter = &ivBlock; - cbc_mechanism.ulParameterLen = blockSize; - break; - case CKM_DES3_MAC_GENERAL: - mac_bytes = *(CK_ULONG *)pMechanism->pParameter; - /* fall through */ - case CKM_DES3_MAC: - blockSize = 8; - PORT_Memset(ivBlock,0,blockSize); - cbc_mechanism.mechanism = CKM_DES3_CBC; - cbc_mechanism.pParameter = &ivBlock; - cbc_mechanism.ulParameterLen = blockSize; - break; - case CKM_CDMF_MAC_GENERAL: - mac_bytes = *(CK_ULONG *)pMechanism->pParameter; - /* fall through */ - case CKM_CDMF_MAC: - blockSize = 8; - PORT_Memset(ivBlock,0,blockSize); - cbc_mechanism.mechanism = CKM_CDMF_CBC; - cbc_mechanism.pParameter = &ivBlock; - cbc_mechanism.ulParameterLen = blockSize; - break; - case CKM_SEED_MAC_GENERAL: - mac_bytes = *(CK_ULONG *)pMechanism->pParameter; - /* fall through */ - case CKM_SEED_MAC: - blockSize = 16; - PORT_Memset(ivBlock,0,blockSize); - cbc_mechanism.mechanism = CKM_SEED_CBC; - cbc_mechanism.pParameter = &ivBlock; - cbc_mechanism.ulParameterLen = blockSize; - break; - case CKM_CAMELLIA_MAC_GENERAL: - mac_bytes = *(CK_ULONG *)pMechanism->pParameter; - /* fall through */ - case CKM_CAMELLIA_MAC: - blockSize = 16; - PORT_Memset(ivBlock,0,blockSize); - cbc_mechanism.mechanism = CKM_CAMELLIA_CBC; - cbc_mechanism.pParameter = &ivBlock; - cbc_mechanism.ulParameterLen = blockSize; - break; - case CKM_AES_MAC_GENERAL: - mac_bytes = *(CK_ULONG *)pMechanism->pParameter; - /* fall through */ - case CKM_AES_MAC: - blockSize = 16; - PORT_Memset(ivBlock,0,blockSize); - cbc_mechanism.mechanism = CKM_AES_CBC; - cbc_mechanism.pParameter = &ivBlock; - cbc_mechanism.ulParameterLen = blockSize; - break; - default: - return CKR_FUNCTION_NOT_SUPPORTED; + /* add cast and idea later */ + case CKM_DES_MAC_GENERAL: + mac_bytes = *(CK_ULONG *)pMechanism->pParameter; + /* fall through */ + case CKM_DES_MAC: + blockSize = 8; + PORT_Memset(ivBlock, 0, blockSize); + cbc_mechanism.mechanism = CKM_DES_CBC; + cbc_mechanism.pParameter = &ivBlock; + cbc_mechanism.ulParameterLen = blockSize; + break; + case CKM_DES3_MAC_GENERAL: + mac_bytes = *(CK_ULONG *)pMechanism->pParameter; + /* fall through */ + case CKM_DES3_MAC: + blockSize = 8; + PORT_Memset(ivBlock, 0, blockSize); + cbc_mechanism.mechanism = CKM_DES3_CBC; + cbc_mechanism.pParameter = &ivBlock; + cbc_mechanism.ulParameterLen = blockSize; + break; + case CKM_CDMF_MAC_GENERAL: + mac_bytes = *(CK_ULONG *)pMechanism->pParameter; + /* fall through */ + case CKM_CDMF_MAC: + blockSize = 8; + PORT_Memset(ivBlock, 0, blockSize); + cbc_mechanism.mechanism = CKM_CDMF_CBC; + cbc_mechanism.pParameter = &ivBlock; + cbc_mechanism.ulParameterLen = blockSize; + break; + case CKM_SEED_MAC_GENERAL: + mac_bytes = *(CK_ULONG *)pMechanism->pParameter; + /* fall through */ + case CKM_SEED_MAC: + blockSize = 16; + PORT_Memset(ivBlock, 0, blockSize); + cbc_mechanism.mechanism = CKM_SEED_CBC; + cbc_mechanism.pParameter = &ivBlock; + cbc_mechanism.ulParameterLen = blockSize; + break; + case CKM_CAMELLIA_MAC_GENERAL: + mac_bytes = *(CK_ULONG *)pMechanism->pParameter; + /* fall through */ + case CKM_CAMELLIA_MAC: + blockSize = 16; + PORT_Memset(ivBlock, 0, blockSize); + cbc_mechanism.mechanism = CKM_CAMELLIA_CBC; + cbc_mechanism.pParameter = &ivBlock; + cbc_mechanism.ulParameterLen = blockSize; + break; + case CKM_AES_MAC_GENERAL: + mac_bytes = *(CK_ULONG *)pMechanism->pParameter; + /* fall through */ + case CKM_AES_MAC: + blockSize = 16; + PORT_Memset(ivBlock, 0, blockSize); + cbc_mechanism.mechanism = CKM_AES_CBC; + cbc_mechanism.pParameter = &ivBlock; + cbc_mechanism.ulParameterLen = blockSize; + break; + default: + return CKR_FUNCTION_NOT_SUPPORTED; } /* if MAC size is externally supplied, it should be checked. @@ -2055,26 +2199,28 @@ sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, if (mac_bytes == SFTK_INVALID_MAC_SIZE) mac_bytes = blockSize >> 1; else { - if( mac_bytes > blockSize ) + if (mac_bytes > blockSize) return CKR_MECHANISM_PARAM_INVALID; } crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey, - CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */ - keyUsage, contextType, PR_TRUE ); - if (crv != CKR_OK) return crv; - crv = sftk_GetContext(hSession,&context,contextType,PR_TRUE,NULL); + CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */ + keyUsage, contextType, PR_TRUE); + if (crv != CKR_OK) + return crv; + crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL); /* this shouldn't happen! */ PORT_Assert(crv == CKR_OK); - if (crv != CKR_OK) return crv; + if (crv != CKR_OK) + return crv; context->blockSize = blockSize; context->macSize = mac_bytes; return CKR_OK; } /* - * encode RSA PKCS #1 Signature data before signing... + * encode RSA PKCS #1 Signature data before signing... */ static SECStatus sftk_RSAHashSign(SFTKHashSignInfo *info, unsigned char *sig, @@ -2094,12 +2240,12 @@ sftk_RSAHashSign(SFTKHashSignInfo *info, unsigned char *sig, /* XXX Old template; want to expunge it eventually. */ static DERTemplate SECAlgorithmIDTemplate[] = { { DER_SEQUENCE, - 0, NULL, sizeof(SECAlgorithmID) }, + 0, NULL, sizeof(SECAlgorithmID) }, { DER_OBJECT_ID, - offsetof(SECAlgorithmID,algorithm), }, + offsetof(SECAlgorithmID, algorithm) }, { DER_OPTIONAL | DER_ANY, - offsetof(SECAlgorithmID,parameters), }, - { 0, } + offsetof(SECAlgorithmID, parameters) }, + { 0 } }; /* @@ -2108,17 +2254,17 @@ static DERTemplate SECAlgorithmIDTemplate[] = { */ static DERTemplate SGNDigestInfoTemplate[] = { { DER_SEQUENCE, - 0, NULL, sizeof(SGNDigestInfo) }, + 0, NULL, sizeof(SGNDigestInfo) }, { DER_INLINE, - offsetof(SGNDigestInfo,digestAlgorithm), - SECAlgorithmIDTemplate, }, + offsetof(SGNDigestInfo, digestAlgorithm), + SECAlgorithmIDTemplate }, { DER_OCTET_STRING, - offsetof(SGNDigestInfo,digest), }, - { 0, } + offsetof(SGNDigestInfo, digest) }, + { 0 } }; /* - * encode RSA PKCS #1 Signature data before signing... + * encode RSA PKCS #1 Signature data before signing... */ SECStatus RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key, @@ -2159,7 +2305,7 @@ RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key, sftk_fatalError = PR_TRUE; } - loser: +loser: SGN_DestroyDigestInfo(di); if (arena != NULL) { PORT_FreeArena(arena, PR_FALSE); @@ -2207,7 +2353,6 @@ sftk_RSASignRaw(NSSLOWKEYPrivateKey *key, unsigned char *output, sftk_fatalError = PR_TRUE; } return rv; - } static SECStatus @@ -2239,7 +2384,7 @@ sftk_RSASignPSS(SFTKHashSignInfo *info, unsigned char *sig, static SECStatus nsc_DSA_Verify_Stub(void *ctx, void *sigBuf, unsigned int sigLen, - void *dataBuf, unsigned int dataLen) + void *dataBuf, unsigned int dataLen) { SECItem signature, digest; NSSLOWKEYPublicKey *key = (NSSLOWKEYPublicKey *)ctx; @@ -2266,7 +2411,7 @@ nsc_DSA_Sign_Stub(void *ctx, void *sigBuf, digest.len = dataLen; rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest); if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { - sftk_fatalError = PR_TRUE; + sftk_fatalError = PR_TRUE; } *sigLen = signature.len; return rv; @@ -2302,7 +2447,7 @@ nsc_ECDSASignStub(void *ctx, void *sigBuf, digest.len = dataLen; rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest); if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { - sftk_fatalError = PR_TRUE; + sftk_fatalError = PR_TRUE; } *sigLen = signature.len; return rv; @@ -2311,28 +2456,29 @@ nsc_ECDSASignStub(void *ctx, void *sigBuf, /* NSC_SignInit setups up the signing operations. There are three basic * types of signing: - * (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied + * (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied * to data in a single Sign operation (which often looks a lot like an * encrypt, with data coming in and data going out). - * (2) Hash based signing, where we continually hash the data, then apply + * (2) Hash based signing, where we continually hash the data, then apply * some sort of signature to the end. - * (3) Block Encryption CBC MAC's, where the Data is encrypted with a key, + * (3) Block Encryption CBC MAC's, where the Data is encrypted with a key, * and only the final block is part of the mac. * * For case number 3, we initialize a context much like the Encryption Context - * (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and + * (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and * C_Final by the following method... if it's not multi-part, and it's doesn't * have a hash context, it must be a block Encryption CBC MAC. * - * For case number 2, we initialize a hash structure, as well as make it + * For case number 2, we initialize a hash structure, as well as make it * multi-part. Updates are simple calls to the hash update function. Final * calls the hashend, then passes the result to the 'update' function (which * operates as a final signature function). In some hash based MAC'ing (as - * opposed to hash base signatures), the update function is can be simply a + * opposed to hash base signatures), the update function is can be simply a * copy (as is the case with HMAC). */ -CK_RV NSC_SignInit(CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) +CK_RV +NSC_SignInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SFTKSession *session; SFTKObject *key; @@ -2346,293 +2492,300 @@ CK_RV NSC_SignInit(CK_SESSION_HANDLE hSession, /* Block Cipher MACing Algorithms use a different Context init method..*/ crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, SFTK_SIGN); - if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv; + if (crv != CKR_FUNCTION_NOT_SUPPORTED) + return crv; /* we're not using a block cipher mac */ session = sftk_SessionFromHandle(hSession); - if (session == NULL) return CKR_SESSION_HANDLE_INVALID; - crv = sftk_InitGeneric(session,&context,SFTK_SIGN,&key,hKey,&key_type, - CKO_PRIVATE_KEY,CKA_SIGN); + if (session == NULL) + return CKR_SESSION_HANDLE_INVALID; + crv = sftk_InitGeneric(session, &context, SFTK_SIGN, &key, hKey, &key_type, + CKO_PRIVATE_KEY, CKA_SIGN); if (crv != CKR_OK) { - sftk_FreeSession(session); - return crv; + sftk_FreeSession(session); + return crv; } context->multi = PR_FALSE; -#define INIT_RSA_SIGN_MECH(mmm) \ - case CKM_ ## mmm ## _RSA_PKCS: \ - context->multi = PR_TRUE; \ - crv = sftk_doSub ## mmm (context); \ - if (crv != CKR_OK) break; \ - context->update = (SFTKCipher) sftk_RSAHashSign; \ - info = PORT_New(SFTKHashSignInfo); \ - if (info == NULL) { crv = CKR_HOST_MEMORY; break; } \ - info->hashOid = SEC_OID_ ## mmm ; \ - goto finish_rsa; - - switch(pMechanism->mechanism) { - INIT_RSA_SIGN_MECH(MD5) - INIT_RSA_SIGN_MECH(MD2) - INIT_RSA_SIGN_MECH(SHA1) - INIT_RSA_SIGN_MECH(SHA224) - INIT_RSA_SIGN_MECH(SHA256) - INIT_RSA_SIGN_MECH(SHA384) - INIT_RSA_SIGN_MECH(SHA512) - - case CKM_RSA_PKCS: - context->update = (SFTKCipher) sftk_RSASign; - goto finish_rsa; - case CKM_RSA_X_509: - context->update = (SFTKCipher) sftk_RSASignRaw; -finish_rsa: - if (key_type != CKK_RSA) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - context->rsa = PR_TRUE; - privKey = sftk_GetPrivKey(key,CKK_RSA,&crv); - if (privKey == NULL) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - /* OK, info is allocated only if we're doing hash and sign mechanism. - * It's necessary to be able to set the correct OID in the final - * signature. - */ - if (info) { - info->key = privKey; - context->cipherInfo = info; - context->destroy = (SFTKDestroy)sftk_Space; - } else { - context->cipherInfo = privKey; - context->destroy = (SFTKDestroy)sftk_Null; - } - context->maxLen = nsslowkey_PrivateModulusLen(privKey); - break; - case CKM_RSA_PKCS_PSS: - if (key_type != CKK_RSA) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - context->rsa = PR_TRUE; - if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) || - !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS*)pMechanism->pParameter)) { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - info = PORT_New(SFTKHashSignInfo); - if (info == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - info->params = pMechanism->pParameter; - info->key = sftk_GetPrivKey(key,CKK_RSA,&crv); - if (info->key == NULL) { - PORT_Free(info); - break; - } - context->cipherInfo = info; - context->destroy = (SFTKDestroy) sftk_Space; - context->update = (SFTKCipher) sftk_RSASignPSS; - context->maxLen = nsslowkey_PrivateModulusLen(info->key); - break; - - case CKM_DSA_SHA1: - context->multi = PR_TRUE; - crv = sftk_doSubSHA1(context); - if (crv != CKR_OK) break; - /* fall through */ - case CKM_DSA: - if (key_type != CKK_DSA) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - privKey = sftk_GetPrivKey(key,CKK_DSA,&crv); - if (privKey == NULL) { - break; - } - context->cipherInfo = privKey; - context->update = (SFTKCipher) nsc_DSA_Sign_Stub; - context->destroy = (privKey == key->objectInfo) ? - (SFTKDestroy) sftk_Null:(SFTKDestroy)sftk_FreePrivKey; - context->maxLen = DSA_MAX_SIGNATURE_LEN; - - break; +#define INIT_RSA_SIGN_MECH(mmm) \ + case CKM_##mmm##_RSA_PKCS: \ + context->multi = PR_TRUE; \ + crv = sftk_doSub##mmm(context); \ + if (crv != CKR_OK) \ + break; \ + context->update = (SFTKCipher)sftk_RSAHashSign; \ + info = PORT_New(SFTKHashSignInfo); \ + if (info == NULL) { \ + crv = CKR_HOST_MEMORY; \ + break; \ + } \ + info->hashOid = SEC_OID_##mmm; \ + goto finish_rsa; + + switch (pMechanism->mechanism) { + INIT_RSA_SIGN_MECH(MD5) + INIT_RSA_SIGN_MECH(MD2) + INIT_RSA_SIGN_MECH(SHA1) + INIT_RSA_SIGN_MECH(SHA224) + INIT_RSA_SIGN_MECH(SHA256) + INIT_RSA_SIGN_MECH(SHA384) + INIT_RSA_SIGN_MECH(SHA512) + + case CKM_RSA_PKCS: + context->update = (SFTKCipher)sftk_RSASign; + goto finish_rsa; + case CKM_RSA_X_509: + context->update = (SFTKCipher)sftk_RSASignRaw; + finish_rsa: + if (key_type != CKK_RSA) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + context->rsa = PR_TRUE; + privKey = sftk_GetPrivKey(key, CKK_RSA, &crv); + if (privKey == NULL) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + /* OK, info is allocated only if we're doing hash and sign mechanism. + * It's necessary to be able to set the correct OID in the final + * signature. + */ + if (info) { + info->key = privKey; + context->cipherInfo = info; + context->destroy = (SFTKDestroy)sftk_Space; + } else { + context->cipherInfo = privKey; + context->destroy = (SFTKDestroy)sftk_Null; + } + context->maxLen = nsslowkey_PrivateModulusLen(privKey); + break; + case CKM_RSA_PKCS_PSS: + if (key_type != CKK_RSA) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + context->rsa = PR_TRUE; + if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) || + !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + info = PORT_New(SFTKHashSignInfo); + if (info == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + info->params = pMechanism->pParameter; + info->key = sftk_GetPrivKey(key, CKK_RSA, &crv); + if (info->key == NULL) { + PORT_Free(info); + break; + } + context->cipherInfo = info; + context->destroy = (SFTKDestroy)sftk_Space; + context->update = (SFTKCipher)sftk_RSASignPSS; + context->maxLen = nsslowkey_PrivateModulusLen(info->key); + break; + + case CKM_DSA_SHA1: + context->multi = PR_TRUE; + crv = sftk_doSubSHA1(context); + if (crv != CKR_OK) + break; + /* fall through */ + case CKM_DSA: + if (key_type != CKK_DSA) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + privKey = sftk_GetPrivKey(key, CKK_DSA, &crv); + if (privKey == NULL) { + break; + } + context->cipherInfo = privKey; + context->update = (SFTKCipher)nsc_DSA_Sign_Stub; + context->destroy = (privKey == key->objectInfo) ? (SFTKDestroy)sftk_Null : (SFTKDestroy)sftk_FreePrivKey; + context->maxLen = DSA_MAX_SIGNATURE_LEN; + + break; #ifndef NSS_DISABLE_ECC - case CKM_ECDSA_SHA1: - context->multi = PR_TRUE; - crv = sftk_doSubSHA1(context); - if (crv != CKR_OK) break; - /* fall through */ - case CKM_ECDSA: - if (key_type != CKK_EC) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - privKey = sftk_GetPrivKey(key,CKK_EC,&crv); - if (privKey == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->cipherInfo = privKey; - context->update = (SFTKCipher) nsc_ECDSASignStub; - context->destroy = (privKey == key->objectInfo) ? - (SFTKDestroy) sftk_Null:(SFTKDestroy)sftk_FreePrivKey; - context->maxLen = MAX_ECKEY_LEN * 2; - - break; + case CKM_ECDSA_SHA1: + context->multi = PR_TRUE; + crv = sftk_doSubSHA1(context); + if (crv != CKR_OK) + break; + /* fall through */ + case CKM_ECDSA: + if (key_type != CKK_EC) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + privKey = sftk_GetPrivKey(key, CKK_EC, &crv); + if (privKey == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + context->cipherInfo = privKey; + context->update = (SFTKCipher)nsc_ECDSASignStub; + context->destroy = (privKey == key->objectInfo) ? (SFTKDestroy)sftk_Null : (SFTKDestroy)sftk_FreePrivKey; + context->maxLen = MAX_ECKEY_LEN * 2; + + break; #endif /* NSS_DISABLE_ECC */ -#define INIT_HMAC_MECH(mmm) \ - case CKM_ ## mmm ## _HMAC_GENERAL: \ - crv = sftk_doHMACInit(context, HASH_Alg ## mmm ,key, \ - *(CK_ULONG *)pMechanism->pParameter); \ - break; \ - case CKM_ ## mmm ## _HMAC: \ - crv = sftk_doHMACInit(context, HASH_Alg ## mmm ,key, mmm ## _LENGTH); \ - break; - - INIT_HMAC_MECH(MD2) - INIT_HMAC_MECH(MD5) - INIT_HMAC_MECH(SHA224) - INIT_HMAC_MECH(SHA256) - INIT_HMAC_MECH(SHA384) - INIT_HMAC_MECH(SHA512) - - case CKM_SHA_1_HMAC_GENERAL: - crv = sftk_doHMACInit(context,HASH_AlgSHA1,key, - *(CK_ULONG *)pMechanism->pParameter); - break; - case CKM_SHA_1_HMAC: - crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH); - break; - - case CKM_SSL3_MD5_MAC: - crv = sftk_doSSLMACInit(context,SEC_OID_MD5,key, - *(CK_ULONG *)pMechanism->pParameter); - break; - case CKM_SSL3_SHA1_MAC: - crv = sftk_doSSLMACInit(context,SEC_OID_SHA1,key, - *(CK_ULONG *)pMechanism->pParameter); - break; - case CKM_TLS_PRF_GENERAL: - crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0); - break; - case CKM_TLS_MAC: { - CK_TLS_MAC_PARAMS *tls12_mac_params; - HASH_HashType tlsPrfHash; - const char *label; - - if (pMechanism->ulParameterLen != sizeof(CK_TLS_MAC_PARAMS)) { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - tls12_mac_params = (CK_TLS_MAC_PARAMS *)pMechanism->pParameter; - if (tls12_mac_params->prfMechanism == CKM_TLS_PRF) { - /* The TLS 1.0 and 1.1 PRF */ - tlsPrfHash = HASH_AlgNULL; - if (tls12_mac_params->ulMacLength != 12) { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - } else { - /* The hash function for the TLS 1.2 PRF */ - tlsPrfHash = - GetHashTypeFromMechanism(tls12_mac_params->prfMechanism); - if (tlsPrfHash == HASH_AlgNULL || - tls12_mac_params->ulMacLength < 12) { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - } - if (tls12_mac_params->ulServerOrClient == 1) { - label = "server finished"; - } else if (tls12_mac_params->ulServerOrClient == 2) { - label = "client finished"; - } else { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - crv = sftk_TLSPRFInit(context, key, key_type, tlsPrfHash, - tls12_mac_params->ulMacLength); - if (crv == CKR_OK) { - context->hashUpdate(context->hashInfo, label, 15); - } - break; - } - case CKM_NSS_TLS_PRF_GENERAL_SHA256: - crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0); - break; - - case CKM_NSS_HMAC_CONSTANT_TIME: { - sftk_MACConstantTimeCtx *ctx = - sftk_HMACConstantTime_New(pMechanism,key); - CK_ULONG *intpointer; - - if (ctx == NULL) { - crv = CKR_ARGUMENTS_BAD; - break; - } - intpointer = PORT_New(CK_ULONG); - if (intpointer == NULL) { - PORT_Free(ctx); - crv = CKR_HOST_MEMORY; - break; - } - *intpointer = ctx->hash->length; - - context->cipherInfo = intpointer; - context->hashInfo = ctx; - context->currentMech = pMechanism->mechanism; - context->hashUpdate = sftk_HMACConstantTime_Update; - context->hashdestroy = sftk_MACConstantTime_DestroyContext; - context->end = sftk_MACConstantTime_EndHash; - context->update = (SFTKCipher) sftk_SignCopy; - context->destroy = sftk_Space; - context->maxLen = 64; - context->multi = PR_TRUE; - break; - } - - case CKM_NSS_SSL3_MAC_CONSTANT_TIME: { - sftk_MACConstantTimeCtx *ctx = - sftk_SSLv3MACConstantTime_New(pMechanism,key); - CK_ULONG *intpointer; - - if (ctx == NULL) { - crv = CKR_ARGUMENTS_BAD; - break; - } - intpointer = PORT_New(CK_ULONG); - if (intpointer == NULL) { - PORT_Free(ctx); - crv = CKR_HOST_MEMORY; - break; - } - *intpointer = ctx->hash->length; - - context->cipherInfo = intpointer; - context->hashInfo = ctx; - context->currentMech = pMechanism->mechanism; - context->hashUpdate = sftk_SSLv3MACConstantTime_Update; - context->hashdestroy = sftk_MACConstantTime_DestroyContext; - context->end = sftk_MACConstantTime_EndHash; - context->update = (SFTKCipher) sftk_SignCopy; - context->destroy = sftk_Space; - context->maxLen = 64; - context->multi = PR_TRUE; - break; - } - - default: - crv = CKR_MECHANISM_INVALID; - break; +#define INIT_HMAC_MECH(mmm) \ + case CKM_##mmm##_HMAC_GENERAL: \ + crv = sftk_doHMACInit(context, HASH_Alg##mmm, key, \ + *(CK_ULONG *)pMechanism->pParameter); \ + break; \ + case CKM_##mmm##_HMAC: \ + crv = sftk_doHMACInit(context, HASH_Alg##mmm, key, mmm##_LENGTH); \ + break; + + INIT_HMAC_MECH(MD2) + INIT_HMAC_MECH(MD5) + INIT_HMAC_MECH(SHA224) + INIT_HMAC_MECH(SHA256) + INIT_HMAC_MECH(SHA384) + INIT_HMAC_MECH(SHA512) + + case CKM_SHA_1_HMAC_GENERAL: + crv = sftk_doHMACInit(context, HASH_AlgSHA1, key, + *(CK_ULONG *)pMechanism->pParameter); + break; + case CKM_SHA_1_HMAC: + crv = sftk_doHMACInit(context, HASH_AlgSHA1, key, SHA1_LENGTH); + break; + + case CKM_SSL3_MD5_MAC: + crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key, + *(CK_ULONG *)pMechanism->pParameter); + break; + case CKM_SSL3_SHA1_MAC: + crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key, + *(CK_ULONG *)pMechanism->pParameter); + break; + case CKM_TLS_PRF_GENERAL: + crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0); + break; + case CKM_TLS_MAC: { + CK_TLS_MAC_PARAMS *tls12_mac_params; + HASH_HashType tlsPrfHash; + const char *label; + + if (pMechanism->ulParameterLen != sizeof(CK_TLS_MAC_PARAMS)) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + tls12_mac_params = (CK_TLS_MAC_PARAMS *)pMechanism->pParameter; + if (tls12_mac_params->prfMechanism == CKM_TLS_PRF) { + /* The TLS 1.0 and 1.1 PRF */ + tlsPrfHash = HASH_AlgNULL; + if (tls12_mac_params->ulMacLength != 12) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + } else { + /* The hash function for the TLS 1.2 PRF */ + tlsPrfHash = + GetHashTypeFromMechanism(tls12_mac_params->prfMechanism); + if (tlsPrfHash == HASH_AlgNULL || + tls12_mac_params->ulMacLength < 12) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + } + if (tls12_mac_params->ulServerOrClient == 1) { + label = "server finished"; + } else if (tls12_mac_params->ulServerOrClient == 2) { + label = "client finished"; + } else { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + crv = sftk_TLSPRFInit(context, key, key_type, tlsPrfHash, + tls12_mac_params->ulMacLength); + if (crv == CKR_OK) { + context->hashUpdate(context->hashInfo, label, 15); + } + break; + } + case CKM_NSS_TLS_PRF_GENERAL_SHA256: + crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0); + break; + + case CKM_NSS_HMAC_CONSTANT_TIME: { + sftk_MACConstantTimeCtx *ctx = + sftk_HMACConstantTime_New(pMechanism, key); + CK_ULONG *intpointer; + + if (ctx == NULL) { + crv = CKR_ARGUMENTS_BAD; + break; + } + intpointer = PORT_New(CK_ULONG); + if (intpointer == NULL) { + PORT_Free(ctx); + crv = CKR_HOST_MEMORY; + break; + } + *intpointer = ctx->hash->length; + + context->cipherInfo = intpointer; + context->hashInfo = ctx; + context->currentMech = pMechanism->mechanism; + context->hashUpdate = sftk_HMACConstantTime_Update; + context->hashdestroy = sftk_MACConstantTime_DestroyContext; + context->end = sftk_MACConstantTime_EndHash; + context->update = (SFTKCipher)sftk_SignCopy; + context->destroy = sftk_Space; + context->maxLen = 64; + context->multi = PR_TRUE; + break; + } + + case CKM_NSS_SSL3_MAC_CONSTANT_TIME: { + sftk_MACConstantTimeCtx *ctx = + sftk_SSLv3MACConstantTime_New(pMechanism, key); + CK_ULONG *intpointer; + + if (ctx == NULL) { + crv = CKR_ARGUMENTS_BAD; + break; + } + intpointer = PORT_New(CK_ULONG); + if (intpointer == NULL) { + PORT_Free(ctx); + crv = CKR_HOST_MEMORY; + break; + } + *intpointer = ctx->hash->length; + + context->cipherInfo = intpointer; + context->hashInfo = ctx; + context->currentMech = pMechanism->mechanism; + context->hashUpdate = sftk_SSLv3MACConstantTime_Update; + context->hashdestroy = sftk_MACConstantTime_DestroyContext; + context->end = sftk_MACConstantTime_EndHash; + context->update = (SFTKCipher)sftk_SignCopy; + context->destroy = sftk_Space; + context->maxLen = 64; + context->multi = PR_TRUE; + break; + } + + default: + crv = CKR_MECHANISM_INVALID; + break; } if (crv != CKR_OK) { - if (info) PORT_Free(info); + if (info) + PORT_Free(info); sftk_FreeContext(context); sftk_FreeSession(session); return crv; @@ -2645,12 +2798,13 @@ finish_rsa: /** MAC one block of data by block cipher */ static CK_RV -sftk_MACBlock( SFTKSessionContext *ctx, void *blk ) +sftk_MACBlock(SFTKSessionContext *ctx, void *blk) { unsigned int outlen; - return ( SECSuccess == (ctx->update)( ctx->cipherInfo, ctx->macBuf, &outlen, - SFTK_MAX_BLOCK_SIZE, blk, ctx->blockSize )) - ? CKR_OK : sftk_MapCryptError(PORT_GetError()); + return (SECSuccess == (ctx->update)(ctx->cipherInfo, ctx->macBuf, &outlen, + SFTK_MAX_BLOCK_SIZE, blk, ctx->blockSize)) + ? CKR_OK + : sftk_MapCryptError(PORT_GetError()); } /** MAC last (incomplete) block of data by block cipher @@ -2658,100 +2812,101 @@ sftk_MACBlock( SFTKSessionContext *ctx, void *blk ) * Call once, then terminate MACing operation. */ static CK_RV -sftk_MACFinal( SFTKSessionContext *ctx ) +sftk_MACFinal(SFTKSessionContext *ctx) { unsigned int padLen = ctx->padDataLength; /* pad and proceed the residual */ - if( padLen ) { + if (padLen) { /* shd clr ctx->padLen to make sftk_MACFinal idempotent */ - PORT_Memset( ctx->padBuf + padLen, 0, ctx->blockSize - padLen ); - return sftk_MACBlock( ctx, ctx->padBuf ); + PORT_Memset(ctx->padBuf + padLen, 0, ctx->blockSize - padLen); + return sftk_MACBlock(ctx, ctx->padBuf); } else return CKR_OK; } /** The common implementation for {Sign,Verify}Update. (S/V only vary in their * setup and final operations). - * + * * A call which results in an error terminates the operation [PKCS#11,v2.11] */ static CK_RV -sftk_MACUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart, - CK_ULONG ulPartLen,SFTKContextType type) +sftk_MACUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, + CK_ULONG ulPartLen, SFTKContextType type) { SFTKSession *session; SFTKSessionContext *context; CK_RV crv; /* make sure we're legal */ - crv = sftk_GetContext(hSession,&context,type, PR_TRUE, &session ); - if (crv != CKR_OK) return crv; + crv = sftk_GetContext(hSession, &context, type, PR_TRUE, &session); + if (crv != CKR_OK) + return crv; if (context->hashInfo) { - (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen); - } else { - /* must be block cipher MACing */ + (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen); + } else { + /* must be block cipher MACing */ - unsigned int blkSize = context->blockSize; + unsigned int blkSize = context->blockSize; unsigned char *residual = /* free room in context->padBuf */ - context->padBuf + context->padDataLength; - unsigned int minInput = /* min input for MACing at least one block */ - blkSize - context->padDataLength; + context->padBuf + context->padDataLength; + unsigned int minInput = /* min input for MACing at least one block */ + blkSize - context->padDataLength; /* not enough data even for one block */ - if( ulPartLen < minInput ) { - PORT_Memcpy( residual, pPart, ulPartLen ); + if (ulPartLen < minInput) { + PORT_Memcpy(residual, pPart, ulPartLen); context->padDataLength += ulPartLen; goto cleanup; } /* MACing residual */ - if( context->padDataLength ) { - PORT_Memcpy( residual, pPart, minInput ); + if (context->padDataLength) { + PORT_Memcpy(residual, pPart, minInput); ulPartLen -= minInput; - pPart += minInput; - if( CKR_OK != (crv = sftk_MACBlock( context, context->padBuf )) ) + pPart += minInput; + if (CKR_OK != (crv = sftk_MACBlock(context, context->padBuf))) goto terminate; } /* MACing full blocks */ - while( ulPartLen >= blkSize ) - { - if( CKR_OK != (crv = sftk_MACBlock( context, pPart )) ) + while (ulPartLen >= blkSize) { + if (CKR_OK != (crv = sftk_MACBlock(context, pPart))) goto terminate; ulPartLen -= blkSize; - pPart += blkSize; + pPart += blkSize; } /* save the residual */ - if( (context->padDataLength = ulPartLen) ) - PORT_Memcpy( context->padBuf, pPart, ulPartLen ); + if ((context->padDataLength = ulPartLen)) + PORT_Memcpy(context->padBuf, pPart, ulPartLen); } /* blk cipher MACing */ - goto cleanup; + goto cleanup; terminate: - sftk_TerminateOp( session, type, context ); + sftk_TerminateOp(session, type, context); cleanup: sftk_FreeSession(session); return crv; } /* NSC_SignUpdate continues a multiple-part signature operation, - * where the signature is (will be) an appendix to the data, - * and plaintext cannot be recovered from the signature + * where the signature is (will be) an appendix to the data, + * and plaintext cannot be recovered from the signature * * A call which results in an error terminates the operation [PKCS#11,v2.11] */ -CK_RV NSC_SignUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart, - CK_ULONG ulPartLen) +CK_RV +NSC_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, + CK_ULONG ulPartLen) { CHECK_FORK(); return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_SIGN); } - -/* NSC_SignFinal finishes a multiple-part signature operation, +/* NSC_SignFinal finishes a multiple-part signature operation, * returning the signature. */ -CK_RV NSC_SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature, - CK_ULONG_PTR pulSignatureLen) +CK_RV +NSC_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen) { SFTKSession *session; SFTKSessionContext *context; @@ -2762,19 +2917,21 @@ CK_RV NSC_SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature, CHECK_FORK(); /* make sure we're legal */ - crv = sftk_GetContext(hSession,&context,SFTK_SIGN,PR_TRUE,&session); - if (crv != CKR_OK) return crv; + crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_TRUE, &session); + if (crv != CKR_OK) + return crv; if (context->hashInfo) { unsigned int digestLen; unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH]; - if( !pSignature ) { - outlen = context->maxLen; goto finish; + if (!pSignature) { + outlen = context->maxLen; + goto finish; } (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf)); - if( SECSuccess != (context->update)(context->cipherInfo, pSignature, - &outlen, maxoutlen, tmpbuf, digestLen)) + if (SECSuccess != (context->update)(context->cipherInfo, pSignature, + &outlen, maxoutlen, tmpbuf, digestLen)) crv = sftk_MapCryptError(PORT_GetError()); /* CKR_BUFFER_TOO_SMALL here isn't continuable, let operation terminate. * Keeping "too small" CK_RV intact is a standard violation, but allows @@ -2783,15 +2940,16 @@ CK_RV NSC_SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature, /* must be block cipher MACing */ outlen = context->macSize; /* null or "too small" buf doesn't terminate operation [PKCS#11,v2.11]*/ - if( !pSignature || maxoutlen < outlen ) { - if( pSignature ) crv = CKR_BUFFER_TOO_SMALL; + if (!pSignature || maxoutlen < outlen) { + if (pSignature) + crv = CKR_BUFFER_TOO_SMALL; goto finish; } - if( CKR_OK == (crv = sftk_MACFinal( context )) ) - PORT_Memcpy(pSignature, context->macBuf, outlen ); + if (CKR_OK == (crv = sftk_MACFinal(context))) + PORT_Memcpy(pSignature, context->macBuf, outlen); } - sftk_TerminateOp( session, SFTK_SIGN, context ); + sftk_TerminateOp(session, SFTK_SIGN, context); finish: *pulSignatureLen = outlen; sftk_FreeSession(session); @@ -2799,11 +2957,12 @@ finish: } /* NSC_Sign signs (encrypts with private key) data in a single part, - * where the signature is (will be) an appendix to the data, + * where the signature is (will be) an appendix to the data, * and plaintext cannot be recovered from the signature */ -CK_RV NSC_Sign(CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature, - CK_ULONG_PTR pulSignatureLen) +CK_RV +NSC_Sign(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen) { SFTKSession *session; SFTKSessionContext *context; @@ -2812,33 +2971,34 @@ CK_RV NSC_Sign(CK_SESSION_HANDLE hSession, CHECK_FORK(); /* make sure we're legal */ - crv = sftk_GetContext(hSession,&context,SFTK_SIGN,PR_FALSE,&session); - if (crv != CKR_OK) return crv; + crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_FALSE, &session); + if (crv != CKR_OK) + return crv; if (!pSignature) { /* see also how C_SignUpdate implements this */ - *pulSignatureLen = (!context->multi || context->hashInfo) - ? context->maxLen - : context->macSize; /* must be block cipher MACing */ - goto finish; + *pulSignatureLen = (!context->multi || context->hashInfo) + ? context->maxLen + : context->macSize; /* must be block cipher MACing */ + goto finish; } /* multi part Signing are completely implemented by SignUpdate and * sign Final */ if (context->multi) { /* SignFinal can't follow failed SignUpdate */ - if( CKR_OK == (crv = NSC_SignUpdate(hSession,pData,ulDataLen) )) + if (CKR_OK == (crv = NSC_SignUpdate(hSession, pData, ulDataLen))) crv = NSC_SignFinal(hSession, pSignature, pulSignatureLen); - } else { - /* single-part PKC signature (e.g. CKM_ECDSA) */ + } else { + /* single-part PKC signature (e.g. CKM_ECDSA) */ unsigned int outlen; unsigned int maxoutlen = *pulSignatureLen; - if( SECSuccess != (*context->update)(context->cipherInfo, pSignature, - &outlen, maxoutlen, pData, ulDataLen)) + if (SECSuccess != (*context->update)(context->cipherInfo, pSignature, + &outlen, maxoutlen, pData, ulDataLen)) crv = sftk_MapCryptError(PORT_GetError()); - *pulSignatureLen = (CK_ULONG) outlen; + *pulSignatureLen = (CK_ULONG)outlen; /* "too small" here is certainly continuable */ - if( crv != CKR_BUFFER_TOO_SMALL ) + if (crv != CKR_BUFFER_TOO_SMALL) sftk_TerminateOp(session, SFTK_SIGN, context); } /* single-part */ @@ -2847,38 +3007,38 @@ finish: return crv; } - /* ************** Crypto Functions: Sign Recover ************************ */ /* NSC_SignRecoverInit initializes a signature operation, - * where the (digest) data can be recovered from the signature. + * where the (digest) data can be recovered from the signature. * E.g. encryption with the user's private key */ -CK_RV NSC_SignRecoverInit(CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey) +CK_RV +NSC_SignRecoverInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CHECK_FORK(); switch (pMechanism->mechanism) { - case CKM_RSA_PKCS: - case CKM_RSA_X_509: - return NSC_SignInit(hSession,pMechanism,hKey); - default: - break; + case CKM_RSA_PKCS: + case CKM_RSA_X_509: + return NSC_SignInit(hSession, pMechanism, hKey); + default: + break; } return CKR_MECHANISM_INVALID; } - /* NSC_SignRecover signs data in a single operation - * where the (digest) data can be recovered from the signature. + * where the (digest) data can be recovered from the signature. * E.g. encryption with the user's private key */ -CK_RV NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, - CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) +CK_RV +NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, + CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { CHECK_FORK(); - return NSC_Sign(hSession,pData,ulDataLen,pSignature,pulSignatureLen); + return NSC_Sign(hSession, pData, ulDataLen, pSignature, pulSignatureLen); } /* @@ -2887,7 +3047,7 @@ CK_RV NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, /* Handle RSA Signature formatting */ static SECStatus -sftk_hashCheckSign(SFTKHashVerifyInfo *info, const unsigned char *sig, +sftk_hashCheckSign(SFTKHashVerifyInfo *info, const unsigned char *sig, unsigned int sigLen, const unsigned char *digest, unsigned int digestLen) { @@ -2922,19 +3082,19 @@ RSA_HashCheckSign(SECOidTag digestOid, NSSLOWKEYPublicKey *key, pkcs1DigestInfo.data = pkcs1DigestInfoData; pkcs1DigestInfo.len = bufferSize; - + /* decrypt the block */ rv = RSA_CheckSignRecover(&key->u.rsa, pkcs1DigestInfo.data, - &pkcs1DigestInfo.len, pkcs1DigestInfo.len, - sig, sigLen); + &pkcs1DigestInfo.len, pkcs1DigestInfo.len, + sig, sigLen); if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_BAD_SIGNATURE); } else { - digest.data = (PRUint8*) digestData; + digest.data = (PRUint8 *)digestData; digest.len = digestLen; rv = _SGN_VerifyPKCS1DigestInfo( - digestOid, &digest, &pkcs1DigestInfo, - PR_TRUE /*XXX: unsafeAllowMissingParameters*/); + digestOid, &digest, &pkcs1DigestInfo, + PR_TRUE /*XXX: unsafeAllowMissingParameters*/); } PORT_Free(pkcs1DigestInfoData); @@ -2991,11 +3151,12 @@ sftk_RSACheckSignPSS(SFTKHashVerifyInfo *info, const unsigned char *sig, params->sLen, sig, sigLen, digest, digestLen); } -/* NSC_VerifyInit initializes a verification operation, - * where the signature is an appendix to the data, +/* NSC_VerifyInit initializes a verification operation, + * where the signature is an appendix to the data, * and plaintext cannot be recovered from the signature (e.g. DSA) */ -CK_RV NSC_VerifyInit(CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey) +CK_RV +NSC_VerifyInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SFTKSession *session; SFTKObject *key; @@ -3009,183 +3170,195 @@ CK_RV NSC_VerifyInit(CK_SESSION_HANDLE hSession, /* Block Cipher MACing Algorithms use a different Context init method..*/ crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_VERIFY, SFTK_VERIFY); - if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv; + if (crv != CKR_FUNCTION_NOT_SUPPORTED) + return crv; session = sftk_SessionFromHandle(hSession); - if (session == NULL) return CKR_SESSION_HANDLE_INVALID; - crv = sftk_InitGeneric(session,&context,SFTK_VERIFY,&key,hKey,&key_type, - CKO_PUBLIC_KEY,CKA_VERIFY); + if (session == NULL) + return CKR_SESSION_HANDLE_INVALID; + crv = sftk_InitGeneric(session, &context, SFTK_VERIFY, &key, hKey, &key_type, + CKO_PUBLIC_KEY, CKA_VERIFY); if (crv != CKR_OK) { - sftk_FreeSession(session); - return crv; + sftk_FreeSession(session); + return crv; } context->multi = PR_FALSE; -#define INIT_RSA_VFY_MECH(mmm) \ - case CKM_ ## mmm ## _RSA_PKCS: \ - context->multi = PR_TRUE; \ - crv = sftk_doSub ## mmm (context); \ - if (crv != CKR_OK) break; \ - context->verify = (SFTKVerify) sftk_hashCheckSign; \ - info = PORT_New(SFTKHashVerifyInfo); \ - if (info == NULL) { crv = CKR_HOST_MEMORY; break; } \ - info->hashOid = SEC_OID_ ## mmm ; \ - goto finish_rsa; - - switch(pMechanism->mechanism) { - INIT_RSA_VFY_MECH(MD5) - INIT_RSA_VFY_MECH(MD2) - INIT_RSA_VFY_MECH(SHA1) - INIT_RSA_VFY_MECH(SHA224) - INIT_RSA_VFY_MECH(SHA256) - INIT_RSA_VFY_MECH(SHA384) - INIT_RSA_VFY_MECH(SHA512) - - case CKM_RSA_PKCS: - context->verify = (SFTKVerify) sftk_RSACheckSign; - goto finish_rsa; - case CKM_RSA_X_509: - context->verify = (SFTKVerify) sftk_RSACheckSignRaw; -finish_rsa: - if (key_type != CKK_RSA) { - if (info) PORT_Free(info); - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - context->rsa = PR_TRUE; - pubKey = sftk_GetPubKey(key,CKK_RSA,&crv); - if (pubKey == NULL) { - if (info) PORT_Free(info); - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - if (info) { - info->key = pubKey; - context->cipherInfo = info; - context->destroy = sftk_Space; - } else { - context->cipherInfo = pubKey; - context->destroy = sftk_Null; - } - break; - case CKM_RSA_PKCS_PSS: - if (key_type != CKK_RSA) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - context->rsa = PR_TRUE; - if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) || - !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS*)pMechanism->pParameter)) { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - info = PORT_New(SFTKHashVerifyInfo); - if (info == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - info->params = pMechanism->pParameter; - info->key = sftk_GetPubKey(key,CKK_RSA,&crv); - if (info->key == NULL) { - PORT_Free(info); - break; - } - context->cipherInfo = info; - context->destroy = (SFTKDestroy) sftk_Space; - context->verify = (SFTKVerify) sftk_RSACheckSignPSS; - break; - case CKM_DSA_SHA1: - context->multi = PR_TRUE; - crv = sftk_doSubSHA1(context); - if (crv != CKR_OK) break; - /* fall through */ - case CKM_DSA: - if (key_type != CKK_DSA) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - pubKey = sftk_GetPubKey(key,CKK_DSA,&crv); - if (pubKey == NULL) { - break; - } - context->cipherInfo = pubKey; - context->verify = (SFTKVerify) nsc_DSA_Verify_Stub; - context->destroy = sftk_Null; - break; +#define INIT_RSA_VFY_MECH(mmm) \ + case CKM_##mmm##_RSA_PKCS: \ + context->multi = PR_TRUE; \ + crv = sftk_doSub##mmm(context); \ + if (crv != CKR_OK) \ + break; \ + context->verify = (SFTKVerify)sftk_hashCheckSign; \ + info = PORT_New(SFTKHashVerifyInfo); \ + if (info == NULL) { \ + crv = CKR_HOST_MEMORY; \ + break; \ + } \ + info->hashOid = SEC_OID_##mmm; \ + goto finish_rsa; + + switch (pMechanism->mechanism) { + INIT_RSA_VFY_MECH(MD5) + INIT_RSA_VFY_MECH(MD2) + INIT_RSA_VFY_MECH(SHA1) + INIT_RSA_VFY_MECH(SHA224) + INIT_RSA_VFY_MECH(SHA256) + INIT_RSA_VFY_MECH(SHA384) + INIT_RSA_VFY_MECH(SHA512) + + case CKM_RSA_PKCS: + context->verify = (SFTKVerify)sftk_RSACheckSign; + goto finish_rsa; + case CKM_RSA_X_509: + context->verify = (SFTKVerify)sftk_RSACheckSignRaw; + finish_rsa: + if (key_type != CKK_RSA) { + if (info) + PORT_Free(info); + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + context->rsa = PR_TRUE; + pubKey = sftk_GetPubKey(key, CKK_RSA, &crv); + if (pubKey == NULL) { + if (info) + PORT_Free(info); + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + if (info) { + info->key = pubKey; + context->cipherInfo = info; + context->destroy = sftk_Space; + } else { + context->cipherInfo = pubKey; + context->destroy = sftk_Null; + } + break; + case CKM_RSA_PKCS_PSS: + if (key_type != CKK_RSA) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + context->rsa = PR_TRUE; + if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) || + !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + info = PORT_New(SFTKHashVerifyInfo); + if (info == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + info->params = pMechanism->pParameter; + info->key = sftk_GetPubKey(key, CKK_RSA, &crv); + if (info->key == NULL) { + PORT_Free(info); + break; + } + context->cipherInfo = info; + context->destroy = (SFTKDestroy)sftk_Space; + context->verify = (SFTKVerify)sftk_RSACheckSignPSS; + break; + case CKM_DSA_SHA1: + context->multi = PR_TRUE; + crv = sftk_doSubSHA1(context); + if (crv != CKR_OK) + break; + /* fall through */ + case CKM_DSA: + if (key_type != CKK_DSA) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + pubKey = sftk_GetPubKey(key, CKK_DSA, &crv); + if (pubKey == NULL) { + break; + } + context->cipherInfo = pubKey; + context->verify = (SFTKVerify)nsc_DSA_Verify_Stub; + context->destroy = sftk_Null; + break; #ifndef NSS_DISABLE_ECC - case CKM_ECDSA_SHA1: - context->multi = PR_TRUE; - crv = sftk_doSubSHA1(context); - if (crv != CKR_OK) break; - /* fall through */ - case CKM_ECDSA: - if (key_type != CKK_EC) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - pubKey = sftk_GetPubKey(key,CKK_EC,&crv); - if (pubKey == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->cipherInfo = pubKey; - context->verify = (SFTKVerify) nsc_ECDSAVerifyStub; - context->destroy = sftk_Null; - break; + case CKM_ECDSA_SHA1: + context->multi = PR_TRUE; + crv = sftk_doSubSHA1(context); + if (crv != CKR_OK) + break; + /* fall through */ + case CKM_ECDSA: + if (key_type != CKK_EC) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + pubKey = sftk_GetPubKey(key, CKK_EC, &crv); + if (pubKey == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + context->cipherInfo = pubKey; + context->verify = (SFTKVerify)nsc_ECDSAVerifyStub; + context->destroy = sftk_Null; + break; #endif /* NSS_DISABLE_ECC */ - INIT_HMAC_MECH(MD2) - INIT_HMAC_MECH(MD5) - INIT_HMAC_MECH(SHA224) - INIT_HMAC_MECH(SHA256) - INIT_HMAC_MECH(SHA384) - INIT_HMAC_MECH(SHA512) - - case CKM_SHA_1_HMAC_GENERAL: - crv = sftk_doHMACInit(context,HASH_AlgSHA1,key, - *(CK_ULONG *)pMechanism->pParameter); - break; - case CKM_SHA_1_HMAC: - crv = sftk_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH); - break; - - case CKM_SSL3_MD5_MAC: - crv = sftk_doSSLMACInit(context,SEC_OID_MD5,key, - *(CK_ULONG *)pMechanism->pParameter); - break; - case CKM_SSL3_SHA1_MAC: - crv = sftk_doSSLMACInit(context,SEC_OID_SHA1,key, - *(CK_ULONG *)pMechanism->pParameter); - break; - case CKM_TLS_PRF_GENERAL: - crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0); - break; - case CKM_NSS_TLS_PRF_GENERAL_SHA256: - crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0); - break; - - default: - crv = CKR_MECHANISM_INVALID; - break; + INIT_HMAC_MECH(MD2) + INIT_HMAC_MECH(MD5) + INIT_HMAC_MECH(SHA224) + INIT_HMAC_MECH(SHA256) + INIT_HMAC_MECH(SHA384) + INIT_HMAC_MECH(SHA512) + + case CKM_SHA_1_HMAC_GENERAL: + crv = sftk_doHMACInit(context, HASH_AlgSHA1, key, + *(CK_ULONG *)pMechanism->pParameter); + break; + case CKM_SHA_1_HMAC: + crv = sftk_doHMACInit(context, HASH_AlgSHA1, key, SHA1_LENGTH); + break; + + case CKM_SSL3_MD5_MAC: + crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key, + *(CK_ULONG *)pMechanism->pParameter); + break; + case CKM_SSL3_SHA1_MAC: + crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key, + *(CK_ULONG *)pMechanism->pParameter); + break; + case CKM_TLS_PRF_GENERAL: + crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0); + break; + case CKM_NSS_TLS_PRF_GENERAL_SHA256: + crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0); + break; + + default: + crv = CKR_MECHANISM_INVALID; + break; } if (crv != CKR_OK) { - if (info) PORT_Free(info); + if (info) + PORT_Free(info); sftk_FreeContext(context); - sftk_FreeSession(session); - return crv; + sftk_FreeSession(session); + return crv; } sftk_SetContextByType(session, SFTK_VERIFY, context); sftk_FreeSession(session); return CKR_OK; } -/* NSC_Verify verifies a signature in a single-part operation, - * where the signature is an appendix to the data, +/* NSC_Verify verifies a signature in a single-part operation, + * where the signature is an appendix to the data, * and plaintext cannot be recovered from the signature */ -CK_RV NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, - CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) +CK_RV +NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, + CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { SFTKSession *session; SFTKSessionContext *context; @@ -3194,45 +3367,46 @@ CK_RV NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CHECK_FORK(); /* make sure we're legal */ - crv = sftk_GetContext(hSession,&context,SFTK_VERIFY,PR_FALSE,&session); - if (crv != CKR_OK) return crv; + crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session); + if (crv != CKR_OK) + return crv; /* multi part Verifying are completely implemented by VerifyUpdate and * VerifyFinal */ if (context->multi) { /* VerifyFinal can't follow failed VerifyUpdate */ - if( CKR_OK == (crv = NSC_VerifyUpdate(hSession, pData, ulDataLen))) + if (CKR_OK == (crv = NSC_VerifyUpdate(hSession, pData, ulDataLen))) crv = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen); } else { - if (SECSuccess != (*context->verify)(context->cipherInfo,pSignature, + if (SECSuccess != (*context->verify)(context->cipherInfo, pSignature, ulSignatureLen, pData, ulDataLen)) crv = sftk_MapCryptError(PORT_GetError()); - sftk_TerminateOp( session, SFTK_VERIFY, context ); + sftk_TerminateOp(session, SFTK_VERIFY, context); } sftk_FreeSession(session); return crv; } - -/* NSC_VerifyUpdate continues a multiple-part verification operation, - * where the signature is an appendix to the data, +/* NSC_VerifyUpdate continues a multiple-part verification operation, + * where the signature is an appendix to the data, * and plaintext cannot be recovered from the signature * * A call which results in an error terminates the operation [PKCS#11,v2.11] */ -CK_RV NSC_VerifyUpdate( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, - CK_ULONG ulPartLen) +CK_RV +NSC_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, + CK_ULONG ulPartLen) { CHECK_FORK(); return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_VERIFY); } - -/* NSC_VerifyFinal finishes a multiple-part verification operation, +/* NSC_VerifyFinal finishes a multiple-part verification operation, * checking the signature. */ -CK_RV NSC_VerifyFinal(CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen) +CK_RV +NSC_VerifyFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { SFTKSession *session; SFTKSessionContext *context; @@ -3240,34 +3414,33 @@ CK_RV NSC_VerifyFinal(CK_SESSION_HANDLE hSession, CHECK_FORK(); - if (!pSignature) - return CKR_ARGUMENTS_BAD; + if (!pSignature) + return CKR_ARGUMENTS_BAD; /* make sure we're legal */ - crv = sftk_GetContext(hSession,&context,SFTK_VERIFY,PR_TRUE,&session); - if (crv != CKR_OK) - return crv; - + crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session); + if (crv != CKR_OK) + return crv; + if (context->hashInfo) { unsigned int digestLen; unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH]; - + (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf)); - if( SECSuccess != (context->verify)(context->cipherInfo, pSignature, + if (SECSuccess != (context->verify)(context->cipherInfo, pSignature, ulSignatureLen, tmpbuf, digestLen)) crv = sftk_MapCryptError(PORT_GetError()); } else if (ulSignatureLen != context->macSize) { - /* must be block cipher MACing */ - crv = CKR_SIGNATURE_LEN_RANGE; + /* must be block cipher MACing */ + crv = CKR_SIGNATURE_LEN_RANGE; } else if (CKR_OK == (crv = sftk_MACFinal(context))) { - if (PORT_Memcmp(pSignature, context->macBuf, ulSignatureLen)) - crv = CKR_SIGNATURE_INVALID; + if (PORT_Memcmp(pSignature, context->macBuf, ulSignatureLen)) + crv = CKR_SIGNATURE_INVALID; } - sftk_TerminateOp( session, SFTK_VERIFY, context ); + sftk_TerminateOp(session, SFTK_VERIFY, context); sftk_FreeSession(session); return crv; - } /* @@ -3303,11 +3476,12 @@ sftk_RSACheckSignRecoverRaw(NSSLOWKEYPublicKey *key, unsigned char *data, sig, sigLen); } -/* NSC_VerifyRecoverInit initializes a signature verification operation, - * where the data is recovered from the signature. +/* NSC_VerifyRecoverInit initializes a signature verification operation, + * where the data is recovered from the signature. * E.g. Decryption with the user's public key */ -CK_RV NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey) +CK_RV +NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { SFTKSession *session; SFTKObject *key; @@ -3319,56 +3493,58 @@ CK_RV NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CHECK_FORK(); session = sftk_SessionFromHandle(hSession); - if (session == NULL) return CKR_SESSION_HANDLE_INVALID; - crv = sftk_InitGeneric(session,&context,SFTK_VERIFY_RECOVER, - &key,hKey,&key_type,CKO_PUBLIC_KEY,CKA_VERIFY_RECOVER); + if (session == NULL) + return CKR_SESSION_HANDLE_INVALID; + crv = sftk_InitGeneric(session, &context, SFTK_VERIFY_RECOVER, + &key, hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY_RECOVER); if (crv != CKR_OK) { - sftk_FreeSession(session); - return crv; + sftk_FreeSession(session); + return crv; } context->multi = PR_TRUE; - switch(pMechanism->mechanism) { - case CKM_RSA_PKCS: - case CKM_RSA_X_509: - if (key_type != CKK_RSA) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - context->multi = PR_FALSE; - context->rsa = PR_TRUE; - pubKey = sftk_GetPubKey(key,CKK_RSA,&crv); - if (pubKey == NULL) { - break; - } - context->cipherInfo = pubKey; - context->update = (SFTKCipher) (pMechanism->mechanism == CKM_RSA_X_509 - ? sftk_RSACheckSignRecoverRaw : sftk_RSACheckSignRecover); - context->destroy = sftk_Null; - break; - default: - crv = CKR_MECHANISM_INVALID; - break; + switch (pMechanism->mechanism) { + case CKM_RSA_PKCS: + case CKM_RSA_X_509: + if (key_type != CKK_RSA) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + context->multi = PR_FALSE; + context->rsa = PR_TRUE; + pubKey = sftk_GetPubKey(key, CKK_RSA, &crv); + if (pubKey == NULL) { + break; + } + context->cipherInfo = pubKey; + context->update = (SFTKCipher)(pMechanism->mechanism == CKM_RSA_X_509 + ? sftk_RSACheckSignRecoverRaw + : sftk_RSACheckSignRecover); + context->destroy = sftk_Null; + break; + default: + crv = CKR_MECHANISM_INVALID; + break; } if (crv != CKR_OK) { PORT_Free(context); - sftk_FreeSession(session); - return crv; + sftk_FreeSession(session); + return crv; } sftk_SetContextByType(session, SFTK_VERIFY_RECOVER, context); sftk_FreeSession(session); return CKR_OK; } - -/* NSC_VerifyRecover verifies a signature in a single-part operation, - * where the data is recovered from the signature. +/* NSC_VerifyRecover verifies a signature in a single-part operation, + * where the data is recovered from the signature. * E.g. Decryption with the user's public key */ -CK_RV NSC_VerifyRecover(CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen, - CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen) +CK_RV +NSC_VerifyRecover(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, + CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { SFTKSession *session; SFTKSessionContext *context; @@ -3380,35 +3556,37 @@ CK_RV NSC_VerifyRecover(CK_SESSION_HANDLE hSession, CHECK_FORK(); /* make sure we're legal */ - crv = sftk_GetContext(hSession,&context,SFTK_VERIFY_RECOVER, - PR_FALSE,&session); - if (crv != CKR_OK) return crv; + crv = sftk_GetContext(hSession, &context, SFTK_VERIFY_RECOVER, + PR_FALSE, &session); + if (crv != CKR_OK) + return crv; if (pData == NULL) { - /* to return the actual size, we need to do the decrypt, just return - * the max size, which is the size of the input signature. */ - *pulDataLen = ulSignatureLen; - rv = SECSuccess; - goto finish; + /* to return the actual size, we need to do the decrypt, just return + * the max size, which is the size of the input signature. */ + *pulDataLen = ulSignatureLen; + rv = SECSuccess; + goto finish; } - rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, - pSignature, ulSignatureLen); - *pulDataLen = (CK_ULONG) outlen; + rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, + pSignature, ulSignatureLen); + *pulDataLen = (CK_ULONG)outlen; sftk_TerminateOp(session, SFTK_VERIFY_RECOVER, context); finish: sftk_FreeSession(session); - return (rv == SECSuccess) ? CKR_OK : sftk_MapVerifyError(PORT_GetError()); + return (rv == SECSuccess) ? CKR_OK : sftk_MapVerifyError(PORT_GetError()); } /* **************************** Random Functions: ************************ */ -/* NSC_SeedRandom mixes additional seed material into the token's random number +/* NSC_SeedRandom mixes additional seed material into the token's random number * generator. */ -CK_RV NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, - CK_ULONG ulSeedLen) +CK_RV +NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, + CK_ULONG ulSeedLen) { SECStatus rv; @@ -3419,8 +3597,9 @@ CK_RV NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, } /* NSC_GenerateRandom generates random data. */ -CK_RV NSC_GenerateRandom(CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) +CK_RV +NSC_GenerateRandom(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) { SECStatus rv; @@ -3438,35 +3617,35 @@ CK_RV NSC_GenerateRandom(CK_SESSION_HANDLE hSession, **************************** Key Functions: ************************ */ - /* * generate a password based encryption key. This code uses * PKCS5 to do the work. */ static CK_RV nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism, - void *buf, CK_ULONG *key_length, PRBool faulty3DES) + void *buf, CK_ULONG *key_length, PRBool faulty3DES) { SECItem *pbe_key = NULL, iv, pwitem; CK_PBE_PARAMS *pbe_params = NULL; CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL; *key_length = 0; - iv.data = NULL; iv.len = 0; + iv.data = NULL; + iv.len = 0; if (pMechanism->mechanism == CKM_PKCS5_PBKD2) { - pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter; - pwitem.data = (unsigned char *)pbkd2_params->pPassword; - /* was this a typo in the PKCS #11 spec? */ - pwitem.len = *pbkd2_params->ulPasswordLen; + pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter; + pwitem.data = (unsigned char *)pbkd2_params->pPassword; + /* was this a typo in the PKCS #11 spec? */ + pwitem.len = *pbkd2_params->ulPasswordLen; } else { - pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; - pwitem.data = (unsigned char *)pbe_params->pPassword; - pwitem.len = pbe_params->ulPasswordLen; + pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; + pwitem.data = (unsigned char *)pbe_params->pPassword; + pwitem.len = pbe_params->ulPasswordLen; } pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES); if (pbe_key == NULL) { - return CKR_HOST_MEMORY; + return CKR_HOST_MEMORY; } PORT_Memcpy(buf, pbe_key->data, pbe_key->len); @@ -3476,7 +3655,7 @@ nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism, if (iv.data) { if (pbe_params && pbe_params->pInitVector != NULL) { - PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len); + PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len); } PORT_Free(iv.data); } @@ -3484,24 +3663,24 @@ nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism, return CKR_OK; } -/* +/* * this is coded for "full" support. These selections will be limitted to * the official subset by freebl. */ static unsigned int sftk_GetSubPrimeFromPrime(unsigned int primeBits) { - if (primeBits <= 1024) { - return 160; - } else if (primeBits <= 2048) { - return 224; - } else if (primeBits <= 3072) { - return 256; - } else if (primeBits <= 7680) { - return 384; - } else { - return 512; - } + if (primeBits <= 1024) { + return 160; + } else if (primeBits <= 2048) { + return 224; + } else if (primeBits <= 3072) { + return 256; + } else if (primeBits <= 7680) { + return 384; + } else { + return 512; + } } static CK_RV @@ -3520,144 +3699,218 @@ nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key) attribute = sftk_FindAttribute(key, CKA_PRIME_BITS); if (attribute == NULL) { - return CKR_TEMPLATE_INCOMPLETE; + attribute = sftk_FindAttribute(key, CKA_PRIME); + if (attribute == NULL) { + return CKR_TEMPLATE_INCOMPLETE; + } else { + primeBits = attribute->attrib.ulValueLen; + sftk_FreeAttribute(attribute); + } + } else { + primeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue; + sftk_FreeAttribute(attribute); } - primeBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue; - sftk_FreeAttribute(attribute); if (primeBits < 1024) { - j = PQG_PBITS_TO_INDEX(primeBits); - if (j == (unsigned int)-1) { - return CKR_ATTRIBUTE_VALUE_INVALID; - } + j = PQG_PBITS_TO_INDEX(primeBits); + if (j == (unsigned int)-1) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } } - attribute = sftk_FindAttribute(key, CKA_NETSCAPE_PQG_SEED_BITS); + attribute = sftk_FindAttribute(key, CKA_NSS_PQG_SEED_BITS); if (attribute != NULL) { - seedBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue; - sftk_FreeAttribute(attribute); + seedBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue; + sftk_FreeAttribute(attribute); } attribute = sftk_FindAttribute(key, CKA_SUBPRIME_BITS); if (attribute != NULL) { - subprimeBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue; - sftk_FreeAttribute(attribute); + subprimeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue; + sftk_FreeAttribute(attribute); + } + + /* if P and Q are supplied, we want to generate a new G */ + attribute = sftk_FindAttribute(key, CKA_PRIME); + if (attribute != NULL) { + PLArenaPool *arena; + + sftk_FreeAttribute(attribute); + arena = PORT_NewArena(1024); + if (arena == NULL) { + crv = CKR_HOST_MEMORY; + goto loser; + } + params = PORT_ArenaAlloc(arena, sizeof(*params)); + if (params == NULL) { + crv = CKR_HOST_MEMORY; + goto loser; + } + params->arena = arena; + crv = sftk_Attribute2SSecItem(arena, ¶ms->prime, key, CKA_PRIME); + if (crv != CKR_OK) { + goto loser; + } + crv = sftk_Attribute2SSecItem(arena, ¶ms->subPrime, + key, CKA_SUBPRIME); + if (crv != CKR_OK) { + goto loser; + } + + arena = PORT_NewArena(1024); + if (arena == NULL) { + crv = CKR_HOST_MEMORY; + goto loser; + } + vfy = PORT_ArenaAlloc(arena, sizeof(*vfy)); + if (vfy == NULL) { + crv = CKR_HOST_MEMORY; + goto loser; + } + vfy->arena = arena; + crv = sftk_Attribute2SSecItem(arena, &vfy->seed, key, CKA_NSS_PQG_SEED); + if (crv != CKR_OK) { + goto loser; + } + crv = sftk_Attribute2SSecItem(arena, &vfy->h, key, CKA_NSS_PQG_H); + if (crv != CKR_OK) { + goto loser; + } + sftk_DeleteAttributeType(key, CKA_PRIME); + sftk_DeleteAttributeType(key, CKA_SUBPRIME); + sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED); + sftk_DeleteAttributeType(key, CKA_NSS_PQG_H); } - sftk_DeleteAttributeType(key,CKA_PRIME_BITS); - sftk_DeleteAttributeType(key,CKA_SUBPRIME_BITS); - sftk_DeleteAttributeType(key,CKA_NETSCAPE_PQG_SEED_BITS); + sftk_DeleteAttributeType(key, CKA_PRIME_BITS); + sftk_DeleteAttributeType(key, CKA_SUBPRIME_BITS); + sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED_BITS); /* use the old PQG interface if we have old input data */ if ((primeBits < 1024) || ((primeBits == 1024) && (subprimeBits == 0))) { - if (seedBits == 0) { - rv = PQG_ParamGen(j, ¶ms, &vfy); - } else { - rv = PQG_ParamGenSeedLen(j,seedBits/8, ¶ms, &vfy); - } + if (seedBits == 0) { + rv = PQG_ParamGen(j, ¶ms, &vfy); + } else { + rv = PQG_ParamGenSeedLen(j, seedBits / 8, ¶ms, &vfy); + } } else { - if (subprimeBits == 0) { - subprimeBits = sftk_GetSubPrimeFromPrime(primeBits); + if (subprimeBits == 0) { + subprimeBits = sftk_GetSubPrimeFromPrime(primeBits); } - if (seedBits == 0) { - seedBits = primeBits; - } - rv = PQG_ParamGenV2(primeBits, subprimeBits, seedBits/8, ¶ms, &vfy); + if (seedBits == 0) { + seedBits = primeBits; + } + rv = PQG_ParamGenV2(primeBits, subprimeBits, seedBits / 8, ¶ms, &vfy); } - - if (rv != SECSuccess) { - if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { - sftk_fatalError = PR_TRUE; - } - return sftk_MapCryptError(PORT_GetError()); - } - crv = sftk_AddAttributeType(key,CKA_PRIME, - params->prime.data, params->prime.len); - if (crv != CKR_OK) goto loser; - crv = sftk_AddAttributeType(key,CKA_SUBPRIME, - params->subPrime.data, params->subPrime.len); - if (crv != CKR_OK) goto loser; - crv = sftk_AddAttributeType(key,CKA_BASE, - params->base.data, params->base.len); - if (crv != CKR_OK) goto loser; + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } + return sftk_MapCryptError(PORT_GetError()); + } + crv = sftk_AddAttributeType(key, CKA_PRIME, + params->prime.data, params->prime.len); + if (crv != CKR_OK) + goto loser; + crv = sftk_AddAttributeType(key, CKA_SUBPRIME, + params->subPrime.data, params->subPrime.len); + if (crv != CKR_OK) + goto loser; + crv = sftk_AddAttributeType(key, CKA_BASE, + params->base.data, params->base.len); + if (crv != CKR_OK) + goto loser; counter = vfy->counter; - crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_COUNTER, - &counter, sizeof(counter)); - crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_SEED, - vfy->seed.data, vfy->seed.len); - if (crv != CKR_OK) goto loser; - crv = sftk_AddAttributeType(key,CKA_NETSCAPE_PQG_H, - vfy->h.data, vfy->h.len); - if (crv != CKR_OK) goto loser; + crv = sftk_AddAttributeType(key, CKA_NSS_PQG_COUNTER, + &counter, sizeof(counter)); + crv = sftk_AddAttributeType(key, CKA_NSS_PQG_SEED, + vfy->seed.data, vfy->seed.len); + if (crv != CKR_OK) + goto loser; + crv = sftk_AddAttributeType(key, CKA_NSS_PQG_H, + vfy->h.data, vfy->h.len); + if (crv != CKR_OK) + goto loser; loser: - PQG_DestroyParams(params); + if (params) { + PQG_DestroyParams(params); + } if (vfy) { - PQG_DestroyVerify(vfy); + PQG_DestroyVerify(vfy); } return crv; } - static CK_RV nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type, - CK_ULONG *key_length) + CK_ULONG *key_length) { CK_RV crv = CKR_OK; switch (mechanism) { - case CKM_RC2_KEY_GEN: - *key_type = CKK_RC2; - if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; - break; + case CKM_RC2_KEY_GEN: + *key_type = CKK_RC2; + if (*key_length == 0) + crv = CKR_TEMPLATE_INCOMPLETE; + break; #if NSS_SOFTOKEN_DOES_RC5 - case CKM_RC5_KEY_GEN: - *key_type = CKK_RC5; - if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; - break; + case CKM_RC5_KEY_GEN: + *key_type = CKK_RC5; + if (*key_length == 0) + crv = CKR_TEMPLATE_INCOMPLETE; + break; #endif - case CKM_RC4_KEY_GEN: - *key_type = CKK_RC4; - if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; - break; - case CKM_GENERIC_SECRET_KEY_GEN: - *key_type = CKK_GENERIC_SECRET; - if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; - break; - case CKM_CDMF_KEY_GEN: - *key_type = CKK_CDMF; - *key_length = 8; - break; - case CKM_DES_KEY_GEN: - *key_type = CKK_DES; - *key_length = 8; - break; - case CKM_DES2_KEY_GEN: - *key_type = CKK_DES2; - *key_length = 16; - break; - case CKM_DES3_KEY_GEN: - *key_type = CKK_DES3; - *key_length = 24; - break; - case CKM_SEED_KEY_GEN: - *key_type = CKK_SEED; - *key_length = 16; - break; - case CKM_CAMELLIA_KEY_GEN: - *key_type = CKK_CAMELLIA; - if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; - break; - case CKM_AES_KEY_GEN: - *key_type = CKK_AES; - if (*key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE; - break; - default: - PORT_Assert(0); - crv = CKR_MECHANISM_INVALID; - break; + case CKM_RC4_KEY_GEN: + *key_type = CKK_RC4; + if (*key_length == 0) + crv = CKR_TEMPLATE_INCOMPLETE; + break; + case CKM_GENERIC_SECRET_KEY_GEN: + *key_type = CKK_GENERIC_SECRET; + if (*key_length == 0) + crv = CKR_TEMPLATE_INCOMPLETE; + break; + case CKM_CDMF_KEY_GEN: + *key_type = CKK_CDMF; + *key_length = 8; + break; + case CKM_DES_KEY_GEN: + *key_type = CKK_DES; + *key_length = 8; + break; + case CKM_DES2_KEY_GEN: + *key_type = CKK_DES2; + *key_length = 16; + break; + case CKM_DES3_KEY_GEN: + *key_type = CKK_DES3; + *key_length = 24; + break; + case CKM_SEED_KEY_GEN: + *key_type = CKK_SEED; + *key_length = 16; + break; + case CKM_CAMELLIA_KEY_GEN: + *key_type = CKK_CAMELLIA; + if (*key_length == 0) + crv = CKR_TEMPLATE_INCOMPLETE; + break; + case CKM_AES_KEY_GEN: + *key_type = CKK_AES; + if (*key_length == 0) + crv = CKR_TEMPLATE_INCOMPLETE; + break; + case CKM_NSS_CHACHA20_KEY_GEN: + *key_type = CKK_NSS_CHACHA20; + if (*key_length == 0) + crv = CKR_TEMPLATE_INCOMPLETE; + break; + default: + PORT_Assert(0); + crv = CKR_MECHANISM_INVALID; + break; } return crv; @@ -3666,7 +3919,7 @@ nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type, CK_RV nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe) { - SECItem salt; + SECItem salt; CK_PBE_PARAMS *pbe_params = NULL; NSSPKCS5PBEParameter *params; PLArenaPool *arena = NULL; @@ -3676,14 +3929,14 @@ nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe) arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); if (arena == NULL) { - return CKR_HOST_MEMORY; + return CKR_HOST_MEMORY; } - params = (NSSPKCS5PBEParameter *) PORT_ArenaZAlloc(arena, - sizeof(NSSPKCS5PBEParameter)); + params = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena, + sizeof(NSSPKCS5PBEParameter)); if (params == NULL) { - PORT_FreeArena(arena,PR_TRUE); - return CKR_HOST_MEMORY; + PORT_FreeArena(arena, PR_TRUE); + return CKR_HOST_MEMORY; } params->poolp = arena; @@ -3699,28 +3952,28 @@ nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe) salt.data = (unsigned char *)pbe_params->pSalt; salt.len = (unsigned int)pbe_params->ulSaltLen; salt.type = siBuffer; - rv = SECITEM_CopyItem(arena,¶ms->salt,&salt); + rv = SECITEM_CopyItem(arena, ¶ms->salt, &salt); if (rv != SECSuccess) { - PORT_FreeArena(arena,PR_TRUE); - return CKR_HOST_MEMORY; + PORT_FreeArena(arena, PR_TRUE); + return CKR_HOST_MEMORY; } switch (pMechanism->mechanism) { - case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN: - case CKM_PBA_SHA1_WITH_SHA1_HMAC: - params->hashType = HASH_AlgSHA1; - params->keyLen = 20; - break; - case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN: - params->hashType = HASH_AlgMD5; - params->keyLen = 16; - break; - case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN: - params->hashType = HASH_AlgMD2; - params->keyLen = 16; - break; - default: - PORT_FreeArena(arena,PR_TRUE); - return CKR_MECHANISM_INVALID; + case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN: + case CKM_PBA_SHA1_WITH_SHA1_HMAC: + params->hashType = HASH_AlgSHA1; + params->keyLen = 20; + break; + case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN: + params->hashType = HASH_AlgMD5; + params->keyLen = 16; + break; + case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN: + params->hashType = HASH_AlgMD2; + params->keyLen = 16; + break; + default: + PORT_FreeArena(arena, PR_TRUE); + return CKR_MECHANISM_INVALID; } *pbe = params; return CKR_OK; @@ -3728,13 +3981,14 @@ nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe) /* maybe this should be table driven? */ static CK_RV -nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe, - CK_KEY_TYPE *key_type, CK_ULONG *key_length) +nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe, + CK_KEY_TYPE *key_type, CK_ULONG *key_length) { CK_RV crv = CKR_OK; SECOidData *oid; CK_PBE_PARAMS *pbe_params = NULL; NSSPKCS5PBEParameter *params = NULL; + HASH_HashType hashType = HASH_AlgSHA1; CK_PKCS5_PBKD2_PARAMS *pbkd2_params = NULL; SECItem salt; CK_ULONG iteration = 0; @@ -3743,85 +3997,100 @@ nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe, oid = SECOID_FindOIDByMechanism(pMechanism->mechanism); if (oid == NULL) { - return CKR_MECHANISM_INVALID; + return CKR_MECHANISM_INVALID; } if (pMechanism->mechanism == CKM_PKCS5_PBKD2) { - pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter; - if (pbkd2_params->saltSource != CKZ_SALT_SPECIFIED) { - return CKR_MECHANISM_PARAM_INVALID; - } - salt.data = (unsigned char *)pbkd2_params->pSaltSourceData; - salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen; - iteration = pbkd2_params->iterations; + pbkd2_params = (CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter; + if (pbkd2_params == NULL) { + return CKR_MECHANISM_PARAM_INVALID; + } + switch (pbkd2_params->prf) { + case CKP_PKCS5_PBKD2_HMAC_SHA1: + hashType = HASH_AlgSHA1; + break; + case CKP_PKCS5_PBKD2_HMAC_SHA224: + hashType = HASH_AlgSHA224; + break; + case CKP_PKCS5_PBKD2_HMAC_SHA256: + hashType = HASH_AlgSHA256; + break; + case CKP_PKCS5_PBKD2_HMAC_SHA384: + hashType = HASH_AlgSHA384; + break; + case CKP_PKCS5_PBKD2_HMAC_SHA512: + hashType = HASH_AlgSHA512; + break; + default: + return CKR_MECHANISM_PARAM_INVALID; + } + if (pbkd2_params->saltSource != CKZ_SALT_SPECIFIED) { + return CKR_MECHANISM_PARAM_INVALID; + } + salt.data = (unsigned char *)pbkd2_params->pSaltSourceData; + salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen; + iteration = pbkd2_params->iterations; } else { - pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; - salt.data = (unsigned char *)pbe_params->pSalt; - salt.len = (unsigned int)pbe_params->ulSaltLen; - iteration = pbe_params->ulIteration; + pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; + salt.data = (unsigned char *)pbe_params->pSalt; + salt.len = (unsigned int)pbe_params->ulSaltLen; + iteration = pbe_params->ulIteration; } - params=nsspkcs5_NewParam(oid->offset, &salt, iteration); + params = nsspkcs5_NewParam(oid->offset, hashType, &salt, iteration); if (params == NULL) { - return CKR_MECHANISM_INVALID; + return CKR_MECHANISM_INVALID; } switch (params->encAlg) { - case SEC_OID_DES_CBC: - *key_type = CKK_DES; - *key_length = params->keyLen; - break; - case SEC_OID_DES_EDE3_CBC: - *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3; - *key_length = params->keyLen; - break; - case SEC_OID_RC2_CBC: - *key_type = CKK_RC2; - *key_length = params->keyLen; - break; - case SEC_OID_RC4: - *key_type = CKK_RC4; - *key_length = params->keyLen; - break; - case SEC_OID_PKCS5_PBKDF2: - /* sigh, PKCS #11 currently only defines SHA1 for the KDF hash type. - * we do the check here because this where we would handle multiple - * hash types in the future */ - if (pbkd2_params == NULL || - pbkd2_params->prf != CKP_PKCS5_PBKD2_HMAC_SHA1) { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - /* key type must already be set */ - if (*key_type == CKK_INVALID_KEY_TYPE) { - crv = CKR_TEMPLATE_INCOMPLETE; - break; - } - /* PBKDF2 needs to calculate the key length from the other parameters - */ - if (*key_length == 0) { - *key_length = sftk_MapKeySize(*key_type); - } - if (*key_length == 0) { - crv = CKR_TEMPLATE_INCOMPLETE; - break; - } - params->keyLen = *key_length; - break; - default: - crv = CKR_MECHANISM_INVALID; - nsspkcs5_DestroyPBEParameter(params); - break; + case SEC_OID_DES_CBC: + *key_type = CKK_DES; + *key_length = params->keyLen; + break; + case SEC_OID_DES_EDE3_CBC: + *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3; + *key_length = params->keyLen; + break; + case SEC_OID_RC2_CBC: + *key_type = CKK_RC2; + *key_length = params->keyLen; + break; + case SEC_OID_RC4: + *key_type = CKK_RC4; + *key_length = params->keyLen; + break; + case SEC_OID_PKCS5_PBKDF2: + /* key type must already be set */ + if (*key_type == CKK_INVALID_KEY_TYPE) { + crv = CKR_TEMPLATE_INCOMPLETE; + break; + } + /* PBKDF2 needs to calculate the key length from the other parameters + */ + if (*key_length == 0) { + *key_length = sftk_MapKeySize(*key_type); + } + if (*key_length == 0) { + crv = CKR_TEMPLATE_INCOMPLETE; + break; + } + params->keyLen = *key_length; + break; + default: + crv = CKR_MECHANISM_INVALID; + nsspkcs5_DestroyPBEParameter(params); + break; } if (crv == CKR_OK) { - *pbe = params; + *pbe = params; } return crv; } /* NSC_GenerateKey generates a secret key, creating a new key object. */ -CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount, - CK_OBJECT_HANDLE_PTR phKey) +CK_RV +NSC_GenerateKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey) { SFTKObject *key; SFTKSession *session; @@ -3834,12 +4103,16 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, int i; SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); unsigned char buf[MAX_KEY_LEN]; - enum {nsc_pbe, nsc_ssl, nsc_bulk, nsc_param, nsc_jpake} key_gen_type; + enum { nsc_pbe, + nsc_ssl, + nsc_bulk, + nsc_param, + nsc_jpake } key_gen_type; NSSPKCS5PBEParameter *pbe_param; SSL3RSAPreMasterSecret *rsa_pms; CK_VERSION *version; - /* in very old versions of NSS, there were implementation errors with key - * generation methods. We want to beable to read these, but not + /* in very old versions of NSS, there were implementation errors with key + * generation methods. We want to beable to read these, but not * produce them any more. The affected algorithm was 3DES. */ PRBool faultyPBE3DES = PR_FALSE; @@ -3855,206 +4128,232 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, */ key = sftk_NewObject(slot); /* fill in the handle later */ if (key == NULL) { - return CKR_HOST_MEMORY; + return CKR_HOST_MEMORY; } /* * load the template values into the object */ - for (i=0; i < (int) ulCount; i++) { - if (pTemplate[i].type == CKA_VALUE_LEN) { - key_length = *(CK_ULONG *)pTemplate[i].pValue; - continue; - } - /* some algorithms need keytype specified */ - if (pTemplate[i].type == CKA_KEY_TYPE) { - key_type = *(CK_ULONG *)pTemplate[i].pValue; - continue; - } - - crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i])); - if (crv != CKR_OK) break; + for (i = 0; i < (int)ulCount; i++) { + if (pTemplate[i].type == CKA_VALUE_LEN) { + key_length = *(CK_ULONG *)pTemplate[i].pValue; + continue; + } + /* some algorithms need keytype specified */ + if (pTemplate[i].type == CKA_KEY_TYPE) { + key_type = *(CK_ULONG *)pTemplate[i].pValue; + continue; + } + + crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i])); + if (crv != CKR_OK) + break; } if (crv != CKR_OK) { - sftk_FreeObject(key); - return crv; + sftk_FreeObject(key); + return crv; } /* make sure we don't have any class, key_type, or value fields */ - sftk_DeleteAttributeType(key,CKA_CLASS); - sftk_DeleteAttributeType(key,CKA_KEY_TYPE); - sftk_DeleteAttributeType(key,CKA_VALUE); + sftk_DeleteAttributeType(key, CKA_CLASS); + sftk_DeleteAttributeType(key, CKA_KEY_TYPE); + sftk_DeleteAttributeType(key, CKA_VALUE); /* Now Set up the parameters to generate the key (based on mechanism) */ key_gen_type = nsc_bulk; /* bulk key by default */ switch (pMechanism->mechanism) { - case CKM_CDMF_KEY_GEN: - case CKM_DES_KEY_GEN: - case CKM_DES2_KEY_GEN: - case CKM_DES3_KEY_GEN: - checkWeak = PR_TRUE; + case CKM_CDMF_KEY_GEN: + case CKM_DES_KEY_GEN: + case CKM_DES2_KEY_GEN: + case CKM_DES3_KEY_GEN: + checkWeak = PR_TRUE; /* fall through */ - case CKM_RC2_KEY_GEN: - case CKM_RC4_KEY_GEN: - case CKM_GENERIC_SECRET_KEY_GEN: - case CKM_SEED_KEY_GEN: - case CKM_CAMELLIA_KEY_GEN: - case CKM_AES_KEY_GEN: + case CKM_RC2_KEY_GEN: + case CKM_RC4_KEY_GEN: + case CKM_GENERIC_SECRET_KEY_GEN: + case CKM_SEED_KEY_GEN: + case CKM_CAMELLIA_KEY_GEN: + case CKM_AES_KEY_GEN: + case CKM_NSS_CHACHA20_KEY_GEN: #if NSS_SOFTOKEN_DOES_RC5 - case CKM_RC5_KEY_GEN: + case CKM_RC5_KEY_GEN: #endif - crv = nsc_SetupBulkKeyGen(pMechanism->mechanism,&key_type,&key_length); - break; - case CKM_SSL3_PRE_MASTER_KEY_GEN: - key_type = CKK_GENERIC_SECRET; - key_length = 48; - key_gen_type = nsc_ssl; - break; - case CKM_PBA_SHA1_WITH_SHA1_HMAC: - case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN: - case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN: - case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN: - key_gen_type = nsc_pbe; - key_type = CKK_GENERIC_SECRET; - crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param); - break; - case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: - faultyPBE3DES = PR_TRUE; + crv = nsc_SetupBulkKeyGen(pMechanism->mechanism, &key_type, &key_length); + break; + case CKM_SSL3_PRE_MASTER_KEY_GEN: + key_type = CKK_GENERIC_SECRET; + key_length = 48; + key_gen_type = nsc_ssl; + break; + case CKM_PBA_SHA1_WITH_SHA1_HMAC: + case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN: + case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN: + case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN: + key_gen_type = nsc_pbe; + key_type = CKK_GENERIC_SECRET; + crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param); + break; + case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: + faultyPBE3DES = PR_TRUE; /* fall through */ - case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: - case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: - case CKM_NETSCAPE_PBE_SHA1_DES_CBC: - case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC: - case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4: - case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4: - case CKM_PBE_SHA1_DES3_EDE_CBC: - case CKM_PBE_SHA1_DES2_EDE_CBC: - case CKM_PBE_SHA1_RC2_128_CBC: - case CKM_PBE_SHA1_RC2_40_CBC: - case CKM_PBE_SHA1_RC4_128: - case CKM_PBE_SHA1_RC4_40: - case CKM_PBE_MD5_DES_CBC: - case CKM_PBE_MD2_DES_CBC: - case CKM_PKCS5_PBKD2: - key_gen_type = nsc_pbe; - crv = nsc_SetupPBEKeyGen(pMechanism,&pbe_param, &key_type, &key_length); - break; - case CKM_DSA_PARAMETER_GEN: - key_gen_type = nsc_param; - key_type = CKK_DSA; - objclass = CKO_KG_PARAMETERS; - crv = CKR_OK; - break; - case CKM_NSS_JPAKE_ROUND1_SHA1: hashType = HASH_AlgSHA1; goto jpake1; - case CKM_NSS_JPAKE_ROUND1_SHA256: hashType = HASH_AlgSHA256; goto jpake1; - case CKM_NSS_JPAKE_ROUND1_SHA384: hashType = HASH_AlgSHA384; goto jpake1; - case CKM_NSS_JPAKE_ROUND1_SHA512: hashType = HASH_AlgSHA512; goto jpake1; -jpake1: - key_gen_type = nsc_jpake; - key_type = CKK_NSS_JPAKE_ROUND1; - objclass = CKO_PRIVATE_KEY; - if (pMechanism->pParameter == NULL || - pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound1Params)) { - crv = CKR_MECHANISM_PARAM_INVALID; + case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: + case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: + case CKM_NETSCAPE_PBE_SHA1_DES_CBC: + case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC: + case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4: + case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4: + case CKM_PBE_SHA1_DES3_EDE_CBC: + case CKM_PBE_SHA1_DES2_EDE_CBC: + case CKM_PBE_SHA1_RC2_128_CBC: + case CKM_PBE_SHA1_RC2_40_CBC: + case CKM_PBE_SHA1_RC4_128: + case CKM_PBE_SHA1_RC4_40: + case CKM_PBE_MD5_DES_CBC: + case CKM_PBE_MD2_DES_CBC: + case CKM_PKCS5_PBKD2: + key_gen_type = nsc_pbe; + crv = nsc_SetupPBEKeyGen(pMechanism, &pbe_param, &key_type, &key_length); break; - } - if (sftk_isTrue(key, CKA_TOKEN)) { - crv = CKR_TEMPLATE_INCONSISTENT; + case CKM_DSA_PARAMETER_GEN: + key_gen_type = nsc_param; + key_type = CKK_DSA; + objclass = CKO_KG_PARAMETERS; + crv = CKR_OK; + break; + case CKM_NSS_JPAKE_ROUND1_SHA1: + hashType = HASH_AlgSHA1; + goto jpake1; + case CKM_NSS_JPAKE_ROUND1_SHA256: + hashType = HASH_AlgSHA256; + goto jpake1; + case CKM_NSS_JPAKE_ROUND1_SHA384: + hashType = HASH_AlgSHA384; + goto jpake1; + case CKM_NSS_JPAKE_ROUND1_SHA512: + hashType = HASH_AlgSHA512; + goto jpake1; + jpake1: + key_gen_type = nsc_jpake; + key_type = CKK_NSS_JPAKE_ROUND1; + objclass = CKO_PRIVATE_KEY; + if (pMechanism->pParameter == NULL || + pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound1Params)) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + if (sftk_isTrue(key, CKA_TOKEN)) { + crv = CKR_TEMPLATE_INCONSISTENT; + break; + } + crv = CKR_OK; + break; + default: + crv = CKR_MECHANISM_INVALID; break; - } - crv = CKR_OK; - break; - default: - crv = CKR_MECHANISM_INVALID; - break; } /* make sure we aren't going to overflow the buffer */ if (sizeof(buf) < key_length) { - /* someone is getting pretty optimistic about how big their key can - * be... */ + /* someone is getting pretty optimistic about how big their key can + * be... */ crv = CKR_TEMPLATE_INCONSISTENT; } - if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } + if (crv != CKR_OK) { + sftk_FreeObject(key); + return crv; + } /* if there was no error, * key_type *MUST* be set in the switch statement above */ - PORT_Assert( key_type != CKK_INVALID_KEY_TYPE ); + PORT_Assert(key_type != CKK_INVALID_KEY_TYPE); /* * now to the actual key gen. */ switch (key_gen_type) { - case nsc_pbe: - crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length, - faultyPBE3DES); - nsspkcs5_DestroyPBEParameter(pbe_param); - break; - case nsc_ssl: - rsa_pms = (SSL3RSAPreMasterSecret *)buf; - version = (CK_VERSION *)pMechanism->pParameter; - rsa_pms->client_version[0] = version->major; - rsa_pms->client_version[1] = version->minor; - crv = - NSC_GenerateRandom(0,&rsa_pms->random[0], sizeof(rsa_pms->random)); - break; - case nsc_bulk: - /* get the key, check for weak keys and repeat if found */ - do { - crv = NSC_GenerateRandom(0, buf, key_length); - } while (crv == CKR_OK && checkWeak && sftk_IsWeakKey(buf,key_type)); - break; - case nsc_param: - /* generate parameters */ - *buf = 0; - crv = nsc_parameter_gen(key_type,key); - break; - case nsc_jpake: - crv = jpake_Round1(hashType, - (CK_NSS_JPAKERound1Params *) pMechanism->pParameter, - key); - break; + case nsc_pbe: + crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length, + faultyPBE3DES); + nsspkcs5_DestroyPBEParameter(pbe_param); + break; + case nsc_ssl: + rsa_pms = (SSL3RSAPreMasterSecret *)buf; + version = (CK_VERSION *)pMechanism->pParameter; + rsa_pms->client_version[0] = version->major; + rsa_pms->client_version[1] = version->minor; + crv = + NSC_GenerateRandom(0, &rsa_pms->random[0], sizeof(rsa_pms->random)); + break; + case nsc_bulk: + /* get the key, check for weak keys and repeat if found */ + do { + crv = NSC_GenerateRandom(0, buf, key_length); + } while (crv == CKR_OK && checkWeak && sftk_IsWeakKey(buf, key_type)); + break; + case nsc_param: + /* generate parameters */ + *buf = 0; + crv = nsc_parameter_gen(key_type, key); + break; + case nsc_jpake: + crv = jpake_Round1(hashType, + (CK_NSS_JPAKERound1Params *)pMechanism->pParameter, + key); + break; } - if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } + if (crv != CKR_OK) { + sftk_FreeObject(key); + return crv; + } /* Add the class, key_type, and value */ - crv = sftk_AddAttributeType(key,CKA_CLASS,&objclass,sizeof(CK_OBJECT_CLASS)); - if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } - crv = sftk_AddAttributeType(key,CKA_KEY_TYPE,&key_type,sizeof(CK_KEY_TYPE)); - if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } + crv = sftk_AddAttributeType(key, CKA_CLASS, &objclass, sizeof(CK_OBJECT_CLASS)); + if (crv != CKR_OK) { + sftk_FreeObject(key); + return crv; + } + crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE)); + if (crv != CKR_OK) { + sftk_FreeObject(key); + return crv; + } if (key_length != 0) { - crv = sftk_AddAttributeType(key,CKA_VALUE,buf,key_length); - if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } + crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length); + if (crv != CKR_OK) { + sftk_FreeObject(key); + return crv; + } } /* get the session */ session = sftk_SessionFromHandle(hSession); if (session == NULL) { - sftk_FreeObject(key); + sftk_FreeObject(key); return CKR_SESSION_HANDLE_INVALID; } /* * handle the base object stuff */ - crv = sftk_handleObject(key,session); + crv = sftk_handleObject(key, session); sftk_FreeSession(session); - if (sftk_isTrue(key,CKA_SENSITIVE)) { - sftk_forceAttribute(key,CKA_ALWAYS_SENSITIVE,&cktrue,sizeof(CK_BBOOL)); + if (crv == CKR_OK && sftk_isTrue(key, CKA_SENSITIVE)) { + crv = sftk_forceAttribute(key, CKA_ALWAYS_SENSITIVE, &cktrue, sizeof(CK_BBOOL)); } - if (!sftk_isTrue(key,CKA_EXTRACTABLE)) { - sftk_forceAttribute(key,CKA_NEVER_EXTRACTABLE,&cktrue,sizeof(CK_BBOOL)); + if (crv == CKR_OK && !sftk_isTrue(key, CKA_EXTRACTABLE)) { + crv = sftk_forceAttribute(key, CKA_NEVER_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL)); + } + if (crv == CKR_OK) { + *phKey = key->handle; } - - *phKey = key->handle; sftk_FreeObject(key); return crv; } -#define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */ -#define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */ +#define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */ +#define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */ /* * FIPS 140-2 pairwise consistency check utilized to validate key pair. @@ -4067,7 +4366,7 @@ jpake1: */ static CK_RV sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, - SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType) + SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType) { /* * Key type Mechanism type @@ -4082,7 +4381,7 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, * * None of these mechanisms has a parameter. */ - CK_MECHANISM mech = {0, NULL, 0}; + CK_MECHANISM mech = { 0, NULL, 0 }; CK_ULONG modulusLen = 0; CK_ULONG subPrimeLen = 0; @@ -4103,146 +4402,145 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, /* Variables used for Signature/Verification functions. */ /* Must be at least 256 bits for DSA2 digest */ - unsigned char *known_digest = (unsigned char *) - "Mozilla Rules the World through NSS!"; + unsigned char *known_digest = (unsigned char *)"Mozilla Rules the World through NSS!"; unsigned char *signature; CK_ULONG signature_length; if (keyType == CKK_RSA) { - SFTKAttribute *attribute; - - /* Get modulus length of private key. */ - attribute = sftk_FindAttribute(privateKey, CKA_MODULUS); - if (attribute == NULL) { - return CKR_DEVICE_ERROR; - } - modulusLen = attribute->attrib.ulValueLen; - if (*(unsigned char *)attribute->attrib.pValue == 0) { - modulusLen--; - } - sftk_FreeAttribute(attribute); + SFTKAttribute *attribute; + + /* Get modulus length of private key. */ + attribute = sftk_FindAttribute(privateKey, CKA_MODULUS); + if (attribute == NULL) { + return CKR_DEVICE_ERROR; + } + modulusLen = attribute->attrib.ulValueLen; + if (*(unsigned char *)attribute->attrib.pValue == 0) { + modulusLen--; + } + sftk_FreeAttribute(attribute); } else if (keyType == CKK_DSA) { - SFTKAttribute *attribute; + SFTKAttribute *attribute; - /* Get subprime length of private key. */ - attribute = sftk_FindAttribute(privateKey, CKA_SUBPRIME); - if (attribute == NULL) { - return CKR_DEVICE_ERROR; - } - subPrimeLen = attribute->attrib.ulValueLen; - if (subPrimeLen > 1 && *(unsigned char *)attribute->attrib.pValue == 0) { - subPrimeLen--; - } - sftk_FreeAttribute(attribute); + /* Get subprime length of private key. */ + attribute = sftk_FindAttribute(privateKey, CKA_SUBPRIME); + if (attribute == NULL) { + return CKR_DEVICE_ERROR; + } + subPrimeLen = attribute->attrib.ulValueLen; + if (subPrimeLen > 1 && *(unsigned char *)attribute->attrib.pValue == 0) { + subPrimeLen--; + } + sftk_FreeAttribute(attribute); } /**************************************************/ /* Pairwise Consistency Check of Encrypt/Decrypt. */ /**************************************************/ - isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT); + isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT); /* * If the decryption attribute is set, attempt to encrypt * with the public key and decrypt with the private key. */ if (isEncryptable) { - if (keyType != CKK_RSA) { - return CKR_DEVICE_ERROR; - } - bytes_encrypted = modulusLen; - mech.mechanism = CKM_RSA_PKCS; - - /* Allocate space for ciphertext. */ - ciphertext = (unsigned char *) PORT_ZAlloc(bytes_encrypted); - if (ciphertext == NULL) { - return CKR_HOST_MEMORY; - } - - /* Prepare for encryption using the public key. */ - crv = NSC_EncryptInit(hSession, &mech, publicKey->handle); - if (crv != CKR_OK) { - PORT_Free(ciphertext); - return crv; - } - - /* Encrypt using the public key. */ - crv = NSC_Encrypt(hSession, - known_message, - PAIRWISE_MESSAGE_LENGTH, - ciphertext, - &bytes_encrypted); - if (crv != CKR_OK) { - PORT_Free(ciphertext); - return crv; - } - - /* Always use the smaller of these two values . . . */ - bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH); - - /* - * If there was a failure, the plaintext - * goes at the end, therefore . . . - */ - text_compared = ciphertext + bytes_encrypted - bytes_compared; - - /* - * Check to ensure that ciphertext does - * NOT EQUAL known input message text - * per FIPS PUB 140-2 directive. - */ - if (PORT_Memcmp(text_compared, known_message, - bytes_compared) == 0) { - /* Set error to Invalid PRIVATE Key. */ - PORT_SetError(SEC_ERROR_INVALID_KEY); - PORT_Free(ciphertext); - return CKR_GENERAL_ERROR; - } - - /* Prepare for decryption using the private key. */ - crv = NSC_DecryptInit(hSession, &mech, privateKey->handle); - if (crv != CKR_OK) { - PORT_Free(ciphertext); - return crv; - } - - memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH); - - /* - * Initialize bytes decrypted to be the - * expected PAIRWISE_MESSAGE_LENGTH. - */ - bytes_decrypted = PAIRWISE_MESSAGE_LENGTH; - - /* - * Decrypt using the private key. - * NOTE: No need to reset the - * value of bytes_encrypted. - */ - crv = NSC_Decrypt(hSession, - ciphertext, - bytes_encrypted, - plaintext, - &bytes_decrypted); - - /* Finished with ciphertext; free it. */ - PORT_Free(ciphertext); - - if (crv != CKR_OK) { - return crv; - } - - /* - * Check to ensure that the output plaintext - * does EQUAL known input message text. - */ - if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) || - (PORT_Memcmp(plaintext, known_message, - PAIRWISE_MESSAGE_LENGTH) != 0)) { - /* Set error to Bad PUBLIC Key. */ - PORT_SetError(SEC_ERROR_BAD_KEY); - return CKR_GENERAL_ERROR; - } + if (keyType != CKK_RSA) { + return CKR_DEVICE_ERROR; + } + bytes_encrypted = modulusLen; + mech.mechanism = CKM_RSA_PKCS; + + /* Allocate space for ciphertext. */ + ciphertext = (unsigned char *)PORT_ZAlloc(bytes_encrypted); + if (ciphertext == NULL) { + return CKR_HOST_MEMORY; + } + + /* Prepare for encryption using the public key. */ + crv = NSC_EncryptInit(hSession, &mech, publicKey->handle); + if (crv != CKR_OK) { + PORT_Free(ciphertext); + return crv; + } + + /* Encrypt using the public key. */ + crv = NSC_Encrypt(hSession, + known_message, + PAIRWISE_MESSAGE_LENGTH, + ciphertext, + &bytes_encrypted); + if (crv != CKR_OK) { + PORT_Free(ciphertext); + return crv; + } + + /* Always use the smaller of these two values . . . */ + bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH); + + /* + * If there was a failure, the plaintext + * goes at the end, therefore . . . + */ + text_compared = ciphertext + bytes_encrypted - bytes_compared; + + /* + * Check to ensure that ciphertext does + * NOT EQUAL known input message text + * per FIPS PUB 140-2 directive. + */ + if (PORT_Memcmp(text_compared, known_message, + bytes_compared) == 0) { + /* Set error to Invalid PRIVATE Key. */ + PORT_SetError(SEC_ERROR_INVALID_KEY); + PORT_Free(ciphertext); + return CKR_GENERAL_ERROR; + } + + /* Prepare for decryption using the private key. */ + crv = NSC_DecryptInit(hSession, &mech, privateKey->handle); + if (crv != CKR_OK) { + PORT_Free(ciphertext); + return crv; + } + + memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH); + + /* + * Initialize bytes decrypted to be the + * expected PAIRWISE_MESSAGE_LENGTH. + */ + bytes_decrypted = PAIRWISE_MESSAGE_LENGTH; + + /* + * Decrypt using the private key. + * NOTE: No need to reset the + * value of bytes_encrypted. + */ + crv = NSC_Decrypt(hSession, + ciphertext, + bytes_encrypted, + plaintext, + &bytes_decrypted); + + /* Finished with ciphertext; free it. */ + PORT_Free(ciphertext); + + if (crv != CKR_OK) { + return crv; + } + + /* + * Check to ensure that the output plaintext + * does EQUAL known input message text. + */ + if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) || + (PORT_Memcmp(plaintext, known_message, + PAIRWISE_MESSAGE_LENGTH) != 0)) { + /* Set error to Bad PUBLIC Key. */ + PORT_SetError(SEC_ERROR_BAD_KEY); + return CKR_GENERAL_ERROR; + } } /**********************************************/ @@ -4250,75 +4548,83 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, /**********************************************/ canSignVerify = sftk_isTrue(privateKey, CKA_SIGN); - + /* Unfortunately CKA_SIGN is always true in lg dbs. We have to check the + * actual curve to determine if we can do sign/verify. */ + if (canSignVerify && keyType == CKK_EC) { + NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(privateKey, CKK_EC, &crv); + if (privKey && privKey->u.ec.ecParams.name == ECCurve25519) { + canSignVerify = PR_FALSE; + } + } + if (canSignVerify) { - /* Determine length of signature. */ - switch (keyType) { - case CKK_RSA: - signature_length = modulusLen; - mech.mechanism = CKM_RSA_PKCS; - break; - case CKK_DSA: - signature_length = DSA_MAX_SIGNATURE_LEN; - pairwise_digest_length = subPrimeLen; - mech.mechanism = CKM_DSA; - break; + /* Determine length of signature. */ + switch (keyType) { + case CKK_RSA: + signature_length = modulusLen; + mech.mechanism = CKM_RSA_PKCS; + break; + case CKK_DSA: + signature_length = DSA_MAX_SIGNATURE_LEN; + pairwise_digest_length = subPrimeLen; + mech.mechanism = CKM_DSA; + break; #ifndef NSS_DISABLE_ECC - case CKK_EC: - signature_length = MAX_ECKEY_LEN * 2; - mech.mechanism = CKM_ECDSA; - break; + case CKK_EC: + signature_length = MAX_ECKEY_LEN * 2; + mech.mechanism = CKM_ECDSA; + break; #endif - default: - return CKR_DEVICE_ERROR; - } - - /* Allocate space for signature data. */ - signature = (unsigned char *) PORT_ZAlloc(signature_length); - if (signature == NULL) { - return CKR_HOST_MEMORY; - } - - /* Sign the known hash using the private key. */ - crv = NSC_SignInit(hSession, &mech, privateKey->handle); - if (crv != CKR_OK) { - PORT_Free(signature); - return crv; - } - - crv = NSC_Sign(hSession, - known_digest, - pairwise_digest_length, - signature, - &signature_length); - if (crv != CKR_OK) { - PORT_Free(signature); - return crv; - } - - /* Verify the known hash using the public key. */ - crv = NSC_VerifyInit(hSession, &mech, publicKey->handle); - if (crv != CKR_OK) { - PORT_Free(signature); - return crv; - } - - crv = NSC_Verify(hSession, - known_digest, - pairwise_digest_length, - signature, - signature_length); - - /* Free signature data. */ - PORT_Free(signature); - - if ((crv == CKR_SIGNATURE_LEN_RANGE) || - (crv == CKR_SIGNATURE_INVALID)) { - return CKR_GENERAL_ERROR; - } - if (crv != CKR_OK) { - return crv; - } + default: + return CKR_DEVICE_ERROR; + } + + /* Allocate space for signature data. */ + signature = (unsigned char *)PORT_ZAlloc(signature_length); + if (signature == NULL) { + return CKR_HOST_MEMORY; + } + + /* Sign the known hash using the private key. */ + crv = NSC_SignInit(hSession, &mech, privateKey->handle); + if (crv != CKR_OK) { + PORT_Free(signature); + return crv; + } + + crv = NSC_Sign(hSession, + known_digest, + pairwise_digest_length, + signature, + &signature_length); + if (crv != CKR_OK) { + PORT_Free(signature); + return crv; + } + + /* Verify the known hash using the public key. */ + crv = NSC_VerifyInit(hSession, &mech, publicKey->handle); + if (crv != CKR_OK) { + PORT_Free(signature); + return crv; + } + + crv = NSC_Verify(hSession, + known_digest, + pairwise_digest_length, + signature, + signature_length); + + /* Free signature data. */ + PORT_Free(signature); + + if ((crv == CKR_SIGNATURE_LEN_RANGE) || + (crv == CKR_SIGNATURE_INVALID)) { + return CKR_GENERAL_ERROR; + } + if (crv != CKR_OK) { + return crv; + } } /**********************************************/ @@ -4326,70 +4632,70 @@ sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, /**********************************************/ isDerivable = sftk_isTrue(privateKey, CKA_DERIVE); - - if (isDerivable) { - /* - * We are not doing consistency check for Diffie-Hellman Key - - * otherwise it would be here - * This is also true for Elliptic Curve Diffie-Hellman keys - * NOTE: EC keys are currently subjected to pairwise - * consistency check for signing/verification. - */ - /* - * FIPS 140-2 had the following pairwise consistency test for - * public and private keys used for key agreement: - * If the keys are used to perform key agreement, then the - * cryptographic module shall create a second, compatible - * key pair. The cryptographic module shall perform both - * sides of the key agreement algorithm and shall compare - * the resulting shared values. If the shared values are - * not equal, the test shall fail. - * This test was removed in Change Notice 3. - */ + if (isDerivable) { + /* + * We are not doing consistency check for Diffie-Hellman Key - + * otherwise it would be here + * This is also true for Elliptic Curve Diffie-Hellman keys + * NOTE: EC keys are currently subjected to pairwise + * consistency check for signing/verification. + */ + /* + * FIPS 140-2 had the following pairwise consistency test for + * public and private keys used for key agreement: + * If the keys are used to perform key agreement, then the + * cryptographic module shall create a second, compatible + * key pair. The cryptographic module shall perform both + * sides of the key agreement algorithm and shall compare + * the resulting shared values. If the shared values are + * not equal, the test shall fail. + * This test was removed in Change Notice 3. + */ } return CKR_OK; } -/* NSC_GenerateKeyPair generates a public-key/private-key pair, +/* NSC_GenerateKeyPair generates a public-key/private-key pair, * creating new key objects. */ -CK_RV NSC_GenerateKeyPair (CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, - CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, - CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, - CK_OBJECT_HANDLE_PTR phPrivateKey) +CK_RV +NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, + CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, + CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, + CK_OBJECT_HANDLE_PTR phPrivateKey) { - SFTKObject * publicKey,*privateKey; - SFTKSession * session; - CK_KEY_TYPE key_type; - CK_RV crv = CKR_OK; - CK_BBOOL cktrue = CK_TRUE; - SECStatus rv; - CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; - CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY; - int i; - SFTKSlot * slot = sftk_SlotFromSessionHandle(hSession); + SFTKObject *publicKey, *privateKey; + SFTKSession *session; + CK_KEY_TYPE key_type; + CK_RV crv = CKR_OK; + CK_BBOOL cktrue = CK_TRUE; + SECStatus rv; + CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; + CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY; + int i; + SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); unsigned int bitSize; /* RSA */ - int public_modulus_bits = 0; - SECItem pubExp; - RSAPrivateKey * rsaPriv; + int public_modulus_bits = 0; + SECItem pubExp; + RSAPrivateKey *rsaPriv; /* DSA */ - PQGParams pqgParam; - DHParams dhParam; - DSAPrivateKey * dsaPriv; + PQGParams pqgParam; + DHParams dhParam; + DSAPrivateKey *dsaPriv; /* Diffie Hellman */ - DHPrivateKey * dhPriv; + DHPrivateKey *dhPriv; #ifndef NSS_DISABLE_ECC /* Elliptic Curve Cryptography */ - SECItem ecEncodedParams; /* DER Encoded parameters */ - ECPrivateKey * ecPriv; - ECParams * ecParams; + SECItem ecEncodedParams; /* DER Encoded parameters */ + ECPrivateKey *ecPriv; + ECParams *ecParams; #endif /* NSS_DISABLE_ECC */ CHECK_FORK(); @@ -4402,435 +4708,462 @@ CK_RV NSC_GenerateKeyPair (CK_SESSION_HANDLE hSession, */ publicKey = sftk_NewObject(slot); /* fill in the handle later */ if (publicKey == NULL) { - return CKR_HOST_MEMORY; + return CKR_HOST_MEMORY; } /* * load the template values into the publicKey */ - for (i=0; i < (int) ulPublicKeyAttributeCount; i++) { - if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) { - public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue; - continue; - } + for (i = 0; i < (int)ulPublicKeyAttributeCount; i++) { + if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) { + public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue; + continue; + } - crv = sftk_AddAttributeType(publicKey, - sftk_attr_expand(&pPublicKeyTemplate[i])); - if (crv != CKR_OK) break; + crv = sftk_AddAttributeType(publicKey, + sftk_attr_expand(&pPublicKeyTemplate[i])); + if (crv != CKR_OK) + break; } if (crv != CKR_OK) { - sftk_FreeObject(publicKey); - return CKR_HOST_MEMORY; + sftk_FreeObject(publicKey); + return CKR_HOST_MEMORY; } privateKey = sftk_NewObject(slot); /* fill in the handle later */ if (privateKey == NULL) { - sftk_FreeObject(publicKey); - return CKR_HOST_MEMORY; + sftk_FreeObject(publicKey); + return CKR_HOST_MEMORY; } /* * now load the private key template */ - for (i=0; i < (int) ulPrivateKeyAttributeCount; i++) { - if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) { - continue; - } + for (i = 0; i < (int)ulPrivateKeyAttributeCount; i++) { + if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) { + continue; + } - crv = sftk_AddAttributeType(privateKey, - sftk_attr_expand(&pPrivateKeyTemplate[i])); - if (crv != CKR_OK) break; + crv = sftk_AddAttributeType(privateKey, + sftk_attr_expand(&pPrivateKeyTemplate[i])); + if (crv != CKR_OK) + break; } if (crv != CKR_OK) { - sftk_FreeObject(publicKey); - sftk_FreeObject(privateKey); - return CKR_HOST_MEMORY; + sftk_FreeObject(publicKey); + sftk_FreeObject(privateKey); + return CKR_HOST_MEMORY; } - sftk_DeleteAttributeType(privateKey,CKA_CLASS); - sftk_DeleteAttributeType(privateKey,CKA_KEY_TYPE); - sftk_DeleteAttributeType(privateKey,CKA_VALUE); - sftk_DeleteAttributeType(publicKey,CKA_CLASS); - sftk_DeleteAttributeType(publicKey,CKA_KEY_TYPE); - sftk_DeleteAttributeType(publicKey,CKA_VALUE); + sftk_DeleteAttributeType(privateKey, CKA_CLASS); + sftk_DeleteAttributeType(privateKey, CKA_KEY_TYPE); + sftk_DeleteAttributeType(privateKey, CKA_VALUE); + sftk_DeleteAttributeType(publicKey, CKA_CLASS); + sftk_DeleteAttributeType(publicKey, CKA_KEY_TYPE); + sftk_DeleteAttributeType(publicKey, CKA_VALUE); /* Now Set up the parameters to generate the key (based on mechanism) */ switch (pMechanism->mechanism) { - case CKM_RSA_PKCS_KEY_PAIR_GEN: - /* format the keys */ - sftk_DeleteAttributeType(publicKey,CKA_MODULUS); - sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB); - sftk_DeleteAttributeType(privateKey,CKA_MODULUS); - sftk_DeleteAttributeType(privateKey,CKA_PRIVATE_EXPONENT); - sftk_DeleteAttributeType(privateKey,CKA_PUBLIC_EXPONENT); - sftk_DeleteAttributeType(privateKey,CKA_PRIME_1); - sftk_DeleteAttributeType(privateKey,CKA_PRIME_2); - sftk_DeleteAttributeType(privateKey,CKA_EXPONENT_1); - sftk_DeleteAttributeType(privateKey,CKA_EXPONENT_2); - sftk_DeleteAttributeType(privateKey,CKA_COEFFICIENT); - key_type = CKK_RSA; - if (public_modulus_bits == 0) { - crv = CKR_TEMPLATE_INCOMPLETE; - break; - } - if (public_modulus_bits < RSA_MIN_MODULUS_BITS) { - crv = CKR_ATTRIBUTE_VALUE_INVALID; - break; - } - if (public_modulus_bits % 2 != 0) { - crv = CKR_ATTRIBUTE_VALUE_INVALID; - break; - } - - /* extract the exponent */ - crv=sftk_Attribute2SSecItem(NULL,&pubExp,publicKey,CKA_PUBLIC_EXPONENT); - if (crv != CKR_OK) break; - bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len); - if (bitSize < 2) { - crv = CKR_ATTRIBUTE_VALUE_INVALID; - break; - } - crv = sftk_AddAttributeType(privateKey,CKA_PUBLIC_EXPONENT, - sftk_item_expand(&pubExp)); - if (crv != CKR_OK) { - PORT_Free(pubExp.data); - break; - } - - rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp); - PORT_Free(pubExp.data); - if (rsaPriv == NULL) { - if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { - sftk_fatalError = PR_TRUE; - } - crv = sftk_MapCryptError(PORT_GetError()); - break; - } - /* now fill in the RSA dependent paramenters in the public key */ - crv = sftk_AddAttributeType(publicKey,CKA_MODULUS, - sftk_item_expand(&rsaPriv->modulus)); - if (crv != CKR_OK) goto kpg_done; - /* now fill in the RSA dependent paramenters in the private key */ - crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB, - sftk_item_expand(&rsaPriv->modulus)); - if (crv != CKR_OK) goto kpg_done; - crv = sftk_AddAttributeType(privateKey,CKA_MODULUS, - sftk_item_expand(&rsaPriv->modulus)); - if (crv != CKR_OK) goto kpg_done; - crv = sftk_AddAttributeType(privateKey,CKA_PRIVATE_EXPONENT, - sftk_item_expand(&rsaPriv->privateExponent)); - if (crv != CKR_OK) goto kpg_done; - crv = sftk_AddAttributeType(privateKey,CKA_PRIME_1, - sftk_item_expand(&rsaPriv->prime1)); - if (crv != CKR_OK) goto kpg_done; - crv = sftk_AddAttributeType(privateKey,CKA_PRIME_2, - sftk_item_expand(&rsaPriv->prime2)); - if (crv != CKR_OK) goto kpg_done; - crv = sftk_AddAttributeType(privateKey,CKA_EXPONENT_1, - sftk_item_expand(&rsaPriv->exponent1)); - if (crv != CKR_OK) goto kpg_done; - crv = sftk_AddAttributeType(privateKey,CKA_EXPONENT_2, - sftk_item_expand(&rsaPriv->exponent2)); - if (crv != CKR_OK) goto kpg_done; - crv = sftk_AddAttributeType(privateKey,CKA_COEFFICIENT, - sftk_item_expand(&rsaPriv->coefficient)); -kpg_done: - /* Should zeroize the contents first, since this func doesn't. */ - PORT_FreeArena(rsaPriv->arena, PR_TRUE); - break; - case CKM_DSA_KEY_PAIR_GEN: - sftk_DeleteAttributeType(publicKey,CKA_VALUE); - sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB); - sftk_DeleteAttributeType(privateKey,CKA_PRIME); - sftk_DeleteAttributeType(privateKey,CKA_SUBPRIME); - sftk_DeleteAttributeType(privateKey,CKA_BASE); - key_type = CKK_DSA; - - /* extract the necessary parameters and copy them to the private key */ - crv=sftk_Attribute2SSecItem(NULL,&pqgParam.prime,publicKey,CKA_PRIME); - if (crv != CKR_OK) break; - crv=sftk_Attribute2SSecItem(NULL,&pqgParam.subPrime,publicKey, - CKA_SUBPRIME); - if (crv != CKR_OK) { - PORT_Free(pqgParam.prime.data); - break; - } - crv=sftk_Attribute2SSecItem(NULL,&pqgParam.base,publicKey,CKA_BASE); - if (crv != CKR_OK) { - PORT_Free(pqgParam.prime.data); - PORT_Free(pqgParam.subPrime.data); - break; - } - crv = sftk_AddAttributeType(privateKey,CKA_PRIME, - sftk_item_expand(&pqgParam.prime)); - if (crv != CKR_OK) { - PORT_Free(pqgParam.prime.data); - PORT_Free(pqgParam.subPrime.data); - PORT_Free(pqgParam.base.data); - break; - } - crv = sftk_AddAttributeType(privateKey,CKA_SUBPRIME, - sftk_item_expand(&pqgParam.subPrime)); - if (crv != CKR_OK) { - PORT_Free(pqgParam.prime.data); - PORT_Free(pqgParam.subPrime.data); - PORT_Free(pqgParam.base.data); - break; - } - crv = sftk_AddAttributeType(privateKey,CKA_BASE, - sftk_item_expand(&pqgParam.base)); - if (crv != CKR_OK) { - PORT_Free(pqgParam.prime.data); - PORT_Free(pqgParam.subPrime.data); - PORT_Free(pqgParam.base.data); - break; - } - - /* - * these are checked by DSA_NewKey - */ - bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data, - pqgParam.subPrime.len); - if ((bitSize < DSA_MIN_Q_BITS) || (bitSize > DSA_MAX_Q_BITS)) { - crv = CKR_TEMPLATE_INCOMPLETE; - PORT_Free(pqgParam.prime.data); - PORT_Free(pqgParam.subPrime.data); - PORT_Free(pqgParam.base.data); - break; - } - bitSize = sftk_GetLengthInBits(pqgParam.prime.data,pqgParam.prime.len); - if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) { - crv = CKR_TEMPLATE_INCOMPLETE; - PORT_Free(pqgParam.prime.data); - PORT_Free(pqgParam.subPrime.data); - PORT_Free(pqgParam.base.data); - break; - } - bitSize = sftk_GetLengthInBits(pqgParam.base.data,pqgParam.base.len); - if ((bitSize < 2) || (bitSize > DSA_MAX_P_BITS)) { - crv = CKR_TEMPLATE_INCOMPLETE; - PORT_Free(pqgParam.prime.data); - PORT_Free(pqgParam.subPrime.data); - PORT_Free(pqgParam.base.data); - break; - } - - /* Generate the key */ - rv = DSA_NewKey(&pqgParam, &dsaPriv); - - PORT_Free(pqgParam.prime.data); - PORT_Free(pqgParam.subPrime.data); - PORT_Free(pqgParam.base.data); - - if (rv != SECSuccess) { - if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { - sftk_fatalError = PR_TRUE; - } - crv = sftk_MapCryptError(PORT_GetError()); - break; - } - - /* store the generated key into the attributes */ - crv = sftk_AddAttributeType(publicKey,CKA_VALUE, - sftk_item_expand(&dsaPriv->publicValue)); - if (crv != CKR_OK) goto dsagn_done; - - /* now fill in the RSA dependent paramenters in the private key */ - crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB, - sftk_item_expand(&dsaPriv->publicValue)); - if (crv != CKR_OK) goto dsagn_done; - crv = sftk_AddAttributeType(privateKey,CKA_VALUE, - sftk_item_expand(&dsaPriv->privateValue)); - -dsagn_done: - /* should zeroize, since this function doesn't. */ - PORT_FreeArena(dsaPriv->params.arena, PR_TRUE); - break; - - case CKM_DH_PKCS_KEY_PAIR_GEN: - sftk_DeleteAttributeType(privateKey,CKA_PRIME); - sftk_DeleteAttributeType(privateKey,CKA_BASE); - sftk_DeleteAttributeType(privateKey,CKA_VALUE); - sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB); - key_type = CKK_DH; - - /* extract the necessary parameters and copy them to private keys */ - crv = sftk_Attribute2SSecItem(NULL, &dhParam.prime, publicKey, - CKA_PRIME); - if (crv != CKR_OK) break; - crv = sftk_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE); - if (crv != CKR_OK) { - PORT_Free(dhParam.prime.data); - break; - } - crv = sftk_AddAttributeType(privateKey, CKA_PRIME, - sftk_item_expand(&dhParam.prime)); - if (crv != CKR_OK) { - PORT_Free(dhParam.prime.data); - PORT_Free(dhParam.base.data); - break; - } - crv = sftk_AddAttributeType(privateKey, CKA_BASE, - sftk_item_expand(&dhParam.base)); - if (crv != CKR_OK) { - PORT_Free(dhParam.prime.data); - PORT_Free(dhParam.base.data); - break; - } - bitSize = sftk_GetLengthInBits(dhParam.prime.data,dhParam.prime.len); - if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) { - crv = CKR_TEMPLATE_INCOMPLETE; - PORT_Free(dhParam.prime.data); - PORT_Free(dhParam.base.data); - break; - } - bitSize = sftk_GetLengthInBits(dhParam.base.data,dhParam.base.len); - if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) { - crv = CKR_TEMPLATE_INCOMPLETE; - PORT_Free(dhParam.prime.data); - PORT_Free(dhParam.base.data); - break; - } - - rv = DH_NewKey(&dhParam, &dhPriv); - PORT_Free(dhParam.prime.data); - PORT_Free(dhParam.base.data); - if (rv != SECSuccess) { - if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { - sftk_fatalError = PR_TRUE; - } - crv = sftk_MapCryptError(PORT_GetError()); - break; - } - - crv=sftk_AddAttributeType(publicKey, CKA_VALUE, - sftk_item_expand(&dhPriv->publicValue)); - if (crv != CKR_OK) goto dhgn_done; - - crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB, - sftk_item_expand(&dhPriv->publicValue)); - if (crv != CKR_OK) goto dhgn_done; - - crv=sftk_AddAttributeType(privateKey, CKA_VALUE, - sftk_item_expand(&dhPriv->privateValue)); - -dhgn_done: - /* should zeroize, since this function doesn't. */ - PORT_FreeArena(dhPriv->arena, PR_TRUE); - break; + case CKM_RSA_PKCS_KEY_PAIR_GEN: + /* format the keys */ + sftk_DeleteAttributeType(publicKey, CKA_MODULUS); + sftk_DeleteAttributeType(privateKey, CKA_NETSCAPE_DB); + sftk_DeleteAttributeType(privateKey, CKA_MODULUS); + sftk_DeleteAttributeType(privateKey, CKA_PRIVATE_EXPONENT); + sftk_DeleteAttributeType(privateKey, CKA_PUBLIC_EXPONENT); + sftk_DeleteAttributeType(privateKey, CKA_PRIME_1); + sftk_DeleteAttributeType(privateKey, CKA_PRIME_2); + sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_1); + sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_2); + sftk_DeleteAttributeType(privateKey, CKA_COEFFICIENT); + key_type = CKK_RSA; + if (public_modulus_bits == 0) { + crv = CKR_TEMPLATE_INCOMPLETE; + break; + } + if (public_modulus_bits < RSA_MIN_MODULUS_BITS) { + crv = CKR_ATTRIBUTE_VALUE_INVALID; + break; + } + if (public_modulus_bits % 2 != 0) { + crv = CKR_ATTRIBUTE_VALUE_INVALID; + break; + } + + /* extract the exponent */ + crv = sftk_Attribute2SSecItem(NULL, &pubExp, publicKey, CKA_PUBLIC_EXPONENT); + if (crv != CKR_OK) + break; + bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len); + if (bitSize < 2) { + crv = CKR_ATTRIBUTE_VALUE_INVALID; + break; + } + crv = sftk_AddAttributeType(privateKey, CKA_PUBLIC_EXPONENT, + sftk_item_expand(&pubExp)); + if (crv != CKR_OK) { + PORT_Free(pubExp.data); + break; + } + + rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp); + PORT_Free(pubExp.data); + if (rsaPriv == NULL) { + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } + crv = sftk_MapCryptError(PORT_GetError()); + break; + } + /* now fill in the RSA dependent paramenters in the public key */ + crv = sftk_AddAttributeType(publicKey, CKA_MODULUS, + sftk_item_expand(&rsaPriv->modulus)); + if (crv != CKR_OK) + goto kpg_done; + /* now fill in the RSA dependent paramenters in the private key */ + crv = sftk_AddAttributeType(privateKey, CKA_NETSCAPE_DB, + sftk_item_expand(&rsaPriv->modulus)); + if (crv != CKR_OK) + goto kpg_done; + crv = sftk_AddAttributeType(privateKey, CKA_MODULUS, + sftk_item_expand(&rsaPriv->modulus)); + if (crv != CKR_OK) + goto kpg_done; + crv = sftk_AddAttributeType(privateKey, CKA_PRIVATE_EXPONENT, + sftk_item_expand(&rsaPriv->privateExponent)); + if (crv != CKR_OK) + goto kpg_done; + crv = sftk_AddAttributeType(privateKey, CKA_PRIME_1, + sftk_item_expand(&rsaPriv->prime1)); + if (crv != CKR_OK) + goto kpg_done; + crv = sftk_AddAttributeType(privateKey, CKA_PRIME_2, + sftk_item_expand(&rsaPriv->prime2)); + if (crv != CKR_OK) + goto kpg_done; + crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_1, + sftk_item_expand(&rsaPriv->exponent1)); + if (crv != CKR_OK) + goto kpg_done; + crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_2, + sftk_item_expand(&rsaPriv->exponent2)); + if (crv != CKR_OK) + goto kpg_done; + crv = sftk_AddAttributeType(privateKey, CKA_COEFFICIENT, + sftk_item_expand(&rsaPriv->coefficient)); + kpg_done: + /* Should zeroize the contents first, since this func doesn't. */ + PORT_FreeArena(rsaPriv->arena, PR_TRUE); + break; + case CKM_DSA_KEY_PAIR_GEN: + sftk_DeleteAttributeType(publicKey, CKA_VALUE); + sftk_DeleteAttributeType(privateKey, CKA_NETSCAPE_DB); + sftk_DeleteAttributeType(privateKey, CKA_PRIME); + sftk_DeleteAttributeType(privateKey, CKA_SUBPRIME); + sftk_DeleteAttributeType(privateKey, CKA_BASE); + key_type = CKK_DSA; + + /* extract the necessary parameters and copy them to the private key */ + crv = sftk_Attribute2SSecItem(NULL, &pqgParam.prime, publicKey, CKA_PRIME); + if (crv != CKR_OK) + break; + crv = sftk_Attribute2SSecItem(NULL, &pqgParam.subPrime, publicKey, + CKA_SUBPRIME); + if (crv != CKR_OK) { + PORT_Free(pqgParam.prime.data); + break; + } + crv = sftk_Attribute2SSecItem(NULL, &pqgParam.base, publicKey, CKA_BASE); + if (crv != CKR_OK) { + PORT_Free(pqgParam.prime.data); + PORT_Free(pqgParam.subPrime.data); + break; + } + crv = sftk_AddAttributeType(privateKey, CKA_PRIME, + sftk_item_expand(&pqgParam.prime)); + if (crv != CKR_OK) { + PORT_Free(pqgParam.prime.data); + PORT_Free(pqgParam.subPrime.data); + PORT_Free(pqgParam.base.data); + break; + } + crv = sftk_AddAttributeType(privateKey, CKA_SUBPRIME, + sftk_item_expand(&pqgParam.subPrime)); + if (crv != CKR_OK) { + PORT_Free(pqgParam.prime.data); + PORT_Free(pqgParam.subPrime.data); + PORT_Free(pqgParam.base.data); + break; + } + crv = sftk_AddAttributeType(privateKey, CKA_BASE, + sftk_item_expand(&pqgParam.base)); + if (crv != CKR_OK) { + PORT_Free(pqgParam.prime.data); + PORT_Free(pqgParam.subPrime.data); + PORT_Free(pqgParam.base.data); + break; + } + + /* + * these are checked by DSA_NewKey + */ + bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data, + pqgParam.subPrime.len); + if ((bitSize < DSA_MIN_Q_BITS) || (bitSize > DSA_MAX_Q_BITS)) { + crv = CKR_TEMPLATE_INCOMPLETE; + PORT_Free(pqgParam.prime.data); + PORT_Free(pqgParam.subPrime.data); + PORT_Free(pqgParam.base.data); + break; + } + bitSize = sftk_GetLengthInBits(pqgParam.prime.data, pqgParam.prime.len); + if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) { + crv = CKR_TEMPLATE_INCOMPLETE; + PORT_Free(pqgParam.prime.data); + PORT_Free(pqgParam.subPrime.data); + PORT_Free(pqgParam.base.data); + break; + } + bitSize = sftk_GetLengthInBits(pqgParam.base.data, pqgParam.base.len); + if ((bitSize < 2) || (bitSize > DSA_MAX_P_BITS)) { + crv = CKR_TEMPLATE_INCOMPLETE; + PORT_Free(pqgParam.prime.data); + PORT_Free(pqgParam.subPrime.data); + PORT_Free(pqgParam.base.data); + break; + } + + /* Generate the key */ + rv = DSA_NewKey(&pqgParam, &dsaPriv); + + PORT_Free(pqgParam.prime.data); + PORT_Free(pqgParam.subPrime.data); + PORT_Free(pqgParam.base.data); + + if (rv != SECSuccess) { + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } + crv = sftk_MapCryptError(PORT_GetError()); + break; + } + + /* store the generated key into the attributes */ + crv = sftk_AddAttributeType(publicKey, CKA_VALUE, + sftk_item_expand(&dsaPriv->publicValue)); + if (crv != CKR_OK) + goto dsagn_done; + + /* now fill in the RSA dependent paramenters in the private key */ + crv = sftk_AddAttributeType(privateKey, CKA_NETSCAPE_DB, + sftk_item_expand(&dsaPriv->publicValue)); + if (crv != CKR_OK) + goto dsagn_done; + crv = sftk_AddAttributeType(privateKey, CKA_VALUE, + sftk_item_expand(&dsaPriv->privateValue)); + + dsagn_done: + /* should zeroize, since this function doesn't. */ + PORT_FreeArena(dsaPriv->params.arena, PR_TRUE); + break; + + case CKM_DH_PKCS_KEY_PAIR_GEN: + sftk_DeleteAttributeType(privateKey, CKA_PRIME); + sftk_DeleteAttributeType(privateKey, CKA_BASE); + sftk_DeleteAttributeType(privateKey, CKA_VALUE); + sftk_DeleteAttributeType(privateKey, CKA_NETSCAPE_DB); + key_type = CKK_DH; + + /* extract the necessary parameters and copy them to private keys */ + crv = sftk_Attribute2SSecItem(NULL, &dhParam.prime, publicKey, + CKA_PRIME); + if (crv != CKR_OK) + break; + crv = sftk_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE); + if (crv != CKR_OK) { + PORT_Free(dhParam.prime.data); + break; + } + crv = sftk_AddAttributeType(privateKey, CKA_PRIME, + sftk_item_expand(&dhParam.prime)); + if (crv != CKR_OK) { + PORT_Free(dhParam.prime.data); + PORT_Free(dhParam.base.data); + break; + } + crv = sftk_AddAttributeType(privateKey, CKA_BASE, + sftk_item_expand(&dhParam.base)); + if (crv != CKR_OK) { + PORT_Free(dhParam.prime.data); + PORT_Free(dhParam.base.data); + break; + } + bitSize = sftk_GetLengthInBits(dhParam.prime.data, dhParam.prime.len); + if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) { + crv = CKR_TEMPLATE_INCOMPLETE; + PORT_Free(dhParam.prime.data); + PORT_Free(dhParam.base.data); + break; + } + bitSize = sftk_GetLengthInBits(dhParam.base.data, dhParam.base.len); + if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) { + crv = CKR_TEMPLATE_INCOMPLETE; + PORT_Free(dhParam.prime.data); + PORT_Free(dhParam.base.data); + break; + } + + rv = DH_NewKey(&dhParam, &dhPriv); + PORT_Free(dhParam.prime.data); + PORT_Free(dhParam.base.data); + if (rv != SECSuccess) { + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } + crv = sftk_MapCryptError(PORT_GetError()); + break; + } + + crv = sftk_AddAttributeType(publicKey, CKA_VALUE, + sftk_item_expand(&dhPriv->publicValue)); + if (crv != CKR_OK) + goto dhgn_done; + + crv = sftk_AddAttributeType(privateKey, CKA_NETSCAPE_DB, + sftk_item_expand(&dhPriv->publicValue)); + if (crv != CKR_OK) + goto dhgn_done; + + crv = sftk_AddAttributeType(privateKey, CKA_VALUE, + sftk_item_expand(&dhPriv->privateValue)); + + dhgn_done: + /* should zeroize, since this function doesn't. */ + PORT_FreeArena(dhPriv->arena, PR_TRUE); + break; #ifndef NSS_DISABLE_ECC - case CKM_EC_KEY_PAIR_GEN: - sftk_DeleteAttributeType(privateKey,CKA_EC_PARAMS); - sftk_DeleteAttributeType(privateKey,CKA_VALUE); - sftk_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB); - key_type = CKK_EC; - - /* extract the necessary parameters and copy them to private keys */ - crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey, - CKA_EC_PARAMS); - if (crv != CKR_OK) break; - - crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS, - sftk_item_expand(&ecEncodedParams)); - if (crv != CKR_OK) { - PORT_Free(ecEncodedParams.data); - break; - } - - /* Decode ec params before calling EC_NewKey */ - rv = EC_DecodeParams(&ecEncodedParams, &ecParams); - PORT_Free(ecEncodedParams.data); - if (rv != SECSuccess) { - crv = sftk_MapCryptError(PORT_GetError()); - break; - } - rv = EC_NewKey(ecParams, &ecPriv); - PORT_FreeArena(ecParams->arena, PR_TRUE); - if (rv != SECSuccess) { - if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { - sftk_fatalError = PR_TRUE; - } - crv = sftk_MapCryptError(PORT_GetError()); - break; - } - - if (getenv("NSS_USE_DECODED_CKA_EC_POINT")) { - crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, - sftk_item_expand(&ecPriv->publicValue)); - } else { - SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, - &ecPriv->publicValue, - SEC_ASN1_GET(SEC_OctetStringTemplate)); - if (!pubValue) { - crv = CKR_ARGUMENTS_BAD; - goto ecgn_done; - } - crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, - sftk_item_expand(pubValue)); - SECITEM_FreeItem(pubValue, PR_TRUE); - } - if (crv != CKR_OK) goto ecgn_done; - - crv = sftk_AddAttributeType(privateKey, CKA_VALUE, - sftk_item_expand(&ecPriv->privateValue)); - if (crv != CKR_OK) goto ecgn_done; - - crv = sftk_AddAttributeType(privateKey,CKA_NETSCAPE_DB, - sftk_item_expand(&ecPriv->publicValue)); -ecgn_done: - /* should zeroize, since this function doesn't. */ - PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE); - break; + case CKM_EC_KEY_PAIR_GEN: + sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS); + sftk_DeleteAttributeType(privateKey, CKA_VALUE); + sftk_DeleteAttributeType(privateKey, CKA_NETSCAPE_DB); + key_type = CKK_EC; + + /* extract the necessary parameters and copy them to private keys */ + crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey, + CKA_EC_PARAMS); + if (crv != CKR_OK) + break; + + crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS, + sftk_item_expand(&ecEncodedParams)); + if (crv != CKR_OK) { + PORT_Free(ecEncodedParams.data); + break; + } + + /* Decode ec params before calling EC_NewKey */ + rv = EC_DecodeParams(&ecEncodedParams, &ecParams); + PORT_Free(ecEncodedParams.data); + if (rv != SECSuccess) { + crv = sftk_MapCryptError(PORT_GetError()); + break; + } + rv = EC_NewKey(ecParams, &ecPriv); + if (rv != SECSuccess) { + if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { + sftk_fatalError = PR_TRUE; + } + PORT_FreeArena(ecParams->arena, PR_TRUE); + crv = sftk_MapCryptError(PORT_GetError()); + break; + } + + if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") || + ecParams->fieldID.type == ec_field_plain) { + PORT_FreeArena(ecParams->arena, PR_TRUE); + crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, + sftk_item_expand(&ecPriv->publicValue)); + } else { + PORT_FreeArena(ecParams->arena, PR_TRUE); + SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, + &ecPriv->publicValue, + SEC_ASN1_GET(SEC_OctetStringTemplate)); + if (!pubValue) { + crv = CKR_ARGUMENTS_BAD; + goto ecgn_done; + } + crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT, + sftk_item_expand(pubValue)); + SECITEM_FreeItem(pubValue, PR_TRUE); + } + if (crv != CKR_OK) + goto ecgn_done; + + crv = sftk_AddAttributeType(privateKey, CKA_VALUE, + sftk_item_expand(&ecPriv->privateValue)); + if (crv != CKR_OK) + goto ecgn_done; + + crv = sftk_AddAttributeType(privateKey, CKA_NETSCAPE_DB, + sftk_item_expand(&ecPriv->publicValue)); + ecgn_done: + /* should zeroize, since this function doesn't. */ + PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE); + break; #endif /* NSS_DISABLE_ECC */ - default: - crv = CKR_MECHANISM_INVALID; + default: + crv = CKR_MECHANISM_INVALID; } if (crv != CKR_OK) { - sftk_FreeObject(privateKey); - sftk_FreeObject(publicKey); - return crv; + sftk_FreeObject(privateKey); + sftk_FreeObject(publicKey); + return crv; } - /* Add the class, key_type The loop lets us check errors blow out * on errors and clean up at the bottom */ session = NULL; /* make pedtantic happy... session cannot leave the*/ - /* loop below NULL unless an error is set... */ + /* loop below NULL unless an error is set... */ do { - crv = sftk_AddAttributeType(privateKey,CKA_CLASS,&privClass, - sizeof(CK_OBJECT_CLASS)); - if (crv != CKR_OK) break; - crv = sftk_AddAttributeType(publicKey,CKA_CLASS,&pubClass, - sizeof(CK_OBJECT_CLASS)); - if (crv != CKR_OK) break; - crv = sftk_AddAttributeType(privateKey,CKA_KEY_TYPE,&key_type, - sizeof(CK_KEY_TYPE)); - if (crv != CKR_OK) break; - crv = sftk_AddAttributeType(publicKey,CKA_KEY_TYPE,&key_type, - sizeof(CK_KEY_TYPE)); - if (crv != CKR_OK) break; + crv = sftk_AddAttributeType(privateKey, CKA_CLASS, &privClass, + sizeof(CK_OBJECT_CLASS)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &pubClass, + sizeof(CK_OBJECT_CLASS)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(privateKey, CKA_KEY_TYPE, &key_type, + sizeof(CK_KEY_TYPE)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &key_type, + sizeof(CK_KEY_TYPE)); + if (crv != CKR_OK) + break; session = sftk_SessionFromHandle(hSession); - if (session == NULL) crv = CKR_SESSION_HANDLE_INVALID; + if (session == NULL) + crv = CKR_SESSION_HANDLE_INVALID; } while (0); if (crv != CKR_OK) { - sftk_FreeObject(privateKey); - sftk_FreeObject(publicKey); - return crv; + sftk_FreeObject(privateKey); + sftk_FreeObject(publicKey); + return crv; } /* * handle the base object cleanup for the public Key */ - crv = sftk_handleObject(privateKey,session); + crv = sftk_handleObject(privateKey, session); if (crv != CKR_OK) { sftk_FreeSession(session); - sftk_FreeObject(privateKey); - sftk_FreeObject(publicKey); - return crv; + sftk_FreeObject(privateKey); + sftk_FreeObject(publicKey); + return crv; } /* @@ -4838,50 +5171,55 @@ ecgn_done: * If we have any problems, we destroy the public Key we've * created and linked. */ - crv = sftk_handleObject(publicKey,session); + crv = sftk_handleObject(publicKey, session); sftk_FreeSession(session); if (crv != CKR_OK) { - sftk_FreeObject(publicKey); - NSC_DestroyObject(hSession,privateKey->handle); - sftk_FreeObject(privateKey); - return crv; + sftk_FreeObject(publicKey); + NSC_DestroyObject(hSession, privateKey->handle); + sftk_FreeObject(privateKey); + return crv; } - if (sftk_isTrue(privateKey,CKA_SENSITIVE)) { - sftk_forceAttribute(privateKey,CKA_ALWAYS_SENSITIVE, - &cktrue,sizeof(CK_BBOOL)); + if (sftk_isTrue(privateKey, CKA_SENSITIVE)) { + crv = sftk_forceAttribute(privateKey, CKA_ALWAYS_SENSITIVE, + &cktrue, sizeof(CK_BBOOL)); } - if (sftk_isTrue(publicKey,CKA_SENSITIVE)) { - sftk_forceAttribute(publicKey,CKA_ALWAYS_SENSITIVE, - &cktrue,sizeof(CK_BBOOL)); + if (crv == CKR_OK && sftk_isTrue(publicKey, CKA_SENSITIVE)) { + crv = sftk_forceAttribute(publicKey, CKA_ALWAYS_SENSITIVE, + &cktrue, sizeof(CK_BBOOL)); } - if (!sftk_isTrue(privateKey,CKA_EXTRACTABLE)) { - sftk_forceAttribute(privateKey,CKA_NEVER_EXTRACTABLE, - &cktrue,sizeof(CK_BBOOL)); + if (crv == CKR_OK && !sftk_isTrue(privateKey, CKA_EXTRACTABLE)) { + crv = sftk_forceAttribute(privateKey, CKA_NEVER_EXTRACTABLE, + &cktrue, sizeof(CK_BBOOL)); } - if (!sftk_isTrue(publicKey,CKA_EXTRACTABLE)) { - sftk_forceAttribute(publicKey,CKA_NEVER_EXTRACTABLE, - &cktrue,sizeof(CK_BBOOL)); + if (crv == CKR_OK && !sftk_isTrue(publicKey, CKA_EXTRACTABLE)) { + crv = sftk_forceAttribute(publicKey, CKA_NEVER_EXTRACTABLE, + &cktrue, sizeof(CK_BBOOL)); + } + + if (crv == CKR_OK) { + /* Perform FIPS 140-2 pairwise consistency check. */ + crv = sftk_PairwiseConsistencyCheck(hSession, + publicKey, privateKey, key_type); + if (crv != CKR_OK) { + if (sftk_audit_enabled) { + char msg[128]; + PR_snprintf(msg, sizeof msg, + "C_GenerateKeyPair(hSession=0x%08lX, " + "pMechanism->mechanism=0x%08lX)=0x%08lX " + "self-test: pair-wise consistency test failed", + (PRUint32)hSession, (PRUint32)pMechanism->mechanism, + (PRUint32)crv); + sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg); + } + } } - /* Perform FIPS 140-2 pairwise consistency check. */ - crv = sftk_PairwiseConsistencyCheck(hSession, - publicKey, privateKey, key_type); if (crv != CKR_OK) { - NSC_DestroyObject(hSession,publicKey->handle); - sftk_FreeObject(publicKey); - NSC_DestroyObject(hSession,privateKey->handle); - sftk_FreeObject(privateKey); - if (sftk_audit_enabled) { - char msg[128]; - PR_snprintf(msg,sizeof msg, - "C_GenerateKeyPair(hSession=0x%08lX, " - "pMechanism->mechanism=0x%08lX)=0x%08lX " - "self-test: pair-wise consistency test failed", - (PRUint32)hSession,(PRUint32)pMechanism->mechanism, - (PRUint32)crv); - sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg); - } - return crv; + NSC_DestroyObject(hSession, publicKey->handle); + sftk_FreeObject(publicKey); + NSC_DestroyObject(hSession, privateKey->handle); + sftk_FreeObject(privateKey); + return crv; } *phPrivateKey = privateKey->handle; @@ -4892,7 +5230,8 @@ ecgn_done: return CKR_OK; } -static SECItem *sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp) +static SECItem * +sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp) { NSSLOWKEYPrivateKey *lk = NULL; NSSLOWKEYPrivateKeyInfo *pki = NULL; @@ -4909,159 +5248,162 @@ static SECItem *sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp) int savelen; #endif - if(!key) { - *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */ - return NULL; + if (!key) { + *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */ + return NULL; } attribute = sftk_FindAttribute(key, CKA_KEY_TYPE); - if(!attribute) { - *crvp = CKR_KEY_TYPE_INCONSISTENT; - return NULL; + if (!attribute) { + *crvp = CKR_KEY_TYPE_INCONSISTENT; + return NULL; } lk = sftk_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue, crvp); sftk_FreeAttribute(attribute); - if(!lk) { - return NULL; + if (!lk) { + return NULL; } - arena = PORT_NewArena(2048); /* XXX different size? */ - if(!arena) { - *crvp = CKR_HOST_MEMORY; - rv = SECFailure; - goto loser; + arena = PORT_NewArena(2048); /* XXX different size? */ + if (!arena) { + *crvp = CKR_HOST_MEMORY; + rv = SECFailure; + goto loser; } - pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena, - sizeof(NSSLOWKEYPrivateKeyInfo)); - if(!pki) { - *crvp = CKR_HOST_MEMORY; - rv = SECFailure; - goto loser; + pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena, + sizeof(NSSLOWKEYPrivateKeyInfo)); + if (!pki) { + *crvp = CKR_HOST_MEMORY; + rv = SECFailure; + goto loser; } pki->arena = arena; param = NULL; - switch(lk->keyType) { - case NSSLOWKEYRSAKey: - prepare_low_rsa_priv_key_for_asn1(lk); - dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, - nsslowkey_RSAPrivateKeyTemplate); - algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; - break; - case NSSLOWKEYDSAKey: + switch (lk->keyType) { + case NSSLOWKEYRSAKey: + prepare_low_rsa_priv_key_for_asn1(lk); + dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, + nsslowkey_RSAPrivateKeyTemplate); + algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION; + break; + case NSSLOWKEYDSAKey: prepare_low_dsa_priv_key_export_for_asn1(lk); - dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, - nsslowkey_DSAPrivateKeyExportTemplate); - prepare_low_pqg_params_for_asn1(&lk->u.dsa.params); - param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params), - nsslowkey_PQGParamsTemplate); - algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE; - break; + dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, + nsslowkey_DSAPrivateKeyExportTemplate); + prepare_low_pqg_params_for_asn1(&lk->u.dsa.params); + param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params), + nsslowkey_PQGParamsTemplate); + algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE; + break; #ifndef NSS_DISABLE_ECC case NSSLOWKEYECKey: prepare_low_ec_priv_key_for_asn1(lk); - /* Public value is encoded as a bit string so adjust length - * to be in bits before ASN encoding and readjust - * immediately after. - * - * Since the SECG specification recommends not including the - * parameters as part of ECPrivateKey, we zero out the curveOID - * length before encoding and restore it later. - */ - lk->u.ec.publicValue.len <<= 3; - savelen = lk->u.ec.ecParams.curveOID.len; - lk->u.ec.ecParams.curveOID.len = 0; - dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, - nsslowkey_ECPrivateKeyTemplate); - lk->u.ec.ecParams.curveOID.len = savelen; - lk->u.ec.publicValue.len >>= 3; + /* Public value is encoded as a bit string so adjust length + * to be in bits before ASN encoding and readjust + * immediately after. + * + * Since the SECG specification recommends not including the + * parameters as part of ECPrivateKey, we zero out the curveOID + * length before encoding and restore it later. + */ + lk->u.ec.publicValue.len <<= 3; + savelen = lk->u.ec.ecParams.curveOID.len; + lk->u.ec.ecParams.curveOID.len = 0; + dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, + nsslowkey_ECPrivateKeyTemplate); + lk->u.ec.ecParams.curveOID.len = savelen; + lk->u.ec.publicValue.len >>= 3; #ifdef EC_DEBUG - fordebug = &pki->privateKey; - SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk->keyType, - fordebug); + fordebug = &pki->privateKey; + SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk->keyType, + fordebug); #endif - param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding); + param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding); - algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY; - break; + algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY; + break; #endif /* NSS_DISABLE_ECC */ - case NSSLOWKEYDHKey: - default: - dummy = NULL; - break; - } - - if(!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) { - *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ - rv = SECFailure; - goto loser; - } - - rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm, - (SECItem*)param); - if(rv != SECSuccess) { - *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ - rv = SECFailure; - goto loser; + case NSSLOWKEYDHKey: + default: + dummy = NULL; + break; + } + + if (!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) { + *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ + rv = SECFailure; + goto loser; + } + + rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm, + (SECItem *)param); + if (rv != SECSuccess) { + *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ + rv = SECFailure; + goto loser; } dummy = SEC_ASN1EncodeInteger(arena, &pki->version, - NSSLOWKEY_PRIVATE_KEY_INFO_VERSION); - if(!dummy) { - *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ - rv = SECFailure; - goto loser; + NSSLOWKEY_PRIVATE_KEY_INFO_VERSION); + if (!dummy) { + *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */ + rv = SECFailure; + goto loser; } - encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki, - nsslowkey_PrivateKeyInfoTemplate); + encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki, + nsslowkey_PrivateKeyInfoTemplate); *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR; #ifdef EC_DEBUG fordebug = encodedKey; SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKeyInfo", lk->keyType, - fordebug); + fordebug); #endif loser: - if(arena) { - PORT_FreeArena(arena, PR_TRUE); + if (arena) { + PORT_FreeArena(arena, PR_TRUE); } - if(lk && (lk != key->objectInfo)) { - nsslowkey_DestroyPrivateKey(lk); + if (lk && (lk != key->objectInfo)) { + nsslowkey_DestroyPrivateKey(lk); } - - if(param) { - SECITEM_ZfreeItem((SECItem*)param, PR_TRUE); + + if (param) { + SECITEM_ZfreeItem((SECItem *)param, PR_TRUE); } - if(rv != SECSuccess) { - return NULL; + if (rv != SECSuccess) { + return NULL; } return encodedKey; } - + /* it doesn't matter yet, since we colapse error conditions in the * level above, but we really should map those few key error differences */ -static CK_RV -sftk_mapWrap(CK_RV crv) -{ +static CK_RV +sftk_mapWrap(CK_RV crv) +{ switch (crv) { - case CKR_ENCRYPTED_DATA_INVALID: crv = CKR_WRAPPED_KEY_INVALID; break; + case CKR_ENCRYPTED_DATA_INVALID: + crv = CKR_WRAPPED_KEY_INVALID; + break; } - return crv; + return crv; } /* NSC_WrapKey wraps (i.e., encrypts) a key. */ -CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, - CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, - CK_ULONG_PTR pulWrappedKeyLen) +CK_RV +NSC_WrapKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, + CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, + CK_ULONG_PTR pulWrappedKeyLen) { SFTKSession *session; SFTKAttribute *attribute; @@ -5072,117 +5414,115 @@ CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession, session = sftk_SessionFromHandle(hSession); if (session == NULL) { - return CKR_SESSION_HANDLE_INVALID; + return CKR_SESSION_HANDLE_INVALID; } - key = sftk_ObjectFromHandle(hKey,session); + key = sftk_ObjectFromHandle(hKey, session); sftk_FreeSession(session); if (key == NULL) { - return CKR_KEY_HANDLE_INVALID; - } - - switch(key->objclass) { - case CKO_SECRET_KEY: - { - SFTKSessionContext *context = NULL; - SECItem pText; - - attribute = sftk_FindAttribute(key,CKA_VALUE); - - if (attribute == NULL) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey, - CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE); - if (crv != CKR_OK) { - sftk_FreeAttribute(attribute); - break; - } - - pText.type = siBuffer; - pText.data = (unsigned char *)attribute->attrib.pValue; - pText.len = attribute->attrib.ulValueLen; - - /* Find out if this is a block cipher. */ - crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_FALSE,NULL); - if (crv != CKR_OK || !context) - break; - if (context->blockSize > 1) { - unsigned int remainder = pText.len % context->blockSize; - if (!context->doPad && remainder) { - /* When wrapping secret keys with unpadded block ciphers, - ** the keys are zero padded, if necessary, to fill out - ** a full block. - */ - pText.len += context->blockSize - remainder; - pText.data = PORT_ZAlloc(pText.len); - if (pText.data) - memcpy(pText.data, attribute->attrib.pValue, - attribute->attrib.ulValueLen); - else { - crv = CKR_HOST_MEMORY; - break; - } - } - } - - crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data, - pText.len, pWrappedKey, pulWrappedKeyLen); - /* always force a finalize, both on errors and when - * we are just getting the size */ - if (crv != CKR_OK || pWrappedKey == NULL) { - CK_RV lcrv ; - lcrv = sftk_GetContext(hSession,&context, - SFTK_ENCRYPT,PR_FALSE,NULL); - sftk_SetContextByType(session, SFTK_ENCRYPT, NULL); - if (lcrv == CKR_OK && context) { - sftk_FreeContext(context); - } - } - - if (pText.data != (unsigned char *)attribute->attrib.pValue) - PORT_ZFree(pText.data, pText.len); - sftk_FreeAttribute(attribute); - break; - } - - case CKO_PRIVATE_KEY: - { - SECItem *bpki = sftk_PackagePrivateKey(key, &crv); - SFTKSessionContext *context = NULL; - - if(!bpki) { - break; - } - - crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey, - CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE); - if(crv != CKR_OK) { - SECITEM_ZfreeItem(bpki, PR_TRUE); - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - - crv = NSC_Encrypt(hSession, bpki->data, bpki->len, - pWrappedKey, pulWrappedKeyLen); - /* always force a finalize */ - if (crv != CKR_OK || pWrappedKey == NULL) { - CK_RV lcrv ; - lcrv = sftk_GetContext(hSession,&context, - SFTK_ENCRYPT,PR_FALSE,NULL); - sftk_SetContextByType(session, SFTK_ENCRYPT, NULL); - if (lcrv == CKR_OK && context) { - sftk_FreeContext(context); - } - } - SECITEM_ZfreeItem(bpki, PR_TRUE); - break; - } - - default: - crv = CKR_KEY_TYPE_INCONSISTENT; - break; + return CKR_KEY_HANDLE_INVALID; + } + + switch (key->objclass) { + case CKO_SECRET_KEY: { + SFTKSessionContext *context = NULL; + SECItem pText; + + attribute = sftk_FindAttribute(key, CKA_VALUE); + + if (attribute == NULL) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey, + CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE); + if (crv != CKR_OK) { + sftk_FreeAttribute(attribute); + break; + } + + pText.type = siBuffer; + pText.data = (unsigned char *)attribute->attrib.pValue; + pText.len = attribute->attrib.ulValueLen; + + /* Find out if this is a block cipher. */ + crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, NULL); + if (crv != CKR_OK || !context) + break; + if (context->blockSize > 1) { + unsigned int remainder = pText.len % context->blockSize; + if (!context->doPad && remainder) { + /* When wrapping secret keys with unpadded block ciphers, + ** the keys are zero padded, if necessary, to fill out + ** a full block. + */ + pText.len += context->blockSize - remainder; + pText.data = PORT_ZAlloc(pText.len); + if (pText.data) + memcpy(pText.data, attribute->attrib.pValue, + attribute->attrib.ulValueLen); + else { + crv = CKR_HOST_MEMORY; + break; + } + } + } + + crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data, + pText.len, pWrappedKey, pulWrappedKeyLen); + /* always force a finalize, both on errors and when + * we are just getting the size */ + if (crv != CKR_OK || pWrappedKey == NULL) { + CK_RV lcrv; + lcrv = sftk_GetContext(hSession, &context, + SFTK_ENCRYPT, PR_FALSE, NULL); + sftk_SetContextByType(session, SFTK_ENCRYPT, NULL); + if (lcrv == CKR_OK && context) { + sftk_FreeContext(context); + } + } + + if (pText.data != (unsigned char *)attribute->attrib.pValue) + PORT_ZFree(pText.data, pText.len); + sftk_FreeAttribute(attribute); + break; + } + + case CKO_PRIVATE_KEY: { + SECItem *bpki = sftk_PackagePrivateKey(key, &crv); + SFTKSessionContext *context = NULL; + + if (!bpki) { + break; + } + + crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey, + CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE); + if (crv != CKR_OK) { + SECITEM_ZfreeItem(bpki, PR_TRUE); + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + + crv = NSC_Encrypt(hSession, bpki->data, bpki->len, + pWrappedKey, pulWrappedKeyLen); + /* always force a finalize */ + if (crv != CKR_OK || pWrappedKey == NULL) { + CK_RV lcrv; + lcrv = sftk_GetContext(hSession, &context, + SFTK_ENCRYPT, PR_FALSE, NULL); + sftk_SetContextByType(session, SFTK_ENCRYPT, NULL); + if (lcrv == CKR_OK && context) { + sftk_FreeContext(context); + } + } + SECITEM_ZfreeItem(bpki, PR_TRUE); + break; + } + + default: + crv = CKR_KEY_TYPE_INCONSISTENT; + break; } sftk_FreeObject(key); @@ -5195,7 +5535,7 @@ CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession, static SECStatus sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki) { - CK_BBOOL cktrue = CK_TRUE; + CK_BBOOL cktrue = CK_TRUE; CK_KEY_TYPE keyType = CKK_RSA; SECStatus rv = SECFailure; const SEC_ASN1Template *keyTemplate, *paramTemplate; @@ -5206,66 +5546,65 @@ sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki) CK_RV crv = CKR_KEY_TYPE_INCONSISTENT; arena = PORT_NewArena(2048); - if(!arena) { - return SECFailure; + if (!arena) { + return SECFailure; } - pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena, - sizeof(NSSLOWKEYPrivateKeyInfo)); - if(!pki) { - PORT_FreeArena(arena, PR_FALSE); - return SECFailure; + pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena, + sizeof(NSSLOWKEYPrivateKeyInfo)); + if (!pki) { + PORT_FreeArena(arena, PR_FALSE); + return SECFailure; } - if(SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki) - != SECSuccess) { - PORT_FreeArena(arena, PR_TRUE); - return SECFailure; + if (SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki) != SECSuccess) { + PORT_FreeArena(arena, PR_TRUE); + return SECFailure; } lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena, - sizeof(NSSLOWKEYPrivateKey)); - if(lpk == NULL) { - goto loser; + sizeof(NSSLOWKEYPrivateKey)); + if (lpk == NULL) { + goto loser; } lpk->arena = arena; - switch(SECOID_GetAlgorithmTag(&pki->algorithm)) { - case SEC_OID_PKCS1_RSA_ENCRYPTION: - keyTemplate = nsslowkey_RSAPrivateKeyTemplate; - paramTemplate = NULL; - paramDest = NULL; - lpk->keyType = NSSLOWKEYRSAKey; - prepare_low_rsa_priv_key_for_asn1(lpk); - break; - case SEC_OID_ANSIX9_DSA_SIGNATURE: - keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate; - paramTemplate = nsslowkey_PQGParamsTemplate; - paramDest = &(lpk->u.dsa.params); - lpk->keyType = NSSLOWKEYDSAKey; - prepare_low_dsa_priv_key_export_for_asn1(lpk); - prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params); - break; - /* case NSSLOWKEYDHKey: */ + switch (SECOID_GetAlgorithmTag(&pki->algorithm)) { + case SEC_OID_PKCS1_RSA_ENCRYPTION: + keyTemplate = nsslowkey_RSAPrivateKeyTemplate; + paramTemplate = NULL; + paramDest = NULL; + lpk->keyType = NSSLOWKEYRSAKey; + prepare_low_rsa_priv_key_for_asn1(lpk); + break; + case SEC_OID_ANSIX9_DSA_SIGNATURE: + keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate; + paramTemplate = nsslowkey_PQGParamsTemplate; + paramDest = &(lpk->u.dsa.params); + lpk->keyType = NSSLOWKEYDSAKey; + prepare_low_dsa_priv_key_export_for_asn1(lpk); + prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params); + break; +/* case NSSLOWKEYDHKey: */ #ifndef NSS_DISABLE_ECC case SEC_OID_ANSIX962_EC_PUBLIC_KEY: - keyTemplate = nsslowkey_ECPrivateKeyTemplate; - paramTemplate = NULL; - paramDest = &(lpk->u.ec.ecParams.DEREncoding); - lpk->keyType = NSSLOWKEYECKey; - prepare_low_ec_priv_key_for_asn1(lpk); - prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams); - break; + keyTemplate = nsslowkey_ECPrivateKeyTemplate; + paramTemplate = NULL; + paramDest = &(lpk->u.ec.ecParams.DEREncoding); + lpk->keyType = NSSLOWKEYECKey; + prepare_low_ec_priv_key_for_asn1(lpk); + prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams); + break; #endif /* NSS_DISABLE_ECC */ - default: - keyTemplate = NULL; - paramTemplate = NULL; - paramDest = NULL; - break; + default: + keyTemplate = NULL; + paramTemplate = NULL; + paramDest = NULL; + break; } - if(!keyTemplate) { - goto loser; + if (!keyTemplate) { + goto loser; } /* decode the private key and any algorithm parameters */ @@ -5274,165 +5613,190 @@ sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki) #ifndef NSS_DISABLE_ECC if (lpk->keyType == NSSLOWKEYECKey) { /* convert length in bits to length in bytes */ - lpk->u.ec.publicValue.len >>= 3; - rv = SECITEM_CopyItem(arena, - &(lpk->u.ec.ecParams.DEREncoding), - &(pki->algorithm.parameters)); - if(rv != SECSuccess) { - goto loser; - } + lpk->u.ec.publicValue.len >>= 3; + rv = SECITEM_CopyItem(arena, + &(lpk->u.ec.ecParams.DEREncoding), + &(pki->algorithm.parameters)); + if (rv != SECSuccess) { + goto loser; + } } #endif /* NSS_DISABLE_ECC */ - if(rv != SECSuccess) { - goto loser; + if (rv != SECSuccess) { + goto loser; } - if(paramDest && paramTemplate) { - rv = SEC_QuickDERDecodeItem(arena, paramDest, paramTemplate, - &(pki->algorithm.parameters)); - if(rv != SECSuccess) { - goto loser; - } + if (paramDest && paramTemplate) { + rv = SEC_QuickDERDecodeItem(arena, paramDest, paramTemplate, + &(pki->algorithm.parameters)); + if (rv != SECSuccess) { + goto loser; + } } rv = SECFailure; switch (lpk->keyType) { case NSSLOWKEYRSAKey: - keyType = CKK_RSA; - if(sftk_hasAttribute(key, CKA_NETSCAPE_DB)) { - sftk_DeleteAttributeType(key, CKA_NETSCAPE_DB); - } - crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, - sizeof(keyType)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_UNWRAP, &cktrue, - sizeof(CK_BBOOL)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_DECRYPT, &cktrue, - sizeof(CK_BBOOL)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, - sizeof(CK_BBOOL)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, - sizeof(CK_BBOOL)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_MODULUS, - sftk_item_expand(&lpk->u.rsa.modulus)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_PUBLIC_EXPONENT, - sftk_item_expand(&lpk->u.rsa.publicExponent)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_PRIVATE_EXPONENT, - sftk_item_expand(&lpk->u.rsa.privateExponent)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_PRIME_1, - sftk_item_expand(&lpk->u.rsa.prime1)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_PRIME_2, - sftk_item_expand(&lpk->u.rsa.prime2)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_EXPONENT_1, - sftk_item_expand(&lpk->u.rsa.exponent1)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_EXPONENT_2, - sftk_item_expand(&lpk->u.rsa.exponent2)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_COEFFICIENT, - sftk_item_expand(&lpk->u.rsa.coefficient)); - break; + keyType = CKK_RSA; + if (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) { + sftk_DeleteAttributeType(key, CKA_NETSCAPE_DB); + } + crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, + sizeof(keyType)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_UNWRAP, &cktrue, + sizeof(CK_BBOOL)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_DECRYPT, &cktrue, + sizeof(CK_BBOOL)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, + sizeof(CK_BBOOL)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, + sizeof(CK_BBOOL)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_MODULUS, + sftk_item_expand(&lpk->u.rsa.modulus)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_PUBLIC_EXPONENT, + sftk_item_expand(&lpk->u.rsa.publicExponent)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_PRIVATE_EXPONENT, + sftk_item_expand(&lpk->u.rsa.privateExponent)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_PRIME_1, + sftk_item_expand(&lpk->u.rsa.prime1)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_PRIME_2, + sftk_item_expand(&lpk->u.rsa.prime2)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_EXPONENT_1, + sftk_item_expand(&lpk->u.rsa.exponent1)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_EXPONENT_2, + sftk_item_expand(&lpk->u.rsa.exponent2)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_COEFFICIENT, + sftk_item_expand(&lpk->u.rsa.coefficient)); + break; case NSSLOWKEYDSAKey: - keyType = CKK_DSA; - crv = (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK : - CKR_KEY_TYPE_INCONSISTENT; - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, - sizeof(keyType)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, - sizeof(CK_BBOOL)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, - sizeof(CK_BBOOL)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_PRIME, - sftk_item_expand(&lpk->u.dsa.params.prime)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_SUBPRIME, - sftk_item_expand(&lpk->u.dsa.params.subPrime)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_BASE, - sftk_item_expand(&lpk->u.dsa.params.base)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_VALUE, - sftk_item_expand(&lpk->u.dsa.privateValue)); - if(crv != CKR_OK) break; - break; + keyType = CKK_DSA; + crv = (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT; + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, + sizeof(keyType)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, + sizeof(CK_BBOOL)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, + sizeof(CK_BBOOL)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_PRIME, + sftk_item_expand(&lpk->u.dsa.params.prime)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_SUBPRIME, + sftk_item_expand(&lpk->u.dsa.params.subPrime)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_BASE, + sftk_item_expand(&lpk->u.dsa.params.base)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_VALUE, + sftk_item_expand(&lpk->u.dsa.privateValue)); + if (crv != CKR_OK) + break; + break; #ifdef notdef case NSSLOWKEYDHKey: - template = dhTemplate; - templateCount = sizeof(dhTemplate)/sizeof(CK_ATTRIBUTE); - keyType = CKK_DH; - break; + template = dhTemplate; + templateCount = sizeof(dhTemplate) / sizeof(CK_ATTRIBUTE); + keyType = CKK_DH; + break; #endif - /* what about fortezza??? */ +/* what about fortezza??? */ #ifndef NSS_DISABLE_ECC case NSSLOWKEYECKey: - keyType = CKK_EC; - crv = (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK : - CKR_KEY_TYPE_INCONSISTENT; - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, - sizeof(keyType)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, - sizeof(CK_BBOOL)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, - sizeof(CK_BBOOL)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue, - sizeof(CK_BBOOL)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_EC_PARAMS, - sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding)); - if(crv != CKR_OK) break; - crv = sftk_AddAttributeType(key, CKA_VALUE, - sftk_item_expand(&lpk->u.ec.privateValue)); - if(crv != CKR_OK) break; - /* XXX Do we need to decode the EC Params here ?? */ - break; + keyType = CKK_EC; + crv = (sftk_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT; + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType, + sizeof(keyType)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue, + sizeof(CK_BBOOL)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, + sizeof(CK_BBOOL)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue, + sizeof(CK_BBOOL)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_EC_PARAMS, + sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding)); + if (crv != CKR_OK) + break; + crv = sftk_AddAttributeType(key, CKA_VALUE, + sftk_item_expand(&lpk->u.ec.privateValue)); + if (crv != CKR_OK) + break; + /* XXX Do we need to decode the EC Params here ?? */ + break; #endif /* NSS_DISABLE_ECC */ - default: - crv = CKR_KEY_TYPE_INCONSISTENT; - break; + default: + crv = CKR_KEY_TYPE_INCONSISTENT; + break; } loser: - if(lpk) { - nsslowkey_DestroyPrivateKey(lpk); + if (lpk) { + nsslowkey_DestroyPrivateKey(lpk); } - if(crv != CKR_OK) { - return SECFailure; + if (crv != CKR_OK) { + return SECFailure; } return SECSuccess; } - /* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */ -CK_RV NSC_UnwrapKey(CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, - CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, - CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, - CK_OBJECT_HANDLE_PTR phKey) +CK_RV +NSC_UnwrapKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, + CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, + CK_OBJECT_HANDLE_PTR phKey) { SFTKObject *key = NULL; SFTKSession *session; CK_ULONG key_length = 0; - unsigned char * buf = NULL; + unsigned char *buf = NULL; CK_RV crv = CKR_OK; int i; CK_ULONG bsize = ulWrappedKeyLen; @@ -5450,99 +5814,102 @@ CK_RV NSC_UnwrapKey(CK_SESSION_HANDLE hSession, */ key = sftk_NewObject(slot); /* fill in the handle later */ if (key == NULL) { - return CKR_HOST_MEMORY; + return CKR_HOST_MEMORY; } /* * load the template values into the object */ - for (i=0; i < (int) ulAttributeCount; i++) { - if (pTemplate[i].type == CKA_VALUE_LEN) { - key_length = *(CK_ULONG *)pTemplate[i].pValue; - continue; - } + for (i = 0; i < (int)ulAttributeCount; i++) { + if (pTemplate[i].type == CKA_VALUE_LEN) { + key_length = *(CK_ULONG *)pTemplate[i].pValue; + continue; + } if (pTemplate[i].type == CKA_CLASS) { - target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue; - } - crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i])); - if (crv != CKR_OK) break; + target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue; + } + crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i])); + if (crv != CKR_OK) + break; } if (crv != CKR_OK) { - sftk_FreeObject(key); - return crv; + sftk_FreeObject(key); + return crv; } - crv = sftk_CryptInit(hSession,pMechanism,hUnwrappingKey,CKA_UNWRAP, - CKA_UNWRAP, SFTK_DECRYPT, PR_FALSE); + crv = sftk_CryptInit(hSession, pMechanism, hUnwrappingKey, CKA_UNWRAP, + CKA_UNWRAP, SFTK_DECRYPT, PR_FALSE); if (crv != CKR_OK) { - sftk_FreeObject(key); - return sftk_mapWrap(crv); + sftk_FreeObject(key); + return sftk_mapWrap(crv); } - /* allocate the buffer to decrypt into + /* allocate the buffer to decrypt into * this assumes the unwrapped key is never larger than the * wrapped key. For all the mechanisms we support this is true */ - buf = (unsigned char *)PORT_Alloc( ulWrappedKeyLen); + buf = (unsigned char *)PORT_Alloc(ulWrappedKeyLen); bsize = ulWrappedKeyLen; crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize); if (crv != CKR_OK) { - sftk_FreeObject(key); - PORT_Free(buf); - return sftk_mapWrap(crv); - } - - switch(target_type) { - case CKO_SECRET_KEY: - if (!sftk_hasAttribute(key,CKA_KEY_TYPE)) { - crv = CKR_TEMPLATE_INCOMPLETE; - break; - } - - if (key_length == 0 || key_length > bsize) { - key_length = bsize; - } - if (key_length > MAX_KEY_LEN) { - crv = CKR_TEMPLATE_INCONSISTENT; - break; - } - - /* add the value */ - crv = sftk_AddAttributeType(key,CKA_VALUE,buf,key_length); - break; - case CKO_PRIVATE_KEY: - bpki.data = (unsigned char *)buf; - bpki.len = bsize; - crv = CKR_OK; - if(sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) { - crv = CKR_TEMPLATE_INCOMPLETE; - } - break; - default: - crv = CKR_TEMPLATE_INCONSISTENT; - break; + sftk_FreeObject(key); + PORT_Free(buf); + return sftk_mapWrap(crv); + } + + switch (target_type) { + case CKO_SECRET_KEY: + if (!sftk_hasAttribute(key, CKA_KEY_TYPE)) { + crv = CKR_TEMPLATE_INCOMPLETE; + break; + } + + if (key_length == 0 || key_length > bsize) { + key_length = bsize; + } + if (key_length > MAX_KEY_LEN) { + crv = CKR_TEMPLATE_INCONSISTENT; + break; + } + + /* add the value */ + crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length); + break; + case CKO_PRIVATE_KEY: + bpki.data = (unsigned char *)buf; + bpki.len = bsize; + crv = CKR_OK; + if (sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) { + crv = CKR_TEMPLATE_INCOMPLETE; + } + break; + default: + crv = CKR_TEMPLATE_INCONSISTENT; + break; } PORT_ZFree(buf, bsize); - if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } + if (crv != CKR_OK) { + sftk_FreeObject(key); + return crv; + } /* get the session */ session = sftk_SessionFromHandle(hSession); if (session == NULL) { - sftk_FreeObject(key); + sftk_FreeObject(key); return CKR_SESSION_HANDLE_INVALID; } /* * handle the base object stuff */ - crv = sftk_handleObject(key,session); + crv = sftk_handleObject(key, session); *phKey = key->handle; sftk_FreeSession(session); sftk_FreeObject(key); return crv; - } /* @@ -5550,9 +5917,9 @@ CK_RV NSC_UnwrapKey(CK_SESSION_HANDLE hSession, * details of each of these key creation. */ static CK_RV -sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey, - PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize, - CK_OBJECT_HANDLE *keyHandle) +sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey, + PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize, + CK_OBJECT_HANDLE *keyHandle) { SFTKObject *key; SFTKSession *session; @@ -5565,43 +5932,57 @@ sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey, * now lets create an object to hang the attributes off of */ *keyHandle = CK_INVALID_HANDLE; - key = sftk_NewObject(baseKey->slot); - if (key == NULL) return CKR_HOST_MEMORY; + key = sftk_NewObject(baseKey->slot); + if (key == NULL) + return CKR_HOST_MEMORY; sftk_narrowToSessionObject(key)->wasDerived = PR_TRUE; - crv = sftk_CopyObject(key,baseKey); - if (crv != CKR_OK) goto loser; + crv = sftk_CopyObject(key, baseKey); + if (crv != CKR_OK) + goto loser; if (isMacKey) { - crv = sftk_forceAttribute(key,CKA_KEY_TYPE,&keyType,sizeof(keyType)); - if (crv != CKR_OK) goto loser; - crv = sftk_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL)); - if (crv != CKR_OK) goto loser; - crv = sftk_forceAttribute(key,CKA_ENCRYPT,&ckfalse,sizeof(CK_BBOOL)); - if (crv != CKR_OK) goto loser; - crv = sftk_forceAttribute(key,CKA_DECRYPT,&ckfalse,sizeof(CK_BBOOL)); - if (crv != CKR_OK) goto loser; - crv = sftk_forceAttribute(key,CKA_SIGN,&cktrue,sizeof(CK_BBOOL)); - if (crv != CKR_OK) goto loser; - crv = sftk_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL)); - if (crv != CKR_OK) goto loser; - crv = sftk_forceAttribute(key,CKA_WRAP,&ckfalse,sizeof(CK_BBOOL)); - if (crv != CKR_OK) goto loser; - crv = sftk_forceAttribute(key,CKA_UNWRAP,&ckfalse,sizeof(CK_BBOOL)); - if (crv != CKR_OK) goto loser; - } - crv = sftk_forceAttribute(key,CKA_VALUE,keyBlock,keySize); - if (crv != CKR_OK) goto loser; + crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType)); + if (crv != CKR_OK) + goto loser; + crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); + if (crv != CKR_OK) + goto loser; + crv = sftk_forceAttribute(key, CKA_ENCRYPT, &ckfalse, sizeof(CK_BBOOL)); + if (crv != CKR_OK) + goto loser; + crv = sftk_forceAttribute(key, CKA_DECRYPT, &ckfalse, sizeof(CK_BBOOL)); + if (crv != CKR_OK) + goto loser; + crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); + if (crv != CKR_OK) + goto loser; + crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); + if (crv != CKR_OK) + goto loser; + crv = sftk_forceAttribute(key, CKA_WRAP, &ckfalse, sizeof(CK_BBOOL)); + if (crv != CKR_OK) + goto loser; + crv = sftk_forceAttribute(key, CKA_UNWRAP, &ckfalse, sizeof(CK_BBOOL)); + if (crv != CKR_OK) + goto loser; + } + crv = sftk_forceAttribute(key, CKA_VALUE, keyBlock, keySize); + if (crv != CKR_OK) + goto loser; /* get the session */ crv = CKR_HOST_MEMORY; session = sftk_SessionFromHandle(hSession); - if (session == NULL) { goto loser; } + if (session == NULL) { + goto loser; + } - crv = sftk_handleObject(key,session); + crv = sftk_handleObject(key, session); sftk_FreeSession(session); *keyHandle = key->handle; loser: - if (key) sftk_FreeObject(key); + if (key) + sftk_FreeObject(key); return crv; } @@ -5611,20 +5992,20 @@ loser: */ static void sftk_freeSSLKeys(CK_SESSION_HANDLE session, - CK_SSL3_KEY_MAT_OUT *returnedMaterial ) + CK_SSL3_KEY_MAT_OUT *returnedMaterial) { - if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) { - NSC_DestroyObject(session,returnedMaterial->hClientMacSecret); - } - if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) { - NSC_DestroyObject(session, returnedMaterial->hServerMacSecret); - } - if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) { - NSC_DestroyObject(session, returnedMaterial->hClientKey); - } - if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) { - NSC_DestroyObject(session, returnedMaterial->hServerKey); - } + if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) { + NSC_DestroyObject(session, returnedMaterial->hClientMacSecret); + } + if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) { + NSC_DestroyObject(session, returnedMaterial->hServerMacSecret); + } + if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) { + NSC_DestroyObject(session, returnedMaterial->hClientKey); + } + if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) { + NSC_DestroyObject(session, returnedMaterial->hServerKey); + } } /* @@ -5633,7 +6014,7 @@ sftk_freeSSLKeys(CK_SESSION_HANDLE session, * semantics. */ static CK_RV -sftk_DeriveSensitiveCheck(SFTKObject *baseKey,SFTKObject *destKey) +sftk_DeriveSensitiveCheck(SFTKObject *baseKey, SFTKObject *destKey) { PRBool hasSensitive; PRBool sensitive = PR_FALSE; @@ -5643,46 +6024,49 @@ sftk_DeriveSensitiveCheck(SFTKObject *baseKey,SFTKObject *destKey) SFTKAttribute *att; hasSensitive = PR_FALSE; - att = sftk_FindAttribute(destKey,CKA_SENSITIVE); + att = sftk_FindAttribute(destKey, CKA_SENSITIVE); if (att) { hasSensitive = PR_TRUE; - sensitive = (PRBool) *(CK_BBOOL *)att->attrib.pValue; - sftk_FreeAttribute(att); + sensitive = (PRBool) * (CK_BBOOL *)att->attrib.pValue; + sftk_FreeAttribute(att); } hasExtractable = PR_FALSE; - att = sftk_FindAttribute(destKey,CKA_EXTRACTABLE); + att = sftk_FindAttribute(destKey, CKA_EXTRACTABLE); if (att) { hasExtractable = PR_TRUE; - extractable = (PRBool) *(CK_BBOOL *)att->attrib.pValue; - sftk_FreeAttribute(att); + extractable = (PRBool) * (CK_BBOOL *)att->attrib.pValue; + sftk_FreeAttribute(att); } - /* don't make a key more accessible */ - if (sftk_isTrue(baseKey,CKA_SENSITIVE) && hasSensitive && - (sensitive == PR_FALSE)) { - return CKR_KEY_FUNCTION_NOT_PERMITTED; + if (sftk_isTrue(baseKey, CKA_SENSITIVE) && hasSensitive && + (sensitive == PR_FALSE)) { + return CKR_KEY_FUNCTION_NOT_PERMITTED; } - if (!sftk_isTrue(baseKey,CKA_EXTRACTABLE) && hasExtractable && - (extractable == PR_TRUE)) { - return CKR_KEY_FUNCTION_NOT_PERMITTED; + if (!sftk_isTrue(baseKey, CKA_EXTRACTABLE) && hasExtractable && + (extractable == PR_TRUE)) { + return CKR_KEY_FUNCTION_NOT_PERMITTED; } /* inherit parent's sensitivity */ if (!hasSensitive) { - att = sftk_FindAttribute(baseKey,CKA_SENSITIVE); - if (att == NULL) return CKR_KEY_TYPE_INCONSISTENT; - crv = sftk_defaultAttribute(destKey,sftk_attr_expand(&att->attrib)); - sftk_FreeAttribute(att); - if (crv != CKR_OK) return crv; + att = sftk_FindAttribute(baseKey, CKA_SENSITIVE); + if (att == NULL) + return CKR_KEY_TYPE_INCONSISTENT; + crv = sftk_defaultAttribute(destKey, sftk_attr_expand(&att->attrib)); + sftk_FreeAttribute(att); + if (crv != CKR_OK) + return crv; } if (!hasExtractable) { - att = sftk_FindAttribute(baseKey,CKA_EXTRACTABLE); - if (att == NULL) return CKR_KEY_TYPE_INCONSISTENT; - crv = sftk_defaultAttribute(destKey,sftk_attr_expand(&att->attrib)); - sftk_FreeAttribute(att); - if (crv != CKR_OK) return crv; + att = sftk_FindAttribute(baseKey, CKA_EXTRACTABLE); + if (att == NULL) + return CKR_KEY_TYPE_INCONSISTENT; + crv = sftk_defaultAttribute(destKey, sftk_attr_expand(&att->attrib)); + sftk_FreeAttribute(att); + if (crv != CKR_OK) + return crv; } /* we should inherit the parent's always extractable/ never sensitive info, @@ -5693,22 +6077,22 @@ sftk_DeriveSensitiveCheck(SFTKObject *baseKey,SFTKObject *destKey) /* * make known fixed PKCS #11 key types to their sizes in bytes - */ + */ unsigned long -sftk_MapKeySize(CK_KEY_TYPE keyType) +sftk_MapKeySize(CK_KEY_TYPE keyType) { switch (keyType) { - case CKK_CDMF: - return 8; - case CKK_DES: - return 8; - case CKK_DES2: - return 16; - case CKK_DES3: - return 24; - /* IDEA and CAST need to be added */ - default: - break; + case CKK_CDMF: + return 8; + case CKK_DES: + return 8; + case CKK_DES2: + return 16; + case CKK_DES3: + return 24; + /* IDEA and CAST need to be added */ + default: + break; } return 0; } @@ -5724,10 +6108,11 @@ sftk_MapKeySize(CK_KEY_TYPE keyType) * Output: * key: Pointer to a buffer containing derived key, if return value is SECSuccess. */ -static CK_RV sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECItem *SharedSecret, - CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen, - SECStatus Hash(unsigned char *, const unsigned char *, PRUint32), - CK_ULONG HashLen) +static CK_RV +sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECItem *SharedSecret, + CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen, + SECStatus Hash(unsigned char *, const unsigned char *, PRUint32), + CK_ULONG HashLen) { unsigned char *buffer = NULL, *output_buffer = NULL; PRUint32 buffer_len, max_counter, i; @@ -5738,26 +6123,26 @@ static CK_RV sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECIte * greatly increased if the code below did not limit the 4-byte counter * to a maximum value of 255. */ if (key_len > 254 * HashLen) - return CKR_ARGUMENTS_BAD; + return CKR_ARGUMENTS_BAD; if (SharedInfo == NULL) - SharedInfoLen = 0; + SharedInfoLen = 0; buffer_len = SharedSecret->len + 4 + SharedInfoLen; buffer = (CK_BYTE *)PORT_Alloc(buffer_len); if (buffer == NULL) { - crv = CKR_HOST_MEMORY; - goto loser; + crv = CKR_HOST_MEMORY; + goto loser; } - max_counter = key_len/HashLen; + max_counter = key_len / HashLen; if (key_len > max_counter * HashLen) - max_counter++; + max_counter++; output_buffer = (CK_BYTE *)PORT_Alloc(max_counter * HashLen); if (output_buffer == NULL) { - crv = CKR_HOST_MEMORY; - goto loser; + crv = CKR_HOST_MEMORY; + goto loser; } /* Populate buffer with SharedSecret || Counter || [SharedInfo] @@ -5768,61 +6153,62 @@ static CK_RV sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECIte buffer[SharedSecret->len + 2] = 0; buffer[SharedSecret->len + 3] = 1; if (SharedInfo) { - PORT_Memcpy(&buffer[SharedSecret->len + 4], SharedInfo, SharedInfoLen); + PORT_Memcpy(&buffer[SharedSecret->len + 4], SharedInfo, SharedInfoLen); } - for(i=0; i < max_counter; i++) { - rv = Hash(&output_buffer[i * HashLen], buffer, buffer_len); - if (rv != SECSuccess) { - /* 'Hash' should not fail. */ - crv = CKR_FUNCTION_FAILED; - goto loser; - } + for (i = 0; i < max_counter; i++) { + rv = Hash(&output_buffer[i * HashLen], buffer, buffer_len); + if (rv != SECSuccess) { + /* 'Hash' should not fail. */ + crv = CKR_FUNCTION_FAILED; + goto loser; + } - /* Increment counter (assumes max_counter < 255) */ - buffer[SharedSecret->len + 3]++; + /* Increment counter (assumes max_counter < 255) */ + buffer[SharedSecret->len + 3]++; } PORT_ZFree(buffer, buffer_len); if (key_len < max_counter * HashLen) { - PORT_Memset(output_buffer + key_len, 0, max_counter * HashLen - key_len); + PORT_Memset(output_buffer + key_len, 0, max_counter * HashLen - key_len); } *key = output_buffer; return CKR_OK; - loser: - if (buffer) { - PORT_ZFree(buffer, buffer_len); - } - if (output_buffer) { - PORT_ZFree(output_buffer, max_counter * HashLen); - } - return crv; +loser: + if (buffer) { + PORT_ZFree(buffer, buffer_len); + } + if (output_buffer) { + PORT_ZFree(output_buffer, max_counter * HashLen); + } + return crv; } -static CK_RV sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, - SECItem *SharedSecret, - CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen, - CK_EC_KDF_TYPE kdf) +static CK_RV +sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, + SECItem *SharedSecret, + CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen, + CK_EC_KDF_TYPE kdf) { if (kdf == CKD_SHA1_KDF) - return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, - SharedInfoLen, SHA1_HashBuf, SHA1_LENGTH); + return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, + SharedInfoLen, SHA1_HashBuf, SHA1_LENGTH); else if (kdf == CKD_SHA224_KDF) - return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, - SharedInfoLen, SHA224_HashBuf, SHA224_LENGTH); + return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, + SharedInfoLen, SHA224_HashBuf, SHA224_LENGTH); else if (kdf == CKD_SHA256_KDF) - return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, - SharedInfoLen, SHA256_HashBuf, SHA256_LENGTH); + return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, + SharedInfoLen, SHA256_HashBuf, SHA256_LENGTH); else if (kdf == CKD_SHA384_KDF) - return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, - SharedInfoLen, SHA384_HashBuf, SHA384_LENGTH); + return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, + SharedInfoLen, SHA384_HashBuf, SHA384_LENGTH); else if (kdf == CKD_SHA512_KDF) - return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, - SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH); + return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo, + SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH); else - return CKR_MECHANISM_INVALID; + return CKR_MECHANISM_INVALID; } #endif /* NSS_DISABLE_ECC */ @@ -5830,59 +6216,59 @@ static CK_RV sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, * SSL Key generation given pre master secret */ #define NUM_MIXERS 9 -static const char * const mixers[NUM_MIXERS] = { - "A", - "BB", - "CCC", - "DDDD", - "EEEEE", - "FFFFFF", +static const char *const mixers[NUM_MIXERS] = { + "A", + "BB", + "CCC", + "DDDD", + "EEEEE", + "FFFFFF", "GGGGGGG", "HHHHHHHH", - "IIIIIIIII" }; + "IIIIIIIII" +}; #define SSL3_PMS_LENGTH 48 #define SSL3_MASTER_SECRET_LENGTH 48 #define SSL3_RANDOM_LENGTH 32 - /* NSC_DeriveKey derives a key from a base key, creating a new key object. */ -CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, - CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, - CK_OBJECT_HANDLE_PTR phKey) +CK_RV +NSC_DeriveKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, + CK_OBJECT_HANDLE_PTR phKey) { - SFTKSession * session; - SFTKSlot * slot = sftk_SlotFromSessionHandle(hSession); - SFTKObject * key; - SFTKObject * sourceKey; - SFTKAttribute * att = NULL; - SFTKAttribute * att2 = NULL; - unsigned char * buf; - SHA1Context * sha; - MD5Context * md5; - MD2Context * md2; - CK_ULONG macSize; - CK_ULONG tmpKeySize; - CK_ULONG IVSize; - CK_ULONG keySize = 0; - CK_RV crv = CKR_OK; - CK_BBOOL cktrue = CK_TRUE; - CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; - CK_OBJECT_CLASS classType = CKO_SECRET_KEY; + SFTKSession *session; + SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); + SFTKObject *key; + SFTKObject *sourceKey; + SFTKAttribute *att = NULL; + SFTKAttribute *att2 = NULL; + unsigned char *buf; + SHA1Context *sha; + MD5Context *md5; + MD2Context *md2; + CK_ULONG macSize; + CK_ULONG tmpKeySize; + CK_ULONG IVSize; + CK_ULONG keySize = 0; + CK_RV crv = CKR_OK; + CK_BBOOL cktrue = CK_TRUE; + CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; + CK_OBJECT_CLASS classType = CKO_SECRET_KEY; CK_KEY_DERIVATION_STRING_DATA *stringPtr; CK_MECHANISM_TYPE mechanism = pMechanism->mechanism; - PRBool isTLS = PR_FALSE; - PRBool isDH = PR_FALSE; - HASH_HashType tlsPrfHash = HASH_AlgNULL; - SECStatus rv; - int i; - unsigned int outLen; - unsigned char sha_out[SHA1_LENGTH]; - unsigned char key_block[NUM_MIXERS * MD5_LENGTH]; - unsigned char key_block2[MD5_LENGTH]; - PRBool isFIPS; - HASH_HashType hashType; - PRBool extractValue = PR_TRUE; + PRBool isTLS = PR_FALSE; + PRBool isDH = PR_FALSE; + HASH_HashType tlsPrfHash = HASH_AlgNULL; + SECStatus rv; + int i; + unsigned int outLen; + unsigned char sha_out[SHA1_LENGTH]; + unsigned char key_block[NUM_MIXERS * SFTK_MAX_MAC_LENGTH]; + PRBool isFIPS; + HASH_HashType hashType; + PRBool extractValue = PR_TRUE; CHECK_FORK(); @@ -5892,75 +6278,80 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, /* * now lets create an object to hang the attributes off of */ - if (phKey) *phKey = CK_INVALID_HANDLE; + if (phKey) + *phKey = CK_INVALID_HANDLE; key = sftk_NewObject(slot); /* fill in the handle later */ if (key == NULL) { - return CKR_HOST_MEMORY; + return CKR_HOST_MEMORY; } isFIPS = (slot->slotID == FIPS_SLOT_ID); /* * load the template values into the object */ - for (i=0; i < (int) ulAttributeCount; i++) { - crv = sftk_AddAttributeType(key,sftk_attr_expand(&pTemplate[i])); - if (crv != CKR_OK) break; + for (i = 0; i < (int)ulAttributeCount; i++) { + crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i])); + if (crv != CKR_OK) + break; - if (pTemplate[i].type == CKA_KEY_TYPE) { - keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue; - } - if (pTemplate[i].type == CKA_VALUE_LEN) { - keySize = *(CK_ULONG *)pTemplate[i].pValue; - } + if (pTemplate[i].type == CKA_KEY_TYPE) { + keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue; + } + if (pTemplate[i].type == CKA_VALUE_LEN) { + keySize = *(CK_ULONG *)pTemplate[i].pValue; + } + } + if (crv != CKR_OK) { + sftk_FreeObject(key); + return crv; } - if (crv != CKR_OK) { sftk_FreeObject(key); return crv; } if (keySize == 0) { - keySize = sftk_MapKeySize(keyType); + keySize = sftk_MapKeySize(keyType); } switch (mechanism) { - case CKM_NSS_JPAKE_ROUND2_SHA1: /* fall through */ - case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */ - case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */ - case CKM_NSS_JPAKE_ROUND2_SHA512: - extractValue = PR_FALSE; - classType = CKO_PRIVATE_KEY; - break; - case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */ - case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */ - case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */ - case CKM_NSS_JPAKE_FINAL_SHA512: - extractValue = PR_FALSE; - /* fall through */ - default: - classType = CKO_SECRET_KEY; - } - - crv = sftk_forceAttribute (key,CKA_CLASS,&classType,sizeof(classType)); + case CKM_NSS_JPAKE_ROUND2_SHA1: /* fall through */ + case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */ + case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */ + case CKM_NSS_JPAKE_ROUND2_SHA512: + extractValue = PR_FALSE; + classType = CKO_PRIVATE_KEY; + break; + case CKM_NSS_JPAKE_FINAL_SHA1: /* fall through */ + case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */ + case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */ + case CKM_NSS_JPAKE_FINAL_SHA512: + extractValue = PR_FALSE; + /* fall through */ + default: + classType = CKO_SECRET_KEY; + } + + crv = sftk_forceAttribute(key, CKA_CLASS, &classType, sizeof(classType)); if (crv != CKR_OK) { - sftk_FreeObject(key); - return crv; + sftk_FreeObject(key); + return crv; } - /* look up the base key we're deriving with */ + /* look up the base key we're deriving with */ session = sftk_SessionFromHandle(hSession); if (session == NULL) { - sftk_FreeObject(key); + sftk_FreeObject(key); return CKR_SESSION_HANDLE_INVALID; } - sourceKey = sftk_ObjectFromHandle(hBaseKey,session); + sourceKey = sftk_ObjectFromHandle(hBaseKey, session); sftk_FreeSession(session); if (sourceKey == NULL) { - sftk_FreeObject(key); + sftk_FreeObject(key); return CKR_KEY_HANDLE_INVALID; } if (extractValue) { /* get the value of the base key */ - att = sftk_FindAttribute(sourceKey,CKA_VALUE); + att = sftk_FindAttribute(sourceKey, CKA_VALUE); if (att == NULL) { sftk_FreeObject(key); sftk_FreeObject(sourceKey); @@ -5969,1283 +6360,1197 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, } switch (mechanism) { - /* - * generate the master secret - */ - case CKM_TLS12_MASTER_KEY_DERIVE: - case CKM_TLS12_MASTER_KEY_DERIVE_DH: - case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256: - case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256: - case CKM_TLS_MASTER_KEY_DERIVE: - case CKM_TLS_MASTER_KEY_DERIVE_DH: - case CKM_SSL3_MASTER_KEY_DERIVE: - case CKM_SSL3_MASTER_KEY_DERIVE_DH: - { - CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master; - SSL3RSAPreMasterSecret * rsa_pms; - unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; - - if ((mechanism == CKM_TLS12_MASTER_KEY_DERIVE) || - (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) { - CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tls12_master = - (CK_TLS12_MASTER_KEY_DERIVE_PARAMS *) pMechanism->pParameter; - tlsPrfHash = GetHashTypeFromMechanism(tls12_master->prfHashMechanism); - if (tlsPrfHash == HASH_AlgNULL) { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - } else if ((mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256) || - (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) { - tlsPrfHash = HASH_AlgSHA256; - } - - if ((mechanism != CKM_SSL3_MASTER_KEY_DERIVE) && - (mechanism != CKM_SSL3_MASTER_KEY_DERIVE_DH)) { - isTLS = PR_TRUE; - } - if ((mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) || - (mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) || - (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256) || - (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) { - isDH = PR_TRUE; - } - - /* first do the consistency checks */ - if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - att2 = sftk_FindAttribute(sourceKey,CKA_KEY_TYPE); - if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != - CKK_GENERIC_SECRET)) { - if (att2) sftk_FreeAttribute(att2); - crv = CKR_KEY_FUNCTION_NOT_PERMITTED; - break; - } - sftk_FreeAttribute(att2); - if (keyType != CKK_GENERIC_SECRET) { - crv = CKR_KEY_FUNCTION_NOT_PERMITTED; - break; - } - if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) { - crv = CKR_KEY_FUNCTION_NOT_PERMITTED; - break; - } - - /* finally do the key gen */ - ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *) - pMechanism->pParameter; - - PORT_Memcpy(crsrdata, - ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); - PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, - ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); - - if (ssl3_master->pVersion) { - SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); - rsa_pms = (SSL3RSAPreMasterSecret *) att->attrib.pValue; - /* don't leak more key material then necessary for SSL to work */ - if ((sessKey == NULL) || sessKey->wasDerived) { - ssl3_master->pVersion->major = 0xff; - ssl3_master->pVersion->minor = 0xff; - } else { - ssl3_master->pVersion->major = rsa_pms->client_version[0]; - ssl3_master->pVersion->minor = rsa_pms->client_version[1]; - } - } - if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - - if (isTLS) { - SECStatus status; - SECItem crsr = { siBuffer, NULL, 0 }; - SECItem master = { siBuffer, NULL, 0 }; - SECItem pms = { siBuffer, NULL, 0 }; - - crsr.data = crsrdata; - crsr.len = sizeof crsrdata; - master.data = key_block; - master.len = SSL3_MASTER_SECRET_LENGTH; - pms.data = (unsigned char*)att->attrib.pValue; - pms.len = att->attrib.ulValueLen; - - if (tlsPrfHash != HASH_AlgNULL) { - status = TLS_P_hash(tlsPrfHash, &pms, "master secret", - &crsr, &master, isFIPS); - } else { - status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS); - } - if (status != SECSuccess) { - crv = CKR_FUNCTION_FAILED; - break; - } - } else { - /* now allocate the hash contexts */ - md5 = MD5_NewContext(); - if (md5 == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - sha = SHA1_NewContext(); - if (sha == NULL) { - PORT_Free(md5); - crv = CKR_HOST_MEMORY; - break; - } - for (i = 0; i < 3; i++) { - SHA1_Begin(sha); - SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i])); - SHA1_Update(sha, (const unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen); - SHA1_Update(sha, crsrdata, sizeof crsrdata); - SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); - PORT_Assert(outLen == SHA1_LENGTH); - - MD5_Begin(md5); - MD5_Update(md5, (const unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen); - MD5_Update(md5, sha_out, outLen); - MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH); - PORT_Assert(outLen == MD5_LENGTH); - } - PORT_Free(md5); - PORT_Free(sha); - } - - /* store the results */ - crv = sftk_forceAttribute - (key,CKA_VALUE,key_block,SSL3_MASTER_SECRET_LENGTH); - if (crv != CKR_OK) break; - keyType = CKK_GENERIC_SECRET; - crv = sftk_forceAttribute (key,CKA_KEY_TYPE,&keyType,sizeof(keyType)); - if (isTLS) { - /* TLS's master secret is used to "sign" finished msgs with PRF. */ - /* XXX This seems like a hack. But SFTK_Derive only accepts - * one "operation" argument. */ - crv = sftk_forceAttribute(key,CKA_SIGN, &cktrue,sizeof(CK_BBOOL)); - if (crv != CKR_OK) break; - crv = sftk_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL)); - if (crv != CKR_OK) break; - /* While we're here, we might as well force this, too. */ - crv = sftk_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL)); - if (crv != CKR_OK) break; - } - break; - } - - /* Extended master key derivation [draft-ietf-tls-session-hash] */ - case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE: - case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH: - { - CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *ems_params; - SSL3RSAPreMasterSecret *rsa_pms; - SECStatus status; - SECItem pms = { siBuffer, NULL, 0 }; - SECItem seed = { siBuffer, NULL, 0 }; - SECItem master = { siBuffer, NULL, 0 }; - - ems_params = (CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS*) - pMechanism->pParameter; - - /* First do the consistency checks */ - if ((mechanism == CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE) && - (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { - crv = CKR_KEY_TYPE_INCONSISTENT; + /* + * generate the master secret + */ + case CKM_TLS12_MASTER_KEY_DERIVE: + case CKM_TLS12_MASTER_KEY_DERIVE_DH: + case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256: + case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256: + case CKM_TLS_MASTER_KEY_DERIVE: + case CKM_TLS_MASTER_KEY_DERIVE_DH: + case CKM_SSL3_MASTER_KEY_DERIVE: + case CKM_SSL3_MASTER_KEY_DERIVE_DH: { + CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master; + SSL3RSAPreMasterSecret *rsa_pms; + unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; + + if ((mechanism == CKM_TLS12_MASTER_KEY_DERIVE) || + (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) { + CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tls12_master = + (CK_TLS12_MASTER_KEY_DERIVE_PARAMS *)pMechanism->pParameter; + tlsPrfHash = GetHashTypeFromMechanism(tls12_master->prfHashMechanism); + if (tlsPrfHash == HASH_AlgNULL) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + } else if ((mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256) || + (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) { + tlsPrfHash = HASH_AlgSHA256; + } + + if ((mechanism != CKM_SSL3_MASTER_KEY_DERIVE) && + (mechanism != CKM_SSL3_MASTER_KEY_DERIVE_DH)) { + isTLS = PR_TRUE; + } + if ((mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) || + (mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) || + (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256) || + (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) { + isDH = PR_TRUE; + } + + /* first do the consistency checks */ + if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE); + if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != + CKK_GENERIC_SECRET)) { + if (att2) + sftk_FreeAttribute(att2); + crv = CKR_KEY_FUNCTION_NOT_PERMITTED; + break; + } + sftk_FreeAttribute(att2); + if (keyType != CKK_GENERIC_SECRET) { + crv = CKR_KEY_FUNCTION_NOT_PERMITTED; + break; + } + if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) { + crv = CKR_KEY_FUNCTION_NOT_PERMITTED; + break; + } + + /* finally do the key gen */ + ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *) + pMechanism->pParameter; + + PORT_Memcpy(crsrdata, + ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); + PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, + ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); + + if (ssl3_master->pVersion) { + SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); + rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue; + /* don't leak more key material then necessary for SSL to work */ + if ((sessKey == NULL) || sessKey->wasDerived) { + ssl3_master->pVersion->major = 0xff; + ssl3_master->pVersion->minor = 0xff; + } else { + ssl3_master->pVersion->major = rsa_pms->client_version[0]; + ssl3_master->pVersion->minor = rsa_pms->client_version[1]; + } + } + if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + + if (isTLS) { + SECStatus status; + SECItem crsr = { siBuffer, NULL, 0 }; + SECItem master = { siBuffer, NULL, 0 }; + SECItem pms = { siBuffer, NULL, 0 }; + + crsr.data = crsrdata; + crsr.len = sizeof crsrdata; + master.data = key_block; + master.len = SSL3_MASTER_SECRET_LENGTH; + pms.data = (unsigned char *)att->attrib.pValue; + pms.len = att->attrib.ulValueLen; + + if (tlsPrfHash != HASH_AlgNULL) { + status = TLS_P_hash(tlsPrfHash, &pms, "master secret", + &crsr, &master, isFIPS); + } else { + status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS); + } + if (status != SECSuccess) { + crv = CKR_FUNCTION_FAILED; + break; + } + } else { + /* now allocate the hash contexts */ + md5 = MD5_NewContext(); + if (md5 == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + sha = SHA1_NewContext(); + if (sha == NULL) { + PORT_Free(md5); + crv = CKR_HOST_MEMORY; + break; + } + for (i = 0; i < 3; i++) { + SHA1_Begin(sha); + SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i])); + SHA1_Update(sha, (const unsigned char *)att->attrib.pValue, + att->attrib.ulValueLen); + SHA1_Update(sha, crsrdata, sizeof crsrdata); + SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); + PORT_Assert(outLen == SHA1_LENGTH); + + MD5_Begin(md5); + MD5_Update(md5, (const unsigned char *)att->attrib.pValue, + att->attrib.ulValueLen); + MD5_Update(md5, sha_out, outLen); + MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH); + PORT_Assert(outLen == MD5_LENGTH); + } + PORT_Free(md5); + PORT_Free(sha); + } + + /* store the results */ + crv = sftk_forceAttribute(key, CKA_VALUE, key_block, SSL3_MASTER_SECRET_LENGTH); + if (crv != CKR_OK) + break; + keyType = CKK_GENERIC_SECRET; + crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType)); + if (isTLS) { + /* TLS's master secret is used to "sign" finished msgs with PRF. */ + /* XXX This seems like a hack. But SFTK_Derive only accepts + * one "operation" argument. */ + crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); + if (crv != CKR_OK) + break; + crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); + if (crv != CKR_OK) + break; + /* While we're here, we might as well force this, too. */ + crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); + if (crv != CKR_OK) + break; + } break; } - att2 = sftk_FindAttribute(sourceKey,CKA_KEY_TYPE); - if ((att2 == NULL) || - (*(CK_KEY_TYPE *)att2->attrib.pValue != CKK_GENERIC_SECRET)) { - if (att2) sftk_FreeAttribute(att2); - crv = CKR_KEY_FUNCTION_NOT_PERMITTED; + + /* Extended master key derivation [draft-ietf-tls-session-hash] */ + case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE: + case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH: { + CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *ems_params; + SSL3RSAPreMasterSecret *rsa_pms; + SECStatus status; + SECItem pms = { siBuffer, NULL, 0 }; + SECItem seed = { siBuffer, NULL, 0 }; + SECItem master = { siBuffer, NULL, 0 }; + + ems_params = (CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *) + pMechanism->pParameter; + + /* First do the consistency checks */ + if ((mechanism == CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE) && + (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) { + crv = CKR_KEY_TYPE_INCONSISTENT; + break; + } + att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE); + if ((att2 == NULL) || + (*(CK_KEY_TYPE *)att2->attrib.pValue != CKK_GENERIC_SECRET)) { + if (att2) + sftk_FreeAttribute(att2); + crv = CKR_KEY_FUNCTION_NOT_PERMITTED; + break; + } + sftk_FreeAttribute(att2); + if (keyType != CKK_GENERIC_SECRET) { + crv = CKR_KEY_FUNCTION_NOT_PERMITTED; + break; + } + if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) { + crv = CKR_KEY_FUNCTION_NOT_PERMITTED; + break; + } + + /* Do the key derivation */ + pms.data = (unsigned char *)att->attrib.pValue; + pms.len = att->attrib.ulValueLen; + seed.data = ems_params->pSessionHash; + seed.len = ems_params->ulSessionHashLen; + master.data = key_block; + master.len = SSL3_MASTER_SECRET_LENGTH; + if (ems_params->prfHashMechanism == CKM_TLS_PRF) { + /* + * In this case, the session hash is the concatenation of SHA-1 + * and MD5, so it should be 36 bytes long. + */ + if (seed.len != MD5_LENGTH + SHA1_LENGTH) { + crv = CKR_TEMPLATE_INCONSISTENT; + break; + } + + status = TLS_PRF(&pms, "extended master secret", + &seed, &master, isFIPS); + } else { + const SECHashObject *hashObj; + + tlsPrfHash = GetHashTypeFromMechanism(ems_params->prfHashMechanism); + if (tlsPrfHash == HASH_AlgNULL) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + + hashObj = HASH_GetRawHashObject(tlsPrfHash); + if (seed.len != hashObj->length) { + crv = CKR_TEMPLATE_INCONSISTENT; + break; + } + + status = TLS_P_hash(tlsPrfHash, &pms, "extended master secret", + &seed, &master, isFIPS); + } + if (status != SECSuccess) { + crv = CKR_FUNCTION_FAILED; + break; + } + + /* Reflect the version if required */ + if (ems_params->pVersion) { + SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); + rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue; + /* don't leak more key material than necessary for SSL to work */ + if ((sessKey == NULL) || sessKey->wasDerived) { + ems_params->pVersion->major = 0xff; + ems_params->pVersion->minor = 0xff; + } else { + ems_params->pVersion->major = rsa_pms->client_version[0]; + ems_params->pVersion->minor = rsa_pms->client_version[1]; + } + } + + /* Store the results */ + crv = sftk_forceAttribute(key, CKA_VALUE, key_block, + SSL3_MASTER_SECRET_LENGTH); break; } - sftk_FreeAttribute(att2); - if (keyType != CKK_GENERIC_SECRET) { - crv = CKR_KEY_FUNCTION_NOT_PERMITTED; + + case CKM_TLS12_KEY_AND_MAC_DERIVE: + case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256: + case CKM_TLS_KEY_AND_MAC_DERIVE: + case CKM_SSL3_KEY_AND_MAC_DERIVE: { + CK_SSL3_KEY_MAT_PARAMS *ssl3_keys; + CK_SSL3_KEY_MAT_OUT *ssl3_keys_out; + CK_ULONG effKeySize; + unsigned int block_needed; + unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2]; + unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; + + if (mechanism == CKM_TLS12_KEY_AND_MAC_DERIVE) { + CK_TLS12_KEY_MAT_PARAMS *tls12_keys = + (CK_TLS12_KEY_MAT_PARAMS *)pMechanism->pParameter; + tlsPrfHash = GetHashTypeFromMechanism(tls12_keys->prfHashMechanism); + if (tlsPrfHash == HASH_AlgNULL) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + } else if (mechanism == CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) { + tlsPrfHash = HASH_AlgSHA256; + } + + if (mechanism != CKM_SSL3_KEY_AND_MAC_DERIVE) { + isTLS = PR_TRUE; + } + + crv = sftk_DeriveSensitiveCheck(sourceKey, key); + if (crv != CKR_OK) + break; + + if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) { + crv = CKR_KEY_FUNCTION_NOT_PERMITTED; + break; + } + att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE); + if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != + CKK_GENERIC_SECRET)) { + if (att2) + sftk_FreeAttribute(att2); + crv = CKR_KEY_FUNCTION_NOT_PERMITTED; + break; + } + sftk_FreeAttribute(att2); + md5 = MD5_NewContext(); + if (md5 == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + sha = SHA1_NewContext(); + if (sha == NULL) { + MD5_DestroyContext(md5, PR_TRUE); + crv = CKR_HOST_MEMORY; + break; + } + ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter; + + PORT_Memcpy(srcrdata, + ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); + PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, + ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); + + PORT_Memcpy(crsrdata, + ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); + PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, + ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); + + /* + * clear out our returned keys so we can recover on failure + */ + ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial; + ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE; + ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE; + ssl3_keys_out->hClientKey = CK_INVALID_HANDLE; + ssl3_keys_out->hServerKey = CK_INVALID_HANDLE; + + /* + * How much key material do we need? + */ + macSize = ssl3_keys->ulMacSizeInBits / 8; + effKeySize = ssl3_keys->ulKeySizeInBits / 8; + IVSize = ssl3_keys->ulIVSizeInBits / 8; + if (keySize == 0) { + effKeySize = keySize; + } + + /* bIsExport must be false. */ + if (ssl3_keys->bIsExport) { + MD5_DestroyContext(md5, PR_TRUE); + SHA1_DestroyContext(sha, PR_TRUE); + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + + block_needed = 2 * (macSize + effKeySize + IVSize); + PORT_Assert(block_needed <= sizeof key_block); + if (block_needed > sizeof key_block) + block_needed = sizeof key_block; + + /* + * generate the key material: This looks amazingly similar to the + * PMS code, and is clearly crying out for a function to provide it. + */ + if (isTLS) { + SECStatus status; + SECItem srcr = { siBuffer, NULL, 0 }; + SECItem keyblk = { siBuffer, NULL, 0 }; + SECItem master = { siBuffer, NULL, 0 }; + + srcr.data = srcrdata; + srcr.len = sizeof srcrdata; + keyblk.data = key_block; + keyblk.len = block_needed; + master.data = (unsigned char *)att->attrib.pValue; + master.len = att->attrib.ulValueLen; + + if (tlsPrfHash != HASH_AlgNULL) { + status = TLS_P_hash(tlsPrfHash, &master, "key expansion", + &srcr, &keyblk, isFIPS); + } else { + status = TLS_PRF(&master, "key expansion", &srcr, &keyblk, + isFIPS); + } + if (status != SECSuccess) { + goto key_and_mac_derive_fail; + } + } else { + unsigned int block_bytes = 0; + /* key_block = + * MD5(master_secret + SHA('A' + master_secret + + * ServerHello.random + ClientHello.random)) + + * MD5(master_secret + SHA('BB' + master_secret + + * ServerHello.random + ClientHello.random)) + + * MD5(master_secret + SHA('CCC' + master_secret + + * ServerHello.random + ClientHello.random)) + + * [...]; + */ + for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) { + SHA1_Begin(sha); + SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i])); + SHA1_Update(sha, (const unsigned char *)att->attrib.pValue, + att->attrib.ulValueLen); + SHA1_Update(sha, srcrdata, sizeof srcrdata); + SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); + PORT_Assert(outLen == SHA1_LENGTH); + MD5_Begin(md5); + MD5_Update(md5, (const unsigned char *)att->attrib.pValue, + att->attrib.ulValueLen); + MD5_Update(md5, sha_out, outLen); + MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH); + PORT_Assert(outLen == MD5_LENGTH); + block_bytes += outLen; + } + } + + /* + * Put the key material where it goes. + */ + i = 0; /* now shows how much consumed */ + + /* + * The key_block is partitioned as follows: + * client_write_MAC_secret[CipherSpec.hash_size] + */ + crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize, + &ssl3_keys_out->hClientMacSecret); + if (crv != CKR_OK) + goto key_and_mac_derive_fail; + + i += macSize; + + /* + * server_write_MAC_secret[CipherSpec.hash_size] + */ + crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize, + &ssl3_keys_out->hServerMacSecret); + if (crv != CKR_OK) { + goto key_and_mac_derive_fail; + } + i += macSize; + + if (keySize) { + /* + ** Generate Domestic write keys and IVs. + ** client_write_key[CipherSpec.key_material] + */ + crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i], + keySize, &ssl3_keys_out->hClientKey); + if (crv != CKR_OK) { + goto key_and_mac_derive_fail; + } + i += keySize; + + /* + ** server_write_key[CipherSpec.key_material] + */ + crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i], + keySize, &ssl3_keys_out->hServerKey); + if (crv != CKR_OK) { + goto key_and_mac_derive_fail; + } + i += keySize; + + /* + ** client_write_IV[CipherSpec.IV_size] + */ + if (IVSize > 0) { + PORT_Memcpy(ssl3_keys_out->pIVClient, + &key_block[i], IVSize); + i += IVSize; + } + + /* + ** server_write_IV[CipherSpec.IV_size] + */ + if (IVSize > 0) { + PORT_Memcpy(ssl3_keys_out->pIVServer, + &key_block[i], IVSize); + i += IVSize; + } + PORT_Assert(i <= sizeof key_block); + } + + crv = CKR_OK; + + if (0) { + key_and_mac_derive_fail: + if (crv == CKR_OK) + crv = CKR_FUNCTION_FAILED; + sftk_freeSSLKeys(hSession, ssl3_keys_out); + } + MD5_DestroyContext(md5, PR_TRUE); + SHA1_DestroyContext(sha, PR_TRUE); + sftk_FreeObject(key); + key = NULL; break; } - if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) { - crv = CKR_KEY_FUNCTION_NOT_PERMITTED; + + case CKM_CONCATENATE_BASE_AND_KEY: { + SFTKObject *newKey; + + crv = sftk_DeriveSensitiveCheck(sourceKey, key); + if (crv != CKR_OK) + break; + + session = sftk_SessionFromHandle(hSession); + if (session == NULL) { + crv = CKR_SESSION_HANDLE_INVALID; + break; + } + + newKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *) + pMechanism->pParameter, + session); + sftk_FreeSession(session); + if (newKey == NULL) { + crv = CKR_KEY_HANDLE_INVALID; + break; + } + + if (sftk_isTrue(newKey, CKA_SENSITIVE)) { + crv = sftk_forceAttribute(newKey, CKA_SENSITIVE, &cktrue, + sizeof(CK_BBOOL)); + if (crv != CKR_OK) { + sftk_FreeObject(newKey); + break; + } + } + + att2 = sftk_FindAttribute(newKey, CKA_VALUE); + if (att2 == NULL) { + sftk_FreeObject(newKey); + crv = CKR_KEY_HANDLE_INVALID; + break; + } + tmpKeySize = att->attrib.ulValueLen + att2->attrib.ulValueLen; + if (keySize == 0) + keySize = tmpKeySize; + if (keySize > tmpKeySize) { + sftk_FreeObject(newKey); + sftk_FreeAttribute(att2); + crv = CKR_TEMPLATE_INCONSISTENT; + break; + } + buf = (unsigned char *)PORT_Alloc(tmpKeySize); + if (buf == NULL) { + sftk_FreeAttribute(att2); + sftk_FreeObject(newKey); + crv = CKR_HOST_MEMORY; + break; + } + + PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen); + PORT_Memcpy(buf + att->attrib.ulValueLen, + att2->attrib.pValue, att2->attrib.ulValueLen); + + crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); + PORT_ZFree(buf, tmpKeySize); + sftk_FreeAttribute(att2); + sftk_FreeObject(newKey); break; } - /* Do the key derivation */ - pms.data = (unsigned char*) att->attrib.pValue; - pms.len = att->attrib.ulValueLen; - seed.data = ems_params->pSessionHash; - seed.len = ems_params->ulSessionHashLen; - master.data = key_block; - master.len = SSL3_MASTER_SECRET_LENGTH; - if (ems_params-> prfHashMechanism == CKM_TLS_PRF) { - /* - * In this case, the session hash is the concatenation of SHA-1 - * and MD5, so it should be 36 bytes long. - */ - if (seed.len != MD5_LENGTH + SHA1_LENGTH) { + case CKM_CONCATENATE_BASE_AND_DATA: + crv = sftk_DeriveSensitiveCheck(sourceKey, key); + if (crv != CKR_OK) + break; + + stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; + tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen; + if (keySize == 0) + keySize = tmpKeySize; + if (keySize > tmpKeySize) { crv = CKR_TEMPLATE_INCONSISTENT; break; } + buf = (unsigned char *)PORT_Alloc(tmpKeySize); + if (buf == NULL) { + crv = CKR_HOST_MEMORY; + break; + } - status = TLS_PRF(&pms, "extended master secret", - &seed, &master, isFIPS); - } else { - const SECHashObject *hashObj; + PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen); + PORT_Memcpy(buf + att->attrib.ulValueLen, stringPtr->pData, + stringPtr->ulLen); - tlsPrfHash = GetHashTypeFromMechanism(ems_params->prfHashMechanism); - if (tlsPrfHash == HASH_AlgNULL) { - crv = CKR_MECHANISM_PARAM_INVALID; + crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); + PORT_ZFree(buf, tmpKeySize); + break; + case CKM_CONCATENATE_DATA_AND_BASE: + crv = sftk_DeriveSensitiveCheck(sourceKey, key); + if (crv != CKR_OK) + break; + + stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; + tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen; + if (keySize == 0) + keySize = tmpKeySize; + if (keySize > tmpKeySize) { + crv = CKR_TEMPLATE_INCONSISTENT; + break; + } + buf = (unsigned char *)PORT_Alloc(tmpKeySize); + if (buf == NULL) { + crv = CKR_HOST_MEMORY; break; } - hashObj = HASH_GetRawHashObject(tlsPrfHash); - if (seed.len != hashObj->length) { + PORT_Memcpy(buf, stringPtr->pData, stringPtr->ulLen); + PORT_Memcpy(buf + stringPtr->ulLen, att->attrib.pValue, + att->attrib.ulValueLen); + + crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); + PORT_ZFree(buf, tmpKeySize); + break; + case CKM_XOR_BASE_AND_DATA: + crv = sftk_DeriveSensitiveCheck(sourceKey, key); + if (crv != CKR_OK) + break; + + stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; + tmpKeySize = PR_MIN(att->attrib.ulValueLen, stringPtr->ulLen); + if (keySize == 0) + keySize = tmpKeySize; + if (keySize > tmpKeySize) { crv = CKR_TEMPLATE_INCONSISTENT; break; } + buf = (unsigned char *)PORT_Alloc(keySize); + if (buf == NULL) { + crv = CKR_HOST_MEMORY; + break; + } - status = TLS_P_hash(tlsPrfHash, &pms, "extended master secret", - &seed, &master, isFIPS); - } - if (status != SECSuccess) { - crv = CKR_FUNCTION_FAILED; + PORT_Memcpy(buf, att->attrib.pValue, keySize); + for (i = 0; i < (int)keySize; i++) { + buf[i] ^= stringPtr->pData[i]; + } + + crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); + PORT_ZFree(buf, keySize); break; - } - /* Reflect the version if required */ - if (ems_params->pVersion) { - SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); - rsa_pms = (SSL3RSAPreMasterSecret *) att->attrib.pValue; - /* don't leak more key material than necessary for SSL to work */ - if ((sessKey == NULL) || sessKey->wasDerived) { - ems_params->pVersion->major = 0xff; - ems_params->pVersion->minor = 0xff; - } else { - ems_params->pVersion->major = rsa_pms->client_version[0]; - ems_params->pVersion->minor = rsa_pms->client_version[1]; + case CKM_EXTRACT_KEY_FROM_KEY: { + /* the following assumes 8 bits per byte */ + CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter; + CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */ + CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */ + + crv = sftk_DeriveSensitiveCheck(sourceKey, key); + if (crv != CKR_OK) + break; + + if (keySize == 0) { + crv = CKR_TEMPLATE_INCOMPLETE; + break; } + /* make sure we have enough bits in the original key */ + if (att->attrib.ulValueLen < + (offset + keySize + ((shift != 0) ? 1 : 0))) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + buf = (unsigned char *)PORT_Alloc(keySize); + if (buf == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + + /* copy the bits we need into the new key */ + for (i = 0; i < (int)keySize; i++) { + unsigned char *value = + ((unsigned char *)att->attrib.pValue) + offset + i; + if (shift) { + buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift)); + } else { + buf[i] = value[0]; + } + } + + crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize); + PORT_ZFree(buf, keySize); + break; } + case CKM_MD2_KEY_DERIVATION: + if (keySize == 0) + keySize = MD2_LENGTH; + if (keySize > MD2_LENGTH) { + crv = CKR_TEMPLATE_INCONSISTENT; + break; + } + /* now allocate the hash contexts */ + md2 = MD2_NewContext(); + if (md2 == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + MD2_Begin(md2); + MD2_Update(md2, (const unsigned char *)att->attrib.pValue, + att->attrib.ulValueLen); + MD2_End(md2, key_block, &outLen, MD2_LENGTH); + MD2_DestroyContext(md2, PR_TRUE); - /* Store the results */ - crv = sftk_forceAttribute(key, CKA_VALUE, key_block, - SSL3_MASTER_SECRET_LENGTH); - break; - } - - case CKM_TLS12_KEY_AND_MAC_DERIVE: - case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256: - case CKM_TLS_KEY_AND_MAC_DERIVE: - case CKM_SSL3_KEY_AND_MAC_DERIVE: - { - CK_SSL3_KEY_MAT_PARAMS *ssl3_keys; - CK_SSL3_KEY_MAT_OUT * ssl3_keys_out; - CK_ULONG effKeySize; - unsigned int block_needed; - unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2]; - unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; - - if (mechanism == CKM_TLS12_KEY_AND_MAC_DERIVE) { - CK_TLS12_KEY_MAT_PARAMS *tls12_keys = - (CK_TLS12_KEY_MAT_PARAMS *) pMechanism->pParameter; - tlsPrfHash = GetHashTypeFromMechanism(tls12_keys->prfHashMechanism); - if (tlsPrfHash == HASH_AlgNULL) { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - } else if (mechanism == CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) { - tlsPrfHash = HASH_AlgSHA256; - } - - if (mechanism != CKM_SSL3_KEY_AND_MAC_DERIVE) { - isTLS = PR_TRUE; - } - - crv = sftk_DeriveSensitiveCheck(sourceKey,key); - if (crv != CKR_OK) break; - - if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) { - crv = CKR_KEY_FUNCTION_NOT_PERMITTED; - break; - } - att2 = sftk_FindAttribute(sourceKey,CKA_KEY_TYPE); - if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue != - CKK_GENERIC_SECRET)) { - if (att2) sftk_FreeAttribute(att2); - crv = CKR_KEY_FUNCTION_NOT_PERMITTED; - break; - } - sftk_FreeAttribute(att2); - md5 = MD5_NewContext(); - if (md5 == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - sha = SHA1_NewContext(); - if (sha == NULL) { - PORT_Free(md5); - crv = CKR_HOST_MEMORY; - break; - } - ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *) pMechanism->pParameter; - - PORT_Memcpy(srcrdata, - ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); - PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, - ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); - - PORT_Memcpy(crsrdata, - ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); - PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, - ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); - - /* - * clear out our returned keys so we can recover on failure - */ - ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial; - ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE; - ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE; - ssl3_keys_out->hClientKey = CK_INVALID_HANDLE; - ssl3_keys_out->hServerKey = CK_INVALID_HANDLE; - - /* - * How much key material do we need? - */ - macSize = ssl3_keys->ulMacSizeInBits/8; - effKeySize = ssl3_keys->ulKeySizeInBits/8; - IVSize = ssl3_keys->ulIVSizeInBits/8; - if (keySize == 0) { - effKeySize = keySize; - } - block_needed = 2 * (macSize + effKeySize + - ((!ssl3_keys->bIsExport) * IVSize)); - PORT_Assert(block_needed <= sizeof key_block); - if (block_needed > sizeof key_block) - block_needed = sizeof key_block; - - /* - * generate the key material: This looks amazingly similar to the - * PMS code, and is clearly crying out for a function to provide it. - */ - if (isTLS) { - SECStatus status; - SECItem srcr = { siBuffer, NULL, 0 }; - SECItem keyblk = { siBuffer, NULL, 0 }; - SECItem master = { siBuffer, NULL, 0 }; - - srcr.data = srcrdata; - srcr.len = sizeof srcrdata; - keyblk.data = key_block; - keyblk.len = block_needed; - master.data = (unsigned char*)att->attrib.pValue; - master.len = att->attrib.ulValueLen; - - if (tlsPrfHash != HASH_AlgNULL) { - status = TLS_P_hash(tlsPrfHash, &master, "key expansion", - &srcr, &keyblk, isFIPS); - } else { - status = TLS_PRF(&master, "key expansion", &srcr, &keyblk, - isFIPS); - } - if (status != SECSuccess) { - goto key_and_mac_derive_fail; - } - } else { - unsigned int block_bytes = 0; - /* key_block = - * MD5(master_secret + SHA('A' + master_secret + - * ServerHello.random + ClientHello.random)) + - * MD5(master_secret + SHA('BB' + master_secret + - * ServerHello.random + ClientHello.random)) + - * MD5(master_secret + SHA('CCC' + master_secret + - * ServerHello.random + ClientHello.random)) + - * [...]; - */ - for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) { - SHA1_Begin(sha); - SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i])); - SHA1_Update(sha, (const unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen); - SHA1_Update(sha, srcrdata, sizeof srcrdata); - SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH); - PORT_Assert(outLen == SHA1_LENGTH); - MD5_Begin(md5); - MD5_Update(md5, (const unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen); - MD5_Update(md5, sha_out, outLen); - MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH); - PORT_Assert(outLen == MD5_LENGTH); - block_bytes += outLen; - } - } - - /* - * Put the key material where it goes. - */ - i = 0; /* now shows how much consumed */ - - /* - * The key_block is partitioned as follows: - * client_write_MAC_secret[CipherSpec.hash_size] - */ - crv = sftk_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize, - &ssl3_keys_out->hClientMacSecret); - if (crv != CKR_OK) - goto key_and_mac_derive_fail; - - i += macSize; - - /* - * server_write_MAC_secret[CipherSpec.hash_size] - */ - crv = sftk_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize, - &ssl3_keys_out->hServerMacSecret); - if (crv != CKR_OK) { - goto key_and_mac_derive_fail; - } - i += macSize; - - if (keySize) { - if (!ssl3_keys->bIsExport) { - /* - ** Generate Domestic write keys and IVs. - ** client_write_key[CipherSpec.key_material] - */ - crv = sftk_buildSSLKey(hSession,key,PR_FALSE,&key_block[i], - keySize, &ssl3_keys_out->hClientKey); - if (crv != CKR_OK) { - goto key_and_mac_derive_fail; - } - i += keySize; - - /* - ** server_write_key[CipherSpec.key_material] - */ - crv = sftk_buildSSLKey(hSession,key,PR_FALSE,&key_block[i], - keySize, &ssl3_keys_out->hServerKey); - if (crv != CKR_OK) { - goto key_and_mac_derive_fail; - } - i += keySize; - - /* - ** client_write_IV[CipherSpec.IV_size] - */ - if (IVSize > 0) { - PORT_Memcpy(ssl3_keys_out->pIVClient, - &key_block[i], IVSize); - i += IVSize; - } - - /* - ** server_write_IV[CipherSpec.IV_size] - */ - if (IVSize > 0) { - PORT_Memcpy(ssl3_keys_out->pIVServer, - &key_block[i], IVSize); - i += IVSize; - } - PORT_Assert(i <= sizeof key_block); - - } else if (!isTLS) { - - /* - ** Generate SSL3 Export write keys and IVs. - ** client_write_key[CipherSpec.key_material] - ** final_client_write_key = MD5(client_write_key + - ** ClientHello.random + ServerHello.random); - */ - MD5_Begin(md5); - MD5_Update(md5, &key_block[i], effKeySize); - MD5_Update(md5, crsrdata, sizeof crsrdata); - MD5_End(md5, key_block2, &outLen, MD5_LENGTH); - i += effKeySize; - crv = sftk_buildSSLKey(hSession,key,PR_FALSE,key_block2, - keySize,&ssl3_keys_out->hClientKey); - if (crv != CKR_OK) { - goto key_and_mac_derive_fail; - } - - /* - ** server_write_key[CipherSpec.key_material] - ** final_server_write_key = MD5(server_write_key + - ** ServerHello.random + ClientHello.random); - */ - MD5_Begin(md5); - MD5_Update(md5, &key_block[i], effKeySize); - MD5_Update(md5, srcrdata, sizeof srcrdata); - MD5_End(md5, key_block2, &outLen, MD5_LENGTH); - i += effKeySize; - crv = sftk_buildSSLKey(hSession,key,PR_FALSE,key_block2, - keySize,&ssl3_keys_out->hServerKey); - if (crv != CKR_OK) { - goto key_and_mac_derive_fail; - } - - /* - ** client_write_IV = - ** MD5(ClientHello.random + ServerHello.random); - */ - MD5_Begin(md5); - MD5_Update(md5, crsrdata, sizeof crsrdata); - MD5_End(md5, key_block2, &outLen, MD5_LENGTH); - PORT_Memcpy(ssl3_keys_out->pIVClient, key_block2, IVSize); - - /* - ** server_write_IV = - ** MD5(ServerHello.random + ClientHello.random); - */ - MD5_Begin(md5); - MD5_Update(md5, srcrdata, sizeof srcrdata); - MD5_End(md5, key_block2, &outLen, MD5_LENGTH); - PORT_Memcpy(ssl3_keys_out->pIVServer, key_block2, IVSize); - - } else { - - /* - ** Generate TLS 1.0 Export write keys and IVs. - */ - SECStatus status; - SECItem secret = { siBuffer, NULL, 0 }; - SECItem crsr = { siBuffer, NULL, 0 }; - SECItem keyblk = { siBuffer, NULL, 0 }; - - /* - ** client_write_key[CipherSpec.key_material] - ** final_client_write_key = PRF(client_write_key, - ** "client write key", - ** client_random + server_random); - */ - secret.data = &key_block[i]; - secret.len = effKeySize; - i += effKeySize; - crsr.data = crsrdata; - crsr.len = sizeof crsrdata; - keyblk.data = key_block2; - keyblk.len = sizeof key_block2; - status = TLS_PRF(&secret, "client write key", &crsr, &keyblk, - isFIPS); - if (status != SECSuccess) { - goto key_and_mac_derive_fail; - } - crv = sftk_buildSSLKey(hSession, key, PR_FALSE, key_block2, - keySize, &ssl3_keys_out->hClientKey); - if (crv != CKR_OK) { - goto key_and_mac_derive_fail; - } - - /* - ** server_write_key[CipherSpec.key_material] - ** final_server_write_key = PRF(server_write_key, - ** "server write key", - ** client_random + server_random); - */ - secret.data = &key_block[i]; - secret.len = effKeySize; - i += effKeySize; - keyblk.data = key_block2; - keyblk.len = sizeof key_block2; - status = TLS_PRF(&secret, "server write key", &crsr, &keyblk, - isFIPS); - if (status != SECSuccess) { - goto key_and_mac_derive_fail; - } - crv = sftk_buildSSLKey(hSession, key, PR_FALSE, key_block2, - keySize, &ssl3_keys_out->hServerKey); - if (crv != CKR_OK) { - goto key_and_mac_derive_fail; - } - - /* - ** iv_block = PRF("", "IV block", - ** client_random + server_random); - ** client_write_IV[SecurityParameters.IV_size] - ** server_write_IV[SecurityParameters.IV_size] - */ - if (IVSize) { - secret.data = NULL; - secret.len = 0; - keyblk.data = &key_block[i]; - keyblk.len = 2 * IVSize; - status = TLS_PRF(&secret, "IV block", &crsr, &keyblk, - isFIPS); - if (status != SECSuccess) { - goto key_and_mac_derive_fail; - } - PORT_Memcpy(ssl3_keys_out->pIVClient, keyblk.data, IVSize); - PORT_Memcpy(ssl3_keys_out->pIVServer, keyblk.data + IVSize, - IVSize); - } - } - } - - crv = CKR_OK; - - if (0) { -key_and_mac_derive_fail: - if (crv == CKR_OK) - crv = CKR_FUNCTION_FAILED; - sftk_freeSSLKeys(hSession, ssl3_keys_out); - } - MD5_DestroyContext(md5, PR_TRUE); - SHA1_DestroyContext(sha, PR_TRUE); - sftk_FreeObject(key); - key = NULL; - break; - } - - case CKM_CONCATENATE_BASE_AND_KEY: - { - SFTKObject *newKey; - - crv = sftk_DeriveSensitiveCheck(sourceKey,key); - if (crv != CKR_OK) break; - - session = sftk_SessionFromHandle(hSession); - if (session == NULL) { - crv = CKR_SESSION_HANDLE_INVALID; - break; - } - - newKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *) - pMechanism->pParameter,session); - sftk_FreeSession(session); - if ( newKey == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - - if (sftk_isTrue(newKey,CKA_SENSITIVE)) { - crv = sftk_forceAttribute(newKey,CKA_SENSITIVE,&cktrue, - sizeof(CK_BBOOL)); - if (crv != CKR_OK) { - sftk_FreeObject(newKey); - break; - } - } - - att2 = sftk_FindAttribute(newKey,CKA_VALUE); - if (att2 == NULL) { - sftk_FreeObject(newKey); - crv = CKR_KEY_HANDLE_INVALID; - break; - } - tmpKeySize = att->attrib.ulValueLen+att2->attrib.ulValueLen; - if (keySize == 0) keySize = tmpKeySize; - if (keySize > tmpKeySize) { - sftk_FreeObject(newKey); - sftk_FreeAttribute(att2); - crv = CKR_TEMPLATE_INCONSISTENT; - break; - } - buf = (unsigned char*)PORT_Alloc(tmpKeySize); - if (buf == NULL) { - sftk_FreeAttribute(att2); - sftk_FreeObject(newKey); - crv = CKR_HOST_MEMORY; - break; - } - - PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen); - PORT_Memcpy(buf+att->attrib.ulValueLen, - att2->attrib.pValue,att2->attrib.ulValueLen); - - crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize); - PORT_ZFree(buf,tmpKeySize); - sftk_FreeAttribute(att2); - sftk_FreeObject(newKey); - break; - } - - case CKM_CONCATENATE_BASE_AND_DATA: - crv = sftk_DeriveSensitiveCheck(sourceKey,key); - if (crv != CKR_OK) break; - - stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) pMechanism->pParameter; - tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen; - if (keySize == 0) keySize = tmpKeySize; - if (keySize > tmpKeySize) { - crv = CKR_TEMPLATE_INCONSISTENT; - break; - } - buf = (unsigned char*)PORT_Alloc(tmpKeySize); - if (buf == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - - PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen); - PORT_Memcpy(buf+att->attrib.ulValueLen,stringPtr->pData, - stringPtr->ulLen); - - crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize); - PORT_ZFree(buf,tmpKeySize); - break; - case CKM_CONCATENATE_DATA_AND_BASE: - crv = sftk_DeriveSensitiveCheck(sourceKey,key); - if (crv != CKR_OK) break; - - stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; - tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen; - if (keySize == 0) keySize = tmpKeySize; - if (keySize > tmpKeySize) { - crv = CKR_TEMPLATE_INCONSISTENT; - break; - } - buf = (unsigned char*)PORT_Alloc(tmpKeySize); - if (buf == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - - PORT_Memcpy(buf,stringPtr->pData,stringPtr->ulLen); - PORT_Memcpy(buf+stringPtr->ulLen,att->attrib.pValue, - att->attrib.ulValueLen); - - crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize); - PORT_ZFree(buf,tmpKeySize); - break; - case CKM_XOR_BASE_AND_DATA: - crv = sftk_DeriveSensitiveCheck(sourceKey,key); - if (crv != CKR_OK) break; - - stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter; - tmpKeySize = PR_MIN(att->attrib.ulValueLen,stringPtr->ulLen); - if (keySize == 0) keySize = tmpKeySize; - if (keySize > tmpKeySize) { - crv = CKR_TEMPLATE_INCONSISTENT; - break; - } - buf = (unsigned char*)PORT_Alloc(keySize); - if (buf == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - - - PORT_Memcpy(buf,att->attrib.pValue,keySize); - for (i=0; i < (int)keySize; i++) { - buf[i] ^= stringPtr->pData[i]; - } - - crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize); - PORT_ZFree(buf,keySize); - break; - - case CKM_EXTRACT_KEY_FROM_KEY: - { - /* the following assumes 8 bits per byte */ - CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter; - CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */ - CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */ - - crv = sftk_DeriveSensitiveCheck(sourceKey,key); - if (crv != CKR_OK) break; - - if (keySize == 0) { - crv = CKR_TEMPLATE_INCOMPLETE; - break; - } - /* make sure we have enough bits in the original key */ - if (att->attrib.ulValueLen < - (offset + keySize + ((shift != 0)? 1 :0)) ) { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - buf = (unsigned char*)PORT_Alloc(keySize); - if (buf == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - - /* copy the bits we need into the new key */ - for (i=0; i < (int)keySize; i++) { - unsigned char *value = - ((unsigned char *)att->attrib.pValue)+offset+i; - if (shift) { - buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift)); - } else { - buf[i] = value[0]; - } - } - - crv = sftk_forceAttribute (key,CKA_VALUE,buf,keySize); - PORT_ZFree(buf,keySize); - break; - } - case CKM_MD2_KEY_DERIVATION: - if (keySize == 0) keySize = MD2_LENGTH; - if (keySize > MD2_LENGTH) { - crv = CKR_TEMPLATE_INCONSISTENT; - break; - } - /* now allocate the hash contexts */ - md2 = MD2_NewContext(); - if (md2 == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - MD2_Begin(md2); - MD2_Update(md2,(const unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen); - MD2_End(md2,key_block,&outLen,MD2_LENGTH); - MD2_DestroyContext(md2, PR_TRUE); - - crv = sftk_forceAttribute (key,CKA_VALUE,key_block,keySize); - break; - case CKM_MD5_KEY_DERIVATION: - if (keySize == 0) keySize = MD5_LENGTH; - if (keySize > MD5_LENGTH) { - crv = CKR_TEMPLATE_INCONSISTENT; - break; - } - MD5_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen); - - crv = sftk_forceAttribute (key,CKA_VALUE,key_block,keySize); - break; - case CKM_SHA1_KEY_DERIVATION: - if (keySize == 0) keySize = SHA1_LENGTH; - if (keySize > SHA1_LENGTH) { - crv = CKR_TEMPLATE_INCONSISTENT; - break; - } - SHA1_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen); - - crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize); - break; - - case CKM_SHA224_KEY_DERIVATION: - if (keySize == 0) keySize = SHA224_LENGTH; - if (keySize > SHA224_LENGTH) { - crv = CKR_TEMPLATE_INCONSISTENT; - break; - } - SHA224_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen); - - crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize); - break; - - case CKM_SHA256_KEY_DERIVATION: - if (keySize == 0) keySize = SHA256_LENGTH; - if (keySize > SHA256_LENGTH) { - crv = CKR_TEMPLATE_INCONSISTENT; - break; - } - SHA256_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen); - - crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize); - break; - - case CKM_SHA384_KEY_DERIVATION: - if (keySize == 0) keySize = SHA384_LENGTH; - if (keySize > SHA384_LENGTH) { - crv = CKR_TEMPLATE_INCONSISTENT; - break; - } - SHA384_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen); - - crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize); - break; - - case CKM_SHA512_KEY_DERIVATION: - if (keySize == 0) keySize = SHA512_LENGTH; - if (keySize > SHA512_LENGTH) { - crv = CKR_TEMPLATE_INCONSISTENT; - break; - } - SHA512_HashBuf(key_block,(const unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen); - - crv = sftk_forceAttribute(key,CKA_VALUE,key_block,keySize); - break; - - case CKM_DH_PKCS_DERIVE: - { - SECItem derived, dhPublic; - SECItem dhPrime, dhValue; - /* sourceKey - values for the local existing low key */ - /* get prime and value attributes */ - crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME); - if (crv != SECSuccess) break; - crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE); - if (crv != SECSuccess) { - PORT_Free(dhPrime.data); - break; - } - - dhPublic.data = pMechanism->pParameter; - dhPublic.len = pMechanism->ulParameterLen; - - /* calculate private value - oct */ - rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize); - - PORT_Free(dhPrime.data); - PORT_Free(dhValue.data); - - if (rv == SECSuccess) { - sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len); - PORT_ZFree(derived.data, derived.len); - } else - crv = CKR_HOST_MEMORY; - - break; - } + crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize); + break; + case CKM_MD5_KEY_DERIVATION: + if (keySize == 0) + keySize = MD5_LENGTH; + if (keySize > MD5_LENGTH) { + crv = CKR_TEMPLATE_INCONSISTENT; + break; + } + MD5_HashBuf(key_block, (const unsigned char *)att->attrib.pValue, + att->attrib.ulValueLen); -#ifndef NSS_DISABLE_ECC - case CKM_ECDH1_DERIVE: - case CKM_ECDH1_COFACTOR_DERIVE: - { - SECItem ecScalar, ecPoint; - SECItem tmp; - PRBool withCofactor = PR_FALSE; - unsigned char *secret; - unsigned char *keyData = NULL; - unsigned int secretlen, curveLen, pubKeyLen; - CK_ECDH1_DERIVE_PARAMS *mechParams; - NSSLOWKEYPrivateKey *privKey; - PLArenaPool *arena = NULL; - - /* Check mechanism parameters */ - mechParams = (CK_ECDH1_DERIVE_PARAMS *) pMechanism->pParameter; - if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) || - ((mechParams->kdf == CKD_NULL) && - ((mechParams->ulSharedDataLen != 0) || - (mechParams->pSharedData != NULL)))) { - crv = CKR_MECHANISM_PARAM_INVALID; - break; - } - - privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv); - if (privKey == NULL) { - break; - } - - /* Now we are working with a non-NULL private key */ - SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue); - - ecPoint.data = mechParams->pPublicData; - ecPoint.len = mechParams->ulPublicDataLen; - - curveLen = (privKey->u.ec.ecParams.fieldID.size +7)/8; - pubKeyLen = (2*curveLen) + 1; - - /* if the len is too small, can't be a valid point */ - if (ecPoint.len < pubKeyLen) { - goto ec_loser; - } - /* if the len is too large, must be an encoded point (length is - * equal case just falls through */ - if (ecPoint.len > pubKeyLen) { - SECItem newPoint; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) { - goto ec_loser; - } - - rv = SEC_QuickDERDecodeItem(arena, &newPoint, - SEC_ASN1_GET(SEC_OctetStringTemplate), - &ecPoint); - if (rv != SECSuccess) { - goto ec_loser; - } - ecPoint = newPoint; - } - - if (mechanism == CKM_ECDH1_COFACTOR_DERIVE) { - withCofactor = PR_TRUE; - } else { - /* When not using cofactor derivation, one should - * validate the public key to avoid small subgroup - * attacks. - */ - if (EC_ValidatePublicKey(&privKey->u.ec.ecParams, &ecPoint) - != SECSuccess) { - goto ec_loser; - } - } - - rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar, - withCofactor, &tmp); - PORT_Free(ecScalar.data); - ecScalar.data = NULL; - if (privKey != sourceKey->objectInfo) { - nsslowkey_DestroyPrivateKey(privKey); - privKey=NULL; - } - if (arena) { - PORT_FreeArena(arena,PR_FALSE); - arena=NULL; - } - - if (rv != SECSuccess) { - crv = sftk_MapCryptError(PORT_GetError()); - break; - } - - - /* - * apply the kdf function. - */ - if (mechParams->kdf == CKD_NULL) { - /* - * tmp is the raw data created by ECDH_Derive, - * secret and secretlen are the values we will - * eventually pass as our generated key. - */ - secret = tmp.data; - secretlen = tmp.len; - } else { - secretlen = keySize; - crv = sftk_ANSI_X9_63_kdf(&secret, keySize, - &tmp, mechParams->pSharedData, - mechParams->ulSharedDataLen, mechParams->kdf); - PORT_ZFree(tmp.data, tmp.len); - if (crv != CKR_OK) { - break; - } - tmp.data = secret; - tmp.len = secretlen; - } - - /* - * if keySize is supplied, then we are generating a key of a specific - * length. This is done by taking the least significant 'keySize' - * bytes from the unsigned value calculated by ECDH. Note: this may - * mean padding temp with extra leading zeros from what ECDH_Derive - * already returned (which itself may contain leading zeros). - */ - if (keySize) { - if (secretlen < keySize) { - keyData = PORT_ZAlloc(keySize); - if (!keyData) { - PORT_ZFree(tmp.data, tmp.len); - crv = CKR_HOST_MEMORY; - break; - } - PORT_Memcpy(&keyData[keySize-secretlen],secret,secretlen); - secret = keyData; - } else { - secret += (secretlen - keySize); - } - secretlen = keySize; - } - - sftk_forceAttribute(key, CKA_VALUE, secret, secretlen); - PORT_ZFree(tmp.data, tmp.len); - if (keyData) { - PORT_ZFree(keyData, keySize); - } - break; - -ec_loser: - crv = CKR_ARGUMENTS_BAD; - PORT_Free(ecScalar.data); - if (privKey != sourceKey->objectInfo) - nsslowkey_DestroyPrivateKey(privKey); - if (arena) { - PORT_FreeArena(arena, PR_FALSE); - } - break; - - } -#endif /* NSS_DISABLE_ECC */ + crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize); + break; + case CKM_SHA1_KEY_DERIVATION: + if (keySize == 0) + keySize = SHA1_LENGTH; + if (keySize > SHA1_LENGTH) { + crv = CKR_TEMPLATE_INCONSISTENT; + break; + } + SHA1_HashBuf(key_block, (const unsigned char *)att->attrib.pValue, + att->attrib.ulValueLen); - /* See RFC 5869 and CK_NSS_HKDFParams for documentation. */ - case CKM_NSS_HKDF_SHA1: hashType = HASH_AlgSHA1; goto hkdf; - case CKM_NSS_HKDF_SHA256: hashType = HASH_AlgSHA256; goto hkdf; - case CKM_NSS_HKDF_SHA384: hashType = HASH_AlgSHA384; goto hkdf; - case CKM_NSS_HKDF_SHA512: hashType = HASH_AlgSHA512; goto hkdf; -hkdf: { - const CK_NSS_HKDFParams * params = - (const CK_NSS_HKDFParams *) pMechanism->pParameter; - const SECHashObject * rawHash; - unsigned hashLen; - CK_BYTE buf[HASH_LENGTH_MAX]; - CK_BYTE * prk; /* psuedo-random key */ - CK_ULONG prkLen; - CK_BYTE * okm; /* output keying material */ - - rawHash = HASH_GetRawHashObject(hashType); - if (rawHash == NULL || rawHash->length > sizeof buf) { - crv = CKR_FUNCTION_FAILED; + crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize); break; - } - hashLen = rawHash->length; - if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams) || - !params || (!params->bExpand && !params->bExtract) || - (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) || - (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) { - crv = CKR_MECHANISM_PARAM_INVALID; + case CKM_SHA224_KEY_DERIVATION: + if (keySize == 0) + keySize = SHA224_LENGTH; + if (keySize > SHA224_LENGTH) { + crv = CKR_TEMPLATE_INCONSISTENT; + break; + } + SHA224_HashBuf(key_block, (const unsigned char *)att->attrib.pValue, + att->attrib.ulValueLen); + + crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize); break; - } - if (keySize == 0 || keySize > sizeof key_block || - (!params->bExpand && keySize > hashLen) || - (params->bExpand && keySize > 255 * hashLen)) { - crv = CKR_TEMPLATE_INCONSISTENT; + + case CKM_SHA256_KEY_DERIVATION: + if (keySize == 0) + keySize = SHA256_LENGTH; + if (keySize > SHA256_LENGTH) { + crv = CKR_TEMPLATE_INCONSISTENT; + break; + } + SHA256_HashBuf(key_block, (const unsigned char *)att->attrib.pValue, + att->attrib.ulValueLen); + + crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize); break; - } - crv = sftk_DeriveSensitiveCheck(sourceKey, key); - if (crv != CKR_OK) + + case CKM_SHA384_KEY_DERIVATION: + if (keySize == 0) + keySize = SHA384_LENGTH; + if (keySize > SHA384_LENGTH) { + crv = CKR_TEMPLATE_INCONSISTENT; + break; + } + SHA384_HashBuf(key_block, (const unsigned char *)att->attrib.pValue, + att->attrib.ulValueLen); + + crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize); break; - /* HKDF-Extract(salt, base key value) */ - if (params->bExtract) { - CK_BYTE * salt; - CK_ULONG saltLen; - HMACContext * hmac; - unsigned int bufLen; + case CKM_SHA512_KEY_DERIVATION: + if (keySize == 0) + keySize = SHA512_LENGTH; + if (keySize > SHA512_LENGTH) { + crv = CKR_TEMPLATE_INCONSISTENT; + break; + } + SHA512_HashBuf(key_block, (const unsigned char *)att->attrib.pValue, + att->attrib.ulValueLen); + + crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize); + break; - salt = params->pSalt; - saltLen = params->ulSaltLen; - if (salt == NULL) { - saltLen = hashLen; - salt = buf; - memset(salt, 0, saltLen); + case CKM_DH_PKCS_DERIVE: { + SECItem derived, dhPublic; + SECItem dhPrime, dhValue; + /* sourceKey - values for the local existing low key */ + /* get prime and value attributes */ + crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME); + if (crv != SECSuccess) + break; + crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE); + if (crv != SECSuccess) { + PORT_Free(dhPrime.data); + break; } - hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS); - if (!hmac) { + + dhPublic.data = pMechanism->pParameter; + dhPublic.len = pMechanism->ulParameterLen; + + /* calculate private value - oct */ + rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize); + + PORT_Free(dhPrime.data); + PORT_Free(dhValue.data); + + if (rv == SECSuccess) { + sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len); + PORT_ZFree(derived.data, derived.len); + } else crv = CKR_HOST_MEMORY; + + break; + } + +#ifndef NSS_DISABLE_ECC + case CKM_ECDH1_DERIVE: + case CKM_ECDH1_COFACTOR_DERIVE: { + SECItem ecScalar, ecPoint; + SECItem tmp; + PRBool withCofactor = PR_FALSE; + unsigned char *secret; + unsigned char *keyData = NULL; + unsigned int secretlen, pubKeyLen; + CK_ECDH1_DERIVE_PARAMS *mechParams; + NSSLOWKEYPrivateKey *privKey; + PLArenaPool *arena = NULL; + + /* Check mechanism parameters */ + mechParams = (CK_ECDH1_DERIVE_PARAMS *)pMechanism->pParameter; + if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) || + ((mechParams->kdf == CKD_NULL) && + ((mechParams->ulSharedDataLen != 0) || + (mechParams->pSharedData != NULL)))) { + crv = CKR_MECHANISM_PARAM_INVALID; break; } - HMAC_Begin(hmac); - HMAC_Update(hmac, (const unsigned char*) att->attrib.pValue, - att->attrib.ulValueLen); - HMAC_Finish(hmac, buf, &bufLen, sizeof(buf)); - HMAC_Destroy(hmac, PR_TRUE); - PORT_Assert(bufLen == rawHash->length); - prk = buf; - prkLen = bufLen; - } else { - /* PRK = base key value */ - prk = (CK_BYTE*) att->attrib.pValue; - prkLen = att->attrib.ulValueLen; - } - - /* HKDF-Expand */ - if (!params->bExpand) { - okm = prk; - } else { - /* T(1) = HMAC-Hash(prk, "" | info | 0x01) - * T(n) = HMAC-Hash(prk, T(n-1) | info | n - * key material = T(1) | ... | T(n) - */ - HMACContext * hmac; - CK_BYTE i; - unsigned iterations = PR_ROUNDUP(keySize, hashLen) / hashLen; - hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS); - if (hmac == NULL) { - crv = CKR_HOST_MEMORY; + + privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv); + if (privKey == NULL) { break; } - for (i = 1; i <= iterations; ++i) { - unsigned len; - HMAC_Begin(hmac); - if (i > 1) { - HMAC_Update(hmac, key_block + ((i-2) * hashLen), hashLen); + + /* Now we are working with a non-NULL private key */ + SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue); + + ecPoint.data = mechParams->pPublicData; + ecPoint.len = mechParams->ulPublicDataLen; + + pubKeyLen = privKey->u.ec.ecParams.pointSize; + + /* if the len is too small, can't be a valid point */ + if (ecPoint.len < pubKeyLen) { + goto ec_loser; + } + /* if the len is too large, must be an encoded point (length is + * equal case just falls through */ + if (ecPoint.len > pubKeyLen) { + SECItem newPoint; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + goto ec_loser; } - if (params->ulInfoLen != 0) { - HMAC_Update(hmac, params->pInfo, params->ulInfoLen); + + rv = SEC_QuickDERDecodeItem(arena, &newPoint, + SEC_ASN1_GET(SEC_OctetStringTemplate), + &ecPoint); + if (rv != SECSuccess) { + goto ec_loser; } - HMAC_Update(hmac, &i, 1); - HMAC_Finish(hmac, key_block + ((i-1) * hashLen), &len, - hashLen); - PORT_Assert(len == hashLen); + ecPoint = newPoint; } - HMAC_Destroy(hmac, PR_TRUE); - okm = key_block; + + if (mechanism == CKM_ECDH1_COFACTOR_DERIVE) { + withCofactor = PR_TRUE; + } else { + /* When not using cofactor derivation, one should + * validate the public key to avoid small subgroup + * attacks. + */ + if (EC_ValidatePublicKey(&privKey->u.ec.ecParams, &ecPoint) != SECSuccess) { + goto ec_loser; + } + } + + rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar, + withCofactor, &tmp); + PORT_Free(ecScalar.data); + ecScalar.data = NULL; + if (privKey != sourceKey->objectInfo) { + nsslowkey_DestroyPrivateKey(privKey); + privKey = NULL; + } + if (arena) { + PORT_FreeArena(arena, PR_FALSE); + arena = NULL; + } + + if (rv != SECSuccess) { + crv = sftk_MapCryptError(PORT_GetError()); + break; + } + + /* + * apply the kdf function. + */ + if (mechParams->kdf == CKD_NULL) { + /* + * tmp is the raw data created by ECDH_Derive, + * secret and secretlen are the values we will + * eventually pass as our generated key. + */ + secret = tmp.data; + secretlen = tmp.len; + } else { + secretlen = keySize; + crv = sftk_ANSI_X9_63_kdf(&secret, keySize, + &tmp, mechParams->pSharedData, + mechParams->ulSharedDataLen, mechParams->kdf); + PORT_ZFree(tmp.data, tmp.len); + if (crv != CKR_OK) { + break; + } + tmp.data = secret; + tmp.len = secretlen; + } + + /* + * if keySize is supplied, then we are generating a key of a specific + * length. This is done by taking the least significant 'keySize' + * bytes from the unsigned value calculated by ECDH. Note: this may + * mean padding temp with extra leading zeros from what ECDH_Derive + * already returned (which itself may contain leading zeros). + */ + if (keySize) { + if (secretlen < keySize) { + keyData = PORT_ZAlloc(keySize); + if (!keyData) { + PORT_ZFree(tmp.data, tmp.len); + crv = CKR_HOST_MEMORY; + break; + } + PORT_Memcpy(&keyData[keySize - secretlen], secret, secretlen); + secret = keyData; + } else { + secret += (secretlen - keySize); + } + secretlen = keySize; + } + + sftk_forceAttribute(key, CKA_VALUE, secret, secretlen); + PORT_ZFree(tmp.data, tmp.len); + if (keyData) { + PORT_ZFree(keyData, keySize); + } + break; + + ec_loser: + crv = CKR_ARGUMENTS_BAD; + PORT_Free(ecScalar.data); + if (privKey != sourceKey->objectInfo) + nsslowkey_DestroyPrivateKey(privKey); + if (arena) { + PORT_FreeArena(arena, PR_FALSE); + } + break; } - /* key material = prk */ - crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize); - break; - } /* end of CKM_NSS_HKDF_* */ - - case CKM_NSS_JPAKE_ROUND2_SHA1: hashType = HASH_AlgSHA1; goto jpake2; - case CKM_NSS_JPAKE_ROUND2_SHA256: hashType = HASH_AlgSHA256; goto jpake2; - case CKM_NSS_JPAKE_ROUND2_SHA384: hashType = HASH_AlgSHA384; goto jpake2; - case CKM_NSS_JPAKE_ROUND2_SHA512: hashType = HASH_AlgSHA512; goto jpake2; -jpake2: - if (pMechanism->pParameter == NULL || - pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params)) - crv = CKR_MECHANISM_PARAM_INVALID; - if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN)) - crv = CKR_TEMPLATE_INCONSISTENT; - if (crv == CKR_OK) +#endif /* NSS_DISABLE_ECC */ + + /* See RFC 5869 and CK_NSS_HKDFParams for documentation. */ + case CKM_NSS_HKDF_SHA1: + hashType = HASH_AlgSHA1; + goto hkdf; + case CKM_NSS_HKDF_SHA256: + hashType = HASH_AlgSHA256; + goto hkdf; + case CKM_NSS_HKDF_SHA384: + hashType = HASH_AlgSHA384; + goto hkdf; + case CKM_NSS_HKDF_SHA512: + hashType = HASH_AlgSHA512; + goto hkdf; + hkdf : { + const CK_NSS_HKDFParams *params = + (const CK_NSS_HKDFParams *)pMechanism->pParameter; + const SECHashObject *rawHash; + unsigned hashLen; + CK_BYTE buf[HASH_LENGTH_MAX]; + CK_BYTE *prk; /* psuedo-random key */ + CK_ULONG prkLen; + CK_BYTE *okm; /* output keying material */ + + rawHash = HASH_GetRawHashObject(hashType); + if (rawHash == NULL || rawHash->length > sizeof buf) { + crv = CKR_FUNCTION_FAILED; + break; + } + hashLen = rawHash->length; + + if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams) || + !params || (!params->bExpand && !params->bExtract) || + (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) || + (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) { + crv = CKR_MECHANISM_PARAM_INVALID; + break; + } + if (keySize == 0 || keySize > sizeof key_block || + (!params->bExpand && keySize > hashLen) || + (params->bExpand && keySize > 255 * hashLen)) { + crv = CKR_TEMPLATE_INCONSISTENT; + break; + } crv = sftk_DeriveSensitiveCheck(sourceKey, key); - if (crv == CKR_OK) - crv = jpake_Round2(hashType, - (CK_NSS_JPAKERound2Params *) pMechanism->pParameter, - sourceKey, key); - break; + if (crv != CKR_OK) + break; - case CKM_NSS_JPAKE_FINAL_SHA1: hashType = HASH_AlgSHA1; goto jpakeFinal; - case CKM_NSS_JPAKE_FINAL_SHA256: hashType = HASH_AlgSHA256; goto jpakeFinal; - case CKM_NSS_JPAKE_FINAL_SHA384: hashType = HASH_AlgSHA384; goto jpakeFinal; - case CKM_NSS_JPAKE_FINAL_SHA512: hashType = HASH_AlgSHA512; goto jpakeFinal; -jpakeFinal: - if (pMechanism->pParameter == NULL || - pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams)) - crv = CKR_MECHANISM_PARAM_INVALID; - /* We purposely do not do the derive sensitivity check; we want to be - able to derive non-sensitive keys while allowing the ROUND1 and - ROUND2 keys to be sensitive (which they always are, since they are - in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE - in the template in order for the resultant keyblock key to be - sensitive. - */ - if (crv == CKR_OK) - crv = jpake_Final(hashType, - (CK_NSS_JPAKEFinalParams *) pMechanism->pParameter, - sourceKey, key); - break; + /* HKDF-Extract(salt, base key value) */ + if (params->bExtract) { + CK_BYTE *salt; + CK_ULONG saltLen; + HMACContext *hmac; + unsigned int bufLen; + + salt = params->pSalt; + saltLen = params->ulSaltLen; + if (salt == NULL) { + saltLen = hashLen; + salt = buf; + memset(salt, 0, saltLen); + } + hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS); + if (!hmac) { + crv = CKR_HOST_MEMORY; + break; + } + HMAC_Begin(hmac); + HMAC_Update(hmac, (const unsigned char *)att->attrib.pValue, + att->attrib.ulValueLen); + HMAC_Finish(hmac, buf, &bufLen, sizeof(buf)); + HMAC_Destroy(hmac, PR_TRUE); + PORT_Assert(bufLen == rawHash->length); + prk = buf; + prkLen = bufLen; + } else { + /* PRK = base key value */ + prk = (CK_BYTE *)att->attrib.pValue; + prkLen = att->attrib.ulValueLen; + } + + /* HKDF-Expand */ + if (!params->bExpand) { + okm = prk; + } else { + /* T(1) = HMAC-Hash(prk, "" | info | 0x01) + * T(n) = HMAC-Hash(prk, T(n-1) | info | n + * key material = T(1) | ... | T(n) + */ + HMACContext *hmac; + CK_BYTE i; + unsigned iterations = PR_ROUNDUP(keySize, hashLen) / hashLen; + hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS); + if (hmac == NULL) { + crv = CKR_HOST_MEMORY; + break; + } + for (i = 1; i <= iterations; ++i) { + unsigned len; + HMAC_Begin(hmac); + if (i > 1) { + HMAC_Update(hmac, key_block + ((i - 2) * hashLen), hashLen); + } + if (params->ulInfoLen != 0) { + HMAC_Update(hmac, params->pInfo, params->ulInfoLen); + } + HMAC_Update(hmac, &i, 1); + HMAC_Finish(hmac, key_block + ((i - 1) * hashLen), &len, + hashLen); + PORT_Assert(len == hashLen); + } + HMAC_Destroy(hmac, PR_TRUE); + okm = key_block; + } + /* key material = prk */ + crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize); + break; + } /* end of CKM_NSS_HKDF_* */ + + case CKM_NSS_JPAKE_ROUND2_SHA1: + hashType = HASH_AlgSHA1; + goto jpake2; + case CKM_NSS_JPAKE_ROUND2_SHA256: + hashType = HASH_AlgSHA256; + goto jpake2; + case CKM_NSS_JPAKE_ROUND2_SHA384: + hashType = HASH_AlgSHA384; + goto jpake2; + case CKM_NSS_JPAKE_ROUND2_SHA512: + hashType = HASH_AlgSHA512; + goto jpake2; + jpake2: + if (pMechanism->pParameter == NULL || + pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params)) + crv = CKR_MECHANISM_PARAM_INVALID; + if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN)) + crv = CKR_TEMPLATE_INCONSISTENT; + if (crv == CKR_OK) + crv = sftk_DeriveSensitiveCheck(sourceKey, key); + if (crv == CKR_OK) + crv = jpake_Round2(hashType, + (CK_NSS_JPAKERound2Params *)pMechanism->pParameter, + sourceKey, key); + break; + + case CKM_NSS_JPAKE_FINAL_SHA1: + hashType = HASH_AlgSHA1; + goto jpakeFinal; + case CKM_NSS_JPAKE_FINAL_SHA256: + hashType = HASH_AlgSHA256; + goto jpakeFinal; + case CKM_NSS_JPAKE_FINAL_SHA384: + hashType = HASH_AlgSHA384; + goto jpakeFinal; + case CKM_NSS_JPAKE_FINAL_SHA512: + hashType = HASH_AlgSHA512; + goto jpakeFinal; + jpakeFinal: + if (pMechanism->pParameter == NULL || + pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams)) + crv = CKR_MECHANISM_PARAM_INVALID; + /* We purposely do not do the derive sensitivity check; we want to be + able to derive non-sensitive keys while allowing the ROUND1 and + ROUND2 keys to be sensitive (which they always are, since they are + in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE + in the template in order for the resultant keyblock key to be + sensitive. + */ + if (crv == CKR_OK) + crv = jpake_Final(hashType, + (CK_NSS_JPAKEFinalParams *)pMechanism->pParameter, + sourceKey, key); + break; - default: - crv = CKR_MECHANISM_INVALID; + default: + crv = CKR_MECHANISM_INVALID; } if (att) { sftk_FreeAttribute(att); } sftk_FreeObject(sourceKey); - if (crv != CKR_OK) { - if (key) sftk_FreeObject(key); - return crv; + if (crv != CKR_OK) { + if (key) + sftk_FreeObject(key); + return crv; } /* link the key object into the list */ if (key) { - SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); - PORT_Assert(sessKey); - /* get the session */ - sessKey->wasDerived = PR_TRUE; - session = sftk_SessionFromHandle(hSession); - if (session == NULL) { - sftk_FreeObject(key); - return CKR_HOST_MEMORY; - } - - crv = sftk_handleObject(key,session); - sftk_FreeSession(session); - *phKey = key->handle; - sftk_FreeObject(key); + SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key); + PORT_Assert(sessKey); + /* get the session */ + sessKey->wasDerived = PR_TRUE; + session = sftk_SessionFromHandle(hSession); + if (session == NULL) { + sftk_FreeObject(key); + return CKR_HOST_MEMORY; + } + + crv = sftk_handleObject(key, session); + sftk_FreeSession(session); + *phKey = key->handle; + sftk_FreeObject(key); } return crv; } - -/* NSC_GetFunctionStatus obtains an updated status of a function running +/* NSC_GetFunctionStatus obtains an updated status of a function running * in parallel with an application. */ -CK_RV NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession) +CK_RV +NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession) { CHECK_FORK(); @@ -7253,20 +7558,22 @@ CK_RV NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession) } /* NSC_CancelFunction cancels a function running in parallel */ -CK_RV NSC_CancelFunction(CK_SESSION_HANDLE hSession) +CK_RV +NSC_CancelFunction(CK_SESSION_HANDLE hSession) { CHECK_FORK(); return CKR_FUNCTION_NOT_PARALLEL; } -/* NSC_GetOperationState saves the state of the cryptographic - *operation in a session. +/* NSC_GetOperationState saves the state of the cryptographic + * operation in a session. * NOTE: This code only works for digest functions for now. eventually need * to add full flatten/resurect to our state stuff so that all types of state * can be saved */ -CK_RV NSC_GetOperationState(CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) +CK_RV +NSC_GetOperationState(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) { SFTKSessionContext *context; SFTKSession *session; @@ -7277,39 +7584,38 @@ CK_RV NSC_GetOperationState(CK_SESSION_HANDLE hSession, /* make sure we're legal */ crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session); - if (crv != CKR_OK) return crv; + if (crv != CKR_OK) + return crv; - *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE) - + sizeof(SFTKContextType); + *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE) + sizeof(SFTKContextType); if (pOperationState == NULL) { sftk_FreeSession(session); - return CKR_OK; + return CKR_OK; } else { - if (pOSLen < *pulOperationStateLen) { - return CKR_BUFFER_TOO_SMALL; - } + if (pOSLen < *pulOperationStateLen) { + return CKR_BUFFER_TOO_SMALL; + } } - PORT_Memcpy(pOperationState,&context->type,sizeof(SFTKContextType)); + PORT_Memcpy(pOperationState, &context->type, sizeof(SFTKContextType)); pOperationState += sizeof(SFTKContextType); - PORT_Memcpy(pOperationState,&context->currentMech, - sizeof(CK_MECHANISM_TYPE)); + PORT_Memcpy(pOperationState, &context->currentMech, + sizeof(CK_MECHANISM_TYPE)); pOperationState += sizeof(CK_MECHANISM_TYPE); - PORT_Memcpy(pOperationState,context->cipherInfo,context->cipherInfoLen); + PORT_Memcpy(pOperationState, context->cipherInfo, context->cipherInfoLen); sftk_FreeSession(session); return CKR_OK; } +#define sftk_Decrement(stateSize, len) \ + stateSize = ((stateSize) > (CK_ULONG)(len)) ? ((stateSize) - (CK_ULONG)(len)) : 0; -#define sftk_Decrement(stateSize,len) \ - stateSize = ((stateSize) > (CK_ULONG)(len)) ? \ - ((stateSize) - (CK_ULONG)(len)) : 0; - -/* NSC_SetOperationState restores the state of the cryptographic +/* NSC_SetOperationState restores the state of the cryptographic * operation in a session. This is coded like it can restore lots of * states, but it only works for truly flat cipher structures. */ -CK_RV NSC_SetOperationState(CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, - CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) +CK_RV +NSC_SetOperationState(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, + CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) { SFTKSessionContext *context; SFTKSession *session; @@ -7320,122 +7626,130 @@ CK_RV NSC_SetOperationState(CK_SESSION_HANDLE hSession, CHECK_FORK(); while (ulOperationStateLen != 0) { - /* get what type of state we're dealing with... */ - PORT_Memcpy(&type,pOperationState, sizeof(SFTKContextType)); - - /* fix up session contexts based on type */ - session = sftk_SessionFromHandle(hSession); - if (session == NULL) return CKR_SESSION_HANDLE_INVALID; - context = sftk_ReturnContextByType(session, type); - sftk_SetContextByType(session, type, NULL); - if (context) { - sftk_FreeContext(context); - } - pOperationState += sizeof(SFTKContextType); - sftk_Decrement(ulOperationStateLen,sizeof(SFTKContextType)); - - - /* get the mechanism structure */ - PORT_Memcpy(&mech.mechanism,pOperationState,sizeof(CK_MECHANISM_TYPE)); - pOperationState += sizeof(CK_MECHANISM_TYPE); - sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE)); - /* should be filled in... but not necessary for hash */ - mech.pParameter = NULL; - mech.ulParameterLen = 0; - switch (type) { - case SFTK_HASH: - crv = NSC_DigestInit(hSession,&mech); - if (crv != CKR_OK) break; - crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, - NULL); - if (crv != CKR_OK) break; - PORT_Memcpy(context->cipherInfo,pOperationState, - context->cipherInfoLen); - pOperationState += context->cipherInfoLen; - sftk_Decrement(ulOperationStateLen,context->cipherInfoLen); - break; - default: - /* do sign/encrypt/decrypt later */ - crv = CKR_SAVED_STATE_INVALID; - } - sftk_FreeSession(session); - if (crv != CKR_OK) break; + /* get what type of state we're dealing with... */ + PORT_Memcpy(&type, pOperationState, sizeof(SFTKContextType)); + + /* fix up session contexts based on type */ + session = sftk_SessionFromHandle(hSession); + if (session == NULL) + return CKR_SESSION_HANDLE_INVALID; + context = sftk_ReturnContextByType(session, type); + sftk_SetContextByType(session, type, NULL); + if (context) { + sftk_FreeContext(context); + } + pOperationState += sizeof(SFTKContextType); + sftk_Decrement(ulOperationStateLen, sizeof(SFTKContextType)); + + /* get the mechanism structure */ + PORT_Memcpy(&mech.mechanism, pOperationState, sizeof(CK_MECHANISM_TYPE)); + pOperationState += sizeof(CK_MECHANISM_TYPE); + sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE)); + /* should be filled in... but not necessary for hash */ + mech.pParameter = NULL; + mech.ulParameterLen = 0; + switch (type) { + case SFTK_HASH: + crv = NSC_DigestInit(hSession, &mech); + if (crv != CKR_OK) + break; + crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, + NULL); + if (crv != CKR_OK) + break; + PORT_Memcpy(context->cipherInfo, pOperationState, + context->cipherInfoLen); + pOperationState += context->cipherInfoLen; + sftk_Decrement(ulOperationStateLen, context->cipherInfoLen); + break; + default: + /* do sign/encrypt/decrypt later */ + crv = CKR_SAVED_STATE_INVALID; + } + sftk_FreeSession(session); + if (crv != CKR_OK) + break; } return crv; } /* Dual-function cryptographic operations */ -/* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption +/* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption * operation. */ -CK_RV NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, - CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, - CK_ULONG_PTR pulEncryptedPartLen) +CK_RV +NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, + CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen) { CK_RV crv; CHECK_FORK(); - crv = NSC_EncryptUpdate(hSession,pPart,ulPartLen, pEncryptedPart, - pulEncryptedPartLen); - if (crv != CKR_OK) return crv; - crv = NSC_DigestUpdate(hSession,pPart,ulPartLen); + crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart, + pulEncryptedPartLen); + if (crv != CKR_OK) + return crv; + crv = NSC_DigestUpdate(hSession, pPart, ulPartLen); return crv; } - -/* NSC_DecryptDigestUpdate continues a multiple-part decryption and +/* NSC_DecryptDigestUpdate continues a multiple-part decryption and * digesting operation. */ -CK_RV NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, - CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) +CK_RV +NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { CK_RV crv; CHECK_FORK(); - crv = NSC_DecryptUpdate(hSession,pEncryptedPart, ulEncryptedPartLen, - pPart, pulPartLen); - if (crv != CKR_OK) return crv; - crv = NSC_DigestUpdate(hSession,pPart,*pulPartLen); + crv = NSC_DecryptUpdate(hSession, pEncryptedPart, ulEncryptedPartLen, + pPart, pulPartLen); + if (crv != CKR_OK) + return crv; + crv = NSC_DigestUpdate(hSession, pPart, *pulPartLen); return crv; } - -/* NSC_SignEncryptUpdate continues a multiple-part signing and +/* NSC_SignEncryptUpdate continues a multiple-part signing and * encryption operation. */ -CK_RV NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, - CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, - CK_ULONG_PTR pulEncryptedPartLen) +CK_RV +NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, + CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen) { CK_RV crv; CHECK_FORK(); - crv = NSC_EncryptUpdate(hSession,pPart,ulPartLen, pEncryptedPart, - pulEncryptedPartLen); - if (crv != CKR_OK) return crv; - crv = NSC_SignUpdate(hSession,pPart,ulPartLen); + crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart, + pulEncryptedPartLen); + if (crv != CKR_OK) + return crv; + crv = NSC_SignUpdate(hSession, pPart, ulPartLen); return crv; } - -/* NSC_DecryptVerifyUpdate continues a multiple-part decryption +/* NSC_DecryptVerifyUpdate continues a multiple-part decryption * and verify operation. */ -CK_RV NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, - CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, - CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) +CK_RV +NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, + CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { CK_RV crv; CHECK_FORK(); - crv = NSC_DecryptUpdate(hSession,pEncryptedData, ulEncryptedDataLen, - pData, pulDataLen); - if (crv != CKR_OK) return crv; + crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen, + pData, pulDataLen); + if (crv != CKR_OK) + return crv; crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen); return crv; @@ -7444,7 +7758,8 @@ CK_RV NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, /* NSC_DigestKey continues a multi-part message-digesting operation, * by digesting the value of a secret key as part of the data already digested. */ -CK_RV NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) +CK_RV +NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) { SFTKSession *session = NULL; SFTKObject *key = NULL; @@ -7454,27 +7769,29 @@ CK_RV NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) CHECK_FORK(); session = sftk_SessionFromHandle(hSession); - if (session == NULL) return CKR_SESSION_HANDLE_INVALID; + if (session == NULL) + return CKR_SESSION_HANDLE_INVALID; - key = sftk_ObjectFromHandle(hKey,session); + key = sftk_ObjectFromHandle(hKey, session); sftk_FreeSession(session); - if (key == NULL) return CKR_KEY_HANDLE_INVALID; + if (key == NULL) + return CKR_KEY_HANDLE_INVALID; /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */ /* make sure it's a valid key for this operation */ if (key->objclass != CKO_SECRET_KEY) { - sftk_FreeObject(key); - return CKR_KEY_TYPE_INCONSISTENT; + sftk_FreeObject(key); + return CKR_KEY_TYPE_INCONSISTENT; } /* get the key value */ - att = sftk_FindAttribute(key,CKA_VALUE); + att = sftk_FindAttribute(key, CKA_VALUE); sftk_FreeObject(key); if (!att) { - return CKR_KEY_HANDLE_INVALID; + return CKR_KEY_HANDLE_INVALID; } - crv = NSC_DigestUpdate(hSession,(CK_BYTE_PTR)att->attrib.pValue, - att->attrib.ulValueLen); + crv = NSC_DigestUpdate(hSession, (CK_BYTE_PTR)att->attrib.pValue, + att->attrib.ulValueLen); sftk_FreeAttribute(att); return crv; } |