/* algo_hmac - hash-based message authentication code (HMAC) wrapper * * Copyright(c) 2021 Glenn Strauss gstrauss()gluelogic.com All rights reserved * License: BSD 3-clause (same as lighttpd) */ #include "first.h" #include "algo_hmac.h" #include "sys-crypto-md.h" #ifdef USE_LIB_CRYPTO #if defined(USE_NETTLE_CRYPTO) #include #elif defined(USE_MBEDTLS_CRYPTO) #include #elif defined(USE_WOLFSSL_CRYPTO) #include #elif defined(USE_OPENSSL_CRYPTO) #include #include #elif defined(USE_GNUTLS_CRYPTO) #include #elif defined(USE_NSS_CRYPTO) #if 0 /*(nss/alghmac.h might not be present)*/ #ifdef NSS_VER_INCLUDE #include #else #include #endif #endif #endif #endif #ifndef USE_NETTLE_CRYPTO #if defined(USE_OPENSSL_CRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L #define HMAC EVP_HMAC static unsigned char * EVP_HMAC (const EVP_MD *evp_md, const void *key, int key_len, const unsigned char *d, int n, unsigned char *md, size_t *md_len) { EVP_PKEY * const pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, key_len); if (NULL == pkey) return NULL; EVP_MD_CTX * const ctx = EVP_MD_CTX_new(); if (NULL == ctx) { EVP_PKEY_free(pkey); return NULL; } int rc = (1 == EVP_DigestSignInit(ctx, NULL, evp_md, NULL, pkey)) && (1 == EVP_DigestSignUpdate(ctx, d, n)) && (1 == EVP_DigestSignFinal(ctx, md, md_len)); EVP_MD_CTX_free(ctx); EVP_PKEY_free(pkey); return (1 == rc) ? md : NULL; } typedef size_t evp_siglen_t; #else typedef unsigned int evp_siglen_t; #endif #endif int li_hmac_md5 (unsigned char digest[MD5_DIGEST_LENGTH], const void * const secret, const uint32_t slen, const unsigned char * const msg, const uint32_t mlen) { struct const_iovec iov[] = { { secret, slen }, { msg, mlen } }; MD5_iov(digest, iov, sizeof(iov)/sizeof(*iov)); return 1; } #ifdef USE_LIB_CRYPTO_SHA1 int li_hmac_sha1 (unsigned char digest[SHA_DIGEST_LENGTH], const void * const secret, const uint32_t slen, const unsigned char * const msg, const uint32_t mlen) { #ifdef USE_LIB_CRYPTO #if defined(USE_NETTLE_CRYPTO) struct hmac_sha1_ctx ctx; hmac_sha1_set_key(&ctx, slen, (const uint8_t *)secret); hmac_sha1_update(&ctx, mlen, (const uint8_t *)msg); hmac_sha1_digest(&ctx, SHA_DIGEST_LENGTH, (uint8_t *)digest); return 1; #elif defined(USE_MBEDTLS_CRYPTO) \ && defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA1_C) return 0 == mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), (const unsigned char *)secret, slen, (const unsigned char *)msg, mlen, digest); #elif defined(USE_WOLFSSL_CRYPTO) Hmac hmac; if (0 != wc_HmacInit(&hmac, NULL, INVALID_DEVID) || wc_HmacSetKey(&hmac, WC_SHA, (const byte *)secret, (word32)slen) < 0 || wc_HmacUpdate(&hmac, (const byte *)msg, (word32)mlen) < 0 || wc_HmacFinal(&hmac, (byte *)digest) < 0) return 0; return 1; #elif defined(USE_OPENSSL_CRYPTO) evp_siglen_t dlen = SHA_DIGEST_LENGTH; return (NULL != HMAC(EVP_sha1(), (const unsigned char *)secret, (int)slen, (const unsigned char *)msg, mlen, digest, &dlen)); #elif defined(USE_GNUTLS_CRYPTO) return 0 == gnutls_hmac_fast(GNUTLS_MAC_SHA1, (const unsigned char *)secret, slen, (const unsigned char *)msg, mlen, digest); #elif defined(USE_NSS_CRYPTO) /*(HMAC* funcs not public export of libfreebl3.so, * even though nss3/alghmac.h is public (WTH?!))*/ #if 0 HMACContext *hmac = HMAC_Create(HASH_GetHashObject(HASH_AlgSHA1), (const unsigned char *)secret, slen, PR_FALSE); if (NULL == hmac) return 0; HMAC_Begin(hmac); HMAC_Update(hmac, (const unsigned char *)msg, mlen); unsigned int dlen; int rc = HMAC_Finish(hmac, digest, &dlen, SHA_DIGEST_LENGTH); HMAC_Destroy(hmac, PR_TRUE); return (SECSuccess == rc); #else UNUSED(digest); UNUSED(secret); UNUSED(slen); UNUSED(msg); UNUSED(mlen); return 0; #endif #else #error "unexpected; crypto lib not configured for HMAC SHA1" #endif #else UNUSED(digest); UNUSED(secret); UNUSED(slen); UNUSED(msg); UNUSED(mlen); return 0; #endif } #endif #ifdef USE_LIB_CRYPTO_SHA256 int li_hmac_sha256 (unsigned char digest[SHA256_DIGEST_LENGTH], const void * const secret, const uint32_t slen, const unsigned char * const msg, const uint32_t mlen) { #ifdef USE_LIB_CRYPTO #if defined(USE_NETTLE_CRYPTO) struct hmac_sha256_ctx ctx; hmac_sha256_set_key(&ctx, slen, (const uint8_t *)secret); hmac_sha256_update(&ctx, mlen, (const uint8_t *)msg); hmac_sha256_digest(&ctx, SHA256_DIGEST_LENGTH, (uint8_t *)digest); return 1; #elif defined(USE_MBEDTLS_CRYPTO) \ && defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA256_C) return 0 == mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), (const unsigned char *)secret, slen, (const unsigned char *)msg, mlen, digest); #elif defined(USE_WOLFSSL_CRYPTO) Hmac hmac; if (0 != wc_HmacInit(&hmac, NULL, INVALID_DEVID) || wc_HmacSetKey(&hmac, WC_SHA256,(const byte *)secret,(word32)slen) < 0 || wc_HmacUpdate(&hmac, (const byte *)msg, (word32)mlen) < 0 || wc_HmacFinal(&hmac, (byte *)digest) < 0) return 0; return 1; #elif defined(USE_OPENSSL_CRYPTO) evp_siglen_t dlen = SHA256_DIGEST_LENGTH; return (NULL != HMAC(EVP_sha256(), (const unsigned char *)secret, (int)slen, (const unsigned char *)msg, mlen, digest, &dlen)); #elif defined(USE_GNUTLS_CRYPTO) return 0 == gnutls_hmac_fast(GNUTLS_MAC_SHA256, (const unsigned char *)secret, slen, (const unsigned char *)msg, mlen, digest); #elif defined(USE_NSS_CRYPTO) /*(HMAC* funcs not public export of libfreebl3.so, * even though nss3/alghmac.h is public (WTH?!))*/ #if 0 HMACContext *hmac = HMAC_Create(HASH_GetHashObject(HASH_AlgSHA256), (const unsigned char *)secret, slen, PR_FALSE); if (NULL == hmac) return 0; HMAC_Begin(hmac); HMAC_Update(hmac, (const unsigned char *)msg, mlen); unsigned int dlen; int rc = HMAC_Finish(hmac, digest, &dlen, SHA256_DIGEST_LENGTH); HMAC_Destroy(hmac, PR_TRUE); return (SECSuccess == rc); #else UNUSED(digest); UNUSED(secret); UNUSED(slen); UNUSED(msg); UNUSED(mlen); return 0; #endif #else #error "unexpected; crypto lib not configured for HMAC SHA256" #endif #else UNUSED(digest); UNUSED(secret); UNUSED(slen); UNUSED(msg); UNUSED(mlen); return 0; #endif } #endif #ifdef USE_LIB_CRYPTO_SHA512 int li_hmac_sha512 (unsigned char digest[SHA512_DIGEST_LENGTH], const void * const secret, const uint32_t slen, const unsigned char * const msg, const uint32_t mlen) { #ifdef USE_LIB_CRYPTO #if defined(USE_NETTLE_CRYPTO) struct hmac_sha512_ctx ctx; hmac_sha512_set_key(&ctx, slen, (const uint8_t *)secret); hmac_sha512_update(&ctx, mlen, (const uint8_t *)msg); hmac_sha512_digest(&ctx, SHA512_DIGEST_LENGTH, (uint8_t *)digest); return 1; #elif defined(USE_MBEDTLS_CRYPTO) \ && defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA512_C) return 0 == mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), (const unsigned char *)secret, slen, (const unsigned char *)msg, mlen, digest); #elif defined(USE_WOLFSSL_CRYPTO) Hmac hmac; if (0 != wc_HmacInit(&hmac, NULL, INVALID_DEVID) || wc_HmacSetKey(&hmac, WC_SHA512,(const byte *)secret,(word32)slen) < 0 || wc_HmacUpdate(&hmac, (const byte *)msg, (word32)mlen) < 0 || wc_HmacFinal(&hmac, (byte *)digest) < 0) return 0; return 1; #elif defined(USE_OPENSSL_CRYPTO) evp_siglen_t dlen = SHA512_DIGEST_LENGTH; return (NULL != HMAC(EVP_sha512(), (const unsigned char *)secret, (int)slen, (const unsigned char *)msg, mlen, digest, &dlen)); #elif defined(USE_GNUTLS_CRYPTO) return 0 == gnutls_hmac_fast(GNUTLS_MAC_SHA512, (const unsigned char *)secret, slen, (const unsigned char *)msg, mlen, digest); #elif defined(USE_NSS_CRYPTO) /*(HMAC* funcs not public export of libfreebl3.so, * even though nss3/alghmac.h is public (WTH?!))*/ #if 0 HMACContext *hmac = HMAC_Create(HASH_GetHashObject(HASH_AlgSHA512), (const unsigned char *)secret, slen, PR_FALSE); if (NULL == hmac) return 0; HMAC_Begin(hmac); HMAC_Update(hmac, (const unsigned char *)msg, mlen); unsigned int dlen; int rc = HMAC_Finish(hmac, digest, &dlen, SHA512_DIGEST_LENGTH); HMAC_Destroy(hmac, PR_TRUE); return (SECSuccess == rc); #else UNUSED(digest); UNUSED(secret); UNUSED(slen); UNUSED(msg); UNUSED(mlen); return 0; #endif #else #error "unexpected; crypto lib not configured for HMAC SHA512" #endif #else UNUSED(digest); UNUSED(secret); UNUSED(slen); UNUSED(msg); UNUSED(mlen); return 0; #endif } #endif