int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) { byte* ip; byte* op; word32 i, hmac_block_size = 0; int ret = 0; void* heap = NULL; if (hmac == NULL || (key == NULL && length != 0) || !(type == MD5 || type == SHA || type == SHA256 || type == SHA384 || type == SHA512 || type == BLAKE2B_ID || type == SHA224)) { return BAD_FUNC_ARG; } hmac->innerHashKeyed = 0; hmac->macType = (byte)type; #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { #if defined(HAVE_CAVIUM) if (length > HMAC_BLOCK_SIZE) { return WC_KEY_SIZE_E; } if (key != NULL) { XMEMCPY(hmac->ipad, key, length); } hmac->keyLen = (word16)length; return 0; /* nothing to do here */ #endif /* HAVE_CAVIUM */ } #endif /* WOLFSSL_ASYNC_CRYPT */ ret = _InitHmac(hmac, type, heap); if (ret != 0) return ret; #ifdef HAVE_FIPS if (length < HMAC_FIPS_MIN_KEY) return HMAC_MIN_KEYLEN_E; #endif ip = (byte*)hmac->ipad; op = (byte*)hmac->opad; switch (hmac->macType) { #ifndef NO_MD5 case MD5: hmac_block_size = MD5_BLOCK_SIZE; if (length <= MD5_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_Md5Update(&hmac->hash.md5, key, length); if (ret != 0) break; ret = wc_Md5Final(&hmac->hash.md5, ip); if (ret != 0) break; length = MD5_DIGEST_SIZE; } break; #endif /* !NO_MD5 */ #ifndef NO_SHA case SHA: hmac_block_size = SHA_BLOCK_SIZE; if (length <= SHA_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_ShaUpdate(&hmac->hash.sha, key, length); if (ret != 0) break; ret = wc_ShaFinal(&hmac->hash.sha, ip); if (ret != 0) break; length = SHA_DIGEST_SIZE; } break; #endif /* !NO_SHA */ #ifdef WOLFSSL_SHA224 case SHA224: { hmac_block_size = SHA224_BLOCK_SIZE; if (length <= SHA224_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_Sha224Update(&hmac->hash.sha224, key, length); if (ret != 0) break; ret = wc_Sha224Final(&hmac->hash.sha224, ip); if (ret != 0) break; length = SHA224_DIGEST_SIZE; } } break; #endif /* WOLFSSL_SHA224 */ #ifndef NO_SHA256 case SHA256: hmac_block_size = SHA256_BLOCK_SIZE; if (length <= SHA256_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_Sha256Update(&hmac->hash.sha256, key, length); if (ret != 0) break; ret = wc_Sha256Final(&hmac->hash.sha256, ip); if (ret != 0) break; length = SHA256_DIGEST_SIZE; } break; #endif /* !NO_SHA256 */ #ifdef WOLFSSL_SHA512 #ifdef WOLFSSL_SHA384 case SHA384: hmac_block_size = SHA384_BLOCK_SIZE; if (length <= SHA384_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_Sha384Update(&hmac->hash.sha384, key, length); if (ret != 0) break; ret = wc_Sha384Final(&hmac->hash.sha384, ip); if (ret != 0) break; length = SHA384_DIGEST_SIZE; } break; #endif /* WOLFSSL_SHA384 */ case SHA512: hmac_block_size = SHA512_BLOCK_SIZE; if (length <= SHA512_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_Sha512Update(&hmac->hash.sha512, key, length); if (ret != 0) break; ret = wc_Sha512Final(&hmac->hash.sha512, ip); if (ret != 0) break; length = SHA512_DIGEST_SIZE; } break; #endif /* WOLFSSL_SHA512 */ #ifdef HAVE_BLAKE2 case BLAKE2B_ID: hmac_block_size = BLAKE2B_BLOCKBYTES; if (length <= BLAKE2B_BLOCKBYTES) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_Blake2bUpdate(&hmac->hash.blake2b, key, length); if (ret != 0) break; ret = wc_Blake2bFinal(&hmac->hash.blake2b, ip, BLAKE2B_256); if (ret != 0) break; length = BLAKE2B_256; } break; #endif /* HAVE_BLAKE2 */ default: return BAD_FUNC_ARG; } #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { #if defined(HAVE_INTEL_QA) if (length > hmac_block_size) length = hmac_block_size; /* update key length */ hmac->keyLen = (word16)length; return ret; /* no need to pad below */ #endif } #endif if (ret == 0) { if (length < hmac_block_size) XMEMSET(ip + length, 0, hmac_block_size - length); for(i = 0; i < hmac_block_size; i++) { op[i] = ip[i] ^ OPAD; ip[i] ^= IPAD; } } return ret; }
int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) { byte* ip; byte* op; word32 i, hmac_block_size = 0; int ret = 0; void* heap = NULL; if (hmac == NULL || (key == NULL && length != 0) || !(type == WC_MD5 || type == WC_SHA || type == WC_SHA224 || type == WC_SHA256 || type == WC_SHA384 || type == WC_SHA512 || type == WC_SHA3_224 || type == WC_SHA3_256 || type == WC_SHA3_384 || type == WC_SHA3_512 || type == BLAKE2B_ID)) { return BAD_FUNC_ARG; } /* if set key has already been run then make sure and free existing */ if (hmac->macType != 0) { wc_HmacFree(hmac); } hmac->innerHashKeyed = 0; hmac->macType = (byte)type; ret = _InitHmac(hmac, type, heap); if (ret != 0) return ret; #ifdef HAVE_FIPS if (length < HMAC_FIPS_MIN_KEY) return HMAC_MIN_KEYLEN_E; #endif #ifdef WOLF_CRYPTO_CB hmac->keyRaw = key; /* use buffer directly */ hmac->keyLen = length; #endif ip = (byte*)hmac->ipad; op = (byte*)hmac->opad; switch (hmac->macType) { #ifndef NO_MD5 case WC_MD5: hmac_block_size = WC_MD5_BLOCK_SIZE; if (length <= WC_MD5_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_Md5Update(&hmac->hash.md5, key, length); if (ret != 0) break; ret = wc_Md5Final(&hmac->hash.md5, ip); if (ret != 0) break; length = WC_MD5_DIGEST_SIZE; } break; #endif /* !NO_MD5 */ #ifndef NO_SHA case WC_SHA: hmac_block_size = WC_SHA_BLOCK_SIZE; if (length <= WC_SHA_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_ShaUpdate(&hmac->hash.sha, key, length); if (ret != 0) break; ret = wc_ShaFinal(&hmac->hash.sha, ip); if (ret != 0) break; length = WC_SHA_DIGEST_SIZE; } break; #endif /* !NO_SHA */ #ifdef WOLFSSL_SHA224 case WC_SHA224: { hmac_block_size = WC_SHA224_BLOCK_SIZE; if (length <= WC_SHA224_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_Sha224Update(&hmac->hash.sha224, key, length); if (ret != 0) break; ret = wc_Sha224Final(&hmac->hash.sha224, ip); if (ret != 0) break; length = WC_SHA224_DIGEST_SIZE; } } break; #endif /* WOLFSSL_SHA224 */ #ifndef NO_SHA256 case WC_SHA256: hmac_block_size = WC_SHA256_BLOCK_SIZE; if (length <= WC_SHA256_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_Sha256Update(&hmac->hash.sha256, key, length); if (ret != 0) break; ret = wc_Sha256Final(&hmac->hash.sha256, ip); if (ret != 0) break; length = WC_SHA256_DIGEST_SIZE; } break; #endif /* !NO_SHA256 */ #ifdef WOLFSSL_SHA384 case WC_SHA384: hmac_block_size = WC_SHA384_BLOCK_SIZE; if (length <= WC_SHA384_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_Sha384Update(&hmac->hash.sha384, key, length); if (ret != 0) break; ret = wc_Sha384Final(&hmac->hash.sha384, ip); if (ret != 0) break; length = WC_SHA384_DIGEST_SIZE; } break; #endif /* WOLFSSL_SHA384 */ #ifdef WOLFSSL_SHA512 case WC_SHA512: hmac_block_size = WC_SHA512_BLOCK_SIZE; if (length <= WC_SHA512_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_Sha512Update(&hmac->hash.sha512, key, length); if (ret != 0) break; ret = wc_Sha512Final(&hmac->hash.sha512, ip); if (ret != 0) break; length = WC_SHA512_DIGEST_SIZE; } break; #endif /* WOLFSSL_SHA512 */ #ifdef HAVE_BLAKE2 case BLAKE2B_ID: hmac_block_size = BLAKE2B_BLOCKBYTES; if (length <= BLAKE2B_BLOCKBYTES) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_Blake2bUpdate(&hmac->hash.blake2b, key, length); if (ret != 0) break; ret = wc_Blake2bFinal(&hmac->hash.blake2b, ip, BLAKE2B_256); if (ret != 0) break; length = BLAKE2B_256; } break; #endif /* HAVE_BLAKE2 */ #ifdef WOLFSSL_SHA3 #ifndef WOLFSSL_NOSHA3_224 case WC_SHA3_224: hmac_block_size = WC_SHA3_224_BLOCK_SIZE; if (length <= WC_SHA3_224_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_Sha3_224_Update(&hmac->hash.sha3, key, length); if (ret != 0) break; ret = wc_Sha3_224_Final(&hmac->hash.sha3, ip); if (ret != 0) break; length = WC_SHA3_224_DIGEST_SIZE; } break; #endif #ifndef WOLFSSL_NOSHA3_256 case WC_SHA3_256: hmac_block_size = WC_SHA3_256_BLOCK_SIZE; if (length <= WC_SHA3_256_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_Sha3_256_Update(&hmac->hash.sha3, key, length); if (ret != 0) break; ret = wc_Sha3_256_Final(&hmac->hash.sha3, ip); if (ret != 0) break; length = WC_SHA3_256_DIGEST_SIZE; } break; #endif #ifndef WOLFSSL_NOSHA3_384 case WC_SHA3_384: hmac_block_size = WC_SHA3_384_BLOCK_SIZE; if (length <= WC_SHA3_384_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_Sha3_384_Update(&hmac->hash.sha3, key, length); if (ret != 0) break; ret = wc_Sha3_384_Final(&hmac->hash.sha3, ip); if (ret != 0) break; length = WC_SHA3_384_DIGEST_SIZE; } break; #endif #ifndef WOLFSSL_NOSHA3_512 case WC_SHA3_512: hmac_block_size = WC_SHA3_512_BLOCK_SIZE; if (length <= WC_SHA3_512_BLOCK_SIZE) { if (key != NULL) { XMEMCPY(ip, key, length); } } else { ret = wc_Sha3_512_Update(&hmac->hash.sha3, key, length); if (ret != 0) break; ret = wc_Sha3_512_Final(&hmac->hash.sha3, ip); if (ret != 0) break; length = WC_SHA3_512_DIGEST_SIZE; } break; #endif #endif /* WOLFSSL_SHA3 */ default: return BAD_FUNC_ARG; } #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { #if defined(HAVE_INTEL_QA) || defined(HAVE_CAVIUM) #ifdef HAVE_INTEL_QA if (IntelQaHmacGetType(hmac->macType, NULL) == 0) #endif { if (length > hmac_block_size) length = hmac_block_size; /* update key length */ hmac->keyLen = (word16)length; return ret; } /* no need to pad below */ #endif } #endif if (ret == 0) { if (length < hmac_block_size) XMEMSET(ip + length, 0, hmac_block_size - length); for(i = 0; i < hmac_block_size; i++) { op[i] = ip[i] ^ OPAD; ip[i] ^= IPAD; } } return ret; }