]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/hmac/hm_meth.c
Move GMAC to providers
[thirdparty/openssl.git] / crypto / hmac / hm_meth.c
1 /*
2 * Copyright 2018 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 #include <string.h>
11 #include <openssl/err.h>
12 #include <openssl/ossl_typ.h>
13 #include <openssl/asn1.h>
14 #include <openssl/hmac.h>
15 #include "internal/evp_int.h"
16
17 /* local HMAC context structure */
18
19 /* typedef EVP_MAC_IMPL */
20 struct evp_mac_impl_st {
21 /* tmpmd and tmpengine are set to NULL after a CMAC_Init call */
22 const EVP_MD *tmpmd; /* HMAC digest */
23 const ENGINE *tmpengine; /* HMAC digest engine */
24 HMAC_CTX *ctx; /* HMAC context */
25 };
26
27 static EVP_MAC_IMPL *hmac_new(void)
28 {
29 EVP_MAC_IMPL *hctx;
30
31 if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL
32 || (hctx->ctx = HMAC_CTX_new()) == NULL) {
33 OPENSSL_free(hctx);
34 return NULL;
35 }
36
37 return hctx;
38 }
39
40 static void hmac_free(EVP_MAC_IMPL *hctx)
41 {
42 if (hctx != NULL) {
43 HMAC_CTX_free(hctx->ctx);
44 OPENSSL_free(hctx);
45 }
46 }
47
48 static EVP_MAC_IMPL *hmac_dup(const EVP_MAC_IMPL *hsrc)
49 {
50 EVP_MAC_IMPL *hdst;
51
52 hdst = hmac_new();
53 if (hdst == NULL)
54 return NULL;
55
56 if (!HMAC_CTX_copy(hdst->ctx, hsrc->ctx)) {
57 hmac_free(hdst);
58 return NULL;
59 }
60
61 hdst->tmpengine = hsrc->tmpengine;
62 hdst->tmpmd = hsrc->tmpmd;
63
64 return hdst;
65 }
66
67 static size_t hmac_size(EVP_MAC_IMPL *hctx)
68 {
69 return HMAC_size(hctx->ctx);
70 }
71
72 static int hmac_init(EVP_MAC_IMPL *hctx)
73 {
74 int rv = 1;
75
76 /* HMAC_Init_ex doesn't tolerate all zero params, so we must be careful */
77 if (hctx->tmpmd != NULL)
78 rv = HMAC_Init_ex(hctx->ctx, NULL, 0, hctx->tmpmd,
79 (ENGINE * )hctx->tmpengine);
80 hctx->tmpengine = NULL;
81 hctx->tmpmd = NULL;
82 return rv;
83 }
84
85 static int hmac_update(EVP_MAC_IMPL *hctx, const unsigned char *data,
86 size_t datalen)
87 {
88 return HMAC_Update(hctx->ctx, data, datalen);
89 }
90
91 static int hmac_final(EVP_MAC_IMPL *hctx, unsigned char *out)
92 {
93 unsigned int hlen;
94
95 return HMAC_Final(hctx->ctx, out, &hlen);
96 }
97
98 static int hmac_ctrl(EVP_MAC_IMPL *hctx, int cmd, va_list args)
99 {
100 switch (cmd) {
101 case EVP_MAC_CTRL_SET_FLAGS:
102 {
103 unsigned long flags = va_arg(args, unsigned long);
104
105 HMAC_CTX_set_flags(hctx->ctx, flags);
106 }
107 break;
108 case EVP_MAC_CTRL_SET_KEY:
109 {
110 const unsigned char *key = va_arg(args, const unsigned char *);
111 size_t keylen = va_arg(args, size_t);
112 int rv = HMAC_Init_ex(hctx->ctx, key, keylen, hctx->tmpmd,
113 (ENGINE *)hctx->tmpengine);
114
115 hctx->tmpengine = NULL;
116 hctx->tmpmd = NULL;
117 return rv;
118 }
119 break;
120 case EVP_MAC_CTRL_SET_MD:
121 hctx->tmpmd = va_arg(args, const EVP_MD *);
122 break;
123 case EVP_MAC_CTRL_SET_ENGINE:
124 hctx->tmpengine = va_arg(args, const ENGINE *);
125 break;
126 default:
127 return -2;
128
129 }
130 return 1;
131 }
132
133 static int hmac_ctrl_int(EVP_MAC_IMPL *hctx, int cmd, ...)
134 {
135 int rv;
136 va_list args;
137
138 va_start(args, cmd);
139 rv = hmac_ctrl(hctx, cmd, args);
140 va_end(args);
141
142 return rv;
143 }
144
145 static int hmac_ctrl_str_cb(void *hctx, int cmd, void *buf, size_t buflen)
146 {
147 return hmac_ctrl_int(hctx, cmd, buf, buflen);
148 }
149
150 static int hmac_ctrl_str(EVP_MAC_IMPL *hctx, const char *type,
151 const char *value)
152 {
153 if (!value)
154 return 0;
155 #ifndef FIPS_MODE
156 /*
157 * We don't have EVP_get_digestbyname() in FIPS_MODE. That function returns
158 * an EVP_MD without an associated provider implementation (i.e. it is
159 * using "implicit fetch"). We could replace it with an "explicit" fetch
160 * using EVP_MD_fetch(), but we'd then be required to free the returned
161 * EVP_MD somewhere. Probably the complexity isn't worth it as we are
162 * unlikely to need this ctrl in FIPS_MODE anyway.
163 */
164 if (strcmp(type, "digest") == 0) {
165 const EVP_MD *d = EVP_get_digestbyname(value);
166
167 if (d == NULL)
168 return 0;
169 return hmac_ctrl_int(hctx, EVP_MAC_CTRL_SET_MD, d);
170 }
171 #endif
172 if (strcmp(type, "key") == 0)
173 return EVP_str2ctrl(hmac_ctrl_str_cb, hctx, EVP_MAC_CTRL_SET_KEY,
174 value);
175 if (strcmp(type, "hexkey") == 0)
176 return EVP_hex2ctrl(hmac_ctrl_str_cb, hctx, EVP_MAC_CTRL_SET_KEY,
177 value);
178 return -2;
179 }
180
181 const EVP_MAC hmac_meth = {
182 EVP_MAC_HMAC,
183 hmac_new,
184 hmac_dup,
185 hmac_free,
186 hmac_size,
187 hmac_init,
188 hmac_update,
189 hmac_final,
190 hmac_ctrl,
191 hmac_ctrl_str
192 };