From 5f045c759957fdff8c85716e6af99e10901fdac0 Mon Sep 17 00:00:00 2001 From: Thomas Pornin Date: Sun, 29 Jan 2017 21:46:33 +0100 Subject: [PATCH] Added AES+GHASH implementation using AES-NI opcodes; also ARM-Thumb assembly for faster Montgomery multiplication on Cortex-M0+. Added selection functions for "default" implementations. --- conf/Unix.mk | 2 +- conf/Unix32.mk | 12 ++ conf/UnixClang.mk | 9 + conf/samd20.mk | 2 +- inc/bearssl_block.h | 222 ++++++++++++++++++++++ inc/bearssl_ec.h | 61 +++++++ inc/bearssl_hash.h | 30 +++ inc/bearssl_rsa.h | 40 ++++ inc/bearssl_ssl.h | 133 +++++++++++++- mk/Rules.mk | 68 ++++++- mk/mkrules.sh | 22 +++ samples/custom_profile.c | 59 +++++- src/config.h | 35 ++++ src/ec/ec_default.c | 36 ++++ src/ec/ecdsa_default_sign_asn1.c | 36 ++++ src/ec/ecdsa_default_sign_raw.c | 36 ++++ src/ec/ecdsa_default_vrfy_asn1.c | 36 ++++ src/ec/ecdsa_default_vrfy_raw.c | 36 ++++ src/hash/ghash_pclmul.c | 253 ++++++++++++++++++++++++++ src/inner.h | 74 ++++++++ src/int/i15_modpow2.c | 3 +- src/int/i15_montmul.c | 93 ++++++++++ src/rsa/rsa_default_pkcs1_sign.c | 36 ++++ src/rsa/rsa_default_pkcs1_vrfy.c | 36 ++++ src/rsa/rsa_default_priv.c | 36 ++++ src/rsa/rsa_default_pub.c | 36 ++++ src/rsa/rsa_i15_priv.c | 31 +++- src/rsa/rsa_i15_pub.c | 18 +- src/ssl/ssl_client_default_rsapub.c | 36 ++++ src/ssl/ssl_client_full.c | 60 ++---- src/ssl/ssl_engine_default_aescbc.c | 56 ++++++ src/ssl/ssl_engine_default_aesgcm.c | 71 ++++++++ src/ssl/ssl_engine_default_chapol.c | 40 ++++ src/ssl/ssl_engine_default_descbc.c | 37 ++++ src/ssl/ssl_engine_default_ec.c | 36 ++++ src/ssl/ssl_engine_default_ecdsa.c | 38 ++++ src/ssl/ssl_engine_default_rsavrfy.c | 36 ++++ src/ssl/ssl_server_full_ec.c | 57 ++---- src/ssl/ssl_server_full_rsa.c | 56 ++---- src/ssl/ssl_server_mine2c.c | 15 +- src/ssl/ssl_server_mine2g.c | 25 +-- src/ssl/ssl_server_minf2c.c | 18 +- src/ssl/ssl_server_minf2g.c | 25 +-- src/ssl/ssl_server_minr2g.c | 25 +-- src/ssl/ssl_server_minu2g.c | 25 +-- src/ssl/ssl_server_minv2g.c | 25 +-- src/symcipher/aes_x86ni.c | 263 +++++++++++++++++++++++++++ src/symcipher/aes_x86ni_cbcdec.c | 224 +++++++++++++++++++++++ src/symcipher/aes_x86ni_cbcenc.c | 125 +++++++++++++ src/symcipher/aes_x86ni_ctr.c | 218 ++++++++++++++++++++++ test/test_crypto.c | 45 ++++- test/test_speed.c | 62 ++++++- test/test_x509.c | 8 +- tools/brssl.h | 12 ++ tools/client.c | 61 ++----- tools/names.c | 104 ++++++++++- tools/server.c | 62 +++---- tools/sslio.c | 51 ++++++ 58 files changed, 3012 insertions(+), 395 deletions(-) create mode 100644 conf/Unix32.mk create mode 100644 conf/UnixClang.mk create mode 100644 src/ec/ec_default.c create mode 100644 src/ec/ecdsa_default_sign_asn1.c create mode 100644 src/ec/ecdsa_default_sign_raw.c create mode 100644 src/ec/ecdsa_default_vrfy_asn1.c create mode 100644 src/ec/ecdsa_default_vrfy_raw.c create mode 100644 src/hash/ghash_pclmul.c create mode 100644 src/rsa/rsa_default_pkcs1_sign.c create mode 100644 src/rsa/rsa_default_pkcs1_vrfy.c create mode 100644 src/rsa/rsa_default_priv.c create mode 100644 src/rsa/rsa_default_pub.c create mode 100644 src/ssl/ssl_client_default_rsapub.c create mode 100644 src/ssl/ssl_engine_default_aescbc.c create mode 100644 src/ssl/ssl_engine_default_aesgcm.c create mode 100644 src/ssl/ssl_engine_default_chapol.c create mode 100644 src/ssl/ssl_engine_default_descbc.c create mode 100644 src/ssl/ssl_engine_default_ec.c create mode 100644 src/ssl/ssl_engine_default_ecdsa.c create mode 100644 src/ssl/ssl_engine_default_rsavrfy.c create mode 100644 src/symcipher/aes_x86ni.c create mode 100644 src/symcipher/aes_x86ni_cbcdec.c create mode 100644 src/symcipher/aes_x86ni_cbcenc.c create mode 100644 src/symcipher/aes_x86ni_ctr.c diff --git a/conf/Unix.mk b/conf/Unix.mk index a9b6450..7764748 100644 --- a/conf/Unix.mk +++ b/conf/Unix.mk @@ -53,7 +53,7 @@ LDDLLOUT = -o # Static linker. LD = gcc -LDFLAGS = +LDFLAGS = LDOUT = -o # C# compiler; we assume usage of Mono. diff --git a/conf/Unix32.mk b/conf/Unix32.mk new file mode 100644 index 0000000..0d3bed8 --- /dev/null +++ b/conf/Unix32.mk @@ -0,0 +1,12 @@ +# Example configuration file for compiling on a Unix-like system with +# GCC, targeting a 32-bit output. Moreover, it enables the "LOMUL" setting +# to make the code select the "small" integer implementations (i15, m15, +# ctmul32...), which is not necessarily a good idea for performance, but +# handy for tests. + +include conf/Unix.mk + +BUILD = build32 +CFLAGS = -W -Wall -Os -fPIC -m32 -DBR_LOMUL +LDFLAGS = -m32 +LDDLLFLAGS = -shared -m32 diff --git a/conf/UnixClang.mk b/conf/UnixClang.mk new file mode 100644 index 0000000..331f4a8 --- /dev/null +++ b/conf/UnixClang.mk @@ -0,0 +1,9 @@ +# Example configuration file for compiling on a Unix-like system with +# clang as compiler instead of gcc. + +# We are on a Unix system so we assume a Single Unix compatible 'make' +# utility, and Unix defaults. +include conf/Unix.mk + +BUILD = bclang +CC = clang diff --git a/conf/samd20.mk b/conf/samd20.mk index acb6272..5b3d500 100644 --- a/conf/samd20.mk +++ b/conf/samd20.mk @@ -10,7 +10,7 @@ BUILD = samd20 # C compiler, linker, and static library builder. CC = arm-none-eabi-gcc -CFLAGS = -W -Wall -Os -mthumb -ffunction-sections -fdata-sections -mcpu=cortex-m0plus +CFLAGS = -W -Wall -Os -mthumb -ffunction-sections -fdata-sections -mcpu=cortex-m0plus -DBR_ARMEL_CORTEXM_GCC LD = arm-none-eabi-gcc AR = arm-none-eabi-ar diff --git a/inc/bearssl_block.h b/inc/bearssl_block.h index 6641e6c..c6f20f5 100644 --- a/inc/bearssl_block.h +++ b/inc/bearssl_block.h @@ -191,6 +191,7 @@ * | aes_small | AES | 16 | 16, 24 and 32 | * | aes_ct | AES | 16 | 16, 24 and 32 | * | aes_ct64 | AES | 16 | 16, 24 and 32 | + * | aes_x86ni | AES | 16 | 16, 24 and 32 | * | des_ct | DES/3DES | 8 | 8, 16 and 24 | * | des_tab | DES/3DES | 8 | 8, 16 and 24 | * @@ -223,6 +224,11 @@ * is typically twice faster than `aes_ct` for modes that allow parallel * operations (i.e. CTR, and CBC decryption, but not CBC encryption). * + * `aes_x86ni` exists only on x86 architectures (32-bit and 64-bit). It + * uses the AES-NI opcodes when available; if the opcodes are not present, + * then it automatically fall backs on an appropriate constant-time + * implementation (`aes_ct` for 32-bit, `aes_ct64` for 64-bit). + * * `des_tab` is a classic, table-based implementation of DES/3DES. It * is not constant-time. * @@ -994,6 +1000,219 @@ void br_aes_ct64_cbcdec_run(const br_aes_ct64_cbcdec_keys *ctx, void *iv, uint32_t br_aes_ct64_ctr_run(const br_aes_ct64_ctr_keys *ctx, const void *iv, uint32_t cc, void *data, size_t len); +/* + * AES implementation using AES-NI opcode (x86 platform). When the + * opcodes are not present, this falls back to "ct" or "ct64" (depending + * on architecture). + */ + +/** \brief AES block size (16 bytes). */ +#define br_aes_x86ni_BLOCK_SIZE 16 + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CBC encryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcenc_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + struct { + uint32_t skey[60]; + } fallback_ct; + struct { + uint64_t skey[30]; + } fallback_ct64; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_cbcenc_keys; + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CBC decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_cbcdec_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + struct { + uint32_t skey[60]; + } fallback_ct; + struct { + uint64_t skey[30]; + } fallback_ct64; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_cbcdec_keys; + +/** + * \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption + * and decryption). + * + * First field is a pointer to the vtable; it is set by the initialisation + * function. Other fields are not supposed to be accessed by user code. + */ +typedef struct { + /** \brief Pointer to vtable for this context. */ + const br_block_ctr_class *vtable; +#ifndef BR_DOXYGEN_IGNORE + union { + unsigned char skni[16 * 15]; + struct { + uint32_t skey[60]; + } fallback_ct; + struct { + uint64_t skey[30]; + } fallback_ct64; + } skey; + unsigned num_rounds; +#endif +} br_aes_x86ni_ctr_keys; + +/** + * \brief Class instance for AES CBC encryption (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_cbcenc_get_vtable()`. + */ +extern const br_block_cbcenc_class br_aes_x86ni_cbcenc_vtable; + +/** + * \brief Class instance for AES CBC decryption (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_cbcdec_get_vtable()`. + */ +extern const br_block_cbcdec_class br_aes_x86ni_cbcdec_vtable; + +/** + * \brief Class instance for AES CTR encryption and decryption + * (`aes_x86ni` implementation). + * + * Since this implementation might be omitted from the library, or the + * AES opcode unavailable on the current CPU, a pointer to this class + * instance should be obtained through `br_aes_x86ni_ctr_get_vtable()`. + */ +extern const br_block_ctr_class br_aes_x86ni_ctr_vtable; + +/** + * \brief Context initialisation (key schedule) for AES CBC encryption + * (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_cbcenc_init(br_aes_x86ni_cbcenc_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CBC decryption + * (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_cbcdec_init(br_aes_x86ni_cbcdec_keys *ctx, + const void *key, size_t len); + +/** + * \brief Context initialisation (key schedule) for AES CTR encryption + * and decryption (`aes_x86ni` implementation). + * + * \param ctx context to initialise. + * \param key secret key. + * \param len secret key length (in bytes). + */ +void br_aes_x86ni_ctr_init(br_aes_x86ni_ctr_keys *ctx, + const void *key, size_t len); + +/** + * \brief CBC encryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to encrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_x86ni_cbcenc_run(const br_aes_x86ni_cbcenc_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CBC decryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (updated). + * \param data data to decrypt (updated). + * \param len data length (in bytes, MUST be multiple of 16). + */ +void br_aes_x86ni_cbcdec_run(const br_aes_x86ni_cbcdec_keys *ctx, void *iv, + void *data, size_t len); + +/** + * \brief CTR encryption and decryption with AES (`aes_x86ni` implementation). + * + * \param ctx context (already initialised). + * \param iv IV (constant, 12 bytes). + * \param cc initial block counter value. + * \param data data to decrypt (updated). + * \param len data length (in bytes). + * \return new block counter value. + */ +uint32_t br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len); + +/** + * \brief Obtain the `aes_x86ni` AES-CBC (encryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_x86ni_cbcenc_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x868ni` AES-CBC (encryption) implementation, or `NULL`. + */ +const br_block_cbcenc_class *br_aes_x86ni_cbcenc_get_vtable(void); + +/** + * \brief Obtain the `aes_x86ni` AES-CBC (decryption) implementation, if + * available. + * + * This function returns a pointer to `br_aes_x86ni_cbcdec_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x868ni` AES-CBC (decryption) implementation, or `NULL`. + */ +const br_block_cbcdec_class *br_aes_x86ni_cbcdec_get_vtable(void); + +/** + * \brief Obtain the `aes_x86ni` AES-CTR implementation, if available. + * + * This function returns a pointer to `br_aes_x86ni_ctr_vtable`, if + * that implementation was compiled in the library _and_ the x86 AES + * opcodes are available on the currently running CPU. If either of + * these conditions is not met, then this function returns `NULL`. + * + * \return the `aes_x868ni` AES-CTR implementation, or `NULL`. + */ +const br_block_ctr_class *br_aes_x86ni_ctr_get_vtable(void); + /** * \brief Aggregate structure large enough to be used as context for * subkeys (CBC encryption) for all AES implementations. @@ -1004,6 +1223,7 @@ typedef union { br_aes_small_cbcenc_keys c_small; br_aes_ct_cbcenc_keys c_ct; br_aes_ct64_cbcenc_keys c_ct64; + br_aes_x86ni_cbcenc_keys c_x86ni; } br_aes_gen_cbcenc_keys; /** @@ -1016,6 +1236,7 @@ typedef union { br_aes_small_cbcdec_keys c_small; br_aes_ct_cbcdec_keys c_ct; br_aes_ct64_cbcdec_keys c_ct64; + br_aes_x86ni_cbcdec_keys c_x86ni; } br_aes_gen_cbcdec_keys; /** @@ -1028,6 +1249,7 @@ typedef union { br_aes_small_ctr_keys c_small; br_aes_ct_ctr_keys c_ct; br_aes_ct64_ctr_keys c_ct64; + br_aes_x86ni_ctr_keys c_x86ni; } br_aes_gen_ctr_keys; /* diff --git a/inc/bearssl_ec.h b/inc/bearssl_ec.h index 5022530..3de86b4 100644 --- a/inc/bearssl_ec.h +++ b/inc/bearssl_ec.h @@ -512,6 +512,27 @@ extern const br_ec_impl br_ec_c25519_m31; */ extern const br_ec_impl br_ec_all_m15; +/** + * \brief Aggregate EC implementation "m31". + * + * This implementation is a wrapper for: + * + * - `br_ec_c25519_m31` for Curve25519 + * - `br_ec_p256_m31` for NIST P-256 + * - `br_ec_prime_i31` for other curves (NIST P-384 and NIST-P512) + */ +extern const br_ec_impl br_ec_all_m31; + +/** + * \brief Get the "default" EC implementation for the current system. + * + * This returns a pointer to the preferred implementation on the + * current system. + * + * \return the default EC implementation. + */ +const br_ec_impl *br_ec_get_default(void); + /** * \brief Convert a signature from "raw" to "asn1". * @@ -732,4 +753,44 @@ uint32_t br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl, const void *hash, size_t hash_len, const br_ec_public_key *pk, const void *sig, size_t sig_len); +/** + * \brief Get "default" ECDSA implementation (signer, asn1 format). + * + * This returns the preferred implementation of ECDSA signature generation + * ("asn1" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_sign br_ecdsa_sign_asn1_get_default(void); + +/** + * \brief Get "default" ECDSA implementation (signer, raw format). + * + * This returns the preferred implementation of ECDSA signature generation + * ("raw" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_sign br_ecdsa_sign_raw_get_default(void); + +/** + * \brief Get "default" ECDSA implementation (verifier, asn1 format). + * + * This returns the preferred implementation of ECDSA signature verification + * ("asn1" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_vrfy br_ecdsa_vrfy_asn1_get_default(void); + +/** + * \brief Get "default" ECDSA implementation (verifier, raw format). + * + * This returns the preferred implementation of ECDSA signature verification + * ("raw" output format) on the current system. + * + * \return the default implementation. + */ +br_ecdsa_vrfy br_ecdsa_vrfy_raw_get_default(void); + #endif diff --git a/inc/bearssl_hash.h b/inc/bearssl_hash.h index e58a54f..524ac01 100644 --- a/inc/bearssl_hash.h +++ b/inc/bearssl_hash.h @@ -1279,4 +1279,34 @@ void br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len); */ void br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len); +/** + * \brief GHASH implementation using the `pclmulqdq` opcode (part of the + * AES-NI instructions). + * + * This implementation is available only on x86 platforms where the + * compiler supports the relevant intrinsic functions. Even if the + * compiler supports these functions, the local CPU might not support + * the `pclmulqdq` opcode, meaning that a call will fail with an + * illegal instruction exception. To safely obtain a pointer to this + * function when supported (or 0 otherwise), use `br_ghash_pclmul_get()`. + * + * \param y the array to update. + * \param h the GHASH key. + * \param data the input data (may be `NULL` if `len` is zero). + * \param len the input data length (in bytes). + */ +void br_ghash_pclmul(void *y, const void *h, const void *data, size_t len); + +/** + * \brief Obtain the `pclmul` GHASH implementation, if available. + * + * If the `pclmul` implementation was compiled in the library (depending + * on the compiler abilities) _and_ the local CPU appears to support the + * opcode, then this function will return a pointer to the + * `br_ghash_pclmul()` function. Otherwise, it will return `0`. + * + * \return the `pclmul` GHASH implementation, or `0`. + */ +br_ghash br_ghash_pclmul_get(void); + #endif diff --git a/inc/bearssl_rsa.h b/inc/bearssl_rsa.h index b9362a3..9e5b418 100644 --- a/inc/bearssl_rsa.h +++ b/inc/bearssl_rsa.h @@ -515,6 +515,46 @@ uint32_t br_rsa_i15_pkcs1_sign(const unsigned char *hash_oid, const unsigned char *hash, size_t hash_len, const br_rsa_private_key *sk, unsigned char *x); +/** + * \brief Get "default" RSA implementation (public-key operations). + * + * This returns the preferred implementation of RSA (public-key operations) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_public br_rsa_public_get_default(void); + +/** + * \brief Get "default" RSA implementation (private-key operations). + * + * This returns the preferred implementation of RSA (private-key operations) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_private br_rsa_private_get_default(void); + +/** + * \brief Get "default" RSA implementation (PKCS#1 signature verification). + * + * This returns the preferred implementation of RSA (signature verification) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pkcs1_vrfy br_rsa_pkcs1_vrfy_get_default(void); + +/** + * \brief Get "default" RSA implementation (PKCS#1 signature generation). + * + * This returns the preferred implementation of RSA (signature generation) + * on the current system. + * + * \return the default implementation. + */ +br_rsa_pkcs1_sign br_rsa_pkcs1_sign_get_default(void); + /** * \brief RSA decryption helper, for SSL/TLS. * diff --git a/inc/bearssl_ssl.h b/inc/bearssl_ssl.h index cf1d2db..fee7b3c 100644 --- a/inc/bearssl_ssl.h +++ b/inc/bearssl_ssl.h @@ -1321,6 +1321,18 @@ br_ssl_engine_set_aes_cbc(br_ssl_engine_context *cc, cc->iaes_cbcdec = impl_dec; } +/** + * \brief Set the "default" AES/CBC implementations. + * + * This function configures in the engine the AES implementations that + * should provide best runtime performance on the local system, while + * still being safe (in particular, constant-time). It also sets the + * handlers for CBC records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_cbc(br_ssl_engine_context *cc); + /** * \brief Set the AES/CTR implementation. * @@ -1334,6 +1346,18 @@ br_ssl_engine_set_aes_ctr(br_ssl_engine_context *cc, cc->iaes_ctr = impl; } +/** + * \brief Set the "default" implementations for AES/GCM (AES/CTR + GHASH). + * + * This function configures in the engine the AES/CTR and GHASH + * implementation that should provide best runtime performance on the local + * system, while still being safe (in particular, constant-time). It also + * sets the handlers for GCM records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_aes_gcm(br_ssl_engine_context *cc); + /** * \brief Set the DES/CBC implementations. * @@ -1350,6 +1374,18 @@ br_ssl_engine_set_des_cbc(br_ssl_engine_context *cc, cc->ides_cbcdec = impl_dec; } +/** + * \brief Set the "default" DES/CBC implementations. + * + * This function configures in the engine the DES implementations that + * should provide best runtime performance on the local system, while + * still being safe (in particular, constant-time). It also sets the + * handlers for CBC records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_des_cbc(br_ssl_engine_context *cc); + /** * \brief Set the GHASH implementation (used in GCM mode). * @@ -1388,6 +1424,18 @@ br_ssl_engine_set_poly1305(br_ssl_engine_context *cc, cc->ipoly = ipoly; } +/** + * \brief Set the "default" ChaCha20 and Poly1305 implementations. + * + * This function configures in the engine the ChaCha20 and Poly1305 + * implementations that should provide best runtime performance on the + * local system, while still being safe (in particular, constant-time). + * It also sets the handlers for ChaCha20+Poly1305 records. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_chapol(br_ssl_engine_context *cc); + /** * \brief Set the record encryption and decryption engines for CBC + HMAC. * @@ -1452,6 +1500,29 @@ br_ssl_engine_set_ec(br_ssl_engine_context *cc, const br_ec_impl *iec) cc->iec = iec; } +/** + * \brief Set the "default" EC implementation. + * + * This function sets the elliptic curve implementation for ECDH and + * ECDHE cipher suites, and for ECDSA support. It selects the fastest + * implementation on the current system. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_ec(br_ssl_engine_context *cc); + +/** + * \brief Get the EC implementation configured in the provided engine. + * + * \param cc SSL engine context. + * \return the EC implementation. + */ +static inline const br_ec_impl * +br_ssl_engine_get_ec(br_ssl_engine_context *cc) +{ + return cc->iec; +} + /** * \brief Set the RSA signature verification implementation. * @@ -1469,6 +1540,29 @@ br_ssl_engine_set_rsavrfy(br_ssl_engine_context *cc, br_rsa_pkcs1_vrfy irsavrfy) cc->irsavrfy = irsavrfy; } +/** + * \brief Set the "default" RSA implementation (signature verification). + * + * This function sets the RSA implementation (signature verification) + * to the fastest implementation available on the current platform. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_rsavrfy(br_ssl_engine_context *cc); + +/** + * \brief Get the RSA implementation (signature verification) configured + * in the provided engine. + * + * \param cc SSL engine context. + * \return the RSA signature verification implementation. + */ +static inline br_rsa_pkcs1_vrfy +br_ssl_engine_get_rsavrfy(br_ssl_engine_context *cc) +{ + return cc->irsavrfy; +} + /* * \brief Set the ECDSA implementation (signature verification). * @@ -1490,6 +1584,31 @@ br_ssl_engine_set_ecdsa(br_ssl_engine_context *cc, br_ecdsa_vrfy iecdsa) cc->iecdsa = iecdsa; } +/** + * \brief Set the "default" ECDSA implementation (signature verification). + * + * This function sets the ECDSA implementation (signature verification) + * to the fastest implementation available on the current platform. This + * call also sets the elliptic curve implementation itself, there again + * to the fastest EC implementation available. + * + * \param cc SSL engine context. + */ +void br_ssl_engine_set_default_ecdsa(br_ssl_engine_context *cc); + +/** + * \brief Get the ECDSA implementation (signature verification) configured + * in the provided engine. + * + * \param cc SSL engine context. + * \return the ECDSA signature verification implementation. + */ +static inline br_ecdsa_vrfy +br_ssl_engine_get_ecdsa(br_ssl_engine_context *cc) +{ + return cc->iecdsa; +} + /** * \brief Set the I/O buffer for the SSL engine. * @@ -2457,6 +2576,17 @@ br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub) cc->irsapub = irsapub; } +/** + * \brief Set the "default" RSA implementation for public-key operations. + * + * This sets the RSA implementation in the client context (for encrypting + * the pre-master secret, in `TLS_RSA_*` cipher suites) to the fastest + * available on the current platform. + * + * \param cc client context. + */ +void br_ssl_client_set_default_rsapub(br_ssl_client_context *cc); + /** * \brief Set the minimum ClientHello length (RFC 7685 padding). * @@ -3165,8 +3295,9 @@ struct br_ssl_server_context_ { * 3 = TLS 1.2 with SHA-384 * -- character 3: encryption * a = AES/CBC - * g = AES/GCM * d = 3DES/CBC + * g = AES/GCM + * c = ChaCha20+Poly1305 */ /** diff --git a/mk/Rules.mk b/mk/Rules.mk index 97d55d6..9e2ba07 100644 --- a/mk/Rules.mk +++ b/mk/Rules.mk @@ -1,6 +1,6 @@ # Automatically generated rules. Use 'mkrules.sh' to modify/regenerate. -OBJ = $(OBJDIR)$Pccopy$O $(OBJDIR)$Pdec16be$O $(OBJDIR)$Pdec16le$O $(OBJDIR)$Pdec32be$O $(OBJDIR)$Pdec32le$O $(OBJDIR)$Pdec64be$O $(OBJDIR)$Pdec64le$O $(OBJDIR)$Penc16be$O $(OBJDIR)$Penc16le$O $(OBJDIR)$Penc32be$O $(OBJDIR)$Penc32le$O $(OBJDIR)$Penc64be$O $(OBJDIR)$Penc64le$O $(OBJDIR)$Ppemdec$O $(OBJDIR)$Pec_all_m15$O $(OBJDIR)$Pec_all_m31$O $(OBJDIR)$Pec_c25519_i15$O $(OBJDIR)$Pec_c25519_i31$O $(OBJDIR)$Pec_c25519_m15$O $(OBJDIR)$Pec_c25519_m31$O $(OBJDIR)$Pec_curve25519$O $(OBJDIR)$Pec_p256_m15$O $(OBJDIR)$Pec_p256_m31$O $(OBJDIR)$Pec_prime_i15$O $(OBJDIR)$Pec_prime_i31$O $(OBJDIR)$Pec_secp256r1$O $(OBJDIR)$Pec_secp384r1$O $(OBJDIR)$Pec_secp521r1$O $(OBJDIR)$Pecdsa_atr$O $(OBJDIR)$Pecdsa_i15_bits$O $(OBJDIR)$Pecdsa_i15_sign_asn1$O $(OBJDIR)$Pecdsa_i15_sign_raw$O $(OBJDIR)$Pecdsa_i15_vrfy_asn1$O $(OBJDIR)$Pecdsa_i15_vrfy_raw$O $(OBJDIR)$Pecdsa_i31_bits$O $(OBJDIR)$Pecdsa_i31_sign_asn1$O $(OBJDIR)$Pecdsa_i31_sign_raw$O $(OBJDIR)$Pecdsa_i31_vrfy_asn1$O $(OBJDIR)$Pecdsa_i31_vrfy_raw$O $(OBJDIR)$Pecdsa_rta$O $(OBJDIR)$Pdig_oid$O $(OBJDIR)$Pdig_size$O $(OBJDIR)$Pghash_ctmul$O $(OBJDIR)$Pghash_ctmul32$O $(OBJDIR)$Pghash_ctmul64$O $(OBJDIR)$Pmd5$O $(OBJDIR)$Pmd5sha1$O $(OBJDIR)$Pmultihash$O $(OBJDIR)$Psha1$O $(OBJDIR)$Psha2big$O $(OBJDIR)$Psha2small$O $(OBJDIR)$Pi15_add$O $(OBJDIR)$Pi15_bitlen$O $(OBJDIR)$Pi15_decmod$O $(OBJDIR)$Pi15_decode$O $(OBJDIR)$Pi15_decred$O $(OBJDIR)$Pi15_encode$O $(OBJDIR)$Pi15_fmont$O $(OBJDIR)$Pi15_iszero$O $(OBJDIR)$Pi15_modpow$O $(OBJDIR)$Pi15_modpow2$O $(OBJDIR)$Pi15_montmul$O $(OBJDIR)$Pi15_mulacc$O $(OBJDIR)$Pi15_muladd$O $(OBJDIR)$Pi15_ninv15$O $(OBJDIR)$Pi15_reduce$O $(OBJDIR)$Pi15_rshift$O $(OBJDIR)$Pi15_sub$O $(OBJDIR)$Pi15_tmont$O $(OBJDIR)$Pi31_add$O $(OBJDIR)$Pi31_bitlen$O $(OBJDIR)$Pi31_decmod$O $(OBJDIR)$Pi31_decode$O $(OBJDIR)$Pi31_decred$O $(OBJDIR)$Pi31_encode$O $(OBJDIR)$Pi31_fmont$O $(OBJDIR)$Pi31_iszero$O $(OBJDIR)$Pi31_modpow$O $(OBJDIR)$Pi31_montmul$O $(OBJDIR)$Pi31_mulacc$O $(OBJDIR)$Pi31_muladd$O $(OBJDIR)$Pi31_ninv31$O $(OBJDIR)$Pi31_reduce$O $(OBJDIR)$Pi31_rshift$O $(OBJDIR)$Pi31_sub$O $(OBJDIR)$Pi31_tmont$O $(OBJDIR)$Pi32_add$O $(OBJDIR)$Pi32_bitlen$O $(OBJDIR)$Pi32_decmod$O $(OBJDIR)$Pi32_decode$O $(OBJDIR)$Pi32_decred$O $(OBJDIR)$Pi32_div32$O $(OBJDIR)$Pi32_encode$O $(OBJDIR)$Pi32_fmont$O $(OBJDIR)$Pi32_iszero$O $(OBJDIR)$Pi32_modpow$O $(OBJDIR)$Pi32_montmul$O $(OBJDIR)$Pi32_mulacc$O $(OBJDIR)$Pi32_muladd$O $(OBJDIR)$Pi32_ninv32$O $(OBJDIR)$Pi32_reduce$O $(OBJDIR)$Pi32_sub$O $(OBJDIR)$Pi32_tmont$O $(OBJDIR)$Phmac$O $(OBJDIR)$Phmac_ct$O $(OBJDIR)$Phmac_drbg$O $(OBJDIR)$Prsa_i15_pkcs1_sign$O $(OBJDIR)$Prsa_i15_pkcs1_vrfy$O $(OBJDIR)$Prsa_i15_priv$O $(OBJDIR)$Prsa_i15_pub$O $(OBJDIR)$Prsa_i31_pkcs1_sign$O $(OBJDIR)$Prsa_i31_pkcs1_vrfy$O $(OBJDIR)$Prsa_i31_priv$O $(OBJDIR)$Prsa_i31_pub$O $(OBJDIR)$Prsa_i32_pkcs1_sign$O $(OBJDIR)$Prsa_i32_pkcs1_vrfy$O $(OBJDIR)$Prsa_i32_priv$O $(OBJDIR)$Prsa_i32_pub$O $(OBJDIR)$Prsa_pkcs1_sig_pad$O $(OBJDIR)$Prsa_pkcs1_sig_unpad$O $(OBJDIR)$Prsa_ssl_decrypt$O $(OBJDIR)$Pprf$O $(OBJDIR)$Pprf_md5sha1$O $(OBJDIR)$Pprf_sha256$O $(OBJDIR)$Pprf_sha384$O $(OBJDIR)$Pssl_ccert_single_ec$O $(OBJDIR)$Pssl_ccert_single_rsa$O $(OBJDIR)$Pssl_client$O $(OBJDIR)$Pssl_client_full$O $(OBJDIR)$Pssl_engine$O $(OBJDIR)$Pssl_hashes$O $(OBJDIR)$Pssl_hs_client$O $(OBJDIR)$Pssl_hs_server$O $(OBJDIR)$Pssl_io$O $(OBJDIR)$Pssl_lru$O $(OBJDIR)$Pssl_rec_cbc$O $(OBJDIR)$Pssl_rec_chapol$O $(OBJDIR)$Pssl_rec_gcm$O $(OBJDIR)$Pssl_scert_single_ec$O $(OBJDIR)$Pssl_scert_single_rsa$O $(OBJDIR)$Pssl_server$O $(OBJDIR)$Pssl_server_full_ec$O $(OBJDIR)$Pssl_server_full_rsa$O $(OBJDIR)$Pssl_server_mine2c$O $(OBJDIR)$Pssl_server_mine2g$O $(OBJDIR)$Pssl_server_minf2c$O $(OBJDIR)$Pssl_server_minf2g$O $(OBJDIR)$Pssl_server_minr2g$O $(OBJDIR)$Pssl_server_minu2g$O $(OBJDIR)$Pssl_server_minv2g$O $(OBJDIR)$Paes_big_cbcdec$O $(OBJDIR)$Paes_big_cbcenc$O $(OBJDIR)$Paes_big_ctr$O $(OBJDIR)$Paes_big_dec$O $(OBJDIR)$Paes_big_enc$O $(OBJDIR)$Paes_common$O $(OBJDIR)$Paes_ct$O $(OBJDIR)$Paes_ct64$O $(OBJDIR)$Paes_ct64_cbcdec$O $(OBJDIR)$Paes_ct64_cbcenc$O $(OBJDIR)$Paes_ct64_ctr$O $(OBJDIR)$Paes_ct64_dec$O $(OBJDIR)$Paes_ct64_enc$O $(OBJDIR)$Paes_ct_cbcdec$O $(OBJDIR)$Paes_ct_cbcenc$O $(OBJDIR)$Paes_ct_ctr$O $(OBJDIR)$Paes_ct_dec$O $(OBJDIR)$Paes_ct_enc$O $(OBJDIR)$Paes_small_cbcdec$O $(OBJDIR)$Paes_small_cbcenc$O $(OBJDIR)$Paes_small_ctr$O $(OBJDIR)$Paes_small_dec$O $(OBJDIR)$Paes_small_enc$O $(OBJDIR)$Pchacha20_ct$O $(OBJDIR)$Pdes_ct$O $(OBJDIR)$Pdes_ct_cbcdec$O $(OBJDIR)$Pdes_ct_cbcenc$O $(OBJDIR)$Pdes_support$O $(OBJDIR)$Pdes_tab$O $(OBJDIR)$Pdes_tab_cbcdec$O $(OBJDIR)$Pdes_tab_cbcenc$O $(OBJDIR)$Ppoly1305_ctmul$O $(OBJDIR)$Ppoly1305_ctmul32$O $(OBJDIR)$Ppoly1305_i15$O $(OBJDIR)$Pskey_decoder$O $(OBJDIR)$Px509_decoder$O $(OBJDIR)$Px509_knownkey$O $(OBJDIR)$Px509_minimal$O $(OBJDIR)$Px509_minimal_full$O +OBJ = $(OBJDIR)$Pccopy$O $(OBJDIR)$Pdec16be$O $(OBJDIR)$Pdec16le$O $(OBJDIR)$Pdec32be$O $(OBJDIR)$Pdec32le$O $(OBJDIR)$Pdec64be$O $(OBJDIR)$Pdec64le$O $(OBJDIR)$Penc16be$O $(OBJDIR)$Penc16le$O $(OBJDIR)$Penc32be$O $(OBJDIR)$Penc32le$O $(OBJDIR)$Penc64be$O $(OBJDIR)$Penc64le$O $(OBJDIR)$Ppemdec$O $(OBJDIR)$Pec_all_m15$O $(OBJDIR)$Pec_all_m31$O $(OBJDIR)$Pec_c25519_i15$O $(OBJDIR)$Pec_c25519_i31$O $(OBJDIR)$Pec_c25519_m15$O $(OBJDIR)$Pec_c25519_m31$O $(OBJDIR)$Pec_curve25519$O $(OBJDIR)$Pec_default$O $(OBJDIR)$Pec_p256_m15$O $(OBJDIR)$Pec_p256_m31$O $(OBJDIR)$Pec_prime_i15$O $(OBJDIR)$Pec_prime_i31$O $(OBJDIR)$Pec_secp256r1$O $(OBJDIR)$Pec_secp384r1$O $(OBJDIR)$Pec_secp521r1$O $(OBJDIR)$Pecdsa_atr$O $(OBJDIR)$Pecdsa_default_sign_asn1$O $(OBJDIR)$Pecdsa_default_sign_raw$O $(OBJDIR)$Pecdsa_default_vrfy_asn1$O $(OBJDIR)$Pecdsa_default_vrfy_raw$O $(OBJDIR)$Pecdsa_i15_bits$O $(OBJDIR)$Pecdsa_i15_sign_asn1$O $(OBJDIR)$Pecdsa_i15_sign_raw$O $(OBJDIR)$Pecdsa_i15_vrfy_asn1$O $(OBJDIR)$Pecdsa_i15_vrfy_raw$O $(OBJDIR)$Pecdsa_i31_bits$O $(OBJDIR)$Pecdsa_i31_sign_asn1$O $(OBJDIR)$Pecdsa_i31_sign_raw$O $(OBJDIR)$Pecdsa_i31_vrfy_asn1$O $(OBJDIR)$Pecdsa_i31_vrfy_raw$O $(OBJDIR)$Pecdsa_rta$O $(OBJDIR)$Pdig_oid$O $(OBJDIR)$Pdig_size$O $(OBJDIR)$Pghash_ctmul$O $(OBJDIR)$Pghash_ctmul32$O $(OBJDIR)$Pghash_ctmul64$O $(OBJDIR)$Pghash_pclmul$O $(OBJDIR)$Pmd5$O $(OBJDIR)$Pmd5sha1$O $(OBJDIR)$Pmultihash$O $(OBJDIR)$Psha1$O $(OBJDIR)$Psha2big$O $(OBJDIR)$Psha2small$O $(OBJDIR)$Pi15_add$O $(OBJDIR)$Pi15_bitlen$O $(OBJDIR)$Pi15_decmod$O $(OBJDIR)$Pi15_decode$O $(OBJDIR)$Pi15_decred$O $(OBJDIR)$Pi15_encode$O $(OBJDIR)$Pi15_fmont$O $(OBJDIR)$Pi15_iszero$O $(OBJDIR)$Pi15_modpow$O $(OBJDIR)$Pi15_modpow2$O $(OBJDIR)$Pi15_montmul$O $(OBJDIR)$Pi15_mulacc$O $(OBJDIR)$Pi15_muladd$O $(OBJDIR)$Pi15_ninv15$O $(OBJDIR)$Pi15_reduce$O $(OBJDIR)$Pi15_rshift$O $(OBJDIR)$Pi15_sub$O $(OBJDIR)$Pi15_tmont$O $(OBJDIR)$Pi31_add$O $(OBJDIR)$Pi31_bitlen$O $(OBJDIR)$Pi31_decmod$O $(OBJDIR)$Pi31_decode$O $(OBJDIR)$Pi31_decred$O $(OBJDIR)$Pi31_encode$O $(OBJDIR)$Pi31_fmont$O $(OBJDIR)$Pi31_iszero$O $(OBJDIR)$Pi31_modpow$O $(OBJDIR)$Pi31_montmul$O $(OBJDIR)$Pi31_mulacc$O $(OBJDIR)$Pi31_muladd$O $(OBJDIR)$Pi31_ninv31$O $(OBJDIR)$Pi31_reduce$O $(OBJDIR)$Pi31_rshift$O $(OBJDIR)$Pi31_sub$O $(OBJDIR)$Pi31_tmont$O $(OBJDIR)$Pi32_add$O $(OBJDIR)$Pi32_bitlen$O $(OBJDIR)$Pi32_decmod$O $(OBJDIR)$Pi32_decode$O $(OBJDIR)$Pi32_decred$O $(OBJDIR)$Pi32_div32$O $(OBJDIR)$Pi32_encode$O $(OBJDIR)$Pi32_fmont$O $(OBJDIR)$Pi32_iszero$O $(OBJDIR)$Pi32_modpow$O $(OBJDIR)$Pi32_montmul$O $(OBJDIR)$Pi32_mulacc$O $(OBJDIR)$Pi32_muladd$O $(OBJDIR)$Pi32_ninv32$O $(OBJDIR)$Pi32_reduce$O $(OBJDIR)$Pi32_sub$O $(OBJDIR)$Pi32_tmont$O $(OBJDIR)$Phmac$O $(OBJDIR)$Phmac_ct$O $(OBJDIR)$Phmac_drbg$O $(OBJDIR)$Prsa_default_pkcs1_sign$O $(OBJDIR)$Prsa_default_pkcs1_vrfy$O $(OBJDIR)$Prsa_default_priv$O $(OBJDIR)$Prsa_default_pub$O $(OBJDIR)$Prsa_i15_pkcs1_sign$O $(OBJDIR)$Prsa_i15_pkcs1_vrfy$O $(OBJDIR)$Prsa_i15_priv$O $(OBJDIR)$Prsa_i15_pub$O $(OBJDIR)$Prsa_i31_pkcs1_sign$O $(OBJDIR)$Prsa_i31_pkcs1_vrfy$O $(OBJDIR)$Prsa_i31_priv$O $(OBJDIR)$Prsa_i31_pub$O $(OBJDIR)$Prsa_i32_pkcs1_sign$O $(OBJDIR)$Prsa_i32_pkcs1_vrfy$O $(OBJDIR)$Prsa_i32_priv$O $(OBJDIR)$Prsa_i32_pub$O $(OBJDIR)$Prsa_pkcs1_sig_pad$O $(OBJDIR)$Prsa_pkcs1_sig_unpad$O $(OBJDIR)$Prsa_ssl_decrypt$O $(OBJDIR)$Pprf$O $(OBJDIR)$Pprf_md5sha1$O $(OBJDIR)$Pprf_sha256$O $(OBJDIR)$Pprf_sha384$O $(OBJDIR)$Pssl_ccert_single_ec$O $(OBJDIR)$Pssl_ccert_single_rsa$O $(OBJDIR)$Pssl_client$O $(OBJDIR)$Pssl_client_default_rsapub$O $(OBJDIR)$Pssl_client_full$O $(OBJDIR)$Pssl_engine$O $(OBJDIR)$Pssl_engine_default_aescbc$O $(OBJDIR)$Pssl_engine_default_aesgcm$O $(OBJDIR)$Pssl_engine_default_chapol$O $(OBJDIR)$Pssl_engine_default_descbc$O $(OBJDIR)$Pssl_engine_default_ec$O $(OBJDIR)$Pssl_engine_default_ecdsa$O $(OBJDIR)$Pssl_engine_default_rsavrfy$O $(OBJDIR)$Pssl_hashes$O $(OBJDIR)$Pssl_hs_client$O $(OBJDIR)$Pssl_hs_server$O $(OBJDIR)$Pssl_io$O $(OBJDIR)$Pssl_lru$O $(OBJDIR)$Pssl_rec_cbc$O $(OBJDIR)$Pssl_rec_chapol$O $(OBJDIR)$Pssl_rec_gcm$O $(OBJDIR)$Pssl_scert_single_ec$O $(OBJDIR)$Pssl_scert_single_rsa$O $(OBJDIR)$Pssl_server$O $(OBJDIR)$Pssl_server_full_ec$O $(OBJDIR)$Pssl_server_full_rsa$O $(OBJDIR)$Pssl_server_mine2c$O $(OBJDIR)$Pssl_server_mine2g$O $(OBJDIR)$Pssl_server_minf2c$O $(OBJDIR)$Pssl_server_minf2g$O $(OBJDIR)$Pssl_server_minr2g$O $(OBJDIR)$Pssl_server_minu2g$O $(OBJDIR)$Pssl_server_minv2g$O $(OBJDIR)$Paes_big_cbcdec$O $(OBJDIR)$Paes_big_cbcenc$O $(OBJDIR)$Paes_big_ctr$O $(OBJDIR)$Paes_big_dec$O $(OBJDIR)$Paes_big_enc$O $(OBJDIR)$Paes_common$O $(OBJDIR)$Paes_ct$O $(OBJDIR)$Paes_ct64$O $(OBJDIR)$Paes_ct64_cbcdec$O $(OBJDIR)$Paes_ct64_cbcenc$O $(OBJDIR)$Paes_ct64_ctr$O $(OBJDIR)$Paes_ct64_dec$O $(OBJDIR)$Paes_ct64_enc$O $(OBJDIR)$Paes_ct_cbcdec$O $(OBJDIR)$Paes_ct_cbcenc$O $(OBJDIR)$Paes_ct_ctr$O $(OBJDIR)$Paes_ct_dec$O $(OBJDIR)$Paes_ct_enc$O $(OBJDIR)$Paes_small_cbcdec$O $(OBJDIR)$Paes_small_cbcenc$O $(OBJDIR)$Paes_small_ctr$O $(OBJDIR)$Paes_small_dec$O $(OBJDIR)$Paes_small_enc$O $(OBJDIR)$Paes_x86ni$O $(OBJDIR)$Paes_x86ni_cbcdec$O $(OBJDIR)$Paes_x86ni_cbcenc$O $(OBJDIR)$Paes_x86ni_ctr$O $(OBJDIR)$Pchacha20_ct$O $(OBJDIR)$Pdes_ct$O $(OBJDIR)$Pdes_ct_cbcdec$O $(OBJDIR)$Pdes_ct_cbcenc$O $(OBJDIR)$Pdes_support$O $(OBJDIR)$Pdes_tab$O $(OBJDIR)$Pdes_tab_cbcdec$O $(OBJDIR)$Pdes_tab_cbcenc$O $(OBJDIR)$Ppoly1305_ctmul$O $(OBJDIR)$Ppoly1305_ctmul32$O $(OBJDIR)$Ppoly1305_i15$O $(OBJDIR)$Pskey_decoder$O $(OBJDIR)$Px509_decoder$O $(OBJDIR)$Px509_knownkey$O $(OBJDIR)$Px509_minimal$O $(OBJDIR)$Px509_minimal_full$O OBJBRSSL = $(OBJDIR)$Pbrssl$O $(OBJDIR)$Pcerts$O $(OBJDIR)$Pchain$O $(OBJDIR)$Pclient$O $(OBJDIR)$Perrors$O $(OBJDIR)$Pfiles$O $(OBJDIR)$Pkeys$O $(OBJDIR)$Pnames$O $(OBJDIR)$Pserver$O $(OBJDIR)$Pskey$O $(OBJDIR)$Psslio$O $(OBJDIR)$Pta$O $(OBJDIR)$Pvector$O $(OBJDIR)$Pverify$O $(OBJDIR)$Pxmem$O OBJTESTCRYPTO = $(OBJDIR)$Ptest_crypto$O OBJTESTSPEED = $(OBJDIR)$Ptest_speed$O @@ -122,6 +122,9 @@ $(OBJDIR)$Pec_c25519_m31$O: src$Pec$Pec_c25519_m31.c $(HEADERSPRIV) $(OBJDIR)$Pec_curve25519$O: src$Pec$Pec_curve25519.c $(HEADERSPRIV) $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_curve25519$O src$Pec$Pec_curve25519.c +$(OBJDIR)$Pec_default$O: src$Pec$Pec_default.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_default$O src$Pec$Pec_default.c + $(OBJDIR)$Pec_p256_m15$O: src$Pec$Pec_p256_m15.c $(HEADERSPRIV) $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pec_p256_m15$O src$Pec$Pec_p256_m15.c @@ -146,6 +149,18 @@ $(OBJDIR)$Pec_secp521r1$O: src$Pec$Pec_secp521r1.c $(HEADERSPRIV) $(OBJDIR)$Pecdsa_atr$O: src$Pec$Pecdsa_atr.c $(HEADERSPRIV) $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_atr$O src$Pec$Pecdsa_atr.c +$(OBJDIR)$Pecdsa_default_sign_asn1$O: src$Pec$Pecdsa_default_sign_asn1.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_default_sign_asn1$O src$Pec$Pecdsa_default_sign_asn1.c + +$(OBJDIR)$Pecdsa_default_sign_raw$O: src$Pec$Pecdsa_default_sign_raw.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_default_sign_raw$O src$Pec$Pecdsa_default_sign_raw.c + +$(OBJDIR)$Pecdsa_default_vrfy_asn1$O: src$Pec$Pecdsa_default_vrfy_asn1.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_default_vrfy_asn1$O src$Pec$Pecdsa_default_vrfy_asn1.c + +$(OBJDIR)$Pecdsa_default_vrfy_raw$O: src$Pec$Pecdsa_default_vrfy_raw.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_default_vrfy_raw$O src$Pec$Pecdsa_default_vrfy_raw.c + $(OBJDIR)$Pecdsa_i15_bits$O: src$Pec$Pecdsa_i15_bits.c $(HEADERSPRIV) $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pecdsa_i15_bits$O src$Pec$Pecdsa_i15_bits.c @@ -194,6 +209,9 @@ $(OBJDIR)$Pghash_ctmul32$O: src$Phash$Pghash_ctmul32.c $(HEADERSPRIV) $(OBJDIR)$Pghash_ctmul64$O: src$Phash$Pghash_ctmul64.c $(HEADERSPRIV) $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pghash_ctmul64$O src$Phash$Pghash_ctmul64.c +$(OBJDIR)$Pghash_pclmul$O: src$Phash$Pghash_pclmul.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pghash_pclmul$O src$Phash$Pghash_pclmul.c + $(OBJDIR)$Pmd5$O: src$Phash$Pmd5.c $(HEADERSPRIV) $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pmd5$O src$Phash$Pmd5.c @@ -377,6 +395,18 @@ $(OBJDIR)$Phmac_ct$O: src$Pmac$Phmac_ct.c $(HEADERSPRIV) $(OBJDIR)$Phmac_drbg$O: src$Prand$Phmac_drbg.c $(HEADERSPRIV) $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Phmac_drbg$O src$Prand$Phmac_drbg.c +$(OBJDIR)$Prsa_default_pkcs1_sign$O: src$Prsa$Prsa_default_pkcs1_sign.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_default_pkcs1_sign$O src$Prsa$Prsa_default_pkcs1_sign.c + +$(OBJDIR)$Prsa_default_pkcs1_vrfy$O: src$Prsa$Prsa_default_pkcs1_vrfy.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_default_pkcs1_vrfy$O src$Prsa$Prsa_default_pkcs1_vrfy.c + +$(OBJDIR)$Prsa_default_priv$O: src$Prsa$Prsa_default_priv.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_default_priv$O src$Prsa$Prsa_default_priv.c + +$(OBJDIR)$Prsa_default_pub$O: src$Prsa$Prsa_default_pub.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_default_pub$O src$Prsa$Prsa_default_pub.c + $(OBJDIR)$Prsa_i15_pkcs1_sign$O: src$Prsa$Prsa_i15_pkcs1_sign.c $(HEADERSPRIV) $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Prsa_i15_pkcs1_sign$O src$Prsa$Prsa_i15_pkcs1_sign.c @@ -443,12 +473,36 @@ $(OBJDIR)$Pssl_ccert_single_rsa$O: src$Pssl$Pssl_ccert_single_rsa.c $(HEADERSPRI $(OBJDIR)$Pssl_client$O: src$Pssl$Pssl_client.c $(HEADERSPRIV) $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_client$O src$Pssl$Pssl_client.c +$(OBJDIR)$Pssl_client_default_rsapub$O: src$Pssl$Pssl_client_default_rsapub.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_client_default_rsapub$O src$Pssl$Pssl_client_default_rsapub.c + $(OBJDIR)$Pssl_client_full$O: src$Pssl$Pssl_client_full.c $(HEADERSPRIV) $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_client_full$O src$Pssl$Pssl_client_full.c $(OBJDIR)$Pssl_engine$O: src$Pssl$Pssl_engine.c $(HEADERSPRIV) $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine$O src$Pssl$Pssl_engine.c +$(OBJDIR)$Pssl_engine_default_aescbc$O: src$Pssl$Pssl_engine_default_aescbc.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine_default_aescbc$O src$Pssl$Pssl_engine_default_aescbc.c + +$(OBJDIR)$Pssl_engine_default_aesgcm$O: src$Pssl$Pssl_engine_default_aesgcm.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine_default_aesgcm$O src$Pssl$Pssl_engine_default_aesgcm.c + +$(OBJDIR)$Pssl_engine_default_chapol$O: src$Pssl$Pssl_engine_default_chapol.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine_default_chapol$O src$Pssl$Pssl_engine_default_chapol.c + +$(OBJDIR)$Pssl_engine_default_descbc$O: src$Pssl$Pssl_engine_default_descbc.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine_default_descbc$O src$Pssl$Pssl_engine_default_descbc.c + +$(OBJDIR)$Pssl_engine_default_ec$O: src$Pssl$Pssl_engine_default_ec.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine_default_ec$O src$Pssl$Pssl_engine_default_ec.c + +$(OBJDIR)$Pssl_engine_default_ecdsa$O: src$Pssl$Pssl_engine_default_ecdsa.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine_default_ecdsa$O src$Pssl$Pssl_engine_default_ecdsa.c + +$(OBJDIR)$Pssl_engine_default_rsavrfy$O: src$Pssl$Pssl_engine_default_rsavrfy.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_engine_default_rsavrfy$O src$Pssl$Pssl_engine_default_rsavrfy.c + $(OBJDIR)$Pssl_hashes$O: src$Pssl$Pssl_hashes.c $(HEADERSPRIV) $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pssl_hashes$O src$Pssl$Pssl_hashes.c @@ -578,6 +632,18 @@ $(OBJDIR)$Paes_small_dec$O: src$Psymcipher$Paes_small_dec.c $(HEADERSPRIV) $(OBJDIR)$Paes_small_enc$O: src$Psymcipher$Paes_small_enc.c $(HEADERSPRIV) $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_small_enc$O src$Psymcipher$Paes_small_enc.c +$(OBJDIR)$Paes_x86ni$O: src$Psymcipher$Paes_x86ni.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_x86ni$O src$Psymcipher$Paes_x86ni.c + +$(OBJDIR)$Paes_x86ni_cbcdec$O: src$Psymcipher$Paes_x86ni_cbcdec.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_x86ni_cbcdec$O src$Psymcipher$Paes_x86ni_cbcdec.c + +$(OBJDIR)$Paes_x86ni_cbcenc$O: src$Psymcipher$Paes_x86ni_cbcenc.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_x86ni_cbcenc$O src$Psymcipher$Paes_x86ni_cbcenc.c + +$(OBJDIR)$Paes_x86ni_ctr$O: src$Psymcipher$Paes_x86ni_ctr.c $(HEADERSPRIV) + $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Paes_x86ni_ctr$O src$Psymcipher$Paes_x86ni_ctr.c + $(OBJDIR)$Pchacha20_ct$O: src$Psymcipher$Pchacha20_ct.c $(HEADERSPRIV) $(CC) $(CFLAGS) $(INCFLAGS) $(CCOUT)$(OBJDIR)$Pchacha20_ct$O src$Psymcipher$Pchacha20_ct.c diff --git a/mk/mkrules.sh b/mk/mkrules.sh index 8e2132b..4c9d2cd 100755 --- a/mk/mkrules.sh +++ b/mk/mkrules.sh @@ -70,6 +70,7 @@ coresrc=" \ src/ec/ec_c25519_m15.c \ src/ec/ec_c25519_m31.c \ src/ec/ec_curve25519.c \ + src/ec/ec_default.c \ src/ec/ec_p256_m15.c \ src/ec/ec_p256_m31.c \ src/ec/ec_prime_i15.c \ @@ -78,6 +79,10 @@ coresrc=" \ src/ec/ec_secp384r1.c \ src/ec/ec_secp521r1.c \ src/ec/ecdsa_atr.c \ + src/ec/ecdsa_default_sign_asn1.c \ + src/ec/ecdsa_default_sign_raw.c \ + src/ec/ecdsa_default_vrfy_asn1.c \ + src/ec/ecdsa_default_vrfy_raw.c \ src/ec/ecdsa_i15_bits.c \ src/ec/ecdsa_i15_sign_asn1.c \ src/ec/ecdsa_i15_sign_raw.c \ @@ -94,6 +99,7 @@ coresrc=" \ src/hash/ghash_ctmul.c \ src/hash/ghash_ctmul32.c \ src/hash/ghash_ctmul64.c \ + src/hash/ghash_pclmul.c \ src/hash/md5.c \ src/hash/md5sha1.c \ src/hash/multihash.c \ @@ -155,6 +161,10 @@ coresrc=" \ src/mac/hmac.c \ src/mac/hmac_ct.c \ src/rand/hmac_drbg.c \ + src/rsa/rsa_default_pkcs1_sign.c \ + src/rsa/rsa_default_pkcs1_vrfy.c \ + src/rsa/rsa_default_priv.c \ + src/rsa/rsa_default_pub.c \ src/rsa/rsa_i15_pkcs1_sign.c \ src/rsa/rsa_i15_pkcs1_vrfy.c \ src/rsa/rsa_i15_priv.c \ @@ -177,8 +187,16 @@ coresrc=" \ src/ssl/ssl_ccert_single_ec.c \ src/ssl/ssl_ccert_single_rsa.c \ src/ssl/ssl_client.c \ + src/ssl/ssl_client_default_rsapub.c \ src/ssl/ssl_client_full.c \ src/ssl/ssl_engine.c \ + src/ssl/ssl_engine_default_aescbc.c \ + src/ssl/ssl_engine_default_aesgcm.c \ + src/ssl/ssl_engine_default_chapol.c \ + src/ssl/ssl_engine_default_descbc.c \ + src/ssl/ssl_engine_default_ec.c \ + src/ssl/ssl_engine_default_ecdsa.c \ + src/ssl/ssl_engine_default_rsavrfy.c \ src/ssl/ssl_hashes.c \ src/ssl/ssl_hs_client.c \ src/ssl/ssl_hs_server.c \ @@ -222,6 +240,10 @@ coresrc=" \ src/symcipher/aes_small_ctr.c \ src/symcipher/aes_small_dec.c \ src/symcipher/aes_small_enc.c \ + src/symcipher/aes_x86ni.c \ + src/symcipher/aes_x86ni_cbcdec.c \ + src/symcipher/aes_x86ni_cbcenc.c \ + src/symcipher/aes_x86ni_ctr.c \ src/symcipher/chacha20_ct.c \ src/symcipher/des_ct.c \ src/symcipher/des_ct_cbcdec.c \ diff --git a/samples/custom_profile.c b/samples/custom_profile.c index e88d948..7191958 100644 --- a/samples/custom_profile.c +++ b/samples/custom_profile.c @@ -53,6 +53,8 @@ example_client_profile(br_ssl_client_context *cc * by BearSSL; trim it done to your needs. */ static const uint16_t suites[] = { + BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, @@ -133,6 +135,15 @@ example_client_profile(br_ssl_client_context *cc * -- With TLS 1.2, cipher suites with a name ending in "SHA" * require both SHA-256 and SHA-1. * + * Moreover, these hash functions are also used to compute + * hashes supporting signatures on the server side (for ECDHE_* + * cipher suites), and on the client side (for client + * certificates, except in the case of full static ECDH). In TLS + * 1.0 and 1.1, SHA-1 (and also MD5) will be used, but with TLS + * 1.2 these hash functions are negotiated between client and + * server; SHA-256 and/or SHA-384 should be sufficient in + * practice. + * * Note that with current implementations, SHA-224 and SHA-256 * share the same file, so if you use one, you may have the other * one with no additional overhead. Similarly, SHA-384 and SHA-512 @@ -168,14 +179,46 @@ example_client_profile(br_ssl_client_context *cc * cipher suites). * * -- ECDSA signature verification is needed for "ECDHE_ECDSA" - * cipher suites (but not for ECDH_ECDSA or ECDH_RSA). + * cipher suites (but not for ECDHE_RSA, ECDH_ECDSA or ECDH_RSA). + * + * The RSA code comes in three variants, called "i15", "i31" and + * "i32". The "i31" code is somewhat faster than the "i32" code. + * Usually, "i31" is faster than "i15", except on some specific + * architectures (ARM Cortex M0, M0+, M1 and M3) where the "i15" + * should be prefered (the "i15" code is constant-time, while + * the "i31" is not, and the "i15" code is faster anyway). + * + * ECDSA code also comes in "i15" and "i31" variants. As in the + * case of RSA, the "i31" code is faster, except on the small + * ARM Cortex M, where the "i15" code is faster and safer. + * + * There are no less than 10 elliptic curve implementations: + * + * - ec_c25519_i15, ec_c25519_i31, ec_c25519_m15 and ec_c25519_m31 + * implement Curve25519. + * + * - ec_p256_m15 and ec_p256_m31 implement NIST curve P-256. * - * The RSA code comes in two variants, called "i31" and "i32". - * Right now, the "i31" is somewhat faster. + * - ec_prime_i15 and ec_prime_i31 implement NIST curves P-256, + * P-384 and P-521. + * + * - ec_all_m15 is an aggregate implementation that uses + * ec_c25519_m15, ec_p256_m15 and ec_prime_i15. + * + * - ec_all_m31 is an aggregate implementation that uses + * ec_c25519_m31, ec_p256_m31 and ec_prime_i31. + * + * For a given curve, "m15" is faster than "i15" (but possibly + * with a larger code footprint) and "m31" is faster than "i31" + * (there again with a larger code footprint). For best + * performance, use ec_all_m31, except on the small ARM Cortex M + * where ec_all_m15 should be used. Referencing the other + * implementations directly will result in smaller code, but + * support for fewer curves and possibly lower performance. */ br_ssl_client_set_rsapub(cc, &br_rsa_i31_public); br_ssl_client_set_rsavrfy(cc, &br_rsa_i31_pkcs1_vrfy); - br_ssl_engine_set_ec(&cc->eng, &br_ec_prime_i31); + br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m31); br_ssl_client_set_ecdsa(cc, &br_ecdsa_i31_vrfy_asn1); /* @@ -184,6 +227,8 @@ example_client_profile(br_ssl_client_context *cc * need the CBC record handler ("set_cbc"). * -- Cipher suites in AES_128_GCM and AES_256_GCM need the GCM * record handler ("set_gcm"). + * -- Cipher suites in CHACHA20_POLY1305 need the ChaCha20+Poly1305 + * record handler ("set_chapol"). */ br_ssl_engine_set_cbc(&cc->eng, &br_sslrec_in_cbc_vtable, @@ -191,6 +236,9 @@ example_client_profile(br_ssl_client_context *cc br_ssl_engine_set_gcm(&cc->eng, &br_sslrec_in_gcm_vtable, &br_sslrec_out_gcm_vtable); + br_ssl_engine_set_chapol(&cc->eng, + &br_sslrec_in_chapol_vtable, + &br_sslrec_out_chapol_vtable); /* * Symmetric encryption: @@ -230,6 +278,9 @@ example_client_profile(br_ssl_client_context *cc * is decently fast and still resonably compact, * but it is not constant-time. * + * aes_x86ni Very fast implementation that uses the AES-NI + * opcodes on recent x86 CPU. + * * Whether having constant-time implementations is absolutely * required for security depends on the context (in particular * whether the target architecture actually has cache memory), diff --git a/src/config.h b/src/config.h index 5de3a5a..9eadaf4 100644 --- a/src/config.h +++ b/src/config.h @@ -41,6 +41,16 @@ #define BR_64 1 */ +/* + * When BR_LOMUL is enabled, then multiplications of 32-bit values whose + * result are truncated to the low 32 bits are assumed to be + * substantially more efficient than 32-bit multiplications that yield + * 64-bit results. This is typically the case on low-end ARM Cortex M + * systems (M0, M0+, M1, and arguably M3 and M4 as well). + * +#define BR_LOMUL 1 + */ + /* * When BR_SLOW_MUL is enabled, multiplications are assumed to be * substantially slow with regards to other integer operations, thus @@ -127,4 +137,29 @@ #define BR_USE_WIN32_TIME 1 */ +/* + * When BR_ARMEL_CORTEXM_GCC is enabled, some operations are replaced with + * inline assembly which is shorter and/or faster. This should be used + * only when all of the following are true: + * - target architecture is ARM in Thumb mode + * - target endianness is little-endian + * - compiler is GCC (or GCC-compatible for inline assembly syntax) + * + * This is meant for the low-end cores (Cortex M0, M0+, M1, M3). + * Note: if BR_LOMUL is not explicitly enabled or disabled, then + * enabling BR_ARMEL_CORTEXM_GCC also enables BR_LOMUL. + * +#define BR_ARMEL_CORTEXM_GCC 1 + */ + +/* + * When BR_AES_X86NI is enabled, the AES implementation using the x86 "NI" + * instructions (dedicated AES opcodes) will be compiled. If this is not + * enabled explicitly, then that AES implementation will be compiled only + * if a compatible compiler is detected. If set explicitly to 0, the + * implementation will not be compiled at all. + * +#define BR_AES_X86NI 1 + */ + #endif diff --git a/src/ec/ec_default.c b/src/ec/ec_default.c new file mode 100644 index 0000000..7bb6e0c --- /dev/null +++ b/src/ec/ec_default.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_ec.h */ +const br_ec_impl * +br_ec_get_default(void) +{ +#if BR_LOMUL + return &br_ec_all_m15; +#else + return &br_ec_all_m31; +#endif +} diff --git a/src/ec/ecdsa_default_sign_asn1.c b/src/ec/ecdsa_default_sign_asn1.c new file mode 100644 index 0000000..afbf8ac --- /dev/null +++ b/src/ec/ecdsa_default_sign_asn1.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_ec.h */ +br_ecdsa_sign +br_ecdsa_sign_asn1_get_default(void) +{ +#if BR_LOMUL + return &br_ecdsa_i15_sign_asn1; +#else + return &br_ecdsa_i31_sign_asn1; +#endif +} diff --git a/src/ec/ecdsa_default_sign_raw.c b/src/ec/ecdsa_default_sign_raw.c new file mode 100644 index 0000000..287c970 --- /dev/null +++ b/src/ec/ecdsa_default_sign_raw.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_ec.h */ +br_ecdsa_sign +br_ecdsa_sign_raw_get_default(void) +{ +#if BR_LOMUL + return &br_ecdsa_i15_sign_raw; +#else + return &br_ecdsa_i31_sign_raw; +#endif +} diff --git a/src/ec/ecdsa_default_vrfy_asn1.c b/src/ec/ecdsa_default_vrfy_asn1.c new file mode 100644 index 0000000..fe0996e --- /dev/null +++ b/src/ec/ecdsa_default_vrfy_asn1.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_ec.h */ +br_ecdsa_vrfy +br_ecdsa_vrfy_asn1_get_default(void) +{ +#if BR_LOMUL + return &br_ecdsa_i15_vrfy_asn1; +#else + return &br_ecdsa_i31_vrfy_asn1; +#endif +} diff --git a/src/ec/ecdsa_default_vrfy_raw.c b/src/ec/ecdsa_default_vrfy_raw.c new file mode 100644 index 0000000..e564a10 --- /dev/null +++ b/src/ec/ecdsa_default_vrfy_raw.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_ec.h */ +br_ecdsa_vrfy +br_ecdsa_vrfy_raw_get_default(void) +{ +#if BR_LOMUL + return &br_ecdsa_i15_vrfy_raw; +#else + return &br_ecdsa_i31_vrfy_raw; +#endif +} diff --git a/src/hash/ghash_pclmul.c b/src/hash/ghash_pclmul.c new file mode 100644 index 0000000..c709889 --- /dev/null +++ b/src/hash/ghash_pclmul.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* + * This is the GHASH implementation that leverages the pclmulqdq opcode + * (from the AES-NI instructions). + */ + +#if BR_AES_X86NI + +#if BR_AES_X86NI_GCC +/* #pragma GCC target "sse2,ssse3,pclmul" */ +#include +#include +#include +#endif + +#if BR_AES_X86NI_MSC +#include +#endif + +/* see bearssl_hash.h */ +BR_TARGET("ssse3,pclmul") +void +br_ghash_pclmul(void *y, const void *h, const void *data, size_t len) +{ + /* + * TODO: loop below processes one 16-bit word at a time. We + * could parallelize, using: + * ((y+x0)*h+x1)*h = (y+x0)*(h^2) + x1*h + * i.e. precompute h^2, then handle two words at a time, mostly + * in parallel (this may extend to more words as well...). + */ + + const unsigned char *buf; + __m128i yx, hx; + __m128i h0, h1, h2; + __m128i byteswap_index; + + byteswap_index = _mm_set_epi8( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + yx = _mm_loadu_si128(y); + hx = _mm_loadu_si128(h); + yx = _mm_shuffle_epi8(yx, byteswap_index); + hx = _mm_shuffle_epi8(hx, byteswap_index); + + /* + * We byte-swap y and h for full big-endian interpretation + * (see below). + */ + + h0 = hx; + h1 = _mm_shuffle_epi32(hx, 0x0E); + h2 = _mm_xor_si128(h0, h1); + + buf = data; + while (len > 0) { + __m128i x; + __m128i t0, t1, t2, v0, v1, v2, v3; + __m128i y0, y1, y2; + + /* + * Load next 128-bit word. If there are not enough bytes + * for the next word, we pad it with zeros (as per the + * API for this function; it's also what is useful for + * implementation of GCM). + */ + if (len >= 16) { + x = _mm_loadu_si128((const void *)buf); + buf += 16; + len -= 16; + } else { + unsigned char tmp[16]; + + memcpy(tmp, buf, len); + memset(tmp + len, 0, (sizeof tmp) - len); + x = _mm_loadu_si128((void *)tmp); + len = 0; + } + + /* + * Specification of GCM is basically "full little-endian", + * i.e. leftmost bit is most significant; but decoding + * performed by _mm_loadu_si128 is "mixed endian" (leftmost + * _byte_ is least significant, but within each byte, the + * leftmost _bit_ is most significant). We could reverse + * bits in each byte; however, it is more efficient to + * swap the bytes and thus emulate full big-endian + * decoding. + * + * Big-endian works here because multiplication in + * GF[2](X) is "carry-less", thereby allowing reversal: + * if rev_n(x) consists in reversing the order of bits + * in x, then: + * rev_128(A)*rev_128(B) = rev_255(A*B) + * so we can compute A*B by using rev_128(A) and rev_128(B), + * and an extra shift at the end (because 255 != 256). Bit + * reversal is exactly what happens when converting from + * full little-endian to full big-endian. + */ + x = _mm_shuffle_epi8(x, byteswap_index); + yx = _mm_xor_si128(yx, x); + + /* + * We want the product to be broken down into four + * 64-bit values, because there is no SSE* opcode that + * can do a shift on a 128-bit value. + */ + y0 = yx; + y1 = _mm_shuffle_epi32(yx, 0x0E); + y2 = _mm_xor_si128(y0, y1); + t0 = _mm_clmulepi64_si128(y0, h0, 0x00); + t1 = _mm_clmulepi64_si128(yx, hx, 0x11); + t2 = _mm_clmulepi64_si128(y2, h2, 0x00); + t2 = _mm_xor_si128(t2, _mm_xor_si128(t0, t1)); + v0 = t0; + v1 = _mm_xor_si128(_mm_shuffle_epi32(t0, 0x0E), t2); + v2 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E)); + v3 = _mm_shuffle_epi32(t1, 0x0E); + + /* + * Do the corrective 1-bit shift (255->256). + */ + v3 = _mm_or_si128( + _mm_slli_epi64(v3, 1), + _mm_srli_epi64(v2, 63)); + v2 = _mm_or_si128( + _mm_slli_epi64(v2, 1), + _mm_srli_epi64(v1, 63)); + v1 = _mm_or_si128( + _mm_slli_epi64(v1, 1), + _mm_srli_epi64(v0, 63)); + v0 = _mm_slli_epi64(v0, 1); + + /* + * Perform polynomial reduction into GF(2^128). + */ + v2 = _mm_xor_si128( + v2, + _mm_xor_si128( + _mm_xor_si128( + v0, + _mm_srli_epi64(v0, 1)), + _mm_xor_si128( + _mm_srli_epi64(v0, 2), + _mm_srli_epi64(v0, 7)))); + v1 = _mm_xor_si128( + _mm_xor_si128( + v1, + _mm_slli_epi64(v0, 63)), + _mm_xor_si128( + _mm_slli_epi64(v0, 62), + _mm_slli_epi64(v0, 57))); + v3 = _mm_xor_si128( + v3, + _mm_xor_si128( + _mm_xor_si128( + v1, + _mm_srli_epi64(v1, 1)), + _mm_xor_si128( + _mm_srli_epi64(v1, 2), + _mm_srli_epi64(v1, 7)))); + v2 = _mm_xor_si128( + _mm_xor_si128( + v2, + _mm_slli_epi64(v1, 63)), + _mm_xor_si128( + _mm_slli_epi64(v1, 62), + _mm_slli_epi64(v1, 57))); + + /* + * We reduced toward the high words (v2 and v3), which + * are the new value for y. + */ + yx = _mm_unpacklo_epi64(v2, v3); + } + + yx = _mm_shuffle_epi8(yx, byteswap_index); + _mm_storeu_si128(y, yx); +} + +/* + * Test CPU support for PCLMULQDQ. + */ +static int +pclmul_supported(void) +{ + /* + * Bit mask for features in ECX: + * 1 PCLMULQDQ support + */ +#define MASK 0x00000002 + +#if BR_AES_X86NI_GCC + unsigned eax, ebx, ecx, edx; + + if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) { + return (ecx & MASK) == MASK; + } else { + return 0; + } +#elif BR_AES_X86NI_MSC + int info[4]; + + __cpuid(info, 1); + return ((uint32_t)info[2] & MASK) == MASK; +#else + return 0; +#endif + +#undef MASK +} + +/* see bearssl_hash.h */ +br_ghash +br_ghash_pclmul_get(void) +{ + return pclmul_supported() ? &br_ghash_pclmul : 0; +} + +#else + +/* see bearssl_hash.h */ +br_ghash +br_ghash_pclmul_get(void) +{ + return 0; +} + +#endif diff --git a/src/inner.h b/src/inner.h index 2bb8192..472dc2e 100644 --- a/src/inner.h +++ b/src/inner.h @@ -105,6 +105,55 @@ #endif #endif +/* + * Set BR_LOMUL on platforms where it makes sense. + */ +#ifndef BR_LOMUL +#if BR_ARMEL_CORTEX_GCC +#define BR_LOMUL 1 +#endif +#endif + +/* + * Determine whether x86 AES instructions are understood by the compiler. + */ +#ifndef BR_AES_X86NI + +#if (__i386__ || __x86_64__) \ + && ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) \ + || (__clang_major__ > 3 \ + || (__clang_major__ == 3 && __clang_minor__ >= 7))) +#define BR_AES_X86NI 1 +#elif (_M_IX86 || _M_X64) && (_MSC_VER >= 1700) +#define BR_AES_X86NI 1 +#endif +#endif + +/* + * If we use x86 AES instruction, determine the compiler brand. + */ +#if BR_AES_X86NI +#ifndef BR_AES_X86NI_GCC +#if __GNUC__ +#define BR_AES_X86NI_GCC 1 +#endif +#endif +#ifndef BR_AES_X86NI_MSC +#if _MSC_VER >= 1700 +#define BR_AES_X86NI_MSC 1 +#endif +#endif +#endif + +/* + * A macro to tag a function with a "target" attribute (for GCC and Clang). + */ +#if BR_AES_X86NI_GCC +#define BR_TARGET(x) __attribute__((target(x))) +#else +#define BR_TARGET(x) +#endif + /* ==================================================================== */ /* * Encoding/decoding functions. @@ -1077,6 +1126,10 @@ void br_i31_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b); /* ==================================================================== */ +/* + * FIXME: document "i15" functions. + */ + static inline void br_i15_zero(uint16_t *x, uint16_t bit_len) { @@ -1424,6 +1477,27 @@ unsigned br_aes_ct64_keysched(uint64_t *comp_skey, void br_aes_ct64_skey_expand(uint64_t *skey, unsigned num_rounds, const uint64_t *comp_skey); +/* + * Test support for AES-NI opcodes. + */ +int br_aes_x86ni_supported(void); + +/* + * AES key schedule, using x86 AES-NI instructions. This yields the + * subkeys in the encryption direction. Number of rounds is returned. + * Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned. + */ +unsigned br_aes_x86ni_keysched_enc(unsigned char *skni, + const void *key, size_t len); + +/* + * AES key schedule, using x86 AES-NI instructions. This yields the + * subkeys in the decryption direction. Number of rounds is returned. + * Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned. + */ +unsigned br_aes_x86ni_keysched_dec(unsigned char *skni, + const void *key, size_t len); + /* ==================================================================== */ /* * RSA. diff --git a/src/int/i15_modpow2.c b/src/int/i15_modpow2.c index dce9941..37073a4 100644 --- a/src/int/i15_modpow2.c +++ b/src/int/i15_modpow2.c @@ -41,6 +41,7 @@ br_i15_modpow_opt(uint16_t *x, */ mwlen = (m[0] + 31) >> 4; mlen = mwlen * sizeof m[0]; + mwlen += (mwlen & 1); t1 = tmp; t2 = tmp + mwlen; @@ -86,7 +87,7 @@ br_i15_modpow_opt(uint16_t *x, * one word-sized shift. */ br_i15_zero(x, m[0]); - x[mwlen - 1] = 1; + x[(m[0] + 15) >> 4] = 1; br_i15_muladd_small(x, 0, m); /* diff --git a/src/int/i15_montmul.c b/src/int/i15_montmul.c index 8da938f..e98bc32 100644 --- a/src/int/i15_montmul.c +++ b/src/int/i15_montmul.c @@ -42,7 +42,99 @@ br_i15_montymul(uint16_t *d, const uint16_t *x, const uint16_t *y, xu = x[u + 1]; f = MUL15((d[1] + MUL15(x[u + 1], y[1])) & 0x7FFF, m0i) & 0x7FFF; +#if BR_ARMEL_CORTEXM_GCC + if (len4 != 0) { + uint16_t *limit; + limit = d + len4; + asm volatile ( +"\n\ + @ carry: r=r2 \n\ + @ multipliers: xu=r3 f=r4 \n\ + @ base registers: d+v=r5 y+v=r6 m+v=r7 \n\ + @ r8 contains 0x7FFF \n\ + @ r9 contains d+len4 \n\ + ldr r0, %[limit] \n\ + ldr r3, %[xu] \n\ + mov r9, r0 \n\ + ldr r4, %[f] \n\ + eor r2, r2 \n\ + ldr r5, %[d] \n\ + sub r1, r2, #1 \n\ + ldr r6, %[y] \n\ + lsr r1, r1, #17 \n\ + ldr r7, %[m] \n\ + mov r8, r1 \n\ +loop%=: \n\ + ldrh r0, [r6, #2] \n\ + ldrh r1, [r7, #2] \n\ + mul r0, r3 \n\ + mul r1, r4 \n\ + add r2, r0, r2 \n\ + ldrh r0, [r5, #2] \n\ + add r2, r1, r2 \n\ + mov r1, r8 \n\ + add r2, r0, r2 \n\ + and r1, r2 \n\ + lsr r2, r2, #15 \n\ + strh r1, [r5, #0] \n\ + \n\ + ldrh r0, [r6, #4] \n\ + ldrh r1, [r7, #4] \n\ + mul r0, r3 \n\ + mul r1, r4 \n\ + add r2, r0, r2 \n\ + ldrh r0, [r5, #4] \n\ + add r2, r1, r2 \n\ + mov r1, r8 \n\ + add r2, r0, r2 \n\ + and r1, r2 \n\ + lsr r2, r2, #15 \n\ + strh r1, [r5, #2] \n\ + \n\ + ldrh r0, [r6, #6] \n\ + ldrh r1, [r7, #6] \n\ + mul r0, r3 \n\ + mul r1, r4 \n\ + add r2, r0, r2 \n\ + ldrh r0, [r5, #6] \n\ + add r2, r1, r2 \n\ + mov r1, r8 \n\ + add r2, r0, r2 \n\ + and r1, r2 \n\ + lsr r2, r2, #15 \n\ + strh r1, [r5, #4] \n\ + \n\ + ldrh r0, [r6, #8] \n\ + ldrh r1, [r7, #8] \n\ + mul r0, r3 \n\ + mul r1, r4 \n\ + add r2, r0, r2 \n\ + ldrh r0, [r5, #8] \n\ + add r2, r1, r2 \n\ + mov r1, r8 \n\ + add r2, r0, r2 \n\ + and r1, r2 \n\ + lsr r2, r2, #15 \n\ + strh r1, [r5, #6] \n\ + \n\ + add r5, r5, #8 \n\ + add r6, r6, #8 \n\ + add r7, r7, #8 \n\ + cmp r5, r9 \n\ + bne loop%= \n\ + \n\ + str r2, %[carry] \n\ +" +: [carry] "=m" (r) +: [xu] "m" (xu), [f] "m" (f), [d] "m" (d), [y] "m" (y), + [m] "m" (m), [limit] "m" (limit) +: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); + } else { + r = 0; + } + v = len4; +#else r = 0; for (v = 0; v < len4; v += 4) { uint32_t z; @@ -64,6 +156,7 @@ br_i15_montymul(uint16_t *d, const uint16_t *x, const uint16_t *y, r = z >> 15; d[v + 3] = z & 0x7FFF; } +#endif for (; v < len; v ++) { uint32_t z; diff --git a/src/rsa/rsa_default_pkcs1_sign.c b/src/rsa/rsa_default_pkcs1_sign.c new file mode 100644 index 0000000..4e8d4ec --- /dev/null +++ b/src/rsa/rsa_default_pkcs1_sign.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_rsa.h */ +br_rsa_pkcs1_sign +br_rsa_pkcs1_sign_get_default(void) +{ +#if BR_LOMUL + return &br_rsa_i15_pkcs1_sign; +#else + return &br_rsa_i31_pkcs1_sign; +#endif +} diff --git a/src/rsa/rsa_default_pkcs1_vrfy.c b/src/rsa/rsa_default_pkcs1_vrfy.c new file mode 100644 index 0000000..c5d81d6 --- /dev/null +++ b/src/rsa/rsa_default_pkcs1_vrfy.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_rsa.h */ +br_rsa_pkcs1_vrfy +br_rsa_pkcs1_vrfy_get_default(void) +{ +#if BR_LOMUL + return &br_rsa_i15_pkcs1_vrfy; +#else + return &br_rsa_i31_pkcs1_vrfy; +#endif +} diff --git a/src/rsa/rsa_default_priv.c b/src/rsa/rsa_default_priv.c new file mode 100644 index 0000000..04e3381 --- /dev/null +++ b/src/rsa/rsa_default_priv.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_rsa.h */ +br_rsa_private +br_rsa_private_get_default(void) +{ +#if BR_LOMUL + return &br_rsa_i15_private; +#else + return &br_rsa_i31_private; +#endif +} diff --git a/src/rsa/rsa_default_pub.c b/src/rsa/rsa_default_pub.c new file mode 100644 index 0000000..1dbfb62 --- /dev/null +++ b/src/rsa/rsa_default_pub.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_rsa.h */ +br_rsa_public +br_rsa_public_get_default(void) +{ +#if BR_LOMUL + return &br_rsa_i15_public; +#else + return &br_rsa_i31_public; +#endif +} diff --git a/src/rsa/rsa_i15_priv.c b/src/rsa/rsa_i15_priv.c index 8dc839a..e692da4 100644 --- a/src/rsa/rsa_i15_priv.c +++ b/src/rsa/rsa_i15_priv.c @@ -24,7 +24,7 @@ #include "inner.h" -#define U (1 + ((BR_MAX_RSA_FACTOR + 14) / 15)) +#define U (2 + ((BR_MAX_RSA_FACTOR + 14) / 15)) #define TLEN (8 * U) /* obsolete @@ -54,7 +54,7 @@ br_rsa_i15_private(unsigned char *x, const br_rsa_private_key *sk) size_t fwlen; uint16_t p0i, q0i; size_t xlen; - uint16_t tmp[TLEN]; + uint16_t tmp[1 + TLEN]; long z; uint16_t *mp, *mq, *s1, *s2, *t1, *t2, *t3; uint32_t r; @@ -86,6 +86,10 @@ br_rsa_i15_private(unsigned char *x, const br_rsa_private_key *sk) z -= 15; fwlen ++; } + /* + * Round up the word length to an even number. + */ + fwlen += (fwlen & 1); /* * We need to fit at least 6 values in the stack buffer. @@ -100,34 +104,41 @@ br_rsa_i15_private(unsigned char *x, const br_rsa_private_key *sk) xlen = (sk->n_bitlen + 7) >> 3; /* - * Decode q. + * Ensure 32-bit alignment for value words. */ mq = tmp; + if (((uintptr_t)mq & 2) == 0) { + mq ++; + } + + /* + * Decode q. + */ br_i15_decode(mq, q, qlen); /* * Compute s2 = x^dq mod q. */ q0i = br_i15_ninv15(mq[1]); - s2 = tmp + fwlen; + s2 = mq + fwlen; br_i15_decode_reduce(s2, x, xlen, mq); r = br_i15_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i, - tmp + 2 * fwlen, TLEN - 2 * fwlen); + mq + 2 * fwlen, TLEN - 2 * fwlen); /* * Decode p. */ - mp = tmp + 2 * fwlen; + mp = mq + 2 * fwlen; br_i15_decode(mp, p, plen); /* * Compute s1 = x^dq mod q. */ p0i = br_i15_ninv15(mp[1]); - s1 = tmp + 3 * fwlen; + s1 = mq + 3 * fwlen; br_i15_decode_reduce(s1, x, xlen, mp); r &= br_i15_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i, - tmp + 4 * fwlen, TLEN - 4 * fwlen); + mq + 4 * fwlen, TLEN - 4 * fwlen); /* * Compute: @@ -142,8 +153,8 @@ br_rsa_i15_private(unsigned char *x, const br_rsa_private_key *sk) * inverse of q modulo p), we also tolerate improperly large * values for this parameter. */ - t1 = tmp + 4 * fwlen; - t2 = tmp + 5 * fwlen; + t1 = mq + 4 * fwlen; + t2 = mq + 5 * fwlen; br_i15_reduce(t2, s2, mp); br_i15_add(s1, mp, br_i15_sub(s1, t2, 1)); br_i15_to_monty(s1, mp); diff --git a/src/rsa/rsa_i15_pub.c b/src/rsa/rsa_i15_pub.c index 09f558a..9eab5e8 100644 --- a/src/rsa/rsa_i15_pub.c +++ b/src/rsa/rsa_i15_pub.c @@ -28,7 +28,7 @@ * As a strict minimum, we need four buffers that can hold a * modular integer. */ -#define TLEN (4 * (1 + ((BR_MAX_RSA_SIZE + 14) / 15))) +#define TLEN (4 * (2 + ((BR_MAX_RSA_SIZE + 14) / 15))) /* see bearssl_rsa.h */ uint32_t @@ -37,7 +37,7 @@ br_rsa_i15_public(unsigned char *x, size_t xlen, { const unsigned char *n; size_t nlen; - uint16_t tmp[TLEN]; + uint16_t tmp[1 + TLEN]; uint16_t *m, *a, *t; size_t fwlen; long z; @@ -63,15 +63,25 @@ br_rsa_i15_public(unsigned char *x, size_t xlen, z -= 15; fwlen ++; } + /* + * Round up length to an even number. + */ + fwlen += (fwlen & 1); /* * The modulus gets decoded into m[]. * The value to exponentiate goes into a[]. * The temporaries for modular exponentiations are in t[]. + * + * We want the first value word of each integer to be aligned + * on a 32-bit boundary. */ m = tmp; - a = tmp + fwlen; - t = tmp + 2 * fwlen; + if (((uintptr_t)m & 2) == 0) { + m ++; + } + a = m + fwlen; + t = m + 2 * fwlen; /* * Decode the modulus. diff --git a/src/ssl/ssl_client_default_rsapub.c b/src/ssl/ssl_client_default_rsapub.c new file mode 100644 index 0000000..733151d --- /dev/null +++ b/src/ssl/ssl_client_default_rsapub.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_ssl.h */ +void +br_ssl_client_set_default_rsapub(br_ssl_client_context *cc) +{ +#if BR_LOMUL + br_ssl_client_set_rsapub(cc, &br_rsa_i15_public); +#else + br_ssl_client_set_rsapub(cc, &br_rsa_i31_public); +#endif +} diff --git a/src/ssl/ssl_client_full.c b/src/ssl/ssl_client_full.c index cd49a93..9c61d23 100644 --- a/src/ssl/ssl_client_full.c +++ b/src/ssl/ssl_client_full.c @@ -125,13 +125,13 @@ br_ssl_client_init_full(br_ssl_client_context *cc, */ br_ssl_engine_set_suites(&cc->eng, suites, (sizeof suites) / (sizeof suites[0])); - br_ssl_client_set_rsapub(cc, &br_rsa_i31_public); - br_ssl_engine_set_rsavrfy(&cc->eng, &br_rsa_i31_pkcs1_vrfy); - br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15); - br_ssl_engine_set_ecdsa(&cc->eng, &br_ecdsa_i31_vrfy_asn1); - br_x509_minimal_set_rsa(xc, &br_rsa_i31_pkcs1_vrfy); + br_ssl_client_set_default_rsapub(cc); + br_ssl_engine_set_default_rsavrfy(&cc->eng); + br_ssl_engine_set_default_ecdsa(&cc->eng); + br_x509_minimal_set_rsa(xc, br_ssl_engine_get_rsavrfy(&cc->eng)); br_x509_minimal_set_ecdsa(xc, - &br_ec_all_m15, &br_ecdsa_i31_vrfy_asn1); + br_ssl_engine_get_ec(&cc->eng), + br_ssl_engine_get_ecdsa(&cc->eng)); /* * Set supported hash functions, for the SSL engine and for the @@ -158,47 +158,11 @@ br_ssl_client_init_full(br_ssl_client_context *cc, br_ssl_engine_set_prf_sha384(&cc->eng, &br_tls12_sha384_prf); /* - * Symmetric encryption. We use the "constant-time" - * implementations, which are the safest. - * - * On architectures detected as "64-bit", use the 64-bit - * versions (aes_ct64, ghash_ctmul64). - */ -#if BR_64 - br_ssl_engine_set_aes_cbc(&cc->eng, - &br_aes_ct64_cbcenc_vtable, - &br_aes_ct64_cbcdec_vtable); - br_ssl_engine_set_aes_ctr(&cc->eng, - &br_aes_ct64_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, - &br_ghash_ctmul64); -#else - br_ssl_engine_set_aes_cbc(&cc->eng, - &br_aes_ct_cbcenc_vtable, - &br_aes_ct_cbcdec_vtable); - br_ssl_engine_set_aes_ctr(&cc->eng, - &br_aes_ct_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, - &br_ghash_ctmul); -#endif - br_ssl_engine_set_des_cbc(&cc->eng, - &br_des_ct_cbcenc_vtable, - &br_des_ct_cbcdec_vtable); - br_ssl_engine_set_chacha20(&cc->eng, - &br_chacha20_ct_run); - br_ssl_engine_set_poly1305(&cc->eng, - &br_poly1305_ctmul_run); - - /* - * Set the SSL record engines (CBC, GCM). + * Symmetric encryption. We use the "default" implementations + * (fastest among constant-time implementations). */ - br_ssl_engine_set_cbc(&cc->eng, - &br_sslrec_in_cbc_vtable, - &br_sslrec_out_cbc_vtable); - br_ssl_engine_set_gcm(&cc->eng, - &br_sslrec_in_gcm_vtable, - &br_sslrec_out_gcm_vtable); - br_ssl_engine_set_chapol(&cc->eng, - &br_sslrec_in_chapol_vtable, - &br_sslrec_out_chapol_vtable); + br_ssl_engine_set_default_aes_cbc(&cc->eng); + br_ssl_engine_set_default_aes_gcm(&cc->eng); + br_ssl_engine_set_default_des_cbc(&cc->eng); + br_ssl_engine_set_default_chapol(&cc->eng); } diff --git a/src/ssl/ssl_engine_default_aescbc.c b/src/ssl/ssl_engine_default_aescbc.c new file mode 100644 index 0000000..556d6eb --- /dev/null +++ b/src/ssl/ssl_engine_default_aescbc.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_default_aes_cbc(br_ssl_engine_context *cc) +{ +#if BR_AES_X86NI + const br_block_cbcenc_class *ienc; + const br_block_cbcdec_class *idec; +#endif + + br_ssl_engine_set_cbc(cc, + &br_sslrec_in_cbc_vtable, + &br_sslrec_out_cbc_vtable); +#if BR_AES_X86NI + ienc = br_aes_x86ni_cbcenc_get_vtable(); + idec = br_aes_x86ni_cbcdec_get_vtable(); + if (ienc != NULL && idec != NULL) { + br_ssl_engine_set_aes_cbc(cc, ienc, idec); + return; + } +#endif +#if BR_64 + br_ssl_engine_set_aes_cbc(cc, + &br_aes_ct64_cbcenc_vtable, + &br_aes_ct64_cbcdec_vtable); +#else + br_ssl_engine_set_aes_cbc(cc, + &br_aes_ct_cbcenc_vtable, + &br_aes_ct_cbcdec_vtable); +#endif +} diff --git a/src/ssl/ssl_engine_default_aesgcm.c b/src/ssl/ssl_engine_default_aesgcm.c new file mode 100644 index 0000000..9968342 --- /dev/null +++ b/src/ssl/ssl_engine_default_aesgcm.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_default_aes_gcm(br_ssl_engine_context *cc) +{ +#if BR_AES_X86NI + const br_block_ctr_class *ictr; + br_ghash ighash; +#endif + + br_ssl_engine_set_gcm(cc, + &br_sslrec_in_gcm_vtable, + &br_sslrec_out_gcm_vtable); +#if BR_AES_X86NI + ictr = br_aes_x86ni_ctr_get_vtable(); + if (ictr != NULL) { + br_ssl_engine_set_aes_ctr(cc, ictr); + } else { +#if BR_64 + br_ssl_engine_set_aes_ctr(cc, &br_aes_ct64_ctr_vtable); +#else + br_ssl_engine_set_aes_ctr(cc, &br_aes_ct_ctr_vtable); +#endif + } +#else +#if BR_64 + br_ssl_engine_set_aes_ctr(cc, &br_aes_ct64_ctr_vtable); +#else + br_ssl_engine_set_aes_ctr(cc, &br_aes_ct_ctr_vtable); +#endif +#endif +#if BR_AES_X86NI + ighash = br_ghash_pclmul_get(); + if (ighash != 0) { + br_ssl_engine_set_ghash(cc, ighash); + return; + } +#endif +#if BR_LOMUL + br_ssl_engine_set_ghash(cc, &br_ghash_ctmul32); +#elif BR_64 + br_ssl_engine_set_ghash(cc, &br_ghash_ctmul64); +#else + br_ssl_engine_set_ghash(cc, &br_ghash_ctmul); +#endif +} diff --git a/src/ssl/ssl_engine_default_chapol.c b/src/ssl/ssl_engine_default_chapol.c new file mode 100644 index 0000000..5f089b1 --- /dev/null +++ b/src/ssl/ssl_engine_default_chapol.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_default_chapol(br_ssl_engine_context *cc) +{ + br_ssl_engine_set_chapol(cc, + &br_sslrec_in_chapol_vtable, + &br_sslrec_out_chapol_vtable); + br_ssl_engine_set_chacha20(cc, &br_chacha20_ct_run); +#if BR_LOMUL + br_ssl_engine_set_poly1305(cc, &br_poly1305_ctmul32_run); +#else + br_ssl_engine_set_poly1305(cc, &br_poly1305_ctmul_run); +#endif +} diff --git a/src/ssl/ssl_engine_default_descbc.c b/src/ssl/ssl_engine_default_descbc.c new file mode 100644 index 0000000..0253cb2 --- /dev/null +++ b/src/ssl/ssl_engine_default_descbc.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_default_des_cbc(br_ssl_engine_context *cc) +{ + br_ssl_engine_set_cbc(cc, + &br_sslrec_in_cbc_vtable, + &br_sslrec_out_cbc_vtable); + br_ssl_engine_set_des_cbc(cc, + &br_des_ct_cbcenc_vtable, + &br_des_ct_cbcdec_vtable); +} diff --git a/src/ssl/ssl_engine_default_ec.c b/src/ssl/ssl_engine_default_ec.c new file mode 100644 index 0000000..0213ae6 --- /dev/null +++ b/src/ssl/ssl_engine_default_ec.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_default_ec(br_ssl_engine_context *cc) +{ +#if BR_LOMUL + br_ssl_engine_set_ec(cc, &br_ec_all_m15); +#else + br_ssl_engine_set_ec(cc, &br_ec_all_m31); +#endif +} diff --git a/src/ssl/ssl_engine_default_ecdsa.c b/src/ssl/ssl_engine_default_ecdsa.c new file mode 100644 index 0000000..1304002 --- /dev/null +++ b/src/ssl/ssl_engine_default_ecdsa.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_default_ecdsa(br_ssl_engine_context *cc) +{ +#if BR_LOMUL + br_ssl_engine_set_ec(cc, &br_ec_all_m15); + br_ssl_engine_set_ecdsa(cc, &br_ecdsa_i15_vrfy_asn1); +#else + br_ssl_engine_set_ec(cc, &br_ec_all_m31); + br_ssl_engine_set_ecdsa(cc, &br_ecdsa_i31_vrfy_asn1); +#endif +} diff --git a/src/ssl/ssl_engine_default_rsavrfy.c b/src/ssl/ssl_engine_default_rsavrfy.c new file mode 100644 index 0000000..f05cc49 --- /dev/null +++ b/src/ssl/ssl_engine_default_rsavrfy.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* see bearssl_ssl.h */ +void +br_ssl_engine_set_default_rsavrfy(br_ssl_engine_context *cc) +{ +#if BR_LOMUL + br_ssl_engine_set_rsavrfy(cc, &br_rsa_i15_pkcs1_vrfy); +#else + br_ssl_engine_set_rsavrfy(cc, &br_rsa_i31_pkcs1_vrfy); +#endif +} diff --git a/src/ssl/ssl_server_full_ec.c b/src/ssl/ssl_server_full_ec.c index dbe215d..e6765f5 100644 --- a/src/ssl/ssl_server_full_ec.c +++ b/src/ssl/ssl_server_full_ec.c @@ -99,7 +99,7 @@ br_ssl_server_init_full_ec(br_ssl_server_context *cc, */ br_ssl_engine_set_suites(&cc->eng, suites, (sizeof suites) / (sizeof suites[0])); - br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15); + br_ssl_engine_set_default_ec(&cc->eng); /* * Set the "server policy": handler for the certificate chain @@ -108,7 +108,13 @@ br_ssl_server_init_full_ec(br_ssl_server_context *cc, br_ssl_server_set_single_ec(cc, chain, chain_len, sk, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, cert_issuer_key_type, - &br_ec_all_m15, br_ecdsa_i31_sign_asn1); + br_ssl_engine_get_ec(&cc->eng), +#if BR_LOMUL + br_ecdsa_i15_sign_asn1 +#else + br_ecdsa_i31_sign_asn1 +#endif + ); /* * Set supported hash functions. @@ -128,47 +134,10 @@ br_ssl_server_init_full_ec(br_ssl_server_context *cc, br_ssl_engine_set_prf_sha384(&cc->eng, &br_tls12_sha384_prf); /* - * Symmetric encryption. We use the "constant-time" - * implementations, which are the safest. - * - * On architectures detected as "64-bit", use the 64-bit - * versions (aes_ct64, ghash_ctmul64). - */ -#if BR_64 - br_ssl_engine_set_aes_cbc(&cc->eng, - &br_aes_ct64_cbcenc_vtable, - &br_aes_ct64_cbcdec_vtable); - br_ssl_engine_set_aes_ctr(&cc->eng, - &br_aes_ct64_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, - &br_ghash_ctmul64); -#else - br_ssl_engine_set_aes_cbc(&cc->eng, - &br_aes_ct_cbcenc_vtable, - &br_aes_ct_cbcdec_vtable); - br_ssl_engine_set_aes_ctr(&cc->eng, - &br_aes_ct_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, - &br_ghash_ctmul); -#endif - br_ssl_engine_set_des_cbc(&cc->eng, - &br_des_ct_cbcenc_vtable, - &br_des_ct_cbcdec_vtable); - br_ssl_engine_set_chacha20(&cc->eng, - &br_chacha20_ct_run); - br_ssl_engine_set_poly1305(&cc->eng, - &br_poly1305_ctmul_run); - - /* - * Set the SSL record engines (CBC, GCM). + * Symmetric encryption. */ - br_ssl_engine_set_cbc(&cc->eng, - &br_sslrec_in_cbc_vtable, - &br_sslrec_out_cbc_vtable); - br_ssl_engine_set_gcm(&cc->eng, - &br_sslrec_in_gcm_vtable, - &br_sslrec_out_gcm_vtable); - br_ssl_engine_set_chapol(&cc->eng, - &br_sslrec_in_chapol_vtable, - &br_sslrec_out_chapol_vtable); + br_ssl_engine_set_default_aes_cbc(&cc->eng); + br_ssl_engine_set_default_aes_gcm(&cc->eng); + br_ssl_engine_set_default_des_cbc(&cc->eng); + br_ssl_engine_set_default_chapol(&cc->eng); } diff --git a/src/ssl/ssl_server_full_rsa.c b/src/ssl/ssl_server_full_rsa.c index ffec9be..cbb60f9 100644 --- a/src/ssl/ssl_server_full_rsa.c +++ b/src/ssl/ssl_server_full_rsa.c @@ -89,7 +89,7 @@ br_ssl_server_init_full_rsa(br_ssl_server_context *cc, */ br_ssl_engine_set_suites(&cc->eng, suites, (sizeof suites) / (sizeof suites[0])); - br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15); + br_ssl_engine_set_default_ec(&cc->eng); /* * Set the "server policy": handler for the certificate chain @@ -97,7 +97,12 @@ br_ssl_server_init_full_rsa(br_ssl_server_context *cc, */ br_ssl_server_set_single_rsa(cc, chain, chain_len, sk, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, - br_rsa_i31_private, br_rsa_i31_pkcs1_sign); +#if BR_LOMUL + br_rsa_i15_private, br_rsa_i15_pkcs1_sign +#else + br_rsa_i31_private, br_rsa_i31_pkcs1_sign +#endif + ); /* * Set supported hash functions. @@ -117,47 +122,10 @@ br_ssl_server_init_full_rsa(br_ssl_server_context *cc, br_ssl_engine_set_prf_sha384(&cc->eng, &br_tls12_sha384_prf); /* - * Symmetric encryption. We use the "constant-time" - * implementations, which are the safest. - * - * On architectures detected as "64-bit", use the 64-bit - * versions (aes_ct64, ghash_ctmul64). - */ -#if BR_64 - br_ssl_engine_set_aes_cbc(&cc->eng, - &br_aes_ct64_cbcenc_vtable, - &br_aes_ct64_cbcdec_vtable); - br_ssl_engine_set_aes_ctr(&cc->eng, - &br_aes_ct64_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, - &br_ghash_ctmul64); -#else - br_ssl_engine_set_aes_cbc(&cc->eng, - &br_aes_ct_cbcenc_vtable, - &br_aes_ct_cbcdec_vtable); - br_ssl_engine_set_aes_ctr(&cc->eng, - &br_aes_ct_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, - &br_ghash_ctmul); -#endif - br_ssl_engine_set_des_cbc(&cc->eng, - &br_des_ct_cbcenc_vtable, - &br_des_ct_cbcdec_vtable); - br_ssl_engine_set_chacha20(&cc->eng, - &br_chacha20_ct_run); - br_ssl_engine_set_poly1305(&cc->eng, - &br_poly1305_ctmul_run); - - /* - * Set the SSL record engines (CBC, GCM, ChaCha20). + * Symmetric encryption. */ - br_ssl_engine_set_cbc(&cc->eng, - &br_sslrec_in_cbc_vtable, - &br_sslrec_out_cbc_vtable); - br_ssl_engine_set_gcm(&cc->eng, - &br_sslrec_in_gcm_vtable, - &br_sslrec_out_gcm_vtable); - br_ssl_engine_set_chapol(&cc->eng, - &br_sslrec_in_chapol_vtable, - &br_sslrec_out_chapol_vtable); + br_ssl_engine_set_default_aes_cbc(&cc->eng); + br_ssl_engine_set_default_aes_gcm(&cc->eng); + br_ssl_engine_set_default_des_cbc(&cc->eng); + br_ssl_engine_set_default_chapol(&cc->eng); } diff --git a/src/ssl/ssl_server_mine2c.c b/src/ssl/ssl_server_mine2c.c index 7c53e29..bf61b56 100644 --- a/src/ssl/ssl_server_mine2c.c +++ b/src/ssl/ssl_server_mine2c.c @@ -65,18 +65,7 @@ br_ssl_server_init_mine2c(br_ssl_server_context *cc, br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); /* - * Symmetric encryption. We use the "constant-time" - * implementations, which are the safest. + * Symmetric encryption. */ - br_ssl_engine_set_chacha20(&cc->eng, - &br_chacha20_ct_run); - br_ssl_engine_set_poly1305(&cc->eng, - &br_poly1305_ctmul_run); - - /* - * Set the SSL record engines. - */ - br_ssl_engine_set_chapol(&cc->eng, - &br_sslrec_in_chapol_vtable, - &br_sslrec_out_chapol_vtable); + br_ssl_engine_set_default_chapol(&cc->eng); } diff --git a/src/ssl/ssl_server_mine2g.c b/src/ssl/ssl_server_mine2g.c index f5a1e7d..80fa5b1 100644 --- a/src/ssl/ssl_server_mine2g.c +++ b/src/ssl/ssl_server_mine2g.c @@ -65,28 +65,7 @@ br_ssl_server_init_mine2g(br_ssl_server_context *cc, br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); /* - * Symmetric encryption. We use the "constant-time" - * implementations, which are the safest. - * - * On architectures detected as "64-bit", use the 64-bit - * versions (aes_ct64, ghash_ctmul64). + * Symmetric encryption. */ -#if BR_64 - br_ssl_engine_set_aes_ctr(&cc->eng, - &br_aes_ct64_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, - &br_ghash_ctmul64); -#else - br_ssl_engine_set_aes_ctr(&cc->eng, - &br_aes_ct_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, - &br_ghash_ctmul); -#endif - - /* - * Set the SSL record engines (CBC, GCM). - */ - br_ssl_engine_set_gcm(&cc->eng, - &br_sslrec_in_gcm_vtable, - &br_sslrec_out_gcm_vtable); + br_ssl_engine_set_default_aes_gcm(&cc->eng); } diff --git a/src/ssl/ssl_server_minf2c.c b/src/ssl/ssl_server_minf2c.c index 7ded293..3f44236 100644 --- a/src/ssl/ssl_server_minf2c.c +++ b/src/ssl/ssl_server_minf2c.c @@ -65,21 +65,7 @@ br_ssl_server_init_minf2c(br_ssl_server_context *cc, br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); /* - * Symmetric encryption. We use the "constant-time" - * implementations, which are the safest. - * - * On architectures detected as "64-bit", use the 64-bit - * versions (aes_ct64, ghash_ctmul64). + * Symmetric encryption. */ - br_ssl_engine_set_chacha20(&cc->eng, - &br_chacha20_ct_run); - br_ssl_engine_set_poly1305(&cc->eng, - &br_poly1305_ctmul_run); - - /* - * Set the SSL record engines. - */ - br_ssl_engine_set_chapol(&cc->eng, - &br_sslrec_in_chapol_vtable, - &br_sslrec_out_chapol_vtable); + br_ssl_engine_set_default_chapol(&cc->eng); } diff --git a/src/ssl/ssl_server_minf2g.c b/src/ssl/ssl_server_minf2g.c index 94f9dfb..8613de1 100644 --- a/src/ssl/ssl_server_minf2g.c +++ b/src/ssl/ssl_server_minf2g.c @@ -65,28 +65,7 @@ br_ssl_server_init_minf2g(br_ssl_server_context *cc, br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); /* - * Symmetric encryption. We use the "constant-time" - * implementations, which are the safest. - * - * On architectures detected as "64-bit", use the 64-bit - * versions (aes_ct64, ghash_ctmul64). + * Symmetric encryption. */ -#if BR_64 - br_ssl_engine_set_aes_ctr(&cc->eng, - &br_aes_ct64_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, - &br_ghash_ctmul64); -#else - br_ssl_engine_set_aes_ctr(&cc->eng, - &br_aes_ct_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, - &br_ghash_ctmul); -#endif - - /* - * Set the SSL record engines (CBC, GCM). - */ - br_ssl_engine_set_gcm(&cc->eng, - &br_sslrec_in_gcm_vtable, - &br_sslrec_out_gcm_vtable); + br_ssl_engine_set_default_aes_gcm(&cc->eng); } diff --git a/src/ssl/ssl_server_minr2g.c b/src/ssl/ssl_server_minr2g.c index 05ad891..83c238b 100644 --- a/src/ssl/ssl_server_minr2g.c +++ b/src/ssl/ssl_server_minr2g.c @@ -64,28 +64,7 @@ br_ssl_server_init_minr2g(br_ssl_server_context *cc, br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); /* - * Symmetric encryption. We use the "constant-time" - * implementations, which are the safest. - * - * On architectures detected as "64-bit", use the 64-bit - * versions (aes_ct64, ghash_ctmul64). + * Symmetric encryption. */ -#if BR_64 - br_ssl_engine_set_aes_ctr(&cc->eng, - &br_aes_ct64_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, - &br_ghash_ctmul64); -#else - br_ssl_engine_set_aes_ctr(&cc->eng, - &br_aes_ct_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, - &br_ghash_ctmul); -#endif - - /* - * Set the SSL record engines (CBC, GCM). - */ - br_ssl_engine_set_gcm(&cc->eng, - &br_sslrec_in_gcm_vtable, - &br_sslrec_out_gcm_vtable); + br_ssl_engine_set_default_aes_gcm(&cc->eng); } diff --git a/src/ssl/ssl_server_minu2g.c b/src/ssl/ssl_server_minu2g.c index cbf1fe4..6721384 100644 --- a/src/ssl/ssl_server_minu2g.c +++ b/src/ssl/ssl_server_minu2g.c @@ -64,28 +64,7 @@ br_ssl_server_init_minu2g(br_ssl_server_context *cc, br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); /* - * Symmetric encryption. We use the "constant-time" - * implementations, which are the safest. - * - * On architectures detected as "64-bit", use the 64-bit - * versions (aes_ct64, ghash_ctmul64). + * Symmetric encryption. */ -#if BR_64 - br_ssl_engine_set_aes_ctr(&cc->eng, - &br_aes_ct64_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, - &br_ghash_ctmul64); -#else - br_ssl_engine_set_aes_ctr(&cc->eng, - &br_aes_ct_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, - &br_ghash_ctmul); -#endif - - /* - * Set the SSL record engines (CBC, GCM). - */ - br_ssl_engine_set_gcm(&cc->eng, - &br_sslrec_in_gcm_vtable, - &br_sslrec_out_gcm_vtable); + br_ssl_engine_set_default_aes_gcm(&cc->eng); } diff --git a/src/ssl/ssl_server_minv2g.c b/src/ssl/ssl_server_minv2g.c index 714a399..194e654 100644 --- a/src/ssl/ssl_server_minv2g.c +++ b/src/ssl/ssl_server_minv2g.c @@ -64,28 +64,7 @@ br_ssl_server_init_minv2g(br_ssl_server_context *cc, br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); /* - * Symmetric encryption. We use the "constant-time" - * implementations, which are the safest. - * - * On architectures detected as "64-bit", use the 64-bit - * versions (aes_ct64, ghash_ctmul64). + * Symmetric encryption. */ -#if BR_64 - br_ssl_engine_set_aes_ctr(&cc->eng, - &br_aes_ct64_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, - &br_ghash_ctmul64); -#else - br_ssl_engine_set_aes_ctr(&cc->eng, - &br_aes_ct_ctr_vtable); - br_ssl_engine_set_ghash(&cc->eng, - &br_ghash_ctmul); -#endif - - /* - * Set the SSL record engines (CBC, GCM). - */ - br_ssl_engine_set_gcm(&cc->eng, - &br_sslrec_in_gcm_vtable, - &br_sslrec_out_gcm_vtable); + br_ssl_engine_set_default_aes_gcm(&cc->eng); } diff --git a/src/symcipher/aes_x86ni.c b/src/symcipher/aes_x86ni.c new file mode 100644 index 0000000..dcc3952 --- /dev/null +++ b/src/symcipher/aes_x86ni.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +/* + * This code contains the AES key schedule implementation using the + * AES-NI opcodes. + */ + +#if BR_AES_X86NI + +#if BR_AES_X86NI_GCC +#include +#include +#endif + +#if BR_AES_X86NI_MSC +#include +#endif + +/* see inner.h */ +int +br_aes_x86ni_supported(void) +{ + /* + * Bit mask for features in ECX: + * 19 SSE4.1 (used for _mm_insert_epi32(), for AES-CTR) + * 25 AES-NI + */ +#define MASK 0x02080000 + +#if BR_AES_X86NI_GCC + unsigned eax, ebx, ecx, edx; + + if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) { + return (ecx & MASK) == MASK; + } else { + return 0; + } +#elif BR_AES_X86NI_MSC + int info[4]; + + __cpuid(info, 1); + return ((uint32_t)info[2] & MASK) == MASK; +#else + return 0; +#endif + +#undef MASK +} + +BR_TARGET("sse2,aes") +static inline __m128i +expand_step128(__m128i k, __m128i k2) +{ + k = _mm_xor_si128(k, _mm_slli_si128(k, 4)); + k = _mm_xor_si128(k, _mm_slli_si128(k, 4)); + k = _mm_xor_si128(k, _mm_slli_si128(k, 4)); + k2 = _mm_shuffle_epi32(k2, 0xFF); + return _mm_xor_si128(k, k2); +} + +BR_TARGET("sse2,aes") +static inline void +expand_step192(__m128i *t1, __m128i *t2, __m128i *t3) +{ + __m128i t4; + + *t2 = _mm_shuffle_epi32(*t2, 0x55); + t4 = _mm_slli_si128(*t1, 0x4); + *t1 = _mm_xor_si128(*t1, t4); + t4 = _mm_slli_si128(t4, 0x4); + *t1 = _mm_xor_si128(*t1, t4); + t4 = _mm_slli_si128(t4, 0x4); + *t1 = _mm_xor_si128(*t1, t4); + *t1 = _mm_xor_si128(*t1, *t2); + *t2 = _mm_shuffle_epi32(*t1, 0xFF); + t4 = _mm_slli_si128(*t3, 0x4); + *t3 = _mm_xor_si128(*t3, t4); + *t3 = _mm_xor_si128(*t3, *t2); +} + +BR_TARGET("sse2,aes") +static inline void +expand_step256_1(__m128i *t1, __m128i *t2) +{ + __m128i t4; + + *t2 = _mm_shuffle_epi32(*t2, 0xFF); + t4 = _mm_slli_si128(*t1, 0x4); + *t1 = _mm_xor_si128(*t1, t4); + t4 = _mm_slli_si128(t4, 0x4); + *t1 = _mm_xor_si128(*t1, t4); + t4 = _mm_slli_si128(t4, 0x4); + *t1 = _mm_xor_si128(*t1, t4); + *t1 = _mm_xor_si128(*t1, *t2); +} + +BR_TARGET("sse2,aes") +static inline void +expand_step256_2(__m128i *t1, __m128i *t3) +{ + __m128i t2, t4; + + t4 = _mm_aeskeygenassist_si128(*t1, 0x0); + t2 = _mm_shuffle_epi32(t4, 0xAA); + t4 = _mm_slli_si128(*t3, 0x4); + *t3 = _mm_xor_si128(*t3, t4); + t4 = _mm_slli_si128(t4, 0x4); + *t3 = _mm_xor_si128(*t3, t4); + t4 = _mm_slli_si128(t4, 0x4); + *t3 = _mm_xor_si128(*t3, t4); + *t3 = _mm_xor_si128(*t3, t2); +} + +/* + * Perform key schedule for AES, encryption direction. Subkeys are written + * in sk[], and the number of rounds is returned. Key length MUST be 16, + * 24 or 32 bytes. + */ +BR_TARGET("sse2,aes") +static unsigned +x86ni_keysched(__m128i *sk, const void *key, size_t len) +{ + const unsigned char *kb; + +#define KEXP128(k, i, rcon) do { \ + k = expand_step128(k, _mm_aeskeygenassist_si128(k, rcon)); \ + sk[i] = k; \ + } while (0) + +#define KEXP192(i, rcon1, rcon2) do { \ + sk[(i) + 0] = t1; \ + sk[(i) + 1] = t3; \ + t2 = _mm_aeskeygenassist_si128(t3, rcon1); \ + expand_step192(&t1, &t2, &t3); \ + sk[(i) + 1] = _mm_castpd_si128(_mm_shuffle_pd( \ + _mm_castsi128_pd(sk[(i) + 1]), \ + _mm_castsi128_pd(t1), 0)); \ + sk[(i) + 2] = _mm_castpd_si128(_mm_shuffle_pd( \ + _mm_castsi128_pd(t1), \ + _mm_castsi128_pd(t3), 1)); \ + t2 = _mm_aeskeygenassist_si128(t3, rcon2); \ + expand_step192(&t1, &t2, &t3); \ + } while (0) + +#define KEXP256(i, rcon) do { \ + sk[(i) + 0] = t3; \ + t2 = _mm_aeskeygenassist_si128(t3, rcon); \ + expand_step256_1(&t1, &t2); \ + sk[(i) + 1] = t1; \ + expand_step256_2(&t1, &t3); \ + } while (0) + + kb = key; + switch (len) { + __m128i t1, t2, t3; + + case 16: + t1 = _mm_loadu_si128((const void *)kb); + sk[0] = t1; + KEXP128(t1, 1, 0x01); + KEXP128(t1, 2, 0x02); + KEXP128(t1, 3, 0x04); + KEXP128(t1, 4, 0x08); + KEXP128(t1, 5, 0x10); + KEXP128(t1, 6, 0x20); + KEXP128(t1, 7, 0x40); + KEXP128(t1, 8, 0x80); + KEXP128(t1, 9, 0x1B); + KEXP128(t1, 10, 0x36); + return 10; + + case 24: + t1 = _mm_loadu_si128((const void *)kb); + t3 = _mm_loadu_si128((const void *)(kb + 8)); + t3 = _mm_shuffle_epi32(t3, 0x4E); + KEXP192(0, 0x01, 0x02); + KEXP192(3, 0x04, 0x08); + KEXP192(6, 0x10, 0x20); + KEXP192(9, 0x40, 0x80); + sk[12] = t1; + return 12; + + case 32: + t1 = _mm_loadu_si128((const void *)kb); + t3 = _mm_loadu_si128((const void *)(kb + 16)); + sk[0] = t1; + KEXP256( 1, 0x01); + KEXP256( 3, 0x02); + KEXP256( 5, 0x04); + KEXP256( 7, 0x08); + KEXP256( 9, 0x10); + KEXP256(11, 0x20); + sk[13] = t3; + t2 = _mm_aeskeygenassist_si128(t3, 0x40); + expand_step256_1(&t1, &t2); + sk[14] = t1; + return 14; + + default: + return 0; + } + +#undef KEXP128 +#undef KEXP192 +#undef KEXP256 +} + +/* see inner.h */ +BR_TARGET("sse2,aes") +unsigned +br_aes_x86ni_keysched_enc(unsigned char *skni, const void *key, size_t len) +{ + __m128i sk[15]; + unsigned num_rounds; + + num_rounds = x86ni_keysched(sk, key, len); + memcpy(skni, sk, (num_rounds + 1) << 4); + return num_rounds; +} + +/* see inner.h */ +BR_TARGET("sse2,aes") +unsigned +br_aes_x86ni_keysched_dec(unsigned char *skni, const void *key, size_t len) +{ + __m128i sk[15]; + unsigned u, num_rounds; + + num_rounds = x86ni_keysched(sk, key, len); + _mm_storeu_si128((void *)skni, sk[num_rounds]); + for (u = 1; u < num_rounds; u ++) { + _mm_storeu_si128((void *)(skni + (u << 4)), + _mm_aesimc_si128(sk[num_rounds - u])); + } + _mm_storeu_si128((void *)(skni + (num_rounds << 4)), sk[0]); + return num_rounds; +} + +#endif diff --git a/src/symcipher/aes_x86ni_cbcdec.c b/src/symcipher/aes_x86ni_cbcdec.c new file mode 100644 index 0000000..6f75348 --- /dev/null +++ b/src/symcipher/aes_x86ni_cbcdec.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +#if BR_AES_X86NI + +#if BR_AES_X86NI_GCC +#include +#endif + +#if BR_AES_X86NI_MSC +#include +#endif + +/* see bearssl_block.h */ +void +br_aes_x86ni_cbcdec_init(br_aes_x86ni_cbcdec_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_x86ni_cbcdec_vtable; + ctx->num_rounds = br_aes_x86ni_keysched_dec(ctx->skey.skni, key, len); +} + +/* see bearssl_block.h */ +BR_TARGET("sse2,aes") +void +br_aes_x86ni_cbcdec_run(const br_aes_x86ni_cbcdec_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char *buf; + unsigned num_rounds; + __m128i sk[15], ivx; + unsigned u; + + buf = data; + ivx = _mm_loadu_si128(iv); + num_rounds = ctx->num_rounds; + for (u = 0; u <= num_rounds; u ++) { + sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); + } + while (len > 0) { + __m128i x0, x1, x2, x3, e0, e1, e2, e3; + + x0 = _mm_loadu_si128((void *)(buf + 0)); + if (len >= 64) { + x1 = _mm_loadu_si128((void *)(buf + 16)); + x2 = _mm_loadu_si128((void *)(buf + 32)); + x3 = _mm_loadu_si128((void *)(buf + 48)); + } else { + x0 = _mm_loadu_si128((void *)(buf + 0)); + if (len >= 32) { + x1 = _mm_loadu_si128((void *)(buf + 16)); + if (len >= 48) { + x2 = _mm_loadu_si128( + (void *)(buf + 32)); + } else { + x2 = x0; + } + } else { + x1 = x0; + x2 = x0; + } + x3 = x0; + } + e0 = x0; + e1 = x1; + e2 = x2; + e3 = x3; + x0 = _mm_xor_si128(x0, sk[0]); + x1 = _mm_xor_si128(x1, sk[0]); + x2 = _mm_xor_si128(x2, sk[0]); + x3 = _mm_xor_si128(x3, sk[0]); + x0 = _mm_aesdec_si128(x0, sk[1]); + x1 = _mm_aesdec_si128(x1, sk[1]); + x2 = _mm_aesdec_si128(x2, sk[1]); + x3 = _mm_aesdec_si128(x3, sk[1]); + x0 = _mm_aesdec_si128(x0, sk[2]); + x1 = _mm_aesdec_si128(x1, sk[2]); + x2 = _mm_aesdec_si128(x2, sk[2]); + x3 = _mm_aesdec_si128(x3, sk[2]); + x0 = _mm_aesdec_si128(x0, sk[3]); + x1 = _mm_aesdec_si128(x1, sk[3]); + x2 = _mm_aesdec_si128(x2, sk[3]); + x3 = _mm_aesdec_si128(x3, sk[3]); + x0 = _mm_aesdec_si128(x0, sk[4]); + x1 = _mm_aesdec_si128(x1, sk[4]); + x2 = _mm_aesdec_si128(x2, sk[4]); + x3 = _mm_aesdec_si128(x3, sk[4]); + x0 = _mm_aesdec_si128(x0, sk[5]); + x1 = _mm_aesdec_si128(x1, sk[5]); + x2 = _mm_aesdec_si128(x2, sk[5]); + x3 = _mm_aesdec_si128(x3, sk[5]); + x0 = _mm_aesdec_si128(x0, sk[6]); + x1 = _mm_aesdec_si128(x1, sk[6]); + x2 = _mm_aesdec_si128(x2, sk[6]); + x3 = _mm_aesdec_si128(x3, sk[6]); + x0 = _mm_aesdec_si128(x0, sk[7]); + x1 = _mm_aesdec_si128(x1, sk[7]); + x2 = _mm_aesdec_si128(x2, sk[7]); + x3 = _mm_aesdec_si128(x3, sk[7]); + x0 = _mm_aesdec_si128(x0, sk[8]); + x1 = _mm_aesdec_si128(x1, sk[8]); + x2 = _mm_aesdec_si128(x2, sk[8]); + x3 = _mm_aesdec_si128(x3, sk[8]); + x0 = _mm_aesdec_si128(x0, sk[9]); + x1 = _mm_aesdec_si128(x1, sk[9]); + x2 = _mm_aesdec_si128(x2, sk[9]); + x3 = _mm_aesdec_si128(x3, sk[9]); + if (num_rounds == 10) { + x0 = _mm_aesdeclast_si128(x0, sk[10]); + x1 = _mm_aesdeclast_si128(x1, sk[10]); + x2 = _mm_aesdeclast_si128(x2, sk[10]); + x3 = _mm_aesdeclast_si128(x3, sk[10]); + } else if (num_rounds == 12) { + x0 = _mm_aesdec_si128(x0, sk[10]); + x1 = _mm_aesdec_si128(x1, sk[10]); + x2 = _mm_aesdec_si128(x2, sk[10]); + x3 = _mm_aesdec_si128(x3, sk[10]); + x0 = _mm_aesdec_si128(x0, sk[11]); + x1 = _mm_aesdec_si128(x1, sk[11]); + x2 = _mm_aesdec_si128(x2, sk[11]); + x3 = _mm_aesdec_si128(x3, sk[11]); + x0 = _mm_aesdeclast_si128(x0, sk[12]); + x1 = _mm_aesdeclast_si128(x1, sk[12]); + x2 = _mm_aesdeclast_si128(x2, sk[12]); + x3 = _mm_aesdeclast_si128(x3, sk[12]); + } else { + x0 = _mm_aesdec_si128(x0, sk[10]); + x1 = _mm_aesdec_si128(x1, sk[10]); + x2 = _mm_aesdec_si128(x2, sk[10]); + x3 = _mm_aesdec_si128(x3, sk[10]); + x0 = _mm_aesdec_si128(x0, sk[11]); + x1 = _mm_aesdec_si128(x1, sk[11]); + x2 = _mm_aesdec_si128(x2, sk[11]); + x3 = _mm_aesdec_si128(x3, sk[11]); + x0 = _mm_aesdec_si128(x0, sk[12]); + x1 = _mm_aesdec_si128(x1, sk[12]); + x2 = _mm_aesdec_si128(x2, sk[12]); + x3 = _mm_aesdec_si128(x3, sk[12]); + x0 = _mm_aesdec_si128(x0, sk[13]); + x1 = _mm_aesdec_si128(x1, sk[13]); + x2 = _mm_aesdec_si128(x2, sk[13]); + x3 = _mm_aesdec_si128(x3, sk[13]); + x0 = _mm_aesdeclast_si128(x0, sk[14]); + x1 = _mm_aesdeclast_si128(x1, sk[14]); + x2 = _mm_aesdeclast_si128(x2, sk[14]); + x3 = _mm_aesdeclast_si128(x3, sk[14]); + } + x0 = _mm_xor_si128(x0, ivx); + x1 = _mm_xor_si128(x1, e0); + x2 = _mm_xor_si128(x2, e1); + x3 = _mm_xor_si128(x3, e2); + ivx = e3; + _mm_storeu_si128((void *)(buf + 0), x0); + if (len >= 64) { + _mm_storeu_si128((void *)(buf + 16), x1); + _mm_storeu_si128((void *)(buf + 32), x2); + _mm_storeu_si128((void *)(buf + 48), x3); + buf += 64; + len -= 64; + } else { + if (len >= 32) { + _mm_storeu_si128((void *)(buf + 16), x1); + if (len >= 48) { + _mm_storeu_si128( + (void *)(buf + 32), x2); + } + } + break; + } + } + _mm_storeu_si128(iv, ivx); +} + +/* see bearssl_block.h */ +const br_block_cbcdec_class br_aes_x86ni_cbcdec_vtable = { + sizeof(br_aes_x86ni_cbcdec_keys), + 16, + 4, + (void (*)(const br_block_cbcdec_class **, const void *, size_t)) + &br_aes_x86ni_cbcdec_init, + (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) + &br_aes_x86ni_cbcdec_run +}; + +/* see bearssl_block.h */ +const br_block_cbcdec_class * +br_aes_x86ni_cbcdec_get_vtable(void) +{ + return br_aes_x86ni_supported() ? &br_aes_x86ni_cbcdec_vtable : NULL; +} + +#else + +/* see bearssl_block.h */ +const br_block_cbcdec_class * +br_aes_x86ni_cbcdec_get_vtable(void) +{ + return NULL; +} + +#endif diff --git a/src/symcipher/aes_x86ni_cbcenc.c b/src/symcipher/aes_x86ni_cbcenc.c new file mode 100644 index 0000000..f1c473e --- /dev/null +++ b/src/symcipher/aes_x86ni_cbcenc.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +#if BR_AES_X86NI + +#if BR_AES_X86NI_GCC +#include +#endif + +#if BR_AES_X86NI_MSC +#include +#endif + +/* see bearssl_block.h */ +void +br_aes_x86ni_cbcenc_init(br_aes_x86ni_cbcenc_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_x86ni_cbcenc_vtable; + ctx->num_rounds = br_aes_x86ni_keysched_enc(ctx->skey.skni, key, len); +} + +/* see bearssl_block.h */ +BR_TARGET("sse2,aes") +void +br_aes_x86ni_cbcenc_run(const br_aes_x86ni_cbcenc_keys *ctx, + void *iv, void *data, size_t len) +{ + unsigned char *buf; + unsigned num_rounds; + __m128i sk[15], ivx; + unsigned u; + + buf = data; + ivx = _mm_loadu_si128(iv); + num_rounds = ctx->num_rounds; + for (u = 0; u <= num_rounds; u ++) { + sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); + } + while (len > 0) { + __m128i x; + + x = _mm_xor_si128(_mm_loadu_si128((void *)buf), ivx); + x = _mm_xor_si128(x, sk[0]); + x = _mm_aesenc_si128(x, sk[1]); + x = _mm_aesenc_si128(x, sk[2]); + x = _mm_aesenc_si128(x, sk[3]); + x = _mm_aesenc_si128(x, sk[4]); + x = _mm_aesenc_si128(x, sk[5]); + x = _mm_aesenc_si128(x, sk[6]); + x = _mm_aesenc_si128(x, sk[7]); + x = _mm_aesenc_si128(x, sk[8]); + x = _mm_aesenc_si128(x, sk[9]); + if (num_rounds == 10) { + x = _mm_aesenclast_si128(x, sk[10]); + } else if (num_rounds == 12) { + x = _mm_aesenc_si128(x, sk[10]); + x = _mm_aesenc_si128(x, sk[11]); + x = _mm_aesenclast_si128(x, sk[12]); + } else { + x = _mm_aesenc_si128(x, sk[10]); + x = _mm_aesenc_si128(x, sk[11]); + x = _mm_aesenc_si128(x, sk[12]); + x = _mm_aesenc_si128(x, sk[13]); + x = _mm_aesenclast_si128(x, sk[14]); + } + ivx = x; + _mm_storeu_si128((void *)buf, x); + buf += 16; + len -= 16; + } + _mm_storeu_si128(iv, ivx); +} + +/* see bearssl_block.h */ +const br_block_cbcenc_class br_aes_x86ni_cbcenc_vtable = { + sizeof(br_aes_x86ni_cbcenc_keys), + 16, + 4, + (void (*)(const br_block_cbcenc_class **, const void *, size_t)) + &br_aes_x86ni_cbcenc_init, + (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) + &br_aes_x86ni_cbcenc_run +}; + +/* see bearssl_block.h */ +const br_block_cbcenc_class * +br_aes_x86ni_cbcenc_get_vtable(void) +{ + return br_aes_x86ni_supported() ? &br_aes_x86ni_cbcenc_vtable : NULL; +} + +#else + +/* see bearssl_block.h */ +const br_block_cbcenc_class * +br_aes_x86ni_cbcenc_get_vtable(void) +{ + return NULL; +} + +#endif diff --git a/src/symcipher/aes_x86ni_ctr.c b/src/symcipher/aes_x86ni_ctr.c new file mode 100644 index 0000000..a476843 --- /dev/null +++ b/src/symcipher/aes_x86ni_ctr.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "inner.h" + +#if BR_AES_X86NI + +#if BR_AES_X86NI_GCC +#include +#include +#define bswap32 __builtin_bswap32 +#endif + +#if BR_AES_X86NI_MSC +#include +#include +#define bswap32 _byteswap_ulong +#endif + +/* see bearssl_block.h */ +void +br_aes_x86ni_ctr_init(br_aes_x86ni_ctr_keys *ctx, + const void *key, size_t len) +{ + ctx->vtable = &br_aes_x86ni_ctr_vtable; + ctx->num_rounds = br_aes_x86ni_keysched_enc(ctx->skey.skni, key, len); +} + +/* see bearssl_block.h */ +BR_TARGET("sse2,sse4.1,aes") +uint32_t +br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx, + const void *iv, uint32_t cc, void *data, size_t len) +{ + unsigned char *buf; + unsigned char ivbuf[16]; + unsigned num_rounds; + __m128i sk[15]; + __m128i ivx; + unsigned u; + + buf = data; + memcpy(ivbuf, iv, 12); + num_rounds = ctx->num_rounds; + for (u = 0; u <= num_rounds; u ++) { + sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); + } + ivx = _mm_loadu_si128((void *)ivbuf); + while (len > 0) { + __m128i x0, x1, x2, x3; + + x0 = _mm_insert_epi32(ivx, bswap32(cc + 0), 3); + x1 = _mm_insert_epi32(ivx, bswap32(cc + 1), 3); + x2 = _mm_insert_epi32(ivx, bswap32(cc + 2), 3); + x3 = _mm_insert_epi32(ivx, bswap32(cc + 3), 3); + x0 = _mm_xor_si128(x0, sk[0]); + x1 = _mm_xor_si128(x1, sk[0]); + x2 = _mm_xor_si128(x2, sk[0]); + x3 = _mm_xor_si128(x3, sk[0]); + x0 = _mm_aesenc_si128(x0, sk[1]); + x1 = _mm_aesenc_si128(x1, sk[1]); + x2 = _mm_aesenc_si128(x2, sk[1]); + x3 = _mm_aesenc_si128(x3, sk[1]); + x0 = _mm_aesenc_si128(x0, sk[2]); + x1 = _mm_aesenc_si128(x1, sk[2]); + x2 = _mm_aesenc_si128(x2, sk[2]); + x3 = _mm_aesenc_si128(x3, sk[2]); + x0 = _mm_aesenc_si128(x0, sk[3]); + x1 = _mm_aesenc_si128(x1, sk[3]); + x2 = _mm_aesenc_si128(x2, sk[3]); + x3 = _mm_aesenc_si128(x3, sk[3]); + x0 = _mm_aesenc_si128(x0, sk[4]); + x1 = _mm_aesenc_si128(x1, sk[4]); + x2 = _mm_aesenc_si128(x2, sk[4]); + x3 = _mm_aesenc_si128(x3, sk[4]); + x0 = _mm_aesenc_si128(x0, sk[5]); + x1 = _mm_aesenc_si128(x1, sk[5]); + x2 = _mm_aesenc_si128(x2, sk[5]); + x3 = _mm_aesenc_si128(x3, sk[5]); + x0 = _mm_aesenc_si128(x0, sk[6]); + x1 = _mm_aesenc_si128(x1, sk[6]); + x2 = _mm_aesenc_si128(x2, sk[6]); + x3 = _mm_aesenc_si128(x3, sk[6]); + x0 = _mm_aesenc_si128(x0, sk[7]); + x1 = _mm_aesenc_si128(x1, sk[7]); + x2 = _mm_aesenc_si128(x2, sk[7]); + x3 = _mm_aesenc_si128(x3, sk[7]); + x0 = _mm_aesenc_si128(x0, sk[8]); + x1 = _mm_aesenc_si128(x1, sk[8]); + x2 = _mm_aesenc_si128(x2, sk[8]); + x3 = _mm_aesenc_si128(x3, sk[8]); + x0 = _mm_aesenc_si128(x0, sk[9]); + x1 = _mm_aesenc_si128(x1, sk[9]); + x2 = _mm_aesenc_si128(x2, sk[9]); + x3 = _mm_aesenc_si128(x3, sk[9]); + if (num_rounds == 10) { + x0 = _mm_aesenclast_si128(x0, sk[10]); + x1 = _mm_aesenclast_si128(x1, sk[10]); + x2 = _mm_aesenclast_si128(x2, sk[10]); + x3 = _mm_aesenclast_si128(x3, sk[10]); + } else if (num_rounds == 12) { + x0 = _mm_aesenc_si128(x0, sk[10]); + x1 = _mm_aesenc_si128(x1, sk[10]); + x2 = _mm_aesenc_si128(x2, sk[10]); + x3 = _mm_aesenc_si128(x3, sk[10]); + x0 = _mm_aesenc_si128(x0, sk[11]); + x1 = _mm_aesenc_si128(x1, sk[11]); + x2 = _mm_aesenc_si128(x2, sk[11]); + x3 = _mm_aesenc_si128(x3, sk[11]); + x0 = _mm_aesenclast_si128(x0, sk[12]); + x1 = _mm_aesenclast_si128(x1, sk[12]); + x2 = _mm_aesenclast_si128(x2, sk[12]); + x3 = _mm_aesenclast_si128(x3, sk[12]); + } else { + x0 = _mm_aesenc_si128(x0, sk[10]); + x1 = _mm_aesenc_si128(x1, sk[10]); + x2 = _mm_aesenc_si128(x2, sk[10]); + x3 = _mm_aesenc_si128(x3, sk[10]); + x0 = _mm_aesenc_si128(x0, sk[11]); + x1 = _mm_aesenc_si128(x1, sk[11]); + x2 = _mm_aesenc_si128(x2, sk[11]); + x3 = _mm_aesenc_si128(x3, sk[11]); + x0 = _mm_aesenc_si128(x0, sk[12]); + x1 = _mm_aesenc_si128(x1, sk[12]); + x2 = _mm_aesenc_si128(x2, sk[12]); + x3 = _mm_aesenc_si128(x3, sk[12]); + x0 = _mm_aesenc_si128(x0, sk[13]); + x1 = _mm_aesenc_si128(x1, sk[13]); + x2 = _mm_aesenc_si128(x2, sk[13]); + x3 = _mm_aesenc_si128(x3, sk[13]); + x0 = _mm_aesenclast_si128(x0, sk[14]); + x1 = _mm_aesenclast_si128(x1, sk[14]); + x2 = _mm_aesenclast_si128(x2, sk[14]); + x3 = _mm_aesenclast_si128(x3, sk[14]); + } + if (len >= 64) { + x0 = _mm_xor_si128(x0, + _mm_loadu_si128((void *)(buf + 0))); + x1 = _mm_xor_si128(x1, + _mm_loadu_si128((void *)(buf + 16))); + x2 = _mm_xor_si128(x2, + _mm_loadu_si128((void *)(buf + 32))); + x3 = _mm_xor_si128(x3, + _mm_loadu_si128((void *)(buf + 48))); + _mm_storeu_si128((void *)(buf + 0), x0); + _mm_storeu_si128((void *)(buf + 16), x1); + _mm_storeu_si128((void *)(buf + 32), x2); + _mm_storeu_si128((void *)(buf + 48), x3); + buf += 64; + len -= 64; + cc += 4; + } else { + unsigned char tmp[64]; + + _mm_storeu_si128((void *)(tmp + 0), x0); + _mm_storeu_si128((void *)(tmp + 16), x1); + _mm_storeu_si128((void *)(tmp + 32), x2); + _mm_storeu_si128((void *)(tmp + 48), x3); + for (u = 0; u < len; u ++) { + buf[u] ^= tmp[u]; + } + cc += (uint32_t)len >> 4; + break; + } + } + return cc; +} + +/* see bearssl_block.h */ +const br_block_ctr_class br_aes_x86ni_ctr_vtable = { + sizeof(br_aes_x86ni_ctr_keys), + 16, + 4, + (void (*)(const br_block_ctr_class **, const void *, size_t)) + &br_aes_x86ni_ctr_init, + (uint32_t (*)(const br_block_ctr_class *const *, + const void *, uint32_t, void *, size_t)) + &br_aes_x86ni_ctr_run +}; + +/* see bearssl_block.h */ +const br_block_ctr_class * +br_aes_x86ni_ctr_get_vtable(void) +{ + return br_aes_x86ni_supported() ? &br_aes_x86ni_ctr_vtable : NULL; +} + +#else + +/* see bearssl_block.h */ +const br_block_ctr_class * +br_aes_x86ni_ctr_get_vtable(void) +{ + return NULL; +} + +#endif diff --git a/test/test_crypto.c b/test/test_crypto.c index 53a5f13..ca7234d 100644 --- a/test/test_crypto.c +++ b/test/test_crypto.c @@ -591,7 +591,7 @@ test_HMAC_CT(const br_hash_class *digest_class, br_hmac_key_init(&kc, digest_class, key, key_len); - for (u = 0; u < 130; u ++) { + for (u = 0; u < 2; u ++) { for (v = 0; v < 130; v ++) { size_t min_len, max_len; size_t w; @@ -3157,7 +3157,6 @@ test_AES_generic(char *name, data_len = hextobin(plain, KAT_AES_CTR[u + 2]); hextobin(cipher, KAT_AES_CTR[u + 3]); vc->init(xc, key, key_len); - memcpy(buf, plain, data_len); vc->run(xc, iv, 1, buf, data_len); check_equals("KAT CTR AES (1)", buf, cipher, data_len); @@ -3271,6 +3270,33 @@ test_AES_ct64(void) 1, 1); } +static void +test_AES_x86ni(void) +{ + const br_block_cbcenc_class *x_cbcenc; + const br_block_cbcdec_class *x_cbcdec; + const br_block_ctr_class *x_ctr; + int hcbcenc, hcbcdec, hctr; + + x_cbcenc = br_aes_x86ni_cbcenc_get_vtable(); + x_cbcdec = br_aes_x86ni_cbcdec_get_vtable(); + x_ctr = br_aes_x86ni_ctr_get_vtable(); + hcbcenc = (x_cbcenc != NULL); + hcbcdec = (x_cbcdec != NULL); + hctr = (x_ctr != NULL); + if (hcbcenc != hctr || hcbcdec != hctr) { + fprintf(stderr, "AES_x86ni availability mismatch (%d/%d/%d)\n", + hcbcenc, hcbcdec, hctr); + exit(EXIT_FAILURE); + } + if (hctr) { + test_AES_generic("AES_x86ni", + x_cbcenc, x_cbcdec, x_ctr, 1, 1); + } else { + printf("Test AES_x86ni: UNAVAILABLE\n"); + } +} + /* * DES known-answer tests. Order: plaintext, key, ciphertext. * (mostly from NIST SP 800-20). @@ -4671,6 +4697,19 @@ test_GHASH_ctmul64(void) test_GHASH("GHASH_ctmul64", br_ghash_ctmul64); } +static void +test_GHASH_pclmul(void) +{ + br_ghash gh; + + gh = br_ghash_pclmul_get(); + if (gh == 0) { + printf("Test GHASH_pclmul: UNAVAILABLE\n"); + } else { + test_GHASH("GHASH_pclmul", gh); + } +} + static void test_EC_inner(const char *sk, const char *sU, const br_ec_impl *impl, int curve) @@ -5559,6 +5598,7 @@ static const struct { STU(AES_small), STU(AES_ct), STU(AES_ct64), + STU(AES_x86ni), STU(DES_tab), STU(DES_ct), STU(ChaCha20_ct), @@ -5571,6 +5611,7 @@ static const struct { STU(GHASH_ctmul), STU(GHASH_ctmul32), STU(GHASH_ctmul64), + STU(GHASH_pclmul), STU(EC_prime_i15), STU(EC_prime_i31), STU(EC_p256_m15), diff --git a/test/test_speed.c b/test/test_speed.c index 0d440ff..d7dfaad 100644 --- a/test/test_speed.c +++ b/test/test_speed.c @@ -88,7 +88,12 @@ test_speed_ ## fname(void) \ memset(key, 'T', sizeof key); \ memset(buf, 'P', sizeof buf); \ memset(iv, 'X', sizeof iv); \ - vt = &br_ ## cname ## _cbc ## dir ## _vtable; \ + vt = br_ ## cname ## _cbc ## dir ## _get_vtable(); \ + if (vt == NULL) { \ + printf("%-30s UNAVAILABLE\n", #Name); \ + fflush(stdout); \ + return; \ + } \ for (i = 0; i < 10; i ++) { \ vt->init(&ec.vtable, key, sizeof key); \ vt->run(&ec.vtable, iv, buf, sizeof buf); \ @@ -132,7 +137,12 @@ test_speed_ ## fname(void) \ memset(key, 'T', sizeof key); \ memset(buf, 'P', sizeof buf); \ memset(iv, 'X', sizeof iv); \ - vt = &br_ ## cname ## _ctr_vtable; \ + vt = br_ ## cname ## _ctr_get_vtable(); \ + if (vt == NULL) { \ + printf("%-30s UNAVAILABLE\n", #Name); \ + fflush(stdout); \ + return; \ + } \ for (i = 0; i < 10; i ++) { \ vt->init(&ec.vtable, key, sizeof key); \ vt->run(&ec.vtable, iv, 1, buf, sizeof buf); \ @@ -206,6 +216,23 @@ SPEED_HASH(SHA-1, sha1) SPEED_HASH(SHA-256, sha256) SPEED_HASH(SHA-512, sha512) +/* + * There are no vtable selection functions for the portable implementations, + * so we define some custom macros. + */ +#define br_aes_big_cbcenc_get_vtable() (&br_aes_big_cbcenc_vtable) +#define br_aes_big_cbcdec_get_vtable() (&br_aes_big_cbcdec_vtable) +#define br_aes_big_ctr_get_vtable() (&br_aes_big_ctr_vtable) +#define br_aes_small_cbcenc_get_vtable() (&br_aes_small_cbcenc_vtable) +#define br_aes_small_cbcdec_get_vtable() (&br_aes_small_cbcdec_vtable) +#define br_aes_small_ctr_get_vtable() (&br_aes_small_ctr_vtable) +#define br_aes_ct_cbcenc_get_vtable() (&br_aes_ct_cbcenc_vtable) +#define br_aes_ct_cbcdec_get_vtable() (&br_aes_ct_cbcdec_vtable) +#define br_aes_ct_ctr_get_vtable() (&br_aes_ct_ctr_vtable) +#define br_aes_ct64_cbcenc_get_vtable() (&br_aes_ct64_cbcenc_vtable) +#define br_aes_ct64_cbcdec_get_vtable() (&br_aes_ct64_cbcdec_vtable) +#define br_aes_ct64_ctr_get_vtable() (&br_aes_ct64_ctr_vtable) + #define SPEED_AES(iname) \ SPEED_BLOCKCIPHER_CBC(AES-128 CBC encrypt (iname), aes128_ ## iname ## _cbcenc, aes_ ## iname, 16, enc) \ SPEED_BLOCKCIPHER_CBC(AES-128 CBC decrypt (iname), aes128_ ## iname ## _cbcdec, aes_ ## iname, 16, dec) \ @@ -221,6 +248,12 @@ SPEED_AES(big) SPEED_AES(small) SPEED_AES(ct) SPEED_AES(ct64) +SPEED_AES(x86ni) + +#define br_des_tab_cbcenc_get_vtable() (&br_des_tab_cbcenc_vtable) +#define br_des_tab_cbcdec_get_vtable() (&br_des_tab_cbcdec_vtable) +#define br_des_ct_cbcenc_get_vtable() (&br_des_ct_cbcenc_vtable) +#define br_des_ct_cbcdec_get_vtable() (&br_des_ct_cbcdec_vtable) #define SPEED_DES(iname) \ SPEED_BLOCKCIPHER_CBC(DES CBC encrypt (iname), des_ ## iname ## _cbcenc, des_ ## iname, 8, enc) \ @@ -287,6 +320,20 @@ test_speed_ghash_ctmul64(void) test_speed_ghash_inner("GHASH (ctmul64)", &br_ghash_ctmul64); } +static void +test_speed_ghash_pclmul(void) +{ + br_ghash gh; + + gh = br_ghash_pclmul_get(); + if (gh == 0) { + printf("%-30s UNAVAILABLE\n", "GHASH (pclmul)"); + fflush(stdout); + } else { + test_speed_ghash_inner("GHASH (pclmul)", gh); + } +} + static uint32_t fake_chacha20(const void *key, const void *iv, uint32_t cc, void *data, size_t len) @@ -1158,6 +1205,16 @@ static const struct { STU(aes192_ct64_ctr), STU(aes256_ct64_ctr), + STU(aes128_x86ni_cbcenc), + STU(aes128_x86ni_cbcdec), + STU(aes192_x86ni_cbcenc), + STU(aes192_x86ni_cbcdec), + STU(aes256_x86ni_cbcenc), + STU(aes256_x86ni_cbcdec), + STU(aes128_x86ni_ctr), + STU(aes192_x86ni_ctr), + STU(aes256_x86ni_ctr), + STU(des_tab_cbcenc), STU(des_tab_cbcdec), STU(3des_tab_cbcenc), @@ -1173,6 +1230,7 @@ static const struct { STU(ghash_ctmul), STU(ghash_ctmul32), STU(ghash_ctmul64), + STU(ghash_pclmul), STU(poly1305_ctmul), STU(poly1305_ctmul32), diff --git a/test/test_x509.c b/test/test_x509.c index 6f75feb..2c61cf5 100644 --- a/test/test_x509.c +++ b/test/test_x509.c @@ -1531,9 +1531,9 @@ run_test_case(test_case *tc) br_x509_minimal_set_hash(&ctx, id, hash_impls[u].impl); } } - br_x509_minimal_set_rsa(&ctx, br_rsa_i31_pkcs1_vrfy); + br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default()); br_x509_minimal_set_ecdsa(&ctx, - &br_ec_prime_i31, br_ecdsa_i31_vrfy_asn1); + br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default()); /* * Set the validation date. @@ -1819,9 +1819,9 @@ test_name_extraction(void) id = hash_impls[u].id; br_x509_minimal_set_hash(&ctx, id, hash_impls[u].impl); } - br_x509_minimal_set_rsa(&ctx, br_rsa_i31_pkcs1_vrfy); + br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default()); br_x509_minimal_set_ecdsa(&ctx, - &br_ec_prime_i31, br_ecdsa_i31_vrfy_asn1); + br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default()); string_to_time(DEFAULT_TIME, &days, &seconds); br_x509_minimal_set_time(&ctx, days, seconds); diff --git a/tools/brssl.h b/tools/brssl.h index 8c84b04..f2957e6 100644 --- a/tools/brssl.h +++ b/tools/brssl.h @@ -471,6 +471,18 @@ const br_hash_class *get_hash_impl(int id); */ const char *find_error_name(int err, const char **comment); +/* + * Find the symbolic name for an algorithm implementation. Provided + * pointer should be a pointer to a vtable or to a function, where + * appropriate. If not recognised, then the string "UNKNOWN" is returned. + * + * If 'long_name' is non-zero, then the returned name recalls the + * algorithm type as well; otherwise, only the core implementation name + * is returned (e.g. the long name could be 'aes_big_cbcenc' while the + * short name is 'big'). + */ +const char *get_algo_name(const void *algo, int long_name); + /* * Run a SSL engine, with a socket connected to the peer, and using * stdin/stdout to exchange application data. diff --git a/tools/client.c b/tools/client.c index 37b8877..fad18e0 100644 --- a/tools/client.c +++ b/tools/client.c @@ -341,14 +341,16 @@ static uint32_t cc_do_keyx(const br_ssl_client_certificate_class **pctx, unsigned char *data, size_t *len) { + const br_ec_impl *iec; ccert_context *zc; size_t xoff, xlen; uint32_t r; zc = (ccert_context *)pctx; - r = br_ec_all_m15.mul(data, *len, zc->sk->key.ec.x, + iec = br_ec_get_default(); + r = iec->mul(data, *len, zc->sk->key.ec.x, zc->sk->key.ec.xlen, zc->sk->key.ec.curve); - xoff = br_ec_all_m15.xoff(zc->sk->key.ec.curve, &xlen); + xoff = iec->xoff(zc->sk->key.ec.curve, &xlen); memmove(data, data + xoff, xlen); *len = xlen; return r; @@ -390,8 +392,8 @@ cc_do_sign(const br_ssl_client_certificate_class **pctx, } return 0; } - x = br_rsa_i31_pkcs1_sign(hash_oid, hv, hv_len, - &zc->sk->key.rsa, data); + x = br_rsa_pkcs1_sign_get_default()( + hash_oid, hv, hv_len, &zc->sk->key.rsa, data); if (!x) { if (zc->verbose) { fprintf(stderr, "ERROR: RSA-sign failure\n"); @@ -418,8 +420,8 @@ cc_do_sign(const br_ssl_client_certificate_class **pctx, } return 0; } - sig_len = br_ecdsa_i31_sign_asn1(&br_ec_all_m15, - hc, hv, &zc->sk->key.ec, data); + sig_len = br_ecdsa_sign_asn1_get_default()( + br_ec_get_default(), hc, hv, &zc->sk->key.ec, data); if (sig_len == 0) { if (zc->verbose) { fprintf(stderr, "ERROR: ECDSA-sign failure\n"); @@ -946,54 +948,29 @@ do_client(int argc, char *argv[]) } /* TODO: algorithm implementation selection */ if ((req & REQ_AESCBC) != 0) { - br_ssl_engine_set_aes_cbc(&cc.eng, - &br_aes_ct_cbcenc_vtable, - &br_aes_ct_cbcdec_vtable); - br_ssl_engine_set_cbc(&cc.eng, - &br_sslrec_in_cbc_vtable, - &br_sslrec_out_cbc_vtable); + br_ssl_engine_set_default_aes_cbc(&cc.eng); } if ((req & REQ_AESGCM) != 0) { - br_ssl_engine_set_aes_ctr(&cc.eng, - &br_aes_ct_ctr_vtable); - br_ssl_engine_set_ghash(&cc.eng, - &br_ghash_ctmul); - br_ssl_engine_set_gcm(&cc.eng, - &br_sslrec_in_gcm_vtable, - &br_sslrec_out_gcm_vtable); + br_ssl_engine_set_default_aes_gcm(&cc.eng); } if ((req & REQ_CHAPOL) != 0) { - br_ssl_engine_set_chacha20(&cc.eng, - &br_chacha20_ct_run); - br_ssl_engine_set_poly1305(&cc.eng, - &br_poly1305_ctmul_run); - br_ssl_engine_set_chapol(&cc.eng, - &br_sslrec_in_chapol_vtable, - &br_sslrec_out_chapol_vtable); + br_ssl_engine_set_default_chapol(&cc.eng); } if ((req & REQ_3DESCBC) != 0) { - br_ssl_engine_set_des_cbc(&cc.eng, - &br_des_ct_cbcenc_vtable, - &br_des_ct_cbcdec_vtable); - br_ssl_engine_set_cbc(&cc.eng, - &br_sslrec_in_cbc_vtable, - &br_sslrec_out_cbc_vtable); + br_ssl_engine_set_default_des_cbc(&cc.eng); } if ((req & REQ_RSAKEYX) != 0) { - br_ssl_client_set_rsapub(&cc, &br_rsa_i31_public); + br_ssl_client_set_default_rsapub(&cc); } if ((req & REQ_ECDHE_RSA) != 0) { - br_ssl_engine_set_ec(&cc.eng, &br_ec_all_m15); - br_ssl_engine_set_rsavrfy(&cc.eng, - &br_rsa_i31_pkcs1_vrfy); + br_ssl_engine_set_default_ec(&cc.eng); + br_ssl_engine_set_default_rsavrfy(&cc.eng); } if ((req & REQ_ECDHE_ECDSA) != 0) { - br_ssl_engine_set_ec(&cc.eng, &br_ec_all_m15); - br_ssl_engine_set_ecdsa(&cc.eng, - &br_ecdsa_i31_vrfy_asn1); + br_ssl_engine_set_default_ecdsa(&cc.eng); } if ((req & REQ_ECDH) != 0) { - br_ssl_engine_set_ec(&cc.eng, &br_ec_all_m15); + br_ssl_engine_set_default_ec(&cc.eng); } } if (fallback) { @@ -1025,9 +1002,9 @@ do_client(int argc, char *argv[]) &br_tls12_sha384_prf); } } - br_x509_minimal_set_rsa(&xc, &br_rsa_i31_pkcs1_vrfy); + br_x509_minimal_set_rsa(&xc, br_rsa_pkcs1_vrfy_get_default()); br_x509_minimal_set_ecdsa(&xc, - &br_ec_all_m15, &br_ecdsa_i31_vrfy_asn1); + br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default()); /* * If there is no provided trust anchor, then certificate validation diff --git a/tools/names.c b/tools/names.c index 438f41a..753a736 100644 --- a/tools/names.c +++ b/tools/names.c @@ -271,7 +271,7 @@ const cipher_suite cipher_suites[] = { { NULL, 0, 0, NULL } }; -static struct { +static const struct { int id; const char *name; } curves[] = { @@ -338,6 +338,108 @@ static struct { { 0, 0 } }; +static const struct { + const char *long_name; + const char *short_name; + const void *impl; +} algo_names[] = { + /* Block ciphers */ + { "aes_big_cbcenc", "big", &br_aes_big_cbcenc_vtable }, + { "aes_big_cbcdec", "big", &br_aes_big_cbcdec_vtable }, + { "aes_big_ctr", "big", &br_aes_big_ctr_vtable }, + { "aes_small_cbcenc", "small", &br_aes_small_cbcenc_vtable }, + { "aes_small_cbcdec", "small", &br_aes_small_cbcdec_vtable }, + { "aes_small_ctr", "small", &br_aes_small_ctr_vtable }, + { "aes_ct_cbcenc", "ct", &br_aes_ct_cbcenc_vtable }, + { "aes_ct_cbcdec", "ct", &br_aes_ct_cbcdec_vtable }, + { "aes_ct_ctr", "ct", &br_aes_ct_ctr_vtable }, + { "aes_ct64_cbcenc", "ct64", &br_aes_ct64_cbcenc_vtable }, + { "aes_ct64_cbcdec", "ct64", &br_aes_ct64_cbcdec_vtable }, + { "aes_ct64_ctr", "ct64", &br_aes_ct64_ctr_vtable }, + + { "des_tab_cbcenc", "tab", &br_des_tab_cbcenc_vtable }, + { "des_tab_cbcdec", "tab", &br_des_tab_cbcdec_vtable }, + { "des_ct_cbcenc", "ct", &br_des_ct_cbcenc_vtable }, + { "des_ct_cbcdec", "ct", &br_des_ct_cbcdec_vtable }, + + { "chacha20_ct", "ct", &br_chacha20_ct_run }, + + { "ghash_ctmul", "ctmul", &br_ghash_ctmul }, + { "ghash_ctmul32", "ctmul32", &br_ghash_ctmul32 }, + { "ghash_ctmul64", "ctmul64", &br_ghash_ctmul64 }, + + { "poly1305_ctmul", "ctmul", &br_poly1305_ctmul_run }, + { "poly1305_ctmul32", "ctmul32", &br_poly1305_ctmul32_run }, + + { "ec_all_m15", "all_m15", &br_ec_all_m15 }, + { "ec_all_m31", "all_m31", &br_ec_all_m31 }, + { "ec_c25519_i15", "c25519_i15", &br_ec_c25519_i15 }, + { "ec_c25519_i31", "c25519_i31", &br_ec_c25519_i31 }, + { "ec_c25519_m15", "c25519_m15", &br_ec_c25519_m15 }, + { "ec_c25519_m31", "c25519_m31", &br_ec_c25519_m31 }, + { "ec_p256_m15", "p256_m15", &br_ec_p256_m15 }, + { "ec_p256_m31", "p256_m31", &br_ec_p256_m31 }, + { "ec_prime_i15", "prime_i15", &br_ec_prime_i15 }, + { "ec_prime_i31", "prime_i31", &br_ec_prime_i31 }, + + { "ecdsa_i15_sign_asn1", "i15_asn1", &br_ecdsa_i15_sign_asn1 }, + { "ecdsa_i15_sign_raw", "i15_raw", &br_ecdsa_i15_sign_raw }, + { "ecdsa_i31_sign_asn1", "i31_asn1", &br_ecdsa_i31_sign_asn1 }, + { "ecdsa_i31_sign_raw", "i31_raw", &br_ecdsa_i31_sign_raw }, + { "ecdsa_i15_vrfy_asn1", "i15_asn1", &br_ecdsa_i15_vrfy_asn1 }, + { "ecdsa_i15_vrfy_raw", "i15_raw", &br_ecdsa_i15_vrfy_raw }, + { "ecdsa_i31_vrfy_asn1", "i31_asn1", &br_ecdsa_i31_vrfy_asn1 }, + { "ecdsa_i31_vrfy_raw", "i31_raw", &br_ecdsa_i31_vrfy_raw }, + + { "rsa_i15_pkcs1_sign", "i15", &br_rsa_i15_pkcs1_sign }, + { "rsa_i31_pkcs1_sign", "i31", &br_rsa_i31_pkcs1_sign }, + { "rsa_i32_pkcs1_sign", "i32", &br_rsa_i32_pkcs1_sign }, + { "rsa_i15_pkcs1_vrfy", "i15", &br_rsa_i15_pkcs1_vrfy }, + { "rsa_i31_pkcs1_vrfy", "i31", &br_rsa_i31_pkcs1_vrfy }, + { "rsa_i32_pkcs1_vrfy", "i32", &br_rsa_i32_pkcs1_vrfy }, + + { 0, 0, 0 } +}; + +static const struct { + const char *long_name; + const char *short_name; + const void *(*get)(void); +} algo_names_dyn[] = { + { "aes_x86ni_cbcenc", "x86ni", + (const void *(*)(void))&br_aes_x86ni_cbcenc_get_vtable }, + { "aes_x86ni_cbcdec", "x86ni", + (const void *(*)(void))&br_aes_x86ni_cbcdec_get_vtable }, + { "aes_x86ni_ctr", "x86ni", + (const void *(*)(void))&br_aes_x86ni_ctr_get_vtable }, + { "ghash_pclmul", "pclmul", + (const void *(*)(void))&br_ghash_pclmul_get }, + { 0, 0, 0, } +}; + +/* see brssl.h */ +const char * +get_algo_name(const void *impl, int long_name) +{ + size_t u; + + for (u = 0; algo_names[u].long_name; u ++) { + if (impl == algo_names[u].impl) { + return long_name + ? algo_names[u].long_name + : algo_names[u].short_name; + } + } + for (u = 0; algo_names_dyn[u].long_name; u ++) { + if (impl == algo_names_dyn[u].get()) { + return long_name + ? algo_names_dyn[u].long_name + : algo_names_dyn[u].short_name; + } + } + return "UNKNOWN"; +} + /* see brssl.h */ const char * get_curve_name(int id) diff --git a/tools/server.c b/tools/server.c index fbc7786..363028f 100644 --- a/tools/server.c +++ b/tools/server.c @@ -475,14 +475,17 @@ sp_do_keyx(const br_ssl_server_policy_class **pctx, pc = (policy_context *)pctx; switch (pc->sk->key_type) { + const br_ec_impl *iec; + case BR_KEYTYPE_RSA: return br_rsa_ssl_decrypt( - &br_rsa_i31_private, &pc->sk->key.rsa, - data, *len); + br_rsa_private_get_default(), + &pc->sk->key.rsa, data, *len); case BR_KEYTYPE_EC: - r = br_ec_all_m15.mul(data, *len, pc->sk->key.ec.x, + iec = br_ec_get_default(); + r = iec->mul(data, *len, pc->sk->key.ec.x, pc->sk->key.ec.xlen, pc->sk->key.ec.curve); - xoff = br_ec_all_m15.xoff(pc->sk->key.ec.curve, &xlen); + xoff = iec->xoff(pc->sk->key.ec.curve, &xlen); memmove(data, data + xoff, xlen); *len = xlen; return r; @@ -556,8 +559,8 @@ sp_do_sign(const br_ssl_server_policy_class **pctx, } return 0; } - x = br_rsa_i31_pkcs1_sign(hash_oid, hv, hv_len, - &pc->sk->key.rsa, data); + x = br_rsa_pkcs1_sign_get_default()( + hash_oid, hv, hv_len, &pc->sk->key.rsa, data); if (!x) { if (pc->verbose) { fprintf(stderr, "ERROR: RSA-sign failure\n"); @@ -584,8 +587,8 @@ sp_do_sign(const br_ssl_server_policy_class **pctx, } return 0; } - sig_len = br_ecdsa_i31_sign_asn1(&br_ec_all_m15, - hc, hv, &pc->sk->key.ec, data); + sig_len = br_ecdsa_sign_asn1_get_default()( + br_ec_get_default(), hc, hv, &pc->sk->key.ec, data); if (sig_len == 0) { if (pc->verbose) { fprintf(stderr, "ERROR: ECDSA-sign failure\n"); @@ -956,7 +959,7 @@ do_server(int argc, char *argv[]) break; case BR_KEYTYPE_EC: curve = sk->key.ec.curve; - supp = br_ec_all_m15.supported_curves; + supp = br_ec_get_default()->supported_curves; if (curve > 31 || !((supp >> curve) & 1)) { fprintf(stderr, "ERROR: private key curve (%d)" " is not supported\n", curve); @@ -1046,41 +1049,19 @@ do_server(int argc, char *argv[]) } /* TODO: algorithm implementation selection */ if ((req & REQ_AESCBC) != 0) { - br_ssl_engine_set_aes_cbc(&cc.eng, - &br_aes_ct_cbcenc_vtable, - &br_aes_ct_cbcdec_vtable); - br_ssl_engine_set_cbc(&cc.eng, - &br_sslrec_in_cbc_vtable, - &br_sslrec_out_cbc_vtable); + br_ssl_engine_set_default_aes_cbc(&cc.eng); } if ((req & REQ_AESGCM) != 0) { - br_ssl_engine_set_aes_ctr(&cc.eng, - &br_aes_ct_ctr_vtable); - br_ssl_engine_set_ghash(&cc.eng, - &br_ghash_ctmul); - br_ssl_engine_set_gcm(&cc.eng, - &br_sslrec_in_gcm_vtable, - &br_sslrec_out_gcm_vtable); + br_ssl_engine_set_default_aes_gcm(&cc.eng); } if ((req & REQ_CHAPOL) != 0) { - br_ssl_engine_set_chacha20(&cc.eng, - &br_chacha20_ct_run); - br_ssl_engine_set_poly1305(&cc.eng, - &br_poly1305_ctmul_run); - br_ssl_engine_set_chapol(&cc.eng, - &br_sslrec_in_chapol_vtable, - &br_sslrec_out_chapol_vtable); + br_ssl_engine_set_default_chapol(&cc.eng); } if ((req & REQ_3DESCBC) != 0) { - br_ssl_engine_set_des_cbc(&cc.eng, - &br_des_ct_cbcenc_vtable, - &br_des_ct_cbcdec_vtable); - br_ssl_engine_set_cbc(&cc.eng, - &br_sslrec_in_cbc_vtable, - &br_sslrec_out_cbc_vtable); + br_ssl_engine_set_default_des_cbc(&cc.eng); } if ((req & (REQ_ECDHE_RSA | REQ_ECDHE_ECDSA)) != 0) { - br_ssl_engine_set_ec(&cc.eng, &br_ec_all_m15); + br_ssl_engine_set_default_ec(&cc.eng); } } br_ssl_engine_set_suites(&cc.eng, suite_ids, num_suites); @@ -1153,12 +1134,11 @@ do_server(int argc, char *argv[]) br_x509_minimal_set_hash(&xc, id, hc); } } - br_ssl_engine_set_rsavrfy(&cc.eng, &br_rsa_i31_pkcs1_vrfy); - br_ssl_engine_set_ec(&cc.eng, &br_ec_all_m15); - br_ssl_engine_set_ecdsa(&cc.eng, &br_ecdsa_i31_vrfy_asn1); - br_x509_minimal_set_rsa(&xc, &br_rsa_i31_pkcs1_vrfy); + br_ssl_engine_set_default_rsavrfy(&cc.eng); + br_ssl_engine_set_default_ecdsa(&cc.eng); + br_x509_minimal_set_rsa(&xc, br_rsa_pkcs1_vrfy_get_default()); br_x509_minimal_set_ecdsa(&xc, - &br_ec_all_m15, &br_ecdsa_i31_vrfy_asn1); + br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default()); br_ssl_engine_set_x509(&cc.eng, &xc.vtable); br_ssl_server_set_trust_anchor_names_alt(&cc, &VEC_ELT(anchors, 0), VEC_LEN(anchors)); diff --git a/tools/sslio.c b/tools/sslio.c index 9941090..8d58ee9 100644 --- a/tools/sslio.c +++ b/tools/sslio.c @@ -262,6 +262,57 @@ run_ssl_engine(br_ssl_engine_context *cc, unsigned long fd, unsigned flags) verbose = (flags & RUN_ENGINE_VERBOSE) != 0; trace = (flags & RUN_ENGINE_TRACE) != 0; + /* + * Print algorithm details. + */ + if (verbose) { + fprintf(stderr, "Algorithms:\n"); + if (cc->iaes_cbcenc != 0) { + fprintf(stderr, " AES/CBC (enc): %s\n", + get_algo_name(cc->iaes_cbcenc, 0)); + } + if (cc->iaes_cbcdec != 0) { + fprintf(stderr, " AES/CBC (dec): %s\n", + get_algo_name(cc->iaes_cbcdec, 0)); + } + if (cc->iaes_ctr != 0) { + fprintf(stderr, " AES/CTR: %s\n", + get_algo_name(cc->iaes_cbcdec, 0)); + } + if (cc->ides_cbcenc != 0) { + fprintf(stderr, " DES/CBC (enc): %s\n", + get_algo_name(cc->ides_cbcenc, 0)); + } + if (cc->ides_cbcdec != 0) { + fprintf(stderr, " DES/CBC (dec): %s\n", + get_algo_name(cc->ides_cbcdec, 0)); + } + if (cc->ighash != 0) { + fprintf(stderr, " GHASH (GCM): %s\n", + get_algo_name(cc->ighash, 0)); + } + if (cc->ichacha != 0) { + fprintf(stderr, " ChaCha20: %s\n", + get_algo_name(cc->ichacha, 0)); + } + if (cc->ipoly != 0) { + fprintf(stderr, " Poly1305: %s\n", + get_algo_name(cc->ipoly, 0)); + } + if (cc->iec != 0) { + fprintf(stderr, " EC: %s\n", + get_algo_name(cc->iec, 0)); + } + if (cc->iecdsa != 0) { + fprintf(stderr, " ECDSA: %s\n", + get_algo_name(cc->iecdsa, 0)); + } + if (cc->irsavrfy != 0) { + fprintf(stderr, " RSA (vrfy): %s\n", + get_algo_name(cc->irsavrfy, 0)); + } + } + #ifdef _WIN32 fd_event = WSA_INVALID_EVENT; can_send = 0; -- 2.17.1