xref: /lighttpd1.4/src/algo_hmac.c (revision 7901259f)
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