Add ABI tests for AES-GCM-SIV assembly Change-Id: I8051799ba060758e74c3fcaa7ede616321c9c1c9 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/98428 Reviewed-by: Adam Langley <agl@google.com> Presubmit-BoringSSL-Verified: boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com <boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com> Commit-Queue: Adam Langley <agl@google.com> Auto-Submit: David Benjamin <davidben@google.com>
diff --git a/crypto/cipher/aead_test.cc b/crypto/cipher/aead_test.cc index 5866112..c3b83b1 100644 --- a/crypto/cipher/aead_test.cc +++ b/crypto/cipher/aead_test.cc
@@ -1383,6 +1383,71 @@ #endif } } + +#if defined(AES_GCM_SIV_ASM) +TEST(AESGCMSIVTest, ABI) { + if (!aes_gcm_siv_asm_capable()) { + return; + } + + uint8_t key128[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + uint8_t key256[32] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}; + aead_aes_gcm_siv_asm_ctx ctx128, ctx256; + CHECK_ABI(aes128gcmsiv_aes_ks, key128, &ctx128.key[0]); + ctx128.is_128_bit = 1; + CHECK_ABI(aes256gcmsiv_aes_ks, key256, &ctx256.key[0]); + ctx256.is_128_bit = 0; + + alignas(16) uint8_t block[16] = {1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16}; + alignas(16) uint8_t out_block[16]; + alignas(16) uint8_t expanded_key[16 * 15]; + alignas(16) uint64_t record_enc_key[4] = {1, 2, 3, 4}; + CHECK_ABI(aes128gcmsiv_aes_ks_enc_x1, block, out_block, expanded_key, + record_enc_key); + CHECK_ABI(aes256gcmsiv_aes_ks_enc_x1, block, out_block, expanded_key, + record_enc_key); + + CHECK_ABI(aes128gcmsiv_ecb_enc_block, block, out_block, &ctx128); + CHECK_ABI(aes256gcmsiv_ecb_enc_block, block, out_block, &ctx256); + + alignas(16) uint8_t padded_nonce[16] = {1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 0, 0, 0, 0}; + alignas(16) uint64_t out_key_material[12]; + CHECK_ABI(aes128gcmsiv_kdf, padded_nonce, out_key_material, &ctx128.key[0]); + CHECK_ABI(aes256gcmsiv_kdf, padded_nonce, out_key_material, &ctx256.key[0]); + + alignas(16) uint8_t auth_key[16] = {1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16}; + alignas(16) uint8_t htable8[16 * 8]; + alignas(16) uint8_t htable6[16 * 6]; + CHECK_ABI(aesgcmsiv_htable_init, htable8, auth_key); + CHECK_ABI(aesgcmsiv_htable6_init, htable6, auth_key); + + uint8_t buf[256] = {0}; + uint8_t out_buf[256] = {0}; + alignas(16) uint8_t poly[16] = {0}; + for (size_t blocks : {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) { + CHECK_ABI(aesgcmsiv_polyval_horner, poly, auth_key, buf, blocks); + } + + alignas(16) uint8_t tag[16] = {0}; + alignas(16) uint8_t calculated_tag_and_scratch[16 * 8] = {0}; + for (size_t len : {0, 16, 32, 48, 64, 80, 96, 112, 128, 144}) { + CHECK_ABI(aesgcmsiv_htable_polyval, htable8, buf, len, poly); + CHECK_ABI(aes128gcmsiv_enc_msg_x4, buf, out_buf, tag, &ctx128, len); + CHECK_ABI(aes256gcmsiv_enc_msg_x4, buf, out_buf, tag, &ctx256, len); + CHECK_ABI(aes128gcmsiv_enc_msg_x8, buf, out_buf, tag, &ctx128, len); + CHECK_ABI(aes256gcmsiv_enc_msg_x8, buf, out_buf, tag, &ctx256, len); + CHECK_ABI(aes128gcmsiv_dec, buf, out_buf, calculated_tag_and_scratch, + htable6, &ctx128, len); + CHECK_ABI(aes256gcmsiv_dec, buf, out_buf, calculated_tag_and_scratch, + htable6, &ctx256, len); + } +} +#endif // AES_GCM_SIV_ASM #endif // SUPPORTS_ABI_TEST TEST(AEADTest, AESCCMLargeAD) {
diff --git a/crypto/cipher/e_aesgcmsiv.cc b/crypto/cipher/e_aesgcmsiv.cc index 5ab7c32..4a3eb03 100644 --- a/crypto/cipher/e_aesgcmsiv.cc +++ b/crypto/cipher/e_aesgcmsiv.cc
@@ -24,6 +24,7 @@ #include "../fipsmodule/aes/internal.h" #include "../fipsmodule/cipher/internal.h" #include "../internal.h" +#include "internal.h" using namespace bssl; @@ -36,18 +37,7 @@ CRYPTO_store_u32_le(tag, CRYPTO_load_u32_le(tag) + by); } -// TODO(davidben): AES-GCM-SIV assembly is not correct for Windows. It must save -// and restore xmm6 through xmm15. -#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \ - !defined(OPENSSL_WINDOWS) -#define AES_GCM_SIV_ASM - -// Optimised AES-GCM-SIV - -struct aead_aes_gcm_siv_asm_ctx { - alignas(16) uint8_t key[16 * 15]; - int is_128_bit; -}; +#if defined(AES_GCM_SIV_ASM) // The assembly code assumes 8-byte alignment of the EVP_AEAD_CTX's state, and // aligns to 16 bytes itself. @@ -57,141 +47,6 @@ static_assert(alignof(union evp_aead_ctx_st_state) >= 8, "AEAD state has insufficient alignment"); -extern "C" { -// aes128gcmsiv_aes_ks writes an AES-128 key schedule for `key` to -// `out_expanded_key`. `out_expanded_key` must be 16-byte aligned. -extern void aes128gcmsiv_aes_ks(const uint8_t key[16], - uint8_t out_expanded_key[16 * 15]); - -// aes256gcmsiv_aes_ks writes an AES-256 key schedule for `key` to -// `out_expanded_key`. `out_expanded_key` must be 16-byte aligned. -extern void aes256gcmsiv_aes_ks(const uint8_t key[32], - uint8_t out_expanded_key[16 * 15]); - -// aesgcmsiv_polyval_horner updates the POLYVAL value in `in_out_poly` to -// include a number (`in_blocks`) of 16-byte blocks of data from `in`, given -// the POLYVAL key in `key`. `in_out_poly` and `key` must be 16-byte aligned. -extern void aesgcmsiv_polyval_horner(const uint8_t in_out_poly[16], - const uint8_t key[16], const uint8_t *in, - size_t in_blocks); - -// aesgcmsiv_htable_init writes powers 1..8 of `auth_key` to `out_htable`. -// `out_htable` and `auth_key` must be 16-byte aligned. -extern void aesgcmsiv_htable_init(uint8_t out_htable[16 * 8], - const uint8_t auth_key[16]); - -// aesgcmsiv_htable6_init writes powers 1..6 of `auth_key` to `out_htable`. -// `out_htable` and `auth_key` must be 16-byte aligned. -extern void aesgcmsiv_htable6_init(uint8_t out_htable[16 * 6], - const uint8_t auth_key[16]); - -// aesgcmsiv_htable_polyval updates the POLYVAL value in `in_out_poly` to -// include `in_len` bytes of data from `in`. (Where `in_len` must be a multiple -// of 16.) It uses the precomputed powers of the key given in `htable`. -// `in_out_poly` and `htable` must be 16-byte aligned. -extern void aesgcmsiv_htable_polyval(const uint8_t htable[16 * 8], - const uint8_t *in, size_t in_len, - uint8_t in_out_poly[16]); - -// aes128gcmsiv_dec decrypts `in_len` & ~15 bytes from `out` and writes them to -// `in`. `in` and `out` may be equal, but must not otherwise alias. -// -// `in_out_calculated_tag_and_scratch`, on entry, must contain: -// 1. The current value of the calculated tag, which will be updated during -// decryption and written back to the beginning of this buffer on exit. -// 2. The claimed tag, which is needed to derive counter values. -// -// While decrypting, the whole of `in_out_calculated_tag_and_scratch` may be -// used for other purposes. `in_out_calculated_tag_and_scratch` and `htable` -// must be 16-byte aligned. In order to decrypt and update the POLYVAL value, it -// uses the expanded key from `key` and the table of powers in `htable`. -extern void aes128gcmsiv_dec(const uint8_t *in, uint8_t *out, - uint8_t in_out_calculated_tag_and_scratch[16 * 8], - const uint8_t htable[16 * 6], - const struct aead_aes_gcm_siv_asm_ctx *key, - size_t in_len); - -// aes256gcmsiv_dec acts like `aes128gcmsiv_dec`, but for AES-256. -// `in_out_calculated_tag_and_scratch` and `htable` must be 16-byte aligned. -extern void aes256gcmsiv_dec(const uint8_t *in, uint8_t *out, - uint8_t in_out_calculated_tag_and_scratch[16 * 8], - const uint8_t htable[16 * 6], - const struct aead_aes_gcm_siv_asm_ctx *key, - size_t in_len); - -// aes128gcmsiv_kdf performs the AES-GCM-SIV KDF given the expanded key from -// `key_schedule` and the nonce in `nonce`. Note that, while only 12 bytes of -// the nonce are used, 16 bytes are read and so the value must be -// right-padded. `nonce`, `out_key_material`, and `key_schedule` must be -// 16-byte aligned. -extern void aes128gcmsiv_kdf(const uint8_t nonce[16], - uint64_t out_key_material[8], - const uint8_t *key_schedule); - -// aes256gcmsiv_kdf acts like `aes128gcmsiv_kdf`, but for AES-256. `nonce`, -// `out_key_material`, and `key_schedule` must be 16-byte aligned. -extern void aes256gcmsiv_kdf(const uint8_t nonce[16], - uint64_t out_key_material[12], - const uint8_t *key_schedule); - -// aes128gcmsiv_aes_ks_enc_x1 performs a key expansion of the AES-128 key in -// `key`, writes the expanded key to `out_expanded_key` and encrypts a single -// block from `in` to `out`. `in`, `out`, `out_expanded_key`, and `key` must be -// 16-byte aligned. -extern void aes128gcmsiv_aes_ks_enc_x1(const uint8_t in[16], uint8_t out[16], - uint8_t out_expanded_key[16 * 15], - const uint64_t key[2]); - -// aes256gcmsiv_aes_ks_enc_x1 acts like `aes128gcmsiv_aes_ks_enc_x1`, but for -// AES-256. `in`, `out`, `out_expanded_key`, and `key` must be 16-byte aligned. -extern void aes256gcmsiv_aes_ks_enc_x1(const uint8_t in[16], uint8_t out[16], - uint8_t out_expanded_key[16 * 15], - const uint64_t key[4]); - -// aes128gcmsiv_ecb_enc_block encrypts a single block from `in` to `out` using -// the expanded key in `expanded_key`. `in` and `out` must be 16-byte aligned. -extern void aes128gcmsiv_ecb_enc_block( - const uint8_t in[16], uint8_t out[16], - const struct aead_aes_gcm_siv_asm_ctx *expanded_key); - -// aes256gcmsiv_ecb_enc_block acts like `aes128gcmsiv_ecb_enc_block`, but for -// AES-256. `in` and `out` must be 16-byte aligned. -extern void aes256gcmsiv_ecb_enc_block( - const uint8_t in[16], uint8_t out[16], - const struct aead_aes_gcm_siv_asm_ctx *expanded_key); - -// aes128gcmsiv_enc_msg_x4 encrypts `in_len` bytes from `in` to `out` using the -// expanded key from `key`. (The value of `in_len` must be a multiple of 16.) -// The `in` and `out` buffers may be equal but must not otherwise overlap. The -// initial counter is constructed from the given `tag` as required by -// AES-GCM-SIV. `tag` must be 16-byte aligned. -extern void aes128gcmsiv_enc_msg_x4(const uint8_t *in, uint8_t *out, - const uint8_t *tag, - const struct aead_aes_gcm_siv_asm_ctx *key, - size_t in_len); - -// aes256gcmsiv_enc_msg_x4 acts like `aes128gcmsiv_enc_msg_x4`, but for -// AES-256. `tag` must be 16-byte aligned. -extern void aes256gcmsiv_enc_msg_x4(const uint8_t *in, uint8_t *out, - const uint8_t *tag, - const struct aead_aes_gcm_siv_asm_ctx *key, - size_t in_len); - -// aes128gcmsiv_enc_msg_x8 acts like `aes128gcmsiv_enc_msg_x4`, but is -// optimised for longer messages. -extern void aes128gcmsiv_enc_msg_x8(const uint8_t *in, uint8_t *out, - const uint8_t *tag, - const struct aead_aes_gcm_siv_asm_ctx *key, - size_t in_len); - -// aes256gcmsiv_enc_msg_x8 acts like `aes256gcmsiv_enc_msg_x4`, but is -// optimised for longer messages. -extern void aes256gcmsiv_enc_msg_x8(const uint8_t *in, uint8_t *out, - const uint8_t *tag, - const struct aead_aes_gcm_siv_asm_ctx *key, - size_t in_len); -} - // asm_ctx_from_ctx returns a 16-byte aligned context pointer from `ctx`. struct aead_aes_gcm_siv_asm_ctx *asm_ctx_from_ctx(const EVP_AEAD_CTX *ctx) { // ctx->state must already be 8-byte aligned. Thus, at most, we may need to @@ -656,7 +511,7 @@ nullptr /* tag_len */, }; -#endif // X86_64 && !NO_ASM && !WINDOWS +#endif // AES_GCM_SIV_ASM struct aead_aes_gcm_siv_ctx { @@ -1044,28 +899,20 @@ }; } // namespace -#if defined(AES_GCM_SIV_ASM) - const EVP_AEAD *EVP_aead_aes_128_gcm_siv() { - if (CRYPTO_is_AVX_capable() && CRYPTO_is_AESNI_capable() && - CRYPTO_is_PCLMUL_capable()) { +#if defined(AES_GCM_SIV_ASM) + if (aes_gcm_siv_asm_capable()) { return &aead_aes_128_gcm_siv_asm; } +#endif return &aead_aes_128_gcm_siv; } const EVP_AEAD *EVP_aead_aes_256_gcm_siv() { - if (CRYPTO_is_AVX_capable() && CRYPTO_is_AESNI_capable() && - CRYPTO_is_PCLMUL_capable()) { +#if defined(AES_GCM_SIV_ASM) + if (aes_gcm_siv_asm_capable()) { return &aead_aes_256_gcm_siv_asm; } +#endif return &aead_aes_256_gcm_siv; } - -#else - -const EVP_AEAD *EVP_aead_aes_128_gcm_siv() { return &aead_aes_128_gcm_siv; } - -const EVP_AEAD *EVP_aead_aes_256_gcm_siv() { return &aead_aes_256_gcm_siv; } - -#endif // AES_GCM_SIV_ASM
diff --git a/crypto/cipher/internal.h b/crypto/cipher/internal.h index 0293e34..8ee1c59 100644 --- a/crypto/cipher/internal.h +++ b/crypto/cipher/internal.h
@@ -18,6 +18,7 @@ #include <assert.h> #include <stdlib.h> +#include <openssl/aead.h> #include <openssl/base.h> #include <openssl/sha.h> #include <openssl/span.h> @@ -103,6 +104,9 @@ bssl::Span<const uint8_t> trailer, size_t data_in_trailer_size, const uint8_t *mac_secret, unsigned mac_secret_length); + +// ChaCha20-Poly1305 Assembly. + #define POLY1305_TAG_LEN 16 // For convenience (the x86_64 calling convention allows only six parameters in @@ -235,6 +239,161 @@ } #endif + +// AES-GCM-SIV Assembly. + +// TODO(davidben): AES-GCM-SIV assembly is not correct for Windows. It must save +// and restore xmm6 through xmm15. +#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \ + !defined(OPENSSL_WINDOWS) +#define AES_GCM_SIV_ASM + +struct aead_aes_gcm_siv_asm_ctx { + alignas(16) uint8_t key[16 * 15]; + int is_128_bit; +}; + +inline int aes_gcm_siv_asm_capable() { + return CRYPTO_is_AVX_capable() && CRYPTO_is_AESNI_capable() && + CRYPTO_is_PCLMUL_capable(); +} + +extern "C" { +// aes128gcmsiv_aes_ks writes an AES-128 key schedule for `key` to +// `out_expanded_key`. `out_expanded_key` must be 16-byte aligned. +extern void aes128gcmsiv_aes_ks(const uint8_t key[16], + uint8_t out_expanded_key[16 * 15]); + +// aes256gcmsiv_aes_ks writes an AES-256 key schedule for `key` to +// `out_expanded_key`. `out_expanded_key` must be 16-byte aligned. +extern void aes256gcmsiv_aes_ks(const uint8_t key[32], + uint8_t out_expanded_key[16 * 15]); + +// aesgcmsiv_polyval_horner updates the POLYVAL value in `in_out_poly` to +// include a number (`in_blocks`) of 16-byte blocks of data from `in`, given +// the POLYVAL key in `key`. `in_out_poly` and `key` must be 16-byte aligned. +extern void aesgcmsiv_polyval_horner(const uint8_t in_out_poly[16], + const uint8_t key[16], const uint8_t *in, + size_t in_blocks); + +// aesgcmsiv_htable_init writes powers 1..8 of `auth_key` to `out_htable`. +// `out_htable` and `auth_key` must be 16-byte aligned. +extern void aesgcmsiv_htable_init(uint8_t out_htable[16 * 8], + const uint8_t auth_key[16]); + +// aesgcmsiv_htable6_init writes powers 1..6 of `auth_key` to `out_htable`. +// `out_htable` and `auth_key` must be 16-byte aligned. +extern void aesgcmsiv_htable6_init(uint8_t out_htable[16 * 6], + const uint8_t auth_key[16]); + +// aesgcmsiv_htable_polyval updates the POLYVAL value in `in_out_poly` to +// include `in_len` bytes of data from `in`. (Where `in_len` must be a multiple +// of 16.) It uses the precomputed powers of the key given in `htable`. +// `in_out_poly` and `htable` must be 16-byte aligned. +extern void aesgcmsiv_htable_polyval(const uint8_t htable[16 * 8], + const uint8_t *in, size_t in_len, + uint8_t in_out_poly[16]); + +// aes128gcmsiv_dec decrypts `in_len` & ~15 bytes from `out` and writes them to +// `in`. `in` and `out` may be equal, but must not otherwise alias. +// +// `in_out_calculated_tag_and_scratch`, on entry, must contain: +// 1. The current value of the calculated tag, which will be updated during +// decryption and written back to the beginning of this buffer on exit. +// 2. The claimed tag, which is needed to derive counter values. +// +// While decrypting, the whole of `in_out_calculated_tag_and_scratch` may be +// used for other purposes. `in_out_calculated_tag_and_scratch` and `htable` +// must be 16-byte aligned. In order to decrypt and update the POLYVAL value, it +// uses the expanded key from `key` and the table of powers in `htable`. +extern void aes128gcmsiv_dec(const uint8_t *in, uint8_t *out, + uint8_t in_out_calculated_tag_and_scratch[16 * 8], + const uint8_t htable[16 * 6], + const struct aead_aes_gcm_siv_asm_ctx *key, + size_t in_len); + +// aes256gcmsiv_dec acts like `aes128gcmsiv_dec`, but for AES-256. +// `in_out_calculated_tag_and_scratch` and `htable` must be 16-byte aligned. +extern void aes256gcmsiv_dec(const uint8_t *in, uint8_t *out, + uint8_t in_out_calculated_tag_and_scratch[16 * 8], + const uint8_t htable[16 * 6], + const struct aead_aes_gcm_siv_asm_ctx *key, + size_t in_len); + +// aes128gcmsiv_kdf performs the AES-GCM-SIV KDF given the expanded key from +// `key_schedule` and the nonce in `nonce`. Note that, while only 12 bytes of +// the nonce are used, 16 bytes are read and so the value must be +// right-padded. `nonce`, `out_key_material`, and `key_schedule` must be +// 16-byte aligned. +extern void aes128gcmsiv_kdf(const uint8_t nonce[16], + uint64_t out_key_material[8], + const uint8_t *key_schedule); + +// aes256gcmsiv_kdf acts like `aes128gcmsiv_kdf`, but for AES-256. `nonce`, +// `out_key_material`, and `key_schedule` must be 16-byte aligned. +extern void aes256gcmsiv_kdf(const uint8_t nonce[16], + uint64_t out_key_material[12], + const uint8_t *key_schedule); + +// aes128gcmsiv_aes_ks_enc_x1 performs a key expansion of the AES-128 key in +// `key`, writes the expanded key to `out_expanded_key` and encrypts a single +// block from `in` to `out`. `in`, `out`, `out_expanded_key`, and `key` must be +// 16-byte aligned. +extern void aes128gcmsiv_aes_ks_enc_x1(const uint8_t in[16], uint8_t out[16], + uint8_t out_expanded_key[16 * 15], + const uint64_t key[2]); + +// aes256gcmsiv_aes_ks_enc_x1 acts like `aes128gcmsiv_aes_ks_enc_x1`, but for +// AES-256. `in`, `out`, `out_expanded_key`, and `key` must be 16-byte aligned. +extern void aes256gcmsiv_aes_ks_enc_x1(const uint8_t in[16], uint8_t out[16], + uint8_t out_expanded_key[16 * 15], + const uint64_t key[4]); + +// aes128gcmsiv_ecb_enc_block encrypts a single block from `in` to `out` using +// the expanded key in `expanded_key`. `in` and `out` must be 16-byte aligned. +extern void aes128gcmsiv_ecb_enc_block( + const uint8_t in[16], uint8_t out[16], + const struct aead_aes_gcm_siv_asm_ctx *expanded_key); + +// aes256gcmsiv_ecb_enc_block acts like `aes128gcmsiv_ecb_enc_block`, but for +// AES-256. `in` and `out` must be 16-byte aligned. +extern void aes256gcmsiv_ecb_enc_block( + const uint8_t in[16], uint8_t out[16], + const struct aead_aes_gcm_siv_asm_ctx *expanded_key); + +// aes128gcmsiv_enc_msg_x4 encrypts `in_len` bytes from `in` to `out` using the +// expanded key from `key`. (The value of `in_len` must be a multiple of 16.) +// The `in` and `out` buffers may be equal but must not otherwise overlap. The +// initial counter is constructed from the given `tag` as required by +// AES-GCM-SIV. `tag` must be 16-byte aligned. +extern void aes128gcmsiv_enc_msg_x4(const uint8_t *in, uint8_t *out, + const uint8_t *tag, + const struct aead_aes_gcm_siv_asm_ctx *key, + size_t in_len); + +// aes256gcmsiv_enc_msg_x4 acts like `aes128gcmsiv_enc_msg_x4`, but for +// AES-256. `tag` must be 16-byte aligned. +extern void aes256gcmsiv_enc_msg_x4(const uint8_t *in, uint8_t *out, + const uint8_t *tag, + const struct aead_aes_gcm_siv_asm_ctx *key, + size_t in_len); + +// aes128gcmsiv_enc_msg_x8 acts like `aes128gcmsiv_enc_msg_x4`, but is +// optimised for longer messages. +extern void aes128gcmsiv_enc_msg_x8(const uint8_t *in, uint8_t *out, + const uint8_t *tag, + const struct aead_aes_gcm_siv_asm_ctx *key, + size_t in_len); + +// aes256gcmsiv_enc_msg_x8 acts like `aes256gcmsiv_enc_msg_x4`, but is +// optimised for longer messages. +extern void aes256gcmsiv_enc_msg_x8(const uint8_t *in, uint8_t *out, + const uint8_t *tag, + const struct aead_aes_gcm_siv_asm_ctx *key, + size_t in_len); +} +#endif // OPENSSL_X86_64 && !OPENSSL_NO_ASM && !OPENSSL_WINDOWS + BSSL_NAMESPACE_END #endif // OPENSSL_HEADER_CRYPTO_CIPHER_INTERNAL_H