195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * All rights reserved.
395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This package is an SSL implementation written
595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * by Eric Young (eay@cryptsoft.com).
695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The implementation was written so as to conform with Netscapes SSL.
795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This library is free for commercial and non-commercial use as long as
995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the following conditions are aheared to.  The following conditions
1095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * apply to all code found in this distribution, be it the RC4, RSA,
1195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * included with this distribution is covered by the same copyright terms
1395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
1595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Copyright remains Eric Young's, and as such any Copyright notices in
1695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the code are not to be removed.
1795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * If this package is used in a product, Eric Young should be given attribution
1895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * as the author of the parts of the library used.
1995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This can be in the form of a textual message at program startup or
2095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * in documentation (online or textual) provided with the package.
2195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
2295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Redistribution and use in source and binary forms, with or without
2395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * modification, are permitted provided that the following conditions
2495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * are met:
2595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1. Redistributions of source code must retain the copyright
2695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer.
2795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2. Redistributions in binary form must reproduce the above copyright
2895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer in the
2995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    documentation and/or other materials provided with the distribution.
3095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3. All advertising materials mentioning features or use of this software
3195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    must display the following acknowledgement:
3295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    "This product includes cryptographic software written by
3395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *     Eric Young (eay@cryptsoft.com)"
3495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    The word 'cryptographic' can be left out if the rouines from the library
3595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    being used are not cryptographic related :-).
3695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 4. If you include any Windows specific code (or a derivative thereof) from
3795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    the apps directory (application code) you must include an acknowledgement:
3895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
3995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
4095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * SUCH DAMAGE.
5195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
5295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The licence and distribution terms for any publically available version or
5395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * derivative of this code cannot be changed.  i.e. this code cannot simply be
5495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * copied and put under another distribution licence
5595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * [including the GNU Public Licence.] */
5695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
5795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/cipher.h>
5895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
5995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <string.h>
6095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <assert.h>
6195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/err.h>
6395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/mem.h>
6495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/obj.h>
6595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "internal.h"
6795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyconst EVP_CIPHER *EVP_get_cipherbynid(int nid) {
7095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  switch (nid) {
7195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case NID_des_ede3_cbc:
7295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return EVP_des_ede3_cbc();
7395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case NID_des_ede_cbc:
7495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return EVP_des_cbc();
7595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case NID_aes_128_cbc:
7695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return EVP_aes_128_cbc();
7795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    case NID_aes_256_cbc:
7895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return EVP_aes_256_cbc();
7995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    default:
8095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return NULL;
8195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
8295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
8395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
8495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx) {
8595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  memset(ctx, 0, sizeof(EVP_CIPHER_CTX));
8695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
8795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
8895c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyEVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void) {
8995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  EVP_CIPHER_CTX *ctx = OPENSSL_malloc(sizeof(EVP_CIPHER_CTX));
9095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx) {
9195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    EVP_CIPHER_CTX_init(ctx);
9295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
9395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return ctx;
9495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
9595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
9695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
9795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                   const unsigned char *key, const unsigned char *iv, int enc) {
9895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (cipher) {
9995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    EVP_CIPHER_CTX_init(ctx);
10095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
10195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc);
10295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
10395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
10495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c) {
10595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (c->cipher != NULL && c->cipher->cleanup && !c->cipher->cleanup(c)) {
10695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 0;
10795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
10895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
10995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (c->cipher_data) {
11095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size);
11195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    OPENSSL_free(c->cipher_data);
11295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
11395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
11495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  memset(c, 0, sizeof(EVP_CIPHER_CTX));
11595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return 1;
11695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
11795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
11895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) {
11995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx) {
12095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    EVP_CIPHER_CTX_cleanup(ctx);
12195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    OPENSSL_free(ctx);
12295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
12395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
12495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) {
12695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (in == NULL || in->cipher == NULL) {
12795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    OPENSSL_PUT_ERROR(CIPHER, EVP_CIPHER_CTX_copy, CIPHER_R_INPUT_NOT_INITIALIZED);
12895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 0;
12995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
13095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
13195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  EVP_CIPHER_CTX_cleanup(out);
13295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  memcpy(out, in, sizeof(EVP_CIPHER_CTX));
13395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
13495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (in->cipher_data && in->cipher->ctx_size) {
13595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size);
13695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (!out->cipher_data) {
13795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      OPENSSL_PUT_ERROR(CIPHER, EVP_CIPHER_CTX_copy, ERR_R_MALLOC_FAILURE);
13895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
13995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
14095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size);
14195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
14295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
1437578f3f0dea091a3392f0be3216989bdc7355ad2Adam Langley  if (in->cipher->flags & EVP_CIPH_CUSTOM_COPY) {
1447578f3f0dea091a3392f0be3216989bdc7355ad2Adam Langley    return in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out);
1457578f3f0dea091a3392f0be3216989bdc7355ad2Adam Langley  }
1467578f3f0dea091a3392f0be3216989bdc7355ad2Adam Langley
14795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return 1;
14895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
14995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
15095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
15195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                      ENGINE *engine, const uint8_t *key, const uint8_t *iv,
15295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                      int enc) {
15395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (enc == -1) {
15495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    enc = ctx->encrypt;
15595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  } else {
15695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (enc) {
15795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      enc = 1;
15895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
15995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ctx->encrypt = enc;
16095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
16195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
16295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (cipher) {
16395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    /* Ensure a context left from last time is cleared (the previous check
16495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley     * attempted to avoid this if the same ENGINE and EVP_CIPHER could be
16595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley     * used). */
16695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (ctx->cipher) {
16795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      EVP_CIPHER_CTX_cleanup(ctx);
16895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      /* Restore encrypt and flags */
16995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      ctx->encrypt = enc;
17095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
17195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
17295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ctx->cipher = cipher;
17395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (ctx->cipher->ctx_size) {
17495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      ctx->cipher_data = OPENSSL_malloc(ctx->cipher->ctx_size);
17595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (!ctx->cipher_data) {
17695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        OPENSSL_PUT_ERROR(CIPHER, EVP_CipherInit_ex, ERR_R_MALLOC_FAILURE);
17795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        return 0;
17895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
17995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    } else {
18095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      ctx->cipher_data = NULL;
18195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
18295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
18395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ctx->key_len = cipher->key_len;
18495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ctx->flags = 0;
18595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
18695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (ctx->cipher->flags & EVP_CIPH_CTRL_INIT) {
18795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) {
18895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        OPENSSL_PUT_ERROR(CIPHER, EVP_CipherInit_ex, CIPHER_R_INITIALIZATION_ERROR);
18995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        return 0;
19095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
19195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
19295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  } else if (!ctx->cipher) {
19395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    OPENSSL_PUT_ERROR(CIPHER, EVP_CipherInit_ex, CIPHER_R_NO_CIPHER_SET);
19495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 0;
19595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
19695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
19795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  /* we assume block size is a power of 2 in *cryptUpdate */
19895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  assert(ctx->cipher->block_size == 1 || ctx->cipher->block_size == 8 ||
19995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley         ctx->cipher->block_size == 16);
20095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
20195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) {
20295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    switch (EVP_CIPHER_CTX_mode(ctx)) {
20395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      case EVP_CIPH_STREAM_CIPHER:
20495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      case EVP_CIPH_ECB_MODE:
20595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        break;
20695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
20795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      case EVP_CIPH_CFB_MODE:
20895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      case EVP_CIPH_OFB_MODE:
20995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        ctx->num = 0;
21095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        /* fall-through */
21195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
21295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      case EVP_CIPH_CBC_MODE:
21395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        assert(EVP_CIPHER_CTX_iv_length(ctx) <= sizeof(ctx->iv));
21495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        if (iv) {
21595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley          memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
21695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        }
21795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
21895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        break;
21995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
22095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      case EVP_CIPH_CTR_MODE:
22195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        ctx->num = 0;
22295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        /* Don't reuse IV for CTR mode */
22395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        if (iv) {
22495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley          memcpy(ctx->iv, iv, EVP_CIPHER_CTX_iv_length(ctx));
22595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        }
22695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        break;
22795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
22895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      default:
22995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        return 0;
23095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
23195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
23295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
23395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) {
23495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (!ctx->cipher->init(ctx, key, iv, enc)) {
23595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
23695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
23795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
23895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
23995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->buf_len = 0;
24095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->final_used = 0;
24195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->block_mask = ctx->cipher->block_size - 1;
24295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return 1;
24395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
24495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
24595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
24695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                       ENGINE *impl, const uint8_t *key, const uint8_t *iv) {
24795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 1);
24895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
24995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
25095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
25195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                       ENGINE *impl, const uint8_t *key, const uint8_t *iv) {
25295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 0);
25395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
25495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
25595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len,
25695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                      const uint8_t *in, int in_len) {
25795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  int i, j, bl;
25895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
25995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
26095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    i = ctx->cipher->cipher(ctx, out, in, in_len);
26195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (i < 0) {
26295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
26395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    } else {
26495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *out_len = i;
26595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
26695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 1;
26795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
26895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
26995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (in_len <= 0) {
27095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *out_len = 0;
27195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return in_len == 0;
27295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
27395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
27495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx->buf_len == 0 && (in_len & ctx->block_mask) == 0) {
27595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (ctx->cipher->cipher(ctx, out, in, in_len)) {
27695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *out_len = in_len;
27795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 1;
27895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    } else {
27995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *out_len = 0;
28095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
28195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
28295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
28395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
28495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  i = ctx->buf_len;
28595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  bl = ctx->cipher->block_size;
28695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  assert(bl <= (int)sizeof(ctx->buf));
28795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (i != 0) {
28895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (i + in_len < bl) {
28995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      memcpy(&ctx->buf[i], in, in_len);
29095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      ctx->buf_len += in_len;
29195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *out_len = 0;
29295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 1;
29395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    } else {
29495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      j = bl - i;
29595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      memcpy(&ctx->buf[i], in, j);
29695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (!ctx->cipher->cipher(ctx, out, ctx->buf, bl)) {
29795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        return 0;
29895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
29995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      in_len -= j;
30095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      in += j;
30195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      out += bl;
30295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *out_len = bl;
30395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
30495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  } else {
30595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *out_len = 0;
30695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
30795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
30895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  i = in_len & ctx->block_mask;
30995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  in_len -= i;
31095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (in_len > 0) {
31195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (!ctx->cipher->cipher(ctx, out, in, in_len)) {
31295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
31395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
31495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *out_len += in_len;
31595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
31695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
31795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (i != 0) {
31895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    memcpy(ctx->buf, &in[in_len], i);
31995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
32095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->buf_len = i;
32195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return 1;
32295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
32395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
32495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) {
32595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  int n, ret;
32695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  unsigned int i, b, bl;
32795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
32895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
32995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ret = ctx->cipher->cipher(ctx, out, NULL, 0);
33095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (ret < 0) {
33195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
33295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    } else {
33395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *out_len = ret;
33495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
33595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 1;
33695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
33795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
33895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  b = ctx->cipher->block_size;
33995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  assert(b <= sizeof(ctx->buf));
34095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (b == 1) {
34195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *out_len = 0;
34295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 1;
34395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
34495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
34595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  bl = ctx->buf_len;
34695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx->flags & EVP_CIPH_NO_PADDING) {
34795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (bl) {
34895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      OPENSSL_PUT_ERROR(CIPHER, EVP_EncryptFinal_ex,
34995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                        CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
35095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
35195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
35295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *out_len = 0;
35395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 1;
35495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
35595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
35695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  n = b - bl;
35795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  for (i = bl; i < b; i++) {
35895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ctx->buf[i] = n;
35995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
36095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ret = ctx->cipher->cipher(ctx, out, ctx->buf, b);
36195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
36295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ret) {
36395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *out_len = b;
36495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
36595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
36695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return ret;
36795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
36895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
36995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len,
37095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                      const uint8_t *in, int in_len) {
37195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  int fix_len;
37295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  unsigned int b;
37395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
37495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
37595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    int r = ctx->cipher->cipher(ctx, out, in, in_len);
37695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (r < 0) {
37795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *out_len = 0;
37895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
37995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    } else {
38095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *out_len = r;
38195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
38295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 1;
38395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
38495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
38595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (in_len <= 0) {
38695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *out_len = 0;
38795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return in_len == 0;
38895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
38995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
39095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx->flags & EVP_CIPH_NO_PADDING) {
39195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return EVP_EncryptUpdate(ctx, out, out_len, in, in_len);
39295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
39395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
39495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  b = ctx->cipher->block_size;
39595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  assert(b <= sizeof(ctx->final));
39695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
39795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx->final_used) {
39895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    memcpy(out, ctx->final, b);
39995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    out += b;
40095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    fix_len = 1;
40195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  } else {
40295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    fix_len = 0;
40395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
40495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
40595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!EVP_EncryptUpdate(ctx, out, out_len, in, in_len)) {
40695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 0;
40795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
40895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
40995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  /* if we have 'decrypted' a multiple of block size, make sure
41095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley   * we have a copy of this last block */
41195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (b > 1 && !ctx->buf_len) {
41295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *out_len -= b;
41395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ctx->final_used = 1;
41495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    memcpy(ctx->final, &out[*out_len], b);
41595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  } else {
41695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ctx->final_used = 0;
41795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
41895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
41995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (fix_len) {
42095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *out_len += b;
42195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
42295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
42395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return 1;
42495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
42595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
42695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len) {
42795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  int i, n;
42895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  unsigned int b;
42995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  *out_len = 0;
43095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
43195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
43295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    i = ctx->cipher->cipher(ctx, out, NULL, 0);
43395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (i < 0) {
43495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
43595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    } else {
43695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *out_len = i;
43795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
43895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 1;
43995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
44095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
44195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  b = ctx->cipher->block_size;
44295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx->flags & EVP_CIPH_NO_PADDING) {
44395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (ctx->buf_len) {
44495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      OPENSSL_PUT_ERROR(CIPHER, EVP_DecryptFinal_ex,
44595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                        CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
44695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
44795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
44895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *out_len = 0;
44995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 1;
45095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
45195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
45295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (b > 1) {
45395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (ctx->buf_len || !ctx->final_used) {
45495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      OPENSSL_PUT_ERROR(CIPHER, EVP_DecryptFinal_ex,
45595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                        CIPHER_R_WRONG_FINAL_BLOCK_LENGTH);
45695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
45795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
45895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    assert(b <= sizeof(ctx->final));
45995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
46095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    /* The following assumes that the ciphertext has been authenticated.
46195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley     * Otherwise it provides a padding oracle. */
46295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    n = ctx->final[b - 1];
46395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (n == 0 || n > (int)b) {
46495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      OPENSSL_PUT_ERROR(CIPHER, EVP_DecryptFinal_ex, CIPHER_R_BAD_DECRYPT);
46595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
46695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
46795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
46895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    for (i = 0; i < n; i++) {
46995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (ctx->final[--b] != n) {
47095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        OPENSSL_PUT_ERROR(CIPHER, EVP_DecryptFinal_ex, CIPHER_R_BAD_DECRYPT);
47195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        return 0;
47295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
47395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
47495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
47595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    n = ctx->cipher->block_size - n;
47695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    for (i = 0; i < n; i++) {
47795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      out[i] = ctx->final[i];
47895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
47995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *out_len = n;
48095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  } else {
48195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *out_len = 0;
48295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
48395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
48495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return 1;
48595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
48695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
48795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_Cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
48895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley               size_t in_len) {
48995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return ctx->cipher->cipher(ctx, out, in, in_len);
49095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
49195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
49295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len,
49395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                     const uint8_t *in, int in_len) {
49495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx->encrypt) {
49595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return EVP_EncryptUpdate(ctx, out, out_len, in, in_len);
49695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  } else {
49795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return EVP_DecryptUpdate(ctx, out, out_len, in, in_len);
49895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
49995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
50095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
50195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) {
50295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx->encrypt) {
50395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return EVP_EncryptFinal_ex(ctx, out, out_len);
50495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  } else {
50595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return EVP_DecryptFinal_ex(ctx, out, out_len);
50695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
50795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
50895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
50995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyconst EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx) {
51095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return ctx->cipher;
51195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
51295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
51395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx) {
51495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return ctx->cipher->nid;
51595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
51695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
51795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyunsigned EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx) {
51895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return ctx->cipher->block_size;
51995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
52095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
52195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyunsigned EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx) {
52295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return ctx->key_len;
52395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
52495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
52595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyunsigned EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx) {
52695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return ctx->cipher->iv_len;
52795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
52895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
52995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx) {
53095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return ctx->app_data;
53195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
53295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
53395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data) {
53495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ctx->app_data = data;
53595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
53695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
53795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyuint32_t EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx) {
53895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return ctx->cipher->flags & ~EVP_CIPH_MODE_MASK;
53995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
54095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
54195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyuint32_t EVP_CIPHER_CTX_mode(const EVP_CIPHER_CTX *ctx) {
54295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return ctx->cipher->flags & EVP_CIPH_MODE_MASK;
54395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
54495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
54595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int command, int arg, void *ptr) {
54695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  int ret;
54795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!ctx->cipher) {
54895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    OPENSSL_PUT_ERROR(CIPHER, EVP_CIPHER_CTX_ctrl, CIPHER_R_NO_CIPHER_SET);
54995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 0;
55095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
55195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
55295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!ctx->cipher->ctrl) {
55395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    OPENSSL_PUT_ERROR(CIPHER, EVP_CIPHER_CTX_ctrl, CIPHER_R_CTRL_NOT_IMPLEMENTED);
55495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 0;
55595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
55695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
55795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ret = ctx->cipher->ctrl(ctx, command, arg, ptr);
55895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ret == -1) {
55995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    OPENSSL_PUT_ERROR(CIPHER, EVP_CIPHER_CTX_ctrl,
56095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                      CIPHER_R_CTRL_OPERATION_NOT_IMPLEMENTED);
56195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 0;
56295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
56395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
56495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return ret;
56595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
56695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
56795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad) {
56895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (pad) {
56995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ctx->flags &= ~EVP_CIPH_NO_PADDING;
57095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  } else {
57195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ctx->flags |= EVP_CIPH_NO_PADDING;
57295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
57395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return 1;
57495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
57595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
576539112fd4447ba9a2c6f669edd16129d824b8b34Adam Langleyint EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, unsigned key_len) {
577539112fd4447ba9a2c6f669edd16129d824b8b34Adam Langley  if (c->key_len == key_len) {
578539112fd4447ba9a2c6f669edd16129d824b8b34Adam Langley    return 1;
579539112fd4447ba9a2c6f669edd16129d824b8b34Adam Langley  }
580539112fd4447ba9a2c6f669edd16129d824b8b34Adam Langley
581539112fd4447ba9a2c6f669edd16129d824b8b34Adam Langley  if (key_len == 0 || !(c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH)) {
582539112fd4447ba9a2c6f669edd16129d824b8b34Adam Langley    OPENSSL_PUT_ERROR(CIPHER, EVP_CIPHER_CTX_set_key_length,
583539112fd4447ba9a2c6f669edd16129d824b8b34Adam Langley                      CIPHER_R_INVALID_KEY_LENGTH);
584539112fd4447ba9a2c6f669edd16129d824b8b34Adam Langley    return 0;
585539112fd4447ba9a2c6f669edd16129d824b8b34Adam Langley  }
586539112fd4447ba9a2c6f669edd16129d824b8b34Adam Langley
587539112fd4447ba9a2c6f669edd16129d824b8b34Adam Langley  c->key_len = key_len;
588539112fd4447ba9a2c6f669edd16129d824b8b34Adam Langley  return 1;
589539112fd4447ba9a2c6f669edd16129d824b8b34Adam Langley}
590539112fd4447ba9a2c6f669edd16129d824b8b34Adam Langley
59195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint EVP_CIPHER_nid(const EVP_CIPHER *cipher) { return cipher->nid; }
59295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
59395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyconst char *EVP_CIPHER_name(const EVP_CIPHER *cipher) {
59495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return OBJ_nid2sn(cipher->nid);
59595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
59695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
59795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyunsigned EVP_CIPHER_block_size(const EVP_CIPHER *cipher) {
59895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return cipher->block_size;
59995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
60095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
60195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyunsigned EVP_CIPHER_key_length(const EVP_CIPHER *cipher) {
60295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return cipher->key_len;
60395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
60495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
60595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyunsigned EVP_CIPHER_iv_length(const EVP_CIPHER *cipher) {
60695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return cipher->iv_len;
60795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
60895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
60995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyuint32_t EVP_CIPHER_flags(const EVP_CIPHER *cipher) {
61095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return cipher->flags & ~EVP_CIPH_MODE_MASK;
61195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
61295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
61395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyuint32_t EVP_CIPHER_mode(const EVP_CIPHER *cipher) {
61495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return cipher->flags & EVP_CIPH_MODE_MASK;
61595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
616