1 /* algo_hmac - hash-based message authentication code (HMAC) wrapper 2 * 3 * Copyright(c) 2021 Glenn Strauss gstrauss()gluelogic.com All rights reserved 4 * License: BSD 3-clause (same as lighttpd) 5 */ 6 #include "first.h" 7 8 #include "algo_hmac.h" 9 10 #include "sys-crypto-md.h" 11 #ifdef USE_LIB_CRYPTO 12 #if defined(USE_NETTLE_CRYPTO) 13 #include <nettle/hmac.h> 14 #elif defined(USE_MBEDTLS_CRYPTO) 15 #include <mbedtls/md.h> 16 #elif defined(USE_WOLFSSL_CRYPTO) 17 #include <wolfssl/wolfcrypt/hmac.h> 18 #elif defined(USE_OPENSSL_CRYPTO) 19 #include <openssl/evp.h> 20 #include <openssl/hmac.h> 21 #elif defined(USE_GNUTLS_CRYPTO) 22 #include <gnutls/crypto.h> 23 #elif defined(USE_NSS_CRYPTO) 24 #if 0 /*(nss/alghmac.h might not be present)*/ 25 #ifdef NSS_VER_INCLUDE 26 #include <nss3/alghmac.h> 27 #else 28 #include <nss/alghmac.h> 29 #endif 30 #endif 31 #endif 32 #endif 33 34 #ifndef USE_NETTLE_CRYPTO 35 #if defined(USE_OPENSSL_CRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L 36 #define HMAC EVP_HMAC 37 static unsigned char * 38 EVP_HMAC (const EVP_MD *evp_md, const void *key, 39 int key_len, const unsigned char *d, int n, 40 unsigned char *md, size_t *md_len) 41 { 42 EVP_PKEY * const pkey = 43 EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, key_len); 44 if (NULL == pkey) return NULL; 45 46 EVP_MD_CTX * const ctx = EVP_MD_CTX_new(); 47 if (NULL == ctx) { 48 EVP_PKEY_free(pkey); 49 return NULL; 50 } 51 52 int rc = (1 == EVP_DigestSignInit(ctx, NULL, evp_md, NULL, pkey)) 53 && (1 == EVP_DigestSignUpdate(ctx, d, n)) 54 && (1 == EVP_DigestSignFinal(ctx, md, md_len)); 55 EVP_MD_CTX_free(ctx); 56 EVP_PKEY_free(pkey); 57 return (1 == rc) ? md : NULL; 58 } 59 #endif 60 #endif 61 62 63 int 64 li_hmac_md5 (unsigned char digest[MD5_DIGEST_LENGTH], 65 const void * const secret, const uint32_t slen, 66 const unsigned char * const msg, const uint32_t mlen) 67 { 68 li_MD5_CTX Md5Ctx; 69 li_MD5_Init(&Md5Ctx); 70 li_MD5_Update(&Md5Ctx, secret, slen); 71 li_MD5_Update(&Md5Ctx, msg, mlen); 72 li_MD5_Final(digest, &Md5Ctx); 73 return 1; 74 } 75 76 77 #ifdef USE_LIB_CRYPTO_SHA1 78 int 79 li_hmac_sha1 (unsigned char digest[SHA_DIGEST_LENGTH], 80 const void * const secret, const uint32_t slen, 81 const unsigned char * const msg, const uint32_t mlen) 82 { 83 #ifdef USE_LIB_CRYPTO 84 #if defined(USE_NETTLE_CRYPTO) 85 struct hmac_sha1_ctx ctx; 86 hmac_sha1_set_key(&ctx, slen, (const uint8_t *)secret); 87 hmac_sha1_update(&ctx, mlen, (const uint8_t *)msg); 88 hmac_sha1_digest(&ctx, SHA_DIGEST_LENGTH, (uint8_t *)digest); 89 return 1; 90 #elif defined(USE_MBEDTLS_CRYPTO) \ 91 && defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA1_C) 92 return 0 == 93 mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 94 (const unsigned char *)secret, slen, 95 (const unsigned char *)msg, mlen, digest); 96 #elif defined(USE_WOLFSSL_CRYPTO) 97 Hmac hmac; 98 if (0 != wc_HmacInit(&hmac, NULL, INVALID_DEVID) 99 || wc_HmacSetKey(&hmac, WC_SHA, (const byte *)secret, (word32)slen) < 0 100 || wc_HmacUpdate(&hmac, (const byte *)msg, (word32)mlen) < 0 101 || wc_HmacFinal(&hmac, (byte *)digest) < 0) 102 return 0; 103 return 1; 104 #elif defined(USE_OPENSSL_CRYPTO) 105 return (NULL != HMAC(EVP_sha1(), 106 (const unsigned char *)secret, (int)slen, 107 (const unsigned char *)msg, mlen, 108 digest, NULL)); 109 #elif defined(USE_GNUTLS_CRYPTO) 110 return 0 == 111 gnutls_hmac_fast(GNUTLS_MAC_SHA1, 112 (const unsigned char *)secret, slen, 113 (const unsigned char *)msg, mlen, digest); 114 #elif defined(USE_NSS_CRYPTO) 115 /*(HMAC* funcs not public export of libfreebl3.so, 116 * even though nss3/alghmac.h is public (WTH?!))*/ 117 #if 0 118 HMACContext *hmac = 119 HMAC_Create(HASH_GetHashObject(HASH_AlgSHA1), 120 (const unsigned char *)secret, slen, PR_FALSE); 121 if (NULL == hmac) 122 return 0; 123 HMAC_Begin(hmac); 124 HMAC_Update(hmac, (const unsigned char *)msg, mlen); 125 unsigned int dlen; 126 int rc = HMAC_Finish(hmac, digest, &dlen, SHA_DIGEST_LENGTH); 127 HMAC_Destroy(hmac, PR_TRUE); 128 return (SECSuccess == rc); 129 #else 130 return 0; 131 #endif 132 #else 133 #error "unexpected; crypto lib not configured for HMAC SHA1" 134 #endif 135 #else 136 UNUSED(digest); 137 UNUSED(secret); 138 UNUSED(slen); 139 UNUSED(msg); 140 UNUSED(mlen); 141 return 0; 142 #endif 143 } 144 #endif 145 146 147 #ifdef USE_LIB_CRYPTO_SHA256 148 int 149 li_hmac_sha256 (unsigned char digest[SHA256_DIGEST_LENGTH], 150 const void * const secret, const uint32_t slen, 151 const unsigned char * const msg, const uint32_t mlen) 152 { 153 #ifdef USE_LIB_CRYPTO 154 #if defined(USE_NETTLE_CRYPTO) 155 struct hmac_sha256_ctx ctx; 156 hmac_sha256_set_key(&ctx, slen, (const uint8_t *)secret); 157 hmac_sha256_update(&ctx, mlen, (const uint8_t *)msg); 158 hmac_sha256_digest(&ctx, SHA256_DIGEST_LENGTH, (uint8_t *)digest); 159 return 1; 160 #elif defined(USE_MBEDTLS_CRYPTO) \ 161 && defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA256_C) 162 return 0 == 163 mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 164 (const unsigned char *)secret, slen, 165 (const unsigned char *)msg, mlen, digest); 166 #elif defined(USE_WOLFSSL_CRYPTO) 167 Hmac hmac; 168 if (0 != wc_HmacInit(&hmac, NULL, INVALID_DEVID) 169 || wc_HmacSetKey(&hmac, WC_SHA256,(const byte *)secret,(word32)slen) < 0 170 || wc_HmacUpdate(&hmac, (const byte *)msg, (word32)mlen) < 0 171 || wc_HmacFinal(&hmac, (byte *)digest) < 0) 172 return 0; 173 return 1; 174 #elif defined(USE_OPENSSL_CRYPTO) 175 return (NULL != HMAC(EVP_sha256(), 176 (const unsigned char *)secret, (int)slen, 177 (const unsigned char *)msg, mlen, 178 digest, NULL)); 179 #elif defined(USE_GNUTLS_CRYPTO) 180 return 0 == 181 gnutls_hmac_fast(GNUTLS_MAC_SHA256, 182 (const unsigned char *)secret, slen, 183 (const unsigned char *)msg, mlen, digest); 184 #elif defined(USE_NSS_CRYPTO) 185 /*(HMAC* funcs not public export of libfreebl3.so, 186 * even though nss3/alghmac.h is public (WTH?!))*/ 187 #if 0 188 HMACContext *hmac = 189 HMAC_Create(HASH_GetHashObject(HASH_AlgSHA256), 190 (const unsigned char *)secret, slen, PR_FALSE); 191 if (NULL == hmac) 192 return 0; 193 HMAC_Begin(hmac); 194 HMAC_Update(hmac, (const unsigned char *)msg, mlen); 195 unsigned int dlen; 196 int rc = HMAC_Finish(hmac, digest, &dlen, SHA256_DIGEST_LENGTH); 197 HMAC_Destroy(hmac, PR_TRUE); 198 return (SECSuccess == rc); 199 #else 200 return 0; 201 #endif 202 #else 203 #error "unexpected; crypto lib not configured for HMAC SHA256" 204 #endif 205 #else 206 UNUSED(digest); 207 UNUSED(secret); 208 UNUSED(slen); 209 UNUSED(msg); 210 UNUSED(mlen); 211 return 0; 212 #endif 213 } 214 #endif 215