summaryrefslogtreecommitdiff
path: root/crypto/evp
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/evp')
-rw-r--r--crypto/evp/Makefile52
-rw-r--r--crypto/evp/c_allc.c11
-rw-r--r--crypto/evp/digest.c12
-rw-r--r--crypto/evp/e_aes.c962
-rw-r--r--crypto/evp/e_aes_cbc_hmac_sha1.c460
-rw-r--r--crypto/evp/e_aes_cbc_hmac_sha256.c973
-rw-r--r--crypto/evp/e_camellia.c321
-rw-r--r--crypto/evp/e_des.c59
-rw-r--r--crypto/evp/e_des3.c273
-rw-r--r--crypto/evp/e_null.c3
-rw-r--r--crypto/evp/encode.c2
-rw-r--r--crypto/evp/evp.h56
-rw-r--r--crypto/evp/evp_enc.c17
-rw-r--r--crypto/evp/evp_err.c5
-rw-r--r--crypto/evp/evp_extra_test.c2
-rw-r--r--crypto/evp/evp_fips.c310
-rw-r--r--crypto/evp/evp_lib.c62
-rw-r--r--crypto/evp/evp_locl.h3
-rw-r--r--crypto/evp/evp_test.c202
-rw-r--r--crypto/evp/evptests.txt67
-rw-r--r--crypto/evp/m_dss.c2
-rw-r--r--crypto/evp/m_dss1.c3
-rw-r--r--crypto/evp/m_ecdsa.c2
-rw-r--r--crypto/evp/m_sha1.c28
-rw-r--r--crypto/evp/m_sigver.c44
-rw-r--r--crypto/evp/p_lib.c2
-rw-r--r--crypto/evp/pmeth_lib.c6
27 files changed, 3325 insertions, 614 deletions
diff --git a/crypto/evp/Makefile b/crypto/evp/Makefile
index ed1502d3a694..aaaad986e0e8 100644
--- a/crypto/evp/Makefile
+++ b/crypto/evp/Makefile
@@ -28,8 +28,8 @@ LIBSRC= encode.c digest.c evp_enc.c evp_key.c evp_acnf.c evp_cnf.c \
bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \
c_all.c c_allc.c c_alld.c evp_lib.c bio_ok.c \
evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c \
- e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c evp_fips.c \
- e_aes_cbc_hmac_sha1.c e_rc4_hmac_md5.c
+ e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \
+ e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c
LIBOBJ= encode.o digest.o evp_enc.o evp_key.o evp_acnf.o evp_cnf.o \
e_des.o e_bf.o e_idea.o e_des3.o e_camellia.o\
@@ -41,8 +41,8 @@ LIBOBJ= encode.o digest.o evp_enc.o evp_key.o evp_acnf.o evp_cnf.o \
bio_md.o bio_b64.o bio_enc.o evp_err.o e_null.o \
c_all.o c_allc.o c_alld.o evp_lib.o bio_ok.o \
evp_pkey.o evp_pbe.o p5_crpt.o p5_crpt2.o \
- e_old.o pmeth_lib.o pmeth_fn.o pmeth_gn.o m_sigver.o evp_fips.o \
- e_aes_cbc_hmac_sha1.o e_rc4_hmac_md5.o
+ e_old.o pmeth_lib.o pmeth_fn.o pmeth_gn.o m_sigver.o \
+ e_aes_cbc_hmac_sha1.o e_aes_cbc_hmac_sha256.o e_rc4_hmac_md5.o
SRC= $(LIBSRC)
@@ -204,16 +204,36 @@ e_aes_cbc_hmac_sha1.o: ../../include/openssl/bio.h
e_aes_cbc_hmac_sha1.o: ../../include/openssl/crypto.h
e_aes_cbc_hmac_sha1.o: ../../include/openssl/e_os2.h
e_aes_cbc_hmac_sha1.o: ../../include/openssl/evp.h
+e_aes_cbc_hmac_sha1.o: ../../include/openssl/modes.h
e_aes_cbc_hmac_sha1.o: ../../include/openssl/obj_mac.h
e_aes_cbc_hmac_sha1.o: ../../include/openssl/objects.h
e_aes_cbc_hmac_sha1.o: ../../include/openssl/opensslconf.h
e_aes_cbc_hmac_sha1.o: ../../include/openssl/opensslv.h
e_aes_cbc_hmac_sha1.o: ../../include/openssl/ossl_typ.h
+e_aes_cbc_hmac_sha1.o: ../../include/openssl/rand.h
e_aes_cbc_hmac_sha1.o: ../../include/openssl/safestack.h
e_aes_cbc_hmac_sha1.o: ../../include/openssl/sha.h
e_aes_cbc_hmac_sha1.o: ../../include/openssl/stack.h
-e_aes_cbc_hmac_sha1.o: ../../include/openssl/symhacks.h e_aes_cbc_hmac_sha1.c
-e_aes_cbc_hmac_sha1.o: evp_locl.h
+e_aes_cbc_hmac_sha1.o: ../../include/openssl/symhacks.h ../modes/modes_lcl.h
+e_aes_cbc_hmac_sha1.o: e_aes_cbc_hmac_sha1.c
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/aes.h
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/asn1.h
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/bio.h
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/crypto.h
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/e_os2.h
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/evp.h
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/modes.h
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/obj_mac.h
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/objects.h
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/opensslconf.h
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/opensslv.h
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/ossl_typ.h
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/rand.h
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/safestack.h
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/sha.h
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/stack.h
+e_aes_cbc_hmac_sha256.o: ../../include/openssl/symhacks.h ../modes/modes_lcl.h
+e_aes_cbc_hmac_sha256.o: e_aes_cbc_hmac_sha256.c
e_bf.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
e_bf.o: ../../include/openssl/blowfish.h ../../include/openssl/buffer.h
e_bf.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
@@ -227,11 +247,13 @@ e_camellia.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
e_camellia.o: ../../include/openssl/camellia.h ../../include/openssl/crypto.h
e_camellia.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h
e_camellia.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
-e_camellia.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+e_camellia.o: ../../include/openssl/modes.h ../../include/openssl/obj_mac.h
+e_camellia.o: ../../include/openssl/objects.h
e_camellia.o: ../../include/openssl/opensslconf.h
e_camellia.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
e_camellia.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
-e_camellia.o: ../../include/openssl/symhacks.h e_camellia.c evp_locl.h
+e_camellia.o: ../../include/openssl/symhacks.h ../modes/modes_lcl.h
+e_camellia.o: e_camellia.c evp_locl.h
e_cast.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
e_cast.o: ../../include/openssl/buffer.h ../../include/openssl/cast.h
e_cast.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
@@ -260,9 +282,10 @@ e_des3.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
e_des3.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
e_des3.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
e_des3.o: ../../include/openssl/ossl_typ.h ../../include/openssl/rand.h
-e_des3.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
-e_des3.o: ../../include/openssl/symhacks.h ../../include/openssl/ui.h
-e_des3.o: ../../include/openssl/ui_compat.h ../cryptlib.h e_des3.c evp_locl.h
+e_des3.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+e_des3.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+e_des3.o: ../../include/openssl/ui.h ../../include/openssl/ui_compat.h
+e_des3.o: ../cryptlib.h e_des3.c evp_locl.h
e_idea.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
e_idea.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
e_idea.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h
@@ -394,13 +417,6 @@ evp_err.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
evp_err.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
evp_err.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
evp_err.o: ../../include/openssl/symhacks.h evp_err.c
-evp_fips.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
-evp_fips.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
-evp_fips.o: ../../include/openssl/evp.h ../../include/openssl/obj_mac.h
-evp_fips.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
-evp_fips.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
-evp_fips.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
-evp_fips.o: ../../include/openssl/symhacks.h evp_fips.c
evp_key.o: ../../e_os.h ../../include/openssl/asn1.h
evp_key.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
evp_key.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
diff --git a/crypto/evp/c_allc.c b/crypto/evp/c_allc.c
index 3097c2112efc..280e58408f2b 100644
--- a/crypto/evp/c_allc.c
+++ b/crypto/evp/c_allc.c
@@ -93,6 +93,7 @@ void OpenSSL_add_all_ciphers(void)
EVP_add_cipher(EVP_des_ecb());
EVP_add_cipher(EVP_des_ede());
EVP_add_cipher(EVP_des_ede3());
+ EVP_add_cipher(EVP_des_ede3_wrap());
#endif
#ifndef OPENSSL_NO_RC4
@@ -172,6 +173,8 @@ void OpenSSL_add_all_ciphers(void)
EVP_add_cipher(EVP_aes_128_ctr());
EVP_add_cipher(EVP_aes_128_gcm());
EVP_add_cipher(EVP_aes_128_xts());
+ EVP_add_cipher(EVP_aes_128_ccm());
+ EVP_add_cipher(EVP_aes_128_wrap());
EVP_add_cipher_alias(SN_aes_128_cbc, "AES128");
EVP_add_cipher_alias(SN_aes_128_cbc, "aes128");
EVP_add_cipher(EVP_aes_192_ecb());
@@ -182,6 +185,8 @@ void OpenSSL_add_all_ciphers(void)
EVP_add_cipher(EVP_aes_192_ofb());
EVP_add_cipher(EVP_aes_192_ctr());
EVP_add_cipher(EVP_aes_192_gcm());
+ EVP_add_cipher(EVP_aes_192_ccm());
+ EVP_add_cipher(EVP_aes_192_wrap());
EVP_add_cipher_alias(SN_aes_192_cbc, "AES192");
EVP_add_cipher_alias(SN_aes_192_cbc, "aes192");
EVP_add_cipher(EVP_aes_256_ecb());
@@ -193,12 +198,18 @@ void OpenSSL_add_all_ciphers(void)
EVP_add_cipher(EVP_aes_256_ctr());
EVP_add_cipher(EVP_aes_256_gcm());
EVP_add_cipher(EVP_aes_256_xts());
+ EVP_add_cipher(EVP_aes_256_ccm());
+ EVP_add_cipher(EVP_aes_256_wrap());
EVP_add_cipher_alias(SN_aes_256_cbc, "AES256");
EVP_add_cipher_alias(SN_aes_256_cbc, "aes256");
# if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
EVP_add_cipher(EVP_aes_128_cbc_hmac_sha1());
EVP_add_cipher(EVP_aes_256_cbc_hmac_sha1());
# endif
+# if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA256)
+ EVP_add_cipher(EVP_aes_128_cbc_hmac_sha256());
+ EVP_add_cipher(EVP_aes_256_cbc_hmac_sha256());
+# endif
#endif
#ifndef OPENSSL_NO_CAMELLIA
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index 2e202c8fe031..f2643f32486a 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -119,6 +119,7 @@
#ifdef OPENSSL_FIPS
# include <openssl/fips.h>
+# include "evp_locl.h"
#endif
void EVP_MD_CTX_init(EVP_MD_CTX *ctx)
@@ -145,6 +146,17 @@ int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
{
EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
+#ifdef OPENSSL_FIPS
+ /* If FIPS mode switch to approved implementation if possible */
+ if (FIPS_mode()) {
+ const EVP_MD *fipsmd;
+ if (type) {
+ fipsmd = evp_get_fips_md(type);
+ if (fipsmd)
+ type = fipsmd;
+ }
+ }
+#endif
#ifndef OPENSSL_NO_ENGINE
/*
* Whether it's nice or not, "Inits" can be used on "Final"'d contexts so
diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c
index a4327fcb0554..1734a823c1e5 100644
--- a/crypto/evp/e_aes.c
+++ b/crypto/evp/e_aes.c
@@ -57,12 +57,17 @@
# include <assert.h>
# include <openssl/aes.h>
# include "evp_locl.h"
-# ifndef OPENSSL_FIPS
-# include "modes_lcl.h"
-# include <openssl/rand.h>
+# include "modes_lcl.h"
+# include <openssl/rand.h>
+
+# undef EVP_CIPH_FLAG_FIPS
+# define EVP_CIPH_FLAG_FIPS 0
typedef struct {
- AES_KEY ks;
+ union {
+ double align;
+ AES_KEY ks;
+ } ks;
block128_f block;
union {
cbc128_f cbc;
@@ -71,7 +76,10 @@ typedef struct {
} EVP_AES_KEY;
typedef struct {
- AES_KEY ks; /* AES key schedule to use */
+ union {
+ double align;
+ AES_KEY ks;
+ } ks; /* AES key schedule to use */
int key_set; /* Set if key initialised */
int iv_set; /* Set if an iv is set */
GCM128_CONTEXT gcm;
@@ -84,7 +92,10 @@ typedef struct {
} EVP_AES_GCM_CTX;
typedef struct {
- AES_KEY ks1, ks2; /* AES key schedules to use */
+ union {
+ double align;
+ AES_KEY ks;
+ } ks1, ks2; /* AES key schedules to use */
XTS128_CONTEXT xts;
void (*stream) (const unsigned char *in,
unsigned char *out, size_t length,
@@ -93,7 +104,10 @@ typedef struct {
} EVP_AES_XTS_CTX;
typedef struct {
- AES_KEY ks; /* AES key schedule to use */
+ union {
+ double align;
+ AES_KEY ks;
+ } ks; /* AES key schedule to use */
int key_set; /* Set if key initialised */
int iv_set; /* Set if an iv is set */
int tag_set; /* Set if tag is valid */
@@ -103,9 +117,9 @@ typedef struct {
ccm128_f str;
} EVP_AES_CCM_CTX;
-# define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4))
+# define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4))
-# ifdef VPAES_ASM
+# ifdef VPAES_ASM
int vpaes_set_encrypt_key(const unsigned char *userKey, int bits,
AES_KEY *key);
int vpaes_set_decrypt_key(const unsigned char *userKey, int bits,
@@ -120,8 +134,8 @@ void vpaes_cbc_encrypt(const unsigned char *in,
unsigned char *out,
size_t length,
const AES_KEY *key, unsigned char *ivec, int enc);
-# endif
-# ifdef BSAES_ASM
+# endif
+# ifdef BSAES_ASM
void bsaes_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char ivec[16], int enc);
@@ -134,40 +148,54 @@ void bsaes_xts_encrypt(const unsigned char *inp, unsigned char *out,
void bsaes_xts_decrypt(const unsigned char *inp, unsigned char *out,
size_t len, const AES_KEY *key1,
const AES_KEY *key2, const unsigned char iv[16]);
-# endif
-# ifdef AES_CTR_ASM
+# endif
+# ifdef AES_CTR_ASM
void AES_ctr32_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key,
const unsigned char ivec[AES_BLOCK_SIZE]);
-# endif
-# ifdef AES_XTS_ASM
+# endif
+# ifdef AES_XTS_ASM
void AES_xts_encrypt(const char *inp, char *out, size_t len,
const AES_KEY *key1, const AES_KEY *key2,
const unsigned char iv[16]);
void AES_xts_decrypt(const char *inp, char *out, size_t len,
const AES_KEY *key1, const AES_KEY *key2,
const unsigned char iv[16]);
+# endif
+
+# if defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC))
+# include "ppc_arch.h"
+# ifdef VPAES_ASM
+# define VPAES_CAPABLE (OPENSSL_ppccap_P & PPC_ALTIVEC)
# endif
+# define HWAES_CAPABLE (OPENSSL_ppccap_P & PPC_CRYPTO207)
+# define HWAES_set_encrypt_key aes_p8_set_encrypt_key
+# define HWAES_set_decrypt_key aes_p8_set_decrypt_key
+# define HWAES_encrypt aes_p8_encrypt
+# define HWAES_decrypt aes_p8_decrypt
+# define HWAES_cbc_encrypt aes_p8_cbc_encrypt
+# define HWAES_ctr32_encrypt_blocks aes_p8_ctr32_encrypt_blocks
+# endif
-# if defined(AES_ASM) && !defined(I386_ONLY) && ( \
+# if defined(AES_ASM) && !defined(I386_ONLY) && ( \
((defined(__i386) || defined(__i386__) || \
defined(_M_IX86)) && defined(OPENSSL_IA32_SSE2))|| \
defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64) || \
defined(__INTEL__) )
-extern unsigned int OPENSSL_ia32cap_P[2];
+extern unsigned int OPENSSL_ia32cap_P[];
-# ifdef VPAES_ASM
-# define VPAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
-# endif
-# ifdef BSAES_ASM
-# define BSAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
-# endif
+# ifdef VPAES_ASM
+# define VPAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
+# endif
+# ifdef BSAES_ASM
+# define BSAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
+# endif
/*
* AES-NI section
*/
-# define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32)))
+# define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32)))
int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
AES_KEY *key);
@@ -218,6 +246,26 @@ void aesni_ccm64_decrypt_blocks(const unsigned char *in,
const unsigned char ivec[16],
unsigned char cmac[16]);
+# if defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
+size_t aesni_gcm_encrypt(const unsigned char *in,
+ unsigned char *out,
+ size_t len,
+ const void *key, unsigned char ivec[16], u64 *Xi);
+# define AES_gcm_encrypt aesni_gcm_encrypt
+size_t aesni_gcm_decrypt(const unsigned char *in,
+ unsigned char *out,
+ size_t len,
+ const void *key, unsigned char ivec[16], u64 *Xi);
+# define AES_gcm_decrypt aesni_gcm_decrypt
+void gcm_ghash_avx(u64 Xi[2], const u128 Htable[16], const u8 *in,
+ size_t len);
+# define AES_GCM_ASM(gctx) (gctx->ctr==aesni_ctr32_encrypt_blocks && \
+ gctx->gcm.ghash==gcm_ghash_avx)
+# define AES_GCM_ASM2(gctx) (gctx->gcm.block==(block128_f)aesni_encrypt && \
+ gctx->gcm.ghash==gcm_ghash_avx)
+# undef AES_GCM_ASM2 /* minor size optimization */
+# endif
+
static int aesni_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
@@ -271,23 +319,23 @@ static int aesni_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return 1;
}
-# define aesni_ofb_cipher aes_ofb_cipher
+# define aesni_ofb_cipher aes_ofb_cipher
static int aesni_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
-# define aesni_cfb_cipher aes_cfb_cipher
+# define aesni_cfb_cipher aes_cfb_cipher
static int aesni_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
-# define aesni_cfb8_cipher aes_cfb8_cipher
+# define aesni_cfb8_cipher aes_cfb8_cipher
static int aesni_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
-# define aesni_cfb1_cipher aes_cfb1_cipher
+# define aesni_cfb1_cipher aes_cfb1_cipher
static int aesni_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
-# define aesni_ctr_cipher aes_ctr_cipher
+# define aesni_ctr_cipher aes_ctr_cipher
static int aesni_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
@@ -298,7 +346,7 @@ static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
if (!iv && !key)
return 1;
if (key) {
- aesni_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks);
+ aesni_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) aesni_encrypt);
gctx->ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
/*
@@ -323,7 +371,7 @@ static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
return 1;
}
-# define aesni_gcm_cipher aes_gcm_cipher
+# define aesni_gcm_cipher aes_gcm_cipher
static int aesni_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
@@ -337,17 +385,17 @@ static int aesni_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
if (key) {
/* key_len is two AES keys */
if (enc) {
- aesni_set_encrypt_key(key, ctx->key_len * 4, &xctx->ks1);
+ aesni_set_encrypt_key(key, ctx->key_len * 4, &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) aesni_encrypt;
xctx->stream = aesni_xts_encrypt;
} else {
- aesni_set_decrypt_key(key, ctx->key_len * 4, &xctx->ks1);
+ aesni_set_decrypt_key(key, ctx->key_len * 4, &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) aesni_decrypt;
xctx->stream = aesni_xts_decrypt;
}
aesni_set_encrypt_key(key + ctx->key_len / 2,
- ctx->key_len * 4, &xctx->ks2);
+ ctx->key_len * 4, &xctx->ks2.ks);
xctx->xts.block2 = (block128_f) aesni_encrypt;
xctx->xts.key1 = &xctx->ks1;
@@ -361,7 +409,7 @@ static int aesni_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
return 1;
}
-# define aesni_xts_cipher aes_xts_cipher
+# define aesni_xts_cipher aes_xts_cipher
static int aesni_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
@@ -372,7 +420,7 @@ static int aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
if (!iv && !key)
return 1;
if (key) {
- aesni_set_encrypt_key(key, ctx->key_len * 8, &cctx->ks);
+ aesni_set_encrypt_key(key, ctx->key_len * 8, &cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
&cctx->ks, (block128_f) aesni_encrypt);
cctx->str = enc ? (ccm128_f) aesni_ccm64_encrypt_blocks :
@@ -386,11 +434,11 @@ static int aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
return 1;
}
-# define aesni_ccm_cipher aes_ccm_cipher
+# define aesni_ccm_cipher aes_ccm_cipher
static int aesni_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
-# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
+# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
static const EVP_CIPHER aesni_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
@@ -411,7 +459,7 @@ static const EVP_CIPHER aes_##keylen##_##mode = { \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; }
-# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
+# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
static const EVP_CIPHER aesni_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
(EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
@@ -433,9 +481,378 @@ static const EVP_CIPHER aes_##keylen##_##mode = { \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; }
+# elif defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
+
+# include "sparc_arch.h"
+
+extern unsigned int OPENSSL_sparcv9cap_P[];
+
+# define SPARC_AES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_AES)
+
+void aes_t4_set_encrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
+void aes_t4_set_decrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
+void aes_t4_encrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key);
+void aes_t4_decrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key);
+/*
+ * Key-length specific subroutines were chosen for following reason.
+ * Each SPARC T4 core can execute up to 8 threads which share core's
+ * resources. Loading as much key material to registers allows to
+ * minimize references to shared memory interface, as well as amount
+ * of instructions in inner loops [much needed on T4]. But then having
+ * non-key-length specific routines would require conditional branches
+ * either in inner loops or on subroutines' entries. Former is hardly
+ * acceptable, while latter means code size increase to size occupied
+ * by multiple key-length specfic subroutines, so why fight?
+ */
+void aes128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const AES_KEY *key,
+ unsigned char *ivec);
+void aes128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const AES_KEY *key,
+ unsigned char *ivec);
+void aes192_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const AES_KEY *key,
+ unsigned char *ivec);
+void aes192_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const AES_KEY *key,
+ unsigned char *ivec);
+void aes256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const AES_KEY *key,
+ unsigned char *ivec);
+void aes256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const AES_KEY *key,
+ unsigned char *ivec);
+void aes128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const AES_KEY *key,
+ unsigned char *ivec);
+void aes192_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const AES_KEY *key,
+ unsigned char *ivec);
+void aes256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const AES_KEY *key,
+ unsigned char *ivec);
+void aes128_t4_xts_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const AES_KEY *key1,
+ const AES_KEY *key2, const unsigned char *ivec);
+void aes128_t4_xts_decrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const AES_KEY *key1,
+ const AES_KEY *key2, const unsigned char *ivec);
+void aes256_t4_xts_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const AES_KEY *key1,
+ const AES_KEY *key2, const unsigned char *ivec);
+void aes256_t4_xts_decrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const AES_KEY *key1,
+ const AES_KEY *key2, const unsigned char *ivec);
+
+static int aes_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ int ret, mode, bits;
+ EVP_AES_KEY *dat = (EVP_AES_KEY *) ctx->cipher_data;
+
+ mode = ctx->cipher->flags & EVP_CIPH_MODE;
+ bits = ctx->key_len * 8;
+ if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
+ && !enc) {
+ ret = 0;
+ aes_t4_set_decrypt_key(key, bits, ctx->cipher_data);
+ dat->block = (block128_f) aes_t4_decrypt;
+ switch (bits) {
+ case 128:
+ dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
+ (cbc128_f) aes128_t4_cbc_decrypt : NULL;
+ break;
+ case 192:
+ dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
+ (cbc128_f) aes192_t4_cbc_decrypt : NULL;
+ break;
+ case 256:
+ dat->stream.cbc = 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, ctx->cipher_data);
+ dat->block = (block128_f) aes_t4_encrypt;
+ switch (bits) {
+ case 128:
+ if (mode == EVP_CIPH_CBC_MODE)
+ dat->stream.cbc = (cbc128_f) aes128_t4_cbc_encrypt;
+ else if (mode == EVP_CIPH_CTR_MODE)
+ dat->stream.ctr = (ctr128_f) aes128_t4_ctr32_encrypt;
+ else
+ dat->stream.cbc = NULL;
+ break;
+ case 192:
+ if (mode == EVP_CIPH_CBC_MODE)
+ dat->stream.cbc = (cbc128_f) aes192_t4_cbc_encrypt;
+ else if (mode == EVP_CIPH_CTR_MODE)
+ dat->stream.ctr = (ctr128_f) aes192_t4_ctr32_encrypt;
+ else
+ dat->stream.cbc = NULL;
+ break;
+ case 256:
+ if (mode == EVP_CIPH_CBC_MODE)
+ dat->stream.cbc = (cbc128_f) aes256_t4_cbc_encrypt;
+ else if (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) {
+ EVPerr(EVP_F_AES_T4_INIT_KEY, EVP_R_AES_KEY_SETUP_FAILED);
+ return 0;
+ }
+
+ return 1;
+}
+
+# define aes_t4_cbc_cipher aes_cbc_cipher
+static int aes_t4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+# define aes_t4_ecb_cipher aes_ecb_cipher
+static int aes_t4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+# define aes_t4_ofb_cipher aes_ofb_cipher
+static int aes_t4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+# define aes_t4_cfb_cipher aes_cfb_cipher
+static int aes_t4_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+# define aes_t4_cfb8_cipher aes_cfb8_cipher
+static int aes_t4_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+# define aes_t4_cfb1_cipher aes_cfb1_cipher
+static int aes_t4_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+# define aes_t4_ctr_cipher aes_ctr_cipher
+static int aes_t4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+static int aes_t4_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
+ if (!iv && !key)
+ return 1;
+ if (key) {
+ int bits = ctx->key_len * 8;
+ aes_t4_set_encrypt_key(key, bits, &gctx->ks.ks);
+ CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
+ (block128_f) aes_t4_encrypt);
+ switch (bits) {
+ case 128:
+ gctx->ctr = (ctr128_f) aes128_t4_ctr32_encrypt;
+ break;
+ case 192:
+ gctx->ctr = (ctr128_f) aes192_t4_ctr32_encrypt;
+ break;
+ case 256:
+ gctx->ctr = (ctr128_f) aes256_t4_ctr32_encrypt;
+ break;
+ default:
+ return 0;
+ }
+ /*
+ * If we have an iv can set it directly, otherwise use saved IV.
+ */
+ if (iv == NULL && gctx->iv_set)
+ iv = gctx->iv;
+ if (iv) {
+ CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
+ gctx->iv_set = 1;
+ }
+ gctx->key_set = 1;
+ } else {
+ /* If key set use IV, otherwise copy */
+ if (gctx->key_set)
+ CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
+ else
+ memcpy(gctx->iv, iv, gctx->ivlen);
+ gctx->iv_set = 1;
+ gctx->iv_gen = 0;
+ }
+ return 1;
+}
+
+# define aes_t4_gcm_cipher aes_gcm_cipher
+static int aes_t4_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+static int aes_t4_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ EVP_AES_XTS_CTX *xctx = ctx->cipher_data;
+ if (!iv && !key)
+ return 1;
+
+ if (key) {
+ int bits = ctx->key_len * 4;
+ xctx->stream = NULL;
+ /* key_len is two AES keys */
+ if (enc) {
+ aes_t4_set_encrypt_key(key, bits, &xctx->ks1.ks);
+ xctx->xts.block1 = (block128_f) aes_t4_encrypt;
+ switch (bits) {
+ case 128:
+ xctx->stream = aes128_t4_xts_encrypt;
+ break;
+# if 0 /* not yet */
+ case 192:
+ xctx->stream = aes192_t4_xts_encrypt;
+ break;
+# endif
+ case 256:
+ xctx->stream = aes256_t4_xts_encrypt;
+ break;
+ default:
+ return 0;
+ }
+ } else {
+ aes_t4_set_decrypt_key(key, ctx->key_len * 4, &xctx->ks1.ks);
+ xctx->xts.block1 = (block128_f) aes_t4_decrypt;
+ switch (bits) {
+ case 128:
+ xctx->stream = aes128_t4_xts_decrypt;
+ break;
+# if 0 /* not yet */
+ case 192:
+ xctx->stream = aes192_t4_xts_decrypt;
+ break;
+# endif
+ case 256:
+ xctx->stream = aes256_t4_xts_decrypt;
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ aes_t4_set_encrypt_key(key + ctx->key_len / 2,
+ ctx->key_len * 4, &xctx->ks2.ks);
+ xctx->xts.block2 = (block128_f) aes_t4_encrypt;
+
+ xctx->xts.key1 = &xctx->ks1;
+ }
+
+ if (iv) {
+ xctx->xts.key2 = &xctx->ks2;
+ memcpy(ctx->iv, iv, 16);
+ }
+
+ return 1;
+}
+
+# define aes_t4_xts_cipher aes_xts_cipher
+static int aes_t4_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+static int aes_t4_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ EVP_AES_CCM_CTX *cctx = ctx->cipher_data;
+ if (!iv && !key)
+ return 1;
+ if (key) {
+ int bits = ctx->key_len * 8;
+ aes_t4_set_encrypt_key(key, bits, &cctx->ks.ks);
+ CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
+ &cctx->ks, (block128_f) aes_t4_encrypt);
+# if 0 /* not yet */
+ switch (bits) {
+ case 128:
+ cctx->str = enc ? (ccm128_f) aes128_t4_ccm64_encrypt :
+ (ccm128_f) ae128_t4_ccm64_decrypt;
+ break;
+ case 192:
+ cctx->str = enc ? (ccm128_f) aes192_t4_ccm64_encrypt :
+ (ccm128_f) ae192_t4_ccm64_decrypt;
+ break;
+ case 256:
+ cctx->str = enc ? (ccm128_f) aes256_t4_ccm64_encrypt :
+ (ccm128_f) ae256_t4_ccm64_decrypt;
+ break;
+ default:
+ return 0;
+ }
# else
+ cctx->str = NULL;
+# endif
+ cctx->key_set = 1;
+ }
+ if (iv) {
+ memcpy(ctx->iv, iv, 15 - cctx->L);
+ cctx->iv_set = 1;
+ }
+ return 1;
+}
-# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
+# define aes_t4_ccm_cipher aes_ccm_cipher
+static int aes_t4_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
+static const EVP_CIPHER aes_t4_##keylen##_##mode = { \
+ nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
+ flags|EVP_CIPH_##MODE##_MODE, \
+ aes_t4_init_key, \
+ aes_t4_##mode##_cipher, \
+ NULL, \
+ sizeof(EVP_AES_KEY), \
+ NULL,NULL,NULL,NULL }; \
+static const EVP_CIPHER aes_##keylen##_##mode = { \
+ nid##_##keylen##_##nmode,blocksize, \
+ keylen/8,ivlen, \
+ flags|EVP_CIPH_##MODE##_MODE, \
+ aes_init_key, \
+ aes_##mode##_cipher, \
+ NULL, \
+ sizeof(EVP_AES_KEY), \
+ NULL,NULL,NULL,NULL }; \
+const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
+{ return SPARC_AES_CAPABLE?&aes_t4_##keylen##_##mode:&aes_##keylen##_##mode; }
+
+# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
+static const EVP_CIPHER aes_t4_##keylen##_##mode = { \
+ nid##_##keylen##_##mode,blocksize, \
+ (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
+ flags|EVP_CIPH_##MODE##_MODE, \
+ aes_t4_##mode##_init_key, \
+ aes_t4_##mode##_cipher, \
+ aes_##mode##_cleanup, \
+ sizeof(EVP_AES_##MODE##_CTX), \
+ NULL,NULL,aes_##mode##_ctrl,NULL }; \
+static const EVP_CIPHER aes_##keylen##_##mode = { \
+ nid##_##keylen##_##mode,blocksize, \
+ (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
+ flags|EVP_CIPH_##MODE##_MODE, \
+ aes_##mode##_init_key, \
+ aes_##mode##_cipher, \
+ aes_##mode##_cleanup, \
+ sizeof(EVP_AES_##MODE##_CTX), \
+ NULL,NULL,aes_##mode##_ctrl,NULL }; \
+const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
+{ return SPARC_AES_CAPABLE?&aes_t4_##keylen##_##mode:&aes_##keylen##_##mode; }
+
+# else
+
+# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
@@ -447,7 +864,7 @@ static const EVP_CIPHER aes_##keylen##_##mode = { \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return &aes_##keylen##_##mode; }
-# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
+# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
(EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
@@ -459,9 +876,42 @@ static const EVP_CIPHER aes_##keylen##_##mode = { \
NULL,NULL,aes_##mode##_ctrl,NULL }; \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return &aes_##keylen##_##mode; }
+# endif
+
+# if defined(OPENSSL_CPUID_OBJ) && (defined(__arm__) || defined(__arm) || defined(__aarch64__))
+# include "arm_arch.h"
+# if __ARM_MAX_ARCH__>=7
+# if defined(BSAES_ASM)
+# define BSAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
+# endif
+# define HWAES_CAPABLE (OPENSSL_armcap_P & ARMV8_AES)
+# define HWAES_set_encrypt_key aes_v8_set_encrypt_key
+# define HWAES_set_decrypt_key aes_v8_set_decrypt_key
+# define HWAES_encrypt aes_v8_encrypt
+# define HWAES_decrypt aes_v8_decrypt
+# define HWAES_cbc_encrypt aes_v8_cbc_encrypt
+# define HWAES_ctr32_encrypt_blocks aes_v8_ctr32_encrypt_blocks
# endif
+# endif
+
+# if defined(HWAES_CAPABLE)
+int HWAES_set_encrypt_key(const unsigned char *userKey, const int bits,
+ AES_KEY *key);
+int HWAES_set_decrypt_key(const unsigned char *userKey, const int bits,
+ AES_KEY *key);
+void HWAES_encrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key);
+void HWAES_decrypt(const unsigned char *in, unsigned char *out,
+ const AES_KEY *key);
+void HWAES_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ size_t length, const AES_KEY *key,
+ unsigned char *ivec, const int enc);
+void HWAES_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
+ size_t len, const AES_KEY *key,
+ const unsigned char ivec[16]);
+# endif
-# define BLOCK_CIPHER_generic_pack(nid,keylen,flags) \
+# define BLOCK_CIPHER_generic_pack(nid,keylen,flags) \
BLOCK_CIPHER_generic(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
BLOCK_CIPHER_generic(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
BLOCK_CIPHER_generic(nid,keylen,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
@@ -479,51 +929,80 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
mode = ctx->cipher->flags & EVP_CIPH_MODE;
if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
&& !enc)
-# ifdef BSAES_CAPABLE
+# ifdef HWAES_CAPABLE
+ if (HWAES_CAPABLE) {
+ ret = HWAES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
+ dat->block = (block128_f) HWAES_decrypt;
+ dat->stream.cbc = NULL;
+# ifdef HWAES_cbc_encrypt
+ if (mode == EVP_CIPH_CBC_MODE)
+ dat->stream.cbc = (cbc128_f) HWAES_cbc_encrypt;
+# endif
+ } else
+# endif
+# ifdef BSAES_CAPABLE
if (BSAES_CAPABLE && mode == EVP_CIPH_CBC_MODE) {
- ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks);
+ ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
dat->block = (block128_f) AES_decrypt;
dat->stream.cbc = (cbc128_f) bsaes_cbc_encrypt;
} else
-# endif
-# ifdef VPAES_CAPABLE
+# endif
+# ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
- ret = vpaes_set_decrypt_key(key, ctx->key_len * 8, &dat->ks);
+ ret = vpaes_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
dat->block = (block128_f) vpaes_decrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) vpaes_cbc_encrypt : NULL;
} else
-# endif
+# endif
{
- ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks);
+ ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
dat->block = (block128_f) AES_decrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) AES_cbc_encrypt : NULL;
} else
-# ifdef BSAES_CAPABLE
+# ifdef HWAES_CAPABLE
+ if (HWAES_CAPABLE) {
+ ret = HWAES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
+ dat->block = (block128_f) HWAES_encrypt;
+ dat->stream.cbc = NULL;
+# ifdef HWAES_cbc_encrypt
+ if (mode == EVP_CIPH_CBC_MODE)
+ dat->stream.cbc = (cbc128_f) HWAES_cbc_encrypt;
+ else
+# endif
+# ifdef HWAES_ctr32_encrypt_blocks
+ if (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 && mode == EVP_CIPH_CTR_MODE) {
- ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks);
+ ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
dat->block = (block128_f) AES_encrypt;
dat->stream.ctr = (ctr128_f) bsaes_ctr32_encrypt_blocks;
} else
-# endif
-# ifdef VPAES_CAPABLE
+# endif
+# ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
- ret = vpaes_set_encrypt_key(key, ctx->key_len * 8, &dat->ks);
+ ret = vpaes_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
dat->block = (block128_f) vpaes_encrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) vpaes_cbc_encrypt : NULL;
} else
-# endif
+# endif
{
- ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks);
+ ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
dat->block = (block128_f) AES_encrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) AES_cbc_encrypt : NULL;
-# ifdef AES_CTR_ASM
+# ifdef AES_CTR_ASM
if (mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f) AES_ctr32_encrypt;
-# endif
+# endif
}
if (ret < 0) {
@@ -544,7 +1023,7 @@ static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
else if (ctx->encrypt)
CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv, dat->block);
else
- CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv, dat->block);
+ CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, ctx->iv, dat->block);
return 1;
}
@@ -680,11 +1159,6 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
case EVP_CTRL_GCM_SET_IVLEN:
if (arg <= 0)
return 0;
-# ifdef OPENSSL_FIPS
- if (FIPS_module_mode() && !(c->flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW)
- && arg < 12)
- return 0;
-# endif
/* Allocate memory for IV if needed */
if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen)) {
if (gctx->iv != c->iv)
@@ -805,34 +1279,47 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
return 1;
if (key) {
do {
-# ifdef BSAES_CAPABLE
+# ifdef HWAES_CAPABLE
+ if (HWAES_CAPABLE) {
+ HWAES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
+ CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
+ (block128_f) HWAES_encrypt);
+# ifdef HWAES_ctr32_encrypt_blocks
+ gctx->ctr = (ctr128_f) HWAES_ctr32_encrypt_blocks;
+# else
+ gctx->ctr = NULL;
+# endif
+ break;
+ } else
+# endif
+# ifdef BSAES_CAPABLE
if (BSAES_CAPABLE) {
- AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks);
+ AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
(block128_f) AES_encrypt);
gctx->ctr = (ctr128_f) bsaes_ctr32_encrypt_blocks;
break;
} else
-# endif
-# ifdef VPAES_CAPABLE
+# endif
+# ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
- vpaes_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks);
+ vpaes_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
(block128_f) vpaes_encrypt);
gctx->ctr = NULL;
break;
} else
-# endif
+# endif
(void)0; /* terminate potentially open 'else' */
- AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks);
+ AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
(block128_f) AES_encrypt);
-# ifdef AES_CTR_ASM
+# ifdef AES_CTR_ASM
gctx->ctr = (ctr128_f) AES_ctr32_encrypt;
-# else
+# else
gctx->ctr = NULL;
-# endif
+# endif
} while (0);
/*
@@ -891,11 +1378,38 @@ static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
if (ctx->encrypt) {
/* Encrypt payload */
if (gctx->ctr) {
+ size_t bulk = 0;
+# if defined(AES_GCM_ASM)
+ if (len >= 32 && AES_GCM_ASM(gctx)) {
+ if (CRYPTO_gcm128_encrypt(&gctx->gcm, NULL, NULL, 0))
+ return -1;
+
+ bulk = AES_gcm_encrypt(in, out, len,
+ gctx->gcm.key,
+ gctx->gcm.Yi.c, gctx->gcm.Xi.u);
+ gctx->gcm.len.u[1] += bulk;
+ }
+# endif
if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm,
- in, out, len, gctx->ctr))
+ in + bulk,
+ out + bulk,
+ len - bulk, gctx->ctr))
goto err;
} else {
- if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
+ size_t bulk = 0;
+# if defined(AES_GCM_ASM2)
+ if (len >= 32 && AES_GCM_ASM2(gctx)) {
+ if (CRYPTO_gcm128_encrypt(&gctx->gcm, NULL, NULL, 0))
+ return -1;
+
+ bulk = AES_gcm_encrypt(in, out, len,
+ gctx->gcm.key,
+ gctx->gcm.Yi.c, gctx->gcm.Xi.u);
+ gctx->gcm.len.u[1] += bulk;
+ }
+# endif
+ if (CRYPTO_gcm128_encrypt(&gctx->gcm,
+ in + bulk, out + bulk, len - bulk))
goto err;
}
out += len;
@@ -905,11 +1419,38 @@ static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
} else {
/* Decrypt */
if (gctx->ctr) {
+ size_t bulk = 0;
+# if defined(AES_GCM_ASM)
+ if (len >= 16 && AES_GCM_ASM(gctx)) {
+ if (CRYPTO_gcm128_decrypt(&gctx->gcm, NULL, NULL, 0))
+ return -1;
+
+ bulk = AES_gcm_decrypt(in, out, len,
+ gctx->gcm.key,
+ gctx->gcm.Yi.c, gctx->gcm.Xi.u);
+ gctx->gcm.len.u[1] += bulk;
+ }
+# endif
if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm,
- in, out, len, gctx->ctr))
+ in + bulk,
+ out + bulk,
+ len - bulk, gctx->ctr))
goto err;
} else {
- if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len))
+ size_t bulk = 0;
+# if defined(AES_GCM_ASM2)
+ if (len >= 16 && AES_GCM_ASM2(gctx)) {
+ if (CRYPTO_gcm128_decrypt(&gctx->gcm, NULL, NULL, 0))
+ return -1;
+
+ bulk = AES_gcm_decrypt(in, out, len,
+ gctx->gcm.key,
+ gctx->gcm.Yi.c, gctx->gcm.Xi.u);
+ gctx->gcm.len.u[1] += bulk;
+ }
+# endif
+ if (CRYPTO_gcm128_decrypt(&gctx->gcm,
+ in + bulk, out + bulk, len - bulk))
goto err;
}
/* Retrieve tag */
@@ -947,20 +1488,90 @@ static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return -1;
} else if (ctx->encrypt) {
if (gctx->ctr) {
+ size_t bulk = 0;
+# if defined(AES_GCM_ASM)
+ if (len >= 32 && AES_GCM_ASM(gctx)) {
+ size_t res = (16 - gctx->gcm.mres) % 16;
+
+ if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, res))
+ return -1;
+
+ bulk = AES_gcm_encrypt(in + res,
+ out + res, len - res,
+ gctx->gcm.key, gctx->gcm.Yi.c,
+ gctx->gcm.Xi.u);
+ gctx->gcm.len.u[1] += bulk;
+ bulk += res;
+ }
+# endif
if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm,
- in, out, len, gctx->ctr))
+ in + bulk,
+ out + bulk,
+ len - bulk, gctx->ctr))
return -1;
} else {
- if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
+ size_t bulk = 0;
+# if defined(AES_GCM_ASM2)
+ if (len >= 32 && AES_GCM_ASM2(gctx)) {
+ size_t res = (16 - gctx->gcm.mres) % 16;
+
+ if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, res))
+ return -1;
+
+ bulk = AES_gcm_encrypt(in + res,
+ out + res, len - res,
+ gctx->gcm.key, gctx->gcm.Yi.c,
+ gctx->gcm.Xi.u);
+ gctx->gcm.len.u[1] += bulk;
+ bulk += res;
+ }
+# endif
+ if (CRYPTO_gcm128_encrypt(&gctx->gcm,
+ in + bulk, out + bulk, len - bulk))
return -1;
}
} else {
if (gctx->ctr) {
+ size_t bulk = 0;
+# if defined(AES_GCM_ASM)
+ if (len >= 16 && AES_GCM_ASM(gctx)) {
+ size_t res = (16 - gctx->gcm.mres) % 16;
+
+ if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, res))
+ return -1;
+
+ bulk = AES_gcm_decrypt(in + res,
+ out + res, len - res,
+ gctx->gcm.key,
+ gctx->gcm.Yi.c, gctx->gcm.Xi.u);
+ gctx->gcm.len.u[1] += bulk;
+ bulk += res;
+ }
+# endif
if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm,
- in, out, len, gctx->ctr))
+ in + bulk,
+ out + bulk,
+ len - bulk, gctx->ctr))
return -1;
} else {
- if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len))
+ size_t bulk = 0;
+# if defined(AES_GCM_ASM2)
+ if (len >= 16 && AES_GCM_ASM2(gctx)) {
+ size_t res = (16 - gctx->gcm.mres) % 16;
+
+ if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, res))
+ return -1;
+
+ bulk = AES_gcm_decrypt(in + res,
+ out + res, len - res,
+ gctx->gcm.key,
+ gctx->gcm.Yi.c, gctx->gcm.Xi.u);
+ gctx->gcm.len.u[1] += bulk;
+ bulk += res;
+ }
+# endif
+ if (CRYPTO_gcm128_decrypt(&gctx->gcm,
+ in + bulk, out + bulk, len - bulk))
return -1;
}
}
@@ -983,7 +1594,7 @@ static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
}
-# define CUSTOM_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \
+# define CUSTOM_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \
| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
| EVP_CIPH_CUSTOM_COPY)
@@ -1032,47 +1643,69 @@ static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
if (key)
do {
-# ifdef AES_XTS_ASM
+# ifdef AES_XTS_ASM
xctx->stream = enc ? AES_xts_encrypt : AES_xts_decrypt;
-# else
+# else
xctx->stream = NULL;
-# endif
+# endif
/* key_len is two AES keys */
-# ifdef BSAES_CAPABLE
+# ifdef HWAES_CAPABLE
+ if (HWAES_CAPABLE) {
+ if (enc) {
+ HWAES_set_encrypt_key(key, ctx->key_len * 4,
+ &xctx->ks1.ks);
+ xctx->xts.block1 = (block128_f) HWAES_encrypt;
+ } else {
+ HWAES_set_decrypt_key(key, ctx->key_len * 4,
+ &xctx->ks1.ks);
+ xctx->xts.block1 = (block128_f) HWAES_decrypt;
+ }
+
+ HWAES_set_encrypt_key(key + ctx->key_len / 2,
+ ctx->key_len * 4, &xctx->ks2.ks);
+ xctx->xts.block2 = (block128_f) HWAES_encrypt;
+
+ xctx->xts.key1 = &xctx->ks1;
+ break;
+ } else
+# endif
+# ifdef BSAES_CAPABLE
if (BSAES_CAPABLE)
xctx->stream = enc ? bsaes_xts_encrypt : bsaes_xts_decrypt;
else
-# endif
-# ifdef VPAES_CAPABLE
+# endif
+# ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
if (enc) {
- vpaes_set_encrypt_key(key, ctx->key_len * 4, &xctx->ks1);
+ vpaes_set_encrypt_key(key, ctx->key_len * 4,
+ &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) vpaes_encrypt;
} else {
- vpaes_set_decrypt_key(key, ctx->key_len * 4, &xctx->ks1);
+ vpaes_set_decrypt_key(key, ctx->key_len * 4,
+ &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) vpaes_decrypt;
}
vpaes_set_encrypt_key(key + ctx->key_len / 2,
- ctx->key_len * 4, &xctx->ks2);
+ ctx->key_len * 4, &xctx->ks2.ks);
xctx->xts.block2 = (block128_f) vpaes_encrypt;
xctx->xts.key1 = &xctx->ks1;
break;
} else
-# endif
+# endif
(void)0; /* terminate potentially open 'else' */
if (enc) {
- AES_set_encrypt_key(key, ctx->key_len * 4, &xctx->ks1);
+ AES_set_encrypt_key(key, ctx->key_len * 4, &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) AES_encrypt;
} else {
- AES_set_decrypt_key(key, ctx->key_len * 4, &xctx->ks1);
+ AES_set_decrypt_key(key, ctx->key_len * 4, &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) AES_decrypt;
}
AES_set_encrypt_key(key + ctx->key_len / 2,
- ctx->key_len * 4, &xctx->ks2);
+ ctx->key_len * 4, &xctx->ks2.ks);
xctx->xts.block2 = (block128_f) AES_encrypt;
xctx->xts.key1 = &xctx->ks1;
@@ -1094,14 +1727,6 @@ static int aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return 0;
if (!out || !in || len < AES_BLOCK_SIZE)
return 0;
-# ifdef OPENSSL_FIPS
- /* Requirement of SP800-38E */
- if (FIPS_module_mode() && !(ctx->flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW) &&
- (len > (1UL << 20) * 16)) {
- EVPerr(EVP_F_AES_XTS_CIPHER, EVP_R_TOO_LARGE);
- return 0;
- }
-# endif
if (xctx->stream)
(*xctx->stream) (in, out, len,
xctx->xts.key1, xctx->xts.key2, ctx->iv);
@@ -1111,9 +1736,9 @@ static int aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return 1;
}
-# define aes_xts_cleanup NULL
+# define aes_xts_cleanup NULL
-# define XTS_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV \
+# define XTS_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV \
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
| EVP_CIPH_CUSTOM_COPY)
@@ -1191,17 +1816,28 @@ static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
return 1;
if (key)
do {
-# ifdef VPAES_CAPABLE
+# ifdef HWAES_CAPABLE
+ if (HWAES_CAPABLE) {
+ HWAES_set_encrypt_key(key, ctx->key_len * 8, &cctx->ks.ks);
+
+ CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
+ &cctx->ks, (block128_f) HWAES_encrypt);
+ cctx->str = NULL;
+ cctx->key_set = 1;
+ break;
+ } else
+# endif
+# ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
- vpaes_set_encrypt_key(key, ctx->key_len * 8, &cctx->ks);
+ vpaes_set_encrypt_key(key, ctx->key_len * 8, &cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
&cctx->ks, (block128_f) vpaes_encrypt);
cctx->str = NULL;
cctx->key_set = 1;
break;
}
-# endif
- AES_set_encrypt_key(key, ctx->key_len * 8, &cctx->ks);
+# endif
+ AES_set_encrypt_key(key, ctx->key_len * 8, &cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
&cctx->ks, (block128_f) AES_encrypt);
cctx->str = NULL;
@@ -1274,7 +1910,7 @@ static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
}
-# define aes_ccm_cleanup NULL
+# define aes_ccm_cleanup NULL
BLOCK_CIPHER_custom(NID_aes, 128, 1, 12, ccm, CCM,
EVP_CIPH_FLAG_FIPS | CUSTOM_FLAGS)
@@ -1282,5 +1918,107 @@ BLOCK_CIPHER_custom(NID_aes, 128, 1, 12, ccm, CCM,
EVP_CIPH_FLAG_FIPS | CUSTOM_FLAGS)
BLOCK_CIPHER_custom(NID_aes, 256, 1, 12, ccm, CCM,
EVP_CIPH_FLAG_FIPS | CUSTOM_FLAGS)
-# endif
#endif
+typedef struct {
+ union {
+ double align;
+ AES_KEY ks;
+ } ks;
+ /* Indicates if IV has been set */
+ unsigned char *iv;
+} EVP_AES_WRAP_CTX;
+
+static int aes_wrap_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ EVP_AES_WRAP_CTX *wctx = ctx->cipher_data;
+ if (!iv && !key)
+ return 1;
+ if (key) {
+ if (ctx->encrypt)
+ AES_set_encrypt_key(key, ctx->key_len * 8, &wctx->ks.ks);
+ else
+ AES_set_decrypt_key(key, ctx->key_len * 8, &wctx->ks.ks);
+ if (!iv)
+ wctx->iv = NULL;
+ }
+ if (iv) {
+ memcpy(ctx->iv, iv, 8);
+ wctx->iv = ctx->iv;
+ }
+ return 1;
+}
+
+static int aes_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inlen)
+{
+ EVP_AES_WRAP_CTX *wctx = ctx->cipher_data;
+ size_t rv;
+ if (!in)
+ return 0;
+ if (inlen % 8)
+ return -1;
+ if (ctx->encrypt && inlen < 8)
+ return -1;
+ if (!ctx->encrypt && inlen < 16)
+ return -1;
+ if (!out) {
+ if (ctx->encrypt)
+ return inlen + 8;
+ else
+ return inlen - 8;
+ }
+ if (ctx->encrypt)
+ rv = CRYPTO_128_wrap(&wctx->ks.ks, wctx->iv, out, in, inlen,
+ (block128_f) AES_encrypt);
+ else
+ rv = CRYPTO_128_unwrap(&wctx->ks.ks, wctx->iv, out, in, inlen,
+ (block128_f) AES_decrypt);
+ return rv ? (int)rv : -1;
+}
+
+#define WRAP_FLAGS (EVP_CIPH_WRAP_MODE \
+ | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
+ | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_FLAG_DEFAULT_ASN1)
+
+static const EVP_CIPHER aes_128_wrap = {
+ NID_id_aes128_wrap,
+ 8, 16, 8, WRAP_FLAGS,
+ aes_wrap_init_key, aes_wrap_cipher,
+ NULL,
+ sizeof(EVP_AES_WRAP_CTX),
+ NULL, NULL, NULL, NULL
+};
+
+const EVP_CIPHER *EVP_aes_128_wrap(void)
+{
+ return &aes_128_wrap;
+}
+
+static const EVP_CIPHER aes_192_wrap = {
+ NID_id_aes192_wrap,
+ 8, 24, 8, WRAP_FLAGS,
+ aes_wrap_init_key, aes_wrap_cipher,
+ NULL,
+ sizeof(EVP_AES_WRAP_CTX),
+ NULL, NULL, NULL, NULL
+};
+
+const EVP_CIPHER *EVP_aes_192_wrap(void)
+{
+ return &aes_192_wrap;
+}
+
+static const EVP_CIPHER aes_256_wrap = {
+ NID_id_aes256_wrap,
+ 8, 32, 8, WRAP_FLAGS,
+ aes_wrap_init_key, aes_wrap_cipher,
+ NULL,
+ sizeof(EVP_AES_WRAP_CTX),
+ NULL, NULL, NULL, NULL
+};
+
+const EVP_CIPHER *EVP_aes_256_wrap(void)
+{
+ return &aes_256_wrap;
+}
diff --git a/crypto/evp/e_aes_cbc_hmac_sha1.c b/crypto/evp/e_aes_cbc_hmac_sha1.c
index d1f5928f628a..8330964ee16b 100644
--- a/crypto/evp/e_aes_cbc_hmac_sha1.c
+++ b/crypto/evp/e_aes_cbc_hmac_sha1.c
@@ -58,7 +58,8 @@
# include <openssl/objects.h>
# include <openssl/aes.h>
# include <openssl/sha.h>
-# include "evp_locl.h"
+# include <openssl/rand.h>
+# include "modes_lcl.h"
# ifndef EVP_CIPH_FLAG_AEAD_CIPHER
# define EVP_CIPH_FLAG_AEAD_CIPHER 0x200000
@@ -70,6 +71,10 @@
# define EVP_CIPH_FLAG_DEFAULT_ASN1 0
# endif
+# if !defined(EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)
+# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0
+# endif
+
# define TLS1_1_VERSION 0x0302
typedef struct {
@@ -89,11 +94,7 @@ typedef struct {
defined(_M_AMD64) || defined(_M_X64) || \
defined(__INTEL__) )
-# if defined(__GNUC__) && __GNUC__>=2 && !defined(PEDANTIC)
-# define BSWAP(x) ({ unsigned int r=(x); asm ("bswapl %0":"=r"(r):"0"(r)); r; })
-# endif
-
-extern unsigned int OPENSSL_ia32cap_P[2];
+extern unsigned int OPENSSL_ia32cap_P[];
# define AESNI_CAPABLE (1<<(57-32))
int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
@@ -110,6 +111,10 @@ 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);
+void aesni256_cbc_sha1_dec(const void *inp, void *out, size_t blocks,
+ const AES_KEY *key, unsigned char iv[16],
+ SHA_CTX *ctx, const void *in0);
+
# define data(ctx) ((EVP_AES_HMAC_SHA1 *)(ctx)->cipher_data)
static int aesni_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx,
@@ -134,6 +139,7 @@ static int aesni_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx,
}
# define STITCHED_CALL
+# undef STITCHED_DECRYPT_CALL
# if !defined(STITCHED_CALL)
# define aes_off 0
@@ -177,6 +183,275 @@ static void sha1_update(SHA_CTX *c, const void *data, size_t len)
# endif
# define SHA1_Update sha1_update
+# if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_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;
+
+void sha1_multi_block(SHA1_MB_CTX *, const HASH_DESC *, int);
+
+typedef struct {
+ const unsigned char *inp;
+ unsigned char *out;
+ int blocks;
+ u64 iv[2];
+} CIPH_DESC;
+
+void aesni_multi_cbc_encrypt(CIPH_DESC *, void *, int);
+
+static size_t tls1_1_multi_block_encrypt(EVP_AES_HMAC_SHA1 *key,
+ unsigned char *out,
+ const unsigned char *inp,
+ size_t inp_len, int n4x)
+{ /* n4x is 1 or 2 */
+ 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 *ctx;
+ unsigned int frag, last, packlen, i, 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((IVs = blocks[0].c), 16 * x4) <= 0)
+ return 0;
+
+ ctx = (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, key->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
+
+ ctx->A[i] = key->md.h0;
+ ctx->B[i] = key->md.h1;
+ ctx->C[i] = key->md.h2;
+ ctx->D[i] = key->md.h3;
+ ctx->E[i] = key->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 *)key->md.data)[j] + carry;
+ carry = (blocks[i].c[j] - carry) >> (sizeof(carry) * 8 - 1);
+ }
+# endif
+ blocks[i].c[8] = ((u8 *)key->md.data)[8];
+ blocks[i].c[9] = ((u8 *)key->md.data)[9];
+ blocks[i].c[10] = ((u8 *)key->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(ctx, 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(ctx, edges, n4x);
+ aesni_multi_cbc_encrypt(ciph_d, &key->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(ctx, 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(ctx, edges, n4x);
+
+ memset(blocks, 0, sizeof(blocks));
+ for (i = 0; i < x4; i++) {
+# ifdef BSWAP4
+ blocks[i].d[0] = BSWAP4(ctx->A[i]);
+ ctx->A[i] = key->tail.h0;
+ blocks[i].d[1] = BSWAP4(ctx->B[i]);
+ ctx->B[i] = key->tail.h1;
+ blocks[i].d[2] = BSWAP4(ctx->C[i]);
+ ctx->C[i] = key->tail.h2;
+ blocks[i].d[3] = BSWAP4(ctx->D[i]);
+ ctx->D[i] = key->tail.h3;
+ blocks[i].d[4] = BSWAP4(ctx->E[i]);
+ ctx->E[i] = key->tail.h4;
+ blocks[i].c[20] = 0x80;
+ blocks[i].d[15] = BSWAP4((64 + 20) * 8);
+# else
+ PUTU32(blocks[i].c + 0, ctx->A[i]);
+ ctx->A[i] = key->tail.h0;
+ PUTU32(blocks[i].c + 4, ctx->B[i]);
+ ctx->B[i] = key->tail.h1;
+ PUTU32(blocks[i].c + 8, ctx->C[i]);
+ ctx->C[i] = key->tail.h2;
+ PUTU32(blocks[i].c + 12, ctx->D[i]);
+ ctx->D[i] = key->tail.h3;
+ PUTU32(blocks[i].c + 16, ctx->E[i]);
+ ctx->E[i] = key->tail.h4;
+ blocks[i].c[20] = 0x80;
+ PUTU32(blocks[i].c + 60, (64 + 20) * 8);
+# endif
+ edges[i].ptr = blocks[i].c;
+ edges[i].blocks = 1;
+ }
+
+ /* finalize MACs */
+ sha1_multi_block(ctx, 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, ctx->A[i]);
+ PUTU32(out + 4, ctx->B[i]);
+ PUTU32(out + 8, ctx->C[i]);
+ PUTU32(out + 12, ctx->D[i]);
+ PUTU32(out + 16, ctx->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 *)key->md.data)[8];
+ out0[1] = ((u8 *)key->md.data)[9];
+ out0[2] = ((u8 *)key->md.data)[10];
+ out0[3] = (u8)(len >> 8);
+ out0[4] = (u8)(len);
+
+ ret += len + 5;
+ inp += frag;
+ }
+
+ aesni_multi_cbc_encrypt(ciph_d, &key->ks, n4x);
+
+ OPENSSL_cleanse(blocks, sizeof(blocks));
+ OPENSSL_cleanse(ctx, sizeof(*ctx));
+
+ return ret;
+}
+# endif
+
static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
@@ -257,10 +532,7 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
/* arrange cache line alignment */
pmac = (void *)(((size_t)mac.c + 31) & ((size_t)0 - 32));
- /* decrypt HMAC|padding at once */
- aesni_cbc_encrypt(in, out, len, &key->ks, ctx->iv, 0);
-
- if (plen) { /* "TLS" mode of operation */
+ 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;
@@ -268,17 +540,37 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
unsigned int u[SHA_LBLOCK];
unsigned char c[SHA_CBLOCK];
} *data = (void *)key->md.data;
+# if defined(STITCHED_DECRYPT_CALL)
+ unsigned char tail_iv[AES_BLOCK_SIZE];
+ int stitch = 0;
+# endif
if ((key->aux.tls_aad[plen - 4] << 8 | key->aux.tls_aad[plen - 3])
- >= TLS1_1_VERSION)
- iv = AES_BLOCK_SIZE;
-
- if (len < (iv + SHA_DIGEST_LENGTH + 1))
+ >= TLS1_1_VERSION) {
+ if (len < (AES_BLOCK_SIZE + SHA_DIGEST_LENGTH + 1))
+ return 0;
+
+ /* omit explicit iv */
+ memcpy(ctx->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;
- /* omit explicit iv */
- out += iv;
- len -= iv;
+# if defined(STITCHED_DECRYPT_CALL)
+ if (len >= 1024 && ctx->key_len == 32) {
+ /* decrypt last block */
+ memcpy(tail_iv, in + len - 2 * AES_BLOCK_SIZE,
+ AES_BLOCK_SIZE);
+ aesni_cbc_encrypt(in + len - AES_BLOCK_SIZE,
+ out + len - AES_BLOCK_SIZE, AES_BLOCK_SIZE,
+ &key->ks, tail_iv, 0);
+ stitch = 1;
+ } else
+# endif
+ /* decrypt HMAC|padding at once */
+ aesni_cbc_encrypt(in, out, len, &key->ks, ctx->iv, 0);
/* figure out payload length */
pad = out[len - 1];
@@ -298,6 +590,29 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
key->md = key->head;
SHA1_Update(&key->md, key->aux.tls_aad, plen);
+# if defined(STITCHED_DECRYPT_CALL)
+ if (stitch) {
+ blocks = (len - (256 + 32 + SHA_CBLOCK)) / SHA_CBLOCK;
+ aes_off = len - AES_BLOCK_SIZE - blocks * SHA_CBLOCK;
+ sha_off = SHA_CBLOCK - plen;
+
+ aesni_cbc_encrypt(in, out, aes_off, &key->ks, ctx->iv, 0);
+
+ SHA1_Update(&key->md, out, sha_off);
+ aesni256_cbc_sha1_dec(in + aes_off,
+ out + aes_off, blocks, &key->ks,
+ ctx->iv, &key->md, out + sha_off);
+
+ sha_off += blocks *= SHA_CBLOCK;
+ out += sha_off;
+ len -= sha_off;
+ inp_len -= sha_off;
+
+ key->md.Nl += (blocks << 3); /* at most 18 bits */
+ memcpy(ctx->iv, tail_iv, AES_BLOCK_SIZE);
+ }
+# endif
+
# if 1
len -= SHA_DIGEST_LENGTH; /* amend mac */
if (len >= (256 + SHA_CBLOCK)) {
@@ -311,8 +626,8 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
/* but pretend as if we hashed padded payload */
bitlen = key->md.Nl + (inp_len << 3); /* at most 18 bits */
-# ifdef BSWAP
- bitlen = BSWAP(bitlen);
+# ifdef BSWAP4
+ bitlen = BSWAP4(bitlen);
# else
mac.c[0] = 0;
mac.c[1] = (unsigned char)(bitlen >> 16);
@@ -376,12 +691,12 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
pmac->u[3] |= key->md.h3 & mask;
pmac->u[4] |= key->md.h4 & mask;
-# ifdef BSWAP
- pmac->u[0] = BSWAP(pmac->u[0]);
- pmac->u[1] = BSWAP(pmac->u[1]);
- pmac->u[2] = BSWAP(pmac->u[2]);
- pmac->u[3] = BSWAP(pmac->u[3]);
- pmac->u[4] = BSWAP(pmac->u[4]);
+# 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];
@@ -458,6 +773,33 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
# endif
return ret;
} else {
+# if defined(STITCHED_DECRYPT_CALL)
+ if (len >= 1024 && ctx->key_len == 32) {
+ if (sha_off %= SHA_CBLOCK)
+ blocks = (len - 3 * SHA_CBLOCK) / SHA_CBLOCK;
+ else
+ blocks = (len - 2 * SHA_CBLOCK) / SHA_CBLOCK;
+ aes_off = len - blocks * SHA_CBLOCK;
+
+ aesni_cbc_encrypt(in, out, aes_off, &key->ks, ctx->iv, 0);
+ SHA1_Update(&key->md, out, sha_off);
+ aesni256_cbc_sha1_dec(in + aes_off,
+ out + aes_off, blocks, &key->ks,
+ ctx->iv, &key->md, out + sha_off);
+
+ sha_off += blocks *= SHA_CBLOCK;
+ out += sha_off;
+ len -= sha_off;
+
+ key->md.Nh += blocks >> 29;
+ key->md.Nl += blocks <<= 3;
+ if (key->md.Nl < (unsigned int)blocks)
+ key->md.Nh++;
+ } else
+# endif
+ /* decrypt HMAC|padding at once */
+ aesni_cbc_encrypt(in, out, len, &key->ks, ctx->iv, 0);
+
SHA1_Update(&key->md, out, len);
}
}
@@ -531,6 +873,70 @@ static int aesni_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
return SHA_DIGEST_LENGTH;
}
}
+# if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
+ case EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE:
+ return (int)(5 + 16 + ((arg + 20 + 16) & -16));
+ case EVP_CTRL_TLS1_1_MULTIBLOCK_AAD:
+ {
+ EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param =
+ (EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *) ptr;
+ unsigned int n4x = 1, x4;
+ unsigned int frag, last, packlen, inp_len;
+
+ if (arg < (int)sizeof(EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM))
+ return -1;
+
+ inp_len = param->inp[11] << 8 | param->inp[12];
+
+ if (ctx->encrypt) {
+ 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;
+
+ key->md = key->head;
+ SHA1_Update(&key->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;
+
+ return (int)packlen;
+ } else
+ return -1; /* not yet */
+ }
+ case EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT:
+ {
+ EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param =
+ (EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *) ptr;
+
+ return (int)tls1_1_multi_block_encrypt(key, param->out,
+ param->inp, param->len,
+ param->interleave / 4);
+ }
+ case EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT:
+# endif
default:
return -1;
}
@@ -544,7 +950,7 @@ static EVP_CIPHER aesni_128_cbc_hmac_sha1_cipher = {
# endif
16, 16, 16,
EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 |
- EVP_CIPH_FLAG_AEAD_CIPHER,
+ EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK,
aesni_cbc_hmac_sha1_init_key,
aesni_cbc_hmac_sha1_cipher,
NULL,
@@ -563,7 +969,7 @@ static EVP_CIPHER aesni_256_cbc_hmac_sha1_cipher = {
# endif
16, 32, 16,
EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 |
- EVP_CIPH_FLAG_AEAD_CIPHER,
+ EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK,
aesni_cbc_hmac_sha1_init_key,
aesni_cbc_hmac_sha1_cipher,
NULL,
diff --git a/crypto/evp/e_aes_cbc_hmac_sha256.c b/crypto/evp/e_aes_cbc_hmac_sha256.c
new file mode 100644
index 000000000000..b1c586e6fd96
--- /dev/null
+++ b/crypto/evp/e_aes_cbc_hmac_sha256.c
@@ -0,0 +1,973 @@
+/* ====================================================================
+ * Copyright (c) 2011-2013 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include <openssl/opensslconf.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#if !defined(OPENSSL_NO_AES) && !defined(OPENSSL_NO_SHA256)
+
+# include <openssl/evp.h>
+# include <openssl/objects.h>
+# include <openssl/aes.h>
+# include <openssl/sha.h>
+# include <openssl/rand.h>
+# include "modes_lcl.h"
+
+# ifndef EVP_CIPH_FLAG_AEAD_CIPHER
+# define EVP_CIPH_FLAG_AEAD_CIPHER 0x200000
+# define EVP_CTRL_AEAD_TLS1_AAD 0x16
+# define EVP_CTRL_AEAD_SET_MAC_KEY 0x17
+# endif
+
+# if !defined(EVP_CIPH_FLAG_DEFAULT_ASN1)
+# define EVP_CIPH_FLAG_DEFAULT_ASN1 0
+# endif
+
+# if !defined(EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)
+# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0
+# endif
+
+# define TLS1_1_VERSION 0x0302
+
+typedef struct {
+ AES_KEY ks;
+ SHA256_CTX head, tail, md;
+ size_t payload_length; /* AAD length in decrypt case */
+ union {
+ unsigned int tls_ver;
+ unsigned char tls_aad[16]; /* 13 used */
+ } aux;
+} EVP_AES_HMAC_SHA256;
+
+# define NO_PAYLOAD_LENGTH ((size_t)-1)
+
+# if defined(AES_ASM) && ( \
+ defined(__x86_64) || defined(__x86_64__) || \
+ defined(_M_AMD64) || defined(_M_X64) || \
+ defined(__INTEL__) )
+
+extern unsigned int OPENSSL_ia32cap_P[];
+# define AESNI_CAPABLE (1<<(57-32))
+
+int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
+ AES_KEY *key);
+int aesni_set_decrypt_key(const unsigned char *userKey, int bits,
+ AES_KEY *key);
+
+void aesni_cbc_encrypt(const unsigned char *in,
+ unsigned char *out,
+ size_t length,
+ const AES_KEY *key, unsigned char *ivec, int enc);
+
+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);
+
+# define data(ctx) ((EVP_AES_HMAC_SHA256 *)(ctx)->cipher_data)
+
+static int aesni_cbc_hmac_sha256_init_key(EVP_CIPHER_CTX *ctx,
+ const unsigned char *inkey,
+ const unsigned char *iv, int enc)
+{
+ EVP_AES_HMAC_SHA256 *key = data(ctx);
+ int ret;
+
+ if (enc)
+ memset(&key->ks, 0, sizeof(key->ks.rd_key)),
+ ret = aesni_set_encrypt_key(inkey, ctx->key_len * 8, &key->ks);
+ else
+ ret = aesni_set_decrypt_key(inkey, ctx->key_len * 8, &key->ks);
+
+ SHA256_Init(&key->head); /* handy when benchmarking */
+ key->tail = key->head;
+ key->md = key->head;
+
+ key->payload_length = NO_PAYLOAD_LENGTH;
+
+ return ret < 0 ? 0 : 1;
+}
+
+# define STITCHED_CALL
+
+# if !defined(STITCHED_CALL)
+# define aes_off 0
+# endif
+
+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);
+}
+
+# ifdef SHA256_Update
+# undef SHA256_Update
+# endif
+# define SHA256_Update sha256_update
+
+# if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_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;
+
+void sha256_multi_block(SHA256_MB_CTX *, const HASH_DESC *, int);
+
+typedef struct {
+ const unsigned char *inp;
+ unsigned char *out;
+ int blocks;
+ u64 iv[2];
+} CIPH_DESC;
+
+void aesni_multi_cbc_encrypt(CIPH_DESC *, void *, int);
+
+static size_t tls1_1_multi_block_encrypt(EVP_AES_HMAC_SHA256 *key,
+ unsigned char *out,
+ const unsigned char *inp,
+ size_t inp_len, int n4x)
+{ /* n4x is 1 or 2 */
+ 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 *ctx;
+ unsigned int frag, last, packlen, i, 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((IVs = blocks[0].c), 16 * x4) <= 0)
+ return 0;
+
+ /* align */
+ ctx = (SHA256_MB_CTX *) (storage + 32 - ((size_t)storage % 32));
+
+ 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, key->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
+
+ ctx->A[i] = key->md.h[0];
+ ctx->B[i] = key->md.h[1];
+ ctx->C[i] = key->md.h[2];
+ ctx->D[i] = key->md.h[3];
+ ctx->E[i] = key->md.h[4];
+ ctx->F[i] = key->md.h[5];
+ ctx->G[i] = key->md.h[6];
+ ctx->H[i] = key->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 *)key->md.data)[j] + carry;
+ carry = (blocks[i].c[j] - carry) >> (sizeof(carry) * 8 - 1);
+ }
+# endif
+ blocks[i].c[8] = ((u8 *)key->md.data)[8];
+ blocks[i].c[9] = ((u8 *)key->md.data)[9];
+ blocks[i].c[10] = ((u8 *)key->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(ctx, 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(ctx, edges, n4x);
+ aesni_multi_cbc_encrypt(ciph_d, &key->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(ctx, 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(ctx, edges, n4x);
+
+ memset(blocks, 0, sizeof(blocks));
+ for (i = 0; i < x4; i++) {
+# ifdef BSWAP4
+ blocks[i].d[0] = BSWAP4(ctx->A[i]);
+ ctx->A[i] = key->tail.h[0];
+ blocks[i].d[1] = BSWAP4(ctx->B[i]);
+ ctx->B[i] = key->tail.h[1];
+ blocks[i].d[2] = BSWAP4(ctx->C[i]);
+ ctx->C[i] = key->tail.h[2];
+ blocks[i].d[3] = BSWAP4(ctx->D[i]);
+ ctx->D[i] = key->tail.h[3];
+ blocks[i].d[4] = BSWAP4(ctx->E[i]);
+ ctx->E[i] = key->tail.h[4];
+ blocks[i].d[5] = BSWAP4(ctx->F[i]);
+ ctx->F[i] = key->tail.h[5];
+ blocks[i].d[6] = BSWAP4(ctx->G[i]);
+ ctx->G[i] = key->tail.h[6];
+ blocks[i].d[7] = BSWAP4(ctx->H[i]);
+ ctx->H[i] = key->tail.h[7];
+ blocks[i].c[32] = 0x80;
+ blocks[i].d[15] = BSWAP4((64 + 32) * 8);
+# else
+ PUTU32(blocks[i].c + 0, ctx->A[i]);
+ ctx->A[i] = key->tail.h[0];
+ PUTU32(blocks[i].c + 4, ctx->B[i]);
+ ctx->B[i] = key->tail.h[1];
+ PUTU32(blocks[i].c + 8, ctx->C[i]);
+ ctx->C[i] = key->tail.h[2];
+ PUTU32(blocks[i].c + 12, ctx->D[i]);
+ ctx->D[i] = key->tail.h[3];
+ PUTU32(blocks[i].c + 16, ctx->E[i]);
+ ctx->E[i] = key->tail.h[4];
+ PUTU32(blocks[i].c + 20, ctx->F[i]);
+ ctx->F[i] = key->tail.h[5];
+ PUTU32(blocks[i].c + 24, ctx->G[i]);
+ ctx->G[i] = key->tail.h[6];
+ PUTU32(blocks[i].c + 28, ctx->H[i]);
+ ctx->H[i] = key->tail.h[7];
+ blocks[i].c[32] = 0x80;
+ PUTU32(blocks[i].c + 60, (64 + 32) * 8);
+# endif
+ edges[i].ptr = blocks[i].c;
+ edges[i].blocks = 1;
+ }
+
+ /* finalize MACs */
+ sha256_multi_block(ctx, 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, ctx->A[i]);
+ PUTU32(out + 4, ctx->B[i]);
+ PUTU32(out + 8, ctx->C[i]);
+ PUTU32(out + 12, ctx->D[i]);
+ PUTU32(out + 16, ctx->E[i]);
+ PUTU32(out + 20, ctx->F[i]);
+ PUTU32(out + 24, ctx->G[i]);
+ PUTU32(out + 28, ctx->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 *)key->md.data)[8];
+ out0[1] = ((u8 *)key->md.data)[9];
+ out0[2] = ((u8 *)key->md.data)[10];
+ out0[3] = (u8)(len >> 8);
+ out0[4] = (u8)(len);
+
+ ret += len + 5;
+ inp += frag;
+ }
+
+ aesni_multi_cbc_encrypt(ciph_d, &key->ks, n4x);
+
+ OPENSSL_cleanse(blocks, sizeof(blocks));
+ OPENSSL_cleanse(ctx, sizeof(*ctx));
+
+ return ret;
+}
+# endif
+
+static int aesni_cbc_hmac_sha256_cipher(EVP_CIPHER_CTX *ctx,
+ unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ EVP_AES_HMAC_SHA256 *key = data(ctx);
+ unsigned int l;
+ size_t plen = key->payload_length, iv = 0, /* explicit IV in TLS 1.1 and
+ * later */
+ sha_off = 0;
+# if defined(STITCHED_CALL)
+ size_t aes_off = 0, blocks;
+
+ sha_off = SHA256_CBLOCK - key->md.num;
+# endif
+
+ key->payload_length = NO_PAYLOAD_LENGTH;
+
+ if (len % AES_BLOCK_SIZE)
+ return 0;
+
+ if (ctx->encrypt) {
+ if (plen == NO_PAYLOAD_LENGTH)
+ plen = len;
+ else if (len !=
+ ((plen + SHA256_DIGEST_LENGTH +
+ AES_BLOCK_SIZE) & -AES_BLOCK_SIZE))
+ return 0;
+ else if (key->aux.tls_ver >= TLS1_1_VERSION)
+ iv = AES_BLOCK_SIZE;
+
+# if defined(STITCHED_CALL)
+ if (OPENSSL_ia32cap_P[1] & (1 << (60 - 32)) && /* AVX? */
+ plen > (sha_off + iv) &&
+ (blocks = (plen - (sha_off + iv)) / SHA256_CBLOCK)) {
+ SHA256_Update(&key->md, in + iv, sha_off);
+
+ (void)aesni_cbc_sha256_enc(in, out, blocks, &key->ks,
+ ctx->iv, &key->md, in + iv + sha_off);
+ blocks *= SHA256_CBLOCK;
+ aes_off += blocks;
+ sha_off += blocks;
+ key->md.Nh += blocks >> 29;
+ key->md.Nl += blocks <<= 3;
+ if (key->md.Nl < (unsigned int)blocks)
+ key->md.Nh++;
+ } else {
+ sha_off = 0;
+ }
+# endif
+ sha_off += iv;
+ SHA256_Update(&key->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, &key->md);
+ key->md = key->tail;
+ SHA256_Update(&key->md, out + plen, SHA256_DIGEST_LENGTH);
+ SHA256_Final(out + plen, &key->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,
+ &key->ks, ctx->iv, 1);
+ } else {
+ aesni_cbc_encrypt(in + aes_off, out + aes_off, len - aes_off,
+ &key->ks, ctx->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, &key->ks, ctx->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 *)key->md.data;
+
+ if ((key->aux.tls_aad[plen - 4] << 8 | key->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;
+
+ inp_len = len - (SHA256_DIGEST_LENGTH + pad + 1);
+ mask = (0 - ((inp_len - len) >> (sizeof(inp_len) * 8 - 1)));
+ inp_len &= mask;
+ ret &= (int)mask;
+
+ key->aux.tls_aad[plen - 2] = inp_len >> 8;
+ key->aux.tls_aad[plen - 1] = inp_len;
+
+ /* calculate HMAC */
+ key->md = key->head;
+ SHA256_Update(&key->md, key->aux.tls_aad, plen);
+
+# if 1
+ len -= SHA256_DIGEST_LENGTH; /* amend mac */
+ if (len >= (256 + SHA256_CBLOCK)) {
+ j = (len - (256 + SHA256_CBLOCK)) & (0 - SHA256_CBLOCK);
+ j += SHA256_CBLOCK - key->md.num;
+ SHA256_Update(&key->md, out, j);
+ out += j;
+ len -= j;
+ inp_len -= j;
+ }
+
+ /* but pretend as if we hashed padded payload */
+ bitlen = key->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
+
+ 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 = key->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(&key->md, data, 1);
+ mask &= 0 - ((j - inp_len - 72) >> (sizeof(j) * 8 - 1));
+ pmac->u[0] |= key->md.h[0] & mask;
+ pmac->u[1] |= key->md.h[1] & mask;
+ pmac->u[2] |= key->md.h[2] & mask;
+ pmac->u[3] |= key->md.h[3] & mask;
+ pmac->u[4] |= key->md.h[4] & mask;
+ pmac->u[5] |= key->md.h[5] & mask;
+ pmac->u[6] |= key->md.h[6] & mask;
+ pmac->u[7] |= key->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(&key->md, data, 1);
+ mask &= 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1));
+ pmac->u[0] |= key->md.h[0] & mask;
+ pmac->u[1] |= key->md.h[1] & mask;
+ pmac->u[2] |= key->md.h[2] & mask;
+ pmac->u[3] |= key->md.h[3] & mask;
+ pmac->u[4] |= key->md.h[4] & mask;
+ pmac->u[5] |= key->md.h[5] & mask;
+ pmac->u[6] |= key->md.h[6] & mask;
+ pmac->u[7] |= key->md.h[7] & mask;
+
+ memset(data, 0, SHA256_CBLOCK);
+ j += 64;
+ }
+ data->u[SHA_LBLOCK - 1] = bitlen;
+ sha256_block_data_order(&key->md, data, 1);
+ mask = 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1));
+ pmac->u[0] |= key->md.h[0] & mask;
+ pmac->u[1] |= key->md.h[1] & mask;
+ pmac->u[2] |= key->md.h[2] & mask;
+ pmac->u[3] |= key->md.h[3] & mask;
+ pmac->u[4] |= key->md.h[4] & mask;
+ pmac->u[5] |= key->md.h[5] & mask;
+ pmac->u[6] |= key->md.h[6] & mask;
+ pmac->u[7] |= key->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
+ len += SHA256_DIGEST_LENGTH;
+# else
+ SHA256_Update(&key->md, out, inp_len);
+ res = key->md.num;
+ SHA256_Final(pmac->c, &key->md);
+
+ {
+ unsigned int inp_blocks, pad_blocks;
+
+ /* but pretend as if we hashed padded payload */
+ inp_blocks =
+ 1 + ((SHA256_CBLOCK - 9 - res) >> (sizeof(res) * 8 - 1));
+ res += (unsigned int)(len - inp_len);
+ pad_blocks = res / SHA256_CBLOCK;
+ res %= SHA256_CBLOCK;
+ pad_blocks +=
+ 1 + ((SHA256_CBLOCK - 9 - res) >> (sizeof(res) * 8 - 1));
+ for (; inp_blocks < pad_blocks; inp_blocks++)
+ sha1_block_data_order(&key->md, data, 1);
+ }
+# endif
+ key->md = key->tail;
+ SHA256_Update(&key->md, pmac->c, SHA256_DIGEST_LENGTH);
+ SHA256_Final(pmac->c, &key->md);
+
+ /* verify HMAC */
+ out += inp_len;
+ len -= inp_len;
+# if 1
+ {
+ unsigned char *p =
+ out + len - 1 - maxpad - SHA256_DIGEST_LENGTH;
+ size_t off = out - p;
+ unsigned int c, cmask;
+
+ maxpad += SHA256_DIGEST_LENGTH;
+ for (res = 0, i = 0, j = 0; j < maxpad; 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;
+ }
+ maxpad -= SHA256_DIGEST_LENGTH;
+
+ res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1));
+ ret &= (int)~res;
+ }
+# else
+ for (res = 0, i = 0; i < SHA256_DIGEST_LENGTH; i++)
+ res |= out[i] ^ pmac->c[i];
+ res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1));
+ ret &= (int)~res;
+
+ /* verify padding */
+ pad = (pad & ~res) | (maxpad & res);
+ out = out + len - 1 - pad;
+ for (res = 0, i = 0; i < pad; i++)
+ res |= out[i] ^ pad;
+
+ res = (0 - res) >> (sizeof(res) * 8 - 1);
+ ret &= (int)~res;
+# endif
+ return ret;
+ } else {
+ SHA256_Update(&key->md, out, len);
+ }
+ }
+
+ return 1;
+}
+
+static int aesni_cbc_hmac_sha256_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
+ void *ptr)
+{
+ EVP_AES_HMAC_SHA256 *key = data(ctx);
+
+ switch (type) {
+ case EVP_CTRL_AEAD_SET_MAC_KEY:
+ {
+ unsigned int i;
+ unsigned char hmac_key[64];
+
+ memset(hmac_key, 0, sizeof(hmac_key));
+
+ if (arg > (int)sizeof(hmac_key)) {
+ SHA256_Init(&key->head);
+ SHA256_Update(&key->head, ptr, arg);
+ SHA256_Final(hmac_key, &key->head);
+ } else {
+ memcpy(hmac_key, ptr, arg);
+ }
+
+ for (i = 0; i < sizeof(hmac_key); i++)
+ hmac_key[i] ^= 0x36; /* ipad */
+ SHA256_Init(&key->head);
+ SHA256_Update(&key->head, hmac_key, sizeof(hmac_key));
+
+ for (i = 0; i < sizeof(hmac_key); i++)
+ hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */
+ SHA256_Init(&key->tail);
+ SHA256_Update(&key->tail, hmac_key, sizeof(hmac_key));
+
+ OPENSSL_cleanse(hmac_key, sizeof(hmac_key));
+
+ return 1;
+ }
+ case EVP_CTRL_AEAD_TLS1_AAD:
+ {
+ unsigned char *p = ptr;
+ unsigned int len = p[arg - 2] << 8 | p[arg - 1];
+
+ if (arg != EVP_AEAD_TLS1_AAD_LEN)
+ return -1;
+
+ len = p[arg - 2] << 8 | p[arg - 1];
+
+ if (ctx->encrypt) {
+ key->payload_length = len;
+ if ((key->aux.tls_ver =
+ p[arg - 4] << 8 | p[arg - 3]) >= TLS1_1_VERSION) {
+ len -= AES_BLOCK_SIZE;
+ p[arg - 2] = len >> 8;
+ p[arg - 1] = len;
+ }
+ key->md = key->head;
+ SHA256_Update(&key->md, p, arg);
+
+ return (int)(((len + SHA256_DIGEST_LENGTH +
+ AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)
+ - len);
+ } else {
+ memcpy(key->aux.tls_aad, ptr, arg);
+ key->payload_length = arg;
+
+ return SHA256_DIGEST_LENGTH;
+ }
+ }
+# if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
+ case EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE:
+ return (int)(5 + 16 + ((arg + 32 + 16) & -16));
+ case EVP_CTRL_TLS1_1_MULTIBLOCK_AAD:
+ {
+ EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param =
+ (EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *) ptr;
+ unsigned int n4x = 1, x4;
+ unsigned int frag, last, packlen, inp_len;
+
+ if (arg < (int)sizeof(EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM))
+ return -1;
+
+ inp_len = param->inp[11] << 8 | param->inp[12];
+
+ if (ctx->encrypt) {
+ 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;
+
+ key->md = key->head;
+ SHA256_Update(&key->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;
+
+ return (int)packlen;
+ } else
+ return -1; /* not yet */
+ }
+ case EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT:
+ {
+ EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param =
+ (EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *) ptr;
+
+ return (int)tls1_1_multi_block_encrypt(key, param->out,
+ param->inp, param->len,
+ param->interleave / 4);
+ }
+ case EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT:
+# endif
+ default:
+ return -1;
+ }
+}
+
+static EVP_CIPHER aesni_128_cbc_hmac_sha256_cipher = {
+# ifdef NID_aes_128_cbc_hmac_sha256
+ NID_aes_128_cbc_hmac_sha256,
+# else
+ NID_undef,
+# endif
+ 16, 16, 16,
+ EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 |
+ EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK,
+ aesni_cbc_hmac_sha256_init_key,
+ aesni_cbc_hmac_sha256_cipher,
+ NULL,
+ sizeof(EVP_AES_HMAC_SHA256),
+ EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv,
+ EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv,
+ aesni_cbc_hmac_sha256_ctrl,
+ NULL
+};
+
+static EVP_CIPHER aesni_256_cbc_hmac_sha256_cipher = {
+# ifdef NID_aes_256_cbc_hmac_sha256
+ NID_aes_256_cbc_hmac_sha256,
+# else
+ NID_undef,
+# endif
+ 16, 32, 16,
+ EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 |
+ EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK,
+ aesni_cbc_hmac_sha256_init_key,
+ aesni_cbc_hmac_sha256_cipher,
+ NULL,
+ sizeof(EVP_AES_HMAC_SHA256),
+ EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv,
+ EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv,
+ aesni_cbc_hmac_sha256_ctrl,
+ NULL
+};
+
+const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha256(void)
+{
+ return ((OPENSSL_ia32cap_P[1] & AESNI_CAPABLE) &&
+ aesni_cbc_sha256_enc(NULL, NULL, 0, NULL, NULL, NULL, NULL) ?
+ &aesni_128_cbc_hmac_sha256_cipher : NULL);
+}
+
+const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha256(void)
+{
+ return ((OPENSSL_ia32cap_P[1] & AESNI_CAPABLE) &&
+ aesni_cbc_sha256_enc(NULL, NULL, 0, NULL, NULL, NULL, NULL) ?
+ &aesni_256_cbc_hmac_sha256_cipher : NULL);
+}
+# else
+const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha256(void)
+{
+ return NULL;
+}
+
+const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha256(void)
+{
+ return NULL;
+}
+# endif
+#endif
diff --git a/crypto/evp/e_camellia.c b/crypto/evp/e_camellia.c
index 27bc4892fff8..f9c84013675d 100644
--- a/crypto/evp/e_camellia.c
+++ b/crypto/evp/e_camellia.c
@@ -61,6 +61,7 @@
# include <assert.h>
# include <openssl/camellia.h>
# include "evp_locl.h"
+# include "modes_lcl.h"
static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
@@ -68,48 +69,322 @@ static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
/* Camellia subkey Structure */
typedef struct {
CAMELLIA_KEY ks;
+ block128_f block;
+ union {
+ cbc128_f cbc;
+ ctr128_f ctr;
+ } stream;
} EVP_CAMELLIA_KEY;
+# define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4))
+
/* Attribute operation for Camellia */
# define data(ctx) EVP_C_DATA(EVP_CAMELLIA_KEY,ctx)
-IMPLEMENT_BLOCK_CIPHER(camellia_128, ks, Camellia, EVP_CAMELLIA_KEY,
- NID_camellia_128, 16, 16, 16, 128,
- 0, camellia_init_key, NULL,
- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL)
- IMPLEMENT_BLOCK_CIPHER(camellia_192, ks, Camellia, EVP_CAMELLIA_KEY,
- NID_camellia_192, 16, 24, 16, 128,
- 0, camellia_init_key, NULL,
- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL)
- IMPLEMENT_BLOCK_CIPHER(camellia_256, ks, Camellia, EVP_CAMELLIA_KEY,
- NID_camellia_256, 16, 32, 16, 128,
- 0, camellia_init_key, NULL,
- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL)
-# define IMPLEMENT_CAMELLIA_CFBR(ksize,cbits) IMPLEMENT_CFBR(camellia,Camellia,EVP_CAMELLIA_KEY,ks,ksize,cbits,16)
- IMPLEMENT_CAMELLIA_CFBR(128, 1)
- IMPLEMENT_CAMELLIA_CFBR(192, 1)
- IMPLEMENT_CAMELLIA_CFBR(256, 1)
-
- IMPLEMENT_CAMELLIA_CFBR(128, 8)
- IMPLEMENT_CAMELLIA_CFBR(192, 8)
- IMPLEMENT_CAMELLIA_CFBR(256, 8)
+# if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
+/* ---------^^^ this is not a typo, just a way to detect that
+ * assembler support was in general requested... */
+# include "sparc_arch.h"
+
+extern unsigned int OPENSSL_sparcv9cap_P[];
+
+# define SPARC_CMLL_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_CAMELLIA)
+
+void cmll_t4_set_key(const unsigned char *key, int bits, CAMELLIA_KEY *ks);
+void cmll_t4_encrypt(const unsigned char *in, unsigned char *out,
+ const CAMELLIA_KEY *key);
+void cmll_t4_decrypt(const unsigned char *in, unsigned char *out,
+ const CAMELLIA_KEY *key);
+
+void cmll128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const CAMELLIA_KEY *key,
+ unsigned char *ivec);
+void cmll128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const CAMELLIA_KEY *key,
+ unsigned char *ivec);
+void cmll256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const CAMELLIA_KEY *key,
+ unsigned char *ivec);
+void cmll256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
+ size_t len, const CAMELLIA_KEY *key,
+ unsigned char *ivec);
+void cmll128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const CAMELLIA_KEY *key,
+ unsigned char *ivec);
+void cmll256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
+ size_t blocks, const CAMELLIA_KEY *key,
+ unsigned char *ivec);
+
+static int cmll_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ int ret, mode, bits;
+ EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data;
+
+ mode = ctx->cipher->flags & EVP_CIPH_MODE;
+ bits = ctx->key_len * 8;
+
+ cmll_t4_set_key(key, bits, &dat->ks);
+
+ if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
+ && !enc) {
+ ret = 0;
+ 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;
+ }
+ } else {
+ ret = 0;
+ 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;
+ }
+ }
+
+ if (ret < 0) {
+ EVPerr(EVP_F_CMLL_T4_INIT_KEY, EVP_R_CAMELLIA_KEY_SETUP_FAILED);
+ return 0;
+ }
+
+ return 1;
+}
+
+# define cmll_t4_cbc_cipher camellia_cbc_cipher
+static int cmll_t4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+# define cmll_t4_ecb_cipher camellia_ecb_cipher
+static int cmll_t4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+# define cmll_t4_ofb_cipher camellia_ofb_cipher
+static int cmll_t4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+# define cmll_t4_cfb_cipher camellia_cfb_cipher
+static int cmll_t4_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+# define cmll_t4_cfb8_cipher camellia_cfb8_cipher
+static int cmll_t4_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+# define cmll_t4_cfb1_cipher camellia_cfb1_cipher
+static int cmll_t4_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+# define cmll_t4_ctr_cipher camellia_ctr_cipher
+static int cmll_t4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+
+# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
+static const EVP_CIPHER cmll_t4_##keylen##_##mode = { \
+ nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
+ flags|EVP_CIPH_##MODE##_MODE, \
+ cmll_t4_init_key, \
+ cmll_t4_##mode##_cipher, \
+ NULL, \
+ sizeof(EVP_CAMELLIA_KEY), \
+ NULL,NULL,NULL,NULL }; \
+static const EVP_CIPHER camellia_##keylen##_##mode = { \
+ nid##_##keylen##_##nmode,blocksize, \
+ keylen/8,ivlen, \
+ flags|EVP_CIPH_##MODE##_MODE, \
+ camellia_init_key, \
+ camellia_##mode##_cipher, \
+ NULL, \
+ sizeof(EVP_CAMELLIA_KEY), \
+ NULL,NULL,NULL,NULL }; \
+const EVP_CIPHER *EVP_camellia_##keylen##_##mode(void) \
+{ return SPARC_CMLL_CAPABLE?&cmll_t4_##keylen##_##mode:&camellia_##keylen##_##mode; }
+
+# else
+
+# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
+static const EVP_CIPHER camellia_##keylen##_##mode = { \
+ nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
+ flags|EVP_CIPH_##MODE##_MODE, \
+ camellia_init_key, \
+ camellia_##mode##_cipher, \
+ NULL, \
+ sizeof(EVP_CAMELLIA_KEY), \
+ NULL,NULL,NULL,NULL }; \
+const EVP_CIPHER *EVP_camellia_##keylen##_##mode(void) \
+{ return &camellia_##keylen##_##mode; }
+
+# endif
+
+# define BLOCK_CIPHER_generic_pack(nid,keylen,flags) \
+ BLOCK_CIPHER_generic(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
+ BLOCK_CIPHER_generic(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
+ BLOCK_CIPHER_generic(nid,keylen,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
+ BLOCK_CIPHER_generic(nid,keylen,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
+ BLOCK_CIPHER_generic(nid,keylen,1,16,cfb1,cfb1,CFB,flags) \
+ BLOCK_CIPHER_generic(nid,keylen,1,16,cfb8,cfb8,CFB,flags)
+# if 0 /* not yet, missing NID */
+BLOCK_CIPHER_generic(nid, keylen, 1, 16, ctr, ctr, CTR, flags)
+# endif
/* The subkey for Camellia is generated. */
static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
- int ret;
-
- ret = Camellia_set_key(key, ctx->key_len * 8, ctx->cipher_data);
+ int ret, mode;
+ EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data;
+ ret = Camellia_set_key(key, ctx->key_len * 8, &dat->ks);
if (ret < 0) {
EVPerr(EVP_F_CAMELLIA_INIT_KEY, EVP_R_CAMELLIA_KEY_SETUP_FAILED);
return 0;
}
+ mode = ctx->cipher->flags & EVP_CIPH_MODE;
+ if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
+ && !enc) {
+ dat->block = (block128_f) Camellia_decrypt;
+ dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
+ (cbc128_f) Camellia_cbc_encrypt : NULL;
+ } else {
+ dat->block = (block128_f) Camellia_encrypt;
+ dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
+ (cbc128_f) Camellia_cbc_encrypt : NULL;
+ }
+
return 1;
}
+static int camellia_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data;
+
+ if (dat->stream.cbc)
+ (*dat->stream.cbc) (in, out, len, &dat->ks, ctx->iv, ctx->encrypt);
+ else if (ctx->encrypt)
+ CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv, dat->block);
+ else
+ CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, ctx->iv, dat->block);
+
+ return 1;
+}
+
+static int camellia_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ size_t bl = ctx->cipher->block_size;
+ size_t i;
+ EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data;
+
+ if (len < bl)
+ return 1;
+
+ for (i = 0, len -= bl; i <= len; i += bl)
+ (*dat->block) (in + i, out + i, &dat->ks);
+
+ return 1;
+}
+
+static int camellia_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data;
+
+ CRYPTO_ofb128_encrypt(in, out, len, &dat->ks,
+ ctx->iv, &ctx->num, dat->block);
+ return 1;
+}
+
+static int camellia_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data;
+
+ CRYPTO_cfb128_encrypt(in, out, len, &dat->ks,
+ ctx->iv, &ctx->num, ctx->encrypt, dat->block);
+ return 1;
+}
+
+static int camellia_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data;
+
+ CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks,
+ ctx->iv, &ctx->num, ctx->encrypt, dat->block);
+ return 1;
+}
+
+static int camellia_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data;
+
+ if (ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) {
+ CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks,
+ ctx->iv, &ctx->num, ctx->encrypt, dat->block);
+ return 1;
+ }
+
+ while (len >= MAXBITCHUNK) {
+ CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, &dat->ks,
+ ctx->iv, &ctx->num, ctx->encrypt, dat->block);
+ len -= MAXBITCHUNK;
+ }
+ if (len)
+ CRYPTO_cfb128_1_encrypt(in, out, len * 8, &dat->ks,
+ ctx->iv, &ctx->num, ctx->encrypt, dat->block);
+
+ return 1;
+}
+
+# if 0 /* not yet, missing NID */
+static int camellia_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ unsigned int num = ctx->num;
+ EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data;
+
+ if (dat->stream.ctr)
+ CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks,
+ ctx->iv, ctx->buf, &num, dat->stream.ctr);
+ else
+ CRYPTO_ctr128_encrypt(in, out, len, &dat->ks,
+ ctx->iv, ctx->buf, &num, dat->block);
+ ctx->num = (size_t)num;
+ return 1;
+}
+# endif
+
+BLOCK_CIPHER_generic_pack(NID_camellia, 128, 0)
+ BLOCK_CIPHER_generic_pack(NID_camellia, 192, 0)
+ BLOCK_CIPHER_generic_pack(NID_camellia, 256, 0)
#else
# ifdef PEDANTIC
diff --git a/crypto/evp/e_des.c b/crypto/evp/e_des.c
index ea1a4c422879..aae13a675694 100644
--- a/crypto/evp/e_des.c
+++ b/crypto/evp/e_des.c
@@ -65,6 +65,32 @@
# include <openssl/des.h>
# include <openssl/rand.h>
+typedef struct {
+ union {
+ double align;
+ DES_key_schedule ks;
+ } ks;
+ union {
+ void (*cbc) (const void *, void *, size_t, const void *, void *);
+ } stream;
+} EVP_DES_KEY;
+
+# if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
+/* ---------^^^ this is not a typo, just a way to detect that
+ * assembler support was in general requested... */
+# include "sparc_arch.h"
+
+extern unsigned int OPENSSL_sparcv9cap_P[];
+
+# define SPARC_DES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_DES)
+
+void des_t4_key_expand(const void *key, DES_key_schedule *ks);
+void des_t4_cbc_encrypt(const void *inp, void *out, size_t len,
+ DES_key_schedule *ks, unsigned char iv[8]);
+void des_t4_cbc_decrypt(const void *inp, void *out, size_t len,
+ DES_key_schedule *ks, unsigned char iv[8]);
+# endif
+
static int des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
static int des_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr);
@@ -102,6 +128,12 @@ static int des_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int des_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
+ EVP_DES_KEY *dat = (EVP_DES_KEY *) ctx->cipher_data;
+
+ if (dat->stream.cbc) {
+ (*dat->stream.cbc) (in, out, inl, &dat->ks.ks, ctx->iv);
+ return 1;
+ }
while (inl >= EVP_MAXCHUNK) {
DES_ncbc_encrypt(in, out, (long)EVP_MAXCHUNK, ctx->cipher_data,
(DES_cblock *)ctx->iv, ctx->encrypt);
@@ -179,16 +211,15 @@ static int des_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
return 1;
}
-BLOCK_CIPHER_defs(des, DES_key_schedule, NID_des, 8, 8, 8, 64,
+BLOCK_CIPHER_defs(des, EVP_DES_KEY, NID_des, 8, 8, 8, 64,
EVP_CIPH_RAND_KEY, des_init_key, NULL,
EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, des_ctrl)
+ BLOCK_CIPHER_def_cfb(des, EVP_DES_KEY, NID_des, 8, 8, 1,
+ EVP_CIPH_RAND_KEY, des_init_key, NULL,
+ EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, des_ctrl)
-BLOCK_CIPHER_def_cfb(des, DES_key_schedule, NID_des, 8, 8, 1,
- EVP_CIPH_RAND_KEY, des_init_key, NULL,
- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, des_ctrl)
-
-BLOCK_CIPHER_def_cfb(des, DES_key_schedule, NID_des, 8, 8, 8,
+ BLOCK_CIPHER_def_cfb(des, EVP_DES_KEY, NID_des, 8, 8, 8,
EVP_CIPH_RAND_KEY, des_init_key, NULL,
EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, des_ctrl)
@@ -196,8 +227,22 @@ static int des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
DES_cblock *deskey = (DES_cblock *)key;
+ EVP_DES_KEY *dat = (EVP_DES_KEY *) ctx->cipher_data;
+
+ dat->stream.cbc = NULL;
+# if defined(SPARC_DES_CAPABLE)
+ if (SPARC_DES_CAPABLE) {
+ int mode = ctx->cipher->flags & EVP_CIPH_MODE;
+
+ if (mode == EVP_CIPH_CBC_MODE) {
+ des_t4_key_expand(key, &dat->ks.ks);
+ dat->stream.cbc = enc ? des_t4_cbc_encrypt : des_t4_cbc_decrypt;
+ return 1;
+ }
+ }
+# endif
# ifdef EVP_CHECK_DES_KEY
- if (DES_set_key_checked(deskey, ctx->cipher_data) != 0)
+ if (DES_set_key_checked(deskey, dat->ks.ks) != 0)
return 0;
# else
DES_set_key_unchecked(deskey, ctx->cipher_data);
diff --git a/crypto/evp/e_des3.c b/crypto/evp/e_des3.c
index 07a5aca606de..96f272eb8046 100644
--- a/crypto/evp/e_des3.c
+++ b/crypto/evp/e_des3.c
@@ -65,7 +65,38 @@
# include <openssl/des.h>
# include <openssl/rand.h>
-# ifndef OPENSSL_FIPS
+/* Block use of implementations in FIPS mode */
+# undef EVP_CIPH_FLAG_FIPS
+# define EVP_CIPH_FLAG_FIPS 0
+
+typedef struct {
+ union {
+ double align;
+ DES_key_schedule ks[3];
+ } ks;
+ union {
+ void (*cbc) (const void *, void *, size_t, const void *, void *);
+ } stream;
+} DES_EDE_KEY;
+# define ks1 ks.ks[0]
+# define ks2 ks.ks[1]
+# define ks3 ks.ks[2]
+
+# if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
+/* ---------^^^ this is not a typo, just a way to detect that
+ * assembler support was in general requested... */
+# include "sparc_arch.h"
+
+extern unsigned int OPENSSL_sparcv9cap_P[];
+
+# define SPARC_DES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_DES)
+
+void des_t4_key_expand(const void *key, DES_key_schedule *ks);
+void des_t4_ede3_cbc_encrypt(const void *inp, void *out, size_t len,
+ DES_key_schedule *ks, unsigned char iv[8]);
+void des_t4_ede3_cbc_decrypt(const void *inp, void *out, size_t len,
+ DES_key_schedule *ks, unsigned char iv[8]);
+# endif
static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
@@ -75,13 +106,7 @@ static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
static int des3_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr);
-typedef struct {
- DES_key_schedule ks1; /* key schedule */
- DES_key_schedule ks2; /* key schedule (for ede) */
- DES_key_schedule ks3; /* key schedule (for ede3) */
-} DES_EDE_KEY;
-
-# define data(ctx) ((DES_EDE_KEY *)(ctx)->cipher_data)
+# define data(ctx) ((DES_EDE_KEY *)(ctx)->cipher_data)
/*
* Because of various casts and different args can't use
@@ -123,7 +148,9 @@ static int des_ede_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
static int des_ede_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
-# ifdef KSSL_DEBUG
+ DES_EDE_KEY *dat = data(ctx);
+
+# ifdef KSSL_DEBUG
{
int i;
fprintf(stderr, "des_ede_cbc_cipher(ctx=%p, buflen=%d)\n", ctx,
@@ -133,21 +160,24 @@ static int des_ede_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
fprintf(stderr, "%02X", ctx->iv[i]);
fprintf(stderr, "\n");
}
-# endif /* KSSL_DEBUG */
+# endif /* KSSL_DEBUG */
+ if (dat->stream.cbc) {
+ (*dat->stream.cbc) (in, out, inl, &dat->ks, ctx->iv);
+ return 1;
+ }
+
while (inl >= EVP_MAXCHUNK) {
DES_ede3_cbc_encrypt(in, out, (long)EVP_MAXCHUNK,
- &data(ctx)->ks1, &data(ctx)->ks2,
- &data(ctx)->ks3, (DES_cblock *)ctx->iv,
- ctx->encrypt);
+ &dat->ks1, &dat->ks2, &dat->ks3,
+ (DES_cblock *)ctx->iv, ctx->encrypt);
inl -= EVP_MAXCHUNK;
in += EVP_MAXCHUNK;
out += EVP_MAXCHUNK;
}
if (inl)
DES_ede3_cbc_encrypt(in, out, (long)inl,
- &data(ctx)->ks1, &data(ctx)->ks2,
- &data(ctx)->ks3, (DES_cblock *)ctx->iv,
- ctx->encrypt);
+ &dat->ks1, &dat->ks2, &dat->ks3,
+ (DES_cblock *)ctx->iv, ctx->encrypt);
return 1;
}
@@ -215,39 +245,57 @@ static int des_ede3_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
}
BLOCK_CIPHER_defs(des_ede, DES_EDE_KEY, NID_des_ede, 8, 16, 8, 64,
- EVP_CIPH_RAND_KEY, des_ede_init_key, NULL,
- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, des3_ctrl)
-# define des_ede3_cfb64_cipher des_ede_cfb64_cipher
-# define des_ede3_ofb_cipher des_ede_ofb_cipher
-# define des_ede3_cbc_cipher des_ede_cbc_cipher
-# define des_ede3_ecb_cipher des_ede_ecb_cipher
+ EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_DEFAULT_ASN1,
+ des_ede_init_key, NULL, NULL, NULL, des3_ctrl)
+# define des_ede3_cfb64_cipher des_ede_cfb64_cipher
+# define des_ede3_ofb_cipher des_ede_ofb_cipher
+# define des_ede3_cbc_cipher des_ede_cbc_cipher
+# define des_ede3_ecb_cipher des_ede_ecb_cipher
BLOCK_CIPHER_defs(des_ede3, DES_EDE_KEY, NID_des_ede3, 8, 24, 8, 64,
- EVP_CIPH_RAND_KEY, des_ede3_init_key, NULL,
- EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, des3_ctrl)
+ EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_FIPS |
+ EVP_CIPH_FLAG_DEFAULT_ASN1, des_ede3_init_key, NULL, NULL, NULL,
+ des3_ctrl)
BLOCK_CIPHER_def_cfb(des_ede3, DES_EDE_KEY, NID_des_ede3, 24, 8, 1,
- EVP_CIPH_RAND_KEY, des_ede3_init_key, NULL,
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv, des3_ctrl)
+ EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_FIPS |
+ EVP_CIPH_FLAG_DEFAULT_ASN1, des_ede3_init_key, NULL, NULL,
+ NULL, des3_ctrl)
BLOCK_CIPHER_def_cfb(des_ede3, DES_EDE_KEY, NID_des_ede3, 24, 8, 8,
- EVP_CIPH_RAND_KEY, des_ede3_init_key, NULL,
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv, des3_ctrl)
+ EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_FIPS |
+ EVP_CIPH_FLAG_DEFAULT_ASN1, des_ede3_init_key, NULL, NULL,
+ NULL, des3_ctrl)
static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
DES_cblock *deskey = (DES_cblock *)key;
-# ifdef EVP_CHECK_DES_KEY
- if (DES_set_key_checked(&deskey[0], &data(ctx)->ks1)
- ! !DES_set_key_checked(&deskey[1], &data(ctx)->ks2))
+ DES_EDE_KEY *dat = data(ctx);
+
+ dat->stream.cbc = NULL;
+# if defined(SPARC_DES_CAPABLE)
+ if (SPARC_DES_CAPABLE) {
+ int mode = ctx->cipher->flags & EVP_CIPH_MODE;
+
+ if (mode == EVP_CIPH_CBC_MODE) {
+ des_t4_key_expand(&deskey[0], &dat->ks1);
+ des_t4_key_expand(&deskey[1], &dat->ks2);
+ memcpy(&dat->ks3, &dat->ks1, sizeof(dat->ks1));
+ dat->stream.cbc = enc ? des_t4_ede3_cbc_encrypt :
+ des_t4_ede3_cbc_decrypt;
+ return 1;
+ }
+ }
+# endif
+# ifdef EVP_CHECK_DES_KEY
+ if (DES_set_key_checked(&deskey[0], &dat->ks1)
+ ! !DES_set_key_checked(&deskey[1], &dat->ks2))
return 0;
-# else
- DES_set_key_unchecked(&deskey[0], &data(ctx)->ks1);
- DES_set_key_unchecked(&deskey[1], &data(ctx)->ks2);
-# endif
- memcpy(&data(ctx)->ks3, &data(ctx)->ks1, sizeof(data(ctx)->ks1));
+# else
+ DES_set_key_unchecked(&deskey[0], &dat->ks1);
+ DES_set_key_unchecked(&deskey[1], &dat->ks2);
+# endif
+ memcpy(&dat->ks3, &dat->ks1, sizeof(dat->ks1));
return 1;
}
@@ -255,7 +303,9 @@ static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
DES_cblock *deskey = (DES_cblock *)key;
-# ifdef KSSL_DEBUG
+ DES_EDE_KEY *dat = data(ctx);
+
+# ifdef KSSL_DEBUG
{
int i;
fprintf(stderr, "des_ede3_init_key(ctx=%p)\n", ctx);
@@ -270,18 +320,33 @@ static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
fprintf(stderr, "\n");
}
}
-# endif /* KSSL_DEBUG */
+# endif /* KSSL_DEBUG */
+
+ dat->stream.cbc = NULL;
+# if defined(SPARC_DES_CAPABLE)
+ if (SPARC_DES_CAPABLE) {
+ int mode = ctx->cipher->flags & EVP_CIPH_MODE;
-# ifdef EVP_CHECK_DES_KEY
- if (DES_set_key_checked(&deskey[0], &data(ctx)->ks1)
- || DES_set_key_checked(&deskey[1], &data(ctx)->ks2)
- || DES_set_key_checked(&deskey[2], &data(ctx)->ks3))
+ if (mode == EVP_CIPH_CBC_MODE) {
+ des_t4_key_expand(&deskey[0], &dat->ks1);
+ des_t4_key_expand(&deskey[1], &dat->ks2);
+ des_t4_key_expand(&deskey[2], &dat->ks3);
+ dat->stream.cbc = enc ? des_t4_ede3_cbc_encrypt :
+ des_t4_ede3_cbc_decrypt;
+ return 1;
+ }
+ }
+# endif
+# ifdef EVP_CHECK_DES_KEY
+ if (DES_set_key_checked(&deskey[0], &dat->ks1)
+ || DES_set_key_checked(&deskey[1], &dat->ks2)
+ || DES_set_key_checked(&deskey[2], &dat->ks3))
return 0;
-# else
- DES_set_key_unchecked(&deskey[0], &data(ctx)->ks1);
- DES_set_key_unchecked(&deskey[1], &data(ctx)->ks2);
- DES_set_key_unchecked(&deskey[2], &data(ctx)->ks3);
-# endif
+# else
+ DES_set_key_unchecked(&deskey[0], &dat->ks1);
+ DES_set_key_unchecked(&deskey[1], &dat->ks2);
+ DES_set_key_unchecked(&deskey[2], &dat->ks3);
+# endif
return 1;
}
@@ -315,5 +380,115 @@ const EVP_CIPHER *EVP_des_ede3(void)
{
return &des_ede3_ecb;
}
+
+# ifndef OPENSSL_NO_SHA
+
+# include <openssl/sha.h>
+
+static const unsigned char wrap_iv[8] =
+ { 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05 };
+
+static int des_ede3_unwrap(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ unsigned char icv[8], iv[8], sha1tmp[SHA_DIGEST_LENGTH];
+ int rv = -1;
+ if (inl < 24)
+ return -1;
+ if (!out)
+ return inl - 16;
+ memcpy(ctx->iv, wrap_iv, 8);
+ /* Decrypt first block which will end up as icv */
+ des_ede_cbc_cipher(ctx, icv, in, 8);
+ /* Decrypt central blocks */
+ /*
+ * If decrypting in place move whole output along a block so the next
+ * des_ede_cbc_cipher is in place.
+ */
+ if (out == in) {
+ memmove(out, out + 8, inl - 8);
+ in -= 8;
+ }
+ des_ede_cbc_cipher(ctx, out, in + 8, inl - 16);
+ /* Decrypt final block which will be IV */
+ des_ede_cbc_cipher(ctx, iv, in + inl - 8, 8);
+ /* Reverse order of everything */
+ BUF_reverse(icv, NULL, 8);
+ BUF_reverse(out, NULL, inl - 16);
+ BUF_reverse(ctx->iv, iv, 8);
+ /* Decrypt again using new IV */
+ des_ede_cbc_cipher(ctx, out, out, inl - 16);
+ des_ede_cbc_cipher(ctx, icv, icv, 8);
+ /* Work out SHA1 hash of first portion */
+ SHA1(out, inl - 16, sha1tmp);
+
+ if (!CRYPTO_memcmp(sha1tmp, icv, 8))
+ rv = inl - 16;
+ OPENSSL_cleanse(icv, 8);
+ OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH);
+ OPENSSL_cleanse(iv, 8);
+ OPENSSL_cleanse(ctx->iv, 8);
+ if (rv == -1)
+ OPENSSL_cleanse(out, inl - 16);
+
+ return rv;
+}
+
+static int des_ede3_wrap(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ unsigned char sha1tmp[SHA_DIGEST_LENGTH];
+ if (!out)
+ return inl + 16;
+ /* Copy input to output buffer + 8 so we have space for IV */
+ memmove(out + 8, in, inl);
+ /* Work out ICV */
+ SHA1(in, inl, sha1tmp);
+ memcpy(out + inl + 8, sha1tmp, 8);
+ OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH);
+ /* Generate random IV */
+ if (RAND_bytes(ctx->iv, 8) <= 0)
+ return -1;
+ memcpy(out, ctx->iv, 8);
+ /* Encrypt everything after IV in place */
+ des_ede_cbc_cipher(ctx, out + 8, out + 8, inl + 8);
+ BUF_reverse(out, NULL, inl + 16);
+ memcpy(ctx->iv, wrap_iv, 8);
+ des_ede_cbc_cipher(ctx, out, out, inl + 16);
+ return inl + 16;
+}
+
+static int des_ede3_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ /*
+ * Sanity check input length: we typically only wrap keys so EVP_MAXCHUNK
+ * is more than will ever be needed. Also input length must be a multiple
+ * of 8 bits.
+ */
+ if (inl >= EVP_MAXCHUNK || inl % 8)
+ return -1;
+ if (ctx->encrypt)
+ return des_ede3_wrap(ctx, out, in, inl);
+ else
+ return des_ede3_unwrap(ctx, out, in, inl);
+}
+
+static const EVP_CIPHER des3_wrap = {
+ NID_id_smime_alg_CMS3DESwrap,
+ 8, 24, 0,
+ EVP_CIPH_WRAP_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER
+ | EVP_CIPH_FLAG_DEFAULT_ASN1,
+ des_ede3_init_key, des_ede3_wrap_cipher,
+ NULL,
+ sizeof(DES_EDE_KEY),
+ NULL, NULL, NULL, NULL
+};
+
+const EVP_CIPHER *EVP_des_ede3_wrap(void)
+{
+ return &des3_wrap;
+}
+
# endif
#endif
diff --git a/crypto/evp/e_null.c b/crypto/evp/e_null.c
index af90ce326bd9..599fcb808d21 100644
--- a/crypto/evp/e_null.c
+++ b/crypto/evp/e_null.c
@@ -61,8 +61,6 @@
#include <openssl/evp.h>
#include <openssl/objects.h>
-#ifndef OPENSSL_FIPS
-
static int null_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
static int null_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
@@ -100,4 +98,3 @@ static int null_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
memcpy((char *)out, (const char *)in, inl);
return 1;
}
-#endif
diff --git a/crypto/evp/encode.c b/crypto/evp/encode.c
index 5c5988fc45e1..c361d1f01269 100644
--- a/crypto/evp/encode.c
+++ b/crypto/evp/encode.c
@@ -248,7 +248,7 @@ int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
/* We parse the input data */
for (i = 0; i < inl; i++) {
- /* If the current line is > 80 characters, scream alot */
+ /* If the current line is > 80 characters, scream a lot */
if (ln >= 80) {
rv = -1;
goto end;
diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h
index 6cf98acc0b79..39ab7937d256 100644
--- a/crypto/evp/evp.h
+++ b/crypto/evp/evp.h
@@ -113,6 +113,7 @@
# define EVP_PKEY_DSA3 NID_dsaWithSHA1
# define EVP_PKEY_DSA4 NID_dsaWithSHA1_2
# define EVP_PKEY_DH NID_dhKeyAgreement
+# define EVP_PKEY_DHX NID_dhpublicnumber
# define EVP_PKEY_EC NID_X9_62_id_ecPublicKey
# define EVP_PKEY_HMAC NID_hmac
# define EVP_PKEY_CMAC NID_cmac
@@ -345,6 +346,7 @@ struct evp_cipher_st {
# define EVP_CIPH_GCM_MODE 0x6
# define EVP_CIPH_CCM_MODE 0x7
# define EVP_CIPH_XTS_MODE 0x10001
+# define EVP_CIPH_WRAP_MODE 0x10002
# define EVP_CIPH_MODE 0xF0007
/* Set if variable length cipher */
# define EVP_CIPH_VARIABLE_LENGTH 0x8
@@ -375,6 +377,14 @@ struct evp_cipher_st {
*/
# define EVP_CIPH_FLAG_CUSTOM_CIPHER 0x100000
# define EVP_CIPH_FLAG_AEAD_CIPHER 0x200000
+# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0x400000
+
+/*
+ * Cipher context flag to indicate we can handle wrap mode: if allowed in
+ * older applications it could overflow buffers.
+ */
+
+# define EVP_CIPHER_CTX_FLAG_WRAP_ALLOW 0x1
/* ctrl() values */
@@ -408,9 +418,21 @@ struct evp_cipher_st {
/* Set the GCM invocation field, decrypt only */
# define EVP_CTRL_GCM_SET_IV_INV 0x18
+# define EVP_CTRL_TLS1_1_MULTIBLOCK_AAD 0x19
+# define EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT 0x1a
+# define EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT 0x1b
+# define EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE 0x1c
+
/* RFC 5246 defines additional data to be 13 bytes in length */
# define EVP_AEAD_TLS1_AAD_LEN 13
+typedef struct {
+ unsigned char *out;
+ const unsigned char *inp;
+ size_t len;
+ unsigned int interleave;
+} EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM;
+
/* GCM TLS constants */
/* Length of fixed part of IV derived from PRF */
# define EVP_GCM_TLS_FIXED_IV_LEN 4
@@ -639,7 +661,8 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx,
int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey);
-int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, unsigned char *sig, size_t siglen);
+int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx,
+ const unsigned char *sig, size_t siglen);
int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
const unsigned char *ek, int ekl, const unsigned char *iv,
@@ -744,6 +767,7 @@ const EVP_CIPHER *EVP_des_cbc(void);
const EVP_CIPHER *EVP_des_ede_cbc(void);
const EVP_CIPHER *EVP_des_ede3_cbc(void);
const EVP_CIPHER *EVP_desx_cbc(void);
+const EVP_CIPHER *EVP_des_ede3_wrap(void);
/*
* This should now be supported through the dev_crypto ENGINE. But also, why
* are rc4 and md5 declarations made here inside a "NO_DES" precompiler
@@ -813,6 +837,7 @@ const EVP_CIPHER *EVP_aes_128_ctr(void);
const EVP_CIPHER *EVP_aes_128_ccm(void);
const EVP_CIPHER *EVP_aes_128_gcm(void);
const EVP_CIPHER *EVP_aes_128_xts(void);
+const EVP_CIPHER *EVP_aes_128_wrap(void);
const EVP_CIPHER *EVP_aes_192_ecb(void);
const EVP_CIPHER *EVP_aes_192_cbc(void);
const EVP_CIPHER *EVP_aes_192_cfb1(void);
@@ -823,6 +848,7 @@ const EVP_CIPHER *EVP_aes_192_ofb(void);
const EVP_CIPHER *EVP_aes_192_ctr(void);
const EVP_CIPHER *EVP_aes_192_ccm(void);
const EVP_CIPHER *EVP_aes_192_gcm(void);
+const EVP_CIPHER *EVP_aes_192_wrap(void);
const EVP_CIPHER *EVP_aes_256_ecb(void);
const EVP_CIPHER *EVP_aes_256_cbc(void);
const EVP_CIPHER *EVP_aes_256_cfb1(void);
@@ -834,10 +860,15 @@ const EVP_CIPHER *EVP_aes_256_ctr(void);
const EVP_CIPHER *EVP_aes_256_ccm(void);
const EVP_CIPHER *EVP_aes_256_gcm(void);
const EVP_CIPHER *EVP_aes_256_xts(void);
+const EVP_CIPHER *EVP_aes_256_wrap(void);
# if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha1(void);
const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha1(void);
# endif
+# ifndef OPENSSL_NO_SHA256
+const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha256(void);
+const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha256(void);
+# endif
# endif
# ifndef OPENSSL_NO_CAMELLIA
const EVP_CIPHER *EVP_camellia_128_ecb(void);
@@ -1028,6 +1059,7 @@ void EVP_PBE_cleanup(void);
# define ASN1_PKEY_CTRL_DEFAULT_MD_NID 0x3
# define ASN1_PKEY_CTRL_CMS_SIGN 0x5
# define ASN1_PKEY_CTRL_CMS_ENVELOPE 0x7
+# define ASN1_PKEY_CTRL_CMS_RI_TYPE 0x8
int EVP_PKEY_asn1_get_count(void);
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx);
@@ -1091,6 +1123,19 @@ void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_ctrl) (EVP_PKEY *pkey, int op,
long arg1, void *arg2));
+void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth,
+ int (*item_verify) (EVP_MD_CTX *ctx,
+ const ASN1_ITEM *it,
+ void *asn,
+ X509_ALGOR *a,
+ ASN1_BIT_STRING *sig,
+ EVP_PKEY *pkey),
+ int (*item_sign) (EVP_MD_CTX *ctx,
+ const ASN1_ITEM *it,
+ void *asn,
+ X509_ALGOR *alg1,
+ X509_ALGOR *alg2,
+ ASN1_BIT_STRING *sig));
# define EVP_PKEY_OP_UNDEFINED 0
# define EVP_PKEY_OP_PARAMGEN (1<<1)
@@ -1121,6 +1166,10 @@ void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \
EVP_PKEY_CTRL_MD, 0, (void *)md)
+# define EVP_PKEY_CTX_get_signature_md(ctx, pmd) \
+ EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \
+ EVP_PKEY_CTRL_GET_MD, 0, (void *)pmd)
+
# define EVP_PKEY_CTRL_MD 1
# define EVP_PKEY_CTRL_PEER_KEY 2
@@ -1142,6 +1191,8 @@ void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
# define EVP_PKEY_CTRL_CIPHER 12
+# define EVP_PKEY_CTRL_GET_MD 13
+
# define EVP_PKEY_ALG_CTRL 0x1000
# define EVP_PKEY_FLAG_AUTOARGLEN 2
@@ -1327,11 +1378,13 @@ void ERR_load_EVP_strings(void);
# define EVP_F_AESNI_INIT_KEY 165
# define EVP_F_AESNI_XTS_CIPHER 176
# define EVP_F_AES_INIT_KEY 133
+# define EVP_F_AES_T4_INIT_KEY 178
# define EVP_F_AES_XTS 172
# define EVP_F_AES_XTS_CIPHER 175
# define EVP_F_ALG_MODULE_INIT 177
# define EVP_F_CAMELLIA_INIT_KEY 159
# define EVP_F_CMAC_INIT 173
+# define EVP_F_CMLL_T4_INIT_KEY 179
# define EVP_F_D2I_PKEY 100
# define EVP_F_DO_SIGVER_INIT 161
# define EVP_F_DSAPKEY2PKCS8 134
@@ -1471,6 +1524,7 @@ void ERR_load_EVP_strings(void);
# define EVP_R_UNSUPPORTED_PRF 125
# define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM 118
# define EVP_R_UNSUPPORTED_SALT_TYPE 126
+# define EVP_R_WRAP_MODE_NOT_ALLOWED 170
# define EVP_R_WRONG_FINAL_BLOCK_LENGTH 109
# define EVP_R_WRONG_PUBLIC_KEY_TYPE 110
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index 4e983c4bda23..65f0e0244dce 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -169,8 +169,14 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
#endif
#ifdef OPENSSL_FIPS
- if (FIPS_mode())
+ if (FIPS_mode()) {
+ const EVP_CIPHER *fcipher;
+ if (cipher)
+ fcipher = evp_get_fips_cipher(cipher);
+ if (fcipher)
+ cipher = fcipher;
return FIPS_cipherinit(ctx, cipher, key, iv, enc);
+ }
#endif
ctx->cipher = cipher;
if (ctx->cipher->ctx_size) {
@@ -183,7 +189,8 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
ctx->cipher_data = NULL;
}
ctx->key_len = cipher->key_len;
- ctx->flags = 0;
+ /* Preserve wrap enable flag, zero everything else */
+ ctx->flags &= EVP_CIPHER_CTX_FLAG_WRAP_ALLOW;
if (ctx->cipher->flags & EVP_CIPH_CTRL_INIT) {
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) {
EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
@@ -206,6 +213,12 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|| ctx->cipher->block_size == 8
|| ctx->cipher->block_size == 16);
+ if (!(ctx->flags & EVP_CIPHER_CTX_FLAG_WRAP_ALLOW)
+ && EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_WRAP_MODE) {
+ EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_WRAP_MODE_NOT_ALLOWED);
+ return 0;
+ }
+
if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) {
switch (EVP_CIPHER_CTX_mode(ctx)) {
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index 686a69958dd7..15cf5532b382 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -1,6 +1,6 @@
/* crypto/evp/evp_err.c */
/* ====================================================================
- * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2013 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -73,11 +73,13 @@ static ERR_STRING_DATA EVP_str_functs[] = {
{ERR_FUNC(EVP_F_AESNI_INIT_KEY), "AESNI_INIT_KEY"},
{ERR_FUNC(EVP_F_AESNI_XTS_CIPHER), "AESNI_XTS_CIPHER"},
{ERR_FUNC(EVP_F_AES_INIT_KEY), "AES_INIT_KEY"},
+ {ERR_FUNC(EVP_F_AES_T4_INIT_KEY), "AES_T4_INIT_KEY"},
{ERR_FUNC(EVP_F_AES_XTS), "AES_XTS"},
{ERR_FUNC(EVP_F_AES_XTS_CIPHER), "AES_XTS_CIPHER"},
{ERR_FUNC(EVP_F_ALG_MODULE_INIT), "ALG_MODULE_INIT"},
{ERR_FUNC(EVP_F_CAMELLIA_INIT_KEY), "CAMELLIA_INIT_KEY"},
{ERR_FUNC(EVP_F_CMAC_INIT), "CMAC_INIT"},
+ {ERR_FUNC(EVP_F_CMLL_T4_INIT_KEY), "CMLL_T4_INIT_KEY"},
{ERR_FUNC(EVP_F_D2I_PKEY), "D2I_PKEY"},
{ERR_FUNC(EVP_F_DO_SIGVER_INIT), "DO_SIGVER_INIT"},
{ERR_FUNC(EVP_F_DSAPKEY2PKCS8), "DSAPKEY2PKCS8"},
@@ -232,6 +234,7 @@ static ERR_STRING_DATA EVP_str_reasons[] = {
{ERR_REASON(EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM),
"unsupported private key algorithm"},
{ERR_REASON(EVP_R_UNSUPPORTED_SALT_TYPE), "unsupported salt type"},
+ {ERR_REASON(EVP_R_WRAP_MODE_NOT_ALLOWED), "wrap mode not allowed"},
{ERR_REASON(EVP_R_WRONG_FINAL_BLOCK_LENGTH), "wrong final block length"},
{ERR_REASON(EVP_R_WRONG_PUBLIC_KEY_TYPE), "wrong public key type"},
{0, NULL}
diff --git a/crypto/evp/evp_extra_test.c b/crypto/evp/evp_extra_test.c
index 21688b0cd383..0f7b011ce85e 100644
--- a/crypto/evp/evp_extra_test.c
+++ b/crypto/evp/evp_extra_test.c
@@ -345,7 +345,7 @@ static int test_EVP_DigestVerifyInit(void)
if (pkey == NULL ||
!EVP_DigestVerifyInit(&md_ctx, NULL, EVP_sha256(), NULL, pkey) ||
!EVP_DigestVerifyUpdate(&md_ctx, kMsg, sizeof(kMsg)) ||
- !EVP_DigestVerifyFinal(&md_ctx, (unsigned char *)kSignature, sizeof(kSignature))) {
+ !EVP_DigestVerifyFinal(&md_ctx, kSignature, sizeof(kSignature))) {
goto out;
}
ret = 1;
diff --git a/crypto/evp/evp_fips.c b/crypto/evp/evp_fips.c
deleted file mode 100644
index 71a32fca8d2a..000000000000
--- a/crypto/evp/evp_fips.c
+++ /dev/null
@@ -1,310 +0,0 @@
-/* crypto/evp/evp_fips.c */
-/*
- * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project.
- */
-/* ====================================================================
- * Copyright (c) 2011 The OpenSSL Project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission. For written permission, please contact
- * licensing@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- * nor may "OpenSSL" appear in their names without prior written
- * permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
-#include <openssl/evp.h>
-
-#ifdef OPENSSL_FIPS
-# include <openssl/fips.h>
-
-const EVP_CIPHER *EVP_aes_128_cbc(void)
-{
- return FIPS_evp_aes_128_cbc();
-}
-
-const EVP_CIPHER *EVP_aes_128_ccm(void)
-{
- return FIPS_evp_aes_128_ccm();
-}
-
-const EVP_CIPHER *EVP_aes_128_cfb1(void)
-{
- return FIPS_evp_aes_128_cfb1();
-}
-
-const EVP_CIPHER *EVP_aes_128_cfb128(void)
-{
- return FIPS_evp_aes_128_cfb128();
-}
-
-const EVP_CIPHER *EVP_aes_128_cfb8(void)
-{
- return FIPS_evp_aes_128_cfb8();
-}
-
-const EVP_CIPHER *EVP_aes_128_ctr(void)
-{
- return FIPS_evp_aes_128_ctr();
-}
-
-const EVP_CIPHER *EVP_aes_128_ecb(void)
-{
- return FIPS_evp_aes_128_ecb();
-}
-
-const EVP_CIPHER *EVP_aes_128_gcm(void)
-{
- return FIPS_evp_aes_128_gcm();
-}
-
-const EVP_CIPHER *EVP_aes_128_ofb(void)
-{
- return FIPS_evp_aes_128_ofb();
-}
-
-const EVP_CIPHER *EVP_aes_128_xts(void)
-{
- return FIPS_evp_aes_128_xts();
-}
-
-const EVP_CIPHER *EVP_aes_192_cbc(void)
-{
- return FIPS_evp_aes_192_cbc();
-}
-
-const EVP_CIPHER *EVP_aes_192_ccm(void)
-{
- return FIPS_evp_aes_192_ccm();
-}
-
-const EVP_CIPHER *EVP_aes_192_cfb1(void)
-{
- return FIPS_evp_aes_192_cfb1();
-}
-
-const EVP_CIPHER *EVP_aes_192_cfb128(void)
-{
- return FIPS_evp_aes_192_cfb128();
-}
-
-const EVP_CIPHER *EVP_aes_192_cfb8(void)
-{
- return FIPS_evp_aes_192_cfb8();
-}
-
-const EVP_CIPHER *EVP_aes_192_ctr(void)
-{
- return FIPS_evp_aes_192_ctr();
-}
-
-const EVP_CIPHER *EVP_aes_192_ecb(void)
-{
- return FIPS_evp_aes_192_ecb();
-}
-
-const EVP_CIPHER *EVP_aes_192_gcm(void)
-{
- return FIPS_evp_aes_192_gcm();
-}
-
-const EVP_CIPHER *EVP_aes_192_ofb(void)
-{
- return FIPS_evp_aes_192_ofb();
-}
-
-const EVP_CIPHER *EVP_aes_256_cbc(void)
-{
- return FIPS_evp_aes_256_cbc();
-}
-
-const EVP_CIPHER *EVP_aes_256_ccm(void)
-{
- return FIPS_evp_aes_256_ccm();
-}
-
-const EVP_CIPHER *EVP_aes_256_cfb1(void)
-{
- return FIPS_evp_aes_256_cfb1();
-}
-
-const EVP_CIPHER *EVP_aes_256_cfb128(void)
-{
- return FIPS_evp_aes_256_cfb128();
-}
-
-const EVP_CIPHER *EVP_aes_256_cfb8(void)
-{
- return FIPS_evp_aes_256_cfb8();
-}
-
-const EVP_CIPHER *EVP_aes_256_ctr(void)
-{
- return FIPS_evp_aes_256_ctr();
-}
-
-const EVP_CIPHER *EVP_aes_256_ecb(void)
-{
- return FIPS_evp_aes_256_ecb();
-}
-
-const EVP_CIPHER *EVP_aes_256_gcm(void)
-{
- return FIPS_evp_aes_256_gcm();
-}
-
-const EVP_CIPHER *EVP_aes_256_ofb(void)
-{
- return FIPS_evp_aes_256_ofb();
-}
-
-const EVP_CIPHER *EVP_aes_256_xts(void)
-{
- return FIPS_evp_aes_256_xts();
-}
-
-const EVP_CIPHER *EVP_des_ede(void)
-{
- return FIPS_evp_des_ede();
-}
-
-const EVP_CIPHER *EVP_des_ede3(void)
-{
- return FIPS_evp_des_ede3();
-}
-
-const EVP_CIPHER *EVP_des_ede3_cbc(void)
-{
- return FIPS_evp_des_ede3_cbc();
-}
-
-const EVP_CIPHER *EVP_des_ede3_cfb1(void)
-{
- return FIPS_evp_des_ede3_cfb1();
-}
-
-const EVP_CIPHER *EVP_des_ede3_cfb64(void)
-{
- return FIPS_evp_des_ede3_cfb64();
-}
-
-const EVP_CIPHER *EVP_des_ede3_cfb8(void)
-{
- return FIPS_evp_des_ede3_cfb8();
-}
-
-const EVP_CIPHER *EVP_des_ede3_ecb(void)
-{
- return FIPS_evp_des_ede3_ecb();
-}
-
-const EVP_CIPHER *EVP_des_ede3_ofb(void)
-{
- return FIPS_evp_des_ede3_ofb();
-}
-
-const EVP_CIPHER *EVP_des_ede_cbc(void)
-{
- return FIPS_evp_des_ede_cbc();
-}
-
-const EVP_CIPHER *EVP_des_ede_cfb64(void)
-{
- return FIPS_evp_des_ede_cfb64();
-}
-
-const EVP_CIPHER *EVP_des_ede_ecb(void)
-{
- return FIPS_evp_des_ede_ecb();
-}
-
-const EVP_CIPHER *EVP_des_ede_ofb(void)
-{
- return FIPS_evp_des_ede_ofb();
-}
-
-const EVP_CIPHER *EVP_enc_null(void)
-{
- return FIPS_evp_enc_null();
-}
-
-const EVP_MD *EVP_sha1(void)
-{
- return FIPS_evp_sha1();
-}
-
-const EVP_MD *EVP_sha224(void)
-{
- return FIPS_evp_sha224();
-}
-
-const EVP_MD *EVP_sha256(void)
-{
- return FIPS_evp_sha256();
-}
-
-const EVP_MD *EVP_sha384(void)
-{
- return FIPS_evp_sha384();
-}
-
-const EVP_MD *EVP_sha512(void)
-{
- return FIPS_evp_sha512();
-}
-
-const EVP_MD *EVP_dss(void)
-{
- return FIPS_evp_dss();
-}
-
-const EVP_MD *EVP_dss1(void)
-{
- return FIPS_evp_dss1();
-}
-
-const EVP_MD *EVP_ecdsa(void)
-{
- return FIPS_evp_ecdsa();
-}
-
-#endif
diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c
index d4d2b4b28081..a53a27ca0c92 100644
--- a/crypto/evp/evp_lib.c
+++ b/crypto/evp/evp_lib.c
@@ -60,6 +60,10 @@
#include "cryptlib.h"
#include <openssl/evp.h>
#include <openssl/objects.h>
+#ifdef OPENSSL_FIPS
+# include <openssl/fips.h>
+# include "evp_locl.h"
+#endif
int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
{
@@ -67,9 +71,13 @@ int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
if (c->cipher->set_asn1_parameters != NULL)
ret = c->cipher->set_asn1_parameters(c, type);
- else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1)
- ret = EVP_CIPHER_set_asn1_iv(c, type);
- else
+ else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) {
+ if (EVP_CIPHER_CTX_mode(c) == EVP_CIPH_WRAP_MODE) {
+ ASN1_TYPE_set(type, V_ASN1_NULL, NULL);
+ ret = 1;
+ } else
+ ret = EVP_CIPHER_set_asn1_iv(c, type);
+ } else
ret = -1;
return (ret);
}
@@ -80,9 +88,11 @@ int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
if (c->cipher->get_asn1_parameters != NULL)
ret = c->cipher->get_asn1_parameters(c, type);
- else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1)
+ else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) {
+ if (EVP_CIPHER_CTX_mode(c) == EVP_CIPH_WRAP_MODE)
+ return 1;
ret = EVP_CIPHER_get_asn1_iv(c, type);
- else
+ } else
ret = -1;
return (ret);
}
@@ -200,12 +210,22 @@ const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx)
unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher)
{
+#ifdef OPENSSL_FIPS
+ const EVP_CIPHER *fcipher;
+ fcipher = evp_get_fips_cipher(cipher);
+ if (fcipher && fcipher->flags & EVP_CIPH_FLAG_FIPS)
+ return cipher->flags | EVP_CIPH_FLAG_FIPS;
+#endif
return cipher->flags;
}
unsigned long EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx)
{
+#ifdef OPENSSL_FIPS
+ return EVP_CIPHER_flags(ctx->cipher);
+#else
return ctx->cipher->flags;
+#endif
}
void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx)
@@ -272,8 +292,40 @@ int EVP_MD_size(const EVP_MD *md)
return md->md_size;
}
+#ifdef OPENSSL_FIPS
+
+const EVP_MD *evp_get_fips_md(const EVP_MD *md)
+{
+ int nid = EVP_MD_type(md);
+ if (nid == NID_dsa)
+ return FIPS_evp_dss1();
+ else if (nid == NID_dsaWithSHA)
+ return FIPS_evp_dss();
+ else if (nid == NID_ecdsa_with_SHA1)
+ return FIPS_evp_ecdsa();
+ else
+ return FIPS_get_digestbynid(nid);
+}
+
+const EVP_CIPHER *evp_get_fips_cipher(const EVP_CIPHER *cipher)
+{
+ int nid = cipher->nid;
+ if (nid == NID_undef)
+ return FIPS_evp_enc_null();
+ else
+ return FIPS_get_cipherbynid(nid);
+}
+
+#endif
+
unsigned long EVP_MD_flags(const EVP_MD *md)
{
+#ifdef OPENSSL_FIPS
+ const EVP_MD *fmd;
+ fmd = evp_get_fips_md(md);
+ if (fmd && fmd->flags & EVP_MD_FLAG_FIPS)
+ return md->flags | EVP_MD_FLAG_FIPS;
+#endif
return md->flags;
}
diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h
index 980dadab23d4..2bb709a065d5 100644
--- a/crypto/evp/evp_locl.h
+++ b/crypto/evp/evp_locl.h
@@ -333,6 +333,9 @@ int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
const EVP_CIPHER *c, const EVP_MD *md,
int en_de);
+const EVP_MD *evp_get_fips_md(const EVP_MD *md);
+const EVP_CIPHER *evp_get_fips_cipher(const EVP_CIPHER *cipher);
+
#ifdef OPENSSL_FIPS
# ifdef OPENSSL_DOING_MAKEDEPEND
diff --git a/crypto/evp/evp_test.c b/crypto/evp/evp_test.c
index d06b4ee50914..d7441ec7b702 100644
--- a/crypto/evp/evp_test.c
+++ b/crypto/evp/evp_test.c
@@ -132,11 +132,13 @@ static int test1_exit(int ec)
static void test1(const EVP_CIPHER *c, const unsigned char *key, int kn,
const unsigned char *iv, int in,
const unsigned char *plaintext, int pn,
- const unsigned char *ciphertext, int cn, int encdec)
+ const unsigned char *ciphertext, int cn,
+ const unsigned char *aad, int an,
+ const unsigned char *tag, int tn, int encdec)
{
EVP_CIPHER_CTX ctx;
unsigned char out[4096];
- int outl, outl2;
+ int outl, outl2, mode;
printf("Testing cipher %s%s\n", EVP_CIPHER_name(c),
(encdec ==
@@ -147,15 +149,78 @@ static void test1(const EVP_CIPHER *c, const unsigned char *key, int kn,
hexdump(stdout, "IV", iv, in);
hexdump(stdout, "Plaintext", plaintext, pn);
hexdump(stdout, "Ciphertext", ciphertext, cn);
-
- if (kn != c->key_len) {
+ if (an)
+ hexdump(stdout, "AAD", aad, an);
+ if (tn)
+ hexdump(stdout, "Tag", tag, tn);
+ mode = EVP_CIPHER_mode(c);
+ if (kn != EVP_CIPHER_key_length(c)) {
fprintf(stderr, "Key length doesn't match, got %d expected %lu\n", kn,
- (unsigned long)c->key_len);
+ (unsigned long)EVP_CIPHER_key_length(c));
test1_exit(5);
}
EVP_CIPHER_CTX_init(&ctx);
+ EVP_CIPHER_CTX_set_flags(&ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
if (encdec != 0) {
- if (!EVP_EncryptInit_ex(&ctx, c, NULL, key, iv)) {
+ if (mode == EVP_CIPH_GCM_MODE) {
+ if (!EVP_EncryptInit_ex(&ctx, c, NULL, NULL, NULL)) {
+ fprintf(stderr, "EncryptInit failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(10);
+ }
+ if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, in, NULL)) {
+ fprintf(stderr, "IV length set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(11);
+ }
+ if (!EVP_EncryptInit_ex(&ctx, NULL, NULL, key, iv)) {
+ fprintf(stderr, "Key/IV set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(12);
+ }
+ if (an && !EVP_EncryptUpdate(&ctx, NULL, &outl, aad, an)) {
+ fprintf(stderr, "AAD set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(13);
+ }
+ } else if (mode == EVP_CIPH_CCM_MODE) {
+ if (!EVP_EncryptInit_ex(&ctx, c, NULL, NULL, NULL)) {
+ fprintf(stderr, "EncryptInit failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(10);
+ }
+ if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_IVLEN, in, NULL)) {
+ fprintf(stderr, "IV length set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(11);
+ }
+ if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_TAG, tn, NULL)) {
+ fprintf(stderr, "Tag length set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(11);
+ }
+ if (!EVP_EncryptInit_ex(&ctx, NULL, NULL, key, iv)) {
+ fprintf(stderr, "Key/IV set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(12);
+ }
+ if (!EVP_EncryptUpdate(&ctx, NULL, &outl, NULL, pn)) {
+ fprintf(stderr, "Plaintext length set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(12);
+ }
+ if (an && !EVP_EncryptUpdate(&ctx, NULL, &outl, aad, an)) {
+ fprintf(stderr, "AAD set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(13);
+ }
+ } else if (mode == EVP_CIPH_WRAP_MODE) {
+ if (!EVP_EncryptInit_ex(&ctx, c, NULL, key, in ? iv : NULL)) {
+ fprintf(stderr, "EncryptInit failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(10);
+ }
+ } else if (!EVP_EncryptInit_ex(&ctx, c, NULL, key, iv)) {
fprintf(stderr, "EncryptInit failed\n");
ERR_print_errors_fp(stderr);
test1_exit(10);
@@ -185,10 +250,93 @@ static void test1(const EVP_CIPHER *c, const unsigned char *key, int kn,
hexdump(stderr, "Expected", ciphertext, cn);
test1_exit(9);
}
+ if (mode == EVP_CIPH_GCM_MODE || mode == EVP_CIPH_CCM_MODE) {
+ unsigned char rtag[16];
+ /*
+ * Note: EVP_CTRL_CCM_GET_TAG has same value as
+ * EVP_CTRL_GCM_GET_TAG
+ */
+ if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, tn, rtag)) {
+ fprintf(stderr, "Get tag failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(14);
+ }
+ if (memcmp(rtag, tag, tn)) {
+ fprintf(stderr, "Tag mismatch\n");
+ hexdump(stderr, "Got", rtag, tn);
+ hexdump(stderr, "Expected", tag, tn);
+ test1_exit(9);
+ }
+ }
}
if (encdec <= 0) {
- if (!EVP_DecryptInit_ex(&ctx, c, NULL, key, iv)) {
+ if (mode == EVP_CIPH_GCM_MODE) {
+ if (!EVP_DecryptInit_ex(&ctx, c, NULL, NULL, NULL)) {
+ fprintf(stderr, "EncryptInit failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(10);
+ }
+ if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, in, NULL)) {
+ fprintf(stderr, "IV length set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(11);
+ }
+ if (!EVP_DecryptInit_ex(&ctx, NULL, NULL, key, iv)) {
+ fprintf(stderr, "Key/IV set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(12);
+ }
+ if (!EVP_CIPHER_CTX_ctrl
+ (&ctx, EVP_CTRL_GCM_SET_TAG, tn, (void *)tag)) {
+ fprintf(stderr, "Set tag failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(14);
+ }
+ if (an && !EVP_DecryptUpdate(&ctx, NULL, &outl, aad, an)) {
+ fprintf(stderr, "AAD set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(13);
+ }
+ } else if (mode == EVP_CIPH_CCM_MODE) {
+ if (!EVP_DecryptInit_ex(&ctx, c, NULL, NULL, NULL)) {
+ fprintf(stderr, "DecryptInit failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(10);
+ }
+ if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_IVLEN, in, NULL)) {
+ fprintf(stderr, "IV length set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(11);
+ }
+ if (!EVP_CIPHER_CTX_ctrl
+ (&ctx, EVP_CTRL_CCM_SET_TAG, tn, (void *)tag)) {
+ fprintf(stderr, "Tag length set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(11);
+ }
+ if (!EVP_DecryptInit_ex(&ctx, NULL, NULL, key, iv)) {
+ fprintf(stderr, "Key/Nonce set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(12);
+ }
+ if (!EVP_DecryptUpdate(&ctx, NULL, &outl, NULL, pn)) {
+ fprintf(stderr, "Plaintext length set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(12);
+ }
+ if (an && !EVP_EncryptUpdate(&ctx, NULL, &outl, aad, an)) {
+ fprintf(stderr, "AAD set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(13);
+ }
+ } else if (mode == EVP_CIPH_WRAP_MODE) {
+ if (!EVP_DecryptInit_ex(&ctx, c, NULL, key, in ? iv : NULL)) {
+ fprintf(stderr, "EncryptInit failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(10);
+ }
+ } else if (!EVP_DecryptInit_ex(&ctx, c, NULL, key, iv)) {
fprintf(stderr, "DecryptInit failed\n");
ERR_print_errors_fp(stderr);
test1_exit(11);
@@ -200,7 +348,8 @@ static void test1(const EVP_CIPHER *c, const unsigned char *key, int kn,
ERR_print_errors_fp(stderr);
test1_exit(6);
}
- if (!EVP_DecryptFinal_ex(&ctx, out + outl, &outl2)) {
+ if (mode != EVP_CIPH_CCM_MODE
+ && !EVP_DecryptFinal_ex(&ctx, out + outl, &outl2)) {
fprintf(stderr, "DecryptFinal failed\n");
ERR_print_errors_fp(stderr);
test1_exit(7);
@@ -228,7 +377,9 @@ static void test1(const EVP_CIPHER *c, const unsigned char *key, int kn,
static int test_cipher(const char *cipher, const unsigned char *key, int kn,
const unsigned char *iv, int in,
const unsigned char *plaintext, int pn,
- const unsigned char *ciphertext, int cn, int encdec)
+ const unsigned char *ciphertext, int cn,
+ const unsigned char *aad, int an,
+ const unsigned char *tag, int tn, int encdec)
{
const EVP_CIPHER *c;
@@ -236,7 +387,8 @@ static int test_cipher(const char *cipher, const unsigned char *key, int kn,
if (!c)
return 0;
- test1(c, key, kn, iv, in, plaintext, pn, ciphertext, cn, encdec);
+ test1(c, key, kn, iv, in, plaintext, pn, ciphertext, cn, aad, an, tag, tn,
+ encdec);
return 1;
}
@@ -316,7 +468,7 @@ int main(int argc, char **argv)
perror(szTestFile);
EXIT(2);
}
-
+ ERR_load_crypto_strings();
/* Load up the software EVP_CIPHER and EVP_MD definitions */
OpenSSL_add_all_ciphers();
OpenSSL_add_all_digests();
@@ -346,9 +498,11 @@ int main(int argc, char **argv)
char line[4096];
char *p;
char *cipher;
- unsigned char *iv, *key, *plaintext, *ciphertext;
+ unsigned char *iv, *key, *plaintext, *ciphertext, *aad, *tag;
int encdec;
int kn, in, pn, cn;
+ int an = 0;
+ int tn = 0;
if (!fgets((char *)line, sizeof line, f))
break;
@@ -361,19 +515,37 @@ int main(int argc, char **argv)
plaintext = ustrsep(&p, ":");
ciphertext = ustrsep(&p, ":");
if (p[-1] == '\n') {
- p[-1] = '\0';
encdec = -1;
+ p[-1] = '\0';
+ tag = aad = NULL;
+ an = tn = 0;
} else {
- encdec = atoi(sstrsep(&p, "\n"));
+ aad = ustrsep(&p, ":");
+ tag = ustrsep(&p, ":");
+ if (tag == NULL) {
+ p = (char *)aad;
+ tag = aad = NULL;
+ an = tn = 0;
+ }
+ if (p[-1] == '\n') {
+ encdec = -1;
+ p[-1] = '\0';
+ } else
+ encdec = atoi(sstrsep(&p, "\n"));
}
kn = convert(key);
in = convert(iv);
pn = convert(plaintext);
cn = convert(ciphertext);
+ if (aad) {
+ an = convert(aad);
+ tn = convert(tag);
+ }
if (!test_cipher
- (cipher, key, kn, iv, in, plaintext, pn, ciphertext, cn, encdec)
+ (cipher, key, kn, iv, in, plaintext, pn, ciphertext, cn, aad, an,
+ tag, tn, encdec)
&& !test_digest(cipher, plaintext, pn, ciphertext, cn)) {
#ifdef OPENSSL_NO_AES
if (strstr(cipher, "AES") == cipher) {
diff --git a/crypto/evp/evptests.txt b/crypto/evp/evptests.txt
index c273707c1444..4e9958b3b5bc 100644
--- a/crypto/evp/evptests.txt
+++ b/crypto/evp/evptests.txt
@@ -1,4 +1,5 @@
#cipher:key:iv:plaintext:ciphertext:0/1(decrypt/encrypt)
+#aadcipher:key:iv:plaintext:ciphertext:aad:tag:0/1(decrypt/encrypt)
#digest:::input:output
# SHA(1) tests (from shatest.c)
@@ -332,3 +333,69 @@ SEED-ECB:00000000000000000000000000000000::000102030405060708090A0B0C0D0E0F:5EBA
SEED-ECB:000102030405060708090A0B0C0D0E0F::00000000000000000000000000000000:C11F22F20140505084483597E4370F43:1
SEED-ECB:4706480851E61BE85D74BFB3FD956185::83A2F8A288641FB9A4E9A5CC2F131C7D:EE54D13EBCAE706D226BC3142CD40D4A:1
SEED-ECB:28DBC3BC49FFD87DCFA509B11D422BE7::B41E6BE2EBA84A148E2EED84593C5EC7:9B9B7BFCD1813CB95D0B3618F40F5122:1
+
+# AES CCM 256 bit key
+aes-256-ccm:1bde3251d41a8b5ea013c195ae128b218b3e0306376357077ef1c1c78548b92e:5b8e40746f6b98e00f1d13ff41:53bd72a97089e312422bf72e242377b3c6ee3e2075389b999c4ef7f28bd2b80a:9a5fcccdb4cf04e7293d2775cc76a488f042382d949b43b7d6bb2b9864786726:c17a32514eb6103f3249e076d4c871dc97e04b286699e54491dc18f6d734d4c0:2024931d73bca480c24a24ece6b6c2bf
+
+# AES GCM test vectors from http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf
+aes-128-gcm:00000000000000000000000000000000:000000000000000000000000::::58e2fccefa7e3061367f1d57a4e7455a
+aes-128-gcm:00000000000000000000000000000000:000000000000000000000000:00000000000000000000000000000000:0388dace60b6a392f328c2b971b2fe78::ab6e47d42cec13bdf53a67b21257bddf
+aes-128-gcm:feffe9928665731c6d6a8f9467308308:cafebabefacedbaddecaf888:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255:42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985::4d5c2af327cd64a62cf35abd2ba6fab4
+aes-128-gcm:feffe9928665731c6d6a8f9467308308:cafebabefacedbaddecaf888:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39:42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091:feedfacedeadbeeffeedfacedeadbeefabaddad2:5bc94fbc3221a5db94fae95ae7121a47
+aes-128-gcm:feffe9928665731c6d6a8f9467308308:cafebabefacedbad:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39:61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598:feedfacedeadbeeffeedfacedeadbeefabaddad2:3612d2e79e3b0785561be14aaca2fccb
+aes-128-gcm:feffe9928665731c6d6a8f9467308308:9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39:8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5:feedfacedeadbeeffeedfacedeadbeefabaddad2:619cc5aefffe0bfa462af43c1699d050
+aes-192-gcm:000000000000000000000000000000000000000000000000:000000000000000000000000::::cd33b28ac773f74ba00ed1f312572435
+aes-192-gcm:000000000000000000000000000000000000000000000000:000000000000000000000000:00000000000000000000000000000000:98e7247c07f0fe411c267e4384b0f600::2ff58d80033927ab8ef4d4587514f0fb
+aes-192-gcm:feffe9928665731c6d6a8f9467308308feffe9928665731c:cafebabefacedbaddecaf888:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255:3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256::9924a7c8587336bfb118024db8674a14
+aes-192-gcm:feffe9928665731c6d6a8f9467308308feffe9928665731c:cafebabefacedbaddecaf888:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39:3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710:feedfacedeadbeeffeedfacedeadbeefabaddad2:2519498e80f1478f37ba55bd6d27618c
+aes-192-gcm:feffe9928665731c6d6a8f9467308308feffe9928665731c:cafebabefacedbad:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39:0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7:feedfacedeadbeeffeedfacedeadbeefabaddad2:65dcc57fcf623a24094fcca40d3533f8
+aes-192-gcm:feffe9928665731c6d6a8f9467308308feffe9928665731c:9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39:d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b:feedfacedeadbeeffeedfacedeadbeefabaddad2:dcf566ff291c25bbb8568fc3d376a6d9
+aes-256-gcm:0000000000000000000000000000000000000000000000000000000000000000:000000000000000000000000::::530f8afbc74536b9a963b4f1c4cb738b
+aes-256-gcm:0000000000000000000000000000000000000000000000000000000000000000:000000000000000000000000:00000000000000000000000000000000:cea7403d4d606b6e074ec5d3baf39d18::d0d1c8a799996bf0265b98b5d48ab919
+aes-256-gcm:feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308:cafebabefacedbaddecaf888:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255:522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad::b094dac5d93471bdec1a502270e3cc6c
+aes-256-gcm:feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308:cafebabefacedbaddecaf888:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39:522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662:feedfacedeadbeeffeedfacedeadbeefabaddad2:76fc6ece0f4e1768cddf8853bb2d551b
+aes-256-gcm:feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308:cafebabefacedbad:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39:c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f:feedfacedeadbeeffeedfacedeadbeefabaddad2:3a337dbf46a792c45e454913fe2ea8f2
+aes-256-gcm:feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308:9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b:d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39:5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f:feedfacedeadbeeffeedfacedeadbeefabaddad2:a44a8266ee1c8eb0c8b5d4cf5ae9f19a
+# local add-ons, primarily streaming ghash tests
+# 128 bytes aad
+aes-128-gcm:00000000000000000000000000000000:000000000000000000000000:::d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad:5fea793a2d6f974d37e68e0cb8ff9492
+# 48 bytes plaintext
+aes-128-gcm:00000000000000000000000000000000:000000000000000000000000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0::9dd0a376b08e40eb00c35f29f9ea61a4
+# 80 bytes plaintext
+aes-128-gcm:00000000000000000000000000000000:000000000000000000000000:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d5270291::98885a3a22bd4742fe7b72172193b163
+# 128 bytes plaintext
+aes-128-gcm:00000000000000000000000000000000:000000000000000000000000:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40::cac45f60e31efd3b5a43b98a22ce1aa1
+# 192 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF
+aes-128-gcm:00000000000000000000000000000000:ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606::566f8ef683078bfdeeffa869d751a017
+# 80 bytes plaintext, submitted by Intel
+aes-128-gcm:843ffcf5d2b72694d19ed01d01249412:dbcca32ebf9b804617c3aa9e:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f:6268c6fa2a80b2d137467f092f657ac04d89be2beaa623d61b5a868c8f03ff95d3dcee23ad2f1ab3a6c80eaf4b140eb05de3457f0fbc111a6b43d0763aa422a3013cf1dc37fe417d1fbfc449b75d4cc5:00000000000000000000000000000000101112131415161718191a1b1c1d1e1f:3b629ccfbc1119b7319e1dce2cd6fd6d
+
+# AES XTS test vectors from IEEE Std 1619-2007
+aes-128-xts:0000000000000000000000000000000000000000000000000000000000000000:00000000000000000000000000000000:0000000000000000000000000000000000000000000000000000000000000000:917cf69ebd68b2ec9b9fe9a3eadda692cd43d2f59598ed858c02c2652fbf922e
+aes-128-xts:1111111111111111111111111111111122222222222222222222222222222222:33333333330000000000000000000000:4444444444444444444444444444444444444444444444444444444444444444:c454185e6a16936e39334038acef838bfb186fff7480adc4289382ecd6d394f0
+aes-128-xts:fffefdfcfbfaf9f8f7f6f5f4f3f2f1f022222222222222222222222222222222:33333333330000000000000000000000:4444444444444444444444444444444444444444444444444444444444444444:af85336b597afc1a900b2eb21ec949d292df4c047e0b21532186a5971a227a89
+aes-128-xts:2718281828459045235360287471352631415926535897932384626433832795:00000000000000000000000000000000:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568
+aes-128-xts:2718281828459045235360287471352631415926535897932384626433832795:01000000000000000000000000000000:27a7479befa1d476489f308cd4cfa6e2a96e4bbe3208ff25287dd3819616e89cc78cf7f5e543445f8333d8fa7f56000005279fa5d8b5e4ad40e736ddb4d35412328063fd2aab53e5ea1e0a9f332500a5df9487d07a5c92cc512c8866c7e860ce93fdf166a24912b422976146ae20ce846bb7dc9ba94a767aaef20c0d61ad02655ea92dc4c4e41a8952c651d33174be51a10c421110e6d81588ede82103a252d8a750e8768defffed9122810aaeb99f9172af82b604dc4b8e51bcb08235a6f4341332e4ca60482a4ba1a03b3e65008fc5da76b70bf1690db4eae29c5f1badd03c5ccf2a55d705ddcd86d449511ceb7ec30bf12b1fa35b913f9f747a8afd1b130e94bff94effd01a91735ca1726acd0b197c4e5b03393697e126826fb6bbde8ecc1e08298516e2c9ed03ff3c1b7860f6de76d4cecd94c8119855ef5297ca67e9f3e7ff72b1e99785ca0a7e7720c5b36dc6d72cac9574c8cbbc2f801e23e56fd344b07f22154beba0f08ce8891e643ed995c94d9a69c9f1b5f499027a78572aeebd74d20cc39881c213ee770b1010e4bea718846977ae119f7a023ab58cca0ad752afe656bb3c17256a9f6e9bf19fdd5a38fc82bbe872c5539edb609ef4f79c203ebb140f2e583cb2ad15b4aa5b655016a8449277dbd477ef2c8d6c017db738b18deb4a427d1923ce3ff262735779a418f20a282df920147beabe421ee5319d0568:264d3ca8512194fec312c8c9891f279fefdd608d0c027b60483a3fa811d65ee59d52d9e40ec5672d81532b38b6b089ce951f0f9c35590b8b978d175213f329bb1c2fd30f2f7f30492a61a532a79f51d36f5e31a7c9a12c286082ff7d2394d18f783e1a8e72c722caaaa52d8f065657d2631fd25bfd8e5baad6e527d763517501c68c5edc3cdd55435c532d7125c8614deed9adaa3acade5888b87bef641c4c994c8091b5bcd387f3963fb5bc37aa922fbfe3df4e5b915e6eb514717bdd2a74079a5073f5c4bfd46adf7d282e7a393a52579d11a028da4d9cd9c77124f9648ee383b1ac763930e7162a8d37f350b2f74b8472cf09902063c6b32e8c2d9290cefbd7346d1c779a0df50edcde4531da07b099c638e83a755944df2aef1aa31752fd323dcb710fb4bfbb9d22b925bc3577e1b8949e729a90bbafeacf7f7879e7b1147e28ba0bae940db795a61b15ecf4df8db07b824bb062802cc98a9545bb2aaeed77cb3fc6db15dcd7d80d7d5bc406c4970a3478ada8899b329198eb61c193fb6275aa8ca340344a75a862aebe92eee1ce032fd950b47d7704a3876923b4ad62844bf4a09c4dbe8b4397184b7471360c9564880aedddb9baa4af2e75394b08cd32ff479c57a07d3eab5d54de5f9738b8d27f27a9f0ab11799d7b7ffefb2704c95c6ad12c39f1e867a4b7b1d7818a4b753dfd2a89ccb45e001a03a867b187f225dd
+aes-128-xts:2718281828459045235360287471352631415926535897932384626433832795:02000000000000000000000000000000:264d3ca8512194fec312c8c9891f279fefdd608d0c027b60483a3fa811d65ee59d52d9e40ec5672d81532b38b6b089ce951f0f9c35590b8b978d175213f329bb1c2fd30f2f7f30492a61a532a79f51d36f5e31a7c9a12c286082ff7d2394d18f783e1a8e72c722caaaa52d8f065657d2631fd25bfd8e5baad6e527d763517501c68c5edc3cdd55435c532d7125c8614deed9adaa3acade5888b87bef641c4c994c8091b5bcd387f3963fb5bc37aa922fbfe3df4e5b915e6eb514717bdd2a74079a5073f5c4bfd46adf7d282e7a393a52579d11a028da4d9cd9c77124f9648ee383b1ac763930e7162a8d37f350b2f74b8472cf09902063c6b32e8c2d9290cefbd7346d1c779a0df50edcde4531da07b099c638e83a755944df2aef1aa31752fd323dcb710fb4bfbb9d22b925bc3577e1b8949e729a90bbafeacf7f7879e7b1147e28ba0bae940db795a61b15ecf4df8db07b824bb062802cc98a9545bb2aaeed77cb3fc6db15dcd7d80d7d5bc406c4970a3478ada8899b329198eb61c193fb6275aa8ca340344a75a862aebe92eee1ce032fd950b47d7704a3876923b4ad62844bf4a09c4dbe8b4397184b7471360c9564880aedddb9baa4af2e75394b08cd32ff479c57a07d3eab5d54de5f9738b8d27f27a9f0ab11799d7b7ffefb2704c95c6ad12c39f1e867a4b7b1d7818a4b753dfd2a89ccb45e001a03a867b187f225dd:fa762a3680b76007928ed4a4f49a9456031b704782e65e16cecb54ed7d017b5e18abd67b338e81078f21edb7868d901ebe9c731a7c18b5e6dec1d6a72e078ac9a4262f860beefa14f4e821018272e411a951502b6e79066e84252c3346f3aa62344351a291d4bedc7a07618bdea2af63145cc7a4b8d4070691ae890cd65733e7946e9021a1dffc4c59f159425ee6d50ca9b135fa6162cea18a939838dc000fb386fad086acce5ac07cb2ece7fd580b00cfa5e98589631dc25e8e2a3daf2ffdec26531659912c9d8f7a15e5865ea8fb5816d6207052bd7128cd743c12c8118791a4736811935eb982a532349e31dd401e0b660a568cb1a4711f552f55ded59f1f15bf7196b3ca12a91e488ef59d64f3a02bf45239499ac6176ae321c4a211ec545365971c5d3f4f09d4eb139bfdf2073d33180b21002b65cc9865e76cb24cd92c874c24c18350399a936ab3637079295d76c417776b94efce3a0ef7206b15110519655c956cbd8b2489405ee2b09a6b6eebe0c53790a12a8998378b33a5b71159625f4ba49d2a2fdba59fbf0897bc7aabd8d707dc140a80f0f309f835d3da54ab584e501dfa0ee977fec543f74186a802b9a37adb3e8291eca04d66520d229e60401e7282bef486ae059aa70696e0e305d777140a7a883ecdcb69b9ff938e8a4231864c69ca2c2043bed007ff3e605e014bcf518138dc3a25c5e236171a2d01d6
+aes-128-xts:2718281828459045235360287471352631415926535897932384626433832795:fd000000000000000000000000000000:8e41b78c390b5af9d758bb214a67e9f6bf7727b09ac6124084c37611398fa45daad94868600ed391fb1acd4857a95b466e62ef9f4b377244d1c152e7b30d731aad30c716d214b707aed99eb5b5e580b3e887cf7497465651d4b60e6042051da3693c3b78c14489543be8b6ad0ba629565bba202313ba7b0d0c94a3252b676f46cc02ce0f8a7d34c0ed229129673c1f61aed579d08a9203a25aac3a77e9db60267996db38df637356d9dcd1632e369939f2a29d89345c66e05066f1a3677aef18dea4113faeb629e46721a66d0a7e785d3e29af2594eb67dfa982affe0aac058f6e15864269b135418261fc3afb089472cf68c45dd7f231c6249ba0255e1e033833fc4d00a3fe02132d7bc3873614b8aee34273581ea0325c81f0270affa13641d052d36f0757d484014354d02d6883ca15c24d8c3956b1bd027bcf41f151fd8023c5340e5606f37e90fdb87c86fb4fa634b3718a30bace06a66eaf8f63c4aa3b637826a87fe8cfa44282e92cb1615af3a28e53bc74c7cba1a0977be9065d0c1a5dec6c54ae38d37f37aa35283e048e5530a85c4e7a29d7b92ec0c3169cdf2a805c7604bce60049b9fb7b8eaac10f51ae23794ceba68bb58112e293b9b692ca721b37c662f8574ed4dba6f88e170881c82cddc1034a0ca7e284bf0962b6b26292d836fa9f73c1ac770eef0f2d3a1eaf61d3e03555fd424eedd67e18a18094f888:d55f684f81f4426e9fde92a5ff02df2ac896af63962888a97910c1379e20b0a3b1db613fb7fe2e07004329ea5c22bfd33e3dbe4cf58cc608c2c26c19a2e2fe22f98732c2b5cb844cc6c0702d91e1d50fc4382a7eba5635cd602432a2306ac4ce82f8d70c8d9bc15f918fe71e74c622d5cf71178bf6e0b9cc9f2b41dd8dbe441c41cd0c73a6dc47a348f6702f9d0e9b1b1431e948e299b9ec2272ab2c5f0c7be86affa5dec87a0bee81d3d50007edaa2bcfccb35605155ff36ed8edd4a40dcd4b243acd11b2b987bdbfaf91a7cac27e9c5aea525ee53de7b2d3332c8644402b823e94a7db26276d2d23aa07180f76b4fd29b9c0823099c9d62c519880aee7e9697617c1497d47bf3e571950311421b6b734d38b0db91eb85331b91ea9f61530f54512a5a52a4bad589eb69781d537f23297bb459bdad2948a29e1550bf4787e0be95bb173cf5fab17dab7a13a052a63453d97ccec1a321954886b7a1299faaeecae35c6eaaca753b041b5e5f093bf83397fd21dd6b3012066fcc058cc32c3b09d7562dee29509b5839392c9ff05f51f3166aaac4ac5f238038a3045e6f72e48ef0fe8bc675e82c318a268e43970271bf119b81bf6a982746554f84e72b9f00280a320a08142923c23c883423ff949827f29bbacdc1ccdb04938ce6098c95ba6b32528f4ef78eed778b2e122ddfd1cbdd11d1c0a6783e011fc536d63d053260637
+aes-128-xts:2718281828459045235360287471352631415926535897932384626433832795:fe000000000000000000000000000000:d55f684f81f4426e9fde92a5ff02df2ac896af63962888a97910c1379e20b0a3b1db613fb7fe2e07004329ea5c22bfd33e3dbe4cf58cc608c2c26c19a2e2fe22f98732c2b5cb844cc6c0702d91e1d50fc4382a7eba5635cd602432a2306ac4ce82f8d70c8d9bc15f918fe71e74c622d5cf71178bf6e0b9cc9f2b41dd8dbe441c41cd0c73a6dc47a348f6702f9d0e9b1b1431e948e299b9ec2272ab2c5f0c7be86affa5dec87a0bee81d3d50007edaa2bcfccb35605155ff36ed8edd4a40dcd4b243acd11b2b987bdbfaf91a7cac27e9c5aea525ee53de7b2d3332c8644402b823e94a7db26276d2d23aa07180f76b4fd29b9c0823099c9d62c519880aee7e9697617c1497d47bf3e571950311421b6b734d38b0db91eb85331b91ea9f61530f54512a5a52a4bad589eb69781d537f23297bb459bdad2948a29e1550bf4787e0be95bb173cf5fab17dab7a13a052a63453d97ccec1a321954886b7a1299faaeecae35c6eaaca753b041b5e5f093bf83397fd21dd6b3012066fcc058cc32c3b09d7562dee29509b5839392c9ff05f51f3166aaac4ac5f238038a3045e6f72e48ef0fe8bc675e82c318a268e43970271bf119b81bf6a982746554f84e72b9f00280a320a08142923c23c883423ff949827f29bbacdc1ccdb04938ce6098c95ba6b32528f4ef78eed778b2e122ddfd1cbdd11d1c0a6783e011fc536d63d053260637:72efc1ebfe1ee25975a6eb3aa8589dda2b261f1c85bdab442a9e5b2dd1d7c3957a16fc08e526d4b1223f1b1232a11af274c3d70dac57f83e0983c498f1a6f1aecb021c3e70085a1e527f1ce41ee5911a82020161529cd82773762daf5459de94a0a82adae7e1703c808543c29ed6fb32d9e004327c1355180c995a07741493a09c21ba01a387882da4f62534b87bb15d60d197201c0fd3bf30c1500a3ecfecdd66d8721f90bcc4c17ee925c61b0a03727a9c0d5f5ca462fbfa0af1c2513a9d9d4b5345bd27a5f6e653f751693e6b6a2b8ead57d511e00e58c45b7b8d005af79288f5c7c22fd4f1bf7a898b03a5634c6a1ae3f9fae5de4f296a2896b23e7ed43ed14fa5a2803f4d28f0d3ffcf24757677aebdb47bb388378708948a8d4126ed1839e0da29a537a8c198b3c66ab00712dd261674bf45a73d67f76914f830ca014b65596f27e4cf62de66125a5566df9975155628b400fbfb3a29040ed50faffdbb18aece7c5c44693260aab386c0a37b11b114f1c415aebb653be468179428d43a4d8bc3ec38813eca30a13cf1bb18d524f1992d44d8b1a42ea30b22e6c95b199d8d182f8840b09d059585c31ad691fa0619ff038aca2c39a943421157361717c49d322028a74648113bd8c9d7ec77cf3c89c1ec8718ceff8516d96b34c3c614f10699c9abc4ed0411506223bea16af35c883accdbe1104eef0cfdb54e12fb230a
+aes-128-xts:2718281828459045235360287471352631415926535897932384626433832795:ff000000000000000000000000000000:72efc1ebfe1ee25975a6eb3aa8589dda2b261f1c85bdab442a9e5b2dd1d7c3957a16fc08e526d4b1223f1b1232a11af274c3d70dac57f83e0983c498f1a6f1aecb021c3e70085a1e527f1ce41ee5911a82020161529cd82773762daf5459de94a0a82adae7e1703c808543c29ed6fb32d9e004327c1355180c995a07741493a09c21ba01a387882da4f62534b87bb15d60d197201c0fd3bf30c1500a3ecfecdd66d8721f90bcc4c17ee925c61b0a03727a9c0d5f5ca462fbfa0af1c2513a9d9d4b5345bd27a5f6e653f751693e6b6a2b8ead57d511e00e58c45b7b8d005af79288f5c7c22fd4f1bf7a898b03a5634c6a1ae3f9fae5de4f296a2896b23e7ed43ed14fa5a2803f4d28f0d3ffcf24757677aebdb47bb388378708948a8d4126ed1839e0da29a537a8c198b3c66ab00712dd261674bf45a73d67f76914f830ca014b65596f27e4cf62de66125a5566df9975155628b400fbfb3a29040ed50faffdbb18aece7c5c44693260aab386c0a37b11b114f1c415aebb653be468179428d43a4d8bc3ec38813eca30a13cf1bb18d524f1992d44d8b1a42ea30b22e6c95b199d8d182f8840b09d059585c31ad691fa0619ff038aca2c39a943421157361717c49d322028a74648113bd8c9d7ec77cf3c89c1ec8718ceff8516d96b34c3c614f10699c9abc4ed0411506223bea16af35c883accdbe1104eef0cfdb54e12fb230a:3260ae8dad1f4a32c5cafe3ab0eb95549d461a67ceb9e5aa2d3afb62dece0553193ba50c75be251e08d1d08f1088576c7efdfaaf3f459559571e12511753b07af073f35da06af0ce0bbf6b8f5ccc5cea500ec1b211bd51f63b606bf6528796ca12173ba39b8935ee44ccce646f90a45bf9ccc567f0ace13dc2d53ebeedc81f58b2e41179dddf0d5a5c42f5d8506c1a5d2f8f59f3ea873cbcd0eec19acbf325423bd3dcb8c2b1bf1d1eaed0eba7f0698e4314fbeb2f1566d1b9253008cbccf45a2b0d9c5c9c21474f4076e02be26050b99dee4fd68a4cf890e496e4fcae7b70f94ea5a9062da0daeba1993d2ccd1dd3c244b8428801495a58b216547e7e847c46d1d756377b6242d2e5fb83bf752b54e0df71e889f3a2bb0f4c10805bf3c590376e3c24e22ff57f7fa965577375325cea5d920db94b9c336b455f6e894c01866fe9fbb8c8d3f70a2957285f6dfb5dcd8cbf54782f8fe7766d4723819913ac773421e3a31095866bad22c86a6036b2518b2059b4229d18c8c2ccbdf906c6cc6e82464ee57bddb0bebcb1dc645325bfb3e665ef7251082c88ebb1cf203bd779fdd38675713c8daadd17e1cabee432b09787b6ddf3304e38b731b45df5df51b78fcfb3d32466028d0ba36555e7e11ab0ee0666061d1645d962444bc47a38188930a84b4d561395c73c087021927ca638b7afc8a8679ccb84c26555440ec7f10445cd
+
+aes-256-xts:27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592:ff000000000000000000000000000000:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:1c3b3a102f770386e4836c99e370cf9bea00803f5e482357a4ae12d414a3e63b5d31e276f8fe4a8d66b317f9ac683f44680a86ac35adfc3345befecb4bb188fd5776926c49a3095eb108fd1098baec70aaa66999a72a82f27d848b21d4a741b0c5cd4d5fff9dac89aeba122961d03a757123e9870f8acf1000020887891429ca2a3e7a7d7df7b10355165c8b9a6d0a7de8b062c4500dc4cd120c0f7418dae3d0b5781c34803fa75421c790dfe1de1834f280d7667b327f6c8cd7557e12ac3a0f93ec05c52e0493ef31a12d3d9260f79a289d6a379bc70c50841473d1a8cc81ec583e9645e07b8d9670655ba5bbcfecc6dc3966380ad8fecb17b6ba02469a020a84e18e8f84252070c13e9f1f289be54fbc481457778f616015e1327a02b140f1505eb309326d68378f8374595c849d84f4c333ec4423885143cb47bd71c5edae9be69a2ffeceb1bec9de244fbe15992b11b77c040f12bd8f6a975a44a0f90c29a9abc3d4d893927284c58754cce294529f8614dcd2aba991925fedc4ae74ffac6e333b93eb4aff0479da9a410e4450e0dd7ae4c6e2910900575da401fc07059f645e8b7e9bfdef33943054ff84011493c27b3429eaedb4ed5376441a77ed43851ad77f16f541dfd269d50d6a5f14fb0aab1cbb4c1550be97f7ab4066193c4caa773dad38014bd2092fa755c824bb5e54c4f36ffda9fcea70b9c6e693e148c151
+aes-256-xts:27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592:ffff0000000000000000000000000000:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:77a31251618a15e6b92d1d66dffe7b50b50bad552305ba0217a610688eff7e11e1d0225438e093242d6db274fde801d4cae06f2092c728b2478559df58e837c2469ee4a4fa794e4bbc7f39bc026e3cb72c33b0888f25b4acf56a2a9804f1ce6d3d6e1dc6ca181d4b546179d55544aa7760c40d06741539c7e3cd9d2f6650b2013fd0eeb8c2b8e3d8d240ccae2d4c98320a7442e1c8d75a42d6e6cfa4c2eca1798d158c7aecdf82490f24bb9b38e108bcda12c3faf9a21141c3613b58367f922aaa26cd22f23d708dae699ad7cb40a8ad0b6e2784973dcb605684c08b8d6998c69aac049921871ebb65301a4619ca80ecb485a31d744223ce8ddc2394828d6a80470c092f5ba413c3378fa6054255c6f9df4495862bbb3287681f931b687c888abf844dfc8fc28331e579928cd12bd2390ae123cf03818d14dedde5c0c24c8ab018bfca75ca096f2d531f3d1619e785f1ada437cab92e980558b3dce1474afb75bfedbf8ff54cb2618e0244c9ac0d3c66fb51598cd2db11f9be39791abe447c63094f7c453b7ff87cb5bb36b7c79efb0872d17058b83b15ab0866ad8a58656c5a7e20dbdf308b2461d97c0ec0024a2715055249cf3b478ddd4740de654f75ca686e0d7345c69ed50cdc2a8b332b1f8824108ac937eb050585608ee734097fc09054fbff89eeaeea791f4a7ab1f9868294a4f9e27b42af8100cb9d59cef9645803
+aes-256-xts:27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592:ffffff00000000000000000000000000:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:e387aaa58ba483afa7e8eb469778317ecf4cf573aa9d4eac23f2cdf914e4e200a8b490e42ee646802dc6ee2b471b278195d60918ececb44bf79966f83faba0499298ebc699c0c8634715a320bb4f075d622e74c8c932004f25b41e361025b5a87815391f6108fc4afa6a05d9303c6ba68a128a55705d415985832fdeaae6c8e19110e84d1b1f199a2692119edc96132658f09da7c623efcec712537a3d94c0bf5d7e352ec94ae5797fdb377dc1551150721adf15bd26a8efc2fcaad56881fa9e62462c28f30ae1ceaca93c345cf243b73f542e2074a705bd2643bb9f7cc79bb6e7091ea6e232df0f9ad0d6cf502327876d82207abf2115cdacf6d5a48f6c1879a65b115f0f8b3cb3c59d15dd8c769bc014795a1837f3901b5845eb491adfefe097b1fa30a12fc1f65ba22905031539971a10f2f36c321bb51331cdefb39e3964c7ef079994f5b69b2edd83a71ef549971ee93f44eac3938fcdd61d01fa71799da3a8091c4c48aa9ed263ff0749df95d44fef6a0bb578ec69456aa5408ae32c7af08ad7ba8921287e3bbee31b767be06a0e705c864a769137df28292283ea81a2480241b44d9921cdbec1bc28dc1fda114bd8e5217ac9d8ebafa720e9da4f9ace231cc949e5b96fe76ffc21063fddc83a6b8679c00d35e09576a875305bed5f36ed242c8900dd1fa965bc950dfce09b132263a1eef52dd6888c309f5a7d712826
+aes-256-xts:27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592:ffffffff000000000000000000000000:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:bf53d2dade78e822a4d949a9bc6766b01b06a8ef70d26748c6a7fc36d80ae4c5520f7c4ab0ac8544424fa405162fef5a6b7f229498063618d39f0003cb5fb8d1c86b643497da1ff945c8d3bedeca4f479702a7a735f043ddb1d6aaade3c4a0ac7ca7f3fa5279bef56f82cd7a2f38672e824814e10700300a055e1630b8f1cb0e919f5e942010a416e2bf48cb46993d3cb6a51c19bacf864785a00bc2ecff15d350875b246ed53e68be6f55bd7e05cfc2b2ed6432198a6444b6d8c247fab941f569768b5c429366f1d3f00f0345b96123d56204c01c63b22ce78baf116e525ed90fdea39fa469494d3866c31e05f295ff21fea8d4e6e13d67e47ce722e9698a1c1048d68ebcde76b86fcf976eab8aa9790268b7068e017a8b9b749409514f1053027fd16c3786ea1bac5f15cb79711ee2abe82f5cf8b13ae73030ef5b9e4457e75d1304f988d62dd6fc4b94ed38ba831da4b7634971b6cd8ec325d9c61c00f1df73627ed3745a5e8489f3a95c69639c32cd6e1d537a85f75cc844726e8a72fc0077ad22000f1d5078f6b866318c668f1ad03d5a5fced5219f2eabbd0aa5c0f460d183f04404a0d6f469558e81fab24a167905ab4c7878502ad3e38fdbe62a41556cec37325759533ce8f25f367c87bb5578d667ae93f9e2fd99bcbc5f2fbba88cf6516139420fcff3b7361d86322c4bd84c82f335abb152c4a93411373aaa8220
+aes-256-xts:27182818284590452353602874713526624977572470936999595749669676273141592653589793238462643383279502884197169399375105820974944592:ffffffffff0000000000000000000000:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:64497e5a831e4a932c09be3e5393376daa599548b816031d224bbf50a818ed2350eae7e96087c8a0db51ad290bd00c1ac1620857635bf246c176ab463be30b808da548081ac847b158e1264be25bb0910bbc92647108089415d45fab1b3d2604e8a8eff1ae4020cfa39936b66827b23f371b92200be90251e6d73c5f86de5fd4a950781933d79a28272b782a2ec313efdfcc0628f43d744c2dc2ff3dcb66999b50c7ca895b0c64791eeaa5f29499fb1c026f84ce5b5c72ba1083cddb5ce45434631665c333b60b11593fb253c5179a2c8db813782a004856a1653011e93fb6d876c18366dd8683f53412c0c180f9c848592d593f8609ca736317d356e13e2bff3a9f59cd9aeb19cd482593d8c46128bb32423b37a9adfb482b99453fbe25a41bf6feb4aa0bef5ed24bf73c762978025482c13115e4015aac992e5613a3b5c2f685b84795cb6e9b2656d8c88157e52c42f978d8634c43d06fea928f2822e465aa6576e9bf419384506cc3ce3c54ac1a6f67dc66f3b30191e698380bc999b05abce19dc0c6dcc2dd001ec535ba18deb2df1a101023108318c75dc98611a09dc48a0acdec676fabdf222f07e026f059b672b56e5cbc8e1d21bbd867dd927212054681d70ea737134cdfce93b6f82ae22423274e58a0821cc5502e2d0ab4585e94de6975be5e0b4efce51cd3e70c25a1fbbbd609d273ad5b0d59631c531f6a0a57b9
+
+aes-128-xts:fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0:9a785634120000000000000000000000:000102030405060708090a0b0c0d0e0f10:6c1625db4671522d3d7599601de7ca09ed
+aes-128-xts:fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0:9a785634120000000000000000000000:000102030405060708090a0b0c0d0e0f1011:d069444b7a7e0cab09e24447d24deb1fedbf
+aes-128-xts:fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0:9a785634120000000000000000000000:000102030405060708090a0b0c0d0e0f101112:e5df1351c0544ba1350b3363cd8ef4beedbf9d
+aes-128-xts:fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0:9a785634120000000000000000000000:000102030405060708090a0b0c0d0e0f10111213:9d84c813f719aa2c7be3f66171c7c5c2edbf9dac
+aes-128-xts:e0e1e2e3e4e5e6e7e8e9eaebecedeeefc0c1c2c3c4c5c6c7c8c9cacbcccdcecf:21436587a90000000000000000000000:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff:38b45812ef43a05bd957e545907e223b954ab4aaf088303ad910eadf14b42be68b2461149d8c8ba85f992be970bc621f1b06573f63e867bf5875acafa04e42ccbd7bd3c2a0fb1fff791ec5ec36c66ae4ac1e806d81fbf709dbe29e471fad38549c8e66f5345d7c1eb94f405d1ec785cc6f6a68f6254dd8339f9d84057e01a17741990482999516b5611a38f41bb6478e6f173f320805dd71b1932fc333cb9ee39936beea9ad96fa10fb4112b901734ddad40bc1878995f8e11aee7d141a2f5d48b7a4e1e7f0b2c04830e69a4fd1378411c2f287edf48c6c4e5c247a19680f7fe41cefbd49b582106e3616cbbe4dfb2344b2ae9519391f3e0fb4922254b1d6d2d19c6d4d537b3a26f3bcc51588b32f3eca0829b6a5ac72578fb814fb43cf80d64a233e3f997a3f02683342f2b33d25b492536b93becb2f5e1a8b82f5b883342729e8ae09d16938841a21a97fb543eea3bbff59f13c1a18449e398701c1ad51648346cbc04c27bb2da3b93a1372ccae548fb53bee476f9e9c91773b1bb19828394d55d3e1a20ed69113a860b6829ffa847224604435070221b257e8dff783615d2cae4803a93aa4334ab482a0afac9c0aeda70b45a481df5dec5df8cc0f423c77a5fd46cd312021d4b438862419a791be03bb4d97c0e59578542531ba466a83baf92cefc151b5cc1611a167893819b63fb8a6b18e86de60290fa72b797b0ce59f3
+# AES wrap tests from RFC3394
+id-aes128-wrap:000102030405060708090A0B0C0D0E0F::00112233445566778899AABBCCDDEEFF:1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5
+id-aes192-wrap:000102030405060708090A0B0C0D0E0F1011121314151617::00112233445566778899AABBCCDDEEFF:96778B25AE6CA435F92B5B97C050AED2468AB8A17AD84E5D
+id-aes256-wrap:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F::00112233445566778899AABBCCDDEEFF:64E8C3F9CE0F5BA263E9777905818A2A93C8191E7D6E8AE7
+id-aes192-wrap:000102030405060708090A0B0C0D0E0F1011121314151617::00112233445566778899AABBCCDDEEFF0001020304050607:031D33264E15D33268F24EC260743EDCE1C6C7DDEE725A936BA814915C6762D2
+id-aes256-wrap:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F::00112233445566778899AABBCCDDEEFF0001020304050607:A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB8958CD5D17D6B254DA1
+id-aes256-wrap:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F::00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F:28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7A02DD21
diff --git a/crypto/evp/m_dss.c b/crypto/evp/m_dss.c
index f22ba522c2f2..147844862d17 100644
--- a/crypto/evp/m_dss.c
+++ b/crypto/evp/m_dss.c
@@ -66,7 +66,6 @@
#endif
#ifndef OPENSSL_NO_SHA
-# ifndef OPENSSL_FIPS
static int init(EVP_MD_CTX *ctx)
{
@@ -102,5 +101,4 @@ const EVP_MD *EVP_dss(void)
{
return (&dsa_md);
}
-# endif
#endif
diff --git a/crypto/evp/m_dss1.c b/crypto/evp/m_dss1.c
index 976148e436a0..e36fabff700e 100644
--- a/crypto/evp/m_dss1.c
+++ b/crypto/evp/m_dss1.c
@@ -68,8 +68,6 @@
# include <openssl/dsa.h>
# endif
-# ifndef OPENSSL_FIPS
-
static int init(EVP_MD_CTX *ctx)
{
return SHA1_Init(ctx->md_data);
@@ -104,5 +102,4 @@ const EVP_MD *EVP_dss1(void)
{
return (&dss1_md);
}
-# endif
#endif
diff --git a/crypto/evp/m_ecdsa.c b/crypto/evp/m_ecdsa.c
index d11a13a6d7a7..803d31495577 100644
--- a/crypto/evp/m_ecdsa.c
+++ b/crypto/evp/m_ecdsa.c
@@ -116,7 +116,6 @@
#include <openssl/x509.h>
#ifndef OPENSSL_NO_SHA
-# ifndef OPENSSL_FIPS
static int init(EVP_MD_CTX *ctx)
{
@@ -152,5 +151,4 @@ const EVP_MD *EVP_ecdsa(void)
{
return (&ecdsa_md);
}
-# endif
#endif
diff --git a/crypto/evp/m_sha1.c b/crypto/evp/m_sha1.c
index 0cc63555ad48..a74e6b77948e 100644
--- a/crypto/evp/m_sha1.c
+++ b/crypto/evp/m_sha1.c
@@ -59,16 +59,14 @@
#include <stdio.h>
#include "cryptlib.h"
-#ifndef OPENSSL_FIPS
+#ifndef OPENSSL_NO_SHA
-# ifndef OPENSSL_NO_SHA
-
-# include <openssl/evp.h>
-# include <openssl/objects.h>
-# include <openssl/sha.h>
-# ifndef OPENSSL_NO_RSA
-# include <openssl/rsa.h>
-# endif
+# include <openssl/evp.h>
+# include <openssl/objects.h>
+# include <openssl/sha.h>
+# ifndef OPENSSL_NO_RSA
+# include <openssl/rsa.h>
+# endif
static int init(EVP_MD_CTX *ctx)
{
@@ -104,9 +102,9 @@ const EVP_MD *EVP_sha1(void)
{
return (&sha1_md);
}
-# endif
+#endif
-# ifndef OPENSSL_NO_SHA256
+#ifndef OPENSSL_NO_SHA256
static int init224(EVP_MD_CTX *ctx)
{
return SHA224_Init(ctx->md_data);
@@ -171,9 +169,9 @@ const EVP_MD *EVP_sha256(void)
{
return (&sha256_md);
}
-# endif /* ifndef OPENSSL_NO_SHA256 */
+#endif /* ifndef OPENSSL_NO_SHA256 */
-# ifndef OPENSSL_NO_SHA512
+#ifndef OPENSSL_NO_SHA512
static int init384(EVP_MD_CTX *ctx)
{
return SHA384_Init(ctx->md_data);
@@ -234,6 +232,4 @@ const EVP_MD *EVP_sha512(void)
{
return (&sha512_md);
}
-# endif /* ifndef OPENSSL_NO_SHA512 */
-
-#endif
+#endif /* ifndef OPENSSL_NO_SHA512 */
diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c
index e153a1833e07..4492d207f28e 100644
--- a/crypto/evp/m_sigver.c
+++ b/crypto/evp/m_sigver.c
@@ -73,15 +73,18 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
if (ctx->pctx == NULL)
return 0;
- if (type == NULL) {
- int def_nid;
- if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0)
- type = EVP_get_digestbynid(def_nid);
- }
+ if (!(ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM)) {
- if (type == NULL) {
- EVPerr(EVP_F_DO_SIGVER_INIT, EVP_R_NO_DEFAULT_DIGEST);
- return 0;
+ if (type == NULL) {
+ int def_nid;
+ if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0)
+ type = EVP_get_digestbynid(def_nid);
+ }
+
+ if (type == NULL) {
+ EVPerr(EVP_F_DO_SIGVER_INIT, EVP_R_NO_DEFAULT_DIGEST);
+ return 0;
+ }
}
if (ver) {
@@ -103,6 +106,8 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
return 0;
if (pctx)
*pctx = ctx->pctx;
+ if (ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM)
+ return 1;
if (!EVP_DigestInit_ex(ctx, type, e))
return 0;
return 1;
@@ -124,7 +129,19 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
size_t *siglen)
{
int sctx, r = 0;
- if (ctx->pctx->pmeth->signctx)
+ EVP_PKEY_CTX *pctx = ctx->pctx;
+ if (pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) {
+ EVP_PKEY_CTX *dctx;
+ if (!sigret)
+ return pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
+ dctx = EVP_PKEY_CTX_dup(ctx->pctx);
+ if (!dctx)
+ return 0;
+ r = dctx->pmeth->signctx(dctx, sigret, siglen, ctx);
+ EVP_PKEY_CTX_free(dctx);
+ return r;
+ }
+ if (pctx->pmeth->signctx)
sctx = 1;
else
sctx = 0;
@@ -147,20 +164,19 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
return 0;
} else {
if (sctx) {
- if (ctx->pctx->pmeth->signctx(ctx->pctx, sigret, siglen, ctx) <=
- 0)
+ if (pctx->pmeth->signctx(pctx, sigret, siglen, ctx) <= 0)
return 0;
} else {
int s = EVP_MD_size(ctx->digest);
- if (s < 0
- || EVP_PKEY_sign(ctx->pctx, sigret, siglen, NULL, s) <= 0)
+ if (s < 0 || EVP_PKEY_sign(pctx, sigret, siglen, NULL, s) <= 0)
return 0;
}
}
return 1;
}
-int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, unsigned char *sig, size_t siglen)
+int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
+ size_t siglen)
{
EVP_MD_CTX tmp_ctx;
unsigned char md[EVP_MAX_MD_SIZE];
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index 2b84dc75ec3a..1171d3086d0b 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -337,7 +337,7 @@ int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key)
DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey)
{
- if (pkey->type != EVP_PKEY_DH) {
+ if (pkey->type != EVP_PKEY_DH && pkey->type != EVP_PKEY_DHX) {
EVPerr(EVP_F_EVP_PKEY_GET1_DH, EVP_R_EXPECTING_A_DH_KEY);
return NULL;
}
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index ae8bccb0c6eb..9f81d10021a0 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -75,6 +75,7 @@ STACK_OF(EVP_PKEY_METHOD) *app_pkey_methods = NULL;
extern const EVP_PKEY_METHOD rsa_pkey_meth, dh_pkey_meth, dsa_pkey_meth;
extern const EVP_PKEY_METHOD ec_pkey_meth, hmac_pkey_meth, cmac_pkey_meth;
+extern const EVP_PKEY_METHOD dhx_pkey_meth;
static const EVP_PKEY_METHOD *standard_methods[] = {
#ifndef OPENSSL_NO_RSA
@@ -90,7 +91,10 @@ static const EVP_PKEY_METHOD *standard_methods[] = {
&ec_pkey_meth,
#endif
&hmac_pkey_meth,
- &cmac_pkey_meth
+ &cmac_pkey_meth,
+#ifndef OPENSSL_NO_DH
+ &dhx_pkey_meth
+#endif
};
DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *,