Remove non-AEAD crypto/cipher interface.
This commit is contained in:
parent
9e6f673f59
commit
e91d7c3c73
@ -18,7 +18,6 @@
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "cipher.h"
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
@ -1,590 +0,0 @@
|
||||
/* 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 "cipher.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx) {
|
||||
memset(ctx, 0, sizeof(EVP_CIPHER_CTX));
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void) {
|
||||
EVP_CIPHER_CTX *ctx = OPENSSL_malloc(sizeof(EVP_CIPHER_CTX));
|
||||
if (ctx) {
|
||||
EVP_CIPHER_CTX_init(ctx);
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c) {
|
||||
if (c->cipher != NULL) {
|
||||
if (c->cipher->cleanup) {
|
||||
c->cipher->cleanup(c);
|
||||
}
|
||||
OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size);
|
||||
}
|
||||
OPENSSL_free(c->cipher_data);
|
||||
|
||||
memset(c, 0, sizeof(EVP_CIPHER_CTX));
|
||||
return 1;
|
||||
}
|
||||
|
||||
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) {
|
||||
if (ctx) {
|
||||
EVP_CIPHER_CTX_cleanup(ctx);
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) {
|
||||
if (in == NULL || in->cipher == NULL) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INPUT_NOT_INITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_cleanup(out);
|
||||
memcpy(out, in, sizeof(EVP_CIPHER_CTX));
|
||||
|
||||
if (in->cipher_data && in->cipher->ctx_size) {
|
||||
out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size);
|
||||
if (!out->cipher_data) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, 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) {
|
||||
return in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
ENGINE *engine, const uint8_t *key, const uint8_t *iv,
|
||||
int enc) {
|
||||
if (enc == -1) {
|
||||
enc = ctx->encrypt;
|
||||
} else {
|
||||
if (enc) {
|
||||
enc = 1;
|
||||
}
|
||||
ctx->encrypt = enc;
|
||||
}
|
||||
|
||||
if (cipher) {
|
||||
/* Ensure a context left from last time is cleared (the previous check
|
||||
* attempted to avoid this if the same ENGINE and EVP_CIPHER could be
|
||||
* used). */
|
||||
if (ctx->cipher) {
|
||||
EVP_CIPHER_CTX_cleanup(ctx);
|
||||
/* Restore encrypt and flags */
|
||||
ctx->encrypt = enc;
|
||||
}
|
||||
|
||||
ctx->cipher = cipher;
|
||||
if (ctx->cipher->ctx_size) {
|
||||
ctx->cipher_data = OPENSSL_malloc(ctx->cipher->ctx_size);
|
||||
if (!ctx->cipher_data) {
|
||||
ctx->cipher = NULL;
|
||||
OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ctx->cipher_data = NULL;
|
||||
}
|
||||
|
||||
ctx->key_len = cipher->key_len;
|
||||
ctx->flags = 0;
|
||||
|
||||
if (ctx->cipher->flags & EVP_CIPH_CTRL_INIT) {
|
||||
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) {
|
||||
ctx->cipher = NULL;
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INITIALIZATION_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if (!ctx->cipher) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_NO_CIPHER_SET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* we assume block size is a power of 2 in *cryptUpdate */
|
||||
assert(ctx->cipher->block_size == 1 || ctx->cipher->block_size == 8 ||
|
||||
ctx->cipher->block_size == 16);
|
||||
|
||||
if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) {
|
||||
switch (EVP_CIPHER_CTX_mode(ctx)) {
|
||||
case EVP_CIPH_STREAM_CIPHER:
|
||||
break;
|
||||
|
||||
case EVP_CIPH_CBC_MODE:
|
||||
assert(EVP_CIPHER_CTX_iv_length(ctx) <= sizeof(ctx->iv));
|
||||
if (iv) {
|
||||
memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
|
||||
}
|
||||
memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
|
||||
break;
|
||||
|
||||
case EVP_CIPH_CTR_MODE:
|
||||
ctx->num = 0;
|
||||
/* Don't reuse IV for CTR mode */
|
||||
if (iv) {
|
||||
memcpy(ctx->iv, iv, EVP_CIPHER_CTX_iv_length(ctx));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) {
|
||||
if (!ctx->cipher->init(ctx, key, iv, enc)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->buf_len = 0;
|
||||
ctx->final_used = 0;
|
||||
ctx->block_mask = ctx->cipher->block_size - 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
ENGINE *impl, const uint8_t *key, const uint8_t *iv) {
|
||||
return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 1);
|
||||
}
|
||||
|
||||
int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
ENGINE *impl, const uint8_t *key, const uint8_t *iv) {
|
||||
return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 0);
|
||||
}
|
||||
|
||||
int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len,
|
||||
const uint8_t *in, int in_len) {
|
||||
int i, j, bl;
|
||||
|
||||
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
|
||||
i = ctx->cipher->cipher(ctx, out, in, in_len);
|
||||
if (i < 0) {
|
||||
return 0;
|
||||
} else {
|
||||
*out_len = i;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (in_len <= 0) {
|
||||
*out_len = 0;
|
||||
return in_len == 0;
|
||||
}
|
||||
|
||||
if (ctx->buf_len == 0 && (in_len & ctx->block_mask) == 0) {
|
||||
if (ctx->cipher->cipher(ctx, out, in, in_len)) {
|
||||
*out_len = in_len;
|
||||
return 1;
|
||||
} else {
|
||||
*out_len = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
i = ctx->buf_len;
|
||||
bl = ctx->cipher->block_size;
|
||||
assert(bl <= (int)sizeof(ctx->buf));
|
||||
if (i != 0) {
|
||||
if (i + in_len < bl) {
|
||||
memcpy(&ctx->buf[i], in, in_len);
|
||||
ctx->buf_len += in_len;
|
||||
*out_len = 0;
|
||||
return 1;
|
||||
} else {
|
||||
j = bl - i;
|
||||
memcpy(&ctx->buf[i], in, j);
|
||||
if (!ctx->cipher->cipher(ctx, out, ctx->buf, bl)) {
|
||||
return 0;
|
||||
}
|
||||
in_len -= j;
|
||||
in += j;
|
||||
out += bl;
|
||||
*out_len = bl;
|
||||
}
|
||||
} else {
|
||||
*out_len = 0;
|
||||
}
|
||||
|
||||
i = in_len & ctx->block_mask;
|
||||
in_len -= i;
|
||||
if (in_len > 0) {
|
||||
if (!ctx->cipher->cipher(ctx, out, in, in_len)) {
|
||||
return 0;
|
||||
}
|
||||
*out_len += in_len;
|
||||
}
|
||||
|
||||
if (i != 0) {
|
||||
memcpy(ctx->buf, &in[in_len], i);
|
||||
}
|
||||
ctx->buf_len = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) {
|
||||
int n, ret;
|
||||
unsigned int i, b, bl;
|
||||
|
||||
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
|
||||
ret = ctx->cipher->cipher(ctx, out, NULL, 0);
|
||||
if (ret < 0) {
|
||||
return 0;
|
||||
} else {
|
||||
*out_len = ret;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
b = ctx->cipher->block_size;
|
||||
assert(b <= sizeof(ctx->buf));
|
||||
if (b == 1) {
|
||||
*out_len = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bl = ctx->buf_len;
|
||||
if (ctx->flags & EVP_CIPH_NO_PADDING) {
|
||||
if (bl) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
*out_len = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
n = b - bl;
|
||||
for (i = bl; i < b; i++) {
|
||||
ctx->buf[i] = n;
|
||||
}
|
||||
ret = ctx->cipher->cipher(ctx, out, ctx->buf, b);
|
||||
|
||||
if (ret) {
|
||||
*out_len = b;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len,
|
||||
const uint8_t *in, int in_len) {
|
||||
int fix_len;
|
||||
unsigned int b;
|
||||
|
||||
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
|
||||
int r = ctx->cipher->cipher(ctx, out, in, in_len);
|
||||
if (r < 0) {
|
||||
*out_len = 0;
|
||||
return 0;
|
||||
} else {
|
||||
*out_len = r;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (in_len <= 0) {
|
||||
*out_len = 0;
|
||||
return in_len == 0;
|
||||
}
|
||||
|
||||
if (ctx->flags & EVP_CIPH_NO_PADDING) {
|
||||
return EVP_EncryptUpdate(ctx, out, out_len, in, in_len);
|
||||
}
|
||||
|
||||
b = ctx->cipher->block_size;
|
||||
assert(b <= sizeof(ctx->final));
|
||||
|
||||
if (ctx->final_used) {
|
||||
memcpy(out, ctx->final, b);
|
||||
out += b;
|
||||
fix_len = 1;
|
||||
} else {
|
||||
fix_len = 0;
|
||||
}
|
||||
|
||||
if (!EVP_EncryptUpdate(ctx, out, out_len, in, in_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if we have 'decrypted' a multiple of block size, make sure
|
||||
* we have a copy of this last block */
|
||||
if (b > 1 && !ctx->buf_len) {
|
||||
*out_len -= b;
|
||||
ctx->final_used = 1;
|
||||
memcpy(ctx->final, &out[*out_len], b);
|
||||
} else {
|
||||
ctx->final_used = 0;
|
||||
}
|
||||
|
||||
if (fix_len) {
|
||||
*out_len += b;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *out_len) {
|
||||
int i, n;
|
||||
unsigned int b;
|
||||
*out_len = 0;
|
||||
|
||||
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
|
||||
i = ctx->cipher->cipher(ctx, out, NULL, 0);
|
||||
if (i < 0) {
|
||||
return 0;
|
||||
} else {
|
||||
*out_len = i;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
b = ctx->cipher->block_size;
|
||||
if (ctx->flags & EVP_CIPH_NO_PADDING) {
|
||||
if (ctx->buf_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
*out_len = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (b > 1) {
|
||||
if (ctx->buf_len || !ctx->final_used) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_WRONG_FINAL_BLOCK_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
assert(b <= sizeof(ctx->final));
|
||||
|
||||
/* The following assumes that the ciphertext has been authenticated.
|
||||
* Otherwise it provides a padding oracle. */
|
||||
n = ctx->final[b - 1];
|
||||
if (n == 0 || n > (int)b) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (ctx->final[--b] != n) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
n = ctx->cipher->block_size - n;
|
||||
for (i = 0; i < n; i++) {
|
||||
out[i] = ctx->final[i];
|
||||
}
|
||||
*out_len = n;
|
||||
} else {
|
||||
*out_len = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_Cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
|
||||
size_t in_len) {
|
||||
return ctx->cipher->cipher(ctx, out, in, in_len);
|
||||
}
|
||||
|
||||
int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len,
|
||||
const uint8_t *in, int in_len) {
|
||||
if (ctx->encrypt) {
|
||||
return EVP_EncryptUpdate(ctx, out, out_len, in, in_len);
|
||||
} else {
|
||||
return EVP_DecryptUpdate(ctx, out, out_len, in, in_len);
|
||||
}
|
||||
}
|
||||
|
||||
int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out, int *out_len) {
|
||||
if (ctx->encrypt) {
|
||||
return EVP_EncryptFinal_ex(ctx, out, out_len);
|
||||
} else {
|
||||
return EVP_DecryptFinal_ex(ctx, out, out_len);
|
||||
}
|
||||
}
|
||||
|
||||
const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx) {
|
||||
return ctx->cipher;
|
||||
}
|
||||
|
||||
unsigned EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx) {
|
||||
return ctx->cipher->block_size;
|
||||
}
|
||||
|
||||
unsigned EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx) {
|
||||
return ctx->key_len;
|
||||
}
|
||||
|
||||
unsigned EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx) {
|
||||
return ctx->cipher->iv_len;
|
||||
}
|
||||
|
||||
void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx) {
|
||||
return ctx->app_data;
|
||||
}
|
||||
|
||||
void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data) {
|
||||
ctx->app_data = data;
|
||||
}
|
||||
|
||||
uint32_t EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx) {
|
||||
return ctx->cipher->flags & ~EVP_CIPH_MODE_MASK;
|
||||
}
|
||||
|
||||
uint32_t EVP_CIPHER_CTX_mode(const EVP_CIPHER_CTX *ctx) {
|
||||
return ctx->cipher->flags & EVP_CIPH_MODE_MASK;
|
||||
}
|
||||
|
||||
int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int command, int arg, void *ptr) {
|
||||
int ret;
|
||||
if (!ctx->cipher) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_NO_CIPHER_SET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ctx->cipher->ctrl) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_CTRL_NOT_IMPLEMENTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = ctx->cipher->ctrl(ctx, command, arg, ptr);
|
||||
if (ret == -1) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_CTRL_OPERATION_NOT_IMPLEMENTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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_set_key_length(EVP_CIPHER_CTX *c, unsigned key_len) {
|
||||
if (c->key_len == key_len) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (key_len == 0 || !(c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_KEY_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
c->key_len = key_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned EVP_CIPHER_block_size(const EVP_CIPHER *cipher) {
|
||||
return cipher->block_size;
|
||||
}
|
||||
|
||||
unsigned EVP_CIPHER_key_length(const EVP_CIPHER *cipher) {
|
||||
return cipher->key_len;
|
||||
}
|
||||
|
||||
unsigned EVP_CIPHER_iv_length(const EVP_CIPHER *cipher) {
|
||||
return cipher->iv_len;
|
||||
}
|
||||
|
||||
uint32_t EVP_CIPHER_flags(const EVP_CIPHER *cipher) {
|
||||
return cipher->flags & ~EVP_CIPH_MODE_MASK;
|
||||
}
|
||||
|
||||
uint32_t EVP_CIPHER_mode(const EVP_CIPHER *cipher) {
|
||||
return cipher->flags & EVP_CIPH_MODE_MASK;
|
||||
}
|
||||
|
||||
int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
const uint8_t *key, const uint8_t *iv, int enc) {
|
||||
if (cipher) {
|
||||
EVP_CIPHER_CTX_init(ctx);
|
||||
}
|
||||
return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc);
|
||||
}
|
||||
|
||||
int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
const uint8_t *key, const uint8_t *iv) {
|
||||
return EVP_CipherInit(ctx, cipher, key, iv, 1);
|
||||
}
|
||||
|
||||
int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
const uint8_t *key, const uint8_t *iv) {
|
||||
return EVP_CipherInit(ctx, cipher, key, iv, 0);
|
||||
}
|
@ -1,479 +0,0 @@
|
||||
/* 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.] */
|
||||
|
||||
#ifndef OPENSSL_HEADER_CIPHER_H
|
||||
#define OPENSSL_HEADER_CIPHER_H
|
||||
|
||||
#include <openssl/base.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Ciphers. */
|
||||
|
||||
|
||||
/* Cipher primitives.
|
||||
*
|
||||
* The following functions return |EVP_CIPHER| objects that implement the named
|
||||
* cipher algorithm. */
|
||||
|
||||
OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_cbc(void);
|
||||
OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_128_ctr(void);
|
||||
|
||||
OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_cbc(void);
|
||||
OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_ctr(void);
|
||||
|
||||
/* Cipher context allocation.
|
||||
*
|
||||
* An |EVP_CIPHER_CTX| represents the state of an encryption or decryption in
|
||||
* progress. */
|
||||
|
||||
/* EVP_CIPHER_CTX_init initialises an, already allocated, |EVP_CIPHER_CTX|. */
|
||||
OPENSSL_EXPORT void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx);
|
||||
|
||||
/* EVP_CIPHER_CTX_new allocates a fresh |EVP_CIPHER_CTX|, calls
|
||||
* |EVP_CIPHER_CTX_init| and returns it, or NULL on allocation failure. */
|
||||
OPENSSL_EXPORT EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
|
||||
|
||||
/* EVP_CIPHER_CTX_cleanup frees any memory referenced by |ctx|. It returns
|
||||
* one. */
|
||||
OPENSSL_EXPORT int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *ctx);
|
||||
|
||||
/* EVP_CIPHER_CTX_free calls |EVP_CIPHER_CTX_cleanup| on |ctx| and then frees
|
||||
* |ctx| itself. */
|
||||
OPENSSL_EXPORT void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx);
|
||||
|
||||
/* EVP_CIPHER_CTX_copy sets |out| to be a duplicate of the current state of
|
||||
* |in|. The |out| argument must have been previously initialised. */
|
||||
OPENSSL_EXPORT int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out,
|
||||
const EVP_CIPHER_CTX *in);
|
||||
|
||||
|
||||
/* Cipher context configuration. */
|
||||
|
||||
/* EVP_CipherInit_ex configures |ctx| for a fresh encryption (or decryption, if
|
||||
* |enc| is zero) operation using |cipher|. If |ctx| has been previously
|
||||
* configured with a cipher then |cipher|, |key| and |iv| may be |NULL| and
|
||||
* |enc| may be -1 to reuse the previous values. The operation will use |key|
|
||||
* as the key and |iv| as the IV (if any). These should have the correct
|
||||
* lengths given by |EVP_CIPHER_key_length| and |EVP_CIPHER_iv_length|. It
|
||||
* returns one on success and zero on error. */
|
||||
OPENSSL_EXPORT int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx,
|
||||
const EVP_CIPHER *cipher, ENGINE *engine,
|
||||
const uint8_t *key, const uint8_t *iv,
|
||||
int enc);
|
||||
|
||||
/* EVP_EncryptInit_ex calls |EVP_CipherInit_ex| with |enc| equal to one. */
|
||||
OPENSSL_EXPORT int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,
|
||||
const EVP_CIPHER *cipher, ENGINE *impl,
|
||||
const uint8_t *key, const uint8_t *iv);
|
||||
|
||||
/* EVP_DecryptInit_ex calls |EVP_CipherInit_ex| with |enc| equal to zero. */
|
||||
OPENSSL_EXPORT int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx,
|
||||
const EVP_CIPHER *cipher, ENGINE *impl,
|
||||
const uint8_t *key, const uint8_t *iv);
|
||||
|
||||
|
||||
/* Cipher operations. */
|
||||
|
||||
/* EVP_EncryptUpdate encrypts |in_len| bytes from |in| to |out|. The number
|
||||
* of output bytes may be up to |in_len| plus the block length minus one and
|
||||
* |out| must have sufficient space. The number of bytes actually output is
|
||||
* written to |*out_len|. It returns one on success and zero otherwise. */
|
||||
OPENSSL_EXPORT int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out,
|
||||
int *out_len, const uint8_t *in,
|
||||
int in_len);
|
||||
|
||||
/* EVP_EncryptFinal_ex writes at most a block of ciphertext to |out| and sets
|
||||
* |*out_len| to the number of bytes written. If padding is enabled (the
|
||||
* default) then standard padding is applied to create the final block. If
|
||||
* padding is disabled (with |EVP_CIPHER_CTX_set_padding|) then any partial
|
||||
* block remaining will cause an error. The function returns one on success and
|
||||
* zero otherwise. */
|
||||
OPENSSL_EXPORT int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out,
|
||||
int *out_len);
|
||||
|
||||
/* EVP_DecryptUpdate decrypts |in_len| bytes from |in| to |out|. The number of
|
||||
* output bytes may be up to |in_len| plus the block length minus one and |out|
|
||||
* must have sufficient space. The number of bytes actually output is written
|
||||
* to |*out_len|. It returns one on success and zero otherwise. */
|
||||
OPENSSL_EXPORT int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out,
|
||||
int *out_len, const uint8_t *in,
|
||||
int in_len);
|
||||
|
||||
/* EVP_DecryptFinal_ex writes at most a block of ciphertext to |out| and sets
|
||||
* |*out_len| to the number of bytes written. If padding is enabled (the
|
||||
* default) then padding is removed from the final block.
|
||||
*
|
||||
* WARNING: it is unsafe to call this function with unauthenticted
|
||||
* ciphertext if padding is enabled. */
|
||||
OPENSSL_EXPORT int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
int *out_len);
|
||||
|
||||
/* EVP_Cipher performs a one-shot encryption/decryption operation. No partial
|
||||
* blocks are maintained between calls. However, any internal cipher state is
|
||||
* still updated. For CBC-mode ciphers, the IV is updated to the final
|
||||
* ciphertext block. For stream ciphers, the stream is advanced past the bytes
|
||||
* used. It returns one on success and zero otherwise, unless |EVP_CIPHER_flags|
|
||||
* has |EVP_CIPH_FLAG_CUSTOM_CIPHER| set. Then it returns the number of bytes
|
||||
* written or -1 on error.
|
||||
*
|
||||
* WARNING: this differs from the usual return value convention when using
|
||||
* |EVP_CIPH_FLAG_CUSTOM_CIPHER|.
|
||||
*
|
||||
* TODO(davidben): The normal ciphers currently never fail, even if, e.g.,
|
||||
* |in_len| is not a multiple of the block size for CBC-mode decryption. The
|
||||
* input just gets rounded up while the output gets truncated. This should
|
||||
* either be officially documented or fail. */
|
||||
OPENSSL_EXPORT int EVP_Cipher(EVP_CIPHER_CTX *ctx, uint8_t *out,
|
||||
const uint8_t *in, size_t in_len);
|
||||
|
||||
/* EVP_CipherUpdate calls either |EVP_EncryptUpdate| or |EVP_DecryptUpdate|
|
||||
* depending on how |ctx| has been setup. */
|
||||
OPENSSL_EXPORT int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, uint8_t *out,
|
||||
int *out_len, const uint8_t *in,
|
||||
int in_len);
|
||||
|
||||
/* EVP_CipherFinal_ex calls either |EVP_EncryptFinal_ex| or
|
||||
* |EVP_DecryptFinal_ex| depending on how |ctx| has been setup. */
|
||||
OPENSSL_EXPORT int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, uint8_t *out,
|
||||
int *out_len);
|
||||
|
||||
|
||||
/* Cipher context accessors. */
|
||||
|
||||
/* EVP_CIPHER_CTX_cipher returns the |EVP_CIPHER| underlying |ctx|, or NULL if
|
||||
* none has been set. */
|
||||
OPENSSL_EXPORT const EVP_CIPHER *EVP_CIPHER_CTX_cipher(
|
||||
const EVP_CIPHER_CTX *ctx);
|
||||
|
||||
/* EVP_CIPHER_CTX_block_size returns the block size, in bytes, of the cipher
|
||||
* underlying |ctx|, or one if the cipher is a stream cipher. It will crash if
|
||||
* no cipher has been configured. */
|
||||
OPENSSL_EXPORT unsigned EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx);
|
||||
|
||||
/* EVP_CIPHER_CTX_key_length returns the key size, in bytes, of the cipher
|
||||
* underlying |ctx| or zero if no cipher has been configured. */
|
||||
OPENSSL_EXPORT unsigned EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx);
|
||||
|
||||
/* EVP_CIPHER_CTX_iv_length returns the IV size, in bytes, of the cipher
|
||||
* underlying |ctx|. It will crash if no cipher has been configured. */
|
||||
OPENSSL_EXPORT unsigned EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx);
|
||||
|
||||
/* EVP_CIPHER_CTX_get_app_data returns the opaque, application data pointer for
|
||||
* |ctx|, or NULL if none has been set. */
|
||||
OPENSSL_EXPORT void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx);
|
||||
|
||||
/* EVP_CIPHER_CTX_set_app_data sets the opaque, application data pointer for
|
||||
* |ctx| to |data|. */
|
||||
OPENSSL_EXPORT void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx,
|
||||
void *data);
|
||||
|
||||
/* EVP_CIPHER_CTX_flags returns a value which is the OR of zero or more
|
||||
* |EVP_CIPH_*| flags. It will crash if no cipher has been configured. */
|
||||
OPENSSL_EXPORT uint32_t EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx);
|
||||
|
||||
/* EVP_CIPHER_CTX_mode returns one of the |EVP_CIPH_*| cipher mode values
|
||||
* enumerated below. It will crash if no cipher has been configured. */
|
||||
OPENSSL_EXPORT uint32_t EVP_CIPHER_CTX_mode(const EVP_CIPHER_CTX *ctx);
|
||||
|
||||
/* EVP_CIPHER_CTX_ctrl is an |ioctl| like function. The |command| argument
|
||||
* should be one of the |EVP_CTRL_*| values. The |arg| and |ptr| arguments are
|
||||
* specific to the command in question. */
|
||||
OPENSSL_EXPORT int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int command,
|
||||
int arg, void *ptr);
|
||||
|
||||
/* EVP_CIPHER_CTX_set_padding sets whether padding is enabled for |ctx| and
|
||||
* returns one. Pass a non-zero |pad| to enable padding (the default) or zero
|
||||
* to disable. */
|
||||
OPENSSL_EXPORT int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad);
|
||||
|
||||
/* EVP_CIPHER_CTX_set_key_length sets the key length for |ctx|. This is only
|
||||
* valid for ciphers that can take a variable length key. It returns one on
|
||||
* success and zero on error. */
|
||||
OPENSSL_EXPORT int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *ctx, unsigned key_len);
|
||||
|
||||
|
||||
/* Cipher accessors. */
|
||||
|
||||
/* EVP_CIPHER_block_size returns the block size, in bytes, for |cipher|, or one
|
||||
* if |cipher| is a stream cipher. */
|
||||
OPENSSL_EXPORT unsigned EVP_CIPHER_block_size(const EVP_CIPHER *cipher);
|
||||
|
||||
/* EVP_CIPHER_key_length returns the key size, in bytes, for |cipher|. If
|
||||
* |cipher| can take a variable key length then this function returns the
|
||||
* default key length and |EVP_CIPHER_flags| will return a value with
|
||||
* |EVP_CIPH_VARIABLE_LENGTH| set. */
|
||||
OPENSSL_EXPORT unsigned EVP_CIPHER_key_length(const EVP_CIPHER *cipher);
|
||||
|
||||
/* EVP_CIPHER_iv_length returns the IV size, in bytes, of |cipher|, or zero if
|
||||
* |cipher| doesn't take an IV. */
|
||||
OPENSSL_EXPORT unsigned EVP_CIPHER_iv_length(const EVP_CIPHER *cipher);
|
||||
|
||||
/* EVP_CIPHER_flags returns a value which is the OR of zero or more
|
||||
* |EVP_CIPH_*| flags. */
|
||||
OPENSSL_EXPORT uint32_t EVP_CIPHER_flags(const EVP_CIPHER *cipher);
|
||||
|
||||
/* EVP_CIPHER_mode returns one of the cipher mode values enumerated below. */
|
||||
OPENSSL_EXPORT uint32_t EVP_CIPHER_mode(const EVP_CIPHER *cipher);
|
||||
|
||||
|
||||
/* Cipher modes (for |EVP_CIPHER_mode|). */
|
||||
|
||||
#define EVP_CIPH_STREAM_CIPHER 0x0
|
||||
#define EVP_CIPH_CBC_MODE 0x2
|
||||
/* EVP_CIPH_CFB_MODE 0x3 */
|
||||
/* EVP_CIPH_OFB_MODE 0x4 */
|
||||
#define EVP_CIPH_CTR_MODE 0x5
|
||||
|
||||
|
||||
/* Cipher flags (for |EVP_CIPHER_flags|). */
|
||||
|
||||
/* EVP_CIPH_VARIABLE_LENGTH indicates that the cipher takes a variable length
|
||||
* key. */
|
||||
#define EVP_CIPH_VARIABLE_LENGTH 0x40
|
||||
|
||||
/* EVP_CIPH_ALWAYS_CALL_INIT indicates that the |init| function for the cipher
|
||||
* should always be called when initialising a new operation, even if the key
|
||||
* is NULL to indicate that the same key is being used. */
|
||||
#define EVP_CIPH_ALWAYS_CALL_INIT 0x80
|
||||
|
||||
/* EVP_CIPH_CUSTOM_IV indicates that the cipher manages the IV itself rather
|
||||
* than keeping it in the |iv| member of |EVP_CIPHER_CTX|. */
|
||||
#define EVP_CIPH_CUSTOM_IV 0x100
|
||||
|
||||
/* EVP_CIPH_CTRL_INIT indicates that EVP_CTRL_INIT should be used when
|
||||
* initialising an |EVP_CIPHER_CTX|. */
|
||||
#define EVP_CIPH_CTRL_INIT 0x200
|
||||
|
||||
/* EVP_CIPH_FLAG_CUSTOM_CIPHER indicates that the cipher manages blocking
|
||||
* itself. This causes EVP_(En|De)crypt_ex to be simple wrapper functions. */
|
||||
#define EVP_CIPH_FLAG_CUSTOM_CIPHER 0x400
|
||||
|
||||
/* EVP_CIPH_FLAG_AEAD_CIPHER specifies that the cipher is an AEAD. This is an
|
||||
* older version of the proper AEAD interface. See aead.h for the current
|
||||
* one. */
|
||||
#define EVP_CIPH_FLAG_AEAD_CIPHER 0x800
|
||||
|
||||
/* EVP_CIPH_CUSTOM_COPY indicates that the |ctrl| callback should be called
|
||||
* with |EVP_CTRL_COPY| at the end of normal |EVP_CIPHER_CTX_copy|
|
||||
* processing. */
|
||||
#define EVP_CIPH_CUSTOM_COPY 0x1000
|
||||
|
||||
|
||||
/* Deprecated functions */
|
||||
|
||||
/* EVP_CipherInit acts like EVP_CipherInit_ex except that |EVP_CIPHER_CTX_init|
|
||||
* is called on |cipher| first, if |cipher| is not NULL. */
|
||||
OPENSSL_EXPORT int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
const uint8_t *key, const uint8_t *iv,
|
||||
int enc);
|
||||
|
||||
/* EVP_EncryptInit calls |EVP_CipherInit| with |enc| equal to one. */
|
||||
OPENSSL_EXPORT int EVP_EncryptInit(EVP_CIPHER_CTX *ctx,
|
||||
const EVP_CIPHER *cipher, const uint8_t *key,
|
||||
const uint8_t *iv);
|
||||
|
||||
/* EVP_DecryptInit calls |EVP_CipherInit| with |enc| equal to zero. */
|
||||
OPENSSL_EXPORT int EVP_DecryptInit(EVP_CIPHER_CTX *ctx,
|
||||
const EVP_CIPHER *cipher, const uint8_t *key,
|
||||
const uint8_t *iv);
|
||||
|
||||
|
||||
/* Private functions. */
|
||||
|
||||
/* EVP_CIPH_NO_PADDING disables padding in block ciphers. */
|
||||
#define EVP_CIPH_NO_PADDING 0x800
|
||||
|
||||
/* EVP_CIPHER_CTX_ctrl commands. */
|
||||
#define EVP_CTRL_INIT 0x0
|
||||
#define EVP_CTRL_SET_KEY_LENGTH 0x1
|
||||
/* EVP_CTRL_GET_RC2_KEY_BITS 0x2 */
|
||||
/* EVP_CTRL_SET_RC2_KEY_BITS 0x3 */
|
||||
#define EVP_CTRL_GET_RC5_ROUNDS 0x4
|
||||
#define EVP_CTRL_SET_RC5_ROUNDS 0x5
|
||||
#define EVP_CTRL_RAND_KEY 0x6
|
||||
#define EVP_CTRL_PBE_PRF_NID 0x7
|
||||
#define EVP_CTRL_COPY 0x8
|
||||
#define EVP_CTRL_AEAD_SET_MAC_KEY 0x17
|
||||
|
||||
#define EVP_MAX_KEY_LENGTH 64
|
||||
#define EVP_MAX_IV_LENGTH 16
|
||||
#define EVP_MAX_BLOCK_LENGTH 32
|
||||
|
||||
struct evp_cipher_ctx_st {
|
||||
/* cipher contains the underlying cipher for this context. */
|
||||
const EVP_CIPHER *cipher;
|
||||
|
||||
/* app_data is a pointer to opaque, user data. */
|
||||
void *app_data; /* application stuff */
|
||||
|
||||
/* cipher_data points to the |cipher| specific state. */
|
||||
void *cipher_data;
|
||||
|
||||
/* key_len contains the length of the key, which may differ from
|
||||
* |cipher->key_len| if the cipher can take a variable key length. */
|
||||
unsigned key_len;
|
||||
|
||||
/* encrypt is one if encrypting and zero if decrypting. */
|
||||
int encrypt;
|
||||
|
||||
/* flags contains the OR of zero or more |EVP_CIPH_*| flags, above. */
|
||||
uint32_t flags;
|
||||
|
||||
/* oiv contains the original IV value. */
|
||||
uint8_t oiv[EVP_MAX_IV_LENGTH];
|
||||
|
||||
/* iv contains the current IV value, which may have been updated. */
|
||||
uint8_t iv[EVP_MAX_IV_LENGTH];
|
||||
|
||||
/* buf contains a partial block which is used by, for example, CTR mode to
|
||||
* store unused keystream bytes. */
|
||||
uint8_t buf[EVP_MAX_BLOCK_LENGTH];
|
||||
|
||||
/* buf_len contains the number of bytes of a partial block contained in
|
||||
* |buf|. */
|
||||
int buf_len;
|
||||
|
||||
/* num contains the number of bytes of |iv| which are valid for modes that
|
||||
* manage partial blocks themselves. */
|
||||
int num;
|
||||
|
||||
/* final_used is non-zero if the |final| buffer contains plaintext. */
|
||||
int final_used;
|
||||
|
||||
/* block_mask contains |cipher->block_size| minus one. (The block size
|
||||
* assumed to be a power of two.) */
|
||||
int block_mask;
|
||||
|
||||
uint8_t final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */
|
||||
} /* EVP_CIPHER_CTX */;
|
||||
|
||||
typedef struct evp_cipher_info_st {
|
||||
const EVP_CIPHER *cipher;
|
||||
unsigned char iv[EVP_MAX_IV_LENGTH];
|
||||
} EVP_CIPHER_INFO;
|
||||
|
||||
struct evp_cipher_st {
|
||||
/* block_size contains the block size, in bytes, of the cipher, or 1 for a
|
||||
* stream cipher. */
|
||||
unsigned block_size;
|
||||
|
||||
/* key_len contains the key size, in bytes, for the cipher. If the cipher
|
||||
* takes a variable key size then this contains the default size. */
|
||||
unsigned key_len;
|
||||
|
||||
/* iv_len contains the IV size, in bytes, or zero if inapplicable. */
|
||||
unsigned iv_len;
|
||||
|
||||
/* ctx_size contains the size, in bytes, of the per-key context for this
|
||||
* cipher. */
|
||||
unsigned ctx_size;
|
||||
|
||||
/* flags contains the OR of a number of flags. See |EVP_CIPH_*|. */
|
||||
uint32_t flags;
|
||||
|
||||
/* app_data is a pointer to opaque, user data. */
|
||||
void *app_data;
|
||||
|
||||
int (*init)(EVP_CIPHER_CTX *ctx, const uint8_t *key, const uint8_t *iv,
|
||||
int enc);
|
||||
|
||||
int (*cipher)(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
|
||||
size_t inl);
|
||||
|
||||
/* cleanup, if non-NULL, releases memory associated with the context. It is
|
||||
* called if |EVP_CTRL_INIT| succeeds. Note that |init| may not have been
|
||||
* called at this point. */
|
||||
void (*cleanup)(EVP_CIPHER_CTX *);
|
||||
|
||||
int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr);
|
||||
};
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#define CIPHER_R_AES_KEY_SETUP_FAILED 100
|
||||
#define CIPHER_R_BAD_DECRYPT 101
|
||||
#define CIPHER_R_BAD_KEY_LENGTH 102
|
||||
#define CIPHER_R_BUFFER_TOO_SMALL 103
|
||||
#define CIPHER_R_CTRL_NOT_IMPLEMENTED 104
|
||||
#define CIPHER_R_CTRL_OPERATION_NOT_IMPLEMENTED 105
|
||||
#define CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH 106
|
||||
#define CIPHER_R_INITIALIZATION_ERROR 107
|
||||
#define CIPHER_R_INPUT_NOT_INITIALIZED 108
|
||||
#define CIPHER_R_INVALID_AD_SIZE 109
|
||||
#define CIPHER_R_INVALID_KEY_LENGTH 110
|
||||
#define CIPHER_R_INVALID_NONCE_SIZE 111
|
||||
#define CIPHER_R_INVALID_OPERATION 112
|
||||
#define CIPHER_R_IV_TOO_LARGE 113
|
||||
#define CIPHER_R_NO_CIPHER_SET 114
|
||||
#define CIPHER_R_OUTPUT_ALIASES_INPUT 115
|
||||
#define CIPHER_R_TAG_TOO_LARGE 116
|
||||
#define CIPHER_R_TOO_LARGE 117
|
||||
#define CIPHER_R_UNSUPPORTED_AD_SIZE 118
|
||||
#define CIPHER_R_UNSUPPORTED_INPUT_SIZE 119
|
||||
#define CIPHER_R_UNSUPPORTED_KEY_SIZE 120
|
||||
#define CIPHER_R_UNSUPPORTED_NONCE_SIZE 121
|
||||
#define CIPHER_R_UNSUPPORTED_TAG_SIZE 122
|
||||
#define CIPHER_R_WRONG_FINAL_BLOCK_LENGTH 123
|
||||
#define CIPHER_R_NO_DIRECTION_SET 124
|
||||
|
||||
#endif /* OPENSSL_HEADER_CIPHER_H */
|
@ -1,234 +0,0 @@
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2015 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
|
||||
* licensing@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.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "../test/file_test.h"
|
||||
#include "../test/scoped_types.h"
|
||||
#include "../test/stl_compat.h"
|
||||
#include "cipher.h"
|
||||
|
||||
|
||||
static const EVP_CIPHER *GetCipher(const std::string &name) {
|
||||
if (name == "AES-128-CBC") {
|
||||
return EVP_aes_128_cbc();
|
||||
} else if (name == "AES-256-CBC") {
|
||||
return EVP_aes_256_cbc();
|
||||
} else if (name == "AES-128-CTR") {
|
||||
return EVP_aes_128_ctr();
|
||||
} else if (name == "AES-256-CTR") {
|
||||
return EVP_aes_256_ctr();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool TestOperation(FileTest *t,
|
||||
const EVP_CIPHER *cipher,
|
||||
bool encrypt,
|
||||
bool streaming,
|
||||
const std::vector<uint8_t> &key,
|
||||
const std::vector<uint8_t> &iv,
|
||||
const std::vector<uint8_t> &plaintext,
|
||||
const std::vector<uint8_t> &ciphertext,
|
||||
const std::vector<uint8_t> &aad,
|
||||
const std::vector<uint8_t> &tag) {
|
||||
const std::vector<uint8_t> *in, *out;
|
||||
if (encrypt) {
|
||||
in = &plaintext;
|
||||
out = &ciphertext;
|
||||
} else {
|
||||
in = &ciphertext;
|
||||
out = &plaintext;
|
||||
}
|
||||
|
||||
ScopedEVP_CIPHER_CTX ctx;
|
||||
if (!EVP_CipherInit_ex(ctx.get(), cipher, nullptr, nullptr, nullptr,
|
||||
encrypt ? 1 : 0)) {
|
||||
return false;
|
||||
}
|
||||
if (t->HasAttribute("IV")) {
|
||||
if (iv.size() != (size_t)EVP_CIPHER_CTX_iv_length(ctx.get())) {
|
||||
t->PrintLine("Bad IV length.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// The ciphers are run with no padding. For each of the ciphers we test, the
|
||||
// output size matches the input size.
|
||||
std::vector<uint8_t> result(in->size());
|
||||
if (in->size() != out->size()) {
|
||||
t->PrintLine("Input/output size mismatch (%u vs %u).", (unsigned)in->size(),
|
||||
(unsigned)out->size());
|
||||
return false;
|
||||
}
|
||||
// Note: the deprecated |EVP_CIPHER|-based AES-GCM API is sensitive to whether
|
||||
// parameters are NULL, so it is important to skip the |in| and |aad|
|
||||
// |EVP_CipherUpdate| calls when empty.
|
||||
int unused, result_len1 = 0, result_len2;
|
||||
if (!EVP_CIPHER_CTX_set_key_length(ctx.get(), key.size()) ||
|
||||
!EVP_CipherInit_ex(ctx.get(), nullptr, nullptr, bssl::vector_data(&key),
|
||||
bssl::vector_data(&iv), -1) ||
|
||||
(!aad.empty() &&
|
||||
!EVP_CipherUpdate(ctx.get(), nullptr, &unused, bssl::vector_data(&aad),
|
||||
aad.size())) ||
|
||||
!EVP_CIPHER_CTX_set_padding(ctx.get(), 0)) {
|
||||
t->PrintLine("Operation failed.");
|
||||
return false;
|
||||
}
|
||||
if (streaming) {
|
||||
for (size_t i = 0; i < in->size(); i++) {
|
||||
uint8_t c = (*in)[i];
|
||||
int len;
|
||||
if (!EVP_CipherUpdate(ctx.get(), bssl::vector_data(&result) + result_len1,
|
||||
&len, &c, 1)) {
|
||||
t->PrintLine("Operation failed.");
|
||||
return false;
|
||||
}
|
||||
result_len1 += len;
|
||||
}
|
||||
} else if (!in->empty() &&
|
||||
!EVP_CipherUpdate(ctx.get(), bssl::vector_data(&result),
|
||||
&result_len1, bssl::vector_data(in),
|
||||
in->size())) {
|
||||
t->PrintLine("Operation failed.");
|
||||
return false;
|
||||
}
|
||||
if (!EVP_CipherFinal_ex(ctx.get(), bssl::vector_data(&result) + result_len1,
|
||||
&result_len2)) {
|
||||
t->PrintLine("Operation failed.");
|
||||
return false;
|
||||
}
|
||||
result.resize(result_len1 + result_len2);
|
||||
if (!t->ExpectBytesEqual(bssl::vector_data(out), out->size(),
|
||||
bssl::vector_data(&result), result.size())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestCipher(FileTest *t, void *arg) {
|
||||
std::string cipher_str;
|
||||
if (!t->GetAttribute(&cipher_str, "Cipher")) {
|
||||
return false;
|
||||
}
|
||||
const EVP_CIPHER *cipher = GetCipher(cipher_str);
|
||||
if (cipher == nullptr) {
|
||||
t->PrintLine("Unknown cipher: '%s'.", cipher_str.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> key, iv, plaintext, ciphertext, aad, tag;
|
||||
if (!t->GetBytes(&key, "Key") ||
|
||||
!t->GetBytes(&plaintext, "Plaintext") ||
|
||||
!t->GetBytes(&ciphertext, "Ciphertext")) {
|
||||
return false;
|
||||
}
|
||||
if (EVP_CIPHER_iv_length(cipher) > 0 &&
|
||||
!t->GetBytes(&iv, "IV")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
enum {
|
||||
kEncrypt,
|
||||
kDecrypt,
|
||||
kBoth,
|
||||
} operation = kBoth;
|
||||
if (t->HasAttribute("Operation")) {
|
||||
const std::string &str = t->GetAttributeOrDie("Operation");
|
||||
if (str == "ENCRYPT") {
|
||||
operation = kEncrypt;
|
||||
} else if (str == "DECRYPT") {
|
||||
operation = kDecrypt;
|
||||
} else {
|
||||
t->PrintLine("Unknown operation: '%s'.", str.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// By default, both directions are run, unless overridden by the operation.
|
||||
if (operation != kDecrypt) {
|
||||
if (!TestOperation(t, cipher, true /* encrypt */, false /* single-shot */,
|
||||
key, iv, plaintext, ciphertext, aad, tag) ||
|
||||
!TestOperation(t, cipher, true /* encrypt */, true /* streaming */, key,
|
||||
iv, plaintext, ciphertext, aad, tag)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (operation != kEncrypt) {
|
||||
if (!TestOperation(t, cipher, false /* decrypt */, false /* single-shot */,
|
||||
key, iv, plaintext, ciphertext, aad, tag) ||
|
||||
!TestOperation(t, cipher, false /* decrypt */, true /* streaming */,
|
||||
key, iv, plaintext, ciphertext, aad, tag)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "%s <test file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return FileTestMain(TestCipher, nullptr, argv[1]);
|
||||
}
|
@ -57,7 +57,6 @@
|
||||
#include <openssl/obj.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include "cipher.h"
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
#include "../modes/internal.h"
|
||||
@ -70,18 +69,6 @@
|
||||
#define EVP_AEAD_AES_GCM_NONCE_LEN 12
|
||||
#define EVP_AEAD_AES_GCM_TAG_LEN 16
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
double align;
|
||||
AES_KEY ks;
|
||||
} ks;
|
||||
block128_f block;
|
||||
union {
|
||||
cbc128_f cbc;
|
||||
ctr128_f ctr;
|
||||
} stream;
|
||||
} EVP_AES_KEY;
|
||||
|
||||
#if !defined(OPENSSL_NO_ASM) && \
|
||||
(defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
|
||||
#define VPAES
|
||||
@ -113,12 +100,7 @@ static int hwaes_capable(void) {
|
||||
|
||||
int aes_v8_set_encrypt_key(const uint8_t *user_key, const int bits,
|
||||
AES_KEY *key);
|
||||
int aes_v8_set_decrypt_key(const uint8_t *user_key, const int bits,
|
||||
AES_KEY *key);
|
||||
void aes_v8_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
||||
void aes_v8_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
||||
void aes_v8_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
||||
const AES_KEY *key, uint8_t *ivec, const int enc);
|
||||
void aes_v8_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len,
|
||||
const AES_KEY *key, const uint8_t ivec[16]);
|
||||
|
||||
@ -127,8 +109,6 @@ void aes_v8_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len,
|
||||
#if defined(BSAES)
|
||||
/* On platforms where BSAES gets defined (just above), then these functions are
|
||||
* provided by asm. */
|
||||
void bsaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
||||
const AES_KEY *key, uint8_t ivec[16], int enc);
|
||||
void bsaes_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len,
|
||||
const AES_KEY *key, const uint8_t ivec[16]);
|
||||
#else
|
||||
@ -138,14 +118,8 @@ static char bsaes_capable(void) {
|
||||
|
||||
/* On other platforms, bsaes_capable() will always return false and so the
|
||||
* following will never be called. */
|
||||
static void bsaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
||||
const AES_KEY *key, uint8_t ivec[16], int enc) {
|
||||
abort();
|
||||
}
|
||||
|
||||
static void bsaes_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
const uint8_t ivec[16]) {
|
||||
void bsaes_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len,
|
||||
const AES_KEY *key, const uint8_t ivec[16]) {
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
@ -154,13 +128,8 @@ static void bsaes_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
|
||||
/* On platforms where VPAES gets defined (just above), then these functions are
|
||||
* provided by asm. */
|
||||
int vpaes_set_encrypt_key(const uint8_t *userKey, int bits, AES_KEY *key);
|
||||
int vpaes_set_decrypt_key(const uint8_t *userKey, int bits, AES_KEY *key);
|
||||
|
||||
void vpaes_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
||||
void vpaes_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
||||
|
||||
void vpaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
||||
const AES_KEY *key, uint8_t *ivec, int enc);
|
||||
#else
|
||||
static char vpaes_capable(void) {
|
||||
return 0;
|
||||
@ -172,20 +141,9 @@ static int vpaes_set_encrypt_key(const uint8_t *userKey, int bits,
|
||||
AES_KEY *key) {
|
||||
abort();
|
||||
}
|
||||
static int vpaes_set_decrypt_key(const uint8_t *userKey, int bits,
|
||||
AES_KEY *key) {
|
||||
abort();
|
||||
}
|
||||
static void vpaes_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
|
||||
abort();
|
||||
}
|
||||
static void vpaes_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
|
||||
abort();
|
||||
}
|
||||
static void vpaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
||||
const AES_KEY *key, uint8_t *ivec, int enc) {
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(HWAES)
|
||||
@ -200,26 +158,11 @@ static int aes_v8_set_encrypt_key(const uint8_t *user_key, int bits,
|
||||
abort();
|
||||
}
|
||||
|
||||
static int aes_v8_set_decrypt_key(const uint8_t *user_key, int bits,
|
||||
AES_KEY *key) {
|
||||
abort();
|
||||
}
|
||||
|
||||
static void aes_v8_encrypt(const uint8_t *in, uint8_t *out,
|
||||
const AES_KEY *key) {
|
||||
abort();
|
||||
}
|
||||
|
||||
static void aes_v8_decrypt(const uint8_t *in, uint8_t *out,
|
||||
const AES_KEY *key) {
|
||||
abort();
|
||||
}
|
||||
|
||||
static void aes_v8_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
||||
const AES_KEY *key, uint8_t *ivec, int enc) {
|
||||
abort();
|
||||
}
|
||||
|
||||
static void aes_v8_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
|
||||
size_t len, const AES_KEY *key,
|
||||
const uint8_t ivec[16]) {
|
||||
@ -230,13 +173,8 @@ static void aes_v8_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
|
||||
#if !defined(OPENSSL_NO_ASM) && \
|
||||
(defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
|
||||
int aesni_set_encrypt_key(const uint8_t *userKey, int bits, AES_KEY *key);
|
||||
int aesni_set_decrypt_key(const uint8_t *userKey, int bits, AES_KEY *key);
|
||||
|
||||
void aesni_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
||||
void aesni_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
|
||||
|
||||
void aesni_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
|
||||
const AES_KEY *key, uint8_t *ivec, int enc);
|
||||
|
||||
void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
|
||||
const void *key, const uint8_t *ivec);
|
||||
@ -260,96 +198,6 @@ static void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
|
||||
|
||||
#endif
|
||||
|
||||
static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
|
||||
const uint8_t *iv, int enc)
|
||||
OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS {
|
||||
int ret, mode;
|
||||
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
|
||||
|
||||
mode = ctx->cipher->flags & EVP_CIPH_MODE_MASK;
|
||||
if (mode == EVP_CIPH_CBC_MODE && !enc) {
|
||||
if (hwaes_capable()) {
|
||||
ret = aes_v8_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)aes_v8_decrypt;
|
||||
dat->stream.cbc = NULL;
|
||||
dat->stream.cbc = (cbc128_f)aes_v8_cbc_encrypt;
|
||||
} else if (bsaes_capable()) {
|
||||
ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)AES_decrypt;
|
||||
dat->stream.cbc = (cbc128_f)bsaes_cbc_encrypt;
|
||||
} else if (vpaes_capable()) {
|
||||
ret = vpaes_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)vpaes_decrypt;
|
||||
dat->stream.cbc = (cbc128_f)vpaes_cbc_encrypt;
|
||||
} else {
|
||||
ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)AES_decrypt;
|
||||
dat->stream.cbc = (cbc128_f)AES_cbc_encrypt;
|
||||
}
|
||||
} else if (hwaes_capable()) {
|
||||
ret = aes_v8_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)aes_v8_encrypt;
|
||||
dat->stream.cbc = NULL;
|
||||
if (mode == EVP_CIPH_CBC_MODE) {
|
||||
dat->stream.cbc = (cbc128_f)aes_v8_cbc_encrypt;
|
||||
} else if (mode == EVP_CIPH_CTR_MODE) {
|
||||
dat->stream.ctr = (ctr128_f)aes_v8_ctr32_encrypt_blocks;
|
||||
}
|
||||
} else if (bsaes_capable() && mode == EVP_CIPH_CTR_MODE) {
|
||||
ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)AES_encrypt;
|
||||
dat->stream.ctr = (ctr128_f)bsaes_ctr32_encrypt_blocks;
|
||||
} else if (vpaes_capable()) {
|
||||
ret = vpaes_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)vpaes_encrypt;
|
||||
dat->stream.cbc =
|
||||
mode == EVP_CIPH_CBC_MODE ? (cbc128_f)vpaes_cbc_encrypt : NULL;
|
||||
} else {
|
||||
ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
|
||||
dat->block = (block128_f)AES_encrypt;
|
||||
dat->stream.cbc =
|
||||
mode == EVP_CIPH_CBC_MODE ? (cbc128_f)AES_cbc_encrypt : NULL;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
|
||||
size_t len) {
|
||||
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
|
||||
|
||||
if (dat->stream.cbc) {
|
||||
(*dat->stream.cbc)(in, out, len, &dat->ks, ctx->iv, ctx->encrypt);
|
||||
} else if (ctx->encrypt) {
|
||||
CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv, dat->block);
|
||||
} else {
|
||||
CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, ctx->iv, dat->block);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
|
||||
size_t len) {
|
||||
unsigned int num = ctx->num;
|
||||
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
|
||||
|
||||
if (dat->stream.ctr) {
|
||||
CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, ctx->iv, ctx->buf, &num,
|
||||
dat->stream.ctr);
|
||||
} else {
|
||||
CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, ctx->buf, &num,
|
||||
dat->block);
|
||||
}
|
||||
ctx->num = (size_t)num;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char aesni_capable(void);
|
||||
|
||||
static ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx,
|
||||
@ -410,147 +258,10 @@ static ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* increment counter (64-bit int) by 1 */
|
||||
static void ctr64_inc(uint8_t *counter) {
|
||||
int n = 8;
|
||||
uint8_t c;
|
||||
|
||||
do {
|
||||
--n;
|
||||
c = counter[n];
|
||||
++c;
|
||||
counter[n] = c;
|
||||
if (c) {
|
||||
return;
|
||||
}
|
||||
} while (n);
|
||||
}
|
||||
|
||||
static const EVP_CIPHER aes_128_cbc = {
|
||||
16 /* block_size */, 16 /* key_size */,
|
||||
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE,
|
||||
NULL /* app_data */, aes_init_key, aes_cbc_cipher,
|
||||
NULL /* cleanup */, NULL /* ctrl */};
|
||||
|
||||
static const EVP_CIPHER aes_128_ctr = {
|
||||
1 /* block_size */, 16 /* key_size */,
|
||||
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE,
|
||||
NULL /* app_data */, aes_init_key, aes_ctr_cipher,
|
||||
NULL /* cleanup */, NULL /* ctrl */};
|
||||
|
||||
|
||||
static const EVP_CIPHER aes_256_cbc = {
|
||||
16 /* block_size */, 32 /* key_size */,
|
||||
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE,
|
||||
NULL /* app_data */, aes_init_key, aes_cbc_cipher,
|
||||
NULL /* cleanup */, NULL /* ctrl */};
|
||||
|
||||
static const EVP_CIPHER aes_256_ctr = {
|
||||
1 /* block_size */, 32 /* key_size */,
|
||||
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE,
|
||||
NULL /* app_data */, aes_init_key, aes_ctr_cipher,
|
||||
NULL /* cleanup */, NULL /* ctrl */};
|
||||
|
||||
#if !defined(OPENSSL_NO_ASM) && \
|
||||
(defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
|
||||
|
||||
/* AES-NI section. */
|
||||
|
||||
static char aesni_capable(void) {
|
||||
return (OPENSSL_ia32cap_P[1] & (1 << (57 - 32))) != 0;
|
||||
}
|
||||
|
||||
static int aesni_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
|
||||
const uint8_t *iv, int enc) {
|
||||
int ret, mode;
|
||||
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
|
||||
|
||||
mode = ctx->cipher->flags & EVP_CIPH_MODE_MASK;
|
||||
if (mode == EVP_CIPH_CBC_MODE && !enc) {
|
||||
ret = aesni_set_decrypt_key(key, ctx->key_len * 8, ctx->cipher_data);
|
||||
dat->block = (block128_f)aesni_decrypt;
|
||||
dat->stream.cbc =
|
||||
mode == EVP_CIPH_CBC_MODE ? (cbc128_f)aesni_cbc_encrypt : NULL;
|
||||
} else {
|
||||
ret = aesni_set_encrypt_key(key, ctx->key_len * 8, ctx->cipher_data);
|
||||
dat->block = (block128_f)aesni_encrypt;
|
||||
if (mode == EVP_CIPH_CBC_MODE) {
|
||||
dat->stream.cbc = (cbc128_f)aesni_cbc_encrypt;
|
||||
} else if (mode == EVP_CIPH_CTR_MODE) {
|
||||
dat->stream.ctr = (ctr128_f)aesni_ctr32_encrypt_blocks;
|
||||
} else {
|
||||
dat->stream.cbc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aesni_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out,
|
||||
const uint8_t *in, size_t len) {
|
||||
aesni_cbc_encrypt(in, out, len, ctx->cipher_data, ctx->iv, ctx->encrypt);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const EVP_CIPHER aesni_128_cbc = {
|
||||
16 /* block_size */, 16 /* key_size */,
|
||||
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE,
|
||||
NULL /* app_data */, aesni_init_key, aesni_cbc_cipher,
|
||||
NULL /* cleanup */, NULL /* ctrl */};
|
||||
|
||||
static const EVP_CIPHER aesni_128_ctr = {
|
||||
1 /* block_size */, 16 /* key_size */,
|
||||
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE,
|
||||
NULL /* app_data */, aesni_init_key, aes_ctr_cipher,
|
||||
NULL /* cleanup */, NULL /* ctrl */};
|
||||
|
||||
|
||||
static const EVP_CIPHER aesni_256_cbc = {
|
||||
16 /* block_size */, 32 /* key_size */,
|
||||
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CBC_MODE,
|
||||
NULL /* app_data */, aesni_init_key, aesni_cbc_cipher,
|
||||
NULL /* cleanup */, NULL /* ctrl */};
|
||||
|
||||
static const EVP_CIPHER aesni_256_ctr = {
|
||||
1 /* block_size */, 32 /* key_size */,
|
||||
16 /* iv_len */, sizeof(EVP_AES_KEY), EVP_CIPH_CTR_MODE,
|
||||
NULL /* app_data */, aesni_init_key, aes_ctr_cipher,
|
||||
NULL /* cleanup */, NULL /* ctrl */};
|
||||
|
||||
#define EVP_CIPHER_FUNCTION(keybits, mode) \
|
||||
const EVP_CIPHER *EVP_aes_##keybits##_##mode(void) { \
|
||||
if (aesni_capable()) { \
|
||||
return &aesni_##keybits##_##mode; \
|
||||
} else { \
|
||||
return &aes_##keybits##_##mode; \
|
||||
} \
|
||||
}
|
||||
|
||||
#else /* ^^^ OPENSSL_X86_64 || OPENSSL_X86 */
|
||||
|
||||
static char aesni_capable(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define EVP_CIPHER_FUNCTION(keybits, mode) \
|
||||
const EVP_CIPHER *EVP_aes_##keybits##_##mode(void) { \
|
||||
return &aes_##keybits##_##mode; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
EVP_CIPHER_FUNCTION(128, cbc)
|
||||
EVP_CIPHER_FUNCTION(128, ctr)
|
||||
|
||||
EVP_CIPHER_FUNCTION(256, cbc)
|
||||
EVP_CIPHER_FUNCTION(256, ctr)
|
||||
|
||||
|
||||
struct aead_aes_gcm_ctx {
|
||||
union {
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/poly1305.h>
|
||||
|
||||
#include "cipher.h"
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
|
@ -66,10 +66,6 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* EVP_CIPH_MODE_MASK contains the bits of |flags| that represent the mode. */
|
||||
#define EVP_CIPH_MODE_MASK 0x3f
|
||||
|
||||
|
||||
/* EVP_AEAD represents a specific AEAD algorithm. */
|
||||
struct evp_aead_st {
|
||||
/* ring: Keep the layout of this in sync with the layout of
|
||||
|
@ -40,7 +40,6 @@
|
||||
<ClCompile Include="chacha\chacha_generic.c" />
|
||||
<ClCompile Include="chacha\chacha_vec.c" />
|
||||
<ClCompile Include="cipher\aead.c" />
|
||||
<ClCompile Include="cipher\cipher.c" />
|
||||
<ClCompile Include="cipher\e_aes.c" />
|
||||
<ClCompile Include="cipher\e_chacha20poly1305.c" />
|
||||
<ClCompile Include="cpu-arm.c" />
|
||||
@ -90,7 +89,6 @@
|
||||
<ClInclude Include="bn\internal.h" />
|
||||
<ClInclude Include="bn\rsaz_exp.h" />
|
||||
<ClInclude Include="bytestring\internal.h" />
|
||||
<ClInclude Include="cipher\cipher.h" />
|
||||
<ClInclude Include="cipher\internal.h" />
|
||||
<ClInclude Include="des\internal.h" />
|
||||
<ClInclude Include="dh\internal.h" />
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "../cipher/cipher.h"
|
||||
#include "stl_compat.h"
|
||||
|
||||
|
||||
@ -87,9 +86,6 @@ using ScopedRSA = ScopedOpenSSLType<RSA, RSA_free>;
|
||||
using ScopedEVP_AEAD_CTX = ScopedOpenSSLContext<EVP_AEAD_CTX, void,
|
||||
EVP_AEAD_CTX_zero,
|
||||
EVP_AEAD_CTX_cleanup>;
|
||||
using ScopedEVP_CIPHER_CTX = ScopedOpenSSLContext<EVP_CIPHER_CTX, int,
|
||||
EVP_CIPHER_CTX_init,
|
||||
EVP_CIPHER_CTX_cleanup>;
|
||||
using ScopedEVP_MD_CTX = ScopedOpenSSLContext<EVP_MD_CTX, int, EVP_MD_CTX_init,
|
||||
EVP_MD_CTX_cleanup>;
|
||||
|
||||
|
@ -44,7 +44,6 @@ RING_SRCS = $(addprefix $(RING_PREFIX), \
|
||||
crypto/chacha/chacha_generic.c \
|
||||
crypto/chacha/chacha_vec.c \
|
||||
crypto/cipher/aead.c \
|
||||
crypto/cipher/cipher.c \
|
||||
crypto/cipher/e_aes.c \
|
||||
crypto/cipher/e_chacha20poly1305.c \
|
||||
crypto/cpu-arm.c \
|
||||
@ -201,7 +200,6 @@ RING_TEST_MAIN_SRCS = $(addprefix $(RING_PREFIX), \
|
||||
crypto/bn/bn_test.cc \
|
||||
crypto/bytestring/bytestring_test.cc \
|
||||
crypto/cipher/aead_test.cc \
|
||||
crypto/cipher/cipher_test.cc \
|
||||
crypto/constant_time_test.c \
|
||||
crypto/dh/dh_test.cc \
|
||||
crypto/digest/digest_test.cc \
|
||||
|
11
ring.sln
11
ring.sln
@ -17,8 +17,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bn_test.Windows", "crypto\b
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bytestring_test.Windows", "crypto\bytestring\bytestring_test.Windows.vcxproj", "{8B0DEF57-6FC5-404F-A1D0-A8FC0FCAD787}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cipher_test.Windows", "crypto\cipher\cipher_test.Windows.vcxproj", "{E9BBE9B6-8361-4007-B523-E59FDB775D01}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "digest_test.Windows", "crypto\digest\digest_test.Windows.vcxproj", "{954615BD-27CB-4AA3-AEE0-D25CD5460B0E}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ecdsa_test.Windows", "crypto\ecdsa\ecdsa_test.Windows.vcxproj", "{8ECBC55D-D42D-40AA-9ACF-EDE67739EE20}"
|
||||
@ -95,14 +93,6 @@ Global
|
||||
{8B0DEF57-6FC5-404F-A1D0-A8FC0FCAD787}.Release|Win32.Build.0 = Release|Win32
|
||||
{8B0DEF57-6FC5-404F-A1D0-A8FC0FCAD787}.Release|x64.ActiveCfg = Release|x64
|
||||
{8B0DEF57-6FC5-404F-A1D0-A8FC0FCAD787}.Release|x64.Build.0 = Release|x64
|
||||
{E9BBE9B6-8361-4007-B523-E59FDB775D01}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{E9BBE9B6-8361-4007-B523-E59FDB775D01}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{E9BBE9B6-8361-4007-B523-E59FDB775D01}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E9BBE9B6-8361-4007-B523-E59FDB775D01}.Debug|x64.Build.0 = Debug|x64
|
||||
{E9BBE9B6-8361-4007-B523-E59FDB775D01}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{E9BBE9B6-8361-4007-B523-E59FDB775D01}.Release|Win32.Build.0 = Release|Win32
|
||||
{E9BBE9B6-8361-4007-B523-E59FDB775D01}.Release|x64.ActiveCfg = Release|x64
|
||||
{E9BBE9B6-8361-4007-B523-E59FDB775D01}.Release|x64.Build.0 = Release|x64
|
||||
{954615BD-27CB-4AA3-AEE0-D25CD5460B0E}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{954615BD-27CB-4AA3-AEE0-D25CD5460B0E}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{954615BD-27CB-4AA3-AEE0-D25CD5460B0E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
@ -193,7 +183,6 @@ Global
|
||||
{95B509DD-F16C-49EE-B962-3B28FAC30CF7} = {73F15439-77AE-4EA2-8CB7-D82876016316}
|
||||
{06C8B12A-97C3-4326-B0AB-8C8004E94A76} = {73F15439-77AE-4EA2-8CB7-D82876016316}
|
||||
{8B0DEF57-6FC5-404F-A1D0-A8FC0FCAD787} = {73F15439-77AE-4EA2-8CB7-D82876016316}
|
||||
{E9BBE9B6-8361-4007-B523-E59FDB775D01} = {73F15439-77AE-4EA2-8CB7-D82876016316}
|
||||
{954615BD-27CB-4AA3-AEE0-D25CD5460B0E} = {73F15439-77AE-4EA2-8CB7-D82876016316}
|
||||
{8ECBC55D-D42D-40AA-9ACF-EDE67739EE20} = {73F15439-77AE-4EA2-8CB7-D82876016316}
|
||||
{A8616FF5-8273-4C80-8BF0-1785D8E1DF74} = {73F15439-77AE-4EA2-8CB7-D82876016316}
|
||||
|
@ -7,7 +7,6 @@
|
||||
["crypto/cipher/aead_test", "aes-256-gcm", "crypto/cipher/test/aes_256_gcm_tests.txt"],
|
||||
["crypto/cipher/aead_test", "aes-256-key-wrap", "crypto/cipher/test/aes_256_key_wrap_tests.txt"],
|
||||
["crypto/cipher/aead_test", "chacha20-poly1305", "crypto/cipher/test/chacha20_poly1305_tests.txt"],
|
||||
["crypto/cipher/cipher_test", "crypto/cipher/test/cipher_test.txt"],
|
||||
["crypto/constant_time_test"],
|
||||
["crypto/dh/dh_test"],
|
||||
["crypto/digest/digest_test"],
|
||||
|
Loading…
x
Reference in New Issue
Block a user