]>
Commit | Line | Data |
---|---|---|
2e5db6ad RL |
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 | ||
bad41b68 MC |
10 | #include <openssl/core_numbers.h> |
11 | #include <openssl/core_names.h> | |
12 | #include <openssl/params.h> | |
13 | #include <openssl/engine.h> | |
14 | #include <openssl/evp.h> | |
15 | #include <openssl/cmac.h> | |
2e5db6ad | 16 | |
bad41b68 MC |
17 | #include "internal/provider_algs.h" |
18 | #include "internal/provider_ctx.h" | |
2e5db6ad RL |
19 | |
20 | /* | |
21 | * Forward declaration of everything implemented here. This is not strictly | |
22 | * necessary for the compiler, but provides an assurance that the signatures | |
23 | * of the functions in the dispatch table are correct. | |
24 | */ | |
25 | static OSSL_OP_mac_newctx_fn cmac_new; | |
26 | static OSSL_OP_mac_dupctx_fn cmac_dup; | |
27 | static OSSL_OP_mac_freectx_fn cmac_free; | |
28 | static OSSL_OP_mac_gettable_ctx_params_fn cmac_gettable_ctx_params; | |
92d9d0ae | 29 | static OSSL_OP_mac_get_ctx_params_fn cmac_get_ctx_params; |
2e5db6ad | 30 | static OSSL_OP_mac_settable_ctx_params_fn cmac_settable_ctx_params; |
92d9d0ae | 31 | static OSSL_OP_mac_set_ctx_params_fn cmac_set_ctx_params; |
2e5db6ad RL |
32 | static OSSL_OP_mac_init_fn cmac_init; |
33 | static OSSL_OP_mac_update_fn cmac_update; | |
34 | static OSSL_OP_mac_final_fn cmac_final; | |
35 | ||
36 | /* local CMAC data */ | |
37 | ||
38 | struct cmac_data_st { | |
39 | void *provctx; | |
40 | CMAC_CTX *ctx; | |
41 | ||
42 | /* | |
43 | * References to the underlying cipher implementation. tmpcipher | |
44 | * caches the cipher, always. alloc_cipher only holds a reference | |
45 | * to an explicitly fetched cipher. | |
46 | * tmpcipher is cleared after a CMAC_Init call. | |
47 | */ | |
48 | const EVP_CIPHER *tmpcipher; /* cached CMAC cipher */ | |
49 | EVP_CIPHER *alloc_cipher; /* fetched CMAC cipher */ | |
50 | ||
51 | /* | |
52 | * Conditions for legacy EVP_CIPHER uses. | |
53 | * tmpengine is cleared after a CMAC_Init call. | |
54 | */ | |
55 | ENGINE *tmpengine; /* CMAC cipher engine (legacy) */ | |
56 | }; | |
57 | ||
58 | static void *cmac_new(void *provctx) | |
59 | { | |
60 | struct cmac_data_st *macctx; | |
61 | ||
62 | if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL | |
63 | || (macctx->ctx = CMAC_CTX_new()) == NULL) { | |
64 | OPENSSL_free(macctx); | |
65 | macctx = NULL; | |
d5f85429 RL |
66 | } else { |
67 | macctx->provctx = provctx; | |
2e5db6ad | 68 | } |
2e5db6ad RL |
69 | |
70 | return macctx; | |
71 | } | |
72 | ||
73 | static void cmac_free(void *vmacctx) | |
74 | { | |
75 | struct cmac_data_st *macctx = vmacctx; | |
76 | ||
77 | if (macctx != NULL) { | |
78 | CMAC_CTX_free(macctx->ctx); | |
550f974a | 79 | EVP_CIPHER_free(macctx->alloc_cipher); |
2e5db6ad RL |
80 | OPENSSL_free(macctx); |
81 | } | |
82 | } | |
83 | ||
84 | static void *cmac_dup(void *vsrc) | |
85 | { | |
86 | struct cmac_data_st *src = vsrc; | |
87 | struct cmac_data_st *dst = cmac_new(src->provctx); | |
88 | ||
89 | if (!CMAC_CTX_copy(dst->ctx, src->ctx)) { | |
90 | cmac_free(dst); | |
91 | return NULL; | |
92 | } | |
93 | ||
94 | if (src->alloc_cipher != NULL && !EVP_CIPHER_up_ref(src->alloc_cipher)) { | |
95 | cmac_free(dst); | |
96 | return NULL; | |
97 | } | |
98 | ||
99 | dst->tmpengine = src->tmpengine; | |
100 | dst->tmpcipher = src->tmpcipher; | |
101 | dst->alloc_cipher = src->alloc_cipher; | |
102 | return dst; | |
103 | } | |
104 | ||
105 | static size_t cmac_size(void *vmacctx) | |
106 | { | |
107 | struct cmac_data_st *macctx = vmacctx; | |
108 | ||
109 | return EVP_CIPHER_CTX_block_size(CMAC_CTX_get0_cipher_ctx(macctx->ctx)); | |
110 | } | |
111 | ||
112 | static int cmac_init(void *vmacctx) | |
113 | { | |
114 | struct cmac_data_st *macctx = vmacctx; | |
115 | int rv = CMAC_Init(macctx->ctx, NULL, 0, macctx->tmpcipher, | |
116 | (ENGINE *)macctx->tmpengine); | |
117 | ||
118 | macctx->tmpcipher = NULL; | |
119 | macctx->tmpengine = NULL; | |
120 | ||
121 | return rv; | |
122 | } | |
123 | ||
124 | static int cmac_update(void *vmacctx, const unsigned char *data, | |
125 | size_t datalen) | |
126 | { | |
127 | struct cmac_data_st *macctx = vmacctx; | |
128 | ||
129 | return CMAC_Update(macctx->ctx, data, datalen); | |
130 | } | |
131 | ||
132 | static int cmac_final(void *vmacctx, unsigned char *out, size_t *outl, | |
133 | size_t outsize) | |
134 | { | |
135 | struct cmac_data_st *macctx = vmacctx; | |
136 | ||
137 | return CMAC_Final(macctx->ctx, out, outl); | |
138 | } | |
139 | ||
140 | static const OSSL_PARAM known_gettable_ctx_params[] = { | |
703170d4 | 141 | OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), |
2e5db6ad RL |
142 | OSSL_PARAM_END |
143 | }; | |
144 | static const OSSL_PARAM *cmac_gettable_ctx_params(void) | |
145 | { | |
146 | return known_gettable_ctx_params; | |
147 | } | |
148 | ||
92d9d0ae | 149 | static int cmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[]) |
2e5db6ad RL |
150 | { |
151 | OSSL_PARAM *p; | |
152 | ||
703170d4 | 153 | if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL) |
2e5db6ad RL |
154 | return OSSL_PARAM_set_size_t(p, cmac_size(vmacctx)); |
155 | ||
156 | return 1; | |
157 | } | |
158 | ||
159 | static const OSSL_PARAM known_settable_ctx_params[] = { | |
2e5db6ad RL |
160 | OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_CIPHER, NULL, 0), |
161 | OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_ENGINE, NULL, 0), | |
162 | OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0), | |
163 | OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), | |
164 | OSSL_PARAM_END | |
165 | }; | |
166 | static const OSSL_PARAM *cmac_settable_ctx_params(void) | |
167 | { | |
168 | return known_settable_ctx_params; | |
169 | } | |
170 | ||
171 | /* | |
172 | * ALL parameters should be set before init(). | |
173 | */ | |
92d9d0ae | 174 | static int cmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[]) |
2e5db6ad RL |
175 | { |
176 | struct cmac_data_st *macctx = vmacctx; | |
177 | const OSSL_PARAM *p; | |
178 | ||
703170d4 | 179 | if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_CIPHER)) != NULL) { |
2e5db6ad RL |
180 | if (p->data_type != OSSL_PARAM_UTF8_STRING) |
181 | return 0; | |
182 | ||
183 | { | |
184 | const char *algoname = p->data; | |
185 | const char *propquery = NULL; | |
186 | ||
3be06e0d MC |
187 | /* Inside the FIPS module, we don't support engines */ |
188 | #if !defined(FIPS_MODE) && !defined(OPENSSL_NO_ENGINE) | |
2e5db6ad RL |
189 | ENGINE_finish(macctx->tmpengine); |
190 | macctx->tmpengine = NULL; | |
191 | ||
192 | if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_ENGINE)) | |
193 | != NULL) { | |
194 | if (p->data_type != OSSL_PARAM_UTF8_STRING) | |
195 | return 0; | |
196 | ||
197 | macctx->tmpengine = ENGINE_by_id(p->data); | |
198 | if (macctx->tmpengine == NULL) | |
199 | return 0; | |
200 | } | |
201 | #endif | |
202 | if ((p = OSSL_PARAM_locate_const(params, | |
203 | OSSL_MAC_PARAM_PROPERTIES)) | |
204 | != NULL) { | |
205 | if (p->data_type != OSSL_PARAM_UTF8_STRING) | |
206 | return 0; | |
207 | ||
208 | propquery = p->data; | |
209 | } | |
210 | ||
550f974a | 211 | EVP_CIPHER_free(macctx->alloc_cipher); |
2e5db6ad RL |
212 | |
213 | macctx->tmpcipher = macctx->alloc_cipher = | |
214 | EVP_CIPHER_fetch(PROV_LIBRARY_CONTEXT_OF(macctx->provctx), | |
215 | algoname, propquery); | |
216 | ||
217 | #ifndef FIPS_MODE /* Inside the FIPS module, we don't support legacy digests */ | |
218 | /* TODO(3.0) BEGIN legacy stuff, to be removed */ | |
219 | if (macctx->tmpcipher == NULL) | |
220 | macctx->tmpcipher = EVP_get_cipherbyname(algoname); | |
221 | /* TODO(3.0) END of legacy stuff */ | |
222 | #endif | |
223 | ||
224 | if (macctx->tmpcipher == NULL) | |
225 | return 0; | |
226 | } | |
227 | } | |
228 | if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) { | |
229 | if (p->data_type != OSSL_PARAM_OCTET_STRING) | |
230 | return 0; | |
231 | ||
232 | if (!CMAC_Init(macctx->ctx, p->data, p->data_size, | |
233 | macctx->tmpcipher, macctx->tmpengine)) | |
234 | return 0; | |
235 | ||
236 | macctx->tmpcipher = NULL; | |
237 | macctx->tmpengine = NULL; | |
238 | } | |
239 | return 1; | |
240 | } | |
241 | ||
242 | const OSSL_DISPATCH cmac_functions[] = { | |
243 | { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))cmac_new }, | |
244 | { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))cmac_dup }, | |
245 | { OSSL_FUNC_MAC_FREECTX, (void (*)(void))cmac_free }, | |
246 | { OSSL_FUNC_MAC_INIT, (void (*)(void))cmac_init }, | |
247 | { OSSL_FUNC_MAC_UPDATE, (void (*)(void))cmac_update }, | |
248 | { OSSL_FUNC_MAC_FINAL, (void (*)(void))cmac_final }, | |
249 | { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, | |
250 | (void (*)(void))cmac_gettable_ctx_params }, | |
92d9d0ae | 251 | { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))cmac_get_ctx_params }, |
2e5db6ad RL |
252 | { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, |
253 | (void (*)(void))cmac_settable_ctx_params }, | |
92d9d0ae | 254 | { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))cmac_set_ctx_params }, |
2e5db6ad RL |
255 | { 0, NULL } |
256 | }; |