]>
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 | ||
20 | static void PROV_AES_KEY_generic_init(PROV_AES_KEY *ctx, | |
21 | const unsigned char *iv, | |
22 | int enc) | |
23 | { | |
24 | if (iv != NULL) | |
25 | memcpy(ctx->iv, iv, AES_BLOCK_SIZE); | |
26 | ctx->enc = enc; | |
27 | } | |
28 | ||
29 | static int aes_einit(void *vctx, const unsigned char *key, | |
30 | const unsigned char *iv) | |
31 | { | |
32 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; | |
33 | ||
34 | PROV_AES_KEY_generic_init(ctx, iv, 1); | |
35 | if (key != NULL) | |
36 | return ctx->ciph->init(ctx, key, ctx->keylen); | |
37 | ||
38 | return 1; | |
39 | } | |
40 | ||
41 | static int aes_dinit(void *vctx, const unsigned char *key, | |
42 | const unsigned char *iv) | |
43 | { | |
44 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; | |
45 | ||
46 | PROV_AES_KEY_generic_init(ctx, iv, 0); | |
47 | if (key != NULL) | |
48 | return ctx->ciph->init(ctx, key, ctx->keylen); | |
49 | ||
50 | return 1; | |
51 | } | |
52 | ||
53 | static int aes_update(void *vctx, unsigned char *out, size_t *outl, | |
54 | const unsigned char *in, size_t inl) | |
55 | { | |
56 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; | |
57 | size_t nextblocks = fillblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE, &in, | |
58 | &inl); | |
59 | size_t outlint = 0; | |
60 | ||
61 | /* | |
62 | * If we're decrypting and we end an update on a block boundary we hold | |
63 | * the last block back in case this is the last update call and the last | |
64 | * block is padded. | |
65 | */ | |
66 | if (ctx->bufsz == AES_BLOCK_SIZE | |
67 | && (ctx->enc || inl > 0 || !ctx->pad)) { | |
68 | if (!ctx->ciph->cipher(ctx, out, ctx->buf, AES_BLOCK_SIZE)) | |
69 | return 0; | |
70 | ctx->bufsz = 0; | |
71 | outlint = AES_BLOCK_SIZE; | |
72 | out += AES_BLOCK_SIZE; | |
73 | } | |
74 | if (nextblocks > 0) { | |
75 | if (!ctx->enc && ctx->pad && nextblocks == inl) { | |
76 | if (!ossl_assert(inl >= AES_BLOCK_SIZE)) | |
77 | return 0; | |
78 | nextblocks -= AES_BLOCK_SIZE; | |
79 | } | |
80 | if (!ctx->ciph->cipher(ctx, out, in, nextblocks)) | |
81 | return 0; | |
82 | in += nextblocks; | |
83 | inl -= nextblocks; | |
84 | outlint += nextblocks; | |
85 | } | |
86 | if (!trailingdata(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE, &in, &inl)) | |
87 | return 0; | |
88 | ||
89 | *outl = outlint; | |
90 | return inl == 0; | |
91 | } | |
92 | ||
93 | static int aes_final(void *vctx, unsigned char *out, size_t *outl) | |
94 | { | |
95 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; | |
96 | ||
97 | if (ctx->enc) { | |
98 | if (ctx->pad) { | |
99 | padblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE); | |
100 | } else if (ctx->bufsz == 0) { | |
101 | *outl = 0; | |
102 | return 1; | |
103 | } else if (ctx->bufsz != AES_BLOCK_SIZE) { | |
104 | /* TODO(3.0): What is the correct error code here? */ | |
105 | return 0; | |
106 | } | |
107 | ||
108 | if (!ctx->ciph->cipher(ctx, out, ctx->buf, AES_BLOCK_SIZE)) | |
109 | return 0; | |
110 | ctx->bufsz = 0; | |
111 | *outl = AES_BLOCK_SIZE; | |
112 | return 1; | |
113 | } | |
114 | ||
115 | /* Decrypting */ | |
116 | /* TODO(3.0): What's the correct error here */ | |
117 | if (ctx->bufsz != AES_BLOCK_SIZE) { | |
118 | if (ctx->bufsz == 0 && !ctx->pad) { | |
119 | *outl = 0; | |
120 | return 1; | |
121 | } | |
122 | return 0; | |
123 | } | |
124 | ||
125 | if (!ctx->ciph->cipher(ctx, ctx->buf, ctx->buf, AES_BLOCK_SIZE)) | |
126 | return 0; | |
127 | ||
128 | /* TODO(3.0): What is the correct error here */ | |
129 | if (ctx->pad && !unpadblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE)) | |
130 | return 0; | |
131 | ||
132 | memcpy(out, ctx->buf, ctx->bufsz); | |
133 | *outl = ctx->bufsz; | |
134 | ctx->bufsz = 0; | |
135 | return 1; | |
136 | } | |
137 | ||
718b133a MC |
138 | static int aes_cipher(void *vctx, unsigned char *out, const unsigned char *in, |
139 | size_t inl) | |
aab26e6f | 140 | { |
718b133a MC |
141 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; |
142 | ||
143 | if (!ctx->ciph->cipher(ctx, out, in, inl)) | |
144 | return 0; | |
aab26e6f | 145 | |
718b133a | 146 | return 1; |
aab26e6f MC |
147 | } |
148 | ||
718b133a MC |
149 | #define IMPLEMENT_new_params(lcmode, UCMODE) \ |
150 | static int aes_##lcmode##_get_params(const OSSL_PARAM params[]) \ | |
151 | { \ | |
152 | const OSSL_PARAM *p; \ | |
153 | \ | |
154 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE); \ | |
155 | if (p != NULL && !OSSL_PARAM_set_int(p, EVP_CIPH_##UCMODE##_MODE)) \ | |
156 | return 0; \ | |
157 | \ | |
158 | return 1; \ | |
159 | } | |
f4a129bb | 160 | |
718b133a MC |
161 | #define IMPLEMENT_new_ctx(lcmode, UCMODE, len) \ |
162 | static void *aes_##len##_##lcmode##_newctx(void) \ | |
163 | { \ | |
164 | PROV_AES_KEY *ctx = OPENSSL_zalloc(sizeof(*ctx)); \ | |
165 | \ | |
166 | ctx->pad = 1; \ | |
167 | ctx->keylen = (len / 8); \ | |
168 | ctx->ciph = PROV_AES_CIPHER_##lcmode(); \ | |
169 | ctx->mode = EVP_CIPH_##UCMODE##_MODE; \ | |
170 | return ctx; \ | |
171 | } | |
f4a129bb | 172 | |
718b133a MC |
173 | /* ECB */ |
174 | IMPLEMENT_new_params(ecb, ECB) | |
175 | IMPLEMENT_new_ctx(ecb, ECB, 256) | |
176 | IMPLEMENT_new_ctx(ecb, ECB, 192) | |
177 | IMPLEMENT_new_ctx(ecb, ECB, 128) | |
f4a129bb | 178 | |
718b133a MC |
179 | /* CBC */ |
180 | IMPLEMENT_new_params(cbc, CBC) | |
181 | IMPLEMENT_new_ctx(cbc, CBC, 256) | |
182 | IMPLEMENT_new_ctx(cbc, CBC, 192) | |
183 | IMPLEMENT_new_ctx(cbc, CBC, 128) | |
f4a129bb | 184 | |
aab26e6f MC |
185 | static void aes_freectx(void *vctx) |
186 | { | |
187 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; | |
188 | ||
189 | OPENSSL_clear_free(ctx, sizeof(*ctx)); | |
190 | } | |
191 | ||
192 | static void *aes_dupctx(void *ctx) | |
193 | { | |
194 | PROV_AES_KEY *in = (PROV_AES_KEY *)ctx; | |
195 | PROV_AES_KEY *ret = OPENSSL_malloc(sizeof(*ret)); | |
196 | ||
197 | *ret = *in; | |
198 | ||
199 | return ret; | |
200 | } | |
201 | ||
202 | static size_t key_length_256(void) | |
203 | { | |
204 | return 256 / 8; | |
205 | } | |
206 | ||
f4a129bb MC |
207 | static size_t key_length_192(void) |
208 | { | |
209 | return 192 / 8; | |
210 | } | |
211 | ||
212 | static size_t key_length_128(void) | |
213 | { | |
214 | return 128 / 8; | |
215 | } | |
216 | ||
718b133a MC |
217 | static size_t iv_length_16(void) |
218 | { | |
219 | return 16; | |
220 | } | |
221 | ||
222 | static size_t iv_length_0(void) | |
223 | { | |
224 | return 0; | |
225 | } | |
226 | ||
227 | static size_t block_size_16(void) | |
228 | { | |
229 | return 16; | |
230 | } | |
231 | ||
232 | static int aes_ctx_get_params(void *vctx, const OSSL_PARAM params[]) | |
aab26e6f MC |
233 | { |
234 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; | |
235 | const OSSL_PARAM *p; | |
236 | ||
237 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING); | |
238 | if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->pad)) | |
239 | return 0; | |
240 | ||
241 | return 1; | |
242 | } | |
243 | ||
718b133a | 244 | static int aes_ctx_set_params(void *vctx, const OSSL_PARAM params[]) |
aab26e6f MC |
245 | { |
246 | PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx; | |
247 | const OSSL_PARAM *p; | |
248 | ||
249 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING); | |
250 | if (p != NULL) { | |
251 | int pad; | |
252 | ||
253 | if (!OSSL_PARAM_get_int(p, &pad)) | |
254 | return 0; | |
255 | ctx->pad = pad ? 1 : 0; | |
256 | } | |
257 | return 1; | |
258 | } | |
259 | ||
718b133a MC |
260 | #define IMPLEMENT_funcs(mode, keylen, ivlen, blksz) \ |
261 | const OSSL_DISPATCH aes##keylen##mode##_functions[] = { \ | |
262 | { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##keylen##_##mode##_newctx }, \ | |
263 | { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_einit }, \ | |
264 | { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_dinit }, \ | |
265 | { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_update }, \ | |
266 | { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_final }, \ | |
267 | { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_cipher }, \ | |
268 | { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_freectx }, \ | |
269 | { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_dupctx }, \ | |
270 | { OSSL_FUNC_CIPHER_KEY_LENGTH, (void (*)(void))key_length_##keylen }, \ | |
271 | { OSSL_FUNC_CIPHER_IV_LENGTH, (void (*)(void))iv_length_##ivlen }, \ | |
272 | { OSSL_FUNC_CIPHER_BLOCK_SIZE, (void (*)(void))block_size_##blksz }, \ | |
273 | { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))aes_##mode##_get_params }, \ | |
274 | { OSSL_FUNC_CIPHER_CTX_GET_PARAMS, (void (*)(void))aes_ctx_get_params }, \ | |
275 | { OSSL_FUNC_CIPHER_CTX_SET_PARAMS, (void (*)(void))aes_ctx_set_params }, \ | |
276 | { 0, NULL } \ | |
277 | }; | |
278 | ||
279 | /* ECB */ | |
280 | ||
281 | IMPLEMENT_funcs(ecb, 256, 0, 16) | |
282 | IMPLEMENT_funcs(ecb, 192, 0, 16) | |
283 | IMPLEMENT_funcs(ecb, 128, 0, 16) | |
284 | ||
285 | /* CBC */ | |
286 | ||
287 | IMPLEMENT_funcs(cbc, 256, 16, 16) | |
288 | IMPLEMENT_funcs(cbc, 192, 16, 16) | |
289 | IMPLEMENT_funcs(cbc, 128, 16, 16) |