summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2023-12-16 09:46:06 +0000
committertb <>2023-12-16 09:46:06 +0000
commit6ca0c8883c60c6abbbfb61d72fa5a87fc7ff57bb (patch)
treef29a261e6fe9edf9f3347445e4d4320286e8d2d9 /src
parent4cf0a9d7b82d30cc1eb329cfe63c9b341b58ce76 (diff)
downloadopenbsd-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.c122
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
268static int
269evp_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
268int 295int
269EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, 296EVP_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)
356int 381int
357EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) 382EVP_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
402int 418int
@@ -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) {