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