andre@0: /* This Source Code Form is subject to the terms of the Mozilla Public andre@0: * License, v. 2.0. If a copy of the MPL was not distributed with this andre@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ andre@0: andre@0: #include "seccomon.h" andre@0: #include "secerr.h" andre@0: #include "blapi.h" andre@0: #include "pkcs11i.h" andre@0: #include "softoken.h" andre@0: #include "hmacct.h" andre@0: andre@0: /* MACMechanismToHash converts a PKCS#11 MAC mechanism into a freebl hash andre@0: * type. */ andre@0: static HASH_HashType andre@0: MACMechanismToHash(CK_MECHANISM_TYPE mech) andre@0: { andre@0: switch (mech) { andre@0: case CKM_MD5_HMAC: andre@0: case CKM_SSL3_MD5_MAC: andre@0: return HASH_AlgMD5; andre@0: case CKM_SHA_1_HMAC: andre@0: case CKM_SSL3_SHA1_MAC: andre@0: return HASH_AlgSHA1; andre@0: case CKM_SHA224_HMAC: andre@0: return HASH_AlgSHA224; andre@0: case CKM_SHA256_HMAC: andre@0: return HASH_AlgSHA256; andre@0: case CKM_SHA384_HMAC: andre@0: return HASH_AlgSHA384; andre@0: case CKM_SHA512_HMAC: andre@0: return HASH_AlgSHA512; andre@0: } andre@0: return HASH_AlgNULL; andre@0: } andre@0: andre@0: static sftk_MACConstantTimeCtx * andre@0: SetupMAC(CK_MECHANISM_PTR mech, SFTKObject *key) andre@0: { andre@0: CK_NSS_MAC_CONSTANT_TIME_PARAMS *params = andre@0: (CK_NSS_MAC_CONSTANT_TIME_PARAMS *) mech->pParameter; andre@0: sftk_MACConstantTimeCtx *ctx; andre@0: HASH_HashType alg; andre@0: SFTKAttribute *keyval; andre@0: unsigned char secret[sizeof(ctx->secret)]; andre@0: unsigned int secretLength; andre@0: andre@0: if (mech->ulParameterLen != sizeof(CK_NSS_MAC_CONSTANT_TIME_PARAMS)) { andre@0: return NULL; andre@0: } andre@0: andre@0: alg = MACMechanismToHash(params->macAlg); andre@0: if (alg == HASH_AlgNULL) { andre@0: return NULL; andre@0: } andre@0: andre@0: keyval = sftk_FindAttribute(key,CKA_VALUE); andre@0: if (keyval == NULL) { andre@0: return NULL; andre@0: } andre@0: secretLength = keyval->attrib.ulValueLen; andre@0: if (secretLength > sizeof(secret)) { andre@0: sftk_FreeAttribute(keyval); andre@0: return NULL; andre@0: } andre@0: memcpy(secret, keyval->attrib.pValue, secretLength); andre@0: sftk_FreeAttribute(keyval); andre@0: andre@0: ctx = PORT_Alloc(sizeof(sftk_MACConstantTimeCtx)); andre@0: if (!ctx) { andre@0: return NULL; andre@0: } andre@0: andre@0: memcpy(ctx->secret, secret, secretLength); andre@0: ctx->secretLength = secretLength; andre@0: ctx->hash = HASH_GetRawHashObject(alg); andre@0: ctx->totalLength = params->ulBodyTotalLen; andre@0: andre@0: return ctx; andre@0: } andre@0: andre@0: sftk_MACConstantTimeCtx * andre@0: sftk_HMACConstantTime_New(CK_MECHANISM_PTR mech, SFTKObject *key) andre@0: { andre@0: CK_NSS_MAC_CONSTANT_TIME_PARAMS *params = andre@0: (CK_NSS_MAC_CONSTANT_TIME_PARAMS *) mech->pParameter; andre@0: sftk_MACConstantTimeCtx *ctx; andre@0: andre@0: if (params->ulHeaderLen > sizeof(ctx->header)) { andre@0: return NULL; andre@0: } andre@0: ctx = SetupMAC(mech, key); andre@0: if (!ctx) { andre@0: return NULL; andre@0: } andre@0: andre@0: ctx->headerLength = params->ulHeaderLen; andre@0: memcpy(ctx->header, params->pHeader, params->ulHeaderLen); andre@0: return ctx; andre@0: } andre@0: andre@0: sftk_MACConstantTimeCtx * andre@0: sftk_SSLv3MACConstantTime_New(CK_MECHANISM_PTR mech, SFTKObject *key) andre@0: { andre@0: CK_NSS_MAC_CONSTANT_TIME_PARAMS *params = andre@0: (CK_NSS_MAC_CONSTANT_TIME_PARAMS *) mech->pParameter; andre@0: unsigned int padLength = 40, j; andre@0: sftk_MACConstantTimeCtx *ctx; andre@0: andre@0: if (params->macAlg != CKM_SSL3_MD5_MAC && andre@0: params->macAlg != CKM_SSL3_SHA1_MAC) { andre@0: return NULL; andre@0: } andre@0: ctx = SetupMAC(mech, key); andre@0: if (!ctx) { andre@0: return NULL; andre@0: } andre@0: andre@0: if (params->macAlg == CKM_SSL3_MD5_MAC) { andre@0: padLength = 48; andre@0: } andre@0: andre@0: ctx->headerLength = andre@0: ctx->secretLength + andre@0: padLength + andre@0: params->ulHeaderLen; andre@0: andre@0: if (ctx->headerLength > sizeof(ctx->header)) { andre@0: goto loser; andre@0: } andre@0: andre@0: j = 0; andre@0: memcpy(&ctx->header[j], ctx->secret, ctx->secretLength); andre@0: j += ctx->secretLength; andre@0: memset(&ctx->header[j], 0x36, padLength); andre@0: j += padLength; andre@0: memcpy(&ctx->header[j], params->pHeader, params->ulHeaderLen); andre@0: andre@0: return ctx; andre@0: andre@0: loser: andre@0: PORT_Free(ctx); andre@0: return NULL; andre@0: } andre@0: andre@0: void andre@0: sftk_HMACConstantTime_Update(void *pctx, void *data, unsigned int len) andre@0: { andre@0: sftk_MACConstantTimeCtx *ctx = (sftk_MACConstantTimeCtx *) pctx; andre@0: SECStatus rv = HMAC_ConstantTime( andre@0: ctx->mac, NULL, sizeof(ctx->mac), andre@0: ctx->hash, andre@0: ctx->secret, ctx->secretLength, andre@0: ctx->header, ctx->headerLength, andre@0: data, len, andre@0: ctx->totalLength); andre@0: PORT_Assert(rv == SECSuccess); andre@0: } andre@0: andre@0: void andre@0: sftk_SSLv3MACConstantTime_Update(void *pctx, void *data, unsigned int len) andre@0: { andre@0: sftk_MACConstantTimeCtx *ctx = (sftk_MACConstantTimeCtx *) pctx; andre@0: SECStatus rv = SSLv3_MAC_ConstantTime( andre@0: ctx->mac, NULL, sizeof(ctx->mac), andre@0: ctx->hash, andre@0: ctx->secret, ctx->secretLength, andre@0: ctx->header, ctx->headerLength, andre@0: data, len, andre@0: ctx->totalLength); andre@0: PORT_Assert(rv == SECSuccess); andre@0: } andre@0: andre@0: void andre@0: sftk_MACConstantTime_EndHash(void *pctx, void *out, unsigned int *outLength, andre@0: unsigned int maxLength) andre@0: { andre@0: const sftk_MACConstantTimeCtx *ctx = (sftk_MACConstantTimeCtx *) pctx; andre@0: unsigned int toCopy = ctx->hash->length; andre@0: if (toCopy > maxLength) { andre@0: toCopy = maxLength; andre@0: } andre@0: memcpy(out, ctx->mac, toCopy); andre@0: if (outLength) { andre@0: *outLength = toCopy; andre@0: } andre@0: } andre@0: andre@0: void andre@0: sftk_MACConstantTime_DestroyContext(void *pctx, PRBool free) andre@0: { andre@0: PORT_Free(pctx); andre@0: }