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