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 struct const_iovec iov[] = { { secret, slen }, { msg, mlen } }; 69 MD5_iov(digest, iov, sizeof(iov)/sizeof(*iov)); 70 return 1; 71 } 72 73 74 #ifdef USE_LIB_CRYPTO_SHA1 75 int 76 li_hmac_sha1 (unsigned char digest[SHA_DIGEST_LENGTH], 77 const void * const secret, const uint32_t slen, 78 const unsigned char * const msg, const uint32_t mlen) 79 { 80 #ifdef USE_LIB_CRYPTO 81 #if defined(USE_NETTLE_CRYPTO) 82 struct hmac_sha1_ctx ctx; 83 hmac_sha1_set_key(&ctx, slen, (const uint8_t *)secret); 84 hmac_sha1_update(&ctx, mlen, (const uint8_t *)msg); 85 hmac_sha1_digest(&ctx, SHA_DIGEST_LENGTH, (uint8_t *)digest); 86 return 1; 87 #elif defined(USE_MBEDTLS_CRYPTO) \ 88 && defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA1_C) 89 return 0 == 90 mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 91 (const unsigned char *)secret, slen, 92 (const unsigned char *)msg, mlen, digest); 93 #elif defined(USE_WOLFSSL_CRYPTO) 94 Hmac hmac; 95 if (0 != wc_HmacInit(&hmac, NULL, INVALID_DEVID) 96 || wc_HmacSetKey(&hmac, WC_SHA, (const byte *)secret, (word32)slen) < 0 97 || wc_HmacUpdate(&hmac, (const byte *)msg, (word32)mlen) < 0 98 || wc_HmacFinal(&hmac, (byte *)digest) < 0) 99 return 0; 100 return 1; 101 #elif defined(USE_OPENSSL_CRYPTO) 102 return (NULL != HMAC(EVP_sha1(), 103 (const unsigned char *)secret, (int)slen, 104 (const unsigned char *)msg, mlen, 105 digest, NULL)); 106 #elif defined(USE_GNUTLS_CRYPTO) 107 return 0 == 108 gnutls_hmac_fast(GNUTLS_MAC_SHA1, 109 (const unsigned char *)secret, slen, 110 (const unsigned char *)msg, mlen, digest); 111 #elif defined(USE_NSS_CRYPTO) 112 /*(HMAC* funcs not public export of libfreebl3.so, 113 * even though nss3/alghmac.h is public (WTH?!))*/ 114 #if 0 115 HMACContext *hmac = 116 HMAC_Create(HASH_GetHashObject(HASH_AlgSHA1), 117 (const unsigned char *)secret, slen, PR_FALSE); 118 if (NULL == hmac) 119 return 0; 120 HMAC_Begin(hmac); 121 HMAC_Update(hmac, (const unsigned char *)msg, mlen); 122 unsigned int dlen; 123 int rc = HMAC_Finish(hmac, digest, &dlen, SHA_DIGEST_LENGTH); 124 HMAC_Destroy(hmac, PR_TRUE); 125 return (SECSuccess == rc); 126 #else 127 UNUSED(digest); 128 UNUSED(secret); 129 UNUSED(slen); 130 UNUSED(msg); 131 UNUSED(mlen); 132 return 0; 133 #endif 134 #else 135 #error "unexpected; crypto lib not configured for HMAC SHA1" 136 #endif 137 #else 138 UNUSED(digest); 139 UNUSED(secret); 140 UNUSED(slen); 141 UNUSED(msg); 142 UNUSED(mlen); 143 return 0; 144 #endif 145 } 146 #endif 147 148 149 #ifdef USE_LIB_CRYPTO_SHA256 150 int 151 li_hmac_sha256 (unsigned char digest[SHA256_DIGEST_LENGTH], 152 const void * const secret, const uint32_t slen, 153 const unsigned char * const msg, const uint32_t mlen) 154 { 155 #ifdef USE_LIB_CRYPTO 156 #if defined(USE_NETTLE_CRYPTO) 157 struct hmac_sha256_ctx ctx; 158 hmac_sha256_set_key(&ctx, slen, (const uint8_t *)secret); 159 hmac_sha256_update(&ctx, mlen, (const uint8_t *)msg); 160 hmac_sha256_digest(&ctx, SHA256_DIGEST_LENGTH, (uint8_t *)digest); 161 return 1; 162 #elif defined(USE_MBEDTLS_CRYPTO) \ 163 && defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA256_C) 164 return 0 == 165 mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 166 (const unsigned char *)secret, slen, 167 (const unsigned char *)msg, mlen, digest); 168 #elif defined(USE_WOLFSSL_CRYPTO) 169 Hmac hmac; 170 if (0 != wc_HmacInit(&hmac, NULL, INVALID_DEVID) 171 || wc_HmacSetKey(&hmac, WC_SHA256,(const byte *)secret,(word32)slen) < 0 172 || wc_HmacUpdate(&hmac, (const byte *)msg, (word32)mlen) < 0 173 || wc_HmacFinal(&hmac, (byte *)digest) < 0) 174 return 0; 175 return 1; 176 #elif defined(USE_OPENSSL_CRYPTO) 177 return (NULL != HMAC(EVP_sha256(), 178 (const unsigned char *)secret, (int)slen, 179 (const unsigned char *)msg, mlen, 180 digest, NULL)); 181 #elif defined(USE_GNUTLS_CRYPTO) 182 return 0 == 183 gnutls_hmac_fast(GNUTLS_MAC_SHA256, 184 (const unsigned char *)secret, slen, 185 (const unsigned char *)msg, mlen, digest); 186 #elif defined(USE_NSS_CRYPTO) 187 /*(HMAC* funcs not public export of libfreebl3.so, 188 * even though nss3/alghmac.h is public (WTH?!))*/ 189 #if 0 190 HMACContext *hmac = 191 HMAC_Create(HASH_GetHashObject(HASH_AlgSHA256), 192 (const unsigned char *)secret, slen, PR_FALSE); 193 if (NULL == hmac) 194 return 0; 195 HMAC_Begin(hmac); 196 HMAC_Update(hmac, (const unsigned char *)msg, mlen); 197 unsigned int dlen; 198 int rc = HMAC_Finish(hmac, digest, &dlen, SHA256_DIGEST_LENGTH); 199 HMAC_Destroy(hmac, PR_TRUE); 200 return (SECSuccess == rc); 201 #else 202 UNUSED(digest); 203 UNUSED(secret); 204 UNUSED(slen); 205 UNUSED(msg); 206 UNUSED(mlen); 207 return 0; 208 #endif 209 #else 210 #error "unexpected; crypto lib not configured for HMAC SHA256" 211 #endif 212 #else 213 UNUSED(digest); 214 UNUSED(secret); 215 UNUSED(slen); 216 UNUSED(msg); 217 UNUSED(mlen); 218 return 0; 219 #endif 220 } 221 #endif 222 223 224 #ifdef USE_LIB_CRYPTO_SHA512 225 int 226 li_hmac_sha512 (unsigned char digest[SHA512_DIGEST_LENGTH], 227 const void * const secret, const uint32_t slen, 228 const unsigned char * const msg, const uint32_t mlen) 229 { 230 #ifdef USE_LIB_CRYPTO 231 #if defined(USE_NETTLE_CRYPTO) 232 struct hmac_sha512_ctx ctx; 233 hmac_sha512_set_key(&ctx, slen, (const uint8_t *)secret); 234 hmac_sha512_update(&ctx, mlen, (const uint8_t *)msg); 235 hmac_sha512_digest(&ctx, SHA512_DIGEST_LENGTH, (uint8_t *)digest); 236 return 1; 237 #elif defined(USE_MBEDTLS_CRYPTO) \ 238 && defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA512_C) 239 return 0 == 240 mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), 241 (const unsigned char *)secret, slen, 242 (const unsigned char *)msg, mlen, digest); 243 #elif defined(USE_WOLFSSL_CRYPTO) 244 Hmac hmac; 245 if (0 != wc_HmacInit(&hmac, NULL, INVALID_DEVID) 246 || wc_HmacSetKey(&hmac, WC_SHA512,(const byte *)secret,(word32)slen) < 0 247 || wc_HmacUpdate(&hmac, (const byte *)msg, (word32)mlen) < 0 248 || wc_HmacFinal(&hmac, (byte *)digest) < 0) 249 return 0; 250 return 1; 251 #elif defined(USE_OPENSSL_CRYPTO) 252 return (NULL != HMAC(EVP_sha512(), 253 (const unsigned char *)secret, (int)slen, 254 (const unsigned char *)msg, mlen, 255 digest, NULL)); 256 #elif defined(USE_GNUTLS_CRYPTO) 257 return 0 == 258 gnutls_hmac_fast(GNUTLS_MAC_SHA512, 259 (const unsigned char *)secret, slen, 260 (const unsigned char *)msg, mlen, digest); 261 #elif defined(USE_NSS_CRYPTO) 262 /*(HMAC* funcs not public export of libfreebl3.so, 263 * even though nss3/alghmac.h is public (WTH?!))*/ 264 #if 0 265 HMACContext *hmac = 266 HMAC_Create(HASH_GetHashObject(HASH_AlgSHA512), 267 (const unsigned char *)secret, slen, PR_FALSE); 268 if (NULL == hmac) 269 return 0; 270 HMAC_Begin(hmac); 271 HMAC_Update(hmac, (const unsigned char *)msg, mlen); 272 unsigned int dlen; 273 int rc = HMAC_Finish(hmac, digest, &dlen, SHA512_DIGEST_LENGTH); 274 HMAC_Destroy(hmac, PR_TRUE); 275 return (SECSuccess == rc); 276 #else 277 UNUSED(digest); 278 UNUSED(secret); 279 UNUSED(slen); 280 UNUSED(msg); 281 UNUSED(mlen); 282 return 0; 283 #endif 284 #else 285 #error "unexpected; crypto lib not configured for HMAC SHA512" 286 #endif 287 #else 288 UNUSED(digest); 289 UNUSED(secret); 290 UNUSED(slen); 291 UNUSED(msg); 292 UNUSED(mlen); 293 return 0; 294 #endif 295 } 296 #endif 297