Latest update.

This commit is contained in:
2019-09-21 00:43:47 +09:00
parent 2e57f602ae
commit 62515c7d8d
1131 changed files with 47556 additions and 24957 deletions
-485
View File
@@ -1,485 +0,0 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/core_numbers.h>
#include <openssl/core_names.h>
#include <openssl/evp.h>
#include <openssl/params.h>
#include "internal/cryptlib.h"
#include "internal/provider_algs.h"
#include "ciphers_locl.h"
#include "internal/providercommonerr.h"
static OSSL_OP_cipher_encrypt_init_fn aes_einit;
static OSSL_OP_cipher_decrypt_init_fn aes_dinit;
static OSSL_OP_cipher_update_fn aes_block_update;
static OSSL_OP_cipher_final_fn aes_block_final;
static OSSL_OP_cipher_update_fn aes_stream_update;
static OSSL_OP_cipher_final_fn aes_stream_final;
static OSSL_OP_cipher_cipher_fn aes_cipher;
static OSSL_OP_cipher_freectx_fn aes_freectx;
static OSSL_OP_cipher_dupctx_fn aes_dupctx;
static OSSL_OP_cipher_ctx_get_params_fn aes_ctx_get_params;
static OSSL_OP_cipher_ctx_set_params_fn aes_ctx_set_params;
static int PROV_AES_KEY_generic_init(PROV_AES_KEY *ctx,
const unsigned char *iv,
size_t ivlen,
int enc)
{
if (iv != NULL && ctx->mode != EVP_CIPH_ECB_MODE) {
if (ivlen != AES_BLOCK_SIZE) {
PROVerr(PROV_F_PROV_AES_KEY_GENERIC_INIT, ERR_R_INTERNAL_ERROR);
return 0;
}
memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
}
ctx->enc = enc;
return 1;
}
static int aes_einit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen)
{
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
if (!PROV_AES_KEY_generic_init(ctx, iv, ivlen, 1)) {
/* PROVerr already called */
return 0;
}
if (key != NULL) {
if (keylen != ctx->keylen) {
PROVerr(PROV_F_AES_EINIT, PROV_R_INVALID_KEYLEN);
return 0;
}
return ctx->ciph->init(ctx, key, ctx->keylen);
}
return 1;
}
static int aes_dinit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen)
{
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
if (!PROV_AES_KEY_generic_init(ctx, iv, ivlen, 0)) {
/* PROVerr already called */
return 0;
}
if (key != NULL) {
if (keylen != ctx->keylen) {
PROVerr(PROV_F_AES_DINIT, PROV_R_INVALID_KEYLEN);
return 0;
}
return ctx->ciph->init(ctx, key, ctx->keylen);
}
return 1;
}
static int aes_block_update(void *vctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in, size_t inl)
{
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
size_t nextblocks = fillblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE, &in,
&inl);
size_t outlint = 0;
/*
* If we're decrypting and we end an update on a block boundary we hold
* the last block back in case this is the last update call and the last
* block is padded.
*/
if (ctx->bufsz == AES_BLOCK_SIZE
&& (ctx->enc || inl > 0 || !ctx->pad)) {
if (outsize < AES_BLOCK_SIZE) {
PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!ctx->ciph->cipher(ctx, out, ctx->buf, AES_BLOCK_SIZE)) {
PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
ctx->bufsz = 0;
outlint = AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
if (nextblocks > 0) {
if (!ctx->enc && ctx->pad && nextblocks == inl) {
if (!ossl_assert(inl >= AES_BLOCK_SIZE)) {
PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
nextblocks -= AES_BLOCK_SIZE;
}
outlint += nextblocks;
if (outsize < outlint) {
PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!ctx->ciph->cipher(ctx, out, in, nextblocks)) {
PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
in += nextblocks;
inl -= nextblocks;
}
if (!trailingdata(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE, &in, &inl)) {
/* PROVerr already called */
return 0;
}
*outl = outlint;
return inl == 0;
}
static int aes_block_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
if (ctx->enc) {
if (ctx->pad) {
padblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE);
} else if (ctx->bufsz == 0) {
*outl = 0;
return 1;
} else if (ctx->bufsz != AES_BLOCK_SIZE) {
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
return 0;
}
if (outsize < AES_BLOCK_SIZE) {
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!ctx->ciph->cipher(ctx, out, ctx->buf, AES_BLOCK_SIZE)) {
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
ctx->bufsz = 0;
*outl = AES_BLOCK_SIZE;
return 1;
}
/* Decrypting */
if (ctx->bufsz != AES_BLOCK_SIZE) {
if (ctx->bufsz == 0 && !ctx->pad) {
*outl = 0;
return 1;
}
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
return 0;
}
if (!ctx->ciph->cipher(ctx, ctx->buf, ctx->buf, AES_BLOCK_SIZE)) {
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
if (ctx->pad && !unpadblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE)) {
/* PROVerr already called */
return 0;
}
if (outsize < ctx->bufsz) {
PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
memcpy(out, ctx->buf, ctx->bufsz);
*outl = ctx->bufsz;
ctx->bufsz = 0;
return 1;
}
static int aes_stream_update(void *vctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in,
size_t inl)
{
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
if (outsize < inl) {
PROVerr(PROV_F_AES_STREAM_UPDATE, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!ctx->ciph->cipher(ctx, out, in, inl)) {
PROVerr(PROV_F_AES_STREAM_UPDATE, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
*outl = inl;
return 1;
}
static int aes_stream_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
*outl = 0;
return 1;
}
static int aes_cipher(void *vctx,
unsigned char *out, size_t *outl, size_t outsize,
const unsigned char *in, size_t inl)
{
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
if (outsize < inl) {
PROVerr(PROV_F_AES_CIPHER, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!ctx->ciph->cipher(ctx, out, in, inl)) {
PROVerr(PROV_F_AES_CIPHER, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
*outl = inl;
return 1;
}
#define IMPLEMENT_cipher(lcmode, UCMODE, flags, kbits, blkbits, ivbits) \
static OSSL_OP_cipher_get_params_fn aes_##kbits##_##lcmode##_get_params; \
static int aes_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
{ \
OSSL_PARAM *p; \
\
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE); \
if (p != NULL) { \
if (!OSSL_PARAM_set_int(p, EVP_CIPH_##UCMODE##_MODE)) \
return 0; \
} \
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_FLAGS); \
if (p != NULL) { \
if (!OSSL_PARAM_set_ulong(p, (flags))) \
return 0; \
} \
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); \
if (p != NULL) { \
if (!OSSL_PARAM_set_int(p, (kbits) / 8)) \
return 0; \
} \
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE); \
if (p != NULL) { \
if (!OSSL_PARAM_set_int(p, (blkbits) / 8)) \
return 0; \
} \
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); \
if (p != NULL) { \
if (!OSSL_PARAM_set_int(p, (ivbits) / 8)) \
return 0; \
} \
\
return 1; \
} \
static OSSL_OP_cipher_newctx_fn aes_##kbits##_##lcmode##_newctx; \
static void *aes_##kbits##_##lcmode##_newctx(void *provctx) \
{ \
PROV_AES_KEY *ctx = OPENSSL_zalloc(sizeof(*ctx)); \
\
ctx->pad = 1; \
ctx->keylen = ((kbits) / 8); \
ctx->ciph = PROV_AES_CIPHER_##lcmode(ctx->keylen); \
ctx->mode = EVP_CIPH_##UCMODE##_MODE; \
return ctx; \
}
/* ECB */
IMPLEMENT_cipher(ecb, ECB, 0, 256, 128, 0)
IMPLEMENT_cipher(ecb, ECB, 0, 192, 128, 0)
IMPLEMENT_cipher(ecb, ECB, 0, 128, 128, 0)
/* CBC */
IMPLEMENT_cipher(cbc, CBC, 0, 256, 128, 128)
IMPLEMENT_cipher(cbc, CBC, 0, 192, 128, 128)
IMPLEMENT_cipher(cbc, CBC, 0, 128, 128, 128)
/* OFB */
IMPLEMENT_cipher(ofb, OFB, 0, 256, 8, 128)
IMPLEMENT_cipher(ofb, OFB, 0, 192, 8, 128)
IMPLEMENT_cipher(ofb, OFB, 0, 128, 8, 128)
/* CFB */
IMPLEMENT_cipher(cfb, CFB, 0, 256, 8, 128)
IMPLEMENT_cipher(cfb, CFB, 0, 192, 8, 128)
IMPLEMENT_cipher(cfb, CFB, 0, 128, 8, 128)
IMPLEMENT_cipher(cfb1, CFB, 0, 256, 8, 128)
IMPLEMENT_cipher(cfb1, CFB, 0, 192, 8, 128)
IMPLEMENT_cipher(cfb1, CFB, 0, 128, 8, 128)
IMPLEMENT_cipher(cfb8, CFB, 0, 256, 8, 128)
IMPLEMENT_cipher(cfb8, CFB, 0, 192, 8, 128)
IMPLEMENT_cipher(cfb8, CFB, 0, 128, 8, 128)
/* CTR */
IMPLEMENT_cipher(ctr, CTR, 0, 256, 8, 128)
IMPLEMENT_cipher(ctr, CTR, 0, 192, 8, 128)
IMPLEMENT_cipher(ctr, CTR, 0, 128, 8, 128)
static void aes_freectx(void *vctx)
{
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static void *aes_dupctx(void *ctx)
{
PROV_AES_KEY *in = (PROV_AES_KEY *)ctx;
PROV_AES_KEY *ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL) {
PROVerr(PROV_F_AES_DUPCTX, ERR_R_MALLOC_FAILURE);
return NULL;
}
*ret = *in;
return ret;
}
static int aes_ctx_get_params(void *vctx, OSSL_PARAM params[])
{
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
OSSL_PARAM *p;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING);
if (p != NULL && !OSSL_PARAM_set_int(p, ctx->pad)) {
PROVerr(PROV_F_AES_CTX_GET_PARAMS, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
if (p != NULL
&& !OSSL_PARAM_set_octet_ptr(p, &ctx->iv, AES_BLOCK_SIZE)
&& !OSSL_PARAM_set_octet_string(p, &ctx->iv, AES_BLOCK_SIZE)) {
PROVerr(PROV_F_AES_CTX_GET_PARAMS,
PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_NUM);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->num)) {
PROVerr(PROV_F_AES_CTX_GET_PARAMS,
PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL && !OSSL_PARAM_set_int(p, ctx->keylen)) {
PROVerr(PROV_F_AES_CTX_GET_PARAMS,
PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
return 1;
}
static int aes_ctx_set_params(void *vctx, const OSSL_PARAM params[])
{
PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
const OSSL_PARAM *p;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_PADDING);
if (p != NULL) {
int pad;
if (!OSSL_PARAM_get_int(p, &pad)) {
PROVerr(PROV_F_AES_CTX_SET_PARAMS,
PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
ctx->pad = pad ? 1 : 0;
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_NUM);
if (p != NULL) {
int num;
if (!OSSL_PARAM_get_int(p, &num)) {
PROVerr(PROV_F_AES_CTX_SET_PARAMS,
PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
ctx->num = num;
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL) {
int keylen;
if (!OSSL_PARAM_get_int(p, &keylen)) {
PROVerr(PROV_F_AES_CTX_SET_PARAMS,
PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
ctx->keylen = keylen;
}
return 1;
}
#define IMPLEMENT_block_funcs(mode, kbits) \
const OSSL_DISPATCH aes##kbits##mode##_functions[] = { \
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##kbits##_##mode##_newctx }, \
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_einit }, \
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_dinit }, \
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_block_update }, \
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_block_final }, \
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_cipher }, \
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_freectx }, \
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_dupctx }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))aes_##kbits##_##mode##_get_params }, \
{ OSSL_FUNC_CIPHER_CTX_GET_PARAMS, (void (*)(void))aes_ctx_get_params }, \
{ OSSL_FUNC_CIPHER_CTX_SET_PARAMS, (void (*)(void))aes_ctx_set_params }, \
{ 0, NULL } \
};
#define IMPLEMENT_stream_funcs(mode, kbits) \
const OSSL_DISPATCH aes##kbits##mode##_functions[] = { \
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##kbits##_##mode##_newctx }, \
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_einit }, \
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_dinit }, \
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_stream_update }, \
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_stream_final }, \
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_cipher }, \
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_freectx }, \
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_dupctx }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))aes_##kbits##_##mode##_get_params }, \
{ OSSL_FUNC_CIPHER_CTX_GET_PARAMS, (void (*)(void))aes_ctx_get_params }, \
{ OSSL_FUNC_CIPHER_CTX_SET_PARAMS, (void (*)(void))aes_ctx_set_params }, \
{ 0, NULL } \
};
/* ECB */
IMPLEMENT_block_funcs(ecb, 256)
IMPLEMENT_block_funcs(ecb, 192)
IMPLEMENT_block_funcs(ecb, 128)
/* CBC */
IMPLEMENT_block_funcs(cbc, 256)
IMPLEMENT_block_funcs(cbc, 192)
IMPLEMENT_block_funcs(cbc, 128)
/* OFB */
IMPLEMENT_stream_funcs(ofb, 256)
IMPLEMENT_stream_funcs(ofb, 192)
IMPLEMENT_stream_funcs(ofb, 128)
/* CFB */
IMPLEMENT_stream_funcs(cfb, 256)
IMPLEMENT_stream_funcs(cfb, 192)
IMPLEMENT_stream_funcs(cfb, 128)
IMPLEMENT_stream_funcs(cfb1, 256)
IMPLEMENT_stream_funcs(cfb1, 192)
IMPLEMENT_stream_funcs(cfb1, 128)
IMPLEMENT_stream_funcs(cfb8, 256)
IMPLEMENT_stream_funcs(cfb8, 192)
IMPLEMENT_stream_funcs(cfb8, 128)
/* CTR */
IMPLEMENT_stream_funcs(ctr, 256)
IMPLEMENT_stream_funcs(ctr, 192)
IMPLEMENT_stream_funcs(ctr, 128)
-866
View File
@@ -1,866 +0,0 @@
/*
* Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/opensslconf.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <string.h>
#include <assert.h>
#include <openssl/aes.h>
#include "internal/evp_int.h"
#include <openssl/rand.h>
#include <openssl/cmac.h>
#include "ciphers_locl.h"
#include "internal/providercommonerr.h"
#define MAXBITCHUNK ((size_t)1 << (sizeof(size_t) * 8 - 4))
#ifdef VPAES_ASM
int vpaes_set_encrypt_key(const unsigned char *userKey, int bits,
AES_KEY *key);
int vpaes_set_decrypt_key(const unsigned char *userKey, int bits,
AES_KEY *key);
void vpaes_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void vpaes_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void vpaes_cbc_encrypt(const unsigned char *in,
unsigned char *out,
size_t length,
const AES_KEY *key, unsigned char *ivec, int enc);
#endif
#ifdef BSAES_ASM
void bsaes_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char ivec[16], int enc);
void bsaes_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
const unsigned char ivec[16]);
#endif
#ifdef AES_CTR_ASM
void AES_ctr32_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key,
const unsigned char ivec[AES_BLOCK_SIZE]);
#endif
#if defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC))
# include "ppc_arch.h"
# ifdef VPAES_ASM
# define VPAES_CAPABLE (OPENSSL_ppccap_P & PPC_ALTIVEC)
# endif
# define HWAES_CAPABLE (OPENSSL_ppccap_P & PPC_CRYPTO207)
# define HWAES_set_encrypt_key aes_p8_set_encrypt_key
# define HWAES_set_decrypt_key aes_p8_set_decrypt_key
# define HWAES_encrypt aes_p8_encrypt
# define HWAES_decrypt aes_p8_decrypt
# define HWAES_cbc_encrypt aes_p8_cbc_encrypt
# define HWAES_ctr32_encrypt_blocks aes_p8_ctr32_encrypt_blocks
# define HWAES_xts_encrypt aes_p8_xts_encrypt
# define HWAES_xts_decrypt aes_p8_xts_decrypt
#endif
#if defined(AES_ASM) && !defined(I386_ONLY) && ( \
((defined(__i386) || defined(__i386__) || \
defined(_M_IX86)) && defined(OPENSSL_IA32_SSE2))|| \
defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64) )
extern unsigned int OPENSSL_ia32cap_P[];
# ifdef VPAES_ASM
# define VPAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
# endif
# ifdef BSAES_ASM
# define BSAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
# endif
/*
* AES-NI section
*/
# define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32)))
int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
AES_KEY *key);
int aesni_set_decrypt_key(const unsigned char *userKey, int bits,
AES_KEY *key);
void aesni_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void aesni_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void aesni_ecb_encrypt(const unsigned char *in,
unsigned char *out,
size_t length, const AES_KEY *key, int enc);
void aesni_cbc_encrypt(const unsigned char *in,
unsigned char *out,
size_t length,
const AES_KEY *key, unsigned char *ivec, int enc);
void aesni_ctr32_encrypt_blocks(const unsigned char *in,
unsigned char *out,
size_t blocks,
const void *key, const unsigned char *ivec);
static int aesni_init_key(PROV_AES_KEY *dat, const unsigned char *key,
size_t keylen)
{
int ret;
if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
&& !dat->enc) {
ret = aesni_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
dat->block = (block128_f) aesni_decrypt;
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) aesni_cbc_encrypt : NULL;
} else {
ret = aesni_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
dat->block = (block128_f) aesni_encrypt;
if (dat->mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt;
else if (dat->mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
else
dat->stream.cbc = NULL;
}
if (ret < 0) {
PROVerr(PROV_F_AESNI_INIT_KEY, PROV_R_AES_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
static int aesni_cbc_cipher(PROV_AES_KEY *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
aesni_cbc_encrypt(in, out, len, &ctx->ks.ks, ctx->iv, ctx->enc);
return 1;
}
static int aesni_ecb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
if (len < AES_BLOCK_SIZE)
return 1;
aesni_ecb_encrypt(in, out, len, &ctx->ks.ks, ctx->enc);
return 1;
}
# define aesni_ofb_cipher aes_ofb_cipher
static int aesni_ofb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aesni_cfb_cipher aes_cfb_cipher
static int aesni_cfb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aesni_cfb8_cipher aes_cfb8_cipher
static int aesni_cfb8_cipher(PROV_AES_KEY *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aesni_cfb1_cipher aes_cfb1_cipher
static int aesni_cfb1_cipher(PROV_AES_KEY *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aesni_ctr_cipher aes_ctr_cipher
static int aesni_ctr_cipher(PROV_AES_KEY *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define BLOCK_CIPHER_generic_prov(mode) \
static const PROV_AES_CIPHER aesni_##mode = { \
aesni_init_key, \
aesni_##mode##_cipher}; \
static const PROV_AES_CIPHER aes_##mode = { \
aes_init_key, \
aes_##mode##_cipher}; \
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
{ return AESNI_CAPABLE?&aesni_##mode:&aes_##mode; }
#elif defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
# include "sparc_arch.h"
extern unsigned int OPENSSL_sparcv9cap_P[];
/*
* Fujitsu SPARC64 X support
*/
# define HWAES_CAPABLE (OPENSSL_sparcv9cap_P[0] & SPARCV9_FJAESX)
# define HWAES_set_encrypt_key aes_fx_set_encrypt_key
# define HWAES_set_decrypt_key aes_fx_set_decrypt_key
# define HWAES_encrypt aes_fx_encrypt
# define HWAES_decrypt aes_fx_decrypt
# define HWAES_cbc_encrypt aes_fx_cbc_encrypt
# define HWAES_ctr32_encrypt_blocks aes_fx_ctr32_encrypt_blocks
# define SPARC_AES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_AES)
void aes_t4_set_encrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
void aes_t4_set_decrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
void aes_t4_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void aes_t4_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
/*
* Key-length specific subroutines were chosen for following reason.
* Each SPARC T4 core can execute up to 8 threads which share core's
* resources. Loading as much key material to registers allows to
* minimize references to shared memory interface, as well as amount
* of instructions in inner loops [much needed on T4]. But then having
* non-key-length specific routines would require conditional branches
* either in inner loops or on subroutines' entries. Former is hardly
* acceptable, while latter means code size increase to size occupied
* by multiple key-length specific subroutines, so why fight?
*/
void aes128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes192_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes192_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key,
unsigned char *ivec);
void aes192_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key,
unsigned char *ivec);
void aes256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key,
unsigned char *ivec);
static int aes_t4_init_key(PROV_AES_KEY *dat, const unsigned char *key,
size_t keylen)
{
int ret, bits;
bits = keylen * 8;
if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
&& !dat->enc) {
ret = 0;
aes_t4_set_decrypt_key(key, bits, &dat->ks.ks);
dat->block = (block128_f) aes_t4_decrypt;
switch (bits) {
case 128:
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) aes128_t4_cbc_decrypt : NULL;
break;
case 192:
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) aes192_t4_cbc_decrypt : NULL;
break;
case 256:
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) aes256_t4_cbc_decrypt : NULL;
break;
default:
ret = -1;
}
} else {
ret = 0;
aes_t4_set_encrypt_key(key, bits, &dat->ks.ks);
dat->block = (block128_f)aes_t4_encrypt;
switch (bits) {
case 128:
if (dat->mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f)aes128_t4_cbc_encrypt;
else if (dat->mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f)aes128_t4_ctr32_encrypt;
else
dat->stream.cbc = NULL;
break;
case 192:
if (dat->mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f)aes192_t4_cbc_encrypt;
else if (dat->mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f)aes192_t4_ctr32_encrypt;
else
dat->stream.cbc = NULL;
break;
case 256:
if (dat->mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f)aes256_t4_cbc_encrypt;
else if (dat->mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f)aes256_t4_ctr32_encrypt;
else
dat->stream.cbc = NULL;
break;
default:
ret = -1;
}
}
if (ret < 0) {
PROVerr(PROV_F_AES_T4_INIT_KEY, PROV_R_AES_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
# define aes_t4_cbc_cipher aes_cbc_cipher
static int aes_t4_cbc_cipher(PROV_AES_KEY *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aes_t4_ecb_cipher aes_ecb_cipher
static int aes_t4_ecb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aes_t4_ofb_cipher aes_ofb_cipher
static int aes_t4_ofb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aes_t4_cfb_cipher aes_cfb_cipher
static int aes_t4_cfb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aes_t4_cfb8_cipher aes_cfb8_cipher
static int aes_t4_cfb8_cipher(PROV_AES_KEY *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aes_t4_cfb1_cipher aes_cfb1_cipher
static int aes_t4_cfb1_cipher(PROV_AES_KEY *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aes_t4_ctr_cipher aes_ctr_cipher
static int aes_t4_ctr_cipher(PROV_AES_KEY *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define BLOCK_CIPHER_generic_prov(mode) \
static const PROV_AES_CIPHER aes_t4_##mode = { \
aes_t4_init_key, \
aes_t4_##mode##_cipher}; \
static const PROV_AES_CIPHER aes_##mode = { \
aes_init_key, \
aes_##mode##_cipher}; \
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
{ return SPARC_AES_CAPABLE?&aes_t4_##mode:&aes_##mode; }
#elif defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
/*
* IBM S390X support
*/
# include "s390x_arch.h"
/* Convert key size to function code: [16,24,32] -> [18,19,20]. */
# define S390X_AES_FC(keylen) (S390X_AES_128 + ((((keylen) << 3) - 128) >> 6))
/* Most modes of operation need km for partial block processing. */
# define S390X_aes_128_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
S390X_CAPBIT(S390X_AES_128))
# define S390X_aes_192_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
S390X_CAPBIT(S390X_AES_192))
# define S390X_aes_256_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
S390X_CAPBIT(S390X_AES_256))
# define s390x_aes_init_key aes_init_key
static int s390x_aes_init_key(PROV_AES_KEY *dat, const unsigned char *key,
size_t keylen);
# define S390X_aes_128_cbc_CAPABLE 1 /* checked by callee */
# define S390X_aes_192_cbc_CAPABLE 1
# define S390X_aes_256_cbc_CAPABLE 1
# define S390X_AES_CBC_CTX PROV_AES_KEY
# define s390x_aes_cbc_init_key aes_init_key
# define s390x_aes_cbc_cipher aes_cbc_cipher
static int s390x_aes_cbc_cipher(PROV_AES_KEY *dat, unsigned char *out,
const unsigned char *in, size_t len);
# define S390X_aes_128_ecb_CAPABLE S390X_aes_128_CAPABLE
# define S390X_aes_192_ecb_CAPABLE S390X_aes_192_CAPABLE
# define S390X_aes_256_ecb_CAPABLE S390X_aes_256_CAPABLE
static int s390x_aes_ecb_init_key(PROV_AES_KEY *dat, const unsigned char *key,
size_t keylen)
{
dat->plat.s390x.fc = S390X_AES_FC(keylen);
if (!dat->enc)
dat->plat.s390x.fc |= S390X_DECRYPT;
memcpy(dat->plat.s390x.param.km.k, key, keylen);
return 1;
}
static int s390x_aes_ecb_cipher(PROV_AES_KEY *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
s390x_km(in, len, out, dat->plat.s390x.fc,
&dat->plat.s390x.param.km);
return 1;
}
# define S390X_aes_128_ofb_CAPABLE (S390X_aes_128_CAPABLE && \
(OPENSSL_s390xcap_P.kmo[0] & \
S390X_CAPBIT(S390X_AES_128)))
# define S390X_aes_192_ofb_CAPABLE (S390X_aes_192_CAPABLE && \
(OPENSSL_s390xcap_P.kmo[0] & \
S390X_CAPBIT(S390X_AES_192)))
# define S390X_aes_256_ofb_CAPABLE (S390X_aes_256_CAPABLE && \
(OPENSSL_s390xcap_P.kmo[0] & \
S390X_CAPBIT(S390X_AES_256)))
static int s390x_aes_ofb_init_key(PROV_AES_KEY *dat, const unsigned char *key,
size_t keylen)
{
memcpy(dat->plat.s390x.param.kmo_kmf.cv, dat->iv, AES_BLOCK_SIZE);
memcpy(dat->plat.s390x.param.kmo_kmf.k, key, keylen);
dat->plat.s390x.fc = S390X_AES_FC(keylen);
dat->plat.s390x.res = 0;
return 1;
}
static int s390x_aes_ofb_cipher(PROV_AES_KEY *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
int n = dat->plat.s390x.res;
int rem;
while (n && len) {
*out = *in ^ dat->plat.s390x.param.kmo_kmf.cv[n];
n = (n + 1) & 0xf;
--len;
++in;
++out;
}
rem = len & 0xf;
len &= ~(size_t)0xf;
if (len) {
s390x_kmo(in, len, out, dat->plat.s390x.fc,
&dat->plat.s390x.param.kmo_kmf);
out += len;
in += len;
}
if (rem) {
s390x_km(dat->plat.s390x.param.kmo_kmf.cv, 16,
dat->plat.s390x.param.kmo_kmf.cv, dat->plat.s390x.fc,
dat->plat.s390x.param.kmo_kmf.k);
while (rem--) {
out[n] = in[n] ^ dat->plat.s390x.param.kmo_kmf.cv[n];
++n;
}
}
dat->plat.s390x.res = n;
return 1;
}
# define S390X_aes_128_cfb_CAPABLE (S390X_aes_128_CAPABLE && \
(OPENSSL_s390xcap_P.kmf[0] & \
S390X_CAPBIT(S390X_AES_128)))
# define S390X_aes_192_cfb_CAPABLE (S390X_aes_192_CAPABLE && \
(OPENSSL_s390xcap_P.kmf[0] & \
S390X_CAPBIT(S390X_AES_192)))
# define S390X_aes_256_cfb_CAPABLE (S390X_aes_256_CAPABLE && \
(OPENSSL_s390xcap_P.kmf[0] & \
S390X_CAPBIT(S390X_AES_256)))
static int s390x_aes_cfb_init_key(PROV_AES_KEY *dat, const unsigned char *key,
size_t keylen)
{
dat->plat.s390x.fc = S390X_AES_FC(keylen);
dat->plat.s390x.fc |= 16 << 24; /* 16 bytes cipher feedback */
if (!dat->enc)
dat->plat.s390x.fc |= S390X_DECRYPT;
dat->plat.s390x.res = 0;
memcpy(dat->plat.s390x.param.kmo_kmf.cv, dat->iv, AES_BLOCK_SIZE);
memcpy(dat->plat.s390x.param.kmo_kmf.k, key, keylen);
return 1;
}
static int s390x_aes_cfb_cipher(PROV_AES_KEY *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
int n = dat->plat.s390x.res;
int rem;
unsigned char tmp;
while (n && len) {
tmp = *in;
*out = dat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
dat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? *out : tmp;
n = (n + 1) & 0xf;
--len;
++in;
++out;
}
rem = len & 0xf;
len &= ~(size_t)0xf;
if (len) {
s390x_kmf(in, len, out, dat->plat.s390x.fc,
&dat->plat.s390x.param.kmo_kmf);
out += len;
in += len;
}
if (rem) {
s390x_km(dat->plat.s390x.param.kmo_kmf.cv, 16,
dat->plat.s390x.param.kmo_kmf.cv,
S390X_AES_FC(dat->keylen), dat->plat.s390x.param.kmo_kmf.k);
while (rem--) {
tmp = in[n];
out[n] = dat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
dat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? out[n] : tmp;
++n;
}
}
dat->plat.s390x.res = n;
return 1;
}
# define S390X_aes_128_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
S390X_CAPBIT(S390X_AES_128))
# define S390X_aes_192_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
S390X_CAPBIT(S390X_AES_192))
# define S390X_aes_256_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
S390X_CAPBIT(S390X_AES_256))
static int s390x_aes_cfb8_init_key(PROV_AES_KEY *dat, const unsigned char *key,
size_t keylen)
{
dat->plat.s390x.fc = S390X_AES_FC(keylen);
dat->plat.s390x.fc |= 1 << 24; /* 1 byte cipher feedback */
if (!dat->enc)
dat->plat.s390x.fc |= S390X_DECRYPT;
memcpy(dat->plat.s390x.param.kmo_kmf.cv, dat->iv, AES_BLOCK_SIZE);
memcpy(dat->plat.s390x.param.kmo_kmf.k, key, keylen);
return 1;
}
static int s390x_aes_cfb8_cipher(PROV_AES_KEY *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
s390x_kmf(in, len, out, dat->plat.s390x.fc,
&dat->plat.s390x.param.kmo_kmf);
return 1;
}
# define S390X_aes_128_cfb1_CAPABLE 0
# define S390X_aes_192_cfb1_CAPABLE 0
# define S390X_aes_256_cfb1_CAPABLE 0
# define s390x_aes_cfb1_init_key aes_init_key
# define s390x_aes_cfb1_cipher aes_cfb1_cipher
static int s390x_aes_cfb1_cipher(PROV_AES_KEY *dat, unsigned char *out,
const unsigned char *in, size_t len);
# define S390X_aes_128_ctr_CAPABLE 1 /* checked by callee */
# define S390X_aes_192_ctr_CAPABLE 1
# define S390X_aes_256_ctr_CAPABLE 1
# define S390X_AES_CTR_CTX PROV_AES_KEY
# define s390x_aes_ctr_init_key aes_init_key
# define s390x_aes_ctr_cipher aes_ctr_cipher
static int s390x_aes_ctr_cipher(PROV_AES_KEY *dat, unsigned char *out,
const unsigned char *in, size_t len);
# define BLOCK_CIPHER_generic_prov(mode) \
static const PROV_AES_CIPHER s390x_aes_##mode = { \
s390x_aes_##mode##_init_key, \
s390x_aes_##mode##_cipher \
}; \
static const PROV_AES_CIPHER aes_##mode = { \
aes_init_key, \
aes_##mode##_cipher \
}; \
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
{ \
if ((keylen == 16 && S390X_aes_128_##mode##_CAPABLE) \
|| (keylen == 24 && S390X_aes_192_##mode##_CAPABLE) \
|| (keylen == 32 && S390X_aes_256_##mode##_CAPABLE)) \
return &s390x_aes_##mode; \
\
return &aes_##mode; \
}
#else
# define BLOCK_CIPHER_generic_prov(mode) \
static const PROV_AES_CIPHER aes_##mode = { \
aes_init_key, \
aes_##mode##_cipher}; \
const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
{ return &aes_##mode; }
#endif
#if defined(OPENSSL_CPUID_OBJ) && (defined(__arm__) || defined(__arm) || defined(__aarch64__))
# include "arm_arch.h"
# if __ARM_MAX_ARCH__>=7
# if defined(BSAES_ASM)
# define BSAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
# endif
# if defined(VPAES_ASM)
# define VPAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
# endif
# define HWAES_CAPABLE (OPENSSL_armcap_P & ARMV8_AES)
# define HWAES_set_encrypt_key aes_v8_set_encrypt_key
# define HWAES_set_decrypt_key aes_v8_set_decrypt_key
# define HWAES_encrypt aes_v8_encrypt
# define HWAES_decrypt aes_v8_decrypt
# define HWAES_cbc_encrypt aes_v8_cbc_encrypt
# define HWAES_ctr32_encrypt_blocks aes_v8_ctr32_encrypt_blocks
# endif
#endif
#if defined(HWAES_CAPABLE)
int HWAES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
int HWAES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
void HWAES_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void HWAES_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void HWAES_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc);
void HWAES_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
const unsigned char ivec[16]);
#endif
static int aes_init_key(PROV_AES_KEY *dat, const unsigned char *key,
size_t keylen)
{
int ret;
if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
&& !dat->enc) {
#ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
ret = HWAES_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
dat->block = (block128_f)HWAES_decrypt;
dat->stream.cbc = NULL;
# ifdef HWAES_cbc_encrypt
if (dat->mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
# endif
} else
#endif
#ifdef BSAES_CAPABLE
if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CBC_MODE) {
ret = AES_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
dat->block = (block128_f)AES_decrypt;
dat->stream.cbc = (cbc128_f)bsaes_cbc_encrypt;
} else
#endif
#ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
ret = vpaes_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
dat->block = (block128_f)vpaes_decrypt;
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
?(cbc128_f)vpaes_cbc_encrypt : NULL;
} else
#endif
{
ret = AES_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
dat->block = (block128_f)AES_decrypt;
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
? (cbc128_f)AES_cbc_encrypt : NULL;
}
} else
#ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
ret = HWAES_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
dat->block = (block128_f)HWAES_encrypt;
dat->stream.cbc = NULL;
# ifdef HWAES_cbc_encrypt
if (dat->mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
else
# endif
# ifdef HWAES_ctr32_encrypt_blocks
if (dat->mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks;
else
# endif
(void)0; /* terminate potentially open 'else' */
} else
#endif
#ifdef BSAES_CAPABLE
if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CTR_MODE) {
ret = AES_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
dat->block = (block128_f)AES_encrypt;
dat->stream.ctr = (ctr128_f)bsaes_ctr32_encrypt_blocks;
} else
#endif
#ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
ret = vpaes_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
dat->block = (block128_f)vpaes_encrypt;
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
? (cbc128_f)vpaes_cbc_encrypt : NULL;
} else
#endif
{
ret = AES_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
dat->block = (block128_f)AES_encrypt;
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
? (cbc128_f)AES_cbc_encrypt : NULL;
#ifdef AES_CTR_ASM
if (dat->mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f)AES_ctr32_encrypt;
#endif
}
if (ret < 0) {
PROVerr(PROV_F_AES_INIT_KEY, PROV_R_AES_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
static int aes_cbc_cipher(PROV_AES_KEY *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
if (dat->stream.cbc)
(*dat->stream.cbc) (in, out, len, &dat->ks, dat->iv, dat->enc);
else if (dat->enc)
CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, dat->iv, dat->block);
else
CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, dat->iv, dat->block);
return 1;
}
static int aes_ecb_cipher(PROV_AES_KEY *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
size_t i;
if (len < AES_BLOCK_SIZE)
return 1;
for (i = 0, len -= AES_BLOCK_SIZE; i <= len; i += AES_BLOCK_SIZE)
(*dat->block) (in + i, out + i, &dat->ks);
return 1;
}
static int aes_ofb_cipher(PROV_AES_KEY *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
int num = dat->num;
CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, dat->iv, &num, dat->block);
dat->num = num;
return 1;
}
static int aes_cfb_cipher(PROV_AES_KEY *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
int num = dat->num;
CRYPTO_cfb128_encrypt(in, out, len, &dat->ks, dat->iv, &num, dat->enc,
dat->block);
dat->num = num;
return 1;
}
static int aes_cfb8_cipher(PROV_AES_KEY *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
int num = dat->num;
CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks, dat->iv, &num, dat->enc,
dat->block);
dat->num = num;
return 1;
}
static int aes_cfb1_cipher(PROV_AES_KEY *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
int num = dat->num;
if ((dat->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) {
CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks, dat->iv, &num,
dat->enc, dat->block);
dat->num = num;
return 1;
}
while (len >= MAXBITCHUNK) {
CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, &dat->ks,
dat->iv, &num, dat->enc, dat->block);
len -= MAXBITCHUNK;
out += MAXBITCHUNK;
in += MAXBITCHUNK;
}
if (len)
CRYPTO_cfb128_1_encrypt(in, out, len * 8, &dat->ks, dat->iv, &num,
dat->enc, dat->block);
dat->num = num;
return 1;
}
static int aes_ctr_cipher(PROV_AES_KEY *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
unsigned int num = dat->num;
if (dat->stream.ctr)
CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, dat->iv, dat->buf,
&num, dat->stream.ctr);
else
CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, dat->iv, dat->buf,
&num, dat->block);
dat->num = num;
return 1;
}
BLOCK_CIPHER_generic_prov(cbc)
BLOCK_CIPHER_generic_prov(ecb)
BLOCK_CIPHER_generic_prov(ofb)
BLOCK_CIPHER_generic_prov(cfb)
BLOCK_CIPHER_generic_prov(cfb1)
BLOCK_CIPHER_generic_prov(cfb8)
BLOCK_CIPHER_generic_prov(ctr)
+5 -8
View File
@@ -7,11 +7,8 @@
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include "ciphers_locl.h"
#include <assert.h>
#include "cipher_locl.h"
#include "internal/providercommonerr.h"
/*
@@ -67,7 +64,7 @@ int trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize,
return 1;
if (*buflen + *inlen > blocksize) {
PROVerr(PROV_F_TRAILINGDATA, ERR_R_INTERNAL_ERROR);
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -94,7 +91,7 @@ int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize)
size_t len = *buflen;
if(len != blocksize) {
PROVerr(PROV_F_UNPADBLOCK, ERR_R_INTERNAL_ERROR);
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -104,12 +101,12 @@ int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize)
*/
pad = buf[blocksize - 1];
if (pad == 0 || pad > blocksize) {
PROVerr(PROV_F_UNPADBLOCK, PROV_R_BAD_DECRYPT);
ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT);
return 0;
}
for (i = 0; i < pad; i++) {
if (buf[--len] != pad) {
PROVerr(PROV_F_UNPADBLOCK, PROV_R_BAD_DECRYPT);
ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT);
return 0;
}
}
+17 -4
View File
@@ -1,8 +1,21 @@
LIBS=../../../libcrypto
SOURCE[../../../libcrypto]=\
block.c aes.c aes_basic.c
IF[{- !$disabled{des} -}]
$COMMON_DES=cipher_tdes.c cipher_tdes_hw.c
ENDIF
$COMMON=cipher_common.c cipher_common_hw.c block.c \
cipher_aes.c cipher_aes_hw.c \
cipher_aes_xts.c cipher_aes_xts_hw.c \
cipher_gcm.c cipher_gcm_hw.c \
cipher_aes_gcm.c cipher_aes_gcm_hw.c \
cipher_ccm.c cipher_ccm_hw.c \
cipher_aes_ccm.c cipher_aes_ccm_hw.c \
cipher_aes_wrp.c \
$COMMON_DES
SOURCE[../../../libcrypto]=$COMMON
INCLUDE[../../../libcrypto]=. ../../../crypto
SOURCE[../../fips]=\
block.c aes.c aes_basic.c
SOURCE[../../fips]=$COMMON
INCLUDE[../../fips]=. ../../../crypto
+80
View File
@@ -0,0 +1,80 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Dispatch functions for AES cipher modes ecb, cbc, ofb, cfb, ctr */
#include "cipher_aes.h"
#include "internal/provider_algs.h"
static OSSL_OP_cipher_freectx_fn aes_freectx;
static OSSL_OP_cipher_dupctx_fn aes_dupctx;
static void aes_freectx(void *vctx)
{
PROV_AES_CTX *ctx = (PROV_AES_CTX *)vctx;
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static void *aes_dupctx(void *ctx)
{
PROV_AES_CTX *in = (PROV_AES_CTX *)ctx;
PROV_AES_CTX *ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
*ret = *in;
return ret;
}
/* aes256ecb_functions */
IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 256, 128, 0, block)
/* aes192ecb_functions */
IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 192, 128, 0, block)
/* aes128ecb_functions */
IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 128, 128, 0, block)
/* aes256cbc_functions */
IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 256, 128, 128, block)
/* aes192cbc_functions */
IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 192, 128, 128, block)
/* aes128cbc_functions */
IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 128, 128, 128, block)
/* aes256ofb_functions */
IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 256, 8, 128, stream)
/* aes192ofb_functions */
IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 192, 8, 128, stream)
/* aes128ofb_functions */
IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 128, 8, 128, stream)
/* aes256cfb_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 256, 8, 128, stream)
/* aes192cfb_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 192, 8, 128, stream)
/* aes128cfb_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 128, 8, 128, stream)
/* aes256cfb1_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 256, 8, 128, stream)
/* aes192cfb1_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 192, 8, 128, stream)
/* aes128cfb1_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 128, 8, 128, stream)
/* aes256cfb8_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 256, 8, 128, stream)
/* aes192cfb8_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 192, 8, 128, stream)
/* aes128cfb8_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 128, 8, 128, stream)
/* aes256ctr_functions */
IMPLEMENT_generic_cipher(aes, AES, ctr, CTR, 0, 256, 8, 128, stream)
/* aes192ctr_functions */
IMPLEMENT_generic_cipher(aes, AES, ctr, CTR, 0, 192, 8, 128, stream)
/* aes128ctr_functions */
IMPLEMENT_generic_cipher(aes, AES, ctr, CTR, 0, 128, 8, 128, stream)
+62
View File
@@ -0,0 +1,62 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/aes.h>
#include "internal/ciphers/ciphercommon.h"
typedef struct prov_aes_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
AES_KEY ks;
} ks;
/* Platform specific data */
union {
int dummy;
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
struct {
union {
OSSL_UNION_ALIGN;
/*-
* KM-AES parameter block - begin
* (see z/Architecture Principles of Operation >= SA22-7832-06)
*/
struct {
unsigned char k[32];
} km;
/* KM-AES parameter block - end */
/*-
* KMO-AES/KMF-AES parameter block - begin
* (see z/Architecture Principles of Operation >= SA22-7832-08)
*/
struct {
unsigned char cv[16];
unsigned char k[32];
} kmo_kmf;
/* KMO-AES/KMF-AES parameter block - end */
} param;
unsigned int fc;
int res;
} s390x;
#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
} plat;
} PROV_AES_CTX;
#define PROV_CIPHER_HW_aes_ofb PROV_CIPHER_HW_aes_ofb128
#define PROV_CIPHER_HW_aes_cfb PROV_CIPHER_HW_aes_cfb128
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_ecb(size_t keybits);
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_cbc(size_t keybits);
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_ofb128(size_t keybits);
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_cfb128(size_t keybits);
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_cfb1(size_t keybits);
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_cfb8(size_t keybits);
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_ctr(size_t keybits);
+39
View File
@@ -0,0 +1,39 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Dispatch functions for AES CCM mode */
#include "cipher_locl.h"
#include "internal/ciphers/cipher_ccm.h"
#include "internal/provider_algs.h"
static void *aes_ccm_newctx(void *provctx, size_t keybits)
{
PROV_AES_CCM_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL)
ccm_initctx(&ctx->base, keybits, PROV_AES_HW_ccm(keybits));
return ctx;
}
static OSSL_OP_cipher_freectx_fn aes_ccm_freectx;
static void aes_ccm_freectx(void *vctx)
{
PROV_AES_CCM_CTX *ctx = (PROV_AES_CCM_CTX *)vctx;
ccm_finalctx((PROV_CCM_CTX *)ctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
/* aes128ccm_functions */
IMPLEMENT_aead_cipher(aes, ccm, CCM, AEAD_FLAGS, 128, 8, 96);
/* aes192ccm_functions */
IMPLEMENT_aead_cipher(aes, ccm, CCM, AEAD_FLAGS, 192, 8, 96);
/* aes256ccm_functions */
IMPLEMENT_aead_cipher(aes, ccm, CCM, AEAD_FLAGS, 256, 8, 96);
@@ -0,0 +1,64 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* AES CCM mode */
#include "cipher_locl.h"
#include "internal/ciphers/cipher_ccm.h"
#define AES_HW_CCM_SET_KEY_FN(fn_set_enc_key, fn_blk, fn_ccm_enc, fn_ccm_dec) \
fn_set_enc_key(key, keylen * 8, &actx->ccm.ks.ks); \
CRYPTO_ccm128_init(&ctx->ccm_ctx, ctx->m, ctx->l, &actx->ccm.ks.ks, \
(block128_f)fn_blk); \
ctx->str = ctx->enc ? (ccm128_f)fn_ccm_enc : (ccm128_f)fn_ccm_dec; \
ctx->key_set = 1;
static int ccm_generic_aes_initkey(PROV_CCM_CTX *ctx, const unsigned char *key,
size_t keylen)
{
PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx;
#ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
AES_HW_CCM_SET_KEY_FN(HWAES_set_encrypt_key, HWAES_encrypt, NULL, NULL);
} else
#endif /* HWAES_CAPABLE */
#ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
AES_HW_CCM_SET_KEY_FN(vpaes_set_encrypt_key, vpaes_encrypt, NULL, NULL);
} else
#endif
{
AES_HW_CCM_SET_KEY_FN(AES_set_encrypt_key, AES_encrypt, NULL, NULL)
}
return 1;
}
static const PROV_CCM_HW aes_ccm = {
ccm_generic_aes_initkey,
ccm_generic_setiv,
ccm_generic_setaad,
ccm_generic_auth_encrypt,
ccm_generic_auth_decrypt,
ccm_generic_gettag
};
#if defined(S390X_aes_128_CAPABLE)
# include "cipher_aes_ccm_hw_s390x.inc"
#elif defined(AESNI_CAPABLE)
# include "cipher_aes_ccm_hw_aesni.inc"
#elif defined(SPARC_AES_CAPABLE)
# include "cipher_aes_ccm_hw_t4.inc"
#else
const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keybits)
{
return &aes_ccm;
}
#endif
@@ -0,0 +1,38 @@
/*
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*-
* AES-NI support for AES CCM.
* This file is included by cipher_ccm_hw.c
*/
static int ccm_aesni_initkey(PROV_CCM_CTX *ctx, const unsigned char *key,
size_t keylen)
{
PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx;
AES_HW_CCM_SET_KEY_FN(aesni_set_encrypt_key, aesni_encrypt,
aesni_ccm64_encrypt_blocks,
aesni_ccm64_decrypt_blocks);
return 1;
}
static const PROV_CCM_HW aesni_ccm = {
ccm_aesni_initkey,
ccm_generic_setiv,
ccm_generic_setaad,
ccm_generic_auth_encrypt,
ccm_generic_auth_decrypt,
ccm_generic_gettag
};
const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keybits)
{
return AESNI_CAPABLE ? &aesni_ccm : &aes_ccm;
}
@@ -0,0 +1,268 @@
/*
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*-
* S390X support for AES CCM.
* This file is included by cipher_ccm_hw.c
*/
#define S390X_CCM_AAD_FLAG 0x40
static int s390x_aes_ccm_initkey(PROV_CCM_CTX *ctx,
const unsigned char *key, size_t keylen)
{
PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
sctx->ccm.s390x.fc = S390X_AES_FC(keylen);
memcpy(&sctx->ccm.s390x.kmac.k, key, keylen);
/* Store encoded m and l. */
sctx->ccm.s390x.nonce.b[0] = ((ctx->l - 1) & 0x7)
| (((ctx->m - 2) >> 1) & 0x7) << 3;
memset(sctx->ccm.s390x.nonce.b + 1, 0, sizeof(sctx->ccm.s390x.nonce.b));
sctx->ccm.s390x.blocks = 0;
ctx->key_set = 1;
return 1;
}
static int s390x_aes_ccm_setiv(PROV_CCM_CTX *ctx,
const unsigned char *nonce, size_t noncelen,
size_t mlen)
{
PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
sctx->ccm.s390x.nonce.b[0] &= ~S390X_CCM_AAD_FLAG;
sctx->ccm.s390x.nonce.g[1] = mlen;
memcpy(sctx->ccm.s390x.nonce.b + 1, nonce, 15 - ctx->l);
return 1;
}
/*-
* Process additional authenticated data. Code is big-endian.
*/
static int s390x_aes_ccm_setaad(PROV_CCM_CTX *ctx,
const unsigned char *aad, size_t alen)
{
PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
unsigned char *ptr;
int i, rem;
if (!alen)
return 1;
sctx->ccm.s390x.nonce.b[0] |= S390X_CCM_AAD_FLAG;
/* Suppress 'type-punned pointer dereference' warning. */
ptr = sctx->ccm.s390x.buf.b;
if (alen < ((1 << 16) - (1 << 8))) {
*(uint16_t *)ptr = alen;
i = 2;
} else if (sizeof(alen) == 8
&& alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) {
*(uint16_t *)ptr = 0xffff;
*(uint64_t *)(ptr + 2) = alen;
i = 10;
} else {
*(uint16_t *)ptr = 0xfffe;
*(uint32_t *)(ptr + 2) = alen;
i = 6;
}
while (i < 16 && alen) {
sctx->ccm.s390x.buf.b[i] = *aad;
++aad;
--alen;
++i;
}
while (i < 16) {
sctx->ccm.s390x.buf.b[i] = 0;
++i;
}
sctx->ccm.s390x.kmac.icv.g[0] = 0;
sctx->ccm.s390x.kmac.icv.g[1] = 0;
s390x_kmac(sctx->ccm.s390x.nonce.b, 32, sctx->ccm.s390x.fc,
&sctx->ccm.s390x.kmac);
sctx->ccm.s390x.blocks += 2;
rem = alen & 0xf;
alen &= ~(size_t)0xf;
if (alen) {
s390x_kmac(aad, alen, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac);
sctx->ccm.s390x.blocks += alen >> 4;
aad += alen;
}
if (rem) {
for (i = 0; i < rem; i++)
sctx->ccm.s390x.kmac.icv.b[i] ^= aad[i];
s390x_km(sctx->ccm.s390x.kmac.icv.b, 16,
sctx->ccm.s390x.kmac.icv.b, sctx->ccm.s390x.fc,
sctx->ccm.s390x.kmac.k);
sctx->ccm.s390x.blocks++;
}
return 1;
}
/*-
* En/de-crypt plain/cipher-text. Compute tag from plaintext. Returns 1 for
* success.
*/
static int s390x_aes_ccm_auth_encdec(PROV_CCM_CTX *ctx,
const unsigned char *in,
unsigned char *out, size_t len, int enc)
{
PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
size_t n, rem;
unsigned int i, l, num;
unsigned char flags;
flags = sctx->ccm.s390x.nonce.b[0];
if (!(flags & S390X_CCM_AAD_FLAG)) {
s390x_km(sctx->ccm.s390x.nonce.b, 16, sctx->ccm.s390x.kmac.icv.b,
sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k);
sctx->ccm.s390x.blocks++;
}
l = flags & 0x7;
sctx->ccm.s390x.nonce.b[0] = l;
/*-
* Reconstruct length from encoded length field
* and initialize it with counter value.
*/
n = 0;
for (i = 15 - l; i < 15; i++) {
n |= sctx->ccm.s390x.nonce.b[i];
sctx->ccm.s390x.nonce.b[i] = 0;
n <<= 8;
}
n |= sctx->ccm.s390x.nonce.b[15];
sctx->ccm.s390x.nonce.b[15] = 1;
if (n != len)
return 0; /* length mismatch */
if (enc) {
/* Two operations per block plus one for tag encryption */
sctx->ccm.s390x.blocks += (((len + 15) >> 4) << 1) + 1;
if (sctx->ccm.s390x.blocks > (1ULL << 61))
return 0; /* too much data */
}
num = 0;
rem = len & 0xf;
len &= ~(size_t)0xf;
if (enc) {
/* mac-then-encrypt */
if (len)
s390x_kmac(in, len, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac);
if (rem) {
for (i = 0; i < rem; i++)
sctx->ccm.s390x.kmac.icv.b[i] ^= in[len + i];
s390x_km(sctx->ccm.s390x.kmac.icv.b, 16,
sctx->ccm.s390x.kmac.icv.b,
sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k);
}
CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &sctx->ccm.ks.ks,
sctx->ccm.s390x.nonce.b, sctx->ccm.s390x.buf.b,
&num, (ctr128_f)AES_ctr32_encrypt);
} else {
/* decrypt-then-mac */
CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &sctx->ccm.ks.ks,
sctx->ccm.s390x.nonce.b, sctx->ccm.s390x.buf.b,
&num, (ctr128_f)AES_ctr32_encrypt);
if (len)
s390x_kmac(out, len, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac);
if (rem) {
for (i = 0; i < rem; i++)
sctx->ccm.s390x.kmac.icv.b[i] ^= out[len + i];
s390x_km(sctx->ccm.s390x.kmac.icv.b, 16,
sctx->ccm.s390x.kmac.icv.b,
sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k);
}
}
/* encrypt tag */
for (i = 15 - l; i < 16; i++)
sctx->ccm.s390x.nonce.b[i] = 0;
s390x_km(sctx->ccm.s390x.nonce.b, 16, sctx->ccm.s390x.buf.b,
sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k);
sctx->ccm.s390x.kmac.icv.g[0] ^= sctx->ccm.s390x.buf.g[0];
sctx->ccm.s390x.kmac.icv.g[1] ^= sctx->ccm.s390x.buf.g[1];
sctx->ccm.s390x.nonce.b[0] = flags; /* restore flags field */
return 1;
}
static int s390x_aes_ccm_gettag(PROV_CCM_CTX *ctx,
unsigned char *tag, size_t tlen)
{
PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
if (tlen > ctx->m)
return 0;
memcpy(tag, sctx->ccm.s390x.kmac.icv.b, tlen);
return 1;
}
static int s390x_aes_ccm_auth_encrypt(PROV_CCM_CTX *ctx,
const unsigned char *in,
unsigned char *out, size_t len,
unsigned char *tag, size_t taglen)
{
int rv;
rv = s390x_aes_ccm_auth_encdec(ctx, in, out, len, 1);
if (rv && tag != NULL)
rv = s390x_aes_ccm_gettag(ctx, tag, taglen);
return rv;
}
static int s390x_aes_ccm_auth_decrypt(PROV_CCM_CTX *ctx,
const unsigned char *in,
unsigned char *out, size_t len,
unsigned char *expected_tag,
size_t taglen)
{
int rv = 0;
PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx;
rv = s390x_aes_ccm_auth_encdec(ctx, in, out, len, 0);
if (rv) {
if (CRYPTO_memcmp(sctx->ccm.s390x.kmac.icv.b, expected_tag, ctx->m) != 0)
rv = 0;
}
if (rv == 0)
OPENSSL_cleanse(out, len);
return rv;
}
static const PROV_CCM_HW s390x_aes_ccm = {
s390x_aes_ccm_initkey,
s390x_aes_ccm_setiv,
s390x_aes_ccm_setaad,
s390x_aes_ccm_auth_encrypt,
s390x_aes_ccm_auth_decrypt,
s390x_aes_ccm_gettag
};
const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keybits)
{
if ((keybits == 128 && S390X_aes_128_ccm_CAPABLE)
|| (keybits == 192 && S390X_aes_192_ccm_CAPABLE)
|| (keybits == 256 && S390X_aes_256_ccm_CAPABLE))
return &s390x_aes_ccm;
return &aes_ccm;
}
@@ -0,0 +1,36 @@
/*
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*-
* Fujitsu SPARC64 X support for AES CCM.
* This file is included by cipher_ccm_hw.c
*/
static int ccm_t4_aes_initkey(PROV_CCM_CTX *ctx, const unsigned char *key,
size_t keylen)
{
PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx;
AES_HW_CCM_SET_KEY_FN(aes_t4_set_encrypt_key, aes_t4_encrypt, NULL, NULL);
return 1;
}
static const PROV_CCM_HW t4_aes_ccm = {
ccm_t4_aes_initkey,
ccm_generic_setiv,
ccm_generic_setaad,
ccm_generic_auth_encrypt,
ccm_generic_auth_decrypt,
ccm_generic_gettag
};
const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keybits)
{
return SPARC_AES_CAPABLE ? &t4_aes_ccm : &aes_ccm;
}
+39
View File
@@ -0,0 +1,39 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Dispatch functions for AES GCM mode */
#include "cipher_locl.h"
#include "internal/ciphers/cipher_gcm.h"
#include "internal/provider_algs.h"
static void *aes_gcm_newctx(void *provctx, size_t keybits)
{
PROV_AES_GCM_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL)
gcm_initctx(provctx, &ctx->base, keybits, PROV_AES_HW_gcm(keybits), 8);
return ctx;
}
static OSSL_OP_cipher_freectx_fn aes_gcm_freectx;
static void aes_gcm_freectx(void *vctx)
{
PROV_AES_GCM_CTX *ctx = (PROV_AES_GCM_CTX *)vctx;
gcm_deinitctx((PROV_GCM_CTX *)ctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
/* aes128gcm_functions */
IMPLEMENT_aead_cipher(aes, gcm, GCM, AEAD_FLAGS, 128, 8, 96);
/* aes192gcm_functions */
IMPLEMENT_aead_cipher(aes, gcm, GCM, AEAD_FLAGS, 192, 8, 96);
/* aes256gcm_functions */
IMPLEMENT_aead_cipher(aes, gcm, GCM, AEAD_FLAGS, 256, 8, 96);
@@ -0,0 +1,78 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Dispatch functions for AES GCM mode */
#include "cipher_locl.h"
#include "internal/ciphers/cipher_gcm.h"
static int generic_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
size_t keylen)
{
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
AES_KEY *ks = &actx->ks.ks;
# ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
# ifdef HWAES_ctr32_encrypt_blocks
GCM_HW_SET_KEY_CTR_FN(ks, HWAES_set_encrypt_key, HWAES_encrypt,
HWAES_ctr32_encrypt_blocks);
# else
GCM_HW_SET_KEY_CTR_FN(ks, HWAES_set_encrypt_key, HWAES_encrypt, NULL);
# endif /* HWAES_ctr32_encrypt_blocks */
} else
# endif /* HWAES_CAPABLE */
# ifdef BSAES_CAPABLE
if (BSAES_CAPABLE) {
GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt,
bsaes_ctr32_encrypt_blocks);
} else
# endif /* BSAES_CAPABLE */
# ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
GCM_HW_SET_KEY_CTR_FN(ks, vpaes_set_encrypt_key, vpaes_encrypt, NULL);
} else
# endif /* VPAES_CAPABLE */
{
# ifdef AES_CTR_ASM
GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt,
AES_ctr32_encrypt);
# else
GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt, NULL);
# endif /* AES_CTR_ASM */
}
ctx->key_set = 1;
return 1;
}
static const PROV_GCM_HW aes_gcm = {
generic_aes_gcm_initkey,
gcm_setiv,
gcm_aad_update,
gcm_cipher_update,
gcm_cipher_final,
gcm_one_shot
};
#if defined(S390X_aes_128_CAPABLE)
# include "cipher_aes_gcm_hw_s390x.inc"
#elif defined(AESNI_CAPABLE)
# include "cipher_aes_gcm_hw_aesni.inc"
#elif defined(SPARC_AES_CAPABLE)
# include "cipher_aes_gcm_hw_t4.inc"
#else
const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits)
{
return &aes_gcm;
}
#endif
@@ -0,0 +1,38 @@
/*
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*-
* AES-NI support for AES GCM.
* This file is included by cipher_gcm_hw.c
*/
static int aesni_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
size_t keylen)
{
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
AES_KEY *ks = &actx->ks.ks;
GCM_HW_SET_KEY_CTR_FN(ks, aesni_set_encrypt_key, aesni_encrypt,
aesni_ctr32_encrypt_blocks);
return 1;
}
static const PROV_GCM_HW aesni_gcm = {
aesni_gcm_initkey,
gcm_setiv,
gcm_aad_update,
gcm_cipher_update,
gcm_cipher_final,
gcm_one_shot
};
const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits)
{
return AESNI_CAPABLE ? &aesni_gcm : &aes_gcm;
}
@@ -0,0 +1,300 @@
/*
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*-
* IBM S390X support for AES GCM.
* This file is included by cipher_gcm_hw.c
*/
/* iv + padding length for iv lengths != 12 */
#define S390X_gcm_ivpadlen(i) ((((i) + 15) >> 4 << 4) + 16)
static int s390x_aes_gcm_initkey(PROV_GCM_CTX *ctx,
const unsigned char *key, size_t keylen)
{
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
ctx->key_set = 1;
memcpy(&actx->plat.s390x.param.kma.k, key, keylen);
actx->plat.s390x.fc = S390X_AES_FC(keylen);
if (!ctx->enc)
actx->plat.s390x.fc |= S390X_DECRYPT;
return 1;
}
static int s390x_aes_gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv,
size_t ivlen)
{
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
kma->t.g[0] = 0;
kma->t.g[1] = 0;
kma->tpcl = 0;
kma->taadl = 0;
actx->plat.s390x.mreslen = 0;
actx->plat.s390x.areslen = 0;
actx->plat.s390x.kreslen = 0;
if (ivlen == GCM_IV_DEFAULT_SIZE) {
memcpy(&kma->j0, iv, ivlen);
kma->j0.w[3] = 1;
kma->cv.w = 1;
} else {
unsigned long long ivbits = ivlen << 3;
size_t len = S390X_gcm_ivpadlen(ivlen);
unsigned char iv_zero_pad[S390X_gcm_ivpadlen(GCM_IV_MAX_SIZE)];
/*
* The IV length needs to be zero padded to be a multiple of 16 bytes
* followed by 8 bytes of zeros and 8 bytes for the IV length.
* The GHASH of this value can then be calculated.
*/
memcpy(iv_zero_pad, iv, ivlen);
memset(iv_zero_pad + ivlen, 0, len - ivlen);
memcpy(iv_zero_pad + len - sizeof(ivbits), &ivbits, sizeof(ivbits));
/*
* Calculate the ghash of the iv - the result is stored into the tag
* param.
*/
s390x_kma(iv_zero_pad, len, NULL, 0, NULL, actx->plat.s390x.fc, kma);
actx->plat.s390x.fc |= S390X_KMA_HS; /* The hash subkey is set */
/* Copy the 128 bit GHASH result into J0 and clear the tag */
kma->j0.g[0] = kma->t.g[0];
kma->j0.g[1] = kma->t.g[1];
kma->t.g[0] = 0;
kma->t.g[1] = 0;
/* Set the 32 bit counter */
kma->cv.w = kma->j0.w[3];
}
return 1;
}
static int s390x_aes_gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag)
{
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
unsigned char out[AES_BLOCK_SIZE];
int rc;
kma->taadl <<= 3;
kma->tpcl <<= 3;
s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen,
actx->plat.s390x.mres, actx->plat.s390x.mreslen, out,
actx->plat.s390x.fc | S390X_KMA_LAAD | S390X_KMA_LPC, kma);
/* gctx->mres already returned to the caller */
OPENSSL_cleanse(out, actx->plat.s390x.mreslen);
if (ctx->enc) {
ctx->taglen = GCM_TAG_MAX_SIZE;
memcpy(tag, kma->t.b, ctx->taglen);
rc = 1;
} else {
rc = (CRYPTO_memcmp(tag, kma->t.b, ctx->taglen) == 0);
}
return rc;
}
static int s390x_aes_gcm_one_shot(PROV_GCM_CTX *ctx,
unsigned char *aad, size_t aad_len,
const unsigned char *in, size_t in_len,
unsigned char *out,
unsigned char *tag, size_t taglen)
{
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
int rc;
kma->taadl = aad_len << 3;
kma->tpcl = in_len << 3;
s390x_kma(aad, aad_len, in, in_len, out,
actx->plat.s390x.fc | S390X_KMA_LAAD | S390X_KMA_LPC, kma);
if (ctx->enc) {
memcpy(tag, kma->t.b, taglen);
rc = 1;
} else {
rc = (CRYPTO_memcmp(tag, kma->t.b, taglen) == 0);
}
return rc;
}
/*
* Process additional authenticated data. Returns 1 on success. Code is
* big-endian.
*/
static int s390x_aes_gcm_aad_update(PROV_GCM_CTX *ctx,
const unsigned char *aad, size_t len)
{
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
unsigned long long alen;
int n, rem;
/* If already processed pt/ct then error */
if (kma->tpcl != 0)
return 0;
/* update the total aad length */
alen = kma->taadl + len;
if (alen > (U64(1) << 61) || (sizeof(len) == 8 && alen < len))
return 0;
kma->taadl = alen;
/* check if there is any existing aad data from a previous add */
n = actx->plat.s390x.areslen;
if (n) {
/* add additional data to a buffer until it has 16 bytes */
while (n && len) {
actx->plat.s390x.ares[n] = *aad;
++aad;
--len;
n = (n + 1) & 0xf;
}
/* ctx->ares contains a complete block if offset has wrapped around */
if (!n) {
s390x_kma(actx->plat.s390x.ares, 16, NULL, 0, NULL,
actx->plat.s390x.fc, kma);
actx->plat.s390x.fc |= S390X_KMA_HS;
}
actx->plat.s390x.areslen = n;
}
/* If there are leftover bytes (< 128 bits) save them for next time */
rem = len & 0xf;
/* Add any remaining 16 byte blocks (128 bit each) */
len &= ~(size_t)0xf;
if (len) {
s390x_kma(aad, len, NULL, 0, NULL, actx->plat.s390x.fc, kma);
actx->plat.s390x.fc |= S390X_KMA_HS;
aad += len;
}
if (rem) {
actx->plat.s390x.areslen = rem;
do {
--rem;
actx->plat.s390x.ares[rem] = aad[rem];
} while (rem);
}
return 1;
}
/*-
* En/de-crypt plain/cipher-text and authenticate ciphertext. Returns 1 for
* success. Code is big-endian.
*/
static int s390x_aes_gcm_cipher_update(PROV_GCM_CTX *ctx,
const unsigned char *in, size_t len,
unsigned char *out)
{
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma;
const unsigned char *inptr;
unsigned long long mlen;
union {
unsigned int w[4];
unsigned char b[16];
} buf;
size_t inlen;
int n, rem, i;
mlen = kma->tpcl + len;
if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len))
return 0;
kma->tpcl = mlen;
n = actx->plat.s390x.mreslen;
if (n) {
inptr = in;
inlen = len;
while (n && inlen) {
actx->plat.s390x.mres[n] = *inptr;
n = (n + 1) & 0xf;
++inptr;
--inlen;
}
/* ctx->mres contains a complete block if offset has wrapped around */
if (!n) {
s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen,
actx->plat.s390x.mres, 16, buf.b,
actx->plat.s390x.fc | S390X_KMA_LAAD, kma);
actx->plat.s390x.fc |= S390X_KMA_HS;
actx->plat.s390x.areslen = 0;
/* previous call already encrypted/decrypted its remainder,
* see comment below */
n = actx->plat.s390x.mreslen;
while (n) {
*out = buf.b[n];
n = (n + 1) & 0xf;
++out;
++in;
--len;
}
actx->plat.s390x.mreslen = 0;
}
}
rem = len & 0xf;
len &= ~(size_t)0xf;
if (len) {
s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen, in, len, out,
actx->plat.s390x.fc | S390X_KMA_LAAD, kma);
in += len;
out += len;
actx->plat.s390x.fc |= S390X_KMA_HS;
actx->plat.s390x.areslen = 0;
}
/*-
* If there is a remainder, it has to be saved such that it can be
* processed by kma later. However, we also have to do the for-now
* unauthenticated encryption/decryption part here and now...
*/
if (rem) {
if (!actx->plat.s390x.mreslen) {
buf.w[0] = kma->j0.w[0];
buf.w[1] = kma->j0.w[1];
buf.w[2] = kma->j0.w[2];
buf.w[3] = kma->cv.w + 1;
s390x_km(buf.b, 16, actx->plat.s390x.kres,
actx->plat.s390x.fc & 0x1f, &kma->k);
}
n = actx->plat.s390x.mreslen;
for (i = 0; i < rem; i++) {
actx->plat.s390x.mres[n + i] = in[i];
out[i] = in[i] ^ actx->plat.s390x.kres[n + i];
}
actx->plat.s390x.mreslen += rem;
}
return 1;
}
static const PROV_GCM_HW s390x_aes_gcm = {
s390x_aes_gcm_initkey,
s390x_aes_gcm_setiv,
s390x_aes_gcm_aad_update,
s390x_aes_gcm_cipher_update,
s390x_aes_gcm_cipher_final,
s390x_aes_gcm_one_shot
};
const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits)
{
if ((keybits == 128 && S390X_aes_128_gcm_CAPABLE)
|| (keybits == 192 && S390X_aes_192_gcm_CAPABLE)
|| (keybits == 256 && S390X_aes_256_gcm_CAPABLE))
return &s390x_aes_gcm;
return &aes_gcm;
}
@@ -0,0 +1,52 @@
/*
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*-
* Fujitsu SPARC64 X support for AES GCM.
* This file is included by cipher_gcm_hw.c
*/
static int t4_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
size_t keylen)
{
ctr128_f ctr;
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
AES_KEY *ks = &actx->ks.ks;
switch (keylen) {
case 16:
ctr = (ctr128_f)aes128_t4_ctr32_encrypt;
break;
case 24:
ctr = (ctr128_f)aes192_t4_ctr32_encrypt;
break;
case 32:
ctr = (ctr128_f)aes256_t4_ctr32_encrypt;
break;
default:
return 0;
}
GCM_HW_SET_KEY_CTR_FN(ks, aes_t4_set_encrypt_key, aes_t4_encrypt, ctr);
return 1;
}
static const PROV_GCM_HW t4_aes_gcm = {
t4_aes_gcm_initkey,
gcm_setiv,
gcm_aad_update,
gcm_cipher_update,
gcm_cipher_final,
gcm_one_shot
};
const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits)
{
return SPARC_AES_CAPABLE ? &t4_aes_gcm : &aes_gcm;
}
+139
View File
@@ -0,0 +1,139 @@
/*
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "cipher_aes.h"
#include "internal/providercommonerr.h"
static int cipher_hw_aes_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
{
int ret;
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
AES_KEY *ks = &adat->ks.ks;
dat->ks = ks;
if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
&& !dat->enc) {
#ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
ret = HWAES_set_decrypt_key(key, keylen * 8, ks);
dat->block = (block128_f)HWAES_decrypt;
dat->stream.cbc = NULL;
# ifdef HWAES_cbc_encrypt
if (dat->mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
# endif
} else
#endif
#ifdef BSAES_CAPABLE
if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CBC_MODE) {
ret = AES_set_decrypt_key(key, keylen * 8, ks);
dat->block = (block128_f)AES_decrypt;
dat->stream.cbc = (cbc128_f)bsaes_cbc_encrypt;
} else
#endif
#ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
ret = vpaes_set_decrypt_key(key, keylen * 8, ks);
dat->block = (block128_f)vpaes_decrypt;
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
?(cbc128_f)vpaes_cbc_encrypt : NULL;
} else
#endif
{
ret = AES_set_decrypt_key(key, keylen * 8, ks);
dat->block = (block128_f)AES_decrypt;
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
? (cbc128_f)AES_cbc_encrypt : NULL;
}
} else
#ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
ret = HWAES_set_encrypt_key(key, keylen * 8, ks);
dat->block = (block128_f)HWAES_encrypt;
dat->stream.cbc = NULL;
# ifdef HWAES_cbc_encrypt
if (dat->mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
else
# endif
# ifdef HWAES_ctr32_encrypt_blocks
if (dat->mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks;
else
# endif
(void)0; /* terminate potentially open 'else' */
} else
#endif
#ifdef BSAES_CAPABLE
if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CTR_MODE) {
ret = AES_set_encrypt_key(key, keylen * 8, ks);
dat->block = (block128_f)AES_encrypt;
dat->stream.ctr = (ctr128_f)bsaes_ctr32_encrypt_blocks;
} else
#endif
#ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
ret = vpaes_set_encrypt_key(key, keylen * 8, ks);
dat->block = (block128_f)vpaes_encrypt;
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
? (cbc128_f)vpaes_cbc_encrypt : NULL;
} else
#endif
{
ret = AES_set_encrypt_key(key, keylen * 8, ks);
dat->block = (block128_f)AES_encrypt;
dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
? (cbc128_f)AES_cbc_encrypt : NULL;
#ifdef AES_CTR_ASM
if (dat->mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f)AES_ctr32_encrypt;
#endif
}
if (ret < 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_AES_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
#define PROV_CIPHER_HW_aes_mode(mode) \
static const PROV_CIPHER_HW aes_##mode = { \
cipher_hw_aes_initkey, \
cipher_hw_generic_##mode \
}; \
PROV_CIPHER_HW_declare(mode) \
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_##mode(size_t keybits) \
{ \
PROV_CIPHER_HW_select(mode) \
return &aes_##mode; \
}
#if defined(AESNI_CAPABLE)
# include "cipher_aes_hw_aesni.inc"
#elif defined(SPARC_AES_CAPABLE)
# include "cipher_aes_hw_t4.inc"
#elif defined(S390X_aes_128_CAPABLE)
# include "cipher_aes_hw_s390x.inc"
#else
/* The generic case */
# define PROV_CIPHER_HW_declare(mode)
# define PROV_CIPHER_HW_select(mode)
#endif
PROV_CIPHER_HW_aes_mode(cbc)
PROV_CIPHER_HW_aes_mode(ecb)
PROV_CIPHER_HW_aes_mode(ofb128)
PROV_CIPHER_HW_aes_mode(cfb128)
PROV_CIPHER_HW_aes_mode(cfb1)
PROV_CIPHER_HW_aes_mode(cfb8)
PROV_CIPHER_HW_aes_mode(ctr)
@@ -0,0 +1,83 @@
/*
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*-
* AES-NI support for AES modes ecb, cbc, ofb, cfb, ctr.
* This file is included by cipher_aes_hw.c
*/
#define cipher_hw_aesni_ofb128 cipher_hw_generic_ofb128
#define cipher_hw_aesni_cfb128 cipher_hw_generic_cfb128
#define cipher_hw_aesni_cfb8 cipher_hw_generic_cfb8
#define cipher_hw_aesni_cfb1 cipher_hw_generic_cfb1
#define cipher_hw_aesni_ctr cipher_hw_generic_ctr
static int cipher_hw_aesni_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
{
int ret;
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
AES_KEY *ks = &adat->ks.ks;
dat->ks = ks;
if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
&& !dat->enc) {
ret = aesni_set_decrypt_key(key, keylen * 8, ks);
dat->block = (block128_f) aesni_decrypt;
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) aesni_cbc_encrypt : NULL;
} else {
ret = aesni_set_encrypt_key(key, keylen * 8, ks);
dat->block = (block128_f) aesni_encrypt;
if (dat->mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt;
else if (dat->mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
else
dat->stream.cbc = NULL;
}
if (ret < 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_AES_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
static int cipher_hw_aesni_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
const AES_KEY *ks = ctx->ks;
aesni_cbc_encrypt(in, out, len, ks, ctx->iv, ctx->enc);
return 1;
}
static int cipher_hw_aesni_ecb(PROV_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
if (len < ctx->blocksize)
return 1;
aesni_ecb_encrypt(in, out, len, ctx->ks, ctx->enc);
return 1;
}
#define PROV_CIPHER_HW_declare(mode) \
static const PROV_CIPHER_HW aesni_##mode = { \
cipher_hw_aesni_initkey, \
cipher_hw_aesni_##mode \
};
#define PROV_CIPHER_HW_select(mode) \
if (AESNI_CAPABLE) \
return &aesni_##mode;
@@ -0,0 +1,203 @@
/*
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* IBM S390X support for AES modes ecb, cbc, ofb, cfb, ctr.
* This file is included by cipher_aes_hw.c
*/
#include "s390x_arch.h"
#define s390x_aes_cbc_initkey cipher_hw_aes_initkey
#define s390x_aes_cfb1_initkey cipher_hw_aes_initkey
#define s390x_aes_ctr_initkey cipher_hw_aes_initkey
#define s390x_aes_cbc_cipher_hw cipher_hw_generic_cbc
#define s390x_aes_cfb1_cipher_hw cipher_hw_generic_cfb1
#define s390x_aes_ctr_cipher_hw cipher_hw_generic_ctr
#define S390X_aes_128_ofb128_CAPABLE S390X_aes_128_ofb_CAPABLE
#define S390X_aes_192_ofb128_CAPABLE S390X_aes_192_ofb_CAPABLE
#define S390X_aes_256_ofb128_CAPABLE S390X_aes_256_ofb_CAPABLE
#define S390X_aes_128_cfb128_CAPABLE S390X_aes_128_cfb_CAPABLE
#define S390X_aes_192_cfb128_CAPABLE S390X_aes_192_cfb_CAPABLE
#define S390X_aes_256_cfb128_CAPABLE S390X_aes_256_cfb_CAPABLE
static int s390x_aes_ecb_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
adat->plat.s390x.fc = S390X_AES_FC(keylen);
if (!dat->enc)
adat->plat.s390x.fc |= S390X_DECRYPT;
memcpy(adat->plat.s390x.param.km.k, key, keylen);
return 1;
}
static int s390x_aes_ecb_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
s390x_km(in, len, out, adat->plat.s390x.fc, &adat->plat.s390x.param.km);
return 1;
}
static int s390x_aes_ofb128_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
adat->plat.s390x.fc = S390X_AES_FC(keylen);
adat->plat.s390x.res = 0;
return 1;
}
static int s390x_aes_ofb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
int n = adat->plat.s390x.res;
int rem;
while (n && len) {
*out = *in ^ adat->plat.s390x.param.kmo_kmf.cv[n];
n = (n + 1) & 0xf;
--len;
++in;
++out;
}
rem = len & 0xf;
len &= ~(size_t)0xf;
if (len) {
s390x_kmo(in, len, out, adat->plat.s390x.fc,
&adat->plat.s390x.param.kmo_kmf);
out += len;
in += len;
}
if (rem) {
s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16,
adat->plat.s390x.param.kmo_kmf.cv, adat->plat.s390x.fc,
adat->plat.s390x.param.kmo_kmf.k);
while (rem--) {
out[n] = in[n] ^ adat->plat.s390x.param.kmo_kmf.cv[n];
++n;
}
}
adat->plat.s390x.res = n;
return 1;
}
static int s390x_aes_cfb128_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
adat->plat.s390x.fc = S390X_AES_FC(keylen);
adat->plat.s390x.fc |= 16 << 24; /* 16 bytes cipher feedback */
if (!dat->enc)
adat->plat.s390x.fc |= S390X_DECRYPT;
adat->plat.s390x.res = 0;
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
return 1;
}
static int s390x_aes_cfb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
int n = adat->plat.s390x.res;
int rem;
unsigned char tmp;
while (n && len) {
tmp = *in;
*out = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? *out : tmp;
n = (n + 1) & 0xf;
--len;
++in;
++out;
}
rem = len & 0xf;
len &= ~(size_t)0xf;
if (len) {
s390x_kmf(in, len, out, adat->plat.s390x.fc,
&adat->plat.s390x.param.kmo_kmf);
out += len;
in += len;
}
if (rem) {
s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16,
adat->plat.s390x.param.kmo_kmf.cv,
S390X_AES_FC(dat->keylen), adat->plat.s390x.param.kmo_kmf.k);
while (rem--) {
tmp = in[n];
out[n] = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? out[n] : tmp;
++n;
}
}
adat->plat.s390x.res = n;
return 1;
}
static int s390x_aes_cfb8_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
adat->plat.s390x.fc = S390X_AES_FC(keylen);
adat->plat.s390x.fc |= 1 << 24; /* 1 byte cipher feedback */
if (!dat->enc)
adat->plat.s390x.fc |= S390X_DECRYPT;
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen);
return 1;
}
static int s390x_aes_cfb8_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
s390x_kmf(in, len, out, adat->plat.s390x.fc,
&adat->plat.s390x.param.kmo_kmf);
return 1;
}
#define PROV_CIPHER_HW_declare(mode) \
static const PROV_CIPHER_HW s390x_aes_##mode = { \
s390x_aes_##mode##_initkey, \
s390x_aes_##mode##_cipher_hw \
};
#define PROV_CIPHER_HW_select(mode) \
if ((keybits == 128 && S390X_aes_128_##mode##_CAPABLE) \
|| (keybits == 192 && S390X_aes_192_##mode##_CAPABLE) \
|| (keybits == 256 && S390X_aes_256_##mode##_CAPABLE)) \
return &s390x_aes_##mode;
@@ -0,0 +1,95 @@
/*
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*-
* Sparc t4 support for AES modes ecb, cbc, ofb, cfb, ctr.
* This file is included by cipher_aes_hw.c
*/
static int cipher_hw_aes_t4_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
{
int ret, bits;
PROV_AES_CTX *adat = (PROV_AES_CTX *)dat;
AES_KEY *ks = &adat->ks.ks;
dat->ks = (const void *)ks; /* used by cipher_hw_generic_XXX */
bits = keylen * 8;
if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
&& !dat->enc) {
ret = 0;
aes_t4_set_decrypt_key(key, bits, ks);
dat->block = (block128_f)aes_t4_decrypt;
switch (bits) {
case 128:
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
(cbc128_f)aes128_t4_cbc_decrypt : NULL;
break;
case 192:
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
(cbc128_f)aes192_t4_cbc_decrypt : NULL;
break;
case 256:
dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
(cbc128_f)aes256_t4_cbc_decrypt : NULL;
break;
default:
ret = -1;
}
} else {
ret = 0;
aes_t4_set_encrypt_key(key, bits, ks);
dat->block = (block128_f)aes_t4_encrypt;
switch (bits) {
case 128:
if (dat->mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f)aes128_t4_cbc_encrypt;
else if (dat->mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f)aes128_t4_ctr32_encrypt;
else
dat->stream.cbc = NULL;
break;
case 192:
if (dat->mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f)aes192_t4_cbc_encrypt;
else if (dat->mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f)aes192_t4_ctr32_encrypt;
else
dat->stream.cbc = NULL;
break;
case 256:
if (dat->mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f)aes256_t4_cbc_encrypt;
else if (dat->mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f)aes256_t4_ctr32_encrypt;
else
dat->stream.cbc = NULL;
break;
default:
ret = -1;
}
}
if (ret < 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_AES_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
#define PROV_CIPHER_HW_declare(mode) \
static const PROV_CIPHER_HW aes_t4_##mode = { \
cipher_hw_aes_t4_initkey, \
cipher_hw_generic_##mode \
};
#define PROV_CIPHER_HW_select(mode) \
if (SPARC_AES_CAPABLE) \
return &aes_t4_##mode;
+246
View File
@@ -0,0 +1,246 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "cipher_aes.h"
#include "internal/providercommonerr.h"
#include "internal/provider_algs.h"
/* AES wrap with padding has IV length of 4, without padding 8 */
#define AES_WRAP_PAD_IVLEN 4
#define AES_WRAP_NOPAD_IVLEN 8
/* TODO(3.0) Figure out what flags need to be passed */
#define WRAP_FLAGS (EVP_CIPH_WRAP_MODE \
| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_FLAG_DEFAULT_ASN1)
typedef size_t (*aeswrap_fn)(void *key, const unsigned char *iv,
unsigned char *out, const unsigned char *in,
size_t inlen, block128_f block);
static OSSL_OP_cipher_encrypt_init_fn aes_wrap_einit;
static OSSL_OP_cipher_decrypt_init_fn aes_wrap_dinit;
static OSSL_OP_cipher_update_fn aes_wrap_cipher;
static OSSL_OP_cipher_final_fn aes_wrap_final;
static OSSL_OP_cipher_freectx_fn aes_wrap_freectx;
typedef struct prov_aes_wrap_ctx_st {
PROV_CIPHER_CTX base;
union {
OSSL_UNION_ALIGN;
AES_KEY ks;
} ks;
unsigned int iv_set : 1;
aeswrap_fn wrapfn;
} PROV_AES_WRAP_CTX;
static void *aes_wrap_newctx(size_t kbits, size_t blkbits,
size_t ivbits, unsigned int mode, uint64_t flags)
{
PROV_AES_WRAP_CTX *wctx = OPENSSL_zalloc(sizeof(*wctx));
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)wctx;
if (ctx != NULL) {
cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags,
NULL, NULL);
ctx->pad = (ctx->ivlen == AES_WRAP_PAD_IVLEN);
}
return wctx;
}
static void aes_wrap_freectx(void *vctx)
{
PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
OPENSSL_cleanse(ctx->iv, sizeof(ctx->iv));
OPENSSL_clear_free(wctx, sizeof(*wctx));
}
static int aes_wrap_init(void *vctx, const unsigned char *key,
size_t keylen, const unsigned char *iv,
size_t ivlen, int enc)
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
ctx->enc = enc;
ctx->block = enc ? (block128_f)AES_encrypt : (block128_f)AES_decrypt;
if (ctx->pad)
wctx->wrapfn = enc ? CRYPTO_128_wrap_pad : CRYPTO_128_unwrap_pad;
else
wctx->wrapfn = enc ? CRYPTO_128_wrap : CRYPTO_128_unwrap;
if (iv != NULL) {
ctx->ivlen = ivlen;
memcpy(ctx->iv, iv, ivlen);
wctx->iv_set = 1;
}
if (key != NULL) {
if (keylen != ctx->keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
if (ctx->enc)
AES_set_encrypt_key(key, keylen * 8, &wctx->ks.ks);
else
AES_set_decrypt_key(key, keylen * 8, &wctx->ks.ks);
}
return 1;
}
static int aes_wrap_einit(void *ctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen)
{
return aes_wrap_init(ctx, key, keylen, iv, ivlen, 1);
}
static int aes_wrap_dinit(void *ctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen)
{
return aes_wrap_init(ctx, key, keylen, iv, ivlen, 0);
}
static int aes_wrap_cipher_internal(void *vctx, unsigned char *out,
const unsigned char *in, size_t inlen)
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
size_t rv;
int pad = ctx->pad;
/* No final operation so always return zero length */
if (in == NULL)
return 0;
/* Input length must always be non-zero */
if (inlen == 0)
return -1;
/* If decrypting need at least 16 bytes and multiple of 8 */
if (!ctx->enc && (inlen < 16 || inlen & 0x7))
return -1;
/* If not padding input must be multiple of 8 */
if (!pad && inlen & 0x7)
return -1;
if (out == NULL) {
if (ctx->enc) {
/* If padding round up to multiple of 8 */
if (pad)
inlen = (inlen + 7) / 8 * 8;
/* 8 byte prefix */
return inlen + 8;
} else {
/*
* If not padding output will be exactly 8 bytes smaller than
* input. If padding it will be at least 8 bytes smaller but we
* don't know how much.
*/
return inlen - 8;
}
}
rv = wctx->wrapfn(&wctx->ks.ks, wctx->iv_set ? ctx->iv : NULL, out, in,
inlen, ctx->block);
return rv ? (int)rv : -1;
}
static int aes_wrap_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
*outl = 0;
return 1;
}
static int aes_wrap_cipher(void *vctx,
unsigned char *out, size_t *outl, size_t outsize,
const unsigned char *in, size_t inl)
{
PROV_AES_WRAP_CTX *ctx = (PROV_AES_WRAP_CTX *)vctx;
size_t len;
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return -1;
}
len = aes_wrap_cipher_internal(ctx, out, in, inl);
if (len == 0)
return -1;
*outl = len;
return 1;
}
static int aes_wrap_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
const OSSL_PARAM *p;
size_t keylen = 0;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL) {
if (!OSSL_PARAM_get_size_t(p, &keylen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (ctx->keylen != keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
}
return 1;
}
#define IMPLEMENT_cipher(mode, fname, UCMODE, flags, kbits, blkbits, ivbits) \
static OSSL_OP_cipher_get_params_fn aes_##kbits##_##fname##_get_params; \
static int aes_##kbits##_##fname##_get_params(OSSL_PARAM params[]) \
{ \
return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
flags, kbits, blkbits, ivbits); \
} \
static OSSL_OP_cipher_newctx_fn aes_##kbits##fname##_newctx; \
static void *aes_##kbits##fname##_newctx(void *provctx) \
{ \
return aes_##mode##_newctx(kbits, blkbits, ivbits, \
EVP_CIPH_##UCMODE##_MODE, flags); \
} \
const OSSL_DISPATCH aes##kbits##fname##_functions[] = { \
{ OSSL_FUNC_CIPHER_NEWCTX, \
(void (*)(void))aes_##kbits##fname##_newctx }, \
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_##mode##_einit }, \
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_##mode##_dinit }, \
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_##mode##_cipher }, \
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_##mode##_final }, \
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_##mode##_freectx }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
(void (*)(void))aes_##kbits##_##fname##_get_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
(void (*)(void))cipher_generic_gettable_params }, \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
(void (*)(void))cipher_generic_get_ctx_params }, \
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
(void (*)(void))aes_wrap_set_ctx_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
(void (*)(void))cipher_generic_gettable_ctx_params }, \
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
(void (*)(void))cipher_generic_settable_ctx_params }, \
{ 0, NULL } \
}
IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_NOPAD_IVLEN * 8);
IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_NOPAD_IVLEN * 8);
IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_NOPAD_IVLEN * 8);
IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_PAD_IVLEN * 8);
IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_PAD_IVLEN * 8);
IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_PAD_IVLEN * 8);
+284
View File
@@ -0,0 +1,284 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "cipher_aes_xts.h"
#include "internal/provider_algs.h"
#include "internal/providercommonerr.h"
/* TODO (3.0) Figure out what flags need to be set */
#define AES_XTS_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV \
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
| EVP_CIPH_CUSTOM_COPY)
#define AES_XTS_IV_BITS 128
#define AES_XTS_BLOCK_BITS 8
#ifdef FIPS_MODE
static const int allow_insecure_decrypt = 0;
#else
static const int allow_insecure_decrypt = 1;
#endif /* FIPS_MODE */
/* forward declarations */
static OSSL_OP_cipher_encrypt_init_fn aes_xts_einit;
static OSSL_OP_cipher_decrypt_init_fn aes_xts_dinit;
static OSSL_OP_cipher_update_fn aes_xts_stream_update;
static OSSL_OP_cipher_final_fn aes_xts_stream_final;
static OSSL_OP_cipher_cipher_fn aes_xts_cipher;
static OSSL_OP_cipher_freectx_fn aes_xts_freectx;
static OSSL_OP_cipher_dupctx_fn aes_xts_dupctx;
static OSSL_OP_cipher_set_ctx_params_fn aes_xts_set_ctx_params;
static OSSL_OP_cipher_settable_ctx_params_fn aes_xts_settable_ctx_params;
/*
* Verify that the two keys are different.
*
* This addresses the vulnerability described in Rogaway's
* September 2004 paper:
*
* "Efficient Instantiations of Tweakable Blockciphers and
* Refinements to Modes OCB and PMAC".
* (http://web.cs.ucdavis.edu/~rogaway/papers/offsets.pdf)
*
* FIPS 140-2 IG A.9 XTS-AES Key Generation Requirements states
* that:
* "The check for Key_1 != Key_2 shall be done at any place
* BEFORE using the keys in the XTS-AES algorithm to process
* data with them."
*/
static int aes_xts_check_keys_differ(const unsigned char *key, size_t bytes,
int enc)
{
if ((!allow_insecure_decrypt || enc)
&& CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DUPLICATED_KEYS);
return 0;
}
return 1;
}
/*-
* Provider dispatch functions
*/
static int aes_xts_init(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen, int enc)
{
PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)vctx;
PROV_CIPHER_CTX *ctx = &xctx->base;
ctx->enc = enc;
if (iv != NULL) {
if (ivlen != ctx->ivlen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
memcpy(ctx->iv, iv, ivlen);
xctx->iv_set = 1;
}
if (key != NULL) {
if (keylen != ctx->keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
if (!aes_xts_check_keys_differ(key, keylen / 2, enc))
return 0;
return ctx->hw->init(ctx, key, keylen);
}
return 1;
}
static int aes_xts_einit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen)
{
return aes_xts_init(vctx, key, keylen, iv, ivlen, 1);
}
static int aes_xts_dinit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen)
{
return aes_xts_init(vctx, key, keylen, iv, ivlen, 0);
}
static void *aes_xts_newctx(void *provctx, unsigned int mode, uint64_t flags,
size_t kbits, size_t blkbits, size_t ivbits)
{
PROV_AES_XTS_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL) {
cipher_generic_initkey(&ctx->base, kbits, blkbits, ivbits, mode, flags,
PROV_CIPHER_HW_aes_xts(kbits), NULL);
}
return ctx;
}
static void aes_xts_freectx(void *vctx)
{
PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static void *aes_xts_dupctx(void *vctx)
{
PROV_AES_XTS_CTX *in = (PROV_AES_XTS_CTX *)vctx;
PROV_AES_XTS_CTX *ret = NULL;
if (in->xts.key1 != NULL) {
if (in->xts.key1 != &in->ks1)
return NULL;
}
if (in->xts.key2 != NULL) {
if (in->xts.key2 != &in->ks2)
return NULL;
}
ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return NULL;
}
*ret = *in;
return ret;
}
static int aes_xts_cipher(void *vctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in, size_t inl)
{
PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;
if (ctx->xts.key1 == NULL
|| ctx->xts.key2 == NULL
|| !ctx->iv_set
|| out == NULL
|| in == NULL
|| inl < AES_BLOCK_SIZE)
return 0;
/*
* Impose a limit of 2^20 blocks per data unit as specifed by
* IEEE Std 1619-2018. The earlier and obsolete IEEE Std 1619-2007
* indicated that this was a SHOULD NOT rather than a MUST NOT.
* NIST SP 800-38E mandates the same limit.
*/
if (inl > XTS_MAX_BLOCKS_PER_DATA_UNIT * AES_BLOCK_SIZE) {
ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE);
return 0;
}
if (ctx->stream != NULL)
(*ctx->stream)(in, out, inl, ctx->xts.key1, ctx->xts.key2, ctx->base.iv);
else if (CRYPTO_xts128_encrypt(&ctx->xts, ctx->base.iv, in, out, inl,
ctx->base.enc))
return 0;
*outl = inl;
return 1;
}
static int aes_xts_stream_update(void *vctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in,
size_t inl)
{
PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!aes_xts_cipher(ctx, out, outl, outsize, in, inl)) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
return 1;
}
static int aes_xts_stream_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
*outl = 0;
return 1;
}
static const OSSL_PARAM aes_xts_known_settable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_END
};
static const OSSL_PARAM *aes_xts_settable_ctx_params(void)
{
return aes_xts_known_settable_ctx_params;
}
static int aes_xts_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
const OSSL_PARAM *p;
/*
* TODO(3.0) We need a general solution for handling missing parameters
* inside set_params and get_params methods.
*/
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL) {
size_t keylen;
if (!OSSL_PARAM_get_size_t(p, &keylen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
/* The key length can not be modified for xts mode */
if (keylen != ctx->keylen)
return 0;
}
return 1;
}
#define IMPLEMENT_cipher(lcmode, UCMODE, kbits, flags) \
static OSSL_OP_cipher_get_params_fn aes_##kbits##_##lcmode##_get_params; \
static int aes_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
{ \
return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
flags, 2 * kbits, AES_XTS_BLOCK_BITS, \
AES_XTS_IV_BITS); \
} \
static OSSL_OP_cipher_newctx_fn aes_##kbits##_xts_newctx; \
static void *aes_##kbits##_xts_newctx(void *provctx) \
{ \
return aes_xts_newctx(provctx, EVP_CIPH_##UCMODE##_MODE, flags, 2 * kbits, \
AES_XTS_BLOCK_BITS, AES_XTS_IV_BITS); \
} \
const OSSL_DISPATCH aes##kbits##xts_functions[] = { \
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##kbits##_xts_newctx }, \
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_xts_einit }, \
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_xts_dinit }, \
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_xts_stream_update }, \
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_xts_stream_final }, \
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_xts_cipher }, \
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_xts_freectx }, \
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_xts_dupctx }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
(void (*)(void))aes_##kbits##_##lcmode##_get_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
(void (*)(void))cipher_generic_gettable_params }, \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
(void (*)(void))cipher_generic_get_ctx_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
(void (*)(void))cipher_generic_gettable_ctx_params }, \
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
(void (*)(void))aes_xts_set_ctx_params }, \
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
(void (*)(void))aes_xts_settable_ctx_params }, \
{ 0, NULL } \
}
IMPLEMENT_cipher(xts, XTS, 256, AES_XTS_FLAGS);
IMPLEMENT_cipher(xts, XTS, 128, AES_XTS_FLAGS);
+29
View File
@@ -0,0 +1,29 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/aes.h>
#include "internal/ciphers/ciphercommon.h"
PROV_CIPHER_FUNC(void, xts_stream,
(const unsigned char *in, unsigned char *out, size_t len,
const AES_KEY *key1, const AES_KEY *key2,
const unsigned char iv[16]));
typedef struct prov_aes_xts_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
AES_KEY ks;
} ks1, ks2; /* AES key schedules to use */
XTS128_CONTEXT xts;
OSSL_xts_stream_fn stream;
unsigned int iv_set : 1; /* Set if an iv is set */
} PROV_AES_XTS_CTX;
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_xts(size_t keybits);
@@ -0,0 +1,153 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "cipher_aes_xts.h"
#define XTS_SET_KEY_FN(fn_set_enc_key, fn_set_dec_key, \
fn_block_enc, fn_block_dec, \
fn_stream_enc, fn_stream_dec) { \
size_t bytes = keylen / 2; \
size_t bits = bytes * 8; \
\
if (ctx->enc) { \
fn_set_enc_key(key, bits, &xctx->ks1.ks); \
xctx->xts.block1 = (block128_f)fn_block_enc; \
} else { \
fn_set_dec_key(key, bits, &xctx->ks1.ks); \
xctx->xts.block1 = (block128_f)fn_block_dec; \
} \
fn_set_enc_key(key + bytes, bits, &xctx->ks2.ks); \
xctx->xts.block2 = (block128_f)fn_block_enc; \
xctx->xts.key1 = &xctx->ks1; \
xctx->xts.key2 = &xctx->ks2; \
xctx->stream = ctx->enc ? fn_stream_enc : fn_stream_dec; \
}
static int cipher_hw_aes_xts_generic_initkey(PROV_CIPHER_CTX *ctx,
const unsigned char *key,
size_t keylen)
{
PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx;
OSSL_xts_stream_fn stream_enc = NULL;
OSSL_xts_stream_fn stream_dec = NULL;
#ifdef AES_XTS_ASM
stream_enc = AES_xts_encrypt;
stream_dec = AES_xts_decrypt;
#endif /* AES_XTS_ASM */
#ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
# ifdef HWAES_xts_encrypt
stream_enc = HWAES_xts_encrypt;
# endif /* HWAES_xts_encrypt */
# ifdef HWAES_xts_decrypt
stream_dec = HWAES_xts_decrypt;
# endif /* HWAES_xts_decrypt */
XTS_SET_KEY_FN(HWAES_set_encrypt_key, HWAES_set_decrypt_key,
HWAES_encrypt, HWAES_decrypt,
stream_enc, stream_dec);
} else
#endif /* HWAES_CAPABLE */
#ifdef BSAES_CAPABLE
if (BSAES_CAPABLE) {
stream_enc = bsaes_xts_encrypt;
stream_dec = bsaes_xts_decrypt;
}
#endif /* BSAES_CAPABLE */
#ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
XTS_SET_KEY_FN(vpaes_set_encrypt_key, vpaes_set_decrypt_key,
vpaes_encrypt, vpaes_decrypt, stream_enc, stream_dec);
} else
#endif /* VPAES_CAPABLE */
{
XTS_SET_KEY_FN(AES_set_encrypt_key, AES_set_decrypt_key,
AES_encrypt, AES_decrypt, stream_enc, stream_dec);
}
return 1;
}
#if defined(AESNI_CAPABLE)
static int cipher_hw_aesni_xts_initkey(PROV_CIPHER_CTX *ctx,
const unsigned char *key, size_t keylen)
{
PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx;
XTS_SET_KEY_FN(aesni_set_encrypt_key, aesni_set_decrypt_key,
aesni_encrypt, aesni_decrypt,
aesni_xts_encrypt, aesni_xts_decrypt);
return 1;
}
# define PROV_CIPHER_HW_declare_xts() \
static const PROV_CIPHER_HW aesni_xts = { \
cipher_hw_aesni_xts_initkey, \
NULL \
};
# define PROV_CIPHER_HW_select_xts() \
if (AESNI_CAPABLE) \
return &aesni_xts;
# elif defined(SPARC_AES_CAPABLE)
static int cipher_hw_aes_xts_t4_initkey(PROV_CIPHER_CTX *ctx,
const unsigned char *key, size_t keylen)
{
PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx;
OSSL_xts_stream_fn stream_enc = NULL;
OSSL_xts_stream_fn stream_dec = NULL;
/* Note: keylen is the size of 2 keys */
switch (keylen) {
case 32:
stream_enc = aes128_t4_xts_encrypt;
stream_dec = aes128_t4_xts_decrypt;
break;
case 64:
stream_enc = aes256_t4_xts_encrypt;
stream_dec = aes256_t4_xts_decrypt;
break;
default:
return 0;
}
XTS_SET_KEY_FN(aes_t4_set_encrypt_key, aes_t4_set_decrypt_key,
aes_t4_encrypt, aes_t4_decrypt,
stream_enc, stream_dec);
return 1;
}
# define PROV_CIPHER_HW_declare_xts() \
static const PROV_CIPHER_HW aes_xts_t4 = { \
cipher_hw_aes_xts_t4_initkey, \
NULL \
};
# define PROV_CIPHER_HW_select_xts() \
if (SPARC_AES_CAPABLE) \
return &aes_xts_t4;
# else
/* The generic case */
# define PROV_CIPHER_HW_declare_xts()
# define PROV_CIPHER_HW_select_xts()
#endif
static const PROV_CIPHER_HW aes_generic_xts = {
cipher_hw_aes_xts_generic_initkey,
NULL
};
PROV_CIPHER_HW_declare_xts()
const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_xts(size_t keybits)
{
PROV_CIPHER_HW_select_xts()
return &aes_generic_xts;
}
+426
View File
@@ -0,0 +1,426 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Dispatch functions for ccm mode */
#include "cipher_locl.h"
#include "internal/ciphers/cipher_ccm.h"
#include "internal/providercommonerr.h"
static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out,
size_t *padlen, const unsigned char *in,
size_t len);
static int ccm_tls_init(PROV_CCM_CTX *ctx, unsigned char *aad, size_t alen)
{
size_t len;
if (alen != EVP_AEAD_TLS1_AAD_LEN)
return 0;
/* Save the aad for later use. */
memcpy(ctx->buf, aad, alen);
ctx->tls_aad_len = alen;
len = ctx->buf[alen - 2] << 8 | ctx->buf[alen - 1];
if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN)
return 0;
/* Correct length for explicit iv. */
len -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
if (!ctx->enc) {
if (len < ctx->m)
return 0;
/* Correct length for tag. */
len -= ctx->m;
}
ctx->buf[alen - 2] = (unsigned char)(len >> 8);
ctx->buf[alen - 1] = (unsigned char)(len & 0xff);
/* Extra padding: tag appended to record. */
return ctx->m;
}
static int ccm_tls_iv_set_fixed(PROV_CCM_CTX *ctx, unsigned char *fixed,
size_t flen)
{
if (flen != EVP_CCM_TLS_FIXED_IV_LEN)
return 0;
/* Copy to first part of the iv. */
memcpy(ctx->iv, fixed, flen);
return 1;
}
static size_t ccm_get_ivlen(PROV_CCM_CTX *ctx)
{
return 15 - ctx->l;
}
int ccm_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
const OSSL_PARAM *p;
size_t sz;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if ((p->data_size & 1) || (p->data_size < 4) || p->data_size > 16) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAGLEN);
return 0;
}
if (p->data != NULL) {
if (ctx->enc) {
ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_NEEDED);
return 0;
}
memcpy(ctx->buf, p->data, p->data_size);
ctx->tag_set = 1;
}
ctx->m = p->data_size;
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN);
if (p != NULL) {
size_t ivlen;
if (!OSSL_PARAM_get_size_t(p, &sz)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
ivlen = 15 - sz;
if (ivlen < 2 || ivlen > 8) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
return 0;
}
ctx->l = ivlen;
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
sz = ccm_tls_init(ctx, p->data, p->data_size);
if (sz == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA);
return 0;
}
ctx->tls_aad_pad_sz = sz;
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (ccm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
return 0;
}
}
return 1;
}
int ccm_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
OSSL_PARAM *p;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ccm_get_ivlen(ctx))) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
if (p != NULL) {
size_t m = ctx->m;
if (!OSSL_PARAM_set_size_t(p, m)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
if (p != NULL) {
if (ccm_get_ivlen(ctx) != p->data_size) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
return 0;
}
if (!OSSL_PARAM_set_octet_string(p, ctx->iv, p->data_size)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
if (p != NULL) {
if (!ctx->enc || !ctx->tag_set) {
ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOTSET);
return 0;
}
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
if (!ctx->hw->gettag(ctx, p->data, p->data_size))
return 0;
ctx->tag_set = 0;
ctx->iv_set = 0;
ctx->len_set = 0;
}
return 1;
}
static int ccm_init(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen, int enc)
{
PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
ctx->enc = enc;
if (iv != NULL) {
if (ivlen != ccm_get_ivlen(ctx)) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
return 0;
}
memcpy(ctx->iv, iv, ivlen);
ctx->iv_set = 1;
}
if (key != NULL) {
if (keylen != ctx->keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN);
return 0;
}
return ctx->hw->setkey(ctx, key, keylen);
}
return 1;
}
int ccm_einit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen)
{
return ccm_init(vctx, key, keylen, iv, ivlen, 1);
}
int ccm_dinit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen)
{
return ccm_init(vctx, key, keylen, iv, ivlen, 0);
}
int ccm_stream_update(void *vctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in,
size_t inl)
{
PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!ccm_cipher_internal(ctx, out, outl, in, inl)) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
return 1;
}
int ccm_stream_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
int i;
i = ccm_cipher_internal(ctx, out, outl, NULL, 0);
if (i <= 0)
return 0;
*outl = 0;
return 1;
}
int ccm_cipher(void *vctx,
unsigned char *out, size_t *outl, size_t outsize,
const unsigned char *in, size_t inl)
{
PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return -1;
}
if (ccm_cipher_internal(ctx, out, outl, in, inl) <= 0)
return -1;
*outl = inl;
return 1;
}
/* Copy the buffered iv */
static int ccm_set_iv(PROV_CCM_CTX *ctx, size_t mlen)
{
const PROV_CCM_HW *hw = ctx->hw;
if (!hw->setiv(ctx, ctx->iv, ccm_get_ivlen(ctx), mlen))
return 0;
ctx->len_set = 1;
return 1;
}
static int ccm_tls_cipher(PROV_CCM_CTX *ctx,
unsigned char *out, size_t *padlen,
const unsigned char *in, size_t len)
{
int rv = 0;
size_t olen = 0;
/* Encrypt/decrypt must be performed in place */
if (out != in || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)ctx->m))
goto err;
/* If encrypting set explicit IV from sequence number (start of AAD) */
if (ctx->enc)
memcpy(out, ctx->buf, EVP_CCM_TLS_EXPLICIT_IV_LEN);
/* Get rest of IV from explicit IV */
memcpy(ctx->iv + EVP_CCM_TLS_FIXED_IV_LEN, in, EVP_CCM_TLS_EXPLICIT_IV_LEN);
/* Correct length value */
len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m;
if (!ccm_set_iv(ctx, len))
goto err;
/* Use saved AAD */
if (!ctx->hw->setaad(ctx, ctx->buf, ctx->tls_aad_len))
goto err;
/* Fix buffer to point to payload */
in += EVP_CCM_TLS_EXPLICIT_IV_LEN;
out += EVP_CCM_TLS_EXPLICIT_IV_LEN;
if (ctx->enc) {
if (!ctx->hw->auth_encrypt(ctx, in, out, len, out + len, ctx->m))
goto err;
olen = len + EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m;
} else {
if (!ctx->hw->auth_decrypt(ctx, in, out, len,
(unsigned char *)in + len, ctx->m))
goto err;
olen = len;
}
rv = 1;
err:
*padlen = olen;
return rv;
}
static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out,
size_t *padlen, const unsigned char *in,
size_t len)
{
int rv = 0;
size_t olen = 0;
const PROV_CCM_HW *hw = ctx->hw;
/* If no key set, return error */
if (!ctx->key_set)
return 0;
if (ctx->tls_aad_len != UNINITIALISED_SIZET)
return ccm_tls_cipher(ctx, out, padlen, in, len);
/* EVP_*Final() doesn't return any data */
if (in == NULL && out != NULL)
goto finish;
if (!ctx->iv_set)
goto err;
if (out == NULL) {
if (in == NULL) {
if (!ccm_set_iv(ctx, len))
goto err;
} else {
/* If we have AAD, we need a message length */
if (!ctx->len_set && len)
goto err;
if (!hw->setaad(ctx, in, len))
goto err;
}
} else {
/* If not set length yet do it */
if (!ctx->len_set && !ccm_set_iv(ctx, len))
goto err;
if (ctx->enc) {
if (!hw->auth_encrypt(ctx, in, out, len, NULL, 0))
goto err;
ctx->tag_set = 1;
} else {
/* The tag must be set before actually decrypting data */
if (!ctx->tag_set)
goto err;
if (!hw->auth_decrypt(ctx, in, out, len, ctx->buf, ctx->m))
goto err;
/* Finished - reset flags so calling this method again will fail */
ctx->iv_set = 0;
ctx->tag_set = 0;
ctx->len_set = 0;
}
}
olen = len;
finish:
rv = 1;
err:
*padlen = olen;
return rv;
}
void ccm_initctx(PROV_CCM_CTX *ctx, size_t keybits, const PROV_CCM_HW *hw)
{
ctx->keylen = keybits / 8;
ctx->key_set = 0;
ctx->iv_set = 0;
ctx->tag_set = 0;
ctx->len_set = 0;
ctx->l = 8;
ctx->m = 12;
ctx->tls_aad_len = UNINITIALISED_SIZET;
ctx->hw = hw;
}
void ccm_finalctx(PROV_CCM_CTX *ctx)
{
OPENSSL_cleanse(ctx->iv, sizeof(ctx->iv));
}
+69
View File
@@ -0,0 +1,69 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "internal/ciphers/ciphercommon.h"
#include "internal/ciphers/cipher_ccm.h"
int ccm_generic_setiv(PROV_CCM_CTX *ctx, const unsigned char *nonce,
size_t nlen, size_t mlen)
{
return CRYPTO_ccm128_setiv(&ctx->ccm_ctx, nonce, nlen, mlen) == 0;
}
int ccm_generic_setaad(PROV_CCM_CTX *ctx, const unsigned char *aad, size_t alen)
{
CRYPTO_ccm128_aad(&ctx->ccm_ctx, aad, alen);
return 1;
}
int ccm_generic_gettag(PROV_CCM_CTX *ctx, unsigned char *tag, size_t tlen)
{
return CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, tlen) > 0;
}
int ccm_generic_auth_encrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
unsigned char *out, size_t len,
unsigned char *tag, size_t taglen)
{
int rv;
if (ctx->str != NULL)
rv = CRYPTO_ccm128_encrypt_ccm64(&ctx->ccm_ctx, in,
out, len, ctx->str) == 0;
else
rv = CRYPTO_ccm128_encrypt(&ctx->ccm_ctx, in, out, len) == 0;
if (rv == 1 && tag != NULL)
rv = (CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, taglen) > 0);
return rv;
}
int ccm_generic_auth_decrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
unsigned char *out, size_t len,
unsigned char *expected_tag, size_t taglen)
{
int rv = 0;
if (ctx->str != NULL)
rv = CRYPTO_ccm128_decrypt_ccm64(&ctx->ccm_ctx, in, out, len,
ctx->str) == 0;
else
rv = CRYPTO_ccm128_decrypt(&ctx->ccm_ctx, in, out, len) == 0;
if (rv) {
unsigned char tag[16];
if (!CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, taglen)
|| CRYPTO_memcmp(tag, expected_tag, taglen) != 0)
rv = 0;
}
if (rv == 0)
OPENSSL_cleanse(out, len);
return rv;
}
+405
View File
@@ -0,0 +1,405 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* Generic dispatch table functions for ciphers.
*/
#include "cipher_locl.h"
#include "internal/provider_ctx.h"
#include "internal/providercommonerr.h"
/*-
* Generic cipher functions for OSSL_PARAM gettables and settables
*/
static const OSSL_PARAM cipher_known_gettable_params[] = {
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_MODE, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_BLOCK_SIZE, NULL),
OSSL_PARAM_ulong(OSSL_CIPHER_PARAM_FLAGS, NULL),
OSSL_PARAM_END
};
const OSSL_PARAM *cipher_generic_gettable_params(void)
{
return cipher_known_gettable_params;
}
int cipher_generic_get_params(OSSL_PARAM params[], unsigned int md,
unsigned long flags,
size_t kbits, size_t blkbits, size_t ivbits)
{
OSSL_PARAM *p;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE);
if (p != NULL && !OSSL_PARAM_set_uint(p, md)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_FLAGS);
if (p != NULL && !OSSL_PARAM_set_ulong(p, flags)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, kbits / 8)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE);
if (p != NULL && !OSSL_PARAM_set_size_t(p, blkbits / 8)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ivbits / 8)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
return 1;
}
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(cipher_generic)
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(cipher_generic)
static const OSSL_PARAM cipher_known_settable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_PADDING, NULL),
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_NUM, NULL),
OSSL_PARAM_END
};
const OSSL_PARAM *cipher_generic_settable_ctx_params(void)
{
return cipher_known_settable_ctx_params;
}
/*-
* AEAD cipher functions for OSSL_PARAM gettables and settables
*/
static const OSSL_PARAM cipher_aead_known_gettable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL),
OSSL_PARAM_END
};
const OSSL_PARAM *cipher_aead_gettable_ctx_params(void)
{
return cipher_aead_known_gettable_ctx_params;
}
static const OSSL_PARAM cipher_aead_known_settable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED, NULL, 0),
OSSL_PARAM_END
};
const OSSL_PARAM *cipher_aead_settable_ctx_params(void)
{
return cipher_aead_known_settable_ctx_params;
}
static int cipher_generic_init_internal(PROV_CIPHER_CTX *ctx,
const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
int enc)
{
ctx->enc = enc ? 1 : 0;
if (iv != NULL && ctx->mode != EVP_CIPH_ECB_MODE) {
if (ivlen != ctx->ivlen) {
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
return 0;
}
memcpy(ctx->iv, iv, ctx->ivlen);
}
if (key != NULL) {
if ((ctx->flags & EVP_CIPH_VARIABLE_LENGTH) == 0) {
if (keylen != ctx->keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN);
return 0;
}
} else {
ctx->keylen = keylen;
}
return ctx->hw->init(ctx, key, ctx->keylen);
}
return 1;
}
int cipher_generic_einit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen)
{
return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx, key, keylen,
iv, ivlen, 1);
}
int cipher_generic_dinit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen)
{
return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx, key, keylen,
iv, ivlen, 0);
}
int cipher_generic_block_update(void *vctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in,
size_t inl)
{
size_t outlint = 0;
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
size_t blksz = ctx->blocksize;
size_t nextblocks = fillblock(ctx->buf, &ctx->bufsz, blksz, &in, &inl);
/*
* If we're decrypting and we end an update on a block boundary we hold
* the last block back in case this is the last update call and the last
* block is padded.
*/
if (ctx->bufsz == blksz && (ctx->enc || inl > 0 || !ctx->pad)) {
if (outsize < blksz) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!ctx->hw->cipher(ctx, out, ctx->buf, blksz)) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
ctx->bufsz = 0;
outlint = blksz;
out += blksz;
}
if (nextblocks > 0) {
if (!ctx->enc && ctx->pad && nextblocks == inl) {
if (!ossl_assert(inl >= blksz)) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
nextblocks -= blksz;
}
outlint += nextblocks;
if (outsize < outlint) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!ctx->hw->cipher(ctx, out, in, nextblocks)) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
in += nextblocks;
inl -= nextblocks;
}
if (!trailingdata(ctx->buf, &ctx->bufsz, blksz, &in, &inl)) {
/* ERR_raise already called */
return 0;
}
*outl = outlint;
return inl == 0;
}
int cipher_generic_block_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
size_t blksz = ctx->blocksize;
if (ctx->enc) {
if (ctx->pad) {
padblock(ctx->buf, &ctx->bufsz, blksz);
} else if (ctx->bufsz == 0) {
*outl = 0;
return 1;
} else if (ctx->bufsz != blksz) {
ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
return 0;
}
if (outsize < blksz) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!ctx->hw->cipher(ctx, out, ctx->buf, blksz)) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
ctx->bufsz = 0;
*outl = blksz;
return 1;
}
/* Decrypting */
if (ctx->bufsz != blksz) {
if (ctx->bufsz == 0 && !ctx->pad) {
*outl = 0;
return 1;
}
ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
return 0;
}
if (!ctx->hw->cipher(ctx, ctx->buf, ctx->buf, blksz)) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
if (ctx->pad && !unpadblock(ctx->buf, &ctx->bufsz, blksz)) {
/* ERR_raise already called */
return 0;
}
if (outsize < ctx->bufsz) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
memcpy(out, ctx->buf, ctx->bufsz);
*outl = ctx->bufsz;
ctx->bufsz = 0;
return 1;
}
int cipher_generic_stream_update(void *vctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in,
size_t inl)
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!ctx->hw->cipher(ctx, out, in, inl)) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
*outl = inl;
return 1;
}
int cipher_generic_stream_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
*outl = 0;
return 1;
}
int cipher_generic_cipher(void *vctx,
unsigned char *out, size_t *outl, size_t outsize,
const unsigned char *in, size_t inl)
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!ctx->hw->cipher(ctx, out, in, inl)) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
*outl = inl;
return 1;
}
int cipher_generic_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
OSSL_PARAM *p;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING);
if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->pad)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
if (p != NULL
&& !OSSL_PARAM_set_octet_ptr(p, &ctx->iv, ctx->ivlen)
&& !OSSL_PARAM_set_octet_string(p, &ctx->iv, ctx->ivlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_NUM);
if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->num)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
return 1;
}
int cipher_generic_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
const OSSL_PARAM *p;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_PADDING);
if (p != NULL) {
unsigned int pad;
if (!OSSL_PARAM_get_uint(p, &pad)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
ctx->pad = pad ? 1 : 0;
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_NUM);
if (p != NULL) {
unsigned int num;
if (!OSSL_PARAM_get_uint(p, &num)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
ctx->num = num;
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL) {
size_t keylen;
if (!OSSL_PARAM_get_size_t(p, &keylen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
ctx->keylen = keylen;
}
return 1;
}
void cipher_generic_initkey(void *vctx, size_t kbits, size_t blkbits,
size_t ivbits, unsigned int mode, uint64_t flags,
const PROV_CIPHER_HW *hw, void *provctx)
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
ctx->flags = flags;
ctx->pad = 1;
ctx->keylen = ((kbits) / 8);
ctx->ivlen = ((ivbits) / 8);
ctx->hw = hw;
ctx->mode = mode;
ctx->blocksize = blkbits / 8;
if (provctx != NULL)
ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); /* used for rand */
}
+189
View File
@@ -0,0 +1,189 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "cipher_locl.h"
/*-
* The generic cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr.
* Used if there is no special hardware implementations.
*/
int cipher_hw_generic_cbc(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
if (dat->stream.cbc)
(*dat->stream.cbc) (in, out, len, dat->ks, dat->iv, dat->enc);
else if (dat->enc)
CRYPTO_cbc128_encrypt(in, out, len, dat->ks, dat->iv, dat->block);
else
CRYPTO_cbc128_decrypt(in, out, len, dat->ks, dat->iv, dat->block);
return 1;
}
int cipher_hw_generic_ecb(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
size_t i, bl = dat->blocksize;
if (len < bl)
return 1;
for (i = 0, len -= bl; i <= len; i += bl)
(*dat->block) (in + i, out + i, dat->ks);
return 1;
}
int cipher_hw_generic_ofb128(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
int num = dat->num;
CRYPTO_ofb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->block);
dat->num = num;
return 1;
}
int cipher_hw_generic_cfb128(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
int num = dat->num;
CRYPTO_cfb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc,
dat->block);
dat->num = num;
return 1;
}
int cipher_hw_generic_cfb8(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
int num = dat->num;
CRYPTO_cfb128_8_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc,
dat->block);
dat->num = num;
return 1;
}
int cipher_hw_generic_cfb1(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
int num = dat->num;
if ((dat->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) {
CRYPTO_cfb128_1_encrypt(in, out, len, dat->ks, dat->iv, &num,
dat->enc, dat->block);
dat->num = num;
return 1;
}
while (len >= MAXBITCHUNK) {
CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, dat->ks,
dat->iv, &num, dat->enc, dat->block);
len -= MAXBITCHUNK;
out += MAXBITCHUNK;
in += MAXBITCHUNK;
}
if (len)
CRYPTO_cfb128_1_encrypt(in, out, len * 8, dat->ks, dat->iv, &num,
dat->enc, dat->block);
dat->num = num;
return 1;
}
int cipher_hw_generic_ctr(PROV_CIPHER_CTX *dat, unsigned char *out,
const unsigned char *in, size_t len)
{
unsigned int num = dat->num;
if (dat->stream.ctr)
CRYPTO_ctr128_encrypt_ctr32(in, out, len, dat->ks, dat->iv, dat->buf,
&num, dat->stream.ctr);
else
CRYPTO_ctr128_encrypt(in, out, len, dat->ks, dat->iv, dat->buf,
&num, dat->block);
dat->num = num;
return 1;
}
/*-
* The chunked cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr.
* Used if there is no special hardware implementations.
*/
int cipher_hw_chunked_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
while (inl >= MAXCHUNK) {
cipher_hw_generic_cbc(ctx, out, in, MAXCHUNK);
inl -= MAXCHUNK;
in += MAXCHUNK;
out += MAXCHUNK;
}
if (inl > 0)
cipher_hw_generic_cbc(ctx, out, in, inl);
return 1;
}
int cipher_hw_chunked_cfb8(PROV_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
size_t chunk = MAXCHUNK;
if (inl < chunk)
chunk = inl;
while (inl > 0 && inl >= chunk) {
cipher_hw_generic_cfb8(ctx, out, in, inl);
inl -= chunk;
in += chunk;
out += chunk;
if (inl < chunk)
chunk = inl;
}
return 1;
}
int cipher_hw_chunked_cfb128(PROV_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
size_t chunk = MAXCHUNK;
if (inl < chunk)
chunk = inl;
while (inl > 0 && inl >= chunk) {
cipher_hw_generic_cfb128(ctx, out, in, inl);
inl -= chunk;
in += chunk;
out += chunk;
if (inl < chunk)
chunk = inl;
}
return 1;
}
int cipher_hw_chunked_ofb128(PROV_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
while (inl >= MAXCHUNK) {
cipher_hw_generic_ofb128(ctx, out, in, MAXCHUNK);
inl -= MAXCHUNK;
in += MAXCHUNK;
out += MAXCHUNK;
}
if (inl > 0)
cipher_hw_generic_ofb128(ctx, out, in, inl);
return 1;
}
+514
View File
@@ -0,0 +1,514 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Dispatch functions for gcm mode */
#include "cipher_locl.h"
#include "internal/ciphers/cipher_gcm.h"
#include "internal/providercommonerr.h"
#include "internal/rand_int.h"
#include "internal/provider_ctx.h"
static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len);
static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv,
size_t len);
static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen,
const unsigned char *in, size_t len);
static int gcm_cipher_internal(PROV_GCM_CTX *ctx, unsigned char *out,
size_t *padlen, const unsigned char *in,
size_t len);
void gcm_initctx(void *provctx, PROV_GCM_CTX *ctx, size_t keybits,
const PROV_GCM_HW *hw, size_t ivlen_min)
{
ctx->pad = 1;
ctx->mode = EVP_CIPH_GCM_MODE;
ctx->taglen = UNINITIALISED_SIZET;
ctx->tls_aad_len = UNINITIALISED_SIZET;
ctx->ivlen_min = ivlen_min;
ctx->ivlen = (EVP_GCM_TLS_FIXED_IV_LEN + EVP_GCM_TLS_EXPLICIT_IV_LEN);
ctx->keylen = keybits / 8;
ctx->hw = hw;
ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
}
void gcm_deinitctx(PROV_GCM_CTX *ctx)
{
OPENSSL_cleanse(ctx->iv, sizeof(ctx->iv));
}
static int gcm_init(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen, int enc)
{
PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
ctx->enc = enc;
if (iv != NULL) {
if (ivlen < ctx->ivlen_min || ivlen > sizeof(ctx->iv)) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
ctx->ivlen = ivlen;
memcpy(ctx->iv, iv, ctx->ivlen);
ctx->iv_state = IV_STATE_BUFFERED;
}
if (key != NULL) {
if (keylen != ctx->keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
return ctx->hw->setkey(ctx, key, ctx->keylen);
}
return 1;
}
int gcm_einit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen)
{
return gcm_init(vctx, key, keylen, iv, ivlen, 1);
}
int gcm_dinit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen)
{
return gcm_init(vctx, key, keylen, iv, ivlen, 0);
}
int gcm_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
OSSL_PARAM *p;
size_t sz;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
if (p != NULL) {
size_t taglen = (ctx->taglen != UNINITIALISED_SIZET) ? ctx->taglen :
GCM_TAG_MAX_SIZE;
if (!OSSL_PARAM_set_size_t(p, taglen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
if (p != NULL) {
if (ctx->iv_gen != 1 && ctx->iv_gen_rand != 1)
return 0;
if (ctx->ivlen != p->data_size) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
if (!OSSL_PARAM_set_octet_string(p, ctx->iv, ctx->ivlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
if (p != NULL) {
sz = p->data_size;
if (sz == 0
|| sz > EVP_GCM_TLS_TAG_LEN
|| !ctx->enc
|| ctx->taglen == UNINITIALISED_SIZET) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG);
return 0;
}
if (!OSSL_PARAM_set_octet_string(p, ctx->buf, sz)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
}
return 1;
}
int gcm_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
const OSSL_PARAM *p;
size_t sz;
void *vp;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
if (p != NULL) {
vp = ctx->buf;
if (!OSSL_PARAM_get_octet_string(p, &vp, EVP_GCM_TLS_TAG_LEN, &sz)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (sz == 0 || ctx->enc) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG);
return 0;
}
ctx->taglen = sz;
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN);
if (p != NULL) {
if (!OSSL_PARAM_get_size_t(p, &sz)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (sz == 0 || sz > sizeof(ctx->iv)) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
ctx->ivlen = sz;
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
sz = gcm_tls_init(ctx, p->data, p->data_size);
if (sz == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_AAD);
return 0;
}
ctx->tls_aad_pad_sz = sz;
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (gcm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
}
/*
* TODO(3.0) Temporary solution to address fuzz test crash, which will be
* reworked once the discussion in PR #9510 is resolved. i.e- We need a
* general solution for handling missing parameters inside set_params and
* get_params methods.
*/
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL) {
size_t keylen;
if (!OSSL_PARAM_get_size_t(p, &keylen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
/* The key length can not be modified for gcm mode */
if (keylen != ctx->keylen)
return 0;
}
return 1;
}
int gcm_stream_update(void *vctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in, size_t inl)
{
PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return -1;
}
if (gcm_cipher_internal(ctx, out, outl, in, inl) <= 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return -1;
}
return 1;
}
int gcm_stream_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
int i;
i = gcm_cipher_internal(ctx, out, outl, NULL, 0);
if (i <= 0)
return 0;
*outl = 0;
return 1;
}
int gcm_cipher(void *vctx,
unsigned char *out, size_t *outl, size_t outsize,
const unsigned char *in, size_t inl)
{
PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return -1;
}
if (gcm_cipher_internal(ctx, out, outl, in, inl) <= 0)
return -1;
*outl = inl;
return 1;
}
/*
* See SP800-38D (GCM) Section 8 "Uniqueness requirement on IVS and keys"
*
* See also 8.2.2 RBG-based construction.
* Random construction consists of a free field (which can be NULL) and a
* random field which will use a DRBG that can return at least 96 bits of
* entropy strength. (The DRBG must be seeded by the FIPS module).
*/
static int gcm_iv_generate(PROV_GCM_CTX *ctx, int offset)
{
int sz = ctx->ivlen - offset;
/* Must be at least 96 bits */
if (sz <= 0 || ctx->ivlen < GCM_IV_DEFAULT_SIZE)
return 0;
/* Use DRBG to generate random iv */
if (rand_bytes_ex(ctx->libctx, ctx->iv + offset, sz) <= 0)
return 0;
ctx->iv_state = IV_STATE_BUFFERED;
ctx->iv_gen_rand = 1;
return 1;
}
static int gcm_cipher_internal(PROV_GCM_CTX *ctx, unsigned char *out,
size_t *padlen, const unsigned char *in,
size_t len)
{
size_t olen = 0;
int rv = 0;
const PROV_GCM_HW *hw = ctx->hw;
if (ctx->tls_aad_len != UNINITIALISED_SIZET)
return gcm_tls_cipher(ctx, out, padlen, in, len);
if (!ctx->key_set || ctx->iv_state == IV_STATE_FINISHED)
goto err;
/*
* FIPS requires generation of AES-GCM IV's inside the FIPS module.
* The IV can still be set externally (the security policy will state that
* this is not FIPS compliant). There are some applications
* where setting the IV externally is the only option available.
*/
if (ctx->iv_state == IV_STATE_UNINITIALISED) {
if (!ctx->enc || !gcm_iv_generate(ctx, 0))
goto err;
}
if (ctx->iv_state == IV_STATE_BUFFERED) {
if (!hw->setiv(ctx, ctx->iv, ctx->ivlen))
goto err;
ctx->iv_state = IV_STATE_COPIED;
}
if (in != NULL) {
/* The input is AAD if out is NULL */
if (out == NULL) {
if (!hw->aadupdate(ctx, in, len))
goto err;
} else {
/* The input is ciphertext OR plaintext */
if (!hw->cipherupdate(ctx, in, len, out))
goto err;
}
} else {
/* The tag must be set before actually decrypting data */
if (!ctx->enc && ctx->taglen == UNINITIALISED_SIZET)
goto err;
if (!hw->cipherfinal(ctx, ctx->buf))
goto err;
ctx->iv_state = IV_STATE_FINISHED; /* Don't reuse the IV */
goto finish;
}
olen = len;
finish:
rv = 1;
err:
*padlen = olen;
return rv;
}
static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len)
{
unsigned char *buf;
size_t len;
if (aad_len != EVP_AEAD_TLS1_AAD_LEN)
return 0;
/* Save the aad for later use. */
buf = dat->buf;
memcpy(buf, aad, aad_len);
dat->tls_aad_len = aad_len;
dat->tls_enc_records = 0;
len = buf[aad_len - 2] << 8 | buf[aad_len - 1];
/* Correct length for explicit iv. */
if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN)
return 0;
len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
/* If decrypting correct for tag too. */
if (!dat->enc) {
if (len < EVP_GCM_TLS_TAG_LEN)
return 0;
len -= EVP_GCM_TLS_TAG_LEN;
}
buf[aad_len - 2] = (unsigned char)(len >> 8);
buf[aad_len - 1] = (unsigned char)(len & 0xff);
/* Extra padding: tag appended to record. */
return EVP_GCM_TLS_TAG_LEN;
}
static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv,
size_t len)
{
/* Special case: -1 length restores whole IV */
if (len == (size_t)-1) {
memcpy(ctx->iv, iv, ctx->ivlen);
ctx->iv_gen = 1;
ctx->iv_state = IV_STATE_BUFFERED;
return 1;
}
/* Fixed field must be at least 4 bytes and invocation field at least 8 */
if ((len < EVP_GCM_TLS_FIXED_IV_LEN)
|| (ctx->ivlen - (int)len) < EVP_GCM_TLS_EXPLICIT_IV_LEN)
return 0;
if (len > 0)
memcpy(ctx->iv, iv, len);
if (ctx->enc
&& rand_bytes_ex(ctx->libctx, ctx->iv + len, ctx->ivlen - len) <= 0)
return 0;
ctx->iv_gen = 1;
ctx->iv_state = IV_STATE_BUFFERED;
return 1;
}
/* increment counter (64-bit int) by 1 */
static void ctr64_inc(unsigned char *counter)
{
int n = 8;
unsigned char c;
do {
--n;
c = counter[n];
++c;
counter[n] = c;
if (c > 0)
return;
} while (n > 0);
}
/*
* Handle TLS GCM packet format. This consists of the last portion of the IV
* followed by the payload and finally the tag. On encrypt generate IV,
* encrypt payload and write the tag. On verify retrieve IV, decrypt payload
* and verify tag.
*/
static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen,
const unsigned char *in, size_t len)
{
int rv = 0;
size_t arg = EVP_GCM_TLS_EXPLICIT_IV_LEN;
size_t plen = 0;
unsigned char *tag = NULL;
if (!ctx->key_set)
goto err;
/* Encrypt/decrypt must be performed in place */
if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
goto err;
/*
* Check for too many keys as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness
* Requirements from SP 800-38D". The requirements is for one party to the
* communication to fail after 2^64 - 1 keys. We do this on the encrypting
* side only.
*/
if (ctx->enc && ++ctx->tls_enc_records == 0) {
ERR_raise(ERR_LIB_PROV, EVP_R_TOO_MANY_RECORDS);
goto err;
}
if (ctx->iv_gen == 0)
goto err;
/*
* Set IV from start of buffer or generate IV and write to start of
* buffer.
*/
if (ctx->enc) {
if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen))
goto err;
if (arg > ctx->ivlen)
arg = ctx->ivlen;
memcpy(out, ctx->iv + ctx->ivlen - arg, arg);
/*
* Invocation field will be at least 8 bytes in size and so no need
* to check wrap around or increment more than last 8 bytes.
*/
ctr64_inc(ctx->iv + ctx->ivlen - 8);
} else {
memcpy(ctx->iv + ctx->ivlen - arg, out, arg);
if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen))
goto err;
}
ctx->iv_state = IV_STATE_COPIED;
/* Fix buffer and length to point to payload */
in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
tag = ctx->enc ? out + len : (unsigned char *)in + len;
if (!ctx->hw->oneshot(ctx, ctx->buf, ctx->tls_aad_len, in, len, out, tag,
EVP_GCM_TLS_TAG_LEN)) {
if (!ctx->enc)
OPENSSL_cleanse(out, len);
goto err;
}
if (ctx->enc)
plen = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
else
plen = len;
rv = 1;
err:
ctx->iv_state = IV_STATE_FINISHED;
ctx->tls_aad_len = UNINITIALISED_SIZET;
*padlen = plen;
return rv;
}
+117
View File
@@ -0,0 +1,117 @@
/*
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "cipher_locl.h"
#include "internal/ciphers/cipher_gcm.h"
int gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, size_t ivlen)
{
CRYPTO_gcm128_setiv(&ctx->gcm, iv, ivlen);
return 1;
}
int gcm_aad_update(PROV_GCM_CTX *ctx, const unsigned char *aad, size_t aad_len)
{
return CRYPTO_gcm128_aad(&ctx->gcm, aad, aad_len) == 0;
}
int gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
size_t len, unsigned char *out)
{
if (ctx->enc) {
if (ctx->ctr != NULL) {
#if defined(AES_GCM_ASM)
size_t bulk = 0;
if (len >= 32 && AES_GCM_ASM(ctx)) {
size_t res = (16 - ctx->gcm.mres) % 16;
if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, res))
return 0;
bulk = aesni_gcm_encrypt(in + res, out + res, len - res,
ctx->gcm.key,
ctx->gcm.Yi.c, ctx->gcm.Xi.u);
ctx->gcm.len.u[1] += bulk;
bulk += res;
}
if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
len - bulk, ctx->ctr))
return 0;
#else
if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
return 0;
#endif /* AES_GCM_ASM */
} else {
if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len))
return 0;
}
} else {
if (ctx->ctr != NULL) {
#if defined(AES_GCM_ASM)
size_t bulk = 0;
if (len >= 16 && AES_GCM_ASM(ctx)) {
size_t res = (16 - ctx->gcm.mres) % 16;
if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, res))
return -1;
bulk = aesni_gcm_decrypt(in + res, out + res, len - res,
ctx->gcm.key,
ctx->gcm.Yi.c, ctx->gcm.Xi.u);
ctx->gcm.len.u[1] += bulk;
bulk += res;
}
if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
len - bulk, ctx->ctr))
return 0;
#else
if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
return 0;
#endif /* AES_GCM_ASM */
} else {
if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len))
return 0;
}
}
return 1;
}
int gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag)
{
if (ctx->enc) {
CRYPTO_gcm128_tag(&ctx->gcm, tag, GCM_TAG_MAX_SIZE);
ctx->taglen = GCM_TAG_MAX_SIZE;
} else {
if (CRYPTO_gcm128_finish(&ctx->gcm, tag, ctx->taglen) != 0)
return 0;
}
return 1;
}
int gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len,
const unsigned char *in, size_t in_len,
unsigned char *out, unsigned char *tag, size_t tag_len)
{
int ret = 0;
/* Use saved AAD */
if (!ctx->hw->aadupdate(ctx, aad, aad_len))
goto err;
if (!ctx->hw->cipherupdate(ctx, in, in_len, out))
goto err;
ctx->taglen = GCM_TAG_MAX_SIZE;
if (!ctx->hw->cipherfinal(ctx, tag))
goto err;
ret = 1;
err:
return ret;
}
+29
View File
@@ -0,0 +1,29 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "internal/ciphers/ciphercommon.h"
#define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(name) \
static const OSSL_PARAM name##_known_gettable_ctx_params[] = { \
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), \
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), \
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_PADDING, NULL), \
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_NUM, NULL), \
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0),
#define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(name) \
OSSL_PARAM_END \
}; \
const OSSL_PARAM * name##_gettable_ctx_params(void) \
{ \
return name##_known_gettable_ctx_params; \
}
void padblock(unsigned char *buf, size_t *buflen, size_t blocksize);
int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize);
+117
View File
@@ -0,0 +1,117 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "cipher_locl.h"
#include "internal/ciphers/cipher_tdes.h"
#include "internal/rand_int.h"
#include "internal/provider_algs.h"
#include "internal/providercommonerr.h"
void *tdes_newctx(void *provctx, int mode, size_t kbits, size_t blkbits,
size_t ivbits, uint64_t flags, const PROV_CIPHER_HW *hw)
{
PROV_TDES_CTX *tctx = OPENSSL_zalloc(sizeof(*tctx));
if (tctx != NULL)
cipher_generic_initkey(tctx, kbits, blkbits, ivbits, mode, flags, hw,
provctx);
return tctx;
}
void tdes_freectx(void *vctx)
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static int tdes_init(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen, int enc)
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
ctx->enc = enc;
if (iv != NULL) {
if (ivlen != TDES_IVLEN) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
return 0;
}
memcpy(ctx->iv, iv, TDES_IVLEN);
}
if (key != NULL) {
if (keylen != ctx->keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN);
return 0;
}
return ctx->hw->init(ctx, key, ctx->keylen);
}
return 1;
}
int tdes_einit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen)
{
return tdes_init(vctx, key, keylen, iv, ivlen, 1);
}
int tdes_dinit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen)
{
return tdes_init(vctx, key, keylen, iv, ivlen, 0);
}
static int tdes_generatekey(PROV_CIPHER_CTX *ctx, void *ptr)
{
DES_cblock *deskey = ptr;
size_t kl = ctx->keylen;
if (kl == 0 || rand_priv_bytes_ex(ctx->libctx, ptr, kl) <= 0)
return 0;
DES_set_odd_parity(deskey);
if (kl >= 16)
DES_set_odd_parity(deskey + 1);
if (kl >= 24) {
DES_set_odd_parity(deskey + 2);
return 1;
}
return 0;
}
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(tdes)
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_RANDOM_KEY, NULL, 0),
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(tdes)
int tdes_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
OSSL_PARAM *p;
if (!cipher_generic_get_ctx_params(vctx, params))
return 0;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_RANDOM_KEY);
if (p != NULL && !tdes_generatekey(ctx, p->data)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GENERATE_KEY);
return 0;
}
return 1;
}
/*
* TODO(3.0) - ECB mode does not use an IV - but existing test code is setting
* an IV. Fixing this could potentially make applications break.
*/
/* tdes_ede3_ecb_functions */
IMPLEMENT_tdes_cipher(ede3, EDE3, ecb, ECB, TDES_FLAGS, 64*3, 64, 64, block);
/* tdes_ede3_cbc_functions */
IMPLEMENT_tdes_cipher(ede3, EDE3, cbc, CBC, TDES_FLAGS, 64*3, 64, 64, block);
+82
View File
@@ -0,0 +1,82 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "cipher_locl.h"
#include "internal/ciphers/cipher_tdes.h"
#define ks1 tks.ks[0]
#define ks2 tks.ks[1]
#define ks3 tks.ks[2]
int cipher_hw_tdes_ede3_initkey(PROV_CIPHER_CTX *ctx, const unsigned char *key,
size_t keylen)
{
PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
DES_cblock *deskey = (DES_cblock *)key;
tctx->tstream.cbc = NULL;
# if defined(SPARC_DES_CAPABLE)
if (SPARC_DES_CAPABLE) {
if (ctx->mode == EVP_CIPH_CBC_MODE) {
des_t4_key_expand(&deskey[0], &tctx->ks1);
des_t4_key_expand(&deskey[1], &tctx->ks2);
des_t4_key_expand(&deskey[2], &tctx->ks3);
tctx->tstream.cbc = ctx->enc ? des_t4_ede3_cbc_encrypt :
des_t4_ede3_cbc_decrypt;
return 1;
}
}
# endif
DES_set_key_unchecked(&deskey[0], &tctx->ks1);
DES_set_key_unchecked(&deskey[1], &tctx->ks2);
DES_set_key_unchecked(&deskey[2], &tctx->ks3);
return 1;
}
int cipher_hw_tdes_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
if (tctx->tstream.cbc != NULL) {
(*tctx->tstream.cbc) (in, out, inl, tctx->tks.ks, ctx->iv);
return 1;
}
while (inl >= MAXCHUNK) {
DES_ede3_cbc_encrypt(in, out, (long)MAXCHUNK, &tctx->ks1, &tctx->ks2,
&tctx->ks3, (DES_cblock *)ctx->iv, ctx->enc);
inl -= MAXCHUNK;
in += MAXCHUNK;
out += MAXCHUNK;
}
if (inl > 0)
DES_ede3_cbc_encrypt(in, out, (long)inl, &tctx->ks1, &tctx->ks2,
&tctx->ks3, (DES_cblock *)ctx->iv, ctx->enc);
return 1;
}
int cipher_hw_tdes_ecb(PROV_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
size_t i;
PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
if (len < DES_BLOCK_SIZE)
return 1;
for (i = 0, len -= DES_BLOCK_SIZE; i <= len; i += DES_BLOCK_SIZE) {
DES_ecb3_encrypt((const_DES_cblock *)(in + i), (DES_cblock *)(out + i),
&tctx->ks1, &tctx->ks2, &tctx->ks3, ctx->enc);
}
return 1;
}
PROV_CIPHER_HW_tdes_mode(ede3, ecb)
PROV_CIPHER_HW_tdes_mode(ede3, cbc)
-109
View File
@@ -1,109 +0,0 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/aes.h>
#include <openssl/modes.h>
#include "internal/cryptlib.h"
typedef struct prov_aes_cipher_st PROV_AES_CIPHER;
typedef struct prov_aes_key_st {
union {
OSSL_UNION_ALIGN;
AES_KEY ks;
} ks;
block128_f block;
union {
cbc128_f cbc;
ctr128_f ctr;
} stream;
/* Platform specific data */
union {
int dummy;
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
struct {
union {
OSSL_UNION_ALIGN;
/*-
* KM-AES parameter block - begin
* (see z/Architecture Principles of Operation >= SA22-7832-06)
*/
struct {
unsigned char k[32];
} km;
/* KM-AES parameter block - end */
/*-
* KMO-AES/KMF-AES parameter block - begin
* (see z/Architecture Principles of Operation >= SA22-7832-08)
*/
struct {
unsigned char cv[16];
unsigned char k[32];
} kmo_kmf;
/* KMO-AES/KMF-AES parameter block - end */
} param;
unsigned int fc;
int res;
} s390x;
#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
} plat;
/* The cipher functions we are going to use */
const PROV_AES_CIPHER *ciph;
/* The mode that we are using */
int mode;
/* Set to 1 if we are encrypting or 0 otherwise */
int enc;
unsigned char iv[AES_BLOCK_SIZE];
/*
* num contains the number of bytes of |iv| which are valid for modes that
* manage partial blocks themselves.
*/
size_t num;
/* Buffer of partial blocks processed via update calls */
unsigned char buf[AES_BLOCK_SIZE];
/* Number of bytes in buf */
size_t bufsz;
uint64_t flags;
size_t keylen;
/* Whether padding should be used or not */
unsigned int pad : 1;
} PROV_AES_KEY;
struct prov_aes_cipher_st {
int (*init)(PROV_AES_KEY *dat, const uint8_t *key, size_t keylen);
int (*cipher)(PROV_AES_KEY *dat, uint8_t *out, const uint8_t *in,
size_t inl);
};
const PROV_AES_CIPHER *PROV_AES_CIPHER_ecb(size_t keylen);
const PROV_AES_CIPHER *PROV_AES_CIPHER_cbc(size_t keylen);
const PROV_AES_CIPHER *PROV_AES_CIPHER_ofb(size_t keylen);
const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb(size_t keylen);
const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb1(size_t keylen);
const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb8(size_t keylen);
const PROV_AES_CIPHER *PROV_AES_CIPHER_ctr(size_t keylen);
size_t fillblock(unsigned char *buf, size_t *buflen, size_t blocksize,
const unsigned char **in, size_t *inlen);
int trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize,
const unsigned char **in, size_t *inlen);
void padblock(unsigned char *buf, size_t *buflen, size_t blocksize);
int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize);