Use more consistent naming for some files in evp
authortb <tb@openbsd.org>
Fri, 29 Dec 2023 05:57:24 +0000 (05:57 +0000)
committertb <tb@openbsd.org>
Fri, 29 Dec 2023 05:57:24 +0000 (05:57 +0000)
EVP_Digest{Init,Update,Final}() move from digest.c to evp_digest.c which
will become the home of all things related to EVP_MD{,_CTX} handling.

EVP_Cipher{Init,Update,Final}() move from evp_enc.c to evp_cipher.c which
will become the home of all things related to EVP_CIPHER{,_CTX} handling.

EVP_Encode{Init,Update,Final}() move from encode.c to evp_encode.c which
already is the home of EVP_ENCODE_CTX_{new,free}().

discussed with jsing

lib/libcrypto/Makefile
lib/libcrypto/evp/digest.c [deleted file]
lib/libcrypto/evp/encode.c [deleted file]
lib/libcrypto/evp/evp_cipher.c [new file with mode: 0644]
lib/libcrypto/evp/evp_digest.c [new file with mode: 0644]
lib/libcrypto/evp/evp_enc.c [deleted file]
lib/libcrypto/evp/evp_encode.c [new file with mode: 0644]

index 6329d30..d9b3e18 100644 (file)
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.159 2023/12/20 13:52:17 tb Exp $
+# $OpenBSD: Makefile,v 1.160 2023/12/29 05:57:24 tb Exp $
 
 LIB=   crypto
 LIBREBUILD=y
@@ -350,7 +350,6 @@ SRCS+= bio_enc.c
 SRCS+= bio_md.c
 SRCS+= c_all.c
 SRCS+= cipher_method_lib.c
-SRCS+= digest.c
 SRCS+= e_aes.c
 SRCS+= e_aes_cbc_hmac_sha1.c
 SRCS+= e_bf.c
@@ -368,9 +367,10 @@ SRCS+= e_rc4.c
 SRCS+= e_rc4_hmac_md5.c
 SRCS+= e_sm4.c
 SRCS+= e_xcbc_d.c
-SRCS+= encode.c
 SRCS+= evp_aead.c
-SRCS+= evp_enc.c
+SRCS+= evp_cipher.c
+SRCS+= evp_digest.c
+SRCS+= evp_encode.c
 SRCS+= evp_err.c
 SRCS+= evp_key.c
 SRCS+= evp_lib.c
diff --git a/lib/libcrypto/evp/digest.c b/lib/libcrypto/evp/digest.c
deleted file mode 100644 (file)
index 56decc2..0000000
+++ /dev/null
@@ -1,369 +0,0 @@
-/* $OpenBSD: digest.c,v 1.41 2023/12/24 22:17:05 tb Exp $ */
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-/* ====================================================================
- * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    openssl-core@openssl.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
- *
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include <openssl/opensslconf.h>
-
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/objects.h>
-
-#include "evp_local.h"
-
-int
-EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
-{
-       EVP_MD_CTX_init(ctx);
-       return EVP_DigestInit_ex(ctx, type, NULL);
-}
-
-int
-EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
-{
-       EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
-
-       if (ctx->digest != type) {
-               if (ctx->digest && ctx->digest->ctx_size && ctx->md_data &&
-                   !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) {
-                       freezero(ctx->md_data, ctx->digest->ctx_size);
-                       ctx->md_data = NULL;
-               }
-               ctx->digest = type;
-               if (!(ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) && type->ctx_size) {
-                       ctx->update = type->update;
-                       ctx->md_data = calloc(1, type->ctx_size);
-                       if (ctx->md_data == NULL) {
-                               EVP_PKEY_CTX_free(ctx->pctx);
-                               ctx->pctx = NULL;
-                               EVPerror(ERR_R_MALLOC_FAILURE);
-                               return 0;
-                       }
-               }
-       }
-       if (ctx->pctx) {
-               int r;
-               r = EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG,
-                   EVP_PKEY_CTRL_DIGESTINIT, 0, ctx);
-               if (r <= 0 && (r != -2))
-                       return 0;
-       }
-       if (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT)
-               return 1;
-       return ctx->digest->init(ctx);
-}
-
-int
-EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count)
-{
-       return ctx->update(ctx, data, count);
-}
-
-/* The caller can assume that this removes any secret data from the context */
-int
-EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
-{
-       int ret;
-
-       ret = EVP_DigestFinal_ex(ctx, md, size);
-       EVP_MD_CTX_cleanup(ctx);
-       return ret;
-}
-
-/* The caller can assume that this removes any secret data from the context */
-int
-EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
-{
-       int ret;
-
-       if ((size_t)ctx->digest->md_size > EVP_MAX_MD_SIZE) {
-               EVPerror(EVP_R_TOO_LARGE);
-               return 0;
-       }
-       ret = ctx->digest->final(ctx, md);
-       if (size != NULL)
-               *size = ctx->digest->md_size;
-       if (ctx->digest->cleanup) {
-               ctx->digest->cleanup(ctx);
-               EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
-       }
-       memset(ctx->md_data, 0, ctx->digest->ctx_size);
-       return ret;
-}
-
-int
-EVP_Digest(const void *data, size_t count,
-    unsigned char *md, unsigned int *size, const EVP_MD *type, ENGINE *impl)
-{
-       EVP_MD_CTX ctx;
-       int ret;
-
-       EVP_MD_CTX_init(&ctx);
-       EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_ONESHOT);
-       ret = EVP_DigestInit_ex(&ctx, type, NULL) &&
-           EVP_DigestUpdate(&ctx, data, count) &&
-           EVP_DigestFinal_ex(&ctx, md, size);
-       EVP_MD_CTX_cleanup(&ctx);
-
-       return ret;
-}
-
-int
-EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in)
-{
-       EVP_MD_CTX_init(out);
-       return EVP_MD_CTX_copy_ex(out, in);
-}
-
-int
-EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
-{
-       unsigned char *tmp_buf;
-
-       if ((in == NULL) || (in->digest == NULL)) {
-               EVPerror(EVP_R_INPUT_NOT_INITIALIZED);
-               return 0;
-       }
-
-       if (out->digest == in->digest) {
-               tmp_buf = out->md_data;
-               EVP_MD_CTX_set_flags(out, EVP_MD_CTX_FLAG_REUSE);
-       } else
-               tmp_buf = NULL;
-       EVP_MD_CTX_cleanup(out);
-       memcpy(out, in, sizeof *out);
-       out->md_data = NULL;
-       out->pctx = NULL;
-
-       /*
-        * Because of the EVP_PKEY_CTX_dup() below, EVP_MD_CTX_cleanup() needs
-        * to free out->pctx in all cases (even if this flag is set on in).
-        */
-       EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
-
-       if (in->md_data && out->digest->ctx_size) {
-               if (tmp_buf) {
-                       out->md_data = tmp_buf;
-               } else {
-                       out->md_data = calloc(1, out->digest->ctx_size);
-                       if (out->md_data == NULL) {
-                               EVPerror(ERR_R_MALLOC_FAILURE);
-                               return 0;
-                       }
-               }
-               memcpy(out->md_data, in->md_data, out->digest->ctx_size);
-       }
-
-       out->update = in->update;
-
-       if (in->pctx) {
-               out->pctx = EVP_PKEY_CTX_dup(in->pctx);
-               if (!out->pctx) {
-                       EVP_MD_CTX_cleanup(out);
-                       return 0;
-               }
-       }
-
-       if (out->digest->copy)
-               return out->digest->copy(out, in);
-
-       return 1;
-}
-
-EVP_MD_CTX *
-EVP_MD_CTX_new(void)
-{
-       return calloc(1, sizeof(EVP_MD_CTX));
-}
-
-void
-EVP_MD_CTX_free(EVP_MD_CTX *ctx)
-{
-       if (ctx == NULL)
-               return;
-
-       EVP_MD_CTX_cleanup(ctx);
-
-       free(ctx);
-}
-
-void
-EVP_MD_CTX_init(EVP_MD_CTX *ctx)
-{
-       memset(ctx, 0, sizeof(*ctx));
-}
-
-int
-EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
-{
-       return EVP_MD_CTX_cleanup(ctx);
-}
-
-EVP_MD_CTX *
-EVP_MD_CTX_create(void)
-{
-       return EVP_MD_CTX_new();
-}
-
-void
-EVP_MD_CTX_destroy(EVP_MD_CTX *ctx)
-{
-       EVP_MD_CTX_free(ctx);
-}
-
-/* This call frees resources associated with the context */
-int
-EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
-{
-       /*
-        * Don't assume ctx->md_data was cleaned in EVP_Digest_Final,
-        * because sometimes only copies of the context are ever finalised.
-        */
-       if (ctx->digest && ctx->digest->cleanup &&
-           !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED))
-               ctx->digest->cleanup(ctx);
-       if (ctx->digest && ctx->digest->ctx_size && ctx->md_data &&
-           !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE))
-               freezero(ctx->md_data, ctx->digest->ctx_size);
-       /*
-        * If EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set, EVP_MD_CTX_set_pkey() was
-        * called and its strange API contract implies we don't own ctx->pctx.
-        */
-       if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX))
-               EVP_PKEY_CTX_free(ctx->pctx);
-       memset(ctx, 0, sizeof(*ctx));
-
-       return 1;
-}
-
-int
-EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
-{
-       int ret;
-
-       if (!ctx->digest) {
-               EVPerror(EVP_R_NO_CIPHER_SET);
-               return 0;
-       }
-
-       if (!ctx->digest->md_ctrl) {
-               EVPerror(EVP_R_CTRL_NOT_IMPLEMENTED);
-               return 0;
-       }
-
-       ret = ctx->digest->md_ctrl(ctx, type, arg, ptr);
-       if (ret == -1) {
-               EVPerror(EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED);
-               return 0;
-       }
-       return ret;
-}
diff --git a/lib/libcrypto/evp/encode.c b/lib/libcrypto/evp/encode.c
deleted file mode 100644 (file)
index c62a1de..0000000
+++ /dev/null
@@ -1,414 +0,0 @@
-/* $OpenBSD: encode.c,v 1.32 2023/07/07 19:37:53 beck Exp $ */
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <openssl/evp.h>
-
-#include "evp_local.h"
-
-static unsigned char conv_ascii2bin(unsigned char a);
-#define conv_bin2ascii(a)      (data_bin2ascii[(a)&0x3f])
-
-/* 64 char lines
- * pad input with 0
- * left over chars are set to =
- * 1 byte  => xx==
- * 2 bytes => xxx=
- * 3 bytes => xxxx
- */
-#define BIN_PER_LINE    (64/4*3)
-#define CHUNKS_PER_LINE (64/4)
-#define CHAR_PER_LINE   (64+1)
-
-static const unsigned char data_bin2ascii[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\
-abcdefghijklmnopqrstuvwxyz0123456789+/";
-
-/* 0xF0 is a EOLN
- * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
- * 0xF2 is EOF
- * 0xE0 is ignore at start of line.
- * 0xFF is error
- */
-
-#define B64_EOLN               0xF0
-#define B64_CR                 0xF1
-#define B64_EOF                        0xF2
-#define B64_WS                 0xE0
-#define B64_ERROR              0xFF
-#define B64_NOT_BASE64(a)      (((a)|0x13) == 0xF3)
-#define B64_BASE64(a)          !B64_NOT_BASE64(a)
-
-static const unsigned char data_ascii2bin[128] = {
-       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-       0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
-       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-       0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-       0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
-       0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
-       0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
-       0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
-       0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
-       0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
-       0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-       0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
-       0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
-       0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
-       0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-static unsigned char
-conv_ascii2bin(unsigned char a)
-{
-       if (a & 0x80)
-               return B64_ERROR;
-       return data_ascii2bin[a];
-}
-
-EVP_ENCODE_CTX *
-EVP_ENCODE_CTX_new(void)
-{
-       return calloc(1, sizeof(EVP_ENCODE_CTX));
-}
-
-void
-EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
-{
-       free(ctx);
-}
-
-void
-EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
-{
-       ctx->length = 48;
-       ctx->num = 0;
-       ctx->line_num = 0;
-}
-
-int
-EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
-    const unsigned char *in, int inl)
-{
-       int i, j;
-       size_t total = 0;
-
-       *outl = 0;
-       if (inl <= 0)
-               return 0;
-       OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data));
-       if (ctx->length - ctx->num > inl) {
-               memcpy(&(ctx->enc_data[ctx->num]), in, inl);
-               ctx->num += inl;
-               return 1;
-       }
-       if (ctx->num != 0) {
-               i = ctx->length - ctx->num;
-               memcpy(&(ctx->enc_data[ctx->num]), in, i);
-               in += i;
-               inl -= i;
-               j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length);
-               ctx->num = 0;
-               out += j;
-               *(out++) = '\n';
-               *out = '\0';
-               total = j + 1;
-       }
-       while (inl >= ctx->length && total <= INT_MAX) {
-               j = EVP_EncodeBlock(out, in, ctx->length);
-               in += ctx->length;
-               inl -= ctx->length;
-               out += j;
-               *(out++) = '\n';
-               *out = '\0';
-               total += j + 1;
-       }
-       if (total > INT_MAX) {
-               /* Too much output data! */
-               *outl = 0;
-               return 0;
-       }
-       if (inl != 0)
-               memcpy(&(ctx->enc_data[0]), in, inl);
-       ctx->num = inl;
-       *outl = total;
-
-       return 1;
-}
-
-void
-EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
-{
-       unsigned int ret = 0;
-
-       if (ctx->num != 0) {
-               ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num);
-               out[ret++] = '\n';
-               out[ret] = '\0';
-               ctx->num = 0;
-       }
-       *outl = ret;
-}
-
-int
-EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
-{
-       int i, ret = 0;
-       unsigned long l;
-
-       for (i = dlen; i > 0; i -= 3) {
-               if (i >= 3) {
-                       l = (((unsigned long)f[0]) << 16L) |
-                           (((unsigned long)f[1]) << 8L) | f[2];
-                       *(t++) = conv_bin2ascii(l >> 18L);
-                       *(t++) = conv_bin2ascii(l >> 12L);
-                       *(t++) = conv_bin2ascii(l >> 6L);
-                       *(t++) = conv_bin2ascii(l     );
-               } else {
-                       l = ((unsigned long)f[0]) << 16L;
-                       if (i == 2)
-                               l |= ((unsigned long)f[1] << 8L);
-
-                       *(t++) = conv_bin2ascii(l >> 18L);
-                       *(t++) = conv_bin2ascii(l >> 12L);
-                       *(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L);
-                       *(t++) = '=';
-               }
-               ret += 4;
-               f += 3;
-       }
-
-       *t = '\0';
-       return (ret);
-}
-
-void
-EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
-{
-       ctx->num = 0;
-       ctx->length = 0;
-       ctx->line_num = 0;
-       ctx->expect_nl = 0;
-}
-
-int
-EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
-    const unsigned char *in, int inl)
-{
-       int seof = 0, eof = 0, rv = -1, ret = 0, i, v, tmp, n, decoded_len;
-       unsigned char *d;
-
-       n = ctx->num;
-       d = ctx->enc_data;
-
-       if (n > 0 && d[n - 1] == '=') {
-               eof++;
-               if (n > 1 && d[n - 2] == '=')
-                       eof++;
-       }
-
-       /* Legacy behaviour: an empty input chunk signals end of input. */
-       if (inl == 0) {
-               rv = 0;
-               goto end;
-       }
-
-       for (i = 0; i < inl; i++) {
-               tmp = *(in++);
-               v = conv_ascii2bin(tmp);
-               if (v == B64_ERROR) {
-                       rv = -1;
-                       goto end;
-               }
-
-               if (tmp == '=') {
-                       eof++;
-               } else if (eof > 0 && B64_BASE64(v)) {
-                       /* More data after padding. */
-                       rv = -1;
-                       goto end;
-               }
-
-               if (eof > 2) {
-                       rv = -1;
-                       goto end;
-               }
-
-               if (v == B64_EOF) {
-                       seof = 1;
-                       goto tail;
-               }
-
-               /* Only save valid base64 characters. */
-               if (B64_BASE64(v)) {
-                       if (n >= 64) {
-                               /*
-                                * We increment n once per loop, and empty the
-                                * buffer as soon as we reach 64 characters, so
-                                * this can only happen if someone's manually
-                                * messed with the ctx. Refuse to write any
-                                * more data.
-                                */
-                               rv = -1;
-                               goto end;
-                       }
-                       OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
-                       d[n++] = tmp;
-               }
-
-               if (n == 64) {
-                       decoded_len = EVP_DecodeBlock(out, d, n);
-                       n = 0;
-                       if (decoded_len < 0 || eof > decoded_len) {
-                               rv = -1;
-                               goto end;
-                       }
-                       ret += decoded_len - eof;
-                       out += decoded_len - eof;
-               }
-       }
-
-       /*
-        * Legacy behaviour: if the current line is a full base64-block (i.e.,
-        * has 0 mod 4 base64 characters), it is processed immediately. We keep
-        * this behaviour as applications may not be calling EVP_DecodeFinal
-        * properly.
-        */
- tail:
-       if (n > 0) {
-               if ((n & 3) == 0) {
-                       decoded_len = EVP_DecodeBlock(out, d, n);
-                       n = 0;
-                       if (decoded_len < 0 || eof > decoded_len) {
-                               rv = -1;
-                               goto end;
-                       }
-                       ret += (decoded_len - eof);
-               } else if (seof) {
-                       /* EOF in the middle of a base64 block. */
-                       rv = -1;
-                       goto end;
-               }
-       }
-
-       rv = seof || (n == 0 && eof) ? 0 : 1;
- end:
-       /* Legacy behaviour. This should probably rather be zeroed on error. */
-       *outl = ret;
-       ctx->num = n;
-       return (rv);
-}
-
-int
-EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
-{
-       int i, ret = 0, a, b, c, d;
-       unsigned long l;
-
-       /* trim white space from the start of the line. */
-       while ((conv_ascii2bin(*f) == B64_WS) && (n > 0)) {
-               f++;
-               n--;
-       }
-
-       /* strip off stuff at the end of the line
-        * ascii2bin values B64_WS, B64_EOLN, B64_EOLN and B64_EOF */
-       while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1]))))
-               n--;
-
-       if (n % 4 != 0)
-               return (-1);
-
-       for (i = 0; i < n; i += 4) {
-               a = conv_ascii2bin(*(f++));
-               b = conv_ascii2bin(*(f++));
-               c = conv_ascii2bin(*(f++));
-               d = conv_ascii2bin(*(f++));
-               if ((a & 0x80) || (b & 0x80) ||
-                   (c & 0x80) || (d & 0x80))
-                       return (-1);
-               l = ((((unsigned long)a) << 18L) |
-                   (((unsigned long)b) << 12L) |
-                   (((unsigned long)c) << 6L) |
-                   (((unsigned long)d)));
-               *(t++) = (unsigned char)(l >> 16L) & 0xff;
-               *(t++) = (unsigned char)(l >> 8L) & 0xff;
-               *(t++) = (unsigned char)(l) & 0xff;
-               ret += 3;
-       }
-       return (ret);
-}
-
-int
-EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
-{
-       int i;
-
-       *outl = 0;
-       if (ctx->num != 0) {
-               i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num);
-               if (i < 0)
-                       return (-1);
-               ctx->num = 0;
-               *outl = i;
-               return (1);
-       } else
-               return (1);
-}
diff --git a/lib/libcrypto/evp/evp_cipher.c b/lib/libcrypto/evp/evp_cipher.c
new file mode 100644 (file)
index 0000000..3b38e18
--- /dev/null
@@ -0,0 +1,687 @@
+/* $OpenBSD: evp_cipher.c,v 1.1 2023/12/29 05:57:24 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/opensslconf.h>
+
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+#include "evp_local.h"
+
+int
+EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+    const unsigned char *key, const unsigned char *iv, int enc)
+{
+       return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc);
+}
+
+int
+EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *engine,
+    const unsigned char *key, const unsigned char *iv, int enc)
+{
+       if (enc == -1)
+               enc = ctx->encrypt;
+       if (enc != 0)
+               enc = 1;
+       ctx->encrypt = enc;
+
+       if (cipher == NULL && ctx->cipher == NULL) {
+               EVPerror(EVP_R_NO_CIPHER_SET);
+               return 0;
+       }
+
+       /*
+        * Set up cipher and context. Allocate cipher data and initialize ctx.
+        * On ctx reuse only retain encryption direction and key wrap flag.
+        */
+       if (cipher != NULL) {
+               unsigned long flags = ctx->flags;
+
+               EVP_CIPHER_CTX_cleanup(ctx);
+               ctx->encrypt = enc;
+               ctx->flags = flags & EVP_CIPHER_CTX_FLAG_WRAP_ALLOW;
+
+               ctx->cipher = cipher;
+               ctx->key_len = cipher->key_len;
+
+               if (ctx->cipher->ctx_size != 0) {
+                       ctx->cipher_data = calloc(1, ctx->cipher->ctx_size);
+                       if (ctx->cipher_data == NULL) {
+                               EVPerror(ERR_R_MALLOC_FAILURE);
+                               return 0;
+                       }
+               }
+
+               if ((ctx->cipher->flags & EVP_CIPH_CTRL_INIT) != 0) {
+                       if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) {
+                               EVPerror(EVP_R_INITIALIZATION_ERROR);
+                               return 0;
+                       }
+               }
+       }
+
+       /* Block sizes must be a power of 2 due to the use of block_mask. */
+       if (ctx->cipher->block_size != 1 &&
+           ctx->cipher->block_size != 8 &&
+           ctx->cipher->block_size != 16) {
+               EVPerror(EVP_R_BAD_BLOCK_LENGTH);
+               return 0;
+       }
+
+       if ((ctx->flags & EVP_CIPHER_CTX_FLAG_WRAP_ALLOW) == 0 &&
+           EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_WRAP_MODE) {
+               EVPerror(EVP_R_WRAP_MODE_NOT_ALLOWED);
+               return 0;
+       }
+
+       if ((EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV) == 0) {
+               int iv_len;
+
+               switch (EVP_CIPHER_CTX_mode(ctx)) {
+
+               case EVP_CIPH_STREAM_CIPHER:
+               case EVP_CIPH_ECB_MODE:
+                       break;
+
+               case EVP_CIPH_CFB_MODE:
+               case EVP_CIPH_OFB_MODE:
+
+                       ctx->num = 0;
+                       /* fall-through */
+
+               case EVP_CIPH_CBC_MODE:
+                       iv_len = EVP_CIPHER_CTX_iv_length(ctx);
+                       if (iv_len < 0 || iv_len > sizeof(ctx->oiv)) {
+                               EVPerror(EVP_R_IV_TOO_LARGE);
+                               return 0;
+                       }
+                       if (iv != NULL)
+                               memcpy(ctx->oiv, iv, iv_len);
+                       memcpy(ctx->iv, ctx->oiv, iv_len);
+                       break;
+
+               case EVP_CIPH_CTR_MODE:
+                       ctx->num = 0;
+                       iv_len = EVP_CIPHER_CTX_iv_length(ctx);
+                       if (iv_len < 0 || iv_len > sizeof(ctx->iv)) {
+                               EVPerror(EVP_R_IV_TOO_LARGE);
+                               return 0;
+                       }
+                       /* Don't reuse IV for CTR mode */
+                       if (iv != NULL)
+                               memcpy(ctx->iv, iv, iv_len);
+                       break;
+
+               default:
+                       return 0;
+                       break;
+               }
+       }
+
+       if (key != NULL || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT) != 0) {
+               if (!ctx->cipher->init(ctx, key, iv, enc))
+                       return 0;
+       }
+
+       ctx->partial_len = 0;
+       ctx->final_used = 0;
+
+       return 1;
+}
+
+int
+EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len,
+    const unsigned char *in, int in_len)
+{
+       if (ctx->encrypt)
+               return EVP_EncryptUpdate(ctx, out, out_len, in, in_len);
+
+       return EVP_DecryptUpdate(ctx, out, out_len, in, in_len);
+}
+
+int
+EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len)
+{
+       if (ctx->encrypt)
+               return EVP_EncryptFinal_ex(ctx, out, out_len);
+
+       return EVP_DecryptFinal_ex(ctx, out, out_len);
+}
+
+int
+EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len)
+{
+       if (ctx->encrypt)
+               return EVP_EncryptFinal_ex(ctx, out, out_len);
+
+       return EVP_DecryptFinal_ex(ctx, out, out_len);
+}
+
+int
+EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+    const unsigned char *key, const unsigned char *iv)
+{
+       return EVP_CipherInit(ctx, cipher, key, iv, 1);
+}
+
+int
+EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *engine,
+    const unsigned char *key, const unsigned char *iv)
+{
+       return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 1);
+}
+
+/*
+ * EVP_Cipher() is an implementation detail of EVP_Cipher{Update,Final}().
+ * Behavior depends on EVP_CIPH_FLAG_CUSTOM_CIPHER being set on ctx->cipher.
+ *
+ * If the flag is set, do_cipher() operates in update mode if in != NULL and
+ * in final mode if in == NULL. It returns the number of bytes written to out
+ * (which may be 0) or -1 on error.
+ *
+ * If the flag is not set, do_cipher() assumes properly aligned data and that
+ * padding is handled correctly by the caller. Most do_cipher() methods will
+ * silently produce garbage and succeed. Returns 1 on success, 0 on error.
+ */
+int
+EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in,
+    unsigned int in_len)
+{
+       return ctx->cipher->do_cipher(ctx, out, in, in_len);
+}
+
+static int
+evp_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len,
+    const unsigned char *in, int in_len)
+{
+       int len;
+
+       *out_len = 0;
+
+       if (in_len < 0)
+               return 0;
+
+       if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0) {
+               if ((len = ctx->cipher->do_cipher(ctx, out, in, in_len)) < 0)
+                       return 0;
+
+               *out_len = len;
+               return 1;
+       }
+
+       if (!ctx->cipher->do_cipher(ctx, out, in, in_len))
+               return 0;
+
+       *out_len = in_len;
+
+       return 1;
+}
+
+int
+EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len,
+    const unsigned char *in, int in_len)
+{
+       const int block_size = ctx->cipher->block_size;
+       const int block_mask = block_size - 1;
+       int partial_len = ctx->partial_len;
+       int len = 0, total_len = 0;
+
+       *out_len = 0;
+
+       if ((block_size & block_mask) != 0)
+               return 0;
+
+       if (in_len < 0)
+               return 0;
+
+       if (in_len == 0 && EVP_CIPHER_mode(ctx->cipher) != EVP_CIPH_CCM_MODE)
+               return 1;
+
+       if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0)
+               return evp_cipher(ctx, out, out_len, in, in_len);
+
+       if (partial_len == 0 && (in_len & block_mask) == 0)
+               return evp_cipher(ctx, out, out_len, in, in_len);
+
+       if (partial_len < 0 || partial_len >= block_size ||
+           block_size > sizeof(ctx->buf)) {
+               EVPerror(EVP_R_BAD_BLOCK_LENGTH);
+               return 0;
+       }
+
+       if (partial_len > 0) {
+               int partial_needed;
+
+               if ((partial_needed = block_size - partial_len) > in_len) {
+                       memcpy(&ctx->buf[partial_len], in, in_len);
+                       ctx->partial_len += in_len;
+                       return 1;
+               }
+
+               /*
+                * Once the first partial_needed bytes from in are processed,
+                * the number of multiples of block_size of data remaining is
+                * (in_len - partial_needed) & ~block_mask.  Ensure that this
+                * plus the block processed from ctx->buf doesn't overflow.
+                */
+               if (((in_len - partial_needed) & ~block_mask) > INT_MAX - block_size) {
+                       EVPerror(EVP_R_TOO_LARGE);
+                       return 0;
+               }
+               memcpy(&ctx->buf[partial_len], in, partial_needed);
+
+               len = 0;
+               if (!evp_cipher(ctx, out, &len, ctx->buf, block_size))
+                       return 0;
+               total_len = len;
+
+               in_len -= partial_needed;
+               in += partial_needed;
+               out += len;
+       }
+
+       partial_len = in_len & block_mask;
+       if ((in_len -= partial_len) > 0) {
+               if (INT_MAX - in_len < total_len)
+                       return 0;
+               len = 0;
+               if (!evp_cipher(ctx, out, &len, in, in_len))
+                       return 0;
+               if (INT_MAX - len < total_len)
+                       return 0;
+               total_len += len;
+       }
+
+       if ((ctx->partial_len = partial_len) > 0)
+               memcpy(ctx->buf, &in[in_len], partial_len);
+
+       *out_len = total_len;
+
+       return 1;
+}
+
+int
+EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len)
+{
+       return EVP_EncryptFinal_ex(ctx, out, out_len);
+}
+
+int
+EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len)
+{
+       const int block_size = ctx->cipher->block_size;
+       int partial_len = ctx->partial_len;
+       int pad;
+
+       *out_len = 0;
+
+       if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0)
+               return evp_cipher(ctx, out, out_len, NULL, 0);
+
+       if (partial_len < 0 || partial_len >= block_size ||
+           block_size > sizeof(ctx->buf)) {
+               EVPerror(EVP_R_BAD_BLOCK_LENGTH);
+               return 0;
+       }
+       if (block_size == 1)
+               return 1;
+
+       if ((ctx->flags & EVP_CIPH_NO_PADDING) != 0) {
+               if (partial_len != 0) {
+                       EVPerror(EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
+                       return 0;
+               }
+               return 1;
+       }
+
+       pad = block_size - partial_len;
+       memset(&ctx->buf[partial_len], pad, pad);
+
+       return evp_cipher(ctx, out, out_len, ctx->buf, block_size);
+}
+
+int
+EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+    const unsigned char *key, const unsigned char *iv)
+{
+       return EVP_CipherInit(ctx, cipher, key, iv, 0);
+}
+
+int
+EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *engine,
+    const unsigned char *key, const unsigned char *iv)
+{
+       return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 0);
+}
+
+int
+EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len,
+    const unsigned char *in, int in_len)
+{
+       const int block_size = ctx->cipher->block_size;
+       const int block_mask = block_size - 1;
+       int len = 0, total_len = 0;
+
+       *out_len = 0;
+
+       if ((block_size & block_mask) != 0)
+               return 0;
+
+       if (in_len < 0)
+               return 0;
+
+       if (in_len == 0 && EVP_CIPHER_mode(ctx->cipher) != EVP_CIPH_CCM_MODE)
+               return 1;
+
+       if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0)
+               return evp_cipher(ctx, out, out_len, in, in_len);
+
+       if ((ctx->flags & EVP_CIPH_NO_PADDING) != 0)
+               return EVP_EncryptUpdate(ctx, out, out_len, in, in_len);
+
+       if (block_size > sizeof(ctx->final)) {
+               EVPerror(EVP_R_BAD_BLOCK_LENGTH);
+               return 0;
+       }
+
+       if (ctx->final_used) {
+               /*
+                * final_used is only set if partial_len is 0. Therefore the
+                * output from EVP_EncryptUpdate() is in_len & ~block_mask.
+                * Ensure (in_len & ~block_mask) + block_size doesn't overflow.
+                */
+               if ((in_len & ~block_mask) > INT_MAX - block_size) {
+                       EVPerror(EVP_R_TOO_LARGE);
+                       return 0;
+               }
+               memcpy(out, ctx->final, block_size);
+               out += block_size;
+               total_len = block_size;
+       }
+
+       ctx->final_used = 0;
+
+       len = 0;
+       if (!EVP_EncryptUpdate(ctx, out, &len, in, in_len))
+               return 0;
+
+       /* Keep copy of last block if a multiple of block_size was decrypted. */
+       if (block_size > 1 && ctx->partial_len == 0) {
+               if (len < block_size)
+                       return 0;
+               len -= block_size;
+               memcpy(ctx->final, &out[len], block_size);
+               ctx->final_used = 1;
+       }
+
+       if (len > INT_MAX - total_len)
+               return 0;
+       total_len += len;
+
+       *out_len = total_len;
+
+       return 1;
+}
+
+int
+EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len)
+{
+       return EVP_DecryptFinal_ex(ctx, out, out_len);
+}
+
+int
+EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len)
+{
+       const int block_size = ctx->cipher->block_size;
+       int partial_len = ctx->partial_len;
+       int i, pad, plain_len;
+
+       *out_len = 0;
+
+       if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0)
+               return evp_cipher(ctx, out, out_len, NULL, 0);
+
+       if ((ctx->flags & EVP_CIPH_NO_PADDING) != 0) {
+               if (partial_len != 0) {
+                       EVPerror(EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
+                       return 0;
+               }
+               return 1;
+       }
+
+       if (block_size == 1)
+               return 1;
+
+       if (partial_len != 0 || !ctx->final_used) {
+               EVPerror(EVP_R_WRONG_FINAL_BLOCK_LENGTH);
+               return 0;
+       }
+
+       if (block_size > sizeof(ctx->final)) {
+               EVPerror(EVP_R_BAD_BLOCK_LENGTH);
+               return 0;
+       }
+
+       pad = ctx->final[block_size - 1];
+       if (pad <= 0 || pad > block_size) {
+               EVPerror(EVP_R_BAD_DECRYPT);
+               return 0;
+       }
+       plain_len = block_size - pad;
+       for (i = plain_len; i < block_size; i++) {
+               if (ctx->final[i] != pad) {
+                       EVPerror(EVP_R_BAD_DECRYPT);
+                       return 0;
+               }
+       }
+
+       memcpy(out, ctx->final, plain_len);
+       *out_len = plain_len;
+
+       return 1;
+}
+
+EVP_CIPHER_CTX *
+EVP_CIPHER_CTX_new(void)
+{
+       return calloc(1, sizeof(EVP_CIPHER_CTX));
+}
+
+void
+EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
+{
+       if (ctx == NULL)
+               return;
+
+       EVP_CIPHER_CTX_cleanup(ctx);
+
+       free(ctx);
+}
+
+void
+EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx)
+{
+       memset(ctx, 0, sizeof(EVP_CIPHER_CTX));
+}
+
+int
+EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *a)
+{
+       return EVP_CIPHER_CTX_cleanup(a);
+}
+
+int
+EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c)
+{
+       if (c->cipher != NULL) {
+               /* XXX - Avoid leaks, so ignore return value of cleanup()... */
+               if (c->cipher->cleanup != NULL)
+                       c->cipher->cleanup(c);
+               if (c->cipher_data != NULL)
+                       explicit_bzero(c->cipher_data, c->cipher->ctx_size);
+       }
+
+       /* XXX - store size of cipher_data so we can always freezero(). */
+       free(c->cipher_data);
+
+       explicit_bzero(c, sizeof(EVP_CIPHER_CTX));
+
+       return 1;
+}
+
+int
+EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
+{
+       if (c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH)
+               return EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_KEY_LENGTH,
+                   keylen, NULL);
+       if (c->key_len == keylen)
+               return 1;
+       if (keylen > 0 && (c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH)) {
+               c->key_len = keylen;
+               return 1;
+       }
+       EVPerror(EVP_R_INVALID_KEY_LENGTH);
+       return 0;
+}
+
+int
+EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad)
+{
+       if (pad)
+               ctx->flags &= ~EVP_CIPH_NO_PADDING;
+       else
+               ctx->flags |= EVP_CIPH_NO_PADDING;
+       return 1;
+}
+
+int
+EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
+{
+       int ret;
+
+       if (!ctx->cipher) {
+               EVPerror(EVP_R_NO_CIPHER_SET);
+               return 0;
+       }
+
+       if (!ctx->cipher->ctrl) {
+               EVPerror(EVP_R_CTRL_NOT_IMPLEMENTED);
+               return 0;
+       }
+
+       ret = ctx->cipher->ctrl(ctx, type, arg, ptr);
+       if (ret == -1) {
+               EVPerror(EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED);
+               return 0;
+       }
+       return ret;
+}
+
+int
+EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key)
+{
+       if (ctx->cipher->flags & EVP_CIPH_RAND_KEY)
+               return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, key);
+       arc4random_buf(key, ctx->key_len);
+       return 1;
+}
+
+int
+EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
+{
+       if (in == NULL || in->cipher == NULL) {
+               EVPerror(EVP_R_INPUT_NOT_INITIALIZED);
+               return 0;
+       }
+
+       EVP_CIPHER_CTX_cleanup(out);
+       memcpy(out, in, sizeof *out);
+
+       if (in->cipher_data && in->cipher->ctx_size) {
+               out->cipher_data = calloc(1, in->cipher->ctx_size);
+               if (out->cipher_data == NULL) {
+                       EVPerror(ERR_R_MALLOC_FAILURE);
+                       return 0;
+               }
+               memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size);
+       }
+
+       if (in->cipher->flags & EVP_CIPH_CUSTOM_COPY) {
+               if (!in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY,
+                   0, out)) {
+                       /*
+                        * If the custom copy control failed, assume that there
+                        * may still be pointers copied in the cipher_data that
+                        * we do not own. This may result in a leak from a bad
+                        * custom copy control, but that's preferable to a
+                        * double free...
+                        */
+                       freezero(out->cipher_data, in->cipher->ctx_size);
+                       out->cipher_data = NULL;
+                       return 0;
+               }
+       }
+
+       return 1;
+}
diff --git a/lib/libcrypto/evp/evp_digest.c b/lib/libcrypto/evp/evp_digest.c
new file mode 100644 (file)
index 0000000..deb282e
--- /dev/null
@@ -0,0 +1,369 @@
+/* $OpenBSD: evp_digest.c,v 1.1 2023/12/29 05:57:24 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/opensslconf.h>
+
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+
+#include "evp_local.h"
+
+int
+EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
+{
+       EVP_MD_CTX_init(ctx);
+       return EVP_DigestInit_ex(ctx, type, NULL);
+}
+
+int
+EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
+{
+       EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
+
+       if (ctx->digest != type) {
+               if (ctx->digest && ctx->digest->ctx_size && ctx->md_data &&
+                   !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) {
+                       freezero(ctx->md_data, ctx->digest->ctx_size);
+                       ctx->md_data = NULL;
+               }
+               ctx->digest = type;
+               if (!(ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) && type->ctx_size) {
+                       ctx->update = type->update;
+                       ctx->md_data = calloc(1, type->ctx_size);
+                       if (ctx->md_data == NULL) {
+                               EVP_PKEY_CTX_free(ctx->pctx);
+                               ctx->pctx = NULL;
+                               EVPerror(ERR_R_MALLOC_FAILURE);
+                               return 0;
+                       }
+               }
+       }
+       if (ctx->pctx) {
+               int r;
+               r = EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG,
+                   EVP_PKEY_CTRL_DIGESTINIT, 0, ctx);
+               if (r <= 0 && (r != -2))
+                       return 0;
+       }
+       if (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT)
+               return 1;
+       return ctx->digest->init(ctx);
+}
+
+int
+EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+       return ctx->update(ctx, data, count);
+}
+
+/* The caller can assume that this removes any secret data from the context */
+int
+EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
+{
+       int ret;
+
+       ret = EVP_DigestFinal_ex(ctx, md, size);
+       EVP_MD_CTX_cleanup(ctx);
+       return ret;
+}
+
+/* The caller can assume that this removes any secret data from the context */
+int
+EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
+{
+       int ret;
+
+       if ((size_t)ctx->digest->md_size > EVP_MAX_MD_SIZE) {
+               EVPerror(EVP_R_TOO_LARGE);
+               return 0;
+       }
+       ret = ctx->digest->final(ctx, md);
+       if (size != NULL)
+               *size = ctx->digest->md_size;
+       if (ctx->digest->cleanup) {
+               ctx->digest->cleanup(ctx);
+               EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
+       }
+       memset(ctx->md_data, 0, ctx->digest->ctx_size);
+       return ret;
+}
+
+int
+EVP_Digest(const void *data, size_t count,
+    unsigned char *md, unsigned int *size, const EVP_MD *type, ENGINE *impl)
+{
+       EVP_MD_CTX ctx;
+       int ret;
+
+       EVP_MD_CTX_init(&ctx);
+       EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_ONESHOT);
+       ret = EVP_DigestInit_ex(&ctx, type, NULL) &&
+           EVP_DigestUpdate(&ctx, data, count) &&
+           EVP_DigestFinal_ex(&ctx, md, size);
+       EVP_MD_CTX_cleanup(&ctx);
+
+       return ret;
+}
+
+int
+EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in)
+{
+       EVP_MD_CTX_init(out);
+       return EVP_MD_CTX_copy_ex(out, in);
+}
+
+int
+EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
+{
+       unsigned char *tmp_buf;
+
+       if ((in == NULL) || (in->digest == NULL)) {
+               EVPerror(EVP_R_INPUT_NOT_INITIALIZED);
+               return 0;
+       }
+
+       if (out->digest == in->digest) {
+               tmp_buf = out->md_data;
+               EVP_MD_CTX_set_flags(out, EVP_MD_CTX_FLAG_REUSE);
+       } else
+               tmp_buf = NULL;
+       EVP_MD_CTX_cleanup(out);
+       memcpy(out, in, sizeof *out);
+       out->md_data = NULL;
+       out->pctx = NULL;
+
+       /*
+        * Because of the EVP_PKEY_CTX_dup() below, EVP_MD_CTX_cleanup() needs
+        * to free out->pctx in all cases (even if this flag is set on in).
+        */
+       EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
+
+       if (in->md_data && out->digest->ctx_size) {
+               if (tmp_buf) {
+                       out->md_data = tmp_buf;
+               } else {
+                       out->md_data = calloc(1, out->digest->ctx_size);
+                       if (out->md_data == NULL) {
+                               EVPerror(ERR_R_MALLOC_FAILURE);
+                               return 0;
+                       }
+               }
+               memcpy(out->md_data, in->md_data, out->digest->ctx_size);
+       }
+
+       out->update = in->update;
+
+       if (in->pctx) {
+               out->pctx = EVP_PKEY_CTX_dup(in->pctx);
+               if (!out->pctx) {
+                       EVP_MD_CTX_cleanup(out);
+                       return 0;
+               }
+       }
+
+       if (out->digest->copy)
+               return out->digest->copy(out, in);
+
+       return 1;
+}
+
+EVP_MD_CTX *
+EVP_MD_CTX_new(void)
+{
+       return calloc(1, sizeof(EVP_MD_CTX));
+}
+
+void
+EVP_MD_CTX_free(EVP_MD_CTX *ctx)
+{
+       if (ctx == NULL)
+               return;
+
+       EVP_MD_CTX_cleanup(ctx);
+
+       free(ctx);
+}
+
+void
+EVP_MD_CTX_init(EVP_MD_CTX *ctx)
+{
+       memset(ctx, 0, sizeof(*ctx));
+}
+
+int
+EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
+{
+       return EVP_MD_CTX_cleanup(ctx);
+}
+
+EVP_MD_CTX *
+EVP_MD_CTX_create(void)
+{
+       return EVP_MD_CTX_new();
+}
+
+void
+EVP_MD_CTX_destroy(EVP_MD_CTX *ctx)
+{
+       EVP_MD_CTX_free(ctx);
+}
+
+/* This call frees resources associated with the context */
+int
+EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
+{
+       /*
+        * Don't assume ctx->md_data was cleaned in EVP_Digest_Final,
+        * because sometimes only copies of the context are ever finalised.
+        */
+       if (ctx->digest && ctx->digest->cleanup &&
+           !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED))
+               ctx->digest->cleanup(ctx);
+       if (ctx->digest && ctx->digest->ctx_size && ctx->md_data &&
+           !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE))
+               freezero(ctx->md_data, ctx->digest->ctx_size);
+       /*
+        * If EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set, EVP_MD_CTX_set_pkey() was
+        * called and its strange API contract implies we don't own ctx->pctx.
+        */
+       if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX))
+               EVP_PKEY_CTX_free(ctx->pctx);
+       memset(ctx, 0, sizeof(*ctx));
+
+       return 1;
+}
+
+int
+EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
+{
+       int ret;
+
+       if (!ctx->digest) {
+               EVPerror(EVP_R_NO_CIPHER_SET);
+               return 0;
+       }
+
+       if (!ctx->digest->md_ctrl) {
+               EVPerror(EVP_R_CTRL_NOT_IMPLEMENTED);
+               return 0;
+       }
+
+       ret = ctx->digest->md_ctrl(ctx, type, arg, ptr);
+       if (ret == -1) {
+               EVPerror(EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED);
+               return 0;
+       }
+       return ret;
+}
diff --git a/lib/libcrypto/evp/evp_enc.c b/lib/libcrypto/evp/evp_enc.c
deleted file mode 100644 (file)
index 3eef53c..0000000
+++ /dev/null
@@ -1,687 +0,0 @@
-/* $OpenBSD: evp_enc.c,v 1.81 2023/12/26 09:04:30 tb Exp $ */
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <openssl/opensslconf.h>
-
-#include <openssl/err.h>
-#include <openssl/evp.h>
-
-#include "evp_local.h"
-
-int
-EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
-    const unsigned char *key, const unsigned char *iv, int enc)
-{
-       return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc);
-}
-
-int
-EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *engine,
-    const unsigned char *key, const unsigned char *iv, int enc)
-{
-       if (enc == -1)
-               enc = ctx->encrypt;
-       if (enc != 0)
-               enc = 1;
-       ctx->encrypt = enc;
-
-       if (cipher == NULL && ctx->cipher == NULL) {
-               EVPerror(EVP_R_NO_CIPHER_SET);
-               return 0;
-       }
-
-       /*
-        * Set up cipher and context. Allocate cipher data and initialize ctx.
-        * On ctx reuse only retain encryption direction and key wrap flag.
-        */
-       if (cipher != NULL) {
-               unsigned long flags = ctx->flags;
-
-               EVP_CIPHER_CTX_cleanup(ctx);
-               ctx->encrypt = enc;
-               ctx->flags = flags & EVP_CIPHER_CTX_FLAG_WRAP_ALLOW;
-
-               ctx->cipher = cipher;
-               ctx->key_len = cipher->key_len;
-
-               if (ctx->cipher->ctx_size != 0) {
-                       ctx->cipher_data = calloc(1, ctx->cipher->ctx_size);
-                       if (ctx->cipher_data == NULL) {
-                               EVPerror(ERR_R_MALLOC_FAILURE);
-                               return 0;
-                       }
-               }
-
-               if ((ctx->cipher->flags & EVP_CIPH_CTRL_INIT) != 0) {
-                       if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) {
-                               EVPerror(EVP_R_INITIALIZATION_ERROR);
-                               return 0;
-                       }
-               }
-       }
-
-       /* Block sizes must be a power of 2 due to the use of block_mask. */
-       if (ctx->cipher->block_size != 1 &&
-           ctx->cipher->block_size != 8 &&
-           ctx->cipher->block_size != 16) {
-               EVPerror(EVP_R_BAD_BLOCK_LENGTH);
-               return 0;
-       }
-
-       if ((ctx->flags & EVP_CIPHER_CTX_FLAG_WRAP_ALLOW) == 0 &&
-           EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_WRAP_MODE) {
-               EVPerror(EVP_R_WRAP_MODE_NOT_ALLOWED);
-               return 0;
-       }
-
-       if ((EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV) == 0) {
-               int iv_len;
-
-               switch (EVP_CIPHER_CTX_mode(ctx)) {
-
-               case EVP_CIPH_STREAM_CIPHER:
-               case EVP_CIPH_ECB_MODE:
-                       break;
-
-               case EVP_CIPH_CFB_MODE:
-               case EVP_CIPH_OFB_MODE:
-
-                       ctx->num = 0;
-                       /* fall-through */
-
-               case EVP_CIPH_CBC_MODE:
-                       iv_len = EVP_CIPHER_CTX_iv_length(ctx);
-                       if (iv_len < 0 || iv_len > sizeof(ctx->oiv)) {
-                               EVPerror(EVP_R_IV_TOO_LARGE);
-                               return 0;
-                       }
-                       if (iv != NULL)
-                               memcpy(ctx->oiv, iv, iv_len);
-                       memcpy(ctx->iv, ctx->oiv, iv_len);
-                       break;
-
-               case EVP_CIPH_CTR_MODE:
-                       ctx->num = 0;
-                       iv_len = EVP_CIPHER_CTX_iv_length(ctx);
-                       if (iv_len < 0 || iv_len > sizeof(ctx->iv)) {
-                               EVPerror(EVP_R_IV_TOO_LARGE);
-                               return 0;
-                       }
-                       /* Don't reuse IV for CTR mode */
-                       if (iv != NULL)
-                               memcpy(ctx->iv, iv, iv_len);
-                       break;
-
-               default:
-                       return 0;
-                       break;
-               }
-       }
-
-       if (key != NULL || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT) != 0) {
-               if (!ctx->cipher->init(ctx, key, iv, enc))
-                       return 0;
-       }
-
-       ctx->partial_len = 0;
-       ctx->final_used = 0;
-
-       return 1;
-}
-
-int
-EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len,
-    const unsigned char *in, int in_len)
-{
-       if (ctx->encrypt)
-               return EVP_EncryptUpdate(ctx, out, out_len, in, in_len);
-
-       return EVP_DecryptUpdate(ctx, out, out_len, in, in_len);
-}
-
-int
-EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len)
-{
-       if (ctx->encrypt)
-               return EVP_EncryptFinal_ex(ctx, out, out_len);
-
-       return EVP_DecryptFinal_ex(ctx, out, out_len);
-}
-
-int
-EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len)
-{
-       if (ctx->encrypt)
-               return EVP_EncryptFinal_ex(ctx, out, out_len);
-
-       return EVP_DecryptFinal_ex(ctx, out, out_len);
-}
-
-int
-EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
-    const unsigned char *key, const unsigned char *iv)
-{
-       return EVP_CipherInit(ctx, cipher, key, iv, 1);
-}
-
-int
-EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *engine,
-    const unsigned char *key, const unsigned char *iv)
-{
-       return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 1);
-}
-
-/*
- * EVP_Cipher() is an implementation detail of EVP_Cipher{Update,Final}().
- * Behavior depends on EVP_CIPH_FLAG_CUSTOM_CIPHER being set on ctx->cipher.
- *
- * If the flag is set, do_cipher() operates in update mode if in != NULL and
- * in final mode if in == NULL. It returns the number of bytes written to out
- * (which may be 0) or -1 on error.
- *
- * If the flag is not set, do_cipher() assumes properly aligned data and that
- * padding is handled correctly by the caller. Most do_cipher() methods will
- * silently produce garbage and succeed. Returns 1 on success, 0 on error.
- */
-int
-EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in,
-    unsigned int in_len)
-{
-       return ctx->cipher->do_cipher(ctx, out, in, in_len);
-}
-
-static int
-evp_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len,
-    const unsigned char *in, int in_len)
-{
-       int len;
-
-       *out_len = 0;
-
-       if (in_len < 0)
-               return 0;
-
-       if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0) {
-               if ((len = ctx->cipher->do_cipher(ctx, out, in, in_len)) < 0)
-                       return 0;
-
-               *out_len = len;
-               return 1;
-       }
-
-       if (!ctx->cipher->do_cipher(ctx, out, in, in_len))
-               return 0;
-
-       *out_len = in_len;
-
-       return 1;
-}
-
-int
-EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len,
-    const unsigned char *in, int in_len)
-{
-       const int block_size = ctx->cipher->block_size;
-       const int block_mask = block_size - 1;
-       int partial_len = ctx->partial_len;
-       int len = 0, total_len = 0;
-
-       *out_len = 0;
-
-       if ((block_size & block_mask) != 0)
-               return 0;
-
-       if (in_len < 0)
-               return 0;
-
-       if (in_len == 0 && EVP_CIPHER_mode(ctx->cipher) != EVP_CIPH_CCM_MODE)
-               return 1;
-
-       if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0)
-               return evp_cipher(ctx, out, out_len, in, in_len);
-
-       if (partial_len == 0 && (in_len & block_mask) == 0)
-               return evp_cipher(ctx, out, out_len, in, in_len);
-
-       if (partial_len < 0 || partial_len >= block_size ||
-           block_size > sizeof(ctx->buf)) {
-               EVPerror(EVP_R_BAD_BLOCK_LENGTH);
-               return 0;
-       }
-
-       if (partial_len > 0) {
-               int partial_needed;
-
-               if ((partial_needed = block_size - partial_len) > in_len) {
-                       memcpy(&ctx->buf[partial_len], in, in_len);
-                       ctx->partial_len += in_len;
-                       return 1;
-               }
-
-               /*
-                * Once the first partial_needed bytes from in are processed,
-                * the number of multiples of block_size of data remaining is
-                * (in_len - partial_needed) & ~block_mask.  Ensure that this
-                * plus the block processed from ctx->buf doesn't overflow.
-                */
-               if (((in_len - partial_needed) & ~block_mask) > INT_MAX - block_size) {
-                       EVPerror(EVP_R_TOO_LARGE);
-                       return 0;
-               }
-               memcpy(&ctx->buf[partial_len], in, partial_needed);
-
-               len = 0;
-               if (!evp_cipher(ctx, out, &len, ctx->buf, block_size))
-                       return 0;
-               total_len = len;
-
-               in_len -= partial_needed;
-               in += partial_needed;
-               out += len;
-       }
-
-       partial_len = in_len & block_mask;
-       if ((in_len -= partial_len) > 0) {
-               if (INT_MAX - in_len < total_len)
-                       return 0;
-               len = 0;
-               if (!evp_cipher(ctx, out, &len, in, in_len))
-                       return 0;
-               if (INT_MAX - len < total_len)
-                       return 0;
-               total_len += len;
-       }
-
-       if ((ctx->partial_len = partial_len) > 0)
-               memcpy(ctx->buf, &in[in_len], partial_len);
-
-       *out_len = total_len;
-
-       return 1;
-}
-
-int
-EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len)
-{
-       return EVP_EncryptFinal_ex(ctx, out, out_len);
-}
-
-int
-EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len)
-{
-       const int block_size = ctx->cipher->block_size;
-       int partial_len = ctx->partial_len;
-       int pad;
-
-       *out_len = 0;
-
-       if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0)
-               return evp_cipher(ctx, out, out_len, NULL, 0);
-
-       if (partial_len < 0 || partial_len >= block_size ||
-           block_size > sizeof(ctx->buf)) {
-               EVPerror(EVP_R_BAD_BLOCK_LENGTH);
-               return 0;
-       }
-       if (block_size == 1)
-               return 1;
-
-       if ((ctx->flags & EVP_CIPH_NO_PADDING) != 0) {
-               if (partial_len != 0) {
-                       EVPerror(EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
-                       return 0;
-               }
-               return 1;
-       }
-
-       pad = block_size - partial_len;
-       memset(&ctx->buf[partial_len], pad, pad);
-
-       return evp_cipher(ctx, out, out_len, ctx->buf, block_size);
-}
-
-int
-EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
-    const unsigned char *key, const unsigned char *iv)
-{
-       return EVP_CipherInit(ctx, cipher, key, iv, 0);
-}
-
-int
-EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *engine,
-    const unsigned char *key, const unsigned char *iv)
-{
-       return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, 0);
-}
-
-int
-EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len,
-    const unsigned char *in, int in_len)
-{
-       const int block_size = ctx->cipher->block_size;
-       const int block_mask = block_size - 1;
-       int len = 0, total_len = 0;
-
-       *out_len = 0;
-
-       if ((block_size & block_mask) != 0)
-               return 0;
-
-       if (in_len < 0)
-               return 0;
-
-       if (in_len == 0 && EVP_CIPHER_mode(ctx->cipher) != EVP_CIPH_CCM_MODE)
-               return 1;
-
-       if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0)
-               return evp_cipher(ctx, out, out_len, in, in_len);
-
-       if ((ctx->flags & EVP_CIPH_NO_PADDING) != 0)
-               return EVP_EncryptUpdate(ctx, out, out_len, in, in_len);
-
-       if (block_size > sizeof(ctx->final)) {
-               EVPerror(EVP_R_BAD_BLOCK_LENGTH);
-               return 0;
-       }
-
-       if (ctx->final_used) {
-               /*
-                * final_used is only set if partial_len is 0. Therefore the
-                * output from EVP_EncryptUpdate() is in_len & ~block_mask.
-                * Ensure (in_len & ~block_mask) + block_size doesn't overflow.
-                */
-               if ((in_len & ~block_mask) > INT_MAX - block_size) {
-                       EVPerror(EVP_R_TOO_LARGE);
-                       return 0;
-               }
-               memcpy(out, ctx->final, block_size);
-               out += block_size;
-               total_len = block_size;
-       }
-
-       ctx->final_used = 0;
-
-       len = 0;
-       if (!EVP_EncryptUpdate(ctx, out, &len, in, in_len))
-               return 0;
-
-       /* Keep copy of last block if a multiple of block_size was decrypted. */
-       if (block_size > 1 && ctx->partial_len == 0) {
-               if (len < block_size)
-                       return 0;
-               len -= block_size;
-               memcpy(ctx->final, &out[len], block_size);
-               ctx->final_used = 1;
-       }
-
-       if (len > INT_MAX - total_len)
-               return 0;
-       total_len += len;
-
-       *out_len = total_len;
-
-       return 1;
-}
-
-int
-EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len)
-{
-       return EVP_DecryptFinal_ex(ctx, out, out_len);
-}
-
-int
-EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len)
-{
-       const int block_size = ctx->cipher->block_size;
-       int partial_len = ctx->partial_len;
-       int i, pad, plain_len;
-
-       *out_len = 0;
-
-       if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0)
-               return evp_cipher(ctx, out, out_len, NULL, 0);
-
-       if ((ctx->flags & EVP_CIPH_NO_PADDING) != 0) {
-               if (partial_len != 0) {
-                       EVPerror(EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
-                       return 0;
-               }
-               return 1;
-       }
-
-       if (block_size == 1)
-               return 1;
-
-       if (partial_len != 0 || !ctx->final_used) {
-               EVPerror(EVP_R_WRONG_FINAL_BLOCK_LENGTH);
-               return 0;
-       }
-
-       if (block_size > sizeof(ctx->final)) {
-               EVPerror(EVP_R_BAD_BLOCK_LENGTH);
-               return 0;
-       }
-
-       pad = ctx->final[block_size - 1];
-       if (pad <= 0 || pad > block_size) {
-               EVPerror(EVP_R_BAD_DECRYPT);
-               return 0;
-       }
-       plain_len = block_size - pad;
-       for (i = plain_len; i < block_size; i++) {
-               if (ctx->final[i] != pad) {
-                       EVPerror(EVP_R_BAD_DECRYPT);
-                       return 0;
-               }
-       }
-
-       memcpy(out, ctx->final, plain_len);
-       *out_len = plain_len;
-
-       return 1;
-}
-
-EVP_CIPHER_CTX *
-EVP_CIPHER_CTX_new(void)
-{
-       return calloc(1, sizeof(EVP_CIPHER_CTX));
-}
-
-void
-EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
-{
-       if (ctx == NULL)
-               return;
-
-       EVP_CIPHER_CTX_cleanup(ctx);
-
-       free(ctx);
-}
-
-void
-EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx)
-{
-       memset(ctx, 0, sizeof(EVP_CIPHER_CTX));
-}
-
-int
-EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *a)
-{
-       return EVP_CIPHER_CTX_cleanup(a);
-}
-
-int
-EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c)
-{
-       if (c->cipher != NULL) {
-               /* XXX - Avoid leaks, so ignore return value of cleanup()... */
-               if (c->cipher->cleanup != NULL)
-                       c->cipher->cleanup(c);
-               if (c->cipher_data != NULL)
-                       explicit_bzero(c->cipher_data, c->cipher->ctx_size);
-       }
-
-       /* XXX - store size of cipher_data so we can always freezero(). */
-       free(c->cipher_data);
-
-       explicit_bzero(c, sizeof(EVP_CIPHER_CTX));
-
-       return 1;
-}
-
-int
-EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
-{
-       if (c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH)
-               return EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_KEY_LENGTH,
-                   keylen, NULL);
-       if (c->key_len == keylen)
-               return 1;
-       if (keylen > 0 && (c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH)) {
-               c->key_len = keylen;
-               return 1;
-       }
-       EVPerror(EVP_R_INVALID_KEY_LENGTH);
-       return 0;
-}
-
-int
-EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad)
-{
-       if (pad)
-               ctx->flags &= ~EVP_CIPH_NO_PADDING;
-       else
-               ctx->flags |= EVP_CIPH_NO_PADDING;
-       return 1;
-}
-
-int
-EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
-{
-       int ret;
-
-       if (!ctx->cipher) {
-               EVPerror(EVP_R_NO_CIPHER_SET);
-               return 0;
-       }
-
-       if (!ctx->cipher->ctrl) {
-               EVPerror(EVP_R_CTRL_NOT_IMPLEMENTED);
-               return 0;
-       }
-
-       ret = ctx->cipher->ctrl(ctx, type, arg, ptr);
-       if (ret == -1) {
-               EVPerror(EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED);
-               return 0;
-       }
-       return ret;
-}
-
-int
-EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key)
-{
-       if (ctx->cipher->flags & EVP_CIPH_RAND_KEY)
-               return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, key);
-       arc4random_buf(key, ctx->key_len);
-       return 1;
-}
-
-int
-EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
-{
-       if (in == NULL || in->cipher == NULL) {
-               EVPerror(EVP_R_INPUT_NOT_INITIALIZED);
-               return 0;
-       }
-
-       EVP_CIPHER_CTX_cleanup(out);
-       memcpy(out, in, sizeof *out);
-
-       if (in->cipher_data && in->cipher->ctx_size) {
-               out->cipher_data = calloc(1, in->cipher->ctx_size);
-               if (out->cipher_data == NULL) {
-                       EVPerror(ERR_R_MALLOC_FAILURE);
-                       return 0;
-               }
-               memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size);
-       }
-
-       if (in->cipher->flags & EVP_CIPH_CUSTOM_COPY) {
-               if (!in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY,
-                   0, out)) {
-                       /*
-                        * If the custom copy control failed, assume that there
-                        * may still be pointers copied in the cipher_data that
-                        * we do not own. This may result in a leak from a bad
-                        * custom copy control, but that's preferable to a
-                        * double free...
-                        */
-                       freezero(out->cipher_data, in->cipher->ctx_size);
-                       out->cipher_data = NULL;
-                       return 0;
-               }
-       }
-
-       return 1;
-}
diff --git a/lib/libcrypto/evp/evp_encode.c b/lib/libcrypto/evp/evp_encode.c
new file mode 100644 (file)
index 0000000..9387328
--- /dev/null
@@ -0,0 +1,414 @@
+/* $OpenBSD: evp_encode.c,v 1.1 2023/12/29 05:57:24 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/evp.h>
+
+#include "evp_local.h"
+
+static unsigned char conv_ascii2bin(unsigned char a);
+#define conv_bin2ascii(a)      (data_bin2ascii[(a)&0x3f])
+
+/* 64 char lines
+ * pad input with 0
+ * left over chars are set to =
+ * 1 byte  => xx==
+ * 2 bytes => xxx=
+ * 3 bytes => xxxx
+ */
+#define BIN_PER_LINE    (64/4*3)
+#define CHUNKS_PER_LINE (64/4)
+#define CHAR_PER_LINE   (64+1)
+
+static const unsigned char data_bin2ascii[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\
+abcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/* 0xF0 is a EOLN
+ * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
+ * 0xF2 is EOF
+ * 0xE0 is ignore at start of line.
+ * 0xFF is error
+ */
+
+#define B64_EOLN               0xF0
+#define B64_CR                 0xF1
+#define B64_EOF                        0xF2
+#define B64_WS                 0xE0
+#define B64_ERROR              0xFF
+#define B64_NOT_BASE64(a)      (((a)|0x13) == 0xF3)
+#define B64_BASE64(a)          !B64_NOT_BASE64(a)
+
+static const unsigned char data_ascii2bin[128] = {
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
+       0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
+       0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
+       0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+       0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+       0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+       0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+       0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
+       0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+       0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
+       0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static unsigned char
+conv_ascii2bin(unsigned char a)
+{
+       if (a & 0x80)
+               return B64_ERROR;
+       return data_ascii2bin[a];
+}
+
+EVP_ENCODE_CTX *
+EVP_ENCODE_CTX_new(void)
+{
+       return calloc(1, sizeof(EVP_ENCODE_CTX));
+}
+
+void
+EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
+{
+       free(ctx);
+}
+
+void
+EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
+{
+       ctx->length = 48;
+       ctx->num = 0;
+       ctx->line_num = 0;
+}
+
+int
+EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
+    const unsigned char *in, int inl)
+{
+       int i, j;
+       size_t total = 0;
+
+       *outl = 0;
+       if (inl <= 0)
+               return 0;
+       OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data));
+       if (ctx->length - ctx->num > inl) {
+               memcpy(&(ctx->enc_data[ctx->num]), in, inl);
+               ctx->num += inl;
+               return 1;
+       }
+       if (ctx->num != 0) {
+               i = ctx->length - ctx->num;
+               memcpy(&(ctx->enc_data[ctx->num]), in, i);
+               in += i;
+               inl -= i;
+               j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length);
+               ctx->num = 0;
+               out += j;
+               *(out++) = '\n';
+               *out = '\0';
+               total = j + 1;
+       }
+       while (inl >= ctx->length && total <= INT_MAX) {
+               j = EVP_EncodeBlock(out, in, ctx->length);
+               in += ctx->length;
+               inl -= ctx->length;
+               out += j;
+               *(out++) = '\n';
+               *out = '\0';
+               total += j + 1;
+       }
+       if (total > INT_MAX) {
+               /* Too much output data! */
+               *outl = 0;
+               return 0;
+       }
+       if (inl != 0)
+               memcpy(&(ctx->enc_data[0]), in, inl);
+       ctx->num = inl;
+       *outl = total;
+
+       return 1;
+}
+
+void
+EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
+{
+       unsigned int ret = 0;
+
+       if (ctx->num != 0) {
+               ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num);
+               out[ret++] = '\n';
+               out[ret] = '\0';
+               ctx->num = 0;
+       }
+       *outl = ret;
+}
+
+int
+EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
+{
+       int i, ret = 0;
+       unsigned long l;
+
+       for (i = dlen; i > 0; i -= 3) {
+               if (i >= 3) {
+                       l = (((unsigned long)f[0]) << 16L) |
+                           (((unsigned long)f[1]) << 8L) | f[2];
+                       *(t++) = conv_bin2ascii(l >> 18L);
+                       *(t++) = conv_bin2ascii(l >> 12L);
+                       *(t++) = conv_bin2ascii(l >> 6L);
+                       *(t++) = conv_bin2ascii(l     );
+               } else {
+                       l = ((unsigned long)f[0]) << 16L;
+                       if (i == 2)
+                               l |= ((unsigned long)f[1] << 8L);
+
+                       *(t++) = conv_bin2ascii(l >> 18L);
+                       *(t++) = conv_bin2ascii(l >> 12L);
+                       *(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L);
+                       *(t++) = '=';
+               }
+               ret += 4;
+               f += 3;
+       }
+
+       *t = '\0';
+       return (ret);
+}
+
+void
+EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
+{
+       ctx->num = 0;
+       ctx->length = 0;
+       ctx->line_num = 0;
+       ctx->expect_nl = 0;
+}
+
+int
+EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
+    const unsigned char *in, int inl)
+{
+       int seof = 0, eof = 0, rv = -1, ret = 0, i, v, tmp, n, decoded_len;
+       unsigned char *d;
+
+       n = ctx->num;
+       d = ctx->enc_data;
+
+       if (n > 0 && d[n - 1] == '=') {
+               eof++;
+               if (n > 1 && d[n - 2] == '=')
+                       eof++;
+       }
+
+       /* Legacy behaviour: an empty input chunk signals end of input. */
+       if (inl == 0) {
+               rv = 0;
+               goto end;
+       }
+
+       for (i = 0; i < inl; i++) {
+               tmp = *(in++);
+               v = conv_ascii2bin(tmp);
+               if (v == B64_ERROR) {
+                       rv = -1;
+                       goto end;
+               }
+
+               if (tmp == '=') {
+                       eof++;
+               } else if (eof > 0 && B64_BASE64(v)) {
+                       /* More data after padding. */
+                       rv = -1;
+                       goto end;
+               }
+
+               if (eof > 2) {
+                       rv = -1;
+                       goto end;
+               }
+
+               if (v == B64_EOF) {
+                       seof = 1;
+                       goto tail;
+               }
+
+               /* Only save valid base64 characters. */
+               if (B64_BASE64(v)) {
+                       if (n >= 64) {
+                               /*
+                                * We increment n once per loop, and empty the
+                                * buffer as soon as we reach 64 characters, so
+                                * this can only happen if someone's manually
+                                * messed with the ctx. Refuse to write any
+                                * more data.
+                                */
+                               rv = -1;
+                               goto end;
+                       }
+                       OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
+                       d[n++] = tmp;
+               }
+
+               if (n == 64) {
+                       decoded_len = EVP_DecodeBlock(out, d, n);
+                       n = 0;
+                       if (decoded_len < 0 || eof > decoded_len) {
+                               rv = -1;
+                               goto end;
+                       }
+                       ret += decoded_len - eof;
+                       out += decoded_len - eof;
+               }
+       }
+
+       /*
+        * Legacy behaviour: if the current line is a full base64-block (i.e.,
+        * has 0 mod 4 base64 characters), it is processed immediately. We keep
+        * this behaviour as applications may not be calling EVP_DecodeFinal
+        * properly.
+        */
+ tail:
+       if (n > 0) {
+               if ((n & 3) == 0) {
+                       decoded_len = EVP_DecodeBlock(out, d, n);
+                       n = 0;
+                       if (decoded_len < 0 || eof > decoded_len) {
+                               rv = -1;
+                               goto end;
+                       }
+                       ret += (decoded_len - eof);
+               } else if (seof) {
+                       /* EOF in the middle of a base64 block. */
+                       rv = -1;
+                       goto end;
+               }
+       }
+
+       rv = seof || (n == 0 && eof) ? 0 : 1;
+ end:
+       /* Legacy behaviour. This should probably rather be zeroed on error. */
+       *outl = ret;
+       ctx->num = n;
+       return (rv);
+}
+
+int
+EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
+{
+       int i, ret = 0, a, b, c, d;
+       unsigned long l;
+
+       /* trim white space from the start of the line. */
+       while ((conv_ascii2bin(*f) == B64_WS) && (n > 0)) {
+               f++;
+               n--;
+       }
+
+       /* strip off stuff at the end of the line
+        * ascii2bin values B64_WS, B64_EOLN, B64_EOLN and B64_EOF */
+       while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1]))))
+               n--;
+
+       if (n % 4 != 0)
+               return (-1);
+
+       for (i = 0; i < n; i += 4) {
+               a = conv_ascii2bin(*(f++));
+               b = conv_ascii2bin(*(f++));
+               c = conv_ascii2bin(*(f++));
+               d = conv_ascii2bin(*(f++));
+               if ((a & 0x80) || (b & 0x80) ||
+                   (c & 0x80) || (d & 0x80))
+                       return (-1);
+               l = ((((unsigned long)a) << 18L) |
+                   (((unsigned long)b) << 12L) |
+                   (((unsigned long)c) << 6L) |
+                   (((unsigned long)d)));
+               *(t++) = (unsigned char)(l >> 16L) & 0xff;
+               *(t++) = (unsigned char)(l >> 8L) & 0xff;
+               *(t++) = (unsigned char)(l) & 0xff;
+               ret += 3;
+       }
+       return (ret);
+}
+
+int
+EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
+{
+       int i;
+
+       *outl = 0;
+       if (ctx->num != 0) {
+               i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num);
+               if (i < 0)
+                       return (-1);
+               ctx->num = 0;
+               *outl = i;
+               return (1);
+       } else
+               return (1);
+}