diff options
Diffstat (limited to 'providers/implementations')
76 files changed, 6070 insertions, 1 deletions
diff --git a/providers/implementations/build.info b/providers/implementations/build.info index 86c581d7f7..0fc0822074 100644 --- a/providers/implementations/build.info +++ b/providers/implementations/build.info @@ -1 +1 @@ -SUBDIRS=digests macs kdfs exchange keymgmt signature +SUBDIRS=digests ciphers macs kdfs exchange keymgmt signature diff --git a/providers/implementations/ciphers/build.info b/providers/implementations/ciphers/build.info new file mode 100644 index 0000000000..fb2b53e58a --- /dev/null +++ b/providers/implementations/ciphers/build.info @@ -0,0 +1,102 @@ +# We make separate GOAL variables for each algorithm, to make it easy to +# switch each to the Legacy provider when needed. +# +# $TDES_1_GOAL and $TDES_2_GOAL separate FIPSable and non-FIPSable TDES. +# The latter may become legacy sooner, so it's comfortable to have two +# variables already now, to switch the non-FIPSable TDES to legacy if needed. + +$AES_GOAL=../../libimplementations.a +$TDES_1_GOAL=../../libimplementations.a +$TDES_2_GOAL=../../libimplementations.a +$DES_GOAL=../../libimplementations.a +$ARIA_GOAL=../../libimplementations.a +$CAMELLIA_GOAL=../../libimplementations.a +$BLOWFISH_GOAL=../../libimplementations.a +$IDEA_GOAL=../../libimplementations.a +$CAST5_GOAL=../../libimplementations.a +$SEED_GOAL=../../libimplementations.a +$SM4_GOAL=../../libimplementations.a +$RC4_GOAL=../../libimplementations.a +$RC5_GOAL=../../libimplementations.a +$RC2_GOAL=../../libimplementations.a + +IF[{- !$disabled{des} -}] + SOURCE[$TDES_1_GOAL]=cipher_tdes.c cipher_tdes_hw.c +ENDIF + +SOURCE[$AES_GOAL]=\ + cipher_aes.c cipher_aes_hw.c \ + cipher_aes_xts.c cipher_aes_xts_hw.c \ + cipher_aes_gcm.c cipher_aes_gcm_hw.c \ + cipher_aes_ccm.c cipher_aes_ccm_hw.c \ + cipher_aes_wrp.c +# Extra code to satisfy the FIPS and non-FIPS separation. +# When the AES-xxx-XTS moves to legacy, this can be removed. +SOURCE[../../libfips.a]=cipher_aes_xts_fips.c +SOURCE[../../libnonfips.a]=cipher_aes_xts_fips.c + +IF[{- !$disabled{des} -}] + SOURCE[$TDES_2_GOAL]=\ + cipher_tdes_default.c cipher_tdes_default_hw.c \ + cipher_tdes_wrap.c cipher_tdes_wrap_hw.c + SOURCE[$DES_GOAL]=\ + cipher_desx.c cipher_desx_hw.c \ + cipher_des.c cipher_des_hw.c +ENDIF + +IF[{- !$disabled{aria} -}] + SOURCE[$ARIA_GOAL]=\ + cipher_aria.c cipher_aria_hw.c \ + cipher_aria_gcm.c cipher_aria_gcm_hw.c \ + cipher_aria_ccm.c cipher_aria_ccm_hw.c +ENDIF + +IF[{- !$disabled{camellia} -}] + SOURCE[$CAMELLIA_GOAL]=\ + cipher_camellia.c cipher_camellia_hw.c +ENDIF + +IF[{- !$disabled{bf} -}] + SOURCE[$BLOWFISH_GOAL]=\ + cipher_blowfish.c cipher_blowfish_hw.c +ENDIF + +IF[{- !$disabled{idea} -}] + SOURCE[$IDEA_GOAL]=\ + cipher_idea.c cipher_idea_hw.c +ENDIF + +IF[{- !$disabled{cast} -}] + SOURCE[$CAST5_GOAL]=\ + cipher_cast5.c cipher_cast5_hw.c +ENDIF + +IF[{- !$disabled{seed} -}] + SOURCE[$SEED_GOAL]=\ + cipher_seed.c cipher_seed_hw.c +ENDIF + +IF[{- !$disabled{sm4} -}] + SOURCE[$SM4_GOAL]=\ + cipher_sm4.c cipher_sm4_hw.c +ENDIF + +IF[{- !$disabled{ocb} -}] + SOURCE[$AES_GOAL]=\ + cipher_aes_ocb.c cipher_aes_ocb_hw.c +ENDIF + +IF[{- !$disabled{rc4} -}] + SOURCE[$RC4_GOAL]=\ + cipher_rc4.c cipher_rc4_hw.c +ENDIF + +IF[{- !$disabled{rc5} -}] + SOURCE[$RC5_GOAL]=\ + cipher_rc5.c cipher_rc5_hw.c +ENDIF + +IF[{- !$disabled{rc2} -}] + SOURCE[$RC2_GOAL]=\ + cipher_rc2.c cipher_rc2_hw.c +ENDIF diff --git a/providers/implementations/ciphers/cipher_aes.c b/providers/implementations/ciphers/cipher_aes.c new file mode 100644 index 0000000000..46880e0bf7 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes.c @@ -0,0 +1,80 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for AES cipher modes ecb, cbc, ofb, cfb, ctr */ + +#include "cipher_aes.h" +#include "internal/provider_algs.h" + +static OSSL_OP_cipher_freectx_fn aes_freectx; +static OSSL_OP_cipher_dupctx_fn aes_dupctx; + +static void aes_freectx(void *vctx) +{ + PROV_AES_CTX *ctx = (PROV_AES_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +static void *aes_dupctx(void *ctx) +{ + PROV_AES_CTX *in = (PROV_AES_CTX *)ctx; + PROV_AES_CTX *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + *ret = *in; + + return ret; +} + +/* aes256ecb_functions */ +IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 256, 128, 0, block) +/* aes192ecb_functions */ +IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 192, 128, 0, block) +/* aes128ecb_functions */ +IMPLEMENT_generic_cipher(aes, AES, ecb, ECB, 0, 128, 128, 0, block) +/* aes256cbc_functions */ +IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 256, 128, 128, block) +/* aes192cbc_functions */ +IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 192, 128, 128, block) +/* aes128cbc_functions */ +IMPLEMENT_generic_cipher(aes, AES, cbc, CBC, 0, 128, 128, 128, block) +/* aes256ofb_functions */ +IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 256, 8, 128, stream) +/* aes192ofb_functions */ +IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 192, 8, 128, stream) +/* aes128ofb_functions */ +IMPLEMENT_generic_cipher(aes, AES, ofb, OFB, 0, 128, 8, 128, stream) +/* aes256cfb_functions */ +IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 256, 8, 128, stream) +/* aes192cfb_functions */ +IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 192, 8, 128, stream) +/* aes128cfb_functions */ +IMPLEMENT_generic_cipher(aes, AES, cfb, CFB, 0, 128, 8, 128, stream) +/* aes256cfb1_functions */ +IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 256, 8, 128, stream) +/* aes192cfb1_functions */ +IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 192, 8, 128, stream) +/* aes128cfb1_functions */ +IMPLEMENT_generic_cipher(aes, AES, cfb1, CFB, 0, 128, 8, 128, stream) +/* aes256cfb8_functions */ +IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 256, 8, 128, stream) +/* aes192cfb8_functions */ +IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 192, 8, 128, stream) +/* aes128cfb8_functions */ +IMPLEMENT_generic_cipher(aes, AES, cfb8, CFB, 0, 128, 8, 128, stream) +/* aes256ctr_functions */ +IMPLEMENT_generic_cipher(aes, AES, ctr, CTR, 0, 256, 8, 128, stream) +/* aes192ctr_functions */ +IMPLEMENT_generic_cipher(aes, AES, ctr, CTR, 0, 192, 8, 128, stream) +/* aes128ctr_functions */ +IMPLEMENT_generic_cipher(aes, AES, ctr, CTR, 0, 128, 8, 128, stream) diff --git a/providers/implementations/ciphers/cipher_aes.h b/providers/implementations/ciphers/cipher_aes.h new file mode 100644 index 0000000000..d00fab13ef --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes.h @@ -0,0 +1,62 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/aes.h> +#include "prov/ciphercommon.h" + +typedef struct prov_aes_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + AES_KEY ks; + } ks; + + /* Platform specific data */ + union { + int dummy; +#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) + struct { + union { + OSSL_UNION_ALIGN; + /*- + * KM-AES parameter block - begin + * (see z/Architecture Principles of Operation >= SA22-7832-06) + */ + struct { + unsigned char k[32]; + } km; + /* KM-AES parameter block - end */ + /*- + * KMO-AES/KMF-AES parameter block - begin + * (see z/Architecture Principles of Operation >= SA22-7832-08) + */ + struct { + unsigned char cv[16]; + unsigned char k[32]; + } kmo_kmf; + /* KMO-AES/KMF-AES parameter block - end */ + } param; + unsigned int fc; + int res; + } s390x; +#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */ + } plat; + +} PROV_AES_CTX; + +#define PROV_CIPHER_HW_aes_ofb PROV_CIPHER_HW_aes_ofb128 +#define PROV_CIPHER_HW_aes_cfb PROV_CIPHER_HW_aes_cfb128 +const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_ecb(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_cbc(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_ofb128(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_cfb128(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_cfb1(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_cfb8(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_ctr(size_t keybits); + diff --git a/providers/implementations/ciphers/cipher_aes_ccm.c b/providers/implementations/ciphers/cipher_aes_ccm.c new file mode 100644 index 0000000000..59fc7274c9 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_ccm.c @@ -0,0 +1,38 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for AES CCM mode */ + +#include "prov/ciphercommon.h" +#include "prov/cipher_ccm.h" +#include "internal/provider_algs.h" + +static void *aes_ccm_newctx(void *provctx, size_t keybits) +{ + PROV_AES_CCM_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx != NULL) + ccm_initctx(&ctx->base, keybits, PROV_AES_HW_ccm(keybits)); + return ctx; +} + +static OSSL_OP_cipher_freectx_fn aes_ccm_freectx; +static void aes_ccm_freectx(void *vctx) +{ + PROV_AES_CCM_CTX *ctx = (PROV_AES_CCM_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +/* aes128ccm_functions */ +IMPLEMENT_aead_cipher(aes, ccm, CCM, AEAD_FLAGS, 128, 8, 96); +/* aes192ccm_functions */ +IMPLEMENT_aead_cipher(aes, ccm, CCM, AEAD_FLAGS, 192, 8, 96); +/* aes256ccm_functions */ +IMPLEMENT_aead_cipher(aes, ccm, CCM, AEAD_FLAGS, 256, 8, 96); diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw.c b/providers/implementations/ciphers/cipher_aes_ccm_hw.c new file mode 100644 index 0000000000..ae200ebada --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_ccm_hw.c @@ -0,0 +1,64 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* AES CCM mode */ + +#include "prov/ciphercommon.h" +#include "prov/cipher_ccm.h" + +#define AES_HW_CCM_SET_KEY_FN(fn_set_enc_key, fn_blk, fn_ccm_enc, fn_ccm_dec) \ + fn_set_enc_key(key, keylen * 8, &actx->ccm.ks.ks); \ + CRYPTO_ccm128_init(&ctx->ccm_ctx, ctx->m, ctx->l, &actx->ccm.ks.ks, \ + (block128_f)fn_blk); \ + ctx->str = ctx->enc ? (ccm128_f)fn_ccm_enc : (ccm128_f)fn_ccm_dec; \ + ctx->key_set = 1; + +static int ccm_generic_aes_initkey(PROV_CCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx; + +#ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { + AES_HW_CCM_SET_KEY_FN(HWAES_set_encrypt_key, HWAES_encrypt, NULL, NULL); + } else +#endif /* HWAES_CAPABLE */ + +#ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { + AES_HW_CCM_SET_KEY_FN(vpaes_set_encrypt_key, vpaes_encrypt, NULL, NULL); + } else +#endif + { + AES_HW_CCM_SET_KEY_FN(AES_set_encrypt_key, AES_encrypt, NULL, NULL) + } + return 1; +} + +static const PROV_CCM_HW aes_ccm = { + ccm_generic_aes_initkey, + ccm_generic_setiv, + ccm_generic_setaad, + ccm_generic_auth_encrypt, + ccm_generic_auth_decrypt, + ccm_generic_gettag +}; + +#if defined(S390X_aes_128_CAPABLE) +# include "cipher_aes_ccm_hw_s390x.inc" +#elif defined(AESNI_CAPABLE) +# include "cipher_aes_ccm_hw_aesni.inc" +#elif defined(SPARC_AES_CAPABLE) +# include "cipher_aes_ccm_hw_t4.inc" +#else +const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keybits) +{ + return &aes_ccm; +} +#endif diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc b/providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc new file mode 100644 index 0000000000..3a5e4a740d --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc @@ -0,0 +1,38 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * AES-NI support for AES CCM. + * This file is included by cipher_ccm_hw.c + */ + +static int ccm_aesni_initkey(PROV_CCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx; + + AES_HW_CCM_SET_KEY_FN(aesni_set_encrypt_key, aesni_encrypt, + aesni_ccm64_encrypt_blocks, + aesni_ccm64_decrypt_blocks); + return 1; +} + +static const PROV_CCM_HW aesni_ccm = { + ccm_aesni_initkey, + ccm_generic_setiv, + ccm_generic_setaad, + ccm_generic_auth_encrypt, + ccm_generic_auth_decrypt, + ccm_generic_gettag +}; + +const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keybits) +{ + return AESNI_CAPABLE ? &aesni_ccm : &aes_ccm; +} diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw_s390x.inc b/providers/implementations/ciphers/cipher_aes_ccm_hw_s390x.inc new file mode 100644 index 0000000000..a5025e5960 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_ccm_hw_s390x.inc @@ -0,0 +1,268 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * S390X support for AES CCM. + * This file is included by cipher_ccm_hw.c + */ + +#define S390X_CCM_AAD_FLAG 0x40 + +static int s390x_aes_ccm_initkey(PROV_CCM_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; + + sctx->ccm.s390x.fc = S390X_AES_FC(keylen); + memcpy(&sctx->ccm.s390x.kmac.k, key, keylen); + /* Store encoded m and l. */ + sctx->ccm.s390x.nonce.b[0] = ((ctx->l - 1) & 0x7) + | (((ctx->m - 2) >> 1) & 0x7) << 3; + memset(sctx->ccm.s390x.nonce.b + 1, 0, sizeof(sctx->ccm.s390x.nonce.b)); + sctx->ccm.s390x.blocks = 0; + ctx->key_set = 1; + return 1; +} + +static int s390x_aes_ccm_setiv(PROV_CCM_CTX *ctx, + const unsigned char *nonce, size_t noncelen, + size_t mlen) +{ + PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; + + sctx->ccm.s390x.nonce.b[0] &= ~S390X_CCM_AAD_FLAG; + sctx->ccm.s390x.nonce.g[1] = mlen; + memcpy(sctx->ccm.s390x.nonce.b + 1, nonce, 15 - ctx->l); + return 1; +} + +/*- + * Process additional authenticated data. Code is big-endian. + */ +static int s390x_aes_ccm_setaad(PROV_CCM_CTX *ctx, + const unsigned char *aad, size_t alen) +{ + PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; + unsigned char *ptr; + int i, rem; + + if (!alen) + return 1; + + sctx->ccm.s390x.nonce.b[0] |= S390X_CCM_AAD_FLAG; + + /* Suppress 'type-punned pointer dereference' warning. */ + ptr = sctx->ccm.s390x.buf.b; + + if (alen < ((1 << 16) - (1 << 8))) { + *(uint16_t *)ptr = alen; + i = 2; + } else if (sizeof(alen) == 8 + && alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) { + *(uint16_t *)ptr = 0xffff; + *(uint64_t *)(ptr + 2) = alen; + i = 10; + } else { + *(uint16_t *)ptr = 0xfffe; + *(uint32_t *)(ptr + 2) = alen; + i = 6; + } + + while (i < 16 && alen) { + sctx->ccm.s390x.buf.b[i] = *aad; + ++aad; + --alen; + ++i; + } + while (i < 16) { + sctx->ccm.s390x.buf.b[i] = 0; + ++i; + } + + sctx->ccm.s390x.kmac.icv.g[0] = 0; + sctx->ccm.s390x.kmac.icv.g[1] = 0; + s390x_kmac(sctx->ccm.s390x.nonce.b, 32, sctx->ccm.s390x.fc, + &sctx->ccm.s390x.kmac); + sctx->ccm.s390x.blocks += 2; + + rem = alen & 0xf; + alen &= ~(size_t)0xf; + if (alen) { + s390x_kmac(aad, alen, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac); + sctx->ccm.s390x.blocks += alen >> 4; + aad += alen; + } + if (rem) { + for (i = 0; i < rem; i++) + sctx->ccm.s390x.kmac.icv.b[i] ^= aad[i]; + + s390x_km(sctx->ccm.s390x.kmac.icv.b, 16, + sctx->ccm.s390x.kmac.icv.b, sctx->ccm.s390x.fc, + sctx->ccm.s390x.kmac.k); + sctx->ccm.s390x.blocks++; + } + return 1; +} + +/*- + * En/de-crypt plain/cipher-text. Compute tag from plaintext. Returns 1 for + * success. + */ +static int s390x_aes_ccm_auth_encdec(PROV_CCM_CTX *ctx, + const unsigned char *in, + unsigned char *out, size_t len, int enc) +{ + PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; + size_t n, rem; + unsigned int i, l, num; + unsigned char flags; + + flags = sctx->ccm.s390x.nonce.b[0]; + if (!(flags & S390X_CCM_AAD_FLAG)) { + s390x_km(sctx->ccm.s390x.nonce.b, 16, sctx->ccm.s390x.kmac.icv.b, + sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k); + sctx->ccm.s390x.blocks++; + } + l = flags & 0x7; + sctx->ccm.s390x.nonce.b[0] = l; + + /*- + * Reconstruct length from encoded length field + * and initialize it with counter value. + */ + n = 0; + for (i = 15 - l; i < 15; i++) { + n |= sctx->ccm.s390x.nonce.b[i]; + sctx->ccm.s390x.nonce.b[i] = 0; + n <<= 8; + } + n |= sctx->ccm.s390x.nonce.b[15]; + sctx->ccm.s390x.nonce.b[15] = 1; + + if (n != len) + return 0; /* length mismatch */ + + if (enc) { + /* Two operations per block plus one for tag encryption */ + sctx->ccm.s390x.blocks += (((len + 15) >> 4) << 1) + 1; + if (sctx->ccm.s390x.blocks > (1ULL << 61)) + return 0; /* too much data */ + } + + num = 0; + rem = len & 0xf; + len &= ~(size_t)0xf; + + if (enc) { + /* mac-then-encrypt */ + if (len) + s390x_kmac(in, len, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac); + if (rem) { + for (i = 0; i < rem; i++) + sctx->ccm.s390x.kmac.icv.b[i] ^= in[len + i]; + + s390x_km(sctx->ccm.s390x.kmac.icv.b, 16, + sctx->ccm.s390x.kmac.icv.b, + sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k); + } + + CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &sctx->ccm.ks.ks, + sctx->ccm.s390x.nonce.b, sctx->ccm.s390x.buf.b, + &num, (ctr128_f)AES_ctr32_encrypt); + } else { + /* decrypt-then-mac */ + CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &sctx->ccm.ks.ks, + sctx->ccm.s390x.nonce.b, sctx->ccm.s390x.buf.b, + &num, (ctr128_f)AES_ctr32_encrypt); + + if (len) + s390x_kmac(out, len, sctx->ccm.s390x.fc, &sctx->ccm.s390x.kmac); + if (rem) { + for (i = 0; i < rem; i++) + sctx->ccm.s390x.kmac.icv.b[i] ^= out[len + i]; + + s390x_km(sctx->ccm.s390x.kmac.icv.b, 16, + sctx->ccm.s390x.kmac.icv.b, + sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k); + } + } + /* encrypt tag */ + for (i = 15 - l; i < 16; i++) + sctx->ccm.s390x.nonce.b[i] = 0; + + s390x_km(sctx->ccm.s390x.nonce.b, 16, sctx->ccm.s390x.buf.b, + sctx->ccm.s390x.fc, sctx->ccm.s390x.kmac.k); + sctx->ccm.s390x.kmac.icv.g[0] ^= sctx->ccm.s390x.buf.g[0]; + sctx->ccm.s390x.kmac.icv.g[1] ^= sctx->ccm.s390x.buf.g[1]; + + sctx->ccm.s390x.nonce.b[0] = flags; /* restore flags field */ + return 1; +} + + +static int s390x_aes_ccm_gettag(PROV_CCM_CTX *ctx, + unsigned char *tag, size_t tlen) +{ + PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; + + if (tlen > ctx->m) + return 0; + memcpy(tag, sctx->ccm.s390x.kmac.icv.b, tlen); + return 1; +} + +static int s390x_aes_ccm_auth_encrypt(PROV_CCM_CTX *ctx, + const unsigned char *in, + unsigned char *out, size_t len, + unsigned char *tag, size_t taglen) +{ + int rv; + + rv = s390x_aes_ccm_auth_encdec(ctx, in, out, len, 1); + if (rv && tag != NULL) + rv = s390x_aes_ccm_gettag(ctx, tag, taglen); + return rv; +} + +static int s390x_aes_ccm_auth_decrypt(PROV_CCM_CTX *ctx, + const unsigned char *in, + unsigned char *out, size_t len, + unsigned char *expected_tag, + size_t taglen) +{ + int rv = 0; + PROV_AES_CCM_CTX *sctx = (PROV_AES_CCM_CTX *)ctx; + + rv = s390x_aes_ccm_auth_encdec(ctx, in, out, len, 0); + if (rv) { + if (CRYPTO_memcmp(sctx->ccm.s390x.kmac.icv.b, expected_tag, ctx->m) != 0) + rv = 0; + } + if (rv == 0) + OPENSSL_cleanse(out, len); + return rv; +} + +static const PROV_CCM_HW s390x_aes_ccm = { + s390x_aes_ccm_initkey, + s390x_aes_ccm_setiv, + s390x_aes_ccm_setaad, + s390x_aes_ccm_auth_encrypt, + s390x_aes_ccm_auth_decrypt, + s390x_aes_ccm_gettag +}; + +const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keybits) +{ + if ((keybits == 128 && S390X_aes_128_ccm_CAPABLE) + || (keybits == 192 && S390X_aes_192_ccm_CAPABLE) + || (keybits == 256 && S390X_aes_256_ccm_CAPABLE)) + return &s390x_aes_ccm; + return &aes_ccm; +} diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw_t4.inc b/providers/implementations/ciphers/cipher_aes_ccm_hw_t4.inc new file mode 100644 index 0000000000..21bf6861e0 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_ccm_hw_t4.inc @@ -0,0 +1,36 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * Fujitsu SPARC64 X support for AES CCM. + * This file is included by cipher_ccm_hw.c + */ + +static int ccm_t4_aes_initkey(PROV_CCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_AES_CCM_CTX *actx = (PROV_AES_CCM_CTX *)ctx; + + AES_HW_CCM_SET_KEY_FN(aes_t4_set_encrypt_key, aes_t4_encrypt, NULL, NULL); + return 1; +} + +static const PROV_CCM_HW t4_aes_ccm = { + ccm_t4_aes_initkey, + ccm_generic_setiv, + ccm_generic_setaad, + ccm_generic_auth_encrypt, + ccm_generic_auth_decrypt, + ccm_generic_gettag +}; + +const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keybits) +{ + return SPARC_AES_CAPABLE ? &t4_aes_ccm : &aes_ccm; +} diff --git a/providers/implementations/ciphers/cipher_aes_gcm.c b/providers/implementations/ciphers/cipher_aes_gcm.c new file mode 100644 index 0000000000..1df1c1dba9 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_gcm.c @@ -0,0 +1,38 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for AES GCM mode */ + +#include "prov/ciphercommon.h" +#include "prov/cipher_gcm.h" +#include "internal/provider_algs.h" + +static void *aes_gcm_newctx(void *provctx, size_t keybits) +{ + PROV_AES_GCM_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx != NULL) + gcm_initctx(provctx, &ctx->base, keybits, PROV_AES_HW_gcm(keybits), 8); + return ctx; +} + +static OSSL_OP_cipher_freectx_fn aes_gcm_freectx; +static void aes_gcm_freectx(void *vctx) +{ + PROV_AES_GCM_CTX *ctx = (PROV_AES_GCM_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +/* aes128gcm_functions */ +IMPLEMENT_aead_cipher(aes, gcm, GCM, AEAD_FLAGS, 128, 8, 96); +/* aes192gcm_functions */ +IMPLEMENT_aead_cipher(aes, gcm, GCM, AEAD_FLAGS, 192, 8, 96); +/* aes256gcm_functions */ +IMPLEMENT_aead_cipher(aes, gcm, GCM, AEAD_FLAGS, 256, 8, 96); diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw.c b/providers/implementations/ciphers/cipher_aes_gcm_hw.c new file mode 100644 index 0000000000..f5dc0c4eed --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw.c @@ -0,0 +1,78 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for AES GCM mode */ + +#include "prov/ciphercommon.h" +#include "prov/cipher_gcm.h" + +static int generic_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + AES_KEY *ks = &actx->ks.ks; + +# ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { +# ifdef HWAES_ctr32_encrypt_blocks + GCM_HW_SET_KEY_CTR_FN(ks, HWAES_set_encrypt_key, HWAES_encrypt, + HWAES_ctr32_encrypt_blocks); +# else + GCM_HW_SET_KEY_CTR_FN(ks, HWAES_set_encrypt_key, HWAES_encrypt, NULL); +# endif /* HWAES_ctr32_encrypt_blocks */ + } else +# endif /* HWAES_CAPABLE */ + +# ifdef BSAES_CAPABLE + if (BSAES_CAPABLE) { + GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt, + bsaes_ctr32_encrypt_blocks); + } else +# endif /* BSAES_CAPABLE */ + +# ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { + GCM_HW_SET_KEY_CTR_FN(ks, vpaes_set_encrypt_key, vpaes_encrypt, NULL); + } else +# endif /* VPAES_CAPABLE */ + + { +# ifdef AES_CTR_ASM + GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt, + AES_ctr32_encrypt); +# else + GCM_HW_SET_KEY_CTR_FN(ks, AES_set_encrypt_key, AES_encrypt, NULL); +# endif /* AES_CTR_ASM */ + } + ctx->key_set = 1; + return 1; +} + +static const PROV_GCM_HW aes_gcm = { + generic_aes_gcm_initkey, + gcm_setiv, + gcm_aad_update, + gcm_cipher_update, + gcm_cipher_final, + gcm_one_shot +}; + +#if defined(S390X_aes_128_CAPABLE) +# include "cipher_aes_gcm_hw_s390x.inc" +#elif defined(AESNI_CAPABLE) +# include "cipher_aes_gcm_hw_aesni.inc" +#elif defined(SPARC_AES_CAPABLE) +# include "cipher_aes_gcm_hw_t4.inc" +#else +const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits) +{ + return &aes_gcm; +} +#endif + diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc new file mode 100644 index 0000000000..eb2a3f343a --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc @@ -0,0 +1,38 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * AES-NI support for AES GCM. + * This file is included by cipher_gcm_hw.c + */ + +static int aesni_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + AES_KEY *ks = &actx->ks.ks; + GCM_HW_SET_KEY_CTR_FN(ks, aesni_set_encrypt_key, aesni_encrypt, + aesni_ctr32_encrypt_blocks); + return 1; +} + +static const PROV_GCM_HW aesni_gcm = { + aesni_gcm_initkey, + gcm_setiv, + gcm_aad_update, + gcm_cipher_update, + gcm_cipher_final, + gcm_one_shot +}; + +const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits) +{ + return AESNI_CAPABLE ? &aesni_gcm : &aes_gcm; +} + diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_s390x.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_s390x.inc new file mode 100644 index 0000000000..44c3bf332d --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_s390x.inc @@ -0,0 +1,300 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * IBM S390X support for AES GCM. + * This file is included by cipher_gcm_hw.c + */ + +/* iv + padding length for iv lengths != 12 */ +#define S390X_gcm_ivpadlen(i) ((((i) + 15) >> 4 << 4) + 16) + +static int s390x_aes_gcm_initkey(PROV_GCM_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + + ctx->key_set = 1; + memcpy(&actx->plat.s390x.param.kma.k, key, keylen); + actx->plat.s390x.fc = S390X_AES_FC(keylen); + if (!ctx->enc) + actx->plat.s390x.fc |= S390X_DECRYPT; + return 1; +} + +static int s390x_aes_gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, + size_t ivlen) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma; + + kma->t.g[0] = 0; + kma->t.g[1] = 0; + kma->tpcl = 0; + kma->taadl = 0; + actx->plat.s390x.mreslen = 0; + actx->plat.s390x.areslen = 0; + actx->plat.s390x.kreslen = 0; + + if (ivlen == GCM_IV_DEFAULT_SIZE) { + memcpy(&kma->j0, iv, ivlen); + kma->j0.w[3] = 1; + kma->cv.w = 1; + } else { + unsigned long long ivbits = ivlen << 3; + size_t len = S390X_gcm_ivpadlen(ivlen); + unsigned char iv_zero_pad[S390X_gcm_ivpadlen(GCM_IV_MAX_SIZE)]; + /* + * The IV length needs to be zero padded to be a multiple of 16 bytes + * followed by 8 bytes of zeros and 8 bytes for the IV length. + * The GHASH of this value can then be calculated. + */ + memcpy(iv_zero_pad, iv, ivlen); + memset(iv_zero_pad + ivlen, 0, len - ivlen); + memcpy(iv_zero_pad + len - sizeof(ivbits), &ivbits, sizeof(ivbits)); + /* + * Calculate the ghash of the iv - the result is stored into the tag + * param. + */ + s390x_kma(iv_zero_pad, len, NULL, 0, NULL, actx->plat.s390x.fc, kma); + actx->plat.s390x.fc |= S390X_KMA_HS; /* The hash subkey is set */ + + /* Copy the 128 bit GHASH result into J0 and clear the tag */ + kma->j0.g[0] = kma->t.g[0]; + kma->j0.g[1] = kma->t.g[1]; + kma->t.g[0] = 0; + kma->t.g[1] = 0; + /* Set the 32 bit counter */ + kma->cv.w = kma->j0.w[3]; + } + return 1; +} + +static int s390x_aes_gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma; + unsigned char out[AES_BLOCK_SIZE]; + int rc; + + kma->taadl <<= 3; + kma->tpcl <<= 3; + s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen, + actx->plat.s390x.mres, actx->plat.s390x.mreslen, out, + actx->plat.s390x.fc | S390X_KMA_LAAD | S390X_KMA_LPC, kma); + + /* gctx->mres already returned to the caller */ + OPENSSL_cleanse(out, actx->plat.s390x.mreslen); + + if (ctx->enc) { + ctx->taglen = GCM_TAG_MAX_SIZE; + memcpy(tag, kma->t.b, ctx->taglen); + rc = 1; + } else { + rc = (CRYPTO_memcmp(tag, kma->t.b, ctx->taglen) == 0); + } + return rc; +} + +static int s390x_aes_gcm_one_shot(PROV_GCM_CTX *ctx, + unsigned char *aad, size_t aad_len, + const unsigned char *in, size_t in_len, + unsigned char *out, + unsigned char *tag, size_t taglen) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma; + int rc; + + kma->taadl = aad_len << 3; + kma->tpcl = in_len << 3; + s390x_kma(aad, aad_len, in, in_len, out, + actx->plat.s390x.fc | S390X_KMA_LAAD | S390X_KMA_LPC, kma); + + if (ctx->enc) { + memcpy(tag, kma->t.b, taglen); + rc = 1; + } else { + rc = (CRYPTO_memcmp(tag, kma->t.b, taglen) == 0); + } + return rc; +} + +/* + * Process additional authenticated data. Returns 1 on success. Code is + * big-endian. + */ +static int s390x_aes_gcm_aad_update(PROV_GCM_CTX *ctx, + const unsigned char *aad, size_t len) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma; + unsigned long long alen; + int n, rem; + + /* If already processed pt/ct then error */ + if (kma->tpcl != 0) + return 0; + + /* update the total aad length */ + alen = kma->taadl + len; + if (alen > (U64(1) << 61) || (sizeof(len) == 8 && alen < len)) + return 0; + kma->taadl = alen; + + /* check if there is any existing aad data from a previous add */ + n = actx->plat.s390x.areslen; + if (n) { + /* add additional data to a buffer until it has 16 bytes */ + while (n && len) { + actx->plat.s390x.ares[n] = *aad; + ++aad; + --len; + n = (n + 1) & 0xf; + } + /* ctx->ares contains a complete block if offset has wrapped around */ + if (!n) { + s390x_kma(actx->plat.s390x.ares, 16, NULL, 0, NULL, + actx->plat.s390x.fc, kma); + actx->plat.s390x.fc |= S390X_KMA_HS; + } + actx->plat.s390x.areslen = n; + } + + /* If there are leftover bytes (< 128 bits) save them for next time */ + rem = len & 0xf; + /* Add any remaining 16 byte blocks (128 bit each) */ + len &= ~(size_t)0xf; + if (len) { + s390x_kma(aad, len, NULL, 0, NULL, actx->plat.s390x.fc, kma); + actx->plat.s390x.fc |= S390X_KMA_HS; + aad += len; + } + + if (rem) { + actx->plat.s390x.areslen = rem; + + do { + --rem; + actx->plat.s390x.ares[rem] = aad[rem]; + } while (rem); + } + return 1; +} + +/*- + * En/de-crypt plain/cipher-text and authenticate ciphertext. Returns 1 for + * success. Code is big-endian. + */ +static int s390x_aes_gcm_cipher_update(PROV_GCM_CTX *ctx, + const unsigned char *in, size_t len, + unsigned char *out) +{ + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + S390X_KMA_PARAMS *kma = &actx->plat.s390x.param.kma; + const unsigned char *inptr; + unsigned long long mlen; + union { + unsigned int w[4]; + unsigned char b[16]; + } buf; + size_t inlen; + int n, rem, i; + + mlen = kma->tpcl + len; + if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len)) + return 0; + kma->tpcl = mlen; + + n = actx->plat.s390x.mreslen; + if (n) { + inptr = in; + inlen = len; + while (n && inlen) { + actx->plat.s390x.mres[n] = *inptr; + n = (n + 1) & 0xf; + ++inptr; + --inlen; + } + /* ctx->mres contains a complete block if offset has wrapped around */ + if (!n) { + s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen, + actx->plat.s390x.mres, 16, buf.b, + actx->plat.s390x.fc | S390X_KMA_LAAD, kma); + actx->plat.s390x.fc |= S390X_KMA_HS; + actx->plat.s390x.areslen = 0; + + /* previous call already encrypted/decrypted its remainder, + * see comment below */ + n = actx->plat.s390x.mreslen; + while (n) { + *out = buf.b[n]; + n = (n + 1) & 0xf; + ++out; + ++in; + --len; + } + actx->plat.s390x.mreslen = 0; + } + } + + rem = len & 0xf; + + len &= ~(size_t)0xf; + if (len) { + s390x_kma(actx->plat.s390x.ares, actx->plat.s390x.areslen, in, len, out, + actx->plat.s390x.fc | S390X_KMA_LAAD, kma); + in += len; + out += len; + actx->plat.s390x.fc |= S390X_KMA_HS; + actx->plat.s390x.areslen = 0; + } + + /*- + * If there is a remainder, it has to be saved such that it can be + * processed by kma later. However, we also have to do the for-now + * unauthenticated encryption/decryption part here and now... + */ + if (rem) { + if (!actx->plat.s390x.mreslen) { + buf.w[0] = kma->j0.w[0]; + buf.w[1] = kma->j0.w[1]; + buf.w[2] = kma->j0.w[2]; + buf.w[3] = kma->cv.w + 1; + s390x_km(buf.b, 16, actx->plat.s390x.kres, + actx->plat.s390x.fc & 0x1f, &kma->k); + } + + n = actx->plat.s390x.mreslen; + for (i = 0; i < rem; i++) { + actx->plat.s390x.mres[n + i] = in[i]; + out[i] = in[i] ^ actx->plat.s390x.kres[n + i]; + } + actx->plat.s390x.mreslen += rem; + } + return 1; +} + +static const PROV_GCM_HW s390x_aes_gcm = { + s390x_aes_gcm_initkey, + s390x_aes_gcm_setiv, + s390x_aes_gcm_aad_update, + s390x_aes_gcm_cipher_update, + s390x_aes_gcm_cipher_final, + s390x_aes_gcm_one_shot +}; + +const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits) +{ + if ((keybits == 128 && S390X_aes_128_gcm_CAPABLE) + || (keybits == 192 && S390X_aes_192_gcm_CAPABLE) + || (keybits == 256 && S390X_aes_256_gcm_CAPABLE)) + return &s390x_aes_gcm; + return &aes_gcm; +} diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_t4.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_t4.inc new file mode 100644 index 0000000000..19e9ccb760 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_t4.inc @@ -0,0 +1,52 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * Fujitsu SPARC64 X support for AES GCM. + * This file is included by cipher_gcm_hw.c + */ + +static int t4_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + ctr128_f ctr; + PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; + AES_KEY *ks = &actx->ks.ks; + + + switch (keylen) { + case 16: + ctr = (ctr128_f)aes128_t4_ctr32_encrypt; + break; + case 24: + ctr = (ctr128_f)aes192_t4_ctr32_encrypt; + break; + case 32: + ctr = (ctr128_f)aes256_t4_ctr32_encrypt; + break; + default: + return 0; + } + + GCM_HW_SET_KEY_CTR_FN(ks, aes_t4_set_encrypt_key, aes_t4_encrypt, ctr); + return 1; +} + +static const PROV_GCM_HW t4_aes_gcm = { + t4_aes_gcm_initkey, + gcm_setiv, + gcm_aad_update, + gcm_cipher_update, + gcm_cipher_final, + gcm_one_shot +}; +const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits) +{ + return SPARC_AES_CAPABLE ? &t4_aes_gcm : &aes_gcm; +} diff --git a/providers/implementations/ciphers/cipher_aes_hw.c b/providers/implementations/ciphers/cipher_aes_hw.c new file mode 100644 index 0000000000..e9b6388300 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_hw.c @@ -0,0 +1,139 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_aes.h" +#include "internal/providercommonerr.h" + +static int cipher_hw_aes_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + int ret; + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + AES_KEY *ks = &adat->ks.ks; + + dat->ks = ks; + + if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE) + && !dat->enc) { +#ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { + ret = HWAES_set_decrypt_key(key, keylen * 8, ks); + dat->block = (block128_f)HWAES_decrypt; + dat->stream.cbc = NULL; +# ifdef HWAES_cbc_encrypt + if (dat->mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt; +# endif + } else +#endif +#ifdef BSAES_CAPABLE + if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CBC_MODE) { + ret = AES_set_decrypt_key(key, keylen * 8, ks); + dat->block = (block128_f)AES_decrypt; + dat->stream.cbc = (cbc128_f)bsaes_cbc_encrypt; + } else +#endif +#ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { + ret = vpaes_set_decrypt_key(key, keylen * 8, ks); + dat->block = (block128_f)vpaes_decrypt; + dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE) + ?(cbc128_f)vpaes_cbc_encrypt : NULL; + } else +#endif + { + ret = AES_set_decrypt_key(key, keylen * 8, ks); + dat->block = (block128_f)AES_decrypt; + dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE) + ? (cbc128_f)AES_cbc_encrypt : NULL; + } + } else +#ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { + ret = HWAES_set_encrypt_key(key, keylen * 8, ks); + dat->block = (block128_f)HWAES_encrypt; + dat->stream.cbc = NULL; +# ifdef HWAES_cbc_encrypt + if (dat->mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt; + else +# endif +# ifdef HWAES_ctr32_encrypt_blocks + if (dat->mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks; + else +# endif + (void)0; /* terminate potentially open 'else' */ + } else +#endif +#ifdef BSAES_CAPABLE + if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CTR_MODE) { + ret = AES_set_encrypt_key(key, keylen * 8, ks); + dat->block = (block128_f)AES_encrypt; + dat->stream.ctr = (ctr128_f)bsaes_ctr32_encrypt_blocks; + } else +#endif +#ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { + ret = vpaes_set_encrypt_key(key, keylen * 8, ks); + dat->block = (block128_f)vpaes_encrypt; + dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE) + ? (cbc128_f)vpaes_cbc_encrypt : NULL; + } else +#endif + { + ret = AES_set_encrypt_key(key, keylen * 8, ks); + dat->block = (block128_f)AES_encrypt; + dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE) + ? (cbc128_f)AES_cbc_encrypt : NULL; +#ifdef AES_CTR_ASM + if (dat->mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f)AES_ctr32_encrypt; +#endif + } + + if (ret < 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_AES_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +#define PROV_CIPHER_HW_aes_mode(mode) \ +static const PROV_CIPHER_HW aes_##mode = { \ + cipher_hw_aes_initkey, \ + cipher_hw_generic_##mode \ +}; \ +PROV_CIPHER_HW_declare(mode) \ +const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_##mode(size_t keybits) \ +{ \ + PROV_CIPHER_HW_select(mode) \ + return &aes_##mode; \ +} + +#if defined(AESNI_CAPABLE) +# include "cipher_aes_hw_aesni.inc" +#elif defined(SPARC_AES_CAPABLE) +# include "cipher_aes_hw_t4.inc" +#elif defined(S390X_aes_128_CAPABLE) +# include "cipher_aes_hw_s390x.inc" +#else +/* The generic case */ +# define PROV_CIPHER_HW_declare(mode) +# define PROV_CIPHER_HW_select(mode) +#endif + +PROV_CIPHER_HW_aes_mode(cbc) +PROV_CIPHER_HW_aes_mode(ecb) +PROV_CIPHER_HW_aes_mode(ofb128) +PROV_CIPHER_HW_aes_mode(cfb128) +PROV_CIPHER_HW_aes_mode(cfb1) +PROV_CIPHER_HW_aes_mode(cfb8) +PROV_CIPHER_HW_aes_mode(ctr) diff --git a/providers/implementations/ciphers/cipher_aes_hw_aesni.inc b/providers/implementations/ciphers/cipher_aes_hw_aesni.inc new file mode 100644 index 0000000000..6070939dee --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_hw_aesni.inc @@ -0,0 +1,83 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * AES-NI support for AES modes ecb, cbc, ofb, cfb, ctr. + * This file is included by cipher_aes_hw.c + */ + +#define cipher_hw_aesni_ofb128 cipher_hw_generic_ofb128 +#define cipher_hw_aesni_cfb128 cipher_hw_generic_cfb128 +#define cipher_hw_aesni_cfb8 cipher_hw_generic_cfb8 +#define cipher_hw_aesni_cfb1 cipher_hw_generic_cfb1 +#define cipher_hw_aesni_ctr cipher_hw_generic_ctr + +static int cipher_hw_aesni_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + int ret; + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + AES_KEY *ks = &adat->ks.ks; + + dat->ks = ks; + + if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE) + && !dat->enc) { + ret = aesni_set_decrypt_key(key, keylen * 8, ks); + dat->block = (block128_f) aesni_decrypt; + dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) aesni_cbc_encrypt : NULL; + } else { + ret = aesni_set_encrypt_key(key, keylen * 8, ks); + dat->block = (block128_f) aesni_encrypt; + if (dat->mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt; + else if (dat->mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f) aesni_ctr32_encrypt_blocks; + else + dat->stream.cbc = NULL; + } + + if (ret < 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_AES_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +static int cipher_hw_aesni_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + const AES_KEY *ks = ctx->ks; + + aesni_cbc_encrypt(in, out, len, ks, ctx->iv, ctx->enc); + + return 1; +} + +static int cipher_hw_aesni_ecb(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + if (len < ctx->blocksize) + return 1; + + aesni_ecb_encrypt(in, out, len, ctx->ks, ctx->enc); + + return 1; +} + +#define PROV_CIPHER_HW_declare(mode) \ +static const PROV_CIPHER_HW aesni_##mode = { \ + cipher_hw_aesni_initkey, \ + cipher_hw_aesni_##mode \ +}; +#define PROV_CIPHER_HW_select(mode) \ +if (AESNI_CAPABLE) \ + return &aesni_##mode; diff --git a/providers/implementations/ciphers/cipher_aes_hw_s390x.inc b/providers/implementations/ciphers/cipher_aes_hw_s390x.inc new file mode 100644 index 0000000000..805fa91e5f --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_hw_s390x.inc @@ -0,0 +1,203 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * IBM S390X support for AES modes ecb, cbc, ofb, cfb, ctr. + * This file is included by cipher_aes_hw.c + */ + +#include "s390x_arch.h" + +#define s390x_aes_cbc_initkey cipher_hw_aes_initkey +#define s390x_aes_cfb1_initkey cipher_hw_aes_initkey +#define s390x_aes_ctr_initkey cipher_hw_aes_initkey +#define s390x_aes_cbc_cipher_hw cipher_hw_generic_cbc +#define s390x_aes_cfb1_cipher_hw cipher_hw_generic_cfb1 +#define s390x_aes_ctr_cipher_hw cipher_hw_generic_ctr + +#define S390X_aes_128_ofb128_CAPABLE S390X_aes_128_ofb_CAPABLE +#define S390X_aes_192_ofb128_CAPABLE S390X_aes_192_ofb_CAPABLE +#define S390X_aes_256_ofb128_CAPABLE S390X_aes_256_ofb_CAPABLE +#define S390X_aes_128_cfb128_CAPABLE S390X_aes_128_cfb_CAPABLE +#define S390X_aes_192_cfb128_CAPABLE S390X_aes_192_cfb_CAPABLE +#define S390X_aes_256_cfb128_CAPABLE S390X_aes_256_cfb_CAPABLE + +static int s390x_aes_ecb_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + + adat->plat.s390x.fc = S390X_AES_FC(keylen); + if (!dat->enc) + adat->plat.s390x.fc |= S390X_DECRYPT; + + memcpy(adat->plat.s390x.param.km.k, key, keylen); + return 1; +} + +static int s390x_aes_ecb_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + + s390x_km(in, len, out, adat->plat.s390x.fc, &adat->plat.s390x.param.km); + return 1; +} + +static int s390x_aes_ofb128_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + + memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen); + memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen); + adat->plat.s390x.fc = S390X_AES_FC(keylen); + adat->plat.s390x.res = 0; + return 1; +} + +static int s390x_aes_ofb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + int n = adat->plat.s390x.res; + int rem; + + while (n && len) { + *out = *in ^ adat->plat.s390x.param.kmo_kmf.cv[n]; + n = (n + 1) & 0xf; + --len; + ++in; + ++out; + } + + rem = len & 0xf; + + len &= ~(size_t)0xf; + if (len) { + s390x_kmo(in, len, out, adat->plat.s390x.fc, + &adat->plat.s390x.param.kmo_kmf); + + out += len; + in += len; + } + + if (rem) { + s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16, + adat->plat.s390x.param.kmo_kmf.cv, adat->plat.s390x.fc, + adat->plat.s390x.param.kmo_kmf.k); + + while (rem--) { + out[n] = in[n] ^ adat->plat.s390x.param.kmo_kmf.cv[n]; + ++n; + } + } + + adat->plat.s390x.res = n; + return 1; +} + +static int s390x_aes_cfb128_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + + adat->plat.s390x.fc = S390X_AES_FC(keylen); + adat->plat.s390x.fc |= 16 << 24; /* 16 bytes cipher feedback */ + if (!dat->enc) + adat->plat.s390x.fc |= S390X_DECRYPT; + + adat->plat.s390x.res = 0; + memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen); + memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen); + return 1; +} + +static int s390x_aes_cfb128_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + int n = adat->plat.s390x.res; + int rem; + unsigned char tmp; + + while (n && len) { + tmp = *in; + *out = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp; + adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? *out : tmp; + n = (n + 1) & 0xf; + --len; + ++in; + ++out; + } + + rem = len & 0xf; + + len &= ~(size_t)0xf; + if (len) { + s390x_kmf(in, len, out, adat->plat.s390x.fc, + &adat->plat.s390x.param.kmo_kmf); + + out += len; + in += len; + } + + if (rem) { + s390x_km(adat->plat.s390x.param.kmo_kmf.cv, 16, + adat->plat.s390x.param.kmo_kmf.cv, + S390X_AES_FC(dat->keylen), adat->plat.s390x.param.kmo_kmf.k); + + while (rem--) { + tmp = in[n]; + out[n] = adat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp; + adat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? out[n] : tmp; + ++n; + } + } + + adat->plat.s390x.res = n; + return 1; +} + +static int s390x_aes_cfb8_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + + adat->plat.s390x.fc = S390X_AES_FC(keylen); + adat->plat.s390x.fc |= 1 << 24; /* 1 byte cipher feedback */ + if (!dat->enc) + adat->plat.s390x.fc |= S390X_DECRYPT; + + memcpy(adat->plat.s390x.param.kmo_kmf.cv, dat->iv, dat->ivlen); + memcpy(adat->plat.s390x.param.kmo_kmf.k, key, keylen); + return 1; +} + +static int s390x_aes_cfb8_cipher_hw(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + + s390x_kmf(in, len, out, adat->plat.s390x.fc, + &adat->plat.s390x.param.kmo_kmf); + return 1; +} + +#define PROV_CIPHER_HW_declare(mode) \ +static const PROV_CIPHER_HW s390x_aes_##mode = { \ + s390x_aes_##mode##_initkey, \ + s390x_aes_##mode##_cipher_hw \ +}; +#define PROV_CIPHER_HW_select(mode) \ +if ((keybits == 128 && S390X_aes_128_##mode##_CAPABLE) \ + || (keybits == 192 && S390X_aes_192_##mode##_CAPABLE) \ + || (keybits == 256 && S390X_aes_256_##mode##_CAPABLE)) \ + return &s390x_aes_##mode; + diff --git a/providers/implementations/ciphers/cipher_aes_hw_t4.inc b/providers/implementations/ciphers/cipher_aes_hw_t4.inc new file mode 100644 index 0000000000..21b672710a --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_hw_t4.inc @@ -0,0 +1,95 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * Sparc t4 support for AES modes ecb, cbc, ofb, cfb, ctr. + * This file is included by cipher_aes_hw.c + */ + +static int cipher_hw_aes_t4_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + int ret, bits; + PROV_AES_CTX *adat = (PROV_AES_CTX *)dat; + AES_KEY *ks = &adat->ks.ks; + + dat->ks = (const void *)ks; /* used by cipher_hw_generic_XXX */ + + bits = keylen * 8; + if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE) + && !dat->enc) { + ret = 0; + aes_t4_set_decrypt_key(key, bits, ks); + dat->block = (block128_f)aes_t4_decrypt; + switch (bits) { + case 128: + dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ? + (cbc128_f)aes128_t4_cbc_decrypt : NULL; + break; + case 192: + dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ? + (cbc128_f)aes192_t4_cbc_decrypt : NULL; + break; + case 256: + dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ? + (cbc128_f)aes256_t4_cbc_decrypt : NULL; + break; + default: + ret = -1; + } + } else { + ret = 0; + aes_t4_set_encrypt_key(key, bits, ks); + dat->block = (block128_f)aes_t4_encrypt; + switch (bits) { + case 128: + if (dat->mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f)aes128_t4_cbc_encrypt; + else if (dat->mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f)aes128_t4_ctr32_encrypt; + else + dat->stream.cbc = NULL; + break; + case 192: + if (dat->mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f)aes192_t4_cbc_encrypt; + else if (dat->mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f)aes192_t4_ctr32_encrypt; + else + dat->stream.cbc = NULL; + break; + case 256: + if (dat->mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f)aes256_t4_cbc_encrypt; + else if (dat->mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f)aes256_t4_ctr32_encrypt; + else + dat->stream.cbc = NULL; + break; + default: + ret = -1; + } + } + + if (ret < 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_AES_KEY_SETUP_FAILED); + return 0; + } + + return 1; +} + +#define PROV_CIPHER_HW_declare(mode) \ +static const PROV_CIPHER_HW aes_t4_##mode = { \ + cipher_hw_aes_t4_initkey, \ + cipher_hw_generic_##mode \ +}; +#define PROV_CIPHER_HW_select(mode) \ + if (SPARC_AES_CAPABLE) \ + return &aes_t4_##mode; diff --git a/providers/implementations/ciphers/cipher_aes_ocb.c b/providers/implementations/ciphers/cipher_aes_ocb.c new file mode 100644 index 0000000000..5ab0b8fd15 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_ocb.c @@ -0,0 +1,495 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_aes_ocb.h" +#include "internal/providercommonerr.h" +#include "prov/cipher_aead.h" +#include "internal/provider_algs.h" + +#define AES_OCB_FLAGS AEAD_FLAGS + +#define OCB_DEFAULT_TAG_LEN 16 +#define OCB_DEFAULT_IV_LEN 12 +#define OCB_MIN_IV_LEN 1 +#define OCB_MAX_IV_LEN 15 + +PROV_CIPHER_FUNC(int, ocb_cipher, (PROV_AES_OCB_CTX *ctx, + const unsigned char *in, unsigned char *out, + size_t nextblock)); +/* forward declarations */ +static OSSL_OP_cipher_encrypt_init_fn aes_ocb_einit; +static OSSL_OP_cipher_decrypt_init_fn aes_ocb_dinit; +static OSSL_OP_cipher_update_fn aes_ocb_block_update; +static OSSL_OP_cipher_final_fn aes_ocb_block_final; +static OSSL_OP_cipher_cipher_fn aes_ocb_cipher; +static OSSL_OP_cipher_freectx_fn aes_ocb_freectx; +static OSSL_OP_cipher_dupctx_fn aes_ocb_dupctx; +static OSSL_OP_cipher_get_ctx_params_fn aes_ocb_get_ctx_params; +static OSSL_OP_cipher_set_ctx_params_fn aes_ocb_set_ctx_params; + +/* + * The following methods could be moved into PROV_AES_OCB_HW if + * multiple hardware implementations are ever needed. + */ +static ossl_inline int aes_generic_ocb_setiv(PROV_AES_OCB_CTX *ctx, + const unsigned char *iv, + size_t ivlen, size_t taglen) +{ + return (CRYPTO_ocb128_setiv(&ctx->ocb, iv, ivlen, taglen) == 1); +} + +static ossl_inline int aes_generic_ocb_setaad(PROV_AES_OCB_CTX *ctx, + const unsigned char *aad, + size_t alen) +{ + return CRYPTO_ocb128_aad(&ctx->ocb, aad, alen) == 1; +} + +static ossl_inline int aes_generic_ocb_gettag(PROV_AES_OCB_CTX *ctx, + unsigned char *tag, size_t tlen) +{ + return CRYPTO_ocb128_tag(&ctx->ocb, tag, tlen) > 0; +} + +static ossl_inline int aes_generic_ocb_final(PROV_AES_OCB_CTX *ctx) +{ + return (CRYPTO_ocb128_finish(&ctx->ocb, ctx->tag, ctx->taglen) == 0); +} + +static ossl_inline void aes_generic_ocb_cleanup(PROV_AES_OCB_CTX *ctx) +{ + CRYPTO_ocb128_cleanup(&ctx->ocb); +} + +static ossl_inline int aes_generic_ocb_cipher(PROV_AES_OCB_CTX *ctx, + const unsigned char *in, + unsigned char *out, size_t len) +{ + if (ctx->base.enc) { + if (!CRYPTO_ocb128_encrypt(&ctx->ocb, in, out, len)) + return 0; + } else { + if (!CRYPTO_ocb128_decrypt(&ctx->ocb, in, out, len)) + return 0; + } + return 1; +} + +static ossl_inline int aes_generic_ocb_copy_ctx(PROV_AES_OCB_CTX *dst, + PROV_AES_OCB_CTX *src) +{ + return (!CRYPTO_ocb128_copy_ctx(&dst->ocb, &src->ocb, + &src->ksenc.ks, &src->ksdec.ks)); +} + +/*- + * Provider dispatch functions + */ +static int aes_ocb_init(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen, int enc) +{ + PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx; + + ctx->base.enc = enc; + + if (iv != NULL) { + if (ivlen != ctx->base.ivlen) { + /* IV len must be 1 to 15 */ + if (ivlen < OCB_MIN_IV_LEN || ivlen > OCB_MAX_IV_LEN) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); + return 0; + } + ctx->base.ivlen = ivlen; + } + if (!cipher_generic_initiv(&ctx->base, iv, ivlen)) + return 0; + ctx->iv_state = IV_STATE_BUFFERED; + } + if (key != NULL) { + if (keylen != ctx->base.keylen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + return ctx->base.hw->init(&ctx->base, key, keylen); + } + return 1; +} + +static int aes_ocb_einit(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + return aes_ocb_init(vctx, key, keylen, iv, ivlen, 1); +} + +static int aes_ocb_dinit(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + return aes_ocb_init(vctx, key, keylen, iv, ivlen, 0); +} + +/* + * Because of the way OCB works, both the AAD and data are buffered in the + * same way. Only the last block can be a partial block. + */ +static int aes_ocb_block_update_internal(PROV_AES_OCB_CTX *ctx, + unsigned char *buf, size_t *bufsz, + unsigned char *out, size_t *outl, + size_t outsize, const unsigned char *in, + size_t inl, OSSL_ocb_cipher_fn ciph) +{ + size_t nextblocks = fillblock(buf, bufsz, AES_BLOCK_SIZE, &in, &inl); + size_t outlint = 0; + + if (*bufsz == AES_BLOCK_SIZE) { + if (outsize < AES_BLOCK_SIZE) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + if (!ciph(ctx, buf, out, AES_BLOCK_SIZE)) { + ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); + return 0; + } + *bufsz = 0; + outlint = AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + if (nextblocks > 0) { + outlint += nextblocks; + if (outsize < outlint) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + if (!ciph(ctx, in, out, nextblocks)) { + ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); + return 0; + } + in += nextblocks; + inl -= nextblocks; + } + if (!trailingdata(buf, bufsz, AES_BLOCK_SIZE, &in, &inl)) { + /* PROVerr already called */ + return 0; + } + + *outl = outlint; + return inl == 0; +} + +/* A wrapper function that has the same signature as cipher */ +static int cipher_updateaad(PROV_AES_OCB_CTX *ctx, const unsigned char *in, + unsigned char *out, size_t len) +{ + return aes_generic_ocb_setaad(ctx, in, len); +} + +static int update_iv(PROV_AES_OCB_CTX *ctx) +{ + if (ctx->iv_state == IV_STATE_FINISHED + || ctx->iv_state == IV_STATE_UNINITIALISED) + return 0; + if (ctx->iv_state == IV_STATE_BUFFERED) { + if (!aes_generic_ocb_setiv(ctx, ctx->base.iv, ctx->base.ivlen, + ctx->taglen)) + return 0; + ctx->iv_state = IV_STATE_COPIED; + } + return 1; +} + +static int aes_ocb_block_update(void *vctx, unsigned char *out, size_t *outl, + size_t outsize, const unsigned char *in, + size_t inl) +{ + PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx; + unsigned char *buf; + size_t *buflen; + OSSL_ocb_cipher_fn fn; + + if (!ctx->key_set || !update_iv(ctx)) + return 0; + + /* Are we dealing with AAD or normal data here? */ + if (out == NULL) { + buf = ctx->aad_buf; + buflen = &ctx->aad_buf_len; + fn = cipher_updateaad; + } else { + buf = ctx->data_buf; + buflen = &ctx->data_buf_len; + fn = aes_generic_ocb_cipher; + } + return aes_ocb_block_update_internal(ctx, buf, buflen, out, outl, outsize, + in, inl, fn); +} + +static int aes_ocb_block_final(void *vctx, unsigned char *out, size_t *outl, + size_t outsize) +{ + PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx; + + /* If no block_update has run then the iv still needs to be set */ + if (!ctx->key_set || !update_iv(ctx)) + return 0; + + /* + * Empty the buffer of any partial block that we might have been provided, + * both for data and AAD + */ + *outl = 0; + if (ctx->data_buf_len > 0) { + if (!aes_generic_ocb_cipher(ctx, ctx->data_buf, out, ctx->data_buf_len)) + return 0; + *outl = ctx->data_buf_len; + ctx->data_buf_len = 0; + } + if (ctx->aad_buf_len > 0) { + if (!aes_generic_ocb_setaad(ctx, ctx->aad_buf, ctx->aad_buf_len)) + return 0; + ctx->aad_buf_len = 0; + } + if (ctx->base.enc) { + /* If encrypting then just get the tag */ + if (!aes_generic_ocb_gettag(ctx, ctx->tag, ctx->taglen)) + return 0; + } else { + /* If decrypting then verify */ + if (ctx->taglen == 0) + return 0; + if (!aes_generic_ocb_final(ctx)) + return 0; + } + /* Don't reuse the IV */ + ctx->iv_state = IV_STATE_FINISHED; + return 1; +} + +static void *aes_ocb_newctx(void *provctx, size_t kbits, size_t blkbits, + size_t ivbits, unsigned int mode, uint64_t flags) +{ + PROV_AES_OCB_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx != NULL) { + cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags, + PROV_CIPHER_HW_aes_ocb(kbits), NULL); + ctx->taglen = OCB_DEFAULT_TAG_LEN; + } + return ctx; +} + +static void aes_ocb_freectx(void *vctx) +{ + PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx; + + if (ctx != NULL) { + aes_generic_ocb_cleanup(ctx); + OPENSSL_clear_free(ctx, sizeof(*ctx)); + } +} + +static void *aes_ocb_dupctx(void *vctx) +{ + PROV_AES_OCB_CTX *in = (PROV_AES_OCB_CTX *)vctx; + PROV_AES_OCB_CTX *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + *ret = *in; + if (!aes_generic_ocb_copy_ctx(ret, in)) { + OPENSSL_free(ret); + ret = NULL; + } + return ret; +} + +static int aes_ocb_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx; + const OSSL_PARAM *p; + size_t sz; + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG); + if (p != NULL) { + if (p->data_type != OSSL_PARAM_OCTET_STRING) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + if (p->data == NULL) { + /* Tag len must be 0 to 16 */ + if (p->data_size > OCB_MAX_TAG_LEN) + return 0; + ctx->taglen = p->data_size; + } else { + if (p->data_size != ctx->taglen || ctx->base.enc) + return 0; + memcpy(ctx->tag, p->data, p->data_size); + } + } + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN); + if (p != NULL) { + if (!OSSL_PARAM_get_size_t(p, &sz)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + /* IV len must be 1 to 15 */ + if (sz < OCB_MIN_IV_LEN || sz > OCB_MAX_IV_LEN) + return 0; + ctx->base.ivlen = sz; + } + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p != NULL) { + size_t keylen; + + if (!OSSL_PARAM_get_size_t(p, &keylen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + if (ctx->base.keylen != keylen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + } + return 1; +} + +static int aes_ocb_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx; + OSSL_PARAM *p; + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.ivlen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.keylen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN); + if (p != NULL) { + if (!OSSL_PARAM_set_size_t(p, ctx->taglen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV); + if (p != NULL) { + if (ctx->base.ivlen != p->data_size) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); + return 0; + } + if (!OSSL_PARAM_set_octet_string(p, ctx->base.oiv, ctx->base.ivlen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG); + if (p != NULL) { + if (p->data_type != OSSL_PARAM_OCTET_STRING) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + if (!ctx->base.enc || p->data_size != ctx->taglen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAGLEN); + return 0; + } + memcpy(p->data, ctx->tag, ctx->taglen); + } + return 1; +} + +static const OSSL_PARAM cipher_ocb_known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), + OSSL_PARAM_END +}; +static const OSSL_PARAM *cipher_ocb_gettable_ctx_params(void) +{ + return cipher_ocb_known_gettable_ctx_params; +} + +static const OSSL_PARAM cipher_ocb_known_settable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, NULL), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), + OSSL_PARAM_END +}; +static const OSSL_PARAM *cipher_ocb_settable_ctx_params(void) +{ + return cipher_ocb_known_settable_ctx_params; +} + +static int aes_ocb_cipher(void *vctx, unsigned char *out, size_t *outl, + size_t outsize, const unsigned char *in, size_t inl) +{ + PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx; + + if (outsize < inl) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (!aes_generic_ocb_cipher(ctx, in, out, inl)) { + ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); + return 0; + } + + *outl = inl; + return 1; +} + +#define IMPLEMENT_cipher(mode, UCMODE, flags, kbits, blkbits, ivbits) \ +static OSSL_OP_cipher_get_params_fn aes_##kbits##_##mode##_get_params; \ +static int aes_##kbits##_##mode##_get_params(OSSL_PARAM params[]) \ +{ \ + return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \ + flags, kbits, blkbits, ivbits); \ +} \ +static OSSL_OP_cipher_newctx_fn aes_##kbits##_##mode##_newctx; \ +static void *aes_##kbits##_##mode##_newctx(void *provctx) \ +{ \ + return aes_##mode##_newctx(provctx, kbits, blkbits, ivbits, \ + EVP_CIPH_##UCMODE##_MODE, flags); \ +} \ +const OSSL_DISPATCH aes##kbits##mode##_functions[] = { \ + { OSSL_FUNC_CIPHER_NEWCTX, \ + (void (*)(void))aes_##kbits##_##mode##_newctx }, \ + { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_##mode##_einit }, \ + { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_##mode##_dinit }, \ + { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_##mode##_block_update }, \ + { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_##mode##_block_final }, \ + { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_ocb_cipher }, \ + { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_##mode##_freectx }, \ + { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_##mode##_dupctx }, \ + { OSSL_FUNC_CIPHER_GET_PARAMS, \ + (void (*)(void))aes_##kbits##_##mode##_get_params }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ + (void (*)(void))aes_##mode##_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ + (void (*)(void))aes_##mode##_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ + (void (*)(void))cipher_generic_gettable_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ + (void (*)(void))cipher_ocb_gettable_ctx_params }, \ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ + (void (*)(void))cipher_ocb_settable_ctx_params }, \ + { 0, NULL } \ +} + +IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 256, 128, OCB_DEFAULT_IV_LEN * 8); +IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 192, 128, OCB_DEFAULT_IV_LEN * 8); +IMPLEMENT_cipher(ocb, OCB, AES_OCB_FLAGS, 128, 128, OCB_DEFAULT_IV_LEN * 8); + diff --git a/providers/implementations/ciphers/cipher_aes_ocb.h b/providers/implementations/ciphers/cipher_aes_ocb.h new file mode 100644 index 0000000000..ba515241e2 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_ocb.h @@ -0,0 +1,38 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/aes.h> +#include "prov/ciphercommon.h" + +#define OCB_MAX_TAG_LEN AES_BLOCK_SIZE +#define OCB_MAX_DATA_LEN AES_BLOCK_SIZE +#define OCB_MAX_AAD_LEN AES_BLOCK_SIZE + +typedef struct prov_aes_ocb_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + AES_KEY ks; + } ksenc; /* AES key schedule to use for encryption/aad */ + union { + OSSL_UNION_ALIGN; + AES_KEY ks; + } ksdec; /* AES key schedule to use for decryption */ + OCB128_CONTEXT ocb; + unsigned int iv_state; /* set to one of IV_STATE_XXX */ + unsigned int key_set : 1; + size_t taglen; + size_t data_buf_len; + size_t aad_buf_len; + unsigned char tag[OCB_MAX_TAG_LEN]; + unsigned char data_buf[OCB_MAX_DATA_LEN]; /* Store partial data blocks */ + unsigned char aad_buf[OCB_MAX_AAD_LEN]; /* Store partial AAD blocks */ +} PROV_AES_OCB_CTX; + +const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_ocb(size_t keybits); diff --git a/providers/implementations/ciphers/cipher_aes_ocb_hw.c b/providers/implementations/ciphers/cipher_aes_ocb_hw.c new file mode 100644 index 0000000000..49f387b5ba --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_ocb_hw.c @@ -0,0 +1,115 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_aes_ocb.h" + +#define OCB_SET_KEY_FN(fn_set_enc_key, fn_set_dec_key, \ + fn_block_enc, fn_block_dec, \ + fn_stream_enc, fn_stream_dec) \ +fn_set_enc_key(key, keylen * 8, &ctx->ksenc.ks); \ +fn_set_dec_key(key, keylen * 8, &ctx->ksdec.ks); \ +if (!CRYPTO_ocb128_init(&ctx->ocb, &ctx->ksenc.ks, &ctx->ksdec.ks, \ + (block128_f)fn_block_enc, (block128_f)fn_block_dec, \ + ctx->base.enc ? (ocb128_f)fn_stream_enc : \ + (ocb128_f)fn_stream_dec)) \ + return 0; \ +ctx->key_set = 1 + + +static int cipher_hw_aes_ocb_generic_initkey(PROV_CIPHER_CTX *vctx, + const unsigned char *key, + size_t keylen) +{ + PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx; + +/* + * We set both the encrypt and decrypt key here because decrypt + * needs both. (i.e- AAD uses encrypt). + */ +# ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { + OCB_SET_KEY_FN(HWAES_set_encrypt_key, HWAES_set_decrypt_key, + HWAES_encrypt, HWAES_decrypt, + HWAES_ocb_encrypt, HWAES_ocb_decrypt); + } else +# endif +# ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { + OCB_SET_KEY_FN(vpaes_set_encrypt_key, vpaes_set_decrypt_key, + vpaes_encrypt, vpaes_decrypt, NULL, NULL); + } else +# endif + { + OCB_SET_KEY_FN(AES_set_encrypt_key, AES_set_decrypt_key, + AES_encrypt, AES_decrypt, NULL, NULL); + } + return 1; +} + +# if defined(AESNI_CAPABLE) + +static int cipher_hw_aes_ocb_aesni_initkey(PROV_CIPHER_CTX *vctx, + const unsigned char *key, + size_t keylen) +{ + PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx; + + OCB_SET_KEY_FN(aesni_set_encrypt_key, aesni_set_decrypt_key, + aesni_encrypt, aesni_decrypt, + aesni_ocb_encrypt, aesni_ocb_decrypt); + return 1; +} + +# define PROV_CIPHER_HW_declare() \ +static const PROV_CIPHER_HW aesni_ocb = { \ + cipher_hw_aes_ocb_aesni_initkey, \ + NULL \ +}; +# define PROV_CIPHER_HW_select() \ + if (AESNI_CAPABLE) \ + return &aesni_ocb; + +#elif defined(SPARC_AES_CAPABLE) + +static int cipher_hw_aes_ocb_t4_initkey(PROV_CIPHER_CTX *vctx, + const unsigned char *key, + size_t keylen) +{ + PROV_AES_OCB_CTX *ctx = (PROV_AES_OCB_CTX *)vctx; + + OCB_SET_KEY_FN(aes_t4_set_encrypt_key, aes_t4_set_decrypt_key, + aes_t4_encrypt, aes_t4_decrypt, NULL, NULL); + return 1; +} + +# define PROV_CIPHER_HW_declare() \ +static const PROV_CIPHER_HW aes_t4_ocb = { \ + cipher_hw_aes_ocb_t4_initkey, \ + NULL \ +}; +# define PROV_CIPHER_HW_select() \ + if (SPARC_AES_CAPABLE) \ + return &aes_t4_ocb; +#else +# define PROV_CIPHER_HW_declare() +# define PROV_CIPHER_HW_select() +# endif + +static const PROV_CIPHER_HW aes_generic_ocb = { + cipher_hw_aes_ocb_generic_initkey, + NULL +}; +PROV_CIPHER_HW_declare() +const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_ocb(size_t keybits) +{ + PROV_CIPHER_HW_select() + return &aes_generic_ocb; +} + + diff --git a/providers/implementations/ciphers/cipher_aes_wrp.c b/providers/implementations/ciphers/cipher_aes_wrp.c new file mode 100644 index 0000000000..1bf4c1793a --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_wrp.c @@ -0,0 +1,242 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_aes.h" +#include "internal/providercommonerr.h" +#include "internal/provider_algs.h" + +/* AES wrap with padding has IV length of 4, without padding 8 */ +#define AES_WRAP_PAD_IVLEN 4 +#define AES_WRAP_NOPAD_IVLEN 8 + +/* TODO(3.0) Figure out what flags need to be passed */ +#define WRAP_FLAGS (EVP_CIPH_WRAP_MODE \ + | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \ + | EVP_CIPH_ALWAYS_CALL_INIT) + +typedef size_t (*aeswrap_fn)(void *key, const unsigned char *iv, + unsigned char *out, const unsigned char *in, + size_t inlen, block128_f block); + +static OSSL_OP_cipher_encrypt_init_fn aes_wrap_einit; +static OSSL_OP_cipher_decrypt_init_fn aes_wrap_dinit; +static OSSL_OP_cipher_update_fn aes_wrap_cipher; +static OSSL_OP_cipher_final_fn aes_wrap_final; +static OSSL_OP_cipher_freectx_fn aes_wrap_freectx; + +typedef struct prov_aes_wrap_ctx_st { + PROV_CIPHER_CTX base; + union { + OSSL_UNION_ALIGN; + AES_KEY ks; + } ks; + aeswrap_fn wrapfn; + +} PROV_AES_WRAP_CTX; + + +static void *aes_wrap_newctx(size_t kbits, size_t blkbits, + size_t ivbits, unsigned int mode, uint64_t flags) +{ + PROV_AES_WRAP_CTX *wctx = OPENSSL_zalloc(sizeof(*wctx)); + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)wctx; + + if (ctx != NULL) { + cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags, + NULL, NULL); + ctx->pad = (ctx->ivlen == AES_WRAP_PAD_IVLEN); + } + return wctx; +} + +static void aes_wrap_freectx(void *vctx) +{ + PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx; + + OPENSSL_clear_free(wctx, sizeof(*wctx)); +} + +static int aes_wrap_init(void *vctx, const unsigned char *key, + size_t keylen, const unsigned char *iv, + size_t ivlen, int enc) +{ + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx; + + ctx->enc = enc; + ctx->block = enc ? (block128_f)AES_encrypt : (block128_f)AES_decrypt; + if (ctx->pad) + wctx->wrapfn = enc ? CRYPTO_128_wrap_pad : CRYPTO_128_unwrap_pad; + else + wctx->wrapfn = enc ? CRYPTO_128_wrap : CRYPTO_128_unwrap; + + if (iv != NULL) { + if (!cipher_generic_initiv(ctx, iv, ivlen)) + return 0; + } + if (key != NULL) { + if (keylen != ctx->keylen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + if (ctx->enc) + AES_set_encrypt_key(key, keylen * 8, &wctx->ks.ks); + else + AES_set_decrypt_key(key, keylen * 8, &wctx->ks.ks); + } + return 1; +} + +static int aes_wrap_einit(void *ctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + return aes_wrap_init(ctx, key, keylen, iv, ivlen, 1); +} + +static int aes_wrap_dinit(void *ctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + return aes_wrap_init(ctx, key, keylen, iv, ivlen, 0); +} + +static int aes_wrap_cipher_internal(void *vctx, unsigned char *out, + const unsigned char *in, size_t inlen) +{ + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx; + size_t rv; + int pad = ctx->pad; + + /* No final operation so always return zero length */ + if (in == NULL) + return 0; + + /* Input length must always be non-zero */ + if (inlen == 0) + return -1; + + /* If decrypting need at least 16 bytes and multiple of 8 */ + if (!ctx->enc && (inlen < 16 || inlen & 0x7)) + return -1; + + /* If not padding input must be multiple of 8 */ + if (!pad && inlen & 0x7) + return -1; + + if (out == NULL) { + if (ctx->enc) { + /* If padding round up to multiple of 8 */ + if (pad) + inlen = (inlen + 7) / 8 * 8; + /* 8 byte prefix */ + return inlen + 8; + } else { + /* + * If not padding output will be exactly 8 bytes smaller than + * input. If padding it will be at least 8 bytes smaller but we + * don't know how much. + */ + return inlen - 8; + } + } + + rv = wctx->wrapfn(&wctx->ks.ks, ctx->iv_set ? ctx->iv : NULL, out, in, + inlen, ctx->block); + return rv ? (int)rv : -1; +} + +static int aes_wrap_final(void *vctx, unsigned char *out, size_t *outl, + size_t outsize) +{ + *outl = 0; + return 1; +} + +static int aes_wrap_cipher(void *vctx, + unsigned char *out, size_t *outl, size_t outsize, + const unsigned char *in, size_t inl) +{ + PROV_AES_WRAP_CTX *ctx = (PROV_AES_WRAP_CTX *)vctx; + size_t len; + + if (outsize < inl) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return -1; + } + + len = aes_wrap_cipher_internal(ctx, out, in, inl); + if (len == 0) + return -1; + + *outl = len; + return 1; +} + +static int aes_wrap_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + const OSSL_PARAM *p; + size_t keylen = 0; + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p != NULL) { + if (!OSSL_PARAM_get_size_t(p, &keylen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + if (ctx->keylen != keylen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + } + return 1; +} + +#define IMPLEMENT_cipher(mode, fname, UCMODE, flags, kbits, blkbits, ivbits) \ + static OSSL_OP_cipher_get_params_fn aes_##kbits##_##fname##_get_params; \ + static int aes_##kbits##_##fname##_get_params(OSSL_PARAM params[]) \ + { \ + return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \ + flags, kbits, blkbits, ivbits); \ + } \ + static OSSL_OP_cipher_newctx_fn aes_##kbits##fname##_newctx; \ + static void *aes_##kbits##fname##_newctx(void *provctx) \ + { \ + return aes_##mode##_newctx(kbits, blkbits, ivbits, \ + EVP_CIPH_##UCMODE##_MODE, flags); \ + } \ + const OSSL_DISPATCH aes##kbits##fname##_functions[] = { \ + { OSSL_FUNC_CIPHER_NEWCTX, \ + (void (*)(void))aes_##kbits##fname##_newctx }, \ + { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_##mode##_einit }, \ + { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_##mode##_dinit }, \ + { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_##mode##_cipher }, \ + { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_##mode##_final }, \ + { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_##mode##_freectx }, \ + { OSSL_FUNC_CIPHER_GET_PARAMS, \ + (void (*)(void))aes_##kbits##_##fname##_get_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ + (void (*)(void))cipher_generic_gettable_params }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ + (void (*)(void))cipher_generic_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ + (void (*)(void))aes_wrap_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ + (void (*)(void))cipher_generic_gettable_ctx_params }, \ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ + (void (*)(void))cipher_generic_settable_ctx_params }, \ + { 0, NULL } \ + } + +IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_NOPAD_IVLEN * 8); +IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_NOPAD_IVLEN * 8); +IMPLEMENT_cipher(wrap, wrap, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_NOPAD_IVLEN * 8); +IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 256, 64, AES_WRAP_PAD_IVLEN * 8); +IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 192, 64, AES_WRAP_PAD_IVLEN * 8); +IMPLEMENT_cipher(wrap, wrappad, WRAP, WRAP_FLAGS, 128, 64, AES_WRAP_PAD_IVLEN * 8); diff --git a/providers/implementations/ciphers/cipher_aes_xts.c b/providers/implementations/ciphers/cipher_aes_xts.c new file mode 100644 index 0000000000..d0b999081e --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_xts.c @@ -0,0 +1,275 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_aes_xts.h" +#include "internal/provider_algs.h" +#include "internal/providercommonerr.h" + +/* TODO (3.0) Figure out what flags need to be set */ +#define AES_XTS_FLAGS (EVP_CIPH_CUSTOM_IV \ + | EVP_CIPH_ALWAYS_CALL_INIT \ + | EVP_CIPH_CTRL_INIT \ + | EVP_CIPH_CUSTOM_COPY) + +#define AES_XTS_IV_BITS 128 +#define AES_XTS_BLOCK_BITS 8 + +/* forward declarations */ +static OSSL_OP_cipher_encrypt_init_fn aes_xts_einit; +static OSSL_OP_cipher_decrypt_init_fn aes_xts_dinit; +static OSSL_OP_cipher_update_fn aes_xts_stream_update; +static OSSL_OP_cipher_final_fn aes_xts_stream_final; +static OSSL_OP_cipher_cipher_fn aes_xts_cipher; +static OSSL_OP_cipher_freectx_fn aes_xts_freectx; +static OSSL_OP_cipher_dupctx_fn aes_xts_dupctx; +static OSSL_OP_cipher_set_ctx_params_fn aes_xts_set_ctx_params; +static OSSL_OP_cipher_settable_ctx_params_fn aes_xts_settable_ctx_params; + +/* + * Verify that the two keys are different. + * + * This addresses the vulnerability described in Rogaway's + * September 2004 paper: + * + * "Efficient Instantiations of Tweakable Blockciphers and + * Refinements to Modes OCB and PMAC". + * (http://web.cs.ucdavis.edu/~rogaway/papers/offsets.pdf) + * + * FIPS 140-2 IG A.9 XTS-AES Key Generation Requirements states + * that: + * "The check for Key_1 != Key_2 shall be done at any place + * BEFORE using the keys in the XTS-AES algorithm to process + * data with them." + */ +static int aes_xts_check_keys_differ(const unsigned char *key, size_t bytes, + int enc) +{ + if ((!allow_insecure_decrypt || enc) + && CRYPTO_memcmp(key, key + bytes, bytes) == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DUPLICATED_KEYS); + return 0; + } + return 1; +} + +/*- + * Provider dispatch functions + */ +static int aes_xts_init(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen, int enc) +{ + PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)vctx; + PROV_CIPHER_CTX *ctx = &xctx->base; + + ctx->enc = enc; + + if (iv != NULL) { + if (!cipher_generic_initiv(vctx, iv, ivlen)) + return 0; + } + if (key != NULL) { + if (keylen != ctx->keylen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + if (!aes_xts_check_keys_differ(key, keylen / 2, enc)) + return 0; + return ctx->hw->init(ctx, key, keylen); + } + return 1; +} + +static int aes_xts_einit(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + return aes_xts_init(vctx, key, keylen, iv, ivlen, 1); +} + +static int aes_xts_dinit(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + return aes_xts_init(vctx, key, keylen, iv, ivlen, 0); +} + +static void *aes_xts_newctx(void *provctx, unsigned int mode, uint64_t flags, + size_t kbits, size_t blkbits, size_t ivbits) +{ + PROV_AES_XTS_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx != NULL) { + cipher_generic_initkey(&ctx->base, kbits, blkbits, ivbits, mode, flags, + PROV_CIPHER_HW_aes_xts(kbits), NULL); + } + return ctx; +} + +static void aes_xts_freectx(void *vctx) +{ + PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +static void *aes_xts_dupctx(void *vctx) +{ + PROV_AES_XTS_CTX *in = (PROV_AES_XTS_CTX *)vctx; + PROV_AES_XTS_CTX *ret = NULL; + + if (in->xts.key1 != NULL) { + if (in->xts.key1 != &in->ks1) + return NULL; + } + if (in->xts.key2 != NULL) { + if (in->xts.key2 != &in->ks2) + return NULL; + } + ret = OPENSSL_malloc(sizeof(*ret)); + if (ret == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + *ret = *in; + return ret; +} + +static int aes_xts_cipher(void *vctx, unsigned char *out, size_t *outl, + size_t outsize, const unsigned char *in, size_t inl) +{ + PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx; + + if (ctx->xts.key1 == NULL + || ctx->xts.key2 == NULL + || !ctx->base.iv_set + || out == NULL + || in == NULL + || inl < AES_BLOCK_SIZE) + return 0; + + /* + * Impose a limit of 2^20 blocks per data unit as specifed by + * IEEE Std 1619-2018. The earlier and obsolete IEEE Std 1619-2007 + * indicated that this was a SHOULD NOT rather than a MUST NOT. + * NIST SP 800-38E mandates the same limit. + */ + if (inl > XTS_MAX_BLOCKS_PER_DATA_UNIT * AES_BLOCK_SIZE) { + ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE); + return 0; + } + + if (ctx->stream != NULL) + (*ctx->stream)(in, out, inl, ctx->xts.key1, ctx->xts.key2, ctx->base.iv); + else if (CRYPTO_xts128_encrypt(&ctx->xts, ctx->base.iv, in, out, inl, + ctx->base.enc)) + return 0; + + *outl = inl; + return 1; +} + +static int aes_xts_stream_update(void *vctx, unsigned char *out, size_t *outl, + size_t outsize, const unsigned char *in, + size_t inl) +{ + PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx; + + if (outsize < inl) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (!aes_xts_cipher(ctx, out, outl, outsize, in, inl)) { + ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); + return 0; + } + + return 1; +} + +static int aes_xts_stream_final(void *vctx, unsigned char *out, size_t *outl, + size_t outsize) +{ + *outl = 0; + return 1; +} + +static const OSSL_PARAM aes_xts_known_settable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), + OSSL_PARAM_END +}; + +static const OSSL_PARAM *aes_xts_settable_ctx_params(void) +{ + return aes_xts_known_settable_ctx_params; +} + +static int aes_xts_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + const OSSL_PARAM *p; + + /* + * TODO(3.0) We need a general solution for handling missing parameters + * inside set_params and get_params methods. + */ + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p != NULL) { + size_t keylen; + + if (!OSSL_PARAM_get_size_t(p, &keylen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + /* The key length can not be modified for xts mode */ + if (keylen != ctx->keylen) + return 0; + } + + return 1; +} + +#define IMPLEMENT_cipher(lcmode, UCMODE, kbits, flags) \ +static OSSL_OP_cipher_get_params_fn aes_##kbits##_##lcmode##_get_params; \ +static int aes_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \ +{ \ + return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \ + flags, 2 * kbits, AES_XTS_BLOCK_BITS, \ + AES_XTS_IV_BITS); \ +} \ +static OSSL_OP_cipher_newctx_fn aes_##kbits##_xts_newctx; \ +static void *aes_##kbits##_xts_newctx(void *provctx) \ +{ \ + return aes_xts_newctx(provctx, EVP_CIPH_##UCMODE##_MODE, flags, 2 * kbits, \ + AES_XTS_BLOCK_BITS, AES_XTS_IV_BITS); \ +} \ +const OSSL_DISPATCH aes##kbits##xts_functions[] = { \ + { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##kbits##_xts_newctx }, \ + { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_xts_einit }, \ + { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_xts_dinit }, \ + { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_xts_stream_update }, \ + { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_xts_stream_final }, \ + { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_xts_cipher }, \ + { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_xts_freectx }, \ + { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_xts_dupctx }, \ + { OSSL_FUNC_CIPHER_GET_PARAMS, \ + (void (*)(void))aes_##kbits##_##lcmode##_get_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ + (void (*)(void))cipher_generic_gettable_params }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ + (void (*)(void))cipher_generic_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ + (void (*)(void))cipher_generic_gettable_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ + (void (*)(void))aes_xts_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ + (void (*)(void))aes_xts_settable_ctx_params }, \ + { 0, NULL } \ +} + +IMPLEMENT_cipher(xts, XTS, 256, AES_XTS_FLAGS); +IMPLEMENT_cipher(xts, XTS, 128, AES_XTS_FLAGS); diff --git a/providers/implementations/ciphers/cipher_aes_xts.h b/providers/implementations/ciphers/cipher_aes_xts.h new file mode 100644 index 0000000000..615ee61905 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_xts.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/aes.h> +#include "prov/ciphercommon.h" + +/* + * Available in cipher_fips.c, and compiled with different values depending + * on we're in the FIPS module or not. + */ +extern const int allow_insecure_decrypt; + +PROV_CIPHER_FUNC(void, xts_stream, + (const unsigned char *in, unsigned char *out, size_t len, + const AES_KEY *key1, const AES_KEY *key2, + const unsigned char iv[16])); + +typedef struct prov_aes_xts_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + AES_KEY ks; + } ks1, ks2; /* AES key schedules to use */ + XTS128_CONTEXT xts; + OSSL_xts_stream_fn stream; +} PROV_AES_XTS_CTX; + +const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_xts(size_t keybits); diff --git a/providers/implementations/ciphers/cipher_aes_xts_fips.c b/providers/implementations/ciphers/cipher_aes_xts_fips.c new file mode 100644 index 0000000000..c99d6ed2f4 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_xts_fips.c @@ -0,0 +1,16 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_aes_xts.h" + +#ifdef FIPS_MODE +const int allow_insecure_decrypt = 0; +#else +const int allow_insecure_decrypt = 1; +#endif /* FIPS_MODE */ diff --git a/providers/implementations/ciphers/cipher_aes_xts_hw.c b/providers/implementations/ciphers/cipher_aes_xts_hw.c new file mode 100644 index 0000000000..9ac70c4fa8 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_xts_hw.c @@ -0,0 +1,153 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_aes_xts.h" + +#define XTS_SET_KEY_FN(fn_set_enc_key, fn_set_dec_key, \ + fn_block_enc, fn_block_dec, \ + fn_stream_enc, fn_stream_dec) { \ + size_t bytes = keylen / 2; \ + size_t bits = bytes * 8; \ + \ + if (ctx->enc) { \ + fn_set_enc_key(key, bits, &xctx->ks1.ks); \ + xctx->xts.block1 = (block128_f)fn_block_enc; \ + } else { \ + fn_set_dec_key(key, bits, &xctx->ks1.ks); \ + xctx->xts.block1 = (block128_f)fn_block_dec; \ + } \ + fn_set_enc_key(key + bytes, bits, &xctx->ks2.ks); \ + xctx->xts.block2 = (block128_f)fn_block_enc; \ + xctx->xts.key1 = &xctx->ks1; \ + xctx->xts.key2 = &xctx->ks2; \ + xctx->stream = ctx->enc ? fn_stream_enc : fn_stream_dec; \ +} + +static int cipher_hw_aes_xts_generic_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, + size_t keylen) +{ + PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx; + OSSL_xts_stream_fn stream_enc = NULL; + OSSL_xts_stream_fn stream_dec = NULL; + +#ifdef AES_XTS_ASM + stream_enc = AES_xts_encrypt; + stream_dec = AES_xts_decrypt; +#endif /* AES_XTS_ASM */ + +#ifdef HWAES_CAPABLE + if (HWAES_CAPABLE) { +# ifdef HWAES_xts_encrypt + stream_enc = HWAES_xts_encrypt; +# endif /* HWAES_xts_encrypt */ +# ifdef HWAES_xts_decrypt + stream_dec = HWAES_xts_decrypt; +# endif /* HWAES_xts_decrypt */ + XTS_SET_KEY_FN(HWAES_set_encrypt_key, HWAES_set_decrypt_key, + HWAES_encrypt, HWAES_decrypt, + stream_enc, stream_dec); + } else +#endif /* HWAES_CAPABLE */ + +#ifdef BSAES_CAPABLE + if (BSAES_CAPABLE) { + stream_enc = bsaes_xts_encrypt; + stream_dec = bsaes_xts_decrypt; + } +#endif /* BSAES_CAPABLE */ + +#ifdef VPAES_CAPABLE + if (VPAES_CAPABLE) { + XTS_SET_KEY_FN(vpaes_set_encrypt_key, vpaes_set_decrypt_key, + vpaes_encrypt, vpaes_decrypt, stream_enc, stream_dec); + } else +#endif /* VPAES_CAPABLE */ + { + XTS_SET_KEY_FN(AES_set_encrypt_key, AES_set_decrypt_key, + AES_encrypt, AES_decrypt, stream_enc, stream_dec); + } + return 1; +} + +#if defined(AESNI_CAPABLE) + +static int cipher_hw_aesni_xts_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx; + + XTS_SET_KEY_FN(aesni_set_encrypt_key, aesni_set_decrypt_key, + aesni_encrypt, aesni_decrypt, + aesni_xts_encrypt, aesni_xts_decrypt); + return 1; +} + +# define PROV_CIPHER_HW_declare_xts() \ +static const PROV_CIPHER_HW aesni_xts = { \ + cipher_hw_aesni_xts_initkey, \ + NULL \ +}; +# define PROV_CIPHER_HW_select_xts() \ +if (AESNI_CAPABLE) \ + return &aesni_xts; + +# elif defined(SPARC_AES_CAPABLE) + +static int cipher_hw_aes_xts_t4_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx; + OSSL_xts_stream_fn stream_enc = NULL; + OSSL_xts_stream_fn stream_dec = NULL; + + /* Note: keylen is the size of 2 keys */ + switch (keylen) { + case 32: + stream_enc = aes128_t4_xts_encrypt; + stream_dec = aes128_t4_xts_decrypt; + break; + case 64: + stream_enc = aes256_t4_xts_encrypt; + stream_dec = aes256_t4_xts_decrypt; + break; + default: + return 0; + } + + XTS_SET_KEY_FN(aes_t4_set_encrypt_key, aes_t4_set_decrypt_key, + aes_t4_encrypt, aes_t4_decrypt, + stream_enc, stream_dec); + return 1; +} + +# define PROV_CIPHER_HW_declare_xts() \ +static const PROV_CIPHER_HW aes_xts_t4 = { \ + cipher_hw_aes_xts_t4_initkey, \ + NULL \ +}; +# define PROV_CIPHER_HW_select_xts() \ +if (SPARC_AES_CAPABLE) \ + return &aes_xts_t4; +# else +/* The generic case */ +# define PROV_CIPHER_HW_declare_xts() +# define PROV_CIPHER_HW_select_xts() +#endif + +static const PROV_CIPHER_HW aes_generic_xts = { + cipher_hw_aes_xts_generic_initkey, + NULL +}; +PROV_CIPHER_HW_declare_xts() +const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_xts(size_t keybits) +{ + PROV_CIPHER_HW_select_xts() + return &aes_generic_xts; +} diff --git a/providers/implementations/ciphers/cipher_aria.c b/providers/implementations/ciphers/cipher_aria.c new file mode 100644 index 0000000000..861b28268b --- /dev/null +++ b/providers/implementations/ciphers/cipher_aria.c @@ -0,0 +1,80 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for ARIA cipher modes ecb, cbc, ofb, cfb, ctr */ + +#include "cipher_aria.h" +#include "internal/provider_algs.h" + +static OSSL_OP_cipher_freectx_fn aria_freectx; +static OSSL_OP_cipher_dupctx_fn aria_dupctx; + +static void aria_freectx(void *vctx) +{ + PROV_ARIA_CTX *ctx = (PROV_ARIA_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +static void *aria_dupctx(void *ctx) +{ + PROV_ARIA_CTX *in = (PROV_ARIA_CTX *)ctx; + PROV_ARIA_CTX *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + *ret = *in; + + return ret; +} + +/* aria256ecb_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, ecb, ECB, 0, 256, 128, 0, block) +/* aria192ecb_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, ecb, ECB, 0, 192, 128, 0, block) +/* aria128ecb_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, ecb, ECB, 0, 128, 128, 0, block) +/* aria256cbc_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, cbc, CBC, 0, 256, 128, 128, block) +/* aria192cbc_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, cbc, CBC, 0, 192, 128, 128, block) +/* aria128cbc_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, cbc, CBC, 0, 128, 128, 128, block) +/* aria256ofb_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, ofb, OFB, 0, 256, 8, 128, stream) +/* aria192ofb_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, ofb, OFB, 0, 192, 8, 128, stream) +/* aria128ofb_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, ofb, OFB, 0, 128, 8, 128, stream) +/* aria256cfb_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, cfb, CFB, 0, 256, 8, 128, stream) +/* aria192cfb_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, cfb, CFB, 0, 192, 8, 128, stream) +/* aria128cfb_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, cfb, CFB, 0, 128, 8, 128, stream) +/* aria256cfb1_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, cfb1, CFB, 0, 256, 8, 128, stream) +/* aria192cfb1_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, cfb1, CFB, 0, 192, 8, 128, stream) +/* aria128cfb1_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, cfb1, CFB, 0, 128, 8, 128, stream) +/* aria256cfb8_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, cfb8, CFB, 0, 256, 8, 128, stream) +/* aria192cfb8_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, cfb8, CFB, 0, 192, 8, 128, stream) +/* aria128cfb8_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, cfb8, CFB, 0, 128, 8, 128, stream) +/* aria256ctr_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, ctr, CTR, 0, 256, 8, 128, stream) +/* aria192ctr_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, ctr, CTR, 0, 192, 8, 128, stream) +/* aria128ctr_functions */ +IMPLEMENT_generic_cipher(aria, ARIA, ctr, CTR, 0, 128, 8, 128, stream) diff --git a/providers/implementations/ciphers/cipher_aria.h b/providers/implementations/ciphers/cipher_aria.h new file mode 100644 index 0000000000..282408c58e --- /dev/null +++ b/providers/implementations/ciphers/cipher_aria.h @@ -0,0 +1,30 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "crypto/aria.h" +#include "prov/ciphercommon.h" + +typedef struct prov_aria_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + ARIA_KEY ks; + } ks; +} PROV_ARIA_CTX; + + +# define PROV_CIPHER_HW_aria_ofb PROV_CIPHER_HW_aria_ofb128 +# define PROV_CIPHER_HW_aria_cfb PROV_CIPHER_HW_aria_cfb128 +const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_ecb(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_cbc(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_ofb128(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_cfb128(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_cfb1(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_cfb8(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_ctr(size_t keybits); diff --git a/providers/implementations/ciphers/cipher_aria_ccm.c b/providers/implementations/ciphers/cipher_aria_ccm.c new file mode 100644 index 0000000000..97e8137db8 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aria_ccm.c @@ -0,0 +1,39 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for ARIA CCM mode */ + +#include "cipher_aria_ccm.h" +#include "internal/provider_algs.h" + +static OSSL_OP_cipher_freectx_fn aria_ccm_freectx; + +static void *aria_ccm_newctx(void *provctx, size_t keybits) +{ + PROV_ARIA_CCM_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx != NULL) + ccm_initctx(&ctx->base, keybits, PROV_ARIA_HW_ccm(keybits)); + return ctx; +} + +static void aria_ccm_freectx(void *vctx) +{ + PROV_ARIA_CCM_CTX *ctx = (PROV_ARIA_CCM_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +/* aria128ccm functions */ +IMPLEMENT_aead_cipher(aria, ccm, CCM, AEAD_FLAGS, 128, 8, 96); +/* aria192ccm functions */ +IMPLEMENT_aead_cipher(aria, ccm, CCM, AEAD_FLAGS, 192, 8, 96); +/* aria256ccm functions */ +IMPLEMENT_aead_cipher(aria, ccm, CCM, AEAD_FLAGS, 256, 8, 96); + diff --git a/providers/implementations/ciphers/cipher_aria_ccm.h b/providers/implementations/ciphers/cipher_aria_ccm.h new file mode 100644 index 0000000000..301ce14306 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aria_ccm.h @@ -0,0 +1,22 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "crypto/aria.h" +#include "prov/ciphercommon.h" +#include "prov/cipher_ccm.h" + +typedef struct prov_aria_ccm_ctx_st { + PROV_CCM_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + ARIA_KEY ks; + } ks; /* ARIA key schedule to use */ +} PROV_ARIA_CCM_CTX; + +const PROV_CCM_HW *PROV_ARIA_HW_ccm(size_t keylen); diff --git a/providers/implementations/ciphers/cipher_aria_ccm_hw.c b/providers/implementations/ciphers/cipher_aria_ccm_hw.c new file mode 100644 index 0000000000..db3a9c8ea8 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aria_ccm_hw.c @@ -0,0 +1,40 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * Generic support for ARIA CCM. + */ + +#include "cipher_aria_ccm.h" + +static int ccm_aria_initkey(PROV_CCM_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_ARIA_CCM_CTX *actx = (PROV_ARIA_CCM_CTX *)ctx; + + aria_set_encrypt_key(key, keylen * 8, &actx->ks.ks); + CRYPTO_ccm128_init(&ctx->ccm_ctx, ctx->m, ctx->l, &actx->ks.ks, + (block128_f)aria_encrypt); + ctx->str = NULL; + ctx->key_set = 1; + return 1; +} + +static const PROV_CCM_HW ccm_aria = { + ccm_aria_initkey, + ccm_generic_setiv, + ccm_generic_setaad, + ccm_generic_auth_encrypt, + ccm_generic_auth_decrypt, + ccm_generic_gettag +}; +const PROV_CCM_HW *PROV_ARIA_HW_ccm(size_t keybits) +{ + return &ccm_aria; +} diff --git a/providers/implementations/ciphers/cipher_aria_gcm.c b/providers/implementations/ciphers/cipher_aria_gcm.c new file mode 100644 index 0000000000..7c9fa3d211 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aria_gcm.c @@ -0,0 +1,38 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for ARIA GCM mode */ + +#include "cipher_aria_gcm.h" +#include "internal/provider_algs.h" + +static void *aria_gcm_newctx(void *provctx, size_t keybits) +{ + PROV_ARIA_GCM_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx != NULL) + gcm_initctx(provctx, &ctx->base, keybits, PROV_ARIA_HW_gcm(keybits), 4); + return ctx; +} + +static OSSL_OP_cipher_freectx_fn aria_gcm_freectx; +static void aria_gcm_freectx(void *vctx) +{ + PROV_ARIA_GCM_CTX *ctx = (PROV_ARIA_GCM_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +/* aria128gcm_functions */ +IMPLEMENT_aead_cipher(aria, gcm, GCM, AEAD_FLAGS, 128, 8, 96); +/* aria192gcm_functions */ +IMPLEMENT_aead_cipher(aria, gcm, GCM, AEAD_FLAGS, 192, 8, 96); +/* aria256gcm_functions */ +IMPLEMENT_aead_cipher(aria, gcm, GCM, AEAD_FLAGS, 256, 8, 96); + diff --git a/providers/implementations/ciphers/cipher_aria_gcm.h b/providers/implementations/ciphers/cipher_aria_gcm.h new file mode 100644 index 0000000000..13fbe175d9 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aria_gcm.h @@ -0,0 +1,22 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "crypto/aria.h" +#include "prov/ciphercommon.h" +#include "prov/cipher_gcm.h" + +typedef struct prov_aria_gcm_ctx_st { + PROV_GCM_CTX base; /* must be first entry in struct */ + union { + OSSL_UNION_ALIGN; + ARIA_KEY ks; + } ks; +} PROV_ARIA_GCM_CTX; + +const PROV_GCM_HW *PROV_ARIA_HW_gcm(size_t keybits); diff --git a/providers/implementations/ciphers/cipher_aria_gcm_hw.c b/providers/implementations/ciphers/cipher_aria_gcm_hw.c new file mode 100644 index 0000000000..ed1e1851dc --- /dev/null +++ b/providers/implementations/ciphers/cipher_aria_gcm_hw.c @@ -0,0 +1,50 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * Generic support for ARIA GCM. + */ + +#include "cipher_aria_gcm.h" + +static int aria_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_ARIA_GCM_CTX *actx = (PROV_ARIA_GCM_CTX *)ctx; + ARIA_KEY *ks = &actx->ks.ks; + + GCM_HW_SET_KEY_CTR_FN(ks, aria_set_encrypt_key, aria_encrypt, NULL); + return 1; +} + +static int aria_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in, + size_t len, unsigned char *out) +{ + if (ctx->enc) { + if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len)) + return 0; + } else { + if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len)) + return 0; + } + return 1; +} + +static const PROV_GCM_HW aria_gcm = { + aria_gcm_initkey, + gcm_setiv, + gcm_aad_update, + aria_cipher_update, + gcm_cipher_final, + gcm_one_shot +}; +const PROV_GCM_HW *PROV_ARIA_HW_gcm(size_t keybits) +{ + return &aria_gcm; +} diff --git a/providers/implementations/ciphers/cipher_aria_hw.c b/providers/implementations/ciphers/cipher_aria_hw.c new file mode 100644 index 0000000000..b644be8dda --- /dev/null +++ b/providers/implementations/ciphers/cipher_aria_hw.c @@ -0,0 +1,48 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_aria.h" + +static int cipher_hw_aria_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + int ret, mode = dat->mode; + PROV_ARIA_CTX *adat = (PROV_ARIA_CTX *)dat; + ARIA_KEY *ks = &adat->ks.ks; + + if (dat->enc || (mode != EVP_CIPH_ECB_MODE && mode != EVP_CIPH_CBC_MODE)) + ret = aria_set_encrypt_key(key, keylen * 8, ks); + else + ret = aria_set_decrypt_key(key, keylen * 8, ks); + if (ret < 0) { + ERR_raise(ERR_LIB_PROV, EVP_R_ARIA_KEY_SETUP_FAILED); + return 0; + } + dat->ks = ks; + dat->block = (block128_f)aria_encrypt; + return 1; +} + +# define PROV_CIPHER_HW_aria_mode(mode) \ +static const PROV_CIPHER_HW aria_##mode = { \ + cipher_hw_aria_initkey, \ + cipher_hw_chunked_##mode \ +}; \ +const PROV_CIPHER_HW *PROV_CIPHER_HW_aria_##mode(size_t keybits) \ +{ \ + return &aria_##mode; \ +} + +PROV_CIPHER_HW_aria_mode(cbc) +PROV_CIPHER_HW_aria_mode(ecb) +PROV_CIPHER_HW_aria_mode(ofb128) +PROV_CIPHER_HW_aria_mode(cfb128) +PROV_CIPHER_HW_aria_mode(cfb1) +PROV_CIPHER_HW_aria_mode(cfb8) +PROV_CIPHER_HW_aria_mode(ctr) diff --git a/providers/implementations/ciphers/cipher_blowfish.c b/providers/implementations/ciphers/cipher_blowfish.c new file mode 100644 index 0000000000..4730f1fd40 --- /dev/null +++ b/providers/implementations/ciphers/cipher_blowfish.c @@ -0,0 +1,48 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for Blowfish cipher modes ecb, cbc, ofb, cfb */ + +#include "cipher_blowfish.h" +#include "internal/provider_algs.h" + +#define BF_FLAGS (EVP_CIPH_VARIABLE_LENGTH) + +static OSSL_OP_cipher_freectx_fn blowfish_freectx; +static OSSL_OP_cipher_dupctx_fn blowfish_dupctx; + +static void blowfish_freectx(void *vctx) +{ + PROV_BLOWFISH_CTX *ctx = (PROV_BLOWFISH_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +static void *blowfish_dupctx(void *ctx) +{ + PROV_BLOWFISH_CTX *in = (PROV_BLOWFISH_CTX *)ctx; + PROV_BLOWFISH_CTX *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + *ret = *in; + + return ret; +} + +/* bf_ecb_functions */ +IMPLEMENT_generic_cipher(blowfish, BLOWFISH, ecb, ECB, BF_FLAGS, 128, 64, 0, block) +/* bf_cbc_functions */ +IMPLEMENT_generic_cipher(blowfish, BLOWFISH, cbc, CBC, BF_FLAGS, 128, 64, 64, block) +/* bf_ofb_functions */ +IMPLEMENT_generic_cipher(blowfish, BLOWFISH, ofb64, OFB, BF_FLAGS, 64, 8, 64, stream) +/* bf_cfb_functions */ +IMPLEMENT_generic_cipher(blowfish, BLOWFISH, cfb64, CFB, BF_FLAGS, 64, 8, 64, stream) diff --git a/providers/implementations/ciphers/cipher_blowfish.h b/providers/implementations/ciphers/cipher_blowfish.h new file mode 100644 index 0000000000..2d66d1bc0e --- /dev/null +++ b/providers/implementations/ciphers/cipher_blowfish.h @@ -0,0 +1,24 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/blowfish.h> +#include "prov/ciphercommon.h" + +typedef struct prov_blowfish_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + BF_KEY ks; + } ks; +} PROV_BLOWFISH_CTX; + +const PROV_CIPHER_HW *PROV_CIPHER_HW_blowfish_cbc(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_blowfish_ecb(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_blowfish_ofb64(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_blowfish_cfb64(size_t keybits); diff --git a/providers/implementations/ciphers/cipher_blowfish_hw.c b/providers/implementations/ciphers/cipher_blowfish_hw.c new file mode 100644 index 0000000000..137aeef5ca --- /dev/null +++ b/providers/implementations/ciphers/cipher_blowfish_hw.c @@ -0,0 +1,36 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_blowfish.h" + +static int cipher_hw_blowfish_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_BLOWFISH_CTX *bctx = (PROV_BLOWFISH_CTX *)ctx; + + BF_set_key(&bctx->ks.ks, keylen, key); + return 1; +} + +# define PROV_CIPHER_HW_blowfish_mode(mode, UCMODE) \ +IMPLEMENT_CIPHER_HW_##UCMODE(mode, blowfish, PROV_BLOWFISH_CTX, BF_KEY, \ + BF_##mode) \ +static const PROV_CIPHER_HW bf_##mode = { \ + cipher_hw_blowfish_initkey, \ + cipher_hw_blowfish_##mode##_cipher \ +}; \ +const PROV_CIPHER_HW *PROV_CIPHER_HW_blowfish_##mode(size_t keybits) \ +{ \ + return &bf_##mode; \ +} + +PROV_CIPHER_HW_blowfish_mode(cbc, CBC) +PROV_CIPHER_HW_blowfish_mode(ecb, ECB) +PROV_CIPHER_HW_blowfish_mode(ofb64, OFB) +PROV_CIPHER_HW_blowfish_mode(cfb64, CFB) diff --git a/providers/implementations/ciphers/cipher_camellia.c b/providers/implementations/ciphers/cipher_camellia.c new file mode 100644 index 0000000000..68c0e91355 --- /dev/null +++ b/providers/implementations/ciphers/cipher_camellia.c @@ -0,0 +1,81 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for CAMELLIA cipher modes ecb, cbc, ofb, cfb, ctr */ + +#include "cipher_camellia.h" +#include "internal/provider_algs.h" + +static OSSL_OP_cipher_freectx_fn camellia_freectx; +static OSSL_OP_cipher_dupctx_fn camellia_dupctx; + +static void camellia_freectx(void *vctx) +{ + PROV_CAMELLIA_CTX *ctx = (PROV_CAMELLIA_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +static void *camellia_dupctx(void *ctx) +{ + PROV_CAMELLIA_CTX *in = (PROV_CAMELLIA_CTX *)ctx; + PROV_CAMELLIA_CTX *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + *ret = *in; + + return ret; +} + +/* camellia256ecb_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, ecb, ECB, 0, 256, 128, 0, block) +/* camellia192ecb_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, ecb, ECB, 0, 192, 128, 0, block) +/* camellia128ecb_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, ecb, ECB, 0, 128, 128, 0, block) +/* camellia256cbc_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, cbc, CBC, 0, 256, 128, 128, block) +/* camellia192cbc_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, cbc, CBC, 0, 192, 128, 128, block) +/* camellia128cbc_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, cbc, CBC, 0, 128, 128, 128, block) +/* camellia256ofb_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, ofb, OFB, 0, 256, 8, 128, stream) +/* camellia192ofb_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, ofb, OFB, 0, 192, 8, 128, stream) +/* camellia128ofb_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, ofb, OFB, 0, 128, 8, 128, stream) +/* camellia256cfb_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb, CFB, 0, 256, 8, 128, stream) +/* camellia192cfb_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb, CFB, 0, 192, 8, 128, stream) +/* camellia128cfb_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb, CFB, 0, 128, 8, 128, stream) +/* camellia256cfb1_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb1, CFB, 0, 256, 8, 128, stream) +/* camellia192cfb1_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb1, CFB, 0, 192, 8, 128, stream) +/* camellia128cfb1_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb1, CFB, 0, 128, 8, 128, stream) +/* camellia256cfb8_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb8, CFB, 0, 256, 8, 128, stream) +/* camellia192cfb8_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb8, CFB, 0, 192, 8, 128, stream) +/* camellia128cfb8_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, cfb8, CFB, 0, 128, 8, 128, stream) +/* camellia256ctr_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, ctr, CTR, 0, 256, 8, 128, stream) +/* camellia192ctr_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, ctr, CTR, 0, 192, 8, 128, stream) +/* camellia128ctr_functions */ +IMPLEMENT_generic_cipher(camellia, CAMELLIA, ctr, CTR, 0, 128, 8, 128, stream) + diff --git a/providers/implementations/ciphers/cipher_camellia.h b/providers/implementations/ciphers/cipher_camellia.h new file mode 100644 index 0000000000..58636f1d32 --- /dev/null +++ b/providers/implementations/ciphers/cipher_camellia.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "openssl/camellia.h" +#include "prov/ciphercommon.h" + +typedef struct prov_camellia_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + CAMELLIA_KEY ks; + } ks; +} PROV_CAMELLIA_CTX; + +#define PROV_CIPHER_HW_camellia_ofb PROV_CIPHER_HW_camellia_ofb128 +#define PROV_CIPHER_HW_camellia_cfb PROV_CIPHER_HW_camellia_cfb128 +const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_ecb(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_cbc(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_ofb128(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_cfb128(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_cfb1(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_cfb8(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_ctr(size_t keybits); diff --git a/providers/implementations/ciphers/cipher_camellia_hw.c b/providers/implementations/ciphers/cipher_camellia_hw.c new file mode 100644 index 0000000000..39ba4bd0ac --- /dev/null +++ b/providers/implementations/ciphers/cipher_camellia_hw.c @@ -0,0 +1,64 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_camellia.h" +#include <openssl/camellia.h> + +static int cipher_hw_camellia_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, size_t keylen) +{ + int ret, mode = dat->mode; + PROV_CAMELLIA_CTX *adat = (PROV_CAMELLIA_CTX *)dat; + CAMELLIA_KEY *ks = &adat->ks.ks; + + dat->ks = ks; + ret = Camellia_set_key(key, keylen * 8, ks); + if (ret < 0) { + ERR_raise(ERR_LIB_PROV, EVP_R_ARIA_KEY_SETUP_FAILED); + return 0; + } + if (dat->enc || (mode != EVP_CIPH_ECB_MODE && mode != EVP_CIPH_CBC_MODE)) { + dat->block = (block128_f) Camellia_encrypt; + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) Camellia_cbc_encrypt : NULL; + } else { + dat->block = (block128_f) Camellia_decrypt; + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) Camellia_cbc_encrypt : NULL; + } + return 1; +} + +# if defined(SPARC_CMLL_CAPABLE) +# include "cipher_camellia_hw_t4.inc" +# else +/* The generic case */ +# define PROV_CIPHER_HW_declare(mode) +# define PROV_CIPHER_HW_select(mode) +# endif /* SPARC_CMLL_CAPABLE */ + +#define PROV_CIPHER_HW_camellia_mode(mode) \ +static const PROV_CIPHER_HW camellia_##mode = { \ + cipher_hw_camellia_initkey, \ + cipher_hw_generic_##mode \ +}; \ +PROV_CIPHER_HW_declare(mode) \ +const PROV_CIPHER_HW *PROV_CIPHER_HW_camellia_##mode(size_t keybits) \ +{ \ + PROV_CIPHER_HW_select(mode) \ + return &camellia_##mode; \ +} + +PROV_CIPHER_HW_camellia_mode(cbc) +PROV_CIPHER_HW_camellia_mode(ecb) +PROV_CIPHER_HW_camellia_mode(ofb128) +PROV_CIPHER_HW_camellia_mode(cfb128) +PROV_CIPHER_HW_camellia_mode(cfb1) +PROV_CIPHER_HW_camellia_mode(cfb8) +PROV_CIPHER_HW_camellia_mode(ctr) diff --git a/providers/implementations/ciphers/cipher_camellia_hw_t4.inc b/providers/implementations/ciphers/cipher_camellia_hw_t4.inc new file mode 100644 index 0000000000..24e104646b --- /dev/null +++ b/providers/implementations/ciphers/cipher_camellia_hw_t4.inc @@ -0,0 +1,83 @@ +/* + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * Fujitsu SPARC64 X support for camellia modes. + * This file is included by cipher_camellia_hw.c + */ + +static int cipher_hw_camellia_t4_initkey(PROV_CIPHER_CTX *dat, + const unsigned char *key, + size_t keylen) +{ + int ret = 0, bits, mode = dat->mode; + PROV_CAMELLIA_CTX *adat = (PROV_CAMELLIA_CTX *)dat; + CAMELLIA_KEY *ks = &adat->ks.ks; + + dat->ks = ks; + bits = keylen * 8; + + cmll_t4_set_key(key, bits, ks); + + if (dat->enc || (mode != EVP_CIPH_ECB_MODE && mode != EVP_CIPH_CBC_MODE)) { + dat->block = (block128_f) cmll_t4_encrypt; + switch (bits) { + case 128: + if (mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) cmll128_t4_cbc_encrypt; + else if (mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f) cmll128_t4_ctr32_encrypt; + else + dat->stream.cbc = NULL; + break; + case 192: + case 256: + if (mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) cmll256_t4_cbc_encrypt; + else if (mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f) cmll256_t4_ctr32_encrypt; + else + dat->stream.cbc = NULL; + break; + default: + ret = -1; + break; + } + } else { + dat->block = (block128_f) cmll_t4_decrypt; + switch (bits) { + case 128: + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) cmll128_t4_cbc_decrypt : NULL; + break; + case 192: + case 256: + dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? + (cbc128_f) cmll256_t4_cbc_decrypt : NULL; + break; + default: + ret = -1; + break; + } + } + if (ret < 0) { + ERR_raise(ERR_LIB_PROV, EVP_R_CAMELLIA_KEY_SETUP_FAILED); + return 0; + } + return 1; +} + +#define PROV_CIPHER_HW_declare(mode) \ +static const PROV_CIPHER_HW t4_camellia_##mode = { \ + cipher_hw_camellia_t4_initkey, \ + cipher_hw_generic_##mode \ +}; +#define PROV_CIPHER_HW_select(mode) \ +if (SPARC_CMLL_CAPABLE) \ + return &t4_camellia_##mode; diff --git a/providers/implementations/ciphers/cipher_cast.h b/providers/implementations/ciphers/cipher_cast.h new file mode 100644 index 0000000000..218f5c4fb5 --- /dev/null +++ b/providers/implementations/ciphers/cipher_cast.h @@ -0,0 +1,24 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/cast.h> +#include "prov/ciphercommon.h" + +typedef struct prov_cast_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + CAST_KEY ks; + } ks; +} PROV_CAST_CTX; + +const PROV_CIPHER_HW *PROV_CIPHER_HW_cast5_cbc(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_cast5_ecb(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_cast5_ofb64(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_cast5_cfb64(size_t keybits); diff --git a/providers/implementations/ciphers/cipher_cast5.c b/providers/implementations/ciphers/cipher_cast5.c new file mode 100644 index 0000000000..eb79aad820 --- /dev/null +++ b/providers/implementations/ciphers/cipher_cast5.c @@ -0,0 +1,48 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for cast cipher modes ecb, cbc, ofb, cfb */ + +#include "cipher_cast.h" +#include "internal/provider_algs.h" + +#define CAST5_FLAGS (EVP_CIPH_VARIABLE_LENGTH) + +static OSSL_OP_cipher_freectx_fn cast5_freectx; +static OSSL_OP_cipher_dupctx_fn cast5_dupctx; + +static void cast5_freectx(void *vctx) +{ + PROV_CAST_CTX *ctx = (PROV_CAST_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +static void *cast5_dupctx(void *ctx) +{ + PROV_CAST_CTX *in = (PROV_CAST_CTX *)ctx; + PROV_CAST_CTX *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + *ret = *in; + + return ret; +} + +/* cast5128ecb_functions */ +IMPLEMENT_generic_cipher(cast5, CAST, ecb, ECB, CAST5_FLAGS, 128, 64, 0, block) +/* cast5128cbc_functions */ +IMPLEMENT_generic_cipher(cast5, CAST, cbc, CBC, CAST5_FLAGS, 128, 64, 64, block) +/* cast564ofb64_functions */ +IMPLEMENT_generic_cipher(cast5, CAST, ofb64, OFB, CAST5_FLAGS, 64, 8, 64, stream) +/* cast564cfb64_functions */ +IMPLEMENT_generic_cipher(cast5, CAST, cfb64, CFB, CAST5_FLAGS, 64, 8, 64, stream) diff --git a/providers/implementations/ciphers/cipher_cast5_hw.c b/providers/implementations/ciphers/cipher_cast5_hw.c new file mode 100644 index 0000000000..227e90d7a7 --- /dev/null +++ b/providers/implementations/ciphers/cipher_cast5_hw.c @@ -0,0 +1,36 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_cast.h" + +static int cipher_hw_cast5_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_CAST_CTX *bctx = (PROV_CAST_CTX *)ctx; + + CAST_set_key(&(bctx->ks.ks), keylen, key); + return 1; +} + +# define PROV_CIPHER_HW_cast_mode(mode, UCMODE) \ +IMPLEMENT_CIPHER_HW_##UCMODE(mode, cast5, PROV_CAST_CTX, CAST_KEY, \ + CAST_##mode) \ +static const PROV_CIPHER_HW cast5_##mode = { \ + cipher_hw_cast5_initkey, \ + cipher_hw_cast5_##mode##_cipher \ +}; \ +const PROV_CIPHER_HW *PROV_CIPHER_HW_cast5_##mode(size_t keybits) \ +{ \ + return &cast5_##mode; \ +} + +PROV_CIPHER_HW_cast_mode(cbc, CBC) +PROV_CIPHER_HW_cast_mode(ecb, ECB) +PROV_CIPHER_HW_cast_mode(ofb64, OFB) +PROV_CIPHER_HW_cast_mode(cfb64, CFB) diff --git a/providers/implementations/ciphers/cipher_des.c b/providers/implementations/ciphers/cipher_des.c new file mode 100644 index 0000000000..5781aa4706 --- /dev/null +++ b/providers/implementations/ciphers/cipher_des.c @@ -0,0 +1,160 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "prov/ciphercommon.h" +#include "cipher_des.h" +#include "crypto/rand.h" +#include "internal/provider_algs.h" +#include "internal/providercommonerr.h" + +/* TODO(3.0) Figure out what flags need to be here */ +#define DES_FLAGS (EVP_CIPH_RAND_KEY) + +static OSSL_OP_cipher_freectx_fn des_freectx; +static OSSL_OP_cipher_encrypt_init_fn des_einit; +static OSSL_OP_cipher_decrypt_init_fn des_dinit; +static OSSL_OP_cipher_get_ctx_params_fn des_get_ctx_params; +static OSSL_OP_cipher_gettable_ctx_params_fn des_gettable_ctx_params; + +static void *des_newctx(void *provctx, size_t kbits, size_t blkbits, + size_t ivbits, unsigned int mode, uint64_t flags, + const PROV_CIPHER_HW *hw) +{ + PROV_DES_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx != NULL) + cipher_generic_initkey(ctx, kbits, blkbits, ivbits, mode, flags, hw, + provctx); + return ctx; +} + +static void des_freectx(void *vctx) +{ + PROV_DES_CTX *ctx = (PROV_DES_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +static int des_init(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen, int enc) +{ + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + + ctx->enc = enc; + + if (iv != NULL) { + if (!cipher_generic_initiv(ctx, iv, ivlen)) + return 0; + } + + if (key != NULL) { + if (keylen != ctx->keylen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN); + return 0; + } + return ctx->hw->init(ctx, key, keylen); + } + return 1; +} + +static int des_einit(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + return des_init(vctx, key, keylen, iv, ivlen, 1); +} + +static int des_dinit(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + return des_init(vctx, key, keylen, iv, ivlen, 0); +} + +static int des_generatekey(PROV_CIPHER_CTX *ctx, void *ptr) +{ + + DES_cblock *deskey = ptr; + size_t kl = ctx->keylen; + + if (kl == 0 || rand_priv_bytes_ex(ctx->libctx, ptr, kl) <= 0) + return 0; + DES_set_odd_parity(deskey); + return 1; +} + +CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(des) + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_RANDOM_KEY, NULL, 0), +CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(des) + +static int des_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + OSSL_PARAM *p; + + if (!cipher_generic_get_ctx_params(vctx, params)) + return 0; + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_RANDOM_KEY); + if (p != NULL && !des_generatekey(ctx, p->data)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GENERATE_KEY); + return 0; + } + return 1; +} + +#define IMPLEMENT_des_cipher(type, lcmode, UCMODE, flags, \ + kbits, blkbits, ivbits, block) \ +static OSSL_OP_cipher_newctx_fn type##_##lcmode##_newctx; \ +static void *des_##lcmode##_newctx(void *provctx) \ +{ \ + return des_newctx(provctx, kbits, blkbits, ivbits, \ + EVP_CIPH_##UCMODE##_MODE, flags, \ + PROV_CIPHER_HW_des_##lcmode()); \ +} \ +static OSSL_OP_cipher_get_params_fn des_##lcmode##_get_params; \ +static int des_##lcmode##_get_params(OSSL_PARAM params[]) \ +{ \ + return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, flags, \ + kbits, blkbits, ivbits); \ +} \ +const OSSL_DISPATCH des_##lcmode##_functions[] = { \ + { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))des_einit }, \ + { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))des_dinit }, \ + { OSSL_FUNC_CIPHER_UPDATE, \ + (void (*)(void))cipher_generic_##block##_update }, \ + { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))cipher_generic_##block##_final },\ + { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))cipher_generic_cipher }, \ + { OSSL_FUNC_CIPHER_NEWCTX, \ + (void (*)(void))des_##lcmode##_newctx }, \ + { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))des_freectx }, \ + { OSSL_FUNC_CIPHER_GET_PARAMS, \ + (void (*)(void))des_##lcmode##_get_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ + (void (*)(void))cipher_generic_gettable_params }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))des_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ + (void (*)(void))des_gettable_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ + (void (*)(void))cipher_generic_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ + (void (*)(void))cipher_generic_settable_ctx_params }, \ + { 0, NULL } \ +} + +/* des_ecb_functions */ +IMPLEMENT_des_cipher(des, ecb, ECB, DES_FLAGS, 64, 64, 0, block); +/* des_cbc_functions */ +IMPLEMENT_des_cipher(des, cbc, CBC, DES_FLAGS, 64, 64, 64, block); +/* des_ofb64_functions */ +IMPLEMENT_des_cipher(des, ofb64, OFB, DES_FLAGS, 64, 8, 64, stream); +/* des_cfb64_functions */ +IMPLEMENT_des_cipher(des, cfb64, CFB, DES_FLAGS, 64, 8, 64, stream); +/* des_cfb1_functions */ +IMPLEMENT_des_cipher(des, cfb1, CFB, DES_FLAGS, 64, 8, 64, stream); +/* des_cfb8_functions */ +IMPLEMENT_des_cipher(des, cfb8, CFB, DES_FLAGS, 64, 8, 64, stream); diff --git a/providers/implementations/ciphers/cipher_des.h b/providers/implementations/ciphers/cipher_des.h new file mode 100644 index 0000000000..92dcfa11e9 --- /dev/null +++ b/providers/implementations/ciphers/cipher_des.h @@ -0,0 +1,33 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/des.h> + +/* TODO(3.0) Figure out what flags need to be here */ +#define TDES_FLAGS (EVP_CIPH_RAND_KEY) + +typedef struct prov_des_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + DES_key_schedule ks; + } dks; + union { + void (*cbc) (const void *, void *, size_t, + const DES_key_schedule *, unsigned char *); + } dstream; + +} PROV_DES_CTX; + +const PROV_CIPHER_HW *PROV_CIPHER_HW_des_cbc(void); +const PROV_CIPHER_HW *PROV_CIPHER_HW_des_ecb(void); +const PROV_CIPHER_HW *PROV_CIPHER_HW_des_ofb64(void); +const PROV_CIPHER_HW *PROV_CIPHER_HW_des_cfb64(void); +const PROV_CIPHER_HW *PROV_CIPHER_HW_des_cfb1(void); +const PROV_CIPHER_HW *PROV_CIPHER_HW_des_cfb8(void); diff --git a/providers/implementations/ciphers/cipher_des_hw.c b/providers/implementations/ciphers/cipher_des_hw.c new file mode 100644 index 0000000000..c3a67080fd --- /dev/null +++ b/providers/implementations/ciphers/cipher_des_hw.c @@ -0,0 +1,173 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "prov/ciphercommon.h" +#include "cipher_des.h" + +static int cipher_hw_des_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_DES_CTX *dctx = (PROV_DES_CTX *)ctx; + DES_cblock *deskey = (DES_cblock *)key; + DES_key_schedule *ks = &dctx->dks.ks; + + dctx->dstream.cbc = NULL; +#if defined(SPARC_DES_CAPABLE) + if (SPARC_DES_CAPABLE) { + if (ctx->mode == EVP_CIPH_CBC_MODE) { + des_t4_key_expand(&deskey[0], ks); + dctx->dstream.cbc = ctx->enc ? des_t4_cbc_encrypt : + des_t4_cbc_decrypt; + return 1; + } + } +#endif + DES_set_key_unchecked(deskey, ks); + return 1; +} + +static int cipher_hw_des_ecb_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + size_t i, bl = ctx->blocksize; + DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks); + + if (len < bl) + return 1; + for (i = 0, len -= bl; i <= len; i += bl) + DES_ecb_encrypt((const_DES_cblock *)(in + i), + (const_DES_cblock *)(out + i), key, ctx->enc); + return 1; +} + +static int cipher_hw_des_cbc_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks); + + while (len >= MAXCHUNK) { + DES_ncbc_encrypt(in, out, MAXCHUNK, key, (DES_cblock *)ctx->iv, + ctx->enc); + len -= MAXCHUNK; + in += MAXCHUNK; + out += MAXCHUNK; + } + if (len > 0) + DES_ncbc_encrypt(in, out, (long)len, key, (DES_cblock *)ctx->iv, + ctx->enc); + return 1; +} + +static int cipher_hw_des_ofb64_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + int num = ctx->num; + DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks); + + while (len >= MAXCHUNK) { + DES_ofb64_encrypt(in, out, MAXCHUNK, key, (DES_cblock *)ctx->iv, &num); + len -= MAXCHUNK; + in += MAXCHUNK; + out += MAXCHUNK; + } + if (len > 0) { + DES_ofb64_encrypt(in, out, (long)len, key, (DES_cblock *)ctx->iv, &num); + } + ctx->num = num; + return 1; +} + +static int cipher_hw_des_cfb64_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + size_t chunk = MAXCHUNK; + DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks); + int num = ctx->num; + + if (len < chunk) + chunk = len; + while (len > 0 && len >= chunk) { + DES_cfb64_encrypt(in, out, (long)chunk, key, (DES_cblock *)ctx->iv, + &num, ctx->enc); + len -= chunk; + in += chunk; + out += chunk; + if (len < chunk) + chunk = len; + } + ctx->num = num; + return 1; +} + +/* + * Although we have a CFB-r implementation for DES, it doesn't pack the right + * way, so wrap it here + */ +static int cipher_hw_des_cfb1_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + size_t n, chunk = MAXCHUNK / 8; + DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks); + unsigned char c[1], d[1]; + + if (inl < chunk) + chunk = inl; + + while (inl && inl >= chunk) { + for (n = 0; n < chunk * 8; ++n) { + c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0; + DES_cfb_encrypt(c, d, 1, 1, key, (DES_cblock *)ctx->iv, ctx->enc); + out[n / 8] = + (out[n / 8] & ~(0x80 >> (unsigned int)(n % 8))) | + ((d[0] & 0x80) >> (unsigned int)(n % 8)); + } + inl -= chunk; + in += chunk; + out += chunk; + if (inl < chunk) + chunk = inl; + } + + return 1; +} + +static int cipher_hw_des_cfb8_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + DES_key_schedule *key = &(((PROV_DES_CTX *)ctx)->dks.ks); + + while (inl >= MAXCHUNK) { + DES_cfb_encrypt(in, out, 8, (long)MAXCHUNK, key, + (DES_cblock *)ctx->iv, ctx->enc); + inl -= MAXCHUNK; + in += MAXCHUNK; + out += MAXCHUNK; + } + if (inl > 0) + DES_cfb_encrypt(in, out, 8, (long)inl, key, + (DES_cblock *)ctx->iv, ctx->enc); + return 1; +} + +#define PROV_CIPHER_HW_des_mode(mode) \ +static const PROV_CIPHER_HW des_##mode = { \ + cipher_hw_des_initkey, \ + cipher_hw_des_##mode##_cipher \ +}; \ +const PROV_CIPHER_HW *PROV_CIPHER_HW_des_##mode(void) \ +{ \ + return &des_##mode; \ +} + +PROV_CIPHER_HW_des_mode(ecb) +PROV_CIPHER_HW_des_mode(cbc) +PROV_CIPHER_HW_des_mode(ofb64) +PROV_CIPHER_HW_des_mode(cfb64) +PROV_CIPHER_HW_des_mode(cfb1) +PROV_CIPHER_HW_des_mode(cfb8) diff --git a/providers/implementations/ciphers/cipher_desx.c b/providers/implementations/ciphers/cipher_desx.c new file mode 100644 index 0000000000..4a232cd080 --- /dev/null +++ b/providers/implementations/ciphers/cipher_desx.c @@ -0,0 +1,15 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_tdes_default.h" +#include "internal/provider_algs.h" + +/* desx_cbc_functions */ +IMPLEMENT_tdes_cipher(desx, DESX, cbc, CBC, TDES_FLAGS, 64*3, 64, 64, block); + diff --git a/providers/implementations/ciphers/cipher_desx_hw.c b/providers/implementations/ciphers/cipher_desx_hw.c new file mode 100644 index 0000000000..ef1b3b0694 --- /dev/null +++ b/providers/implementations/ciphers/cipher_desx_hw.c @@ -0,0 +1,62 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/des.h> +#include "cipher_tdes_default.h" + +/* + * Note the PROV_TDES_CTX has been used for the DESX cipher, just to reduce + * code size. + */ +#define ks1 tks.ks[0] +#define ks2 tks.ks[1].ks[0].cblock +#define ks3 tks.ks[2].ks[0].cblock + +static int cipher_hw_desx_cbc_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx; + DES_cblock *deskey = (DES_cblock *)key; + + DES_set_key_unchecked(deskey, &tctx->ks1); + memcpy(&tctx->ks2, &key[8], 8); + memcpy(&tctx->ks3, &key[16], 8); + + return 1; +} + +static int cipher_hw_desx_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx; + + while (inl >= MAXCHUNK) { + DES_xcbc_encrypt(in, out, (long)MAXCHUNK, &tctx->ks1, + (DES_cblock *)ctx->iv, &tctx->ks2, &tctx->ks3, + ctx->enc); + inl -= MAXCHUNK; + in += MAXCHUNK; + out += MAXCHUNK; + } + if (inl > 0) + DES_xcbc_encrypt(in, out, (long)inl, &tctx->ks1, + (DES_cblock *)ctx->iv, &tctx->ks2, &tctx->ks3, + ctx->enc); + return 1; +} + +static const PROV_CIPHER_HW desx_cbc = +{ + cipher_hw_desx_cbc_initkey, + cipher_hw_desx_cbc +}; +const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_desx_cbc(void) +{ + return &desx_cbc; +} diff --git a/providers/implementations/ciphers/cipher_idea.c b/providers/implementations/ciphers/cipher_idea.c new file mode 100644 index 0000000000..6bb5419b6d --- /dev/null +++ b/providers/implementations/ciphers/cipher_idea.c @@ -0,0 +1,46 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for Idea cipher modes ecb, cbc, ofb, cfb */ + +#include "cipher_idea.h" +#include "internal/provider_algs.h" + +static OSSL_OP_cipher_freectx_fn idea_freectx; +static OSSL_OP_cipher_dupctx_fn idea_dupctx; + +static void idea_freectx(void *vctx) +{ + PROV_IDEA_CTX *ctx = (PROV_IDEA_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +static void *idea_dupctx(void *ctx) +{ + PROV_IDEA_CTX *in = (PROV_IDEA_CTX *)ctx; + PROV_IDEA_CTX *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + *ret = *in; + + return ret; +} + +/* idea128ecb_functions */ +IMPLEMENT_generic_cipher(idea, IDEA, ecb, ECB, 0, 128, 64, 0, block) +/* idea128cbc_functions */ +IMPLEMENT_generic_cipher(idea, IDEA, cbc, CBC, 0, 128, 64, 64, block) +/* idea128ofb64_functions */ +IMPLEMENT_generic_cipher(idea, IDEA, ofb64, OFB, 0, 128, 8, 64, stream) +/* idea128cfb64_functions */ +IMPLEMENT_generic_cipher(idea, IDEA, cfb64, CFB, 0, 128, 8, 64, stream) diff --git a/providers/implementations/ciphers/cipher_idea.h b/providers/implementations/ciphers/cipher_idea.h new file mode 100644 index 0000000000..ebe590b93c --- /dev/null +++ b/providers/implementations/ciphers/cipher_idea.h @@ -0,0 +1,24 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/idea.h> +#include "prov/ciphercommon.h" + +typedef struct prov_idea_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + IDEA_KEY_SCHEDULE ks; + } ks; +} PROV_IDEA_CTX; + +const PROV_CIPHER_HW *PROV_CIPHER_HW_idea_cbc(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_idea_ecb(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_idea_ofb64(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_idea_cfb64(size_t keybits); diff --git a/providers/implementations/ciphers/cipher_idea_hw.c b/providers/implementations/ciphers/cipher_idea_hw.c new file mode 100644 index 0000000000..d722cc7a27 --- /dev/null +++ b/providers/implementations/ciphers/cipher_idea_hw.c @@ -0,0 +1,56 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_idea.h" + +static int cipher_hw_idea_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_IDEA_CTX *ictx = (PROV_IDEA_CTX *)ctx; + IDEA_KEY_SCHEDULE *ks = &(ictx->ks.ks); + + if (ctx->enc + || ctx->mode == EVP_CIPH_OFB_MODE + || ctx->mode == EVP_CIPH_CFB_MODE) { + IDEA_set_encrypt_key(key, ks); + } else { + IDEA_KEY_SCHEDULE tmp; + + IDEA_set_encrypt_key(key, &tmp); + IDEA_set_decrypt_key(&tmp, ks); + OPENSSL_cleanse((unsigned char *)&tmp, sizeof(IDEA_KEY_SCHEDULE)); + } + return 1; +} + +# define PROV_CIPHER_HW_idea_mode_ex(mode, UCMODE, fname) \ +IMPLEMENT_CIPHER_HW_##UCMODE(mode, idea, PROV_IDEA_CTX, IDEA_KEY_SCHEDULE, \ + fname) \ +static const PROV_CIPHER_HW idea_##mode = { \ + cipher_hw_idea_initkey, \ + cipher_hw_idea_##mode##_cipher \ +}; \ +const PROV_CIPHER_HW *PROV_CIPHER_HW_idea_##mode(size_t keybits) \ +{ \ + return &idea_##mode; \ +} + +# define PROV_CIPHER_HW_idea_mode(mode, UCMODE) \ + PROV_CIPHER_HW_idea_mode_ex(mode, UCMODE, IDEA_##mode) + +PROV_CIPHER_HW_idea_mode(cbc, CBC) +PROV_CIPHER_HW_idea_mode(ofb64, OFB) +PROV_CIPHER_HW_idea_mode(cfb64, CFB) +/* + * IDEA_ecb_encrypt() does not have a enc parameter - so we create a macro + * that ignores this parameter when IMPLEMENT_CIPHER_HW_ecb() is called. + */ +#define IDEA2_ecb_encrypt(in, out, ks, enc) IDEA_ecb_encrypt(in, out, ks) + +PROV_CIPHER_HW_idea_mode_ex(ecb, ECB, IDEA2_ecb) diff --git a/providers/implementations/ciphers/cipher_rc2.c b/providers/implementations/ciphers/cipher_rc2.c new file mode 100644 index 0000000000..f7ee268276 --- /dev/null +++ b/providers/implementations/ciphers/cipher_rc2.c @@ -0,0 +1,239 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for RC2 cipher modes ecb, cbc, ofb, cfb */ + +#include "cipher_rc2.h" +#include "internal/provider_algs.h" +#include "internal/providercommonerr.h" + +#define RC2_40_MAGIC 0xa0 +#define RC2_64_MAGIC 0x78 +#define RC2_128_MAGIC 0x3a + +static OSSL_OP_cipher_freectx_fn rc2_freectx; +static OSSL_OP_cipher_dupctx_fn rc2_dupctx; +static OSSL_OP_cipher_gettable_ctx_params_fn rc2_gettable_ctx_params; +static OSSL_OP_cipher_settable_ctx_params_fn rc2_settable_ctx_params; + +static void rc2_freectx(void *vctx) +{ + PROV_RC2_CTX *ctx = (PROV_RC2_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +static void *rc2_dupctx(void *ctx) +{ + PROV_RC2_CTX *in = (PROV_RC2_CTX *)ctx; + PROV_RC2_CTX *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + *ret = *in; + + return ret; +} + +static int rc2_keybits_to_magic(int keybits) +{ + switch (keybits) { + case 128: + return RC2_128_MAGIC; + case 64: + return RC2_64_MAGIC; + case 40: + return RC2_40_MAGIC; + } + ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_KEY_SIZE); + return 0; +} + +static int rc2_magic_to_keybits(int magic) +{ + switch (magic) { + case RC2_128_MAGIC: + return 128; + case RC2_64_MAGIC: + return 64; + case RC2_40_MAGIC: + return 40; + } + ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_KEY_SIZE); + return 0; +} + +static int rc2_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + PROV_RC2_CTX *ctx = (PROV_RC2_CTX *)vctx; + OSSL_PARAM *p; + + if (!cipher_generic_get_ctx_params(vctx, params)) + return 0; + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_RC2_KEYBITS); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->key_bits)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_ALG_ID); + if (p != NULL) { + long num; + int i; + ASN1_TYPE *type; + unsigned char *d = p->data; + unsigned char **dd = d == NULL ? NULL : &d; + + if (p->data_type != OSSL_PARAM_OCTET_STRING) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + if ((type = ASN1_TYPE_new()) == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return 0; + } + + /* Is this the original IV or the running IV? */ + num = rc2_keybits_to_magic(ctx->key_bits); + if (!ASN1_TYPE_set_int_octetstring(type, num, + ctx->base.iv, ctx->base.ivlen)) { + ASN1_TYPE_free(type); + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return 0; + } + /* + * IF the caller has a buffer, we pray to the gods they got the + * size right. There's no way to tell the i2d functions... + */ + i = i2d_ASN1_TYPE(type, dd); + if (i >= 0) + p->return_size = (size_t)i; + + ASN1_TYPE_free(type); + if (i < 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + } + return 1; +} + +static int rc2_set_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + PROV_RC2_CTX *ctx = (PROV_RC2_CTX *)vctx; + const OSSL_PARAM *p; + + if (!cipher_generic_set_ctx_params(vctx, params)) + return 0; + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_RC2_KEYBITS); + if (p != NULL) { + if (!OSSL_PARAM_get_size_t(p, &ctx->key_bits)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_ALG_ID); + if (p != NULL) { + ASN1_TYPE *type = NULL; + long num = 0; + const unsigned char *d = p->data; + int ret = 1; + unsigned char iv[16]; + + if (p->data_type != OSSL_PARAM_OCTET_STRING + || ctx->base.ivlen > sizeof(iv) + || (type = d2i_ASN1_TYPE(NULL, &d, p->data_size)) == NULL + || ((size_t)ASN1_TYPE_get_int_octetstring(type, &num, iv, + ctx->base.ivlen) + != ctx->base.ivlen) + || !cipher_generic_initiv(&ctx->base, iv, ctx->base.ivlen) + || (ctx->key_bits = rc2_magic_to_keybits(num)) == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + ret = 0; + } + ASN1_TYPE_free(type); + if (ret == 0) + return 0; + /* + * This code assumes that the caller will call + * EVP_CipherInit_ex() with a non NULL key in order to setup a key that + * uses the keylen and keybits that were set here. + */ + ctx->base.keylen = ctx->key_bits / 8; + } + return 1; +} + +CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(rc2) +OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_RC2_KEYBITS, NULL), +CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(rc2) + +CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(rc2) +OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_RC2_KEYBITS, NULL), +CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(rc2) + +#define IMPLEMENT_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, blkbits, \ + ivbits, typ) \ +static OSSL_OP_cipher_get_params_fn alg##_##kbits##_##lcmode##_get_params; \ +static int alg##_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \ +{ \ + return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, flags, \ + kbits, blkbits, ivbits); \ +} \ +static OSSL_OP_cipher_newctx_fn alg##_##kbits##_##lcmode##_newctx; \ +static void * alg##_##kbits##_##lcmode##_newctx(void *provctx) \ +{ \ + PROV_##UCALG##_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); \ + if (ctx != NULL) { \ + cipher_generic_initkey(ctx, kbits, blkbits, ivbits, \ + EVP_CIPH_##UCMODE##_MODE, flags, \ + PROV_CIPHER_HW_##alg##_##lcmode(kbits), NULL); \ + ctx->key_bits = kbits; \ + } \ + return ctx; \ +} \ +const OSSL_DISPATCH alg##kbits##lcmode##_functions[] = { \ + { OSSL_FUNC_CIPHER_NEWCTX, \ + (void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \ + { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \ + { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \ + { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))cipher_generic_einit }, \ + { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))cipher_generic_dinit }, \ + { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))cipher_generic_##typ##_update },\ + { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))cipher_generic_##typ##_final }, \ + { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))cipher_generic_cipher }, \ + { OSSL_FUNC_CIPHER_GET_PARAMS, \ + (void (*)(void)) alg##_##kbits##_##lcmode##_get_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ + (void (*)(void))cipher_generic_gettable_params }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ + (void (*)(void))rc2_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ + (void (*)(void))rc2_gettable_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ + (void (*)(void))rc2_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ + (void (*)(void))rc2_settable_ctx_params }, \ + { 0, NULL } \ +}; + +/* rc2128ecb_functions */ +IMPLEMENT_cipher(rc2, RC2, ecb, ECB, EVP_CIPH_VARIABLE_LENGTH, 128, 64, 0, block) +/* rc2128cbc_functions */ +IMPLEMENT_cipher(rc2, RC2, cbc, CBC, EVP_CIPH_VARIABLE_LENGTH, 128, 64, 64, block) +/* rc240cbc_functions */ +IMPLEMENT_cipher(rc2, RC2, cbc, CBC, EVP_CIPH_VARIABLE_LENGTH, 40, 64, 64, block) +/* rc264cbc_functions */ +IMPLEMENT_cipher(rc2, RC2, cbc, CBC, EVP_CIPH_VARIABLE_LENGTH, 64, 64, 64, block) + +/* rc2128ofb128_functions */ +IMPLEMENT_cipher(rc2, RC2, ofb128, OFB, EVP_CIPH_VARIABLE_LENGTH, 128, 8, 64, stream) +/* rc2128cfb128_functions */ +IMPLEMENT_cipher(rc2, RC2, cfb128, CFB, EVP_CIPH_VARIABLE_LENGTH, 128, 8, 64, stream) diff --git a/providers/implementations/ciphers/cipher_rc2.h b/providers/implementations/ciphers/cipher_rc2.h new file mode 100644 index 0000000000..82f0f6ca74 --- /dev/null +++ b/providers/implementations/ciphers/cipher_rc2.h @@ -0,0 +1,28 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/rc2.h> +#include "prov/ciphercommon.h" + +typedef struct prov_rc2_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + RC2_KEY ks; + } ks; + size_t key_bits; +} PROV_RC2_CTX; + +#define PROV_CIPHER_HW_rc2_ofb128 PROV_CIPHER_HW_rc2_ofb64 +#define PROV_CIPHER_HW_rc2_cfb128 PROV_CIPHER_HW_rc2_cfb64 + +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc2_cbc(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc2_ecb(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc2_ofb64(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc2_cfb64(size_t keybits); diff --git a/providers/implementations/ciphers/cipher_rc2_hw.c b/providers/implementations/ciphers/cipher_rc2_hw.c new file mode 100644 index 0000000000..83d7560d41 --- /dev/null +++ b/providers/implementations/ciphers/cipher_rc2_hw.c @@ -0,0 +1,37 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_rc2.h" + +static int cipher_hw_rc2_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_RC2_CTX *rctx = (PROV_RC2_CTX *)ctx; + RC2_KEY *ks = &(rctx->ks.ks); + + RC2_set_key(ks, (int)ctx->keylen, key, (int)rctx->key_bits); + return 1; +} + +# define PROV_CIPHER_HW_rc2_mode(mode, UCMODE) \ +IMPLEMENT_CIPHER_HW_##UCMODE(mode, rc2, PROV_RC2_CTX, RC2_KEY, \ + RC2_##mode) \ +static const PROV_CIPHER_HW rc2_##mode = { \ + cipher_hw_rc2_initkey, \ + cipher_hw_rc2_##mode##_cipher \ +}; \ +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc2_##mode(size_t keybits) \ +{ \ + return &rc2_##mode; \ +} + +PROV_CIPHER_HW_rc2_mode(cbc, CBC) +PROV_CIPHER_HW_rc2_mode(ecb, ECB) +PROV_CIPHER_HW_rc2_mode(ofb64, OFB) +PROV_CIPHER_HW_rc2_mode(cfb64, CFB) diff --git a/providers/implementations/ciphers/cipher_rc4.c b/providers/implementations/ciphers/cipher_rc4.c new file mode 100644 index 0000000000..d81b776bc2 --- /dev/null +++ b/providers/implementations/ciphers/cipher_rc4.c @@ -0,0 +1,87 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for RC4 ciphers */ + +#include "cipher_rc4.h" +#include "internal/provider_algs.h" + +/* TODO (3.0) Figure out what flags are required */ +#define RC4_FLAGS EVP_CIPH_FLAG_DEFAULT_ASN1 + +static OSSL_OP_cipher_freectx_fn rc4_freectx; +static OSSL_OP_cipher_dupctx_fn rc4_dupctx; + +static void rc4_freectx(void *vctx) +{ + PROV_RC4_CTX *ctx = (PROV_RC4_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +static void *rc4_dupctx(void *ctx) +{ + PROV_RC4_CTX *in = (PROV_RC4_CTX *)ctx; + PROV_RC4_CTX *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + *ret = *in; + + return ret; +} + +#define IMPLEMENT_cipher(alg, UCALG, flags, kbits, blkbits, ivbits, typ) \ +static OSSL_OP_cipher_get_params_fn alg##_##kbits##_get_params; \ +static int alg##_##kbits##_get_params(OSSL_PARAM params[]) \ +{ \ + return cipher_generic_get_params(params, 0, flags, \ + kbits, blkbits, ivbits); \ +} \ +static OSSL_OP_cipher_newctx_fn alg##_##kbits##_newctx; \ +static void * alg##_##kbits##_newctx(void *provctx) \ +{ \ + PROV_##UCALG##_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); \ + if (ctx != NULL) { \ + cipher_generic_initkey(ctx, kbits, blkbits, ivbits, 0, flags, \ + PROV_CIPHER_HW_##alg(kbits), NULL); \ + } \ + return ctx; \ +} \ +const OSSL_DISPATCH alg##kbits##_functions[] = { \ + { OSSL_FUNC_CIPHER_NEWCTX, \ + (void (*)(void)) alg##_##kbits##_newctx }, \ + { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \ + { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \ + { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))cipher_generic_einit }, \ + { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))cipher_generic_dinit }, \ + { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))cipher_generic_##typ##_update },\ + { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))cipher_generic_##typ##_final }, \ + { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))cipher_generic_cipher }, \ + { OSSL_FUNC_CIPHER_GET_PARAMS, \ + (void (*)(void)) alg##_##kbits##_get_params }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ + (void (*)(void))cipher_generic_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ + (void (*)(void))cipher_generic_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ + (void (*)(void))cipher_generic_gettable_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ + (void (*)(void))cipher_generic_gettable_ctx_params }, \ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ + (void (*)(void))cipher_generic_settable_ctx_params }, \ + { 0, NULL } \ +}; + +/* rc440_functions */ +IMPLEMENT_cipher(rc4, RC4, EVP_CIPH_VARIABLE_LENGTH, 40, 8, 0, stream) +/* rc4128_functions */ +IMPLEMENT_cipher(rc4, RC4, EVP_CIPH_VARIABLE_LENGTH, 128, 8, 0, stream) diff --git a/providers/implementations/ciphers/cipher_rc4.h b/providers/implementations/ciphers/cipher_rc4.h new file mode 100644 index 0000000000..a2d0a50f21 --- /dev/null +++ b/providers/implementations/ciphers/cipher_rc4.h @@ -0,0 +1,21 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/rc4.h> +#include "prov/ciphercommon.h" + +typedef struct prov_rc4_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + RC4_KEY ks; + } ks; +} PROV_RC4_CTX; + +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc4(size_t keybits); diff --git a/providers/implementations/ciphers/cipher_rc4_hw.c b/providers/implementations/ciphers/cipher_rc4_hw.c new file mode 100644 index 0000000000..503a618914 --- /dev/null +++ b/providers/implementations/ciphers/cipher_rc4_hw.c @@ -0,0 +1,38 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_rc4.h" + +static int cipher_hw_rc4_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_RC4_CTX *rctx = (PROV_RC4_CTX *)ctx; + + RC4_set_key(&rctx->ks.ks, keylen, key); + return 1; +} + +static int cipher_hw_rc4_cipher(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + PROV_RC4_CTX *rctx = (PROV_RC4_CTX *)ctx; + + RC4(&rctx->ks.ks, len, in, out); + return 1; +} + +static const PROV_CIPHER_HW rc4_hw = { + cipher_hw_rc4_initkey, + cipher_hw_rc4_cipher +}; +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc4(size_t keybits) +{ + return &rc4_hw; +} + diff --git a/providers/implementations/ciphers/cipher_rc5.c b/providers/implementations/ciphers/cipher_rc5.c new file mode 100644 index 0000000000..645a6b8b64 --- /dev/null +++ b/providers/implementations/ciphers/cipher_rc5.c @@ -0,0 +1,145 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for RC5 cipher modes ecb, cbc, ofb, cfb */ + +#include "cipher_rc5.h" +#include "internal/provider_algs.h" +#include "internal/providercommonerr.h" + +static OSSL_OP_cipher_freectx_fn rc5_freectx; +static OSSL_OP_cipher_dupctx_fn rc5_dupctx; +OSSL_OP_cipher_gettable_ctx_params_fn rc5_gettable_ctx_params; +OSSL_OP_cipher_settable_ctx_params_fn rc5_settable_ctx_params; + +static void rc5_freectx(void *vctx) +{ + PROV_RC5_CTX *ctx = (PROV_RC5_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +static void *rc5_dupctx(void *ctx) +{ + PROV_RC5_CTX *in = (PROV_RC5_CTX *)ctx; + PROV_RC5_CTX *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + *ret = *in; + + return ret; +} + +static int rc5_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + PROV_RC5_CTX *ctx = (PROV_RC5_CTX *)vctx; + const OSSL_PARAM *p; + + if (!cipher_generic_set_ctx_params(vctx, params)) + return 0; + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_ROUNDS); + if (p != NULL) { + unsigned int rounds; + + if (!OSSL_PARAM_get_uint(p, &rounds)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + if (rounds != RC5_8_ROUNDS + && rounds != RC5_12_ROUNDS + && rounds != RC5_16_ROUNDS) { + ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS); + return 0; + } + ctx->rounds = rounds; + } + return 1; +} + +CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(rc5) + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_ROUNDS, NULL), +CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(rc5) + +CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(rc5) + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_ROUNDS, NULL), +CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(rc5) + + +static int rc5_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + PROV_RC5_CTX *ctx = (PROV_RC5_CTX *)vctx; + OSSL_PARAM *p; + + if (!cipher_generic_get_ctx_params(vctx, params)) + return 0; + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_ROUNDS); + if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->rounds)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + return 1; +} + +#define IMPLEMENT_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \ + blkbits, ivbits, typ) \ +static OSSL_OP_cipher_get_params_fn alg##_##kbits##_##lcmode##_get_params; \ +static int alg##_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \ +{ \ + return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, flags, \ + kbits, blkbits, ivbits); \ +} \ +static OSSL_OP_cipher_newctx_fn alg##_##kbits##_##lcmode##_newctx; \ +static void * alg##_##kbits##_##lcmode##_newctx(void *provctx) \ +{ \ + PROV_##UCALG##_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); \ + if (ctx != NULL) { \ + cipher_generic_initkey(ctx, kbits, blkbits, ivbits, \ + EVP_CIPH_##UCMODE##_MODE, flags, \ + PROV_CIPHER_HW_##alg##_##lcmode(kbits), NULL); \ + ctx->rounds = RC5_12_ROUNDS; \ + } \ + return ctx; \ +} \ +const OSSL_DISPATCH alg##kbits##lcmode##_functions[] = { \ + { OSSL_FUNC_CIPHER_NEWCTX, \ + (void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \ + { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \ + { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \ + { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))cipher_generic_einit }, \ + { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))cipher_generic_dinit }, \ + { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))cipher_generic_##typ##_update },\ + { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))cipher_generic_##typ##_final }, \ + { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))cipher_generic_cipher }, \ + { OSSL_FUNC_CIPHER_GET_PARAMS, \ + (void (*)(void)) alg##_##kbits##_##lcmode##_get_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ + (void (*)(void))cipher_generic_gettable_params }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ + (void (*)(void))rc5_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ + (void (*)(void))rc5_gettable_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ + (void (*)(void))rc5_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ + (void (*)(void))rc5_settable_ctx_params }, \ + { 0, NULL } \ +}; + +/* rc5128ecb_functions */ +IMPLEMENT_cipher(rc5, RC5, ecb, ECB, EVP_CIPH_VARIABLE_LENGTH, 128, 64, 0, block) +/* rc5128cbc_functions */ +IMPLEMENT_cipher(rc5, RC5, cbc, CBC, EVP_CIPH_VARIABLE_LENGTH, 128, 64, 64, block) +/* rc5128ofb64_functions */ +IMPLEMENT_cipher(rc5, RC5, ofb64, OFB, EVP_CIPH_VARIABLE_LENGTH, 128, 8, 64, stream) +/* rc5128cfb64_functions */ +IMPLEMENT_cipher(rc5, RC5, cfb64, CFB, EVP_CIPH_VARIABLE_LENGTH, 128, 8, 64, stream) diff --git a/providers/implementations/ciphers/cipher_rc5.h b/providers/implementations/ciphers/cipher_rc5.h new file mode 100644 index 0000000000..fe0d09f710 --- /dev/null +++ b/providers/implementations/ciphers/cipher_rc5.h @@ -0,0 +1,25 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/rc5.h> +#include "prov/ciphercommon.h" + +typedef struct prov_blowfish_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + RC5_32_KEY ks; /* key schedule */ + } ks; + unsigned int rounds; /* number of rounds */ +} PROV_RC5_CTX; + +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc5_cbc(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc5_ecb(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc5_ofb64(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc5_cfb64(size_t keybits); diff --git a/providers/implementations/ciphers/cipher_rc5_hw.c b/providers/implementations/ciphers/cipher_rc5_hw.c new file mode 100644 index 0000000000..a9a05ba32f --- /dev/null +++ b/providers/implementations/ciphers/cipher_rc5_hw.c @@ -0,0 +1,35 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_rc5.h" + +static int cipher_hw_rc5_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_RC5_CTX *rctx = (PROV_RC5_CTX *)ctx; + + return RC5_32_set_key(&rctx->ks.ks, keylen, key, rctx->rounds); +} + +# define PROV_CIPHER_HW_rc5_mode(mode, UCMODE) \ +IMPLEMENT_CIPHER_HW_##UCMODE(mode, rc5, PROV_RC5_CTX, RC5_32_KEY, \ + RC5_32_##mode) \ +static const PROV_CIPHER_HW rc5_##mode = { \ + cipher_hw_rc5_initkey, \ + cipher_hw_rc5_##mode##_cipher \ +}; \ +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc5_##mode(size_t keybits) \ +{ \ + return &rc5_##mode; \ +} + +PROV_CIPHER_HW_rc5_mode(cbc, CBC) +PROV_CIPHER_HW_rc5_mode(ecb, ECB) +PROV_CIPHER_HW_rc5_mode(ofb64, OFB) +PROV_CIPHER_HW_rc5_mode(cfb64, CFB) diff --git a/providers/implementations/ciphers/cipher_seed.c b/providers/implementations/ciphers/cipher_seed.c new file mode 100644 index 0000000000..397671dd06 --- /dev/null +++ b/providers/implementations/ciphers/cipher_seed.c @@ -0,0 +1,46 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for Seed cipher modes ecb, cbc, ofb, cfb */ + +#include "cipher_seed.h" +#include "internal/provider_algs.h" + +static OSSL_OP_cipher_freectx_fn seed_freectx; +static OSSL_OP_cipher_dupctx_fn seed_dupctx; + +static void seed_freectx(void *vctx) +{ + PROV_SEED_CTX *ctx = (PROV_SEED_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +static void *seed_dupctx(void *ctx) +{ + PROV_SEED_CTX *in = (PROV_SEED_CTX *)ctx; + PROV_SEED_CTX *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + *ret = *in; + + return ret; +} + +/* seed128ecb_functions */ +IMPLEMENT_generic_cipher(seed, SEED, ecb, ECB, 0, 128, 128, 0, block) +/* seed128cbc_functions */ +IMPLEMENT_generic_cipher(seed, SEED, cbc, CBC, 0, 128, 128, 128, block) +/* seed128ofb128_functions */ +IMPLEMENT_generic_cipher(seed, SEED, ofb128, OFB, 0, 128, 8, 128, stream) +/* seed128cfb128_functions */ +IMPLEMENT_generic_cipher(seed, SEED, cfb128, CFB, 0, 128, 8, 128, stream) diff --git a/providers/implementations/ciphers/cipher_seed.h b/providers/implementations/ciphers/cipher_seed.h new file mode 100644 index 0000000000..976af35005 --- /dev/null +++ b/providers/implementations/ciphers/cipher_seed.h @@ -0,0 +1,24 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/seed.h> +#include "prov/ciphercommon.h" + +typedef struct prov_seed_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + SEED_KEY_SCHEDULE ks; + } ks; +} PROV_SEED_CTX; + +const PROV_CIPHER_HW *PROV_CIPHER_HW_seed_cbc(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_seed_ecb(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_seed_ofb128(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_seed_cfb128(size_t keybits); diff --git a/providers/implementations/ciphers/cipher_seed_hw.c b/providers/implementations/ciphers/cipher_seed_hw.c new file mode 100644 index 0000000000..3bd3323dc0 --- /dev/null +++ b/providers/implementations/ciphers/cipher_seed_hw.c @@ -0,0 +1,36 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_seed.h" + +static int cipher_hw_seed_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_SEED_CTX *sctx = (PROV_SEED_CTX *)ctx; + + SEED_set_key(key, &(sctx->ks.ks)); + return 1; +} + +# define PROV_CIPHER_HW_seed_mode(mode, UCMODE) \ +IMPLEMENT_CIPHER_HW_##UCMODE(mode, seed, PROV_SEED_CTX, SEED_KEY_SCHEDULE, \ + SEED_##mode) \ +static const PROV_CIPHER_HW seed_##mode = { \ + cipher_hw_seed_initkey, \ + cipher_hw_seed_##mode##_cipher \ +}; \ +const PROV_CIPHER_HW *PROV_CIPHER_HW_seed_##mode(size_t keybits) \ +{ \ + return &seed_##mode; \ +} + +PROV_CIPHER_HW_seed_mode(cbc, CBC) +PROV_CIPHER_HW_seed_mode(ecb, ECB) +PROV_CIPHER_HW_seed_mode(ofb128, OFB) +PROV_CIPHER_HW_seed_mode(cfb128, CFB) diff --git a/providers/implementations/ciphers/cipher_sm4.c b/providers/implementations/ciphers/cipher_sm4.c new file mode 100644 index 0000000000..2c1e587863 --- /dev/null +++ b/providers/implementations/ciphers/cipher_sm4.c @@ -0,0 +1,48 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for cast cipher modes ecb, cbc, ofb, cfb */ + +#include "cipher_sm4.h" +#include "internal/provider_algs.h" + +static OSSL_OP_cipher_freectx_fn sm4_freectx; +static OSSL_OP_cipher_dupctx_fn sm4_dupctx; + +static void sm4_freectx(void *vctx) +{ + PROV_SM4_CTX *ctx = (PROV_SM4_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +static void *sm4_dupctx(void *ctx) +{ + PROV_SM4_CTX *in = (PROV_SM4_CTX *)ctx; + PROV_SM4_CTX *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + *ret = *in; + + return ret; +} + +/* sm4128ecb_functions */ +IMPLEMENT_generic_cipher(sm4, SM4, ecb, ECB, 0, 128, 128, 0, block) +/* sm4128cbc_functions */ +IMPLEMENT_generic_cipher(sm4, SM4, cbc, CBC, 0, 128, 128, 128, block) +/* sm4128ctr_functions */ +IMPLEMENT_generic_cipher(sm4, SM4, ctr, CTR, 0, 128, 8, 128, stream) +/* sm4128ofb128_functions */ +IMPLEMENT_generic_cipher(sm4, SM4, ofb128, OFB, 0, 128, 8, 128, stream) +/* sm4128cfb128_functions */ +IMPLEMENT_generic_cipher(sm4, SM4, cfb128, CFB, 0, 128, 8, 128, stream) diff --git a/providers/implementations/ciphers/cipher_sm4.h b/providers/implementations/ciphers/cipher_sm4.h new file mode 100644 index 0000000000..d5c9633552 --- /dev/null +++ b/providers/implementations/ciphers/cipher_sm4.h @@ -0,0 +1,25 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "prov/ciphercommon.h" +#include "crypto/sm4.h" + +typedef struct prov_cast_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + SM4_KEY ks; + } ks; +} PROV_SM4_CTX; + +const PROV_CIPHER_HW *PROV_CIPHER_HW_sm4_cbc(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_sm4_ecb(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_sm4_ctr(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_sm4_ofb128(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_sm4_cfb128(size_t keybits); diff --git a/providers/implementations/ciphers/cipher_sm4_hw.c b/providers/implementations/ciphers/cipher_sm4_hw.c new file mode 100644 index 0000000000..9ecaf0b997 --- /dev/null +++ b/providers/implementations/ciphers/cipher_sm4_hw.c @@ -0,0 +1,43 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_sm4.h" + +static int cipher_hw_sm4_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_SM4_CTX *sctx = (PROV_SM4_CTX *)ctx; + SM4_KEY *ks = &sctx->ks.ks; + + SM4_set_key(key, ks); + ctx->ks = ks; + if (ctx->enc + || (ctx->mode != EVP_CIPH_ECB_MODE + && ctx->mode != EVP_CIPH_CBC_MODE)) + ctx->block = (block128_f)SM4_encrypt; + else + ctx->block = (block128_f)SM4_decrypt; + return 1; +} + +# define PROV_CIPHER_HW_sm4_mode(mode) \ +static const PROV_CIPHER_HW sm4_##mode = { \ + cipher_hw_sm4_initkey, \ + cipher_hw_chunked_##mode \ +}; \ +const PROV_CIPHER_HW *PROV_CIPHER_HW_sm4_##mode(size_t keybits) \ +{ \ + return &sm4_##mode; \ +} + +PROV_CIPHER_HW_sm4_mode(cbc) +PROV_CIPHER_HW_sm4_mode(ecb) +PROV_CIPHER_HW_sm4_mode(ofb128) +PROV_CIPHER_HW_sm4_mode(cfb128) +PROV_CIPHER_HW_sm4_mode(ctr) diff --git a/providers/implementations/ciphers/cipher_tdes.c b/providers/implementations/ciphers/cipher_tdes.c new file mode 100644 index 0000000000..9c032902e9 --- /dev/null +++ b/providers/implementations/ciphers/cipher_tdes.c @@ -0,0 +1,114 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "prov/ciphercommon.h" +#include "cipher_tdes.h" +#include "crypto/rand.h" +#include "internal/provider_algs.h" +#include "internal/providercommonerr.h" + +void *tdes_newctx(void *provctx, int mode, size_t kbits, size_t blkbits, + size_t ivbits, uint64_t flags, const PROV_CIPHER_HW *hw) +{ + PROV_TDES_CTX *tctx = OPENSSL_zalloc(sizeof(*tctx)); + + if (tctx != NULL) + cipher_generic_initkey(tctx, kbits, blkbits, ivbits, mode, flags, hw, + provctx); + return tctx; +} + +void tdes_freectx(void *vctx) +{ + PROV_TDES_CTX *ctx = (PROV_TDES_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +static int tdes_init(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen, int enc) +{ + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + + ctx->enc = enc; + + if (iv != NULL) { + if (!cipher_generic_initiv(ctx, iv, ivlen)) + return 0; + } + + if (key != NULL) { + if (keylen != ctx->keylen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN); + return 0; + } + return ctx->hw->init(ctx, key, ctx->keylen); + } + return 1; +} + +int tdes_einit(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + return tdes_init(vctx, key, keylen, iv, ivlen, 1); +} + +int tdes_dinit(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + return tdes_init(vctx, key, keylen, iv, ivlen, 0); +} + +static int tdes_generatekey(PROV_CIPHER_CTX *ctx, void *ptr) +{ + + DES_cblock *deskey = ptr; + size_t kl = ctx->keylen; + + if (kl == 0 || rand_priv_bytes_ex(ctx->libctx, ptr, kl) <= 0) + return 0; + DES_set_odd_parity(deskey); + if (kl >= 16) + DES_set_odd_parity(deskey + 1); + if (kl >= 24) { + DES_set_odd_parity(deskey + 2); + return 1; + } + return 0; +} + +CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(tdes) + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_RANDOM_KEY, NULL, 0), +CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(tdes) + +int tdes_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + OSSL_PARAM *p; + + if (!cipher_generic_get_ctx_params(vctx, params)) + return 0; + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_RANDOM_KEY); + if (p != NULL && !tdes_generatekey(ctx, p->data)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GENERATE_KEY); + return 0; + } + return 1; +} + +/* + * TODO(3.0) - ECB mode does not use an IV - but existing test code is setting + * an IV. Fixing this could potentially make applications break. + */ + +/* tdes_ede3_ecb_functions */ +IMPLEMENT_tdes_cipher(ede3, EDE3, ecb, ECB, TDES_FLAGS, 64*3, 64, 64, block); +/* tdes_ede3_cbc_functions */ +IMPLEMENT_tdes_cipher(ede3, EDE3, cbc, CBC, TDES_FLAGS, 64*3, 64, 64, block); diff --git a/providers/implementations/ciphers/cipher_tdes.h b/providers/implementations/ciphers/cipher_tdes.h new file mode 100644 index 0000000000..7bb879fb4f --- /dev/null +++ b/providers/implementations/ciphers/cipher_tdes.h @@ -0,0 +1,96 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/des.h> +#include <openssl/core_numbers.h> + +#define DES_BLOCK_SIZE 8 +#define TDES_IVLEN 8 + +/* TODO(3.0) Figure out what flags need to be here */ +#define TDES_FLAGS (EVP_CIPH_RAND_KEY) + +typedef struct prov_tdes_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + DES_key_schedule ks[3]; + } tks; + union { + void (*cbc) (const void *, void *, size_t, + const DES_key_schedule *, unsigned char *); + } tstream; + +} PROV_TDES_CTX; + +#define IMPLEMENT_tdes_cipher(type, UCTYPE, lcmode, UCMODE, flags, \ + kbits, blkbits, ivbits, block) \ +static OSSL_OP_cipher_newctx_fn tdes_##type##_##lcmode##_newctx; \ +static void *tdes_##type##_##lcmode##_newctx(void *provctx) \ +{ \ + return tdes_newctx(provctx, EVP_CIPH_##UCMODE##_MODE, kbits, blkbits, \ + ivbits, flags, PROV_CIPHER_HW_tdes_##type##_##lcmode());\ +} \ +static OSSL_OP_cipher_get_params_fn tdes_##type##_##lcmode##_get_params; \ +static int tdes_##type##_##lcmode##_get_params(OSSL_PARAM params[]) \ +{ \ + return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, flags, \ + kbits, blkbits, ivbits); \ +} \ +const OSSL_DISPATCH tdes_##type##_##lcmode##_functions[] = { \ + { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))tdes_einit }, \ + { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))tdes_dinit }, \ + { OSSL_FUNC_CIPHER_UPDATE, \ + (void (*)(void))cipher_generic_##block##_update }, \ + { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))cipher_generic_##block##_final },\ + { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))cipher_generic_cipher }, \ + { OSSL_FUNC_CIPHER_NEWCTX, \ + (void (*)(void))tdes_##type##_##lcmode##_newctx }, \ + { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))tdes_freectx }, \ + { OSSL_FUNC_CIPHER_GET_PARAMS, \ + (void (*)(void))tdes_##type##_##lcmode##_get_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ + (void (*)(void))cipher_generic_gettable_params }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))tdes_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ + (void (*)(void))tdes_gettable_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ + (void (*)(void))cipher_generic_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ + (void (*)(void))cipher_generic_settable_ctx_params }, \ + { 0, NULL } \ +} + +void *tdes_newctx(void *provctx, int mode, size_t kbits, size_t blkbits, + size_t ivbits, uint64_t flags, const PROV_CIPHER_HW *hw); +OSSL_OP_cipher_freectx_fn tdes_freectx; +OSSL_OP_cipher_encrypt_init_fn tdes_einit; +OSSL_OP_cipher_decrypt_init_fn tdes_dinit; +OSSL_OP_cipher_get_ctx_params_fn tdes_get_ctx_params; +OSSL_OP_cipher_gettable_ctx_params_fn tdes_gettable_ctx_params; + +#define PROV_CIPHER_HW_tdes_mode(type, mode) \ +static const PROV_CIPHER_HW type##_##mode = { \ + cipher_hw_tdes_##type##_initkey, \ + cipher_hw_tdes_##mode \ +}; \ +const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_##type##_##mode(void) \ +{ \ + return &type##_##mode; \ +} + +int cipher_hw_tdes_ede3_initkey(PROV_CIPHER_CTX *ctx, const unsigned char *key, + size_t keylen); +int cipher_hw_tdes_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); +int cipher_hw_tdes_ecb(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len); + +const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_ede3_cbc(void); +const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_ede3_ecb(void); diff --git a/providers/implementations/ciphers/cipher_tdes_default.c b/providers/implementations/ciphers/cipher_tdes_default.c new file mode 100644 index 0000000000..73a78e8089 --- /dev/null +++ b/providers/implementations/ciphers/cipher_tdes_default.c @@ -0,0 +1,29 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_tdes_default.h" +#include "internal/provider_algs.h" + +/* tdes_ede3_ofb_functions */ +IMPLEMENT_tdes_cipher(ede3, EDE3, ofb, OFB, TDES_FLAGS, 64*3, 8, 64, stream); +/* tdes_ede3_cfb_functions */ +IMPLEMENT_tdes_cipher(ede3, EDE3, cfb, CFB, TDES_FLAGS, 64*3, 8, 64, stream); +/* tdes_ede3_cfb1_functions */ +IMPLEMENT_tdes_cipher(ede3, EDE3, cfb1, CFB, TDES_FLAGS, 64*3, 8, 64, stream); +/* tdes_ede3_cfb8_functions */ +IMPLEMENT_tdes_cipher(ede3, EDE3, cfb8, CFB, TDES_FLAGS, 64*3, 8, 64, stream); + +/* tdes_ede2_ecb_functions */ +IMPLEMENT_tdes_cipher(ede2, EDE2, ecb, ECB, TDES_FLAGS, 64*2, 64, 64, block); +/* tdes_ede2_cbc_functions */ +IMPLEMENT_tdes_cipher(ede2, EDE2, cbc, CBC, TDES_FLAGS, 64*2, 64, 64, block); +/* tdes_ede2_ofb_functions */ +IMPLEMENT_tdes_cipher(ede2, EDE2, ofb, OFB, TDES_FLAGS, 64*2, 8, 64, stream); +/* tdes_ede2_cfb_functions */ +IMPLEMENT_tdes_cipher(ede2, EDE2, cfb, CFB, TDES_FLAGS, 64*2, 8, 64, stream); diff --git a/providers/implementations/ciphers/cipher_tdes_default.h b/providers/implementations/ciphers/cipher_tdes_default.h new file mode 100644 index 0000000000..0bc499fc86 --- /dev/null +++ b/providers/implementations/ciphers/cipher_tdes_default.h @@ -0,0 +1,25 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "prov/ciphercommon.h" +#include "cipher_tdes.h" + +const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_ede3_ofb(void); +const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_ede3_cfb(void); +const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_ede3_cfb1(void); +const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_ede3_cfb8(void); + +const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_ede2_cbc(void); +const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_ede2_ecb(void); +const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_ede2_ofb(void); +const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_ede2_cfb(void); + +const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_desx_cbc(void); + +const PROV_CIPHER_HW *PROV_CIPHER_HW_tdes_wrap_cbc(void); diff --git a/providers/implementations/ciphers/cipher_tdes_default_hw.c b/providers/implementations/ciphers/cipher_tdes_default_hw.c new file mode 100644 index 0000000000..73169a0e56 --- /dev/null +++ b/providers/implementations/ciphers/cipher_tdes_default_hw.c @@ -0,0 +1,140 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_tdes_default.h" + +#define ks1 tks.ks[0] +#define ks2 tks.ks[1] +#define ks3 tks.ks[2] + +static int cipher_hw_tdes_ede2_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx; + DES_cblock *deskey = (DES_cblock *)key; + + tctx->tstream.cbc = NULL; +# if defined(SPARC_DES_CAPABLE) + if (SPARC_DES_CAPABLE) { + if (ctx->mode == EVP_CIPH_CBC_MODE) { + des_t4_key_expand(&deskey[0], &tctx->ks1); + des_t4_key_expand(&deskey[1], &tctx->ks2); + memcpy(&tctx->ks3, &tctx->ks1, sizeof(tctx->ks1)); + tctx->tstream.cbc = ctx->enc ? des_t4_ede3_cbc_encrypt : + des_t4_ede3_cbc_decrypt; + return 1; + } + } +# endif + DES_set_key_unchecked(&deskey[0], &tctx->ks1); + DES_set_key_unchecked(&deskey[1], &tctx->ks2); + memcpy(&tctx->ks3, &tctx->ks1, sizeof(tctx->ks1)); + return 1; +} + +static int cipher_hw_tdes_ofb(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx; + int num = ctx->num; + + while (inl >= MAXCHUNK) { + DES_ede3_ofb64_encrypt(in, out, (long)MAXCHUNK, &tctx->ks1, &tctx->ks2, + &tctx->ks3, (DES_cblock *)ctx->iv, &num); + inl -= MAXCHUNK; + in += MAXCHUNK; + out += MAXCHUNK; + } + if (inl > 0) { + DES_ede3_ofb64_encrypt(in, out, (long)inl, &tctx->ks1, &tctx->ks2, + &tctx->ks3, (DES_cblock *)ctx->iv, &num); + } + ctx->num = num; + return 1; +} + +static int cipher_hw_tdes_cfb(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx; + int num = ctx->num; + + while (inl >= MAXCHUNK) { + + DES_ede3_cfb64_encrypt(in, out, (long)MAXCHUNK, + &tctx->ks1, &tctx->ks2, &tctx->ks3, + (DES_cblock *)ctx->iv, &num, ctx->enc); + inl -= MAXCHUNK; + in += MAXCHUNK; + out += MAXCHUNK; + } + if (inl > 0) { + DES_ede3_cfb64_encrypt(in, out, (long)inl, + &tctx->ks1, &tctx->ks2, &tctx->ks3, + (DES_cblock *)ctx->iv, &num, ctx->enc); + } + ctx->num = num; + return 1; +} + +/* + * Although we have a CFB-r implementation for 3-DES, it doesn't pack the + * right way, so wrap it here + */ +static int cipher_hw_tdes_cfb1(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx; + size_t n; + unsigned char c[1], d[1]; + + if ((ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) == 0) + inl *= 8; + for (n = 0; n < inl; ++n) { + c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0; + DES_ede3_cfb_encrypt(c, d, 1, 1, + &tctx->ks1, &tctx->ks2, &tctx->ks3, + (DES_cblock *)ctx->iv, ctx->enc); + out[n / 8] = (out[n / 8] & ~(0x80 >> (unsigned int)(n % 8))) + | ((d[0] & 0x80) >> (unsigned int)(n % 8)); + } + + return 1; +} + +static int cipher_hw_tdes_cfb8(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx; + + while (inl >= MAXCHUNK) { + DES_ede3_cfb_encrypt(in, out, 8, (long)MAXCHUNK, + &tctx->ks1, &tctx->ks2, &tctx->ks3, + (DES_cblock *)ctx->iv, ctx->enc); + inl -= MAXCHUNK; + in += MAXCHUNK; + out += MAXCHUNK; + } + if (inl > 0) + DES_ede3_cfb_encrypt(in, out, 8, (long)inl, + &tctx->ks1, &tctx->ks2, &tctx->ks3, + (DES_cblock *)ctx->iv, ctx->enc); + return 1; +} + +PROV_CIPHER_HW_tdes_mode(ede3, ofb) +PROV_CIPHER_HW_tdes_mode(ede3, cfb) +PROV_CIPHER_HW_tdes_mode(ede3, cfb1) +PROV_CIPHER_HW_tdes_mode(ede3, cfb8) + +PROV_CIPHER_HW_tdes_mode(ede2, ecb) +PROV_CIPHER_HW_tdes_mode(ede2, cbc) +PROV_CIPHER_HW_tdes_mode(ede2, ofb) +PROV_CIPHER_HW_tdes_mode(ede2, cfb) + diff --git a/providers/implementations/ciphers/cipher_tdes_hw.c b/providers/implementations/ciphers/cipher_tdes_hw.c new file mode 100644 index 0000000000..208e83df0f --- /dev/null +++ b/providers/implementations/ciphers/cipher_tdes_hw.c @@ -0,0 +1,82 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "prov/ciphercommon.h" +#include "cipher_tdes.h" + +#define ks1 tks.ks[0] +#define ks2 tks.ks[1] +#define ks3 tks.ks[2] + +int cipher_hw_tdes_ede3_initkey(PROV_CIPHER_CTX *ctx, const unsigned char *key, + size_t keylen) +{ + PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx; + DES_cblock *deskey = (DES_cblock *)key; + + tctx->tstream.cbc = NULL; +# if defined(SPARC_DES_CAPABLE) + if (SPARC_DES_CAPABLE) { + if (ctx->mode == EVP_CIPH_CBC_MODE) { + des_t4_key_expand(&deskey[0], &tctx->ks1); + des_t4_key_expand(&deskey[1], &tctx->ks2); + des_t4_key_expand(&deskey[2], &tctx->ks3); + tctx->tstream.cbc = ctx->enc ? des_t4_ede3_cbc_encrypt : + des_t4_ede3_cbc_decrypt; + return 1; + } + } +# endif + DES_set_key_unchecked(&deskey[0], &tctx->ks1); + DES_set_key_unchecked(&deskey[1], &tctx->ks2); + DES_set_key_unchecked(&deskey[2], &tctx->ks3); + return 1; +} + +int cipher_hw_tdes_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx; + + if (tctx->tstream.cbc != NULL) { + (*tctx->tstream.cbc) (in, out, inl, tctx->tks.ks, ctx->iv); + return 1; + } + + while (inl >= MAXCHUNK) { + DES_ede3_cbc_encrypt(in, out, (long)MAXCHUNK, &tctx->ks1, &tctx->ks2, + &tctx->ks3, (DES_cblock *)ctx->iv, ctx->enc); + inl -= MAXCHUNK; + in += MAXCHUNK; + out += MAXCHUNK; + } + if (inl > 0) + DES_ede3_cbc_encrypt(in, out, (long)inl, &tctx->ks1, &tctx->ks2, + &tctx->ks3, (DES_cblock *)ctx->iv, ctx->enc); + return 1; +} + +int cipher_hw_tdes_ecb(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + size_t i; + PROV_TDES_CTX *tctx = (PROV_TDES_CTX *)ctx; + + if (len < DES_BLOCK_SIZE) + return 1; + + for (i = 0, len -= DES_BLOCK_SIZE; i <= len; i += DES_BLOCK_SIZE) { + DES_ecb3_encrypt((const_DES_cblock *)(in + i), (DES_cblock *)(out + i), + &tctx->ks1, &tctx->ks2, &tctx->ks3, ctx->enc); + } + return 1; +} + +PROV_CIPHER_HW_tdes_mode(ede3, ecb) +PROV_CIPHER_HW_tdes_mode(ede3, cbc) diff --git a/providers/implementations/ciphers/cipher_tdes_wrap.c b/providers/implementations/ciphers/cipher_tdes_wrap.c new file mode 100644 index 0000000000..1ee0044489 --- /dev/null +++ b/providers/implementations/ciphers/cipher_tdes_wrap.c @@ -0,0 +1,199 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/sha.h> +#include "cipher_tdes_default.h" +#include "crypto/evp.h" +#include "crypto/rand.h" +#include "internal/provider_algs.h" +#include "internal/providercommonerr.h" + +/* TODO (3.0) Figure out what flags are requred */ +#define TDES_WRAP_FLAGS (EVP_CIPH_WRAP_MODE \ + | EVP_CIPH_CUSTOM_IV \ + | EVP_CIPH_FLAG_CUSTOM_CIPHER) + + +static OSSL_OP_cipher_update_fn tdes_wrap_update; +static OSSL_OP_cipher_cipher_fn tdes_wrap_cipher; + +static const unsigned char wrap_iv[8] = +{ + 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05 +}; + +static int des_ede3_unwrap(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + unsigned char icv[8], iv[TDES_IVLEN], sha1tmp[SHA_DIGEST_LENGTH]; + int rv = -1; + + if (inl < 24) + return -1; + if (out == NULL) + return inl - 16; + + memcpy(ctx->iv, wrap_iv, 8); + /* Decrypt first block which will end up as icv */ + ctx->hw->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; + } + ctx->hw->cipher(ctx, out, in + 8, inl - 16); + /* Decrypt final block which will be IV */ + ctx->hw->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 */ + ctx->hw->cipher(ctx, out, out, inl - 16); + ctx->hw->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, sizeof(ctx->iv)); + if (rv == -1) + OPENSSL_cleanse(out, inl - 16); + + return rv; +} + +static int des_ede3_wrap(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + unsigned char sha1tmp[SHA_DIGEST_LENGTH]; + size_t ivlen = TDES_IVLEN; + size_t icvlen = TDES_IVLEN; + size_t len = inl + ivlen + icvlen; + + if (out == NULL) + return len; + + /* Copy input to output buffer + 8 so we have space for IV */ + memmove(out + ivlen, in, inl); + /* Work out ICV */ + SHA1(in, inl, sha1tmp); + memcpy(out + inl + ivlen, sha1tmp, icvlen); + OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH); + /* Generate random IV */ + if (rand_bytes_ex(ctx->libctx, ctx->iv, ivlen) <= 0) + return 0; + memcpy(out, ctx->iv, ivlen); + /* Encrypt everything after IV in place */ + ctx->hw->cipher(ctx, out + ivlen, out + ivlen, inl + ivlen); + BUF_reverse(out, NULL, len); + memcpy(ctx->iv, wrap_iv, ivlen); + ctx->hw->cipher(ctx, out, out, len); + return len; +} + +static int tdes_wrap_cipher_internal(PROV_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->enc) + return des_ede3_wrap(ctx, out, in, inl); + else + return des_ede3_unwrap(ctx, out, in, inl); +} + +static int tdes_wrap_cipher(void *vctx, + unsigned char *out, size_t *outl, size_t outsize, + const unsigned char *in, size_t inl) +{ + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + int ret; + + *outl = 0; + if (outsize < inl) { + PROVerr(0, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return -1; + } + + ret = tdes_wrap_cipher_internal(ctx, out, in, inl); + if (ret <= 0) + return 0; + + *outl = ret; + return 1; +} + +static int tdes_wrap_update(void *vctx, unsigned char *out, size_t *outl, + size_t outsize, const unsigned char *in, + size_t inl) +{ + *outl = 0; + if (outsize < inl) { + PROVerr(0, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (!tdes_wrap_cipher(vctx, out, outl, outsize, in, inl)) { + PROVerr(0, PROV_R_CIPHER_OPERATION_FAILED); + return 0; + } + return 1; +} + + +# define IMPLEMENT_WRAP_CIPHER(flags, kbits, blkbits, ivbits) \ +static OSSL_OP_cipher_newctx_fn tdes_wrap_newctx; \ +static void *tdes_wrap_newctx(void *provctx) \ +{ \ + return tdes_newctx(provctx, EVP_CIPH_WRAP_MODE, kbits, blkbits, ivbits, \ + flags, PROV_CIPHER_HW_tdes_wrap_cbc()); \ +} \ +static OSSL_OP_cipher_get_params_fn tdes_wrap_get_params; \ +static int tdes_wrap_get_params(OSSL_PARAM params[]) \ +{ \ + return cipher_generic_get_params(params, EVP_CIPH_WRAP_MODE, flags, \ + kbits, blkbits, ivbits); \ +} \ +const OSSL_DISPATCH tdes_wrap_cbc_functions[] = \ +{ \ + { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void)) tdes_einit }, \ + { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void)) tdes_dinit }, \ + { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))tdes_wrap_cipher }, \ + { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))tdes_wrap_newctx }, \ + { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))tdes_freectx }, \ + { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))tdes_wrap_update }, \ + { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))cipher_generic_stream_final }, \ + { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))tdes_wrap_get_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ + (void (*)(void))cipher_generic_gettable_params }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))tdes_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ + (void (*)(void))tdes_gettable_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ + (void (*)(void))cipher_generic_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ + (void (*)(void))cipher_generic_settable_ctx_params }, \ + { 0, NULL } \ +} + +/* tdes_wrap_cbc_functions */ +IMPLEMENT_WRAP_CIPHER(TDES_WRAP_FLAGS, 64*3, 64, 0); diff --git a/providers/implementations/ciphers/cipher_tdes_wrap_hw.c b/providers/implementations/ciphers/cipher_tdes_wrap_hw.c new file mode 100644 index 0000000000..09155b6f48 --- /dev/null +++ b/providers/implementations/ciphers/cipher_tdes_wrap_hw.c @@ -0,0 +1,14 @@ +/* + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_tdes_default.h" + +#define cipher_hw_tdes_wrap_initkey cipher_hw_tdes_ede3_initkey + +PROV_CIPHER_HW_tdes_mode(wrap, cbc) |