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 | /* |
11 | * Generic dispatch table functions for ciphers. |
12 | */ |
13 | |
14 | #include "ciphercommon_local.h" |
15 | #include "prov/provider_ctx.h" |
16 | #include "prov/providercommonerr.h" |
17 | |
18 | /*- |
19 | * Generic cipher functions for OSSL_PARAM gettables and settables |
20 | */ |
21 | static const OSSL_PARAM cipher_known_gettable_params[] = { |
22 | OSSL_PARAM_uint(OSSL_CIPHER_PARAM_MODE, NULL), |
23 | OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), |
24 | OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), |
25 | OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_BLOCK_SIZE, NULL), |
26 | OSSL_PARAM_ulong(OSSL_CIPHER_PARAM_FLAGS, NULL), |
27 | OSSL_PARAM_END |
28 | }; |
29 | const OSSL_PARAM *cipher_generic_gettable_params(void) |
30 | { |
31 | return cipher_known_gettable_params; |
32 | } |
33 | |
34 | int cipher_generic_get_params(OSSL_PARAM params[], unsigned int md, |
35 | unsigned long flags, |
36 | size_t kbits, size_t blkbits, size_t ivbits) |
37 | { |
38 | OSSL_PARAM *p; |
39 | |
40 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE); |
41 | if (p != NULL && !OSSL_PARAM_set_uint(p, md)) { |
42 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); |
43 | return 0; |
44 | } |
45 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_FLAGS); |
46 | if (p != NULL && !OSSL_PARAM_set_ulong(p, flags)) { |
47 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); |
48 | return 0; |
49 | } |
50 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); |
51 | if (p != NULL && !OSSL_PARAM_set_size_t(p, kbits / 8)) { |
52 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); |
53 | return 0; |
54 | } |
55 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE); |
56 | if (p != NULL && !OSSL_PARAM_set_size_t(p, blkbits / 8)) { |
57 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); |
58 | return 0; |
59 | } |
60 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); |
61 | if (p != NULL && !OSSL_PARAM_set_size_t(p, ivbits / 8)) { |
62 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); |
63 | return 0; |
64 | } |
65 | return 1; |
66 | } |
67 | |
68 | CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(cipher_generic) |
69 | CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(cipher_generic) |
70 | |
71 | CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(cipher_generic) |
72 | CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(cipher_generic) |
73 | |
74 | /* |
75 | * Variable key length cipher functions for OSSL_PARAM settables |
76 | */ |
77 | |
78 | int cipher_var_keylen_set_ctx_params(void *vctx, const OSSL_PARAM params[]) |
79 | { |
80 | PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; |
81 | const OSSL_PARAM *p; |
82 | |
83 | if (!cipher_generic_set_ctx_params(vctx, params)) |
84 | return 0; |
85 | p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); |
86 | if (p != NULL) { |
87 | size_t keylen; |
88 | |
89 | if (!OSSL_PARAM_get_size_t(p, &keylen)) { |
90 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); |
91 | return 0; |
92 | } |
93 | ctx->keylen = keylen; |
94 | } |
95 | return 1; |
96 | } |
97 | |
98 | CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(cipher_var_keylen) |
99 | OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), |
100 | CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(cipher_var_keylen) |
101 | |
102 | /*- |
103 | * AEAD cipher functions for OSSL_PARAM gettables and settables |
104 | */ |
105 | static const OSSL_PARAM cipher_aead_known_gettable_ctx_params[] = { |
106 | OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), |
107 | OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), |
108 | OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL), |
109 | OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0), |
110 | OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), |
111 | OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL), |
112 | OSSL_PARAM_END |
113 | }; |
114 | const OSSL_PARAM *cipher_aead_gettable_ctx_params(void) |
115 | { |
116 | return cipher_aead_known_gettable_ctx_params; |
117 | } |
118 | |
119 | static const OSSL_PARAM cipher_aead_known_settable_ctx_params[] = { |
120 | OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, NULL), |
121 | OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), |
122 | OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0), |
123 | OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED, NULL, 0), |
124 | OSSL_PARAM_END |
125 | }; |
126 | const OSSL_PARAM *cipher_aead_settable_ctx_params(void) |
127 | { |
128 | return cipher_aead_known_settable_ctx_params; |
129 | } |
130 | |
131 | static int cipher_generic_init_internal(PROV_CIPHER_CTX *ctx, |
132 | const unsigned char *key, size_t keylen, |
133 | const unsigned char *iv, size_t ivlen, |
134 | int enc) |
135 | { |
136 | ctx->enc = enc ? 1 : 0; |
137 | |
138 | if (iv != NULL && ctx->mode != EVP_CIPH_ECB_MODE) { |
139 | if (!cipher_generic_initiv(ctx, iv, ivlen)) |
140 | return 0; |
141 | } |
142 | if (key != NULL) { |
143 | if ((ctx->flags & EVP_CIPH_VARIABLE_LENGTH) == 0) { |
144 | if (keylen != ctx->keylen) { |
145 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN); |
146 | return 0; |
147 | } |
148 | } else { |
149 | ctx->keylen = keylen; |
150 | } |
151 | return ctx->hw->init(ctx, key, ctx->keylen); |
152 | } |
153 | return 1; |
154 | } |
155 | |
156 | int cipher_generic_einit(void *vctx, const unsigned char *key, size_t keylen, |
157 | const unsigned char *iv, size_t ivlen) |
158 | { |
159 | return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx, key, keylen, |
160 | iv, ivlen, 1); |
161 | } |
162 | |
163 | int cipher_generic_dinit(void *vctx, const unsigned char *key, size_t keylen, |
164 | const unsigned char *iv, size_t ivlen) |
165 | { |
166 | return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx, key, keylen, |
167 | iv, ivlen, 0); |
168 | } |
169 | |
170 | int cipher_generic_block_update(void *vctx, unsigned char *out, size_t *outl, |
171 | size_t outsize, const unsigned char *in, |
172 | size_t inl) |
173 | { |
174 | size_t outlint = 0; |
175 | PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; |
176 | size_t blksz = ctx->blocksize; |
177 | size_t nextblocks = fillblock(ctx->buf, &ctx->bufsz, blksz, &in, &inl); |
178 | |
179 | /* |
180 | * If we're decrypting and we end an update on a block boundary we hold |
181 | * the last block back in case this is the last update call and the last |
182 | * block is padded. |
183 | */ |
184 | if (ctx->bufsz == blksz && (ctx->enc || inl > 0 || !ctx->pad)) { |
185 | if (outsize < blksz) { |
186 | ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); |
187 | return 0; |
188 | } |
189 | if (!ctx->hw->cipher(ctx, out, ctx->buf, blksz)) { |
190 | ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); |
191 | return 0; |
192 | } |
193 | ctx->bufsz = 0; |
194 | outlint = blksz; |
195 | out += blksz; |
196 | } |
197 | if (nextblocks > 0) { |
198 | if (!ctx->enc && ctx->pad && nextblocks == inl) { |
199 | if (!ossl_assert(inl >= blksz)) { |
200 | ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); |
201 | return 0; |
202 | } |
203 | nextblocks -= blksz; |
204 | } |
205 | outlint += nextblocks; |
206 | if (outsize < outlint) { |
207 | ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); |
208 | return 0; |
209 | } |
210 | } |
211 | if (nextblocks > 0) { |
212 | if (!ctx->hw->cipher(ctx, out, in, nextblocks)) { |
213 | ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); |
214 | return 0; |
215 | } |
216 | in += nextblocks; |
217 | inl -= nextblocks; |
218 | } |
219 | if (!trailingdata(ctx->buf, &ctx->bufsz, blksz, &in, &inl)) { |
220 | /* ERR_raise already called */ |
221 | return 0; |
222 | } |
223 | |
224 | *outl = outlint; |
225 | return inl == 0; |
226 | } |
227 | |
228 | int cipher_generic_block_final(void *vctx, unsigned char *out, size_t *outl, |
229 | size_t outsize) |
230 | { |
231 | PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; |
232 | size_t blksz = ctx->blocksize; |
233 | |
234 | if (ctx->enc) { |
235 | if (ctx->pad) { |
236 | padblock(ctx->buf, &ctx->bufsz, blksz); |
237 | } else if (ctx->bufsz == 0) { |
238 | *outl = 0; |
239 | return 1; |
240 | } else if (ctx->bufsz != blksz) { |
241 | ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH); |
242 | return 0; |
243 | } |
244 | |
245 | if (outsize < blksz) { |
246 | ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); |
247 | return 0; |
248 | } |
249 | if (!ctx->hw->cipher(ctx, out, ctx->buf, blksz)) { |
250 | ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); |
251 | return 0; |
252 | } |
253 | ctx->bufsz = 0; |
254 | *outl = blksz; |
255 | return 1; |
256 | } |
257 | |
258 | /* Decrypting */ |
259 | if (ctx->bufsz != blksz) { |
260 | if (ctx->bufsz == 0 && !ctx->pad) { |
261 | *outl = 0; |
262 | return 1; |
263 | } |
264 | ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH); |
265 | return 0; |
266 | } |
267 | |
268 | if (!ctx->hw->cipher(ctx, ctx->buf, ctx->buf, blksz)) { |
269 | ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); |
270 | return 0; |
271 | } |
272 | |
273 | if (ctx->pad && !unpadblock(ctx->buf, &ctx->bufsz, blksz)) { |
274 | /* ERR_raise already called */ |
275 | return 0; |
276 | } |
277 | |
278 | if (outsize < ctx->bufsz) { |
279 | ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); |
280 | return 0; |
281 | } |
282 | memcpy(out, ctx->buf, ctx->bufsz); |
283 | *outl = ctx->bufsz; |
284 | ctx->bufsz = 0; |
285 | return 1; |
286 | } |
287 | |
288 | int cipher_generic_stream_update(void *vctx, unsigned char *out, size_t *outl, |
289 | size_t outsize, const unsigned char *in, |
290 | size_t inl) |
291 | { |
292 | PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; |
293 | |
294 | if (inl == 0) { |
295 | *outl = 0; |
296 | return 1; |
297 | } |
298 | |
299 | if (outsize < inl) { |
300 | ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); |
301 | return 0; |
302 | } |
303 | |
304 | if (!ctx->hw->cipher(ctx, out, in, inl)) { |
305 | ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); |
306 | return 0; |
307 | } |
308 | |
309 | *outl = inl; |
310 | return 1; |
311 | } |
312 | int cipher_generic_stream_final(void *vctx, unsigned char *out, size_t *outl, |
313 | size_t outsize) |
314 | { |
315 | *outl = 0; |
316 | return 1; |
317 | } |
318 | |
319 | int cipher_generic_cipher(void *vctx, |
320 | unsigned char *out, size_t *outl, size_t outsize, |
321 | const unsigned char *in, size_t inl) |
322 | { |
323 | PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; |
324 | |
325 | if (outsize < inl) { |
326 | ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); |
327 | return 0; |
328 | } |
329 | |
330 | if (!ctx->hw->cipher(ctx, out, in, inl)) { |
331 | ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); |
332 | return 0; |
333 | } |
334 | |
335 | *outl = inl; |
336 | return 1; |
337 | } |
338 | |
339 | int cipher_generic_get_ctx_params(void *vctx, OSSL_PARAM params[]) |
340 | { |
341 | PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; |
342 | OSSL_PARAM *p; |
343 | |
344 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); |
345 | if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) { |
346 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); |
347 | return 0; |
348 | } |
349 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING); |
350 | if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->pad)) { |
351 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); |
352 | return 0; |
353 | } |
354 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV); |
355 | if (p != NULL |
356 | && !OSSL_PARAM_set_octet_ptr(p, &ctx->oiv, ctx->ivlen) |
357 | && !OSSL_PARAM_set_octet_string(p, &ctx->oiv, ctx->ivlen)) { |
358 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); |
359 | return 0; |
360 | } |
361 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_NUM); |
362 | if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->num)) { |
363 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); |
364 | return 0; |
365 | } |
366 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); |
367 | if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) { |
368 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); |
369 | return 0; |
370 | } |
371 | return 1; |
372 | } |
373 | |
374 | int cipher_generic_set_ctx_params(void *vctx, const OSSL_PARAM params[]) |
375 | { |
376 | PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; |
377 | const OSSL_PARAM *p; |
378 | |
379 | p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_PADDING); |
380 | if (p != NULL) { |
381 | unsigned int pad; |
382 | |
383 | if (!OSSL_PARAM_get_uint(p, &pad)) { |
384 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); |
385 | return 0; |
386 | } |
387 | ctx->pad = pad ? 1 : 0; |
388 | } |
389 | p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_NUM); |
390 | if (p != NULL) { |
391 | unsigned int num; |
392 | |
393 | if (!OSSL_PARAM_get_uint(p, &num)) { |
394 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); |
395 | return 0; |
396 | } |
397 | ctx->num = num; |
398 | } |
399 | return 1; |
400 | } |
401 | |
402 | int cipher_generic_initiv(PROV_CIPHER_CTX *ctx, const unsigned char *iv, |
403 | size_t ivlen) |
404 | { |
405 | if (ivlen != ctx->ivlen |
406 | || ivlen > sizeof(ctx->iv)) { |
407 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN); |
408 | return 0; |
409 | } |
410 | ctx->iv_set = 1; |
411 | memcpy(ctx->iv, iv, ivlen); |
412 | memcpy(ctx->oiv, iv, ivlen); |
413 | return 1; |
414 | } |
415 | |
416 | void cipher_generic_initkey(void *vctx, size_t kbits, size_t blkbits, |
417 | size_t ivbits, unsigned int mode, uint64_t flags, |
418 | const PROV_CIPHER_HW *hw, void *provctx) |
419 | { |
420 | PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; |
421 | |
422 | ctx->flags = flags; |
423 | ctx->pad = 1; |
424 | ctx->keylen = ((kbits) / 8); |
425 | ctx->ivlen = ((ivbits) / 8); |
426 | ctx->hw = hw; |
427 | ctx->mode = mode; |
428 | ctx->blocksize = blkbits / 8; |
429 | if (provctx != NULL) |
430 | ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); /* used for rand */ |
431 | } |
432 | |