]>
Commit | Line | Data |
---|---|---|
aab26e6f MC |
1 | /* |
2 | * Copyright 2019 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/crypto.h> | |
12 | #include <openssl/core_numbers.h> | |
13 | #include <openssl/core_names.h> | |
14 | #include <openssl/evp.h> | |
15 | #include <openssl/params.h> | |
16 | #include "internal/cryptlib.h" | |
861b8f87 | 17 | #include "internal/provider_algs.h" |
aab26e6f MC |
18 | #include "ciphers_locl.h" |
19 | ||
3a7b15e4 MC |
20 | static OSSL_OP_cipher_encrypt_init_fn aes_einit; |
21 | static OSSL_OP_cipher_decrypt_init_fn aes_dinit; | |
22 | static OSSL_OP_cipher_update_fn aes_block_update; | |
23 | static OSSL_OP_cipher_final_fn aes_block_final; | |
24 | static OSSL_OP_cipher_update_fn aes_stream_update; | |
25 | static OSSL_OP_cipher_final_fn aes_stream_final; | |
26 | static OSSL_OP_cipher_cipher_fn aes_cipher; | |
27 | static OSSL_OP_cipher_freectx_fn aes_freectx; | |
28 | static OSSL_OP_cipher_dupctx_fn aes_dupctx; | |
29 | static OSSL_OP_cipher_key_length_fn key_length_256; | |
30 | static OSSL_OP_cipher_key_length_fn key_length_192; | |
31 | static OSSL_OP_cipher_key_length_fn key_length_128; | |
32 | static OSSL_OP_cipher_iv_length_fn iv_length_16; | |
33 | static OSSL_OP_cipher_iv_length_fn iv_length_0; | |
34 | static OSSL_OP_cipher_block_size_fn block_size_16; | |
35 | static OSSL_OP_cipher_block_size_fn block_size_1; | |
36 | static OSSL_OP_cipher_ctx_get_params_fn aes_ctx_get_params; | |
37 | static OSSL_OP_cipher_ctx_set_params_fn aes_ctx_set_params; | |
38 | ||
344cfa34 | 39 | static int PROV_AES_KEY_generic_init(PROV_AES_KEY *ctx, |
aab26e6f | 40 | const unsigned char *iv, |
344cfa34 | 41 | size_t ivlen, |
aab26e6f MC |
42 | int enc) |
43 | { | |
344cfa34 MC |
44 | if (iv != NULL && ctx->mode != EVP_CIPH_ECB_MODE) { |
45 | if (ivlen != AES_BLOCK_SIZE) | |
46 | return 0; | |
aab26e6f | 47 | memcpy(ctx->iv, iv, AES_BLOCK_SIZE); |
344cfa34 | 48 | } |
aab26e6f | 49 | ctx->enc = enc; |
344cfa34 MC |
50 | |
51 | return 1; | |
aab26e6f MC |
52 | } |
53 | ||
344cfa34 MC |
54 | static int aes_einit(void *vctx, const unsigned char *key, size_t keylen, |
55 | const unsigned char *iv, size_t ivlen) | |
aab26e6f MC |
56 | { |
57 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; | |
58 | ||
344cfa34 MC |
59 | if (!PROV_AES_KEY_generic_init(ctx, iv, ivlen, 1)) |
60 | return 0; | |
61 | if (key != NULL) { | |
62 | if (keylen != ctx->keylen) | |
63 | return 0; | |
aab26e6f | 64 | return ctx->ciph->init(ctx, key, ctx->keylen); |
344cfa34 | 65 | } |
aab26e6f MC |
66 | |
67 | return 1; | |
68 | } | |
69 | ||
344cfa34 MC |
70 | static int aes_dinit(void *vctx, const unsigned char *key, size_t keylen, |
71 | const unsigned char *iv, size_t ivlen) | |
aab26e6f MC |
72 | { |
73 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; | |
74 | ||
344cfa34 MC |
75 | if (!PROV_AES_KEY_generic_init(ctx, iv, ivlen, 0)) |
76 | return 0; | |
77 | if (key != NULL) { | |
78 | if (keylen != ctx->keylen) | |
79 | return 0; | |
aab26e6f | 80 | return ctx->ciph->init(ctx, key, ctx->keylen); |
344cfa34 | 81 | } |
aab26e6f MC |
82 | |
83 | return 1; | |
84 | } | |
85 | ||
ed98df51 | 86 | static int aes_block_update(void *vctx, unsigned char *out, size_t *outl, |
3b94944c | 87 | size_t outsize, const unsigned char *in, size_t inl) |
aab26e6f MC |
88 | { |
89 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; | |
90 | size_t nextblocks = fillblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE, &in, | |
91 | &inl); | |
92 | size_t outlint = 0; | |
93 | ||
94 | /* | |
95 | * If we're decrypting and we end an update on a block boundary we hold | |
96 | * the last block back in case this is the last update call and the last | |
97 | * block is padded. | |
98 | */ | |
99 | if (ctx->bufsz == AES_BLOCK_SIZE | |
100 | && (ctx->enc || inl > 0 || !ctx->pad)) { | |
3b94944c MC |
101 | if (outsize < AES_BLOCK_SIZE) |
102 | return 0; | |
aab26e6f MC |
103 | if (!ctx->ciph->cipher(ctx, out, ctx->buf, AES_BLOCK_SIZE)) |
104 | return 0; | |
105 | ctx->bufsz = 0; | |
106 | outlint = AES_BLOCK_SIZE; | |
107 | out += AES_BLOCK_SIZE; | |
108 | } | |
109 | if (nextblocks > 0) { | |
110 | if (!ctx->enc && ctx->pad && nextblocks == inl) { | |
111 | if (!ossl_assert(inl >= AES_BLOCK_SIZE)) | |
112 | return 0; | |
113 | nextblocks -= AES_BLOCK_SIZE; | |
114 | } | |
3b94944c MC |
115 | outlint += nextblocks; |
116 | if (outsize < outlint) | |
117 | return 0; | |
aab26e6f MC |
118 | if (!ctx->ciph->cipher(ctx, out, in, nextblocks)) |
119 | return 0; | |
120 | in += nextblocks; | |
121 | inl -= nextblocks; | |
aab26e6f MC |
122 | } |
123 | if (!trailingdata(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE, &in, &inl)) | |
124 | return 0; | |
125 | ||
126 | *outl = outlint; | |
127 | return inl == 0; | |
128 | } | |
129 | ||
3b94944c MC |
130 | static int aes_block_final(void *vctx, unsigned char *out, size_t *outl, |
131 | size_t outsize) | |
aab26e6f MC |
132 | { |
133 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; | |
134 | ||
135 | if (ctx->enc) { | |
136 | if (ctx->pad) { | |
137 | padblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE); | |
138 | } else if (ctx->bufsz == 0) { | |
139 | *outl = 0; | |
140 | return 1; | |
141 | } else if (ctx->bufsz != AES_BLOCK_SIZE) { | |
142 | /* TODO(3.0): What is the correct error code here? */ | |
143 | return 0; | |
144 | } | |
145 | ||
3b94944c MC |
146 | if (outsize < AES_BLOCK_SIZE) |
147 | return 0; | |
aab26e6f MC |
148 | if (!ctx->ciph->cipher(ctx, out, ctx->buf, AES_BLOCK_SIZE)) |
149 | return 0; | |
150 | ctx->bufsz = 0; | |
151 | *outl = AES_BLOCK_SIZE; | |
152 | return 1; | |
153 | } | |
154 | ||
155 | /* Decrypting */ | |
156 | /* TODO(3.0): What's the correct error here */ | |
157 | if (ctx->bufsz != AES_BLOCK_SIZE) { | |
158 | if (ctx->bufsz == 0 && !ctx->pad) { | |
159 | *outl = 0; | |
160 | return 1; | |
161 | } | |
162 | return 0; | |
163 | } | |
164 | ||
165 | if (!ctx->ciph->cipher(ctx, ctx->buf, ctx->buf, AES_BLOCK_SIZE)) | |
166 | return 0; | |
167 | ||
168 | /* TODO(3.0): What is the correct error here */ | |
169 | if (ctx->pad && !unpadblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE)) | |
170 | return 0; | |
171 | ||
3b94944c MC |
172 | if (outsize < ctx->bufsz) |
173 | return 0; | |
aab26e6f MC |
174 | memcpy(out, ctx->buf, ctx->bufsz); |
175 | *outl = ctx->bufsz; | |
176 | ctx->bufsz = 0; | |
177 | return 1; | |
178 | } | |
179 | ||
ed98df51 | 180 | static int aes_stream_update(void *vctx, unsigned char *out, size_t *outl, |
3b94944c MC |
181 | size_t outsize, const unsigned char *in, |
182 | size_t inl) | |
ed98df51 MC |
183 | { |
184 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; | |
185 | ||
3b94944c MC |
186 | if (outsize < inl) |
187 | return 0; | |
188 | ||
ed98df51 MC |
189 | if (!ctx->ciph->cipher(ctx, out, in, inl)) |
190 | return 0; | |
191 | ||
192 | *outl = inl; | |
193 | return 1; | |
194 | } | |
3b94944c MC |
195 | static int aes_stream_final(void *vctx, unsigned char *out, size_t *outl, |
196 | size_t outsize) | |
ed98df51 MC |
197 | { |
198 | *outl = 0; | |
199 | return 1; | |
200 | } | |
201 | ||
718b133a MC |
202 | static int aes_cipher(void *vctx, unsigned char *out, const unsigned char *in, |
203 | size_t inl) | |
aab26e6f | 204 | { |
718b133a MC |
205 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; |
206 | ||
207 | if (!ctx->ciph->cipher(ctx, out, in, inl)) | |
208 | return 0; | |
aab26e6f | 209 | |
718b133a | 210 | return 1; |
aab26e6f MC |
211 | } |
212 | ||
718b133a | 213 | #define IMPLEMENT_new_params(lcmode, UCMODE) \ |
3a7b15e4 | 214 | static OSSL_OP_cipher_get_params_fn aes_##lcmode##_get_params; \ |
718b133a MC |
215 | static int aes_##lcmode##_get_params(const OSSL_PARAM params[]) \ |
216 | { \ | |
217 | const OSSL_PARAM *p; \ | |
218 | \ | |
219 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE); \ | |
220 | if (p != NULL && !OSSL_PARAM_set_int(p, EVP_CIPH_##UCMODE##_MODE)) \ | |
221 | return 0; \ | |
222 | \ | |
223 | return 1; \ | |
224 | } | |
f4a129bb | 225 | |
718b133a | 226 | #define IMPLEMENT_new_ctx(lcmode, UCMODE, len) \ |
3a7b15e4 | 227 | static OSSL_OP_cipher_newctx_fn aes_##len##_##lcmode##_newctx; \ |
718b133a MC |
228 | static void *aes_##len##_##lcmode##_newctx(void) \ |
229 | { \ | |
230 | PROV_AES_KEY *ctx = OPENSSL_zalloc(sizeof(*ctx)); \ | |
231 | \ | |
232 | ctx->pad = 1; \ | |
233 | ctx->keylen = (len / 8); \ | |
64adf9aa | 234 | ctx->ciph = PROV_AES_CIPHER_##lcmode(ctx->keylen); \ |
718b133a MC |
235 | ctx->mode = EVP_CIPH_##UCMODE##_MODE; \ |
236 | return ctx; \ | |
237 | } | |
f4a129bb | 238 | |
718b133a MC |
239 | /* ECB */ |
240 | IMPLEMENT_new_params(ecb, ECB) | |
241 | IMPLEMENT_new_ctx(ecb, ECB, 256) | |
242 | IMPLEMENT_new_ctx(ecb, ECB, 192) | |
243 | IMPLEMENT_new_ctx(ecb, ECB, 128) | |
f4a129bb | 244 | |
718b133a MC |
245 | /* CBC */ |
246 | IMPLEMENT_new_params(cbc, CBC) | |
247 | IMPLEMENT_new_ctx(cbc, CBC, 256) | |
248 | IMPLEMENT_new_ctx(cbc, CBC, 192) | |
249 | IMPLEMENT_new_ctx(cbc, CBC, 128) | |
f4a129bb | 250 | |
ed98df51 MC |
251 | /* OFB */ |
252 | IMPLEMENT_new_params(ofb, OFB) | |
253 | IMPLEMENT_new_ctx(ofb, OFB, 256) | |
254 | IMPLEMENT_new_ctx(ofb, OFB, 192) | |
255 | IMPLEMENT_new_ctx(ofb, OFB, 128) | |
256 | ||
75dd6d64 MC |
257 | /* CFB */ |
258 | IMPLEMENT_new_params(cfb, CFB) | |
259 | IMPLEMENT_new_params(cfb1, CFB) | |
260 | IMPLEMENT_new_params(cfb8, CFB) | |
261 | IMPLEMENT_new_ctx(cfb, CFB, 256) | |
262 | IMPLEMENT_new_ctx(cfb, CFB, 192) | |
263 | IMPLEMENT_new_ctx(cfb, CFB, 128) | |
264 | IMPLEMENT_new_ctx(cfb1, CFB, 256) | |
265 | IMPLEMENT_new_ctx(cfb1, CFB, 192) | |
266 | IMPLEMENT_new_ctx(cfb1, CFB, 128) | |
267 | IMPLEMENT_new_ctx(cfb8, CFB, 256) | |
268 | IMPLEMENT_new_ctx(cfb8, CFB, 192) | |
269 | IMPLEMENT_new_ctx(cfb8, CFB, 128) | |
ed98df51 | 270 | |
819a7ae9 MC |
271 | /* CTR */ |
272 | IMPLEMENT_new_params(ctr, CTR) | |
273 | IMPLEMENT_new_ctx(ctr, CTR, 256) | |
274 | IMPLEMENT_new_ctx(ctr, CTR, 192) | |
275 | IMPLEMENT_new_ctx(ctr, CTR, 128) | |
276 | ||
aab26e6f MC |
277 | static void aes_freectx(void *vctx) |
278 | { | |
279 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; | |
280 | ||
281 | OPENSSL_clear_free(ctx, sizeof(*ctx)); | |
282 | } | |
283 | ||
284 | static void *aes_dupctx(void *ctx) | |
285 | { | |
286 | PROV_AES_KEY *in = (PROV_AES_KEY *)ctx; | |
287 | PROV_AES_KEY *ret = OPENSSL_malloc(sizeof(*ret)); | |
288 | ||
289 | *ret = *in; | |
290 | ||
291 | return ret; | |
292 | } | |
293 | ||
294 | static size_t key_length_256(void) | |
295 | { | |
296 | return 256 / 8; | |
297 | } | |
298 | ||
f4a129bb MC |
299 | static size_t key_length_192(void) |
300 | { | |
301 | return 192 / 8; | |
302 | } | |
303 | ||
304 | static size_t key_length_128(void) | |
305 | { | |
306 | return 128 / 8; | |
307 | } | |
308 | ||
718b133a MC |
309 | static size_t iv_length_16(void) |
310 | { | |
311 | return 16; | |
312 | } | |
313 | ||
314 | static size_t iv_length_0(void) | |
315 | { | |
316 | return 0; | |
317 | } | |
318 | ||
319 | static size_t block_size_16(void) | |
320 | { | |
321 | return 16; | |
322 | } | |
323 | ||
ed98df51 MC |
324 | static size_t block_size_1(void) |
325 | { | |
326 | return 1; | |
327 | } | |
328 | ||
718b133a | 329 | static int aes_ctx_get_params(void *vctx, const OSSL_PARAM params[]) |
aab26e6f MC |
330 | { |
331 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; | |
332 | const OSSL_PARAM *p; | |
333 | ||
334 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING); | |
335 | if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->pad)) | |
336 | return 0; | |
337 | ||
338 | return 1; | |
339 | } | |
340 | ||
718b133a | 341 | static int aes_ctx_set_params(void *vctx, const OSSL_PARAM params[]) |
aab26e6f MC |
342 | { |
343 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; | |
344 | const OSSL_PARAM *p; | |
345 | ||
346 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING); | |
347 | if (p != NULL) { | |
348 | int pad; | |
349 | ||
350 | if (!OSSL_PARAM_get_int(p, &pad)) | |
351 | return 0; | |
352 | ctx->pad = pad ? 1 : 0; | |
353 | } | |
354 | return 1; | |
355 | } | |
356 | ||
ed98df51 | 357 | #define IMPLEMENT_block_funcs(mode, keylen, ivlen) \ |
718b133a MC |
358 | const OSSL_DISPATCH aes##keylen##mode##_functions[] = { \ |
359 | { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##keylen##_##mode##_newctx }, \ | |
360 | { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_einit }, \ | |
361 | { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_dinit }, \ | |
ed98df51 MC |
362 | { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_block_update }, \ |
363 | { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_block_final }, \ | |
718b133a MC |
364 | { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_cipher }, \ |
365 | { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_freectx }, \ | |
366 | { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_dupctx }, \ | |
367 | { OSSL_FUNC_CIPHER_KEY_LENGTH, (void (*)(void))key_length_##keylen }, \ | |
368 | { OSSL_FUNC_CIPHER_IV_LENGTH, (void (*)(void))iv_length_##ivlen }, \ | |
ed98df51 | 369 | { OSSL_FUNC_CIPHER_BLOCK_SIZE, (void (*)(void))block_size_16 }, \ |
718b133a MC |
370 | { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))aes_##mode##_get_params }, \ |
371 | { OSSL_FUNC_CIPHER_CTX_GET_PARAMS, (void (*)(void))aes_ctx_get_params }, \ | |
372 | { OSSL_FUNC_CIPHER_CTX_SET_PARAMS, (void (*)(void))aes_ctx_set_params }, \ | |
373 | { 0, NULL } \ | |
374 | }; | |
375 | ||
ed98df51 MC |
376 | #define IMPLEMENT_stream_funcs(mode, keylen, ivlen) \ |
377 | const OSSL_DISPATCH aes##keylen##mode##_functions[] = { \ | |
378 | { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##keylen##_##mode##_newctx }, \ | |
379 | { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_einit }, \ | |
380 | { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_dinit }, \ | |
381 | { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_stream_update }, \ | |
382 | { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_stream_final }, \ | |
383 | { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_cipher }, \ | |
384 | { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_freectx }, \ | |
385 | { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_dupctx }, \ | |
386 | { OSSL_FUNC_CIPHER_KEY_LENGTH, (void (*)(void))key_length_##keylen }, \ | |
387 | { OSSL_FUNC_CIPHER_IV_LENGTH, (void (*)(void))iv_length_##ivlen }, \ | |
388 | { OSSL_FUNC_CIPHER_BLOCK_SIZE, (void (*)(void))block_size_1 }, \ | |
389 | { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))aes_##mode##_get_params }, \ | |
390 | { OSSL_FUNC_CIPHER_CTX_GET_PARAMS, (void (*)(void))aes_ctx_get_params }, \ | |
391 | { OSSL_FUNC_CIPHER_CTX_SET_PARAMS, (void (*)(void))aes_ctx_set_params }, \ | |
392 | { 0, NULL } \ | |
393 | }; | |
718b133a | 394 | |
ed98df51 MC |
395 | /* ECB */ |
396 | IMPLEMENT_block_funcs(ecb, 256, 0) | |
397 | IMPLEMENT_block_funcs(ecb, 192, 0) | |
398 | IMPLEMENT_block_funcs(ecb, 128, 0) | |
718b133a MC |
399 | |
400 | /* CBC */ | |
ed98df51 MC |
401 | IMPLEMENT_block_funcs(cbc, 256, 16) |
402 | IMPLEMENT_block_funcs(cbc, 192, 16) | |
403 | IMPLEMENT_block_funcs(cbc, 128, 16) | |
404 | ||
405 | /* OFB */ | |
406 | IMPLEMENT_stream_funcs(ofb, 256, 16) | |
407 | IMPLEMENT_stream_funcs(ofb, 192, 16) | |
408 | IMPLEMENT_stream_funcs(ofb, 128, 16) | |
75dd6d64 MC |
409 | |
410 | /* CFB */ | |
411 | IMPLEMENT_stream_funcs(cfb, 256, 16) | |
412 | IMPLEMENT_stream_funcs(cfb, 192, 16) | |
413 | IMPLEMENT_stream_funcs(cfb, 128, 16) | |
414 | IMPLEMENT_stream_funcs(cfb1, 256, 16) | |
415 | IMPLEMENT_stream_funcs(cfb1, 192, 16) | |
416 | IMPLEMENT_stream_funcs(cfb1, 128, 16) | |
417 | IMPLEMENT_stream_funcs(cfb8, 256, 16) | |
418 | IMPLEMENT_stream_funcs(cfb8, 192, 16) | |
419 | IMPLEMENT_stream_funcs(cfb8, 128, 16) | |
819a7ae9 MC |
420 | |
421 | /* CTR */ | |
422 | IMPLEMENT_stream_funcs(ctr, 256, 16) | |
423 | IMPLEMENT_stream_funcs(ctr, 192, 16) | |
424 | IMPLEMENT_stream_funcs(ctr, 128, 16) |