Adding in curl and openssl repos

This commit is contained in:
2025-08-14 12:09:30 -04:00
parent af2117b574
commit 0ace93e303
21174 changed files with 3607720 additions and 2 deletions

View File

@@ -0,0 +1,194 @@
# We make separate GOAL variables for each algorithm, to make it easy to
# switch each to the Legacy provider when needed.
#
# $TDES_1_GOAL and $TDES_2_GOAL separate FIPSable and non-FIPSable TDES.
# The latter may become legacy sooner, so it's comfortable to have two
# variables already now, to switch the non-FIPSable TDES to legacy if needed.
$COMMON_GOAL=../../libcommon.a
$NULL_GOAL=../../libdefault.a
$AES_GOAL=../../libdefault.a ../../libfips.a
$TDES_1_GOAL=../../libdefault.a ../../libfips.a
$TDES_2_GOAL=../../libdefault.a
$ARIA_GOAL=../../libdefault.a
$CAMELLIA_GOAL=../../libdefault.a
$DES_GOAL=../../liblegacy.a
$BLOWFISH_GOAL=../../liblegacy.a
$IDEA_GOAL=../../liblegacy.a
$CAST5_GOAL=../../liblegacy.a
$RC2_GOAL=../../liblegacy.a
$RC4_GOAL=../../liblegacy.a
$RC5_GOAL=../../liblegacy.a
$SEED_GOAL=../../liblegacy.a
$SM4_GOAL=../../libdefault.a
$CHACHA_GOAL=../../libdefault.a
$CHACHAPOLY_GOAL=../../libdefault.a
$SIV_GOAL=../../libdefault.a
$SIV_GCM_GOAL=../../libdefault.a
IF[{- !$disabled{asm} -}]
$GHASHDEF_x86=GHASH_ASM
$GHASHDEF_x86_sse2=OPENSSL_IA32_SSE2
$GHASHDEF_x86_64=GHASH_ASM
$GHASHDEF_x86_64_sse2=OPENSSL_IA32_SSE2
# ghash-ia64.s doesn't work on VMS
IF[{- $config{target} !~ /^vms-/ -}]
$GHASHDEF_ia64=GHASH_ASM
ENDIF
$GHASHDEF_sparcv9=GHASH_ASM
$GHASHDEF_alpha=GHASH_ASM
$GHASHDEF_s390x=GHASH_ASM
$GHASHDEF_armv4=GHASH_ASM
$GHASHDEF_aarch64=
$GHASHDEF_parisc11=GHASH_ASM
$GHASHDEF_parisc20_64=$GHASHDEF_parisc11
$GHASHDEF_ppc32=
$GHASHDEF_ppc64=$GHASHDEF_ppc32
$GHASHDEF_c64xplus=GHASH_ASM
$GHASHDEF_riscv64=GHASH_ASM
# Now that we have defined all the arch specific variables, use the
# appropriate one, and define the appropriate macros
IF[$GHASHDEF_{- $target{asm_arch} -}]
$GHASHDEF=$GHASHDEF_{- $target{asm_arch} -}
IF[{- !$disabled{sse2} -}]
IF[$GHASHDEF_{- $target{asm_arch} -}_sse2]
$GHASHDEF=$GHASHDEF_{- $target{asm_arch} -}_sse2
ENDIF
ENDIF
ENDIF
ENDIF
# This source is common building blocks for all ciphers in all our providers.
SOURCE[$COMMON_GOAL]=\
ciphercommon.c ciphercommon_hw.c ciphercommon_block.c \
ciphercommon_gcm.c ciphercommon_gcm_hw.c \
ciphercommon_ccm.c ciphercommon_ccm_hw.c
IF[{- !$disabled{des} -}]
SOURCE[$TDES_1_GOAL]=cipher_tdes.c cipher_tdes_common.c cipher_tdes_hw.c
ENDIF
SOURCE[$NULL_GOAL]=\
cipher_null.c
SOURCE[$AES_GOAL]=\
cipher_aes.c cipher_aes_hw.c \
cipher_aes_xts.c cipher_aes_xts_hw.c \
cipher_aes_gcm.c cipher_aes_gcm_hw.c \
cipher_aes_ccm.c cipher_aes_ccm_hw.c \
cipher_aes_wrp.c \
cipher_aes_cbc_hmac_sha.c \
cipher_aes_cbc_hmac_sha256_hw.c cipher_aes_cbc_hmac_sha1_hw.c \
cipher_cts.c
# Extra code to satisfy the FIPS and non-FIPS separation.
# When the AES-xxx-XTS moves to legacy, cipher_aes_xts_fips.c can be removed.
SOURCE[$AES_GOAL]=cipher_aes_xts_fips.c
IF[{- !$disabled{siv} -}]
DEFINE[$SIV_GCM_GOAL]=$GHASHDEF
SOURCE[$SIV_GCM_GOAL]=\
cipher_aes_gcm_siv.c cipher_aes_gcm_siv_hw.c \
cipher_aes_gcm_siv_polyval.c
SOURCE[$SIV_GOAL]=cipher_aes_siv.c cipher_aes_siv_hw.c
ENDIF
IF[{- !$disabled{des} -}]
SOURCE[$TDES_2_GOAL]=\
cipher_tdes_default.c cipher_tdes_default_hw.c \
cipher_tdes_wrap.c cipher_tdes_wrap_hw.c
SOURCE[$DES_GOAL]=\
cipher_desx.c cipher_desx_hw.c \
cipher_des.c cipher_des_hw.c
IF[{- !$disabled{module} -}]
SOURCE[$DES_GOAL]=\
cipher_tdes_common.c
ENDIF
ENDIF
IF[{- !$disabled{aria} -}]
SOURCE[$ARIA_GOAL]=\
cipher_aria.c cipher_aria_hw.c \
cipher_aria_gcm.c cipher_aria_gcm_hw.c \
cipher_aria_ccm.c cipher_aria_ccm_hw.c
ENDIF
IF[{- !$disabled{camellia} -}]
SOURCE[$CAMELLIA_GOAL]=\
cipher_camellia.c cipher_camellia_hw.c
ENDIF
IF[{- !$disabled{bf} -}]
SOURCE[$BLOWFISH_GOAL]=\
cipher_blowfish.c cipher_blowfish_hw.c
ENDIF
IF[{- !$disabled{idea} -}]
SOURCE[$IDEA_GOAL]=\
cipher_idea.c cipher_idea_hw.c
ENDIF
IF[{- !$disabled{cast} -}]
SOURCE[$CAST5_GOAL]=\
cipher_cast5.c cipher_cast5_hw.c
ENDIF
IF[{- !$disabled{seed} -}]
SOURCE[$SEED_GOAL]=\
cipher_seed.c cipher_seed_hw.c
ENDIF
IF[{- !$disabled{sm4} -}]
SOURCE[$SM4_GOAL]=\
cipher_sm4.c cipher_sm4_hw.c \
cipher_sm4_gcm.c cipher_sm4_gcm_hw.c \
cipher_sm4_ccm.c cipher_sm4_ccm_hw.c \
cipher_sm4_xts.c cipher_sm4_xts_hw.c
ENDIF
IF[{- !$disabled{ocb} -}]
SOURCE[$AES_GOAL]=\
cipher_aes_ocb.c cipher_aes_ocb_hw.c
ENDIF
IF[{- !$disabled{rc4} -}]
SOURCE[$RC4_GOAL]=\
cipher_rc4.c cipher_rc4_hw.c
IF[{- !$disabled{md5} -}]
SOURCE[$RC4_GOAL]=\
cipher_rc4_hmac_md5.c cipher_rc4_hmac_md5_hw.c
ENDIF
ENDIF
IF[{- !$disabled{rc5} -}]
SOURCE[$RC5_GOAL]=\
cipher_rc5.c cipher_rc5_hw.c
ENDIF
IF[{- !$disabled{rc2} -}]
SOURCE[$RC2_GOAL]=\
cipher_rc2.c cipher_rc2_hw.c
ENDIF
IF[{- !$disabled{chacha} -}]
SOURCE[$CHACHA_GOAL]=\
cipher_chacha20.c cipher_chacha20_hw.c
IF[{- !$disabled{poly1305} -}]
SOURCE[$CHACHAPOLY_GOAL]=\
cipher_chacha20_poly1305.c cipher_chacha20_poly1305_hw.c
ENDIF
ENDIF

View File

@@ -0,0 +1,93 @@
/*
* Copyright 2019-2020 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 low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
/* Dispatch functions for AES cipher modes ecb, cbc, ofb, cfb, ctr */
#include "cipher_aes.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
static OSSL_FUNC_cipher_freectx_fn aes_freectx;
static OSSL_FUNC_cipher_dupctx_fn aes_dupctx;
static void aes_freectx(void *vctx)
{
PROV_AES_CTX *ctx = (PROV_AES_CTX *)vctx;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_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;
if (!ossl_prov_is_running())
return NULL;
ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL)
return NULL;
in->base.hw->copyctx(&ret->base, &in->base);
return ret;
}
/* ossl_aes256ecb_functions */
IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 256, 128, 0, block)
/* ossl_aes192ecb_functions */
IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 192, 128, 0, block)
/* ossl_aes128ecb_functions */
IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 128, 128, 0, block)
/* ossl_aes256cbc_functions */
IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 256, 128, 128, block)
/* ossl_aes192cbc_functions */
IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 192, 128, 128, block)
/* ossl_aes128cbc_functions */
IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 128, 128, 128, block)
/* ossl_aes256ofb_functions */
IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 256, 8, 128, stream)
/* ossl_aes192ofb_functions */
IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 192, 8, 128, stream)
/* ossl_aes128ofb_functions */
IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 128, 8, 128, stream)
/* ossl_aes256cfb_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 256, 8, 128, stream)
/* ossl_aes192cfb_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 192, 8, 128, stream)
/* ossl_aes128cfb_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 128, 8, 128, stream)
/* ossl_aes256cfb1_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 256, 8, 128, stream)
/* ossl_aes192cfb1_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 192, 8, 128, stream)
/* ossl_aes128cfb1_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 128, 8, 128, stream)
/* ossl_aes256cfb8_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 256, 8, 128, stream)
/* ossl_aes192cfb8_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 192, 8, 128, stream)
/* ossl_aes128cfb8_functions */
IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 128, 8, 128, stream)
/* ossl_aes256ctr_functions */
IMPLEMENT_generic_cipher(aes, AES, ctr, CTR, 0, 256, 8, 128, stream)
/* ossl_aes192ctr_functions */
IMPLEMENT_generic_cipher(aes, AES, ctr, CTR, 0, 192, 8, 128, stream)
/* ossl_aes128ctr_functions */
IMPLEMENT_generic_cipher(aes, AES, ctr, CTR, 0, 128, 8, 128, stream)
#include "cipher_aes_cts.inc"

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2019-2024 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 "prov/ciphercommon.h"
#include "crypto/aes_platform.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;
} s390x;
#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
} plat;
} PROV_AES_CTX;
#define ossl_prov_cipher_hw_aes_ofb ossl_prov_cipher_hw_aes_ofb128
#define ossl_prov_cipher_hw_aes_cfb ossl_prov_cipher_hw_aes_cfb128
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ecb(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cbc(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ofb128(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb128(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb1(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_cfb8(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ctr(size_t keybits);

View File

@@ -0,0 +1,442 @@
/*
* Copyright 2019-2024 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 low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
/* Dispatch functions for AES_CBC_HMAC_SHA ciphers */
/* For SSL3_VERSION and TLS1_VERSION */
#include <openssl/prov_ssl.h>
#include <openssl/proverr.h>
#include "cipher_aes_cbc_hmac_sha.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#ifndef AES_CBC_HMAC_SHA_CAPABLE
# define IMPLEMENT_CIPHER(nm, sub, kbits, blkbits, ivbits, flags) \
const OSSL_DISPATCH ossl_##nm##kbits##sub##_functions[] = { \
OSSL_DISPATCH_END \
};
#else
# define AES_CBC_HMAC_SHA_FLAGS (PROV_CIPHER_FLAG_AEAD \
| PROV_CIPHER_FLAG_TLS1_MULTIBLOCK)
static OSSL_FUNC_cipher_encrypt_init_fn aes_einit;
static OSSL_FUNC_cipher_decrypt_init_fn aes_dinit;
static OSSL_FUNC_cipher_freectx_fn aes_cbc_hmac_sha1_freectx;
static OSSL_FUNC_cipher_freectx_fn aes_cbc_hmac_sha256_freectx;
static OSSL_FUNC_cipher_get_ctx_params_fn aes_get_ctx_params;
static OSSL_FUNC_cipher_gettable_ctx_params_fn aes_gettable_ctx_params;
static OSSL_FUNC_cipher_set_ctx_params_fn aes_set_ctx_params;
static OSSL_FUNC_cipher_settable_ctx_params_fn aes_settable_ctx_params;
# define aes_gettable_params ossl_cipher_generic_gettable_params
# define aes_update ossl_cipher_generic_stream_update
# define aes_final ossl_cipher_generic_stream_final
# define aes_cipher ossl_cipher_generic_cipher
static int aes_einit(void *ctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
if (!ossl_cipher_generic_einit(ctx, key, keylen, iv, ivlen, NULL))
return 0;
return aes_set_ctx_params(ctx, params);
}
static int aes_dinit(void *ctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
if (!ossl_cipher_generic_dinit(ctx, key, keylen, iv, ivlen, NULL))
return 0;
return aes_set_ctx_params(ctx, params);
}
static const OSSL_PARAM cipher_aes_known_settable_ctx_params[] = {
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_MAC_KEY, NULL, 0),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0),
# if !defined(OPENSSL_NO_MULTIBLOCK)
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD, NULL),
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC, NULL, 0),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN, NULL, 0),
# endif /* !defined(OPENSSL_NO_MULTIBLOCK) */
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_END
};
const OSSL_PARAM *aes_settable_ctx_params(ossl_unused void *cctx,
ossl_unused void *provctx)
{
return cipher_aes_known_settable_ctx_params;
}
static int aes_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_CIPHER_HW_AES_HMAC_SHA *hw =
(PROV_CIPHER_HW_AES_HMAC_SHA *)ctx->hw;
const OSSL_PARAM *p;
int ret = 1;
# if !defined(OPENSSL_NO_MULTIBLOCK)
EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
# endif
if (params == NULL)
return 1;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_MAC_KEY);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
hw->init_mac_key(ctx, p->data, p->data_size);
}
# if !defined(OPENSSL_NO_MULTIBLOCK)
p = OSSL_PARAM_locate_const(params,
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT);
if (p != NULL
&& !OSSL_PARAM_get_size_t(p, &ctx->multiblock_max_send_fragment)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
/*
* The inputs to tls1_multiblock_aad are:
* mb_param->inp
* mb_param->len
* mb_param->interleave
* The outputs of tls1_multiblock_aad are written to:
* ctx->multiblock_interleave
* ctx->multiblock_aad_packlen
*/
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD);
if (p != NULL) {
const OSSL_PARAM *p1 = OSSL_PARAM_locate_const(params,
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE);
if (p->data_type != OSSL_PARAM_OCTET_STRING
|| p1 == NULL
|| !OSSL_PARAM_get_uint(p1, &mb_param.interleave)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
mb_param.inp = p->data;
mb_param.len = p->data_size;
if (hw->tls1_multiblock_aad(vctx, &mb_param) <= 0)
return 0;
}
/*
* The inputs to tls1_multiblock_encrypt are:
* mb_param->inp
* mb_param->len
* mb_param->interleave
* mb_param->out
* The outputs of tls1_multiblock_encrypt are:
* ctx->multiblock_encrypt_len
*/
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC);
if (p != NULL) {
const OSSL_PARAM *p1 = OSSL_PARAM_locate_const(params,
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE);
const OSSL_PARAM *pin = OSSL_PARAM_locate_const(params,
OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN);
if (p->data_type != OSSL_PARAM_OCTET_STRING
|| pin == NULL
|| pin->data_type != OSSL_PARAM_OCTET_STRING
|| p1 == NULL
|| !OSSL_PARAM_get_uint(p1, &mb_param.interleave)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
mb_param.out = p->data;
mb_param.inp = pin->data;
mb_param.len = pin->data_size;
if (hw->tls1_multiblock_encrypt(vctx, &mb_param) <= 0)
return 0;
}
# endif /* !defined(OPENSSL_NO_MULTIBLOCK) */
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;
}
if (hw->set_tls1_aad(ctx, p->data, p->data_size) <= 0)
return 0;
}
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;
}
if (ctx->base.keylen != keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLS_VERSION);
if (p != NULL) {
if (!OSSL_PARAM_get_uint(p, &ctx->base.tlsversion)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (ctx->base.tlsversion == SSL3_VERSION
|| ctx->base.tlsversion == TLS1_VERSION) {
if (!ossl_assert(ctx->base.removetlsfixed >= AES_BLOCK_SIZE)) {
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
return 0;
}
/*
* There is no explicit IV with these TLS versions, so don't attempt
* to remove it.
*/
ctx->base.removetlsfixed -= AES_BLOCK_SIZE;
}
}
return ret;
}
static int aes_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
OSSL_PARAM *p;
# if !defined(OPENSSL_NO_MULTIBLOCK)
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE);
if (p != NULL) {
PROV_CIPHER_HW_AES_HMAC_SHA *hw =
(PROV_CIPHER_HW_AES_HMAC_SHA *)ctx->hw;
size_t len = hw->tls1_multiblock_max_bufsize(ctx);
if (!OSSL_PARAM_set_size_t(p, len)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE);
if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->multiblock_interleave)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN);
if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->multiblock_aad_packlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->multiblock_encrypt_len)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
# endif /* !defined(OPENSSL_NO_MULTIBLOCK) */
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)) {
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->base.keylen)) {
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, ctx->base.ivlen)) {
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_string(p, ctx->base.oiv, ctx->base.ivlen)
&& !OSSL_PARAM_set_octet_ptr(p, &ctx->base.oiv, ctx->base.ivlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_UPDATED_IV);
if (p != NULL
&& !OSSL_PARAM_set_octet_string(p, ctx->base.iv, ctx->base.ivlen)
&& !OSSL_PARAM_set_octet_ptr(p, &ctx->base.iv, ctx->base.ivlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
return 1;
}
static const OSSL_PARAM cipher_aes_known_gettable_ctx_params[] = {
# if !defined(OPENSSL_NO_MULTIBLOCK)
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE, NULL),
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE, NULL),
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN, NULL),
# endif /* !defined(OPENSSL_NO_MULTIBLOCK) */
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_UPDATED_IV, NULL, 0),
OSSL_PARAM_END
};
const OSSL_PARAM *aes_gettable_ctx_params(ossl_unused void *cctx,
ossl_unused void *provctx)
{
return cipher_aes_known_gettable_ctx_params;
}
static void base_init(void *provctx, PROV_AES_HMAC_SHA_CTX *ctx,
const PROV_CIPHER_HW_AES_HMAC_SHA *meths,
size_t kbits, size_t blkbits, size_t ivbits,
uint64_t flags)
{
ossl_cipher_generic_initkey(&ctx->base, kbits, blkbits, ivbits,
EVP_CIPH_CBC_MODE, flags,
&meths->base, provctx);
ctx->hw = (PROV_CIPHER_HW_AES_HMAC_SHA *)ctx->base.hw;
}
static void *aes_cbc_hmac_sha1_newctx(void *provctx, size_t kbits,
size_t blkbits, size_t ivbits,
uint64_t flags)
{
PROV_AES_HMAC_SHA1_CTX *ctx;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL)
base_init(provctx, &ctx->base_ctx,
ossl_prov_cipher_hw_aes_cbc_hmac_sha1(), kbits, blkbits,
ivbits, flags);
return ctx;
}
static void *aes_cbc_hmac_sha1_dupctx(void *provctx)
{
PROV_AES_HMAC_SHA1_CTX *ctx = provctx;
if (!ossl_prov_is_running())
return NULL;
if (ctx == NULL)
return NULL;
return OPENSSL_memdup(ctx, sizeof(*ctx));
}
static void aes_cbc_hmac_sha1_freectx(void *vctx)
{
PROV_AES_HMAC_SHA1_CTX *ctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
if (ctx != NULL) {
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
}
static void *aes_cbc_hmac_sha256_newctx(void *provctx, size_t kbits,
size_t blkbits, size_t ivbits,
uint64_t flags)
{
PROV_AES_HMAC_SHA256_CTX *ctx;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL)
base_init(provctx, &ctx->base_ctx,
ossl_prov_cipher_hw_aes_cbc_hmac_sha256(), kbits, blkbits,
ivbits, flags);
return ctx;
}
static void *aes_cbc_hmac_sha256_dupctx(void *provctx)
{
PROV_AES_HMAC_SHA256_CTX *ctx = provctx;
if (!ossl_prov_is_running())
return NULL;
return OPENSSL_memdup(ctx, sizeof(*ctx));
}
static void aes_cbc_hmac_sha256_freectx(void *vctx)
{
PROV_AES_HMAC_SHA256_CTX *ctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
if (ctx != NULL) {
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
}
# define IMPLEMENT_CIPHER(nm, sub, kbits, blkbits, ivbits, flags) \
static OSSL_FUNC_cipher_newctx_fn nm##_##kbits##_##sub##_newctx; \
static void *nm##_##kbits##_##sub##_newctx(void *provctx) \
{ \
return nm##_##sub##_newctx(provctx, kbits, blkbits, ivbits, flags); \
} \
static OSSL_FUNC_cipher_get_params_fn nm##_##kbits##_##sub##_get_params; \
static int nm##_##kbits##_##sub##_get_params(OSSL_PARAM params[]) \
{ \
return ossl_cipher_generic_get_params(params, EVP_CIPH_CBC_MODE, \
flags, kbits, blkbits, ivbits); \
} \
const OSSL_DISPATCH ossl_##nm##kbits##sub##_functions[] = { \
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))nm##_##kbits##_##sub##_newctx },\
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))nm##_##sub##_freectx }, \
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))nm##_##sub##_dupctx}, \
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))nm##_einit }, \
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))nm##_dinit }, \
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))nm##_update }, \
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))nm##_final }, \
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))nm##_cipher }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
(void (*)(void))nm##_##kbits##_##sub##_get_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
(void (*)(void))nm##_gettable_params }, \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
(void (*)(void))nm##_get_ctx_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
(void (*)(void))nm##_gettable_ctx_params }, \
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
(void (*)(void))nm##_set_ctx_params }, \
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
(void (*)(void))nm##_settable_ctx_params }, \
OSSL_DISPATCH_END \
};
#endif /* AES_CBC_HMAC_SHA_CAPABLE */
/* ossl_aes128cbc_hmac_sha1_functions */
IMPLEMENT_CIPHER(aes, cbc_hmac_sha1, 128, 128, 128, AES_CBC_HMAC_SHA_FLAGS)
/* ossl_aes256cbc_hmac_sha1_functions */
IMPLEMENT_CIPHER(aes, cbc_hmac_sha1, 256, 128, 128, AES_CBC_HMAC_SHA_FLAGS)
/* ossl_aes128cbc_hmac_sha256_functions */
IMPLEMENT_CIPHER(aes, cbc_hmac_sha256, 128, 128, 128, AES_CBC_HMAC_SHA_FLAGS)
/* ossl_aes256cbc_hmac_sha256_functions */
IMPLEMENT_CIPHER(aes, cbc_hmac_sha256, 256, 128, 128, AES_CBC_HMAC_SHA_FLAGS)

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2019-2020 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 "prov/ciphercommon.h"
#include "crypto/aes_platform.h"
int ossl_cipher_capable_aes_cbc_hmac_sha1(void);
int ossl_cipher_capable_aes_cbc_hmac_sha256(void);
typedef struct prov_cipher_hw_aes_hmac_sha_ctx_st {
PROV_CIPHER_HW base; /* must be first */
void (*init_mac_key)(void *ctx, const unsigned char *inkey, size_t inlen);
int (*set_tls1_aad)(void *ctx, unsigned char *aad_rec, int aad_len);
# if !defined(OPENSSL_NO_MULTIBLOCK)
int (*tls1_multiblock_max_bufsize)(void *ctx);
int (*tls1_multiblock_aad)(
void *vctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param);
int (*tls1_multiblock_encrypt)(
void *ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param);
# endif /* OPENSSL_NO_MULTIBLOCK) */
} PROV_CIPHER_HW_AES_HMAC_SHA;
const PROV_CIPHER_HW_AES_HMAC_SHA *ossl_prov_cipher_hw_aes_cbc_hmac_sha1(void);
const PROV_CIPHER_HW_AES_HMAC_SHA *ossl_prov_cipher_hw_aes_cbc_hmac_sha256(void);
#ifdef AES_CBC_HMAC_SHA_CAPABLE
# include <openssl/aes.h>
# include <openssl/sha.h>
typedef struct prov_aes_hmac_sha_ctx_st {
PROV_CIPHER_CTX base;
AES_KEY ks;
size_t payload_length; /* AAD length in decrypt case */
union {
unsigned int tls_ver;
unsigned char tls_aad[16]; /* 13 used */
} aux;
const PROV_CIPHER_HW_AES_HMAC_SHA *hw;
/* some value that are setup by set methods - that can be retrieved */
unsigned int multiblock_interleave;
unsigned int multiblock_aad_packlen;
size_t multiblock_max_send_fragment;
size_t multiblock_encrypt_len;
size_t tls_aad_pad;
} PROV_AES_HMAC_SHA_CTX;
typedef struct prov_aes_hmac_sha1_ctx_st {
PROV_AES_HMAC_SHA_CTX base_ctx;
SHA_CTX head, tail, md;
} PROV_AES_HMAC_SHA1_CTX;
typedef struct prov_aes_hmac_sha256_ctx_st {
PROV_AES_HMAC_SHA_CTX base_ctx;
SHA256_CTX head, tail, md;
} PROV_AES_HMAC_SHA256_CTX;
# define NO_PAYLOAD_LENGTH ((size_t)-1)
#endif /* AES_CBC_HMAC_SHA_CAPABLE */

View File

@@ -0,0 +1,795 @@
/*
* Copyright 2011-2021 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
*/
/*
* All low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
#include "cipher_aes_cbc_hmac_sha.h"
#if !defined(AES_CBC_HMAC_SHA_CAPABLE) || !defined(AESNI_CAPABLE)
int ossl_cipher_capable_aes_cbc_hmac_sha1(void)
{
return 0;
}
const PROV_CIPHER_HW_AES_HMAC_SHA *ossl_prov_cipher_hw_aes_cbc_hmac_sha1(void)
{
return NULL;
}
#else
# include <openssl/rand.h>
# include "crypto/evp.h"
# include "internal/constant_time.h"
void sha1_block_data_order(void *c, const void *p, size_t len);
void aesni_cbc_sha1_enc(const void *inp, void *out, size_t blocks,
const AES_KEY *key, unsigned char iv[16],
SHA_CTX *ctx, const void *in0);
int ossl_cipher_capable_aes_cbc_hmac_sha1(void)
{
return AESNI_CBC_HMAC_SHA_CAPABLE;
}
static int aesni_cbc_hmac_sha1_init_key(PROV_CIPHER_CTX *vctx,
const unsigned char *key, size_t keylen)
{
int ret;
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
if (ctx->base.enc)
ret = aesni_set_encrypt_key(key, keylen * 8, &ctx->ks);
else
ret = aesni_set_decrypt_key(key, keylen * 8, &ctx->ks);
SHA1_Init(&sctx->head); /* handy when benchmarking */
sctx->tail = sctx->head;
sctx->md = sctx->head;
ctx->payload_length = NO_PAYLOAD_LENGTH;
vctx->removetlspad = 1;
vctx->removetlsfixed = SHA_DIGEST_LENGTH + AES_BLOCK_SIZE;
return ret < 0 ? 0 : 1;
}
static void sha1_update(SHA_CTX *c, const void *data, size_t len)
{
const unsigned char *ptr = data;
size_t res;
if ((res = c->num)) {
res = SHA_CBLOCK - res;
if (len < res)
res = len;
SHA1_Update(c, ptr, res);
ptr += res;
len -= res;
}
res = len % SHA_CBLOCK;
len -= res;
if (len) {
sha1_block_data_order(c, ptr, len / SHA_CBLOCK);
ptr += len;
c->Nh += len >> 29;
c->Nl += len <<= 3;
if (c->Nl < (unsigned int)len)
c->Nh++;
}
if (res)
SHA1_Update(c, ptr, res);
}
# if !defined(OPENSSL_NO_MULTIBLOCK)
typedef struct {
unsigned int A[8], B[8], C[8], D[8], E[8];
} SHA1_MB_CTX;
typedef struct {
const unsigned char *ptr;
int blocks;
} HASH_DESC;
typedef struct {
const unsigned char *inp;
unsigned char *out;
int blocks;
u64 iv[2];
} CIPH_DESC;
void sha1_multi_block(SHA1_MB_CTX *, const HASH_DESC *, int);
void aesni_multi_cbc_encrypt(CIPH_DESC *, void *, int);
static size_t tls1_multi_block_encrypt(void *vctx,
unsigned char *out,
const unsigned char *inp,
size_t inp_len, int n4x)
{ /* n4x is 1 or 2 */
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
HASH_DESC hash_d[8], edges[8];
CIPH_DESC ciph_d[8];
unsigned char storage[sizeof(SHA1_MB_CTX) + 32];
union {
u64 q[16];
u32 d[32];
u8 c[128];
} blocks[8];
SHA1_MB_CTX *mctx;
unsigned int frag, last, packlen, i;
unsigned int x4 = 4 * n4x, minblocks, processed = 0;
size_t ret = 0;
u8 *IVs;
# if defined(BSWAP8)
u64 seqnum;
# endif
/* ask for IVs in bulk */
if (RAND_bytes_ex(ctx->base.libctx, (IVs = blocks[0].c), 16 * x4, 0) <= 0)
return 0;
mctx = (SHA1_MB_CTX *) (storage + 32 - ((size_t)storage % 32)); /* align */
frag = (unsigned int)inp_len >> (1 + n4x);
last = (unsigned int)inp_len + frag - (frag << (1 + n4x));
if (last > frag && ((last + 13 + 9) % 64) < (x4 - 1)) {
frag++;
last -= x4 - 1;
}
packlen = 5 + 16 + ((frag + 20 + 16) & -16);
/* populate descriptors with pointers and IVs */
hash_d[0].ptr = inp;
ciph_d[0].inp = inp;
/* 5+16 is place for header and explicit IV */
ciph_d[0].out = out + 5 + 16;
memcpy(ciph_d[0].out - 16, IVs, 16);
memcpy(ciph_d[0].iv, IVs, 16);
IVs += 16;
for (i = 1; i < x4; i++) {
ciph_d[i].inp = hash_d[i].ptr = hash_d[i - 1].ptr + frag;
ciph_d[i].out = ciph_d[i - 1].out + packlen;
memcpy(ciph_d[i].out - 16, IVs, 16);
memcpy(ciph_d[i].iv, IVs, 16);
IVs += 16;
}
# if defined(BSWAP8)
memcpy(blocks[0].c, sctx->md.data, 8);
seqnum = BSWAP8(blocks[0].q[0]);
# endif
for (i = 0; i < x4; i++) {
unsigned int len = (i == (x4 - 1) ? last : frag);
# if !defined(BSWAP8)
unsigned int carry, j;
# endif
mctx->A[i] = sctx->md.h0;
mctx->B[i] = sctx->md.h1;
mctx->C[i] = sctx->md.h2;
mctx->D[i] = sctx->md.h3;
mctx->E[i] = sctx->md.h4;
/* fix seqnum */
# if defined(BSWAP8)
blocks[i].q[0] = BSWAP8(seqnum + i);
# else
for (carry = i, j = 8; j--;) {
blocks[i].c[j] = ((u8 *)sctx->md.data)[j] + carry;
carry = (blocks[i].c[j] - carry) >> (sizeof(carry) * 8 - 1);
}
# endif
blocks[i].c[8] = ((u8 *)sctx->md.data)[8];
blocks[i].c[9] = ((u8 *)sctx->md.data)[9];
blocks[i].c[10] = ((u8 *)sctx->md.data)[10];
/* fix length */
blocks[i].c[11] = (u8)(len >> 8);
blocks[i].c[12] = (u8)(len);
memcpy(blocks[i].c + 13, hash_d[i].ptr, 64 - 13);
hash_d[i].ptr += 64 - 13;
hash_d[i].blocks = (len - (64 - 13)) / 64;
edges[i].ptr = blocks[i].c;
edges[i].blocks = 1;
}
/* hash 13-byte headers and first 64-13 bytes of inputs */
sha1_multi_block(mctx, edges, n4x);
/* hash bulk inputs */
# define MAXCHUNKSIZE 2048
# if MAXCHUNKSIZE%64
# error "MAXCHUNKSIZE is not divisible by 64"
# elif MAXCHUNKSIZE
/*
* goal is to minimize pressure on L1 cache by moving in shorter steps,
* so that hashed data is still in the cache by the time we encrypt it
*/
minblocks = ((frag <= last ? frag : last) - (64 - 13)) / 64;
if (minblocks > MAXCHUNKSIZE / 64) {
for (i = 0; i < x4; i++) {
edges[i].ptr = hash_d[i].ptr;
edges[i].blocks = MAXCHUNKSIZE / 64;
ciph_d[i].blocks = MAXCHUNKSIZE / 16;
}
do {
sha1_multi_block(mctx, edges, n4x);
aesni_multi_cbc_encrypt(ciph_d, &ctx->ks, n4x);
for (i = 0; i < x4; i++) {
edges[i].ptr = hash_d[i].ptr += MAXCHUNKSIZE;
hash_d[i].blocks -= MAXCHUNKSIZE / 64;
edges[i].blocks = MAXCHUNKSIZE / 64;
ciph_d[i].inp += MAXCHUNKSIZE;
ciph_d[i].out += MAXCHUNKSIZE;
ciph_d[i].blocks = MAXCHUNKSIZE / 16;
memcpy(ciph_d[i].iv, ciph_d[i].out - 16, 16);
}
processed += MAXCHUNKSIZE;
minblocks -= MAXCHUNKSIZE / 64;
} while (minblocks > MAXCHUNKSIZE / 64);
}
# endif
# undef MAXCHUNKSIZE
sha1_multi_block(mctx, hash_d, n4x);
memset(blocks, 0, sizeof(blocks));
for (i = 0; i < x4; i++) {
unsigned int len = (i == (x4 - 1) ? last : frag),
off = hash_d[i].blocks * 64;
const unsigned char *ptr = hash_d[i].ptr + off;
off = (len - processed) - (64 - 13) - off; /* remainder actually */
memcpy(blocks[i].c, ptr, off);
blocks[i].c[off] = 0x80;
len += 64 + 13; /* 64 is HMAC header */
len *= 8; /* convert to bits */
if (off < (64 - 8)) {
# ifdef BSWAP4
blocks[i].d[15] = BSWAP4(len);
# else
PUTU32(blocks[i].c + 60, len);
# endif
edges[i].blocks = 1;
} else {
# ifdef BSWAP4
blocks[i].d[31] = BSWAP4(len);
# else
PUTU32(blocks[i].c + 124, len);
# endif
edges[i].blocks = 2;
}
edges[i].ptr = blocks[i].c;
}
/* hash input tails and finalize */
sha1_multi_block(mctx, edges, n4x);
memset(blocks, 0, sizeof(blocks));
for (i = 0; i < x4; i++) {
# ifdef BSWAP4
blocks[i].d[0] = BSWAP4(mctx->A[i]);
mctx->A[i] = sctx->tail.h0;
blocks[i].d[1] = BSWAP4(mctx->B[i]);
mctx->B[i] = sctx->tail.h1;
blocks[i].d[2] = BSWAP4(mctx->C[i]);
mctx->C[i] = sctx->tail.h2;
blocks[i].d[3] = BSWAP4(mctx->D[i]);
mctx->D[i] = sctx->tail.h3;
blocks[i].d[4] = BSWAP4(mctx->E[i]);
mctx->E[i] = sctx->tail.h4;
blocks[i].c[20] = 0x80;
blocks[i].d[15] = BSWAP4((64 + 20) * 8);
# else
PUTU32(blocks[i].c + 0, mctx->A[i]);
mctx->A[i] = sctx->tail.h0;
PUTU32(blocks[i].c + 4, mctx->B[i]);
mctx->B[i] = sctx->tail.h1;
PUTU32(blocks[i].c + 8, mctx->C[i]);
mctx->C[i] = sctx->tail.h2;
PUTU32(blocks[i].c + 12, mctx->D[i]);
mctx->D[i] = sctx->tail.h3;
PUTU32(blocks[i].c + 16, mctx->E[i]);
mctx->E[i] = sctx->tail.h4;
blocks[i].c[20] = 0x80;
PUTU32(blocks[i].c + 60, (64 + 20) * 8);
# endif /* BSWAP */
edges[i].ptr = blocks[i].c;
edges[i].blocks = 1;
}
/* finalize MACs */
sha1_multi_block(mctx, edges, n4x);
for (i = 0; i < x4; i++) {
unsigned int len = (i == (x4 - 1) ? last : frag), pad, j;
unsigned char *out0 = out;
memcpy(ciph_d[i].out, ciph_d[i].inp, len - processed);
ciph_d[i].inp = ciph_d[i].out;
out += 5 + 16 + len;
/* write MAC */
PUTU32(out + 0, mctx->A[i]);
PUTU32(out + 4, mctx->B[i]);
PUTU32(out + 8, mctx->C[i]);
PUTU32(out + 12, mctx->D[i]);
PUTU32(out + 16, mctx->E[i]);
out += 20;
len += 20;
/* pad */
pad = 15 - len % 16;
for (j = 0; j <= pad; j++)
*(out++) = pad;
len += pad + 1;
ciph_d[i].blocks = (len - processed) / 16;
len += 16; /* account for explicit iv */
/* arrange header */
out0[0] = ((u8 *)sctx->md.data)[8];
out0[1] = ((u8 *)sctx->md.data)[9];
out0[2] = ((u8 *)sctx->md.data)[10];
out0[3] = (u8)(len >> 8);
out0[4] = (u8)(len);
ret += len + 5;
inp += frag;
}
aesni_multi_cbc_encrypt(ciph_d, &ctx->ks, n4x);
OPENSSL_cleanse(blocks, sizeof(blocks));
OPENSSL_cleanse(mctx, sizeof(*mctx));
ctx->multiblock_encrypt_len = ret;
return ret;
}
# endif /* OPENSSL_NO_MULTIBLOCK */
static int aesni_cbc_hmac_sha1_cipher(PROV_CIPHER_CTX *vctx,
unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
unsigned int l;
size_t plen = ctx->payload_length;
size_t iv = 0; /* explicit IV in TLS 1.1 and later */
size_t aes_off = 0, blocks;
size_t sha_off = SHA_CBLOCK - sctx->md.num;
ctx->payload_length = NO_PAYLOAD_LENGTH;
if (len % AES_BLOCK_SIZE)
return 0;
if (ctx->base.enc) {
if (plen == NO_PAYLOAD_LENGTH)
plen = len;
else if (len !=
((plen + SHA_DIGEST_LENGTH +
AES_BLOCK_SIZE) & -AES_BLOCK_SIZE))
return 0;
else if (ctx->aux.tls_ver >= TLS1_1_VERSION)
iv = AES_BLOCK_SIZE;
if (plen > (sha_off + iv)
&& (blocks = (plen - (sha_off + iv)) / SHA_CBLOCK)) {
sha1_update(&sctx->md, in + iv, sha_off);
aesni_cbc_sha1_enc(in, out, blocks, &ctx->ks, ctx->base.iv,
&sctx->md, in + iv + sha_off);
blocks *= SHA_CBLOCK;
aes_off += blocks;
sha_off += blocks;
sctx->md.Nh += blocks >> 29;
sctx->md.Nl += blocks <<= 3;
if (sctx->md.Nl < (unsigned int)blocks)
sctx->md.Nh++;
} else {
sha_off = 0;
}
sha_off += iv;
sha1_update(&sctx->md, in + sha_off, plen - sha_off);
if (plen != len) { /* "TLS" mode of operation */
if (in != out)
memcpy(out + aes_off, in + aes_off, plen - aes_off);
/* calculate HMAC and append it to payload */
SHA1_Final(out + plen, &sctx->md);
sctx->md = sctx->tail;
sha1_update(&sctx->md, out + plen, SHA_DIGEST_LENGTH);
SHA1_Final(out + plen, &sctx->md);
/* pad the payload|hmac */
plen += SHA_DIGEST_LENGTH;
for (l = len - plen - 1; plen < len; plen++)
out[plen] = l;
/* encrypt HMAC|padding at once */
aesni_cbc_encrypt(out + aes_off, out + aes_off, len - aes_off,
&ctx->ks, ctx->base.iv, 1);
} else {
aesni_cbc_encrypt(in + aes_off, out + aes_off, len - aes_off,
&ctx->ks, ctx->base.iv, 1);
}
} else {
union {
unsigned int u[SHA_DIGEST_LENGTH / sizeof(unsigned int)];
unsigned char c[32 + SHA_DIGEST_LENGTH];
} mac, *pmac;
/* arrange cache line alignment */
pmac = (void *)(((size_t)mac.c + 31) & ((size_t)0 - 32));
if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */
size_t inp_len, mask, j, i;
unsigned int res, maxpad, pad, bitlen;
int ret = 1;
union {
unsigned int u[SHA_LBLOCK];
unsigned char c[SHA_CBLOCK];
} *data = (void *)sctx->md.data;
if ((ctx->aux.tls_aad[plen - 4] << 8 | ctx->aux.tls_aad[plen - 3])
>= TLS1_1_VERSION) {
if (len < (AES_BLOCK_SIZE + SHA_DIGEST_LENGTH + 1))
return 0;
/* omit explicit iv */
memcpy(ctx->base.iv, in, AES_BLOCK_SIZE);
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
len -= AES_BLOCK_SIZE;
} else if (len < (SHA_DIGEST_LENGTH + 1))
return 0;
/* decrypt HMAC|padding at once */
aesni_cbc_encrypt(in, out, len, &ctx->ks, ctx->base.iv, 0);
/* figure out payload length */
pad = out[len - 1];
maxpad = len - (SHA_DIGEST_LENGTH + 1);
maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8);
maxpad &= 255;
mask = constant_time_ge(maxpad, pad);
ret &= mask;
/*
* If pad is invalid then we will fail the above test but we must
* continue anyway because we are in constant time code. However,
* we'll use the maxpad value instead of the supplied pad to make
* sure we perform well defined pointer arithmetic.
*/
pad = constant_time_select(mask, pad, maxpad);
inp_len = len - (SHA_DIGEST_LENGTH + pad + 1);
ctx->aux.tls_aad[plen - 2] = inp_len >> 8;
ctx->aux.tls_aad[plen - 1] = inp_len;
/* calculate HMAC */
sctx->md = sctx->head;
sha1_update(&sctx->md, ctx->aux.tls_aad, plen);
/* code containing lucky-13 fix */
len -= SHA_DIGEST_LENGTH; /* amend mac */
if (len >= (256 + SHA_CBLOCK)) {
j = (len - (256 + SHA_CBLOCK)) & (0 - SHA_CBLOCK);
j += SHA_CBLOCK - sctx->md.num;
sha1_update(&sctx->md, out, j);
out += j;
len -= j;
inp_len -= j;
}
/* but pretend as if we hashed padded payload */
bitlen = sctx->md.Nl + (inp_len << 3); /* at most 18 bits */
# ifdef BSWAP4
bitlen = BSWAP4(bitlen);
# else
mac.c[0] = 0;
mac.c[1] = (unsigned char)(bitlen >> 16);
mac.c[2] = (unsigned char)(bitlen >> 8);
mac.c[3] = (unsigned char)bitlen;
bitlen = mac.u[0];
# endif /* BSWAP */
pmac->u[0] = 0;
pmac->u[1] = 0;
pmac->u[2] = 0;
pmac->u[3] = 0;
pmac->u[4] = 0;
for (res = sctx->md.num, j = 0; j < len; j++) {
size_t c = out[j];
mask = (j - inp_len) >> (sizeof(j) * 8 - 8);
c &= mask;
c |= 0x80 & ~mask & ~((inp_len - j) >> (sizeof(j) * 8 - 8));
data->c[res++] = (unsigned char)c;
if (res != SHA_CBLOCK)
continue;
/* j is not incremented yet */
mask = 0 - ((inp_len + 7 - j) >> (sizeof(j) * 8 - 1));
data->u[SHA_LBLOCK - 1] |= bitlen & mask;
sha1_block_data_order(&sctx->md, data, 1);
mask &= 0 - ((j - inp_len - 72) >> (sizeof(j) * 8 - 1));
pmac->u[0] |= sctx->md.h0 & mask;
pmac->u[1] |= sctx->md.h1 & mask;
pmac->u[2] |= sctx->md.h2 & mask;
pmac->u[3] |= sctx->md.h3 & mask;
pmac->u[4] |= sctx->md.h4 & mask;
res = 0;
}
for (i = res; i < SHA_CBLOCK; i++, j++)
data->c[i] = 0;
if (res > SHA_CBLOCK - 8) {
mask = 0 - ((inp_len + 8 - j) >> (sizeof(j) * 8 - 1));
data->u[SHA_LBLOCK - 1] |= bitlen & mask;
sha1_block_data_order(&sctx->md, data, 1);
mask &= 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1));
pmac->u[0] |= sctx->md.h0 & mask;
pmac->u[1] |= sctx->md.h1 & mask;
pmac->u[2] |= sctx->md.h2 & mask;
pmac->u[3] |= sctx->md.h3 & mask;
pmac->u[4] |= sctx->md.h4 & mask;
memset(data, 0, SHA_CBLOCK);
j += 64;
}
data->u[SHA_LBLOCK - 1] = bitlen;
sha1_block_data_order(&sctx->md, data, 1);
mask = 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1));
pmac->u[0] |= sctx->md.h0 & mask;
pmac->u[1] |= sctx->md.h1 & mask;
pmac->u[2] |= sctx->md.h2 & mask;
pmac->u[3] |= sctx->md.h3 & mask;
pmac->u[4] |= sctx->md.h4 & mask;
# ifdef BSWAP4
pmac->u[0] = BSWAP4(pmac->u[0]);
pmac->u[1] = BSWAP4(pmac->u[1]);
pmac->u[2] = BSWAP4(pmac->u[2]);
pmac->u[3] = BSWAP4(pmac->u[3]);
pmac->u[4] = BSWAP4(pmac->u[4]);
# else
for (i = 0; i < 5; i++) {
res = pmac->u[i];
pmac->c[4 * i + 0] = (unsigned char)(res >> 24);
pmac->c[4 * i + 1] = (unsigned char)(res >> 16);
pmac->c[4 * i + 2] = (unsigned char)(res >> 8);
pmac->c[4 * i + 3] = (unsigned char)res;
}
# endif /* BSWAP4 */
len += SHA_DIGEST_LENGTH;
sctx->md = sctx->tail;
sha1_update(&sctx->md, pmac->c, SHA_DIGEST_LENGTH);
SHA1_Final(pmac->c, &sctx->md);
/* verify HMAC */
out += inp_len;
len -= inp_len;
/* version of code with lucky-13 fix */
{
unsigned char *p = out + len - 1 - maxpad - SHA_DIGEST_LENGTH;
size_t off = out - p;
unsigned int c, cmask;
for (res = 0, i = 0, j = 0; j < maxpad + SHA_DIGEST_LENGTH; j++) {
c = p[j];
cmask =
((int)(j - off - SHA_DIGEST_LENGTH)) >> (sizeof(int) *
8 - 1);
res |= (c ^ pad) & ~cmask; /* ... and padding */
cmask &= ((int)(off - 1 - j)) >> (sizeof(int) * 8 - 1);
res |= (c ^ pmac->c[i]) & cmask;
i += 1 & cmask;
}
res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1));
ret &= (int)~res;
}
return ret;
} else {
/* decrypt HMAC|padding at once */
aesni_cbc_encrypt(in, out, len, &ctx->ks, ctx->base.iv, 0);
sha1_update(&sctx->md, out, len);
}
}
return 1;
}
/* EVP_CTRL_AEAD_SET_MAC_KEY */
static void aesni_cbc_hmac_sha1_set_mac_key(void *vctx,
const unsigned char *mac, size_t len)
{
PROV_AES_HMAC_SHA1_CTX *ctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
unsigned int i;
unsigned char hmac_key[64];
memset(hmac_key, 0, sizeof(hmac_key));
if (len > (int)sizeof(hmac_key)) {
SHA1_Init(&ctx->head);
sha1_update(&ctx->head, mac, len);
SHA1_Final(hmac_key, &ctx->head);
} else {
memcpy(hmac_key, mac, len);
}
for (i = 0; i < sizeof(hmac_key); i++)
hmac_key[i] ^= 0x36; /* ipad */
SHA1_Init(&ctx->head);
sha1_update(&ctx->head, hmac_key, sizeof(hmac_key));
for (i = 0; i < sizeof(hmac_key); i++)
hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */
SHA1_Init(&ctx->tail);
sha1_update(&ctx->tail, hmac_key, sizeof(hmac_key));
OPENSSL_cleanse(hmac_key, sizeof(hmac_key));
}
/* EVP_CTRL_AEAD_TLS1_AAD */
static int aesni_cbc_hmac_sha1_set_tls1_aad(void *vctx,
unsigned char *aad_rec, int aad_len)
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
unsigned char *p = aad_rec;
unsigned int len;
if (aad_len != EVP_AEAD_TLS1_AAD_LEN)
return -1;
len = p[aad_len - 2] << 8 | p[aad_len - 1];
if (ctx->base.enc) {
ctx->payload_length = len;
if ((ctx->aux.tls_ver =
p[aad_len - 4] << 8 | p[aad_len - 3]) >= TLS1_1_VERSION) {
if (len < AES_BLOCK_SIZE)
return 0;
len -= AES_BLOCK_SIZE;
p[aad_len - 2] = len >> 8;
p[aad_len - 1] = len;
}
sctx->md = sctx->head;
sha1_update(&sctx->md, p, aad_len);
ctx->tls_aad_pad = (int)(((len + SHA_DIGEST_LENGTH +
AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)
- len);
return 1;
} else {
memcpy(ctx->aux.tls_aad, aad_rec, aad_len);
ctx->payload_length = aad_len;
ctx->tls_aad_pad = SHA_DIGEST_LENGTH;
return 1;
}
}
# if !defined(OPENSSL_NO_MULTIBLOCK)
/* EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE */
static int aesni_cbc_hmac_sha1_tls1_multiblock_max_bufsize(void *vctx)
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
OPENSSL_assert(ctx->multiblock_max_send_fragment != 0);
return (int)(5 + 16
+ (((int)ctx->multiblock_max_send_fragment + 20 + 16) & -16));
}
/* EVP_CTRL_TLS1_1_MULTIBLOCK_AAD */
static int aesni_cbc_hmac_sha1_tls1_multiblock_aad(
void *vctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param)
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx;
unsigned int n4x = 1, x4;
unsigned int frag, last, packlen, inp_len;
inp_len = param->inp[11] << 8 | param->inp[12];
ctx->multiblock_interleave = param->interleave;
if (ctx->base.enc) {
if ((param->inp[9] << 8 | param->inp[10]) < TLS1_1_VERSION)
return -1;
if (inp_len) {
if (inp_len < 4096)
return 0; /* too short */
if (inp_len >= 8192 && OPENSSL_ia32cap_P[2] & (1 << 5))
n4x = 2; /* AVX2 */
} else if ((n4x = param->interleave / 4) && n4x <= 2)
inp_len = param->len;
else
return -1;
sctx->md = sctx->head;
sha1_update(&sctx->md, param->inp, 13);
x4 = 4 * n4x;
n4x += 1;
frag = inp_len >> n4x;
last = inp_len + frag - (frag << n4x);
if (last > frag && ((last + 13 + 9) % 64 < (x4 - 1))) {
frag++;
last -= x4 - 1;
}
packlen = 5 + 16 + ((frag + 20 + 16) & -16);
packlen = (packlen << n4x) - packlen;
packlen += 5 + 16 + ((last + 20 + 16) & -16);
param->interleave = x4;
/* The returned values used by get need to be stored */
ctx->multiblock_interleave = x4;
ctx->multiblock_aad_packlen = packlen;
return 1;
}
return -1; /* not yet */
}
/* EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT */
static int aesni_cbc_hmac_sha1_tls1_multiblock_encrypt(
void *ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param)
{
return (int)tls1_multi_block_encrypt(ctx, param->out,
param->inp, param->len,
param->interleave / 4);
}
# endif /* OPENSSL_NO_MULTIBLOCK */
static const PROV_CIPHER_HW_AES_HMAC_SHA cipher_hw_aes_hmac_sha1 = {
{
aesni_cbc_hmac_sha1_init_key,
aesni_cbc_hmac_sha1_cipher
},
aesni_cbc_hmac_sha1_set_mac_key,
aesni_cbc_hmac_sha1_set_tls1_aad,
# if !defined(OPENSSL_NO_MULTIBLOCK)
aesni_cbc_hmac_sha1_tls1_multiblock_max_bufsize,
aesni_cbc_hmac_sha1_tls1_multiblock_aad,
aesni_cbc_hmac_sha1_tls1_multiblock_encrypt
# endif
};
const PROV_CIPHER_HW_AES_HMAC_SHA *ossl_prov_cipher_hw_aes_cbc_hmac_sha1(void)
{
return &cipher_hw_aes_hmac_sha1;
}
#endif /* !defined(AES_CBC_HMAC_SHA_CAPABLE) || !defined(AESNI_CAPABLE) */

View File

@@ -0,0 +1,846 @@
/*
* Copyright 2011-2021 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
*/
/*
* All low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
#include "cipher_aes_cbc_hmac_sha.h"
#if !defined(AES_CBC_HMAC_SHA_CAPABLE) || !defined(AESNI_CAPABLE)
int ossl_cipher_capable_aes_cbc_hmac_sha256(void)
{
return 0;
}
const PROV_CIPHER_HW_AES_HMAC_SHA *ossl_prov_cipher_hw_aes_cbc_hmac_sha256(void)
{
return NULL;
}
#else
# include <openssl/rand.h>
# include "crypto/evp.h"
# include "internal/constant_time.h"
void sha256_block_data_order(void *c, const void *p, size_t len);
int aesni_cbc_sha256_enc(const void *inp, void *out, size_t blocks,
const AES_KEY *key, unsigned char iv[16],
SHA256_CTX *ctx, const void *in0);
int ossl_cipher_capable_aes_cbc_hmac_sha256(void)
{
return AESNI_CBC_HMAC_SHA_CAPABLE
&& aesni_cbc_sha256_enc(NULL, NULL, 0, NULL, NULL, NULL, NULL);
}
static int aesni_cbc_hmac_sha256_init_key(PROV_CIPHER_CTX *vctx,
const unsigned char *key,
size_t keylen)
{
int ret;
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
if (ctx->base.enc)
ret = aesni_set_encrypt_key(key, ctx->base.keylen * 8, &ctx->ks);
else
ret = aesni_set_decrypt_key(key, ctx->base.keylen * 8, &ctx->ks);
SHA256_Init(&sctx->head); /* handy when benchmarking */
sctx->tail = sctx->head;
sctx->md = sctx->head;
ctx->payload_length = NO_PAYLOAD_LENGTH;
vctx->removetlspad = 1;
vctx->removetlsfixed = SHA256_DIGEST_LENGTH + AES_BLOCK_SIZE;
return ret < 0 ? 0 : 1;
}
void sha256_block_data_order(void *c, const void *p, size_t len);
static void sha256_update(SHA256_CTX *c, const void *data, size_t len)
{
const unsigned char *ptr = data;
size_t res;
if ((res = c->num)) {
res = SHA256_CBLOCK - res;
if (len < res)
res = len;
SHA256_Update(c, ptr, res);
ptr += res;
len -= res;
}
res = len % SHA256_CBLOCK;
len -= res;
if (len) {
sha256_block_data_order(c, ptr, len / SHA256_CBLOCK);
ptr += len;
c->Nh += len >> 29;
c->Nl += len <<= 3;
if (c->Nl < (unsigned int)len)
c->Nh++;
}
if (res)
SHA256_Update(c, ptr, res);
}
# if !defined(OPENSSL_NO_MULTIBLOCK)
typedef struct {
unsigned int A[8], B[8], C[8], D[8], E[8], F[8], G[8], H[8];
} SHA256_MB_CTX;
typedef struct {
const unsigned char *ptr;
int blocks;
} HASH_DESC;
typedef struct {
const unsigned char *inp;
unsigned char *out;
int blocks;
u64 iv[2];
} CIPH_DESC;
void sha256_multi_block(SHA256_MB_CTX *, const HASH_DESC *, int);
void aesni_multi_cbc_encrypt(CIPH_DESC *, void *, int);
static size_t tls1_multi_block_encrypt(void *vctx,
unsigned char *out,
const unsigned char *inp,
size_t inp_len, int n4x)
{ /* n4x is 1 or 2 */
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
HASH_DESC hash_d[8], edges[8];
CIPH_DESC ciph_d[8];
unsigned char storage[sizeof(SHA256_MB_CTX) + 32];
union {
u64 q[16];
u32 d[32];
u8 c[128];
} blocks[8];
SHA256_MB_CTX *mctx;
unsigned int frag, last, packlen, i;
unsigned int x4 = 4 * n4x, minblocks, processed = 0;
size_t ret = 0;
u8 *IVs;
# if defined(BSWAP8)
u64 seqnum;
# endif
/* ask for IVs in bulk */
if (RAND_bytes_ex(ctx->base.libctx, (IVs = blocks[0].c), 16 * x4, 0) <= 0)
return 0;
mctx = (SHA256_MB_CTX *) (storage + 32 - ((size_t)storage % 32)); /* align */
frag = (unsigned int)inp_len >> (1 + n4x);
last = (unsigned int)inp_len + frag - (frag << (1 + n4x));
if (last > frag && ((last + 13 + 9) % 64) < (x4 - 1)) {
frag++;
last -= x4 - 1;
}
packlen = 5 + 16 + ((frag + 32 + 16) & -16);
/* populate descriptors with pointers and IVs */
hash_d[0].ptr = inp;
ciph_d[0].inp = inp;
/* 5+16 is place for header and explicit IV */
ciph_d[0].out = out + 5 + 16;
memcpy(ciph_d[0].out - 16, IVs, 16);
memcpy(ciph_d[0].iv, IVs, 16);
IVs += 16;
for (i = 1; i < x4; i++) {
ciph_d[i].inp = hash_d[i].ptr = hash_d[i - 1].ptr + frag;
ciph_d[i].out = ciph_d[i - 1].out + packlen;
memcpy(ciph_d[i].out - 16, IVs, 16);
memcpy(ciph_d[i].iv, IVs, 16);
IVs += 16;
}
# if defined(BSWAP8)
memcpy(blocks[0].c, sctx->md.data, 8);
seqnum = BSWAP8(blocks[0].q[0]);
# endif
for (i = 0; i < x4; i++) {
unsigned int len = (i == (x4 - 1) ? last : frag);
# if !defined(BSWAP8)
unsigned int carry, j;
# endif
mctx->A[i] = sctx->md.h[0];
mctx->B[i] = sctx->md.h[1];
mctx->C[i] = sctx->md.h[2];
mctx->D[i] = sctx->md.h[3];
mctx->E[i] = sctx->md.h[4];
mctx->F[i] = sctx->md.h[5];
mctx->G[i] = sctx->md.h[6];
mctx->H[i] = sctx->md.h[7];
/* fix seqnum */
# if defined(BSWAP8)
blocks[i].q[0] = BSWAP8(seqnum + i);
# else
for (carry = i, j = 8; j--;) {
blocks[i].c[j] = ((u8 *)sctx->md.data)[j] + carry;
carry = (blocks[i].c[j] - carry) >> (sizeof(carry) * 8 - 1);
}
# endif
blocks[i].c[8] = ((u8 *)sctx->md.data)[8];
blocks[i].c[9] = ((u8 *)sctx->md.data)[9];
blocks[i].c[10] = ((u8 *)sctx->md.data)[10];
/* fix length */
blocks[i].c[11] = (u8)(len >> 8);
blocks[i].c[12] = (u8)(len);
memcpy(blocks[i].c + 13, hash_d[i].ptr, 64 - 13);
hash_d[i].ptr += 64 - 13;
hash_d[i].blocks = (len - (64 - 13)) / 64;
edges[i].ptr = blocks[i].c;
edges[i].blocks = 1;
}
/* hash 13-byte headers and first 64-13 bytes of inputs */
sha256_multi_block(mctx, edges, n4x);
/* hash bulk inputs */
# define MAXCHUNKSIZE 2048
# if MAXCHUNKSIZE%64
# error "MAXCHUNKSIZE is not divisible by 64"
# elif MAXCHUNKSIZE
/*
* goal is to minimize pressure on L1 cache by moving in shorter steps,
* so that hashed data is still in the cache by the time we encrypt it
*/
minblocks = ((frag <= last ? frag : last) - (64 - 13)) / 64;
if (minblocks > MAXCHUNKSIZE / 64) {
for (i = 0; i < x4; i++) {
edges[i].ptr = hash_d[i].ptr;
edges[i].blocks = MAXCHUNKSIZE / 64;
ciph_d[i].blocks = MAXCHUNKSIZE / 16;
}
do {
sha256_multi_block(mctx, edges, n4x);
aesni_multi_cbc_encrypt(ciph_d, &ctx->ks, n4x);
for (i = 0; i < x4; i++) {
edges[i].ptr = hash_d[i].ptr += MAXCHUNKSIZE;
hash_d[i].blocks -= MAXCHUNKSIZE / 64;
edges[i].blocks = MAXCHUNKSIZE / 64;
ciph_d[i].inp += MAXCHUNKSIZE;
ciph_d[i].out += MAXCHUNKSIZE;
ciph_d[i].blocks = MAXCHUNKSIZE / 16;
memcpy(ciph_d[i].iv, ciph_d[i].out - 16, 16);
}
processed += MAXCHUNKSIZE;
minblocks -= MAXCHUNKSIZE / 64;
} while (minblocks > MAXCHUNKSIZE / 64);
}
# endif
# undef MAXCHUNKSIZE
sha256_multi_block(mctx, hash_d, n4x);
memset(blocks, 0, sizeof(blocks));
for (i = 0; i < x4; i++) {
unsigned int len = (i == (x4 - 1) ? last : frag),
off = hash_d[i].blocks * 64;
const unsigned char *ptr = hash_d[i].ptr + off;
off = (len - processed) - (64 - 13) - off; /* remainder actually */
memcpy(blocks[i].c, ptr, off);
blocks[i].c[off] = 0x80;
len += 64 + 13; /* 64 is HMAC header */
len *= 8; /* convert to bits */
if (off < (64 - 8)) {
# ifdef BSWAP4
blocks[i].d[15] = BSWAP4(len);
# else
PUTU32(blocks[i].c + 60, len);
# endif
edges[i].blocks = 1;
} else {
# ifdef BSWAP4
blocks[i].d[31] = BSWAP4(len);
# else
PUTU32(blocks[i].c + 124, len);
# endif
edges[i].blocks = 2;
}
edges[i].ptr = blocks[i].c;
}
/* hash input tails and finalize */
sha256_multi_block(mctx, edges, n4x);
memset(blocks, 0, sizeof(blocks));
for (i = 0; i < x4; i++) {
# ifdef BSWAP4
blocks[i].d[0] = BSWAP4(mctx->A[i]);
mctx->A[i] = sctx->tail.h[0];
blocks[i].d[1] = BSWAP4(mctx->B[i]);
mctx->B[i] = sctx->tail.h[1];
blocks[i].d[2] = BSWAP4(mctx->C[i]);
mctx->C[i] = sctx->tail.h[2];
blocks[i].d[3] = BSWAP4(mctx->D[i]);
mctx->D[i] = sctx->tail.h[3];
blocks[i].d[4] = BSWAP4(mctx->E[i]);
mctx->E[i] = sctx->tail.h[4];
blocks[i].d[5] = BSWAP4(mctx->F[i]);
mctx->F[i] = sctx->tail.h[5];
blocks[i].d[6] = BSWAP4(mctx->G[i]);
mctx->G[i] = sctx->tail.h[6];
blocks[i].d[7] = BSWAP4(mctx->H[i]);
mctx->H[i] = sctx->tail.h[7];
blocks[i].c[32] = 0x80;
blocks[i].d[15] = BSWAP4((64 + 32) * 8);
# else
PUTU32(blocks[i].c + 0, mctx->A[i]);
mctx->A[i] = sctx->tail.h[0];
PUTU32(blocks[i].c + 4, mctx->B[i]);
mctx->B[i] = sctx->tail.h[1];
PUTU32(blocks[i].c + 8, mctx->C[i]);
mctx->C[i] = sctx->tail.h[2];
PUTU32(blocks[i].c + 12, mctx->D[i]);
mctx->D[i] = sctx->tail.h[3];
PUTU32(blocks[i].c + 16, mctx->E[i]);
mctx->E[i] = sctx->tail.h[4];
PUTU32(blocks[i].c + 20, mctx->F[i]);
mctx->F[i] = sctx->tail.h[5];
PUTU32(blocks[i].c + 24, mctx->G[i]);
mctx->G[i] = sctx->tail.h[6];
PUTU32(blocks[i].c + 28, mctx->H[i]);
mctx->H[i] = sctx->tail.h[7];
blocks[i].c[32] = 0x80;
PUTU32(blocks[i].c + 60, (64 + 32) * 8);
# endif /* BSWAP */
edges[i].ptr = blocks[i].c;
edges[i].blocks = 1;
}
/* finalize MACs */
sha256_multi_block(mctx, edges, n4x);
for (i = 0; i < x4; i++) {
unsigned int len = (i == (x4 - 1) ? last : frag), pad, j;
unsigned char *out0 = out;
memcpy(ciph_d[i].out, ciph_d[i].inp, len - processed);
ciph_d[i].inp = ciph_d[i].out;
out += 5 + 16 + len;
/* write MAC */
PUTU32(out + 0, mctx->A[i]);
PUTU32(out + 4, mctx->B[i]);
PUTU32(out + 8, mctx->C[i]);
PUTU32(out + 12, mctx->D[i]);
PUTU32(out + 16, mctx->E[i]);
PUTU32(out + 20, mctx->F[i]);
PUTU32(out + 24, mctx->G[i]);
PUTU32(out + 28, mctx->H[i]);
out += 32;
len += 32;
/* pad */
pad = 15 - len % 16;
for (j = 0; j <= pad; j++)
*(out++) = pad;
len += pad + 1;
ciph_d[i].blocks = (len - processed) / 16;
len += 16; /* account for explicit iv */
/* arrange header */
out0[0] = ((u8 *)sctx->md.data)[8];
out0[1] = ((u8 *)sctx->md.data)[9];
out0[2] = ((u8 *)sctx->md.data)[10];
out0[3] = (u8)(len >> 8);
out0[4] = (u8)(len);
ret += len + 5;
inp += frag;
}
aesni_multi_cbc_encrypt(ciph_d, &ctx->ks, n4x);
OPENSSL_cleanse(blocks, sizeof(blocks));
OPENSSL_cleanse(mctx, sizeof(*mctx));
ctx->multiblock_encrypt_len = ret;
return ret;
}
# endif /* !OPENSSL_NO_MULTIBLOCK */
static int aesni_cbc_hmac_sha256_cipher(PROV_CIPHER_CTX *vctx,
unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
unsigned int l;
size_t plen = ctx->payload_length;
size_t iv = 0; /* explicit IV in TLS 1.1 and * later */
size_t aes_off = 0, blocks;
size_t sha_off = SHA256_CBLOCK - sctx->md.num;
ctx->payload_length = NO_PAYLOAD_LENGTH;
if (len % AES_BLOCK_SIZE)
return 0;
if (ctx->base.enc) {
if (plen == NO_PAYLOAD_LENGTH)
plen = len;
else if (len !=
((plen + SHA256_DIGEST_LENGTH +
AES_BLOCK_SIZE) & -AES_BLOCK_SIZE))
return 0;
else if (ctx->aux.tls_ver >= TLS1_1_VERSION)
iv = AES_BLOCK_SIZE;
/*
* Assembly stitch handles AVX-capable processors, but its
* performance is not optimal on AMD Jaguar, ~40% worse, for
* unknown reasons. Incidentally processor in question supports
* AVX, but not AMD-specific XOP extension, which can be used
* to identify it and avoid stitch invocation. So that after we
* establish that current CPU supports AVX, we even see if it's
* either even XOP-capable Bulldozer-based or GenuineIntel one.
* But SHAEXT-capable go ahead...
*/
if (((OPENSSL_ia32cap_P[2] & (1 << 29)) || /* SHAEXT? */
((OPENSSL_ia32cap_P[1] & (1 << (60 - 32))) && /* AVX? */
((OPENSSL_ia32cap_P[1] & (1 << (43 - 32))) /* XOP? */
| (OPENSSL_ia32cap_P[0] & (1 << 30))))) && /* "Intel CPU"? */
plen > (sha_off + iv) &&
(blocks = (plen - (sha_off + iv)) / SHA256_CBLOCK)) {
sha256_update(&sctx->md, in + iv, sha_off);
(void)aesni_cbc_sha256_enc(in, out, blocks, &ctx->ks,
ctx->base.iv,
&sctx->md, in + iv + sha_off);
blocks *= SHA256_CBLOCK;
aes_off += blocks;
sha_off += blocks;
sctx->md.Nh += blocks >> 29;
sctx->md.Nl += blocks <<= 3;
if (sctx->md.Nl < (unsigned int)blocks)
sctx->md.Nh++;
} else {
sha_off = 0;
}
sha_off += iv;
sha256_update(&sctx->md, in + sha_off, plen - sha_off);
if (plen != len) { /* "TLS" mode of operation */
if (in != out)
memcpy(out + aes_off, in + aes_off, plen - aes_off);
/* calculate HMAC and append it to payload */
SHA256_Final(out + plen, &sctx->md);
sctx->md = sctx->tail;
sha256_update(&sctx->md, out + plen, SHA256_DIGEST_LENGTH);
SHA256_Final(out + plen, &sctx->md);
/* pad the payload|hmac */
plen += SHA256_DIGEST_LENGTH;
for (l = len - plen - 1; plen < len; plen++)
out[plen] = l;
/* encrypt HMAC|padding at once */
aesni_cbc_encrypt(out + aes_off, out + aes_off, len - aes_off,
&ctx->ks, ctx->base.iv, 1);
} else {
aesni_cbc_encrypt(in + aes_off, out + aes_off, len - aes_off,
&ctx->ks, ctx->base.iv, 1);
}
} else {
union {
unsigned int u[SHA256_DIGEST_LENGTH / sizeof(unsigned int)];
unsigned char c[64 + SHA256_DIGEST_LENGTH];
} mac, *pmac;
/* arrange cache line alignment */
pmac = (void *)(((size_t)mac.c + 63) & ((size_t)0 - 64));
/* decrypt HMAC|padding at once */
aesni_cbc_encrypt(in, out, len, &ctx->ks,
ctx->base.iv, 0);
if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */
size_t inp_len, mask, j, i;
unsigned int res, maxpad, pad, bitlen;
int ret = 1;
union {
unsigned int u[SHA_LBLOCK];
unsigned char c[SHA256_CBLOCK];
} *data = (void *)sctx->md.data;
if ((ctx->aux.tls_aad[plen - 4] << 8 | ctx->aux.tls_aad[plen - 3])
>= TLS1_1_VERSION)
iv = AES_BLOCK_SIZE;
if (len < (iv + SHA256_DIGEST_LENGTH + 1))
return 0;
/* omit explicit iv */
out += iv;
len -= iv;
/* figure out payload length */
pad = out[len - 1];
maxpad = len - (SHA256_DIGEST_LENGTH + 1);
maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8);
maxpad &= 255;
mask = constant_time_ge(maxpad, pad);
ret &= mask;
/*
* If pad is invalid then we will fail the above test but we must
* continue anyway because we are in constant time code. However,
* we'll use the maxpad value instead of the supplied pad to make
* sure we perform well defined pointer arithmetic.
*/
pad = constant_time_select(mask, pad, maxpad);
inp_len = len - (SHA256_DIGEST_LENGTH + pad + 1);
ctx->aux.tls_aad[plen - 2] = inp_len >> 8;
ctx->aux.tls_aad[plen - 1] = inp_len;
/* calculate HMAC */
sctx->md = sctx->head;
sha256_update(&sctx->md, ctx->aux.tls_aad, plen);
/* code with lucky-13 fix */
len -= SHA256_DIGEST_LENGTH; /* amend mac */
if (len >= (256 + SHA256_CBLOCK)) {
j = (len - (256 + SHA256_CBLOCK)) & (0 - SHA256_CBLOCK);
j += SHA256_CBLOCK - sctx->md.num;
sha256_update(&sctx->md, out, j);
out += j;
len -= j;
inp_len -= j;
}
/* but pretend as if we hashed padded payload */
bitlen = sctx->md.Nl + (inp_len << 3); /* at most 18 bits */
# ifdef BSWAP4
bitlen = BSWAP4(bitlen);
# else
mac.c[0] = 0;
mac.c[1] = (unsigned char)(bitlen >> 16);
mac.c[2] = (unsigned char)(bitlen >> 8);
mac.c[3] = (unsigned char)bitlen;
bitlen = mac.u[0];
# endif /* BSWAP */
pmac->u[0] = 0;
pmac->u[1] = 0;
pmac->u[2] = 0;
pmac->u[3] = 0;
pmac->u[4] = 0;
pmac->u[5] = 0;
pmac->u[6] = 0;
pmac->u[7] = 0;
for (res = sctx->md.num, j = 0; j < len; j++) {
size_t c = out[j];
mask = (j - inp_len) >> (sizeof(j) * 8 - 8);
c &= mask;
c |= 0x80 & ~mask & ~((inp_len - j) >> (sizeof(j) * 8 - 8));
data->c[res++] = (unsigned char)c;
if (res != SHA256_CBLOCK)
continue;
/* j is not incremented yet */
mask = 0 - ((inp_len + 7 - j) >> (sizeof(j) * 8 - 1));
data->u[SHA_LBLOCK - 1] |= bitlen & mask;
sha256_block_data_order(&sctx->md, data, 1);
mask &= 0 - ((j - inp_len - 72) >> (sizeof(j) * 8 - 1));
pmac->u[0] |= sctx->md.h[0] & mask;
pmac->u[1] |= sctx->md.h[1] & mask;
pmac->u[2] |= sctx->md.h[2] & mask;
pmac->u[3] |= sctx->md.h[3] & mask;
pmac->u[4] |= sctx->md.h[4] & mask;
pmac->u[5] |= sctx->md.h[5] & mask;
pmac->u[6] |= sctx->md.h[6] & mask;
pmac->u[7] |= sctx->md.h[7] & mask;
res = 0;
}
for (i = res; i < SHA256_CBLOCK; i++, j++)
data->c[i] = 0;
if (res > SHA256_CBLOCK - 8) {
mask = 0 - ((inp_len + 8 - j) >> (sizeof(j) * 8 - 1));
data->u[SHA_LBLOCK - 1] |= bitlen & mask;
sha256_block_data_order(&sctx->md, data, 1);
mask &= 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1));
pmac->u[0] |= sctx->md.h[0] & mask;
pmac->u[1] |= sctx->md.h[1] & mask;
pmac->u[2] |= sctx->md.h[2] & mask;
pmac->u[3] |= sctx->md.h[3] & mask;
pmac->u[4] |= sctx->md.h[4] & mask;
pmac->u[5] |= sctx->md.h[5] & mask;
pmac->u[6] |= sctx->md.h[6] & mask;
pmac->u[7] |= sctx->md.h[7] & mask;
memset(data, 0, SHA256_CBLOCK);
j += 64;
}
data->u[SHA_LBLOCK - 1] = bitlen;
sha256_block_data_order(&sctx->md, data, 1);
mask = 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1));
pmac->u[0] |= sctx->md.h[0] & mask;
pmac->u[1] |= sctx->md.h[1] & mask;
pmac->u[2] |= sctx->md.h[2] & mask;
pmac->u[3] |= sctx->md.h[3] & mask;
pmac->u[4] |= sctx->md.h[4] & mask;
pmac->u[5] |= sctx->md.h[5] & mask;
pmac->u[6] |= sctx->md.h[6] & mask;
pmac->u[7] |= sctx->md.h[7] & mask;
# ifdef BSWAP4
pmac->u[0] = BSWAP4(pmac->u[0]);
pmac->u[1] = BSWAP4(pmac->u[1]);
pmac->u[2] = BSWAP4(pmac->u[2]);
pmac->u[3] = BSWAP4(pmac->u[3]);
pmac->u[4] = BSWAP4(pmac->u[4]);
pmac->u[5] = BSWAP4(pmac->u[5]);
pmac->u[6] = BSWAP4(pmac->u[6]);
pmac->u[7] = BSWAP4(pmac->u[7]);
# else
for (i = 0; i < 8; i++) {
res = pmac->u[i];
pmac->c[4 * i + 0] = (unsigned char)(res >> 24);
pmac->c[4 * i + 1] = (unsigned char)(res >> 16);
pmac->c[4 * i + 2] = (unsigned char)(res >> 8);
pmac->c[4 * i + 3] = (unsigned char)res;
}
# endif /* BSWAP */
len += SHA256_DIGEST_LENGTH;
sctx->md = sctx->tail;
sha256_update(&sctx->md, pmac->c, SHA256_DIGEST_LENGTH);
SHA256_Final(pmac->c, &sctx->md);
/* verify HMAC */
out += inp_len;
len -= inp_len;
/* code containing lucky-13 fix */
{
unsigned char *p =
out + len - 1 - maxpad - SHA256_DIGEST_LENGTH;
size_t off = out - p;
unsigned int c, cmask;
for (res = 0, i = 0, j = 0;
j < maxpad + SHA256_DIGEST_LENGTH;
j++) {
c = p[j];
cmask =
((int)(j - off - SHA256_DIGEST_LENGTH)) >>
(sizeof(int) * 8 - 1);
res |= (c ^ pad) & ~cmask; /* ... and padding */
cmask &= ((int)(off - 1 - j)) >> (sizeof(int) * 8 - 1);
res |= (c ^ pmac->c[i]) & cmask;
i += 1 & cmask;
}
res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1));
ret &= (int)~res;
}
return ret;
} else {
sha256_update(&sctx->md, out, len);
}
}
return 1;
}
/* EVP_CTRL_AEAD_SET_MAC_KEY */
static void aesni_cbc_hmac_sha256_set_mac_key(void *vctx,
const unsigned char *mackey,
size_t len)
{
PROV_AES_HMAC_SHA256_CTX *ctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
unsigned int i;
unsigned char hmac_key[64];
memset(hmac_key, 0, sizeof(hmac_key));
if (len > sizeof(hmac_key)) {
SHA256_Init(&ctx->head);
sha256_update(&ctx->head, mackey, len);
SHA256_Final(hmac_key, &ctx->head);
} else {
memcpy(hmac_key, mackey, len);
}
for (i = 0; i < sizeof(hmac_key); i++)
hmac_key[i] ^= 0x36; /* ipad */
SHA256_Init(&ctx->head);
sha256_update(&ctx->head, hmac_key, sizeof(hmac_key));
for (i = 0; i < sizeof(hmac_key); i++)
hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */
SHA256_Init(&ctx->tail);
sha256_update(&ctx->tail, hmac_key, sizeof(hmac_key));
OPENSSL_cleanse(hmac_key, sizeof(hmac_key));
}
/* EVP_CTRL_AEAD_TLS1_AAD */
static int aesni_cbc_hmac_sha256_set_tls1_aad(void *vctx,
unsigned char *aad_rec, int aad_len)
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
unsigned char *p = aad_rec;
unsigned int len;
if (aad_len != EVP_AEAD_TLS1_AAD_LEN)
return -1;
len = p[aad_len - 2] << 8 | p[aad_len - 1];
if (ctx->base.enc) {
ctx->payload_length = len;
if ((ctx->aux.tls_ver =
p[aad_len - 4] << 8 | p[aad_len - 3]) >= TLS1_1_VERSION) {
if (len < AES_BLOCK_SIZE)
return 0;
len -= AES_BLOCK_SIZE;
p[aad_len - 2] = len >> 8;
p[aad_len - 1] = len;
}
sctx->md = sctx->head;
sha256_update(&sctx->md, p, aad_len);
ctx->tls_aad_pad = (int)(((len + SHA256_DIGEST_LENGTH +
AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)
- len);
return 1;
} else {
memcpy(ctx->aux.tls_aad, p, aad_len);
ctx->payload_length = aad_len;
ctx->tls_aad_pad = SHA256_DIGEST_LENGTH;
return 1;
}
}
# if !defined(OPENSSL_NO_MULTIBLOCK)
/* EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE */
static int aesni_cbc_hmac_sha256_tls1_multiblock_max_bufsize(
void *vctx)
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
OPENSSL_assert(ctx->multiblock_max_send_fragment != 0);
return (int)(5 + 16
+ (((int)ctx->multiblock_max_send_fragment + 32 + 16) & -16));
}
/* EVP_CTRL_TLS1_1_MULTIBLOCK_AAD */
static int aesni_cbc_hmac_sha256_tls1_multiblock_aad(
void *vctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param)
{
PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx;
PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx;
unsigned int n4x = 1, x4;
unsigned int frag, last, packlen, inp_len;
inp_len = param->inp[11] << 8 | param->inp[12];
if (ctx->base.enc) {
if ((param->inp[9] << 8 | param->inp[10]) < TLS1_1_VERSION)
return -1;
if (inp_len) {
if (inp_len < 4096)
return 0; /* too short */
if (inp_len >= 8192 && OPENSSL_ia32cap_P[2] & (1 << 5))
n4x = 2; /* AVX2 */
} else if ((n4x = param->interleave / 4) && n4x <= 2)
inp_len = param->len;
else
return -1;
sctx->md = sctx->head;
sha256_update(&sctx->md, param->inp, 13);
x4 = 4 * n4x;
n4x += 1;
frag = inp_len >> n4x;
last = inp_len + frag - (frag << n4x);
if (last > frag && ((last + 13 + 9) % 64 < (x4 - 1))) {
frag++;
last -= x4 - 1;
}
packlen = 5 + 16 + ((frag + 32 + 16) & -16);
packlen = (packlen << n4x) - packlen;
packlen += 5 + 16 + ((last + 32 + 16) & -16);
param->interleave = x4;
/* The returned values used by get need to be stored */
ctx->multiblock_interleave = x4;
ctx->multiblock_aad_packlen = packlen;
return 1;
}
return -1; /* not yet */
}
/* EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT */
static int aesni_cbc_hmac_sha256_tls1_multiblock_encrypt(
void *ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param)
{
return (int)tls1_multi_block_encrypt(ctx, param->out,
param->inp, param->len,
param->interleave / 4);
}
# endif
static const PROV_CIPHER_HW_AES_HMAC_SHA cipher_hw_aes_hmac_sha256 = {
{
aesni_cbc_hmac_sha256_init_key,
aesni_cbc_hmac_sha256_cipher
},
aesni_cbc_hmac_sha256_set_mac_key,
aesni_cbc_hmac_sha256_set_tls1_aad,
# if !defined(OPENSSL_NO_MULTIBLOCK)
aesni_cbc_hmac_sha256_tls1_multiblock_max_bufsize,
aesni_cbc_hmac_sha256_tls1_multiblock_aad,
aesni_cbc_hmac_sha256_tls1_multiblock_encrypt
# endif
};
const PROV_CIPHER_HW_AES_HMAC_SHA *ossl_prov_cipher_hw_aes_cbc_hmac_sha256(void)
{
return &cipher_hw_aes_hmac_sha256;
}
#endif /* !defined(AES_CBC_HMAC_SHA_CAPABLE) || !defined(AESNI_CAPABLE) */

View File

@@ -0,0 +1,72 @@
/*
* Copyright 2019-2024 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 low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
/* Dispatch functions for AES CCM mode */
#include "cipher_aes_ccm.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
static void *aes_ccm_newctx(void *provctx, size_t keybits)
{
PROV_AES_CCM_CTX *ctx;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL)
ossl_ccm_initctx(&ctx->base, keybits, ossl_prov_aes_hw_ccm(keybits));
return ctx;
}
static void *aes_ccm_dupctx(void *provctx)
{
PROV_AES_CCM_CTX *ctx = provctx;
PROV_AES_CCM_CTX *dupctx = NULL;
if (!ossl_prov_is_running())
return NULL;
if (ctx == NULL)
return NULL;
dupctx = OPENSSL_memdup(provctx, sizeof(*ctx));
if (dupctx == NULL)
return NULL;
/*
* ossl_cm_initctx, via the ossl_prov_aes_hw_ccm functions assign a
* provctx->ccm.ks.ks to the ccm context key so we need to point it to
* the memduped copy
*/
dupctx->base.ccm_ctx.key = &dupctx->ccm.ks.ks;
return dupctx;
}
static OSSL_FUNC_cipher_freectx_fn aes_ccm_freectx;
static void aes_ccm_freectx(void *vctx)
{
PROV_AES_CCM_CTX *ctx = (PROV_AES_CCM_CTX *)vctx;
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
/* ossl_aes128ccm_functions */
IMPLEMENT_aead_cipher(aes, ccm, CCM, AEAD_FLAGS, 128, 8, 96);
/* ossl_aes192ccm_functions */
IMPLEMENT_aead_cipher(aes, ccm, CCM, AEAD_FLAGS, 192, 8, 96);
/* ossl_aes256ccm_functions */
IMPLEMENT_aead_cipher(aes, ccm, CCM, AEAD_FLAGS, 256, 8, 96);

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2019-2020 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 "prov/ciphercommon.h"
#include "prov/ciphercommon_ccm.h"
#include "crypto/aes_platform.h"
typedef struct prov_aes_ccm_ctx_st {
PROV_CCM_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
/*-
* Padding is chosen so that s390x.kmac.k overlaps with ks.ks and
* fc with ks.ks.rounds. Remember that on s390x, an AES_KEY's
* rounds field is used to store the function code and that the key
* schedule is not stored (if aes hardware support is detected).
*/
struct {
unsigned char pad[16];
AES_KEY ks;
} ks;
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
struct {
S390X_KMAC_PARAMS kmac;
unsigned long long blocks;
union {
unsigned long long g[2];
unsigned char b[AES_BLOCK_SIZE];
} nonce;
union {
unsigned long long g[2];
unsigned char b[AES_BLOCK_SIZE];
} buf;
unsigned char dummy_pad[168];
unsigned int fc; /* fc has same offset as ks.ks.rounds */
} s390x;
#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
} ccm;
} PROV_AES_CCM_CTX;
const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keylen);

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2019-2023 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 */
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#include "cipher_aes_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,
ossl_ccm_generic_setiv,
ossl_ccm_generic_setaad,
ossl_ccm_generic_auth_encrypt,
ossl_ccm_generic_auth_decrypt,
ossl_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"
#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
# include "cipher_aes_ccm_hw_rv64i.inc"
#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32
# include "cipher_aes_ccm_hw_rv32i.inc"
#else
const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keybits)
{
return &aes_ccm;
}
#endif

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2001-2021 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_aes_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,
ossl_ccm_generic_setiv,
ossl_ccm_generic_setaad,
ossl_ccm_generic_auth_encrypt,
ossl_ccm_generic_auth_decrypt,
ossl_ccm_generic_gettag
};
const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keybits)
{
return AESNI_CAPABLE ? &aesni_ccm : &aes_ccm;
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2022-2023 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
*/
/*-
* RISC-V 32 ZKND ZKNE support for AES CCM.
* This file is included by cipher_aes_ccm_hw.c
*/
static int ccm_rv32i_zknd_zkne_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(rv32i_zkne_set_encrypt_key, rv32i_zkne_encrypt,
NULL, NULL);
return 1;
}
static int ccm_rv32i_zbkb_zknd_zkne_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(rv32i_zbkb_zkne_set_encrypt_key, rv32i_zkne_encrypt,
NULL, NULL);
return 1;
}
static const PROV_CCM_HW rv32i_zknd_zkne_ccm = {
ccm_rv32i_zknd_zkne_initkey,
ossl_ccm_generic_setiv,
ossl_ccm_generic_setaad,
ossl_ccm_generic_auth_encrypt,
ossl_ccm_generic_auth_decrypt,
ossl_ccm_generic_gettag
};
static const PROV_CCM_HW rv32i_zbkb_zknd_zkne_ccm = {
ccm_rv32i_zbkb_zknd_zkne_initkey,
ossl_ccm_generic_setiv,
ossl_ccm_generic_setaad,
ossl_ccm_generic_auth_encrypt,
ossl_ccm_generic_auth_decrypt,
ossl_ccm_generic_gettag
};
const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keybits)
{
if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE())
return &rv32i_zbkb_zknd_zkne_ccm;
if (RISCV_HAS_ZKND_AND_ZKNE())
return &rv32i_zknd_zkne_ccm;
return &aes_ccm;
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2022-2023 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
*/
/*-
* RISC-V 64 ZKND ZKNE support for AES CCM.
* This file is included by cipher_aes_ccm_hw.c
*/
static int ccm_rv64i_zknd_zkne_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(rv64i_zkne_set_encrypt_key, rv64i_zkne_encrypt,
NULL, NULL);
return 1;
}
static const PROV_CCM_HW rv64i_zknd_zkne_ccm = {
ccm_rv64i_zknd_zkne_initkey,
ossl_ccm_generic_setiv,
ossl_ccm_generic_setaad,
ossl_ccm_generic_auth_encrypt,
ossl_ccm_generic_auth_decrypt,
ossl_ccm_generic_gettag
};
/*-
* RISC-V RV64 ZVKNED support for AES CCM.
* This file is included by cipher_aes_ccm_hw.c
*/
static int ccm_rv64i_zvkned_initkey(PROV_CCM_CTX *ctx, const unsigned char *key,
size_t keylen)
{
PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx;
/* Zvkned only supports 128 and 256 bit keys for key schedule generation. */
if (keylen * 8 == 128 || keylen * 8 == 256) {
AES_HW_CCM_SET_KEY_FN(rv64i_zvkned_set_encrypt_key, rv64i_zvkned_encrypt,
NULL, NULL);
} else {
AES_HW_CCM_SET_KEY_FN(AES_set_encrypt_key, rv64i_zvkned_encrypt, NULL, NULL)
}
return 1;
}
static const PROV_CCM_HW rv64i_zvkned_ccm = {
ccm_rv64i_zvkned_initkey,
ossl_ccm_generic_setiv,
ossl_ccm_generic_setaad,
ossl_ccm_generic_auth_encrypt,
ossl_ccm_generic_auth_decrypt,
ossl_ccm_generic_gettag
};
const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keybits)
{
if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128)
return &rv64i_zvkned_ccm;
else if (RISCV_HAS_ZKND_AND_ZKNE())
return &rv64i_zknd_zkne_ccm;
else
return &aes_ccm;
}

View File

@@ -0,0 +1,268 @@
/*
* Copyright 2001-2020 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_aes_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 *ossl_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;
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2001-2021 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_aes_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,
ossl_ccm_generic_setiv,
ossl_ccm_generic_setaad,
ossl_ccm_generic_auth_encrypt,
ossl_ccm_generic_auth_decrypt,
ossl_ccm_generic_gettag
};
const PROV_CCM_HW *ossl_prov_aes_hw_ccm(size_t keybits)
{
return SPARC_AES_CAPABLE ? &t4_aes_ccm : &aes_ccm;
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2020-2021 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 CBC CTS ciphers */
#include <openssl/proverr.h>
#include "cipher_cts.h"
#define CTS_FLAGS PROV_CIPHER_FLAG_CTS
static OSSL_FUNC_cipher_encrypt_init_fn aes_cbc_cts_einit;
static OSSL_FUNC_cipher_decrypt_init_fn aes_cbc_cts_dinit;
static OSSL_FUNC_cipher_get_ctx_params_fn aes_cbc_cts_get_ctx_params;
static OSSL_FUNC_cipher_set_ctx_params_fn aes_cbc_cts_set_ctx_params;
static OSSL_FUNC_cipher_gettable_ctx_params_fn aes_cbc_cts_gettable_ctx_params;
static OSSL_FUNC_cipher_settable_ctx_params_fn aes_cbc_cts_settable_ctx_params;
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(aes_cbc_cts)
OSSL_PARAM_utf8_string(OSSL_CIPHER_PARAM_CTS_MODE, NULL, 0),
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(aes_cbc_cts)
static int aes_cbc_cts_einit(void *ctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
if (!ossl_cipher_generic_einit(ctx, key, keylen, iv, ivlen, NULL))
return 0;
return aes_cbc_cts_set_ctx_params(ctx, params);
}
static int aes_cbc_cts_dinit(void *ctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
if (!ossl_cipher_generic_dinit(ctx, key, keylen, iv, ivlen, NULL))
return 0;
return aes_cbc_cts_set_ctx_params(ctx, params);
}
static int aes_cbc_cts_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_CTS_MODE);
if (p != NULL) {
const char *name = ossl_cipher_cbc_cts_mode_id2name(ctx->cts_mode);
if (name == NULL || !OSSL_PARAM_set_utf8_string(p, name)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
}
return ossl_cipher_generic_get_ctx_params(vctx, params);
}
CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(aes_cbc_cts)
OSSL_PARAM_utf8_string(OSSL_CIPHER_PARAM_CTS_MODE, NULL, 0),
CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(aes_cbc_cts)
static int aes_cbc_cts_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
const OSSL_PARAM *p;
int id;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_CTS_MODE);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_UTF8_STRING)
goto err;
id = ossl_cipher_cbc_cts_mode_name2id(p->data);
if (id < 0)
goto err;
ctx->cts_mode = (unsigned int)id;
}
return ossl_cipher_generic_set_ctx_params(vctx, params);
err:
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
/* ossl_aes256cbc_cts_functions */
IMPLEMENT_cts_cipher(aes, AES, cbc, CBC, CTS_FLAGS, 256, 128, 128, block)
/* ossl_aes192cbc_cts_functions */
IMPLEMENT_cts_cipher(aes, AES, cbc, CBC, CTS_FLAGS, 192, 128, 128, block)
/* ossl_aes128cbc_cts_functions */
IMPLEMENT_cts_cipher(aes, AES, cbc, CBC, CTS_FLAGS, 128, 128, 128, block)

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2019-2024 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 low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
/* Dispatch functions for AES GCM mode */
#include "cipher_aes_gcm.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
static void *aes_gcm_newctx(void *provctx, size_t keybits)
{
PROV_AES_GCM_CTX *ctx;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL)
ossl_gcm_initctx(provctx, &ctx->base, keybits,
ossl_prov_aes_hw_gcm(keybits));
return ctx;
}
static void *aes_gcm_dupctx(void *provctx)
{
PROV_AES_GCM_CTX *ctx = provctx;
PROV_AES_GCM_CTX *dctx = NULL;
if (!ossl_prov_is_running())
return NULL;
if (ctx == NULL)
return NULL;
dctx = OPENSSL_memdup(ctx, sizeof(*ctx));
if (dctx != NULL && dctx->base.gcm.key != NULL)
dctx->base.gcm.key = &dctx->ks.ks;
return dctx;
}
static OSSL_FUNC_cipher_freectx_fn aes_gcm_freectx;
static void aes_gcm_freectx(void *vctx)
{
PROV_AES_GCM_CTX *ctx = (PROV_AES_GCM_CTX *)vctx;
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
/* ossl_aes128gcm_functions */
IMPLEMENT_aead_cipher(aes, gcm, GCM, AEAD_FLAGS, 128, 8, 96);
/* ossl_aes192gcm_functions */
IMPLEMENT_aead_cipher(aes, gcm, GCM, AEAD_FLAGS, 192, 8, 96);
/* ossl_aes256gcm_functions */
IMPLEMENT_aead_cipher(aes, gcm, GCM, AEAD_FLAGS, 256, 8, 96);

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2019-2021 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 "prov/ciphercommon.h"
#include "prov/ciphercommon_gcm.h"
#include "crypto/aes_platform.h"
typedef struct prov_aes_gcm_ctx_st {
PROV_GCM_CTX base; /* must be first entry in struct */
union {
OSSL_UNION_ALIGN;
AES_KEY ks;
} ks; /* AES key schedule to use */
/* Platform specific data */
union {
int dummy;
#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
struct {
union {
OSSL_UNION_ALIGN;
S390X_KMA_PARAMS kma;
} param;
unsigned int fc;
unsigned int hsflag; /* hash subkey set flag */
unsigned char ares[16];
unsigned char mres[16];
unsigned char kres[16];
int areslen;
int mreslen;
int kreslen;
int res;
} s390x;
#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
} plat;
} PROV_AES_GCM_CTX;
const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits);

View File

@@ -0,0 +1,155 @@
/*
* Copyright 2019-2024 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 */
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#include "cipher_aes_gcm.h"
static int 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,
ossl_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 */
}
return 1;
}
static int generic_aes_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 >= AES_GCM_ENC_BYTES && AES_GCM_ASM(ctx)) {
size_t res = (16 - ctx->gcm.mres) % 16;
if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, res))
return 0;
bulk = AES_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 >= AES_GCM_DEC_BYTES && AES_GCM_ASM(ctx)) {
size_t res = (16 - ctx->gcm.mres) % 16;
if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, res))
return 0;
bulk = AES_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;
}
static const PROV_GCM_HW aes_gcm = {
aes_gcm_initkey,
ossl_gcm_setiv,
ossl_gcm_aad_update,
generic_aes_gcm_cipher_update,
ossl_gcm_cipher_final,
ossl_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"
#elif defined(AES_PMULL_CAPABLE) && defined(AES_GCM_ASM)
# include "cipher_aes_gcm_hw_armv8.inc"
#elif defined(PPC_AES_GCM_CAPABLE) && defined(_ARCH_PPC64)
# include "cipher_aes_gcm_hw_ppc.inc"
#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
# include "cipher_aes_gcm_hw_rv64i.inc"
#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32
# include "cipher_aes_gcm_hw_rv32i.inc"
#else
const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits)
{
return &aes_gcm;
}
#endif

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2001-2022 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_aes_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,
ossl_gcm_setiv,
ossl_gcm_aad_update,
generic_aes_gcm_cipher_update,
ossl_gcm_cipher_final,
ossl_gcm_one_shot
};
#include "cipher_aes_gcm_hw_vaes_avx512.inc"
const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits)
{
#ifdef VAES_GCM_ENABLED
if (ossl_vaes_vpclmulqdq_capable())
return &vaes_gcm;
else
#endif
if (AESNI_CAPABLE)
return &aesni_gcm;
else
return &aes_gcm;
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright 2019-2025 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
*/
/*
* Crypto extension support for AES GCM.
* This file is included by cipher_aes_gcm_hw.c
*/
size_t armv8_aes_gcm_encrypt(const unsigned char *in, unsigned char *out, size_t len,
const void *key, unsigned char ivec[16], u64 *Xi)
{
AES_KEY *aes_key = (AES_KEY *)key;
size_t align_bytes = len - len % 16;
switch(aes_key->rounds) {
case 10:
if (IS_CPU_SUPPORT_UNROLL8_EOR3()) {
unroll8_eor3_aes_gcm_enc_128_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
} else {
aes_gcm_enc_128_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
}
break;
case 12:
if (IS_CPU_SUPPORT_UNROLL8_EOR3()) {
unroll8_eor3_aes_gcm_enc_192_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
} else {
aes_gcm_enc_192_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
}
break;
case 14:
if (IS_CPU_SUPPORT_UNROLL8_EOR3()) {
unroll8_eor3_aes_gcm_enc_256_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
} else {
aes_gcm_enc_256_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
}
break;
}
return align_bytes;
}
size_t armv8_aes_gcm_decrypt(const unsigned char *in, unsigned char *out, size_t len,
const void *key, unsigned char ivec[16], u64 *Xi)
{
AES_KEY *aes_key = (AES_KEY *)key;
size_t align_bytes = len - len % 16;
switch(aes_key->rounds) {
case 10:
if (IS_CPU_SUPPORT_UNROLL8_EOR3()) {
unroll8_eor3_aes_gcm_dec_128_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
} else {
aes_gcm_dec_128_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
}
break;
case 12:
if (IS_CPU_SUPPORT_UNROLL8_EOR3()) {
unroll8_eor3_aes_gcm_dec_192_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
} else {
aes_gcm_dec_192_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
}
break;
case 14:
if (IS_CPU_SUPPORT_UNROLL8_EOR3()) {
unroll8_eor3_aes_gcm_dec_256_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
} else {
aes_gcm_dec_256_kernel(in, align_bytes * 8, out, (uint64_t *)Xi, ivec, key);
}
break;
}
return align_bytes;
}
static int armv8_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;
if (AES_UNROLL12_EOR3_CAPABLE) {
GCM_HW_SET_KEY_CTR_FN(ks, aes_v8_set_encrypt_key, aes_v8_encrypt,
aes_v8_ctr32_encrypt_blocks_unroll12_eor3);
} else {
GCM_HW_SET_KEY_CTR_FN(ks, aes_v8_set_encrypt_key, aes_v8_encrypt,
aes_v8_ctr32_encrypt_blocks);
}
return 1;
}
static const PROV_GCM_HW armv8_aes_gcm = {
armv8_aes_gcm_initkey,
ossl_gcm_setiv,
ossl_gcm_aad_update,
generic_aes_gcm_cipher_update,
ossl_gcm_cipher_final,
ossl_gcm_one_shot
};
const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits)
{
return AES_PMULL_CAPABLE ? &armv8_aes_gcm : &aes_gcm;
}

View File

@@ -0,0 +1,155 @@
/*
* Copyright 2001-2022 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
*/
/*-
* PPC support for AES GCM.
* This file is included by cipher_aes_gcm_hw.c
*/
static int aes_ppc_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, aes_p8_set_encrypt_key, aes_p8_encrypt,
aes_p8_ctr32_encrypt_blocks);
return 1;
}
static inline u32 UTO32(unsigned char *buf)
{
return ((u32) buf[0] << 24) | ((u32) buf[1] << 16) | ((u32) buf[2] << 8) | ((u32) buf[3]);
}
static inline u32 add32TOU(unsigned char buf[4], u32 n)
{
u32 r;
r = UTO32(buf);
r += n;
buf[0] = (unsigned char) (r >> 24) & 0xFF;
buf[1] = (unsigned char) (r >> 16) & 0xFF;
buf[2] = (unsigned char) (r >> 8) & 0xFF;
buf[3] = (unsigned char) r & 0xFF;
return r;
}
static size_t ppc_aes_gcm_crypt(const unsigned char *in, unsigned char *out, size_t len,
const void *key, unsigned char ivec[16], u64 *Xi, int encrypt)
{
int s = 0;
int ndone = 0;
int ctr_reset = 0;
u64 blocks_unused;
u64 nb = len / 16;
u64 next_ctr = 0;
unsigned char ctr_saved[12];
memcpy(ctr_saved, ivec, 12);
while (nb) {
blocks_unused = (u64) 0xffffffffU + 1 - (u64) UTO32 (ivec + 12);
if (nb > blocks_unused) {
len = blocks_unused * 16;
nb -= blocks_unused;
next_ctr = blocks_unused;
ctr_reset = 1;
} else {
len = nb * 16;
next_ctr = nb;
nb = 0;
}
s = encrypt ? ppc_aes_gcm_encrypt(in, out, len, key, ivec, Xi)
: ppc_aes_gcm_decrypt(in, out, len, key, ivec, Xi);
/* add counter to ivec */
add32TOU(ivec + 12, (u32) next_ctr);
if (ctr_reset) {
ctr_reset = 0;
in += len;
out += len;
}
memcpy(ivec, ctr_saved, 12);
ndone += s;
}
return ndone;
}
static int ppc_aes_gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
size_t len, unsigned char *out)
{
if (ctx->enc) {
if (ctx->ctr != NULL) {
size_t bulk = 0;
if (len >= AES_GCM_ENC_BYTES && AES_GCM_ASM_PPC(ctx)) {
size_t res = (16 - ctx->gcm.mres) % 16;
if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, res))
return 0;
bulk = ppc_aes_gcm_crypt(in + res, out + res, len - res,
ctx->gcm.key,
ctx->gcm.Yi.c, ctx->gcm.Xi.u, 1);
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(&ctx->gcm, in, out, len))
return 0;
}
} else {
if (ctx->ctr != NULL) {
size_t bulk = 0;
if (len >= AES_GCM_DEC_BYTES && AES_GCM_ASM_PPC(ctx)) {
size_t res = (16 - ctx->gcm.mres) % 16;
if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, res))
return -1;
bulk = ppc_aes_gcm_crypt(in + res, out + res, len - res,
ctx->gcm.key,
ctx->gcm.Yi.c, ctx->gcm.Xi.u, 0);
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(&ctx->gcm, in, out, len))
return 0;
}
}
return 1;
}
static const PROV_GCM_HW aes_ppc_gcm = {
aes_ppc_gcm_initkey,
ossl_gcm_setiv,
ossl_gcm_aad_update,
ppc_aes_gcm_cipher_update,
ossl_gcm_cipher_final,
ossl_gcm_one_shot
};
const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits)
{
return PPC_AES_GCM_CAPABLE ? &aes_ppc_gcm : &aes_gcm;
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2022-2023 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
*/
/*-
* RISC-V 32 ZKND ZKNE support for AES GCM.
* This file is included by cipher_aes_gcm_hw.c
*/
static int rv32i_zknd_zkne_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, rv32i_zkne_set_encrypt_key, rv32i_zkne_encrypt,
NULL);
return 1;
}
static int rv32i_zbkb_zknd_zkne_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, rv32i_zbkb_zkne_set_encrypt_key, rv32i_zkne_encrypt,
NULL);
return 1;
}
static const PROV_GCM_HW rv32i_zknd_zkne_gcm = {
rv32i_zknd_zkne_gcm_initkey,
ossl_gcm_setiv,
ossl_gcm_aad_update,
generic_aes_gcm_cipher_update,
ossl_gcm_cipher_final,
ossl_gcm_one_shot
};
static const PROV_GCM_HW rv32i_zbkb_zknd_zkne_gcm = {
rv32i_zbkb_zknd_zkne_gcm_initkey,
ossl_gcm_setiv,
ossl_gcm_aad_update,
generic_aes_gcm_cipher_update,
ossl_gcm_cipher_final,
ossl_gcm_one_shot
};
const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits)
{
if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE())
return &rv32i_zbkb_zknd_zkne_gcm;
if (RISCV_HAS_ZKND_AND_ZKNE())
return &rv32i_zknd_zkne_gcm;
return &aes_gcm;
}

View File

@@ -0,0 +1,118 @@
/*
* Copyright 2022-2023 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
*/
/*-
* RISC-V 64 support for AES GCM.
* This file is included by cipher_aes_gcm_hw.c
*/
/*-
* RISC-V 64 ZKND and ZKNE support for AES GCM.
*/
static int rv64i_zknd_zkne_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, rv64i_zkne_set_encrypt_key, rv64i_zkne_encrypt,
NULL);
return 1;
}
static const PROV_GCM_HW rv64i_zknd_zkne_gcm = {
rv64i_zknd_zkne_gcm_initkey,
ossl_gcm_setiv,
ossl_gcm_aad_update,
generic_aes_gcm_cipher_update,
ossl_gcm_cipher_final,
ossl_gcm_one_shot
};
/*-
* RISC-V RV64 ZVKNED support for AES GCM.
*/
static int rv64i_zvkned_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;
/*
* Zvkned only supports 128 and 256 bit keys for key schedule generation.
* For AES-192 case, we could fallback to `AES_set_encrypt_key`.
*/
if (keylen * 8 == 128 || keylen * 8 == 256) {
GCM_HW_SET_KEY_CTR_FN(ks, rv64i_zvkned_set_encrypt_key,
rv64i_zvkned_encrypt, NULL);
} else {
GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key,
rv64i_zvkned_encrypt, NULL);
}
return 1;
}
static const PROV_GCM_HW rv64i_zvkned_gcm = {
rv64i_zvkned_gcm_initkey,
ossl_gcm_setiv,
ossl_gcm_aad_update,
generic_aes_gcm_cipher_update,
ossl_gcm_cipher_final,
ossl_gcm_one_shot
};
/*-
* RISC-V RV64 ZVKB, ZVKG and ZVKNED support for AES GCM.
*/
static int rv64i_zvkb_zvkg_zvkned_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;
/*
* Zvkned only supports 128 and 256 bit keys for key schedule generation.
* For AES-192 case, we could fallback to `AES_set_encrypt_key`.
*/
if (keylen * 8 == 128 || keylen * 8 == 256) {
GCM_HW_SET_KEY_CTR_FN(ks, rv64i_zvkned_set_encrypt_key,
rv64i_zvkned_encrypt,
rv64i_zvkb_zvkned_ctr32_encrypt_blocks);
} else {
GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key,
rv64i_zvkned_encrypt,
rv64i_zvkb_zvkned_ctr32_encrypt_blocks);
}
return 1;
}
static const PROV_GCM_HW rv64i_zvkb_zvkg_zvkned_gcm = {
rv64i_zvkb_zvkg_zvkned_gcm_initkey,
ossl_gcm_setiv,
ossl_gcm_aad_update,
generic_aes_gcm_cipher_update,
ossl_gcm_cipher_final,
ossl_gcm_one_shot
};
const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits) {
if (RISCV_HAS_ZVKNED()) {
if (RISCV_HAS_ZVKB() && RISCV_HAS_ZVKG() && riscv_vlen() >= 128) {
return &rv64i_zvkb_zvkg_zvkned_gcm;
}
return &rv64i_zvkned_gcm;
}
if (RISCV_HAS_ZKND_AND_ZKNE()) {
return &rv64i_zknd_zkne_gcm;
}
return &aes_gcm;
}

View File

@@ -0,0 +1,312 @@
/*
* Copyright 2001-2021 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_aes_gcm_hw.c
*/
/* iv + padding length for iv lengths != 12 */
#define S390X_gcm_ivpadlen(i) ((((i) + 15) >> 4 << 4) + 16)
/* Additional flag or'ed to fc for decryption */
#define S390X_gcm_decrypt_flag(ctx) (((ctx)->enc) ? 0 : S390X_DECRYPT)
#define S390X_gcm_fc(A,C) ((A)->plat.s390x.fc | (A)->plat.s390x.hsflag |\
S390X_gcm_decrypt_flag((C)))
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);
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;
actx->plat.s390x.hsflag = 0;
} 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.hsflag = 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];
unsigned int fc;
int rc;
kma->taadl <<= 3;
kma->tpcl <<= 3;
fc = S390X_gcm_fc(actx, ctx) | S390X_KMA_LAAD | S390X_KMA_LPC;
s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen,
actx->plat.s390x.mres, actx->plat.s390x.mreslen, out,
fc, 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;
unsigned int fc;
int rc;
kma->taadl = aad_len << 3;
kma->tpcl = in_len << 3;
fc = S390X_gcm_fc(actx, ctx) | S390X_KMA_LAAD | S390X_KMA_LPC;
s390x_kma(aad, aad_len, in, in_len, out, fc, 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;
unsigned int fc;
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) {
fc = S390X_gcm_fc(actx, ctx);
s390x_kma(actx->plat.s390x.ares, 16, NULL, 0, NULL, fc, kma);
actx->plat.s390x.hsflag = 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) {
fc = S390X_gcm_fc(actx, ctx);
s390x_kma(aad, len, NULL, 0, NULL, fc, kma);
actx->plat.s390x.hsflag = 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;
unsigned int fc;
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;
fc = S390X_gcm_fc(actx, ctx) | S390X_KMA_LAAD;
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, fc, kma);
actx->plat.s390x.hsflag = S390X_KMA_HS;
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,
fc, kma);
in += len;
out += len;
actx->plat.s390x.hsflag = 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,
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 *ossl_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;
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2001-2021 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_aes_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,
ossl_gcm_setiv,
ossl_gcm_aad_update,
generic_aes_gcm_cipher_update,
ossl_gcm_cipher_final,
ossl_gcm_one_shot
};
const PROV_GCM_HW *ossl_prov_aes_hw_gcm(size_t keybits)
{
return SPARC_AES_CAPABLE ? &t4_aes_gcm : &aes_gcm;
}

View File

@@ -0,0 +1,204 @@
/*
* Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2021, Intel Corporation. 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
*/
/*-
* AVX512 VAES + VPCLMULDQD support for AES GCM.
* This file is included by cipher_aes_gcm_hw_aesni.inc
*/
#undef VAES_GCM_ENABLED
#if (defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64))
# define VAES_GCM_ENABLED
/* Returns non-zero when AVX512F + VAES + VPCLMULDQD combination is available */
int ossl_vaes_vpclmulqdq_capable(void);
# define OSSL_AES_GCM_UPDATE(direction) \
void ossl_aes_gcm_ ## direction ## _avx512(const void *ks, \
void *gcm128ctx, \
unsigned int *pblocklen, \
const unsigned char *in, \
size_t len, \
unsigned char *out);
OSSL_AES_GCM_UPDATE(encrypt)
OSSL_AES_GCM_UPDATE(decrypt)
void ossl_aes_gcm_init_avx512(const void *ks, void *gcm128ctx);
void ossl_aes_gcm_setiv_avx512(const void *ks, void *gcm128ctx,
const unsigned char *iv, size_t ivlen);
void ossl_aes_gcm_update_aad_avx512(void *gcm128ctx, const unsigned char *aad,
size_t aadlen);
void ossl_aes_gcm_finalize_avx512(void *gcm128ctx, unsigned int pblocklen);
void ossl_gcm_gmult_avx512(u64 Xi[2], const void *gcm128ctx);
static int vaes_gcm_setkey(PROV_GCM_CTX *ctx, const unsigned char *key,
size_t keylen)
{
GCM128_CONTEXT *gcmctx = &ctx->gcm;
PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx;
AES_KEY *ks = &actx->ks.ks;
aesni_set_encrypt_key(key, keylen * 8, ks);
memset(gcmctx, 0, sizeof(*gcmctx));
gcmctx->key = ks;
ctx->key_set = 1;
ossl_aes_gcm_init_avx512(ks, gcmctx);
return 1;
}
static int vaes_gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv,
size_t ivlen)
{
GCM128_CONTEXT *gcmctx = &ctx->gcm;
gcmctx->Yi.u[0] = 0; /* Current counter */
gcmctx->Yi.u[1] = 0;
gcmctx->Xi.u[0] = 0; /* AAD hash */
gcmctx->Xi.u[1] = 0;
gcmctx->len.u[0] = 0; /* AAD length */
gcmctx->len.u[1] = 0; /* Message length */
gcmctx->ares = 0;
gcmctx->mres = 0;
/* IV is limited by 2^64 bits, thus 2^61 bytes */
if (ivlen > (U64(1) << 61))
return 0;
ossl_aes_gcm_setiv_avx512(gcmctx->key, gcmctx, iv, ivlen);
return 1;
}
static int vaes_gcm_aadupdate(PROV_GCM_CTX *ctx,
const unsigned char *aad,
size_t aad_len)
{
GCM128_CONTEXT *gcmctx = &ctx->gcm;
u64 alen = gcmctx->len.u[0];
unsigned int ares;
size_t i, lenBlks;
/* Bad sequence: call of AAD update after message processing */
if (gcmctx->len.u[1] > 0)
return 0;
alen += aad_len;
/* AAD is limited by 2^64 bits, thus 2^61 bytes */
if ((alen > (U64(1) << 61)) || (alen < aad_len))
return 0;
gcmctx->len.u[0] = alen;
ares = gcmctx->ares;
/* Partial AAD block left from previous AAD update calls */
if (ares > 0) {
/*
* Fill partial block buffer till full block
* (note, the hash is stored reflected)
*/
while (ares > 0 && aad_len > 0) {
gcmctx->Xi.c[15 - ares] ^= *(aad++);
--aad_len;
ares = (ares + 1) % AES_BLOCK_SIZE;
}
/* Full block gathered */
if (ares == 0) {
ossl_gcm_gmult_avx512(gcmctx->Xi.u, gcmctx);
} else { /* no more AAD */
gcmctx->ares = ares;
return 1;
}
}
/* Bulk AAD processing */
lenBlks = aad_len & ((size_t)(-AES_BLOCK_SIZE));
if (lenBlks > 0) {
ossl_aes_gcm_update_aad_avx512(gcmctx, aad, lenBlks);
aad += lenBlks;
aad_len -= lenBlks;
}
/* Add remaining AAD to the hash (note, the hash is stored reflected) */
if (aad_len > 0) {
ares = aad_len;
for (i = 0; i < aad_len; i++)
gcmctx->Xi.c[15 - i] ^= aad[i];
}
gcmctx->ares = ares;
return 1;
}
static int vaes_gcm_cipherupdate(PROV_GCM_CTX *ctx, const unsigned char *in,
size_t len, unsigned char *out)
{
GCM128_CONTEXT *gcmctx = &ctx->gcm;
u64 mlen = gcmctx->len.u[1];
mlen += len;
if (mlen > ((U64(1) << 36) - 32) || (mlen < len))
return 0;
gcmctx->len.u[1] = mlen;
/* Finalize GHASH(AAD) if AAD partial blocks left unprocessed */
if (gcmctx->ares > 0) {
ossl_gcm_gmult_avx512(gcmctx->Xi.u, gcmctx);
gcmctx->ares = 0;
}
if (ctx->enc)
ossl_aes_gcm_encrypt_avx512(gcmctx->key, gcmctx, &gcmctx->mres, in, len, out);
else
ossl_aes_gcm_decrypt_avx512(gcmctx->key, gcmctx, &gcmctx->mres, in, len, out);
return 1;
}
static int vaes_gcm_cipherfinal(PROV_GCM_CTX *ctx, unsigned char *tag)
{
GCM128_CONTEXT *gcmctx = &ctx->gcm;
unsigned int *res = &gcmctx->mres;
/* Finalize AAD processing */
if (gcmctx->ares > 0)
res = &gcmctx->ares;
ossl_aes_gcm_finalize_avx512(gcmctx, *res);
if (ctx->enc) {
ctx->taglen = GCM_TAG_MAX_SIZE;
memcpy(tag, gcmctx->Xi.c,
ctx->taglen <= sizeof(gcmctx->Xi.c) ? ctx->taglen :
sizeof(gcmctx->Xi.c));
*res = 0;
} else {
return !CRYPTO_memcmp(gcmctx->Xi.c, tag, ctx->taglen);
}
return 1;
}
static const PROV_GCM_HW vaes_gcm = {
vaes_gcm_setkey,
vaes_gcm_setiv,
vaes_gcm_aadupdate,
vaes_gcm_cipherupdate,
vaes_gcm_cipherfinal,
ossl_gcm_one_shot
};
#endif

View File

@@ -0,0 +1,323 @@
/*
* Copyright 2019-2023 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 SIV mode */
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#include <openssl/proverr.h>
#include "prov/implementations.h"
#include "prov/providercommon.h"
#include "prov/ciphercommon_aead.h"
#include "prov/provider_ctx.h"
#include "cipher_aes_gcm_siv.h"
static int ossl_aes_gcm_siv_set_ctx_params(void *vctx, const OSSL_PARAM params[]);
static void *ossl_aes_gcm_siv_newctx(void *provctx, size_t keybits)
{
PROV_AES_GCM_SIV_CTX *ctx;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL) {
ctx->key_len = keybits / 8;
ctx->hw = ossl_prov_cipher_hw_aes_gcm_siv(keybits);
ctx->libctx = PROV_LIBCTX_OF(provctx);
ctx->provctx = provctx;
}
return ctx;
}
static void ossl_aes_gcm_siv_freectx(void *vctx)
{
PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
if (ctx == NULL)
return;
OPENSSL_clear_free(ctx->aad, ctx->aad_len);
ctx->hw->clean_ctx(ctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static void *ossl_aes_gcm_siv_dupctx(void *vctx)
{
PROV_AES_GCM_SIV_CTX *in = (PROV_AES_GCM_SIV_CTX *)vctx;
PROV_AES_GCM_SIV_CTX *ret;
if (!ossl_prov_is_running())
return NULL;
if (in->hw == NULL)
return NULL;
ret = OPENSSL_memdup(in, sizeof(*in));
if (ret == NULL)
return NULL;
/* NULL-out these things we create later */
ret->aad = NULL;
ret->ecb_ctx = NULL;
if (in->aad != NULL) {
if ((ret->aad = OPENSSL_memdup(in->aad, UP16(ret->aad_len))) == NULL)
goto err;
}
if (!in->hw->dup_ctx(ret, in))
goto err;
return ret;
err:
if (ret != NULL) {
OPENSSL_clear_free(ret->aad, ret->aad_len);
OPENSSL_free(ret);
}
return NULL;
}
static int ossl_aes_gcm_siv_init(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[], int enc)
{
PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
if (!ossl_prov_is_running())
return 0;
ctx->enc = enc;
if (key != NULL) {
if (keylen != ctx->key_len) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
memcpy(ctx->key_gen_key, key, ctx->key_len);
}
if (iv != NULL) {
if (ivlen != sizeof(ctx->nonce)) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
memcpy(ctx->nonce, iv, sizeof(ctx->nonce));
}
if (!ctx->hw->initkey(ctx))
return 0;
return ossl_aes_gcm_siv_set_ctx_params(ctx, params);
}
static int ossl_aes_gcm_siv_einit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
return ossl_aes_gcm_siv_init(vctx, key, keylen, iv, ivlen, params, 1);
}
static int ossl_aes_gcm_siv_dinit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
return ossl_aes_gcm_siv_init(vctx, key, keylen, iv, ivlen, params, 0);
}
#define ossl_aes_gcm_siv_stream_update ossl_aes_gcm_siv_cipher
static int ossl_aes_gcm_siv_cipher(void *vctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in, size_t inl)
{
PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
int error = 0;
if (!ossl_prov_is_running())
return 0;
/* The RFC has a test case for this, but we don't try to do anything */
if (inl == 0) {
if (outl != NULL)
*outl = 0;
return 1;
}
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
error |= !ctx->hw->cipher(ctx, out, in, inl);
if (outl != NULL && !error)
*outl = inl;
return !error;
}
static int ossl_aes_gcm_siv_stream_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
int error = 0;
if (!ossl_prov_is_running())
return 0;
error |= !ctx->hw->cipher(vctx, out, NULL, 0);
if (outl != NULL && !error)
*outl = 0;
return !error;
}
static int ossl_aes_gcm_siv_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
OSSL_PARAM *p;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
if (p != NULL && p->data_type == OSSL_PARAM_OCTET_STRING) {
if (!ctx->enc || !ctx->generated_tag
|| p->data_size != sizeof(ctx->tag)
|| !OSSL_PARAM_set_octet_string(p, ctx->tag, sizeof(ctx->tag))) {
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 && !OSSL_PARAM_set_size_t(p, sizeof(ctx->tag))) {
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->key_len)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
return 1;
}
static const OSSL_PARAM aes_gcm_siv_known_gettable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *ossl_aes_gcm_siv_gettable_ctx_params(ossl_unused void *cctx,
ossl_unused void *provctx)
{
return aes_gcm_siv_known_gettable_ctx_params;
}
static int ossl_aes_gcm_siv_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
const OSSL_PARAM *p;
unsigned int speed = 0;
if (params == NULL)
return 1;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_OCTET_STRING
|| p->data_size != sizeof(ctx->user_tag)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (!ctx->enc) {
memcpy(ctx->user_tag, p->data, sizeof(ctx->tag));
ctx->have_user_tag = 1;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_SPEED);
if (p != NULL) {
if (!OSSL_PARAM_get_uint(p, &speed)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
ctx->speed = !!speed;
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL) {
size_t key_len;
if (!OSSL_PARAM_get_size_t(p, &key_len)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
/* The key length can not be modified */
if (key_len != ctx->key_len) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
}
return 1;
}
static const OSSL_PARAM aes_gcm_siv_known_settable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_SPEED, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *ossl_aes_gcm_siv_settable_ctx_params(ossl_unused void *cctx,
ossl_unused void *provctx)
{
return aes_gcm_siv_known_settable_ctx_params;
}
#define IMPLEMENT_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits) \
static OSSL_FUNC_cipher_newctx_fn ossl_##alg##kbits##_##lc##_newctx; \
static OSSL_FUNC_cipher_freectx_fn ossl_##alg##_##lc##_freectx; \
static OSSL_FUNC_cipher_dupctx_fn ossl_##alg##_##lc##_dupctx; \
static OSSL_FUNC_cipher_encrypt_init_fn ossl_##alg##_##lc##_einit; \
static OSSL_FUNC_cipher_decrypt_init_fn ossl_##alg##_##lc##_dinit; \
static OSSL_FUNC_cipher_update_fn ossl_##alg##_##lc##_stream_update; \
static OSSL_FUNC_cipher_final_fn ossl_##alg##_##lc##_stream_final; \
static OSSL_FUNC_cipher_cipher_fn ossl_##alg##_##lc##_cipher; \
static OSSL_FUNC_cipher_get_params_fn ossl_##alg##_##kbits##_##lc##_get_params; \
static OSSL_FUNC_cipher_get_ctx_params_fn ossl_##alg##_##lc##_get_ctx_params; \
static OSSL_FUNC_cipher_gettable_ctx_params_fn ossl_##alg##_##lc##_gettable_ctx_params; \
static OSSL_FUNC_cipher_set_ctx_params_fn ossl_##alg##_##lc##_set_ctx_params; \
static OSSL_FUNC_cipher_settable_ctx_params_fn ossl_##alg##_##lc##_settable_ctx_params; \
static int ossl_##alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[]) \
{ \
return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
flags, kbits, blkbits, ivbits); \
} \
static void *ossl_##alg##kbits##_##lc##_newctx(void *provctx) \
{ \
return ossl_##alg##_##lc##_newctx(provctx, kbits); \
} \
const OSSL_DISPATCH ossl_##alg##kbits##lc##_functions[] = { \
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))ossl_##alg##kbits##_##lc##_newctx }, \
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))ossl_##alg##_##lc##_freectx }, \
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))ossl_##alg##_##lc##_dupctx }, \
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_##alg##_##lc##_einit }, \
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_##alg##_##lc##_dinit }, \
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_##alg##_##lc##_stream_update }, \
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_##alg##_##lc##_stream_final }, \
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_##alg##_##lc##_cipher }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))ossl_##alg##_##kbits##_##lc##_get_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, (void (*)(void))ossl_cipher_generic_gettable_params }, \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_get_ctx_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_gettable_ctx_params }, \
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_set_ctx_params }, \
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_settable_ctx_params }, \
OSSL_DISPATCH_END \
}
IMPLEMENT_cipher(aes, gcm_siv, GCM_SIV, AEAD_FLAGS, 128, 8, 96);
IMPLEMENT_cipher(aes, gcm_siv, GCM_SIV, AEAD_FLAGS, 192, 8, 96);
IMPLEMENT_cipher(aes, gcm_siv, GCM_SIV, AEAD_FLAGS, 256, 8, 96);

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2019-2021 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 "prov/ciphercommon.h"
#include "crypto/aes_platform.h"
#define BLOCK_SIZE 16
#define NONCE_SIZE 12
#define TAG_SIZE 16
/* AAD manipulation macros */
#define UP16(x) (((x) + 15) & ~0x0F)
#define DOWN16(x) ((x) & ~0x0F)
#define REMAINDER16(x) ((x) & 0x0F)
#define IS16(x) (((x) & 0x0F) == 0)
typedef struct prov_cipher_hw_aes_gcm_siv_st {
int (*initkey)(void *vctx);
int (*cipher)(void *vctx, unsigned char *out, const unsigned char *in,
size_t len);
int (*dup_ctx)(void *vdst, void *vsrc);
void (*clean_ctx)(void *vctx);
} PROV_CIPHER_HW_AES_GCM_SIV;
/* Arranged for alignment purposes */
typedef struct prov_aes_gcm_siv_ctx_st {
EVP_CIPHER_CTX *ecb_ctx;
const PROV_CIPHER_HW_AES_GCM_SIV *hw; /* maybe not used, yet? */
uint8_t *aad; /* Allocated, rounded up to 16 bytes, from user */
OSSL_LIB_CTX *libctx;
OSSL_PROVIDER *provctx;
size_t aad_len; /* actual AAD length */
size_t key_len;
uint8_t key_gen_key[32]; /* from user */
uint8_t msg_enc_key[32]; /* depends on key size */
uint8_t msg_auth_key[BLOCK_SIZE];
uint8_t tag[TAG_SIZE]; /* generated tag, given to user or compared to user */
uint8_t user_tag[TAG_SIZE]; /* from user */
uint8_t nonce[NONCE_SIZE]; /* from user */
u128 Htable[16]; /* Polyval calculations via ghash */
unsigned int enc : 1; /* Set to 1 if we are encrypting or 0 otherwise */
unsigned int have_user_tag : 1;
unsigned int generated_tag : 1;
unsigned int used_enc : 1;
unsigned int used_dec : 1;
unsigned int speed : 1;
} PROV_AES_GCM_SIV_CTX;
const PROV_CIPHER_HW_AES_GCM_SIV *ossl_prov_cipher_hw_aes_gcm_siv(size_t keybits);
void ossl_polyval_ghash_init(u128 Htable[16], const uint64_t H[2]);
void ossl_polyval_ghash_hash(const u128 Htable[16], uint8_t *tag, const uint8_t *inp, size_t len);
/* Define GSWAP8/GSWAP4 - used for BOTH little and big endian architectures */
static ossl_inline uint32_t GSWAP4(uint32_t n)
{
return (((n & 0x000000FF) << 24)
| ((n & 0x0000FF00) << 8)
| ((n & 0x00FF0000) >> 8)
| ((n & 0xFF000000) >> 24));
}
static ossl_inline uint64_t GSWAP8(uint64_t n)
{
uint64_t result;
result = GSWAP4(n & 0x0FFFFFFFF);
result <<= 32;
return result | GSWAP4(n >> 32);
}

View File

@@ -0,0 +1,372 @@
/*
* Copyright 2019-2024 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 low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
#include <openssl/evp.h>
#include <internal/endian.h>
#include <prov/implementations.h>
#include "cipher_aes_gcm_siv.h"
static int aes_gcm_siv_ctr32(PROV_AES_GCM_SIV_CTX *ctx, const unsigned char *init_counter,
unsigned char *out, const unsigned char *in, size_t len);
static int aes_gcm_siv_initkey(void *vctx)
{
PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
uint8_t output[BLOCK_SIZE];
uint32_t counter = 0x0;
size_t i;
union {
uint32_t counter;
uint8_t block[BLOCK_SIZE];
} data;
int out_len;
EVP_CIPHER *ecb = NULL;
DECLARE_IS_ENDIAN;
switch (ctx->key_len) {
case 16:
ecb = EVP_CIPHER_fetch(ctx->libctx, "AES-128-ECB", NULL);
break;
case 24:
ecb = EVP_CIPHER_fetch(ctx->libctx, "AES-192-ECB", NULL);
break;
case 32:
ecb = EVP_CIPHER_fetch(ctx->libctx, "AES-256-ECB", NULL);
break;
default:
goto err;
}
if (ctx->ecb_ctx == NULL && (ctx->ecb_ctx = EVP_CIPHER_CTX_new()) == NULL)
goto err;
if (!EVP_EncryptInit_ex2(ctx->ecb_ctx, ecb, ctx->key_gen_key, NULL, NULL))
goto err;
memset(&data, 0, sizeof(data));
memcpy(&data.block[sizeof(data.counter)], ctx->nonce, NONCE_SIZE);
/* msg_auth_key is always 16 bytes in size, regardless of AES128/AES256 */
/* counter is stored little-endian */
for (i = 0; i < BLOCK_SIZE; i += 8) {
if (IS_LITTLE_ENDIAN) {
data.counter = counter;
} else {
data.counter = GSWAP4(counter);
}
/* Block size is 16 (128 bits), but only 8 bytes are used */
out_len = BLOCK_SIZE;
if (!EVP_EncryptUpdate(ctx->ecb_ctx, output, &out_len, data.block, BLOCK_SIZE))
goto err;
memcpy(&ctx->msg_auth_key[i], output, 8);
counter++;
}
/* msg_enc_key length is directly tied to key length AES128/AES256 */
for (i = 0; i < ctx->key_len; i += 8) {
if (IS_LITTLE_ENDIAN) {
data.counter = counter;
} else {
data.counter = GSWAP4(counter);
}
/* Block size is 16 bytes (128 bits), but only 8 bytes are used */
out_len = BLOCK_SIZE;
if (!EVP_EncryptUpdate(ctx->ecb_ctx, output, &out_len, data.block, BLOCK_SIZE))
goto err;
memcpy(&ctx->msg_enc_key[i], output, 8);
counter++;
}
if (!EVP_EncryptInit_ex2(ctx->ecb_ctx, ecb, ctx->msg_enc_key, NULL, NULL))
goto err;
/* Freshen up the state */
ctx->used_enc = 0;
ctx->used_dec = 0;
EVP_CIPHER_free(ecb);
return 1;
err:
EVP_CIPHER_CTX_free(ctx->ecb_ctx);
EVP_CIPHER_free(ecb);
ctx->ecb_ctx = NULL;
return 0;
}
static int aes_gcm_siv_aad(PROV_AES_GCM_SIV_CTX *ctx,
const unsigned char *aad, size_t len)
{
size_t to_alloc;
uint8_t *ptr;
uint64_t len64;
/* length of 0 resets the AAD */
if (len == 0) {
OPENSSL_free(ctx->aad);
ctx->aad = NULL;
ctx->aad_len = 0;
return 1;
}
to_alloc = UP16(ctx->aad_len + len);
/* need to check the size of the AAD per RFC8452 */
len64 = to_alloc;
if (len64 > ((uint64_t)1 << 36))
return 0;
ptr = OPENSSL_realloc(ctx->aad, to_alloc);
if (ptr == NULL)
return 0;
ctx->aad = ptr;
memcpy(&ctx->aad[ctx->aad_len], aad, len);
ctx->aad_len += len;
if (to_alloc > ctx->aad_len)
memset(&ctx->aad[ctx->aad_len], 0, to_alloc - ctx->aad_len);
return 1;
}
static int aes_gcm_siv_finish(PROV_AES_GCM_SIV_CTX *ctx)
{
int ret = 0;
if (ctx->enc)
return ctx->generated_tag;
ret = !CRYPTO_memcmp(ctx->tag, ctx->user_tag, sizeof(ctx->tag));
ret &= ctx->have_user_tag;
return ret;
}
static int aes_gcm_siv_encrypt(PROV_AES_GCM_SIV_CTX *ctx, const unsigned char *in,
unsigned char *out, size_t len)
{
uint64_t len_blk[2];
uint8_t S_s[TAG_SIZE];
uint8_t counter_block[TAG_SIZE];
uint8_t padding[BLOCK_SIZE];
size_t i;
int64_t len64 = len;
int out_len;
int error = 0;
DECLARE_IS_ENDIAN;
ctx->generated_tag = 0;
if (!ctx->speed && ctx->used_enc)
return 0;
/* need to check the size of the input! */
if (len64 > ((int64_t)1 << 36) || len == 0)
return 0;
if (IS_LITTLE_ENDIAN) {
len_blk[0] = (uint64_t)ctx->aad_len * 8;
len_blk[1] = (uint64_t)len * 8;
} else {
len_blk[0] = GSWAP8((uint64_t)ctx->aad_len * 8);
len_blk[1] = GSWAP8((uint64_t)len * 8);
}
memset(S_s, 0, TAG_SIZE);
ossl_polyval_ghash_init(ctx->Htable, (const uint64_t*)ctx->msg_auth_key);
if (ctx->aad != NULL) {
/* AAD is allocated with padding, but need to adjust length */
ossl_polyval_ghash_hash(ctx->Htable, S_s, ctx->aad, UP16(ctx->aad_len));
}
if (DOWN16(len) > 0)
ossl_polyval_ghash_hash(ctx->Htable, S_s, (uint8_t *) in, DOWN16(len));
if (!IS16(len)) {
/* deal with padding - probably easier to memset the padding first rather than calculate */
memset(padding, 0, sizeof(padding));
memcpy(padding, &in[DOWN16(len)], REMAINDER16(len));
ossl_polyval_ghash_hash(ctx->Htable, S_s, padding, sizeof(padding));
}
ossl_polyval_ghash_hash(ctx->Htable, S_s, (uint8_t *) len_blk, sizeof(len_blk));
for (i = 0; i < NONCE_SIZE; i++)
S_s[i] ^= ctx->nonce[i];
S_s[TAG_SIZE - 1] &= 0x7f;
out_len = sizeof(ctx->tag);
error |= !EVP_EncryptUpdate(ctx->ecb_ctx, ctx->tag, &out_len, S_s, sizeof(S_s));
memcpy(counter_block, ctx->tag, TAG_SIZE);
counter_block[TAG_SIZE - 1] |= 0x80;
error |= !aes_gcm_siv_ctr32(ctx, counter_block, out, in, len);
ctx->generated_tag = !error;
/* Regardless of error */
ctx->used_enc = 1;
return !error;
}
static int aes_gcm_siv_decrypt(PROV_AES_GCM_SIV_CTX *ctx, const unsigned char *in,
unsigned char *out, size_t len)
{
uint8_t counter_block[TAG_SIZE];
uint64_t len_blk[2];
uint8_t S_s[TAG_SIZE];
size_t i;
uint64_t padding[2];
int64_t len64 = len;
int out_len;
int error = 0;
DECLARE_IS_ENDIAN;
ctx->generated_tag = 0;
if (!ctx->speed && ctx->used_dec)
return 0;
/* need to check the size of the input! */
if (len64 > ((int64_t)1 << 36) || len == 0)
return 0;
memcpy(counter_block, ctx->user_tag, sizeof(counter_block));
counter_block[TAG_SIZE - 1] |= 0x80;
error |= !aes_gcm_siv_ctr32(ctx, counter_block, out, in, len);
if (IS_LITTLE_ENDIAN) {
len_blk[0] = (uint64_t)ctx->aad_len * 8;
len_blk[1] = (uint64_t)len * 8;
} else {
len_blk[0] = GSWAP8((uint64_t)ctx->aad_len * 8);
len_blk[1] = GSWAP8((uint64_t)len * 8);
}
memset(S_s, 0, TAG_SIZE);
ossl_polyval_ghash_init(ctx->Htable, (const uint64_t*)ctx->msg_auth_key);
if (ctx->aad != NULL) {
/* AAD allocated with padding, but need to adjust length */
ossl_polyval_ghash_hash(ctx->Htable, S_s, ctx->aad, UP16(ctx->aad_len));
}
if (DOWN16(len) > 0)
ossl_polyval_ghash_hash(ctx->Htable, S_s, out, DOWN16(len));
if (!IS16(len)) {
/* deal with padding - probably easier to "memset" the padding first rather than calculate */
padding[0] = padding[1] = 0;
memcpy(padding, &out[DOWN16(len)], REMAINDER16(len));
ossl_polyval_ghash_hash(ctx->Htable, S_s, (uint8_t *)padding, sizeof(padding));
}
ossl_polyval_ghash_hash(ctx->Htable, S_s, (uint8_t *)len_blk, TAG_SIZE);
for (i = 0; i < NONCE_SIZE; i++)
S_s[i] ^= ctx->nonce[i];
S_s[TAG_SIZE - 1] &= 0x7f;
/*
* In the ctx, user_tag is the one received/set by the user,
* and tag is generated from the input
*/
out_len = sizeof(ctx->tag);
error |= !EVP_EncryptUpdate(ctx->ecb_ctx, ctx->tag, &out_len, S_s, sizeof(S_s));
ctx->generated_tag = !error;
/* Regardless of error */
ctx->used_dec = 1;
return !error;
}
static int aes_gcm_siv_cipher(void *vctx, unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
/* EncryptFinal or DecryptFinal */
if (in == NULL)
return aes_gcm_siv_finish(ctx);
/* Deal with associated data */
if (out == NULL)
return aes_gcm_siv_aad(ctx, in, len);
if (ctx->enc)
return aes_gcm_siv_encrypt(ctx, in, out, len);
return aes_gcm_siv_decrypt(ctx, in, out, len);
}
static void aes_gcm_siv_clean_ctx(void *vctx)
{
PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
EVP_CIPHER_CTX_free(ctx->ecb_ctx);
ctx->ecb_ctx = NULL;
}
static int aes_gcm_siv_dup_ctx(void *vdst, void *vsrc)
{
PROV_AES_GCM_SIV_CTX *dst = (PROV_AES_GCM_SIV_CTX *)vdst;
PROV_AES_GCM_SIV_CTX *src = (PROV_AES_GCM_SIV_CTX *)vsrc;
dst->ecb_ctx = NULL;
if (src->ecb_ctx != NULL) {
if ((dst->ecb_ctx = EVP_CIPHER_CTX_new()) == NULL)
goto err;
if (!EVP_CIPHER_CTX_copy(dst->ecb_ctx, src->ecb_ctx))
goto err;
}
return 1;
err:
EVP_CIPHER_CTX_free(dst->ecb_ctx);
dst->ecb_ctx = NULL;
return 0;
}
static const PROV_CIPHER_HW_AES_GCM_SIV aes_gcm_siv_hw = {
aes_gcm_siv_initkey,
aes_gcm_siv_cipher,
aes_gcm_siv_dup_ctx,
aes_gcm_siv_clean_ctx,
};
const PROV_CIPHER_HW_AES_GCM_SIV *ossl_prov_cipher_hw_aes_gcm_siv(size_t keybits)
{
return &aes_gcm_siv_hw;
}
/* AES-GCM-SIV needs AES-CTR32, which is different than the AES-CTR implementation */
static int aes_gcm_siv_ctr32(PROV_AES_GCM_SIV_CTX *ctx, const unsigned char *init_counter,
unsigned char *out, const unsigned char *in, size_t len)
{
uint8_t keystream[BLOCK_SIZE];
int out_len;
size_t i;
size_t j;
size_t todo;
uint32_t counter;
int error = 0;
union {
uint32_t x32[BLOCK_SIZE / sizeof(uint32_t)];
uint8_t x8[BLOCK_SIZE];
} block;
DECLARE_IS_ENDIAN;
memcpy(&block, init_counter, sizeof(block));
if (IS_BIG_ENDIAN) {
counter = GSWAP4(block.x32[0]);
}
for (i = 0; i < len; i += sizeof(block)) {
out_len = BLOCK_SIZE;
error |= !EVP_EncryptUpdate(ctx->ecb_ctx, keystream, &out_len, (uint8_t*)&block, sizeof(block));
if (IS_LITTLE_ENDIAN) {
block.x32[0]++;
} else {
counter++;
block.x32[0] = GSWAP4(counter);
}
todo = len - i;
if (todo > sizeof(keystream))
todo = sizeof(keystream);
/* Non optimal, but avoids alignment issues */
for (j = 0; j < todo; j++)
out[i + j] = in[i + j] ^ keystream[j];
}
return !error;
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2019-2023 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 low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
#include <openssl/evp.h>
#include <internal/endian.h>
#include <prov/implementations.h>
#include "cipher_aes_gcm_siv.h"
static ossl_inline void mulx_ghash(uint64_t *a)
{
uint64_t t[2], mask;
DECLARE_IS_ENDIAN;
if (IS_LITTLE_ENDIAN) {
t[0] = GSWAP8(a[0]);
t[1] = GSWAP8(a[1]);
} else {
t[0] = a[0];
t[1] = a[1];
}
mask = -(int64_t)(t[1] & 1) & 0xe1;
mask <<= 56;
if (IS_LITTLE_ENDIAN) {
a[1] = GSWAP8((t[1] >> 1) ^ (t[0] << 63));
a[0] = GSWAP8((t[0] >> 1) ^ mask);
} else {
a[1] = (t[1] >> 1) ^ (t[0] << 63);
a[0] = (t[0] >> 1) ^ mask;
}
}
#define aligned64(p) (((uintptr_t)p & 0x07) == 0)
static ossl_inline void byte_reverse16(uint8_t *out, const uint8_t *in)
{
if (aligned64(out) && aligned64(in)) {
((uint64_t *)out)[0] = GSWAP8(((uint64_t *)in)[1]);
((uint64_t *)out)[1] = GSWAP8(((uint64_t *)in)[0]);
} else {
int i;
for (i = 0; i < 16; i++)
out[i] = in[15 - i];
}
}
/* Initialization of POLYVAL via existing GHASH implementation */
void ossl_polyval_ghash_init(u128 Htable[16], const uint64_t H[2])
{
uint64_t tmp[2];
DECLARE_IS_ENDIAN;
byte_reverse16((uint8_t *)tmp, (const uint8_t *)H);
mulx_ghash(tmp);
if (IS_LITTLE_ENDIAN) {
/* "H is stored in host byte order" */
tmp[0] = GSWAP8(tmp[0]);
tmp[1] = GSWAP8(tmp[1]);
}
ossl_gcm_init_4bit(Htable, (u64*)tmp);
}
/* Implementation of POLYVAL via existing GHASH implementation */
void ossl_polyval_ghash_hash(const u128 Htable[16], uint8_t *tag, const uint8_t *inp, size_t len)
{
uint64_t out[2];
uint64_t tmp[2];
size_t i;
byte_reverse16((uint8_t *)out, (uint8_t *)tag);
/*
* This implementation doesn't deal with partials, callers do,
* so, len is a multiple of 16
*/
for (i = 0; i < len; i += 16) {
byte_reverse16((uint8_t *)tmp, &inp[i]);
ossl_gcm_ghash_4bit((u64*)out, Htable, (uint8_t *)tmp, 16);
}
byte_reverse16(tag, (uint8_t *)out);
}

View File

@@ -0,0 +1,163 @@
/*
* Copyright 2001-2024 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
*/
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#include <openssl/proverr.h>
#include "cipher_aes.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
# ifdef HWAES_ecb_encrypt
if (dat->mode == EVP_CIPH_ECB_MODE)
dat->stream.ecb = (ecb128_f)HWAES_ecb_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)ossl_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_ecb_encrypt
if (dat->mode == EVP_CIPH_ECB_MODE)
dat->stream.ecb = (ecb128_f)HWAES_ecb_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)ossl_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_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
IMPLEMENT_CIPHER_HW_COPYCTX(cipher_hw_aes_copyctx, PROV_AES_CTX)
#define PROV_CIPHER_HW_aes_mode(mode) \
static const PROV_CIPHER_HW aes_##mode = { \
cipher_hw_aes_initkey, \
ossl_cipher_hw_generic_##mode, \
cipher_hw_aes_copyctx \
}; \
PROV_CIPHER_HW_declare(mode) \
const PROV_CIPHER_HW *ossl_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"
#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
# include "cipher_aes_hw_rv64i.inc"
#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32
# include "cipher_aes_hw_rv32i.inc"
#elif defined (ARMv8_HWAES_CAPABLE)
# include "cipher_aes_hw_armv8.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)

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2001-2021 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 ossl_cipher_hw_generic_ofb128
#define cipher_hw_aesni_cfb128 ossl_cipher_hw_generic_cfb128
#define cipher_hw_aesni_cfb8 ossl_cipher_hw_generic_cfb8
#define cipher_hw_aesni_cfb1 ossl_cipher_hw_generic_cfb1
#define cipher_hw_aesni_ctr ossl_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_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, \
cipher_hw_aes_copyctx \
};
#define PROV_CIPHER_HW_select(mode) \
if (AESNI_CAPABLE) \
return &aesni_##mode;

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2023 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
*/
/*
* Crypto extension support for AES modes ecb, cbc, ofb, cfb, ctr.
* This file is included by cipher_aes_hw.c
*/
static int cipher_hw_aes_arm_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key,
size_t keylen)
{
int ret = cipher_hw_aes_initkey(dat, key, keylen);
if (AES_UNROLL12_EOR3_CAPABLE && dat->mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks_unroll12_eor3;
return ret;
}
#define PROV_CIPHER_HW_declare(mode) \
static const PROV_CIPHER_HW aes_arm_##mode = { \
cipher_hw_aes_arm_initkey, \
ossl_cipher_hw_generic_##mode, \
cipher_hw_aes_copyctx \
};
#define PROV_CIPHER_HW_select(mode) \
if (ARMv8_HWAES_CAPABLE) \
return &aes_arm_##mode;

View File

@@ -0,0 +1,102 @@
/*
* Copyright 2022-2023 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
*/
/*-
* RISC-V 32 ZKND ZKNE support for AES modes ecb, cbc, ofb, cfb, ctr.
* This file is included by cipher_aes_hw.c
*/
#define cipher_hw_rv32i_zknd_zkne_cbc ossl_cipher_hw_generic_cbc
#define cipher_hw_rv32i_zknd_zkne_ecb ossl_cipher_hw_generic_ecb
#define cipher_hw_rv32i_zknd_zkne_ofb128 ossl_cipher_hw_generic_ofb128
#define cipher_hw_rv32i_zknd_zkne_cfb128 ossl_cipher_hw_generic_cfb128
#define cipher_hw_rv32i_zknd_zkne_cfb8 ossl_cipher_hw_generic_cfb8
#define cipher_hw_rv32i_zknd_zkne_cfb1 ossl_cipher_hw_generic_cfb1
#define cipher_hw_rv32i_zknd_zkne_ctr ossl_cipher_hw_generic_ctr
#define cipher_hw_rv32i_zbkb_zknd_zkne_cbc ossl_cipher_hw_generic_cbc
#define cipher_hw_rv32i_zbkb_zknd_zkne_ecb ossl_cipher_hw_generic_ecb
#define cipher_hw_rv32i_zbkb_zknd_zkne_ofb128 ossl_cipher_hw_generic_ofb128
#define cipher_hw_rv32i_zbkb_zknd_zkne_cfb128 ossl_cipher_hw_generic_cfb128
#define cipher_hw_rv32i_zbkb_zknd_zkne_cfb8 ossl_cipher_hw_generic_cfb8
#define cipher_hw_rv32i_zbkb_zknd_zkne_cfb1 ossl_cipher_hw_generic_cfb1
#define cipher_hw_rv32i_zbkb_zknd_zkne_ctr ossl_cipher_hw_generic_ctr
static int cipher_hw_rv32i_zknd_zkne_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 = rv32i_zknd_zkne_set_decrypt_key(key, keylen * 8, ks);
dat->block = (block128_f) rv32i_zknd_decrypt;
dat->stream.cbc = NULL;
} else {
ret = rv32i_zkne_set_encrypt_key(key, keylen * 8, ks);
dat->block = (block128_f) rv32i_zkne_encrypt;
dat->stream.cbc = NULL;
}
if (ret < 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
static int cipher_hw_rv32i_zbkb_zknd_zkne_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 = rv32i_zbkb_zknd_zkne_set_decrypt_key(key, keylen * 8, ks);
dat->block = (block128_f) rv32i_zknd_decrypt;
dat->stream.cbc = NULL;
} else {
ret = rv32i_zbkb_zkne_set_encrypt_key(key, keylen * 8, ks);
dat->block = (block128_f) rv32i_zkne_encrypt;
dat->stream.cbc = NULL;
}
if (ret < 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
#define PROV_CIPHER_HW_declare(mode) \
static const PROV_CIPHER_HW rv32i_zknd_zkne_##mode = { \
cipher_hw_rv32i_zknd_zkne_initkey, \
cipher_hw_rv32i_zknd_zkne_##mode, \
cipher_hw_aes_copyctx \
}; \
static const PROV_CIPHER_HW rv32i_zbkb_zknd_zkne_##mode = { \
cipher_hw_rv32i_zbkb_zknd_zkne_initkey, \
cipher_hw_rv32i_zbkb_zknd_zkne_##mode, \
cipher_hw_aes_copyctx \
};
#define PROV_CIPHER_HW_select(mode) \
if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE()) \
return &rv32i_zbkb_zknd_zkne_##mode; \
if (RISCV_HAS_ZKND_AND_ZKNE()) \
return &rv32i_zknd_zkne_##mode;

View File

@@ -0,0 +1,135 @@
/*
* Copyright 2022-2023 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
*/
/*-
* RISC-V 64 ZKND ZKNE support for AES modes ecb, cbc, ofb, cfb, ctr.
* This file is included by cipher_aes_hw.c
*/
#define cipher_hw_rv64i_zknd_zkne_cbc ossl_cipher_hw_generic_cbc
#define cipher_hw_rv64i_zknd_zkne_ecb ossl_cipher_hw_generic_ecb
#define cipher_hw_rv64i_zknd_zkne_ofb128 ossl_cipher_hw_generic_ofb128
#define cipher_hw_rv64i_zknd_zkne_cfb128 ossl_cipher_hw_generic_cfb128
#define cipher_hw_rv64i_zknd_zkne_cfb8 ossl_cipher_hw_generic_cfb8
#define cipher_hw_rv64i_zknd_zkne_cfb1 ossl_cipher_hw_generic_cfb1
#define cipher_hw_rv64i_zknd_zkne_ctr ossl_cipher_hw_generic_ctr
static int cipher_hw_rv64i_zknd_zkne_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 = rv64i_zknd_set_decrypt_key(key, keylen * 8, ks);
dat->block = (block128_f) rv64i_zknd_decrypt;
dat->stream.cbc = NULL;
} else {
ret = rv64i_zkne_set_encrypt_key(key, keylen * 8, ks);
dat->block = (block128_f) rv64i_zkne_encrypt;
dat->stream.cbc = NULL;
}
if (ret < 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
/*-
* RISC-V RV64 ZVKNED support for AES modes ecb, cbc, ofb, cfb, ctr.
* This file is included by cipher_aes_hw.c
*/
#define cipher_hw_rv64i_zvkned_cbc ossl_cipher_hw_generic_cbc
#define cipher_hw_rv64i_zvkned_ecb ossl_cipher_hw_generic_ecb
#define cipher_hw_rv64i_zvkned_ofb128 ossl_cipher_hw_generic_ofb128
#define cipher_hw_rv64i_zvkned_cfb128 ossl_cipher_hw_generic_cfb128
#define cipher_hw_rv64i_zvkned_cfb8 ossl_cipher_hw_generic_cfb8
#define cipher_hw_rv64i_zvkned_cfb1 ossl_cipher_hw_generic_cfb1
#define cipher_hw_rv64i_zvkned_ctr ossl_cipher_hw_generic_ctr
static int cipher_hw_rv64i_zvkned_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;
/*
* Zvkned only supports 128 and 256 bit keys for key schedule generation.
* For AES-192 case, we could fallback to `AES_set_encrypt_key`.
* All Zvkned-based implementations use the same `encrypt-key` scheduling
* for both encryption and decryption.
*/
if (keylen * 8 == 128 || keylen * 8 == 256) {
ret = rv64i_zvkned_set_encrypt_key(key, keylen * 8, ks);
} else {
ret = AES_set_encrypt_key(key, keylen * 8, ks);
}
if (dat->mode == EVP_CIPH_CBC_MODE) {
if (dat->enc) {
dat->stream.cbc = (cbc128_f) rv64i_zvkned_cbc_encrypt;
} else {
dat->stream.cbc = (cbc128_f) rv64i_zvkned_cbc_decrypt;
}
} else if (dat->mode == EVP_CIPH_CTR_MODE) {
if (RISCV_HAS_ZVKB()) {
dat->stream.ctr = (ctr128_f) rv64i_zvkb_zvkned_ctr32_encrypt_blocks;
}
} else if (dat->mode == EVP_CIPH_ECB_MODE) {
if (dat->enc) {
dat->stream.ecb = (ecb128_f) rv64i_zvkned_ecb_encrypt;
} else {
dat->stream.ecb = (ecb128_f) rv64i_zvkned_ecb_decrypt;
}
}
/* Zvkned supports aes-128/192/256 encryption and decryption. */
if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE) &&
!dat->enc) {
dat->block = (block128_f) rv64i_zvkned_decrypt;
} else {
dat->block = (block128_f) rv64i_zvkned_encrypt;
}
if (ret < 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
#define PROV_CIPHER_HW_declare(mode) \
static const PROV_CIPHER_HW rv64i_zknd_zkne_##mode = { \
cipher_hw_rv64i_zknd_zkne_initkey, \
cipher_hw_rv64i_zknd_zkne_##mode, \
cipher_hw_aes_copyctx \
}; \
static const PROV_CIPHER_HW rv64i_zvkned_##mode = { \
cipher_hw_rv64i_zvkned_initkey, \
cipher_hw_rv64i_zvkned_##mode, \
cipher_hw_aes_copyctx \
};
#define PROV_CIPHER_HW_select(mode) \
if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) \
return &rv64i_zvkned_##mode; \
else if (RISCV_HAS_ZKND_AND_ZKNE()) \
return &rv64i_zknd_zkne_##mode;

View File

@@ -0,0 +1,204 @@
/*
* Copyright 2001-2024 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"
#include <stdio.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 ossl_cipher_hw_generic_cbc
#define s390x_aes_cfb1_cipher_hw ossl_cipher_hw_generic_cfb1
#define s390x_aes_ctr_cipher_hw ossl_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);
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;
unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT;
s390x_km(in, len, out, adat->plat.s390x.fc | modifier,
&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.k, key, keylen);
adat->plat.s390x.fc = S390X_AES_FC(keylen);
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 = dat->num;
int rem;
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
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;
}
}
memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
dat->num = 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 */
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;
unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT;
int n = dat->num;
int rem;
unsigned char tmp;
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
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 | modifier,
&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;
}
}
memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
dat->num = 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 */
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;
unsigned int modifier = adat->base.enc ? 0 : S390X_DECRYPT;
memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen);
s390x_kmf(in, len, out, adat->plat.s390x.fc | modifier,
&adat->plat.s390x.param.kmo_kmf);
memcpy(dat->iv, adat->plat.s390x.param.kmo_kmf.cv, dat->ivlen);
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, \
cipher_hw_aes_copyctx \
};
#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;

View File

@@ -0,0 +1,96 @@
/*
* Copyright 2001-2021 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_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, \
ossl_cipher_hw_generic_##mode, \
cipher_hw_aes_copyctx \
};
#define PROV_CIPHER_HW_select(mode) \
if (SPARC_AES_CAPABLE) \
return &aes_t4_##mode;

View File

@@ -0,0 +1,568 @@
/*
* Copyright 2019-2024 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 low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
#include <openssl/proverr.h>
#include "cipher_aes_ocb.h"
#include "prov/providercommon.h"
#include "prov/ciphercommon_aead.h"
#include "prov/implementations.h"
#define AES_OCB_FLAGS AEAD_FLAGS
#define OCB_DEFAULT_TAG_LEN 16
#define OCB_DEFAULT_IV_LEN 12
#define OCB_MIN_IV_LEN 1
#define OCB_MAX_IV_LEN 15
PROV_CIPHER_FUNC(int, ocb_cipher, (PROV_AES_OCB_CTX *ctx,
const unsigned char *in, unsigned char *out,
size_t nextblock));
/* forward declarations */
static OSSL_FUNC_cipher_encrypt_init_fn aes_ocb_einit;
static OSSL_FUNC_cipher_decrypt_init_fn aes_ocb_dinit;
static OSSL_FUNC_cipher_update_fn aes_ocb_block_update;
static OSSL_FUNC_cipher_final_fn aes_ocb_block_final;
static OSSL_FUNC_cipher_cipher_fn aes_ocb_cipher;
static OSSL_FUNC_cipher_freectx_fn aes_ocb_freectx;
static OSSL_FUNC_cipher_dupctx_fn aes_ocb_dupctx;
static OSSL_FUNC_cipher_get_ctx_params_fn aes_ocb_get_ctx_params;
static OSSL_FUNC_cipher_set_ctx_params_fn aes_ocb_set_ctx_params;
static OSSL_FUNC_cipher_gettable_ctx_params_fn cipher_ocb_gettable_ctx_params;
static OSSL_FUNC_cipher_settable_ctx_params_fn cipher_ocb_settable_ctx_params;
/*
* The following methods could be moved into PROV_AES_OCB_HW if
* multiple hardware implementations are ever needed.
*/
static ossl_inline int aes_generic_ocb_setiv(PROV_AES_OCB_CTX *ctx,
const unsigned char *iv,
size_t ivlen, size_t taglen)
{
return (CRYPTO_ocb128_setiv(&ctx->ocb, iv, ivlen, taglen) == 1);
}
static ossl_inline int aes_generic_ocb_setaad(PROV_AES_OCB_CTX *ctx,
const unsigned char *aad,
size_t alen)
{
return CRYPTO_ocb128_aad(&ctx->ocb, aad, alen) == 1;
}
static ossl_inline int aes_generic_ocb_gettag(PROV_AES_OCB_CTX *ctx,
unsigned char *tag, size_t tlen)
{
return CRYPTO_ocb128_tag(&ctx->ocb, tag, tlen) > 0;
}
static ossl_inline int aes_generic_ocb_final(PROV_AES_OCB_CTX *ctx)
{
return (CRYPTO_ocb128_finish(&ctx->ocb, ctx->tag, ctx->taglen) == 0);
}
static ossl_inline void aes_generic_ocb_cleanup(PROV_AES_OCB_CTX *ctx)
{
CRYPTO_ocb128_cleanup(&ctx->ocb);
}
static ossl_inline int aes_generic_ocb_cipher(PROV_AES_OCB_CTX *ctx,
const unsigned char *in,
unsigned char *out, size_t len)
{
if (ctx->base.enc) {
if (!CRYPTO_ocb128_encrypt(&ctx->ocb, in, out, len))
return 0;
} else {
if (!CRYPTO_ocb128_decrypt(&ctx->ocb, in, out, len))
return 0;
}
return 1;
}
static ossl_inline int aes_generic_ocb_copy_ctx(PROV_AES_OCB_CTX *dst,
PROV_AES_OCB_CTX *src)
{
return CRYPTO_ocb128_copy_ctx(&dst->ocb, &src->ocb,
&dst->ksenc.ks, &dst->ksdec.ks);
}
/*-
* Provider dispatch functions
*/
static int aes_ocb_init(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[], int enc)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
if (!ossl_prov_is_running())
return 0;
ctx->aad_buf_len = 0;
ctx->data_buf_len = 0;
ctx->base.enc = enc;
if (iv != NULL) {
if (ivlen != ctx->base.ivlen) {
/* IV len must be 1 to 15 */
if (ivlen < OCB_MIN_IV_LEN || ivlen > OCB_MAX_IV_LEN) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
ctx->base.ivlen = ivlen;
}
if (!ossl_cipher_generic_initiv(&ctx->base, iv, ivlen))
return 0;
ctx->iv_state = IV_STATE_BUFFERED;
}
if (key != NULL) {
if (keylen != ctx->base.keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
if (!ctx->base.hw->init(&ctx->base, key, keylen))
return 0;
}
return aes_ocb_set_ctx_params(ctx, params);
}
static int aes_ocb_einit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
return aes_ocb_init(vctx, key, keylen, iv, ivlen, params, 1);
}
static int aes_ocb_dinit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
return aes_ocb_init(vctx, key, keylen, iv, ivlen, params, 0);
}
/*
* Because of the way OCB works, both the AAD and data are buffered in the
* same way. Only the last block can be a partial block.
*/
static int aes_ocb_block_update_internal(PROV_AES_OCB_CTX *ctx,
unsigned char *buf, size_t *bufsz,
unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in,
size_t inl, OSSL_ocb_cipher_fn ciph)
{
size_t nextblocks;
size_t outlint = 0;
if (*bufsz != 0)
nextblocks = ossl_cipher_fillblock(buf, bufsz, AES_BLOCK_SIZE, &in, &inl);
else
nextblocks = inl & ~(AES_BLOCK_SIZE-1);
if (*bufsz == AES_BLOCK_SIZE) {
if (outsize < AES_BLOCK_SIZE) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!ciph(ctx, buf, out, AES_BLOCK_SIZE)) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
*bufsz = 0;
outlint = AES_BLOCK_SIZE;
if (out != NULL)
out += AES_BLOCK_SIZE;
}
if (nextblocks > 0) {
outlint += nextblocks;
if (outsize < outlint) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!ciph(ctx, in, out, nextblocks)) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
in += nextblocks;
inl -= nextblocks;
}
if (inl != 0
&& !ossl_cipher_trailingdata(buf, bufsz, AES_BLOCK_SIZE, &in, &inl)) {
/* PROVerr already called */
return 0;
}
*outl = outlint;
return inl == 0;
}
/* A wrapper function that has the same signature as cipher */
static int cipher_updateaad(PROV_AES_OCB_CTX *ctx, const unsigned char *in,
unsigned char *out, size_t len)
{
return aes_generic_ocb_setaad(ctx, in, len);
}
static int update_iv(PROV_AES_OCB_CTX *ctx)
{
if (ctx->iv_state == IV_STATE_FINISHED
|| ctx->iv_state == IV_STATE_UNINITIALISED)
return 0;
if (ctx->iv_state == IV_STATE_BUFFERED) {
if (!aes_generic_ocb_setiv(ctx, ctx->base.iv, ctx->base.ivlen,
ctx->taglen))
return 0;
ctx->iv_state = IV_STATE_COPIED;
}
return 1;
}
static int aes_ocb_block_update(void *vctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in,
size_t inl)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
unsigned char *buf;
size_t *buflen;
OSSL_ocb_cipher_fn fn;
if (!ctx->key_set || !update_iv(ctx))
return 0;
if (inl == 0) {
*outl = 0;
return 1;
}
/* Are we dealing with AAD or normal data here? */
if (out == NULL) {
buf = ctx->aad_buf;
buflen = &ctx->aad_buf_len;
fn = cipher_updateaad;
} else {
buf = ctx->data_buf;
buflen = &ctx->data_buf_len;
fn = aes_generic_ocb_cipher;
}
return aes_ocb_block_update_internal(ctx, buf, buflen, out, outl, outsize,
in, inl, fn);
}
static int aes_ocb_block_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
if (!ossl_prov_is_running())
return 0;
/* If no block_update has run then the iv still needs to be set */
if (!ctx->key_set || !update_iv(ctx))
return 0;
/*
* Empty the buffer of any partial block that we might have been provided,
* both for data and AAD
*/
*outl = 0;
if (ctx->data_buf_len > 0) {
if (!aes_generic_ocb_cipher(ctx, ctx->data_buf, out, ctx->data_buf_len))
return 0;
*outl = ctx->data_buf_len;
ctx->data_buf_len = 0;
}
if (ctx->aad_buf_len > 0) {
if (!aes_generic_ocb_setaad(ctx, ctx->aad_buf, ctx->aad_buf_len))
return 0;
ctx->aad_buf_len = 0;
}
if (ctx->base.enc) {
/* If encrypting then just get the tag */
if (!aes_generic_ocb_gettag(ctx, ctx->tag, ctx->taglen))
return 0;
} else {
/* If decrypting then verify */
if (ctx->taglen == 0)
return 0;
if (!aes_generic_ocb_final(ctx))
return 0;
}
/* Don't reuse the IV */
ctx->iv_state = IV_STATE_FINISHED;
return 1;
}
static void *aes_ocb_newctx(void *provctx, size_t kbits, size_t blkbits,
size_t ivbits, unsigned int mode, uint64_t flags)
{
PROV_AES_OCB_CTX *ctx;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL) {
ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags,
ossl_prov_cipher_hw_aes_ocb(kbits), NULL);
ctx->taglen = OCB_DEFAULT_TAG_LEN;
}
return ctx;
}
static void aes_ocb_freectx(void *vctx)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
if (ctx != NULL) {
aes_generic_ocb_cleanup(ctx);
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
}
static void *aes_ocb_dupctx(void *vctx)
{
PROV_AES_OCB_CTX *in = (PROV_AES_OCB_CTX *)vctx;
PROV_AES_OCB_CTX *ret;
if (!ossl_prov_is_running())
return NULL;
ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL)
return NULL;
*ret = *in;
if (!aes_generic_ocb_copy_ctx(ret, in)) {
OPENSSL_free(ret);
ret = NULL;
}
return ret;
}
static int aes_ocb_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
const OSSL_PARAM *p;
size_t sz;
if (params == NULL)
return 1;
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 == NULL) {
/* Tag len must be 0 to 16 */
if (p->data_size > OCB_MAX_TAG_LEN) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH);
return 0;
}
ctx->taglen = p->data_size;
} else {
if (ctx->base.enc) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
if (p->data_size != ctx->taglen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH);
return 0;
}
memcpy(ctx->tag, p->data, p->data_size);
}
}
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;
}
/* IV len must be 1 to 15 */
if (sz < OCB_MIN_IV_LEN || sz > OCB_MAX_IV_LEN)
return 0;
if (ctx->base.ivlen != sz) {
ctx->base.ivlen = sz;
ctx->iv_state = IV_STATE_UNINITIALISED;
}
}
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;
}
if (ctx->base.keylen != keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
}
return 1;
}
static int aes_ocb_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
OSSL_PARAM *p;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.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->base.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) {
if (!OSSL_PARAM_set_size_t(p, ctx->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->base.ivlen > p->data_size) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
if (!OSSL_PARAM_set_octet_string(p, ctx->base.oiv, ctx->base.ivlen)
&& !OSSL_PARAM_set_octet_ptr(p, &ctx->base.oiv, ctx->base.ivlen)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_UPDATED_IV);
if (p != NULL) {
if (ctx->base.ivlen > p->data_size) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
if (!OSSL_PARAM_set_octet_string(p, ctx->base.iv, ctx->base.ivlen)
&& !OSSL_PARAM_set_octet_ptr(p, &ctx->base.iv, ctx->base.ivlen)) {
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 (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (!ctx->base.enc || p->data_size != ctx->taglen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH);
return 0;
}
memcpy(p->data, ctx->tag, ctx->taglen);
}
return 1;
}
static const OSSL_PARAM cipher_ocb_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_UPDATED_IV, NULL, 0),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *cipher_ocb_gettable_ctx_params(ossl_unused void *cctx,
ossl_unused void *p_ctx)
{
return cipher_ocb_known_gettable_ctx_params;
}
static const OSSL_PARAM cipher_ocb_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_END
};
static const OSSL_PARAM *cipher_ocb_settable_ctx_params(ossl_unused void *cctx,
ossl_unused void *p_ctx)
{
return cipher_ocb_known_settable_ctx_params;
}
static int aes_ocb_cipher(void *vctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in, size_t inl)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
if (!ossl_prov_is_running())
return 0;
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!aes_generic_ocb_cipher(ctx, in, out, inl)) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return 0;
}
*outl = inl;
return 1;
}
#define IMPLEMENT_cipher(mode, UCMODE, flags, kbits, blkbits, ivbits) \
static OSSL_FUNC_cipher_get_params_fn aes_##kbits##_##mode##_get_params; \
static int aes_##kbits##_##mode##_get_params(OSSL_PARAM params[]) \
{ \
return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
flags, kbits, blkbits, ivbits); \
} \
static OSSL_FUNC_cipher_newctx_fn aes_##kbits##_##mode##_newctx; \
static void *aes_##kbits##_##mode##_newctx(void *provctx) \
{ \
return aes_##mode##_newctx(provctx, kbits, blkbits, ivbits, \
EVP_CIPH_##UCMODE##_MODE, flags); \
} \
const OSSL_DISPATCH ossl_##aes##kbits##mode##_functions[] = { \
{ OSSL_FUNC_CIPHER_NEWCTX, \
(void (*)(void))aes_##kbits##_##mode##_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##_block_update }, \
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_##mode##_block_final }, \
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_ocb_cipher }, \
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_##mode##_freectx }, \
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_##mode##_dupctx }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
(void (*)(void))aes_##kbits##_##mode##_get_params }, \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
(void (*)(void))aes_##mode##_get_ctx_params }, \
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
(void (*)(void))aes_##mode##_set_ctx_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
(void (*)(void))ossl_cipher_generic_gettable_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
(void (*)(void))cipher_ocb_gettable_ctx_params }, \
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
(void (*)(void))cipher_ocb_settable_ctx_params }, \
OSSL_DISPATCH_END \
}
IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 256, 128, OCB_DEFAULT_IV_LEN * 8);
IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 192, 128, OCB_DEFAULT_IV_LEN * 8);
IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 128, 128, OCB_DEFAULT_IV_LEN * 8);

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2019-2020 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 "prov/ciphercommon.h"
#include "crypto/aes_platform.h"
#define OCB_MAX_TAG_LEN AES_BLOCK_SIZE
#define OCB_MAX_DATA_LEN AES_BLOCK_SIZE
#define OCB_MAX_AAD_LEN AES_BLOCK_SIZE
typedef struct prov_aes_ocb_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
AES_KEY ks;
} ksenc; /* AES key schedule to use for encryption/aad */
union {
OSSL_UNION_ALIGN;
AES_KEY ks;
} ksdec; /* AES key schedule to use for decryption */
OCB128_CONTEXT ocb;
unsigned int iv_state; /* set to one of IV_STATE_XXX */
unsigned int key_set : 1;
size_t taglen;
size_t data_buf_len;
size_t aad_buf_len;
unsigned char tag[OCB_MAX_TAG_LEN];
unsigned char data_buf[OCB_MAX_DATA_LEN]; /* Store partial data blocks */
unsigned char aad_buf[OCB_MAX_AAD_LEN]; /* Store partial AAD blocks */
} PROV_AES_OCB_CTX;
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ocb(size_t keybits);

View File

@@ -0,0 +1,209 @@
/*
* Copyright 2019-2024 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
*/
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#include "cipher_aes_ocb.h"
#define OCB_SET_KEY_FN(fn_set_enc_key, fn_set_dec_key, \
fn_block_enc, fn_block_dec, \
fn_stream_enc, fn_stream_dec) \
CRYPTO_ocb128_cleanup(&ctx->ocb); \
fn_set_enc_key(key, keylen * 8, &ctx->ksenc.ks); \
fn_set_dec_key(key, keylen * 8, &ctx->ksdec.ks); \
if (!CRYPTO_ocb128_init(&ctx->ocb, &ctx->ksenc.ks, &ctx->ksdec.ks, \
(block128_f)fn_block_enc, (block128_f)fn_block_dec, \
ctx->base.enc ? (ocb128_f)fn_stream_enc : \
(ocb128_f)fn_stream_dec)) \
return 0; \
ctx->key_set = 1
static int cipher_hw_aes_ocb_generic_initkey(PROV_CIPHER_CTX *vctx,
const unsigned char *key,
size_t keylen)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
/*
* We set both the encrypt and decrypt key here because decrypt
* needs both. (i.e- AAD uses encrypt).
*/
# ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
OCB_SET_KEY_FN(HWAES_set_encrypt_key, HWAES_set_decrypt_key,
HWAES_encrypt, HWAES_decrypt,
HWAES_ocb_encrypt, HWAES_ocb_decrypt);
} else
# endif
# ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
OCB_SET_KEY_FN(vpaes_set_encrypt_key, vpaes_set_decrypt_key,
vpaes_encrypt, vpaes_decrypt, NULL, NULL);
} else
# endif
{
OCB_SET_KEY_FN(AES_set_encrypt_key, AES_set_decrypt_key,
AES_encrypt, AES_decrypt, NULL, NULL);
}
return 1;
}
# if defined(AESNI_CAPABLE)
static int cipher_hw_aes_ocb_aesni_initkey(PROV_CIPHER_CTX *vctx,
const unsigned char *key,
size_t keylen)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
OCB_SET_KEY_FN(aesni_set_encrypt_key, aesni_set_decrypt_key,
aesni_encrypt, aesni_decrypt,
aesni_ocb_encrypt, aesni_ocb_decrypt);
return 1;
}
# define PROV_CIPHER_HW_declare() \
static const PROV_CIPHER_HW aesni_ocb = { \
cipher_hw_aes_ocb_aesni_initkey, \
NULL \
};
# define PROV_CIPHER_HW_select() \
if (AESNI_CAPABLE) \
return &aesni_ocb;
#elif defined(SPARC_AES_CAPABLE)
static int cipher_hw_aes_ocb_t4_initkey(PROV_CIPHER_CTX *vctx,
const unsigned char *key,
size_t keylen)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
OCB_SET_KEY_FN(aes_t4_set_encrypt_key, aes_t4_set_decrypt_key,
aes_t4_encrypt, aes_t4_decrypt, NULL, NULL);
return 1;
}
# define PROV_CIPHER_HW_declare() \
static const PROV_CIPHER_HW aes_t4_ocb = { \
cipher_hw_aes_ocb_t4_initkey, \
NULL \
};
# define PROV_CIPHER_HW_select() \
if (SPARC_AES_CAPABLE) \
return &aes_t4_ocb;
#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
static int cipher_hw_aes_ocb_rv64i_zknd_zkne_initkey(PROV_CIPHER_CTX *vctx,
const unsigned char *key,
size_t keylen)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
OCB_SET_KEY_FN(rv64i_zkne_set_encrypt_key, rv64i_zknd_set_decrypt_key,
rv64i_zkne_encrypt, rv64i_zknd_decrypt, NULL, NULL);
return 1;
}
static int cipher_hw_aes_ocb_rv64i_zvkned_initkey(PROV_CIPHER_CTX *vctx,
const unsigned char *key,
size_t keylen)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
/* Zvkned only supports 128 and 256 bit keys. */
if (keylen * 8 == 128 || keylen * 8 == 256) {
OCB_SET_KEY_FN(rv64i_zvkned_set_encrypt_key,
rv64i_zvkned_set_decrypt_key,
rv64i_zvkned_encrypt, rv64i_zvkned_decrypt,
NULL, NULL);
} else {
OCB_SET_KEY_FN(AES_set_encrypt_key, AES_set_encrypt_key,
rv64i_zvkned_encrypt, rv64i_zvkned_decrypt,
NULL, NULL);
}
return 1;
}
# define PROV_CIPHER_HW_declare() \
static const PROV_CIPHER_HW aes_rv64i_zknd_zkne_ocb = { \
cipher_hw_aes_ocb_rv64i_zknd_zkne_initkey, \
NULL \
}; \
static const PROV_CIPHER_HW aes_rv64i_zvkned_ocb = { \
cipher_hw_aes_ocb_rv64i_zvkned_initkey, \
NULL \
};
# define PROV_CIPHER_HW_select() \
if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) \
return &aes_rv64i_zvkned_ocb; \
else if (RISCV_HAS_ZKND_AND_ZKNE()) \
return &aes_rv64i_zknd_zkne_ocb;
#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32
static int cipher_hw_aes_ocb_rv32i_zknd_zkne_initkey(PROV_CIPHER_CTX *vctx,
const unsigned char *key,
size_t keylen)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
OCB_SET_KEY_FN(rv32i_zkne_set_encrypt_key, rv32i_zknd_zkne_set_decrypt_key,
rv32i_zkne_encrypt, rv32i_zknd_decrypt, NULL, NULL);
return 1;
}
static int cipher_hw_aes_ocb_rv32i_zbkb_zknd_zkne_initkey(PROV_CIPHER_CTX *vctx,
const unsigned char *key,
size_t keylen)
{
PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx;
OCB_SET_KEY_FN(rv32i_zbkb_zkne_set_encrypt_key, rv32i_zbkb_zknd_zkne_set_decrypt_key,
rv32i_zkne_encrypt, rv32i_zknd_decrypt, NULL, NULL);
return 1;
}
# define PROV_CIPHER_HW_declare() \
static const PROV_CIPHER_HW aes_rv32i_zknd_zkne_ocb = { \
cipher_hw_aes_ocb_rv32i_zknd_zkne_initkey, \
NULL \
}; \
static const PROV_CIPHER_HW aes_rv32i_zbkb_zknd_zkne_ocb = { \
cipher_hw_aes_ocb_rv32i_zbkb_zknd_zkne_initkey, \
NULL \
};
# define PROV_CIPHER_HW_select() \
if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE()) \
return &aes_rv32i_zbkb_zknd_zkne_ocb; \
if (RISCV_HAS_ZKND_AND_ZKNE()) \
return &aes_rv32i_zknd_zkne_ocb;
#else
# define PROV_CIPHER_HW_declare()
# define PROV_CIPHER_HW_select()
# endif
static const PROV_CIPHER_HW aes_generic_ocb = {
cipher_hw_aes_ocb_generic_initkey,
NULL
};
PROV_CIPHER_HW_declare()
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_ocb(size_t keybits)
{
PROV_CIPHER_HW_select()
return &aes_generic_ocb;
}

View File

@@ -0,0 +1,305 @@
/*
* Copyright 2019-2023 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 SIV mode */
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#include <openssl/proverr.h>
#include "cipher_aes_siv.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#include "prov/ciphercommon_aead.h"
#include "prov/provider_ctx.h"
#define siv_stream_update siv_cipher
#define SIV_FLAGS AEAD_FLAGS
static OSSL_FUNC_cipher_set_ctx_params_fn aes_siv_set_ctx_params;
static void *aes_siv_newctx(void *provctx, size_t keybits, unsigned int mode,
uint64_t flags)
{
PROV_AES_SIV_CTX *ctx;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL) {
ctx->taglen = SIV_LEN;
ctx->mode = mode;
ctx->keylen = keybits / 8;
ctx->hw = ossl_prov_cipher_hw_aes_siv(keybits);
ctx->libctx = PROV_LIBCTX_OF(provctx);
}
return ctx;
}
static void aes_siv_freectx(void *vctx)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
if (ctx != NULL) {
ctx->hw->cleanup(ctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
}
static void *siv_dupctx(void *vctx)
{
PROV_AES_SIV_CTX *in = (PROV_AES_SIV_CTX *)vctx;
PROV_AES_SIV_CTX *ret;
if (!ossl_prov_is_running())
return NULL;
ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL)
return NULL;
if (!in->hw->dupctx(in, ret)) {
OPENSSL_free(ret);
ret = NULL;
}
return ret;
}
static int siv_init(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[], int enc)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
if (!ossl_prov_is_running())
return 0;
ctx->enc = enc;
if (key != NULL) {
if (keylen != ctx->keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
if (!ctx->hw->initkey(ctx, key, ctx->keylen))
return 0;
}
return aes_siv_set_ctx_params(ctx, params);
}
static int siv_einit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
return siv_init(vctx, key, keylen, iv, ivlen, params, 1);
}
static int siv_dinit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
return siv_init(vctx, key, keylen, iv, ivlen, params, 0);
}
static int siv_cipher(void *vctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in, size_t inl)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
if (!ossl_prov_is_running())
return 0;
/* Ignore just empty encryption/decryption call and not AAD. */
if (out != NULL) {
if (inl == 0) {
if (outl != NULL)
*outl = 0;
return 1;
}
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
}
if (ctx->hw->cipher(ctx, out, in, inl) <= 0)
return 0;
if (outl != NULL)
*outl = inl;
return 1;
}
static int siv_stream_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
if (!ossl_prov_is_running())
return 0;
if (!ctx->hw->cipher(vctx, out, NULL, 0))
return 0;
if (outl != NULL)
*outl = 0;
return 1;
}
static int aes_siv_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
SIV128_CONTEXT *sctx = &ctx->siv;
OSSL_PARAM *p;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
if (p != NULL && p->data_type == OSSL_PARAM_OCTET_STRING) {
if (!ctx->enc
|| p->data_size != ctx->taglen
|| !OSSL_PARAM_set_octet_string(p, &sctx->tag.byte, ctx->taglen)) {
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 && !OSSL_PARAM_set_size_t(p, ctx->taglen)) {
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;
}
static const OSSL_PARAM aes_siv_known_gettable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *aes_siv_gettable_ctx_params(ossl_unused void *cctx,
ossl_unused void *provctx)
{
return aes_siv_known_gettable_ctx_params;
}
static int aes_siv_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
const OSSL_PARAM *p;
unsigned int speed = 0;
if (params == NULL)
return 1;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
if (p != NULL) {
if (ctx->enc)
return 1;
if (p->data_type != OSSL_PARAM_OCTET_STRING
|| !ctx->hw->settag(ctx, p->data, p->data_size)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_SPEED);
if (p != NULL) {
if (!OSSL_PARAM_get_uint(p, &speed)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
ctx->hw->setspeed(ctx, (int)speed);
}
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 */
if (keylen != ctx->keylen)
return 0;
}
return 1;
}
static const OSSL_PARAM aes_siv_known_settable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_SPEED, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *aes_siv_settable_ctx_params(ossl_unused void *cctx,
ossl_unused void *provctx)
{
return aes_siv_known_settable_ctx_params;
}
#define IMPLEMENT_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits) \
static OSSL_FUNC_cipher_newctx_fn alg##kbits##lc##_newctx; \
static OSSL_FUNC_cipher_freectx_fn alg##_##lc##_freectx; \
static OSSL_FUNC_cipher_dupctx_fn lc##_dupctx; \
static OSSL_FUNC_cipher_encrypt_init_fn lc##_einit; \
static OSSL_FUNC_cipher_decrypt_init_fn lc##_dinit; \
static OSSL_FUNC_cipher_update_fn lc##_stream_update; \
static OSSL_FUNC_cipher_final_fn lc##_stream_final; \
static OSSL_FUNC_cipher_cipher_fn lc##_cipher; \
static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lc##_get_params; \
static OSSL_FUNC_cipher_get_ctx_params_fn alg##_##lc##_get_ctx_params; \
static OSSL_FUNC_cipher_gettable_ctx_params_fn \
alg##_##lc##_gettable_ctx_params; \
static OSSL_FUNC_cipher_set_ctx_params_fn alg##_##lc##_set_ctx_params; \
static OSSL_FUNC_cipher_settable_ctx_params_fn \
alg##_##lc##_settable_ctx_params; \
static int alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[]) \
{ \
return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
flags, 2*kbits, blkbits, ivbits); \
} \
static void *alg##kbits##lc##_newctx(void *provctx) \
{ \
return alg##_##lc##_newctx(provctx, 2*kbits, EVP_CIPH_##UCMODE##_MODE, \
flags); \
} \
const OSSL_DISPATCH ossl_##alg##kbits##lc##_functions[] = { \
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))alg##kbits##lc##_newctx }, \
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))alg##_##lc##_freectx }, \
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) lc##_dupctx }, \
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void)) lc##_einit }, \
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void)) lc##_dinit }, \
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void)) lc##_stream_update }, \
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void)) lc##_stream_final }, \
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void)) lc##_cipher }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
(void (*)(void)) alg##_##kbits##_##lc##_get_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
(void (*)(void))ossl_cipher_generic_gettable_params }, \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
(void (*)(void)) alg##_##lc##_get_ctx_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
(void (*)(void)) alg##_##lc##_gettable_ctx_params }, \
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
(void (*)(void)) alg##_##lc##_set_ctx_params }, \
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
(void (*)(void)) alg##_##lc##_settable_ctx_params }, \
OSSL_DISPATCH_END \
};
IMPLEMENT_cipher(aes, siv, SIV, SIV_FLAGS, 128, 8, 0)
IMPLEMENT_cipher(aes, siv, SIV, SIV_FLAGS, 192, 8, 0)
IMPLEMENT_cipher(aes, siv, SIV, SIV_FLAGS, 256, 8, 0)

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2019-2021 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 "prov/ciphercommon.h"
#include "crypto/aes_platform.h"
#include "crypto/siv.h"
typedef struct prov_cipher_hw_aes_siv_st {
int (*initkey)(void *ctx, const uint8_t *key, size_t keylen);
int (*cipher)(void *ctx, unsigned char *out, const unsigned char *in,
size_t len);
void (*setspeed)(void *ctx, int speed);
int (*settag)(void *ctx, const unsigned char *tag, size_t tagl);
void (*cleanup)(void *ctx);
int (*dupctx)(void *src, void *dst);
} PROV_CIPHER_HW_AES_SIV;
typedef struct prov_siv_ctx_st {
unsigned int mode; /* The mode that we are using */
unsigned int enc : 1; /* Set to 1 if we are encrypting or 0 otherwise */
size_t keylen; /* The input keylength (twice the alg key length) */
size_t taglen; /* the taglen is the same as the sivlen */
SIV128_CONTEXT siv;
EVP_CIPHER *ctr; /* These are fetched - so we need to free them */
EVP_CIPHER *cbc;
const PROV_CIPHER_HW_AES_SIV *hw;
OSSL_LIB_CTX *libctx;
} PROV_AES_SIV_CTX;
const PROV_CIPHER_HW_AES_SIV *ossl_prov_cipher_hw_aes_siv(size_t keybits);

View File

@@ -0,0 +1,135 @@
/*
* Copyright 2019-2024 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
*/
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#include "cipher_aes_siv.h"
static void aes_siv_cleanup(void *vctx);
static int aes_siv_initkey(void *vctx, const unsigned char *key, size_t keylen)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
SIV128_CONTEXT *sctx = &ctx->siv;
size_t klen = keylen / 2;
OSSL_LIB_CTX *libctx = ctx->libctx;
const char *propq = NULL;
EVP_CIPHER_free(ctx->cbc);
EVP_CIPHER_free(ctx->ctr);
ctx->cbc = NULL;
ctx->ctr = NULL;
switch (klen) {
case 16:
ctx->cbc = EVP_CIPHER_fetch(libctx, "AES-128-CBC", propq);
ctx->ctr = EVP_CIPHER_fetch(libctx, "AES-128-CTR", propq);
break;
case 24:
ctx->cbc = EVP_CIPHER_fetch(libctx, "AES-192-CBC", propq);
ctx->ctr = EVP_CIPHER_fetch(libctx, "AES-192-CTR", propq);
break;
case 32:
ctx->cbc = EVP_CIPHER_fetch(libctx, "AES-256-CBC", propq);
ctx->ctr = EVP_CIPHER_fetch(libctx, "AES-256-CTR", propq);
break;
default:
break;
}
if (ctx->cbc == NULL || ctx->ctr == NULL)
return 0;
/*
* klen is the length of the underlying cipher, not the input key,
* which should be twice as long
*/
return ossl_siv128_init(sctx, key, klen, ctx->cbc, ctx->ctr, libctx,
propq);
}
static int aes_siv_dupctx(void *in_vctx, void *out_vctx)
{
PROV_AES_SIV_CTX *in = (PROV_AES_SIV_CTX *)in_vctx;
PROV_AES_SIV_CTX *out = (PROV_AES_SIV_CTX *)out_vctx;
*out = *in;
out->siv.cipher_ctx = NULL;
out->siv.mac_ctx_init = NULL;
out->siv.mac = NULL;
if (!ossl_siv128_copy_ctx(&out->siv, &in->siv))
return 0;
if (out->cbc != NULL)
EVP_CIPHER_up_ref(out->cbc);
if (out->ctr != NULL)
EVP_CIPHER_up_ref(out->ctr);
return 1;
}
static int aes_siv_settag(void *vctx, const unsigned char *tag, size_t tagl)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
SIV128_CONTEXT *sctx = &ctx->siv;
return ossl_siv128_set_tag(sctx, tag, tagl);
}
static void aes_siv_setspeed(void *vctx, int speed)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
SIV128_CONTEXT *sctx = &ctx->siv;
ossl_siv128_speed(sctx, (int)speed);
}
static void aes_siv_cleanup(void *vctx)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
SIV128_CONTEXT *sctx = &ctx->siv;
ossl_siv128_cleanup(sctx);
EVP_CIPHER_free(ctx->cbc);
EVP_CIPHER_free(ctx->ctr);
}
static int aes_siv_cipher(void *vctx, unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
SIV128_CONTEXT *sctx = &ctx->siv;
/* EncryptFinal or DecryptFinal */
if (in == NULL)
return ossl_siv128_finish(sctx) == 0;
/* Deal with associated data */
if (out == NULL)
return (ossl_siv128_aad(sctx, in, len) == 1);
if (ctx->enc)
return ossl_siv128_encrypt(sctx, in, out, len) > 0;
return ossl_siv128_decrypt(sctx, in, out, len) > 0;
}
static const PROV_CIPHER_HW_AES_SIV aes_siv_hw = {
aes_siv_initkey,
aes_siv_cipher,
aes_siv_setspeed,
aes_siv_settag,
aes_siv_cleanup,
aes_siv_dupctx,
};
const PROV_CIPHER_HW_AES_SIV *ossl_prov_cipher_hw_aes_siv(size_t keybits)
{
return &aes_siv_hw;
}

View File

@@ -0,0 +1,335 @@
/*
* Copyright 2019-2024 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
*/
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#include <openssl/proverr.h>
#include "cipher_aes.h"
#include "prov/providercommon.h"
#include "prov/implementations.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
#define WRAP_FLAGS (PROV_CIPHER_FLAG_CUSTOM_IV)
#define WRAP_FLAGS_INV (WRAP_FLAGS | PROV_CIPHER_FLAG_INVERSE_CIPHER)
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_FUNC_cipher_encrypt_init_fn aes_wrap_einit;
static OSSL_FUNC_cipher_decrypt_init_fn aes_wrap_dinit;
static OSSL_FUNC_cipher_update_fn aes_wrap_cipher;
static OSSL_FUNC_cipher_final_fn aes_wrap_final;
static OSSL_FUNC_cipher_freectx_fn aes_wrap_freectx;
static OSSL_FUNC_cipher_set_ctx_params_fn aes_wrap_set_ctx_params;
typedef struct prov_aes_wrap_ctx_st {
PROV_CIPHER_CTX base;
union {
OSSL_UNION_ALIGN;
AES_KEY ks;
} ks;
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;
PROV_CIPHER_CTX *ctx;
if (!ossl_prov_is_running())
return NULL;
wctx = OPENSSL_zalloc(sizeof(*wctx));
ctx = (PROV_CIPHER_CTX *)wctx;
if (ctx != NULL) {
ossl_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_dupctx(void *wctx)
{
PROV_AES_WRAP_CTX *ctx = wctx;
PROV_AES_WRAP_CTX *dctx = wctx;
if (!ossl_prov_is_running())
return NULL;
if (ctx == NULL)
return NULL;
dctx = OPENSSL_memdup(ctx, sizeof(*ctx));
if (dctx != NULL && dctx->base.tlsmac != NULL && dctx->base.alloced) {
dctx->base.tlsmac = OPENSSL_memdup(dctx->base.tlsmac,
dctx->base.tlsmacsize);
if (dctx->base.tlsmac == NULL) {
OPENSSL_free(dctx);
dctx = NULL;
}
}
return dctx;
}
static void aes_wrap_freectx(void *vctx)
{
PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
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, const OSSL_PARAM params[], int enc)
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx;
if (!ossl_prov_is_running())
return 0;
ctx->enc = enc;
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) {
if (!ossl_cipher_generic_initiv(ctx, iv, ivlen))
return 0;
}
if (key != NULL) {
int use_forward_transform;
if (keylen != ctx->keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
/*
* See SP800-38F : Section 5.1
* The forward and inverse transformations for the AES block
* cipher—called “cipher” and “inverse cipher” are informally known as
* the AES encryption and AES decryption functions, respectively.
* If the designated cipher function for a key-wrap algorithm is chosen
* to be the AES decryption function, then CIPH-1K will be the AES
* encryption function.
*/
if (ctx->inverse_cipher == 0)
use_forward_transform = ctx->enc;
else
use_forward_transform = !ctx->enc;
if (use_forward_transform) {
AES_set_encrypt_key(key, keylen * 8, &wctx->ks.ks);
ctx->block = (block128_f)AES_encrypt;
} else {
AES_set_decrypt_key(key, keylen * 8, &wctx->ks.ks);
ctx->block = (block128_f)AES_decrypt;
}
}
return aes_wrap_set_ctx_params(ctx, params);
}
static int aes_wrap_einit(void *ctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
return aes_wrap_init(ctx, key, keylen, iv, ivlen, params, 1);
}
static int aes_wrap_dinit(void *ctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
return aes_wrap_init(ctx, key, keylen, iv, ivlen, params, 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) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH);
return -1;
}
/* If decrypting need at least 16 bytes and multiple of 8 */
if (!ctx->enc && (inlen < 16 || inlen & 0x7)) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH);
return -1;
}
/* If not padding input must be multiple of 8 */
if (!pad && inlen & 0x7) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH);
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, ctx->iv_set ? ctx->iv : NULL, out, in,
inlen, ctx->block);
if (!rv) {
ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
return -1;
}
if (rv > INT_MAX) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH);
return -1;
}
return (int)rv;
}
static int aes_wrap_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
if (!ossl_prov_is_running())
return 0;
*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 (!ossl_prov_is_running())
return 0;
if (inl == 0) {
*outl = 0;
return 1;
}
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
len = aes_wrap_cipher_internal(ctx, out, in, inl);
if (len <= 0)
return 0;
*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;
if (params == NULL)
return 1;
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_FUNC_cipher_get_params_fn aes_##kbits##_##fname##_get_params; \
static int aes_##kbits##_##fname##_get_params(OSSL_PARAM params[]) \
{ \
return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,\
flags, kbits, blkbits, ivbits); \
} \
static OSSL_FUNC_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 ossl_##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_DUPCTX, (void (*)(void))aes_##mode##_dupctx }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
(void (*)(void))aes_##kbits##_##fname##_get_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
(void (*)(void))ossl_cipher_generic_gettable_params }, \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
(void (*)(void))ossl_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))ossl_cipher_generic_gettable_ctx_params }, \
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
(void (*)(void))ossl_cipher_generic_settable_ctx_params }, \
OSSL_DISPATCH_END \
}
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);
IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 256, 64, AES_WRAP_NOPAD_IVLEN * 8);
IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 192, 64, AES_WRAP_NOPAD_IVLEN * 8);
IMPLEMENT_cipher(wrap, wrapinv, WRAP, WRAP_FLAGS_INV, 128, 64, AES_WRAP_NOPAD_IVLEN * 8);
IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 256, 64, AES_WRAP_PAD_IVLEN * 8);
IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 192, 64, AES_WRAP_PAD_IVLEN * 8);
IMPLEMENT_cipher(wrap, wrappadinv, WRAP, WRAP_FLAGS_INV, 128, 64, AES_WRAP_PAD_IVLEN * 8);

View File

@@ -0,0 +1,296 @@
/*
* Copyright 2019-2024 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 low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
#include <openssl/proverr.h>
#include "cipher_aes_xts.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#define AES_XTS_FLAGS PROV_CIPHER_FLAG_CUSTOM_IV
#define AES_XTS_IV_BITS 128
#define AES_XTS_BLOCK_BITS 8
/* forward declarations */
static OSSL_FUNC_cipher_encrypt_init_fn aes_xts_einit;
static OSSL_FUNC_cipher_decrypt_init_fn aes_xts_dinit;
static OSSL_FUNC_cipher_update_fn aes_xts_stream_update;
static OSSL_FUNC_cipher_final_fn aes_xts_stream_final;
static OSSL_FUNC_cipher_cipher_fn aes_xts_cipher;
static OSSL_FUNC_cipher_freectx_fn aes_xts_freectx;
static OSSL_FUNC_cipher_dupctx_fn aes_xts_dupctx;
static OSSL_FUNC_cipher_set_ctx_params_fn aes_xts_set_ctx_params;
static OSSL_FUNC_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 ((!ossl_aes_xts_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,
const OSSL_PARAM params[], int enc)
{
PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)vctx;
PROV_CIPHER_CTX *ctx = &xctx->base;
if (!ossl_prov_is_running())
return 0;
ctx->enc = enc;
if (iv != NULL) {
if (!ossl_cipher_generic_initiv(vctx, iv, ivlen))
return 0;
}
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;
if (!ctx->hw->init(ctx, key, keylen))
return 0;
}
return aes_xts_set_ctx_params(ctx, params);
}
static int aes_xts_einit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
return aes_xts_init(vctx, key, keylen, iv, ivlen, params, 1);
}
static int aes_xts_dinit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
return aes_xts_init(vctx, key, keylen, iv, ivlen, params, 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;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL) {
ossl_cipher_generic_initkey(&ctx->base, kbits, blkbits, ivbits, mode,
flags, ossl_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;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_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 (!ossl_prov_is_running())
return 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)
return NULL;
in->base.hw->copyctx(&ret->base, &in->base);
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 (!ossl_prov_is_running()
|| ctx->xts.key1 == NULL
|| ctx->xts.key2 == NULL
|| !ctx->base.iv_set
|| out == NULL
|| in == NULL
|| inl < AES_BLOCK_SIZE)
return 0;
/*
* Impose a limit of 2^20 blocks per data unit as specified 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)
{
if (!ossl_prov_is_running())
return 0;
*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(ossl_unused void *cctx,
ossl_unused void *provctx)
{
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;
if (params == NULL)
return 1;
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_FUNC_cipher_get_params_fn aes_##kbits##_##lcmode##_get_params; \
static int aes_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
{ \
return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
flags, 2 * kbits, AES_XTS_BLOCK_BITS, \
AES_XTS_IV_BITS); \
} \
static OSSL_FUNC_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 ossl_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))ossl_cipher_generic_gettable_params }, \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
(void (*)(void))ossl_cipher_generic_get_ctx_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
(void (*)(void))ossl_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 }, \
OSSL_DISPATCH_END \
}
IMPLEMENT_cipher(xts, XTS, 256, AES_XTS_FLAGS);
IMPLEMENT_cipher(xts, XTS, 128, AES_XTS_FLAGS);

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2019-2021 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 "prov/ciphercommon.h"
#include "crypto/aes_platform.h"
/*
* Available in cipher_fips.c, and compiled with different values depending
* on we're in the FIPS module or not.
*/
extern const int ossl_aes_xts_allow_insecure_decrypt;
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;
} PROV_AES_XTS_CTX;
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts(size_t keybits);

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2019-2021 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 low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
#include "cipher_aes_xts.h"
#ifdef FIPS_MODULE
const int ossl_aes_xts_allow_insecure_decrypt = 0;
#else
const int ossl_aes_xts_allow_insecure_decrypt = 1;
#endif /* FIPS_MODULE */

View File

@@ -0,0 +1,306 @@
/*
* Copyright 2019-2024 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
*/
/*
* This file uses the low level AES functions (which are deprecated for
* non-internal use) in order to implement provider AES ciphers.
*/
#include "internal/deprecated.h"
#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);
return 1;
} else
#endif /* HWAES_CAPABLE */
#ifdef BSAES_CAPABLE
if (BSAES_CAPABLE) {
stream_enc = ossl_bsaes_xts_encrypt;
stream_dec = ossl_bsaes_xts_decrypt;
} else
#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);
return 1;
} else
#endif /* VPAES_CAPABLE */
{
(void)0;
}
{
XTS_SET_KEY_FN(AES_set_encrypt_key, AES_set_decrypt_key,
AES_encrypt, AES_decrypt, stream_enc, stream_dec);
}
return 1;
}
static void cipher_hw_aes_xts_copyctx(PROV_CIPHER_CTX *dst,
const PROV_CIPHER_CTX *src)
{
PROV_AES_XTS_CTX *sctx = (PROV_AES_XTS_CTX *)src;
PROV_AES_XTS_CTX *dctx = (PROV_AES_XTS_CTX *)dst;
*dctx = *sctx;
dctx->xts.key1 = &dctx->ks1.ks;
dctx->xts.key2 = &dctx->ks2.ks;
}
#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, \
cipher_hw_aes_xts_copyctx \
};
# 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, \
cipher_hw_aes_xts_copyctx \
};
# define PROV_CIPHER_HW_select_xts() \
if (SPARC_AES_CAPABLE) \
return &aes_xts_t4;
#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64
static int cipher_hw_aes_xts_rv64i_zknd_zkne_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;
XTS_SET_KEY_FN(rv64i_zkne_set_encrypt_key, rv64i_zknd_set_decrypt_key,
rv64i_zkne_encrypt, rv64i_zknd_decrypt,
stream_enc, stream_dec);
return 1;
}
static int cipher_hw_aes_xts_rv64i_zvbb_zvkg_zvkned_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;
/* Zvkned only supports 128 and 256 bit keys. */
if (keylen * 8 == 128 * 2 || keylen * 8 == 256 * 2) {
XTS_SET_KEY_FN(rv64i_zvkned_set_encrypt_key,
rv64i_zvkned_set_decrypt_key, rv64i_zvkned_encrypt,
rv64i_zvkned_decrypt,
rv64i_zvbb_zvkg_zvkned_aes_xts_encrypt,
rv64i_zvbb_zvkg_zvkned_aes_xts_decrypt);
} else {
XTS_SET_KEY_FN(AES_set_encrypt_key, AES_set_encrypt_key,
rv64i_zvkned_encrypt, rv64i_zvkned_decrypt,
stream_enc, stream_dec);
}
return 1;
}
static int cipher_hw_aes_xts_rv64i_zvkned_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;
/* Zvkned only supports 128 and 256 bit keys. */
if (keylen * 8 == 128 * 2 || keylen * 8 == 256 * 2) {
XTS_SET_KEY_FN(rv64i_zvkned_set_encrypt_key,
rv64i_zvkned_set_decrypt_key,
rv64i_zvkned_encrypt, rv64i_zvkned_decrypt,
stream_enc, stream_dec);
} else {
XTS_SET_KEY_FN(AES_set_encrypt_key, AES_set_encrypt_key,
rv64i_zvkned_encrypt, rv64i_zvkned_decrypt,
stream_enc, stream_dec);
}
return 1;
}
# define PROV_CIPHER_HW_declare_xts() \
static const PROV_CIPHER_HW aes_xts_rv64i_zknd_zkne = { \
cipher_hw_aes_xts_rv64i_zknd_zkne_initkey, \
NULL, \
cipher_hw_aes_xts_copyctx \
}; \
static const PROV_CIPHER_HW aes_xts_rv64i_zvkned = { \
cipher_hw_aes_xts_rv64i_zvkned_initkey, \
NULL, \
cipher_hw_aes_xts_copyctx \
}; \
static const PROV_CIPHER_HW aes_xts_rv64i_zvbb_zvkg_zvkned = { \
cipher_hw_aes_xts_rv64i_zvbb_zvkg_zvkned_initkey, \
NULL, \
cipher_hw_aes_xts_copyctx \
};
# define PROV_CIPHER_HW_select_xts() \
if (RISCV_HAS_ZVBB() && RISCV_HAS_ZVKG() && RISCV_HAS_ZVKNED() && \
riscv_vlen() >= 128) \
return &aes_xts_rv64i_zvbb_zvkg_zvkned; \
if (RISCV_HAS_ZVKNED() && riscv_vlen() >= 128) \
return &aes_xts_rv64i_zvkned; \
else if (RISCV_HAS_ZKND_AND_ZKNE()) \
return &aes_xts_rv64i_zknd_zkne;
#elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 32
static int cipher_hw_aes_xts_rv32i_zknd_zkne_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(rv32i_zkne_set_encrypt_key, rv32i_zknd_zkne_set_decrypt_key,
rv32i_zkne_encrypt, rv32i_zknd_decrypt,
NULL, NULL);
return 1;
}
static int cipher_hw_aes_xts_rv32i_zbkb_zknd_zkne_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(rv32i_zbkb_zkne_set_encrypt_key, rv32i_zbkb_zknd_zkne_set_decrypt_key,
rv32i_zkne_encrypt, rv32i_zknd_decrypt,
NULL, NULL);
return 1;
}
# define PROV_CIPHER_HW_declare_xts() \
static const PROV_CIPHER_HW aes_xts_rv32i_zknd_zkne = { \
cipher_hw_aes_xts_rv32i_zknd_zkne_initkey, \
NULL, \
cipher_hw_aes_xts_copyctx \
}; \
static const PROV_CIPHER_HW aes_xts_rv32i_zbkb_zknd_zkne = { \
cipher_hw_aes_xts_rv32i_zbkb_zknd_zkne_initkey, \
NULL, \
cipher_hw_aes_xts_copyctx \
};
# define PROV_CIPHER_HW_select_xts() \
if (RISCV_HAS_ZBKB_AND_ZKND_AND_ZKNE()) \
return &aes_xts_rv32i_zbkb_zknd_zkne; \
if (RISCV_HAS_ZKND_AND_ZKNE()) \
return &aes_xts_rv32i_zknd_zkne;
# 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,
cipher_hw_aes_xts_copyctx
};
PROV_CIPHER_HW_declare_xts()
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aes_xts(size_t keybits)
{
PROV_CIPHER_HW_select_xts()
return &aes_generic_xts;
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2019-2020 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 ARIA cipher modes ecb, cbc, ofb, cfb, ctr */
#include "cipher_aria.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
static OSSL_FUNC_cipher_freectx_fn aria_freectx;
static OSSL_FUNC_cipher_dupctx_fn aria_dupctx;
static void aria_freectx(void *vctx)
{
PROV_ARIA_CTX *ctx = (PROV_ARIA_CTX *)vctx;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static void *aria_dupctx(void *ctx)
{
PROV_ARIA_CTX *in = (PROV_ARIA_CTX *)ctx;
PROV_ARIA_CTX *ret;
if (!ossl_prov_is_running())
return NULL;
ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL)
return NULL;
in->base.hw->copyctx(&ret->base, &in->base);
return ret;
}
/* ossl_aria256ecb_functions */
IMPLEMENT_generic_cipher(aria, ARIA, ecb, ECB, 0, 256, 128, 0, block)
/* ossl_aria192ecb_functions */
IMPLEMENT_generic_cipher(aria, ARIA, ecb, ECB, 0, 192, 128, 0, block)
/* ossl_aria128ecb_functions */
IMPLEMENT_generic_cipher(aria, ARIA, ecb, ECB, 0, 128, 128, 0, block)
/* ossl_aria256cbc_functions */
IMPLEMENT_generic_cipher(aria, ARIA, cbc, CBC, 0, 256, 128, 128, block)
/* ossl_aria192cbc_functions */
IMPLEMENT_generic_cipher(aria, ARIA, cbc, CBC, 0, 192, 128, 128, block)
/* ossl_aria128cbc_functions */
IMPLEMENT_generic_cipher(aria, ARIA, cbc, CBC, 0, 128, 128, 128, block)
/* ossl_aria256ofb_functions */
IMPLEMENT_generic_cipher(aria, ARIA, ofb, OFB, 0, 256, 8, 128, stream)
/* ossl_aria192ofb_functions */
IMPLEMENT_generic_cipher(aria, ARIA, ofb, OFB, 0, 192, 8, 128, stream)
/* ossl_aria128ofb_functions */
IMPLEMENT_generic_cipher(aria, ARIA, ofb, OFB, 0, 128, 8, 128, stream)
/* ossl_aria256cfb_functions */
IMPLEMENT_generic_cipher(aria, ARIA, cfb, CFB, 0, 256, 8, 128, stream)
/* ossl_aria192cfb_functions */
IMPLEMENT_generic_cipher(aria, ARIA, cfb, CFB, 0, 192, 8, 128, stream)
/* ossl_aria128cfb_functions */
IMPLEMENT_generic_cipher(aria, ARIA, cfb, CFB, 0, 128, 8, 128, stream)
/* ossl_aria256cfb1_functions */
IMPLEMENT_generic_cipher(aria, ARIA, cfb1, CFB, 0, 256, 8, 128, stream)
/* ossl_aria192cfb1_functions */
IMPLEMENT_generic_cipher(aria, ARIA, cfb1, CFB, 0, 192, 8, 128, stream)
/* ossl_aria128cfb1_functions */
IMPLEMENT_generic_cipher(aria, ARIA, cfb1, CFB, 0, 128, 8, 128, stream)
/* ossl_aria256cfb8_functions */
IMPLEMENT_generic_cipher(aria, ARIA, cfb8, CFB, 0, 256, 8, 128, stream)
/* ossl_aria192cfb8_functions */
IMPLEMENT_generic_cipher(aria, ARIA, cfb8, CFB, 0, 192, 8, 128, stream)
/* ossl_aria128cfb8_functions */
IMPLEMENT_generic_cipher(aria, ARIA, cfb8, CFB, 0, 128, 8, 128, stream)
/* ossl_aria256ctr_functions */
IMPLEMENT_generic_cipher(aria, ARIA, ctr, CTR, 0, 256, 8, 128, stream)
/* ossl_aria192ctr_functions */
IMPLEMENT_generic_cipher(aria, ARIA, ctr, CTR, 0, 192, 8, 128, stream)
/* ossl_aria128ctr_functions */
IMPLEMENT_generic_cipher(aria, ARIA, ctr, CTR, 0, 128, 8, 128, stream)

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2019-2020 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 "crypto/aria.h"
#include "prov/ciphercommon.h"
typedef struct prov_aria_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
ARIA_KEY ks;
} ks;
} PROV_ARIA_CTX;
#define ossl_prov_cipher_hw_aria_ofb ossl_prov_cipher_hw_aria_ofb128
#define ossl_prov_cipher_hw_aria_cfb ossl_prov_cipher_hw_aria_cfb128
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aria_ecb(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aria_cbc(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aria_ofb128(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aria_cfb128(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aria_cfb1(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aria_cfb8(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aria_ctr(size_t keybits);

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2019-2023 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 ARIA CCM mode */
#include "cipher_aria_ccm.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
static OSSL_FUNC_cipher_freectx_fn aria_ccm_freectx;
static void *aria_ccm_newctx(void *provctx, size_t keybits)
{
PROV_ARIA_CCM_CTX *ctx;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL)
ossl_ccm_initctx(&ctx->base, keybits, ossl_prov_aria_hw_ccm(keybits));
return ctx;
}
static void *aria_ccm_dupctx(void *provctx)
{
PROV_ARIA_CCM_CTX *ctx = provctx;
PROV_ARIA_CCM_CTX *dctx = NULL;
if (ctx == NULL)
return NULL;
dctx = OPENSSL_memdup(ctx, sizeof(*ctx));
if (dctx != NULL && dctx->base.ccm_ctx.key != NULL)
dctx->base.ccm_ctx.key = &dctx->ks.ks;
return dctx;
}
static void aria_ccm_freectx(void *vctx)
{
PROV_ARIA_CCM_CTX *ctx = (PROV_ARIA_CCM_CTX *)vctx;
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
/* aria128ccm functions */
IMPLEMENT_aead_cipher(aria, ccm, CCM, AEAD_FLAGS, 128, 8, 96);
/* aria192ccm functions */
IMPLEMENT_aead_cipher(aria, ccm, CCM, AEAD_FLAGS, 192, 8, 96);
/* aria256ccm functions */
IMPLEMENT_aead_cipher(aria, ccm, CCM, AEAD_FLAGS, 256, 8, 96);

View File

@@ -0,0 +1,22 @@
/*
* Copyright 2019-2020 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 "crypto/aria.h"
#include "prov/ciphercommon.h"
#include "prov/ciphercommon_ccm.h"
typedef struct prov_aria_ccm_ctx_st {
PROV_CCM_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
ARIA_KEY ks;
} ks; /* ARIA key schedule to use */
} PROV_ARIA_CCM_CTX;
const PROV_CCM_HW *ossl_prov_aria_hw_ccm(size_t keylen);

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2019-2021 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 support for ARIA CCM.
*/
#include "cipher_aria_ccm.h"
static int ccm_aria_initkey(PROV_CCM_CTX *ctx,
const unsigned char *key, size_t keylen)
{
PROV_ARIA_CCM_CTX *actx = (PROV_ARIA_CCM_CTX *)ctx;
ossl_aria_set_encrypt_key(key, keylen * 8, &actx->ks.ks);
CRYPTO_ccm128_init(&ctx->ccm_ctx, ctx->m, ctx->l, &actx->ks.ks,
(block128_f)ossl_aria_encrypt);
ctx->str = NULL;
ctx->key_set = 1;
return 1;
}
static const PROV_CCM_HW ccm_aria = {
ccm_aria_initkey,
ossl_ccm_generic_setiv,
ossl_ccm_generic_setaad,
ossl_ccm_generic_auth_encrypt,
ossl_ccm_generic_auth_decrypt,
ossl_ccm_generic_gettag
};
const PROV_CCM_HW *ossl_prov_aria_hw_ccm(size_t keybits)
{
return &ccm_aria;
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2019-2023 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 ARIA GCM mode */
#include "cipher_aria_gcm.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
static void *aria_gcm_newctx(void *provctx, size_t keybits)
{
PROV_ARIA_GCM_CTX *ctx;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL)
ossl_gcm_initctx(provctx, &ctx->base, keybits,
ossl_prov_aria_hw_gcm(keybits));
return ctx;
}
static void *aria_gcm_dupctx(void *provctx)
{
PROV_ARIA_GCM_CTX *ctx = provctx;
PROV_ARIA_GCM_CTX *dctx = NULL;
if (ctx == NULL)
return NULL;
dctx = OPENSSL_memdup(ctx, sizeof(*ctx));
if (dctx != NULL && dctx->base.gcm.key != NULL)
dctx->base.gcm.key = &dctx->ks.ks;
return dctx;
}
static OSSL_FUNC_cipher_freectx_fn aria_gcm_freectx;
static void aria_gcm_freectx(void *vctx)
{
PROV_ARIA_GCM_CTX *ctx = (PROV_ARIA_GCM_CTX *)vctx;
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
/* ossl_aria128gcm_functions */
IMPLEMENT_aead_cipher(aria, gcm, GCM, AEAD_FLAGS, 128, 8, 96);
/* ossl_aria192gcm_functions */
IMPLEMENT_aead_cipher(aria, gcm, GCM, AEAD_FLAGS, 192, 8, 96);
/* ossl_aria256gcm_functions */
IMPLEMENT_aead_cipher(aria, gcm, GCM, AEAD_FLAGS, 256, 8, 96);

View File

@@ -0,0 +1,22 @@
/*
* Copyright 2019-2020 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 "crypto/aria.h"
#include "prov/ciphercommon.h"
#include "prov/ciphercommon_gcm.h"
typedef struct prov_aria_gcm_ctx_st {
PROV_GCM_CTX base; /* must be first entry in struct */
union {
OSSL_UNION_ALIGN;
ARIA_KEY ks;
} ks;
} PROV_ARIA_GCM_CTX;
const PROV_GCM_HW *ossl_prov_aria_hw_gcm(size_t keybits);

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2019-2021 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 support for ARIA GCM.
*/
#include "cipher_aria_gcm.h"
static int aria_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
size_t keylen)
{
PROV_ARIA_GCM_CTX *actx = (PROV_ARIA_GCM_CTX *)ctx;
ARIA_KEY *ks = &actx->ks.ks;
GCM_HW_SET_KEY_CTR_FN(ks, ossl_aria_set_encrypt_key, ossl_aria_encrypt, NULL);
return 1;
}
static const PROV_GCM_HW aria_gcm = {
aria_gcm_initkey,
ossl_gcm_setiv,
ossl_gcm_aad_update,
ossl_gcm_cipher_update,
ossl_gcm_cipher_final,
ossl_gcm_one_shot
};
const PROV_GCM_HW *ossl_prov_aria_hw_gcm(size_t keybits)
{
return &aria_gcm;
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2001-2021 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/proverr.h>
#include "cipher_aria.h"
static int cipher_hw_aria_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
{
int ret, mode = dat->mode;
PROV_ARIA_CTX *adat = (PROV_ARIA_CTX *)dat;
ARIA_KEY *ks = &adat->ks.ks;
if (dat->enc || (mode != EVP_CIPH_ECB_MODE && mode != EVP_CIPH_CBC_MODE))
ret = ossl_aria_set_encrypt_key(key, keylen * 8, ks);
else
ret = ossl_aria_set_decrypt_key(key, keylen * 8, ks);
if (ret < 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
return 0;
}
dat->ks = ks;
dat->block = (block128_f)ossl_aria_encrypt;
return 1;
}
IMPLEMENT_CIPHER_HW_COPYCTX(cipher_hw_aria_copyctx, PROV_ARIA_CTX)
# define PROV_CIPHER_HW_aria_mode(mode) \
static const PROV_CIPHER_HW aria_##mode = { \
cipher_hw_aria_initkey, \
ossl_cipher_hw_chunked_##mode, \
cipher_hw_aria_copyctx \
}; \
const PROV_CIPHER_HW *ossl_prov_cipher_hw_aria_##mode(size_t keybits) \
{ \
return &aria_##mode; \
}
PROV_CIPHER_HW_aria_mode(cbc)
PROV_CIPHER_HW_aria_mode(ecb)
PROV_CIPHER_HW_aria_mode(ofb128)
PROV_CIPHER_HW_aria_mode(cfb128)
PROV_CIPHER_HW_aria_mode(cfb1)
PROV_CIPHER_HW_aria_mode(cfb8)
PROV_CIPHER_HW_aria_mode(ctr)

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2019-2021 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 Blowfish cipher modes ecb, cbc, ofb, cfb */
/*
* BF low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_blowfish.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#define BF_FLAGS PROV_CIPHER_FLAG_VARIABLE_LENGTH
static OSSL_FUNC_cipher_freectx_fn blowfish_freectx;
static OSSL_FUNC_cipher_dupctx_fn blowfish_dupctx;
static void blowfish_freectx(void *vctx)
{
PROV_BLOWFISH_CTX *ctx = (PROV_BLOWFISH_CTX *)vctx;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static void *blowfish_dupctx(void *ctx)
{
PROV_BLOWFISH_CTX *in = (PROV_BLOWFISH_CTX *)ctx;
PROV_BLOWFISH_CTX *ret;
if (!ossl_prov_is_running())
return NULL;
ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL)
return NULL;
*ret = *in;
return ret;
}
/* bf_ecb_functions */
IMPLEMENT_var_keylen_cipher(blowfish, BLOWFISH, ecb, ECB, BF_FLAGS, 128, 64, 0, block)
/* bf_cbc_functions */
IMPLEMENT_var_keylen_cipher(blowfish, BLOWFISH, cbc, CBC, BF_FLAGS, 128, 64, 64, block)
/* bf_ofb_functions */
IMPLEMENT_var_keylen_cipher(blowfish, BLOWFISH, ofb64, OFB, BF_FLAGS, 128, 8, 64, stream)
/* bf_cfb_functions */
IMPLEMENT_var_keylen_cipher(blowfish, BLOWFISH, cfb64, CFB, BF_FLAGS, 128, 8, 64, stream)

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2019-2020 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/blowfish.h>
#include "prov/ciphercommon.h"
typedef struct prov_blowfish_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
BF_KEY ks;
} ks;
} PROV_BLOWFISH_CTX;
const PROV_CIPHER_HW *ossl_prov_cipher_hw_blowfish_cbc(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_blowfish_ecb(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_blowfish_ofb64(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_blowfish_cfb64(size_t keybits);

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2019-2020 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
*/
/*
* BF low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_blowfish.h"
static int cipher_hw_blowfish_initkey(PROV_CIPHER_CTX *ctx,
const unsigned char *key, size_t keylen)
{
PROV_BLOWFISH_CTX *bctx = (PROV_BLOWFISH_CTX *)ctx;
BF_set_key(&bctx->ks.ks, keylen, key);
return 1;
}
# define PROV_CIPHER_HW_blowfish_mode(mode, UCMODE) \
IMPLEMENT_CIPHER_HW_##UCMODE(mode, blowfish, PROV_BLOWFISH_CTX, BF_KEY, \
BF_##mode) \
static const PROV_CIPHER_HW bf_##mode = { \
cipher_hw_blowfish_initkey, \
cipher_hw_blowfish_##mode##_cipher \
}; \
const PROV_CIPHER_HW *ossl_prov_cipher_hw_blowfish_##mode(size_t keybits) \
{ \
return &bf_##mode; \
}
PROV_CIPHER_HW_blowfish_mode(cbc, CBC)
PROV_CIPHER_HW_blowfish_mode(ecb, ECB)
PROV_CIPHER_HW_blowfish_mode(ofb64, OFB)
PROV_CIPHER_HW_blowfish_mode(cfb64, CFB)

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2019-2021 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
*/
/*
* Camellia low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
/* Dispatch functions for CAMELLIA cipher modes ecb, cbc, ofb, cfb, ctr */
#include "cipher_camellia.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
static OSSL_FUNC_cipher_freectx_fn camellia_freectx;
static OSSL_FUNC_cipher_dupctx_fn camellia_dupctx;
static void camellia_freectx(void *vctx)
{
PROV_CAMELLIA_CTX *ctx = (PROV_CAMELLIA_CTX *)vctx;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static void *camellia_dupctx(void *ctx)
{
PROV_CAMELLIA_CTX *in = (PROV_CAMELLIA_CTX *)ctx;
PROV_CAMELLIA_CTX *ret;
if (!ossl_prov_is_running())
return NULL;
ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL)
return NULL;
in->base.hw->copyctx(&ret->base, &in->base);
return ret;
}
/* ossl_camellia256ecb_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ecb, ECB, 0, 256, 128, 0, block)
/* ossl_camellia192ecb_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ecb, ECB, 0, 192, 128, 0, block)
/* ossl_camellia128ecb_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ecb, ECB, 0, 128, 128, 0, block)
/* ossl_camellia256cbc_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cbc, CBC, 0, 256, 128, 128, block)
/* ossl_camellia192cbc_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cbc, CBC, 0, 192, 128, 128, block)
/* ossl_camellia128cbc_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cbc, CBC, 0, 128, 128, 128, block)
/* ossl_camellia256ofb_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ofb, OFB, 0, 256, 8, 128, stream)
/* ossl_camellia192ofb_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ofb, OFB, 0, 192, 8, 128, stream)
/* ossl_camellia128ofb_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ofb, OFB, 0, 128, 8, 128, stream)
/* ossl_camellia256cfb_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb, CFB, 0, 256, 8, 128, stream)
/* ossl_camellia192cfb_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb, CFB, 0, 192, 8, 128, stream)
/* ossl_camellia128cfb_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb, CFB, 0, 128, 8, 128, stream)
/* ossl_camellia256cfb1_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb1, CFB, 0, 256, 8, 128, stream)
/* ossl_camellia192cfb1_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb1, CFB, 0, 192, 8, 128, stream)
/* ossl_camellia128cfb1_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb1, CFB, 0, 128, 8, 128, stream)
/* ossl_camellia256cfb8_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb8, CFB, 0, 256, 8, 128, stream)
/* ossl_camellia192cfb8_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb8, CFB, 0, 192, 8, 128, stream)
/* ossl_camellia128cfb8_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb8, CFB, 0, 128, 8, 128, stream)
/* ossl_camellia256ctr_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ctr, CTR, 0, 256, 8, 128, stream)
/* ossl_camellia192ctr_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ctr, CTR, 0, 192, 8, 128, stream)
/* ossl_camellia128ctr_functions */
IMPLEMENT_generic_cipher(camellia, CAMELLIA, ctr, CTR, 0, 128, 8, 128, stream)
#include "cipher_camellia_cts.inc"

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2019-2021 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/camellia.h>
#include "prov/ciphercommon.h"
#include "crypto/cmll_platform.h"
typedef struct prov_camellia_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
CAMELLIA_KEY ks;
} ks;
} PROV_CAMELLIA_CTX;
#define ossl_prov_cipher_hw_camellia_ofb ossl_prov_cipher_hw_camellia_ofb128
#define ossl_prov_cipher_hw_camellia_cfb ossl_prov_cipher_hw_camellia_cfb128
const PROV_CIPHER_HW *ossl_prov_cipher_hw_camellia_ecb(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_camellia_cbc(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_camellia_ofb128(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_camellia_cfb128(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_camellia_cfb1(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_camellia_cfb8(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_camellia_ctr(size_t keybits);

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2021 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 CAMELLIA CBC CTS ciphers */
#include <openssl/proverr.h>
#include "cipher_cts.h"
#define CTS_FLAGS PROV_CIPHER_FLAG_CTS
static OSSL_FUNC_cipher_encrypt_init_fn camellia_cbc_cts_einit;
static OSSL_FUNC_cipher_decrypt_init_fn camellia_cbc_cts_dinit;
static OSSL_FUNC_cipher_get_ctx_params_fn camellia_cbc_cts_get_ctx_params;
static OSSL_FUNC_cipher_set_ctx_params_fn camellia_cbc_cts_set_ctx_params;
static OSSL_FUNC_cipher_gettable_ctx_params_fn camellia_cbc_cts_gettable_ctx_params;
static OSSL_FUNC_cipher_settable_ctx_params_fn camellia_cbc_cts_settable_ctx_params;
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(camellia_cbc_cts)
OSSL_PARAM_utf8_string(OSSL_CIPHER_PARAM_CTS_MODE, NULL, 0),
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(camellia_cbc_cts)
static int camellia_cbc_cts_einit(void *ctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
if (!ossl_cipher_generic_einit(ctx, key, keylen, iv, ivlen, NULL))
return 0;
return camellia_cbc_cts_set_ctx_params(ctx, params);
}
static int camellia_cbc_cts_dinit(void *ctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
if (!ossl_cipher_generic_dinit(ctx, key, keylen, iv, ivlen, NULL))
return 0;
return camellia_cbc_cts_set_ctx_params(ctx, params);
}
static int camellia_cbc_cts_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_CTS_MODE);
if (p != NULL) {
const char *name = ossl_cipher_cbc_cts_mode_id2name(ctx->cts_mode);
if (name == NULL || !OSSL_PARAM_set_utf8_string(p, name)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
}
return ossl_cipher_generic_get_ctx_params(vctx, params);
}
CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(camellia_cbc_cts)
OSSL_PARAM_utf8_string(OSSL_CIPHER_PARAM_CTS_MODE, NULL, 0),
CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(camellia_cbc_cts)
static int camellia_cbc_cts_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
const OSSL_PARAM *p;
int id;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_CTS_MODE);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_UTF8_STRING)
goto err;
id = ossl_cipher_cbc_cts_mode_name2id(p->data);
if (id < 0)
goto err;
ctx->cts_mode = (unsigned int)id;
}
return ossl_cipher_generic_set_ctx_params(vctx, params);
err:
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
/* ossl_camellia256cbc_cts_functions */
IMPLEMENT_cts_cipher(camellia, CAMELLIA, cbc, CBC, CTS_FLAGS, 256, 128, 128, block)
/* ossl_camellia192cbc_cts_functions */
IMPLEMENT_cts_cipher(camellia, CAMELLIA, cbc, CBC, CTS_FLAGS, 192, 128, 128, block)
/* ossl_camellia128cbc_cts_functions */
IMPLEMENT_cts_cipher(camellia, CAMELLIA, cbc, CBC, CTS_FLAGS, 128, 128, 128, block)

View File

@@ -0,0 +1,74 @@
/*
* Copyright 2001-2021 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
*/
/*
* Camellia low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <openssl/camellia.h>
#include <openssl/proverr.h>
#include "cipher_camellia.h"
static int cipher_hw_camellia_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key, size_t keylen)
{
int ret, mode = dat->mode;
PROV_CAMELLIA_CTX *adat = (PROV_CAMELLIA_CTX *)dat;
CAMELLIA_KEY *ks = &adat->ks.ks;
dat->ks = ks;
ret = Camellia_set_key(key, keylen * 8, ks);
if (ret < 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
return 0;
}
if (dat->enc || (mode != EVP_CIPH_ECB_MODE && mode != EVP_CIPH_CBC_MODE)) {
dat->block = (block128_f) Camellia_encrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) Camellia_cbc_encrypt : NULL;
} else {
dat->block = (block128_f) Camellia_decrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) Camellia_cbc_encrypt : NULL;
}
return 1;
}
IMPLEMENT_CIPHER_HW_COPYCTX(cipher_hw_camellia_copyctx, PROV_CAMELLIA_CTX)
# if defined(SPARC_CMLL_CAPABLE)
# include "cipher_camellia_hw_t4.inc"
# else
/* The generic case */
# define PROV_CIPHER_HW_declare(mode)
# define PROV_CIPHER_HW_select(mode)
# endif /* SPARC_CMLL_CAPABLE */
#define PROV_CIPHER_HW_camellia_mode(mode) \
static const PROV_CIPHER_HW camellia_##mode = { \
cipher_hw_camellia_initkey, \
ossl_cipher_hw_generic_##mode, \
cipher_hw_camellia_copyctx \
}; \
PROV_CIPHER_HW_declare(mode) \
const PROV_CIPHER_HW *ossl_prov_cipher_hw_camellia_##mode(size_t keybits) \
{ \
PROV_CIPHER_HW_select(mode) \
return &camellia_##mode; \
}
PROV_CIPHER_HW_camellia_mode(cbc)
PROV_CIPHER_HW_camellia_mode(ecb)
PROV_CIPHER_HW_camellia_mode(ofb128)
PROV_CIPHER_HW_camellia_mode(cfb128)
PROV_CIPHER_HW_camellia_mode(cfb1)
PROV_CIPHER_HW_camellia_mode(cfb8)
PROV_CIPHER_HW_camellia_mode(ctr)

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2001-2021 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 camellia modes.
* This file is included by cipher_camellia_hw.c
*/
static int cipher_hw_camellia_t4_initkey(PROV_CIPHER_CTX *dat,
const unsigned char *key,
size_t keylen)
{
int ret = 0, bits, mode = dat->mode;
PROV_CAMELLIA_CTX *adat = (PROV_CAMELLIA_CTX *)dat;
CAMELLIA_KEY *ks = &adat->ks.ks;
dat->ks = ks;
bits = keylen * 8;
cmll_t4_set_key(key, bits, ks);
if (dat->enc || (mode != EVP_CIPH_ECB_MODE && mode != EVP_CIPH_CBC_MODE)) {
dat->block = (block128_f) cmll_t4_encrypt;
switch (bits) {
case 128:
if (mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f) cmll128_t4_cbc_encrypt;
else if (mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f) cmll128_t4_ctr32_encrypt;
else
dat->stream.cbc = NULL;
break;
case 192:
case 256:
if (mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f) cmll256_t4_cbc_encrypt;
else if (mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f) cmll256_t4_ctr32_encrypt;
else
dat->stream.cbc = NULL;
break;
default:
ret = -1;
break;
}
} else {
dat->block = (block128_f) cmll_t4_decrypt;
switch (bits) {
case 128:
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) cmll128_t4_cbc_decrypt : NULL;
break;
case 192:
case 256:
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) cmll256_t4_cbc_decrypt : NULL;
break;
default:
ret = -1;
break;
}
}
if (ret < 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
#define PROV_CIPHER_HW_declare(mode) \
static const PROV_CIPHER_HW t4_camellia_##mode = { \
cipher_hw_camellia_t4_initkey, \
ossl_cipher_hw_generic_##mode, \
cipher_hw_camellia_copyctx \
};
#define PROV_CIPHER_HW_select(mode) \
if (SPARC_CMLL_CAPABLE) \
return &t4_camellia_##mode;

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2019-2020 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/cast.h>
#include "prov/ciphercommon.h"
typedef struct prov_cast_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
CAST_KEY ks;
} ks;
} PROV_CAST_CTX;
const PROV_CIPHER_HW *ossl_prov_cipher_hw_cast5_cbc(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_cast5_ecb(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_cast5_ofb64(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_cast5_cfb64(size_t keybits);

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2019-2021 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
*/
/*
* CAST low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
/* Dispatch functions for cast cipher modes ecb, cbc, ofb, cfb */
#include <openssl/proverr.h>
#include "cipher_cast.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#define CAST5_FLAGS PROV_CIPHER_FLAG_VARIABLE_LENGTH
static OSSL_FUNC_cipher_freectx_fn cast5_freectx;
static OSSL_FUNC_cipher_dupctx_fn cast5_dupctx;
static void cast5_freectx(void *vctx)
{
PROV_CAST_CTX *ctx = (PROV_CAST_CTX *)vctx;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static void *cast5_dupctx(void *ctx)
{
PROV_CAST_CTX *in = (PROV_CAST_CTX *)ctx;
PROV_CAST_CTX *ret;
if (!ossl_prov_is_running())
return NULL;
ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL)
return NULL;
*ret = *in;
return ret;
}
/* ossl_cast5128ecb_functions */
IMPLEMENT_var_keylen_cipher(cast5, CAST, ecb, ECB, CAST5_FLAGS, 128, 64, 0, block)
/* ossl_cast5128cbc_functions */
IMPLEMENT_var_keylen_cipher(cast5, CAST, cbc, CBC, CAST5_FLAGS, 128, 64, 64, block)
/* ossl_cast5128ofb64_functions */
IMPLEMENT_var_keylen_cipher(cast5, CAST, ofb64, OFB, CAST5_FLAGS, 128, 8, 64, stream)
/* ossl_cast5128cfb64_functions */
IMPLEMENT_var_keylen_cipher(cast5, CAST, cfb64, CFB, CAST5_FLAGS, 128, 8, 64, stream)

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2019-2020 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
*/
/*
* CAST low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include "cipher_cast.h"
static int cipher_hw_cast5_initkey(PROV_CIPHER_CTX *ctx,
const unsigned char *key, size_t keylen)
{
PROV_CAST_CTX *bctx = (PROV_CAST_CTX *)ctx;
CAST_set_key(&(bctx->ks.ks), keylen, key);
return 1;
}
# define PROV_CIPHER_HW_cast_mode(mode, UCMODE) \
IMPLEMENT_CIPHER_HW_##UCMODE(mode, cast5, PROV_CAST_CTX, CAST_KEY, \
CAST_##mode) \
static const PROV_CIPHER_HW cast5_##mode = { \
cipher_hw_cast5_initkey, \
cipher_hw_cast5_##mode##_cipher \
}; \
const PROV_CIPHER_HW *ossl_prov_cipher_hw_cast5_##mode(size_t keybits) \
{ \
return &cast5_##mode; \
}
PROV_CIPHER_HW_cast_mode(cbc, CBC)
PROV_CIPHER_HW_cast_mode(ecb, ECB)
PROV_CIPHER_HW_cast_mode(ofb64, OFB)
PROV_CIPHER_HW_cast_mode(cfb64, CFB)

View File

@@ -0,0 +1,226 @@
/*
* Copyright 2019-2023 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 chacha20 cipher */
#include <openssl/proverr.h>
#include "cipher_chacha20.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#define CHACHA20_KEYLEN (CHACHA_KEY_SIZE)
#define CHACHA20_BLKLEN (1)
#define CHACHA20_IVLEN (CHACHA_CTR_SIZE)
#define CHACHA20_FLAGS (PROV_CIPHER_FLAG_CUSTOM_IV)
static OSSL_FUNC_cipher_newctx_fn chacha20_newctx;
static OSSL_FUNC_cipher_freectx_fn chacha20_freectx;
static OSSL_FUNC_cipher_dupctx_fn chacha20_dupctx;
static OSSL_FUNC_cipher_get_params_fn chacha20_get_params;
static OSSL_FUNC_cipher_get_ctx_params_fn chacha20_get_ctx_params;
static OSSL_FUNC_cipher_set_ctx_params_fn chacha20_set_ctx_params;
static OSSL_FUNC_cipher_gettable_ctx_params_fn chacha20_gettable_ctx_params;
static OSSL_FUNC_cipher_settable_ctx_params_fn chacha20_settable_ctx_params;
#define chacha20_cipher ossl_cipher_generic_cipher
#define chacha20_update ossl_cipher_generic_stream_update
#define chacha20_final ossl_cipher_generic_stream_final
#define chacha20_gettable_params ossl_cipher_generic_gettable_params
void ossl_chacha20_initctx(PROV_CHACHA20_CTX *ctx)
{
ossl_cipher_generic_initkey(ctx, CHACHA20_KEYLEN * 8,
CHACHA20_BLKLEN * 8,
CHACHA20_IVLEN * 8,
0, CHACHA20_FLAGS,
ossl_prov_cipher_hw_chacha20(CHACHA20_KEYLEN * 8),
NULL);
}
static void *chacha20_newctx(void *provctx)
{
PROV_CHACHA20_CTX *ctx;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL)
ossl_chacha20_initctx(ctx);
return ctx;
}
static void chacha20_freectx(void *vctx)
{
PROV_CHACHA20_CTX *ctx = (PROV_CHACHA20_CTX *)vctx;
if (ctx != NULL) {
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
}
static void *chacha20_dupctx(void *vctx)
{
PROV_CHACHA20_CTX *ctx = (PROV_CHACHA20_CTX *)vctx;
PROV_CHACHA20_CTX *dupctx = NULL;
if (ctx != NULL) {
dupctx = OPENSSL_memdup(ctx, sizeof(*dupctx));
if (dupctx != NULL && dupctx->base.tlsmac != NULL && dupctx->base.alloced) {
dupctx->base.tlsmac = OPENSSL_memdup(dupctx->base.tlsmac,
dupctx->base.tlsmacsize);
if (dupctx->base.tlsmac == NULL) {
OPENSSL_free(dupctx);
dupctx = NULL;
}
}
}
return dupctx;
}
static int chacha20_get_params(OSSL_PARAM params[])
{
return ossl_cipher_generic_get_params(params, 0, CHACHA20_FLAGS,
CHACHA20_KEYLEN * 8,
CHACHA20_BLKLEN * 8,
CHACHA20_IVLEN * 8);
}
static int chacha20_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
OSSL_PARAM *p;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, CHACHA20_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, CHACHA20_KEYLEN)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
return 1;
}
static const OSSL_PARAM chacha20_known_gettable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
OSSL_PARAM_END
};
const OSSL_PARAM *chacha20_gettable_ctx_params(ossl_unused void *cctx,
ossl_unused void *provctx)
{
return chacha20_known_gettable_ctx_params;
}
static int chacha20_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
const OSSL_PARAM *p;
size_t len;
if (params == NULL)
return 1;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL) {
if (!OSSL_PARAM_get_size_t(p, &len)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (len != CHACHA20_KEYLEN) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL) {
if (!OSSL_PARAM_get_size_t(p, &len)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (len != CHACHA20_IVLEN) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
}
return 1;
}
static const OSSL_PARAM chacha20_known_settable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
OSSL_PARAM_END
};
const OSSL_PARAM *chacha20_settable_ctx_params(ossl_unused void *cctx,
ossl_unused void *provctx)
{
return chacha20_known_settable_ctx_params;
}
int ossl_chacha20_einit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
int ret;
/* The generic function checks for ossl_prov_is_running() */
ret = ossl_cipher_generic_einit(vctx, key, keylen, iv, ivlen, NULL);
if (ret && iv != NULL) {
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
PROV_CIPHER_HW_CHACHA20 *hw = (PROV_CIPHER_HW_CHACHA20 *)ctx->hw;
hw->initiv(ctx);
}
if (ret && !chacha20_set_ctx_params(vctx, params))
ret = 0;
return ret;
}
int ossl_chacha20_dinit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
int ret;
/* The generic function checks for ossl_prov_is_running() */
ret = ossl_cipher_generic_dinit(vctx, key, keylen, iv, ivlen, NULL);
if (ret && iv != NULL) {
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
PROV_CIPHER_HW_CHACHA20 *hw = (PROV_CIPHER_HW_CHACHA20 *)ctx->hw;
hw->initiv(ctx);
}
if (ret && !chacha20_set_ctx_params(vctx, params))
ret = 0;
return ret;
}
/* ossl_chacha20_functions */
const OSSL_DISPATCH ossl_chacha20_functions[] = {
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))chacha20_newctx },
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))chacha20_freectx },
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))chacha20_dupctx },
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_chacha20_einit },
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_chacha20_dinit },
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))chacha20_update },
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))chacha20_final },
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))chacha20_cipher},
{ OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))chacha20_get_params },
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, (void (*)(void))chacha20_gettable_params },
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))chacha20_get_ctx_params },
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
(void (*)(void))chacha20_gettable_ctx_params },
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (void (*)(void))chacha20_set_ctx_params },
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
(void (*)(void))chacha20_settable_ctx_params },
OSSL_DISPATCH_END
};

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2019-2021 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 "include/crypto/chacha.h"
#include "prov/ciphercommon.h"
typedef struct {
PROV_CIPHER_CTX base; /* must be first */
union {
OSSL_UNION_ALIGN;
unsigned int d[CHACHA_KEY_SIZE / 4];
} key;
unsigned int counter[CHACHA_CTR_SIZE / 4];
unsigned char buf[CHACHA_BLK_SIZE];
unsigned int partial_len;
} PROV_CHACHA20_CTX;
typedef struct prov_cipher_hw_chacha20_st {
PROV_CIPHER_HW base; /* must be first */
int (*initiv)(PROV_CIPHER_CTX *ctx);
} PROV_CIPHER_HW_CHACHA20;
const PROV_CIPHER_HW *ossl_prov_cipher_hw_chacha20(size_t keybits);
OSSL_FUNC_cipher_encrypt_init_fn ossl_chacha20_einit;
OSSL_FUNC_cipher_decrypt_init_fn ossl_chacha20_dinit;
void ossl_chacha20_initctx(PROV_CHACHA20_CTX *ctx);

View File

@@ -0,0 +1,122 @@
/*
* Copyright 2019-2021 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
*/
/* chacha20 cipher implementation */
#include "cipher_chacha20.h"
static int chacha20_initkey(PROV_CIPHER_CTX *bctx, const uint8_t *key,
size_t keylen)
{
PROV_CHACHA20_CTX *ctx = (PROV_CHACHA20_CTX *)bctx;
unsigned int i;
if (key != NULL) {
for (i = 0; i < CHACHA_KEY_SIZE; i += 4)
ctx->key.d[i / 4] = CHACHA_U8TOU32(key + i);
}
ctx->partial_len = 0;
return 1;
}
static int chacha20_initiv(PROV_CIPHER_CTX *bctx)
{
PROV_CHACHA20_CTX *ctx = (PROV_CHACHA20_CTX *)bctx;
unsigned int i;
if (bctx->iv_set) {
for (i = 0; i < CHACHA_CTR_SIZE; i += 4)
ctx->counter[i / 4] = CHACHA_U8TOU32(bctx->oiv + i);
}
ctx->partial_len = 0;
return 1;
}
static int chacha20_cipher(PROV_CIPHER_CTX *bctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
PROV_CHACHA20_CTX *ctx = (PROV_CHACHA20_CTX *)bctx;
unsigned int n, rem, ctr32;
n = ctx->partial_len;
if (n > 0) {
while (inl > 0 && n < CHACHA_BLK_SIZE) {
*out++ = *in++ ^ ctx->buf[n++];
inl--;
}
ctx->partial_len = n;
if (inl == 0)
return 1;
if (n == CHACHA_BLK_SIZE) {
ctx->partial_len = 0;
ctx->counter[0]++;
if (ctx->counter[0] == 0)
ctx->counter[1]++;
}
}
rem = (unsigned int)(inl % CHACHA_BLK_SIZE);
inl -= rem;
ctr32 = ctx->counter[0];
while (inl >= CHACHA_BLK_SIZE) {
size_t blocks = inl / CHACHA_BLK_SIZE;
/*
* 1<<28 is just a not-so-small yet not-so-large number...
* Below condition is practically never met, but it has to
* be checked for code correctness.
*/
if (sizeof(size_t) > sizeof(unsigned int) && blocks > (1U << 28))
blocks = (1U << 28);
/*
* As ChaCha20_ctr32 operates on 32-bit counter, caller
* has to handle overflow. 'if' below detects the
* overflow, which is then handled by limiting the
* amount of blocks to the exact overflow point...
*/
ctr32 += (unsigned int)blocks;
if (ctr32 < blocks) {
blocks -= ctr32;
ctr32 = 0;
}
blocks *= CHACHA_BLK_SIZE;
ChaCha20_ctr32(out, in, blocks, ctx->key.d, ctx->counter);
inl -= blocks;
in += blocks;
out += blocks;
ctx->counter[0] = ctr32;
if (ctr32 == 0) ctx->counter[1]++;
}
if (rem > 0) {
memset(ctx->buf, 0, sizeof(ctx->buf));
ChaCha20_ctr32(ctx->buf, ctx->buf, CHACHA_BLK_SIZE,
ctx->key.d, ctx->counter);
for (n = 0; n < rem; n++)
out[n] = in[n] ^ ctx->buf[n];
ctx->partial_len = rem;
}
return 1;
}
static const PROV_CIPHER_HW_CHACHA20 chacha20_hw = {
{ chacha20_initkey, chacha20_cipher },
chacha20_initiv
};
const PROV_CIPHER_HW *ossl_prov_cipher_hw_chacha20(size_t keybits)
{
return (PROV_CIPHER_HW *)&chacha20_hw;
}

View File

@@ -0,0 +1,367 @@
/*
* Copyright 2019-2025 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 chacha20_poly1305 cipher */
#include <openssl/proverr.h>
#include "cipher_chacha20_poly1305.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#define CHACHA20_POLY1305_KEYLEN CHACHA_KEY_SIZE
#define CHACHA20_POLY1305_BLKLEN 1
#define CHACHA20_POLY1305_MAX_IVLEN 12
#define CHACHA20_POLY1305_MODE 0
#define CHACHA20_POLY1305_FLAGS (PROV_CIPHER_FLAG_AEAD \
| PROV_CIPHER_FLAG_CUSTOM_IV)
static OSSL_FUNC_cipher_newctx_fn chacha20_poly1305_newctx;
static OSSL_FUNC_cipher_freectx_fn chacha20_poly1305_freectx;
static OSSL_FUNC_cipher_dupctx_fn chacha20_poly1305_dupctx;
static OSSL_FUNC_cipher_encrypt_init_fn chacha20_poly1305_einit;
static OSSL_FUNC_cipher_decrypt_init_fn chacha20_poly1305_dinit;
static OSSL_FUNC_cipher_get_params_fn chacha20_poly1305_get_params;
static OSSL_FUNC_cipher_get_ctx_params_fn chacha20_poly1305_get_ctx_params;
static OSSL_FUNC_cipher_set_ctx_params_fn chacha20_poly1305_set_ctx_params;
static OSSL_FUNC_cipher_cipher_fn chacha20_poly1305_cipher;
static OSSL_FUNC_cipher_final_fn chacha20_poly1305_final;
static OSSL_FUNC_cipher_gettable_ctx_params_fn chacha20_poly1305_gettable_ctx_params;
static OSSL_FUNC_cipher_settable_ctx_params_fn chacha20_poly1305_settable_ctx_params;
#define chacha20_poly1305_gettable_params ossl_cipher_generic_gettable_params
#define chacha20_poly1305_update chacha20_poly1305_cipher
static void *chacha20_poly1305_newctx(void *provctx)
{
PROV_CHACHA20_POLY1305_CTX *ctx;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL) {
ossl_cipher_generic_initkey(&ctx->base, CHACHA20_POLY1305_KEYLEN * 8,
CHACHA20_POLY1305_BLKLEN * 8,
CHACHA20_POLY1305_IVLEN * 8,
CHACHA20_POLY1305_MODE,
CHACHA20_POLY1305_FLAGS,
ossl_prov_cipher_hw_chacha20_poly1305(
CHACHA20_POLY1305_KEYLEN * 8),
NULL);
ctx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
ossl_chacha20_initctx(&ctx->chacha);
}
return ctx;
}
static void *chacha20_poly1305_dupctx(void *provctx)
{
PROV_CHACHA20_POLY1305_CTX *ctx = provctx;
PROV_CHACHA20_POLY1305_CTX *dctx = NULL;
if (ctx == NULL)
return NULL;
dctx = OPENSSL_memdup(ctx, sizeof(*ctx));
if (dctx != NULL && dctx->base.tlsmac != NULL && dctx->base.alloced) {
dctx->base.tlsmac = OPENSSL_memdup(dctx->base.tlsmac,
dctx->base.tlsmacsize);
if (dctx->base.tlsmac == NULL) {
OPENSSL_free(dctx);
dctx = NULL;
}
}
return dctx;
}
static void chacha20_poly1305_freectx(void *vctx)
{
PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)vctx;
if (ctx != NULL) {
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
}
static int chacha20_poly1305_get_params(OSSL_PARAM params[])
{
return ossl_cipher_generic_get_params(params, 0, CHACHA20_POLY1305_FLAGS,
CHACHA20_POLY1305_KEYLEN * 8,
CHACHA20_POLY1305_BLKLEN * 8,
CHACHA20_POLY1305_IVLEN * 8);
}
static int chacha20_poly1305_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)vctx;
OSSL_PARAM *p;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL) {
if (!OSSL_PARAM_set_size_t(p, CHACHA20_POLY1305_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, CHACHA20_POLY1305_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 && !OSSL_PARAM_set_size_t(p, ctx->tag_len)) {
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 (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
if (!ctx->base.enc) {
ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_SET);
return 0;
}
if (p->data_size == 0 || p->data_size > POLY1305_BLOCK_SIZE) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH);
return 0;
}
memcpy(p->data, ctx->tag, p->data_size);
}
return 1;
}
static const OSSL_PARAM chacha20_poly1305_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_AEAD_TAG, NULL, 0),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL),
OSSL_PARAM_END
};
static const OSSL_PARAM *chacha20_poly1305_gettable_ctx_params
(ossl_unused void *cctx, ossl_unused void *provctx)
{
return chacha20_poly1305_known_gettable_ctx_params;
}
static const OSSL_PARAM chacha20_poly1305_known_settable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_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
};
static const OSSL_PARAM *chacha20_poly1305_settable_ctx_params(
ossl_unused void *cctx, ossl_unused void *provctx
)
{
return chacha20_poly1305_known_settable_ctx_params;
}
static int chacha20_poly1305_set_ctx_params(void *vctx,
const OSSL_PARAM params[])
{
const OSSL_PARAM *p;
size_t len;
PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)vctx;
PROV_CIPHER_HW_CHACHA20_POLY1305 *hw =
(PROV_CIPHER_HW_CHACHA20_POLY1305 *)ctx->base.hw;
if (params == NULL)
return 1;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL) {
if (!OSSL_PARAM_get_size_t(p, &len)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (len != CHACHA20_POLY1305_KEYLEN) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL) {
if (!OSSL_PARAM_get_size_t(p, &len)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (len != CHACHA20_POLY1305_MAX_IVLEN) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
}
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 == 0 || p->data_size > POLY1305_BLOCK_SIZE) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG_LENGTH);
return 0;
}
if (p->data != NULL) {
if (ctx->base.enc) {
ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_NEEDED);
return 0;
}
memcpy(ctx->tag, p->data, p->data_size);
}
ctx->tag_len = p->data_size;
}
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;
}
len = hw->tls_init(&ctx->base, p->data, p->data_size);
if (len == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA);
return 0;
}
ctx->tls_aad_pad_sz = len;
}
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 (hw->tls_iv_set_fixed(&ctx->base, p->data, p->data_size) == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
}
return 1;
}
static int chacha20_poly1305_einit(void *vctx, const unsigned char *key,
size_t keylen, const unsigned char *iv,
size_t ivlen, const OSSL_PARAM params[])
{
int ret;
/* The generic function checks for ossl_prov_is_running() */
ret = ossl_cipher_generic_einit(vctx, key, keylen, iv, ivlen, NULL);
if (ret && iv != NULL) {
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
PROV_CIPHER_HW_CHACHA20_POLY1305 *hw =
(PROV_CIPHER_HW_CHACHA20_POLY1305 *)ctx->hw;
hw->initiv(ctx);
}
if (ret && !chacha20_poly1305_set_ctx_params(vctx, params))
ret = 0;
return ret;
}
static int chacha20_poly1305_dinit(void *vctx, const unsigned char *key,
size_t keylen, const unsigned char *iv,
size_t ivlen, const OSSL_PARAM params[])
{
int ret;
/* The generic function checks for ossl_prov_is_running() */
ret = ossl_cipher_generic_dinit(vctx, key, keylen, iv, ivlen, NULL);
if (ret && iv != NULL) {
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
PROV_CIPHER_HW_CHACHA20_POLY1305 *hw =
(PROV_CIPHER_HW_CHACHA20_POLY1305 *)ctx->hw;
hw->initiv(ctx);
}
if (ret && !chacha20_poly1305_set_ctx_params(vctx, params))
ret = 0;
return ret;
}
static int chacha20_poly1305_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;
PROV_CIPHER_HW_CHACHA20_POLY1305 *hw =
(PROV_CIPHER_HW_CHACHA20_POLY1305 *)ctx->hw;
if (!ossl_prov_is_running())
return 0;
if (inl == 0) {
*outl = 0;
return 1;
}
if (outsize < inl) {
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (!hw->aead_cipher(ctx, out, outl, in, inl))
return 0;
return 1;
}
static int chacha20_poly1305_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
PROV_CIPHER_HW_CHACHA20_POLY1305 *hw =
(PROV_CIPHER_HW_CHACHA20_POLY1305 *)ctx->hw;
if (!ossl_prov_is_running())
return 0;
if (hw->aead_cipher(ctx, out, outl, NULL, 0) <= 0)
return 0;
*outl = 0;
return 1;
}
/* ossl_chacha20_ossl_poly1305_functions */
const OSSL_DISPATCH ossl_chacha20_ossl_poly1305_functions[] = {
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))chacha20_poly1305_newctx },
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))chacha20_poly1305_freectx },
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))chacha20_poly1305_dupctx },
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))chacha20_poly1305_einit },
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))chacha20_poly1305_dinit },
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))chacha20_poly1305_update },
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))chacha20_poly1305_final },
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))chacha20_poly1305_cipher },
{ OSSL_FUNC_CIPHER_GET_PARAMS,
(void (*)(void))chacha20_poly1305_get_params },
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS,
(void (*)(void))chacha20_poly1305_gettable_params },
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS,
(void (*)(void))chacha20_poly1305_get_ctx_params },
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
(void (*)(void))chacha20_poly1305_gettable_ctx_params },
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS,
(void (*)(void))chacha20_poly1305_set_ctx_params },
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
(void (*)(void))chacha20_poly1305_settable_ctx_params },
OSSL_DISPATCH_END
};

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2019-2023 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 chacha20_poly1305 cipher */
#include "include/crypto/poly1305.h"
#include "cipher_chacha20.h"
#define NO_TLS_PAYLOAD_LENGTH ((size_t)-1)
#define CHACHA20_POLY1305_IVLEN 12
typedef struct {
PROV_CIPHER_CTX base; /* must be first */
PROV_CHACHA20_CTX chacha;
POLY1305 poly1305;
unsigned int nonce[12 / 4];
unsigned char tag[POLY1305_BLOCK_SIZE];
unsigned char tls_aad[POLY1305_BLOCK_SIZE];
struct { uint64_t aad, text; } len;
unsigned int aad : 1;
unsigned int mac_inited : 1;
size_t tag_len;
size_t tls_payload_length;
size_t tls_aad_pad_sz;
} PROV_CHACHA20_POLY1305_CTX;
typedef struct prov_cipher_hw_chacha_aead_st {
PROV_CIPHER_HW base; /* must be first */
int (*aead_cipher)(PROV_CIPHER_CTX *dat, unsigned char *out, size_t *outl,
const unsigned char *in, size_t len);
int (*initiv)(PROV_CIPHER_CTX *ctx);
int (*tls_init)(PROV_CIPHER_CTX *ctx, unsigned char *aad, size_t alen);
int (*tls_iv_set_fixed)(PROV_CIPHER_CTX *ctx, unsigned char *fixed,
size_t flen);
} PROV_CIPHER_HW_CHACHA20_POLY1305;
const PROV_CIPHER_HW *ossl_prov_cipher_hw_chacha20_poly1305(size_t keybits);

View File

@@ -0,0 +1,412 @@
/*
* Copyright 2019-2024 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
*/
/* chacha20_poly1305 cipher implementation */
#include "internal/endian.h"
#include "cipher_chacha20_poly1305.h"
static int chacha_poly1305_tls_init(PROV_CIPHER_CTX *bctx,
unsigned char *aad, size_t alen)
{
unsigned int len;
PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)bctx;
if (alen != EVP_AEAD_TLS1_AAD_LEN)
return 0;
memcpy(ctx->tls_aad, aad, EVP_AEAD_TLS1_AAD_LEN);
len = aad[EVP_AEAD_TLS1_AAD_LEN - 2] << 8 | aad[EVP_AEAD_TLS1_AAD_LEN - 1];
aad = ctx->tls_aad;
if (!bctx->enc) {
if (len < POLY1305_BLOCK_SIZE)
return 0;
len -= POLY1305_BLOCK_SIZE; /* discount attached tag */
aad[EVP_AEAD_TLS1_AAD_LEN - 2] = (unsigned char)(len >> 8);
aad[EVP_AEAD_TLS1_AAD_LEN - 1] = (unsigned char)len;
}
ctx->tls_payload_length = len;
/* merge record sequence number as per RFC7905 */
ctx->chacha.counter[1] = ctx->nonce[0];
ctx->chacha.counter[2] = ctx->nonce[1] ^ CHACHA_U8TOU32(aad);
ctx->chacha.counter[3] = ctx->nonce[2] ^ CHACHA_U8TOU32(aad+4);
ctx->mac_inited = 0;
return POLY1305_BLOCK_SIZE; /* tag length */
}
static int chacha_poly1305_tls_iv_set_fixed(PROV_CIPHER_CTX *bctx,
unsigned char *fixed, size_t flen)
{
PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)bctx;
if (flen != CHACHA20_POLY1305_IVLEN)
return 0;
ctx->nonce[0] = ctx->chacha.counter[1] = CHACHA_U8TOU32(fixed);
ctx->nonce[1] = ctx->chacha.counter[2] = CHACHA_U8TOU32(fixed + 4);
ctx->nonce[2] = ctx->chacha.counter[3] = CHACHA_U8TOU32(fixed + 8);
return 1;
}
static int chacha20_poly1305_initkey(PROV_CIPHER_CTX *bctx,
const unsigned char *key, size_t keylen)
{
PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)bctx;
ctx->len.aad = 0;
ctx->len.text = 0;
ctx->aad = 0;
ctx->mac_inited = 0;
ctx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
if (bctx->enc)
return ossl_chacha20_einit(&ctx->chacha, key, keylen, NULL, 0, NULL);
else
return ossl_chacha20_dinit(&ctx->chacha, key, keylen, NULL, 0, NULL);
}
static int chacha20_poly1305_initiv(PROV_CIPHER_CTX *bctx)
{
PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)bctx;
unsigned char tempiv[CHACHA_CTR_SIZE] = { 0 };
int ret = 1;
size_t noncelen = CHACHA20_POLY1305_IVLEN;
ctx->len.aad = 0;
ctx->len.text = 0;
ctx->aad = 0;
ctx->mac_inited = 0;
ctx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
/* pad on the left */
memcpy(tempiv + CHACHA_CTR_SIZE - noncelen, bctx->oiv,
noncelen);
if (bctx->enc)
ret = ossl_chacha20_einit(&ctx->chacha, NULL, 0,
tempiv, sizeof(tempiv), NULL);
else
ret = ossl_chacha20_dinit(&ctx->chacha, NULL, 0,
tempiv, sizeof(tempiv), NULL);
ctx->nonce[0] = ctx->chacha.counter[1];
ctx->nonce[1] = ctx->chacha.counter[2];
ctx->nonce[2] = ctx->chacha.counter[3];
bctx->iv_set = 1;
return ret;
}
#if !defined(OPENSSL_SMALL_FOOTPRINT)
# if defined(POLY1305_ASM) && (defined(__x86_64) || defined(__x86_64__) \
|| defined(_M_AMD64) || defined(_M_X64))
# define XOR128_HELPERS
void *xor128_encrypt_n_pad(void *out, const void *inp, void *otp, size_t len);
void *xor128_decrypt_n_pad(void *out, const void *inp, void *otp, size_t len);
static const unsigned char zero[4 * CHACHA_BLK_SIZE] = { 0 };
# else
static const unsigned char zero[2 * CHACHA_BLK_SIZE] = { 0 };
# endif
static int chacha20_poly1305_tls_cipher(PROV_CIPHER_CTX *bctx,
unsigned char *out,
size_t *out_padlen,
const unsigned char *in, size_t len)
{
PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)bctx;
POLY1305 *poly = &ctx->poly1305;
size_t tail, tohash_len, buf_len, plen = ctx->tls_payload_length;
unsigned char *buf, *tohash, *ctr, storage[sizeof(zero) + 32];
DECLARE_IS_ENDIAN;
buf = storage + ((0 - (size_t)storage) & 15); /* align */
ctr = buf + CHACHA_BLK_SIZE;
tohash = buf + CHACHA_BLK_SIZE - POLY1305_BLOCK_SIZE;
# ifdef XOR128_HELPERS
if (plen <= 3 * CHACHA_BLK_SIZE) {
ctx->chacha.counter[0] = 0;
buf_len = (plen + 2 * CHACHA_BLK_SIZE - 1) & (0 - CHACHA_BLK_SIZE);
ChaCha20_ctr32(buf, zero, buf_len, ctx->chacha.key.d, ctx->chacha.counter);
Poly1305_Init(poly, buf);
ctx->chacha.partial_len = 0;
memcpy(tohash, ctx->tls_aad, POLY1305_BLOCK_SIZE);
tohash_len = POLY1305_BLOCK_SIZE;
ctx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
ctx->len.text = plen;
if (plen) {
if (bctx->enc)
ctr = xor128_encrypt_n_pad(out, in, ctr, plen);
else
ctr = xor128_decrypt_n_pad(out, in, ctr, plen);
in += plen;
out += plen;
tohash_len = (size_t)(ctr - tohash);
}
}
# else
if (plen <= CHACHA_BLK_SIZE) {
size_t i;
ctx->chacha.counter[0] = 0;
ChaCha20_ctr32(buf, zero, (buf_len = 2 * CHACHA_BLK_SIZE),
ctx->chacha.key.d, ctx->chacha.counter);
Poly1305_Init(poly, buf);
ctx->chacha.partial_len = 0;
memcpy(tohash, ctx->tls_aad, POLY1305_BLOCK_SIZE);
tohash_len = POLY1305_BLOCK_SIZE;
ctx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
ctx->len.text = plen;
if (bctx->enc) {
for (i = 0; i < plen; i++)
out[i] = ctr[i] ^= in[i];
} else {
for (i = 0; i < plen; i++) {
unsigned char c = in[i];
out[i] = ctr[i] ^ c;
ctr[i] = c;
}
}
in += i;
out += i;
tail = (0 - i) & (POLY1305_BLOCK_SIZE - 1);
memset(ctr + i, 0, tail);
ctr += i + tail;
tohash_len += i + tail;
}
# endif
else {
ctx->chacha.counter[0] = 0;
ChaCha20_ctr32(buf, zero, (buf_len = CHACHA_BLK_SIZE),
ctx->chacha.key.d, ctx->chacha.counter);
Poly1305_Init(poly, buf);
ctx->chacha.counter[0] = 1;
ctx->chacha.partial_len = 0;
Poly1305_Update(poly, ctx->tls_aad, POLY1305_BLOCK_SIZE);
tohash = ctr;
tohash_len = 0;
ctx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
ctx->len.text = plen;
if (bctx->enc) {
ChaCha20_ctr32(out, in, plen, ctx->chacha.key.d, ctx->chacha.counter);
Poly1305_Update(poly, out, plen);
} else {
Poly1305_Update(poly, in, plen);
ChaCha20_ctr32(out, in, plen, ctx->chacha.key.d, ctx->chacha.counter);
}
in += plen;
out += plen;
tail = (0 - plen) & (POLY1305_BLOCK_SIZE - 1);
Poly1305_Update(poly, zero, tail);
}
if (IS_LITTLE_ENDIAN) {
memcpy(ctr, (unsigned char *)&ctx->len, POLY1305_BLOCK_SIZE);
} else {
ctr[0] = (unsigned char)(ctx->len.aad);
ctr[1] = (unsigned char)(ctx->len.aad>>8);
ctr[2] = (unsigned char)(ctx->len.aad>>16);
ctr[3] = (unsigned char)(ctx->len.aad>>24);
ctr[4] = (unsigned char)(ctx->len.aad>>32);
ctr[5] = (unsigned char)(ctx->len.aad>>40);
ctr[6] = (unsigned char)(ctx->len.aad>>48);
ctr[7] = (unsigned char)(ctx->len.aad>>56);
ctr[8] = (unsigned char)(ctx->len.text);
ctr[9] = (unsigned char)(ctx->len.text>>8);
ctr[10] = (unsigned char)(ctx->len.text>>16);
ctr[11] = (unsigned char)(ctx->len.text>>24);
ctr[12] = (unsigned char)(ctx->len.text>>32);
ctr[13] = (unsigned char)(ctx->len.text>>40);
ctr[14] = (unsigned char)(ctx->len.text>>48);
ctr[15] = (unsigned char)(ctx->len.text>>56);
}
tohash_len += POLY1305_BLOCK_SIZE;
Poly1305_Update(poly, tohash, tohash_len);
OPENSSL_cleanse(buf, buf_len);
Poly1305_Final(poly, bctx->enc ? ctx->tag : tohash);
ctx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
if (bctx->enc) {
memcpy(out, ctx->tag, POLY1305_BLOCK_SIZE);
} else {
if (CRYPTO_memcmp(tohash, in, POLY1305_BLOCK_SIZE)) {
if (len > POLY1305_BLOCK_SIZE)
memset(out - (len - POLY1305_BLOCK_SIZE), 0,
len - POLY1305_BLOCK_SIZE);
return 0;
}
/* Strip the tag */
len -= POLY1305_BLOCK_SIZE;
}
*out_padlen = len;
return 1;
}
#else
static const unsigned char zero[CHACHA_BLK_SIZE] = { 0 };
#endif /* OPENSSL_SMALL_FOOTPRINT */
static int chacha20_poly1305_aead_cipher(PROV_CIPHER_CTX *bctx,
unsigned char *out, size_t *outl,
const unsigned char *in, size_t inl)
{
PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)bctx;
POLY1305 *poly = &ctx->poly1305;
size_t rem, plen = ctx->tls_payload_length;
size_t olen = 0;
int rv = 0;
DECLARE_IS_ENDIAN;
if (!ctx->mac_inited) {
if (plen != NO_TLS_PAYLOAD_LENGTH && out != NULL) {
if (inl != plen + POLY1305_BLOCK_SIZE)
return 0;
#if !defined(OPENSSL_SMALL_FOOTPRINT)
return chacha20_poly1305_tls_cipher(bctx, out, outl, in, inl);
#endif
}
ctx->chacha.counter[0] = 0;
ChaCha20_ctr32(ctx->chacha.buf, zero, CHACHA_BLK_SIZE,
ctx->chacha.key.d, ctx->chacha.counter);
Poly1305_Init(poly, ctx->chacha.buf);
ctx->chacha.counter[0] = 1;
ctx->chacha.partial_len = 0;
ctx->len.aad = ctx->len.text = 0;
ctx->mac_inited = 1;
if (plen != NO_TLS_PAYLOAD_LENGTH) {
Poly1305_Update(poly, ctx->tls_aad, EVP_AEAD_TLS1_AAD_LEN);
ctx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
ctx->aad = 1;
}
}
if (in != NULL) { /* aad or text */
if (out == NULL) { /* aad */
Poly1305_Update(poly, in, inl);
ctx->len.aad += inl;
ctx->aad = 1;
goto finish;
} else { /* plain- or ciphertext */
if (ctx->aad) { /* wrap up aad */
if ((rem = (size_t)ctx->len.aad % POLY1305_BLOCK_SIZE))
Poly1305_Update(poly, zero, POLY1305_BLOCK_SIZE - rem);
ctx->aad = 0;
}
ctx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
if (plen == NO_TLS_PAYLOAD_LENGTH)
plen = inl;
else if (inl != plen + POLY1305_BLOCK_SIZE)
goto err;
if (bctx->enc) { /* plaintext */
ctx->chacha.base.hw->cipher(&ctx->chacha.base, out, in, plen);
Poly1305_Update(poly, out, plen);
in += plen;
out += plen;
ctx->len.text += plen;
} else { /* ciphertext */
Poly1305_Update(poly, in, plen);
ctx->chacha.base.hw->cipher(&ctx->chacha.base, out, in, plen);
in += plen;
out += plen;
ctx->len.text += plen;
}
}
}
/* explicit final, or tls mode */
if (in == NULL || inl != plen) {
unsigned char temp[POLY1305_BLOCK_SIZE];
if (ctx->aad) { /* wrap up aad */
if ((rem = (size_t)ctx->len.aad % POLY1305_BLOCK_SIZE))
Poly1305_Update(poly, zero, POLY1305_BLOCK_SIZE - rem);
ctx->aad = 0;
}
if ((rem = (size_t)ctx->len.text % POLY1305_BLOCK_SIZE))
Poly1305_Update(poly, zero, POLY1305_BLOCK_SIZE - rem);
if (IS_LITTLE_ENDIAN) {
Poly1305_Update(poly, (unsigned char *)&ctx->len,
POLY1305_BLOCK_SIZE);
} else {
temp[0] = (unsigned char)(ctx->len.aad);
temp[1] = (unsigned char)(ctx->len.aad>>8);
temp[2] = (unsigned char)(ctx->len.aad>>16);
temp[3] = (unsigned char)(ctx->len.aad>>24);
temp[4] = (unsigned char)(ctx->len.aad>>32);
temp[5] = (unsigned char)(ctx->len.aad>>40);
temp[6] = (unsigned char)(ctx->len.aad>>48);
temp[7] = (unsigned char)(ctx->len.aad>>56);
temp[8] = (unsigned char)(ctx->len.text);
temp[9] = (unsigned char)(ctx->len.text>>8);
temp[10] = (unsigned char)(ctx->len.text>>16);
temp[11] = (unsigned char)(ctx->len.text>>24);
temp[12] = (unsigned char)(ctx->len.text>>32);
temp[13] = (unsigned char)(ctx->len.text>>40);
temp[14] = (unsigned char)(ctx->len.text>>48);
temp[15] = (unsigned char)(ctx->len.text>>56);
Poly1305_Update(poly, temp, POLY1305_BLOCK_SIZE);
}
Poly1305_Final(poly, bctx->enc ? ctx->tag : temp);
ctx->mac_inited = 0;
if (in != NULL && inl != plen) {
if (bctx->enc) {
memcpy(out, ctx->tag, POLY1305_BLOCK_SIZE);
} else {
if (CRYPTO_memcmp(temp, in, POLY1305_BLOCK_SIZE)) {
memset(out - plen, 0, plen);
goto err;
}
/* Strip the tag */
inl -= POLY1305_BLOCK_SIZE;
}
}
else if (!bctx->enc) {
if (CRYPTO_memcmp(temp, ctx->tag, ctx->tag_len))
goto err;
}
}
finish:
olen = inl;
rv = 1;
err:
*outl = olen;
return rv;
}
static const PROV_CIPHER_HW_CHACHA20_POLY1305 chacha20poly1305_hw = {
{ chacha20_poly1305_initkey, NULL },
chacha20_poly1305_aead_cipher,
chacha20_poly1305_initiv,
chacha_poly1305_tls_init,
chacha_poly1305_tls_iv_set_fixed
};
const PROV_CIPHER_HW *ossl_prov_cipher_hw_chacha20_poly1305(size_t keybits)
{
return (PROV_CIPHER_HW *)&chacha20poly1305_hw;
}

View File

@@ -0,0 +1,377 @@
/*
* Copyright 2020-2024 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
*/
/*
* Helper functions for 128 bit CBC CTS ciphers (Currently AES and Camellia).
*
* The function dispatch tables are embedded into cipher_aes.c
* and cipher_camellia.c using cipher_aes_cts.inc and cipher_camellia_cts.inc
*/
/*
* Refer to SP800-38A-Addendum
*
* Ciphertext stealing encrypts plaintext using a block cipher, without padding
* the message to a multiple of the block size, so the ciphertext is the same
* size as the plaintext.
* It does this by altering processing of the last two blocks of the message.
* The processing of all but the last two blocks is unchanged, but a portion of
* the second-last block's ciphertext is "stolen" to pad the last plaintext
* block. The padded final block is then encrypted as usual.
* The final ciphertext for the last two blocks, consists of the partial block
* (with the "stolen" portion omitted) plus the full final block,
* which are the same size as the original plaintext.
* Decryption requires decrypting the final block first, then restoring the
* stolen ciphertext to the partial block, which can then be decrypted as usual.
* AES_CBC_CTS has 3 variants:
* (1) CS1 The NIST variant.
* If the length is a multiple of the blocksize it is the same as CBC mode.
* otherwise it produces C1||C2||(C(n-1))*||Cn.
* Where C(n-1)* is a partial block.
* (2) CS2
* If the length is a multiple of the blocksize it is the same as CBC mode.
* otherwise it produces C1||C2||Cn||(C(n-1))*.
* Where C(n-1)* is a partial block.
* (3) CS3 The Kerberos5 variant.
* Produces C1||C2||Cn||(C(n-1))* regardless of the length.
* If the length is a multiple of the blocksize it looks similar to CBC mode
* with the last 2 blocks swapped.
* Otherwise it is the same as CS2.
*/
#include <openssl/core_names.h>
#include "prov/ciphercommon.h"
#include "internal/nelem.h"
#include "cipher_cts.h"
/* The value assigned to 0 is the default */
#define CTS_CS1 0
#define CTS_CS2 1
#define CTS_CS3 2
#define CTS_BLOCK_SIZE 16
typedef union {
size_t align;
unsigned char c[CTS_BLOCK_SIZE];
} aligned_16bytes;
typedef struct cts_mode_name2id_st {
unsigned int id;
const char *name;
} CTS_MODE_NAME2ID;
static CTS_MODE_NAME2ID cts_modes[] = {
{ CTS_CS1, OSSL_CIPHER_CTS_MODE_CS1 },
{ CTS_CS2, OSSL_CIPHER_CTS_MODE_CS2 },
{ CTS_CS3, OSSL_CIPHER_CTS_MODE_CS3 },
};
const char *ossl_cipher_cbc_cts_mode_id2name(unsigned int id)
{
size_t i;
for (i = 0; i < OSSL_NELEM(cts_modes); ++i) {
if (cts_modes[i].id == id)
return cts_modes[i].name;
}
return NULL;
}
int ossl_cipher_cbc_cts_mode_name2id(const char *name)
{
size_t i;
for (i = 0; i < OSSL_NELEM(cts_modes); ++i) {
if (OPENSSL_strcasecmp(name, cts_modes[i].name) == 0)
return (int)cts_modes[i].id;
}
return -1;
}
static size_t cts128_cs1_encrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
unsigned char *out, size_t len)
{
aligned_16bytes tmp_in;
size_t residue;
residue = len % CTS_BLOCK_SIZE;
len -= residue;
if (!ctx->hw->cipher(ctx, out, in, len))
return 0;
if (residue == 0)
return len;
in += len;
out += len;
memset(tmp_in.c, 0, sizeof(tmp_in));
memcpy(tmp_in.c, in, residue);
if (!ctx->hw->cipher(ctx, out - CTS_BLOCK_SIZE + residue, tmp_in.c,
CTS_BLOCK_SIZE))
return 0;
return len + residue;
}
static void do_xor(const unsigned char *in1, const unsigned char *in2,
size_t len, unsigned char *out)
{
size_t i;
for (i = 0; i < len; ++i)
out[i] = in1[i] ^ in2[i];
}
static size_t cts128_cs1_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
unsigned char *out, size_t len)
{
aligned_16bytes mid_iv, ct_mid, cn, pt_last;
size_t residue;
residue = len % CTS_BLOCK_SIZE;
if (residue == 0) {
/* If there are no partial blocks then it is the same as CBC mode */
if (!ctx->hw->cipher(ctx, out, in, len))
return 0;
return len;
}
/* Process blocks at the start - but leave the last 2 blocks */
len -= CTS_BLOCK_SIZE + residue;
if (len > 0) {
if (!ctx->hw->cipher(ctx, out, in, len))
return 0;
in += len;
out += len;
}
/* Save the iv that will be used by the second last block */
memcpy(mid_iv.c, ctx->iv, CTS_BLOCK_SIZE);
/* Save the C(n) block */
memcpy(cn.c, in + residue, CTS_BLOCK_SIZE);
/* Decrypt the last block first using an iv of zero */
memset(ctx->iv, 0, CTS_BLOCK_SIZE);
if (!ctx->hw->cipher(ctx, pt_last.c, in + residue, CTS_BLOCK_SIZE))
return 0;
/*
* Rebuild the ciphertext of the second last block as a combination of
* the decrypted last block + replace the start with the ciphertext bytes
* of the partial second last block.
*/
memcpy(ct_mid.c, in, residue);
memcpy(ct_mid.c + residue, pt_last.c + residue, CTS_BLOCK_SIZE - residue);
/*
* Restore the last partial ciphertext block.
* Now that we have the cipher text of the second last block, apply
* that to the partial plaintext end block. We have already decrypted the
* block using an IV of zero. For decryption the IV is just XORed after
* doing an Cipher CBC block - so just XOR in the cipher text.
*/
do_xor(ct_mid.c, pt_last.c, residue, out + CTS_BLOCK_SIZE);
/* Restore the iv needed by the second last block */
memcpy(ctx->iv, mid_iv.c, CTS_BLOCK_SIZE);
/*
* Decrypt the second last plaintext block now that we have rebuilt the
* ciphertext.
*/
if (!ctx->hw->cipher(ctx, out, ct_mid.c, CTS_BLOCK_SIZE))
return 0;
/* The returned iv is the C(n) block */
memcpy(ctx->iv, cn.c, CTS_BLOCK_SIZE);
return len + CTS_BLOCK_SIZE + residue;
}
static size_t cts128_cs3_encrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
unsigned char *out, size_t len)
{
aligned_16bytes tmp_in;
size_t residue;
if (len < CTS_BLOCK_SIZE) /* CS3 requires at least one block */
return 0;
/* If we only have one block then just process the aligned block */
if (len == CTS_BLOCK_SIZE)
return ctx->hw->cipher(ctx, out, in, len) ? len : 0;
residue = len % CTS_BLOCK_SIZE;
if (residue == 0)
residue = CTS_BLOCK_SIZE;
len -= residue;
if (!ctx->hw->cipher(ctx, out, in, len))
return 0;
in += len;
out += len;
memset(tmp_in.c, 0, sizeof(tmp_in));
memcpy(tmp_in.c, in, residue);
memcpy(out, out - CTS_BLOCK_SIZE, residue);
if (!ctx->hw->cipher(ctx, out - CTS_BLOCK_SIZE, tmp_in.c, CTS_BLOCK_SIZE))
return 0;
return len + residue;
}
/*
* Note:
* The cipher text (in) is of the form C(0), C(1), ., C(n), C(n-1)* where
* C(n) is a full block and C(n-1)* can be a partial block
* (but could be a full block).
* This means that the output plaintext (out) needs to swap the plaintext of
* the last two decoded ciphertext blocks.
*/
static size_t cts128_cs3_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
unsigned char *out, size_t len)
{
aligned_16bytes mid_iv, ct_mid, cn, pt_last;
size_t residue;
if (len < CTS_BLOCK_SIZE) /* CS3 requires at least one block */
return 0;
/* If we only have one block then just process the aligned block */
if (len == CTS_BLOCK_SIZE)
return ctx->hw->cipher(ctx, out, in, len) ? len : 0;
/* Process blocks at the start - but leave the last 2 blocks */
residue = len % CTS_BLOCK_SIZE;
if (residue == 0)
residue = CTS_BLOCK_SIZE;
len -= CTS_BLOCK_SIZE + residue;
if (len > 0) {
if (!ctx->hw->cipher(ctx, out, in, len))
return 0;
in += len;
out += len;
}
/* Save the iv that will be used by the second last block */
memcpy(mid_iv.c, ctx->iv, CTS_BLOCK_SIZE);
/* Save the C(n) block : For CS3 it is C(1)||...||C(n-2)||C(n)||C(n-1)* */
memcpy(cn.c, in, CTS_BLOCK_SIZE);
/* Decrypt the C(n) block first using an iv of zero */
memset(ctx->iv, 0, CTS_BLOCK_SIZE);
if (!ctx->hw->cipher(ctx, pt_last.c, in, CTS_BLOCK_SIZE))
return 0;
/*
* Rebuild the ciphertext of C(n-1) as a combination of
* the decrypted C(n) block + replace the start with the ciphertext bytes
* of the partial last block.
*/
memcpy(ct_mid.c, in + CTS_BLOCK_SIZE, residue);
if (residue != CTS_BLOCK_SIZE)
memcpy(ct_mid.c + residue, pt_last.c + residue, CTS_BLOCK_SIZE - residue);
/*
* Restore the last partial ciphertext block.
* Now that we have the cipher text of the second last block, apply
* that to the partial plaintext end block. We have already decrypted the
* block using an IV of zero. For decryption the IV is just XORed after
* doing an AES block - so just XOR in the ciphertext.
*/
do_xor(ct_mid.c, pt_last.c, residue, out + CTS_BLOCK_SIZE);
/* Restore the iv needed by the second last block */
memcpy(ctx->iv, mid_iv.c, CTS_BLOCK_SIZE);
/*
* Decrypt the second last plaintext block now that we have rebuilt the
* ciphertext.
*/
if (!ctx->hw->cipher(ctx, out, ct_mid.c, CTS_BLOCK_SIZE))
return 0;
/* The returned iv is the C(n) block */
memcpy(ctx->iv, cn.c, CTS_BLOCK_SIZE);
return len + CTS_BLOCK_SIZE + residue;
}
static size_t cts128_cs2_encrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
unsigned char *out, size_t len)
{
if (len % CTS_BLOCK_SIZE == 0) {
/* If there are no partial blocks then it is the same as CBC mode */
if (!ctx->hw->cipher(ctx, out, in, len))
return 0;
return len;
}
/* For partial blocks CS2 is equivalent to CS3 */
return cts128_cs3_encrypt(ctx, in, out, len);
}
static size_t cts128_cs2_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
unsigned char *out, size_t len)
{
if (len % CTS_BLOCK_SIZE == 0) {
/* If there are no partial blocks then it is the same as CBC mode */
if (!ctx->hw->cipher(ctx, out, in, len))
return 0;
return len;
}
/* For partial blocks CS2 is equivalent to CS3 */
return cts128_cs3_decrypt(ctx, in, out, len);
}
int ossl_cipher_cbc_cts_block_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;
size_t sz = 0;
if (inl < CTS_BLOCK_SIZE) /* There must be at least one block for CTS mode */
return 0;
if (outsize < inl)
return 0;
if (out == NULL) {
*outl = inl;
return 1;
}
/*
* Return an error if the update is called multiple times, only one shot
* is supported.
*/
if (ctx->updated == 1)
return 0;
if (ctx->enc) {
if (ctx->cts_mode == CTS_CS1)
sz = cts128_cs1_encrypt(ctx, in, out, inl);
else if (ctx->cts_mode == CTS_CS2)
sz = cts128_cs2_encrypt(ctx, in, out, inl);
else if (ctx->cts_mode == CTS_CS3)
sz = cts128_cs3_encrypt(ctx, in, out, inl);
} else {
if (ctx->cts_mode == CTS_CS1)
sz = cts128_cs1_decrypt(ctx, in, out, inl);
else if (ctx->cts_mode == CTS_CS2)
sz = cts128_cs2_decrypt(ctx, in, out, inl);
else if (ctx->cts_mode == CTS_CS3)
sz = cts128_cs3_decrypt(ctx, in, out, inl);
}
if (sz == 0)
return 0;
ctx->updated = 1; /* Stop multiple updates being allowed */
*outl = sz;
return 1;
}
int ossl_cipher_cbc_cts_block_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
*outl = 0;
return 1;
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2020-2023 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 "crypto/evp.h"
/* NOTE: The underlying block cipher is CBC so we reuse most of the code */
#define IMPLEMENT_cts_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \
blkbits, ivbits, typ) \
static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lcmode##_get_params; \
static int alg##_cts_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
{ \
return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
flags, kbits, blkbits, ivbits); \
} \
const OSSL_DISPATCH ossl_##alg##kbits##lcmode##_cts_functions[] = { \
{ OSSL_FUNC_CIPHER_NEWCTX, \
(void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void)) alg##_cbc_cts_einit }, \
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void)) alg##_cbc_cts_dinit }, \
{ OSSL_FUNC_CIPHER_UPDATE, \
(void (*)(void)) ossl_cipher_cbc_cts_block_update }, \
{ OSSL_FUNC_CIPHER_FINAL, \
(void (*)(void)) ossl_cipher_cbc_cts_block_final }, \
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_cipher_generic_cipher }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
(void (*)(void)) alg##_cts_##kbits##_##lcmode##_get_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
(void (*)(void))ossl_cipher_generic_gettable_params }, \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
(void (*)(void)) alg##_cbc_cts_get_ctx_params }, \
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
(void (*)(void)) alg##_cbc_cts_set_ctx_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
(void (*)(void)) alg##_cbc_cts_gettable_ctx_params }, \
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
(void (*)(void)) alg##_cbc_cts_settable_ctx_params }, \
OSSL_DISPATCH_END \
};
OSSL_FUNC_cipher_update_fn ossl_cipher_cbc_cts_block_update;
OSSL_FUNC_cipher_final_fn ossl_cipher_cbc_cts_block_final;
const char *ossl_cipher_cbc_cts_mode_id2name(unsigned int id);
int ossl_cipher_cbc_cts_mode_name2id(const char *name);

View File

@@ -0,0 +1,201 @@
/*
* Copyright 2019-2023 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
*/
/*
* DES low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include <openssl/rand.h>
#include <openssl/proverr.h>
#include "prov/ciphercommon.h"
#include "cipher_des.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#define DES_FLAGS PROV_CIPHER_FLAG_RAND_KEY
static OSSL_FUNC_cipher_freectx_fn des_freectx;
static OSSL_FUNC_cipher_encrypt_init_fn des_einit;
static OSSL_FUNC_cipher_decrypt_init_fn des_dinit;
static OSSL_FUNC_cipher_get_ctx_params_fn des_get_ctx_params;
static OSSL_FUNC_cipher_gettable_ctx_params_fn des_gettable_ctx_params;
static void *des_newctx(void *provctx, size_t kbits, size_t blkbits,
size_t ivbits, unsigned int mode, uint64_t flags,
const PROV_CIPHER_HW *hw)
{
PROV_DES_CTX *ctx;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL)
ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags,
hw, provctx);
return ctx;
}
static void *des_dupctx(void *ctx)
{
PROV_DES_CTX *in = (PROV_DES_CTX *)ctx;
PROV_DES_CTX *ret;
if (!ossl_prov_is_running())
return NULL;
ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL)
return NULL;
in->base.hw->copyctx(&ret->base, &in->base);
return ret;
}
static void des_freectx(void *vctx)
{
PROV_DES_CTX *ctx = (PROV_DES_CTX *)vctx;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static int des_init(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[], int enc)
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
if (!ossl_prov_is_running())
return 0;
ctx->num = 0;
ctx->bufsz = 0;
ctx->enc = enc;
if (iv != NULL) {
if (!ossl_cipher_generic_initiv(ctx, iv, ivlen))
return 0;
} else if (ctx->iv_set) {
/* reset IV to keep compatibility with 1.1.1 */
memcpy(ctx->iv, ctx->oiv, ctx->ivlen);
}
if (key != NULL) {
if (keylen != ctx->keylen) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
if (!ctx->hw->init(ctx, key, keylen))
return 0;
ctx->key_set = 1;
}
return ossl_cipher_generic_set_ctx_params(ctx, params);
}
static int des_einit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
return des_init(vctx, key, keylen, iv, ivlen, params, 1);
}
static int des_dinit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
return des_init(vctx, key, keylen, iv, ivlen, params, 0);
}
static int des_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) <= 0)
return 0;
DES_set_odd_parity(deskey);
return 1;
}
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(des)
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_RANDOM_KEY, NULL, 0),
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(des)
static int des_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
OSSL_PARAM *p;
if (!ossl_cipher_generic_get_ctx_params(vctx, params))
return 0;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_RANDOM_KEY);
if (p != NULL && !des_generatekey(ctx, p->data)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GENERATE_KEY);
return 0;
}
return 1;
}
#define IMPLEMENT_des_cipher(type, lcmode, UCMODE, flags, \
kbits, blkbits, ivbits, block) \
static OSSL_FUNC_cipher_newctx_fn type##_##lcmode##_newctx; \
static void *des_##lcmode##_newctx(void *provctx) \
{ \
return des_newctx(provctx, kbits, blkbits, ivbits, \
EVP_CIPH_##UCMODE##_MODE, flags, \
ossl_prov_cipher_hw_des_##lcmode()); \
} \
static OSSL_FUNC_cipher_get_params_fn des_##lcmode##_get_params; \
static int des_##lcmode##_get_params(OSSL_PARAM params[]) \
{ \
return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
flags, kbits, blkbits, ivbits); \
} \
const OSSL_DISPATCH ossl_##des_##lcmode##_functions[] = { \
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))des_einit }, \
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))des_dinit }, \
{ OSSL_FUNC_CIPHER_UPDATE, \
(void (*)(void))ossl_cipher_generic_##block##_update }, \
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_cipher_generic_##block##_final },\
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_cipher_generic_cipher }, \
{ OSSL_FUNC_CIPHER_NEWCTX, \
(void (*)(void))des_##lcmode##_newctx }, \
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))des_dupctx }, \
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))des_freectx }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
(void (*)(void))des_##lcmode##_get_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
(void (*)(void))ossl_cipher_generic_gettable_params }, \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))des_get_ctx_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
(void (*)(void))des_gettable_ctx_params }, \
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
(void (*)(void))ossl_cipher_generic_set_ctx_params }, \
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
(void (*)(void))ossl_cipher_generic_settable_ctx_params }, \
OSSL_DISPATCH_END \
}
/* ossl_des_ecb_functions */
IMPLEMENT_des_cipher(des, ecb, ECB, DES_FLAGS, 64, 64, 0, block);
/* ossl_des_cbc_functions */
IMPLEMENT_des_cipher(des, cbc, CBC, DES_FLAGS, 64, 64, 64, block);
/* ossl_des_ofb64_functions */
IMPLEMENT_des_cipher(des, ofb64, OFB, DES_FLAGS, 64, 8, 64, stream);
/* ossl_des_cfb64_functions */
IMPLEMENT_des_cipher(des, cfb64, CFB, DES_FLAGS, 64, 8, 64, stream);
/* ossl_des_cfb1_functions */
IMPLEMENT_des_cipher(des, cfb1, CFB, DES_FLAGS, 64, 8, 64, stream);
/* ossl_des_cfb8_functions */
IMPLEMENT_des_cipher(des, cfb8, CFB, DES_FLAGS, 64, 8, 64, stream);

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2019-2021 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/des.h>
#include "crypto/des_platform.h"
#define TDES_FLAGS 0
typedef struct prov_des_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
DES_key_schedule ks;
} dks;
union {
void (*cbc) (const void *, void *, size_t,
const DES_key_schedule *, unsigned char *);
} dstream;
} PROV_DES_CTX;
const PROV_CIPHER_HW *ossl_prov_cipher_hw_des_cbc(void);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_des_ecb(void);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_des_ofb64(void);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_des_cfb64(void);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_des_cfb1(void);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_des_cfb8(void);

View File

@@ -0,0 +1,197 @@
/*
* Copyright 1995-2021 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
*/
/*
* DES low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "prov/ciphercommon.h"
#include "cipher_des.h"
static int cipher_hw_des_initkey(PROV_CIPHER_CTX *ctx,
const unsigned char *key, size_t keylen)
{
PROV_DES_CTX *dctx = (PROV_DES_CTX *)ctx;
DES_cblock *deskey = (DES_cblock *)key;
DES_key_schedule *ks = &dctx->dks.ks;
dctx->dstream.cbc = NULL;
#if defined(SPARC_DES_CAPABLE)
if (SPARC_DES_CAPABLE) {
if (ctx->mode == EVP_CIPH_CBC_MODE) {
des_t4_key_expand(&deskey[0], ks);
dctx->dstream.cbc = ctx->enc ? des_t4_cbc_encrypt :
des_t4_cbc_decrypt;
return 1;
}
}
#endif
DES_set_key_unchecked(deskey, ks);
return 1;
}
static void cipher_hw_des_copyctx(PROV_CIPHER_CTX *dst,
const PROV_CIPHER_CTX *src)
{
PROV_DES_CTX *sctx = (PROV_DES_CTX *)src;
PROV_DES_CTX *dctx = (PROV_DES_CTX *)dst;
*dctx = *sctx;
dst->ks = &dctx->dks.ks;
}
static int cipher_hw_des_ecb_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
size_t i, bl = ctx->blocksize;
DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
if (len < bl)
return 1;
for (i = 0, len -= bl; i <= len; i += bl)
DES_ecb_encrypt((const_DES_cblock *)(in + i),
(const_DES_cblock *)(out + i), key, ctx->enc);
return 1;
}
static int cipher_hw_des_cbc_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_DES_CTX *dctx = (PROV_DES_CTX *)ctx;
DES_key_schedule *key = &(dctx->dks.ks);
if (dctx->dstream.cbc != NULL) {
(*dctx->dstream.cbc) (in, out, len, key, ctx->iv);
return 1;
}
while (len >= MAXCHUNK) {
DES_ncbc_encrypt(in, out, MAXCHUNK, key, (DES_cblock *)ctx->iv,
ctx->enc);
len -= MAXCHUNK;
in += MAXCHUNK;
out += MAXCHUNK;
}
if (len > 0)
DES_ncbc_encrypt(in, out, (long)len, key, (DES_cblock *)ctx->iv,
ctx->enc);
return 1;
}
static int cipher_hw_des_ofb64_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
int num = ctx->num;
DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
while (len >= MAXCHUNK) {
DES_ofb64_encrypt(in, out, MAXCHUNK, key, (DES_cblock *)ctx->iv, &num);
len -= MAXCHUNK;
in += MAXCHUNK;
out += MAXCHUNK;
}
if (len > 0) {
DES_ofb64_encrypt(in, out, (long)len, key, (DES_cblock *)ctx->iv, &num);
}
ctx->num = num;
return 1;
}
static int cipher_hw_des_cfb64_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
size_t chunk = MAXCHUNK;
DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
int num = ctx->num;
if (len < chunk)
chunk = len;
while (len > 0 && len >= chunk) {
DES_cfb64_encrypt(in, out, (long)chunk, key, (DES_cblock *)ctx->iv,
&num, ctx->enc);
len -= chunk;
in += chunk;
out += chunk;
if (len < chunk)
chunk = len;
}
ctx->num = num;
return 1;
}
/*
* Although we have a CFB-r implementation for DES, it doesn't pack the right
* way, so wrap it here
*/
static int cipher_hw_des_cfb1_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
size_t n, chunk = MAXCHUNK / 8;
DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
unsigned char c[1];
unsigned char d[1] = { 0 };
if (inl < chunk)
chunk = inl;
while (inl && inl >= chunk) {
for (n = 0; n < chunk * 8; ++n) {
c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0;
DES_cfb_encrypt(c, d, 1, 1, key, (DES_cblock *)ctx->iv, ctx->enc);
out[n / 8] =
(out[n / 8] & ~(0x80 >> (unsigned int)(n % 8))) |
((d[0] & 0x80) >> (unsigned int)(n % 8));
}
inl -= chunk;
in += chunk;
out += chunk;
if (inl < chunk)
chunk = inl;
}
return 1;
}
static int cipher_hw_des_cfb8_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks);
while (inl >= MAXCHUNK) {
DES_cfb_encrypt(in, out, 8, (long)MAXCHUNK, key,
(DES_cblock *)ctx->iv, ctx->enc);
inl -= MAXCHUNK;
in += MAXCHUNK;
out += MAXCHUNK;
}
if (inl > 0)
DES_cfb_encrypt(in, out, 8, (long)inl, key,
(DES_cblock *)ctx->iv, ctx->enc);
return 1;
}
#define PROV_CIPHER_HW_des_mode(mode) \
static const PROV_CIPHER_HW des_##mode = { \
cipher_hw_des_initkey, \
cipher_hw_des_##mode##_cipher, \
cipher_hw_des_copyctx \
}; \
const PROV_CIPHER_HW *ossl_prov_cipher_hw_des_##mode(void) \
{ \
return &des_##mode; \
}
PROV_CIPHER_HW_des_mode(ecb)
PROV_CIPHER_HW_des_mode(cbc)
PROV_CIPHER_HW_des_mode(ofb64)
PROV_CIPHER_HW_des_mode(cfb64)
PROV_CIPHER_HW_des_mode(cfb1)
PROV_CIPHER_HW_des_mode(cfb8)

View File

@@ -0,0 +1,21 @@
/*
* Copyright 2019-2020 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
*/
/*
* DES low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_tdes_default.h"
#include "prov/implementations.h"
/* desx_cbc_functions */
IMPLEMENT_tdes_cipher(desx, DESX, cbc, CBC, TDES_FLAGS, 64*3, 64, 64, block);

View File

@@ -0,0 +1,79 @@
/*
* Copyright 1995-2024 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
*/
/*
* DES low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include <openssl/des.h>
#include "cipher_tdes_default.h"
/*
* Note the PROV_TDES_CTX has been used for the DESX cipher, just to reduce
* code size.
*/
#define ks1 tks.ks[0]
#define ks2 tks.ks[1].ks[0].cblock
#define ks3 tks.ks[2].ks[0].cblock
static int cipher_hw_desx_cbc_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;
DES_set_key_unchecked(deskey, &tctx->ks1);
memcpy(&tctx->ks2, &key[8], 8);
memcpy(&tctx->ks3, &key[16], 8);
return 1;
}
static void cipher_hw_desx_copyctx(PROV_CIPHER_CTX *dst,
const PROV_CIPHER_CTX *src)
{
PROV_TDES_CTX *sctx = (PROV_TDES_CTX *)src;
PROV_TDES_CTX *dctx = (PROV_TDES_CTX *)dst;
*dctx = *sctx;
dst->ks = &dctx->tks.ks;
}
static int cipher_hw_desx_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx;
while (inl >= MAXCHUNK) {
DES_xcbc_encrypt(in, out, (long)MAXCHUNK, &tctx->ks1,
(DES_cblock *)ctx->iv, &tctx->ks2, &tctx->ks3,
ctx->enc);
inl -= MAXCHUNK;
in += MAXCHUNK;
out += MAXCHUNK;
}
if (inl > 0)
DES_xcbc_encrypt(in, out, (long)inl, &tctx->ks1,
(DES_cblock *)ctx->iv, &tctx->ks2, &tctx->ks3,
ctx->enc);
return 1;
}
static const PROV_CIPHER_HW desx_cbc = {
cipher_hw_desx_cbc_initkey,
cipher_hw_desx_cbc,
cipher_hw_desx_copyctx
};
const PROV_CIPHER_HW *ossl_prov_cipher_hw_tdes_desx_cbc(void)
{
return &desx_cbc;
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2019-2020 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
*/
/*
* IDEA low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
/* Dispatch functions for Idea cipher modes ecb, cbc, ofb, cfb */
#include "cipher_idea.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
static OSSL_FUNC_cipher_freectx_fn idea_freectx;
static OSSL_FUNC_cipher_dupctx_fn idea_dupctx;
static void idea_freectx(void *vctx)
{
PROV_IDEA_CTX *ctx = (PROV_IDEA_CTX *)vctx;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static void *idea_dupctx(void *ctx)
{
PROV_IDEA_CTX *in = (PROV_IDEA_CTX *)ctx;
PROV_IDEA_CTX *ret;
if (!ossl_prov_is_running())
return NULL;
ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL)
return NULL;
*ret = *in;
return ret;
}
/* ossl_idea128ecb_functions */
IMPLEMENT_generic_cipher(idea, IDEA, ecb, ECB, 0, 128, 64, 0, block)
/* ossl_idea128cbc_functions */
IMPLEMENT_generic_cipher(idea, IDEA, cbc, CBC, 0, 128, 64, 64, block)
/* ossl_idea128ofb64_functions */
IMPLEMENT_generic_cipher(idea, IDEA, ofb64, OFB, 0, 128, 8, 64, stream)
/* ossl_idea128cfb64_functions */
IMPLEMENT_generic_cipher(idea, IDEA, cfb64, CFB, 0, 128, 8, 64, stream)

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2019-2020 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/idea.h>
#include "prov/ciphercommon.h"
typedef struct prov_idea_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
IDEA_KEY_SCHEDULE ks;
} ks;
} PROV_IDEA_CTX;
const PROV_CIPHER_HW *ossl_prov_cipher_hw_idea_cbc(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_idea_ecb(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_idea_ofb64(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_idea_cfb64(size_t keybits);

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2019-2020 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
*/
/*
* IDEA low level APIs are deprecated for public use, but still ok for internal
* use where we're using them to implement the higher level EVP interface, as is
* the case here.
*/
#include "internal/deprecated.h"
#include "cipher_idea.h"
static int cipher_hw_idea_initkey(PROV_CIPHER_CTX *ctx,
const unsigned char *key, size_t keylen)
{
PROV_IDEA_CTX *ictx = (PROV_IDEA_CTX *)ctx;
IDEA_KEY_SCHEDULE *ks = &(ictx->ks.ks);
if (ctx->enc
|| ctx->mode == EVP_CIPH_OFB_MODE
|| ctx->mode == EVP_CIPH_CFB_MODE) {
IDEA_set_encrypt_key(key, ks);
} else {
IDEA_KEY_SCHEDULE tmp;
IDEA_set_encrypt_key(key, &tmp);
IDEA_set_decrypt_key(&tmp, ks);
OPENSSL_cleanse((unsigned char *)&tmp, sizeof(IDEA_KEY_SCHEDULE));
}
return 1;
}
# define PROV_CIPHER_HW_idea_mode_ex(mode, UCMODE, fname) \
IMPLEMENT_CIPHER_HW_##UCMODE(mode, idea, PROV_IDEA_CTX, IDEA_KEY_SCHEDULE, \
fname) \
static const PROV_CIPHER_HW idea_##mode = { \
cipher_hw_idea_initkey, \
cipher_hw_idea_##mode##_cipher \
}; \
const PROV_CIPHER_HW *ossl_prov_cipher_hw_idea_##mode(size_t keybits) \
{ \
return &idea_##mode; \
}
# define PROV_CIPHER_HW_idea_mode(mode, UCMODE) \
PROV_CIPHER_HW_idea_mode_ex(mode, UCMODE, IDEA_##mode)
PROV_CIPHER_HW_idea_mode(cbc, CBC)
PROV_CIPHER_HW_idea_mode(ofb64, OFB)
PROV_CIPHER_HW_idea_mode(cfb64, CFB)
/*
* IDEA_ecb_encrypt() does not have a enc parameter - so we create a macro
* that ignores this parameter when IMPLEMENT_CIPHER_HW_ecb() is called.
*/
#define IDEA2_ecb_encrypt(in, out, ks, enc) IDEA_ecb_encrypt(in, out, ks)
PROV_CIPHER_HW_idea_mode_ex(ecb, ECB, IDEA2_ecb)

View File

@@ -0,0 +1,197 @@
/*
* Copyright 2020-2024 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_dispatch.h>
#include <openssl/proverr.h>
#include "prov/implementations.h"
#include "prov/ciphercommon.h"
#include "prov/providercommon.h"
typedef struct prov_cipher_null_ctx_st {
int enc;
size_t tlsmacsize;
const unsigned char *tlsmac;
} PROV_CIPHER_NULL_CTX;
static OSSL_FUNC_cipher_newctx_fn null_newctx;
static void *null_newctx(void *provctx)
{
if (!ossl_prov_is_running())
return NULL;
return OPENSSL_zalloc(sizeof(PROV_CIPHER_NULL_CTX));
}
static OSSL_FUNC_cipher_freectx_fn null_freectx;
static void null_freectx(void *vctx)
{
OPENSSL_free(vctx);
}
static OSSL_FUNC_cipher_encrypt_init_fn null_einit;
static int null_einit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
PROV_CIPHER_NULL_CTX *ctx = (PROV_CIPHER_NULL_CTX *)vctx;
if (!ossl_prov_is_running())
return 0;
ctx->enc = 1;
return 1;
}
static OSSL_FUNC_cipher_decrypt_init_fn null_dinit;
static int null_dinit(void *vctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
if (!ossl_prov_is_running())
return 0;
return 1;
}
static OSSL_FUNC_cipher_cipher_fn null_cipher;
static int null_cipher(void *vctx, unsigned char *out, size_t *outl,
size_t outsize, const unsigned char *in, size_t inl)
{
PROV_CIPHER_NULL_CTX *ctx = (PROV_CIPHER_NULL_CTX *)vctx;
if (!ossl_prov_is_running())
return 0;
if (!ctx->enc && ctx->tlsmacsize > 0) {
/*
* TLS NULL cipher as per:
* https://tools.ietf.org/html/rfc5246#section-6.2.3.1
*/
if (inl < ctx->tlsmacsize)
return 0;
ctx->tlsmac = in + inl - ctx->tlsmacsize;
inl -= ctx->tlsmacsize;
}
if (outsize < inl)
return 0;
if (out != NULL && in != out)
memcpy(out, in, inl);
*outl = inl;
return 1;
}
static OSSL_FUNC_cipher_final_fn null_final;
static int null_final(void *vctx, unsigned char *out, size_t *outl,
size_t outsize)
{
if (!ossl_prov_is_running())
return 0;
*outl = 0;
return 1;
}
static OSSL_FUNC_cipher_get_params_fn null_get_params;
static int null_get_params(OSSL_PARAM params[])
{
return ossl_cipher_generic_get_params(params, 0, 0, 0, 8, 0);
}
static const OSSL_PARAM null_known_gettable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
{ OSSL_CIPHER_PARAM_TLS_MAC, OSSL_PARAM_OCTET_PTR, NULL, 0, OSSL_PARAM_UNMODIFIED },
OSSL_PARAM_END
};
static OSSL_FUNC_cipher_gettable_ctx_params_fn null_gettable_ctx_params;
static const OSSL_PARAM *null_gettable_ctx_params(ossl_unused void *cctx,
ossl_unused void *provctx)
{
return null_known_gettable_ctx_params;
}
static OSSL_FUNC_cipher_get_ctx_params_fn null_get_ctx_params;
static int null_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_CIPHER_NULL_CTX *ctx = (PROV_CIPHER_NULL_CTX *)vctx;
OSSL_PARAM *p;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, 0)) {
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, 0)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS_MAC);
if (p != NULL
&& !OSSL_PARAM_set_octet_ptr(p, ctx->tlsmac, ctx->tlsmacsize)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
return 1;
}
static const OSSL_PARAM null_known_settable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS_MAC_SIZE, NULL),
OSSL_PARAM_END
};
static OSSL_FUNC_cipher_settable_ctx_params_fn null_settable_ctx_params;
static const OSSL_PARAM *null_settable_ctx_params(ossl_unused void *cctx,
ossl_unused void *provctx)
{
return null_known_settable_ctx_params;
}
static OSSL_FUNC_cipher_set_ctx_params_fn null_set_ctx_params;
static int null_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_CIPHER_NULL_CTX *ctx = (PROV_CIPHER_NULL_CTX *)vctx;
const OSSL_PARAM *p;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLS_MAC_SIZE);
if (p != NULL) {
if (!OSSL_PARAM_get_size_t(p, &ctx->tlsmacsize)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
}
return 1;
}
const OSSL_DISPATCH ossl_null_functions[] = {
{ OSSL_FUNC_CIPHER_NEWCTX,
(void (*)(void)) null_newctx },
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) null_freectx },
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) null_newctx },
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))null_einit },
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))null_dinit },
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))null_cipher },
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))null_final },
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))null_cipher },
{ OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void)) null_get_params },
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS,
(void (*)(void))ossl_cipher_generic_gettable_params },
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))null_get_ctx_params },
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
(void (*)(void))null_gettable_ctx_params },
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (void (*)(void))null_set_ctx_params },
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
(void (*)(void))null_settable_ctx_params },
OSSL_DISPATCH_END
};

View File

@@ -0,0 +1,295 @@
/*
* Copyright 2019-2024 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 RC2 cipher modes ecb, cbc, ofb, cfb */
/*
* RC2 low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include <openssl/proverr.h>
#include "cipher_rc2.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#define RC2_40_MAGIC 0xa0
#define RC2_64_MAGIC 0x78
#define RC2_128_MAGIC 0x3a
#define RC2_FLAGS PROV_CIPHER_FLAG_VARIABLE_LENGTH
static OSSL_FUNC_cipher_encrypt_init_fn rc2_einit;
static OSSL_FUNC_cipher_decrypt_init_fn rc2_dinit;
static OSSL_FUNC_cipher_freectx_fn rc2_freectx;
static OSSL_FUNC_cipher_dupctx_fn rc2_dupctx;
static OSSL_FUNC_cipher_gettable_ctx_params_fn rc2_gettable_ctx_params;
static OSSL_FUNC_cipher_settable_ctx_params_fn rc2_settable_ctx_params;
static OSSL_FUNC_cipher_set_ctx_params_fn rc2_set_ctx_params;
static void rc2_freectx(void *vctx)
{
PROV_RC2_CTX *ctx = (PROV_RC2_CTX *)vctx;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static void *rc2_dupctx(void *ctx)
{
PROV_RC2_CTX *in = (PROV_RC2_CTX *)ctx;
PROV_RC2_CTX *ret;
if (!ossl_prov_is_running())
return NULL;
ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL)
return NULL;
*ret = *in;
return ret;
}
static int rc2_keybits_to_magic(int keybits)
{
switch (keybits) {
case 128:
return RC2_128_MAGIC;
case 64:
return RC2_64_MAGIC;
case 40:
return RC2_40_MAGIC;
}
ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_KEY_SIZE);
return 0;
}
static int rc2_magic_to_keybits(int magic)
{
switch (magic) {
case RC2_128_MAGIC:
return 128;
case RC2_64_MAGIC:
return 64;
case RC2_40_MAGIC:
return 40;
}
ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_KEY_SIZE);
return 0;
}
static int rc2_einit(void *ctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
if (!ossl_cipher_generic_einit(ctx, key, keylen, iv, ivlen, NULL))
return 0;
return rc2_set_ctx_params(ctx, params);
}
static int rc2_dinit(void *ctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
if (!ossl_cipher_generic_dinit(ctx, key, keylen, iv, ivlen, NULL))
return 0;
return rc2_set_ctx_params(ctx, params);
}
static int rc2_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_RC2_CTX *ctx = (PROV_RC2_CTX *)vctx;
OSSL_PARAM *p, *p1, *p2;
if (!ossl_cipher_generic_get_ctx_params(vctx, params))
return 0;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_RC2_KEYBITS);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->key_bits)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
p1 = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS);
p2 = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS_OLD);
if (p1 != NULL || p2 != NULL) {
long num;
int i;
ASN1_TYPE *type;
unsigned char *d1 = (p1 == NULL) ? NULL : p1->data;
unsigned char *d2 = (p2 == NULL) ? NULL : p2->data;
unsigned char **dd1 = d1 == NULL ? NULL : &d1;
unsigned char **dd2 = d2 == NULL ? NULL : &d2;
if ((p1 != NULL && p1->data_type != OSSL_PARAM_OCTET_STRING)
|| (p2 != NULL && p2->data_type != OSSL_PARAM_OCTET_STRING)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
if ((type = ASN1_TYPE_new()) == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_ASN1_LIB);
return 0;
}
/* Is this the original IV or the running IV? */
num = rc2_keybits_to_magic(ctx->key_bits);
if (!ASN1_TYPE_set_int_octetstring(type, num,
ctx->base.iv, ctx->base.ivlen)) {
ASN1_TYPE_free(type);
ERR_raise(ERR_LIB_PROV, ERR_R_ASN1_LIB);
return 0;
}
/*
* IF the caller has a buffer, we pray to the gods they got the
* size right. There's no way to tell the i2d functions...
*/
i = i2d_ASN1_TYPE(type, dd1);
if (p1 != NULL && i >= 0)
p1->return_size = (size_t)i;
/*
* If the buffers differ, redo the i2d on the second buffer.
* Otherwise, just use |i| as computed above
*/
if (d1 != d2)
i = i2d_ASN1_TYPE(type, dd2);
if (p2 != NULL && i >= 0)
p2->return_size = (size_t)i;
ASN1_TYPE_free(type);
if (i < 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
}
return 1;
}
static int rc2_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_RC2_CTX *ctx = (PROV_RC2_CTX *)vctx;
const OSSL_PARAM *p;
if (params == NULL)
return 1;
if (!ossl_cipher_var_keylen_set_ctx_params(vctx, params))
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_RC2_KEYBITS);
if (p != NULL) {
if (!OSSL_PARAM_get_size_t(p, &ctx->key_bits)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS);
if (p != NULL) {
ASN1_TYPE *type = NULL;
long num = 0;
const unsigned char *d = p->data;
int ret = 1;
unsigned char iv[16];
if (p->data_type != OSSL_PARAM_OCTET_STRING
|| ctx->base.ivlen > sizeof(iv)
|| (type = d2i_ASN1_TYPE(NULL, &d, p->data_size)) == NULL
|| ((size_t)ASN1_TYPE_get_int_octetstring(type, &num, iv,
ctx->base.ivlen)
!= ctx->base.ivlen)
|| !ossl_cipher_generic_initiv(&ctx->base, iv, ctx->base.ivlen)
|| (ctx->key_bits = rc2_magic_to_keybits(num)) == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
ret = 0;
}
ASN1_TYPE_free(type);
if (ret == 0)
return 0;
/*
* This code assumes that the caller will call
* EVP_CipherInit_ex() with a non NULL key in order to setup a key that
* uses the keylen and keybits that were set here.
*/
ctx->base.keylen = ctx->key_bits / 8;
}
return 1;
}
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(rc2)
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_RC2_KEYBITS, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS, NULL, 0),
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(rc2)
CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(rc2)
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_RC2_KEYBITS, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS, NULL, 0),
CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(rc2)
#define IMPLEMENT_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, blkbits, \
ivbits, typ) \
static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lcmode##_get_params; \
static int alg##_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
{ \
return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
flags, kbits, blkbits, ivbits); \
} \
static OSSL_FUNC_cipher_newctx_fn alg##_##kbits##_##lcmode##_newctx; \
static void *alg##_##kbits##_##lcmode##_newctx(void *provctx) \
{ \
PROV_##UCALG##_CTX *ctx; \
if (!ossl_prov_is_running()) \
return NULL; \
ctx = OPENSSL_zalloc(sizeof(*ctx)); \
if (ctx != NULL) { \
ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, \
EVP_CIPH_##UCMODE##_MODE, flags, \
ossl_prov_cipher_hw_##alg##_##lcmode(kbits), \
NULL); \
ctx->key_bits = kbits; \
} \
return ctx; \
} \
const OSSL_DISPATCH ossl_##alg##kbits##lcmode##_functions[] = { \
{ OSSL_FUNC_CIPHER_NEWCTX, \
(void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))rc2_einit }, \
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))rc2_dinit }, \
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_cipher_generic_##typ##_update },\
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_cipher_generic_##typ##_final }, \
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_cipher_generic_cipher }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
(void (*)(void)) alg##_##kbits##_##lcmode##_get_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
(void (*)(void))ossl_cipher_generic_gettable_params }, \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
(void (*)(void))rc2_get_ctx_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
(void (*)(void))rc2_gettable_ctx_params }, \
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
(void (*)(void))rc2_set_ctx_params }, \
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
(void (*)(void))rc2_settable_ctx_params }, \
OSSL_DISPATCH_END \
};
/* ossl_rc2128ecb_functions */
IMPLEMENT_cipher(rc2, RC2, ecb, ECB, RC2_FLAGS, 128, 64, 0, block)
/* ossl_rc2128cbc_functions */
IMPLEMENT_cipher(rc2, RC2, cbc, CBC, RC2_FLAGS, 128, 64, 64, block)
/* ossl_rc240cbc_functions */
IMPLEMENT_cipher(rc2, RC2, cbc, CBC, RC2_FLAGS, 40, 64, 64, block)
/* ossl_rc264cbc_functions */
IMPLEMENT_cipher(rc2, RC2, cbc, CBC, RC2_FLAGS, 64, 64, 64, block)
/* ossl_rc2128ofb128_functions */
IMPLEMENT_cipher(rc2, RC2, ofb128, OFB, RC2_FLAGS, 128, 8, 64, stream)
/* ossl_rc2128cfb128_functions */
IMPLEMENT_cipher(rc2, RC2, cfb128, CFB, RC2_FLAGS, 128, 8, 64, stream)

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2019-2020 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/rc2.h>
#include "prov/ciphercommon.h"
typedef struct prov_rc2_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
RC2_KEY ks;
} ks;
size_t key_bits;
} PROV_RC2_CTX;
#define ossl_prov_cipher_hw_rc2_ofb128 ossl_prov_cipher_hw_rc2_ofb64
#define ossl_prov_cipher_hw_rc2_cfb128 ossl_prov_cipher_hw_rc2_cfb64
const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc2_cbc(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc2_ecb(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc2_ofb64(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc2_cfb64(size_t keybits);

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2019-2020 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
*/
/*
* RC2 low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_rc2.h"
static int cipher_hw_rc2_initkey(PROV_CIPHER_CTX *ctx,
const unsigned char *key, size_t keylen)
{
PROV_RC2_CTX *rctx = (PROV_RC2_CTX *)ctx;
RC2_KEY *ks = &(rctx->ks.ks);
RC2_set_key(ks, (int)ctx->keylen, key, (int)rctx->key_bits);
return 1;
}
# define PROV_CIPHER_HW_rc2_mode(mode, UCMODE) \
IMPLEMENT_CIPHER_HW_##UCMODE(mode, rc2, PROV_RC2_CTX, RC2_KEY, \
RC2_##mode) \
static const PROV_CIPHER_HW rc2_##mode = { \
cipher_hw_rc2_initkey, \
cipher_hw_rc2_##mode##_cipher \
}; \
const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc2_##mode(size_t keybits) \
{ \
return &rc2_##mode; \
}
PROV_CIPHER_HW_rc2_mode(cbc, CBC)
PROV_CIPHER_HW_rc2_mode(ecb, ECB)
PROV_CIPHER_HW_rc2_mode(ofb64, OFB)
PROV_CIPHER_HW_rc2_mode(cfb64, CFB)

View File

@@ -0,0 +1,119 @@
/*
* Copyright 2019-2023 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 RC4 ciphers */
/*
* RC4 low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_rc4.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#define RC4_FLAGS PROV_CIPHER_FLAG_VARIABLE_LENGTH
static OSSL_FUNC_cipher_encrypt_init_fn rc4_einit;
static OSSL_FUNC_cipher_decrypt_init_fn rc4_dinit;
static OSSL_FUNC_cipher_freectx_fn rc4_freectx;
static OSSL_FUNC_cipher_dupctx_fn rc4_dupctx;
static void rc4_freectx(void *vctx)
{
PROV_RC4_CTX *ctx = (PROV_RC4_CTX *)vctx;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static void *rc4_dupctx(void *ctx)
{
PROV_RC4_CTX *in = (PROV_RC4_CTX *)ctx;
PROV_RC4_CTX *ret;
if (!ossl_prov_is_running())
return NULL;
ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL)
return NULL;
*ret = *in;
return ret;
}
static int rc4_einit(void *ctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
if (!ossl_cipher_generic_einit(ctx, key, keylen, iv, ivlen, NULL))
return 0;
return ossl_cipher_var_keylen_set_ctx_params(ctx, params);
}
static int rc4_dinit(void *ctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
if (!ossl_cipher_generic_dinit(ctx, key, keylen, iv, ivlen, NULL))
return 0;
return ossl_cipher_var_keylen_set_ctx_params(ctx, params);
}
#define IMPLEMENT_cipher(alg, UCALG, flags, kbits, blkbits, ivbits, typ) \
static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_get_params; \
static int alg##_##kbits##_get_params(OSSL_PARAM params[]) \
{ \
return ossl_cipher_generic_get_params(params, 0, flags, \
kbits, blkbits, ivbits); \
} \
static OSSL_FUNC_cipher_newctx_fn alg##_##kbits##_newctx; \
static void *alg##_##kbits##_newctx(void *provctx) \
{ \
PROV_##UCALG##_CTX *ctx; \
if (!ossl_prov_is_running()) \
return NULL; \
ctx = OPENSSL_zalloc(sizeof(*ctx)); \
if (ctx != NULL) { \
ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, 0, flags, \
ossl_prov_cipher_hw_##alg(kbits), NULL); \
} \
return ctx; \
} \
const OSSL_DISPATCH ossl_##alg##kbits##_functions[] = { \
{ OSSL_FUNC_CIPHER_NEWCTX, \
(void (*)(void)) alg##_##kbits##_newctx }, \
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))rc4_einit }, \
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))rc4_dinit }, \
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_cipher_generic_##typ##_update },\
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_cipher_generic_##typ##_final }, \
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_cipher_generic_cipher }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
(void (*)(void)) alg##_##kbits##_get_params }, \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
(void (*)(void))ossl_cipher_generic_get_ctx_params }, \
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
(void (*)(void))ossl_cipher_var_keylen_set_ctx_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
(void (*)(void))ossl_cipher_generic_gettable_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
(void (*)(void))ossl_cipher_generic_gettable_ctx_params }, \
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
(void (*)(void))ossl_cipher_var_keylen_settable_ctx_params }, \
OSSL_DISPATCH_END \
};
/* ossl_rc440_functions */
IMPLEMENT_cipher(rc4, RC4, RC4_FLAGS, 40, 8, 0, stream)
/* ossl_rc4128_functions */
IMPLEMENT_cipher(rc4, RC4, RC4_FLAGS, 128, 8, 0, stream)

View File

@@ -0,0 +1,21 @@
/*
* Copyright 2019-2020 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/rc4.h>
#include "prov/ciphercommon.h"
typedef struct prov_rc4_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
RC4_KEY ks;
} ks;
} PROV_RC4_CTX;
const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc4(size_t keybits);

View File

@@ -0,0 +1,245 @@
/*
* Copyright 2019-2023 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 RC4_HMAC_MD5 cipher */
/*
* MD5 and RC4 low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <openssl/proverr.h>
#include "cipher_rc4_hmac_md5.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#define RC4_HMAC_MD5_FLAGS (PROV_CIPHER_FLAG_VARIABLE_LENGTH \
| PROV_CIPHER_FLAG_AEAD)
#define RC4_HMAC_MD5_KEY_BITS (16 * 8)
#define RC4_HMAC_MD5_BLOCK_BITS (1 * 8)
#define RC4_HMAC_MD5_IV_BITS 0
#define RC4_HMAC_MD5_MODE 0
#define GET_HW(ctx) ((PROV_CIPHER_HW_RC4_HMAC_MD5 *)ctx->base.hw)
static OSSL_FUNC_cipher_encrypt_init_fn rc4_hmac_md5_einit;
static OSSL_FUNC_cipher_decrypt_init_fn rc4_hmac_md5_dinit;
static OSSL_FUNC_cipher_newctx_fn rc4_hmac_md5_newctx;
static OSSL_FUNC_cipher_freectx_fn rc4_hmac_md5_freectx;
static OSSL_FUNC_cipher_dupctx_fn rc4_hmac_md5_dupctx;
static OSSL_FUNC_cipher_get_ctx_params_fn rc4_hmac_md5_get_ctx_params;
static OSSL_FUNC_cipher_gettable_ctx_params_fn rc4_hmac_md5_gettable_ctx_params;
static OSSL_FUNC_cipher_set_ctx_params_fn rc4_hmac_md5_set_ctx_params;
static OSSL_FUNC_cipher_settable_ctx_params_fn rc4_hmac_md5_settable_ctx_params;
static OSSL_FUNC_cipher_get_params_fn rc4_hmac_md5_get_params;
#define rc4_hmac_md5_gettable_params ossl_cipher_generic_gettable_params
#define rc4_hmac_md5_update ossl_cipher_generic_stream_update
#define rc4_hmac_md5_final ossl_cipher_generic_stream_final
#define rc4_hmac_md5_cipher ossl_cipher_generic_cipher
static void *rc4_hmac_md5_newctx(void *provctx)
{
PROV_RC4_HMAC_MD5_CTX *ctx;
if (!ossl_prov_is_running())
return NULL;
ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL)
ossl_cipher_generic_initkey(ctx, RC4_HMAC_MD5_KEY_BITS,
RC4_HMAC_MD5_BLOCK_BITS,
RC4_HMAC_MD5_IV_BITS,
RC4_HMAC_MD5_MODE, RC4_HMAC_MD5_FLAGS,
ossl_prov_cipher_hw_rc4_hmac_md5(
RC4_HMAC_MD5_KEY_BITS
), NULL);
return ctx;
}
static void rc4_hmac_md5_freectx(void *vctx)
{
PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)vctx;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static void *rc4_hmac_md5_dupctx(void *vctx)
{
PROV_RC4_HMAC_MD5_CTX *ctx = vctx;
if (ctx == NULL)
return NULL;
return OPENSSL_memdup(ctx, sizeof(*ctx));
}
static int rc4_hmac_md5_einit(void *ctx, const unsigned char *key,
size_t keylen, const unsigned char *iv,
size_t ivlen, const OSSL_PARAM params[])
{
if (!ossl_cipher_generic_einit(ctx, key, keylen, iv, ivlen, NULL))
return 0;
return rc4_hmac_md5_set_ctx_params(ctx, params);
}
static int rc4_hmac_md5_dinit(void *ctx, const unsigned char *key,
size_t keylen, const unsigned char *iv,
size_t ivlen, const OSSL_PARAM params[])
{
if (!ossl_cipher_generic_dinit(ctx, key, keylen, iv, ivlen, NULL))
return 0;
return rc4_hmac_md5_set_ctx_params(ctx, params);
}
static const OSSL_PARAM rc4_hmac_md5_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_TLS1_AAD_PAD, NULL),
OSSL_PARAM_END
};
const OSSL_PARAM *rc4_hmac_md5_gettable_ctx_params(ossl_unused void *cctx,
ossl_unused void *provctx)
{
return rc4_hmac_md5_known_gettable_ctx_params;
}
static int rc4_hmac_md5_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)vctx;
OSSL_PARAM *p;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.keylen)) {
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, ctx->base.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;
}
return 1;
}
static const OSSL_PARAM rc4_hmac_md5_known_settable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0),
OSSL_PARAM_END
};
const OSSL_PARAM *rc4_hmac_md5_settable_ctx_params(ossl_unused void *cctx,
ossl_unused void *provctx)
{
return rc4_hmac_md5_known_settable_ctx_params;
}
static int rc4_hmac_md5_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)vctx;
const OSSL_PARAM *p;
size_t sz;
if (params == NULL)
return 1;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
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 (ctx->base.keylen != sz) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
return 0;
}
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_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 (ctx->base.ivlen != sz) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
return 0;
}
}
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 = GET_HW(ctx)->tls_init(&ctx->base, 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_MAC_KEY);
if (p != NULL) {
if (p->data_type != OSSL_PARAM_OCTET_STRING) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
GET_HW(ctx)->init_mackey(&ctx->base, p->data, p->data_size);
}
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLS_VERSION);
if (p != NULL) {
if (!OSSL_PARAM_get_uint(p, &ctx->base.tlsversion)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
}
return 1;
}
static int rc4_hmac_md5_get_params(OSSL_PARAM params[])
{
return ossl_cipher_generic_get_params(params, RC4_HMAC_MD5_MODE,
RC4_HMAC_MD5_FLAGS,
RC4_HMAC_MD5_KEY_BITS,
RC4_HMAC_MD5_BLOCK_BITS,
RC4_HMAC_MD5_IV_BITS);
}
const OSSL_DISPATCH ossl_rc4_hmac_ossl_md5_functions[] = {
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))rc4_hmac_md5_newctx },
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))rc4_hmac_md5_freectx },
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))rc4_hmac_md5_dupctx },
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))rc4_hmac_md5_einit },
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))rc4_hmac_md5_dinit },
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))rc4_hmac_md5_update },
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))rc4_hmac_md5_final },
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))rc4_hmac_md5_cipher },
{ OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))rc4_hmac_md5_get_params },
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS,
(void (*)(void))rc4_hmac_md5_gettable_params },
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS,
(void (*)(void))rc4_hmac_md5_get_ctx_params },
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
(void (*)(void))rc4_hmac_md5_gettable_ctx_params },
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS,
(void (*)(void))rc4_hmac_md5_set_ctx_params },
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
(void (*)(void))rc4_hmac_md5_settable_ctx_params },
OSSL_DISPATCH_END
};

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2019-2023 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/rc4.h>
#include <openssl/md5.h>
#include "prov/ciphercommon.h"
typedef struct prov_rc4_hmac_md5_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
RC4_KEY ks;
} ks;
MD5_CTX head, tail, md;
size_t payload_length;
size_t tls_aad_pad_sz;
} PROV_RC4_HMAC_MD5_CTX;
typedef struct prov_cipher_hw_rc4_hmac_md5_st {
PROV_CIPHER_HW base; /* Must be first */
int (*tls_init)(PROV_CIPHER_CTX *ctx, unsigned char *aad, size_t aad_len);
void (*init_mackey)(PROV_CIPHER_CTX *ctx, const unsigned char *key,
size_t len);
} PROV_CIPHER_HW_RC4_HMAC_MD5;
const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc4_hmac_md5(size_t keybits);
void rc4_md5_enc(RC4_KEY *key, const void *in0, void *out,
MD5_CTX *ctx, const void *inp, size_t blocks);

View File

@@ -0,0 +1,233 @@
/*
* Copyright 2019-2020 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
*/
/* RC4_HMAC_MD5 cipher implementation */
/*
* MD5 and RC4 low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include "cipher_rc4_hmac_md5.h"
#define NO_PAYLOAD_LENGTH ((size_t)-1)
#if defined(RC4_ASM) \
&& defined(MD5_ASM) \
&& (defined(__x86_64) \
|| defined(__x86_64__) \
|| defined(_M_AMD64) \
|| defined(_M_X64))
# define STITCHED_CALL
# define MOD 32 /* 32 is $MOD from rc4_md5-x86_64.pl */
#else
# define rc4_off 0
# define md5_off 0
#endif
static int cipher_hw_rc4_hmac_md5_initkey(PROV_CIPHER_CTX *bctx,
const uint8_t *key, size_t keylen)
{
PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)bctx;
RC4_set_key(&ctx->ks.ks, keylen, key);
MD5_Init(&ctx->head); /* handy when benchmarking */
ctx->tail = ctx->head;
ctx->md = ctx->head;
ctx->payload_length = NO_PAYLOAD_LENGTH;
bctx->removetlsfixed = MD5_DIGEST_LENGTH;
return 1;
}
static int cipher_hw_rc4_hmac_md5_cipher(PROV_CIPHER_CTX *bctx,
unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)bctx;
RC4_KEY *ks = &ctx->ks.ks;
#if defined(STITCHED_CALL)
size_t rc4_off = MOD - 1 - (ks->x & (MOD - 1));
size_t md5_off = MD5_CBLOCK - ctx->md.num, blocks;
unsigned int l;
#endif
size_t plen = ctx->payload_length;
if (plen != NO_PAYLOAD_LENGTH && len != (plen + MD5_DIGEST_LENGTH))
return 0;
if (ctx->base.enc) {
if (plen == NO_PAYLOAD_LENGTH)
plen = len;
#if defined(STITCHED_CALL)
/* cipher has to "fall behind" */
if (rc4_off > md5_off)
md5_off += MD5_CBLOCK;
if (plen > md5_off
&& (blocks = (plen - md5_off) / MD5_CBLOCK)
&& (OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) {
MD5_Update(&ctx->md, in, md5_off);
RC4(ks, rc4_off, in, out);
rc4_md5_enc(ks, in + rc4_off, out + rc4_off,
&ctx->md, in + md5_off, blocks);
blocks *= MD5_CBLOCK;
rc4_off += blocks;
md5_off += blocks;
ctx->md.Nh += blocks >> 29;
ctx->md.Nl += blocks <<= 3;
if (ctx->md.Nl < (unsigned int)blocks)
ctx->md.Nh++;
} else {
rc4_off = 0;
md5_off = 0;
}
#endif
MD5_Update(&ctx->md, in + md5_off, plen - md5_off);
if (plen != len) { /* "TLS" mode of operation */
if (in != out)
memcpy(out + rc4_off, in + rc4_off, plen - rc4_off);
/* calculate HMAC and append it to payload */
MD5_Final(out + plen, &ctx->md);
ctx->md = ctx->tail;
MD5_Update(&ctx->md, out + plen, MD5_DIGEST_LENGTH);
MD5_Final(out + plen, &ctx->md);
/* encrypt HMAC at once */
RC4(ks, len - rc4_off, out + rc4_off, out + rc4_off);
} else {
RC4(ks, len - rc4_off, in + rc4_off, out + rc4_off);
}
} else {
unsigned char mac[MD5_DIGEST_LENGTH];
#if defined(STITCHED_CALL)
/* digest has to "fall behind" */
if (md5_off > rc4_off)
rc4_off += 2 * MD5_CBLOCK;
else
rc4_off += MD5_CBLOCK;
if (len > rc4_off
&& (blocks = (len - rc4_off) / MD5_CBLOCK)
&& (OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) {
RC4(ks, rc4_off, in, out);
MD5_Update(&ctx->md, out, md5_off);
rc4_md5_enc(ks, in + rc4_off, out + rc4_off,
&ctx->md, out + md5_off, blocks);
blocks *= MD5_CBLOCK;
rc4_off += blocks;
md5_off += blocks;
l = (ctx->md.Nl + (blocks << 3)) & 0xffffffffU;
if (l < ctx->md.Nl)
ctx->md.Nh++;
ctx->md.Nl = l;
ctx->md.Nh += blocks >> 29;
} else {
md5_off = 0;
rc4_off = 0;
}
#endif
/* decrypt HMAC at once */
RC4(ks, len - rc4_off, in + rc4_off, out + rc4_off);
if (plen != NO_PAYLOAD_LENGTH) {
/* "TLS" mode of operation */
MD5_Update(&ctx->md, out + md5_off, plen - md5_off);
/* calculate HMAC and verify it */
MD5_Final(mac, &ctx->md);
ctx->md = ctx->tail;
MD5_Update(&ctx->md, mac, MD5_DIGEST_LENGTH);
MD5_Final(mac, &ctx->md);
if (CRYPTO_memcmp(out + plen, mac, MD5_DIGEST_LENGTH))
return 0;
} else {
MD5_Update(&ctx->md, out + md5_off, len - md5_off);
}
}
ctx->payload_length = NO_PAYLOAD_LENGTH;
return 1;
}
static int cipher_hw_rc4_hmac_md5_tls_init(PROV_CIPHER_CTX *bctx,
unsigned char *aad, size_t aad_len)
{
PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)bctx;
unsigned int len;
if (aad_len != EVP_AEAD_TLS1_AAD_LEN)
return 0;
len = aad[aad_len - 2] << 8 | aad[aad_len - 1];
if (!bctx->enc) {
if (len < MD5_DIGEST_LENGTH)
return 0;
len -= MD5_DIGEST_LENGTH;
aad[aad_len - 2] = len >> 8;
aad[aad_len - 1] = len;
}
ctx->payload_length = len;
ctx->md = ctx->head;
MD5_Update(&ctx->md, aad, aad_len);
return MD5_DIGEST_LENGTH;
}
static void cipher_hw_rc4_hmac_md5_init_mackey(PROV_CIPHER_CTX *bctx,
const unsigned char *key,
size_t len)
{
PROV_RC4_HMAC_MD5_CTX *ctx = (PROV_RC4_HMAC_MD5_CTX *)bctx;
unsigned int i;
unsigned char hmac_key[64];
memset(hmac_key, 0, sizeof(hmac_key));
if (len > (int)sizeof(hmac_key)) {
MD5_Init(&ctx->head);
MD5_Update(&ctx->head, key, len);
MD5_Final(hmac_key, &ctx->head);
} else {
memcpy(hmac_key, key, len);
}
for (i = 0; i < sizeof(hmac_key); i++)
hmac_key[i] ^= 0x36; /* ipad */
MD5_Init(&ctx->head);
MD5_Update(&ctx->head, hmac_key, sizeof(hmac_key));
for (i = 0; i < sizeof(hmac_key); i++)
hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */
MD5_Init(&ctx->tail);
MD5_Update(&ctx->tail, hmac_key, sizeof(hmac_key));
OPENSSL_cleanse(hmac_key, sizeof(hmac_key));
}
static const PROV_CIPHER_HW_RC4_HMAC_MD5 rc4_hmac_md5_hw = {
{
cipher_hw_rc4_hmac_md5_initkey,
cipher_hw_rc4_hmac_md5_cipher
},
cipher_hw_rc4_hmac_md5_tls_init,
cipher_hw_rc4_hmac_md5_init_mackey
};
const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc4_hmac_md5(size_t keybits)
{
return (PROV_CIPHER_HW *)&rc4_hmac_md5_hw;
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2019-2020 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
*/
/*
* RC4 low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_rc4.h"
static int cipher_hw_rc4_initkey(PROV_CIPHER_CTX *ctx,
const unsigned char *key, size_t keylen)
{
PROV_RC4_CTX *rctx = (PROV_RC4_CTX *)ctx;
RC4_set_key(&rctx->ks.ks, keylen, key);
return 1;
}
static int cipher_hw_rc4_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
PROV_RC4_CTX *rctx = (PROV_RC4_CTX *)ctx;
RC4(&rctx->ks.ks, len, in, out);
return 1;
}
static const PROV_CIPHER_HW rc4_hw = {
cipher_hw_rc4_initkey,
cipher_hw_rc4_cipher
};
const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc4(size_t keybits)
{
return &rc4_hw;
}

View File

@@ -0,0 +1,186 @@
/*
* Copyright 2019-2023 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 RC5 cipher modes ecb, cbc, ofb, cfb */
/*
* RC5 low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include <openssl/proverr.h>
#include "cipher_rc5.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
#define RC5_FLAGS PROV_CIPHER_FLAG_VARIABLE_LENGTH
static OSSL_FUNC_cipher_encrypt_init_fn rc5_einit;
static OSSL_FUNC_cipher_decrypt_init_fn rc5_dinit;
static OSSL_FUNC_cipher_freectx_fn rc5_freectx;
static OSSL_FUNC_cipher_dupctx_fn rc5_dupctx;
OSSL_FUNC_cipher_gettable_ctx_params_fn rc5_gettable_ctx_params;
OSSL_FUNC_cipher_settable_ctx_params_fn rc5_settable_ctx_params;
static OSSL_FUNC_cipher_set_ctx_params_fn rc5_set_ctx_params;
static void rc5_freectx(void *vctx)
{
PROV_RC5_CTX *ctx = (PROV_RC5_CTX *)vctx;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static void *rc5_dupctx(void *ctx)
{
PROV_RC5_CTX *in = (PROV_RC5_CTX *)ctx;
PROV_RC5_CTX *ret;
if (!ossl_prov_is_running())
return NULL;
ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL)
return NULL;
*ret = *in;
return ret;
}
static int rc5_einit(void *ctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
if (!ossl_cipher_generic_einit(ctx, key, keylen, iv, ivlen, NULL))
return 0;
return rc5_set_ctx_params(ctx, params);
}
static int rc5_dinit(void *ctx, const unsigned char *key, size_t keylen,
const unsigned char *iv, size_t ivlen,
const OSSL_PARAM params[])
{
if (!ossl_cipher_generic_dinit(ctx, key, keylen, iv, ivlen, NULL))
return 0;
return rc5_set_ctx_params(ctx, params);
}
static int rc5_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_RC5_CTX *ctx = (PROV_RC5_CTX *)vctx;
const OSSL_PARAM *p;
if (params == NULL)
return 1;
if (!ossl_cipher_var_keylen_set_ctx_params(vctx, params))
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_ROUNDS);
if (p != NULL) {
unsigned int rounds;
if (!OSSL_PARAM_get_uint(p, &rounds)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
return 0;
}
if (rounds != RC5_8_ROUNDS
&& rounds != RC5_12_ROUNDS
&& rounds != RC5_16_ROUNDS) {
ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS);
return 0;
}
ctx->rounds = rounds;
}
return 1;
}
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(rc5)
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_ROUNDS, NULL),
CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(rc5)
CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(rc5)
OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
OSSL_PARAM_uint(OSSL_CIPHER_PARAM_ROUNDS, NULL),
CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(rc5)
static int rc5_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
PROV_RC5_CTX *ctx = (PROV_RC5_CTX *)vctx;
OSSL_PARAM *p;
if (!ossl_cipher_generic_get_ctx_params(vctx, params))
return 0;
p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_ROUNDS);
if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->rounds)) {
ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
return 0;
}
return 1;
}
#define IMPLEMENT_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \
blkbits, ivbits, typ) \
static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lcmode##_get_params; \
static int alg##_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \
{ \
return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
flags, kbits, blkbits, ivbits); \
} \
static OSSL_FUNC_cipher_newctx_fn alg##_##kbits##_##lcmode##_newctx; \
static void *alg##_##kbits##_##lcmode##_newctx(void *provctx) \
{ \
PROV_##UCALG##_CTX *ctx; \
if (!ossl_prov_is_running()) \
return NULL; \
ctx = OPENSSL_zalloc(sizeof(*ctx)); \
if (ctx != NULL) { \
ossl_cipher_generic_initkey(ctx, kbits, blkbits, ivbits, \
EVP_CIPH_##UCMODE##_MODE, flags, \
ossl_prov_cipher_hw_##alg##_##lcmode(kbits),\
NULL); \
ctx->rounds = RC5_12_ROUNDS; \
} \
return ctx; \
} \
const OSSL_DISPATCH ossl_##alg##kbits##lcmode##_functions[] = { \
{ OSSL_FUNC_CIPHER_NEWCTX, \
(void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))rc5_einit }, \
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))rc5_dinit }, \
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_cipher_generic_##typ##_update },\
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_cipher_generic_##typ##_final }, \
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_cipher_generic_cipher }, \
{ OSSL_FUNC_CIPHER_GET_PARAMS, \
(void (*)(void)) alg##_##kbits##_##lcmode##_get_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \
(void (*)(void))ossl_cipher_generic_gettable_params }, \
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \
(void (*)(void))rc5_get_ctx_params }, \
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \
(void (*)(void))rc5_gettable_ctx_params }, \
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \
(void (*)(void))rc5_set_ctx_params }, \
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \
(void (*)(void))rc5_settable_ctx_params }, \
OSSL_DISPATCH_END \
};
/* ossl_rc5128ecb_functions */
IMPLEMENT_cipher(rc5, RC5, ecb, ECB, RC5_FLAGS, 128, 64, 0, block)
/* ossl_rc5128cbc_functions */
IMPLEMENT_cipher(rc5, RC5, cbc, CBC, RC5_FLAGS, 128, 64, 64, block)
/* ossl_rc5128ofb64_functions */
IMPLEMENT_cipher(rc5, RC5, ofb64, OFB, RC5_FLAGS, 128, 8, 64, stream)
/* ossl_rc5128cfb64_functions */
IMPLEMENT_cipher(rc5, RC5, cfb64, CFB, RC5_FLAGS, 128, 8, 64, stream)

View File

@@ -0,0 +1,25 @@
/*
* Copyright 2019-2020 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/rc5.h>
#include "prov/ciphercommon.h"
typedef struct prov_rc5_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
RC5_32_KEY ks; /* key schedule */
} ks;
unsigned int rounds; /* number of rounds */
} PROV_RC5_CTX;
const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc5_cbc(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc5_ecb(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc5_ofb64(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc5_cfb64(size_t keybits);

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2019-2020 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
*/
/*
* RC5 low level APIs are deprecated for public use, but still ok for internal
* use.
*/
#include "internal/deprecated.h"
#include "cipher_rc5.h"
static int cipher_hw_rc5_initkey(PROV_CIPHER_CTX *ctx,
const unsigned char *key, size_t keylen)
{
PROV_RC5_CTX *rctx = (PROV_RC5_CTX *)ctx;
return RC5_32_set_key(&rctx->ks.ks, keylen, key, rctx->rounds);
}
# define PROV_CIPHER_HW_rc5_mode(mode, UCMODE) \
IMPLEMENT_CIPHER_HW_##UCMODE(mode, rc5, PROV_RC5_CTX, RC5_32_KEY, \
RC5_32_##mode) \
static const PROV_CIPHER_HW rc5_##mode = { \
cipher_hw_rc5_initkey, \
cipher_hw_rc5_##mode##_cipher \
}; \
const PROV_CIPHER_HW *ossl_prov_cipher_hw_rc5_##mode(size_t keybits) \
{ \
return &rc5_##mode; \
}
PROV_CIPHER_HW_rc5_mode(cbc, CBC)
PROV_CIPHER_HW_rc5_mode(ecb, ECB)
PROV_CIPHER_HW_rc5_mode(ofb64, OFB)
PROV_CIPHER_HW_rc5_mode(cfb64, CFB)

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2019-2020 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 Seed cipher modes ecb, cbc, ofb, cfb */
/*
* SEED low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include "cipher_seed.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
static OSSL_FUNC_cipher_freectx_fn seed_freectx;
static OSSL_FUNC_cipher_dupctx_fn seed_dupctx;
static void seed_freectx(void *vctx)
{
PROV_SEED_CTX *ctx = (PROV_SEED_CTX *)vctx;
ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx);
OPENSSL_clear_free(ctx, sizeof(*ctx));
}
static void *seed_dupctx(void *ctx)
{
PROV_SEED_CTX *in = (PROV_SEED_CTX *)ctx;
PROV_SEED_CTX *ret;
if (!ossl_prov_is_running())
return NULL;
ret = OPENSSL_malloc(sizeof(*ret));
if (ret == NULL)
return NULL;
*ret = *in;
return ret;
}
/* ossl_seed128ecb_functions */
IMPLEMENT_generic_cipher(seed, SEED, ecb, ECB, 0, 128, 128, 0, block)
/* ossl_seed128cbc_functions */
IMPLEMENT_generic_cipher(seed, SEED, cbc, CBC, 0, 128, 128, 128, block)
/* ossl_seed128ofb128_functions */
IMPLEMENT_generic_cipher(seed, SEED, ofb128, OFB, 0, 128, 8, 128, stream)
/* ossl_seed128cfb128_functions */
IMPLEMENT_generic_cipher(seed, SEED, cfb128, CFB, 0, 128, 8, 128, stream)

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2019-2020 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/seed.h>
#include "prov/ciphercommon.h"
typedef struct prov_seed_ctx_st {
PROV_CIPHER_CTX base; /* Must be first */
union {
OSSL_UNION_ALIGN;
SEED_KEY_SCHEDULE ks;
} ks;
} PROV_SEED_CTX;
const PROV_CIPHER_HW *ossl_prov_cipher_hw_seed_cbc(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_seed_ecb(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_seed_ofb128(size_t keybits);
const PROV_CIPHER_HW *ossl_prov_cipher_hw_seed_cfb128(size_t keybits);

Some files were not shown because too many files have changed in this diff Show More