diff options
author | tb <> | 2023-12-16 09:46:06 +0000 |
---|---|---|
committer | tb <> | 2023-12-16 09:46:06 +0000 |
commit | 6ca0c8883c60c6abbbfb61d72fa5a87fc7ff57bb (patch) | |
tree | f29a261e6fe9edf9f3347445e4d4320286e8d2d9 /src | |
parent | 4cf0a9d7b82d30cc1eb329cfe63c9b341b58ce76 (diff) | |
download | openbsd-6ca0c8883c60c6abbbfb61d72fa5a87fc7ff57bb.tar.gz openbsd-6ca0c8883c60c6abbbfb61d72fa5a87fc7ff57bb.tar.bz2 openbsd-6ca0c8883c60c6abbbfb61d72fa5a87fc7ff57bb.zip |
Implement and use a do_cipher() wrapper
Instead of using five different idioms for eight callers of the do_cipher()
method in EVP_{Decrypt,Encrypt}{Update,Final_ex}(), wrap the API insanity
in an evp_cipher() function that calls do_cipher() as appropriate depending
on the EVP_CIPH_FLAG_CUSTOM_CIPHER being set or not. This wrapper has the
usual OpenSSL calling conventions.
There is one complication in EVP_EncryptUpdate() in the case a previous
call wrote only a partial buffer. In that case, the evp_cipher() call is
made twice and the lengths have to be added. Add overflow checks and only
set outl (the number of bytes written) to out on success.
ok jsing
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libcrypto/evp/evp_enc.c | 122 |
1 files changed, 63 insertions, 59 deletions
diff --git a/src/lib/libcrypto/evp/evp_enc.c b/src/lib/libcrypto/evp/evp_enc.c index e8944dc9a4..edc15fdab4 100644 --- a/src/lib/libcrypto/evp/evp_enc.c +++ b/src/lib/libcrypto/evp/evp_enc.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: evp_enc.c,v 1.60 2023/12/15 13:33:10 tb Exp $ */ | 1 | /* $OpenBSD: evp_enc.c,v 1.61 2023/12/16 09:46:06 tb Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -265,11 +265,39 @@ EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, | |||
265 | return ctx->cipher->do_cipher(ctx, out, in, inl); | 265 | return ctx->cipher->do_cipher(ctx, out, in, inl); |
266 | } | 266 | } |
267 | 267 | ||
268 | static int | ||
269 | evp_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len, | ||
270 | const unsigned char *in, int in_len) | ||
271 | { | ||
272 | int len; | ||
273 | |||
274 | *out_len = 0; | ||
275 | |||
276 | if (in_len < 0) | ||
277 | return 0; | ||
278 | |||
279 | if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0) { | ||
280 | if ((len = ctx->cipher->do_cipher(ctx, out, in, in_len)) < 0) | ||
281 | return 0; | ||
282 | |||
283 | *out_len = len; | ||
284 | return 1; | ||
285 | } | ||
286 | |||
287 | if (!ctx->cipher->do_cipher(ctx, out, in, in_len)) | ||
288 | return 0; | ||
289 | |||
290 | *out_len = in_len; | ||
291 | |||
292 | return 1; | ||
293 | } | ||
294 | |||
268 | int | 295 | int |
269 | EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, | 296 | EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, |
270 | const unsigned char *in, int inl) | 297 | const unsigned char *in, int inl) |
271 | { | 298 | { |
272 | int i, j, bl; | 299 | int i, j, bl; |
300 | int len = 0, total_len = 0; | ||
273 | 301 | ||
274 | *outl = 0; | 302 | *outl = 0; |
275 | 303 | ||
@@ -279,36 +307,22 @@ EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, | |||
279 | if (inl == 0 && EVP_CIPHER_mode(ctx->cipher) != EVP_CIPH_CCM_MODE) | 307 | if (inl == 0 && EVP_CIPHER_mode(ctx->cipher) != EVP_CIPH_CCM_MODE) |
280 | return 1; | 308 | return 1; |
281 | 309 | ||
282 | if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { | 310 | if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0) |
283 | i = ctx->cipher->do_cipher(ctx, out, in, inl); | 311 | return evp_cipher(ctx, out, outl, in, inl); |
284 | if (i < 0) | 312 | |
285 | return 0; | 313 | if (ctx->buf_len == 0 && (inl & ctx->block_mask) == 0) |
286 | else | 314 | return evp_cipher(ctx, out, outl, in, inl); |
287 | *outl = i; | ||
288 | return 1; | ||
289 | } | ||
290 | 315 | ||
291 | if (ctx->buf_len == 0 && (inl&(ctx->block_mask)) == 0) { | ||
292 | if (ctx->cipher->do_cipher(ctx, out, in, inl)) { | ||
293 | *outl = inl; | ||
294 | return 1; | ||
295 | } else { | ||
296 | *outl = 0; | ||
297 | return 0; | ||
298 | } | ||
299 | } | ||
300 | i = ctx->buf_len; | 316 | i = ctx->buf_len; |
301 | bl = ctx->cipher->block_size; | 317 | bl = ctx->cipher->block_size; |
302 | if ((size_t)bl > sizeof(ctx->buf)) { | 318 | if ((size_t)bl > sizeof(ctx->buf)) { |
303 | EVPerror(EVP_R_BAD_BLOCK_LENGTH); | 319 | EVPerror(EVP_R_BAD_BLOCK_LENGTH); |
304 | *outl = 0; | ||
305 | return 0; | 320 | return 0; |
306 | } | 321 | } |
307 | if (i != 0) { | 322 | if (i != 0) { |
308 | if (bl - i > inl) { | 323 | if (bl - i > inl) { |
309 | memcpy(&(ctx->buf[i]), in, inl); | 324 | memcpy(&(ctx->buf[i]), in, inl); |
310 | ctx->buf_len += inl; | 325 | ctx->buf_len += inl; |
311 | *outl = 0; | ||
312 | return 1; | 326 | return 1; |
313 | } else { | 327 | } else { |
314 | j = bl - i; | 328 | j = bl - i; |
@@ -324,26 +338,37 @@ EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, | |||
324 | return 0; | 338 | return 0; |
325 | } | 339 | } |
326 | memcpy(&(ctx->buf[i]), in, j); | 340 | memcpy(&(ctx->buf[i]), in, j); |
327 | if (!ctx->cipher->do_cipher(ctx, out, ctx->buf, bl)) | 341 | |
342 | len = 0; | ||
343 | if (!evp_cipher(ctx, out, &len, ctx->buf, bl)) | ||
328 | return 0; | 344 | return 0; |
345 | total_len = len; | ||
346 | |||
329 | inl -= j; | 347 | inl -= j; |
330 | in += j; | 348 | in += j; |
331 | out += bl; | 349 | out += len; |
332 | *outl = bl; | ||
333 | } | 350 | } |
334 | } else | 351 | } |
335 | *outl = 0; | 352 | |
336 | i = inl&(bl - 1); | 353 | i = inl&(bl - 1); |
337 | inl -= i; | 354 | inl -= i; |
338 | if (inl > 0) { | 355 | if (inl > 0) { |
339 | if (!ctx->cipher->do_cipher(ctx, out, in, inl)) | 356 | if (INT_MAX - inl < total_len) |
357 | return 0; | ||
358 | len = 0; | ||
359 | if (!evp_cipher(ctx, out, &len, in, inl)) | ||
340 | return 0; | 360 | return 0; |
341 | *outl += inl; | 361 | if (INT_MAX - len < total_len) |
362 | return 0; | ||
363 | total_len += len; | ||
342 | } | 364 | } |
343 | 365 | ||
344 | if (i != 0) | 366 | if (i != 0) |
345 | memcpy(ctx->buf, &(in[inl]), i); | 367 | memcpy(ctx->buf, &(in[inl]), i); |
346 | ctx->buf_len = i; | 368 | ctx->buf_len = i; |
369 | |||
370 | *outl = total_len; | ||
371 | |||
347 | return 1; | 372 | return 1; |
348 | } | 373 | } |
349 | 374 | ||
@@ -356,17 +381,13 @@ EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) | |||
356 | int | 381 | int |
357 | EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) | 382 | EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) |
358 | { | 383 | { |
359 | int n, ret; | 384 | int n; |
360 | unsigned int i, b, bl; | 385 | unsigned int i, b, bl; |
361 | 386 | ||
362 | if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { | 387 | *outl = 0; |
363 | ret = ctx->cipher->do_cipher(ctx, out, NULL, 0); | 388 | |
364 | if (ret < 0) | 389 | if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0) |
365 | return 0; | 390 | return evp_cipher(ctx, out, outl, NULL, 0); |
366 | else | ||
367 | *outl = ret; | ||
368 | return 1; | ||
369 | } | ||
370 | 391 | ||
371 | b = ctx->cipher->block_size; | 392 | b = ctx->cipher->block_size; |
372 | if (b > sizeof ctx->buf) { | 393 | if (b > sizeof ctx->buf) { |
@@ -390,13 +411,8 @@ EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) | |||
390 | n = b - bl; | 411 | n = b - bl; |
391 | for (i = bl; i < b; i++) | 412 | for (i = bl; i < b; i++) |
392 | ctx->buf[i] = n; | 413 | ctx->buf[i] = n; |
393 | ret = ctx->cipher->do_cipher(ctx, out, ctx->buf, b); | ||
394 | |||
395 | 414 | ||
396 | if (ret) | 415 | return evp_cipher(ctx, out, outl, ctx->buf, b); |
397 | *outl = b; | ||
398 | |||
399 | return ret; | ||
400 | } | 416 | } |
401 | 417 | ||
402 | int | 418 | int |
@@ -414,15 +430,8 @@ EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, | |||
414 | if (inl == 0 && EVP_CIPHER_mode(ctx->cipher) != EVP_CIPH_CCM_MODE) | 430 | if (inl == 0 && EVP_CIPHER_mode(ctx->cipher) != EVP_CIPH_CCM_MODE) |
415 | return 1; | 431 | return 1; |
416 | 432 | ||
417 | if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { | 433 | if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0) |
418 | fix_len = ctx->cipher->do_cipher(ctx, out, in, inl); | 434 | return evp_cipher(ctx, out, outl, in, inl); |
419 | if (fix_len < 0) { | ||
420 | *outl = 0; | ||
421 | return 0; | ||
422 | } else | ||
423 | *outl = fix_len; | ||
424 | return 1; | ||
425 | } | ||
426 | 435 | ||
427 | if (ctx->flags & EVP_CIPH_NO_PADDING) | 436 | if (ctx->flags & EVP_CIPH_NO_PADDING) |
428 | return EVP_EncryptUpdate(ctx, out, outl, in, inl); | 437 | return EVP_EncryptUpdate(ctx, out, outl, in, inl); |
@@ -480,16 +489,11 @@ EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) | |||
480 | { | 489 | { |
481 | int i, n; | 490 | int i, n; |
482 | unsigned int b; | 491 | unsigned int b; |
492 | |||
483 | *outl = 0; | 493 | *outl = 0; |
484 | 494 | ||
485 | if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { | 495 | if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0) |
486 | i = ctx->cipher->do_cipher(ctx, out, NULL, 0); | 496 | return evp_cipher(ctx, out, outl, NULL, 0); |
487 | if (i < 0) | ||
488 | return 0; | ||
489 | else | ||
490 | *outl = i; | ||
491 | return 1; | ||
492 | } | ||
493 | 497 | ||
494 | b = ctx->cipher->block_size; | 498 | b = ctx->cipher->block_size; |
495 | if (ctx->flags & EVP_CIPH_NO_PADDING) { | 499 | if (ctx->flags & EVP_CIPH_NO_PADDING) { |