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