diff options
author | Shane Lontis <shane.lontis@oracle.com> | 2020-01-06 13:02:16 +1000 |
---|---|---|
committer | Shane Lontis <shane.lontis@oracle.com> | 2020-01-06 13:02:16 +1000 |
commit | 0d2bfe52bb7e839f7bddcdb1160c335f2994df2f (patch) | |
tree | 91d972d9aca1832ae2bdfc5ebd130e1c74dc4bc1 /providers | |
parent | 26583f6aa8dc28e3598e61db66e54e2fdf8b195f (diff) | |
download | openssl-0d2bfe52bb7e839f7bddcdb1160c335f2994df2f.zip openssl-0d2bfe52bb7e839f7bddcdb1160c335f2994df2f.tar.gz openssl-0d2bfe52bb7e839f7bddcdb1160c335f2994df2f.tar.bz2 |
Add AES_CBC_HMAC_SHA ciphers to providers.
Also Add ability for providers to dynamically exclude cipher algorithms.
Cipher algorithms are only returned from providers if their capable() method is either NULL,
or the method returns 1.
This is mainly required for ciphers that only have hardware implementations.
If there is no hardware support, then the algorithm needs to be not available.
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10146)
Diffstat (limited to 'providers')
-rw-r--r-- | providers/common/include/prov/provider_util.h | 12 | ||||
-rw-r--r-- | providers/common/include/prov/providercommon.h | 2 | ||||
-rw-r--r-- | providers/common/provider_util.c | 14 | ||||
-rw-r--r-- | providers/defltprov.c | 317 | ||||
-rw-r--r-- | providers/fips/fipsprov.c | 89 | ||||
-rw-r--r-- | providers/implementations/ciphers/build.info | 6 | ||||
-rw-r--r-- | providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c | 345 | ||||
-rw-r--r-- | providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.h | 65 | ||||
-rw-r--r-- | providers/implementations/ciphers/cipher_aes_cbc_hmac_sha1_hw.c | 782 | ||||
-rw-r--r-- | providers/implementations/ciphers/cipher_aes_cbc_hmac_sha256_hw.c | 831 | ||||
-rw-r--r-- | providers/implementations/include/prov/implementations.h | 4 |
11 files changed, 2279 insertions, 188 deletions
diff --git a/providers/common/include/prov/provider_util.h b/providers/common/include/prov/provider_util.h index 9925ac2..ca3550b 100644 --- a/providers/common/include/prov/provider_util.h +++ b/providers/common/include/prov/provider_util.h @@ -101,3 +101,15 @@ int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx, const char *ciphername, const char *mdname, OPENSSL_CTX *ctx); + +typedef struct ag_capable_st { + OSSL_ALGORITHM alg; + int (*capable)(void); +} OSSL_ALGORITHM_CAPABLE; + +/* + * Dynamically select algorithms by calling a capable() method. + * If this method is NULL or the method returns 1 then the algorithm is added. + */ +void ossl_prov_cache_exported_algorithms(const OSSL_ALGORITHM_CAPABLE *in, + OSSL_ALGORITHM *out); diff --git a/providers/common/include/prov/providercommon.h b/providers/common/include/prov/providercommon.h index 569c08c..995c685 100644 --- a/providers/common/include/prov/providercommon.h +++ b/providers/common/include/prov/providercommon.h @@ -13,3 +13,5 @@ const OSSL_PROVIDER *FIPS_get_provider(OPENSSL_CTX *ctx); const char *ossl_prov_util_nid_to_name(int nid); +int cipher_capable_aes_cbc_hmac_sha1(void); +int cipher_capable_aes_cbc_hmac_sha256(void); diff --git a/providers/common/provider_util.c b/providers/common/provider_util.c index ef4396f..504463d 100644 --- a/providers/common/provider_util.c +++ b/providers/common/provider_util.c @@ -237,3 +237,17 @@ int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx, *macctx = NULL; return 0; } + +void ossl_prov_cache_exported_algorithms(const OSSL_ALGORITHM_CAPABLE *in, + OSSL_ALGORITHM *out) +{ + int i, j; + + if (out[0].algorithm_names == NULL) { + for (i = j = 0; in[i].alg.algorithm_names != NULL; ++i) { + if (in[i].capable == NULL || in[i].capable()) + out[j++] = in[i].alg; + } + out[j++] = in[i].alg; + } +} diff --git a/providers/defltprov.c b/providers/defltprov.c index 51cd2b9..5c11b4a 100644 --- a/providers/defltprov.c +++ b/providers/defltprov.c @@ -15,7 +15,13 @@ #include <openssl/core_names.h> #include <openssl/params.h> #include "prov/bio.h" +#include "prov/providercommon.h" #include "prov/implementations.h" +#include "prov/provider_util.h" +#include "internal/nelem.h" + +#define ALGC(NAMES, FUNC, CHECK) { { NAMES, "default=yes", FUNC }, CHECK } +#define ALG(NAMES, FUNC) ALGC(NAMES, FUNC, NULL) /* Functions provided by the core */ static OSSL_core_gettable_params_fn *c_gettable_params = NULL; @@ -131,190 +137,196 @@ static const OSSL_ALGORITHM deflt_digests[] = { { NULL, NULL, NULL } }; -static const OSSL_ALGORITHM deflt_ciphers[] = { - { "AES-256-ECB", "default=yes", aes256ecb_functions }, - { "AES-192-ECB", "default=yes", aes192ecb_functions }, - { "AES-128-ECB", "default=yes", aes128ecb_functions }, - { "AES-256-CBC", "default=yes", aes256cbc_functions }, - { "AES-192-CBC", "default=yes", aes192cbc_functions }, - { "AES-128-CBC", "default=yes", aes128cbc_functions }, - { "AES-256-OFB", "default=yes", aes256ofb_functions }, - { "AES-192-OFB", "default=yes", aes192ofb_functions }, - { "AES-128-OFB", "default=yes", aes128ofb_functions }, - { "AES-256-CFB", "default=yes", aes256cfb_functions }, - { "AES-192-CFB", "default=yes", aes192cfb_functions }, - { "AES-128-CFB", "default=yes", aes128cfb_functions }, - { "AES-256-CFB1", "default=yes", aes256cfb1_functions }, - { "AES-192-CFB1", "default=yes", aes192cfb1_functions }, - { "AES-128-CFB1", "default=yes", aes128cfb1_functions }, - { "AES-256-CFB8", "default=yes", aes256cfb8_functions }, - { "AES-192-CFB8", "default=yes", aes192cfb8_functions }, - { "AES-128-CFB8", "default=yes", aes128cfb8_functions }, - { "AES-256-CTR", "default=yes", aes256ctr_functions }, - { "AES-192-CTR", "default=yes", aes192ctr_functions }, - { "AES-128-CTR", "default=yes", aes128ctr_functions }, - { "AES-256-XTS", "default=yes", aes256xts_functions }, - { "AES-128-XTS", "default=yes", aes128xts_functions }, +static const OSSL_ALGORITHM_CAPABLE deflt_ciphers[] = { + ALG("AES-256-ECB", aes256ecb_functions), + ALG("AES-192-ECB", aes192ecb_functions), + ALG("AES-128-ECB", aes128ecb_functions), + ALG("AES-256-CBC", aes256cbc_functions), + ALG("AES-192-CBC", aes192cbc_functions), + ALG("AES-128-CBC", aes128cbc_functions), + ALG("AES-256-OFB", aes256ofb_functions), + ALG("AES-192-OFB", aes192ofb_functions), + ALG("AES-128-OFB", aes128ofb_functions), + ALG("AES-256-CFB", aes256cfb_functions), + ALG("AES-192-CFB", aes192cfb_functions), + ALG("AES-128-CFB", aes128cfb_functions), + ALG("AES-256-CFB1", aes256cfb1_functions), + ALG("AES-192-CFB1", aes192cfb1_functions), + ALG("AES-128-CFB1", aes128cfb1_functions), + ALG("AES-256-CFB8", aes256cfb8_functions), + ALG("AES-192-CFB8", aes192cfb8_functions), + ALG("AES-128-CFB8", aes128cfb8_functions), + ALG("AES-256-CTR", aes256ctr_functions), + ALG("AES-192-CTR", aes192ctr_functions), + ALG("AES-128-CTR", aes128ctr_functions), + ALG("AES-256-XTS", aes256xts_functions), + ALG("AES-128-XTS", aes128xts_functions), #ifndef OPENSSL_NO_OCB - { "AES-256-OCB", "default=yes", aes256ocb_functions }, - { "AES-192-OCB", "default=yes", aes192ocb_functions }, - { "AES-128-OCB", "default=yes", aes128ocb_functions }, + ALG("AES-256-OCB", aes256ocb_functions), + ALG("AES-192-OCB", aes192ocb_functions), + ALG("AES-128-OCB", aes128ocb_functions), #endif /* OPENSSL_NO_OCB */ #ifndef OPENSSL_NO_SIV - { "AES-128-SIV", "default=yes", aes128siv_functions }, - { "AES-192-SIV", "default=yes", aes192siv_functions }, - { "AES-256-SIV", "default=yes", aes256siv_functions }, + ALG("AES-128-SIV", aes128siv_functions), + ALG("AES-192-SIV", aes192siv_functions), + ALG("AES-256-SIV", aes256siv_functions), #endif /* OPENSSL_NO_SIV */ - { "AES-256-GCM:id-aes256-GCM", "default=yes", aes256gcm_functions }, - { "AES-192-GCM:id-aes192-GCM", "default=yes", aes192gcm_functions }, - { "AES-128-GCM:id-aes128-GCM", "default=yes", aes128gcm_functions }, - { "AES-256-CCM:id-aes256-CCM", "default=yes", aes256ccm_functions }, - { "AES-192-CCM:id-aes192-CCM", "default=yes", aes192ccm_functions }, - { "AES-128-CCM:id-aes128-CCM", "default=yes", aes128ccm_functions }, - { "AES-256-WRAP:id-aes256-wrap:AES256-WRAP", "default=yes", - aes256wrap_functions }, - { "AES-192-WRAP:id-aes192-wrap:AES192-WRAP", "default=yes", - aes192wrap_functions }, - { "AES-128-WRAP:id-aes128-wrap:AES128-WRAP", "default=yes", - aes128wrap_functions }, - { "AES-256-WRAP-PAD:id-aes256-wrap-pad:AES256-WRAP-PAD", "default=yes", - aes256wrappad_functions }, - { "AES-192-WRAP-PAD:id-aes192-wrap-pad:AES192-WRAP-PAD", "default=yes", - aes192wrappad_functions }, - { "AES-128-WRAP-PAD:id-aes128-wrap-pad:AES128-WRAP-PAD", "default=yes", - aes128wrappad_functions }, + ALG("AES-256-GCM:id-aes256-GCM", aes256gcm_functions), + ALG("AES-192-GCM:id-aes192-GCM", aes192gcm_functions), + ALG("AES-128-GCM:id-aes128-GCM", aes128gcm_functions), + ALG("AES-256-CCM:id-aes256-CCM", aes256ccm_functions), + ALG("AES-192-CCM:id-aes192-CCM", aes192ccm_functions), + ALG("AES-128-CCM:id-aes128-CCM", aes128ccm_functions), + ALG("AES-256-WRAP:id-aes256-wrap:AES256-WRAP", aes256wrap_functions), + ALG("AES-192-WRAP:id-aes192-wrap:AES192-WRAP", aes192wrap_functions), + ALG("AES-128-WRAP:id-aes128-wrap:AES128-WRAP", aes128wrap_functions), + ALG("AES-256-WRAP-PAD:id-aes256-wrap-pad:AES256-WRAP-PAD", + aes256wrappad_functions), + ALG("AES-192-WRAP-PAD:id-aes192-wrap-pad:AES192-WRAP-PAD", + aes192wrappad_functions), + ALG("AES-128-WRAP-PAD:id-aes128-wrap-pad:AES128-WRAP-PAD", + aes128wrappad_functions), + ALGC("AES-128-CBC-HMAC-SHA1", aes128cbc_hmac_sha1_functions, + cipher_capable_aes_cbc_hmac_sha1), + ALGC("AES-256-CBC-HMAC-SHA1", aes256cbc_hmac_sha1_functions, + cipher_capable_aes_cbc_hmac_sha1), + ALGC("AES-128-CBC-HMAC-SHA256", aes128cbc_hmac_sha256_functions, + cipher_capable_aes_cbc_hmac_sha256), + ALGC("AES-256-CBC-HMAC-SHA256", aes256cbc_hmac_sha256_functions, + cipher_capable_aes_cbc_hmac_sha256), #ifndef OPENSSL_NO_ARIA - { "ARIA-256-GCM", "default=yes", aria256gcm_functions }, - { "ARIA-192-GCM", "default=yes", aria192gcm_functions }, - { "ARIA-128-GCM", "default=yes", aria128gcm_functions }, - { "ARIA-256-CCM", "default=yes", aria256ccm_functions }, - { "ARIA-192-CCM", "default=yes", aria192ccm_functions }, - { "ARIA-128-CCM", "default=yes", aria128ccm_functions }, - { "ARIA-256-ECB", "default=yes", aria256ecb_functions }, - { "ARIA-192-ECB", "default=yes", aria192ecb_functions }, - { "ARIA-128-ECB", "default=yes", aria128ecb_functions }, - { "ARIA-256-CBC:ARIA256", "default=yes", aria256cbc_functions }, - { "ARIA-192-CBC:ARIA192", "default=yes", aria192cbc_functions }, - { "ARIA-128-CBC:ARIA128", "default=yes", aria128cbc_functions }, - { "ARIA-256-OFB", "default=yes", aria256ofb_functions }, - { "ARIA-192-OFB", "default=yes", aria192ofb_functions }, - { "ARIA-128-OFB", "default=yes", aria128ofb_functions }, - { "ARIA-256-CFB", "default=yes", aria256cfb_functions }, - { "ARIA-192-CFB", "default=yes", aria192cfb_functions }, - { "ARIA-128-CFB", "default=yes", aria128cfb_functions }, - { "ARIA-256-CFB1", "default=yes", aria256cfb1_functions }, - { "ARIA-192-CFB1", "default=yes", aria192cfb1_functions }, - { "ARIA-128-CFB1", "default=yes", aria128cfb1_functions }, - { "ARIA-256-CFB8", "default=yes", aria256cfb8_functions }, - { "ARIA-192-CFB8", "default=yes", aria192cfb8_functions }, - { "ARIA-128-CFB8", "default=yes", aria128cfb8_functions }, - { "ARIA-256-CTR", "default=yes", aria256ctr_functions }, - { "ARIA-192-CTR", "default=yes", aria192ctr_functions }, - { "ARIA-128-CTR", "default=yes", aria128ctr_functions }, + ALG("ARIA-256-GCM", aria256gcm_functions), + ALG("ARIA-192-GCM", aria192gcm_functions), + ALG("ARIA-128-GCM", aria128gcm_functions), + ALG("ARIA-256-CCM", aria256ccm_functions), + ALG("ARIA-192-CCM", aria192ccm_functions), + ALG("ARIA-128-CCM", aria128ccm_functions), + ALG("ARIA-256-ECB", aria256ecb_functions), + ALG("ARIA-192-ECB", aria192ecb_functions), + ALG("ARIA-128-ECB", aria128ecb_functions), + ALG("ARIA-256-CBC:ARIA256", aria256cbc_functions), + ALG("ARIA-192-CBC:ARIA192", aria192cbc_functions), + ALG("ARIA-128-CBC:ARIA128", aria128cbc_functions), + ALG("ARIA-256-OFB", aria256ofb_functions), + ALG("ARIA-192-OFB", aria192ofb_functions), + ALG("ARIA-128-OFB", aria128ofb_functions), + ALG("ARIA-256-CFB", aria256cfb_functions), + ALG("ARIA-192-CFB", aria192cfb_functions), + ALG("ARIA-128-CFB", aria128cfb_functions), + ALG("ARIA-256-CFB1", aria256cfb1_functions), + ALG("ARIA-192-CFB1", aria192cfb1_functions), + ALG("ARIA-128-CFB1", aria128cfb1_functions), + ALG("ARIA-256-CFB8", aria256cfb8_functions), + ALG("ARIA-192-CFB8", aria192cfb8_functions), + ALG("ARIA-128-CFB8", aria128cfb8_functions), + ALG("ARIA-256-CTR", aria256ctr_functions), + ALG("ARIA-192-CTR", aria192ctr_functions), + ALG("ARIA-128-CTR", aria128ctr_functions), #endif /* OPENSSL_NO_ARIA */ #ifndef OPENSSL_NO_CAMELLIA - { "CAMELLIA-256-ECB", "default=yes", camellia256ecb_functions }, - { "CAMELLIA-192-ECB", "default=yes", camellia192ecb_functions }, - { "CAMELLIA-128-ECB", "default=yes", camellia128ecb_functions }, - { "CAMELLIA-256-CBC:CAMELLIA256", "default=yes", camellia256cbc_functions }, - { "CAMELLIA-192-CBC:CAMELLIA192", "default=yes", camellia192cbc_functions }, - { "CAMELLIA-128-CBC:CAMELLIA128", "default=yes", camellia128cbc_functions }, - { "CAMELLIA-256-OFB", "default=yes", camellia256ofb_functions }, - { "CAMELLIA-192-OFB", "default=yes", camellia192ofb_functions }, - { "CAMELLIA-128-OFB", "default=yes", camellia128ofb_functions }, - { "CAMELLIA-256-CFB", "default=yes", camellia256cfb_functions }, - { "CAMELLIA-192-CFB", "default=yes", camellia192cfb_functions }, - { "CAMELLIA-128-CFB", "default=yes", camellia128cfb_functions }, - { "CAMELLIA-256-CFB1", "default=yes", camellia256cfb1_functions }, - { "CAMELLIA-192-CFB1", "default=yes", camellia192cfb1_functions }, - { "CAMELLIA-128-CFB1", "default=yes", camellia128cfb1_functions }, - { "CAMELLIA-256-CFB8", "default=yes", camellia256cfb8_functions }, - { "CAMELLIA-192-CFB8", "default=yes", camellia192cfb8_functions }, - { "CAMELLIA-128-CFB8", "default=yes", camellia128cfb8_functions }, - { "CAMELLIA-256-CTR", "default=yes", camellia256ctr_functions }, - { "CAMELLIA-192-CTR", "default=yes", camellia192ctr_functions }, - { "CAMELLIA-128-CTR", "default=yes", camellia128ctr_functions }, + ALG("CAMELLIA-256-ECB", camellia256ecb_functions), + ALG("CAMELLIA-192-ECB", camellia192ecb_functions), + ALG("CAMELLIA-128-ECB", camellia128ecb_functions), + ALG("CAMELLIA-256-CBC:CAMELLIA256", camellia256cbc_functions), + ALG("CAMELLIA-192-CBC:CAMELLIA192", camellia192cbc_functions), + ALG("CAMELLIA-128-CBC:CAMELLIA128", camellia128cbc_functions), + ALG("CAMELLIA-256-OFB", camellia256ofb_functions), + ALG("CAMELLIA-192-OFB", camellia192ofb_functions), + ALG("CAMELLIA-128-OFB", camellia128ofb_functions), + ALG("CAMELLIA-256-CFB", camellia256cfb_functions), + ALG("CAMELLIA-192-CFB", camellia192cfb_functions), + ALG("CAMELLIA-128-CFB", camellia128cfb_functions), + ALG("CAMELLIA-256-CFB1", camellia256cfb1_functions), + ALG("CAMELLIA-192-CFB1", camellia192cfb1_functions), + ALG("CAMELLIA-128-CFB1", camellia128cfb1_functions), + ALG("CAMELLIA-256-CFB8", camellia256cfb8_functions), + ALG("CAMELLIA-192-CFB8", camellia192cfb8_functions), + ALG("CAMELLIA-128-CFB8", camellia128cfb8_functions), + ALG("CAMELLIA-256-CTR", camellia256ctr_functions), + ALG("CAMELLIA-192-CTR", camellia192ctr_functions), + ALG("CAMELLIA-128-CTR", camellia128ctr_functions), #endif /* OPENSSL_NO_CAMELLIA */ #ifndef OPENSSL_NO_DES - { "DES-EDE3-ECB:DES-EDE3", "default=yes", tdes_ede3_ecb_functions }, - { "DES-EDE3-CBC:DES3", "default=yes", tdes_ede3_cbc_functions }, - { "DES-EDE3-OFB", "default=yes", tdes_ede3_ofb_functions }, - { "DES-EDE3-CFB", "default=yes", tdes_ede3_cfb_functions }, - { "DES-EDE3-CFB8", "default=yes", tdes_ede3_cfb8_functions }, - { "DES-EDE3-CFB1", "default=yes", tdes_ede3_cfb1_functions }, - { "DES-EDE-ECB:DES-EDE", "default=yes", tdes_ede2_ecb_functions }, - { "DES-EDE-CBC", "default=yes", tdes_ede2_cbc_functions }, - { "DES-EDE-OFB", "default=yes", tdes_ede2_ofb_functions }, - { "DES-EDE-CFB", "default=yes", tdes_ede2_cfb_functions }, - { "DESX-CBC:DESX", "default=yes", tdes_desx_cbc_functions }, - { "DES3-WRAP:id-smime-alg-CMS3DESwrap", "default=yes", tdes_wrap_cbc_functions }, - { "DES-ECB", "default=yes", des_ecb_functions }, - { "DES-CBC:DES", "default=yes", des_cbc_functions }, - { "DES-OFB", "default=yes", des_ofb64_functions }, - { "DES-CFB", "default=yes", des_cfb64_functions }, - { "DES-CFB1", "default=yes", des_cfb1_functions }, - { "DES-CFB8", "default=yes", des_cfb8_functions }, + ALG("DES-EDE3-ECB:DES-EDE3", tdes_ede3_ecb_functions), + ALG("DES-EDE3-CBC:DES3", tdes_ede3_cbc_functions), + ALG("DES-EDE3-OFB", tdes_ede3_ofb_functions), + ALG("DES-EDE3-CFB", tdes_ede3_cfb_functions), + ALG("DES-EDE3-CFB8", tdes_ede3_cfb8_functions), + ALG("DES-EDE3-CFB1", tdes_ede3_cfb1_functions), + ALG("DES-EDE-ECB:DES-EDE", tdes_ede2_ecb_functions), + ALG("DES-EDE-CBC", tdes_ede2_cbc_functions), + ALG("DES-EDE-OFB", tdes_ede2_ofb_functions), + ALG("DES-EDE-CFB", tdes_ede2_cfb_functions), + ALG("DESX-CBC:DESX", tdes_desx_cbc_functions), + ALG("DES3-WRAP:id-smime-alg-CMS3DESwrap", tdes_wrap_cbc_functions), + ALG("DES-ECB", des_ecb_functions), + ALG("DES-CBC:DES", des_cbc_functions), + ALG("DES-OFB", des_ofb64_functions), + ALG("DES-CFB", des_cfb64_functions), + ALG("DES-CFB1", des_cfb1_functions), + ALG("DES-CFB8", des_cfb8_functions), #endif /* OPENSSL_NO_DES */ #ifndef OPENSSL_NO_BF - { "BF-ECB", "default=yes", blowfish128ecb_functions }, - { "BF-CBC:BF:BLOWFISH", "default=yes", blowfish128cbc_functions }, - { "BF-OFB", "default=yes", blowfish64ofb64_functions }, - { "BF-CFB", "default=yes", blowfish64cfb64_functions }, + ALG("BF-ECB", blowfish128ecb_functions), + ALG("BF-CBC:BF:BLOWFISH", blowfish128cbc_functions), + ALG("BF-OFB", blowfish64ofb64_functions), + ALG("BF-CFB", blowfish64cfb64_functions), #endif /* OPENSSL_NO_BF */ #ifndef OPENSSL_NO_IDEA - { "IDEA-ECB", "default=yes", idea128ecb_functions }, - { "IDEA-CBC:IDEA", "default=yes", idea128cbc_functions }, - { "IDEA-OFB:IDEA-OFB64", "default=yes", idea128ofb64_functions }, - { "IDEA-CFB:IDEA-CFB64", "default=yes", idea128cfb64_functions }, + ALG("IDEA-ECB", idea128ecb_functions), + ALG("IDEA-CBC:IDEA", idea128cbc_functions), + ALG("IDEA-OFB:IDEA-OFB64", idea128ofb64_functions), + ALG("IDEA-CFB:IDEA-CFB64", idea128cfb64_functions), #endif /* OPENSSL_NO_IDEA */ #ifndef OPENSSL_NO_CAST - { "CAST5-ECB", "default=yes", cast5128ecb_functions }, - { "CAST5-CBC:CAST-CBC:CAST", "default=yes", cast5128cbc_functions }, - { "CAST5-OFB", "default=yes", cast564ofb64_functions }, - { "CAST5-CFB", "default=yes", cast564cfb64_functions }, + ALG("CAST5-ECB", cast5128ecb_functions), + ALG("CAST5-CBC:CAST-CBC:CAST", cast5128cbc_functions), + ALG("CAST5-OFB", cast564ofb64_functions), + ALG("CAST5-CFB", cast564cfb64_functions), #endif /* OPENSSL_NO_CAST */ #ifndef OPENSSL_NO_SEED - { "SEED-ECB", "default=yes", seed128ecb_functions }, - { "SEED-CBC:SEED", "default=yes", seed128cbc_functions }, - { "SEED-OFB:SEED-OFB128", "default=yes", seed128ofb128_functions }, - { "SEED-CFB:SEED-CFB128", "default=yes", seed128cfb128_functions }, + ALG("SEED-ECB", seed128ecb_functions), + ALG("SEED-CBC:SEED", seed128cbc_functions), + ALG("SEED-OFB:SEED-OFB128", seed128ofb128_functions), + ALG("SEED-CFB:SEED-CFB128", seed128cfb128_functions), #endif /* OPENSSL_NO_SEED */ #ifndef OPENSSL_NO_SM4 - { "SM4-ECB", "default=yes", sm4128ecb_functions }, - { "SM4-CBC:SM4", "default=yes", sm4128cbc_functions }, - { "SM4-CTR", "default=yes", sm4128ctr_functions }, - { "SM4-OFB:SM4-OFB128", "default=yes", sm4128ofb128_functions }, - { "SM4-CFB:SM4-CFB128", "default=yes", sm4128cfb128_functions }, + ALG("SM4-ECB", sm4128ecb_functions), + ALG("SM4-CBC:SM4", sm4128cbc_functions), + ALG("SM4-CTR", sm4128ctr_functions), + ALG("SM4-OFB:SM4-OFB128", sm4128ofb128_functions), + ALG("SM4-CFB:SM4-CFB128", sm4128cfb128_functions), #endif /* OPENSSL_NO_SM4 */ #ifndef OPENSSL_NO_RC4 - { "RC4", "default=yes", rc4128_functions }, - { "RC4-40", "default=yes", rc440_functions }, + ALG("RC4", rc4128_functions), + ALG("RC4-40", rc440_functions), # ifndef OPENSSL_NO_MD5 - { "RC4-HMAC-MD5", "default=yes", rc4_hmac_md5_functions }, + ALG("RC4-HMAC-MD5", rc4_hmac_md5_functions), # endif /* OPENSSL_NO_MD5 */ #endif /* OPENSSL_NO_RC4 */ #ifndef OPENSSL_NO_RC5 - { "RC5-ECB", "default=yes", rc5128ecb_functions }, - { "RC5-CBC", "default=yes", rc5128cbc_functions }, - { "RC5-OFB", "default=yes", rc5128ofb64_functions }, - { "RC5-CFB", "default=yes", rc5128cfb64_functions }, + ALG("RC5-ECB", rc5128ecb_functions), + ALG("RC5-CBC", rc5128cbc_functions), + ALG("RC5-OFB", rc5128ofb64_functions), + ALG("RC5-CFB", rc5128cfb64_functions), #endif /* OPENSSL_NO_RC5 */ #ifndef OPENSSL_NO_RC2 - { "RC2-ECB", "default=yes", rc2128ecb_functions }, - { "RC2-CBC", "default=yes", rc2128cbc_functions }, - { "RC2-40-CBC", "default=yes", rc240cbc_functions }, - { "RC2-64-CBC", "default=yes", rc264cbc_functions }, - { "RC2-CFB", "default=yes", rc2128cfb128_functions }, - { "RC2-OFB", "default=yes", rc2128ofb128_functions }, + ALG("RC2-ECB", rc2128ecb_functions), + ALG("RC2-CBC", rc2128cbc_functions), + ALG("RC2-40-CBC", rc240cbc_functions), + ALG("RC2-64-CBC", rc264cbc_functions), + ALG("RC2-CFB", rc2128cfb128_functions), + ALG("RC2-OFB", rc2128ofb128_functions), #endif /* OPENSSL_NO_RC2 */ #ifndef OPENSSL_NO_CHACHA - { "ChaCha20", "default=yes", chacha20_functions }, + ALG("ChaCha20", chacha20_functions), # ifndef OPENSSL_NO_POLY1305 - { "ChaCha20-Poly1305", "default=yes", chacha20_poly1305_functions }, + ALG("ChaCha20-Poly1305", chacha20_poly1305_functions), # endif /* OPENSSL_NO_POLY1305 */ #endif /* OPENSSL_NO_CHACHA */ - { NULL, NULL, NULL } + { { NULL, NULL, NULL }, NULL } }; +static OSSL_ALGORITHM exported_ciphers[OSSL_NELEM(deflt_ciphers)]; static const OSSL_ALGORITHM deflt_macs[] = { #ifndef OPENSSL_NO_BLAKE2 @@ -432,7 +444,8 @@ static const OSSL_ALGORITHM *deflt_query(OSSL_PROVIDER *prov, case OSSL_OP_DIGEST: return deflt_digests; case OSSL_OP_CIPHER: - return deflt_ciphers; + ossl_prov_cache_exported_algorithms(deflt_ciphers, exported_ciphers); + return exported_ciphers; case OSSL_OP_MAC: return deflt_macs; case OSSL_OP_KDF: diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index 12c471f..7afab78 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -25,12 +25,17 @@ #include "internal/cryptlib.h" #include "internal/property.h" +#include "internal/nelem.h" #include "crypto/evp.h" #include "prov/implementations.h" #include "prov/provider_ctx.h" #include "prov/providercommon.h" +#include "prov/provider_util.h" #include "selftest.h" +#define ALGC(NAMES, FUNC, CHECK) { { NAMES, "fips=yes", FUNC }, CHECK } +#define ALG(NAMES, FUNC) ALGC(NAMES, FUNC, NULL) + extern OSSL_core_thread_start_fn *c_thread_start; /* @@ -300,6 +305,14 @@ const char *ossl_prov_util_nid_to_name(int nid) return "DES-EDE3"; case NID_des_ede3_cbc: return "DES-EDE3-CBC"; + case NID_aes_256_cbc_hmac_sha256: + return "AES-256-CBC-HMAC-SHA256"; + case NID_aes_128_cbc_hmac_sha256: + return "AES-128-CBC-HMAC-SHA256"; + case NID_aes_256_cbc_hmac_sha1: + return "AES-256-CBC-HMAC-SHA1"; + case NID_aes_128_cbc_hmac_sha1: + return "AES-128-CBC-HMAC-SHA1"; default: break; } @@ -358,43 +371,49 @@ static const OSSL_ALGORITHM fips_digests[] = { { NULL, NULL, NULL } }; -static const OSSL_ALGORITHM fips_ciphers[] = { +static const OSSL_ALGORITHM_CAPABLE fips_ciphers[] = { /* Our primary name[:ASN.1 OID name][:our older names] */ - { "AES-256-ECB", "fips=yes", aes256ecb_functions }, - { "AES-192-ECB", "fips=yes", aes192ecb_functions }, - { "AES-128-ECB", "fips=yes", aes128ecb_functions }, - { "AES-256-CBC", "fips=yes", aes256cbc_functions }, - { "AES-192-CBC", "fips=yes", aes192cbc_functions }, - { "AES-128-CBC", "fips=yes", aes128cbc_functions }, - { "AES-256-CTR", "fips=yes", aes256ctr_functions }, - { "AES-192-CTR", "fips=yes", aes192ctr_functions }, - { "AES-128-CTR", "fips=yes", aes128ctr_functions }, - { "AES-256-XTS", "fips=yes", aes256xts_functions }, - { "AES-128-XTS", "fips=yes", aes128xts_functions }, - { "AES-256-GCM:id-aes256-GCM", "fips=yes", aes256gcm_functions }, - { "AES-192-GCM:id-aes192-GCM", "fips=yes", aes192gcm_functions }, - { "AES-128-GCM:id-aes128-GCM", "fips=yes", aes128gcm_functions }, - { "AES-256-CCM:id-aes256-CCM", "fips=yes", aes256ccm_functions }, - { "AES-192-CCM:id-aes192-CCM", "fips=yes", aes192ccm_functions }, - { "AES-128-CCM:id-aes128-CCM", "fips=yes", aes128ccm_functions }, - { "AES-256-WRAP:id-aes256-wrap:AES256-WRAP", "fips=yes", - aes256wrap_functions }, - { "AES-192-WRAP:id-aes192-wrap:AES192-WRAP", "fips=yes", - aes192wrap_functions }, - { "AES-128-WRAP:id-aes128-wrap:AES128-WRAP", "fips=yes", - aes128wrap_functions }, - { "AES-256-WRAP-PAD:id-aes256-wrap-pad:AES256-WRAP-PAD", "fips=yes", - aes256wrappad_functions }, - { "AES-192-WRAP-PAD:id-aes192-wrap-pad:AES192-WRAP-PAD", "fips=yes", - aes192wrappad_functions }, - { "AES-128-WRAP-PAD:id-aes128-wrap-pad:AES128-WRAP-PAD", "fips=yes", - aes128wrappad_functions }, + ALG("AES-256-ECB", aes256ecb_functions), + ALG("AES-192-ECB", aes192ecb_functions), + ALG("AES-128-ECB", aes128ecb_functions), + ALG("AES-256-CBC", aes256cbc_functions), + ALG("AES-192-CBC", aes192cbc_functions), + ALG("AES-128-CBC", aes128cbc_functions), + ALG("AES-256-CTR", aes256ctr_functions), + ALG("AES-192-CTR", aes192ctr_functions), + ALG("AES-128-CTR", aes128ctr_functions), + ALG("AES-256-XTS", aes256xts_functions), + ALG("AES-128-XTS", aes128xts_functions), + ALG("AES-256-GCM:id-aes256-GCM", aes256gcm_functions), + ALG("AES-192-GCM:id-aes192-GCM", aes192gcm_functions), + ALG("AES-128-GCM:id-aes128-GCM", aes128gcm_functions), + ALG("AES-256-CCM:id-aes256-CCM", aes256ccm_functions), + ALG("AES-192-CCM:id-aes192-CCM", aes192ccm_functions), + ALG("AES-128-CCM:id-aes128-CCM", aes128ccm_functions), + ALG("AES-256-WRAP:id-aes256-wrap:AES256-WRAP", aes256wrap_functions), + ALG("AES-192-WRAP:id-aes192-wrap:AES192-WRAP", aes192wrap_functions), + ALG("AES-128-WRAP:id-aes128-wrap:AES128-WRAP", aes128wrap_functions), + ALG("AES-256-WRAP-PAD:id-aes256-wrap-pad:AES256-WRAP-PAD", + aes256wrappad_functions), + ALG("AES-192-WRAP-PAD:id-aes192-wrap-pad:AES192-WRAP-PAD", + aes192wrappad_functions), + ALG("AES-128-WRAP-PAD:id-aes128-wrap-pad:AES128-WRAP-PAD", + aes128wrappad_functions), + ALGC("AES-128-CBC-HMAC-SHA1", aes128cbc_hmac_sha1_functions, + cipher_capable_aes_cbc_hmac_sha1), + ALGC("AES-256-CBC-HMAC-SHA1", aes256cbc_hmac_sha1_functions, + cipher_capable_aes_cbc_hmac_sha1), + ALGC("AES-128-CBC-HMAC-SHA256", aes128cbc_hmac_sha256_functions, + cipher_capable_aes_cbc_hmac_sha256), + ALGC("AES-256-CBC-HMAC-SHA256", aes256cbc_hmac_sha256_functions, + cipher_capable_aes_cbc_hmac_sha256), #ifndef OPENSSL_NO_DES - { "DES-EDE3-ECB:DES-EDE3", "fips=yes", tdes_ede3_ecb_functions }, - { "DES-EDE3-CBC:DES3", "fips=yes", tdes_ede3_cbc_functions }, + ALG("DES-EDE3-ECB:DES-EDE3", tdes_ede3_ecb_functions), + ALG("DES-EDE3-CBC:DES3", tdes_ede3_cbc_functions), #endif /* OPENSSL_NO_DES */ - { NULL, NULL, NULL } + { { NULL, NULL, NULL }, NULL } }; +static OSSL_ALGORITHM exported_fips_ciphers[OSSL_NELEM(fips_ciphers)]; static const OSSL_ALGORITHM fips_macs[] = { #ifndef OPENSSL_NO_CMAC @@ -416,6 +435,7 @@ static const OSSL_ALGORITHM fips_kdfs[] = { { NULL, NULL, NULL } }; + static const OSSL_ALGORITHM *fips_query(OSSL_PROVIDER *prov, int operation_id, int *no_cache) @@ -425,7 +445,8 @@ static const OSSL_ALGORITHM *fips_query(OSSL_PROVIDER *prov, case OSSL_OP_DIGEST: return fips_digests; case OSSL_OP_CIPHER: - return fips_ciphers; + ossl_prov_cache_exported_algorithms(fips_ciphers, exported_fips_ciphers); + return exported_fips_ciphers; case OSSL_OP_MAC: return fips_macs; case OSSL_OP_KDF: diff --git a/providers/implementations/ciphers/build.info b/providers/implementations/ciphers/build.info index abc193b..bff5a2d 100644 --- a/providers/implementations/ciphers/build.info +++ b/providers/implementations/ciphers/build.info @@ -40,7 +40,10 @@ SOURCE[$AES_GOAL]=\ cipher_aes_xts.c cipher_aes_xts_hw.c \ cipher_aes_gcm.c cipher_aes_gcm_hw.c \ cipher_aes_ccm.c cipher_aes_ccm_hw.c \ - cipher_aes_wrp.c + cipher_aes_wrp.c \ + cipher_aes_cbc_hmac_sha.c \ + cipher_aes_cbc_hmac_sha256_hw.c cipher_aes_cbc_hmac_sha1_hw.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 @@ -129,4 +132,3 @@ IF[{- !$disabled{chacha} -}] cipher_chacha20_poly1305.c cipher_chacha20_poly1305_hw.c ENDIF ENDIF - diff --git a/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c new file mode 100644 index 0000000..00b46c3 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c @@ -0,0 +1,345 @@ +/* + * 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_CBC_HMAC_SHA ciphers */ + + +#include "cipher_aes_cbc_hmac_sha.h" +#include "prov/implementations.h" + +#ifndef AES_CBC_HMAC_SHA_CAPABLE +# define IMPLEMENT_CIPHER(nm, sub, kbits, blkbits, ivbits, flags) \ +const OSSL_DISPATCH nm##kbits##sub##_functions[] = { \ + { 0, NULL } \ +}; +#else +# include "prov/providercommonerr.h" + +/* TODO(3.0) Figure out what flags are required */ +# define AES_CBC_HMAC_SHA_FLAGS (EVP_CIPH_CBC_MODE \ + | EVP_CIPH_FLAG_DEFAULT_ASN1 \ + | EVP_CIPH_FLAG_AEAD_CIPHER \ + | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) + +static OSSL_OP_cipher_freectx_fn aes_cbc_hmac_sha1_freectx; +static OSSL_OP_cipher_freectx_fn aes_cbc_hmac_sha256_freectx; +static OSSL_OP_cipher_get_ctx_params_fn aes_get_ctx_params; +static OSSL_OP_cipher_gettable_ctx_params_fn aes_gettable_ctx_params; +static OSSL_OP_cipher_set_ctx_params_fn aes_set_ctx_params; +static OSSL_OP_cipher_settable_ctx_params_fn aes_settable_ctx_params; +# define aes_gettable_params cipher_generic_gettable_params +# define aes_einit cipher_generic_einit +# define aes_dinit cipher_generic_dinit +# define aes_update cipher_generic_stream_update +# define aes_final cipher_generic_stream_final +# define aes_cipher cipher_generic_cipher + +static const OSSL_PARAM cipher_aes_known_settable_ctx_params[] = { + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_MAC_KEY, NULL, 0), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0), +# if !defined(OPENSSL_NO_MULTIBLOCK) + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD, NULL), + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE, NULL), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC, NULL, 0), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN, NULL, 0), +# endif /* !defined(OPENSSL_NO_MULTIBLOCK) */ + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), + OSSL_PARAM_END +}; +const OSSL_PARAM *aes_settable_ctx_params(void) +{ + return cipher_aes_known_settable_ctx_params; +} + +static int aes_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx; + PROV_CIPHER_HW_AES_HMAC_SHA *hw = + (PROV_CIPHER_HW_AES_HMAC_SHA *)ctx->hw; + EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param; + const OSSL_PARAM *p, *p1, *pin; + int ret = 1; + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_MAC_KEY); + if (p != NULL) { + if (p->data_type != OSSL_PARAM_OCTET_STRING) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + hw->init_mac_key(ctx, p->data, p->data_size); + } + +# if !defined(OPENSSL_NO_MULTIBLOCK) + p = OSSL_PARAM_locate_const(params, + OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_SEND_FRAGMENT); + if (p != NULL + && !OSSL_PARAM_get_size_t(p, &ctx->multiblock_max_send_fragment)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + /* + * The inputs to tls1_multiblock_aad are: + * mb_param->inp + * mb_param->len + * mb_param->interleave + * The outputs of tls1_multiblock_aad are written to: + * ctx->multiblock_interleave + * ctx->multiblock_aad_packlen + */ + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD); + if (p != NULL) { + p1 = OSSL_PARAM_locate_const(params, + OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE); + if (p->data_type != OSSL_PARAM_OCTET_STRING + || p1 == NULL + || !OSSL_PARAM_get_uint(p1, &mb_param.interleave)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + mb_param.inp = p->data; + mb_param.len = p->data_size; + if (hw->tls1_multiblock_aad(vctx, &mb_param) <= 0) + return 0; + } + + /* + * The inputs to tls1_multiblock_encrypt are: + * mb_param->inp + * mb_param->len + * mb_param->interleave + * mb_param->out + * The outputs of tls1_multiblock_encrypt are: + * ctx->multiblock_encrypt_len + */ + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC); + if (p != NULL) { + p1 = OSSL_PARAM_locate_const(params, + OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE); + pin = OSSL_PARAM_locate_const(params, + OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_IN); + if (p->data_type != OSSL_PARAM_OCTET_STRING + || pin == NULL + || pin->data_type != OSSL_PARAM_OCTET_STRING + || p1 == NULL + || !OSSL_PARAM_get_uint(p1, &mb_param.interleave)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + mb_param.out = p->data; + mb_param.inp = pin->data; + mb_param.len = pin->data_size; + if (hw->tls1_multiblock_encrypt(vctx, &mb_param) <= 0) + return 0; + } +# endif /* !defined(OPENSSL_NO_MULTIBLOCK) */ + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD); + if (p != NULL) { + if (p->data_type != OSSL_PARAM_OCTET_STRING) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + if (hw->set_tls1_aad(ctx, p->data, p->data_size) <= 0) + return 0; + } + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p != NULL) { + size_t keylen; + + if (!OSSL_PARAM_get_size_t(p, &keylen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + if (ctx->base.keylen != keylen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + } + return ret; +} + +static int aes_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx; + PROV_CIPHER_HW_AES_HMAC_SHA *hw = + (PROV_CIPHER_HW_AES_HMAC_SHA *)ctx->hw; + OSSL_PARAM *p; + +# if !defined(OPENSSL_NO_MULTIBLOCK) + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE); + if (p != NULL) { + size_t len = hw->tls1_multiblock_max_bufsize(ctx); + + if (!OSSL_PARAM_set_size_t(p, len)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE); + if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->multiblock_interleave)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN); + if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->multiblock_aad_packlen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->multiblock_encrypt_len)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } +# endif /* !defined(OPENSSL_NO_MULTIBLOCK) */ + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.keylen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->base.ivlen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV); + if (p != NULL + && !OSSL_PARAM_set_octet_string(p, ctx->base.oiv, ctx->base.ivlen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + return 1; +} + +static const OSSL_PARAM cipher_aes_known_gettable_ctx_params[] = { +# if !defined(OPENSSL_NO_MULTIBLOCK) + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_MAX_BUFSIZE, NULL), + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_INTERLEAVE, NULL), + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_AAD_PACKLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK_ENC_LEN, NULL), +# endif /* !defined(OPENSSL_NO_MULTIBLOCK) */ + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0), + OSSL_PARAM_END +}; +const OSSL_PARAM *aes_gettable_ctx_params(void) +{ + return cipher_aes_known_gettable_ctx_params; +} + +static void base_init(void *provctx, PROV_AES_HMAC_SHA_CTX *ctx, + const PROV_CIPHER_HW_AES_HMAC_SHA *meths, + size_t kbits, size_t blkbits, size_t ivbits, + uint64_t flags) +{ + cipher_generic_initkey(&ctx->base, kbits, blkbits, ivbits, + EVP_CIPH_CBC_MODE, flags, + &meths->base, provctx); + ctx->hw = (PROV_CIPHER_HW_AES_HMAC_SHA *)ctx->base.hw; +} + +static void *aes_cbc_hmac_sha1_newctx(void *provctx, size_t kbits, + size_t blkbits, size_t ivbits, + uint64_t flags) +{ + PROV_AES_HMAC_SHA1_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx != NULL) + base_init(provctx, &ctx->base_ctx, + PROV_CIPHER_HW_aes_cbc_hmac_sha1(), kbits, blkbits, + ivbits, flags); + return ctx; +} + +static void aes_cbc_hmac_sha1_freectx(void *vctx) +{ + PROV_AES_HMAC_SHA1_CTX *ctx = (PROV_AES_HMAC_SHA1_CTX *)vctx; + + if (ctx != NULL) + OPENSSL_clear_free(ctx, sizeof(ctx)); +} + +static void *aes_cbc_hmac_sha256_newctx(void *provctx, size_t kbits, + size_t blkbits, size_t ivbits, + uint64_t flags) +{ + PROV_AES_HMAC_SHA256_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx != NULL) + base_init(provctx, &ctx->base_ctx, + PROV_CIPHER_HW_aes_cbc_hmac_sha256(), kbits, blkbits, + ivbits, flags); + return ctx; +} + +static void aes_cbc_hmac_sha256_freectx(void *vctx) +{ + PROV_AES_HMAC_SHA256_CTX *ctx = (PROV_AES_HMAC_SHA256_CTX *)vctx; + + if (ctx != NULL) + OPENSSL_clear_free(ctx, sizeof(ctx)); +} + +# define IMPLEMENT_CIPHER(nm, sub, kbits, blkbits, ivbits, flags) \ +static OSSL_OP_cipher_newctx_fn nm##_##kbits##_##sub##_newctx; \ +static void *nm##_##kbits##_##sub##_newctx(void *provctx) \ +{ \ + return nm##_##sub##_newctx(provctx, kbits, blkbits, ivbits, flags); \ +} \ +static OSSL_OP_cipher_get_params_fn nm##_##kbits##_##sub##_get_params; \ +static int nm##_##kbits##_##sub##_get_params(OSSL_PARAM params[]) \ +{ \ + return cipher_generic_get_params(params, EVP_CIPH_CBC_MODE, \ + flags, kbits, blkbits, ivbits); \ +} \ +const OSSL_DISPATCH nm##kbits##sub##_functions[] = { \ + { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))nm##_##kbits##_##sub##_newctx },\ + { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))nm##_##sub##_freectx }, \ + { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))nm##_einit }, \ + { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))nm##_dinit }, \ + { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))nm##_update }, \ + { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))nm##_final }, \ + { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))nm##_cipher }, \ + { OSSL_FUNC_CIPHER_GET_PARAMS, \ + (void (*)(void))nm##_##kbits##_##sub##_get_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ + (void (*)(void))nm##_gettable_params }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ + (void (*)(void))nm##_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ + (void (*)(void))nm##_gettable_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ + (void (*)(void))nm##_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ + (void (*)(void))nm##_settable_ctx_params }, \ + { 0, NULL } \ +}; + +#endif /* AES_CBC_HMAC_SHA_CAPABLE */ + +/* aes128cbc_hmac_sha1_functions */ +IMPLEMENT_CIPHER(aes, cbc_hmac_sha1, 128, 128, 128, AES_CBC_HMAC_SHA_FLAGS) +/* aes256cbc_hmac_sha1_functions */ +IMPLEMENT_CIPHER(aes, cbc_hmac_sha1, 256, 128, 128, AES_CBC_HMAC_SHA_FLAGS) +/* aes128cbc_hmac_sha256_functions */ +IMPLEMENT_CIPHER(aes, cbc_hmac_sha256, 128, 128, 128, AES_CBC_HMAC_SHA_FLAGS) +/* aes256cbc_hmac_sha256_functions */ +IMPLEMENT_CIPHER(aes, cbc_hmac_sha256, 256, 128, 128, AES_CBC_HMAC_SHA_FLAGS) diff --git a/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.h b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.h new file mode 100644 index 0000000..86da791 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.h @@ -0,0 +1,65 @@ +/* + * 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/aes_platform.h" + +int cipher_capable_aes_cbc_hmac_sha1(void); +int cipher_capable_aes_cbc_hmac_sha256(void); + +#ifdef AES_CBC_HMAC_SHA_CAPABLE +# include <openssl/aes.h> +# include <openssl/sha.h> + +typedef struct prov_cipher_hw_aes_hmac_sha_ctx_st { + PROV_CIPHER_HW base; /* must be first */ + void (*init_mac_key)(void *ctx, const unsigned char *inkey, size_t inlen); + int (*set_tls1_aad)(void *ctx, unsigned char *aad_rec, int aad_len); +# if !defined(OPENSSL_NO_MULTIBLOCK) + int (*tls1_multiblock_max_bufsize)(void *ctx); + int (*tls1_multiblock_aad)( + void *vctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param); + int (*tls1_multiblock_encrypt)( + void *ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param); +# endif /* OPENSSL_NO_MULTIBLOCK) */ +} PROV_CIPHER_HW_AES_HMAC_SHA; + +typedef struct prov_aes_hmac_sha_ctx_st { + PROV_CIPHER_CTX base; + AES_KEY ks; + size_t payload_length; /* AAD length in decrypt case */ + union { + unsigned int tls_ver; + unsigned char tls_aad[16]; /* 13 used */ + } aux; + const PROV_CIPHER_HW_AES_HMAC_SHA *hw; + /* some value that are setup by set methods - that can be retrieved */ + unsigned int multiblock_interleave; + unsigned int multiblock_aad_packlen; + size_t multiblock_max_send_fragment; + size_t multiblock_encrypt_len; + size_t tls_aad_pad; +} PROV_AES_HMAC_SHA_CTX; + +typedef struct prov_aes_hmac_sha1_ctx_st { + PROV_AES_HMAC_SHA_CTX base_ctx; + SHA_CTX head, tail, md; +} PROV_AES_HMAC_SHA1_CTX; + +typedef struct prov_aes_hmac_sha256_ctx_st { + PROV_AES_HMAC_SHA_CTX base_ctx; + SHA256_CTX head, tail, md; +} PROV_AES_HMAC_SHA256_CTX; + +# define NO_PAYLOAD_LENGTH ((size_t)-1) + +const PROV_CIPHER_HW_AES_HMAC_SHA *PROV_CIPHER_HW_aes_cbc_hmac_sha1(void); +const PROV_CIPHER_HW_AES_HMAC_SHA *PROV_CIPHER_HW_aes_cbc_hmac_sha256(void); + +#endif /* AES_CBC_HMAC_SHA_CAPABLE */ diff --git a/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha1_hw.c b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha1_hw.c new file mode 100644 index 0000000..125369d --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha1_hw.c @@ -0,0 +1,782 @@ +/* + * Copyright 2011-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_cbc_hmac_sha.h" + +#ifndef AES_CBC_HMAC_SHA_CAPABLE +int cipher_capable_aes_cbc_hmac_sha1(void) +{ + return 0; +} +#else + +# include "crypto/rand.h" +# include "crypto/evp.h" +# include "internal/constant_time.h" + +void sha1_block_data_order(void *c, const void *p, size_t len); +void aesni_cbc_sha1_enc(const void *inp, void *out, size_t blocks, + const AES_KEY *key, unsigned char iv[16], + SHA_CTX *ctx, const void *in0); + +int cipher_capable_aes_cbc_hmac_sha1(void) +{ + return AESNI_CBC_HMAC_SHA_CAPABLE; +} + +static int aesni_cbc_hmac_sha1_init_key(PROV_CIPHER_CTX *vctx, + const unsigned char *key, size_t keylen) +{ + int ret; + PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx; + PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx; + + if (ctx->base.enc) + ret = aesni_set_encrypt_key(key, keylen * 8, &ctx->ks); + else + ret = aesni_set_decrypt_key(key, keylen * 8, &ctx->ks); + + SHA1_Init(&sctx->head); /* handy when benchmarking */ + sctx->tail = sctx->head; + sctx->md = sctx->head; + + ctx->payload_length = NO_PAYLOAD_LENGTH; + + return ret < 0 ? 0 : 1; +} + +static void sha1_update(SHA_CTX *c, const void *data, size_t len) +{ + const unsigned char *ptr = data; + size_t res; + + if ((res = c->num)) { + res = SHA_CBLOCK - res; + if (len < res) + res = len; + SHA1_Update(c, ptr, res); + ptr += res; + len -= res; + } + + res = len % SHA_CBLOCK; + len -= res; + + if (len) { + sha1_block_data_order(c, ptr, len / SHA_CBLOCK); + + ptr += len; + c->Nh += len >> 29; + c->Nl += len <<= 3; + if (c->Nl < (unsigned int)len) + c->Nh++; + } + + if (res) + SHA1_Update(c, ptr, res); +} + +# if !defined(OPENSSL_NO_MULTIBLOCK) + +typedef struct { + unsigned int A[8], B[8], C[8], D[8], E[8]; +} SHA1_MB_CTX; + +typedef struct { + const unsigned char *ptr; + int blocks; +} HASH_DESC; + +typedef struct { + const unsigned char *inp; + unsigned char *out; + int blocks; + u64 iv[2]; +} CIPH_DESC; + +void sha1_multi_block(SHA1_MB_CTX *, const HASH_DESC *, int); +void aesni_multi_cbc_encrypt(CIPH_DESC *, void *, int); + +static size_t tls1_multi_block_encrypt(void *vctx, + unsigned char *out, + const unsigned char *inp, + size_t inp_len, int n4x) +{ /* n4x is 1 or 2 */ + PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx; + PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx; + HASH_DESC hash_d[8], edges[8]; + CIPH_DESC ciph_d[8]; + unsigned char storage[sizeof(SHA1_MB_CTX) + 32]; + union { + u64 q[16]; + u32 d[32]; + u8 c[128]; + } blocks[8]; + SHA1_MB_CTX *mctx; + unsigned int frag, last, packlen, i; + unsigned int x4 = 4 * n4x, minblocks, processed = 0; + size_t ret = 0; + u8 *IVs; +# if defined(BSWAP8) + u64 seqnum; +# endif + + /* ask for IVs in bulk */ + if (rand_bytes_ex(ctx->base.libctx, (IVs = blocks[0].c), 16 * x4) <= 0) + return 0; + + mctx = (SHA1_MB_CTX *) (storage + 32 - ((size_t)storage % 32)); /* align */ + + frag = (unsigned int)inp_len >> (1 + n4x); + last = (unsigned int)inp_len + frag - (frag << (1 + n4x)); + if (last > frag && ((last + 13 + 9) % 64) < (x4 - 1)) { + frag++; + last -= x4 - 1; + } + + packlen = 5 + 16 + ((frag + 20 + 16) & -16); + + /* populate descriptors with pointers and IVs */ + hash_d[0].ptr = inp; + ciph_d[0].inp = inp; + /* 5+16 is place for header and explicit IV */ + ciph_d[0].out = out + 5 + 16; + memcpy(ciph_d[0].out - 16, IVs, 16); + memcpy(ciph_d[0].iv, IVs, 16); + IVs += 16; + + for (i = 1; i < x4; i++) { + ciph_d[i].inp = hash_d[i].ptr = hash_d[i - 1].ptr + frag; + ciph_d[i].out = ciph_d[i - 1].out + packlen; + memcpy(ciph_d[i].out - 16, IVs, 16); + memcpy(ciph_d[i].iv, IVs, 16); + IVs += 16; + } + +# if defined(BSWAP8) + memcpy(blocks[0].c, sctx->md.data, 8); + seqnum = BSWAP8(blocks[0].q[0]); +# endif + for (i = 0; i < x4; i++) { + unsigned int len = (i == (x4 - 1) ? last : frag); +# if !defined(BSWAP8) + unsigned int carry, j; +# endif + + mctx->A[i] = sctx->md.h0; + mctx->B[i] = sctx->md.h1; + mctx->C[i] = sctx->md.h2; + mctx->D[i] = sctx->md.h3; + mctx->E[i] = sctx->md.h4; + + /* fix seqnum */ +# if defined(BSWAP8) + blocks[i].q[0] = BSWAP8(seqnum + i); +# else + for (carry = i, j = 8; j--;) { + blocks[i].c[j] = ((u8 *)sctx->md.data)[j] + carry; + carry = (blocks[i].c[j] - carry) >> (sizeof(carry) * 8 - 1); + } +# endif + blocks[i].c[8] = ((u8 *)sctx->md.data)[8]; + blocks[i].c[9] = ((u8 *)sctx->md.data)[9]; + blocks[i].c[10] = ((u8 *)sctx->md.data)[10]; + /* fix length */ + blocks[i].c[11] = (u8)(len >> 8); + blocks[i].c[12] = (u8)(len); + + memcpy(blocks[i].c + 13, hash_d[i].ptr, 64 - 13); + hash_d[i].ptr += 64 - 13; + hash_d[i].blocks = (len - (64 - 13)) / 64; + + edges[i].ptr = blocks[i].c; + edges[i].blocks = 1; + } + + /* hash 13-byte headers and first 64-13 bytes of inputs */ + sha1_multi_block(mctx, edges, n4x); + /* hash bulk inputs */ +# define MAXCHUNKSIZE 2048 +# if MAXCHUNKSIZE%64 +# error "MAXCHUNKSIZE is not divisible by 64" +# elif MAXCHUNKSIZE + /* + * goal is to minimize pressure on L1 cache by moving in shorter steps, + * so that hashed data is still in the cache by the time we encrypt it + */ + minblocks = ((frag <= last ? frag : last) - (64 - 13)) / 64; + if (minblocks > MAXCHUNKSIZE / 64) { + for (i = 0; i < x4; i++) { + edges[i].ptr = hash_d[i].ptr; + edges[i].blocks = MAXCHUNKSIZE / 64; + ciph_d[i].blocks = MAXCHUNKSIZE / 16; + } + do { + sha1_multi_block(mctx, edges, n4x); + aesni_multi_cbc_encrypt(ciph_d, &ctx->ks, n4x); + + for (i = 0; i < x4; i++) { + edges[i].ptr = hash_d[i].ptr += MAXCHUNKSIZE; + hash_d[i].blocks -= MAXCHUNKSIZE / 64; + edges[i].blocks = MAXCHUNKSIZE / 64; + ciph_d[i].inp += MAXCHUNKSIZE; + ciph_d[i].out += MAXCHUNKSIZE; + ciph_d[i].blocks = MAXCHUNKSIZE / 16; + memcpy(ciph_d[i].iv, ciph_d[i].out - 16, 16); + } + processed += MAXCHUNKSIZE; + minblocks -= MAXCHUNKSIZE / 64; + } while (minblocks > MAXCHUNKSIZE / 64); + } +# endif +# undef MAXCHUNKSIZE + sha1_multi_block(mctx, hash_d, n4x); + + memset(blocks, 0, sizeof(blocks)); + for (i = 0; i < x4; i++) { + unsigned int len = (i == (x4 - 1) ? last : frag), + off = hash_d[i].blocks * 64; + const unsigned char *ptr = hash_d[i].ptr + off; + + off = (len - processed) - (64 - 13) - off; /* remainder actually */ + memcpy(blocks[i].c, ptr, off); + blocks[i].c[off] = 0x80; + len += 64 + 13; /* 64 is HMAC header */ + len *= 8; /* convert to bits */ + if (off < (64 - 8)) { +# ifdef BSWAP4 + blocks[i].d[15] = BSWAP4(len); +# else + PUTU32(blocks[i].c + 60, len); +# endif + edges[i].blocks = 1; + } else { +# ifdef BSWAP4 + blocks[i].d[31] = BSWAP4(len); +# else + PUTU32(blocks[i].c + 124, len); +# endif + edges[i].blocks = 2; + } + edges[i].ptr = blocks[i].c; + } + + /* hash input tails and finalize */ + sha1_multi_block(mctx, edges, n4x); + + memset(blocks, 0, sizeof(blocks)); + for (i = 0; i < x4; i++) { +# ifdef BSWAP4 + blocks[i].d[0] = BSWAP4(mctx->A[i]); + mctx->A[i] = sctx->tail.h0; + blocks[i].d[1] = BSWAP4(mctx->B[i]); + mctx->B[i] = sctx->tail.h1; + blocks[i].d[2] = BSWAP4(mctx->C[i]); + mctx->C[i] = sctx->tail.h2; + blocks[i].d[3] = BSWAP4(mctx->D[i]); + mctx->D[i] = sctx->tail.h3; + blocks[i].d[4] = BSWAP4(mctx->E[i]); + mctx->E[i] = sctx->tail.h4; + blocks[i].c[20] = 0x80; + blocks[i].d[15] = BSWAP4((64 + 20) * 8); +# else + PUTU32(blocks[i].c + 0, mctx->A[i]); + mctx->A[i] = sctx->tail.h0; + PUTU32(blocks[i].c + 4, mctx->B[i]); + mctx->B[i] = sctx->tail.h1; + PUTU32(blocks[i].c + 8, mctx->C[i]); + mctx->C[i] = sctx->tail.h2; + PUTU32(blocks[i].c + 12, mctx->D[i]); + mctx->D[i] = sctx->tail.h3; + PUTU32(blocks[i].c + 16, mctx->E[i]); + mctx->E[i] = sctx->tail.h4; + blocks[i].c[20] = 0x80; + PUTU32(blocks[i].c + 60, (64 + 20) * 8); +# endif /* BSWAP */ + edges[i].ptr = blocks[i].c; + edges[i].blocks = 1; + } + + /* finalize MACs */ + sha1_multi_block(mctx, edges, n4x); + + for (i = 0; i < x4; i++) { + unsigned int len = (i == (x4 - 1) ? last : frag), pad, j; + unsigned char *out0 = out; + + memcpy(ciph_d[i].out, ciph_d[i].inp, len - processed); + ciph_d[i].inp = ciph_d[i].out; + + out += 5 + 16 + len; + + /* write MAC */ + PUTU32(out + 0, mctx->A[i]); + PUTU32(out + 4, mctx->B[i]); + PUTU32(out + 8, mctx->C[i]); + PUTU32(out + 12, mctx->D[i]); + PUTU32(out + 16, mctx->E[i]); + out += 20; + len += 20; + + /* pad */ + pad = 15 - len % 16; + for (j = 0; j <= pad; j++) + *(out++) = pad; + len += pad + 1; + + ciph_d[i].blocks = (len - processed) / 16; + len += 16; /* account for explicit iv */ + + /* arrange header */ + out0[0] = ((u8 *)sctx->md.data)[8]; + out0[1] = ((u8 *)sctx->md.data)[9]; + out0[2] = ((u8 *)sctx->md.data)[10]; + out0[3] = (u8)(len >> 8); + out0[4] = (u8)(len); + + ret += len + 5; + inp += frag; + } + + aesni_multi_cbc_encrypt(ciph_d, &ctx->ks, n4x); + + OPENSSL_cleanse(blocks, sizeof(blocks)); + OPENSSL_cleanse(mctx, sizeof(*mctx)); + + ctx->multiblock_encrypt_len = ret; + return ret; +} +# endif /* OPENSSL_NO_MULTIBLOCK */ + +static int aesni_cbc_hmac_sha1_cipher(PROV_CIPHER_CTX *vctx, + unsigned char *out, + const unsigned char *in, size_t len) +{ + PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx; + PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx; + unsigned int l; + size_t plen = ctx->payload_length; + size_t iv = 0; /* explicit IV in TLS 1.1 and later */ + size_t aes_off = 0, blocks; + size_t sha_off = SHA_CBLOCK - sctx->md.num; + + ctx->payload_length = NO_PAYLOAD_LENGTH; + + if (len % AES_BLOCK_SIZE) + return 0; + + if (ctx->base.enc) { + if (plen == NO_PAYLOAD_LENGTH) + plen = len; + else if (len != + ((plen + SHA_DIGEST_LENGTH + + AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)) + return 0; + else if (ctx->aux.tls_ver >= TLS1_1_VERSION) + iv = AES_BLOCK_SIZE; + + if (plen > (sha_off + iv) + && (blocks = (plen - (sha_off + iv)) / SHA_CBLOCK)) { + sha1_update(&sctx->md, in + iv, sha_off); + + aesni_cbc_sha1_enc(in, out, blocks, &ctx->ks, ctx->base.iv, + &sctx->md, in + iv + sha_off); + blocks *= SHA_CBLOCK; + aes_off += blocks; + sha_off += blocks; + sctx->md.Nh += blocks >> 29; + sctx->md.Nl += blocks <<= 3; + if (sctx->md.Nl < (unsigned int)blocks) + sctx->md.Nh++; + } else { + sha_off = 0; + } + sha_off += iv; + sha1_update(&sctx->md, in + sha_off, plen - sha_off); + + if (plen != len) { /* "TLS" mode of operation */ + if (in != out) + memcpy(out + aes_off, in + aes_off, plen - aes_off); + + /* calculate HMAC and append it to payload */ + SHA1_Final(out + plen, &sctx->md); + sctx->md = sctx->tail; + sha1_update(&sctx->md, out + plen, SHA_DIGEST_LENGTH); + SHA1_Final(out + plen, &sctx->md); + + /* pad the payload|hmac */ + plen += SHA_DIGEST_LENGTH; + for (l = len - plen - 1; plen < len; plen++) + out[plen] = l; + /* encrypt HMAC|padding at once */ + aesni_cbc_encrypt(out + aes_off, out + aes_off, len - aes_off, + &ctx->ks, ctx->base.iv, 1); + } else { + aesni_cbc_encrypt(in + aes_off, out + aes_off, len - aes_off, + &ctx->ks, ctx->base.iv, 1); + } + } else { + union { + unsigned int u[SHA_DIGEST_LENGTH / sizeof(unsigned int)]; + unsigned char c[32 + SHA_DIGEST_LENGTH]; + } mac, *pmac; + + /* arrange cache line alignment */ + pmac = (void *)(((size_t)mac.c + 31) & ((size_t)0 - 32)); + + if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */ + size_t inp_len, mask, j, i; + unsigned int res, maxpad, pad, bitlen; + int ret = 1; + union { + unsigned int u[SHA_LBLOCK]; + unsigned char c[SHA_CBLOCK]; + } *data = (void *)sctx->md.data; + + if ((ctx->aux.tls_aad[plen - 4] << 8 | ctx->aux.tls_aad[plen - 3]) + >= TLS1_1_VERSION) { + if (len < (AES_BLOCK_SIZE + SHA_DIGEST_LENGTH + 1)) + return 0; + + /* omit explicit iv */ + memcpy(ctx->base.iv, in, AES_BLOCK_SIZE); + + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + len -= AES_BLOCK_SIZE; + } else if (len < (SHA_DIGEST_LENGTH + 1)) + return 0; + + /* decrypt HMAC|padding at once */ + aesni_cbc_encrypt(in, out, len, &ctx->ks, ctx->base.iv, 0); + + /* figure out payload length */ + pad = out[len - 1]; + maxpad = len - (SHA_DIGEST_LENGTH + 1); + maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8); + maxpad &= 255; + + mask = constant_time_ge(maxpad, pad); + ret &= mask; + /* + * If pad is invalid then we will fail the above test but we must + * continue anyway because we are in constant time code. However, + * we'll use the maxpad value instead of the supplied pad to make + * sure we perform well defined pointer arithmetic. + */ + pad = constant_time_select(mask, pad, maxpad); + + inp_len = len - (SHA_DIGEST_LENGTH + pad + 1); + + ctx->aux.tls_aad[plen - 2] = inp_len >> 8; + ctx->aux.tls_aad[plen - 1] = inp_len; + + /* calculate HMAC */ + sctx->md = sctx->head; + sha1_update(&sctx->md, ctx->aux.tls_aad, plen); + + /* code containing lucky-13 fix */ + len -= SHA_DIGEST_LENGTH; /* amend mac */ + if (len >= (256 + SHA_CBLOCK)) { + j = (len - (256 + SHA_CBLOCK)) & (0 - SHA_CBLOCK); + j += SHA_CBLOCK - sctx->md.num; + sha1_update(&sctx->md, out, j); + out += j; + len -= j; + inp_len -= j; + } + + /* but pretend as if we hashed padded payload */ + bitlen = sctx->md.Nl + (inp_len << 3); /* at most 18 bits */ +# ifdef BSWAP4 + bitlen = BSWAP4(bitlen); +# else + mac.c[0] = 0; + mac.c[1] = (unsigned char)(bitlen >> 16); + mac.c[2] = (unsigned char)(bitlen >> 8); + mac.c[3] = (unsigned char)bitlen; + bitlen = mac.u[0]; +# endif /* BSWAP */ + + pmac->u[0] = 0; + pmac->u[1] = 0; + pmac->u[2] = 0; + pmac->u[3] = 0; + pmac->u[4] = 0; + + for (res = sctx->md.num, j = 0; j < len; j++) { + size_t c = out[j]; + mask = (j - inp_len) >> (sizeof(j) * 8 - 8); + c &= mask; + c |= 0x80 & ~mask & ~((inp_len - j) >> (sizeof(j) * 8 - 8)); + data->c[res++] = (unsigned char)c; + + if (res != SHA_CBLOCK) + continue; + + /* j is not incremented yet */ + mask = 0 - ((inp_len + 7 - j) >> (sizeof(j) * 8 - 1)); + data->u[SHA_LBLOCK - 1] |= bitlen & mask; + sha1_block_data_order(&sctx->md, data, 1); + mask &= 0 - ((j - inp_len - 72) >> (sizeof(j) * 8 - 1)); + pmac->u[0] |= sctx->md.h0 & mask; + pmac->u[1] |= sctx->md.h1 & mask; + pmac->u[2] |= sctx->md.h2 & mask; + pmac->u[3] |= sctx->md.h3 & mask; + pmac->u[4] |= sctx->md.h4 & mask; + res = 0; + } + + for (i = res; i < SHA_CBLOCK; i++, j++) + data->c[i] = 0; + + if (res > SHA_CBLOCK - 8) { + mask = 0 - ((inp_len + 8 - j) >> (sizeof(j) * 8 - 1)); + data->u[SHA_LBLOCK - 1] |= bitlen & mask; + sha1_block_data_order(&sctx->md, data, 1); + mask &= 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1)); + pmac->u[0] |= sctx->md.h0 & mask; + pmac->u[1] |= sctx->md.h1 & mask; + pmac->u[2] |= sctx->md.h2 & mask; + pmac->u[3] |= sctx->md.h3 & mask; + pmac->u[4] |= sctx->md.h4 & mask; + + memset(data, 0, SHA_CBLOCK); + j += 64; + } + data->u[SHA_LBLOCK - 1] = bitlen; + sha1_block_data_order(&sctx->md, data, 1); + mask = 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1)); + pmac->u[0] |= sctx->md.h0 & mask; + pmac->u[1] |= sctx->md.h1 & mask; + pmac->u[2] |= sctx->md.h2 & mask; + pmac->u[3] |= sctx->md.h3 & mask; + pmac->u[4] |= sctx->md.h4 & mask; + +# ifdef BSWAP4 + pmac->u[0] = BSWAP4(pmac->u[0]); + pmac->u[1] = BSWAP4(pmac->u[1]); + pmac->u[2] = BSWAP4(pmac->u[2]); + pmac->u[3] = BSWAP4(pmac->u[3]); + pmac->u[4] = BSWAP4(pmac->u[4]); +# else + for (i = 0; i < 5; i++) { + res = pmac->u[i]; + pmac->c[4 * i + 0] = (unsigned char)(res >> 24); + pmac->c[4 * i + 1] = (unsigned char)(res >> 16); + pmac->c[4 * i + 2] = (unsigned char)(res >> 8); + pmac->c[4 * i + 3] = (unsigned char)res; + } +# endif /* BSWAP4 */ + len += SHA_DIGEST_LENGTH; + sctx->md = sctx->tail; + sha1_update(&sctx->md, pmac->c, SHA_DIGEST_LENGTH); + SHA1_Final(pmac->c, &sctx->md); + + /* verify HMAC */ + out += inp_len; + len -= inp_len; + /* version of code with lucky-13 fix */ + { + unsigned char *p = out + len - 1 - maxpad - SHA_DIGEST_LENGTH; + size_t off = out - p; + unsigned int c, cmask; + + maxpad += SHA_DIGEST_LENGTH; + for (res = 0, i = 0, j = 0; j < maxpad; j++) { + c = p[j]; + cmask = + ((int)(j - off - SHA_DIGEST_LENGTH)) >> (sizeof(int) * + 8 - 1); + res |= (c ^ pad) & ~cmask; /* ... and padding */ + cmask &= ((int)(off - 1 - j)) >> (sizeof(int) * 8 - 1); + res |= (c ^ pmac->c[i]) & cmask; + i += 1 & cmask; + } + maxpad -= SHA_DIGEST_LENGTH; + + res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1)); + ret &= (int)~res; + } + return ret; + } else { + /* decrypt HMAC|padding at once */ + aesni_cbc_encrypt(in, out, len, &ctx->ks, ctx->base.iv, 0); + sha1_update(&sctx->md, out, len); + } + } + + return 1; +} + +/* EVP_CTRL_AEAD_SET_MAC_KEY */ +static void aesni_cbc_hmac_sha1_set_mac_key(void *vctx, + const unsigned char *mac, size_t len) +{ + PROV_AES_HMAC_SHA1_CTX *ctx = (PROV_AES_HMAC_SHA1_CTX *)vctx; + unsigned int i; + unsigned char hmac_key[64]; + + memset(hmac_key, 0, sizeof(hmac_key)); + + if (len > (int)sizeof(hmac_key)) { + SHA1_Init(&ctx->head); + sha1_update(&ctx->head, mac, len); + SHA1_Final(hmac_key, &ctx->head); + } else { + memcpy(hmac_key, mac, len); + } + + for (i = 0; i < sizeof(hmac_key); i++) + hmac_key[i] ^= 0x36; /* ipad */ + SHA1_Init(&ctx->head); + sha1_update(&ctx->head, hmac_key, sizeof(hmac_key)); + + for (i = 0; i < sizeof(hmac_key); i++) + hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */ + SHA1_Init(&ctx->tail); + sha1_update(&ctx->tail, hmac_key, sizeof(hmac_key)); + + OPENSSL_cleanse(hmac_key, sizeof(hmac_key)); +} + +/* EVP_CTRL_AEAD_TLS1_AAD */ +static int aesni_cbc_hmac_sha1_set_tls1_aad(void *vctx, + unsigned char *aad_rec, int aad_len) +{ + PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx; + PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx; + unsigned char *p = aad_rec; + unsigned int len; + + if (aad_len != EVP_AEAD_TLS1_AAD_LEN) + return -1; + + len = p[aad_len - 2] << 8 | p[aad_len - 1]; + + if (ctx->base.enc) { + ctx->payload_length = len; + if ((ctx->aux.tls_ver = + p[aad_len - 4] << 8 | p[aad_len - 3]) >= TLS1_1_VERSION) { + if (len < AES_BLOCK_SIZE) + return 0; + len -= AES_BLOCK_SIZE; + p[aad_len - 2] = len >> 8; + p[aad_len - 1] = len; + } + sctx->md = sctx->head; + sha1_update(&sctx->md, p, aad_len); + ctx->tls_aad_pad = (int)(((len + SHA_DIGEST_LENGTH + + AES_BLOCK_SIZE) & -AES_BLOCK_SIZE) + - len); + return 1; + } else { + memcpy(ctx->aux.tls_aad, aad_rec, aad_len); + ctx->payload_length = aad_len; + ctx->tls_aad_pad = SHA_DIGEST_LENGTH; + return 1; + } +} + +# if !defined(OPENSSL_NO_MULTIBLOCK) + +/* EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE */ +static int aesni_cbc_hmac_sha1_tls1_multiblock_max_bufsize(void *vctx) +{ + PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx; + + OPENSSL_assert(ctx->multiblock_max_send_fragment != 0); + return (int)(5 + 16 + + (((int)ctx->multiblock_max_send_fragment + 20 + 16) & -16)); +} + +/* EVP_CTRL_TLS1_1_MULTIBLOCK_AAD */ +static int aesni_cbc_hmac_sha1_tls1_multiblock_aad( + void *vctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param) +{ + PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx; + PROV_AES_HMAC_SHA1_CTX *sctx = (PROV_AES_HMAC_SHA1_CTX *)vctx; + unsigned int n4x = 1, x4; + unsigned int frag, last, packlen, inp_len; + + inp_len = param->inp[11] << 8 | param->inp[12]; + ctx->multiblock_interleave = param->interleave; + + if (ctx->base.enc) { + if ((param->inp[9] << 8 | param->inp[10]) < TLS1_1_VERSION) + return -1; + + if (inp_len) { + if (inp_len < 4096) + return 0; /* too short */ + + if (inp_len >= 8192 && OPENSSL_ia32cap_P[2] & (1 << 5)) + n4x = 2; /* AVX2 */ + } else if ((n4x = param->interleave / 4) && n4x <= 2) + inp_len = param->len; + else + return -1; + + sctx->md = sctx->head; + sha1_update(&sctx->md, param->inp, 13); + + x4 = 4 * n4x; + n4x += 1; + + frag = inp_len >> n4x; + last = inp_len + frag - (frag << n4x); + if (last > frag && ((last + 13 + 9) % 64 < (x4 - 1))) { + frag++; + last -= x4 - 1; + } + + packlen = 5 + 16 + ((frag + 20 + 16) & -16); + packlen = (packlen << n4x) - packlen; + packlen += 5 + 16 + ((last + 20 + 16) & -16); + + param->interleave = x4; + /* The returned values used by get need to be stored */ + ctx->multiblock_interleave = x4; + ctx->multiblock_aad_packlen = packlen; + return 1; + } + return -1; /* not yet */ +} + +/* EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT */ +static int aesni_cbc_hmac_sha1_tls1_multiblock_encrypt( + void *ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param) +{ + return (int)tls1_multi_block_encrypt(ctx, param->out, + param->inp, param->len, + param->interleave / 4); +} + +#endif /* OPENSSL_NO_MULTIBLOCK */ + +static const PROV_CIPHER_HW_AES_HMAC_SHA cipher_hw_aes_hmac_sha1 = { + { + aesni_cbc_hmac_sha1_init_key, + aesni_cbc_hmac_sha1_cipher + }, + aesni_cbc_hmac_sha1_set_mac_key, + aesni_cbc_hmac_sha1_set_tls1_aad, +# if !defined(OPENSSL_NO_MULTIBLOCK) + aesni_cbc_hmac_sha1_tls1_multiblock_max_bufsize, + aesni_cbc_hmac_sha1_tls1_multiblock_aad, + aesni_cbc_hmac_sha1_tls1_multiblock_encrypt +# endif +}; + +const PROV_CIPHER_HW_AES_HMAC_SHA *PROV_CIPHER_HW_aes_cbc_hmac_sha1(void) +{ + return &cipher_hw_aes_hmac_sha1; +} + +#endif /* AES_CBC_HMAC_SHA_CAPABLE */ diff --git a/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha256_hw.c b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha256_hw.c new file mode 100644 index 0000000..4352476 --- /dev/null +++ b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha256_hw.c @@ -0,0 +1,831 @@ +/* + * Copyright 2011-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_cbc_hmac_sha.h" + +#ifndef AES_CBC_HMAC_SHA_CAPABLE +int cipher_capable_aes_cbc_hmac_sha256(void) +{ + return 0; +} +#else + +# include "crypto/rand.h" +# include "crypto/evp.h" +# include "internal/constant_time.h" + +void sha256_block_data_order(void *c, const void *p, size_t len); +int aesni_cbc_sha256_enc(const void *inp, void *out, size_t blocks, + const AES_KEY *key, unsigned char iv[16], + SHA256_CTX *ctx, const void *in0); + +int cipher_capable_aes_cbc_hmac_sha256(void) +{ + return AESNI_CBC_HMAC_SHA_CAPABLE + && aesni_cbc_sha256_enc(NULL, NULL, 0, NULL, NULL, NULL, NULL); +} + +static int aesni_cbc_hmac_sha256_init_key(PROV_CIPHER_CTX *vctx, + const unsigned char *key, + size_t keylen) +{ + int ret; + PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx; + PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx; + + if (ctx->base.enc) + ret = aesni_set_encrypt_key(key, ctx->base.keylen * 8, &ctx->ks); + else + ret = aesni_set_decrypt_key(key, ctx->base.keylen * 8, &ctx->ks); + + SHA256_Init(&sctx->head); /* handy when benchmarking */ + sctx->tail = sctx->head; + sctx->md = sctx->head; + + ctx->payload_length = NO_PAYLOAD_LENGTH; + + return ret < 0 ? 0 : 1; +} + +void sha256_block_data_order(void *c, const void *p, size_t len); + +static void sha256_update(SHA256_CTX *c, const void *data, size_t len) +{ + const unsigned char *ptr = data; + size_t res; + + if ((res = c->num)) { + res = SHA256_CBLOCK - res; + if (len < res) + res = len; + SHA256_Update(c, ptr, res); + ptr += res; + len -= res; + } + + res = len % SHA256_CBLOCK; + len -= res; + + if (len) { + sha256_block_data_order(c, ptr, len / SHA256_CBLOCK); + + ptr += len; + c->Nh += len >> 29; + c->Nl += len <<= 3; + if (c->Nl < (unsigned int)len) + c->Nh++; + } + + if (res) + SHA256_Update(c, ptr, res); +} + +# if !defined(OPENSSL_NO_MULTIBLOCK) + +typedef struct { + unsigned int A[8], B[8], C[8], D[8], E[8], F[8], G[8], H[8]; +} SHA256_MB_CTX; + +typedef struct { + const unsigned char *ptr; + int blocks; +} HASH_DESC; + +typedef struct { + const unsigned char *inp; + unsigned char *out; + int blocks; + u64 iv[2]; +} CIPH_DESC; + +void sha256_multi_block(SHA256_MB_CTX *, const HASH_DESC *, int); +void aesni_multi_cbc_encrypt(CIPH_DESC *, void *, int); + +static size_t tls1_multi_block_encrypt(void *vctx, + unsigned char *out, + const unsigned char *inp, + size_t inp_len, int n4x) +{ /* n4x is 1 or 2 */ + PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx; + PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx; + HASH_DESC hash_d[8], edges[8]; + CIPH_DESC ciph_d[8]; + unsigned char storage[sizeof(SHA256_MB_CTX) + 32]; + union { + u64 q[16]; + u32 d[32]; + u8 c[128]; + } blocks[8]; + SHA256_MB_CTX *mctx; + unsigned int frag, last, packlen, i; + unsigned int x4 = 4 * n4x, minblocks, processed = 0; + size_t ret = 0; + u8 *IVs; +# if defined(BSWAP8) + u64 seqnum; +# endif + + /* ask for IVs in bulk */ + if (rand_bytes_ex(ctx->base.libctx, (IVs = blocks[0].c), 16 * x4) <= 0) + return 0; + + mctx = (SHA256_MB_CTX *) (storage + 32 - ((size_t)storage % 32)); /* align */ + + frag = (unsigned int)inp_len >> (1 + n4x); + last = (unsigned int)inp_len + frag - (frag << (1 + n4x)); + if (last > frag && ((last + 13 + 9) % 64) < (x4 - 1)) { + frag++; + last -= x4 - 1; + } + + packlen = 5 + 16 + ((frag + 32 + 16) & -16); + + /* populate descriptors with pointers and IVs */ + hash_d[0].ptr = inp; + ciph_d[0].inp = inp; + /* 5+16 is place for header and explicit IV */ + ciph_d[0].out = out + 5 + 16; + memcpy(ciph_d[0].out - 16, IVs, 16); + memcpy(ciph_d[0].iv, IVs, 16); + IVs += 16; + + for (i = 1; i < x4; i++) { + ciph_d[i].inp = hash_d[i].ptr = hash_d[i - 1].ptr + frag; + ciph_d[i].out = ciph_d[i - 1].out + packlen; + memcpy(ciph_d[i].out - 16, IVs, 16); + memcpy(ciph_d[i].iv, IVs, 16); + IVs += 16; + } + +# if defined(BSWAP8) + memcpy(blocks[0].c, sctx->md.data, 8); + seqnum = BSWAP8(blocks[0].q[0]); +# endif + + for (i = 0; i < x4; i++) { + unsigned int len = (i == (x4 - 1) ? last : frag); +# if !defined(BSWAP8) + unsigned int carry, j; +# endif + + mctx->A[i] = sctx->md.h[0]; + mctx->B[i] = sctx->md.h[1]; + mctx->C[i] = sctx->md.h[2]; + mctx->D[i] = sctx->md.h[3]; + mctx->E[i] = sctx->md.h[4]; + mctx->F[i] = sctx->md.h[5]; + mctx->G[i] = sctx->md.h[6]; + mctx->H[i] = sctx->md.h[7]; + + /* fix seqnum */ +# if defined(BSWAP8) + blocks[i].q[0] = BSWAP8(seqnum + i); +# else + for (carry = i, j = 8; j--;) { + blocks[i].c[j] = ((u8 *)sctx->md.data)[j] + carry; + carry = (blocks[i].c[j] - carry) >> (sizeof(carry) * 8 - 1); + } +# endif + blocks[i].c[8] = ((u8 *)sctx->md.data)[8]; + blocks[i].c[9] = ((u8 *)sctx->md.data)[9]; + blocks[i].c[10] = ((u8 *)sctx->md.data)[10]; + /* fix length */ + blocks[i].c[11] = (u8)(len >> 8); + blocks[i].c[12] = (u8)(len); + + memcpy(blocks[i].c + 13, hash_d[i].ptr, 64 - 13); + hash_d[i].ptr += 64 - 13; + hash_d[i].blocks = (len - (64 - 13)) / 64; + + edges[i].ptr = blocks[i].c; + edges[i].blocks = 1; + } + + /* hash 13-byte headers and first 64-13 bytes of inputs */ + sha256_multi_block(mctx, edges, n4x); + /* hash bulk inputs */ +# define MAXCHUNKSIZE 2048 +# if MAXCHUNKSIZE%64 +# error "MAXCHUNKSIZE is not divisible by 64" +# elif MAXCHUNKSIZE + /* + * goal is to minimize pressure on L1 cache by moving in shorter steps, + * so that hashed data is still in the cache by the time we encrypt it + */ + minblocks = ((frag <= last ? frag : last) - (64 - 13)) / 64; + if (minblocks > MAXCHUNKSIZE / 64) { + for (i = 0; i < x4; i++) { + edges[i].ptr = hash_d[i].ptr; + edges[i].blocks = MAXCHUNKSIZE / 64; + ciph_d[i].blocks = MAXCHUNKSIZE / 16; + } + do { + sha256_multi_block(mctx, edges, n4x); + aesni_multi_cbc_encrypt(ciph_d, &ctx->ks, n4x); + + for (i = 0; i < x4; i++) { + edges[i].ptr = hash_d[i].ptr += MAXCHUNKSIZE; + hash_d[i].blocks -= MAXCHUNKSIZE / 64; + edges[i].blocks = MAXCHUNKSIZE / 64; + ciph_d[i].inp += MAXCHUNKSIZE; + ciph_d[i].out += MAXCHUNKSIZE; + ciph_d[i].blocks = MAXCHUNKSIZE / 16; + memcpy(ciph_d[i].iv, ciph_d[i].out - 16, 16); + } + processed += MAXCHUNKSIZE; + minblocks -= MAXCHUNKSIZE / 64; + } while (minblocks > MAXCHUNKSIZE / 64); + } +# endif +# undef MAXCHUNKSIZE + sha256_multi_block(mctx, hash_d, n4x); + + memset(blocks, 0, sizeof(blocks)); + for (i = 0; i < x4; i++) { + unsigned int len = (i == (x4 - 1) ? last : frag), + off = hash_d[i].blocks * 64; + const unsigned char *ptr = hash_d[i].ptr + off; + + off = (len - processed) - (64 - 13) - off; /* remainder actually */ + memcpy(blocks[i].c, ptr, off); + blocks[i].c[off] = 0x80; + len += 64 + 13; /* 64 is HMAC header */ + len *= 8; /* convert to bits */ + if (off < (64 - 8)) { +# ifdef BSWAP4 + blocks[i].d[15] = BSWAP4(len); +# else + PUTU32(blocks[i].c + 60, len); +# endif + edges[i].blocks = 1; + } else { +# ifdef BSWAP4 + blocks[i].d[31] = BSWAP4(len); +# else + PUTU32(blocks[i].c + 124, len); +# endif + edges[i].blocks = 2; + } + edges[i].ptr = blocks[i].c; + } + + /* hash input tails and finalize */ + sha256_multi_block(mctx, edges, n4x); + + memset(blocks, 0, sizeof(blocks)); + for (i = 0; i < x4; i++) { +# ifdef BSWAP4 + blocks[i].d[0] = BSWAP4(mctx->A[i]); + mctx->A[i] = sctx->tail.h[0]; + blocks[i].d[1] = BSWAP4(mctx->B[i]); + mctx->B[i] = sctx->tail.h[1]; + blocks[i].d[2] = BSWAP4(mctx->C[i]); + mctx->C[i] = sctx->tail.h[2]; + blocks[i].d[3] = BSWAP4(mctx->D[i]); + mctx->D[i] = sctx->tail.h[3]; + blocks[i].d[4] = BSWAP4(mctx->E[i]); + mctx->E[i] = sctx->tail.h[4]; + blocks[i].d[5] = BSWAP4(mctx->F[i]); + mctx->F[i] = sctx->tail.h[5]; + blocks[i].d[6] = BSWAP4(mctx->G[i]); + mctx->G[i] = sctx->tail.h[6]; + blocks[i].d[7] = BSWAP4(mctx->H[i]); + mctx->H[i] = sctx->tail.h[7]; + blocks[i].c[32] = 0x80; + blocks[i].d[15] = BSWAP4((64 + 32) * 8); +# else + PUTU32(blocks[i].c + 0, mctx->A[i]); + mctx->A[i] = sctx->tail.h[0]; + PUTU32(blocks[i].c + 4, mctx->B[i]); + mctx->B[i] = sctx->tail.h[1]; + PUTU32(blocks[i].c + 8, mctx->C[i]); + mctx->C[i] = sctx->tail.h[2]; + PUTU32(blocks[i].c + 12, mctx->D[i]); + mctx->D[i] = sctx->tail.h[3]; + PUTU32(blocks[i].c + 16, mctx->E[i]); + mctx->E[i] = sctx->tail.h[4]; + PUTU32(blocks[i].c + 20, mctx->F[i]); + mctx->F[i] = sctx->tail.h[5]; + PUTU32(blocks[i].c + 24, mctx->G[i]); + mctx->G[i] = sctx->tail.h[6]; + PUTU32(blocks[i].c + 28, mctx->H[i]); + mctx->H[i] = sctx->tail.h[7]; + blocks[i].c[32] = 0x80; + PUTU32(blocks[i].c + 60, (64 + 32) * 8); +# endif /* BSWAP */ + edges[i].ptr = blocks[i].c; + edges[i].blocks = 1; + } + + /* finalize MACs */ + sha256_multi_block(mctx, edges, n4x); + + for (i = 0; i < x4; i++) { + unsigned int len = (i == (x4 - 1) ? last : frag), pad, j; + unsigned char *out0 = out; + + memcpy(ciph_d[i].out, ciph_d[i].inp, len - processed); + ciph_d[i].inp = ciph_d[i].out; + + out += 5 + 16 + len; + + /* write MAC */ + PUTU32(out + 0, mctx->A[i]); + PUTU32(out + 4, mctx->B[i]); + PUTU32(out + 8, mctx->C[i]); + PUTU32(out + 12, mctx->D[i]); + PUTU32(out + 16, mctx->E[i]); + PUTU32(out + 20, mctx->F[i]); + PUTU32(out + 24, mctx->G[i]); + PUTU32(out + 28, mctx->H[i]); + out += 32; + len += 32; + + /* pad */ + pad = 15 - len % 16; + for (j = 0; j <= pad; j++) + *(out++) = pad; + len += pad + 1; + + ciph_d[i].blocks = (len - processed) / 16; + len += 16; /* account for explicit iv */ + + /* arrange header */ + out0[0] = ((u8 *)sctx->md.data)[8]; + out0[1] = ((u8 *)sctx->md.data)[9]; + out0[2] = ((u8 *)sctx->md.data)[10]; + out0[3] = (u8)(len >> 8); + out0[4] = (u8)(len); + + ret += len + 5; + inp += frag; + } + + aesni_multi_cbc_encrypt(ciph_d, &ctx->ks, n4x); + + OPENSSL_cleanse(blocks, sizeof(blocks)); + OPENSSL_cleanse(mctx, sizeof(*mctx)); + + ctx->multiblock_encrypt_len = ret; + return ret; +} +# endif /* !OPENSSL_NO_MULTIBLOCK */ + +static int aesni_cbc_hmac_sha256_cipher(PROV_CIPHER_CTX *vctx, + unsigned char *out, + const unsigned char *in, size_t len) +{ + PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx; + PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx; + unsigned int l; + size_t plen = ctx->payload_length; + size_t iv = 0; /* explicit IV in TLS 1.1 and * later */ + size_t aes_off = 0, blocks; + size_t sha_off = SHA256_CBLOCK - sctx->md.num; + + ctx->payload_length = NO_PAYLOAD_LENGTH; + + if (len % AES_BLOCK_SIZE) + return 0; + + if (ctx->base.enc) { + if (plen == NO_PAYLOAD_LENGTH) + plen = len; + else if (len != + ((plen + SHA256_DIGEST_LENGTH + + AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)) + return 0; + else if (ctx->aux.tls_ver >= TLS1_1_VERSION) + iv = AES_BLOCK_SIZE; + + /* + * Assembly stitch handles AVX-capable processors, but its + * performance is not optimal on AMD Jaguar, ~40% worse, for + * unknown reasons. Incidentally processor in question supports + * AVX, but not AMD-specific XOP extension, which can be used + * to identify it and avoid stitch invocation. So that after we + * establish that current CPU supports AVX, we even see if it's + * either even XOP-capable Bulldozer-based or GenuineIntel one. + * But SHAEXT-capable go ahead... + */ + if (((OPENSSL_ia32cap_P[2] & (1 << 29)) || /* SHAEXT? */ + ((OPENSSL_ia32cap_P[1] & (1 << (60 - 32))) && /* AVX? */ + ((OPENSSL_ia32cap_P[1] & (1 << (43 - 32))) /* XOP? */ + | (OPENSSL_ia32cap_P[0] & (1 << 30))))) && /* "Intel CPU"? */ + plen > (sha_off + iv) && + (blocks = (plen - (sha_off + iv)) / SHA256_CBLOCK)) { + sha256_update(&sctx->md, in + iv, sha_off); + + (void)aesni_cbc_sha256_enc(in, out, blocks, &ctx->ks, + ctx->base.iv, + &sctx->md, in + iv + sha_off); + blocks *= SHA256_CBLOCK; + aes_off += blocks; + sha_off += blocks; + sctx->md.Nh += blocks >> 29; + sctx->md.Nl += blocks <<= 3; + if (sctx->md.Nl < (unsigned int)blocks) + sctx->md.Nh++; + } else { + sha_off = 0; + } + sha_off += iv; + sha256_update(&sctx->md, in + sha_off, plen - sha_off); + + if (plen != len) { /* "TLS" mode of operation */ + if (in != out) + memcpy(out + aes_off, in + aes_off, plen - aes_off); + + /* calculate HMAC and append it to payload */ + SHA256_Final(out + plen, &sctx->md); + sctx->md = sctx->tail; + sha256_update(&sctx->md, out + plen, SHA256_DIGEST_LENGTH); + SHA256_Final(out + plen, &sctx->md); + + /* pad the payload|hmac */ + plen += SHA256_DIGEST_LENGTH; + for (l = len - plen - 1; plen < len; plen++) + out[plen] = l; + /* encrypt HMAC|padding at once */ + aesni_cbc_encrypt(out + aes_off, out + aes_off, len - aes_off, + &ctx->ks, ctx->base.iv, 1); + } else { + aesni_cbc_encrypt(in + aes_off, out + aes_off, len - aes_off, + &ctx->ks, ctx->base.iv, 1); + } + } else { + union { + unsigned int u[SHA256_DIGEST_LENGTH / sizeof(unsigned int)]; + unsigned char c[64 + SHA256_DIGEST_LENGTH]; + } mac, *pmac; + + /* arrange cache line alignment */ + pmac = (void *)(((size_t)mac.c + 63) & ((size_t)0 - 64)); + + /* decrypt HMAC|padding at once */ + aesni_cbc_encrypt(in, out, len, &ctx->ks, + ctx->base.iv, 0); + + if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */ + size_t inp_len, mask, j, i; + unsigned int res, maxpad, pad, bitlen; + int ret = 1; + union { + unsigned int u[SHA_LBLOCK]; + unsigned char c[SHA256_CBLOCK]; + } *data = (void *)sctx->md.data; + + if ((ctx->aux.tls_aad[plen - 4] << 8 | ctx->aux.tls_aad[plen - 3]) + >= TLS1_1_VERSION) + iv = AES_BLOCK_SIZE; + + if (len < (iv + SHA256_DIGEST_LENGTH + 1)) + return 0; + + /* omit explicit iv */ + out += iv; + len -= iv; + + /* figure out payload length */ + pad = out[len - 1]; + maxpad = len - (SHA256_DIGEST_LENGTH + 1); + maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8); + maxpad &= 255; + + mask = constant_time_ge(maxpad, pad); + ret &= mask; + /* + * If pad is invalid then we will fail the above test but we must + * continue anyway because we are in constant time code. However, + * we'll use the maxpad value instead of the supplied pad to make + * sure we perform well defined pointer arithmetic. + */ + pad = constant_time_select(mask, pad, maxpad); + + inp_len = len - (SHA256_DIGEST_LENGTH + pad + 1); + + ctx->aux.tls_aad[plen - 2] = inp_len >> 8; + ctx->aux.tls_aad[plen - 1] = inp_len; + + /* calculate HMAC */ + sctx->md = sctx->head; + sha256_update(&sctx->md, ctx->aux.tls_aad, plen); + + /* code with lucky-13 fix */ + len -= SHA256_DIGEST_LENGTH; /* amend mac */ + if (len >= (256 + SHA256_CBLOCK)) { + j = (len - (256 + SHA256_CBLOCK)) & (0 - SHA256_CBLOCK); + j += SHA256_CBLOCK - sctx->md.num; + sha256_update(&sctx->md, out, j); + out += j; + len -= j; + inp_len -= j; + } + + /* but pretend as if we hashed padded payload */ + bitlen = sctx->md.Nl + (inp_len << 3); /* at most 18 bits */ +# ifdef BSWAP4 + bitlen = BSWAP4(bitlen); +# else + mac.c[0] = 0; + mac.c[1] = (unsigned char)(bitlen >> 16); + mac.c[2] = (unsigned char)(bitlen >> 8); + mac.c[3] = (unsigned char)bitlen; + bitlen = mac.u[0]; +# endif /* BSWAP */ + + pmac->u[0] = 0; + pmac->u[1] = 0; + pmac->u[2] = 0; + pmac->u[3] = 0; + pmac->u[4] = 0; + pmac->u[5] = 0; + pmac->u[6] = 0; + pmac->u[7] = 0; + + for (res = sctx->md.num, j = 0; j < len; j++) { + size_t c = out[j]; + mask = (j - inp_len) >> (sizeof(j) * 8 - 8); + c &= mask; + c |= 0x80 & ~mask & ~((inp_len - j) >> (sizeof(j) * 8 - 8)); + data->c[res++] = (unsigned char)c; + + if (res != SHA256_CBLOCK) + continue; + + /* j is not incremented yet */ + mask = 0 - ((inp_len + 7 - j) >> (sizeof(j) * 8 - 1)); + data->u[SHA_LBLOCK - 1] |= bitlen & mask; + sha256_block_data_order(&sctx->md, data, 1); + mask &= 0 - ((j - inp_len - 72) >> (sizeof(j) * 8 - 1)); + pmac->u[0] |= sctx->md.h[0] & mask; + pmac->u[1] |= sctx->md.h[1] & mask; + pmac->u[2] |= sctx->md.h[2] & mask; + pmac->u[3] |= sctx->md.h[3] & mask; + pmac->u[4] |= sctx->md.h[4] & mask; + pmac->u[5] |= sctx->md.h[5] & mask; + pmac->u[6] |= sctx->md.h[6] & mask; + pmac->u[7] |= sctx->md.h[7] & mask; + res = 0; + } + + for (i = res; i < SHA256_CBLOCK; i++, j++) + data->c[i] = 0; + + if (res > SHA256_CBLOCK - 8) { + mask = 0 - ((inp_len + 8 - j) >> (sizeof(j) * 8 - 1)); + data->u[SHA_LBLOCK - 1] |= bitlen & mask; + sha256_block_data_order(&sctx->md, data, 1); + mask &= 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1)); + pmac->u[0] |= sctx->md.h[0] & mask; + pmac->u[1] |= sctx->md.h[1] & mask; + pmac->u[2] |= sctx->md.h[2] & mask; + pmac->u[3] |= sctx->md.h[3] & mask; + pmac->u[4] |= sctx->md.h[4] & mask; + pmac->u[5] |= sctx->md.h[5] & mask; + pmac->u[6] |= sctx->md.h[6] & mask; + pmac->u[7] |= sctx->md.h[7] & mask; + + memset(data, 0, SHA256_CBLOCK); + j += 64; + } + data->u[SHA_LBLOCK - 1] = bitlen; + sha256_block_data_order(&sctx->md, data, 1); + mask = 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1)); + pmac->u[0] |= sctx->md.h[0] & mask; + pmac->u[1] |= sctx->md.h[1] & mask; + pmac->u[2] |= sctx->md.h[2] & mask; + pmac->u[3] |= sctx->md.h[3] & mask; + pmac->u[4] |= sctx->md.h[4] & mask; + pmac->u[5] |= sctx->md.h[5] & mask; + pmac->u[6] |= sctx->md.h[6] & mask; + pmac->u[7] |= sctx->md.h[7] & mask; + +# ifdef BSWAP4 + pmac->u[0] = BSWAP4(pmac->u[0]); + pmac->u[1] = BSWAP4(pmac->u[1]); + pmac->u[2] = BSWAP4(pmac->u[2]); + pmac->u[3] = BSWAP4(pmac->u[3]); + pmac->u[4] = BSWAP4(pmac->u[4]); + pmac->u[5] = BSWAP4(pmac->u[5]); + pmac->u[6] = BSWAP4(pmac->u[6]); + pmac->u[7] = BSWAP4(pmac->u[7]); +# else + for (i = 0; i < 8; i++) { + res = pmac->u[i]; + pmac->c[4 * i + 0] = (unsigned char)(res >> 24); + pmac->c[4 * i + 1] = (unsigned char)(res >> 16); + pmac->c[4 * i + 2] = (unsigned char)(res >> 8); + pmac->c[4 * i + 3] = (unsigned char)res; + } +# endif /* BSWAP */ + len += SHA256_DIGEST_LENGTH; + sctx->md = sctx->tail; + sha256_update(&sctx->md, pmac->c, SHA256_DIGEST_LENGTH); + SHA256_Final(pmac->c, &sctx->md); + + /* verify HMAC */ + out += inp_len; + len -= inp_len; + /* code containing lucky-13 fix */ + { + unsigned char *p = + out + len - 1 - maxpad - SHA256_DIGEST_LENGTH; + size_t off = out - p; + unsigned int c, cmask; + + maxpad += SHA256_DIGEST_LENGTH; + for (res = 0, i = 0, j = 0; j < maxpad; j++) { + c = p[j]; + cmask = + ((int)(j - off - SHA256_DIGEST_LENGTH)) >> + (sizeof(int) * 8 - 1); + res |= (c ^ pad) & ~cmask; /* ... and padding */ + cmask &= ((int)(off - 1 - j)) >> (sizeof(int) * 8 - 1); + res |= (c ^ pmac->c[i]) & cmask; + i += 1 & cmask; + } + maxpad -= SHA256_DIGEST_LENGTH; + + res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1)); + ret &= (int)~res; + } + return ret; + } else { + sha256_update(&sctx->md, out, len); + } + } + + return 1; +} + +/* EVP_CTRL_AEAD_SET_MAC_KEY */ +static void aesni_cbc_hmac_sha256_set_mac_key(void *vctx, + const unsigned char *mackey, + size_t len) +{ + PROV_AES_HMAC_SHA256_CTX *ctx = (PROV_AES_HMAC_SHA256_CTX *)vctx; + unsigned int i; + unsigned char hmac_key[64]; + + memset(hmac_key, 0, sizeof(hmac_key)); + + if (len > sizeof(hmac_key)) { + SHA256_Init(&ctx->head); + sha256_update(&ctx->head, mackey, len); + SHA256_Final(hmac_key, &ctx->head); + } else { + memcpy(hmac_key, mackey, len); + } + + for (i = 0; i < sizeof(hmac_key); i++) + hmac_key[i] ^= 0x36; /* ipad */ + SHA256_Init(&ctx->head); + sha256_update(&ctx->head, hmac_key, sizeof(hmac_key)); + + for (i = 0; i < sizeof(hmac_key); i++) + hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */ + SHA256_Init(&ctx->tail); + sha256_update(&ctx->tail, hmac_key, sizeof(hmac_key)); + + OPENSSL_cleanse(hmac_key, sizeof(hmac_key)); +} + +/* EVP_CTRL_AEAD_TLS1_AAD */ +static int aesni_cbc_hmac_sha256_set_tls1_aad(void *vctx, + unsigned char *aad_rec, int aad_len) +{ + PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx; + PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx; + unsigned char *p = aad_rec; + unsigned int len; + + if (aad_len != EVP_AEAD_TLS1_AAD_LEN) + return -1; + + len = p[aad_len - 2] << 8 | p[aad_len - 1]; + + if (ctx->base.enc) { + ctx->payload_length = len; + if ((ctx->aux.tls_ver = + p[aad_len - 4] << 8 | p[aad_len - 3]) >= TLS1_1_VERSION) { + if (len < AES_BLOCK_SIZE) + return 0; + len -= AES_BLOCK_SIZE; + p[aad_len] = len >> 8; + p[aad_len - 1] = len; + } + sctx->md = sctx->head; + sha256_update(&sctx->md, p, aad_len); + ctx->tls_aad_pad = (int)(((len + SHA256_DIGEST_LENGTH + + AES_BLOCK_SIZE) & -AES_BLOCK_SIZE) + - len); + return 1; + } else { + memcpy(ctx->aux.tls_aad, p, aad_len); + ctx->payload_length = aad_len; + ctx->tls_aad_pad = SHA256_DIGEST_LENGTH; + return 1; + } +} + +# if !defined(OPENSSL_NO_MULTIBLOCK) +/* EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE */ +static int aesni_cbc_hmac_sha256_tls1_multiblock_max_bufsize( + void *vctx) +{ + PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx; + + OPENSSL_assert(ctx->multiblock_max_send_fragment != 0); + return (int)(5 + 16 + + (((int)ctx->multiblock_max_send_fragment + 32 + 16) & -16)); +} + +/* EVP_CTRL_TLS1_1_MULTIBLOCK_AAD */ +static int aesni_cbc_hmac_sha256_tls1_multiblock_aad( + void *vctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param) +{ + PROV_AES_HMAC_SHA_CTX *ctx = (PROV_AES_HMAC_SHA_CTX *)vctx; + PROV_AES_HMAC_SHA256_CTX *sctx = (PROV_AES_HMAC_SHA256_CTX *)vctx; + unsigned int n4x = 1, x4; + unsigned int frag, last, packlen, inp_len; + + inp_len = param->inp[11] << 8 | param->inp[12]; + + if (ctx->base.enc) { + if ((param->inp[9] << 8 | param->inp[10]) < TLS1_1_VERSION) + return -1; + + if (inp_len) { + if (inp_len < 4096) + return 0; /* too short */ + + if (inp_len >= 8192 && OPENSSL_ia32cap_P[2] & (1 << 5)) + n4x = 2; /* AVX2 */ + } else if ((n4x = param->interleave / 4) && n4x <= 2) + inp_len = param->len; + else + return -1; + + sctx->md = sctx->head; + sha256_update(&sctx->md, param->inp, 13); + + x4 = 4 * n4x; + n4x += 1; + + frag = inp_len >> n4x; + last = inp_len + frag - (frag << n4x); + if (last > frag && ((last + 13 + 9) % 64 < (x4 - 1))) { + frag++; + last -= x4 - 1; + } + + packlen = 5 + 16 + ((frag + 32 + 16) & -16); + packlen = (packlen << n4x) - packlen; + packlen += 5 + 16 + ((last + 32 + 16) & -16); + + param->interleave = x4; + /* The returned values used by get need to be stored */ + ctx->multiblock_interleave = x4; + ctx->multiblock_aad_packlen = packlen; + return 1; + } + return -1; /* not yet */ +} + +/* EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT */ +static int aesni_cbc_hmac_sha256_tls1_multiblock_encrypt( + void *ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param) +{ + return (int)tls1_multi_block_encrypt(ctx, param->out, + param->inp, param->len, + param->interleave / 4); +} +#endif + +static const PROV_CIPHER_HW_AES_HMAC_SHA cipher_hw_aes_hmac_sha256 = { + { + aesni_cbc_hmac_sha256_init_key, + aesni_cbc_hmac_sha256_cipher + }, + aesni_cbc_hmac_sha256_set_mac_key, + aesni_cbc_hmac_sha256_set_tls1_aad, +# if !defined(OPENSSL_NO_MULTIBLOCK) + aesni_cbc_hmac_sha256_tls1_multiblock_max_bufsize, + aesni_cbc_hmac_sha256_tls1_multiblock_aad, + aesni_cbc_hmac_sha256_tls1_multiblock_encrypt +# endif +}; + +const PROV_CIPHER_HW_AES_HMAC_SHA *PROV_CIPHER_HW_aes_cbc_hmac_sha256(void) +{ + return &cipher_hw_aes_hmac_sha256; +} + +#endif /* AES_CBC_HMAC_SHA_CAPABLE */ diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h index 75c20a0..ed44d68 100644 --- a/providers/implementations/include/prov/implementations.h +++ b/providers/implementations/include/prov/implementations.h @@ -75,6 +75,10 @@ extern const OSSL_DISPATCH aes128wrap_functions[]; extern const OSSL_DISPATCH aes256wrappad_functions[]; extern const OSSL_DISPATCH aes192wrappad_functions[]; extern const OSSL_DISPATCH aes128wrappad_functions[]; +extern const OSSL_DISPATCH aes256cbc_hmac_sha1_functions[]; +extern const OSSL_DISPATCH aes128cbc_hmac_sha1_functions[]; +extern const OSSL_DISPATCH aes256cbc_hmac_sha256_functions[]; +extern const OSSL_DISPATCH aes128cbc_hmac_sha256_functions[]; #ifndef OPENSSL_NO_ARIA extern const OSSL_DISPATCH aria256gcm_functions[]; |