Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock X-Debbugs-Cc: mbed...@packages.debian.org Control: affects -1 + src:mbedtls
Please unblock package mbedtls [ Reason ] Upstream released a new LTS bugfix version, and I'd like to have it in bookworm. Since mbedtls is a crypto library and backporting single commits can be dangerous, importing new versions is the safest and most appropriate thing to do, especially since the upstream developers do a pretty good job in maintaining LTS versions for a long time. [ Impact ] If not granted, Debian will release with a somewhat vulnerable/buggy version of a widely used crypto library. [ Tests ] I've manually reviewed the changelog and diffs of the new release, tested it locally with the upstream test suite and autopkgtest, and it has passed all the CI checks on Salsa (repo available at <https://salsa.debian.org/debian/mbedtls>). [ Risks ] Risks should be low, as upstream usually does a good job with backporting. The "only" issue is that between 2.28.2 and 2.28.3 they have adopted a new code style, and reformatted the whole codebase accordingly; this means that the debdiff is huge, even though the changes are only a few. To make reviewing easier for me and you too, I've prepared three git diffs that exclude the upstream commits that reformatted the code, and another one that adds the string "\emptydescription" to many documentation strings in the source files. As upstream also always backports test code along with fixes, these diffs only include changes from the include/ and library/ directories, since that's where the code that gets into the binary packages resides. . The diffs were generated with these commands: . $ git clone https://github.com/Mbed-TLS/mbedtls.git $ cd mbedtls $ git diff v2.28.2..160df1d13621ca3ee70e1fa19d0da88398da9683~1 include/ library/ $ git diff b37f6c1b95815d39fea26b2a17e318602eefe709..b361e04207831f753a29d6036361d4447aaaa3bc~1 include/ library/ $ git diff 7a5168e90db359e17e72591cb5ddb06ef5f0388f..v2.28.3 include/ library/ [ Checklist ] [x] all changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in testing [ Other info ] I mistakenly uploaded the new mbedtls version to unstable because I didn't realize it was a key package, and thought that a regular 20 days of waiting would suffice. This is also my first unblock request, so please be clement with me, thanks! :D Also, the debdiff is not directly attached to this email to avoid hitting the size limit of the mailing list. You can find it here: <https://bin.snopyta.org/?b47ce8f3107c9a0a#92ZuUuxNvi8AWA1bVTPXCDFxakvxG1XUgcguoLnQKVcw> unblock mbedtls/2.28.2-1
diff --git a/include/mbedtls/bn_mul.h b/include/mbedtls/bn_mul.h index a3fc36381..bce9ce38c 100644 --- a/include/mbedtls/bn_mul.h +++ b/include/mbedtls/bn_mul.h @@ -84,6 +84,7 @@ #endif /* bits in mbedtls_mpi_uint */ +/* *INDENT-OFF* */ #if defined(MBEDTLS_HAVE_ASM) #ifndef asm @@ -1001,4 +1002,5 @@ #endif /* C (generic) */ #endif /* C (longlong) */ +/* *INDENT-ON* */ #endif /* bn_mul.h */ diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 7ae1ff94d..2ab99823e 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -28,6 +28,7 @@ #ifndef MBEDTLS_CHECK_CONFIG_H #define MBEDTLS_CHECK_CONFIG_H +/* *INDENT-OFF* */ /* * We assume CHAR_BIT is 8 in many places. In practice, this is true on our * target platforms, so not an issue, but let's just be extra sure. @@ -143,6 +144,11 @@ #error "MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED defined, but MBEDTLS_ECDH_LEGACY_CONTEXT not disabled" #endif +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + !defined(MBEDTLS_ECP_C) +#error "MBEDTLS_ECP_RESTARTABLE defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) #error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" #endif @@ -955,4 +961,5 @@ */ typedef int mbedtls_iso_c_forbids_empty_translation_units; +/* *INDENT-ON* */ #endif /* MBEDTLS_CHECK_CONFIG_H */ diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h index 6d83da882..ce100d3ed 100644 --- a/include/mbedtls/cipher.h +++ b/include/mbedtls/cipher.h @@ -917,13 +917,13 @@ int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, * parameter-verification failure. * \return A cipher-specific error code on failure. */ -int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, - unsigned char *tag, size_t tag_len ) - MBEDTLS_DEPRECATED; +int MBEDTLS_DEPRECATED mbedtls_cipher_auth_encrypt( + mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ); /** * \brief The generic authenticated decryption (AEAD) function. @@ -976,13 +976,13 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, * \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic. * \return A cipher-specific error code on failure. */ -int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, - const unsigned char *tag, size_t tag_len ) - MBEDTLS_DEPRECATED; +int MBEDTLS_DEPRECATED mbedtls_cipher_auth_decrypt( + mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ); #undef MBEDTLS_DEPRECATED #endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_CIPHER_MODE_AEAD */ diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 61db79362..9a2de676d 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -859,12 +859,37 @@ * This is useful in non-threaded environments if you want to avoid blocking * for too long on ECC (and, hence, X.509 or SSL/TLS) operations. * - * Uncomment this macro to enable restartable ECC computations. + * This option: + * - Adds xxx_restartable() variants of existing operations in the + * following modules, with corresponding restart context types: + * - ECP (for Short Weierstrass curves only): scalar multiplication (mul), + * linear combination (muladd); + * - ECDSA: signature generation & verification; + * - PK: signature generation & verification; + * - X509: certificate chain verification. + * - Adds mbedtls_ecdh_enable_restart() in the ECDH module. + * - Changes the behaviour of TLS 1.2 clients (not servers) when using the + * ECDHE-ECDSA key exchange (not other key exchanges) to make all ECC + * computations restartable: + * - ECDH operations from the key exchange, only for Short Weierstass + * curves; + * - verification of the server's key exchange signature; + * - verification of the server's certificate chain; + * - generation of the client's signature if client authentication is used, + * with an ECC key/certificate. + * + * \note In the cases above, the usual SSL/TLS functions, such as + * mbedtls_ssl_handshake(), can now return + * MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS. * * \note This option only works with the default software implementation of * elliptic curve functionality. It is incompatible with - * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT, MBEDTLS_ECDSA_XXX_ALT - * and MBEDTLS_ECDH_LEGACY_CONTEXT. + * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT, MBEDTLS_ECDSA_XXX_ALT, + * MBEDTLS_ECDH_LEGACY_CONTEXT, and MBEDTLS_USE_PSA_CRYPTO. + * + * Requires: MBEDTLS_ECP_C + * + * Uncomment this macro to enable restartable ECC computations. */ //#define MBEDTLS_ECP_RESTARTABLE diff --git a/include/psa/crypto.h b/include/psa/crypto.h index faa3b9e3f..b75947cdb 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -2861,7 +2861,7 @@ psa_status_t psa_aead_abort(psa_aead_operation_t *operation); * * \note To perform a multi-part hash-and-sign signature algorithm, first use * a multi-part hash operation and then pass the resulting hash to - * psa_sign_hash(). PSA_ALG_GET_HASH(\p alg) can be used to determine the + * psa_sign_hash(). PSA_ALG_SIGN_GET_HASH(\p alg) can be used to determine the * hash algorithm to use. * * \param[in] key Identifier of the key to use for the operation. @@ -2927,7 +2927,7 @@ psa_status_t psa_sign_message( mbedtls_svc_key_id_t key, * \note To perform a multi-part hash-and-sign signature verification * algorithm, first use a multi-part hash operation to hash the message * and then pass the resulting hash to psa_verify_hash(). - * PSA_ALG_GET_HASH(\p alg) can be used to determine the hash algorithm + * PSA_ALG_SIGN_GET_HASH(\p alg) can be used to determine the hash algorithm * to use. * * \param[in] key Identifier of the key to use for the operation. diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index a4b4927e9..a9fddb797 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -57,6 +57,13 @@ * value, check with the Arm PSA framework group to pick one that other * domains aren't already using. */ +/* Tell uncrustify not to touch the constant definitions, otherwise + * it might change the spacing to something that is not PSA-compliant + * (e.g. adding a space after casts). + * + * *INDENT-OFF* + */ + /** The action was completed successfully. */ #define PSA_SUCCESS ((psa_status_t)0) @@ -327,6 +334,8 @@ */ #define PSA_ERROR_DATA_INVALID ((psa_status_t)-153) +/* *INDENT-ON* */ + /**@}*/ /** \defgroup crypto_types Key and algorithm types @@ -819,7 +828,9 @@ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) /** An invalid algorithm identifier value. */ +/* *INDENT-OFF* (https://github.com/ARM-software/psa-arch-tests/issues/337) */ #define PSA_ALG_NONE ((psa_algorithm_t)0) +/* *INDENT-ON* */ #define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) /** MD2 */ @@ -1690,7 +1701,7 @@ #define PSA_ALG_HKDF_BASE ((psa_algorithm_t)0x08000100) /** Macro to build an HKDF algorithm. * - * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF using HMAC-SHA-256. + * For example, `PSA_ALG_HKDF(PSA_ALG_SHA_256)` is HKDF using HMAC-SHA-256. * * This key derivation algorithm uses the following inputs: * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the "extract" step. @@ -1743,7 +1754,7 @@ * concatenation of ServerHello.Random + ClientHello.Random, * and the label is "key expansion". * - * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` represents the + * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)` represents the * TLS 1.2 PRF using HMAC-SHA-256. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that @@ -1789,7 +1800,7 @@ * ClientHello.Random + ServerHello.Random, * and the label is "master secret" or "extended master secret". * - * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA256)` represents the + * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256)` represents the * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that @@ -2085,7 +2096,9 @@ /** The null key identifier. */ +/* *INDENT-OFF* (https://github.com/ARM-software/psa-arch-tests/issues/337) */ #define PSA_KEY_ID_NULL ((psa_key_id_t)0) +/* *INDENT-ON* */ /** The minimum value for a key identifier chosen by the application. */ #define PSA_KEY_ID_USER_MIN ((psa_key_id_t)0x00000001) diff --git a/library/aesni.c b/library/aesni.c index 996292ff6..4b16d9250 100644 --- a/library/aesni.c +++ b/library/aesni.c @@ -36,9 +36,11 @@ #include <string.h> +/* *INDENT-OFF* */ #ifndef asm #define asm __asm #endif +/* *INDENT-ON* */ #if defined(MBEDTLS_HAVE_X86_64) diff --git a/library/bignum.c b/library/bignum.c index 37193f55a..32038f8eb 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -1559,9 +1559,9 @@ static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, */ if( 0 == d || u1 >= d ) { - if (r != NULL) *r = ~0; + if (r != NULL) *r = ~(mbedtls_mpi_uint)0u; - return ( ~0 ); + return ( ~(mbedtls_mpi_uint)0u ); } #if defined(MBEDTLS_HAVE_UDBL) @@ -1700,7 +1700,7 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, for( i = n; i > t ; i-- ) { if( X.p[i] >= Y.p[t] ) - Z.p[i - t - 1] = ~0; + Z.p[i - t - 1] = ~(mbedtls_mpi_uint)0u; else { Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], diff --git a/library/entropy.c b/library/entropy.c index e3b337ff3..77e2bfdd5 100644 --- a/library/entropy.c +++ b/library/entropy.c @@ -590,7 +590,7 @@ static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf } /* - * A test to ensure hat the entropy sources are functioning correctly + * A test to ensure that the entropy sources are functioning correctly * and there is no obvious failure. The test performs the following checks: * - The entropy source is not providing only 0s (all bits unset) or 1s (all * bits set). diff --git a/library/padlock.c b/library/padlock.c index 837337413..12ea2472d 100644 --- a/library/padlock.c +++ b/library/padlock.c @@ -31,9 +31,11 @@ #include <string.h> +/* *INDENT-OFF* */ #ifndef asm #define asm __asm #endif +/* *INDENT-ON* */ #if defined(MBEDTLS_HAVE_X86) diff --git a/library/psa_crypto_aead.h b/library/psa_crypto_aead.h index aab0f835c..e18e85d1c 100644 --- a/library/psa_crypto_aead.h +++ b/library/psa_crypto_aead.h @@ -148,4 +148,4 @@ psa_status_t mbedtls_psa_aead_decrypt( const uint8_t *ciphertext, size_t ciphertext_length, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length ); -#endif /* PSA_CRYPTO_AEAD */ +#endif /* PSA_CRYPTO_AEAD_H */ diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index c455ecb93..c9b86fe81 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -275,7 +275,7 @@ psa_status_t psa_driver_wrapper_sign_hash( alg, hash, hash_length, signature, signature_size, signature_length ) ); } -#endif /* PSA_CRYPTO_SE_C */ +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = @@ -359,7 +359,7 @@ psa_status_t psa_driver_wrapper_verify_hash( alg, hash, hash_length, signature, signature_length ) ); } -#endif /* PSA_CRYPTO_SE_C */ +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = @@ -579,7 +579,7 @@ psa_status_t psa_driver_wrapper_import_key( return( PSA_SUCCESS ); } -#endif /* PSA_CRYPTO_SE_C */ +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ switch( location ) { @@ -641,7 +641,7 @@ psa_status_t psa_driver_wrapper_export_key( *( (psa_key_slot_number_t *)key_buffer ), data, data_size, data_length ) ); } -#endif /* PSA_CRYPTO_SE_C */ +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ switch( location ) { diff --git a/library/psa_crypto_its.h b/library/psa_crypto_its.h index 3a3f49a72..90e761237 100644 --- a/library/psa_crypto_its.h +++ b/library/psa_crypto_its.h @@ -54,11 +54,6 @@ struct psa_storage_info_t /** Flag indicating that \ref psa_storage_create and \ref psa_storage_set_extended are supported */ #define PSA_STORAGE_SUPPORT_SET_EXTENDED (1 << 0) -/** \brief PSA storage specific error codes - */ -#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) -#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) - #define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the PSA ITS API. It will be incremented on significant updates that may include breaking changes */ #define PSA_ITS_API_VERSION_MINOR 1 /**< The minor version number of the PSA ITS API. It will be incremented in small updates that are unlikely to include breaking changes */ @@ -73,7 +68,7 @@ struct psa_storage_info_t * \return A status indicating the success/failure of the operation * * \retval #PSA_SUCCESS The operation completed successfully - * \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided `uid` value was already created with PSA_STORAGE_WRITE_ONCE_FLAG + * \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided `uid` value was already created with PSA_STORAGE_FLAG_WRITE_ONCE * \retval #PSA_ERROR_NOT_SUPPORTED The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid * \retval #PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium * \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) @@ -137,7 +132,7 @@ psa_status_t psa_its_get_info(psa_storage_uid_t uid, * * \retval #PSA_SUCCESS The operation completed successfully * \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided key value was not found in the storage - * \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided key value was created with PSA_STORAGE_WRITE_ONCE_FLAG + * \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided key value was created with PSA_STORAGE_FLAG_WRITE_ONCE * \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) */ psa_status_t psa_its_remove(psa_storage_uid_t uid); diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 0563c0b59..8efccce55 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -1363,10 +1363,23 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) for( i = 0; ciphersuites[i] != 0; i++ ) + { + if( p[0] != 0 || + MBEDTLS_GET_UINT16_BE(p, 1) != ciphersuites[i] ) + continue; + + got_common_suite = 1; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite_v2; + } #else for( i = 0; ciphersuites[i] != 0; i++ ) for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) -#endif { if( p[0] != 0 || MBEDTLS_GET_UINT16_BE(p, 1) != ciphersuites[i] ) @@ -1381,6 +1394,7 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) if( ciphersuite_info != NULL ) goto have_ciphersuite_v2; } +#endif if( got_common_suite ) { @@ -2233,10 +2247,22 @@ read_record_header: #if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) for( i = 0; ciphersuites[i] != 0; i++ ) + { + if( MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i] ) + continue; + + got_common_suite = 1; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite; + } #else for( i = 0; ciphersuites[i] != 0; i++ ) for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) -#endif { if( MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i] ) continue; @@ -2250,6 +2276,7 @@ read_record_header: if( ciphersuite_info != NULL ) goto have_ciphersuite; } +#endif if( got_common_suite ) { diff --git a/library/timing.c b/library/timing.c index 6c14a4fd0..7f559bebd 100644 --- a/library/timing.c +++ b/library/timing.c @@ -33,9 +33,11 @@ #error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h" #endif +/* *INDENT-OFF* */ #ifndef asm #define asm __asm #endif +/* *INDENT-ON* */ #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) @@ -223,7 +225,7 @@ unsigned long mbedtls_timing_hardclock( void ) } gettimeofday( &tv_cur, NULL ); - return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 + return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000U + ( tv_cur.tv_usec - tv_init.tv_usec ) ); } #endif /* !HAVE_HARDCLOCK */
diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h index 02421e4c8..aa155d7bf 100644 --- a/include/mbedtls/cipher.h +++ b/include/mbedtls/cipher.h @@ -83,16 +83,16 @@ extern "C" { /** * \brief Supported cipher types. * - * \warning RC4 and DES are considered weak ciphers and their use - * constitutes a security risk. Arm recommends considering stronger + * \warning RC4 and DES/3DES are considered weak ciphers and their use + * constitutes a security risk. We recommend considering stronger * ciphers instead. */ typedef enum { MBEDTLS_CIPHER_ID_NONE = 0, /**< Placeholder to mark the end of cipher ID lists. */ MBEDTLS_CIPHER_ID_NULL, /**< The identity cipher, treated as a stream cipher. */ MBEDTLS_CIPHER_ID_AES, /**< The AES cipher. */ - MBEDTLS_CIPHER_ID_DES, /**< The DES cipher. */ - MBEDTLS_CIPHER_ID_3DES, /**< The Triple DES cipher. */ + MBEDTLS_CIPHER_ID_DES, /**< The DES cipher. \warning DES is considered weak. */ + MBEDTLS_CIPHER_ID_3DES, /**< The Triple DES cipher. \warning 3DES is considered weak. */ MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ MBEDTLS_CIPHER_ID_BLOWFISH, /**< The Blowfish cipher. */ MBEDTLS_CIPHER_ID_ARC4, /**< The RC4 cipher. */ @@ -103,8 +103,8 @@ typedef enum { /** * \brief Supported {cipher type, cipher mode} pairs. * - * \warning RC4 and DES are considered weak ciphers and their use - * constitutes a security risk. Arm recommends considering stronger + * \warning RC4 and DES/3DES are considered weak ciphers and their use + * constitutes a security risk. We recommend considering stronger * ciphers instead. */ typedef enum { @@ -140,12 +140,12 @@ typedef enum { MBEDTLS_CIPHER_CAMELLIA_128_GCM, /**< Camellia cipher with 128-bit GCM mode. */ MBEDTLS_CIPHER_CAMELLIA_192_GCM, /**< Camellia cipher with 192-bit GCM mode. */ MBEDTLS_CIPHER_CAMELLIA_256_GCM, /**< Camellia cipher with 256-bit GCM mode. */ - MBEDTLS_CIPHER_DES_ECB, /**< DES cipher with ECB mode. */ - MBEDTLS_CIPHER_DES_CBC, /**< DES cipher with CBC mode. */ - MBEDTLS_CIPHER_DES_EDE_ECB, /**< DES cipher with EDE ECB mode. */ - MBEDTLS_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. */ - MBEDTLS_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. */ - MBEDTLS_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. */ + MBEDTLS_CIPHER_DES_ECB, /**< DES cipher with ECB mode. \warning DES is considered weak. */ + MBEDTLS_CIPHER_DES_CBC, /**< DES cipher with CBC mode. \warning DES is considered weak. */ + MBEDTLS_CIPHER_DES_EDE_ECB, /**< DES cipher with EDE ECB mode. \warning 3DES is considered weak. */ + MBEDTLS_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. \warning 3DES is considered weak. */ + MBEDTLS_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. \warning 3DES is considered weak. */ + MBEDTLS_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. \warning 3DES is considered weak. */ MBEDTLS_CIPHER_BLOWFISH_ECB, /**< Blowfish cipher with ECB mode. */ MBEDTLS_CIPHER_BLOWFISH_CBC, /**< Blowfish cipher with CBC mode. */ MBEDTLS_CIPHER_BLOWFISH_CFB64, /**< Blowfish cipher with CFB64 mode. */ @@ -226,11 +226,11 @@ typedef enum { enum { /** Undefined key length. */ MBEDTLS_KEY_LENGTH_NONE = 0, - /** Key length, in bits (including parity), for DES keys. */ + /** Key length, in bits (including parity), for DES keys. \warning DES is considered weak. */ MBEDTLS_KEY_LENGTH_DES = 64, - /** Key length in bits, including parity, for DES in two-key EDE. */ + /** Key length in bits, including parity, for DES in two-key EDE. \warning 3DES is considered weak. */ MBEDTLS_KEY_LENGTH_DES_EDE = 128, - /** Key length in bits, including parity, for DES in three-key EDE. */ + /** Key length in bits, including parity, for DES in three-key EDE. \warning 3DES is considered weak. */ MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, }; diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 9a2de676d..5dcbdd1dd 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -2765,7 +2765,7 @@ * * PEM_PARSE uses DES/3DES for decrypting encrypted keys. * - * \warning DES is considered a weak cipher and its use constitutes a + * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers instead. */ #define MBEDTLS_DES_C diff --git a/include/mbedtls/des.h b/include/mbedtls/des.h index 2944d5cf1..f2bc58138 100644 --- a/include/mbedtls/des.h +++ b/include/mbedtls/des.h @@ -3,7 +3,7 @@ * * \brief DES block cipher * - * \warning DES is considered a weak cipher and its use constitutes a + * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ @@ -60,7 +60,7 @@ extern "C" { /** * \brief DES context structure * - * \warning DES is considered a weak cipher and its use constitutes a + * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ @@ -71,6 +71,10 @@ mbedtls_des_context; /** * \brief Triple-DES context structure + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ typedef struct mbedtls_des3_context { uint32_t sk[96]; /*!< 3DES subkeys */ @@ -86,7 +90,7 @@ mbedtls_des3_context; * * \param ctx DES context to be initialized * - * \warning DES is considered a weak cipher and its use constitutes a + * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ @@ -97,7 +101,7 @@ void mbedtls_des_init(mbedtls_des_context *ctx); * * \param ctx DES context to be cleared * - * \warning DES is considered a weak cipher and its use constitutes a + * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ @@ -107,6 +111,10 @@ void mbedtls_des_free(mbedtls_des_context *ctx); * \brief Initialize Triple-DES context * * \param ctx DES3 context to be initialized + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ void mbedtls_des3_init(mbedtls_des3_context *ctx); @@ -114,6 +122,10 @@ void mbedtls_des3_init(mbedtls_des3_context *ctx); * \brief Clear Triple-DES context * * \param ctx DES3 context to be cleared + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ void mbedtls_des3_free(mbedtls_des3_context *ctx); @@ -125,7 +137,7 @@ void mbedtls_des3_free(mbedtls_des3_context *ctx); * * \param key 8-byte secret key * - * \warning DES is considered a weak cipher and its use constitutes a + * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ @@ -141,7 +153,7 @@ void mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE]); * * \return 0 is parity was ok, 1 if parity was not correct. * - * \warning DES is considered a weak cipher and its use constitutes a + * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ @@ -155,7 +167,7 @@ int mbedtls_des_key_check_key_parity(const unsigned char key[MBEDTLS_DES_KEY_SIZ * * \return 0 if no weak key was found, 1 if a weak key was identified. * - * \warning DES is considered a weak cipher and its use constitutes a + * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ @@ -170,7 +182,7 @@ int mbedtls_des_key_check_weak(const unsigned char key[MBEDTLS_DES_KEY_SIZE]); * * \return 0 * - * \warning DES is considered a weak cipher and its use constitutes a + * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ @@ -185,7 +197,7 @@ int mbedtls_des_setkey_enc(mbedtls_des_context *ctx, const unsigned char key[MBE * * \return 0 * - * \warning DES is considered a weak cipher and its use constitutes a + * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ @@ -199,6 +211,10 @@ int mbedtls_des_setkey_dec(mbedtls_des_context *ctx, const unsigned char key[MBE * \param key 16-byte secret key * * \return 0 + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_set2key_enc(mbedtls_des3_context *ctx, @@ -211,6 +227,10 @@ int mbedtls_des3_set2key_enc(mbedtls_des3_context *ctx, * \param key 16-byte secret key * * \return 0 + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_set2key_dec(mbedtls_des3_context *ctx, @@ -223,6 +243,10 @@ int mbedtls_des3_set2key_dec(mbedtls_des3_context *ctx, * \param key 24-byte secret key * * \return 0 + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_set3key_enc(mbedtls_des3_context *ctx, @@ -235,6 +259,10 @@ int mbedtls_des3_set3key_enc(mbedtls_des3_context *ctx, * \param key 24-byte secret key * * \return 0 + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_set3key_dec(mbedtls_des3_context *ctx, @@ -249,7 +277,7 @@ int mbedtls_des3_set3key_dec(mbedtls_des3_context *ctx, * * \return 0 if successful * - * \warning DES is considered a weak cipher and its use constitutes a + * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ @@ -277,7 +305,7 @@ int mbedtls_des_crypt_ecb(mbedtls_des_context *ctx, * \param input buffer holding the input data * \param output buffer holding the output data * - * \warning DES is considered a weak cipher and its use constitutes a + * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ @@ -298,6 +326,10 @@ int mbedtls_des_crypt_cbc(mbedtls_des_context *ctx, * \param output 64-bit output block * * \return 0 if successful + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_crypt_ecb(mbedtls_des3_context *ctx, @@ -324,6 +356,10 @@ int mbedtls_des3_crypt_ecb(mbedtls_des3_context *ctx, * \param output buffer holding the output data * * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH + * + * \warning DES/3DES are considered weak ciphers and their use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx, @@ -342,7 +378,7 @@ int mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx, * \param SK Round keys * \param key Base key * - * \warning DES is considered a weak cipher and its use constitutes a + * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ diff --git a/library/Makefile b/library/Makefile index 3b91e2556..b011e8873 100644 --- a/library/Makefile +++ b/library/Makefile @@ -186,6 +186,13 @@ else all: shared static endif +ifdef TEST_TIMING_ALT_IMPL +OBJS_CRYPTO += external_timing_for_test.o +external_timing_for_test.o: ../tests/src/external_timing/external_timing_for_test.c + echo " CC $<" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $< +endif + static: libmbedcrypto.a libmbedx509.a libmbedtls.a cd ../tests && echo "This is a seedfile that contains 64 bytes (65 on Windows)......" > seedfile diff --git a/library/bignum.c b/library/bignum.c index 5ec0541e8..d915ade63 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -1280,7 +1280,7 @@ int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi /* Set the high limbs of X to match A. Don't touch the lower limbs * because X might be aliased to B, and we must not overwrite the * significant digits of B. */ - if (A->n > n) { + if (A->n > n && A != X) { memcpy(X->p + n, A->p + n, (A->n - n) * ciL); } if (X->n > A->n) { @@ -2063,6 +2063,7 @@ int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A, size_t window_bitsize; size_t i, j, nblimbs; size_t bufsize, nbits; + size_t exponent_bits_in_window = 0; mbedtls_mpi_uint ei, mm, state; mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos; int neg; @@ -2236,7 +2237,6 @@ int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A, nblimbs = E->n; bufsize = 0; nbits = 0; - size_t exponent_bits_in_window = 0; state = 0; while (1) { diff --git a/library/ccm.c b/library/ccm.c index 82c308aa8..2d2695e97 100644 --- a/library/ccm.c +++ b/library/ccm.c @@ -478,7 +478,7 @@ int mbedtls_ccm_self_test(int verbose) mbedtls_ccm_init(&ctx); if (mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key_test_data, - 8 * sizeof key_test_data) != 0) { + 8 * sizeof(key_test_data)) != 0) { if (verbose != 0) { mbedtls_printf(" CCM: setup failed"); } diff --git a/library/ecp.c b/library/ecp.c index a029c2206..9051490b1 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -163,7 +163,8 @@ static int ecp_drbg_seed(ecp_drbg_context *ctx, int ret; unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES]; /* The list starts with strong hashes */ - const mbedtls_md_type_t md_type = mbedtls_md_list()[0]; + const mbedtls_md_type_t md_type = + (const mbedtls_md_type_t) (mbedtls_md_list()[0]); const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type); if (secret_len > MBEDTLS_ECP_MAX_BYTES) { @@ -2062,12 +2063,13 @@ static int ecp_mul_comb_core(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, } else #endif { + int have_rng = 1; + /* Start with a non-zero point and randomize its coordinates */ i = d; MBEDTLS_MPI_CHK(ecp_select_comb(grp, R, T, T_size, x[i])); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&R->Z, 1)); - int have_rng = 1; #if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) if (f_rng == NULL) { have_rng = 0; @@ -2172,6 +2174,7 @@ static int ecp_mul_comb_after_precomp(const mbedtls_ecp_group *grp, unsigned char parity_trick; unsigned char k[COMB_MAX_D + 1]; mbedtls_ecp_point *RR = R; + int have_rng = 1; #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { @@ -2208,7 +2211,6 @@ final_norm: * * Avoid the leak by randomizing coordinates before we normalize them. */ - int have_rng = 1; #if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) if (f_rng == NULL) { have_rng = 0; diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 8a9f79e2e..6ce4f64c1 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -533,7 +533,7 @@ static const mbedtls_mpi_uint brainpoolP512r1_n[] = { #if defined(ECP_LOAD_GROUP) /* * Create an MPI from embedded constants - * (assumes len is an exact multiple of sizeof mbedtls_mpi_uint) + * (assumes len is an exact multiple of sizeof(mbedtls_mpi_uint)) */ static inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len) { @@ -1252,7 +1252,7 @@ static int ecp_mod_p255(mbedtls_mpi *N) return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } M.p = Mp; - memset(Mp, 0, sizeof Mp); + memset(Mp, 0, sizeof(Mp)); memcpy(Mp, N->p + P255_WIDTH - 1, M.n * sizeof(mbedtls_mpi_uint)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, 255 % (8 * sizeof(mbedtls_mpi_uint)))); M.n++; /* Make room for multiplication by 19 */ @@ -1386,7 +1386,7 @@ static inline int ecp_mod_koblitz(mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p if (M.n > p_limbs + adjust) { M.n = p_limbs + adjust; } - memset(Mp, 0, sizeof Mp); + memset(Mp, 0, sizeof(Mp)); memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint)); if (shift != 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, shift)); @@ -1412,7 +1412,7 @@ static inline int ecp_mod_koblitz(mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p if (M.n > p_limbs + adjust) { M.n = p_limbs + adjust; } - memset(Mp, 0, sizeof Mp); + memset(Mp, 0, sizeof(Mp)); memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint)); if (shift != 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, shift)); diff --git a/library/entropy.c b/library/entropy.c index 1a4ac9645..af78acc1b 100644 --- a/library/entropy.c +++ b/library/entropy.c @@ -706,7 +706,7 @@ int mbedtls_entropy_self_test(int verbose) goto cleanup; } - if ((ret = mbedtls_entropy_update_manual(&ctx, buf, sizeof buf)) != 0) { + if ((ret = mbedtls_entropy_update_manual(&ctx, buf, sizeof(buf))) != 0) { goto cleanup; } diff --git a/library/oid.c b/library/oid.c index fcff15273..4ec752fb9 100644 --- a/library/oid.c +++ b/library/oid.c @@ -796,21 +796,55 @@ int mbedtls_oid_get_numeric_string(char *buf, size_t size, p = buf; n = size; - /* First byte contains first two dots */ - if (oid->len > 0) { - ret = mbedtls_snprintf(p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40); - OID_SAFE_SNPRINTF; + /* First subidentifier contains first two OID components */ + i = 0; + value = 0; + if ((oid->p[0]) == 0x80) { + /* Overlong encoding is not allowed */ + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + + while (i < oid->len && ((oid->p[i] & 0x80) != 0)) { + /* Prevent overflow in value. */ + if (value > (UINT_MAX >> 7)) { + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + + value |= oid->p[i] & 0x7F; + value <<= 7; + i++; + } + if (i >= oid->len) { + return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } + /* Last byte of first subidentifier */ + value |= oid->p[i] & 0x7F; + i++; + + unsigned int component1 = value / 40; + if (component1 > 2) { + /* The first component can only be 0, 1 or 2. + * If oid->p[0] / 40 is greater than 2, the leftover belongs to + * the second component. */ + component1 = 2; + } + unsigned int component2 = value - (40 * component1); + ret = mbedtls_snprintf(p, n, "%u.%u", component1, component2); + OID_SAFE_SNPRINTF; value = 0; - for (i = 1; i < oid->len; i++) { + for (; i < oid->len; i++) { /* Prevent overflow in value. */ - if (((value << 7) >> 7) != value) { - return MBEDTLS_ERR_OID_BUF_TOO_SMALL; + if (value > (UINT_MAX >> 7)) { + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + if ((value == 0) && ((oid->p[i]) == 0x80)) { + /* Overlong encoding is not allowed */ + return MBEDTLS_ERR_ASN1_INVALID_DATA; } value <<= 7; - value += oid->p[i] & 0x7F; + value |= oid->p[i] & 0x7F; if (!(oid->p[i] & 0x80)) { /* Last byte */ diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index 48ad6d5fb..615638533 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -1060,8 +1060,9 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( } return status; -#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ +#else /* MBEDTLS_PSA_BUILTIN_CIPHER */ return PSA_ERROR_NOT_SUPPORTED; +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) diff --git a/library/ripemd160.c b/library/ripemd160.c index f5dc5f59e..a2e11cdf0 100644 --- a/library/ripemd160.c +++ b/library/ripemd160.c @@ -496,7 +496,7 @@ int mbedtls_ripemd160_self_test(int verbose) int i, ret = 0; unsigned char output[20]; - memset(output, 0, sizeof output); + memset(output, 0, sizeof(output)); for (i = 0; i < TESTS; i++) { if (verbose != 0) { diff --git a/library/timing.c b/library/timing.c index d4f9554ee..47e34f922 100644 --- a/library/timing.c +++ b/library/timing.c @@ -352,9 +352,9 @@ int mbedtls_timing_get_delay(void *data) return 0; } +#endif /* !MBEDTLS_TIMING_ALT */ #if defined(MBEDTLS_SELF_TEST) - /* * Busy-waits for the given number of milliseconds. * Used for testing mbedtls_timing_hardclock. @@ -383,9 +383,8 @@ static void busy_msleep(unsigned long msec) mbedtls_printf(" cycles=%lu ratio=%lu millisecs=%lu secs=%lu hardfail=%d a=%lu b=%lu\n", \ cycles, ratio, millisecs, secs, hardfail, \ (unsigned long) a, (unsigned long) b); \ - mbedtls_printf(" elapsed(hires)=%lu elapsed(ctx)=%lu status(ctx)=%d\n", \ + mbedtls_printf(" elapsed(hires)=%lu status(ctx)=%d\n", \ mbedtls_timing_get_timer(&hires, 0), \ - mbedtls_timing_get_timer(&ctx.timer, 0), \ mbedtls_timing_get_delay(&ctx)); \ } \ return 1; \ @@ -526,5 +525,4 @@ hard_test_done: } #endif /* MBEDTLS_SELF_TEST */ -#endif /* !MBEDTLS_TIMING_ALT */ #endif /* MBEDTLS_TIMING_C */ diff --git a/library/x509_crt.c b/library/x509_crt.c index 9ea96b0aa..e7fcaf462 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -639,8 +639,6 @@ static int x509_get_subject_alt_name(unsigned char **p, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len, tag_len; - mbedtls_asn1_buf *buf; - unsigned char tag; mbedtls_asn1_sequence *cur = subject_alt_name; /* Get main sequence tag */ @@ -656,15 +654,20 @@ static int x509_get_subject_alt_name(unsigned char **p, while (*p < end) { mbedtls_x509_subject_alternative_name dummy_san_buf; + mbedtls_x509_buf tmp_san_buf; memset(&dummy_san_buf, 0, sizeof(dummy_san_buf)); - tag = **p; + tmp_san_buf.tag = **p; (*p)++; + if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } - if ((tag & MBEDTLS_ASN1_TAG_CLASS_MASK) != + tmp_san_buf.p = *p; + tmp_san_buf.len = tag_len; + + if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) != MBEDTLS_ASN1_CONTEXT_SPECIFIC) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); @@ -673,7 +676,7 @@ static int x509_get_subject_alt_name(unsigned char **p, /* * Check that the SAN is structured correctly. */ - ret = mbedtls_x509_parse_subject_alt_name(&(cur->buf), &dummy_san_buf); + ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, &dummy_san_buf); /* * In case the extension is malformed, return an error, * and clear the allocated sequences. @@ -708,11 +711,8 @@ static int x509_get_subject_alt_name(unsigned char **p, cur = cur->next; } - buf = &(cur->buf); - buf->tag = tag; - buf->p = *p; - buf->len = tag_len; - *p += buf->len; + cur->buf = tmp_san_buf; + *p += tmp_san_buf.len; } /* Set final sequence entry's next pointer to NULL */ @@ -1601,8 +1601,8 @@ int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path) } w_ret = WideCharToMultiByte(CP_ACP, 0, file_data.cFileName, - lstrlenW(file_data.cFileName), - p, (int) len - 1, + -1, + p, (int) len, NULL, NULL); if (w_ret == 0) { ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; @@ -1645,10 +1645,10 @@ cleanup: memset(&sb, 0, sizeof(sb)); while ((entry = readdir(dir)) != NULL) { - snp_ret = mbedtls_snprintf(entry_name, sizeof entry_name, + snp_ret = mbedtls_snprintf(entry_name, sizeof(entry_name), "%s/%s", path, entry->d_name); - if (snp_ret < 0 || (size_t) snp_ret >= sizeof entry_name) { + if (snp_ret < 0 || (size_t) snp_ret >= sizeof(entry_name)) { ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; goto cleanup; } else if (stat(entry_name, &sb) == -1) { @@ -1742,11 +1742,6 @@ static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name, return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } - if (p + len >= end) { - mbedtls_platform_zeroize(other_name, sizeof(*other_name)); - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } p += len; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != @@ -1754,11 +1749,21 @@ static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name, return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } + if (end != p + len) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } + if (end != p + len) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } @@ -1767,11 +1772,6 @@ static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name, other_name->value.hardware_module_name.oid.p = p; other_name->value.hardware_module_name.oid.len = len; - if (p + len >= end) { - mbedtls_platform_zeroize(other_name, sizeof(*other_name)); - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } p += len; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { @@ -1783,8 +1783,6 @@ static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name, other_name->value.hardware_module_name.val.len = len; p += len; if (p != end) { - mbedtls_platform_zeroize(other_name, - sizeof(*other_name)); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); }
diff --git a/include/mbedtls/aesni.h b/include/mbedtls/aesni.h index 653b146e7..6741dead0 100644 --- a/include/mbedtls/aesni.h +++ b/include/mbedtls/aesni.h @@ -36,13 +36,49 @@ #define MBEDTLS_AESNI_AES 0x02000000u #define MBEDTLS_AESNI_CLMUL 0x00000002u -#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \ +/* Can we do AESNI with inline assembly? + * (Only implemented with gas syntax, only for 64-bit.) + */ +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \ (defined(__amd64__) || defined(__x86_64__)) && \ !defined(MBEDTLS_HAVE_X86_64) #define MBEDTLS_HAVE_X86_64 #endif +#if defined(MBEDTLS_AESNI_C) + +/* Can we do AESNI with intrinsics? + * (Only implemented with certain compilers, only for certain targets.) + * + * NOTE: MBEDTLS_AESNI_HAVE_INTRINSICS and MBEDTLS_AESNI_HAVE_CODE are internal + * macros that may change in future releases. + */ +#undef MBEDTLS_AESNI_HAVE_INTRINSICS +#if defined(_MSC_VER) +/* Visual Studio supports AESNI intrinsics since VS 2008 SP1. We only support + * VS 2013 and up for other reasons anyway, so no need to check the version. */ +#define MBEDTLS_AESNI_HAVE_INTRINSICS +#endif +/* GCC-like compilers: currently, we only support intrinsics if the requisite + * target flag is enabled when building the library (e.g. `gcc -mpclmul -msse2` + * or `clang -maes -mpclmul`). */ +#if defined(__GNUC__) && defined(__AES__) && defined(__PCLMUL__) +#define MBEDTLS_AESNI_HAVE_INTRINSICS +#endif + +/* Choose the implementation of AESNI, if one is available. */ +#undef MBEDTLS_AESNI_HAVE_CODE +/* To minimize disruption when releasing the intrinsics-based implementation, + * favor the assembly-based implementation if it's available. We intend to + * revise this in a later release of Mbed TLS 3.x. In the long run, we will + * likely remove the assembly implementation. */ #if defined(MBEDTLS_HAVE_X86_64) +#define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly +#elif defined(MBEDTLS_AESNI_HAVE_INTRINSICS) +#define MBEDTLS_AESNI_HAVE_CODE 2 // via intrinsics +#endif + +#if defined(MBEDTLS_AESNI_HAVE_CODE) #ifdef __cplusplus extern "C" { @@ -131,6 +167,7 @@ int mbedtls_aesni_setkey_enc(unsigned char *rk, } #endif -#endif /* MBEDTLS_HAVE_X86_64 */ +#endif /* MBEDTLS_AESNI_HAVE_CODE */ +#endif /* MBEDTLS_AESNI_C */ #endif /* MBEDTLS_AESNI_H */ diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 2ab99823e..2cb36e9e1 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -69,10 +69,6 @@ #error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" #endif -#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM) -#error "MBEDTLS_AESNI_C defined, but not all prerequisites" -#endif - #if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) #error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" #endif diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 1e4d95e0c..1381c1fd1 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -51,7 +51,7 @@ * include/mbedtls/bn_mul.h * * Required by: - * MBEDTLS_AESNI_C + * MBEDTLS_AESNI_C (on some platforms) * MBEDTLS_PADLOCK_C * * Comment to disable the use of assembly code. @@ -871,7 +871,7 @@ * - Changes the behaviour of TLS 1.2 clients (not servers) when using the * ECDHE-ECDSA key exchange (not other key exchanges) to make all ECC * computations restartable: - * - ECDH operations from the key exchange, only for Short Weierstass + * - ECDH operations from the key exchange, only for Short Weierstrass * curves; * - verification of the server's key exchange signature; * - verification of the server's certificate chain; @@ -2344,14 +2344,32 @@ /** * \def MBEDTLS_AESNI_C * - * Enable AES-NI support on x86-64. + * Enable AES-NI support on x86-64 or x86-32. + * + * \note AESNI is only supported with certain compilers and target options: + * - Visual Studio 2013: supported. + * - GCC, x86-64, target not explicitly supporting AESNI: + * requires MBEDTLS_HAVE_ASM. + * - GCC, x86-32, target not explicitly supporting AESNI: + * not supported. + * - GCC, x86-64 or x86-32, target supporting AESNI: supported. + * For this assembly-less implementation, you must currently compile + * `library/aesni.c` and `library/aes.c` with machine options to enable + * SSE2 and AESNI instructions: `gcc -msse2 -maes -mpclmul` or + * `clang -maes -mpclmul`. + * - Non-x86 targets: this option is silently ignored. + * - Other compilers: this option is silently ignored. + * + * \note + * Above, "GCC" includes compatible compilers such as Clang. + * The limitations on target support are likely to be relaxed in the future. * * Module: library/aesni.c * Caller: library/aes.c * - * Requires: MBEDTLS_HAVE_ASM + * Requires: MBEDTLS_HAVE_ASM (on some platforms, see note) * - * This modules adds support for the AES-NI instructions on x86-64 + * This modules adds support for the AES-NI instructions on x86. */ #define MBEDTLS_AESNI_C diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h index a226e7173..ec8355136 100644 --- a/include/mbedtls/pk.h +++ b/include/mbedtls/pk.h @@ -402,6 +402,11 @@ int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type); * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) * to verify RSASSA_PSS signatures. * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function, + * if the key might be an ECC (ECDSA) key. + * * \note If hash_len is 0, then the length associated with md_alg * is used instead, or an error returned if it is invalid. * diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 7836ecec6..26e4ec400 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -1544,6 +1544,10 @@ void mbedtls_ssl_init(mbedtls_ssl_context *ssl); * Calling mbedtls_ssl_setup again is not supported, even * if no session is active. * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * * \param ssl SSL context * \param conf SSL configuration to use * @@ -3980,6 +3984,10 @@ int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl, mbedtls_ssl_session * in which case the datagram of the underlying transport that is * currently being processed might or might not contain further * DTLS records. + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. */ int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl); diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h index 1324eaebe..0ef52138f 100644 --- a/include/mbedtls/version.h +++ b/include/mbedtls/version.h @@ -38,16 +38,16 @@ */ #define MBEDTLS_VERSION_MAJOR 2 #define MBEDTLS_VERSION_MINOR 28 -#define MBEDTLS_VERSION_PATCH 2 +#define MBEDTLS_VERSION_PATCH 3 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x021C0200 -#define MBEDTLS_VERSION_STRING "2.28.2" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.28.2" +#define MBEDTLS_VERSION_NUMBER 0x021C0300 +#define MBEDTLS_VERSION_STRING "2.28.3" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.28.3" #if defined(MBEDTLS_VERSION_C) diff --git a/include/mbedtls/x509_crl.h b/include/mbedtls/x509_crl.h index 895eca0d6..140502140 100644 --- a/include/mbedtls/x509_crl.h +++ b/include/mbedtls/x509_crl.h @@ -95,6 +95,10 @@ mbedtls_x509_crl; /** * \brief Parse a DER-encoded CRL and append it to the chained list * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * * \param chain points to the start of the chain * \param buf buffer holding the CRL data in DER format * \param buflen size of the buffer @@ -109,6 +113,10 @@ int mbedtls_x509_crl_parse_der(mbedtls_x509_crl *chain, * * \note Multiple CRLs are accepted only if using PEM format * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * * \param chain points to the start of the chain * \param buf buffer holding the CRL data in PEM or DER format * \param buflen size of the buffer @@ -124,6 +132,10 @@ int mbedtls_x509_crl_parse(mbedtls_x509_crl *chain, const unsigned char *buf, si * * \note Multiple CRLs are accepted only if using PEM format * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * * \param chain points to the start of the chain * \param path filename to read the CRLs from (in PEM or DER encoding) * diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 235e00c06..466611f79 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -283,6 +283,10 @@ extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; * \brief Parse a single DER formatted certificate and add it * to the end of the provided chained list. * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * * \param chain The pointer to the start of the CRT chain to attach to. * When parsing the first CRT in a chain, this should point * to an instance of ::mbedtls_x509_crt initialized through @@ -344,6 +348,10 @@ typedef int (*mbedtls_x509_crt_ext_cb_t)(void *p_ctx, * \brief Parse a single DER formatted certificate and add it * to the end of the provided chained list. * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * * \param chain The pointer to the start of the CRT chain to attach to. * When parsing the first CRT in a chain, this should point * to an instance of ::mbedtls_x509_crt initialized through @@ -394,6 +402,10 @@ int mbedtls_x509_crt_parse_der_with_ext_cb(mbedtls_x509_crt *chain, * temporary ownership of the CRT buffer until the CRT * is destroyed. * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * * \param chain The pointer to the start of the CRT chain to attach to. * When parsing the first CRT in a chain, this should point * to an instance of ::mbedtls_x509_crt initialized through @@ -434,6 +446,10 @@ int mbedtls_x509_crt_parse_der_nocopy(mbedtls_x509_crt *chain, * long as the certificates are enclosed in the PEM specific * '-----{BEGIN/END} CERTIFICATE-----' delimiters. * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * * \param chain The chain to which to add the parsed certificates. * \param buf The buffer holding the certificate data in PEM or DER format. * For certificates in PEM encoding, this may be a concatenation @@ -458,6 +474,10 @@ int mbedtls_x509_crt_parse(mbedtls_x509_crt *chain, const unsigned char *buf, si * of failed certificates it encountered. If none complete * correctly, the first error is returned. * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * * \param chain points to the start of the chain * \param path filename to read the certificates from * diff --git a/include/mbedtls/x509_csr.h b/include/mbedtls/x509_csr.h index fa7ef04a2..5975584da 100644 --- a/include/mbedtls/x509_csr.h +++ b/include/mbedtls/x509_csr.h @@ -82,6 +82,10 @@ mbedtls_x509write_csr; * * \note CSR attributes (if any) are currently silently ignored. * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * * \param csr CSR context to fill * \param buf buffer holding the CRL data * \param buflen size of the buffer @@ -96,6 +100,10 @@ int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr, * * \note See notes for \c mbedtls_x509_csr_parse_der() * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * * \param csr CSR context to fill * \param buf buffer holding the CRL data * \param buflen size of the buffer diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index fd3a3e71c..553569ebd 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -204,15 +204,15 @@ endif(USE_STATIC_MBEDTLS_LIBRARY) if(USE_SHARED_MBEDTLS_LIBRARY) set(CMAKE_LIBRARY_PATH ${CMAKE_CURRENT_BINARY_DIR}) add_library(${mbedcrypto_target} SHARED ${src_crypto}) - set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 2.28.2 SOVERSION 7) + set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 2.28.3 SOVERSION 7) target_link_libraries(${mbedcrypto_target} PUBLIC ${libs}) add_library(${mbedx509_target} SHARED ${src_x509}) - set_target_properties(${mbedx509_target} PROPERTIES VERSION 2.28.2 SOVERSION 1) + set_target_properties(${mbedx509_target} PROPERTIES VERSION 2.28.3 SOVERSION 1) target_link_libraries(${mbedx509_target} PUBLIC ${libs} ${mbedcrypto_target}) add_library(${mbedtls_target} SHARED ${src_tls}) - set_target_properties(${mbedtls_target} PROPERTIES VERSION 2.28.2 SOVERSION 14) + set_target_properties(${mbedtls_target} PROPERTIES VERSION 2.28.3 SOVERSION 14) target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target}) endif(USE_SHARED_MBEDTLS_LIBRARY) diff --git a/library/aes.c b/library/aes.c index bcdf3c782..f08a21f59 100644 --- a/library/aes.c +++ b/library/aes.c @@ -50,8 +50,7 @@ #define AES_VALIDATE(cond) \ MBEDTLS_INTERNAL_VALIDATE(cond) -#if defined(MBEDTLS_PADLOCK_C) && \ - (defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16)) +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) static int aes_padlock_ace = -1; #endif @@ -512,6 +511,53 @@ void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx) } #endif /* MBEDTLS_CIPHER_MODE_XTS */ +/* Some implementations need the round keys to be aligned. + * Return an offset to be added to buf, such that (buf + offset) is + * correctly aligned. + * Note that the offset is in units of elements of buf, i.e. 32-bit words, + * i.e. an offset of 1 means 4 bytes and so on. + */ +#if (defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)) || \ + (defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2) +#define MAY_NEED_TO_ALIGN +#endif +static unsigned mbedtls_aes_rk_offset(uint32_t *buf) +{ +#if defined(MAY_NEED_TO_ALIGN) + int align_16_bytes = 0; + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if (aes_padlock_ace == -1) { + aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE); + } + if (aes_padlock_ace) { + align_16_bytes = 1; + } +#endif + +#if defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2 + if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { + align_16_bytes = 1; + } +#endif + + if (align_16_bytes) { + /* These implementations needs 16-byte alignment + * for the round key array. */ + unsigned delta = ((uintptr_t) buf & 0x0000000fU) / 4; + if (delta == 0) { + return 0; + } else { + return 4 - delta; // 16 bytes = 4 uint32_t + } + } +#else /* MAY_NEED_TO_ALIGN */ + (void) buf; +#endif /* MAY_NEED_TO_ALIGN */ + + return 0; +} + /* * AES key schedule (encryption) */ @@ -539,18 +585,9 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, } #endif -#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) - if (aes_padlock_ace == -1) { - aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE); - } - - if (aes_padlock_ace) { - ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16(ctx->buf); - } else -#endif - ctx->rk = RK = ctx->buf; + ctx->rk = RK = ctx->buf + mbedtls_aes_rk_offset(ctx->buf); -#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) +#if defined(MBEDTLS_AESNI_HAVE_CODE) if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { return mbedtls_aesni_setkey_enc((unsigned char *) ctx->rk, key, keybits); } @@ -640,16 +677,7 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, mbedtls_aes_init(&cty); -#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) - if (aes_padlock_ace == -1) { - aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE); - } - - if (aes_padlock_ace) { - ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16(ctx->buf); - } else -#endif - ctx->rk = RK = ctx->buf; + ctx->rk = RK = ctx->buf + mbedtls_aes_rk_offset(ctx->buf); /* Also checks keybits */ if ((ret = mbedtls_aes_setkey_enc(&cty, key, keybits)) != 0) { @@ -658,7 +686,7 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, ctx->nr = cty.nr; -#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) +#if defined(MBEDTLS_AESNI_HAVE_CODE) if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { mbedtls_aesni_inverse_key((unsigned char *) ctx->rk, (const unsigned char *) cty.rk, ctx->nr); @@ -964,6 +992,30 @@ void mbedtls_aes_decrypt(mbedtls_aes_context *ctx, } #endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#if defined(MAY_NEED_TO_ALIGN) +/* VIA Padlock and our intrinsics-based implementation of AESNI require + * the round keys to be aligned on a 16-byte boundary. We take care of this + * before creating them, but the AES context may have moved (this can happen + * if the library is called from a language with managed memory), and in later + * calls it might have a different alignment with respect to 16-byte memory. + * So we may need to realign. + * NOTE: In the LTS branch, the context contains a pointer to within itself, + * so if it has been moved, things will probably go pear-shaped. We keep this + * code for compatibility with the development branch, in case of future changes. + */ +static void aes_maybe_realign(mbedtls_aes_context *ctx) +{ + unsigned current_offset = (unsigned) (ctx->rk - ctx->buf); + unsigned new_offset = mbedtls_aes_rk_offset(ctx->buf); + if (new_offset != current_offset) { + memmove(ctx->buf + new_offset, // new address + ctx->buf + current_offset, // current address + (ctx->nr + 1) * 16); // number of round keys * bytes per rk + ctx->rk = ctx->buf + new_offset; + } +} +#endif + /* * AES-ECB block encryption/decryption */ @@ -978,7 +1030,11 @@ int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT || mode == MBEDTLS_AES_DECRYPT); -#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) +#if defined(MAY_NEED_TO_ALIGN) + aes_maybe_realign(ctx); +#endif + +#if defined(MBEDTLS_AESNI_HAVE_CODE) if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { return mbedtls_aesni_crypt_ecb(ctx, mode, input, output); } @@ -986,13 +1042,7 @@ int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, #if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) if (aes_padlock_ace) { - if (mbedtls_padlock_xcryptecb(ctx, mode, input, output) == 0) { - return 0; - } - - // If padlock data misaligned, we just fall back to - // unaccelerated mode - // + return mbedtls_padlock_xcryptecb(ctx, mode, input, output); } #endif @@ -1785,6 +1835,32 @@ int mbedtls_aes_self_test(int verbose) memset(key, 0, 32); mbedtls_aes_init(&ctx); + if (verbose != 0) { +#if defined(MBEDTLS_AES_ALT) + mbedtls_printf(" AES note: alternative implementation.\n"); +#else /* MBEDTLS_AES_ALT */ +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) { + mbedtls_printf(" AES note: using VIA Padlock.\n"); + } else +#endif +#if defined(MBEDTLS_AESNI_HAVE_CODE) + if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { + mbedtls_printf(" AES note: using AESNI via "); +#if MBEDTLS_AESNI_HAVE_CODE == 1 + mbedtls_printf("assembly"); +#elif MBEDTLS_AESNI_HAVE_CODE == 2 + mbedtls_printf("intrinsics"); +#else + mbedtls_printf("(unknown)"); +#endif + mbedtls_printf(".\n"); + } else +#endif + mbedtls_printf(" AES note: built-in implementation.\n"); +#endif /* MBEDTLS_AES_ALT */ + } + /* * ECB mode */ diff --git a/library/aesni.c b/library/aesni.c index 2a44b0ea3..c909f654c 100644 --- a/library/aesni.c +++ b/library/aesni.c @@ -18,21 +18,14 @@ */ /* - * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set - * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/ + * [AES-WP] https://www.intel.com/content/www/us/en/developer/articles/tool/intel-advanced-encryption-standard-aes-instructions-set.html + * [CLMUL-WP] https://www.intel.com/content/www/us/en/develop/download/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode.html */ #include "common.h" #if defined(MBEDTLS_AESNI_C) -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) -#warning \ - "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code." -#endif -#endif - #include "mbedtls/aesni.h" #include <string.h> @@ -43,7 +36,14 @@ #endif /* *INDENT-ON* */ -#if defined(MBEDTLS_HAVE_X86_64) +#if defined(MBEDTLS_AESNI_HAVE_CODE) + +#if MBEDTLS_AESNI_HAVE_CODE == 2 +#if !defined(_WIN32) +#include <cpuid.h> +#endif +#include <immintrin.h> +#endif /* * AES-NI support detection routine @@ -54,17 +54,355 @@ int mbedtls_aesni_has_support(unsigned int what) static unsigned int c = 0; if (!done) { +#if MBEDTLS_AESNI_HAVE_CODE == 2 + static unsigned info[4] = { 0, 0, 0, 0 }; +#if defined(_MSC_VER) + __cpuid(info, 1); +#else + __cpuid(1, info[0], info[1], info[2], info[3]); +#endif + c = info[2]; +#else /* AESNI using asm */ asm ("movl $1, %%eax \n\t" "cpuid \n\t" : "=c" (c) : : "eax", "ebx", "edx"); +#endif /* MBEDTLS_AESNI_HAVE_CODE */ done = 1; } return (c & what) != 0; } +#if MBEDTLS_AESNI_HAVE_CODE == 2 + +/* + * AES-NI AES-ECB block en(de)cryption + */ +int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16]) +{ + const __m128i *rk = (const __m128i *) (ctx->rk); + unsigned nr = ctx->nr; // Number of remaining rounds + + // Load round key 0 + __m128i state; + memcpy(&state, input, 16); + state = _mm_xor_si128(state, rk[0]); // state ^= *rk; + ++rk; + --nr; + + if (mode == 0) { + while (nr != 0) { + state = _mm_aesdec_si128(state, *rk); + ++rk; + --nr; + } + state = _mm_aesdeclast_si128(state, *rk); + } else { + while (nr != 0) { + state = _mm_aesenc_si128(state, *rk); + ++rk; + --nr; + } + state = _mm_aesenclast_si128(state, *rk); + } + + memcpy(output, &state, 16); + return 0; +} + +/* + * GCM multiplication: c = a times b in GF(2^128) + * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. + */ + +static void gcm_clmul(const __m128i aa, const __m128i bb, + __m128i *cc, __m128i *dd) +{ + /* + * Caryless multiplication dd:cc = aa * bb + * using [CLMUL-WP] algorithm 1 (p. 12). + */ + *cc = _mm_clmulepi64_si128(aa, bb, 0x00); // a0*b0 = c1:c0 + *dd = _mm_clmulepi64_si128(aa, bb, 0x11); // a1*b1 = d1:d0 + __m128i ee = _mm_clmulepi64_si128(aa, bb, 0x10); // a0*b1 = e1:e0 + __m128i ff = _mm_clmulepi64_si128(aa, bb, 0x01); // a1*b0 = f1:f0 + ff = _mm_xor_si128(ff, ee); // e1+f1:e0+f0 + ee = ff; // e1+f1:e0+f0 + ff = _mm_srli_si128(ff, 8); // 0:e1+f1 + ee = _mm_slli_si128(ee, 8); // e0+f0:0 + *dd = _mm_xor_si128(*dd, ff); // d1:d0+e1+f1 + *cc = _mm_xor_si128(*cc, ee); // c1+e0+f0:c0 +} + +static void gcm_shift(__m128i *cc, __m128i *dd) +{ + /* [CMUCL-WP] Algorithm 5 Step 1: shift cc:dd one bit to the left, + * taking advantage of [CLMUL-WP] eq 27 (p. 18). */ + // // *cc = r1:r0 + // // *dd = r3:r2 + __m128i cc_lo = _mm_slli_epi64(*cc, 1); // r1<<1:r0<<1 + __m128i dd_lo = _mm_slli_epi64(*dd, 1); // r3<<1:r2<<1 + __m128i cc_hi = _mm_srli_epi64(*cc, 63); // r1>>63:r0>>63 + __m128i dd_hi = _mm_srli_epi64(*dd, 63); // r3>>63:r2>>63 + __m128i xmm5 = _mm_srli_si128(cc_hi, 8); // 0:r1>>63 + cc_hi = _mm_slli_si128(cc_hi, 8); // r0>>63:0 + dd_hi = _mm_slli_si128(dd_hi, 8); // 0:r1>>63 + + *cc = _mm_or_si128(cc_lo, cc_hi); // r1<<1|r0>>63:r0<<1 + *dd = _mm_or_si128(_mm_or_si128(dd_lo, dd_hi), xmm5); // r3<<1|r2>>62:r2<<1|r1>>63 +} + +static __m128i gcm_reduce(__m128i xx) +{ + // // xx = x1:x0 + /* [CLMUL-WP] Algorithm 5 Step 2 */ + __m128i aa = _mm_slli_epi64(xx, 63); // x1<<63:x0<<63 = stuff:a + __m128i bb = _mm_slli_epi64(xx, 62); // x1<<62:x0<<62 = stuff:b + __m128i cc = _mm_slli_epi64(xx, 57); // x1<<57:x0<<57 = stuff:c + __m128i dd = _mm_slli_si128(_mm_xor_si128(_mm_xor_si128(aa, bb), cc), 8); // a+b+c:0 + return _mm_xor_si128(dd, xx); // x1+a+b+c:x0 = d:x0 +} + +static __m128i gcm_mix(__m128i dx) +{ + /* [CLMUL-WP] Algorithm 5 Steps 3 and 4 */ + __m128i ee = _mm_srli_epi64(dx, 1); // e1:x0>>1 = e1:e0' + __m128i ff = _mm_srli_epi64(dx, 2); // f1:x0>>2 = f1:f0' + __m128i gg = _mm_srli_epi64(dx, 7); // g1:x0>>7 = g1:g0' + + // e0'+f0'+g0' is almost e0+f0+g0, except for some missing + // bits carried from d. Now get those bits back in. + __m128i eh = _mm_slli_epi64(dx, 63); // d<<63:stuff + __m128i fh = _mm_slli_epi64(dx, 62); // d<<62:stuff + __m128i gh = _mm_slli_epi64(dx, 57); // d<<57:stuff + __m128i hh = _mm_srli_si128(_mm_xor_si128(_mm_xor_si128(eh, fh), gh), 8); // 0:missing bits of d + + return _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_xor_si128(ee, ff), gg), hh), dx); +} + +void mbedtls_aesni_gcm_mult(unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16]) +{ + __m128i aa, bb, cc, dd; + + /* The inputs are in big-endian order, so byte-reverse them */ + for (size_t i = 0; i < 16; i++) { + ((uint8_t *) &aa)[i] = a[15 - i]; + ((uint8_t *) &bb)[i] = b[15 - i]; + } + + gcm_clmul(aa, bb, &cc, &dd); + gcm_shift(&cc, &dd); + /* + * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 + * using [CLMUL-WP] algorithm 5 (p. 18). + * Currently dd:cc holds x3:x2:x1:x0 (already shifted). + */ + __m128i dx = gcm_reduce(cc); + __m128i xh = gcm_mix(dx); + cc = _mm_xor_si128(xh, dd); // x3+h1:x2+h0 + + /* Now byte-reverse the outputs */ + for (size_t i = 0; i < 16; i++) { + c[i] = ((uint8_t *) &cc)[15 - i]; + } + + return; +} + +/* + * Compute decryption round keys from encryption round keys + */ +void mbedtls_aesni_inverse_key(unsigned char *invkey, + const unsigned char *fwdkey, int nr) +{ + __m128i *ik = (__m128i *) invkey; + const __m128i *fk = (const __m128i *) fwdkey + nr; + + *ik = *fk; + for (--fk, ++ik; fk > (const __m128i *) fwdkey; --fk, ++ik) { + *ik = _mm_aesimc_si128(*fk); + } + *ik = *fk; +} + +/* + * Key expansion, 128-bit case + */ +static __m128i aesni_set_rk_128(__m128i state, __m128i xword) +{ + /* + * Finish generating the next round key. + * + * On entry state is r3:r2:r1:r0 and xword is X:stuff:stuff:stuff + * with X = rot( sub( r3 ) ) ^ RCON (obtained with AESKEYGENASSIST). + * + * On exit, xword is r7:r6:r5:r4 + * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 + * and this is returned, to be written to the round key buffer. + */ + xword = _mm_shuffle_epi32(xword, 0xff); // X:X:X:X + xword = _mm_xor_si128(xword, state); // X+r3:X+r2:X+r1:r4 + state = _mm_slli_si128(state, 4); // r2:r1:r0:0 + xword = _mm_xor_si128(xword, state); // X+r3+r2:X+r2+r1:r5:r4 + state = _mm_slli_si128(state, 4); // r1:r0:0:0 + xword = _mm_xor_si128(xword, state); // X+r3+r2+r1:r6:r5:r4 + state = _mm_slli_si128(state, 4); // r0:0:0:0 + state = _mm_xor_si128(xword, state); // r7:r6:r5:r4 + return state; +} + +static void aesni_setkey_enc_128(unsigned char *rk_bytes, + const unsigned char *key) +{ + __m128i *rk = (__m128i *) rk_bytes; + + memcpy(&rk[0], key, 16); + rk[1] = aesni_set_rk_128(rk[0], _mm_aeskeygenassist_si128(rk[0], 0x01)); + rk[2] = aesni_set_rk_128(rk[1], _mm_aeskeygenassist_si128(rk[1], 0x02)); + rk[3] = aesni_set_rk_128(rk[2], _mm_aeskeygenassist_si128(rk[2], 0x04)); + rk[4] = aesni_set_rk_128(rk[3], _mm_aeskeygenassist_si128(rk[3], 0x08)); + rk[5] = aesni_set_rk_128(rk[4], _mm_aeskeygenassist_si128(rk[4], 0x10)); + rk[6] = aesni_set_rk_128(rk[5], _mm_aeskeygenassist_si128(rk[5], 0x20)); + rk[7] = aesni_set_rk_128(rk[6], _mm_aeskeygenassist_si128(rk[6], 0x40)); + rk[8] = aesni_set_rk_128(rk[7], _mm_aeskeygenassist_si128(rk[7], 0x80)); + rk[9] = aesni_set_rk_128(rk[8], _mm_aeskeygenassist_si128(rk[8], 0x1B)); + rk[10] = aesni_set_rk_128(rk[9], _mm_aeskeygenassist_si128(rk[9], 0x36)); +} + +/* + * Key expansion, 192-bit case + */ +static void aesni_set_rk_192(__m128i *state0, __m128i *state1, __m128i xword, + unsigned char *rk) +{ + /* + * Finish generating the next 6 quarter-keys. + * + * On entry state0 is r3:r2:r1:r0, state1 is stuff:stuff:r5:r4 + * and xword is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON + * (obtained with AESKEYGENASSIST). + * + * On exit, state0 is r9:r8:r7:r6 and state1 is stuff:stuff:r11:r10 + * and those are written to the round key buffer. + */ + xword = _mm_shuffle_epi32(xword, 0x55); // X:X:X:X + xword = _mm_xor_si128(xword, *state0); // X+r3:X+r2:X+r1:X+r0 + *state0 = _mm_slli_si128(*state0, 4); // r2:r1:r0:0 + xword = _mm_xor_si128(xword, *state0); // X+r3+r2:X+r2+r1:X+r1+r0:X+r0 + *state0 = _mm_slli_si128(*state0, 4); // r1:r0:0:0 + xword = _mm_xor_si128(xword, *state0); // X+r3+r2+r1:X+r2+r1+r0:X+r1+r0:X+r0 + *state0 = _mm_slli_si128(*state0, 4); // r0:0:0:0 + xword = _mm_xor_si128(xword, *state0); // X+r3+r2+r1+r0:X+r2+r1+r0:X+r1+r0:X+r0 + *state0 = xword; // = r9:r8:r7:r6 + + xword = _mm_shuffle_epi32(xword, 0xff); // r9:r9:r9:r9 + xword = _mm_xor_si128(xword, *state1); // stuff:stuff:r9+r5:r9+r4 + *state1 = _mm_slli_si128(*state1, 4); // stuff:stuff:r4:0 + xword = _mm_xor_si128(xword, *state1); // stuff:stuff:r9+r5+r4:r9+r4 + *state1 = xword; // = stuff:stuff:r11:r10 + + /* Store state0 and the low half of state1 into rk, which is conceptually + * an array of 24-byte elements. Since 24 is not a multiple of 16, + * rk is not necessarily aligned so just `*rk = *state0` doesn't work. */ + memcpy(rk, state0, 16); + memcpy(rk + 16, state1, 8); +} + +static void aesni_setkey_enc_192(unsigned char *rk, + const unsigned char *key) +{ + /* First round: use original key */ + memcpy(rk, key, 24); + /* aes.c guarantees that rk is aligned on a 16-byte boundary. */ + __m128i state0 = ((__m128i *) rk)[0]; + __m128i state1 = _mm_loadl_epi64(((__m128i *) rk) + 1); + + aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x01), rk + 24 * 1); + aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x02), rk + 24 * 2); + aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x04), rk + 24 * 3); + aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x08), rk + 24 * 4); + aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x10), rk + 24 * 5); + aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x20), rk + 24 * 6); + aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x40), rk + 24 * 7); + aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x80), rk + 24 * 8); +} + +/* + * Key expansion, 256-bit case + */ +static void aesni_set_rk_256(__m128i state0, __m128i state1, __m128i xword, + __m128i *rk0, __m128i *rk1) +{ + /* + * Finish generating the next two round keys. + * + * On entry state0 is r3:r2:r1:r0, state1 is r7:r6:r5:r4 and + * xword is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON + * (obtained with AESKEYGENASSIST). + * + * On exit, *rk0 is r11:r10:r9:r8 and *rk1 is r15:r14:r13:r12 + */ + xword = _mm_shuffle_epi32(xword, 0xff); + xword = _mm_xor_si128(xword, state0); + state0 = _mm_slli_si128(state0, 4); + xword = _mm_xor_si128(xword, state0); + state0 = _mm_slli_si128(state0, 4); + xword = _mm_xor_si128(xword, state0); + state0 = _mm_slli_si128(state0, 4); + state0 = _mm_xor_si128(state0, xword); + *rk0 = state0; + + /* Set xword to stuff:Y:stuff:stuff with Y = subword( r11 ) + * and proceed to generate next round key from there */ + xword = _mm_aeskeygenassist_si128(state0, 0x00); + xword = _mm_shuffle_epi32(xword, 0xaa); + xword = _mm_xor_si128(xword, state1); + state1 = _mm_slli_si128(state1, 4); + xword = _mm_xor_si128(xword, state1); + state1 = _mm_slli_si128(state1, 4); + xword = _mm_xor_si128(xword, state1); + state1 = _mm_slli_si128(state1, 4); + state1 = _mm_xor_si128(state1, xword); + *rk1 = state1; +} + +static void aesni_setkey_enc_256(unsigned char *rk_bytes, + const unsigned char *key) +{ + __m128i *rk = (__m128i *) rk_bytes; + + memcpy(&rk[0], key, 16); + memcpy(&rk[1], key + 16, 16); + + /* + * Main "loop" - Generating one more key than necessary, + * see definition of mbedtls_aes_context.buf + */ + aesni_set_rk_256(rk[0], rk[1], _mm_aeskeygenassist_si128(rk[1], 0x01), &rk[2], &rk[3]); + aesni_set_rk_256(rk[2], rk[3], _mm_aeskeygenassist_si128(rk[3], 0x02), &rk[4], &rk[5]); + aesni_set_rk_256(rk[4], rk[5], _mm_aeskeygenassist_si128(rk[5], 0x04), &rk[6], &rk[7]); + aesni_set_rk_256(rk[6], rk[7], _mm_aeskeygenassist_si128(rk[7], 0x08), &rk[8], &rk[9]); + aesni_set_rk_256(rk[8], rk[9], _mm_aeskeygenassist_si128(rk[9], 0x10), &rk[10], &rk[11]); + aesni_set_rk_256(rk[10], rk[11], _mm_aeskeygenassist_si128(rk[11], 0x20), &rk[12], &rk[13]); + aesni_set_rk_256(rk[12], rk[13], _mm_aeskeygenassist_si128(rk[13], 0x40), &rk[14], &rk[15]); +} + +#else /* MBEDTLS_AESNI_HAVE_CODE == 1 */ + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#warning \ + "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code." +#endif +#endif + /* * Binutils needs to be at least 2.19 to support AES-NI instructions. * Unfortunately, a lot of users have a lower version now (2014-04). @@ -75,13 +413,13 @@ int mbedtls_aesni_has_support(unsigned int what) * Operand macros are in gas order (src, dst) as opposed to Intel order * (dst, src) in order to blend better into the surrounding assembly code. */ -#define AESDEC ".byte 0x66,0x0F,0x38,0xDE," -#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF," -#define AESENC ".byte 0x66,0x0F,0x38,0xDC," -#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD," -#define AESIMC ".byte 0x66,0x0F,0x38,0xDB," -#define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF," -#define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44," +#define AESDEC(regs) ".byte 0x66,0x0F,0x38,0xDE," regs "\n\t" +#define AESDECLAST(regs) ".byte 0x66,0x0F,0x38,0xDF," regs "\n\t" +#define AESENC(regs) ".byte 0x66,0x0F,0x38,0xDC," regs "\n\t" +#define AESENCLAST(regs) ".byte 0x66,0x0F,0x38,0xDD," regs "\n\t" +#define AESIMC(regs) ".byte 0x66,0x0F,0x38,0xDB," regs "\n\t" +#define AESKEYGENA(regs, imm) ".byte 0x66,0x0F,0x3A,0xDF," regs "," imm "\n\t" +#define PCLMULQDQ(regs, imm) ".byte 0x66,0x0F,0x3A,0x44," regs "," imm "\n\t" #define xmm0_xmm0 "0xC0" #define xmm0_xmm1 "0xC8" @@ -109,25 +447,25 @@ int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx, "1: \n\t" // encryption loop "movdqu (%1), %%xmm1 \n\t" // load round key - AESENC xmm1_xmm0 "\n\t" // do round - "add $16, %1 \n\t" // point to next round key - "subl $1, %0 \n\t" // loop - "jnz 1b \n\t" - "movdqu (%1), %%xmm1 \n\t" // load round key - AESENCLAST xmm1_xmm0 "\n\t" // last round - "jmp 3f \n\t" - - "2: \n\t" // decryption loop - "movdqu (%1), %%xmm1 \n\t" - AESDEC xmm1_xmm0 "\n\t" // do round - "add $16, %1 \n\t" - "subl $1, %0 \n\t" - "jnz 2b \n\t" - "movdqu (%1), %%xmm1 \n\t" // load round key - AESDECLAST xmm1_xmm0 "\n\t" // last round - - "3: \n\t" - "movdqu %%xmm0, (%4) \n\t" // export output + AESENC(xmm1_xmm0) // do round + "add $16, %1 \n\t" // point to next round key + "subl $1, %0 \n\t" // loop + "jnz 1b \n\t" + "movdqu (%1), %%xmm1 \n\t" // load round key + AESENCLAST(xmm1_xmm0) // last round + "jmp 3f \n\t" + + "2: \n\t" // decryption loop + "movdqu (%1), %%xmm1 \n\t" + AESDEC(xmm1_xmm0) // do round + "add $16, %1 \n\t" + "subl $1, %0 \n\t" + "jnz 2b \n\t" + "movdqu (%1), %%xmm1 \n\t" // load round key + AESDECLAST(xmm1_xmm0) // last round + + "3: \n\t" + "movdqu %%xmm0, (%4) \n\t" // export output : : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output) : "memory", "cc", "xmm0", "xmm1"); @@ -158,84 +496,84 @@ void mbedtls_aesni_gcm_mult(unsigned char c[16], /* * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1 - * using [CLMUL-WP] algorithm 1 (p. 13). + * using [CLMUL-WP] algorithm 1 (p. 12). */ "movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0 "movdqa %%xmm1, %%xmm3 \n\t" // same "movdqa %%xmm1, %%xmm4 \n\t" // same - PCLMULQDQ xmm0_xmm1 ",0x00 \n\t" // a0*b0 = c1:c0 - PCLMULQDQ xmm0_xmm2 ",0x11 \n\t" // a1*b1 = d1:d0 - PCLMULQDQ xmm0_xmm3 ",0x10 \n\t" // a0*b1 = e1:e0 - PCLMULQDQ xmm0_xmm4 ",0x01 \n\t" // a1*b0 = f1:f0 - "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0 - "movdqa %%xmm4, %%xmm3 \n\t" // same - "psrldq $8, %%xmm4 \n\t" // 0:e1+f1 - "pslldq $8, %%xmm3 \n\t" // e0+f0:0 - "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1 - "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0 + PCLMULQDQ(xmm0_xmm1, "0x00") // a0*b0 = c1:c0 + PCLMULQDQ(xmm0_xmm2, "0x11") // a1*b1 = d1:d0 + PCLMULQDQ(xmm0_xmm3, "0x10") // a0*b1 = e1:e0 + PCLMULQDQ(xmm0_xmm4, "0x01") // a1*b0 = f1:f0 + "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0 + "movdqa %%xmm4, %%xmm3 \n\t" // same + "psrldq $8, %%xmm4 \n\t" // 0:e1+f1 + "pslldq $8, %%xmm3 \n\t" // e0+f0:0 + "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1 + "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0 /* * Now shift the result one bit to the left, - * taking advantage of [CLMUL-WP] eq 27 (p. 20) + * taking advantage of [CLMUL-WP] eq 27 (p. 18) */ - "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0 - "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2 - "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1 - "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1 - "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63 - "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63 - "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63 - "pslldq $8, %%xmm3 \n\t" // r0>>63:0 - "pslldq $8, %%xmm4 \n\t" // r2>>63:0 - "psrldq $8, %%xmm5 \n\t" // 0:r1>>63 - "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1 - "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1 - "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63 + "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0 + "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2 + "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1 + "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1 + "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63 + "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63 + "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63 + "pslldq $8, %%xmm3 \n\t" // r0>>63:0 + "pslldq $8, %%xmm4 \n\t" // r2>>63:0 + "psrldq $8, %%xmm5 \n\t" // 0:r1>>63 + "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1 + "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1 + "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63 /* * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 - * using [CLMUL-WP] algorithm 5 (p. 20). + * using [CLMUL-WP] algorithm 5 (p. 18). * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted). */ /* Step 2 (1) */ - "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0 - "movdqa %%xmm1, %%xmm4 \n\t" // same - "movdqa %%xmm1, %%xmm5 \n\t" // same - "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a - "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b - "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c + "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0 + "movdqa %%xmm1, %%xmm4 \n\t" // same + "movdqa %%xmm1, %%xmm5 \n\t" // same + "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a + "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b + "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c /* Step 2 (2) */ - "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b - "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c - "pslldq $8, %%xmm3 \n\t" // a+b+c:0 - "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0 + "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b + "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c + "pslldq $8, %%xmm3 \n\t" // a+b+c:0 + "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0 /* Steps 3 and 4 */ - "movdqa %%xmm1,%%xmm0 \n\t" // d:x0 - "movdqa %%xmm1,%%xmm4 \n\t" // same - "movdqa %%xmm1,%%xmm5 \n\t" // same - "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0' - "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0' - "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0' - "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0' - "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0' + "movdqa %%xmm1,%%xmm0 \n\t" // d:x0 + "movdqa %%xmm1,%%xmm4 \n\t" // same + "movdqa %%xmm1,%%xmm5 \n\t" // same + "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0' + "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0' + "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0' + "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0' + "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0' // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing // bits carried from d. Now get those\t bits back in. - "movdqa %%xmm1,%%xmm3 \n\t" // d:x0 - "movdqa %%xmm1,%%xmm4 \n\t" // same - "movdqa %%xmm1,%%xmm5 \n\t" // same - "psllq $63, %%xmm3 \n\t" // d<<63:stuff - "psllq $62, %%xmm4 \n\t" // d<<62:stuff - "psllq $57, %%xmm5 \n\t" // d<<57:stuff - "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff - "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff - "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d - "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0 - "pxor %%xmm1, %%xmm0 \n\t" // h1:h0 - "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0 - - "movdqu %%xmm0, (%2) \n\t" // done + "movdqa %%xmm1,%%xmm3 \n\t" // d:x0 + "movdqa %%xmm1,%%xmm4 \n\t" // same + "movdqa %%xmm1,%%xmm5 \n\t" // same + "psllq $63, %%xmm3 \n\t" // d<<63:stuff + "psllq $62, %%xmm4 \n\t" // d<<62:stuff + "psllq $57, %%xmm5 \n\t" // d<<57:stuff + "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff + "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff + "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d + "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0 + "pxor %%xmm1, %%xmm0 \n\t" // h1:h0 + "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0 + + "movdqu %%xmm0, (%2) \n\t" // done : : "r" (aa), "r" (bb), "r" (cc) : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); @@ -261,8 +599,8 @@ void mbedtls_aesni_inverse_key(unsigned char *invkey, for (fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16) { asm ("movdqu (%0), %%xmm0 \n\t" - AESIMC xmm0_xmm0 "\n\t" - "movdqu %%xmm0, (%1) \n\t" + AESIMC(xmm0_xmm0) + "movdqu %%xmm0, (%1) \n\t" : : "r" (fk), "r" (ik) : "memory", "xmm0"); @@ -306,16 +644,16 @@ static void aesni_setkey_enc_128(unsigned char *rk, /* Main "loop" */ "2: \n\t" - AESKEYGENA xmm0_xmm1 ",0x01 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x01") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x02") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x04") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x08") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x10") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x20") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x40") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x80") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x1B") "call 1b \n\t" + AESKEYGENA(xmm0_xmm1, "0x36") "call 1b \n\t" : : "r" (rk), "r" (key) : "memory", "cc", "0"); @@ -364,14 +702,14 @@ static void aesni_setkey_enc_192(unsigned char *rk, "ret \n\t" "2: \n\t" - AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x01") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x02") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x04") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x08") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x10") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x20") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x40") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x80") "call 1b \n\t" : : "r" (rk), "r" (key) @@ -414,36 +752,38 @@ static void aesni_setkey_enc_256(unsigned char *rk, /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 ) * and proceed to generate next round key from there */ - AESKEYGENA xmm0_xmm2 ",0x00 \n\t" - "pshufd $0xaa, %%xmm2, %%xmm2 \n\t" - "pxor %%xmm1, %%xmm2 \n\t" - "pslldq $4, %%xmm1 \n\t" - "pxor %%xmm1, %%xmm2 \n\t" - "pslldq $4, %%xmm1 \n\t" - "pxor %%xmm1, %%xmm2 \n\t" - "pslldq $4, %%xmm1 \n\t" - "pxor %%xmm2, %%xmm1 \n\t" - "add $16, %0 \n\t" - "movdqu %%xmm1, (%0) \n\t" - "ret \n\t" + AESKEYGENA(xmm0_xmm2, "0x00") + "pshufd $0xaa, %%xmm2, %%xmm2 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm2, %%xmm1 \n\t" + "add $16, %0 \n\t" + "movdqu %%xmm1, (%0) \n\t" + "ret \n\t" /* * Main "loop" - Generating one more key than necessary, * see definition of mbedtls_aes_context.buf */ - "2: \n\t" - AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" + "2: \n\t" + AESKEYGENA(xmm1_xmm2, "0x01") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x02") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x04") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x08") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x10") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x20") "call 1b \n\t" + AESKEYGENA(xmm1_xmm2, "0x40") "call 1b \n\t" : : "r" (rk), "r" (key) : "memory", "cc", "0"); } +#endif /* MBEDTLS_AESNI_HAVE_CODE */ + /* * Key expansion, wrapper */ @@ -461,6 +801,6 @@ int mbedtls_aesni_setkey_enc(unsigned char *rk, return 0; } -#endif /* MBEDTLS_HAVE_X86_64 */ +#endif /* MBEDTLS_AESNI_HAVE_CODE */ #endif /* MBEDTLS_AESNI_C */ diff --git a/library/common.h b/library/common.h index 2786c97d4..e162aa3cf 100644 --- a/library/common.h +++ b/library/common.h @@ -29,6 +29,7 @@ #include "mbedtls/config.h" #endif +#include <assert.h> #include <stddef.h> #include <stdint.h> @@ -347,4 +348,18 @@ static inline const unsigned char *mbedtls_buffer_offset_const( } #endif +/* Always provide a static assert macro, so it can be used unconditionally. + * It will expand to nothing on some systems. + * Can be used outside functions (but don't add a trailing ';' in that case: + * the semicolon is included here to avoid triggering -Wextra-semi when + * MBEDTLS_STATIC_ASSERT() expands to nothing). + * Can't use the C11-style `defined(static_assert)` on FreeBSD, since it + * defines static_assert even with -std=c99, but then complains about it. + */ +#if defined(static_assert) && !defined(__FreeBSD__) +#define MBEDTLS_STATIC_ASSERT(expr, msg) static_assert(expr, msg); +#else +#define MBEDTLS_STATIC_ASSERT(expr, msg) +#endif + #endif /* MBEDTLS_LIBRARY_COMMON_H */ diff --git a/library/gcm.c b/library/gcm.c index f7db0d42d..0c958c729 100644 --- a/library/gcm.c +++ b/library/gcm.c @@ -93,7 +93,7 @@ static int gcm_gen_table(mbedtls_gcm_context *ctx) ctx->HL[8] = vl; ctx->HH[8] = vh; -#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) +#if defined(MBEDTLS_AESNI_HAVE_CODE) /* With CLMUL support, we need only h, not the rest of the table */ if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { return 0; @@ -190,7 +190,7 @@ static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16], unsigned char lo, hi, rem; uint64_t zh, zl; -#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) +#if defined(MBEDTLS_AESNI_HAVE_CODE) if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { unsigned char h[16]; @@ -202,7 +202,7 @@ static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16], mbedtls_aesni_gcm_mult(output, x, h); return; } -#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */ +#endif /* MBEDTLS_AESNI_HAVE_CODE */ lo = x[15] & 0xf; @@ -754,6 +754,27 @@ int mbedtls_gcm_self_test(int verbose) int i, j, ret; mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; + if (verbose != 0) { +#if defined(MBEDTLS_GCM_ALT) + mbedtls_printf(" GCM note: alternative implementation.\n"); +#else /* MBEDTLS_GCM_ALT */ +#if defined(MBEDTLS_AESNI_HAVE_CODE) + if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { + mbedtls_printf(" GCM note: using AESNI via "); +#if MBEDTLS_AESNI_HAVE_CODE == 1 + mbedtls_printf("assembly"); +#elif MBEDTLS_AESNI_HAVE_CODE == 2 + mbedtls_printf("intrinsics"); +#else + mbedtls_printf("(unknown)"); +#endif + mbedtls_printf(".\n"); + } else +#endif + mbedtls_printf(" GCM note: built-in implementation.\n"); +#endif /* MBEDTLS_GCM_ALT */ + } + for (j = 0; j < 3; j++) { int key_len = 128 + 64 * j; diff --git a/library/oid.c b/library/oid.c index 4ec752fb9..12a96503b 100644 --- a/library/oid.c +++ b/library/oid.c @@ -775,65 +775,26 @@ FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, cipher_alg) #endif /* MBEDTLS_PKCS12_C */ -#define OID_SAFE_SNPRINTF \ - do { \ - if (ret < 0 || (size_t) ret >= n) \ - return MBEDTLS_ERR_OID_BUF_TOO_SMALL; \ - \ - n -= (size_t) ret; \ - p += (size_t) ret; \ - } while (0) - /* Return the x.y.z.... style numeric string for the given OID */ int mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_buf *oid) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t i, n; - unsigned int value; - char *p; - - p = buf; - n = size; - - /* First subidentifier contains first two OID components */ - i = 0; - value = 0; - if ((oid->p[0]) == 0x80) { - /* Overlong encoding is not allowed */ - return MBEDTLS_ERR_ASN1_INVALID_DATA; - } - - while (i < oid->len && ((oid->p[i] & 0x80) != 0)) { - /* Prevent overflow in value. */ - if (value > (UINT_MAX >> 7)) { - return MBEDTLS_ERR_ASN1_INVALID_DATA; - } + char *p = buf; + size_t n = size; + unsigned int value = 0; - value |= oid->p[i] & 0x7F; - value <<= 7; - i++; + if (size > INT_MAX) { + /* Avoid overflow computing return value */ + return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } - if (i >= oid->len) { + + if (oid->len <= 0) { + /* OID must not be empty */ return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } - /* Last byte of first subidentifier */ - value |= oid->p[i] & 0x7F; - i++; - - unsigned int component1 = value / 40; - if (component1 > 2) { - /* The first component can only be 0, 1 or 2. - * If oid->p[0] / 40 is greater than 2, the leftover belongs to - * the second component. */ - component1 = 2; - } - unsigned int component2 = value - (40 * component1); - ret = mbedtls_snprintf(p, n, "%u.%u", component1, component2); - OID_SAFE_SNPRINTF; - value = 0; - for (; i < oid->len; i++) { + for (size_t i = 0; i < oid->len; i++) { /* Prevent overflow in value. */ if (value > (UINT_MAX >> 7)) { return MBEDTLS_ERR_ASN1_INVALID_DATA; @@ -848,12 +809,38 @@ int mbedtls_oid_get_numeric_string(char *buf, size_t size, if (!(oid->p[i] & 0x80)) { /* Last byte */ - ret = mbedtls_snprintf(p, n, ".%u", value); - OID_SAFE_SNPRINTF; + if (n == size) { + int component1; + unsigned int component2; + /* First subidentifier contains first two OID components */ + if (value >= 80) { + component1 = '2'; + component2 = value - 80; + } else if (value >= 40) { + component1 = '1'; + component2 = value - 40; + } else { + component1 = '0'; + component2 = value; + } + ret = mbedtls_snprintf(p, n, "%c.%u", component1, component2); + } else { + ret = mbedtls_snprintf(p, n, ".%u", value); + } + if (ret < 2 || (size_t) ret >= n) { + return MBEDTLS_ERR_OID_BUF_TOO_SMALL; + } + n -= (size_t) ret; + p += ret; value = 0; } } + if (value != 0) { + /* Unterminated subidentifier */ + return MBEDTLS_ERR_ASN1_OUT_OF_DATA; + } + return (int) (size - n); } diff --git a/library/psa_crypto.c b/library/psa_crypto.c index d8a994045..bad7f4697 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -47,7 +47,6 @@ #include "psa_crypto_random_impl.h" -#include <assert.h> #include <stdlib.h> #include <string.h> #include "mbedtls/platform.h" @@ -1512,14 +1511,12 @@ exit: return (status == PSA_SUCCESS) ? unlock_status : status; } -#if defined(static_assert) -static_assert((MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE) == 0, - "One or more key attribute flag is listed as both external-only and dual-use"); -static_assert((PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE) == 0, - "One or more key attribute flag is listed as both internal-only and dual-use"); -static_assert((PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY) == 0, - "One or more key attribute flag is listed as both internal-only and external-only"); -#endif +MBEDTLS_STATIC_ASSERT((MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE) == 0, + "One or more key attribute flag is listed as both external-only and dual-use") +MBEDTLS_STATIC_ASSERT((PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE) == 0, + "One or more key attribute flag is listed as both internal-only and dual-use") +MBEDTLS_STATIC_ASSERT((PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY) == 0, + "One or more key attribute flag is listed as both internal-only and external-only") /** Validate that a key policy is internally well-formed. * @@ -1782,11 +1779,10 @@ static psa_status_t psa_finish_key_creation( psa_key_slot_number_t slot_number = psa_key_slot_get_slot_number(slot); -#if defined(static_assert) - static_assert(sizeof(slot_number) == - sizeof(data.slot_number), - "Slot number size does not match psa_se_key_data_storage_t"); -#endif + MBEDTLS_STATIC_ASSERT(sizeof(slot_number) == + sizeof(data.slot_number), + "Slot number size does not match psa_se_key_data_storage_t"); + memcpy(&data.slot_number, &slot_number, sizeof(slot_number)); status = psa_save_persistent_key(&slot->attr, (uint8_t *) &data, diff --git a/library/psa_crypto_se.c b/library/psa_crypto_se.c index b66039364..7bea10ad6 100644 --- a/library/psa_crypto_se.c +++ b/library/psa_crypto_se.c @@ -22,7 +22,6 @@ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) -#include <assert.h> #include <stdint.h> #include <string.h> @@ -315,10 +314,8 @@ psa_status_t psa_register_se_driver( } /* Driver table entries are 0-initialized. 0 is not a valid driver * location because it means a transparent key. */ -#if defined(static_assert) - static_assert(PSA_KEY_LOCATION_LOCAL_STORAGE == 0, - "Secure element support requires 0 to mean a local key"); -#endif + MBEDTLS_STATIC_ASSERT(PSA_KEY_LOCATION_LOCAL_STORAGE == 0, + "Secure element support requires 0 to mean a local key"); if (location == PSA_KEY_LOCATION_LOCAL_STORAGE) { return PSA_ERROR_INVALID_ARGUMENT; } diff --git a/library/ssl_msg.c b/library/ssl_msg.c index a38e76440..8a2ab7b9b 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -5429,8 +5429,10 @@ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) n = (len < ssl->in_msglen) ? len : ssl->in_msglen; - memcpy(buf, ssl->in_offt, n); - ssl->in_msglen -= n; + if (len != 0) { + memcpy(buf, ssl->in_offt, n); + ssl->in_msglen -= n; + } /* Zeroising the plaintext buffer to erase unused application data from the memory. */ @@ -5506,7 +5508,9 @@ static int ssl_write_real(mbedtls_ssl_context *ssl, */ ssl->out_msglen = len; ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; - memcpy(ssl->out_msg, buf, len); + if (len > 0) { + memcpy(ssl->out_msg, buf, len); + } if ((ret = mbedtls_ssl_write_record(ssl, SSL_FORCE_FLUSH)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_record", ret);