xref: /openssl/crypto/hmac/hmac.c (revision 14c45338)
1 /*
2  * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 /*
11  * HMAC low level APIs are deprecated for public use, but still ok for internal
12  * use.
13  */
14 #include "internal/deprecated.h"
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include "internal/cryptlib.h"
20 #include <openssl/opensslconf.h>
21 #include <openssl/hmac.h>
22 #include <openssl/core_names.h>
23 #include "hmac_local.h"
24 
HMAC_Init_ex(HMAC_CTX * ctx,const void * key,int len,const EVP_MD * md,ENGINE * impl)25 int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
26                  const EVP_MD *md, ENGINE *impl)
27 {
28     int rv = 0, reset = 0;
29     int i, j;
30     unsigned char pad[HMAC_MAX_MD_CBLOCK_SIZE];
31     unsigned int keytmp_length;
32     unsigned char keytmp[HMAC_MAX_MD_CBLOCK_SIZE];
33 
34     /* If we are changing MD then we must have a key */
35     if (md != NULL && md != ctx->md && (key == NULL || len < 0))
36         return 0;
37 
38     if (md != NULL)
39         ctx->md = md;
40     else if (ctx->md != NULL)
41         md = ctx->md;
42     else
43         return 0;
44 
45     /*
46      * The HMAC construction is not allowed to be used with the
47      * extendable-output functions (XOF) shake128 and shake256.
48      */
49     if (EVP_MD_xof(md))
50         return 0;
51 
52 #ifdef OPENSSL_HMAC_S390X
53     rv = s390x_HMAC_init(ctx, key, len, impl);
54     if (rv >= 1)
55         return rv;
56 #endif
57 
58     if (key != NULL) {
59         reset = 1;
60 
61         j = EVP_MD_get_block_size(md);
62         if (!ossl_assert(j <= (int)sizeof(keytmp)))
63             return 0;
64         if (j < 0)
65             return 0;
66         if (j < len) {
67             if (!EVP_DigestInit_ex(ctx->md_ctx, md, impl)
68                     || !EVP_DigestUpdate(ctx->md_ctx, key, len)
69                     || !EVP_DigestFinal_ex(ctx->md_ctx, keytmp,
70                                            &keytmp_length))
71                 return 0;
72         } else {
73             if (len < 0 || len > (int)sizeof(keytmp))
74                 return 0;
75             memcpy(keytmp, key, len);
76             keytmp_length = len;
77         }
78         if (keytmp_length != HMAC_MAX_MD_CBLOCK_SIZE)
79             memset(&keytmp[keytmp_length], 0,
80                    HMAC_MAX_MD_CBLOCK_SIZE - keytmp_length);
81 
82         for (i = 0; i < HMAC_MAX_MD_CBLOCK_SIZE; i++)
83             pad[i] = 0x36 ^ keytmp[i];
84         if (!EVP_DigestInit_ex(ctx->i_ctx, md, impl)
85                 || !EVP_DigestUpdate(ctx->i_ctx, pad,
86                                      EVP_MD_get_block_size(md)))
87             goto err;
88 
89         for (i = 0; i < HMAC_MAX_MD_CBLOCK_SIZE; i++)
90             pad[i] = 0x5c ^ keytmp[i];
91         if (!EVP_DigestInit_ex(ctx->o_ctx, md, impl)
92                 || !EVP_DigestUpdate(ctx->o_ctx, pad,
93                                      EVP_MD_get_block_size(md)))
94             goto err;
95     }
96     if (!EVP_MD_CTX_copy_ex(ctx->md_ctx, ctx->i_ctx))
97         goto err;
98     rv = 1;
99  err:
100     if (reset) {
101         OPENSSL_cleanse(keytmp, sizeof(keytmp));
102         OPENSSL_cleanse(pad, sizeof(pad));
103     }
104     return rv;
105 }
106 
107 #ifndef OPENSSL_NO_DEPRECATED_1_1_0
HMAC_Init(HMAC_CTX * ctx,const void * key,int len,const EVP_MD * md)108 int HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md)
109 {
110     if (key && md)
111         HMAC_CTX_reset(ctx);
112     return HMAC_Init_ex(ctx, key, len, md, NULL);
113 }
114 #endif
115 
HMAC_Update(HMAC_CTX * ctx,const unsigned char * data,size_t len)116 int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len)
117 {
118     if (!ctx->md)
119         return 0;
120 
121 #ifdef OPENSSL_HMAC_S390X
122     if (ctx->plat.s390x.fc)
123         return s390x_HMAC_update(ctx, data, len);
124 #endif
125 
126     return EVP_DigestUpdate(ctx->md_ctx, data, len);
127 }
128 
HMAC_Final(HMAC_CTX * ctx,unsigned char * md,unsigned int * len)129 int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len)
130 {
131     unsigned int i;
132     unsigned char buf[EVP_MAX_MD_SIZE];
133 
134     if (!ctx->md)
135         goto err;
136 
137 #ifdef OPENSSL_HMAC_S390X
138     if (ctx->plat.s390x.fc)
139         return s390x_HMAC_final(ctx, md, len);
140 #endif
141 
142     if (!EVP_DigestFinal_ex(ctx->md_ctx, buf, &i))
143         goto err;
144     if (!EVP_MD_CTX_copy_ex(ctx->md_ctx, ctx->o_ctx))
145         goto err;
146     if (!EVP_DigestUpdate(ctx->md_ctx, buf, i))
147         goto err;
148     if (!EVP_DigestFinal_ex(ctx->md_ctx, md, len))
149         goto err;
150     return 1;
151  err:
152     return 0;
153 }
154 
HMAC_size(const HMAC_CTX * ctx)155 size_t HMAC_size(const HMAC_CTX *ctx)
156 {
157     int size = EVP_MD_get_size((ctx)->md);
158 
159     return (size < 0) ? 0 : size;
160 }
161 
HMAC_CTX_new(void)162 HMAC_CTX *HMAC_CTX_new(void)
163 {
164     HMAC_CTX *ctx = OPENSSL_zalloc(sizeof(HMAC_CTX));
165 
166     if (ctx != NULL) {
167         if (!HMAC_CTX_reset(ctx)) {
168             HMAC_CTX_free(ctx);
169             return NULL;
170         }
171     }
172     return ctx;
173 }
174 
hmac_ctx_cleanup(HMAC_CTX * ctx)175 static void hmac_ctx_cleanup(HMAC_CTX *ctx)
176 {
177     EVP_MD_CTX_reset(ctx->i_ctx);
178     EVP_MD_CTX_reset(ctx->o_ctx);
179     EVP_MD_CTX_reset(ctx->md_ctx);
180     ctx->md = NULL;
181 
182 #ifdef OPENSSL_HMAC_S390X
183     s390x_HMAC_CTX_cleanup(ctx);
184 #endif
185 }
186 
HMAC_CTX_free(HMAC_CTX * ctx)187 void HMAC_CTX_free(HMAC_CTX *ctx)
188 {
189     if (ctx != NULL) {
190         hmac_ctx_cleanup(ctx);
191         EVP_MD_CTX_free(ctx->i_ctx);
192         EVP_MD_CTX_free(ctx->o_ctx);
193         EVP_MD_CTX_free(ctx->md_ctx);
194         OPENSSL_free(ctx);
195     }
196 }
197 
hmac_ctx_alloc_mds(HMAC_CTX * ctx)198 static int hmac_ctx_alloc_mds(HMAC_CTX *ctx)
199 {
200     if (ctx->i_ctx == NULL)
201         ctx->i_ctx = EVP_MD_CTX_new();
202     if (ctx->i_ctx == NULL)
203         return 0;
204     if (ctx->o_ctx == NULL)
205         ctx->o_ctx = EVP_MD_CTX_new();
206     if (ctx->o_ctx == NULL)
207         return 0;
208     if (ctx->md_ctx == NULL)
209         ctx->md_ctx = EVP_MD_CTX_new();
210     if (ctx->md_ctx == NULL)
211         return 0;
212     return 1;
213 }
214 
HMAC_CTX_reset(HMAC_CTX * ctx)215 int HMAC_CTX_reset(HMAC_CTX *ctx)
216 {
217     hmac_ctx_cleanup(ctx);
218     if (!hmac_ctx_alloc_mds(ctx)) {
219         hmac_ctx_cleanup(ctx);
220         return 0;
221     }
222     return 1;
223 }
224 
HMAC_CTX_copy(HMAC_CTX * dctx,HMAC_CTX * sctx)225 int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx)
226 {
227     if (!hmac_ctx_alloc_mds(dctx))
228         goto err;
229     if (!EVP_MD_CTX_copy_ex(dctx->i_ctx, sctx->i_ctx))
230         goto err;
231     if (!EVP_MD_CTX_copy_ex(dctx->o_ctx, sctx->o_ctx))
232         goto err;
233     if (!EVP_MD_CTX_copy_ex(dctx->md_ctx, sctx->md_ctx))
234         goto err;
235     dctx->md = sctx->md;
236 
237 #ifdef OPENSSL_HMAC_S390X
238     if (s390x_HMAC_CTX_copy(dctx, sctx) == 0)
239         goto err;
240 #endif
241 
242     return 1;
243  err:
244     hmac_ctx_cleanup(dctx);
245     return 0;
246 }
247 
HMAC(const EVP_MD * evp_md,const void * key,int key_len,const unsigned char * data,size_t data_len,unsigned char * md,unsigned int * md_len)248 unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
249                     const unsigned char *data, size_t data_len,
250                     unsigned char *md, unsigned int *md_len)
251 {
252     static unsigned char static_md[EVP_MAX_MD_SIZE];
253     int size = EVP_MD_get_size(evp_md);
254     size_t temp_md_len = 0;
255     unsigned char *ret = NULL;
256 
257     if (size > 0) {
258         ret = EVP_Q_mac(NULL, "HMAC", NULL, EVP_MD_get0_name(evp_md), NULL,
259                         key, key_len, data, data_len,
260                         md == NULL ? static_md : md, size, &temp_md_len);
261         if (md_len != NULL)
262             *md_len = (unsigned int)temp_md_len;
263     }
264     return ret;
265 }
266 
HMAC_CTX_set_flags(HMAC_CTX * ctx,unsigned long flags)267 void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags)
268 {
269     EVP_MD_CTX_set_flags(ctx->i_ctx, flags);
270     EVP_MD_CTX_set_flags(ctx->o_ctx, flags);
271     EVP_MD_CTX_set_flags(ctx->md_ctx, flags);
272 }
273 
HMAC_CTX_get_md(const HMAC_CTX * ctx)274 const EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx)
275 {
276     return ctx->md;
277 }
278