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 *
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)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
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)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
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)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
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)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
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)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