diff --git a/.travis.yml b/.travis.yml index 67cb3ca61e..eaf817a7b9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,8 +25,40 @@ jobs: - tests/scripts/all.sh -k build_arm_linux_gnueabi_gcc_arm5vte build_arm_none_eabi_gcc_m0plus - name: full configuration + os: linux + dist: focal + addons: + apt: + packages: + - clang-10 + - gnutls-bin script: - - tests/scripts/all.sh -k test_full_cmake_gcc_asan + # Do a manual build+test sequence rather than using all.sh, + # because there's no all.sh component that does what we want, + # which is a build with Clang >= 10 and ASan, running all the SSL + # testing. + # - The clang executable in the default PATH is Clang 7 on + # Travis's focal instances, but we want Clang >= 10. + # - Running all the SSL testing requires a specific set of + # OpenSSL and GnuTLS versions and we don't want to bother + # with those on Travis. + # So we explicitly select clang-10 as the compiler, and we + # have ad hoc restrictions on SSL testing based on what is + # passing at the time of writing. We will remove these limitations + # gradually. + - make generated_files + - make CC=clang-10 CFLAGS='-Werror -Wall -Wextra -fsanitize=address,undefined -fno-sanitize-recover=all -O2' LDFLAGS='-Werror -Wall -Wextra -fsanitize=address,undefined -fno-sanitize-recover=all' + - make test + - programs/test/selftest + - tests/scripts/test_psa_constant_names.py + - tests/ssl-opt.sh + # Modern OpenSSL does not support fixed ECDH or null ciphers. + - tests/compat.sh -p OpenSSL -e 'NULL\|ECDH-' + - tests/scripts/travis-log-failure.sh + # GnuTLS supports CAMELLIA but compat.sh doesn't properly enable it. + - tests/compat.sh -p GnuTLS -e 'CAMELLIA' + - tests/scripts/travis-log-failure.sh + - tests/context-info.sh - name: Windows os: windows diff --git a/ChangeLog.d/driver-only-hashes.txt b/ChangeLog.d/driver-only-hashes.txt index 2062bcb57d..6ccd199ba1 100644 --- a/ChangeLog.d/driver-only-hashes.txt +++ b/ChangeLog.d/driver-only-hashes.txt @@ -1,20 +1,19 @@ Features - * Some crypto modules that previously depended on MD or a low-level hash - module, either unconditionally (RSA, PK, PKCS5, PKCS12, EC J-PAKE), or - for some features (PEM for encrypted files), are now able to use PSA - Crypto instead when the legacy API is not available. This means it is - now possible to use all features from those modules in configurations - where the built-in implementations of hashes are excluded and the hashes - are only provided by PSA drivers. In these configurations, you need to - call `psa_crypto_init()` before you call any function from those - modules; this is not required in configurations where the built-in - implementation is still available. Note that some crypto modules and - features still depend on the built-in implementation of hashes: - MBEDTLS_HKDF_C (but the PSA HKDF function do not depend on it), - MBEDTLS_ENTROPY_C, MBEDTLS_HMAC_DRBG_C and MBEDTLS_ECDSA_DETERMINISTIC. - In particular, for now, compiling without built-in hashes requires use - of MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG. - * When MBEDTLS_USE_PSA_CRYPTO is enabled, X.509, TLS 1.2 and TLS 1.3 no - longer depend on MD. This means it is now possible to use them in - configurations where the built-in implementations of hashes are excluded - and the hashes are only provided by PSA drivers. + * Some modules can now use PSA drivers for hashes, including with no + built-in implementation present, but only in some configurations. + - RSA OAEP and PSS (PKCS#1 v2.1), PKCS5, PKCS12 and EC J-PAKE now use + hashes from PSA when (and only when) MBEDTLS_MD_C is disabled. + - PEM parsing of encrypted files now uses MD-5 from PSA when (and only + when) MBEDTLS_MD5_C is disabled. + See the documentation of the corresponding macros in mbedtls_config.h for + details. + Note that some modules are not able to use hashes from PSA yet, including + the entropy module. As a consequence, for now the only way to build with + all hashes only provided by drivers (no built-in hash) is to use + MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG. + * When MBEDTLS_USE_PSA_CRYPTO is enabled, X.509, TLS 1.2 and TLS 1.3 now + properly negotiate/accept hashes based on their availability in PSA. + As a consequence, they now work in configurations where the built-in + implementations of (some) hashes are excluded and those hashes are only + provided by PSA drivers. (See previous entry for limitation on RSA-PSS + though: that module only use hashes from PSA when MBEDTLS_MD_C is off). diff --git a/ChangeLog.d/fix-possible-false-success-in-mbedtls_cipher_check_tag.txt b/ChangeLog.d/fix-possible-false-success-in-mbedtls_cipher_check_tag.txt new file mode 100644 index 0000000000..1f9e0aa350 --- /dev/null +++ b/ChangeLog.d/fix-possible-false-success-in-mbedtls_cipher_check_tag.txt @@ -0,0 +1,5 @@ +Changes + * Calling AEAD tag-specific functions for non-AEAD algorithms (which + should not be done - they are documented for use only by AES-GCM and + ChaCha20+Poly1305) now returns MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE + instead of success (0). diff --git a/ChangeLog.d/pkcs7-parser.txt b/ChangeLog.d/pkcs7-parser.txt new file mode 100644 index 0000000000..7f85f0ce1d --- /dev/null +++ b/ChangeLog.d/pkcs7-parser.txt @@ -0,0 +1,13 @@ +Features + * Added partial support for parsing the PKCS7 cryptographic message syntax, + as defined in RFC 2315. Currently, support is limited to the following: + - Only the signed data content type, version 1 is supported. + - Only DER encoding is supported. + - Only a single digest algorithm per message is supported. + - Only 0 or 1, certificate is supported per message, which must be in + X509 format. + - There is no support for certificate-revocation lists. + - The authenticated and unauthenticated attribute fields of SignerInfo + must be empty. + Many thanks to Daniel Axtens, Nayna Jain, and Nick Child from IBM for + contributing this feature. diff --git a/ChangeLog.d/psa-ecb-ub.txt b/ChangeLog.d/psa-ecb-ub.txt new file mode 100644 index 0000000000..9d725ac706 --- /dev/null +++ b/ChangeLog.d/psa-ecb-ub.txt @@ -0,0 +1,3 @@ +Bugfix + * Fix undefined behavior (typically harmless in practice) in PSA ECB + encryption and decryption. diff --git a/docs/architecture/tls13-support.md b/docs/architecture/tls13-support.md index f30590bd47..85482ba9ed 100644 --- a/docs/architecture/tls13-support.md +++ b/docs/architecture/tls13-support.md @@ -478,3 +478,175 @@ outbound message on server side as well. * state change: the state change is done in the main state handler to ease the navigation of the state machine transitions. + + +Writing and reading early or 0-RTT data +--------------------------------------- + +An application function to write and send a buffer of data to a server through +TLS may plausibly look like: + +``` +int write_data( mbedtls_ssl_context *ssl, + const unsigned char *data_to_write, + size_t data_to_write_len, + size_t *data_written ) +{ + *data_written = 0; + + while( *data_written < data_to_write_len ) + { + ret = mbedtls_ssl_write( ssl, data_to_write + *data_written, + data_to_write_len - *data_written ); + + if( ret < 0 && + ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + return( ret ); + } + + *data_written += ret; + } + + return( 0 ); +} +``` +where ssl is the SSL context to use, data_to_write the address of the data +buffer and data_to_write_len the number of data bytes. The handshake may +not be completed, not even started for the SSL context ssl when the function is +called and in that case the mbedtls_ssl_write() API takes care transparently of +completing the handshake before to write and send data to the server. The +mbedtls_ssl_write() may not been able to write and send all data in one go thus +the need for a loop calling it as long as there are still data to write and +send. + +An application function to write and send early data and only early data, +data sent during the first flight of client messages while the handshake is in +its initial phase, would look completely similar but the call to +mbedtls_ssl_write_early_data() instead of mbedtls_ssl_write(). +``` +int write_early_data( mbedtls_ssl_context *ssl, + const unsigned char *data_to_write, + size_t data_to_write_len, + size_t *data_written ) +{ + *data_written = 0; + + while( *data_written < data_to_write_len ) + { + ret = mbedtls_ssl_write_early_data( ssl, data_to_write + *data_written, + data_to_write_len - *data_written ); + + if( ret < 0 && + ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + return( ret ); + } + + *data_written += ret; + } + + return( 0 ); +} +``` +Note that compared to write_data(), write_early_data() can also return +MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA and that should be handled +specifically by the user of write_early_data(). A fresh SSL context (typically +just after a call to mbedtls_ssl_setup() or mbedtls_ssl_session_reset()) would +be expected when calling `write_early_data`. + +All together, code to write and send a buffer of data as long as possible as +early data and then as standard post-handshake application data could +plausibly look like: + +``` +ret = write_early_data( ssl, data_to_write, data_to_write_len, + &early_data_written ); +if( ret < 0 && + ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA ) +{ + goto error; +} + +ret = write_data( ssl, data_to_write + early_data_written, + data_to_write_len - early_data_written, &data_written ); +if( ret < 0 ) + goto error; + +data_written += early_data_written; +``` + +Finally, taking into account that the server may reject early data, application +code to write and send a buffer of data could plausibly look like: +``` +ret = write_early_data( ssl, data_to_write, data_to_write_len, + &early_data_written ); +if( ret < 0 && + ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA ) +{ + goto error; +} + +/* + * Make sure the handshake is completed as it is a requisite to + * mbedtls_ssl_get_early_data_status(). + */ +while( !mbedtls_ssl_is_handshake_over( ssl ) ) +{ + ret = mbedtls_ssl_handshake( ssl ); + if( ret < 0 && + ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + goto error; + } +} + +ret = mbedtls_ssl_get_early_data_status( ssl ); +if( ret < 0 ) + goto error; + +if( ret == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED ) + early_data_written = 0; + +ret = write_data( ssl, data_to_write + early_data_written, + data_to_write_len - early_data_written, &data_written ); +if( ret < 0 ) + goto error; + +data_written += early_data_written; +``` + +Basically, the same holds for reading early data on the server side without the +complication of possible rejection. An application function to read early data +into a given buffer could plausibly look like: +``` +int read_early_data( mbedtls_ssl_context *ssl, + unsigned char *buffer, + size_t buffer_size, + size_t *data_len ) +{ + *data_len = 0; + + while( *data_len < buffer_size ) + { + ret = mbedtls_ssl_read_early_data( ssl, buffer + *data_len, + buffer_size - *data_len ); + + if( ret < 0 && + ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + return( ret ); + } + + *data_len += ret; + } + + return( 0 ); +} +``` +with again calls to read_early_data() expected to be done with a fresh SSL +context. diff --git a/docs/use-psa-crypto.md b/docs/use-psa-crypto.md index b22d37f65f..11442ed66d 100644 --- a/docs/use-psa-crypto.md +++ b/docs/use-psa-crypto.md @@ -86,7 +86,6 @@ is enabled, no change required on the application side. Current exceptions: -- EC J-PAKE (when `MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED` is defined) - finite-field (non-EC) Diffie-Hellman (used in key exchanges: DHE-RSA, DHE-PSK) diff --git a/include/mbedtls/aes.h b/include/mbedtls/aes.h index c359011227..1cd20fe06c 100644 --- a/include/mbedtls/aes.h +++ b/include/mbedtls/aes.h @@ -61,11 +61,6 @@ /** Invalid input data. */ #define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - #ifdef __cplusplus extern "C" { #endif diff --git a/include/mbedtls/asn1.h b/include/mbedtls/asn1.h index 8b66ee228c..5e3f3878c1 100644 --- a/include/mbedtls/asn1.h +++ b/include/mbedtls/asn1.h @@ -39,8 +39,9 @@ /** * \name ASN1 Error codes - * These error codes are OR'ed to X509 error codes for + * These error codes are combined with other error codes for * higher error granularity. + * e.g. X.509 and PKCS #7 error codes * ASN1 is a standard to specify data structures. * \{ */ diff --git a/include/mbedtls/build_info.h b/include/mbedtls/build_info.h index 170cbebbee..362ce2fd59 100644 --- a/include/mbedtls/build_info.h +++ b/include/mbedtls/build_info.h @@ -53,6 +53,12 @@ #define _CRT_SECURE_NO_DEPRECATE 1 #endif +/* Define `inline` on some non-C99-compliant compilers. */ +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/mbedtls_config.h" #else diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 3918639719..38a45303d1 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -1062,6 +1062,14 @@ #error "MBEDTLS_SSL_TRUNCATED_HMAC was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4341" #endif +#if defined(MBEDTLS_PKCS7_C) && ( ( !defined(MBEDTLS_ASN1_PARSE_C) ) || \ + ( !defined(MBEDTLS_OID_C) ) || ( !defined(MBEDTLS_PK_PARSE_C) ) || \ + ( !defined(MBEDTLS_X509_CRT_PARSE_C) ) ||\ + ( !defined(MBEDTLS_X509_CRL_PARSE_C) ) || ( !defined(MBEDTLS_BIGNUM_C) ) || \ + ( !defined(MBEDTLS_MD_C) ) ) +#error "MBEDTLS_PKCS7_C is defined, but not all prerequisites" +#endif + /* * Avoid warning from -pedantic. This is a convenient place for this * workaround since this is included by every single file before the diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h index a3f52ea71f..151da1d83e 100644 --- a/include/mbedtls/cipher.h +++ b/include/mbedtls/cipher.h @@ -46,11 +46,6 @@ #define MBEDTLS_CIPHER_MODE_STREAM #endif -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - /** The selected feature is not available. */ #define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /** Bad input parameters. */ diff --git a/include/mbedtls/ecjpake.h b/include/mbedtls/ecjpake.h index e7ca1b2354..3dd3361a1b 100644 --- a/include/mbedtls/ecjpake.h +++ b/include/mbedtls/ecjpake.h @@ -113,7 +113,7 @@ void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ); * \param curve The identifier of the elliptic curve to use, * for example #MBEDTLS_ECP_DP_SECP256R1. * \param secret The pre-shared secret (passphrase). This must be - * a readable buffer of length \p len Bytes. It need + * a readable not empty buffer of length \p len Bytes. It need * only be valid for the duration of this call. * \param len The length of the pre-shared secret \p secret. * diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h index eb8391311f..4a97d652be 100644 --- a/include/mbedtls/error.h +++ b/include/mbedtls/error.h @@ -26,11 +26,6 @@ #include -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - /** * Error code layout. * @@ -96,6 +91,7 @@ * ECP 4 10 (Started from top) * MD 5 5 * HKDF 5 1 (Started from top) + * PKCS7 5 12 (Started from 0x5300) * SSL 5 2 (Started from 0x5F00) * CIPHER 6 8 (Started from 0x6080) * SSL 6 22 (Started from top, plus 0x6000) diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 3f869b9ffc..a4d0328b99 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -1146,6 +1146,11 @@ * \warning If building without MBEDTLS_MD_C, you must call psa_crypto_init() * before doing any PKCS#1 v2.1 operation. * + * \warning When building with MBEDTLS_MD_C, all hashes used with this + * need to be available as built-ins (that is, for SHA-256, MBEDTLS_SHA256_C, + * etc.) as opposed to just PSA drivers. So far, PSA drivers are only used by + * this module in builds where MBEDTLS_MD_C is disabled. + * * This enables support for RSAES-OAEP and RSASSA-PSS operations. */ #define MBEDTLS_PKCS1_V21 @@ -1648,7 +1653,7 @@ * production. * */ -#define MBEDTLS_SSL_EARLY_DATA +//#define MBEDTLS_SSL_EARLY_DATA /** * \def MBEDTLS_SSL_PROTO_DTLS @@ -2433,6 +2438,11 @@ * * \warning If building without MBEDTLS_MD_C, you must call psa_crypto_init() * before doing any EC J-PAKE operations. + * + * \warning When building with MBEDTLS_MD_C, all hashes used with this + * need to be available as built-ins (that is, for SHA-256, MBEDTLS_SHA256_C, + * etc.) as opposed to just PSA drivers. So far, PSA drivers are only used by + * this module in builds where MBEDTLS_MD_C is disabled. */ #define MBEDTLS_ECJPAKE_C @@ -2777,10 +2787,31 @@ * \warning If building without MBEDTLS_MD_C, you must call psa_crypto_init() * before doing any PKCS5 operation. * + * \warning When building with MBEDTLS_MD_C, all hashes used with this + * need to be available as built-ins (that is, for SHA-256, MBEDTLS_SHA256_C, + * etc.) as opposed to just PSA drivers. So far, PSA drivers are only used by + * this module in builds where MBEDTLS_MD_C is disabled. + * * This module adds support for the PKCS#5 functions. */ #define MBEDTLS_PKCS5_C +/** + * \def MBEDTLS_PKCS7_C + * + * Enable PKCS7 core for using PKCS7 formatted signatures. + * RFC Link - https://tools.ietf.org/html/rfc2315 + * + * Module: library/pkcs7.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_OID_C, MBEDTLS_PK_PARSE_C, + * MBEDTLS_X509_CRT_PARSE_C MBEDTLS_X509_CRL_PARSE_C, + * MBEDTLS_BIGNUM_C, MBEDTLS_MD_C + * + * This module is required for the PKCS7 parsing modules. + */ +#define MBEDTLS_PKCS7_C + /** * \def MBEDTLS_PKCS12_C * @@ -2796,6 +2827,11 @@ * \warning If building without MBEDTLS_MD_C, you must call psa_crypto_init() * before doing any PKCS12 operation. * + * \warning When building with MBEDTLS_MD_C, all hashes used with this + * need to be available as built-ins (that is, for SHA-256, MBEDTLS_SHA256_C, + * etc.) as opposed to just PSA drivers. So far, PSA drivers are only used by + * this module in builds where MBEDTLS_MD_C is disabled. + * * This module enables PKCS#12 functions. */ #define MBEDTLS_PKCS12_C diff --git a/include/mbedtls/oid.h b/include/mbedtls/oid.h index 4ee3f93fbe..e5c4b92493 100644 --- a/include/mbedtls/oid.h +++ b/include/mbedtls/oid.h @@ -220,6 +220,7 @@ #define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ #define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ #define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ +#define MBEDTLS_OID_PKCS7 MBEDTLS_OID_PKCS "\x07" /**< pkcs-7 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 } */ #define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ #define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ @@ -300,6 +301,16 @@ #define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ #define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ +/* + * PKCS#7 OIDs + */ +#define MBEDTLS_OID_PKCS7_DATA MBEDTLS_OID_PKCS7 "\x01" /**< Content type is Data OBJECT IDENTIFIER ::= {pkcs-7 1} */ +#define MBEDTLS_OID_PKCS7_SIGNED_DATA MBEDTLS_OID_PKCS7 "\x02" /**< Content type is Signed Data OBJECT IDENTIFIER ::= {pkcs-7 2} */ +#define MBEDTLS_OID_PKCS7_ENVELOPED_DATA MBEDTLS_OID_PKCS7 "\x03" /**< Content type is Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 3} */ +#define MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA MBEDTLS_OID_PKCS7 "\x04" /**< Content type is Signed and Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 4} */ +#define MBEDTLS_OID_PKCS7_DIGESTED_DATA MBEDTLS_OID_PKCS7 "\x05" /**< Content type is Digested Data OBJECT IDENTIFIER ::= {pkcs-7 5} */ +#define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA MBEDTLS_OID_PKCS7 "\x06" /**< Content type is Encrypted Data OBJECT IDENTIFIER ::= {pkcs-7 6} */ + /* * PKCS#8 OIDs */ diff --git a/include/mbedtls/pem.h b/include/mbedtls/pem.h index c75a1246ad..a4c6fb89f9 100644 --- a/include/mbedtls/pem.h +++ b/include/mbedtls/pem.h @@ -27,11 +27,6 @@ #include -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - /** * \name PEM Error codes * These error codes are returned in case of errors reading the diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h index 867961d329..db0bfacab3 100644 --- a/include/mbedtls/pk.h +++ b/include/mbedtls/pk.h @@ -44,11 +44,6 @@ #include "psa/crypto.h" #endif -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - /** Memory allocation failed. */ #define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 /** Type mismatch, eg attempt to encrypt with an ECDSA key */ diff --git a/include/mbedtls/pkcs7.h b/include/mbedtls/pkcs7.h new file mode 100644 index 0000000000..52895ac2b7 --- /dev/null +++ b/include/mbedtls/pkcs7.h @@ -0,0 +1,241 @@ +/** + * \file pkcs7.h + * + * \brief PKCS7 generic defines and structures + * https://tools.ietf.org/html/rfc2315 + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Note: For the time being, this implementation of the PKCS7 cryptographic + * message syntax is a partial implementation of RFC 2315. + * Differences include: + * - The RFC specifies 6 different content types. The only type currently + * supported in Mbed TLS is the signed data content type. + * - The only supported PKCS7 Signed Data syntax version is version 1 + * - The RFC specifies support for BER. This implementation is limited to + * DER only. + * - The RFC specifies that multiple digest algorithms can be specified + * in the Signed Data type. Only one digest algorithm is supported in Mbed TLS. + * - The RFC specifies the Signed Data type can contain multiple X509 or PKCS6 + * certificates. In Mbed TLS, this list can only contain 0 or 1 certificates + * and they must be in X509 format. + * - The RFC specifies the Signed Data type can contain + * certificate-revocation lists (crls). This implementation has no support + * for crls so it is assumed to be an empty list. + * - The RFC allows for SignerInfo structure to optionally contain + * unauthenticatedAttributes and authenticatedAttributes. In Mbed TLS it is + * assumed these fields are empty. + */ + +#ifndef MBEDTLS_PKCS7_H +#define MBEDTLS_PKCS7_H + +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/asn1.h" +#include "mbedtls/x509.h" +#include "mbedtls/x509_crt.h" + +/** + * \name PKCS7 Module Error codes + * \{ + */ +#define MBEDTLS_ERR_PKCS7_INVALID_FORMAT -0x5300 /**< The format is invalid, e.g. different type expected. */ +#define MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE -0x5380 /**< Unavailable feature, e.g. anything other than signed data. */ +#define MBEDTLS_ERR_PKCS7_INVALID_VERSION -0x5400 /**< The PKCS7 version element is invalid or cannot be parsed. */ +#define MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO -0x5480 /**< The PKCS7 content info invalid or cannot be parsed. */ +#define MBEDTLS_ERR_PKCS7_INVALID_ALG -0x5500 /**< The algorithm tag or value is invalid or cannot be parsed. */ +#define MBEDTLS_ERR_PKCS7_INVALID_CERT -0x5580 /**< The certificate tag or value is invalid or cannot be parsed. */ +#define MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE -0x5600 /**< Error parsing the signature */ +#define MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO -0x5680 /**< Error parsing the signer's info */ +#define MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA -0x5700 /**< Input invalid. */ +#define MBEDTLS_ERR_PKCS7_ALLOC_FAILED -0x5780 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_PKCS7_VERIFY_FAIL -0x5800 /**< Verification Failed */ +#define MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID -0x5880 /**< The PKCS7 date issued/expired dates are invalid */ +/* \} name */ + +/** + * \name PKCS7 Supported Version + * \{ + */ +#define MBEDTLS_PKCS7_SUPPORTED_VERSION 0x01 +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef mbedtls_asn1_buf mbedtls_pkcs7_buf; + +/** + * Container for ASN1 named information objects. + * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). + */ +typedef mbedtls_asn1_named_data mbedtls_pkcs7_name; + +/** + * Container for a sequence of ASN.1 items + */ +typedef mbedtls_asn1_sequence mbedtls_pkcs7_sequence; + +/** + * PKCS7 types + */ +typedef enum { + MBEDTLS_PKCS7_NONE=0, + MBEDTLS_PKCS7_DATA, + MBEDTLS_PKCS7_SIGNED_DATA, + MBEDTLS_PKCS7_ENVELOPED_DATA, + MBEDTLS_PKCS7_SIGNED_AND_ENVELOPED_DATA, + MBEDTLS_PKCS7_DIGESTED_DATA, + MBEDTLS_PKCS7_ENCRYPTED_DATA, +} +mbedtls_pkcs7_type; + +/** + * Structure holding PKCS7 signer info + */ +typedef struct mbedtls_pkcs7_signer_info +{ + int MBEDTLS_PRIVATE(version); + mbedtls_x509_buf MBEDTLS_PRIVATE(serial); + mbedtls_x509_name MBEDTLS_PRIVATE(issuer); + mbedtls_x509_buf MBEDTLS_PRIVATE(issuer_raw); + mbedtls_x509_buf MBEDTLS_PRIVATE(alg_identifier); + mbedtls_x509_buf MBEDTLS_PRIVATE(sig_alg_identifier); + mbedtls_x509_buf MBEDTLS_PRIVATE(sig); + struct mbedtls_pkcs7_signer_info *MBEDTLS_PRIVATE(next); +} +mbedtls_pkcs7_signer_info; + +/** + * Structure holding attached data as part of PKCS7 signed data format + */ +typedef struct mbedtls_pkcs7_data +{ + mbedtls_pkcs7_buf MBEDTLS_PRIVATE(oid); + mbedtls_pkcs7_buf MBEDTLS_PRIVATE(data); +} +mbedtls_pkcs7_data; + +/** + * Structure holding the signed data section + */ +typedef struct mbedtls_pkcs7_signed_data +{ + int MBEDTLS_PRIVATE(version); + mbedtls_pkcs7_buf MBEDTLS_PRIVATE(digest_alg_identifiers); + struct mbedtls_pkcs7_data MBEDTLS_PRIVATE(content); + int MBEDTLS_PRIVATE(no_of_certs); + mbedtls_x509_crt MBEDTLS_PRIVATE(certs); + int MBEDTLS_PRIVATE(no_of_crls); + mbedtls_x509_crl MBEDTLS_PRIVATE(crl); + int MBEDTLS_PRIVATE(no_of_signers); + mbedtls_pkcs7_signer_info MBEDTLS_PRIVATE(signers); +} +mbedtls_pkcs7_signed_data; + +/** + * Structure holding PKCS7 structure, only signed data for now + */ +typedef struct mbedtls_pkcs7 +{ + mbedtls_pkcs7_buf MBEDTLS_PRIVATE(raw); + mbedtls_pkcs7_buf MBEDTLS_PRIVATE(content_type_oid); + mbedtls_pkcs7_signed_data MBEDTLS_PRIVATE(signed_data); +} +mbedtls_pkcs7; + +/** + * \brief Initialize pkcs7 structure. + * + * \param pkcs7 pkcs7 structure. + */ +void mbedtls_pkcs7_init( mbedtls_pkcs7 *pkcs7 ); + +/** + * \brief Parse a single DER formatted pkcs7 content. + * + * \param pkcs7 The pkcs7 structure to be filled by parser for the output. + * \param buf The buffer holding the DER encoded pkcs7. + * \param buflen The size in Bytes of \p buf. + * + * \note This function makes an internal copy of the PKCS7 buffer + * \p buf. In particular, \p buf may be destroyed or reused + * after this call returns. + * + * \return The \c mbedtls_pkcs7_type of \p buf, if successful. + * \return A negative error code on failure. + */ +int mbedtls_pkcs7_parse_der( mbedtls_pkcs7 *pkcs7, const unsigned char *buf, + const size_t buflen ); + +/** + * \brief Verification of PKCS7 signature. + * + * \param pkcs7 PKCS7 structure containing signature. + * \param cert Certificate containing key to verify signature. + * \param data Plain data on which signature has to be verified. + * \param datalen Length of the data. + * + * \note This function internally calculates the hash on the supplied + * plain data for signature verification. + * + * \return A negative error code on failure. + */ +int mbedtls_pkcs7_signed_data_verify( mbedtls_pkcs7 *pkcs7, + const mbedtls_x509_crt *cert, + const unsigned char *data, + size_t datalen ); + +/** + * \brief Verification of PKCS7 signature. + * + * \param pkcs7 PKCS7 structure containing signature. + * \param cert Certificate containing key to verify signature. + * \param hash Hash of the plain data on which signature has to be verified. + * \param hashlen Length of the hash. + * + * \note This function is different from mbedtls_pkcs7_signed_data_verify() + * in a way that it directly recieves the hash of the data. + * + * \return A negative error code on failure. + */ +int mbedtls_pkcs7_signed_hash_verify( mbedtls_pkcs7 *pkcs7, + const mbedtls_x509_crt *cert, + const unsigned char *hash, size_t hashlen); + +/** + * \brief Unallocate all PKCS7 data and zeroize the memory. + * It doesn't free pkcs7 itself. It should be done by the caller. + * + * \param pkcs7 PKCS7 structure to free. + */ +void mbedtls_pkcs7_free( mbedtls_pkcs7 *pkcs7 ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs7.h */ diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index d0558511a8..ea58661088 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -96,12 +96,16 @@ /* Error space gap */ /** Processing of the Certificate handshake message failed. */ #define MBEDTLS_ERR_SSL_BAD_CERTIFICATE -0x7A00 -/** Received NewSessionTicket Post Handshake Message */ +/* Error space gap */ +/** + * Received NewSessionTicket Post Handshake Message. + * This error code is experimental and may be changed or removed without notice. + */ #define MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET -0x7B00 -/* Error space gap */ -/* Error space gap */ -/* Error space gap */ -/* Error space gap */ +/** Not possible to read early data */ +#define MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA -0x7B80 +/** Not possible to write early data */ +#define MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA -0x7C00 /* Error space gap */ /* Error space gap */ /* Error space gap */ @@ -661,7 +665,7 @@ typedef enum MBEDTLS_SSL_SERVER_FINISHED, MBEDTLS_SSL_FLUSH_BUFFERS, MBEDTLS_SSL_HANDSHAKE_WRAPUP, - MBEDTLS_SSL_HANDSHAKE_OVER, + MBEDTLS_SSL_NEW_SESSION_TICKET, MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT, MBEDTLS_SSL_HELLO_RETRY_REQUEST, @@ -671,7 +675,9 @@ typedef enum MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO, MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO, MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST, - MBEDTLS_SSL_NEW_SESSION_TICKET_FLUSH, + MBEDTLS_SSL_HANDSHAKE_OVER, + MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET, + MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH, } mbedtls_ssl_states; @@ -801,14 +807,6 @@ typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; #endif -#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) -#define MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN 0 -#define MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT 1 -#define MBEDTLS_SSL_EARLY_DATA_STATUS_INDICATION_SENT 2 -#define MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED 3 -#define MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED 4 -#endif - #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) typedef uint8_t mbedtls_ssl_tls13_ticket_flags; @@ -3851,9 +3849,10 @@ void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, * \note The SSL context needs to be already set up. The right place * to call this function is between \c mbedtls_ssl_setup() or * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). + * Password cannot be empty (see RFC 8236). * * \param ssl SSL context - * \param pw EC J-PAKE password (pre-shared secret) + * \param pw EC J-PAKE password (pre-shared secret). It cannot be empty * \param pw_len length of pw in bytes * * \return 0 on success, or a negative error code. @@ -4651,7 +4650,7 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); */ static inline int mbedtls_ssl_is_handshake_over( mbedtls_ssl_context *ssl ) { - return( ssl->MBEDTLS_PRIVATE( state ) == MBEDTLS_SSL_HANDSHAKE_OVER ); + return( ssl->MBEDTLS_PRIVATE( state ) >= MBEDTLS_SSL_HANDSHAKE_OVER ); } /** @@ -4891,6 +4890,151 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, */ int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); +#if defined(MBEDTLS_SSL_EARLY_DATA) + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Read at most 'len' application data bytes while performing + * the handshake (early data). + * + * \note This function behaves mainly as mbedtls_ssl_read(). The + * specification of mbedtls_ssl_read() relevant to TLS 1.3 + * (thus not the parts specific to (D)TLS 1.2) applies to this + * function and the present documentation is restricted to the + * differences with mbedtls_ssl_read(). + * + * \param ssl SSL context + * \param buf buffer that will hold the data + * \param len maximum number of bytes to read + * + * \return One additional specific return value: + * #MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA. + * + * #MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA is returned when it + * is not possible to read early data for the SSL context + * \p ssl. + * + * It may have been possible and it is not possible + * anymore because the server received the End of Early Data + * message or the maximum number of allowed early data for the + * PSK in use has been reached. + * + * It may never have been possible and will never be possible + * for the SSL context \p ssl because the use of early data + * is disabled for that context or more generally the context + * is not suitably configured to enable early data or the + * client does not use early data or the first call to the + * function was done while the handshake was already too + * advanced to gather and accept early data. + * + * It is not possible to read early data for the SSL context + * \p ssl but this does not preclude for using it with + * mbedtls_ssl_write(), mbedtls_ssl_read() or + * mbedtls_ssl_handshake(). + * + * \note When a server wants to retrieve early data, it is expected + * that this function starts the handshake for the SSL context + * \p ssl. But this is not mandatory. + * + */ +int mbedtls_ssl_read_early_data( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t len ); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Try to write exactly 'len' application data bytes while + * performing the handshake (early data). + * + * \note This function behaves mainly as mbedtls_ssl_write(). The + * specification of mbedtls_ssl_write() relevant to TLS 1.3 + * (thus not the parts specific to (D)TLS1.2) applies to this + * function and the present documentation is restricted to the + * differences with mbedtls_ssl_write(). + * + * \param ssl SSL context + * \param buf buffer holding the data + * \param len how many bytes must be written + * + * \return One additional specific return value: + * #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA. + * + * #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA is returned when it + * is not possible to write early data for the SSL context + * \p ssl. + * + * It may have been possible and it is not possible + * anymore because the client received the server Finished + * message, the server rejected early data or the maximum + * number of allowed early data for the PSK in use has been + * reached. + * + * It may never have been possible and will never be possible + * for the SSL context \p ssl because the use of early data + * is disabled for that context or more generally the context + * is not suitably configured to enable early data or the first + * call to the function was done while the handshake was + * already completed. + * + * It is not possible to write early data for the SSL context + * \p ssl but this does not preclude for using it with + * mbedtls_ssl_write(), mbedtls_ssl_read() or + * mbedtls_ssl_handshake(). + * + * \note This function may write early data only if the SSL context + * has been configured for the handshake with a PSK for which + * early data is allowed. + * + * \note To maximize the number of early data that can be written in + * the course of the handshake, it is expected that this + * function starts the handshake for the SSL context \p ssl. + * But this is not mandatory. + * + * \note This function does not provide any information on whether + * the server has accepted or will accept early data or not. + * When it returns a positive value, it just means that it + * has written early data to the server. To know whether the + * server has accepted early data or not, you should call + * mbedtls_ssl_get_early_data_status() with the handshake + * completed. + */ +int mbedtls_ssl_write_early_data( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ); + +#define MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT 0 +#define MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED 1 +#define MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED 2 +/** + * \brief Get the status of the negotiation of the use of early data. + * + * \param ssl The SSL context to query + * + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if this function is called + * from the server-side. + * + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if this function is called + * prior to completion of the handshake. + * + * \return #MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT if the client has + * not indicated the use of early data to the server. + * + * \return #MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED if the client has + * indicated the use of early data and the server has accepted + * it. + * + * \return #MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED if the client has + * indicated the use of early data but the server has rejected + * it. In this situation, the client may want to re-send the + * early data it may have tried to send by calling + * mbedtls_ssl_write_early_data() as ordinary post-handshake + * application data by calling mbedtls_ssl_write(). + * + */ +int mbedtls_ssl_get_early_data_status( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_CLI_C */ + +#endif /* MBEDTLS_SSL_EARLY_DATA */ + /** * \brief Free referenced items in an SSL context and clear memory * diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index 4f65398e24..33e2e77b99 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -1829,7 +1829,7 @@ psa_status_t psa_pake_abort( psa_pake_operation_t * operation ); */ #if defined(MBEDTLS_PSA_BUILTIN_PAKE) #define PSA_PAKE_OPERATION_INIT {PSA_ALG_NONE, 0, 0, 0, 0, \ - MBEDTLS_SVC_KEY_ID_INIT, \ + NULL, 0 , \ PSA_PAKE_ROLE_NONE, {0}, 0, 0, \ {.dummy = 0}} #else @@ -1920,7 +1920,8 @@ struct psa_pake_operation_s #if defined(MBEDTLS_PSA_BUILTIN_PAKE) unsigned int MBEDTLS_PRIVATE(input_step); unsigned int MBEDTLS_PRIVATE(output_step); - mbedtls_svc_key_id_t MBEDTLS_PRIVATE(password); + uint8_t* MBEDTLS_PRIVATE(password); + size_t MBEDTLS_PRIVATE(password_len); psa_pake_role_t MBEDTLS_PRIVATE(role); uint8_t MBEDTLS_PRIVATE(buffer[MBEDTLS_PSA_PAKE_BUFFER_SIZE]); size_t MBEDTLS_PRIVATE(buffer_length); diff --git a/include/psa/crypto_platform.h b/include/psa/crypto_platform.h index 47ab1cf9f2..573b33c856 100644 --- a/include/psa/crypto_platform.h +++ b/include/psa/crypto_platform.h @@ -45,11 +45,6 @@ /* PSA requires several types which C99 provides in stdint.h. */ #include -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) /* Building for the PSA Crypto service on a PSA platform, a key owner is a PSA diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 7c325f7bae..60b1cf4dd5 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -92,6 +92,7 @@ set(src_crypto ) set(src_x509 + pkcs7.c x509.c x509_create.c x509_crl.c diff --git a/library/Makefile b/library/Makefile index b1cdc7f0ea..6c3b758208 100644 --- a/library/Makefile +++ b/library/Makefile @@ -168,6 +168,7 @@ OBJS_X509= \ x509_csr.o \ x509write_crt.o \ x509write_csr.o \ + pkcs7.o \ # This line is intentionally left blank OBJS_TLS= \ diff --git a/library/aria.c b/library/aria.c index a1876b7763..682d4ec419 100644 --- a/library/aria.c +++ b/library/aria.c @@ -37,11 +37,6 @@ #include "mbedtls/platform_util.h" -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - /* Parameter validation macros */ #define ARIA_VALIDATE_RET( cond ) \ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ) diff --git a/library/bignum.c b/library/bignum.c index ba03988254..a68957a534 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -968,17 +968,15 @@ int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi carry = mbedtls_mpi_core_sub( X->p, A->p, B->p, n ); if( carry != 0 ) { - /* Propagate the carry to the first nonzero limb of X. */ - for( ; n < X->n && X->p[n] == 0; n++ ) - --X->p[n]; - /* If we ran out of space for the carry, it means that the result - * is negative. */ - if( n == X->n ) + /* Propagate the carry through the rest of X. */ + carry = mbedtls_mpi_core_sub_int( X->p + n, X->p + n, carry, X->n - n ); + + /* If we have further carry/borrow, the result is negative. */ + if( carry != 0 ) { ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; goto cleanup; } - --X->p[n]; } /* X should always be positive as a result of unsigned subtractions. */ diff --git a/library/bignum_core.c b/library/bignum_core.c index 34aecda501..41d3239688 100644 --- a/library/bignum_core.c +++ b/library/bignum_core.c @@ -590,6 +590,22 @@ cleanup: /* BEGIN MERGE SLOT 3 */ +mbedtls_mpi_uint mbedtls_mpi_core_sub_int( mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + mbedtls_mpi_uint c, /* doubles as carry */ + size_t limbs ) +{ + for( size_t i = 0; i < limbs; i++ ) + { + mbedtls_mpi_uint s = A[i]; + mbedtls_mpi_uint t = s - c; + c = ( t > s ); + X[i] = t; + } + + return( c ); +} + /* END MERGE SLOT 3 */ /* BEGIN MERGE SLOT 4 */ diff --git a/library/bignum_core.h b/library/bignum_core.h index ad04e08283..d48e7053bb 100644 --- a/library/bignum_core.h +++ b/library/bignum_core.h @@ -504,6 +504,23 @@ int mbedtls_mpi_core_fill_random( mbedtls_mpi_uint *X, size_t X_limbs, /* BEGIN MERGE SLOT 3 */ +/** + * \brief Subtract unsigned integer from known-size large unsigned integers. + * Return the borrow. + * + * \param[out] X The result of the subtraction. + * \param[in] A The left operand. + * \param b The unsigned scalar to subtract. + * \param limbs Number of limbs of \p X and \p A. + * + * \return 1 if `A < b`. + * 0 if `A >= b`. + */ +mbedtls_mpi_uint mbedtls_mpi_core_sub_int( mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + mbedtls_mpi_uint b, + size_t limbs ); + /* END MERGE SLOT 3 */ /* BEGIN MERGE SLOT 4 */ diff --git a/library/bignum_mod_raw.c b/library/bignum_mod_raw.c index b43add77d3..6c694b0c58 100644 --- a/library/bignum_mod_raw.c +++ b/library/bignum_mod_raw.c @@ -108,6 +108,16 @@ int mbedtls_mpi_mod_raw_write( const mbedtls_mpi_uint *A, /* BEGIN MERGE SLOT 2 */ +void mbedtls_mpi_mod_raw_sub( mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + const mbedtls_mpi_mod_modulus *N ) +{ + mbedtls_mpi_uint c = mbedtls_mpi_core_sub( X, A, B, N->limbs ); + + (void) mbedtls_mpi_core_add_if( X, N->p, N->limbs, (unsigned) c ); +} + /* END MERGE SLOT 2 */ /* BEGIN MERGE SLOT 3 */ diff --git a/library/bignum_mod_raw.h b/library/bignum_mod_raw.h index f738e917e1..05fa9d6ac8 100644 --- a/library/bignum_mod_raw.h +++ b/library/bignum_mod_raw.h @@ -144,6 +144,28 @@ int mbedtls_mpi_mod_raw_write( const mbedtls_mpi_uint *A, /* BEGIN MERGE SLOT 2 */ +/** \brief Subtract two MPIs, returning the residue modulo the specified + * modulus. + * + * The size of the operation is determined by \p N. \p A and \p B must have + * the same number of limbs as \p N. + * + * \p X may be aliased to \p A or \p B, or even both, but may not overlap + * either otherwise. + * + * \param[out] X The address of the result MPI. + * This must be initialized. Must have enough limbs to + * store the full value of the result. + * \param[in] A The address of the first MPI. This must be initialized. + * \param[in] B The address of the second MPI. This must be initialized. + * \param[in] N The address of the modulus. Used to perform a modulo + * operation on the result of the subtraction. + */ +void mbedtls_mpi_mod_raw_sub( mbedtls_mpi_uint *X, + const mbedtls_mpi_uint *A, + const mbedtls_mpi_uint *B, + const mbedtls_mpi_mod_modulus *N ); + /* END MERGE SLOT 2 */ /* BEGIN MERGE SLOT 3 */ diff --git a/library/chacha20.c b/library/chacha20.c index 28751043ab..d17c58c269 100644 --- a/library/chacha20.c +++ b/library/chacha20.c @@ -36,11 +36,6 @@ #if !defined(MBEDTLS_CHACHA20_ALT) -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - #define ROTL32( value, amount ) \ ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) ) diff --git a/library/cipher.c b/library/cipher.c index dfb7329938..dffe3adca4 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -500,7 +500,7 @@ int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, } #endif - return( 0 ); + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); } #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ @@ -1129,7 +1129,7 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, } #endif - return( 0 ); + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); } int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, @@ -1156,11 +1156,8 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, } #endif /* MBEDTLS_USE_PSA_CRYPTO */ - /* Status to return on a non-authenticated algorithm. It would make sense - * to return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT or perhaps - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, but at the time I write this our - * unit tests assume 0. */ - ret = 0; + /* Status to return on a non-authenticated algorithm. */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; #if defined(MBEDTLS_GCM_C) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) diff --git a/library/common.h b/library/common.h index 2cc44fb71d..97d180aefb 100644 --- a/library/common.h +++ b/library/common.h @@ -26,6 +26,7 @@ #include "mbedtls/build_info.h" #include "alignment.h" +#include #include #include @@ -75,6 +76,44 @@ extern void (*mbedtls_test_hook_test_fail)( const char * test, int line, const c */ #define MBEDTLS_ALLOW_PRIVATE_ACCESS +/** Return an offset into a buffer. + * + * This is just the addition of an offset to a pointer, except that this + * function also accepts an offset of 0 into a buffer whose pointer is null. + * (`p + n` has undefined behavior when `p` is null, even when `n == 0`. + * A null pointer is a valid buffer pointer when the size is 0, for example + * as the result of `malloc(0)` on some platforms.) + * + * \param p Pointer to a buffer of at least n bytes. + * This may be \p NULL if \p n is zero. + * \param n An offset in bytes. + * \return Pointer to offset \p n in the buffer \p p. + * Note that this is only a valid pointer if the size of the + * buffer is at least \p n + 1. + */ +static inline unsigned char *mbedtls_buffer_offset( + unsigned char *p, size_t n ) +{ + return( p == NULL ? NULL : p + n ); +} + +/** Return an offset into a read-only buffer. + * + * Similar to mbedtls_buffer_offset(), but for const pointers. + * + * \param p Pointer to a buffer of at least n bytes. + * This may be \p NULL if \p n is zero. + * \param n An offset in bytes. + * \return Pointer to offset \p n in the buffer \p p. + * Note that this is only a valid pointer if the size of the + * buffer is at least \p n + 1. + */ +static inline const unsigned char *mbedtls_buffer_offset_const( + const unsigned char *p, size_t n ) +{ + return( p == NULL ? NULL : p + n ); +} + /** * Perform a fast block XOR operation, such that * r[i] = a[i] ^ b[i] where 0 <= i < n diff --git a/library/debug.c b/library/debug.c index bdbf6dd11e..6114a460fd 100644 --- a/library/debug.c +++ b/library/debug.c @@ -30,11 +30,6 @@ #include #include -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - #define DEBUG_BUF_SIZE 512 static int debug_threshold = 0; diff --git a/library/ecp.c b/library/ecp.c index 37f6090a83..cd7d5543c3 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -88,11 +88,6 @@ #include "ecp_internal_alt.h" -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - #if defined(MBEDTLS_SELF_TEST) /* * Counts of point addition and doubling, and field multiplications. diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 7b142370dd..5cd2828f73 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -39,11 +39,6 @@ #define ECP_VALIDATE( cond ) \ MBEDTLS_INTERNAL_VALIDATE( cond ) -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - #define ECP_MPI_INIT(s, n, p) {s, (n), (mbedtls_mpi_uint *)(p)} #define ECP_MPI_INIT_ARRAY(x) \ diff --git a/library/mps_reader.c b/library/mps_reader.c index 36958b46b8..6f823bde15 100644 --- a/library/mps_reader.c +++ b/library/mps_reader.c @@ -29,11 +29,6 @@ #include -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - #if defined(MBEDTLS_MPS_ENABLE_TRACE) static int mbedtls_mps_trace_id = MBEDTLS_MPS_TRACE_BIT_READER; #endif /* MBEDTLS_MPS_ENABLE_TRACE */ diff --git a/library/pkcs7.c b/library/pkcs7.c new file mode 100644 index 0000000000..ca0170a6dc --- /dev/null +++ b/library/pkcs7.c @@ -0,0 +1,753 @@ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "common.h" + +#include "mbedtls/build_info.h" +#if defined(MBEDTLS_PKCS7_C) +#include "mbedtls/pkcs7.h" +#include "mbedtls/x509.h" +#include "mbedtls/asn1.h" +#include "mbedtls/x509_crt.h" +#include "mbedtls/x509_crl.h" +#include "mbedtls/oid.h" +#include "mbedtls/error.h" + +#include +#include +#include +#if defined(MBEDTLS_FS_IO) +#include +#include +#endif + +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include +#endif + +/** + * Initializes the pkcs7 structure. + */ +void mbedtls_pkcs7_init( mbedtls_pkcs7 *pkcs7 ) +{ + memset( pkcs7, 0, sizeof( *pkcs7 ) ); +} + +static int pkcs7_get_next_content_len( unsigned char **p, unsigned char *end, + size_t *len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_CONTEXT_SPECIFIC ); + if( ret != 0 ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret ); + } + + return( ret ); +} + +/** + * version Version + * Version ::= INTEGER + **/ +static int pkcs7_get_version( unsigned char **p, unsigned char *end, int *ver ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_asn1_get_int( p, end, ver ); + if( ret != 0 ) + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_VERSION, ret ); + + /* If version != 1, return invalid version */ + if( *ver != MBEDTLS_PKCS7_SUPPORTED_VERSION ) + ret = MBEDTLS_ERR_PKCS7_INVALID_VERSION; + + return( ret ); +} + +/** + * ContentInfo ::= SEQUENCE { + * contentType ContentType, + * content + * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL } + **/ +static int pkcs7_get_content_info_type( unsigned char **p, unsigned char *end, + mbedtls_pkcs7_buf *pkcs7 ) +{ + size_t len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *start = *p; + + ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SEQUENCE ); + if( ret != 0 ) { + *p = start; + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret ); + goto out; + } + + ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OID ); + if( ret != 0 ) { + *p = start; + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret ); + goto out; + } + + pkcs7->tag = MBEDTLS_ASN1_OID; + pkcs7->len = len; + pkcs7->p = *p; + *p += len; + +out: + return( ret ); +} + +/** + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * This is from x509.h + **/ +static int pkcs7_get_digest_algorithm( unsigned char **p, unsigned char *end, + mbedtls_x509_buf *alg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 ) + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret ); + + return( ret ); +} + +/** + * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier + **/ +static int pkcs7_get_digest_algorithm_set( unsigned char **p, + unsigned char *end, + mbedtls_x509_buf *alg ) +{ + size_t len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SET ); + if( ret != 0 ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret ); + goto out; + } + + end = *p + len; + + ret = mbedtls_asn1_get_alg_null( p, end, alg ); + if( ret != 0 ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret ); + goto out; + } + + /** For now, it assumes there is only one digest algorithm specified **/ + if ( *p != end ) + ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; + +out: + return( ret ); +} + +/** + * certificates :: SET OF ExtendedCertificateOrCertificate, + * ExtendedCertificateOrCertificate ::= CHOICE { + * certificate Certificate -- x509, + * extendedCertificate[0] IMPLICIT ExtendedCertificate } + * Return number of certificates added to the signed data, + * 0 or higher is valid. + * Return negative error code for failure. + **/ +static int pkcs7_get_certificates( unsigned char **p, unsigned char *end, + mbedtls_x509_crt *certs ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len1 = 0; + size_t len2 = 0; + unsigned char *end_set, *end_cert, *start; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + ret = 0; + else + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret ); + goto out; + } + start = *p; + end_set = *p + len1; + + ret = mbedtls_asn1_get_tag( p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SEQUENCE ); + if( ret != 0 ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CERT, ret ); + goto out; + } + + end_cert = *p + len2; + + /* + * This is to verify that there is only one signer certificate. It seems it is + * not easy to differentiate between the chain vs different signer's certificate. + * So, we support only the root certificate and the single signer. + * The behaviour would be improved with addition of multiple signer support. + */ + if ( end_cert != end_set ) + { + ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; + goto out; + } + + *p = start; + if( ( ret = mbedtls_x509_crt_parse_der( certs, *p, len1 ) ) < 0 ) + { + ret = MBEDTLS_ERR_PKCS7_INVALID_CERT; + goto out; + } + + *p = *p + len1; + + /* + * Since in this version we strictly support single certificate, and reaching + * here implies we have parsed successfully, we return 1. + */ + ret = 1; + +out: + return( ret ); +} + +/** + * EncryptedDigest ::= OCTET STRING + **/ +static int pkcs7_get_signature( unsigned char **p, unsigned char *end, + mbedtls_pkcs7_buf *signature ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OCTET_STRING ); + if( ret != 0 ) + goto out; + + signature->tag = MBEDTLS_ASN1_OCTET_STRING; + signature->len = len; + signature->p = *p; + + *p = *p + len; + +out: + return( ret ); +} + +/** + * SignerInfo ::= SEQUENCE { + * version Version; + * issuerAndSerialNumber IssuerAndSerialNumber, + * digestAlgorithm DigestAlgorithmIdentifier, + * authenticatedAttributes + * [0] IMPLICIT Attributes OPTIONAL, + * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier, + * encryptedDigest EncryptedDigest, + * unauthenticatedAttributes + * [1] IMPLICIT Attributes OPTIONAL, + * Returns 0 if the signerInfo is valid. + * Return negative error code for failure. + * Structure must not contain vales for authenticatedAttributes + * and unauthenticatedAttributes. + **/ +static int pkcs7_get_signer_info( unsigned char **p, unsigned char *end, + mbedtls_pkcs7_signer_info *signer ) +{ + unsigned char *end_signer; + int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + asn1_ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SEQUENCE ); + if( asn1_ret != 0 ) + goto out; + + end_signer = *p + len; + + ret = pkcs7_get_version( p, end_signer, &signer->version ); + if( ret != 0 ) + goto out; + + asn1_ret = mbedtls_asn1_get_tag( p, end_signer, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ); + if( asn1_ret != 0 ) + goto out; + + /* Parsing IssuerAndSerialNumber */ + signer->issuer_raw.p = *p; + + asn1_ret = mbedtls_asn1_get_tag( p, end_signer, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ); + if( asn1_ret != 0 ) + goto out; + + ret = mbedtls_x509_get_name( p, *p + len, &signer->issuer ); + if( ret != 0 ) + goto out; + + signer->issuer_raw.len = *p - signer->issuer_raw.p; + + ret = mbedtls_x509_get_serial( p, end_signer, &signer->serial ); + if( ret != 0 ) + goto out; + + ret = pkcs7_get_digest_algorithm( p, end_signer, &signer->alg_identifier ); + if( ret != 0 ) + goto out; + + /* Asssume authenticatedAttributes is nonexistent */ + + ret = pkcs7_get_digest_algorithm( p, end_signer, &signer->sig_alg_identifier ); + if( ret != 0 ) + goto out; + + ret = pkcs7_get_signature( p, end_signer, &signer->sig ); + if( ret != 0 ) + goto out; + + /* Do not permit any unauthenticated attributes */ + if( *p != end_signer ) + ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO; + +out: + if( asn1_ret != 0 ) + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, + asn1_ret ); + else if( ret != 0 ) + ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO; + + return( ret ); +} + +static void pkcs7_free_signer_info( mbedtls_pkcs7_signer_info *signer ) +{ + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + + if( signer == NULL ) + return; + + name_cur = signer->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_free( name_prv ); + } +} + +/** + * SignerInfos ::= SET of SignerInfo + * Return number of signers added to the signed data, + * 0 or higher is valid. + * Return negative error code for failure. + **/ +static int pkcs7_get_signers_info_set( unsigned char **p, unsigned char *end, + mbedtls_pkcs7_signer_info *signers_set ) +{ + unsigned char *end_set; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int count = 0; + size_t len = 0; + mbedtls_pkcs7_signer_info *signer, *prev; + + ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SET ); + if( ret != 0 ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret ); + goto out; + } + + /* Detect zero signers */ + if( len == 0 ) + { + ret = 0; + goto out; + } + + end_set = *p + len; + + ret = pkcs7_get_signer_info( p, end_set, signers_set ); + if( ret != 0 ) + goto out; + count++; + + prev = signers_set; + while( *p != end_set ) + { + signer = mbedtls_calloc( 1, sizeof( mbedtls_pkcs7_signer_info ) ); + if( !signer ) + { + ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED; + goto cleanup; + } + + ret = pkcs7_get_signer_info( p, end_set, signer ); + if( ret != 0 ) { + mbedtls_free( signer ); + goto cleanup; + } + prev->next = signer; + prev = signer; + count++; + } + + ret = count; + goto out; + +cleanup: + signer = signers_set->next; + pkcs7_free_signer_info( signers_set ); + while( signer ) + { + prev = signer; + signer = signer->next; + pkcs7_free_signer_info( prev ); + mbedtls_free( prev ); + } + +out: + return( ret ); +} + +/** + * SignedData ::= SEQUENCE { + * version Version, + * digestAlgorithms DigestAlgorithmIdentifiers, + * contentInfo ContentInfo, + * certificates + * [0] IMPLICIT ExtendedCertificatesAndCertificates + * OPTIONAL, + * crls + * [0] IMPLICIT CertificateRevocationLists OPTIONAL, + * signerInfos SignerInfos } + */ +static int pkcs7_get_signed_data( unsigned char *buf, size_t buflen, + mbedtls_pkcs7_signed_data *signed_data ) +{ + unsigned char *p = buf; + unsigned char *end = buf + buflen; + unsigned char *end_set; + size_t len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_alg; + + ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED + | MBEDTLS_ASN1_SEQUENCE ); + if( ret != 0 ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret ); + goto out; + } + + end_set = p + len; + + /* Get version of signed data */ + ret = pkcs7_get_version( &p, end_set, &signed_data->version ); + if( ret != 0 ) + goto out; + + /* Get digest algorithm */ + ret = pkcs7_get_digest_algorithm_set( &p, end_set, + &signed_data->digest_alg_identifiers ); + if( ret != 0 ) + goto out; + + ret = mbedtls_oid_get_md_alg( &signed_data->digest_alg_identifiers, &md_alg ); + if( ret != 0 ) + { + ret = MBEDTLS_ERR_PKCS7_INVALID_ALG; + goto out; + } + + /* Do not expect any content */ + ret = pkcs7_get_content_info_type( &p, end_set, &signed_data->content.oid ); + if( ret != 0 ) + goto out; + + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &signed_data->content.oid ) ) + { + ret = MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO; + goto out; + } + + /* Look for certificates, there may or may not be any */ + mbedtls_x509_crt_init( &signed_data->certs ); + ret = pkcs7_get_certificates( &p, end_set, &signed_data->certs ); + if( ret < 0 ) + goto out; + + signed_data->no_of_certs = ret; + + /* + * Currently CRLs are not supported. If CRL exist, the parsing will fail + * at next step of getting signers info and return error as invalid + * signer info. + */ + + signed_data->no_of_crls = 0; + + /* Get signers info */ + ret = pkcs7_get_signers_info_set( &p, end_set, &signed_data->signers ); + if( ret < 0 ) + goto out; + + signed_data->no_of_signers = ret; + + /* Don't permit trailing data */ + if ( p != end ) + ret = MBEDTLS_ERR_PKCS7_INVALID_FORMAT; + else + ret = 0; + +out: + return( ret ); +} + +int mbedtls_pkcs7_parse_der( mbedtls_pkcs7 *pkcs7, const unsigned char *buf, + const size_t buflen ) +{ + unsigned char *p; + unsigned char *end; + size_t len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int isoidset = 0; + + if( !pkcs7 ) + { + ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; + goto out; + } + + /* make an internal copy of the buffer for parsing */ + pkcs7->raw.p = p = mbedtls_calloc( 1, buflen ); + if( pkcs7->raw.p == NULL ) + { + ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED; + goto out; + } + memcpy( p, buf, buflen ); + pkcs7->raw.len = buflen; + end = p + buflen; + + ret = pkcs7_get_content_info_type( &p, end, &pkcs7->content_type_oid ); + if( ret != 0 ) + { + len = buflen; + goto try_data; + } + + if( ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &pkcs7->content_type_oid ) + || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid ) + || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENVELOPED_DATA, &pkcs7->content_type_oid ) + || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, &pkcs7->content_type_oid ) + || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DIGESTED_DATA, &pkcs7->content_type_oid ) + || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid ) ) + { + ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; + goto out; + } + + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_SIGNED_DATA, &pkcs7->content_type_oid ) ) + { + ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; + goto out; + } + + isoidset = 1; + + ret = pkcs7_get_next_content_len( &p, end, &len ); + if( ret != 0 ) + goto out; + +try_data: + ret = pkcs7_get_signed_data( p, len, &pkcs7->signed_data ); + if ( ret != 0 ) + goto out; + + if ( !isoidset ) + { + pkcs7->content_type_oid.tag = MBEDTLS_ASN1_OID; + pkcs7->content_type_oid.len = MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS7_SIGNED_DATA ); + pkcs7->content_type_oid.p = (unsigned char *)MBEDTLS_OID_PKCS7_SIGNED_DATA; + } + + ret = MBEDTLS_PKCS7_SIGNED_DATA; + +out: + if ( ret < 0 ) + mbedtls_pkcs7_free( pkcs7 ); + + return( ret ); +} + +static int mbedtls_pkcs7_data_or_hash_verify( mbedtls_pkcs7 *pkcs7, + const mbedtls_x509_crt *cert, + const unsigned char *data, + size_t datalen, + const int is_data_hash ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *hash; + mbedtls_pk_context pk_cxt = cert->pk; + const mbedtls_md_info_t *md_info; + mbedtls_md_type_t md_alg; + mbedtls_pkcs7_signer_info *signer; + + if( pkcs7->signed_data.no_of_signers == 0 ) + { + ret = MBEDTLS_ERR_PKCS7_INVALID_CERT; + goto out; + } + + if( mbedtls_x509_time_is_past( &cert->valid_to ) || + mbedtls_x509_time_is_future( &cert->valid_from )) + { + ret = MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID; + goto out; + } + + /* + * Potential TODOs + * Currently we iterate over all signers and return success if any of them + * verify. + * + * However, we could make this better by checking against the certificate's + * identification and SignerIdentifier fields first. That would also allow + * us to distinguish between 'no signature for key' and 'signature for key + * failed to validate'. + * + * We could also cache hashes by md, so if there are several sigs all using + * the same algo we don't recalculate the hash each time. + */ + for( signer = &pkcs7->signed_data.signers; signer; signer = signer->next ) + { + ret = mbedtls_oid_get_md_alg( &signer->alg_identifier, &md_alg ); + if( ret != 0 ) + { + ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL; + continue; + } + + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + { + ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL; + continue; + } + + hash = mbedtls_calloc( mbedtls_md_get_size( md_info ), 1 ); + if( hash == NULL ) { + ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED; + goto out; + } + if( is_data_hash ) + { + if( datalen != mbedtls_md_get_size( md_info )) + ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL; + else + memcpy(hash, data, datalen); + } + else + { + ret = mbedtls_md( md_info, data, datalen, hash ); + } + if( ret != 0 ) + { + ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL; + mbedtls_free( hash ); + continue; + } + + ret = mbedtls_pk_verify( &pk_cxt, md_alg, hash, + mbedtls_md_get_size( md_info ), + signer->sig.p, signer->sig.len ); + mbedtls_free( hash ); + + if( ret == 0 ) + break; + } + +out: + return( ret ); +} +int mbedtls_pkcs7_signed_data_verify( mbedtls_pkcs7 *pkcs7, + const mbedtls_x509_crt *cert, + const unsigned char *data, + size_t datalen ) +{ + return( mbedtls_pkcs7_data_or_hash_verify( pkcs7, cert, data, datalen, 0 ) ); +} + +int mbedtls_pkcs7_signed_hash_verify( mbedtls_pkcs7 *pkcs7, + const mbedtls_x509_crt *cert, + const unsigned char *hash, + size_t hashlen ) +{ + return( mbedtls_pkcs7_data_or_hash_verify( pkcs7, cert, hash, hashlen, 1 ) ); +} + +/* + * Unallocate all pkcs7 data + */ +void mbedtls_pkcs7_free( mbedtls_pkcs7 *pkcs7 ) +{ + mbedtls_pkcs7_signer_info *signer_cur; + mbedtls_pkcs7_signer_info *signer_prev; + + if( pkcs7 == NULL || pkcs7->raw.p == NULL ) + return; + + mbedtls_free( pkcs7->raw.p ); + + mbedtls_x509_crt_free( &pkcs7->signed_data.certs ); + mbedtls_x509_crl_free( &pkcs7->signed_data.crl ); + + signer_cur = pkcs7->signed_data.signers.next; + pkcs7_free_signer_info( &pkcs7->signed_data.signers ); + while( signer_cur != NULL ) + { + signer_prev = signer_cur; + signer_cur = signer_prev->next; + pkcs7_free_signer_info( signer_prev ); + mbedtls_free( signer_prev ); + } + + pkcs7->raw.p = NULL; +} + +#endif diff --git a/library/poly1305.c b/library/poly1305.c index 0850f66a34..4d0cdee257 100644 --- a/library/poly1305.c +++ b/library/poly1305.c @@ -32,11 +32,6 @@ #if !defined(MBEDTLS_POLY1305_ALT) -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - #define POLY1305_BLOCK_SIZE_BYTES ( 16U ) /* diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 2ce5e4320d..e881f2f3cb 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -877,20 +877,7 @@ static psa_status_t psa_restrict_key_policy( return( PSA_SUCCESS ); } -/** Get the description of a key given its identifier and policy constraints - * and lock it. - * - * The key must have allow all the usage flags set in \p usage. If \p alg is - * nonzero, the key must allow operations with this algorithm. If \p alg is - * zero, the algorithm is not checked. - * - * In case of a persistent key, the function loads the description of the key - * into a key slot if not already done. - * - * On success, the returned key slot is locked. It is the responsibility of - * the caller to unlock the key slot when it does not access it anymore. - */ -static psa_status_t psa_get_and_lock_key_slot_with_policy( +psa_status_t psa_get_and_lock_key_slot_with_policy( mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot, psa_key_usage_t usage, @@ -3467,8 +3454,8 @@ psa_status_t psa_cipher_encrypt( mbedtls_svc_key_id_t key, status = psa_driver_wrapper_cipher_encrypt( &attributes, slot->key.data, slot->key.bytes, alg, local_iv, default_iv_length, input, input_length, - output + default_iv_length, output_size - default_iv_length, - output_length ); + mbedtls_buffer_offset( output, default_iv_length ), + output_size - default_iv_length, output_length ); exit: unlock_status = psa_unlock_key_slot( slot ); diff --git a/library/psa_crypto_cipher.c b/library/psa_crypto_cipher.c index 70dc74d748..91a0e3b30d 100644 --- a/library/psa_crypto_cipher.c +++ b/library/psa_crypto_cipher.c @@ -516,10 +516,10 @@ psa_status_t mbedtls_psa_cipher_encrypt( if( status != PSA_SUCCESS ) goto exit; - status = mbedtls_psa_cipher_finish( &operation, - output + update_output_length, - output_size - update_output_length, - &finish_output_length ); + status = mbedtls_psa_cipher_finish( + &operation, + mbedtls_buffer_offset( output, update_output_length ), + output_size - update_output_length, &finish_output_length ); if( status != PSA_SUCCESS ) goto exit; @@ -563,17 +563,20 @@ psa_status_t mbedtls_psa_cipher_decrypt( goto exit; } - status = mbedtls_psa_cipher_update( &operation, input + operation.iv_length, - input_length - operation.iv_length, - output, output_size, &olength ); + status = mbedtls_psa_cipher_update( + &operation, + mbedtls_buffer_offset_const( input, operation.iv_length ), + input_length - operation.iv_length, + output, output_size, &olength ); if( status != PSA_SUCCESS ) goto exit; accumulated_length = olength; - status = mbedtls_psa_cipher_finish( &operation, output + accumulated_length, - output_size - accumulated_length, - &olength ); + status = mbedtls_psa_cipher_finish( + &operation, + mbedtls_buffer_offset( output, accumulated_length ), + output_size - accumulated_length, &olength ); if( status != PSA_SUCCESS ) goto exit; diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 98638481c8..5cefa273aa 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -183,6 +183,24 @@ static inline psa_key_slot_number_t psa_key_slot_get_slot_number( } #endif +/** Get the description of a key given its identifier and policy constraints + * and lock it. + * + * The key must have allow all the usage flags set in \p usage. If \p alg is + * nonzero, the key must allow operations with this algorithm. If \p alg is + * zero, the algorithm is not checked. + * + * In case of a persistent key, the function loads the description of the key + * into a key slot if not already done. + * + * On success, the returned key slot is locked. It is the responsibility of + * the caller to unlock the key slot when it does not access it anymore. + */ +psa_status_t psa_get_and_lock_key_slot_with_policy( mbedtls_svc_key_id_t key, + psa_key_slot_t **p_slot, + psa_key_usage_t usage, + psa_algorithm_t alg ); + /** Completely wipe a slot in memory, including its policy. * * Persistent storage is not affected. diff --git a/library/psa_crypto_pake.c b/library/psa_crypto_pake.c index 870b5b5654..659b712a5b 100644 --- a/library/psa_crypto_pake.c +++ b/library/psa_crypto_pake.c @@ -248,6 +248,7 @@ psa_status_t psa_pake_set_password_key( psa_pake_operation_t *operation, psa_key_attributes_t attributes = psa_key_attributes_init(); psa_key_type_t type; psa_key_usage_t usage; + psa_key_slot_t *slot = NULL; if( operation->alg == PSA_ALG_NONE || operation->state != PSA_PAKE_STATE_SETUP ) @@ -273,7 +274,27 @@ psa_status_t psa_pake_set_password_key( psa_pake_operation_t *operation, if( ( usage & PSA_KEY_USAGE_DERIVE ) == 0 ) return( PSA_ERROR_NOT_PERMITTED ); - operation->password = password; + if( operation->password != NULL ) + return( PSA_ERROR_BAD_STATE ); + + status = psa_get_and_lock_key_slot_with_policy( password, &slot, + PSA_KEY_USAGE_DERIVE, + PSA_ALG_JPAKE ); + if( status != PSA_SUCCESS ) + return( status ); + + operation->password = mbedtls_calloc( 1, slot->key.bytes ); + if( operation->password == NULL ) + { + psa_unlock_key_slot( slot ); + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + } + memcpy( operation->password, slot->key.data, slot->key.bytes ); + operation->password_len = slot->key.bytes; + + status = psa_unlock_key_slot( slot ); + if( status != PSA_SUCCESS ) + return( status ); return( PSA_SUCCESS ); } @@ -348,9 +369,7 @@ psa_status_t psa_pake_set_role( psa_pake_operation_t *operation, static psa_status_t psa_pake_ecjpake_setup( psa_pake_operation_t *operation ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_ecjpake_role role; - psa_key_slot_t *slot = NULL; if( operation->role == PSA_PAKE_ROLE_CLIENT ) role = MBEDTLS_ECJPAKE_CLIENT; @@ -359,22 +378,20 @@ static psa_status_t psa_pake_ecjpake_setup( psa_pake_operation_t *operation ) else return( PSA_ERROR_BAD_STATE ); - if( psa_is_valid_key_id( operation->password, 1 ) == 0 ) + if( operation->password_len == 0 ) return( PSA_ERROR_BAD_STATE ); - status = psa_get_and_lock_key_slot( operation->password, &slot ); - if( status != PSA_SUCCESS ) - return( status ); - - ret = mbedtls_ecjpake_setup( &operation->ctx.ecjpake, role, MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, - slot->key.data, slot->key.bytes ); + operation->password, + operation->password_len ); - psa_unlock_key_slot( slot ); - slot = NULL; + mbedtls_platform_zeroize( operation->password, operation->password_len ); + mbedtls_free( operation->password ); + operation->password = NULL; + operation->password_len = 0; if( ret != 0 ) return( mbedtls_ecjpake_to_psa_error( ret ) ); @@ -840,7 +857,11 @@ psa_status_t psa_pake_abort(psa_pake_operation_t * operation) { operation->input_step = PSA_PAKE_STEP_INVALID; operation->output_step = PSA_PAKE_STEP_INVALID; - operation->password = MBEDTLS_SVC_KEY_ID_INIT; + if( operation->password_len > 0 ) + mbedtls_platform_zeroize( operation->password, operation->password_len ); + mbedtls_free( operation->password ); + operation->password = NULL; + operation->password_len = 0; operation->role = PSA_PAKE_ROLE_NONE; mbedtls_platform_zeroize( operation->buffer, MBEDTLS_PSA_PAKE_BUFFER_SIZE ); operation->buffer_length = 0; diff --git a/library/ssl_misc.h b/library/ssl_misc.h index 4d7f63547d..1902d715d2 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -50,17 +50,13 @@ #include "mbedtls/sha512.h" #endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + !defined(MBEDTLS_USE_PSA_CRYPTO) #include "mbedtls/ecjpake.h" #endif #include "common.h" -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - /* Shorthand for restartable ECC */ #if defined(MBEDTLS_ECP_RESTARTABLE) && \ defined(MBEDTLS_SSL_CLI_C) && \ @@ -776,7 +772,13 @@ struct mbedtls_ssl_handshake_params #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_pake_operation_t psa_pake_ctx; /*!< EC J-PAKE key exchange */ + mbedtls_svc_key_id_t psa_pake_password; + uint8_t psa_pake_ctx_is_ok; +#else mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_CLI_C) unsigned char *ecjpake_cache; /*!< Cache for ClientHello ext */ size_t ecjpake_cache_len; /*!< Length of cached data */ @@ -2493,6 +2495,52 @@ static inline int psa_ssl_status_to_mbedtls( psa_status_t status ) } #endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) + +typedef enum { + MBEDTLS_ECJPAKE_ROUND_ONE, + MBEDTLS_ECJPAKE_ROUND_TWO +} mbedtls_ecjpake_rounds_t; + +/** + * \brief Parse the provided input buffer for getting the first round + * of key exchange. This code is common between server and client + * + * \param pake_ctx [in] the PAKE's operation/context structure + * \param buf [in] input buffer to parse + * \param len [in] length of the input buffer + * \param round [in] either MBEDTLS_ECJPAKE_ROUND_ONE or + * MBEDTLS_ECJPAKE_ROUND_TWO + * + * \return 0 on success or a negative error code in case of failure + */ +int mbedtls_psa_ecjpake_read_round( + psa_pake_operation_t *pake_ctx, + const unsigned char *buf, + size_t len, mbedtls_ecjpake_rounds_t round ); + +/** + * \brief Write the first round of key exchange into the provided output + * buffer. This code is common between server and client + * + * \param pake_ctx [in] the PAKE's operation/context structure + * \param buf [out] the output buffer in which data will be written to + * \param len [in] length of the output buffer + * \param olen [out] the length of the data really written on the buffer + * \param round [in] either MBEDTLS_ECJPAKE_ROUND_ONE or + * MBEDTLS_ECJPAKE_ROUND_TWO + * + * \return 0 on success or a negative error code in case of failure + */ +int mbedtls_psa_ecjpake_write_round( + psa_pake_operation_t *pake_ctx, + unsigned char *buf, + size_t len, size_t *olen, + mbedtls_ecjpake_rounds_t round ); + +#endif //MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO + /** * \brief TLS record protection modes */ diff --git a/library/ssl_msg.c b/library/ssl_msg.c index 085233c151..732c346b9e 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -1904,7 +1904,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) ); mbedtls_ssl_set_timer( ssl, 0 ); - if( mbedtls_ssl_is_handshake_over( ssl ) == 0 ) + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) { if( ssl_double_retransmit_timeout( ssl ) != 0 ) { @@ -5296,7 +5296,7 @@ static int ssl_tls13_check_new_session_ticket( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 3, ( "NewSessionTicket received" ) ); mbedtls_ssl_handshake_set_state( ssl, - MBEDTLS_SSL_NEW_SESSION_TICKET ); + MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET ); return( MBEDTLS_ERR_SSL_WANT_READ ); } @@ -5499,7 +5499,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) } #endif - if( mbedtls_ssl_is_handshake_over( ssl ) == 0 ) + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) { ret = mbedtls_ssl_handshake( ssl ); if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && @@ -5755,7 +5755,7 @@ int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_ } #endif - if( mbedtls_ssl_is_handshake_over( ssl ) == 0 ) + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) { if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) { diff --git a/library/ssl_tls.c b/library/ssl_tls.c index da90b2350f..3d3491bc6c 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -907,7 +907,12 @@ static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) mbedtls_ecdh_init( &handshake->ecdh_ctx ); #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + handshake->psa_pake_ctx = psa_pake_operation_init(); + handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT; +#else mbedtls_ecjpake_init( &handshake->ecjpake_ctx ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_CLI_C) handshake->ecjpake_cache = NULL; handshake->ecjpake_cache_len = 0; @@ -1850,6 +1855,73 @@ void mbedtls_ssl_set_verify( mbedtls_ssl_context *ssl, /* * Set EC J-PAKE password for current handshake */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ) +{ + psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init(); + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_pake_role_t psa_role; + psa_status_t status; + + if( ssl->handshake == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + psa_role = PSA_PAKE_ROLE_SERVER; + else + psa_role = PSA_PAKE_ROLE_CLIENT; + + /* Empty password is not valid */ + if( ( pw == NULL) || ( pw_len == 0 ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE ); + psa_set_key_algorithm( &attributes, PSA_ALG_JPAKE ); + psa_set_key_type( &attributes, PSA_KEY_TYPE_PASSWORD ); + + status = psa_import_key( &attributes, pw, pw_len, + &ssl->handshake->psa_pake_password ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + + psa_pake_cs_set_algorithm( &cipher_suite, PSA_ALG_JPAKE ); + psa_pake_cs_set_primitive( &cipher_suite, + PSA_PAKE_PRIMITIVE( PSA_PAKE_PRIMITIVE_TYPE_ECC, + PSA_ECC_FAMILY_SECP_R1, + 256) ); + psa_pake_cs_set_hash( &cipher_suite, PSA_ALG_SHA_256 ); + + status = psa_pake_setup( &ssl->handshake->psa_pake_ctx, &cipher_suite ); + if( status != PSA_SUCCESS ) + { + psa_destroy_key( ssl->handshake->psa_pake_password ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_pake_set_role( &ssl->handshake->psa_pake_ctx, psa_role ); + if( status != PSA_SUCCESS ) + { + psa_destroy_key( ssl->handshake->psa_pake_password ); + psa_pake_abort( &ssl->handshake->psa_pake_ctx ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + psa_pake_set_password_key( &ssl->handshake->psa_pake_ctx, + ssl->handshake->psa_pake_password ); + if( status != PSA_SUCCESS ) + { + psa_destroy_key( ssl->handshake->psa_pake_password ); + psa_pake_abort( &ssl->handshake->psa_pake_ctx ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + ssl->handshake->psa_pake_ctx_is_ok = 1; + + return( 0 ); +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, const unsigned char *pw, size_t pw_len ) @@ -1870,6 +1942,7 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, MBEDTLS_ECP_DP_SECP256R1, pw, pw_len ) ); } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) @@ -3602,7 +3675,7 @@ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ) if( ssl == NULL || ssl->conf == NULL || ssl->handshake == NULL || - mbedtls_ssl_is_handshake_over( ssl ) == 1 ) + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) { return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } @@ -3706,7 +3779,7 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); /* Main handshake loop */ - while( mbedtls_ssl_is_handshake_over( ssl ) == 0 ) + while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) { ret = mbedtls_ssl_handshake_step( ssl ); @@ -3908,8 +3981,15 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) #if !defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECDH_C) mbedtls_ecdh_free( &handshake->ecdh_ctx ); #endif + #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_pake_abort( &handshake->psa_pake_ctx ); + psa_destroy_key( handshake->psa_pake_password ); + handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT; +#else mbedtls_ecjpake_free( &handshake->ecjpake_ctx ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_CLI_C) mbedtls_free( handshake->ecjpake_cache ); handshake->ecjpake_cache = NULL; @@ -6123,6 +6203,55 @@ static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, else #endif { +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + psa_status_t status; + psa_algorithm_t alg = PSA_ALG_TLS12_ECJPAKE_TO_PMS; + psa_key_derivation_operation_t derivation = + PSA_KEY_DERIVATION_OPERATION_INIT; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "perform PSA-based PMS KDF for ECJPAKE" ) ); + + handshake->pmslen = PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE; + + status = psa_key_derivation_setup( &derivation, alg ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + + status = psa_key_derivation_set_capacity( &derivation, + PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_pake_get_implicit_key( &handshake->psa_pake_ctx, + &derivation ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_output_bytes( &derivation, + handshake->premaster, + handshake->pmslen ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_abort( &derivation ); + if( status != PSA_SUCCESS ) + { + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, lbl, seed, seed_len, master, @@ -7544,7 +7673,7 @@ void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) #endif mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl ); - ssl->state++; + ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER; MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); } @@ -8306,6 +8435,99 @@ end: return( ret ); } +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_psa_ecjpake_read_round( + psa_pake_operation_t *pake_ctx, + const unsigned char *buf, + size_t len, mbedtls_ecjpake_rounds_t round ) +{ + psa_status_t status; + size_t input_offset = 0; + /* + * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice + * At round two perform a single cycle + */ + unsigned int remaining_steps = ( round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1; + + for( ; remaining_steps > 0; remaining_steps-- ) + { + for( psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE; + step <= PSA_PAKE_STEP_ZK_PROOF; + ++step ) + { + /* Length is stored at the first byte */ + size_t length = buf[input_offset]; + input_offset += 1; + + if( input_offset + length > len ) + { + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + + status = psa_pake_input( pake_ctx, step, + buf + input_offset, length ); + if( status != PSA_SUCCESS) + { + return psa_ssl_status_to_mbedtls( status ); + } + + input_offset += length; + } + } + + if( input_offset != len ) + return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + + return( 0 ); +} + +int mbedtls_psa_ecjpake_write_round( + psa_pake_operation_t *pake_ctx, + unsigned char *buf, + size_t len, size_t *olen, + mbedtls_ecjpake_rounds_t round ) +{ + psa_status_t status; + size_t output_offset = 0; + size_t output_len; + /* + * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice + * At round two perform a single cycle + */ + unsigned int remaining_steps = ( round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1; + + for( ; remaining_steps > 0; remaining_steps-- ) + { + for( psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE; + step <= PSA_PAKE_STEP_ZK_PROOF; + ++step ) + { + /* + * For each step, prepend 1 byte with the length of the data as + * given by psa_pake_output(). + */ + status = psa_pake_output( pake_ctx, step, + buf + output_offset + 1, + len - output_offset - 1, + &output_len ); + if( status != PSA_SUCCESS ) + { + return( psa_ssl_status_to_mbedtls( status ) ); + } + + *(buf + output_offset) = (uint8_t) output_len; + + output_offset += output_len + 1; + } + } + + *olen = output_offset; + + return( 0 ); +} +#endif //MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO + #if defined(MBEDTLS_USE_PSA_CRYPTO) int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, unsigned char *hash, size_t *hashlen, @@ -8864,8 +9086,13 @@ int mbedtls_ssl_validate_ciphersuite( #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_CLI_C) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + ssl->handshake->psa_pake_ctx_is_ok != 1 ) +#else if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ { return( -1 ); } diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c index 21b3ba6216..79c884b18c 100644 --- a/library/ssl_tls12_client.c +++ b/library/ssl_tls12_client.c @@ -132,13 +132,18 @@ static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; - size_t kkpp_len; + size_t kkpp_len = 0; *olen = 0; /* Skip costly extension if we can't use EC J-PAKE anyway */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ssl->handshake->psa_pake_ctx_is_ok != 1 ) + return( 0 ); +#else if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) return( 0 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding ecjpake_kkpp extension" ) ); @@ -158,6 +163,18 @@ static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, { MBEDTLS_SSL_DEBUG_MSG( 3, ( "generating new ecjpake parameters" ) ); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, + p + 2, end - p - 2, &kkpp_len, + MBEDTLS_ECJPAKE_ROUND_ONE ); + if ( ret != 0 ) + { + psa_destroy_key( ssl->handshake->psa_pake_password ); + psa_pake_abort( &ssl->handshake->psa_pake_ctx ); + MBEDTLS_SSL_DEBUG_RET( 1 , "psa_pake_output", ret ); + return( ret ); + } +#else ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, p + 2, end - p - 2, &kkpp_len, ssl->conf->f_rng, ssl->conf->p_rng ); @@ -167,6 +184,7 @@ static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, "mbedtls_ecjpake_write_round_one", ret ); return( ret ); } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ ssl->handshake->ecjpake_cache = mbedtls_calloc( 1, kkpp_len ); if( ssl->handshake->ecjpake_cache == NULL ) @@ -849,10 +867,11 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, ssl->handshake->ecdh_ctx.point_format = p[0]; #endif /* !MBEDTLS_USE_PSA_CRYPTO && ( MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ) */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) mbedtls_ecjpake_set_point_format( &ssl->handshake->ecjpake_ctx, p[0] ); -#endif +#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); return( 0 ); } @@ -889,6 +908,24 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, ssl->handshake->ecjpake_cache = NULL; ssl->handshake->ecjpake_cache_len = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ( ret = mbedtls_psa_ecjpake_read_round( + &ssl->handshake->psa_pake_ctx, buf, len, + MBEDTLS_ECJPAKE_ROUND_ONE ) ) != 0 ) + { + psa_destroy_key( ssl->handshake->psa_pake_password ); + psa_pake_abort( &ssl->handshake->psa_pake_ctx ); + + MBEDTLS_SSL_DEBUG_RET( 1, "psa_pake_input round one", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( ret ); + } + + return( 0 ); +#else if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, buf, len ) ) != 0 ) { @@ -901,6 +938,7 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, } return( 0 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ @@ -2296,6 +2334,47 @@ start_processing: #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* + * The first 3 bytes are: + * [0] MBEDTLS_ECP_TLS_NAMED_CURVE + * [1, 2] elliptic curve's TLS ID + * + * However since we only support secp256r1 for now, we check only + * that TLS ID here + */ + uint16_t read_tls_id = MBEDTLS_GET_UINT16_BE( p, 1 ); + const mbedtls_ecp_curve_info *curve_info; + + if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( + MBEDTLS_ECP_DP_SECP256R1 ) ) == NULL ) + { + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + if( ( *p != MBEDTLS_ECP_TLS_NAMED_CURVE ) || + ( read_tls_id != curve_info->tls_id ) ) + { + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + p += 3; + + if( ( ret = mbedtls_psa_ecjpake_read_round( + &ssl->handshake->psa_pake_ctx, p, end - p, + MBEDTLS_ECJPAKE_ROUND_TWO ) ) != 0 ) + { + psa_destroy_key( ssl->handshake->psa_pake_password ); + psa_pake_abort( &ssl->handshake->psa_pake_ctx ); + + MBEDTLS_SSL_DEBUG_RET( 1, "psa_pake_input round two", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } +#else ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, p, end - p ); if( ret != 0 ) @@ -2307,6 +2386,7 @@ start_processing: MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ @@ -3227,6 +3307,21 @@ ecdh_calc_secret: { header_len = 4; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + unsigned char *out_p = ssl->out_msg + header_len; + unsigned char *end_p = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN - + header_len; + ret = mbedtls_psa_ecjpake_write_round( &ssl->handshake->psa_pake_ctx, + out_p, end_p - out_p, &content_len, + MBEDTLS_ECJPAKE_ROUND_TWO ); + if ( ret != 0 ) + { + psa_destroy_key( ssl->handshake->psa_pake_password ); + psa_pake_abort( &ssl->handshake->psa_pake_ctx ); + MBEDTLS_SSL_DEBUG_RET( 1 , "psa_pake_output", ret ); + return( ret ); + } +#else ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, ssl->out_msg + header_len, MBEDTLS_SSL_OUT_CONTENT_LEN - header_len, @@ -3246,6 +3341,7 @@ ecdh_calc_secret: MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); return( ret ); } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c index 3dab2467c6..8aa89c67e5 100644 --- a/library/ssl_tls12_server.c +++ b/library/ssl_tls12_server.c @@ -268,10 +268,11 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, ssl->handshake->ecdh_ctx.point_format = p[0]; #endif /* !MBEDTLS_USE_PSA_CRYPTO && ( MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ) */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) mbedtls_ecjpake_set_point_format( &ssl->handshake->ecjpake_ctx, p[0] ); -#endif +#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); return( 0 ); } @@ -289,16 +290,37 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, const unsigned char *buf, - size_t len ) + size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ssl->handshake->psa_pake_ctx_is_ok != 1 ) +#else if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ { MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); return( 0 ); } +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ( ret = mbedtls_psa_ecjpake_read_round( + &ssl->handshake->psa_pake_ctx, buf, len, + MBEDTLS_ECJPAKE_ROUND_ONE ) ) != 0 ) + { + psa_destroy_key( ssl->handshake->psa_pake_password ); + psa_pake_abort( &ssl->handshake->psa_pake_ctx ); + + MBEDTLS_SSL_DEBUG_RET( 1, "psa_pake_input round one", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + + return( ret ); + } +#else if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, buf, len ) ) != 0 ) { @@ -307,6 +329,7 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( ret ); } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Only mark the extension as OK when we're sure it is */ ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK; @@ -1996,6 +2019,18 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0 ); p += 2; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = mbedtls_psa_ecjpake_write_round( &ssl->handshake->psa_pake_ctx, + p + 2, end - p - 2, &kkpp_len, + MBEDTLS_ECJPAKE_ROUND_ONE ); + if ( ret != 0 ) + { + psa_destroy_key( ssl->handshake->psa_pake_password ); + psa_pake_abort( &ssl->handshake->psa_pake_ctx ); + MBEDTLS_SSL_DEBUG_RET( 1 , "psa_pake_output", ret ); + return; + } +#else ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, p + 2, end - p - 2, &kkpp_len, ssl->conf->f_rng, ssl->conf->p_rng ); @@ -2004,6 +2039,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); return; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_PUT_UINT16_BE( kkpp_len, p, 0 ); p += 2; @@ -2813,6 +2849,46 @@ static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + unsigned char *out_p = ssl->out_msg + ssl->out_msglen; + unsigned char *end_p = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN - + ssl->out_msglen; + size_t output_offset = 0; + size_t output_len = 0; + const mbedtls_ecp_curve_info *curve_info; + + /* + * The first 3 bytes are: + * [0] MBEDTLS_ECP_TLS_NAMED_CURVE + * [1, 2] elliptic curve's TLS ID + * + * However since we only support secp256r1 for now, we hardcode its + * TLS ID here + */ + if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( + MBEDTLS_ECP_DP_SECP256R1 ) ) == NULL ) + { + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + *out_p = MBEDTLS_ECP_TLS_NAMED_CURVE; + MBEDTLS_PUT_UINT16_BE( curve_info->tls_id, out_p, 1 ); + output_offset += 3; + + ret = mbedtls_psa_ecjpake_write_round( &ssl->handshake->psa_pake_ctx, + out_p + output_offset, + end_p - out_p - output_offset, &output_len, + MBEDTLS_ECJPAKE_ROUND_TWO ); + if( ret != 0 ) + { + psa_destroy_key( ssl->handshake->psa_pake_password ); + psa_pake_abort( &ssl->handshake->psa_pake_ctx ); + MBEDTLS_SSL_DEBUG_RET( 1 , "psa_pake_output", ret ); + return( ret ); + } + + output_offset += output_len; + ssl->out_msglen += output_offset; +#else size_t len = 0; ret = mbedtls_ecjpake_write_round_two( @@ -2827,6 +2903,7 @@ static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, } ssl->out_msglen += len; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ @@ -4044,6 +4121,18 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ( ret = mbedtls_psa_ecjpake_read_round( + &ssl->handshake->psa_pake_ctx, p, end - p, + MBEDTLS_ECJPAKE_ROUND_TWO ) ) != 0 ) + { + psa_destroy_key( ssl->handshake->psa_pake_password ); + psa_pake_abort( &ssl->handshake->psa_pake_ctx ); + + MBEDTLS_SSL_DEBUG_RET( 1, "psa_pake_input round two", ret ); + return( ret ); + } +#else ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, p, end - p ); if( ret != 0 ) @@ -4060,6 +4149,7 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); return( ret ); } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index 0372f2d98d..0109f776c0 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -1183,11 +1183,11 @@ int mbedtls_ssl_tls13_write_client_hello_exts( mbedtls_ssl_context *ssl, return( ret ); p += ext_len; - /* Initializes the status to `indication sent`. It will be updated to - * `accepted` or `rejected` depending on whether the EncryptedExtension - * message will contain an early data indication extension or not. + /* Initializes the status to `rejected`. It will be updated to + * `accepted` if the EncryptedExtension message contain an early data + * indication extension. */ - ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_INDICATION_SENT; + ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED; } else { @@ -2060,6 +2060,21 @@ static int ssl_tls13_parse_encrypted_extensions( mbedtls_ssl_context *ssl, break; #endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_EARLY_DATA) + case MBEDTLS_TLS_EXT_EARLY_DATA: + + if( extension_data_len != 0 ) + { + /* The message must be empty. */ + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + break; +#endif /* MBEDTLS_SSL_EARLY_DATA */ + default: MBEDTLS_SSL_PRINT_EXT( 3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, @@ -2102,6 +2117,14 @@ static int ssl_tls13_process_encrypted_extensions( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_PROC_CHK( ssl_tls13_parse_encrypted_extensions( ssl, buf, buf + buf_len ) ); +#if defined(MBEDTLS_SSL_EARLY_DATA) + if( ssl->handshake->received_extensions & + MBEDTLS_SSL_EXT_MASK( EARLY_DATA ) ) + { + ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED; + } +#endif + mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, buf, buf_len ); @@ -2743,7 +2766,7 @@ static int ssl_tls13_postprocess_new_session_ticket( mbedtls_ssl_context *ssl, } /* - * Handler for MBEDTLS_SSL_NEW_SESSION_TICKET + * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_new_session_ticket( mbedtls_ssl_context *ssl ) @@ -2857,7 +2880,7 @@ int mbedtls_ssl_tls13_handshake_client_step( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) - case MBEDTLS_SSL_NEW_SESSION_TICKET: + case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET: ret = ssl_tls13_process_new_session_ticket( ssl ); if( ret != 0 ) break; diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c index 3cd03108f6..ce8767c5fd 100644 --- a/library/ssl_tls13_server.c +++ b/library/ssl_tls13_server.c @@ -2628,7 +2628,7 @@ static int ssl_tls13_handshake_wrapup( mbedtls_ssl_context *ssl ) mbedtls_ssl_tls13_handshake_wrapup( ssl ); #if defined(MBEDTLS_SSL_SESSION_TICKETS) - mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_NEW_SESSION_TICKET ); + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET ); #else mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_HANDSHAKE_OVER ); #endif @@ -2636,7 +2636,7 @@ static int ssl_tls13_handshake_wrapup( mbedtls_ssl_context *ssl ) } /* - * Handler for MBEDTLS_SSL_NEW_SESSION_TICKET + * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET */ #define SSL_NEW_SESSION_TICKET_SKIP 0 #define SSL_NEW_SESSION_TICKET_WRITE 1 @@ -2872,7 +2872,7 @@ static int ssl_tls13_write_new_session_ticket_body( mbedtls_ssl_context *ssl, } /* - * Handler for MBEDTLS_SSL_NEW_SESSION_TICKET + * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET */ static int ssl_tls13_write_new_session_ticket( mbedtls_ssl_context *ssl ) { @@ -2908,8 +2908,8 @@ static int ssl_tls13_write_new_session_ticket( mbedtls_ssl_context *ssl ) else ssl->handshake->new_session_tickets_count--; - mbedtls_ssl_handshake_set_state( ssl, - MBEDTLS_SSL_NEW_SESSION_TICKET_FLUSH ); + mbedtls_ssl_handshake_set_state( + ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH ); } else { @@ -3045,7 +3045,7 @@ int mbedtls_ssl_tls13_handshake_server_step( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) - case MBEDTLS_SSL_NEW_SESSION_TICKET: + case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET: ret = ssl_tls13_write_new_session_ticket( ssl ); if( ret != 0 ) { @@ -3054,9 +3054,9 @@ int mbedtls_ssl_tls13_handshake_server_step( mbedtls_ssl_context *ssl ) ret ); } break; - case MBEDTLS_SSL_NEW_SESSION_TICKET_FLUSH: + case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH: /* This state is necessary to do the flush of the New Session - * Ticket message written in MBEDTLS_SSL_NEW_SESSION_TICKET + * Ticket message written in MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET * as part of ssl_prepare_handshake_step. */ ret = 0; @@ -3064,7 +3064,7 @@ int mbedtls_ssl_tls13_handshake_server_step( mbedtls_ssl_context *ssl ) if( ssl->handshake->new_session_tickets_count == 0 ) mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_HANDSHAKE_OVER ); else - mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_NEW_SESSION_TICKET ); + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET ); break; #endif /* MBEDTLS_SSL_SESSION_TICKETS */ diff --git a/programs/fuzz/.gitignore b/programs/fuzz/.gitignore index 5dc0960551..34e3ed0882 100644 --- a/programs/fuzz/.gitignore +++ b/programs/fuzz/.gitignore @@ -1,6 +1,7 @@ fuzz_client fuzz_dtlsclient fuzz_dtlsserver +fuzz_pkcs7 fuzz_privkey fuzz_pubkey fuzz_server diff --git a/programs/fuzz/CMakeLists.txt b/programs/fuzz/CMakeLists.txt index c7fcd356bc..7747744cd1 100644 --- a/programs/fuzz/CMakeLists.txt +++ b/programs/fuzz/CMakeLists.txt @@ -12,6 +12,7 @@ set(executables_no_common_c fuzz_x509crl fuzz_x509crt fuzz_x509csr + fuzz_pkcs7 ) set(executables_with_common_c diff --git a/programs/fuzz/fuzz_pkcs7.c b/programs/fuzz/fuzz_pkcs7.c new file mode 100644 index 0000000000..960007d7ab --- /dev/null +++ b/programs/fuzz/fuzz_pkcs7.c @@ -0,0 +1,19 @@ +#include +#include "mbedtls/pkcs7.h" + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { +#ifdef MBEDTLS_PKCS7_C + mbedtls_pkcs7 pkcs7; + + mbedtls_pkcs7_init( &pkcs7 ); + + mbedtls_pkcs7_parse_der( &pkcs7, Data, Size ); + + mbedtls_pkcs7_free( &pkcs7 ); +#else + (void) Data; + (void) Size; +#endif + + return 0; +} diff --git a/programs/fuzz/fuzz_pkcs7.options b/programs/fuzz/fuzz_pkcs7.options new file mode 100644 index 0000000000..0824b19fab --- /dev/null +++ b/programs/fuzz/fuzz_pkcs7.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65535 diff --git a/scripts/config.py b/scripts/config.py index 470c63dc8f..7e58acd0a4 100755 --- a/scripts/config.py +++ b/scripts/config.py @@ -311,6 +311,7 @@ def include_in_crypto(name): if name in [ 'MBEDTLS_DEBUG_C', # part of libmbedtls 'MBEDTLS_NET_C', # part of libmbedtls + 'MBEDTLS_PKCS7_C', # part of libmbedx509 ]: return False return True diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl index 41b03377d0..5395abf419 100755 --- a/scripts/generate_errors.pl +++ b/scripts/generate_errors.pl @@ -52,7 +52,7 @@ my @low_level_modules = qw( AES ARIA ASN1 BASE64 BIGNUM SHA1 SHA256 SHA512 THREADING ); my @high_level_modules = qw( CIPHER DHM ECP MD PEM PK PKCS12 PKCS5 - RSA SSL X509 ); + RSA SSL X509 PKCS7 ); undef $/; @@ -136,6 +136,7 @@ foreach my $match (@matches) $define_name = "ASN1_PARSE" if ($define_name eq "ASN1"); $define_name = "SSL_TLS" if ($define_name eq "SSL"); $define_name = "PEM_PARSE,PEM_WRITE" if ($define_name eq "PEM"); + $define_name = "PKCS7" if ($define_name eq "PKCS7"); my $include_name = $module_name; $include_name =~ tr/A-Z/a-z/; diff --git a/scripts/mbedtls_dev/bignum_common.py b/scripts/mbedtls_dev/bignum_common.py index 8b11bc283c..67ea78db46 100644 --- a/scripts/mbedtls_dev/bignum_common.py +++ b/scripts/mbedtls_dev/bignum_common.py @@ -15,7 +15,12 @@ # limitations under the License. from abc import abstractmethod -from typing import Iterator, List, Tuple, TypeVar +from typing import Iterator, List, Tuple, TypeVar, Any +from itertools import chain + +from . import test_case +from . import test_data_generation +from .bignum_data import INPUTS_DEFAULT, MODULI_DEFAULT T = TypeVar('T') #pylint: disable=invalid-name @@ -63,8 +68,7 @@ def combination_pairs(values: List[T]) -> List[Tuple[T, T]]: """Return all pair combinations from input values.""" return [(x, y) for x in values for y in values] - -class OperationCommon: +class OperationCommon(test_data_generation.BaseTest): """Common features for bignum binary operations. This adds functionality common in binary operation tests. @@ -78,22 +82,106 @@ class OperationCommon: unique_combinations_only: Boolean to select if test case combinations must be unique. If True, only A,B or B,A would be included as a test case. If False, both A,B and B,A would be included. + input_style: Controls the way how test data is passed to the functions + in the generated test cases. "variable" passes them as they are + defined in the python source. "arch_split" pads the values with + zeroes depending on the architecture/limb size. If this is set, + test cases are generated for all architectures. + arity: the number of operands for the operation. Currently supported + values are 1 and 2. """ symbol = "" - input_values = [] # type: List[str] - input_cases = [] # type: List[Tuple[str, str]] - unique_combinations_only = True + input_values = INPUTS_DEFAULT # type: List[str] + input_cases = [] # type: List[Any] + unique_combinations_only = False + input_styles = ["variable", "fixed", "arch_split"] # type: List[str] + input_style = "variable" # type: str + limb_sizes = [32, 64] # type: List[int] + arities = [1, 2] + arity = 2 - def __init__(self, val_a: str, val_b: str) -> None: - self.arg_a = val_a - self.arg_b = val_b + def __init__(self, val_a: str, val_b: str = "0", bits_in_limb: int = 32) -> None: + self.val_a = val_a + self.val_b = val_b + # Setting the int versions here as opposed to making them @properties + # provides earlier/more robust input validation. self.int_a = hex_to_int(val_a) self.int_b = hex_to_int(val_b) + if bits_in_limb not in self.limb_sizes: + raise ValueError("Invalid number of bits in limb!") + if self.input_style == "arch_split": + self.dependencies = ["MBEDTLS_HAVE_INT{:d}".format(bits_in_limb)] + self.bits_in_limb = bits_in_limb + + @property + def boundary(self) -> int: + if self.arity == 1: + return self.int_a + elif self.arity == 2: + return max(self.int_a, self.int_b) + raise ValueError("Unsupported number of operands!") + + @property + def limb_boundary(self) -> int: + return bound_mpi(self.boundary, self.bits_in_limb) + + @property + def limbs(self) -> int: + return limbs_mpi(self.boundary, self.bits_in_limb) + + @property + def hex_digits(self) -> int: + return 2 * (self.limbs * self.bits_in_limb // 8) + + def format_arg(self, val) -> str: + if self.input_style not in self.input_styles: + raise ValueError("Unknown input style!") + if self.input_style == "variable": + return val + else: + return val.zfill(self.hex_digits) + + def format_result(self, res) -> str: + res_str = '{:x}'.format(res) + return quote_str(self.format_arg(res_str)) + + @property + def arg_a(self) -> str: + return self.format_arg(self.val_a) + + @property + def arg_b(self) -> str: + if self.arity == 1: + raise AttributeError("Operation is unary and doesn't have arg_b!") + return self.format_arg(self.val_b) def arguments(self) -> List[str]: - return [ - quote_str(self.arg_a), quote_str(self.arg_b) - ] + self.result() + args = [quote_str(self.arg_a)] + if self.arity == 2: + args.append(quote_str(self.arg_b)) + return args + self.result() + + def description(self) -> str: + """Generate a description for the test case. + + If not set, case_description uses the form A `symbol` B, where symbol + is used to represent the operation. Descriptions of each value are + generated to provide some context to the test case. + """ + if not self.case_description: + if self.arity == 1: + self.case_description = "{} {:x}".format( + self.symbol, self.int_a + ) + elif self.arity == 2: + self.case_description = "{:x} {} {:x}".format( + self.int_a, self.symbol, self.int_b + ) + return super().description() + + @property + def is_valid(self) -> bool: + return True @abstractmethod def result(self) -> List[str]: @@ -111,15 +199,134 @@ class OperationCommon: Combinations are first generated from all input values, and then specific cases provided. """ - if cls.unique_combinations_only: - yield from combination_pairs(cls.input_values) + if cls.arity == 1: + yield from ((a, "0") for a in cls.input_values) + elif cls.arity == 2: + if cls.unique_combinations_only: + yield from combination_pairs(cls.input_values) + else: + yield from ( + (a, b) + for a in cls.input_values + for b in cls.input_values + ) else: - yield from ( - (a, b) - for a in cls.input_values - for b in cls.input_values - ) - yield from cls.input_cases + raise ValueError("Unsupported number of operands!") + + @classmethod + def generate_function_tests(cls) -> Iterator[test_case.TestCase]: + if cls.input_style not in cls.input_styles: + raise ValueError("Unknown input style!") + if cls.arity not in cls.arities: + raise ValueError("Unsupported number of operands!") + if cls.input_style == "arch_split": + test_objects = (cls(a, b, bits_in_limb=bil) + for a, b in cls.get_value_pairs() + for bil in cls.limb_sizes) + special_cases = (cls(*args, bits_in_limb=bil) # type: ignore + for args in cls.input_cases + for bil in cls.limb_sizes) + else: + test_objects = (cls(a, b) + for a, b in cls.get_value_pairs()) + special_cases = (cls(*args) for args in cls.input_cases) + yield from (valid_test_object.create_test_case() + for valid_test_object in filter( + lambda test_object: test_object.is_valid, + chain(test_objects, special_cases) + ) + ) + + +class ModOperationCommon(OperationCommon): + #pylint: disable=abstract-method + """Target for bignum mod_raw test case generation.""" + moduli = MODULI_DEFAULT # type: List[str] + + def __init__(self, val_n: str, val_a: str, val_b: str = "0", + bits_in_limb: int = 64) -> None: + super().__init__(val_a=val_a, val_b=val_b, bits_in_limb=bits_in_limb) + self.val_n = val_n + # Setting the int versions here as opposed to making them @properties + # provides earlier/more robust input validation. + self.int_n = hex_to_int(val_n) + + @property + def boundary(self) -> int: + return self.int_n + + @property + def arg_n(self) -> str: + return self.format_arg(self.val_n) + + def arguments(self) -> List[str]: + return [quote_str(self.arg_n)] + super().arguments() + + @property + def r(self) -> int: # pylint: disable=invalid-name + l = limbs_mpi(self.int_n, self.bits_in_limb) + return bound_mpi_limbs(l, self.bits_in_limb) + + @property + def r_inv(self) -> int: + return invmod(self.r, self.int_n) + + @property + def r2(self) -> int: # pylint: disable=invalid-name + return pow(self.r, 2) + + @property + def is_valid(self) -> bool: + if self.int_a >= self.int_n: + return False + if self.arity == 2 and self.int_b >= self.int_n: + return False + return True + + def description(self) -> str: + """Generate a description for the test case. + + It uses the form A `symbol` B mod N, where symbol is used to represent + the operation. + """ + + if not self.case_description: + return super().description() + " mod {:x}".format(self.int_n) + return super().description() + + @classmethod + def input_cases_args(cls) -> Iterator[Tuple[Any, Any, Any]]: + if cls.arity == 1: + yield from ((n, a, "0") for a, n in cls.input_cases) + elif cls.arity == 2: + yield from ((n, a, b) for a, b, n in cls.input_cases) + else: + raise ValueError("Unsupported number of operands!") + + @classmethod + def generate_function_tests(cls) -> Iterator[test_case.TestCase]: + if cls.input_style not in cls.input_styles: + raise ValueError("Unknown input style!") + if cls.arity not in cls.arities: + raise ValueError("Unsupported number of operands!") + if cls.input_style == "arch_split": + test_objects = (cls(n, a, b, bits_in_limb=bil) + for n in cls.moduli + for a, b in cls.get_value_pairs() + for bil in cls.limb_sizes) + special_cases = (cls(*args, bits_in_limb=bil) + for args in cls.input_cases_args() + for bil in cls.limb_sizes) + else: + test_objects = (cls(n, a, b) + for n in cls.moduli + for a, b in cls.get_value_pairs()) + special_cases = (cls(*args) for args in cls.input_cases_args()) + yield from (valid_test_object.create_test_case() + for valid_test_object in filter( + lambda test_object: test_object.is_valid, + chain(test_objects, special_cases) + )) # BEGIN MERGE SLOT 1 diff --git a/scripts/mbedtls_dev/bignum_core.py b/scripts/mbedtls_dev/bignum_core.py index 0cc86b8096..b8e2a31239 100644 --- a/scripts/mbedtls_dev/bignum_core.py +++ b/scripts/mbedtls_dev/bignum_core.py @@ -16,20 +16,19 @@ import random -from abc import ABCMeta from typing import Dict, Iterator, List, Tuple from . import test_case from . import test_data_generation from . import bignum_common -class BignumCoreTarget(test_data_generation.BaseTarget, metaclass=ABCMeta): - #pylint: disable=abstract-method +class BignumCoreTarget(test_data_generation.BaseTarget): + #pylint: disable=abstract-method, too-few-public-methods """Target for bignum core test case generation.""" target_basename = 'test_suite_bignum_core.generated' -class BignumCoreShiftR(BignumCoreTarget, metaclass=ABCMeta): +class BignumCoreShiftR(BignumCoreTarget, test_data_generation.BaseTest): """Test cases for mbedtls_bignum_core_shift_r().""" count = 0 test_function = "mpi_core_shift_r" @@ -69,7 +68,7 @@ class BignumCoreShiftR(BignumCoreTarget, metaclass=ABCMeta): for count in counts: yield cls(input_hex, descr, count).create_test_case() -class BignumCoreCTLookup(BignumCoreTarget, metaclass=ABCMeta): +class BignumCoreCTLookup(BignumCoreTarget, test_data_generation.BaseTest): """Test cases for mbedtls_mpi_core_ct_uint_table_lookup().""" test_function = "mpi_core_ct_uint_table_lookup" test_name = "Constant time MPI table lookup" @@ -107,104 +106,33 @@ class BignumCoreCTLookup(BignumCoreTarget, metaclass=ABCMeta): yield (cls(bitsize, bitsize_description, window_size) .create_test_case()) -class BignumCoreOperation(bignum_common.OperationCommon, BignumCoreTarget, metaclass=ABCMeta): - #pylint: disable=abstract-method - """Common features for bignum core operations.""" - input_values = [ - "0", "1", "3", "f", "fe", "ff", "100", "ff00", "fffe", "ffff", "10000", - "fffffffe", "ffffffff", "100000000", "1f7f7f7f7f7f7f", - "8000000000000000", "fefefefefefefefe", "fffffffffffffffe", - "ffffffffffffffff", "10000000000000000", "1234567890abcdef0", - "fffffffffffffffffefefefefefefefe", "fffffffffffffffffffffffffffffffe", - "ffffffffffffffffffffffffffffffff", "100000000000000000000000000000000", - "1234567890abcdef01234567890abcdef0", - "fffffffffffffffffffffffffffffffffffffffffffffffffefefefefefefefe", - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "10000000000000000000000000000000000000000000000000000000000000000", - "1234567890abcdef01234567890abcdef01234567890abcdef01234567890abcdef0", - ( - "4df72d07b4b71c8dacb6cffa954f8d88254b6277099308baf003fab73227f34029" - "643b5a263f66e0d3c3fa297ef71755efd53b8fb6cb812c6bbf7bcf179298bd9947" - "c4c8b14324140a2c0f5fad7958a69050a987a6096e9f055fb38edf0c5889eca4a0" - "cfa99b45fbdeee4c696b328ddceae4723945901ec025076b12b" - ) - ] - def description(self) -> str: - """Generate a description for the test case. - - If not set, case_description uses the form A `symbol` B, where symbol - is used to represent the operation. Descriptions of each value are - generated to provide some context to the test case. - """ - if not self.case_description: - self.case_description = "{:x} {} {:x}".format( - self.int_a, self.symbol, self.int_b - ) - return super().description() - - @classmethod - def generate_function_tests(cls) -> Iterator[test_case.TestCase]: - for a_value, b_value in cls.get_value_pairs(): - yield cls(a_value, b_value).create_test_case() - - -class BignumCoreOperationArchSplit(BignumCoreOperation): - #pylint: disable=abstract-method - """Common features for bignum core operations where the result depends on - the limb size.""" - - def __init__(self, val_a: str, val_b: str, bits_in_limb: int) -> None: - super().__init__(val_a, val_b) - bound_val = max(self.int_a, self.int_b) - self.bits_in_limb = bits_in_limb - self.bound = bignum_common.bound_mpi(bound_val, self.bits_in_limb) - limbs = bignum_common.limbs_mpi(bound_val, self.bits_in_limb) - byte_len = limbs * self.bits_in_limb // 8 - self.hex_digits = 2 * byte_len - if self.bits_in_limb == 32: - self.dependencies = ["MBEDTLS_HAVE_INT32"] - elif self.bits_in_limb == 64: - self.dependencies = ["MBEDTLS_HAVE_INT64"] - else: - raise ValueError("Invalid number of bits in limb!") - self.arg_a = self.arg_a.zfill(self.hex_digits) - self.arg_b = self.arg_b.zfill(self.hex_digits) - - def pad_to_limbs(self, val) -> str: - return "{:x}".format(val).zfill(self.hex_digits) - - @classmethod - def generate_function_tests(cls) -> Iterator[test_case.TestCase]: - for a_value, b_value in cls.get_value_pairs(): - yield cls(a_value, b_value, 32).create_test_case() - yield cls(a_value, b_value, 64).create_test_case() - -class BignumCoreAddAndAddIf(BignumCoreOperationArchSplit): +class BignumCoreAddAndAddIf(BignumCoreTarget, bignum_common.OperationCommon): """Test cases for bignum core add and add-if.""" count = 0 symbol = "+" test_function = "mpi_core_add_and_add_if" test_name = "mpi_core_add_and_add_if" + input_style = "arch_split" + unique_combinations_only = True def result(self) -> List[str]: result = self.int_a + self.int_b - carry, result = divmod(result, self.bound) + carry, result = divmod(result, self.limb_boundary) return [ - bignum_common.quote_str(self.pad_to_limbs(result)), + self.format_result(result), str(carry) ] -class BignumCoreSub(BignumCoreOperation): + +class BignumCoreSub(BignumCoreTarget, bignum_common.OperationCommon): """Test cases for bignum core sub.""" count = 0 symbol = "-" test_function = "mpi_core_sub" test_name = "mbedtls_mpi_core_sub" - unique_combinations_only = False def result(self) -> List[str]: if self.int_a >= self.int_b: @@ -224,12 +152,11 @@ class BignumCoreSub(BignumCoreOperation): ] -class BignumCoreMLA(BignumCoreOperation): +class BignumCoreMLA(BignumCoreTarget, bignum_common.OperationCommon): """Test cases for fixed-size multiply accumulate.""" count = 0 test_function = "mpi_core_mla" test_name = "mbedtls_mpi_core_mla" - unique_combinations_only = False input_values = [ "0", "1", "fffe", "ffffffff", "100000000", "20000000000000", @@ -288,6 +215,16 @@ class BignumCoreMLA(BignumCoreOperation): "\"{:x}\"".format(carry_8) ] + @classmethod + def get_value_pairs(cls) -> Iterator[Tuple[str, str]]: + """Generator to yield pairs of inputs. + + Combinations are first generated from all input values, and then + specific cases provided. + """ + yield from super().get_value_pairs() + yield from cls.input_cases + @classmethod def generate_function_tests(cls) -> Iterator[test_case.TestCase]: """Override for additional scalar input.""" @@ -297,7 +234,7 @@ class BignumCoreMLA(BignumCoreOperation): yield cur_op.create_test_case() -class BignumCoreMontmul(BignumCoreTarget): +class BignumCoreMontmul(BignumCoreTarget, test_data_generation.BaseTest): """Test cases for Montgomery multiplication.""" count = 0 test_function = "mpi_core_montmul" @@ -826,6 +763,37 @@ def mpi_modmul_case_generate() -> None: # BEGIN MERGE SLOT 3 +class BignumCoreSubInt(BignumCoreTarget, bignum_common.OperationCommon): + """Test cases for bignum core sub int.""" + count = 0 + symbol = "-" + test_function = "mpi_core_sub_int" + test_name = "mpi_core_sub_int" + input_style = "arch_split" + + @property + def is_valid(self) -> bool: + # This is "sub int", so b is only one limb + if bignum_common.limbs_mpi(self.int_b, self.bits_in_limb) > 1: + return False + return True + + # Overriding because we don't want leading zeros on b + @property + def arg_b(self) -> str: + return self.val_b + + def result(self) -> List[str]: + result = self.int_a - self.int_b + + borrow, result = divmod(result, self.limb_boundary) + + # Borrow will be -1 if non-zero, but we want it to be 1 in the test data + return [ + self.format_result(result), + str(-borrow) + ] + # END MERGE SLOT 3 # BEGIN MERGE SLOT 4 diff --git a/scripts/mbedtls_dev/bignum_data.py b/scripts/mbedtls_dev/bignum_data.py new file mode 100644 index 0000000000..74d21d0ca5 --- /dev/null +++ b/scripts/mbedtls_dev/bignum_data.py @@ -0,0 +1,136 @@ +"""Base values and datasets for bignum generated tests and helper functions that +produced them.""" +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import random + +# Functions calling these were used to produce test data and are here only for +# reproducability, they are not used by the test generation framework/classes +try: + from Cryptodome.Util.number import isPrime, getPrime #type: ignore #pylint: disable=import-error +except ImportError: + pass + +# Generated by bignum_common.gen_safe_prime(192,1) +SAFE_PRIME_192_BIT_SEED_1 = "d1c127a667786703830500038ebaef20e5a3e2dc378fb75b" + +# First number generated by random.getrandbits(192) - seed(2,2), not a prime +RANDOM_192_BIT_SEED_2_NO1 = "177219d30e7a269fd95bafc8f2a4d27bdcf4bb99f4bea973" + +# Second number generated by random.getrandbits(192) - seed(2,2), not a prime +RANDOM_192_BIT_SEED_2_NO2 = "cf1822ffbc6887782b491044d5e341245c6e433715ba2bdd" + +# Third number generated by random.getrandbits(192) - seed(2,2), not a prime +RANDOM_192_BIT_SEED_2_NO3 = "3653f8dd9b1f282e4067c3584ee207f8da94e3e8ab73738f" + +# Fourth number generated by random.getrandbits(192) - seed(2,2), not a prime +RANDOM_192_BIT_SEED_2_NO4 = "ffed9235288bc781ae66267594c9c9500925e4749b575bd1" + +# Ninth number generated by random.getrandbits(192) - seed(2,2), not a prime +RANDOM_192_BIT_SEED_2_NO9 = "2a1be9cd8697bbd0e2520e33e44c50556c71c4a66148a86f" + +# Generated by bignum_common.gen_safe_prime(1024,3) +SAFE_PRIME_1024_BIT_SEED_3 = ("c93ba7ec74d96f411ba008bdb78e63ff11bb5df46a51e16b" + "2c9d156f8e4e18abf5e052cb01f47d0d1925a77f60991577" + "e128fb6f52f34a27950a594baadd3d8057abeb222cf3cca9" + "62db16abf79f2ada5bd29ab2f51244bf295eff9f6aaba130" + "2efc449b128be75eeaca04bc3c1a155d11d14e8be32a2c82" + "87b3996cf6ad5223") + +# First number generated by random.getrandbits(1024) - seed(4,2), not a prime +RANDOM_1024_BIT_SEED_4_NO1 = ("6905269ed6f0b09f165c8ce36e2f24b43000de01b2ed40ed" + "3addccb2c33be0ac79d679346d4ac7a5c3902b38963dc6e8" + "534f45738d048ec0f1099c6c3e1b258fd724452ccea71ff4" + "a14876aeaff1a098ca5996666ceab360512bd13110722311" + "710cf5327ac435a7a97c643656412a9b8a1abcd1a6916c74" + "da4f9fc3c6da5d7") + +# Second number generated by random.getrandbits(1024) - seed(4,2), not a prime +RANDOM_1024_BIT_SEED_4_NO2 = ("f1cfd99216df648647adec26793d0e453f5082492d83a823" + "3fb62d2c81862fc9634f806fabf4a07c566002249b191bf4" + "d8441b5616332aca5f552773e14b0190d93936e1daca3c06" + "f5ff0c03bb5d7385de08caa1a08179104a25e4664f5253a0" + "2a3187853184ff27459142deccea264542a00403ce80c4b0" + "a4042bb3d4341aad") + +# Third number generated by random.getrandbits(1024) - seed(4,2), not a prime +RANDOM_1024_BIT_SEED_4_NO3 = ("14c15c910b11ad28cc21ce88d0060cc54278c2614e1bcb38" + "3bb4a570294c4ea3738d243a6e58d5ca49c7b59b995253fd" + "6c79a3de69f85e3131f3b9238224b122c3e4a892d9196ada" + "4fcfa583e1df8af9b474c7e89286a1754abcb06ae8abb93f" + "01d89a024cdce7a6d7288ff68c320f89f1347e0cdd905ecf" + "d160c5d0ef412ed6") + +# Fourth number generated by random.getrandbits(1024) - seed(4,2), not a prime +RANDOM_1024_BIT_SEED_4_NO4 = ("32decd6b8efbc170a26a25c852175b7a96b98b5fbf37a2be" + "6f98bca35b17b9662f0733c846bbe9e870ef55b1a1f65507" + "a2909cb633e238b4e9dd38b869ace91311021c9e32111ac1" + "ac7cc4a4ff4dab102522d53857c49391b36cc9aa78a330a1" + "a5e333cb88dcf94384d4cd1f47ca7883ff5a52f1a05885ac" + "7671863c0bdbc23a") + +# Fifth number generated by random.getrandbits(1024) - seed(4,2), not a prime +RANDOM_1024_BIT_SEED_4_NO5 = ("53be4721f5b9e1f5acdac615bc20f6264922b9ccf469aef8" + "f6e7d078e55b85dd1525f363b281b8885b69dc230af5ac87" + "0692b534758240df4a7a03052d733dcdef40af2e54c0ce68" + "1f44ebd13cc75f3edcb285f89d8cf4d4950b16ffc3e1ac3b" + "4708d9893a973000b54a23020fc5b043d6e4a51519d9c9cc" + "52d32377e78131c1") + +# Adding 192 bit and 1024 bit numbers because these are the shortest required +# for ECC and RSA respectively. +INPUTS_DEFAULT = [ + "0", "1", # corner cases + "2", "3", # small primes + "4", # non-prime even + "38", # small random + SAFE_PRIME_192_BIT_SEED_1, # prime + RANDOM_192_BIT_SEED_2_NO1, # not a prime + RANDOM_192_BIT_SEED_2_NO2, # not a prime + SAFE_PRIME_1024_BIT_SEED_3, # prime + RANDOM_1024_BIT_SEED_4_NO1, # not a prime + RANDOM_1024_BIT_SEED_4_NO3, # not a prime + RANDOM_1024_BIT_SEED_4_NO2, # largest (not a prime) + ] + +# Only odd moduli are present as in the new bignum code only odd moduli are +# supported for now. +MODULI_DEFAULT = [ + "53", # safe prime + "45", # non-prime + SAFE_PRIME_192_BIT_SEED_1, # safe prime + RANDOM_192_BIT_SEED_2_NO4, # not a prime + SAFE_PRIME_1024_BIT_SEED_3, # safe prime + RANDOM_1024_BIT_SEED_4_NO5, # not a prime + ] + +def __gen_safe_prime(bits, seed): + ''' + Generate a safe prime. + + This function is intended for generating constants offline and shouldn't be + used in test generation classes. + + Requires pycryptodomex for getPrime and isPrime and python 3.9 or later for + randbytes. + ''' + rng = random.Random() + # We want reproducability across python versions + rng.seed(seed, version=2) + while True: + prime = 2*getPrime(bits-1, rng.randbytes)+1 #pylint: disable=no-member + if isPrime(prime, 1e-30): + return prime diff --git a/scripts/mbedtls_dev/bignum_mod.py b/scripts/mbedtls_dev/bignum_mod.py index 2bd7fbbda3..a604cc0c59 100644 --- a/scripts/mbedtls_dev/bignum_mod.py +++ b/scripts/mbedtls_dev/bignum_mod.py @@ -14,12 +14,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -from abc import ABCMeta - from . import test_data_generation -class BignumModTarget(test_data_generation.BaseTarget, metaclass=ABCMeta): - #pylint: disable=abstract-method +class BignumModTarget(test_data_generation.BaseTarget): + #pylint: disable=abstract-method, too-few-public-methods """Target for bignum mod test case generation.""" target_basename = 'test_suite_bignum_mod.generated' diff --git a/scripts/mbedtls_dev/bignum_mod_raw.py b/scripts/mbedtls_dev/bignum_mod_raw.py index bd694a6084..c271048548 100644 --- a/scripts/mbedtls_dev/bignum_mod_raw.py +++ b/scripts/mbedtls_dev/bignum_mod_raw.py @@ -14,95 +14,41 @@ # See the License for the specific language governing permissions and # limitations under the License. -from abc import ABCMeta -from typing import Dict, Iterator, List +from typing import Dict, List -from . import test_case from . import test_data_generation from . import bignum_common -class BignumModRawTarget(test_data_generation.BaseTarget, metaclass=ABCMeta): - #pylint: disable=abstract-method +class BignumModRawTarget(test_data_generation.BaseTarget): + #pylint: disable=abstract-method, too-few-public-methods """Target for bignum mod_raw test case generation.""" target_basename = 'test_suite_bignum_mod_raw.generated' -class BignumModRawOperation(bignum_common.OperationCommon, BignumModRawTarget, metaclass=ABCMeta): - #pylint: disable=abstract-method - """Target for bignum mod_raw test case generation.""" - - def __init__(self, val_n: str, val_a: str, val_b: str = "0", bits_in_limb: int = 64) -> None: - super().__init__(val_a=val_a, val_b=val_b) - self.val_n = val_n - self.bits_in_limb = bits_in_limb - - @property - def int_n(self) -> int: - return bignum_common.hex_to_int(self.val_n) - - @property - def boundary(self) -> int: - data_in = [self.int_a, self.int_b, self.int_n] - return max([n for n in data_in if n is not None]) - - @property - def limbs(self) -> int: - return bignum_common.limbs_mpi(self.boundary, self.bits_in_limb) - - @property - def hex_digits(self) -> int: - return 2 * (self.limbs * self.bits_in_limb // 8) - - @property - def hex_n(self) -> str: - return "{:x}".format(self.int_n).zfill(self.hex_digits) - - @property - def hex_a(self) -> str: - return "{:x}".format(self.int_a).zfill(self.hex_digits) - - @property - def hex_b(self) -> str: - return "{:x}".format(self.int_b).zfill(self.hex_digits) - - @property - def r(self) -> int: # pylint: disable=invalid-name - l = bignum_common.limbs_mpi(self.int_n, self.bits_in_limb) - return bignum_common.bound_mpi_limbs(l, self.bits_in_limb) - - @property - def r_inv(self) -> int: - return bignum_common.invmod(self.r, self.int_n) - - @property - def r2(self) -> int: # pylint: disable=invalid-name - return pow(self.r, 2) - -class BignumModRawOperationArchSplit(BignumModRawOperation): - #pylint: disable=abstract-method - """Common features for bignum mod raw operations where the result depends on - the limb size.""" - - limb_sizes = [32, 64] # type: List[int] - - def __init__(self, val_n: str, val_a: str, val_b: str = "0", bits_in_limb: int = 64) -> None: - super().__init__(val_n=val_n, val_a=val_a, val_b=val_b, bits_in_limb=bits_in_limb) - - if bits_in_limb not in self.limb_sizes: - raise ValueError("Invalid number of bits in limb!") - - self.dependencies = ["MBEDTLS_HAVE_INT{:d}".format(bits_in_limb)] - - @classmethod - def generate_function_tests(cls) -> Iterator[test_case.TestCase]: - for a_value, b_value in cls.get_value_pairs(): - for bil in cls.limb_sizes: - yield cls(a_value, b_value, bits_in_limb=bil).create_test_case() # BEGIN MERGE SLOT 1 # END MERGE SLOT 1 # BEGIN MERGE SLOT 2 +class BignumModRawSub(bignum_common.ModOperationCommon, + BignumModRawTarget): + """Test cases for bignum mpi_mod_raw_sub().""" + symbol = "-" + test_function = "mpi_mod_raw_sub" + test_name = "mbedtls_mpi_mod_raw_sub" + input_style = "fixed" + arity = 2 + + def arguments(self) -> List[str]: + return [bignum_common.quote_str(n) for n in [self.arg_a, + self.arg_b, + self.arg_n] + ] + self.result() + + def result(self) -> List[str]: + result = (self.int_a - self.int_b) % self.int_n + return [self.format_result(result)] + # END MERGE SLOT 2 # BEGIN MERGE SLOT 3 @@ -122,126 +68,35 @@ class BignumModRawOperationArchSplit(BignumModRawOperation): # END MERGE SLOT 6 # BEGIN MERGE SLOT 7 -class BignumModRawConvertToMont(BignumModRawOperationArchSplit): - """ Test cases for mpi_mod_raw_to_mont_rep(). """ +class BignumModRawConvertToMont(bignum_common.ModOperationCommon, + BignumModRawTarget): + """ Test cases for mpi_mod_raw_to_mont_rep(). """ test_function = "mpi_mod_raw_to_mont_rep" test_name = "Convert into Mont: " - - test_data_moduli = ["b", - "fd", - "eeff99aa37", - "eeff99aa11", - "800000000005", - "7fffffffffffffff", - "80fe000a10000001", - "25a55a46e5da99c71c7", - "1058ad82120c3a10196bb36229c1", - "7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f" - "18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a" - "98df75154f8c914a282f8b", - "8335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63", - "ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f" - "2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a6" - "4d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2" - "deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d" - "6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a0" - "7e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d389" - "8c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6" - "bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3a" - "d4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181d" - "b8896f33bb12e6ef73f12ec5c5ea7a8a337" - ] - - test_input_numbers = ["0", - "1", - "97", - "f5", - "6f5c3", - "745bfe50f7", - "ffa1f9924123", - "334a8b983c79bd", - "5b84f632b58f3461", - "19acd15bc38008e1", - "ffffffffffffffff", - "54ce6a6bb8247fa0427cfc75a6b0599", - "fecafe8eca052f154ce6a6bb8247fa019558bfeecce9bb9", - "a87d7a56fa4bfdc7da42ef798b9cf6843d4c54794698cb14d72" - "851dec9586a319f4bb6d5695acbd7c92e7a42a5ede6972adcbc" - "f68425265887f2d721f462b7f1b91531bac29fa648facb8e3c6" - "1bd5ae42d5a59ba1c89a95897bfe541a8ce1d633b98f379c481" - "6f25e21f6ac49286b261adb4b78274fe5f61c187581f213e84b" - "2a821e341ef956ecd5de89e6c1a35418cd74a549379d2d4594a" - "577543147f8e35b3514e62cf3e89d1156cdc91ab5f4c928fbd6" - "9148c35df5962fed381f4d8a62852a36823d5425f7487c13a12" - "523473fb823aa9d6ea5f42e794e15f2c1a8785cf6b7d51a4617" - "947fb3baf674f74a673cf1d38126983a19ed52c7439fab42c2185" - ] - - descr_tpl = '{} #{} N: \"{}\" A: \"{}\".' + symbol = "R *" + input_style = "arch_split" + arity = 1 def result(self) -> List[str]: - return [self.hex_x] + result = (self.int_a * self.r) % self.int_n + return [self.format_result(result)] - def arguments(self) -> List[str]: - return [bignum_common.quote_str(n) for n in [self.hex_n, - self.hex_a, - self.hex_x]] - def description(self) -> str: - return self.descr_tpl.format(self.test_name, - self.count, - self.int_n, - self.int_a) - - @classmethod - def generate_function_tests(cls) -> Iterator[test_case.TestCase]: - for bil in [32, 64]: - for n in cls.test_data_moduli: - for i in cls.test_input_numbers: - # Skip invalid combinations where A.limbs > N.limbs - if bignum_common.hex_to_int(i) > bignum_common.hex_to_int(n): - continue - yield cls(n, i, bits_in_limb=bil).create_test_case() - - @property - def x(self) -> int: # pylint: disable=invalid-name - return (self.int_a * self.r) % self.int_n - - @property - def hex_x(self) -> str: - return "{:x}".format(self.x).zfill(self.hex_digits) - -class BignumModRawConvertFromMont(BignumModRawConvertToMont): +class BignumModRawConvertFromMont(bignum_common.ModOperationCommon, + BignumModRawTarget): """ Test cases for mpi_mod_raw_from_mont_rep(). """ - test_function = "mpi_mod_raw_from_mont_rep" test_name = "Convert from Mont: " + symbol = "1/R *" + input_style = "arch_split" + arity = 1 + + def result(self) -> List[str]: + result = (self.int_a * self.r_inv) % self.int_n + return [self.format_result(result)] - test_input_numbers = ["0", - "1", - "3ca", - "539ed428", - "7dfe5c6beb35a2d6", - "dca8de1c2adfc6d7aafb9b48e", - "a7d17b6c4be72f3d5c16bf9c1af6fc933", - "2fec97beec546f9553142ed52f147845463f579", - "378dc83b8bc5a7b62cba495af4919578dce6d4f175cadc4f", - "b6415f2a1a8e48a518345db11f56db3829c8f2c6415ab4a395a" - "b3ac2ea4cbef4af86eb18a84eb6ded4c6ecbfc4b59c2879a675" - "487f687adea9d197a84a5242a5cf6125ce19a6ad2e7341f1c57" - "d43ea4f4c852a51cb63dabcd1c9de2b827a3146a3d175b35bea" - "41ae75d2a286a3e9d43623152ac513dcdea1d72a7da846a8ab3" - "58d9be4926c79cfb287cf1cf25b689de3b912176be5dcaf4d4c" - "6e7cb839a4a3243a6c47c1e2c99d65c59d6fa3672575c2f1ca8" - "de6a32e854ec9d8ec635c96af7679fce26d7d159e4a9da3bd74" - "e1272c376cd926d74fe3fb164a5935cff3d5cdb92b35fe2cea32" - "138a7e6bfbc319ebd1725dacb9a359cbf693f2ecb785efb9d627" - ] - @property - def x(self): # pylint: disable=invalid-name - return (self.int_a * self.r_inv) % self.int_n # END MERGE SLOT 7 # BEGIN MERGE SLOT 8 diff --git a/scripts/mbedtls_dev/test_data_generation.py b/scripts/mbedtls_dev/test_data_generation.py index eec0f9d978..02aa510518 100644 --- a/scripts/mbedtls_dev/test_data_generation.py +++ b/scripts/mbedtls_dev/test_data_generation.py @@ -25,6 +25,7 @@ import argparse import os import posixpath import re +import inspect from abc import ABCMeta, abstractmethod from typing import Callable, Dict, Iterable, Iterator, List, Type, TypeVar @@ -35,12 +36,8 @@ from . import test_case T = TypeVar('T') #pylint: disable=invalid-name -class BaseTarget(metaclass=ABCMeta): - """Base target for test case generation. - - Child classes of this class represent an output file, and can be referred - to as file targets. These indicate where test cases will be written to for - all subclasses of the file target, which is set by `target_basename`. +class BaseTest(metaclass=ABCMeta): + """Base class for test case generation. Attributes: count: Counter for test cases from this class. @@ -48,8 +45,6 @@ class BaseTarget(metaclass=ABCMeta): automatically generated using the class, or manually set. dependencies: A list of dependencies required for the test case. show_test_count: Toggle for inclusion of `count` in the test description. - target_basename: Basename of file to write generated tests to. This - should be specified in a child class of BaseTarget. test_function: Test function which the class generates cases for. test_name: A common name or description of the test function. This can be `test_function`, a clearer equivalent, or a short summary of the @@ -59,7 +54,6 @@ class BaseTarget(metaclass=ABCMeta): case_description = "" dependencies = [] # type: List[str] show_test_count = True - target_basename = "" test_function = "" test_name = "" @@ -121,6 +115,21 @@ class BaseTarget(metaclass=ABCMeta): """ raise NotImplementedError + +class BaseTarget: + #pylint: disable=too-few-public-methods + """Base target for test case generation. + + Child classes of this class represent an output file, and can be referred + to as file targets. These indicate where test cases will be written to for + all subclasses of the file target, which is set by `target_basename`. + + Attributes: + target_basename: Basename of file to write generated tests to. This + should be specified in a child class of BaseTarget. + """ + target_basename = "" + @classmethod def generate_tests(cls) -> Iterator[test_case.TestCase]: """Generate test cases for the class and its subclasses. @@ -132,7 +141,8 @@ class BaseTarget(metaclass=ABCMeta): yield from `generate_tests()` in each. Calling this method on a class X will yield test cases from all classes derived from X. """ - if cls.test_function: + if issubclass(cls, BaseTest) and not inspect.isabstract(cls): + #pylint: disable=no-member yield from cls.generate_function_tests() for subclass in sorted(cls.__subclasses__(), key=lambda c: c.__name__): yield from subclass.generate_tests() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c23cb6b3d9..0ef6fdbc4c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -70,6 +70,7 @@ if(GEN_FILES) ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_bignum_tests.py ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_common.py ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_core.py + ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_mod_raw.py ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_case.py ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_data_generation.py ) diff --git a/tests/Makefile b/tests/Makefile index 7c08f54e14..0b31cdd076 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -94,6 +94,7 @@ $(GENERATED_BIGNUM_DATA_FILES): generated_bignum_test_data generated_bignum_test_data: scripts/generate_bignum_tests.py generated_bignum_test_data: ../scripts/mbedtls_dev/bignum_common.py generated_bignum_test_data: ../scripts/mbedtls_dev/bignum_core.py +generated_bignum_test_data: ../scripts/mbedtls_dev/bignum_mod_raw.py generated_bignum_test_data: ../scripts/mbedtls_dev/test_case.py generated_bignum_test_data: ../scripts/mbedtls_dev/test_data_generation.py generated_bignum_test_data: diff --git a/tests/compat.sh b/tests/compat.sh index d681217127..529c2c5422 100755 --- a/tests/compat.sh +++ b/tests/compat.sh @@ -595,6 +595,20 @@ setup_arguments() G_CLIENT_ARGS="-p $PORT --debug 3 $G_MODE" G_CLIENT_PRIO="NONE:$G_PRIO_MODE:+COMP-NULL:+CURVE-ALL:+SIGN-ALL" + # Newer versions of OpenSSL have a syntax to enable all "ciphers", even + # low-security ones. This covers not just cipher suites but also protocol + # versions. It is necessary, for example, to use (D)TLS 1.0/1.1 on + # OpenSSL 1.1.1f from Ubuntu 20.04. The syntax was only introduced in + # OpenSSL 1.1.0 (21e0c1d23afff48601eb93135defddae51f7e2e3) and I can't find + # a way to discover it from -help, so check the openssl version. + case $($OPENSSL_CMD version) in + "OpenSSL 0"*|"OpenSSL 1.0"*) :;; + *) + O_CLIENT_ARGS="$O_CLIENT_ARGS -cipher ALL@SECLEVEL=0" + O_SERVER_ARGS="$O_SERVER_ARGS -cipher ALL@SECLEVEL=0" + ;; + esac + if [ "X$VERIFY" = "XYES" ]; then M_SERVER_ARGS="$M_SERVER_ARGS ca_file=data_files/test-ca_cat12.crt auth_mode=required" diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile index d4f2011e93..5591669d19 100644 --- a/tests/data_files/Makefile +++ b/tests/data_files/Makefile @@ -1139,6 +1139,108 @@ ecdsa_secp521r1.crt: ecdsa_secp521r1.csr all_final += ecdsa_secp521r1.crt ecdsa_secp521r1.key tls13_certs: ecdsa_secp521r1.crt ecdsa_secp521r1.key +# PKCS7 test data +pkcs7_test_cert_1 = pkcs7-rsa-sha256-1.crt +pkcs7_test_cert_2 = pkcs7-rsa-sha256-2.crt +pkcs7_test_file = pkcs7_data.bin + +$(pkcs7_test_file): + echo -e "Hello\xd" > $@ +all_final += $(pkcs7_test_file) + +pkcs7_data_1.bin: + echo -e "2\xd" > $@ +all_final += pkcs7_data_1.bin + +# Generate signing cert +pkcs7-rsa-sha256-1.crt: + $(OPENSSL) req -x509 -subj="/C=NL/O=PKCS7/CN=PKCS7 Cert 1" -sha256 -nodes -days 365 -newkey rsa:2048 -keyout pkcs7-rsa-sha256-1.key -out pkcs7-rsa-sha256-1.crt + cat pkcs7-rsa-sha256-1.crt pkcs7-rsa-sha256-1.key > pkcs7-rsa-sha256-1.pem +all_final += pkcs7-rsa-sha256-1.crt + +pkcs7-rsa-sha256-2.crt: + $(OPENSSL) req -x509 -subj="/C=NL/O=PKCS7/CN=PKCS7 Cert 2" -sha256 -nodes -days 365 -newkey rsa:2048 -keyout pkcs7-rsa-sha256-2.key -out pkcs7-rsa-sha256-2.crt + cat pkcs7-rsa-sha256-2.crt pkcs7-rsa-sha256-2.key > pkcs7-rsa-sha256-2.pem +all_final += pkcs7-rsa-sha256-2.crt + +# Convert signing certs to DER for testing PEM-free builds +pkcs7-rsa-sha256-1.der: $(pkcs7_test_cert_1) + $(OPENSSL) x509 -in pkcs7-rsa-sha256-1.crt -out $@ -outform DER +all_final += pkcs7-rsa-sha256-1.der + +pkcs7-rsa-sha256-2.der: $(pkcs7_test_cert_2) + $(OPENSSL) x509 -in pkcs7-rsa-sha256-2.crt -out $@ -outform DER +all_final += pkcs7-rsa-sha256-2.der + +# pkcs7 signature file with CERT +pkcs7_data_cert_signed_sha256.der: $(pkcs7_test_file) $(pkcs7_test_cert_1) + $(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha256 -signer pkcs7-rsa-sha256-1.pem -noattr -outform DER -out $@ +all_final += pkcs7_data_cert_signed_sha256.der + +# pkcs7 signature file with CERT and sha1 +pkcs7_data_cert_signed_sha1.der: $(pkcs7_test_file) $(pkcs7_test_cert_1) + $(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha1 -signer pkcs7-rsa-sha256-1.pem -noattr -outform DER -out $@ +all_final += pkcs7_data_cert_signed_sha1.der + +# pkcs7 signature file with CERT and sha512 +pkcs7_data_cert_signed_sha512.der: $(pkcs7_test_file) $(pkcs7_test_cert_1) + $(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha512 -signer pkcs7-rsa-sha256-1.pem -noattr -outform DER -out $@ +all_final += pkcs7_data_cert_signed_sha512.der + +# pkcs7 signature file without CERT +pkcs7_data_without_cert_signed.der: $(pkcs7_test_file) $(pkcs7_test_cert_1) + $(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha256 -signer pkcs7-rsa-sha256-1.pem -nocerts -noattr -outform DER -out $@ +all_final += pkcs7_data_without_cert_signed.der + +# pkcs7 signature file with multiple signers +pkcs7_data_multiple_signed.der: $(pkcs7_test_file) $(pkcs7_test_cert_1) $(pkcs7_test_cert_2) + $(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha256 -signer pkcs7-rsa-sha256-1.pem -signer pkcs7-rsa-sha256-2.pem -nocerts -noattr -outform DER -out $@ +all_final += pkcs7_data_multiple_signed.der + +# pkcs7 signature file with multiple certificates +pkcs7_data_multiple_certs_signed.der: $(pkcs7_test_file) $(pkcs7_test_cert_1) $(pkcs7_test_cert_2) + $(OPENSSL) smime -sign -binary -in pkcs7_data.bin -out $@ -md sha256 -signer pkcs7-rsa-sha256-1.pem -signer pkcs7-rsa-sha256-2.pem -noattr -outform DER -out $@ +all_final += pkcs7_data_multiple_certs_signed.der + +# pkcs7 signature file with corrupted CERT +pkcs7_data_signed_badcert.der: pkcs7_data_cert_signed_sha256.der + cp pkcs7_data_cert_signed_sha256.der $@ + echo -en '\xa1' | dd of=$@ bs=1 seek=547 conv=notrunc +all_final += pkcs7_data_signed_badcert.der + +# pkcs7 signature file with corrupted signer info +pkcs7_data_signed_badsigner.der: pkcs7_data_cert_signed_sha256.der + cp pkcs7_data_cert_signed_sha256.der $@ + echo -en '\xa1' | dd of=$@ bs=1 seek=918 conv=notrunc +all_final += pkcs7_data_signed_badsigner.der + +# pkcs7 file with version 2 +pkcs7_data_cert_signed_v2.der: pkcs7_data_cert_signed_sha256.der + cp pkcs7_data_cert_signed_sha256.der $@ + echo -en '\x02' | dd of=$@ bs=1 seek=25 conv=notrunc +all_final += pkcs7_data_cert_signed_v2.der + +pkcs7_data_cert_encrypted.der: $(pkcs7_test_file) $(pkcs7_test_cert_1) + $(OPENSSL) smime -encrypt -aes256 -in pkcs7_data.bin -binary -outform DER -out $@ pkcs7-rsa-sha256-1.crt +all_final += pkcs7_data_cert_encrypted.der + +## Negative tests +# For some interesting sizes, what happens if we make them off-by-one? +pkcs7_signerInfo_issuer_invalid_size.der: pkcs7_data_cert_signed_sha256.der + cp $< $@ + echo -en '\x35' | dd of=$@ seek=919 bs=1 conv=notrunc +all_final += pkcs7_signerInfo_issuer_invalid_size.der + +pkcs7_signerInfo_serial_invalid_size.der: pkcs7_data_cert_signed_sha256.der + cp $< $@ + echo -en '\x15' | dd of=$@ seek=973 bs=1 conv=notrunc +all_final += pkcs7_signerInfo_serial_invalid_size.der + +# pkcs7 signature file just with signed data +pkcs7_data_cert_signeddata_sha256.der: pkcs7_data_cert_signed_sha256.der + dd if=pkcs7_data_cert_signed_sha256.der of=$@ skip=19 bs=1 +all_final += pkcs7_data_cert_signeddata_sha256.der + ################################################################ #### Diffie-Hellman parameters ################################################################ diff --git a/tests/data_files/pkcs7-rsa-sha256-1.crt b/tests/data_files/pkcs7-rsa-sha256-1.crt new file mode 100644 index 0000000000..9e461cd0c6 --- /dev/null +++ b/tests/data_files/pkcs7-rsa-sha256-1.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDSTCCAjGgAwIBAgIUe97d0kRM0c3+XEGoECyJt98ubL8wDQYJKoZIhvcNAQEL +BQAwNDELMAkGA1UEBhMCTkwxDjAMBgNVBAoMBVBLQ1M3MRUwEwYDVQQDDAxQS0NT +NyBDZXJ0IDEwHhcNMjIxMDI4MTYxMDU2WhcNMjMxMDI4MTYxMDU2WjA0MQswCQYD +VQQGEwJOTDEOMAwGA1UECgwFUEtDUzcxFTATBgNVBAMMDFBLQ1M3IENlcnQgMTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMi2z2mJnNHw67TKZFwF5w4N +Lv7dzGHQicvVFaOaNXm5I0O2HsdQBg+07TeHYzJADkJfHTdsfnXClzMU7fS7MMj4 +3QO5/P+VWiRdSRN61uYAVsrBlVKoZdUhhxh8wELJxJ4+OpwXpTS0U82rwMsRO09j +9bMXS57pkCsZENEUlqJ5p0Mmrc/uEL/Z5+uvuzd76bY5WRZdE91XURccra08HTra +xovIAR1htUz2AXi+NoOaiayRq0GePKN9a6iB0lUYxNtovKb3yDYC9pmoaxf7Hnc7 +y+dLuTpJslGuhkKLV0Dhhoux1vq54ocS6Y7DGa2Pyk1zAQxLCcS4BFiWHnzwg1MC +AwEAAaNTMFEwHQYDVR0OBBYEFIru5ZR8xnxd1RWnbip+zTHuUv3IMB8GA1UdIwQY +MBaAFIru5ZR8xnxd1RWnbip+zTHuUv3IMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBAIIda5jNRX3r0rCBrKJ+vs1Pk6zIKEQ7Oeq/+p+k6eRUO0b8 +wx4rW0gXeQPeppaaxKLMZXBlA5DxsI1DpML5dcfti/M1bHIYOAISRRqPEd5GVTy8 +1ltCVN249mg06yHdoqjzO1geFIRVesoblO6JMd3xYDe3pxcTIakZNq/Cf/zjld51 +1fcMuLWu4F/1BwiNZa8eQ5Zs1Cy+b3+s+NrgVd2CIrFpZSFyP4EkUXhZXJha6Rf9 +SzmYdz4al7e9EAhURvQlm8wJpFSSkoLBuJtx7Vh6d14KPUU2NB9F2ulp6AbJb+/H +EGd3bAK6IhIrkZmxTAwowESHUJBwuX890tbZcnM= +-----END CERTIFICATE----- diff --git a/tests/data_files/pkcs7-rsa-sha256-1.der b/tests/data_files/pkcs7-rsa-sha256-1.der new file mode 100644 index 0000000000..0d799ea335 Binary files /dev/null and b/tests/data_files/pkcs7-rsa-sha256-1.der differ diff --git a/tests/data_files/pkcs7-rsa-sha256-1.key b/tests/data_files/pkcs7-rsa-sha256-1.key new file mode 100644 index 0000000000..e31159d561 --- /dev/null +++ b/tests/data_files/pkcs7-rsa-sha256-1.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDIts9piZzR8Ou0 +ymRcBecODS7+3cxh0InL1RWjmjV5uSNDth7HUAYPtO03h2MyQA5CXx03bH51wpcz +FO30uzDI+N0Dufz/lVokXUkTetbmAFbKwZVSqGXVIYcYfMBCycSePjqcF6U0tFPN +q8DLETtPY/WzF0ue6ZArGRDRFJaieadDJq3P7hC/2efrr7s3e+m2OVkWXRPdV1EX +HK2tPB062saLyAEdYbVM9gF4vjaDmomskatBnjyjfWuogdJVGMTbaLym98g2AvaZ +qGsX+x53O8vnS7k6SbJRroZCi1dA4YaLsdb6ueKHEumOwxmtj8pNcwEMSwnEuARY +lh588INTAgMBAAECggEBAIg+P1B+TurbRMQ11iX5A7wwCsSKPh/vdHneLJAfL0lu ++JcP2piko1iqEZPt3NHRVVyMP8LNbJH3Ardz74p+PkFNXIkZCLlc4hFpGR+V9KWv +eTqsaPXwxR8FYTSoCcHMQCDCUPp/um6qMXCcs4OkMMRVMATfPT+jf28h1p52AUJL +aAoBJfn7gP3WiB0FWq0bRZgSZzNYowE/MhGAQ+DuBGTSASSK3YJcxE94044fBVE8 +EqYKrxoY/x56li5cZ0v9kaURCrvhqCeq2+U5kIkgtvp2l6wF0Mm1du3BLxo2LQEI +Y2j+6BFEV74Mtv48GTwrZcyit787zyo9vVGcviSD5VECgYEA/mgLc5KfF/cQLmM/ +20T4k0edvktkRIJHFUBphowt5Hb0a0wM5C1VM4z3yN3b9ikQK+ZaQXETdPATBXIe +LntX1D1xtbMxdcAfd1FSq8QxAuaPknJZBgtzlpCsx3ZvMnNuzKZN/TU8kR1biwPE +9HaeEG3bouUu+CI/l/DqrBbQRacCgYEAyfiqsLWGhXQ7e3pLk47PDYlMOsjDWPjs +SGcatH1/lIMWyZue4W2IUcFMbpbjA6QWibo3VnOavIRSTn97JNUWYvgc5MmaQ7iX +Iss4m3vJ1LIqx30iUgw3EfDoWdpufEEYssZ/VxJPs3sdmZGALgd3CaqxHJuhuS+U +eVhWzD6LonUCgYBRCbt8GRxsedrBrAPPSO0VnR52W3WZDRavglEa9tQ3jlzVQOhq +VrZpMWJMrb8/bl0kXsApUGeuPDsS5QMQM2IKzXfHNUlwBL8BNvpqlJg4IFFjiOEq +t8MeFv+ymdtZ6sNElUUKf0bHwt5CLfUzGgXHnfb0sKSBjgdL0wYtwyacyQKBgQDJ +NcyG4zEy/srLhtiIFnu8Fo40+hFzL/nlX6JBMc3KHJa1Hy43krF+ET6d5gAffndd +moDKxbzgFksRHPuHhCobSucuHpJq6RjYdvDcJYS7OwxXVRi9+KFcZE52RaBQdWGv +qQTvr7RrMDoa5dN3B8TVgpGT2JBTN02JXjKKo7zkiQKBgCZwKDiXl7qsGidvlFZc +4CEtFsCgnNgdRTzsTL/Pr8q9CBK3BhjZjNzQALF1iGFDC1FdFYFOwI1E3j+MRHJB +rQMF8zbmmlZ6SC5QtqatCSCCKUyrUjD5J+4UfJqWFjiBBdwz+5VJojHw1yijEwl4 +LrS/V2yBrDJVczQQM4psonLF +-----END PRIVATE KEY----- diff --git a/tests/data_files/pkcs7-rsa-sha256-1.pem b/tests/data_files/pkcs7-rsa-sha256-1.pem new file mode 100644 index 0000000000..3795b71887 --- /dev/null +++ b/tests/data_files/pkcs7-rsa-sha256-1.pem @@ -0,0 +1,48 @@ +-----BEGIN CERTIFICATE----- +MIIDSTCCAjGgAwIBAgIUe97d0kRM0c3+XEGoECyJt98ubL8wDQYJKoZIhvcNAQEL +BQAwNDELMAkGA1UEBhMCTkwxDjAMBgNVBAoMBVBLQ1M3MRUwEwYDVQQDDAxQS0NT +NyBDZXJ0IDEwHhcNMjIxMDI4MTYxMDU2WhcNMjMxMDI4MTYxMDU2WjA0MQswCQYD +VQQGEwJOTDEOMAwGA1UECgwFUEtDUzcxFTATBgNVBAMMDFBLQ1M3IENlcnQgMTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMi2z2mJnNHw67TKZFwF5w4N +Lv7dzGHQicvVFaOaNXm5I0O2HsdQBg+07TeHYzJADkJfHTdsfnXClzMU7fS7MMj4 +3QO5/P+VWiRdSRN61uYAVsrBlVKoZdUhhxh8wELJxJ4+OpwXpTS0U82rwMsRO09j +9bMXS57pkCsZENEUlqJ5p0Mmrc/uEL/Z5+uvuzd76bY5WRZdE91XURccra08HTra +xovIAR1htUz2AXi+NoOaiayRq0GePKN9a6iB0lUYxNtovKb3yDYC9pmoaxf7Hnc7 +y+dLuTpJslGuhkKLV0Dhhoux1vq54ocS6Y7DGa2Pyk1zAQxLCcS4BFiWHnzwg1MC +AwEAAaNTMFEwHQYDVR0OBBYEFIru5ZR8xnxd1RWnbip+zTHuUv3IMB8GA1UdIwQY +MBaAFIru5ZR8xnxd1RWnbip+zTHuUv3IMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBAIIda5jNRX3r0rCBrKJ+vs1Pk6zIKEQ7Oeq/+p+k6eRUO0b8 +wx4rW0gXeQPeppaaxKLMZXBlA5DxsI1DpML5dcfti/M1bHIYOAISRRqPEd5GVTy8 +1ltCVN249mg06yHdoqjzO1geFIRVesoblO6JMd3xYDe3pxcTIakZNq/Cf/zjld51 +1fcMuLWu4F/1BwiNZa8eQ5Zs1Cy+b3+s+NrgVd2CIrFpZSFyP4EkUXhZXJha6Rf9 +SzmYdz4al7e9EAhURvQlm8wJpFSSkoLBuJtx7Vh6d14KPUU2NB9F2ulp6AbJb+/H +EGd3bAK6IhIrkZmxTAwowESHUJBwuX890tbZcnM= +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDIts9piZzR8Ou0 +ymRcBecODS7+3cxh0InL1RWjmjV5uSNDth7HUAYPtO03h2MyQA5CXx03bH51wpcz +FO30uzDI+N0Dufz/lVokXUkTetbmAFbKwZVSqGXVIYcYfMBCycSePjqcF6U0tFPN +q8DLETtPY/WzF0ue6ZArGRDRFJaieadDJq3P7hC/2efrr7s3e+m2OVkWXRPdV1EX +HK2tPB062saLyAEdYbVM9gF4vjaDmomskatBnjyjfWuogdJVGMTbaLym98g2AvaZ +qGsX+x53O8vnS7k6SbJRroZCi1dA4YaLsdb6ueKHEumOwxmtj8pNcwEMSwnEuARY +lh588INTAgMBAAECggEBAIg+P1B+TurbRMQ11iX5A7wwCsSKPh/vdHneLJAfL0lu ++JcP2piko1iqEZPt3NHRVVyMP8LNbJH3Ardz74p+PkFNXIkZCLlc4hFpGR+V9KWv +eTqsaPXwxR8FYTSoCcHMQCDCUPp/um6qMXCcs4OkMMRVMATfPT+jf28h1p52AUJL +aAoBJfn7gP3WiB0FWq0bRZgSZzNYowE/MhGAQ+DuBGTSASSK3YJcxE94044fBVE8 +EqYKrxoY/x56li5cZ0v9kaURCrvhqCeq2+U5kIkgtvp2l6wF0Mm1du3BLxo2LQEI +Y2j+6BFEV74Mtv48GTwrZcyit787zyo9vVGcviSD5VECgYEA/mgLc5KfF/cQLmM/ +20T4k0edvktkRIJHFUBphowt5Hb0a0wM5C1VM4z3yN3b9ikQK+ZaQXETdPATBXIe +LntX1D1xtbMxdcAfd1FSq8QxAuaPknJZBgtzlpCsx3ZvMnNuzKZN/TU8kR1biwPE +9HaeEG3bouUu+CI/l/DqrBbQRacCgYEAyfiqsLWGhXQ7e3pLk47PDYlMOsjDWPjs +SGcatH1/lIMWyZue4W2IUcFMbpbjA6QWibo3VnOavIRSTn97JNUWYvgc5MmaQ7iX +Iss4m3vJ1LIqx30iUgw3EfDoWdpufEEYssZ/VxJPs3sdmZGALgd3CaqxHJuhuS+U +eVhWzD6LonUCgYBRCbt8GRxsedrBrAPPSO0VnR52W3WZDRavglEa9tQ3jlzVQOhq +VrZpMWJMrb8/bl0kXsApUGeuPDsS5QMQM2IKzXfHNUlwBL8BNvpqlJg4IFFjiOEq +t8MeFv+ymdtZ6sNElUUKf0bHwt5CLfUzGgXHnfb0sKSBjgdL0wYtwyacyQKBgQDJ +NcyG4zEy/srLhtiIFnu8Fo40+hFzL/nlX6JBMc3KHJa1Hy43krF+ET6d5gAffndd +moDKxbzgFksRHPuHhCobSucuHpJq6RjYdvDcJYS7OwxXVRi9+KFcZE52RaBQdWGv +qQTvr7RrMDoa5dN3B8TVgpGT2JBTN02JXjKKo7zkiQKBgCZwKDiXl7qsGidvlFZc +4CEtFsCgnNgdRTzsTL/Pr8q9CBK3BhjZjNzQALF1iGFDC1FdFYFOwI1E3j+MRHJB +rQMF8zbmmlZ6SC5QtqatCSCCKUyrUjD5J+4UfJqWFjiBBdwz+5VJojHw1yijEwl4 +LrS/V2yBrDJVczQQM4psonLF +-----END PRIVATE KEY----- diff --git a/tests/data_files/pkcs7-rsa-sha256-2.crt b/tests/data_files/pkcs7-rsa-sha256-2.crt new file mode 100644 index 0000000000..a0df7d93db --- /dev/null +++ b/tests/data_files/pkcs7-rsa-sha256-2.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDSTCCAjGgAwIBAgIUVk1VQCWvWZ4ycHmycg7wDfN8+3wwDQYJKoZIhvcNAQEL +BQAwNDELMAkGA1UEBhMCTkwxDjAMBgNVBAoMBVBLQ1M3MRUwEwYDVQQDDAxQS0NT +NyBDZXJ0IDIwHhcNMjIxMDI4MTYxMDU2WhcNMjMxMDI4MTYxMDU2WjA0MQswCQYD +VQQGEwJOTDEOMAwGA1UECgwFUEtDUzcxFTATBgNVBAMMDFBLQ1M3IENlcnQgMjCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMmVNZZ0/qcT+h/lVNO+gP65 +lERTTudQ15h8QTLjaKhx5SSTLnuUhD0jLbR+ng8PMqdJ8ePkZEh1+7mi9MHzID4Y +c47jH8M+Jc/JdBr6cSjbFd23QHESUjKKmV1IjSHc6Llbxe962z4gEXYjJAMkfr6B +g1iecK3AlnEI4F0BsQfC5dgA4Qce2okvcTuhYgvHtLZ+UN4ca50Kw0o4u5FYdl89 +KDCE4zNp8MaaxGC83xcM4A9XqjHyZ7a2wvACTlmLQ2q/E+RN/8THEel4Y+yv82Uj +j2LqqEaA06dvSdOPdaGz9jUZauqBw7TcuGGVzrrsZ0g/sHXKng9TppehAV/HrJUC +AwEAAaNTMFEwHQYDVR0OBBYEFI5FVrtfLwPXRERcyVX6qBVvfoduMB8GA1UdIwQY +MBaAFI5FVrtfLwPXRERcyVX6qBVvfoduMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBAKRl0wgREe6eAduJSV5fs+Ec0s2qs2lHQqt/0JGEIbZBBtka +q1UH9CIMMAd6Kb0kh5GlJT2shg/EAYWoitMwntkeRYTln2k2/B5jux+U5Ph4HyC+ +ad2GqmsoXWDru79rltT7Pv1hS1ofJyQ4Jv88vQA/SuIIRGdTC24VAVgg00JxvDRB +xeqsQ9Pld4ebg4VvqsInnSpmKCcxfWxFhJk/Ax8bK/tV/GnrPiwsvry1j9nZyebS +IyI01/6DwJS2ZhFnsLGyPHFOAFNtomjIdQ6gf2L1wq0qiGOKj/K9IzFNCpCz82a+ +gMgqFzCT5TCZC16kUG2NA2pXAx9O4uppKjRk97U= +-----END CERTIFICATE----- diff --git a/tests/data_files/pkcs7-rsa-sha256-2.der b/tests/data_files/pkcs7-rsa-sha256-2.der new file mode 100644 index 0000000000..fc7a3eabf7 Binary files /dev/null and b/tests/data_files/pkcs7-rsa-sha256-2.der differ diff --git a/tests/data_files/pkcs7-rsa-sha256-2.key b/tests/data_files/pkcs7-rsa-sha256-2.key new file mode 100644 index 0000000000..659c015666 --- /dev/null +++ b/tests/data_files/pkcs7-rsa-sha256-2.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDJlTWWdP6nE/of +5VTTvoD+uZREU07nUNeYfEEy42ioceUkky57lIQ9Iy20fp4PDzKnSfHj5GRIdfu5 +ovTB8yA+GHOO4x/DPiXPyXQa+nEo2xXdt0BxElIyipldSI0h3Oi5W8Xvets+IBF2 +IyQDJH6+gYNYnnCtwJZxCOBdAbEHwuXYAOEHHtqJL3E7oWILx7S2flDeHGudCsNK +OLuRWHZfPSgwhOMzafDGmsRgvN8XDOAPV6ox8me2tsLwAk5Zi0NqvxPkTf/ExxHp +eGPsr/NlI49i6qhGgNOnb0nTj3Whs/Y1GWrqgcO03Lhhlc667GdIP7B1yp4PU6aX +oQFfx6yVAgMBAAECggEBAMVHm3w134qQCHfyroPTqtaftDTx+wRyn6yB3iT5XdGM +NZ8H07Pp80kKBo7gY7uFOiNyQKKxQFuR69sPWc3+LI3YzC8IpGslhUfHdjN46gn7 +73hfAVgnf/4qmlEq0cRUOAY/hIUMjUhNhglB9tqEeu3iPjMaTFgfZJwW/czH/QMD +w4zj5XoLgwRkqVvUceu/dBgV8KP5DpON+q8wpfWtjunv7rg5Nc3BVBrpb5SadJ7T +i5TsS+pZQyp+mTvyCI3A1hkr2Vw5tULWO8SPhuEQkdtC/CL+luCUO7L16lU6KhFB +qP5Fduik5skyLCVvAMUkjKcrC22k0gkhOHvfmMhjaAECgYEA68+hAQIiV9ErZGk9 +ZLu+VJHBSPmEQCkUcbviwzoRo8YSyka12TZERy+NJcvmD9deNgFbp8GyZf01XJWH +slSYt6LyInrJrTpv+3q2Vl5GQp0f+39i7MHnwGGKbWsDbSAm+L9yKTJzYJz1O5fo +in06AiyyGPwnXd1cm5bTXVX+dQECgYEA2tdi6DXF8awE23pv4HphPBhXS5hmYP/D +NC7CtP8wQsxjPdiIxkBFFVEaFCC2njq1VhTyJb5noJM4kOIwcoaQ/zgyyxQa0u7w ++CqvAh1WwG+sT/B7vivrtDmmYeyGQapFo5DRIz+MflKAhzDhtnEyT9vLuCdn8J95 +0YvxZJ9+k5UCgYEAh+e7SER9nJUt6AoLWyIlGMKEXlWIFh5W7RG3KIMwJW6D59aG ++fAfu9M5Cx6PsnOSlZeExpOJCOS9O2Xmti2xcqzT1nFkCJWUcqCPtAlTfxLlmuIZ +FpDOy36r9FHnwJ32OAjGd93ex0DOyZDMcfyoURaHcoTo/10UAYwUt0dXhwECgYAI +xad2TWmA1XdgYNkJM36gTQ16v0IjUz084z70yGHj25OC0CIzaDIct6KG+gS39Px9 +1dsa/jXjLuOOkzKD9LbtNBB9KXIl0GQiXnujZw+qKQ/MKISdS99n2wO7WyLKkQu3 +kb+AXTTBf4cdZC04BfORVesll5bIA2x7pNNpSCdnvQKBgG7VXYcPlIV7iAyi2xFa +uN1jccu/AK7xA0G1jz2SHNlpet74LmWR8XsTujJeo8WG1IRFxSky4h/pAP0XWIFO +0LPK7eeDtnFq6y1/DXpI+/9BWX5T/8+4Yk93p37YrBVWKfd21dhrAklQs11m3rlQ +Qn6c/zyvMKSyrCVxo5pTd5Il +-----END PRIVATE KEY----- diff --git a/tests/data_files/pkcs7-rsa-sha256-2.pem b/tests/data_files/pkcs7-rsa-sha256-2.pem new file mode 100644 index 0000000000..b11a00a199 --- /dev/null +++ b/tests/data_files/pkcs7-rsa-sha256-2.pem @@ -0,0 +1,48 @@ +-----BEGIN CERTIFICATE----- +MIIDSTCCAjGgAwIBAgIUVk1VQCWvWZ4ycHmycg7wDfN8+3wwDQYJKoZIhvcNAQEL +BQAwNDELMAkGA1UEBhMCTkwxDjAMBgNVBAoMBVBLQ1M3MRUwEwYDVQQDDAxQS0NT +NyBDZXJ0IDIwHhcNMjIxMDI4MTYxMDU2WhcNMjMxMDI4MTYxMDU2WjA0MQswCQYD +VQQGEwJOTDEOMAwGA1UECgwFUEtDUzcxFTATBgNVBAMMDFBLQ1M3IENlcnQgMjCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMmVNZZ0/qcT+h/lVNO+gP65 +lERTTudQ15h8QTLjaKhx5SSTLnuUhD0jLbR+ng8PMqdJ8ePkZEh1+7mi9MHzID4Y +c47jH8M+Jc/JdBr6cSjbFd23QHESUjKKmV1IjSHc6Llbxe962z4gEXYjJAMkfr6B +g1iecK3AlnEI4F0BsQfC5dgA4Qce2okvcTuhYgvHtLZ+UN4ca50Kw0o4u5FYdl89 +KDCE4zNp8MaaxGC83xcM4A9XqjHyZ7a2wvACTlmLQ2q/E+RN/8THEel4Y+yv82Uj +j2LqqEaA06dvSdOPdaGz9jUZauqBw7TcuGGVzrrsZ0g/sHXKng9TppehAV/HrJUC +AwEAAaNTMFEwHQYDVR0OBBYEFI5FVrtfLwPXRERcyVX6qBVvfoduMB8GA1UdIwQY +MBaAFI5FVrtfLwPXRERcyVX6qBVvfoduMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBAKRl0wgREe6eAduJSV5fs+Ec0s2qs2lHQqt/0JGEIbZBBtka +q1UH9CIMMAd6Kb0kh5GlJT2shg/EAYWoitMwntkeRYTln2k2/B5jux+U5Ph4HyC+ +ad2GqmsoXWDru79rltT7Pv1hS1ofJyQ4Jv88vQA/SuIIRGdTC24VAVgg00JxvDRB +xeqsQ9Pld4ebg4VvqsInnSpmKCcxfWxFhJk/Ax8bK/tV/GnrPiwsvry1j9nZyebS +IyI01/6DwJS2ZhFnsLGyPHFOAFNtomjIdQ6gf2L1wq0qiGOKj/K9IzFNCpCz82a+ +gMgqFzCT5TCZC16kUG2NA2pXAx9O4uppKjRk97U= +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDJlTWWdP6nE/of +5VTTvoD+uZREU07nUNeYfEEy42ioceUkky57lIQ9Iy20fp4PDzKnSfHj5GRIdfu5 +ovTB8yA+GHOO4x/DPiXPyXQa+nEo2xXdt0BxElIyipldSI0h3Oi5W8Xvets+IBF2 +IyQDJH6+gYNYnnCtwJZxCOBdAbEHwuXYAOEHHtqJL3E7oWILx7S2flDeHGudCsNK +OLuRWHZfPSgwhOMzafDGmsRgvN8XDOAPV6ox8me2tsLwAk5Zi0NqvxPkTf/ExxHp +eGPsr/NlI49i6qhGgNOnb0nTj3Whs/Y1GWrqgcO03Lhhlc667GdIP7B1yp4PU6aX +oQFfx6yVAgMBAAECggEBAMVHm3w134qQCHfyroPTqtaftDTx+wRyn6yB3iT5XdGM +NZ8H07Pp80kKBo7gY7uFOiNyQKKxQFuR69sPWc3+LI3YzC8IpGslhUfHdjN46gn7 +73hfAVgnf/4qmlEq0cRUOAY/hIUMjUhNhglB9tqEeu3iPjMaTFgfZJwW/czH/QMD +w4zj5XoLgwRkqVvUceu/dBgV8KP5DpON+q8wpfWtjunv7rg5Nc3BVBrpb5SadJ7T +i5TsS+pZQyp+mTvyCI3A1hkr2Vw5tULWO8SPhuEQkdtC/CL+luCUO7L16lU6KhFB +qP5Fduik5skyLCVvAMUkjKcrC22k0gkhOHvfmMhjaAECgYEA68+hAQIiV9ErZGk9 +ZLu+VJHBSPmEQCkUcbviwzoRo8YSyka12TZERy+NJcvmD9deNgFbp8GyZf01XJWH +slSYt6LyInrJrTpv+3q2Vl5GQp0f+39i7MHnwGGKbWsDbSAm+L9yKTJzYJz1O5fo +in06AiyyGPwnXd1cm5bTXVX+dQECgYEA2tdi6DXF8awE23pv4HphPBhXS5hmYP/D +NC7CtP8wQsxjPdiIxkBFFVEaFCC2njq1VhTyJb5noJM4kOIwcoaQ/zgyyxQa0u7w ++CqvAh1WwG+sT/B7vivrtDmmYeyGQapFo5DRIz+MflKAhzDhtnEyT9vLuCdn8J95 +0YvxZJ9+k5UCgYEAh+e7SER9nJUt6AoLWyIlGMKEXlWIFh5W7RG3KIMwJW6D59aG ++fAfu9M5Cx6PsnOSlZeExpOJCOS9O2Xmti2xcqzT1nFkCJWUcqCPtAlTfxLlmuIZ +FpDOy36r9FHnwJ32OAjGd93ex0DOyZDMcfyoURaHcoTo/10UAYwUt0dXhwECgYAI +xad2TWmA1XdgYNkJM36gTQ16v0IjUz084z70yGHj25OC0CIzaDIct6KG+gS39Px9 +1dsa/jXjLuOOkzKD9LbtNBB9KXIl0GQiXnujZw+qKQ/MKISdS99n2wO7WyLKkQu3 +kb+AXTTBf4cdZC04BfORVesll5bIA2x7pNNpSCdnvQKBgG7VXYcPlIV7iAyi2xFa +uN1jccu/AK7xA0G1jz2SHNlpet74LmWR8XsTujJeo8WG1IRFxSky4h/pAP0XWIFO +0LPK7eeDtnFq6y1/DXpI+/9BWX5T/8+4Yk93p37YrBVWKfd21dhrAklQs11m3rlQ +Qn6c/zyvMKSyrCVxo5pTd5Il +-----END PRIVATE KEY----- diff --git a/tests/data_files/pkcs7_data.bin b/tests/data_files/pkcs7_data.bin new file mode 100644 index 0000000000..40ee264774 --- /dev/null +++ b/tests/data_files/pkcs7_data.bin @@ -0,0 +1 @@ +Hello diff --git a/tests/data_files/pkcs7_data_1.bin b/tests/data_files/pkcs7_data_1.bin new file mode 100644 index 0000000000..78c6baefdd --- /dev/null +++ b/tests/data_files/pkcs7_data_1.bin @@ -0,0 +1 @@ +2 diff --git a/tests/data_files/pkcs7_data_cert_encrypted.der b/tests/data_files/pkcs7_data_cert_encrypted.der new file mode 100644 index 0000000000..b7b1c8331d Binary files /dev/null and b/tests/data_files/pkcs7_data_cert_encrypted.der differ diff --git a/tests/data_files/pkcs7_data_cert_signed_sha1.der b/tests/data_files/pkcs7_data_cert_signed_sha1.der new file mode 100644 index 0000000000..fb1deb0fc6 Binary files /dev/null and b/tests/data_files/pkcs7_data_cert_signed_sha1.der differ diff --git a/tests/data_files/pkcs7_data_cert_signed_sha256.der b/tests/data_files/pkcs7_data_cert_signed_sha256.der new file mode 100644 index 0000000000..8dc2f4c9cd Binary files /dev/null and b/tests/data_files/pkcs7_data_cert_signed_sha256.der differ diff --git a/tests/data_files/pkcs7_data_cert_signed_sha512.der b/tests/data_files/pkcs7_data_cert_signed_sha512.der new file mode 100644 index 0000000000..a4aa587587 Binary files /dev/null and b/tests/data_files/pkcs7_data_cert_signed_sha512.der differ diff --git a/tests/data_files/pkcs7_data_cert_signed_v2.der b/tests/data_files/pkcs7_data_cert_signed_v2.der new file mode 100644 index 0000000000..4f4cb047e0 Binary files /dev/null and b/tests/data_files/pkcs7_data_cert_signed_v2.der differ diff --git a/tests/data_files/pkcs7_data_cert_signeddata_sha256.der b/tests/data_files/pkcs7_data_cert_signeddata_sha256.der new file mode 100644 index 0000000000..cb7d75103d Binary files /dev/null and b/tests/data_files/pkcs7_data_cert_signeddata_sha256.der differ diff --git a/tests/data_files/pkcs7_data_multiple_certs_signed.der b/tests/data_files/pkcs7_data_multiple_certs_signed.der new file mode 100644 index 0000000000..4a237e9d14 Binary files /dev/null and b/tests/data_files/pkcs7_data_multiple_certs_signed.der differ diff --git a/tests/data_files/pkcs7_data_multiple_signed.der b/tests/data_files/pkcs7_data_multiple_signed.der new file mode 100644 index 0000000000..095b80ce1b Binary files /dev/null and b/tests/data_files/pkcs7_data_multiple_signed.der differ diff --git a/tests/data_files/pkcs7_data_signed_badcert.der b/tests/data_files/pkcs7_data_signed_badcert.der new file mode 100644 index 0000000000..ed00f65fa3 Binary files /dev/null and b/tests/data_files/pkcs7_data_signed_badcert.der differ diff --git a/tests/data_files/pkcs7_data_signed_badsigner.der b/tests/data_files/pkcs7_data_signed_badsigner.der new file mode 100644 index 0000000000..aa5447c44d Binary files /dev/null and b/tests/data_files/pkcs7_data_signed_badsigner.der differ diff --git a/tests/data_files/pkcs7_data_without_cert_signed.der b/tests/data_files/pkcs7_data_without_cert_signed.der new file mode 100644 index 0000000000..b47fe927e5 Binary files /dev/null and b/tests/data_files/pkcs7_data_without_cert_signed.der differ diff --git a/tests/data_files/pkcs7_signerInfo_issuer_invalid_size.der b/tests/data_files/pkcs7_signerInfo_issuer_invalid_size.der new file mode 100644 index 0000000000..898ca6777a Binary files /dev/null and b/tests/data_files/pkcs7_signerInfo_issuer_invalid_size.der differ diff --git a/tests/data_files/pkcs7_signerInfo_serial_invalid_size.der b/tests/data_files/pkcs7_signerInfo_serial_invalid_size.der new file mode 100644 index 0000000000..f4b4e384db Binary files /dev/null and b/tests/data_files/pkcs7_signerInfo_serial_invalid_size.der differ diff --git a/tests/opt-testcases/tls13-misc.sh b/tests/opt-testcases/tls13-misc.sh index edece456b3..ed428480c4 100755 --- a/tests/opt-testcases/tls13-misc.sh +++ b/tests/opt-testcases/tls13-misc.sh @@ -301,7 +301,7 @@ run_test "TLS 1.3 m->G: EarlyData: basic check, good" \ -c "NewSessionTicket: early_data(42) extension received." \ -c "ClientHello: early_data(42) extension exists." \ -c "EncryptedExtensions: early_data(42) extension received." \ - -c "EncryptedExtensions: early_data(42) extension ( ignored )." \ + -c "EncryptedExtensions: early_data(42) extension exists." \ -s "Parsing extension 'Early Data/42' (0 bytes)" \ -s "Sending extension Early Data/42 (0 bytes)" \ -s "early data accepted" @@ -322,7 +322,7 @@ run_test "TLS 1.3 m->G: EarlyData: no early_data in NewSessionTicket, good" \ -C "NewSessionTicket: early_data(42) extension received." \ -c "ClientHello: early_data(42) extension does not exist." \ -C "EncryptedExtensions: early_data(42) extension received." \ - -C "EncryptedExtensions: early_data(42) extension ( ignored )." + -C "EncryptedExtensions: early_data(42) extension exists." #TODO: OpenSSL tests don't work now. It might be openssl options issue, cause GnuTLS has worked. skip_next_test diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 8272dcc312..b43f999d80 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -1217,6 +1217,7 @@ component_test_crypto_full_no_md () { # Direct dependencies scripts/config.py unset MBEDTLS_HKDF_C scripts/config.py unset MBEDTLS_HMAC_DRBG_C + scripts/config.py unset MBEDTLS_PKCS7_C # Indirect dependencies scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC make @@ -1437,6 +1438,31 @@ component_test_tls1_2_default_cbc_legacy_cbc_etm_cipher_only_use_psa () { tests/ssl-opt.sh -f "TLS 1.2" } +# We're not aware of any other (open source) implementation of EC J-PAKE in TLS +# that we could use for interop testing. However, we now have sort of two +# implementations ourselves: one using PSA, the other not. At least test that +# these two interoperate with each other. +component_test_tls1_2_ecjpake_compatibility() { + msg "build: TLS1.2 server+client w/ EC-JPAKE w/o USE_PSA" + scripts/config.py set MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + make -C programs ssl/ssl_server2 ssl/ssl_client2 + cp programs/ssl/ssl_server2 s2_no_use_psa + cp programs/ssl/ssl_client2 c2_no_use_psa + + msg "build: TLS1.2 server+client w/ EC-JPAKE w/ USE_PSA" + scripts/config.py set MBEDTLS_USE_PSA_CRYPTO + make clean + make -C programs ssl/ssl_server2 ssl/ssl_client2 + make -C programs test/udp_proxy test/query_compile_time_config + + msg "test: server w/o USE_PSA - client w/ USE_PSA" + P_SRV=../s2_no_use_psa tests/ssl-opt.sh -f ECJPAKE + msg "test: client w/o USE_PSA - server w/ USE_PSA" + P_CLI=../c2_no_use_psa tests/ssl-opt.sh -f ECJPAKE + + rm s2_no_use_psa c2_no_use_psa +} + component_test_psa_external_rng_use_psa_crypto () { msg "build: full + PSA_CRYPTO_EXTERNAL_RNG + USE_PSA_CRYPTO minus CTR_DRBG" scripts/config.py full @@ -2099,6 +2125,7 @@ config_psa_crypto_hash_use_psa () { fi scripts/config.py unset MBEDTLS_HKDF_C # has independent PSA implementation scripts/config.py unset MBEDTLS_HMAC_DRBG_C + scripts/config.py unset MBEDTLS_PKCS7_C scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_DETERMINISTIC_ECDSA } @@ -3250,6 +3277,7 @@ component_build_armcc () { component_test_tls13_only () { msg "build: default config with MBEDTLS_SSL_PROTO_TLS1_3, without MBEDTLS_SSL_PROTO_TLS1_2" + scripts/config.py set MBEDTLS_SSL_EARLY_DATA make CFLAGS="'-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/tls13-only.h\"'" msg "test: TLS 1.3 only, all key exchange modes enabled" @@ -3269,6 +3297,8 @@ component_test_tls13_only_psk () { scripts/config.py unset MBEDTLS_SSL_SERVER_NAME_INDICATION scripts/config.py unset MBEDTLS_ECDSA_C scripts/config.py unset MBEDTLS_PKCS1_V21 + scripts/config.py unset MBEDTLS_PKCS7_C + scripts/config.py set MBEDTLS_SSL_EARLY_DATA make CFLAGS="'-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/tls13-only.h\"'" msg "test_suite_ssl: TLS 1.3 only, only PSK key exchange mode enabled" @@ -3301,6 +3331,8 @@ component_test_tls13_only_psk_ephemeral () { scripts/config.py unset MBEDTLS_SSL_SERVER_NAME_INDICATION scripts/config.py unset MBEDTLS_ECDSA_C scripts/config.py unset MBEDTLS_PKCS1_V21 + scripts/config.py unset MBEDTLS_PKCS7_C + scripts/config.py set MBEDTLS_SSL_EARLY_DATA make CFLAGS="'-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/tls13-only.h\"'" msg "test_suite_ssl: TLS 1.3 only, only PSK ephemeral key exchange mode" @@ -3318,6 +3350,8 @@ component_test_tls13_only_psk_all () { scripts/config.py unset MBEDTLS_SSL_SERVER_NAME_INDICATION scripts/config.py unset MBEDTLS_ECDSA_C scripts/config.py unset MBEDTLS_PKCS1_V21 + scripts/config.py unset MBEDTLS_PKCS7_C + scripts/config.py set MBEDTLS_SSL_EARLY_DATA make CFLAGS="'-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/tls13-only.h\"'" msg "test_suite_ssl: TLS 1.3 only, PSK and PSK ephemeral key exchange modes" @@ -3330,6 +3364,7 @@ component_test_tls13_only_psk_all () { component_test_tls13_only_ephemeral_all () { msg "build: TLS 1.3 only from default, without PSK key exchange mode" scripts/config.py unset MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED + scripts/config.py set MBEDTLS_SSL_EARLY_DATA make CFLAGS="'-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/tls13-only.h\"'" msg "test_suite_ssl: TLS 1.3 only, ephemeral and PSK ephemeral key exchange modes" @@ -3344,6 +3379,7 @@ component_test_tls13 () { scripts/config.py set MBEDTLS_SSL_PROTO_TLS1_3 scripts/config.py set MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE scripts/config.py set MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 1 + scripts/config.py set MBEDTLS_SSL_EARLY_DATA CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . make msg "test: default config with MBEDTLS_SSL_PROTO_TLS1_3 enabled, without padding" @@ -3357,6 +3393,7 @@ component_test_tls13_no_compatibility_mode () { scripts/config.py set MBEDTLS_SSL_PROTO_TLS1_3 scripts/config.py unset MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE scripts/config.py set MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 1 + scripts/config.py set MBEDTLS_SSL_EARLY_DATA CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . make msg "test: default config with MBEDTLS_SSL_PROTO_TLS1_3 enabled, without padding" diff --git a/tests/scripts/check_files.py b/tests/scripts/check_files.py index 5c18702def..42f2e82c99 100755 --- a/tests/scripts/check_files.py +++ b/tests/scripts/check_files.py @@ -122,6 +122,7 @@ BINARY_FILE_PATH_RE_LIST = [ r'tests/data_files/.*\.req\.[^/]+\Z', r'tests/data_files/.*malformed[^/]+\Z', r'tests/data_files/format_pkcs12\.fmt\Z', + r'tests/data_files/pkcs7_data.*\.bin\Z', ] BINARY_FILE_PATH_RE = re.compile('|'.join(BINARY_FILE_PATH_RE_LIST)) diff --git a/tests/scripts/generate_bignum_tests.py b/tests/scripts/generate_bignum_tests.py index eee2f657ad..c3058e98a9 100755 --- a/tests/scripts/generate_bignum_tests.py +++ b/tests/scripts/generate_bignum_tests.py @@ -57,7 +57,7 @@ of BaseTarget in test_data_generation.py. import sys from abc import ABCMeta -from typing import Iterator, List +from typing import List import scripts_path # pylint: disable=unused-import from mbedtls_dev import test_case @@ -68,15 +68,17 @@ from mbedtls_dev import bignum_common # the framework from mbedtls_dev import bignum_core, bignum_mod_raw # pylint: disable=unused-import -class BignumTarget(test_data_generation.BaseTarget, metaclass=ABCMeta): - #pylint: disable=abstract-method +class BignumTarget(test_data_generation.BaseTarget): + #pylint: disable=too-few-public-methods """Target for bignum (legacy) test case generation.""" target_basename = 'test_suite_bignum.generated' -class BignumOperation(bignum_common.OperationCommon, BignumTarget, metaclass=ABCMeta): +class BignumOperation(bignum_common.OperationCommon, BignumTarget, + metaclass=ABCMeta): #pylint: disable=abstract-method """Common features for bignum operations in legacy tests.""" + unique_combinations_only = True input_values = [ "", "0", "-", "-0", "7b", "-7b", @@ -132,11 +134,6 @@ class BignumOperation(bignum_common.OperationCommon, BignumTarget, metaclass=ABC tmp = "large " + tmp return tmp - @classmethod - def generate_function_tests(cls) -> Iterator[test_case.TestCase]: - for a_value, b_value in cls.get_value_pairs(): - yield cls(a_value, b_value).create_test_case() - class BignumCmp(BignumOperation): """Test cases for bignum value comparison.""" diff --git a/tests/scripts/run-test-suites.pl b/tests/scripts/run-test-suites.pl index 8a5bb937dc..cedc0bfa5a 100755 --- a/tests/scripts/run-test-suites.pl +++ b/tests/scripts/run-test-suites.pl @@ -50,10 +50,10 @@ GetOptions( 'verbose|v:1' => \$verbose, ) or die; -# All test suites = executable files derived from a .data file. +# All test suites = executable files with a .datax file. my @suites = (); -for my $data_file (glob 'suites/test_suite_*.data') { - (my $base = $data_file) =~ s#^suites/(.*)\.data$#$1#; +for my $data_file (glob 'test_suite_*.datax') { + (my $base = $data_file) =~ s/\.datax$//; push @suites, $base if -x $base; push @suites, "$base.exe" if -e "$base.exe"; } diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 62205274c7..c6f6e29635 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1362,7 +1362,7 @@ do_run_test_once() { if [ -n "$PXY_CMD" ]; then kill $PXY_PID >/dev/null 2>&1 - wait $PXY_PID + wait $PXY_PID >> $PXY_OUT 2>&1 fi } @@ -1689,6 +1689,20 @@ if [ -n "${OPENSSL_LEGACY:-}" ]; then O_LEGACY_CLI="$O_LEGACY_CLI -connect 127.0.0.1:+SRV_PORT" fi +# Newer versions of OpenSSL have a syntax to enable all "ciphers", even +# low-security ones. This covers not just cipher suites but also protocol +# versions. It is necessary, for example, to use (D)TLS 1.0/1.1 on +# OpenSSL 1.1.1f from Ubuntu 20.04. The syntax was only introduced in +# OpenSSL 1.1.0 (21e0c1d23afff48601eb93135defddae51f7e2e3) and I can't find +# a way to discover it from -help, so check the openssl version. +case $($OPENSSL_CMD version) in + "OpenSSL 0"*|"OpenSSL 1.0"*) :;; + *) + O_CLI="$O_CLI -cipher ALL@SECLEVEL=0" + O_SRV="$O_SRV -cipher ALL@SECLEVEL=0" + ;; +esac + if [ -n "${OPENSSL_NEXT:-}" ]; then O_NEXT_SRV="$O_NEXT_SRV -accept $SRV_PORT" O_NEXT_SRV_NO_CERT="$O_NEXT_SRV_NO_CERT -accept $SRV_PORT" @@ -12945,8 +12959,8 @@ run_test "TLS 1.3: NewSessionTicket: Basic check, O->m" \ "$O_NEXT_CLI -msg -debug -tls1_3 -reconnect" \ 0 \ -s "=> write NewSessionTicket msg" \ - -s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET" \ - -s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET_FLUSH" + -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET" \ + -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH" requires_gnutls_tls1_3 requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS @@ -12962,8 +12976,8 @@ run_test "TLS 1.3: NewSessionTicket: Basic check, G->m" \ -c "Connecting again- trying to resume previous session" \ -c "NEW SESSION TICKET (4) was received" \ -s "=> write NewSessionTicket msg" \ - -s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET" \ - -s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET_FLUSH" \ + -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET" \ + -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH" \ -s "key exchange mode: ephemeral" \ -s "key exchange mode: psk_ephemeral" \ -s "found pre_shared_key extension" @@ -12985,8 +12999,8 @@ run_test "TLS 1.3: NewSessionTicket: Basic check, m->m" \ -c "Reconnecting with saved session" \ -c "HTTP/1.0 200 OK" \ -s "=> write NewSessionTicket msg" \ - -s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET" \ - -s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET_FLUSH" \ + -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET" \ + -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH" \ -s "key exchange mode: ephemeral" \ -s "key exchange mode: psk_ephemeral" \ -s "found pre_shared_key extension" @@ -13040,8 +13054,8 @@ run_test "TLS 1.3: NewSessionTicket: servername check, m->m" \ -c "Reconnecting with saved session" \ -c "HTTP/1.0 200 OK" \ -s "=> write NewSessionTicket msg" \ - -s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET" \ - -s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET_FLUSH" \ + -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET" \ + -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH" \ -s "key exchange mode: ephemeral" \ -s "key exchange mode: psk_ephemeral" \ -s "found pre_shared_key extension" @@ -13064,8 +13078,8 @@ run_test "TLS 1.3: NewSessionTicket: servername negative check, m->m" \ -c "Reconnecting with saved session" \ -c "Hostname mismatch the session ticket, disable session resumption." \ -s "=> write NewSessionTicket msg" \ - -s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET" \ - -s "server state: MBEDTLS_SSL_NEW_SESSION_TICKET_FLUSH" + -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET" \ + -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH" # Test heap memory usage after handshake requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 diff --git a/tests/suites/test_suite_bignum_core.function b/tests/suites/test_suite_bignum_core.function index 612a7c6bd4..d5bb420023 100644 --- a/tests/suites/test_suite_bignum_core.function +++ b/tests/suites/test_suite_bignum_core.function @@ -1049,6 +1049,52 @@ exit: /* BEGIN MERGE SLOT 3 */ +/* BEGIN_CASE */ +void mpi_core_sub_int( char * input_A, char * input_B, + char * input_X, int borrow ) +{ + /* We are testing A - b, where A is an MPI and b is a scalar, expecting + * result X with borrow borrow. However, for ease of handling we encode b + * as a 1-limb MPI (B) in the .data file. */ + + mbedtls_mpi_uint *A = NULL; + mbedtls_mpi_uint *B = NULL; + mbedtls_mpi_uint *X = NULL; + mbedtls_mpi_uint *R = NULL; + size_t A_limbs, B_limbs, X_limbs; + + TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &A, &A_limbs, input_A ) ); + TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &B, &B_limbs, input_B ) ); + TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &X, &X_limbs, input_X ) ); + + /* The MPI encoding of scalar b must be only 1 limb */ + TEST_EQUAL( B_limbs, 1 ); + + /* The subtraction is fixed-width, so A and X must have the same number of limbs */ + TEST_EQUAL( A_limbs, X_limbs ); + size_t limbs = A_limbs; + + ASSERT_ALLOC( R, limbs ); + +#define TEST_COMPARE_CORE_MPIS( A, B, limbs ) \ + ASSERT_COMPARE( A, (limbs) * sizeof(mbedtls_mpi_uint), B, (limbs) * sizeof(mbedtls_mpi_uint) ) + + /* 1. R = A - b. Result and borrow should be correct */ + TEST_EQUAL( mbedtls_mpi_core_sub_int( R, A, B[0], limbs ), borrow ); + TEST_COMPARE_CORE_MPIS( R, X, limbs ); + + /* 2. A = A - b. Result and borrow should be correct */ + TEST_EQUAL( mbedtls_mpi_core_sub_int( A, A, B[0], limbs ), borrow ); + TEST_COMPARE_CORE_MPIS( A, X, limbs ); + +exit: + mbedtls_free( A ); + mbedtls_free( B ); + mbedtls_free( X ); + mbedtls_free( R ); +} +/* END_CASE */ + /* END MERGE SLOT 3 */ /* BEGIN MERGE SLOT 4 */ diff --git a/tests/suites/test_suite_bignum_mod_raw.function b/tests/suites/test_suite_bignum_mod_raw.function index 4adccce25b..2d9e412280 100644 --- a/tests/suites/test_suite_bignum_mod_raw.function +++ b/tests/suites/test_suite_bignum_mod_raw.function @@ -275,6 +275,79 @@ exit: /* BEGIN MERGE SLOT 2 */ +/* BEGIN_CASE */ +void mpi_mod_raw_sub( char * input_A, + char * input_B, + char * input_N, + char * result ) +{ + mbedtls_mpi_uint *A = NULL; + mbedtls_mpi_uint *B = NULL; + mbedtls_mpi_uint *N = NULL; + mbedtls_mpi_uint *X = NULL; + mbedtls_mpi_uint *res = NULL; + size_t limbs_A; + size_t limbs_B; + size_t limbs_N; + size_t limbs_res; + + mbedtls_mpi_mod_modulus m; + mbedtls_mpi_mod_modulus_init( &m ); + + TEST_EQUAL( mbedtls_test_read_mpi_core( &A, &limbs_A, input_A ), 0 ); + TEST_EQUAL( mbedtls_test_read_mpi_core( &B, &limbs_B, input_B ), 0 ); + TEST_EQUAL( mbedtls_test_read_mpi_core( &N, &limbs_N, input_N ), 0 ); + TEST_EQUAL( mbedtls_test_read_mpi_core( &res, &limbs_res, result ), 0 ); + + size_t limbs = limbs_N; + size_t bytes = limbs * sizeof( mbedtls_mpi_uint ); + + TEST_EQUAL( limbs_A, limbs ); + TEST_EQUAL( limbs_B, limbs ); + TEST_EQUAL( limbs_res, limbs ); + + ASSERT_ALLOC( X, limbs ); + + TEST_EQUAL( mbedtls_mpi_mod_modulus_setup( + &m, N, limbs, + MBEDTLS_MPI_MOD_EXT_REP_BE, + MBEDTLS_MPI_MOD_REP_MONTGOMERY ), 0 ); + + mbedtls_mpi_mod_raw_sub( X, A, B, &m ); + ASSERT_COMPARE( X, bytes, res, bytes ); + + /* alias X to A */ + memcpy( X, A, bytes ); + mbedtls_mpi_mod_raw_sub( X, X, B, &m ); + ASSERT_COMPARE( X, bytes, res, bytes ); + + /* alias X to B */ + memcpy( X, B, bytes ); + mbedtls_mpi_mod_raw_sub( X, A, X, &m ); + ASSERT_COMPARE( X, bytes, res, bytes ); + + /* A == B: alias A and B */ + if( memcmp( A, B, bytes ) == 0 ) + { + mbedtls_mpi_mod_raw_sub( X, A, A, &m ); + ASSERT_COMPARE( X, bytes, res, bytes ); + + /* X, A, B all aliased together */ + memcpy( X, A, bytes ); + mbedtls_mpi_mod_raw_sub( X, X, X, &m ); + ASSERT_COMPARE( X, bytes, res, bytes ); + } +exit: + mbedtls_free( A ); + mbedtls_free( B ); + mbedtls_free( X ); + mbedtls_free( res ); + + mbedtls_mpi_mod_modulus_free( &m ); + mbedtls_free( N ); +} +/* END_CASE */ + /* END MERGE SLOT 2 */ /* BEGIN MERGE SLOT 3 */ diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function index b7c3b5144a..ff936dfba1 100644 --- a/tests/suites/test_suite_cipher.function +++ b/tests/suites/test_suite_cipher.function @@ -450,8 +450,12 @@ void enc_dec_buf( int cipher_id, char * cipher_string, int key_len, TEST_ASSERT( 0 == mbedtls_cipher_reset( &ctx_enc ) ); #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) - TEST_ASSERT( 0 == mbedtls_cipher_update_ad( &ctx_dec, ad, sizeof( ad ) - i ) ); - TEST_ASSERT( 0 == mbedtls_cipher_update_ad( &ctx_enc, ad, sizeof( ad ) - i ) ); + int expected = ( cipher_info->mode == MBEDTLS_MODE_GCM || + cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) ? + 0 : MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + + TEST_EQUAL( expected, mbedtls_cipher_update_ad( &ctx_dec, ad, sizeof(ad) - i ) ); + TEST_EQUAL( expected, mbedtls_cipher_update_ad( &ctx_enc, ad, sizeof(ad) - i ) ); #endif block_size = mbedtls_cipher_get_block_size( &ctx_enc ); @@ -470,7 +474,7 @@ void enc_dec_buf( int cipher_id, char * cipher_string, int key_len, total_len += outlen; #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) - TEST_ASSERT( 0 == mbedtls_cipher_write_tag( &ctx_enc, tag, sizeof( tag ) ) ); + TEST_EQUAL( expected, mbedtls_cipher_write_tag( &ctx_enc, tag, sizeof(tag) ) ); #endif TEST_ASSERT( total_len == length || @@ -491,7 +495,7 @@ void enc_dec_buf( int cipher_id, char * cipher_string, int key_len, total_len += outlen; #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) - TEST_ASSERT( 0 == mbedtls_cipher_check_tag( &ctx_dec, tag, sizeof( tag ) ) ); + TEST_EQUAL( expected, mbedtls_cipher_check_tag( &ctx_dec, tag, sizeof(tag) ) ); #endif /* check result */ @@ -547,7 +551,11 @@ void enc_fail( int cipher_id, int pad_mode, int key_len, int length_val, TEST_ASSERT( 0 == mbedtls_cipher_set_iv( &ctx, iv, 16 ) ); TEST_ASSERT( 0 == mbedtls_cipher_reset( &ctx ) ); #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) - TEST_ASSERT( 0 == mbedtls_cipher_update_ad( &ctx, NULL, 0 ) ); + int expected = ( cipher_info->mode == MBEDTLS_MODE_GCM || + cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) ? + 0 : MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + + TEST_EQUAL( expected, mbedtls_cipher_update_ad( &ctx, NULL, 0 ) ); #endif /* encode length number of bytes from inbuf */ @@ -609,7 +617,11 @@ void dec_empty_buf( int cipher, TEST_ASSERT( 0 == mbedtls_cipher_reset( &ctx_dec ) ); #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) - TEST_ASSERT( 0 == mbedtls_cipher_update_ad( &ctx_dec, NULL, 0 ) ); + int expected = ( cipher_info->mode == MBEDTLS_MODE_GCM || + cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) ? + 0 : MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + + TEST_EQUAL( expected, mbedtls_cipher_update_ad( &ctx_dec, NULL, 0 ) ); #endif /* decode 0-byte string */ @@ -710,8 +722,12 @@ void enc_dec_buf_multipart( int cipher_id, int key_len, int first_length_val, TEST_ASSERT( 0 == mbedtls_cipher_reset( &ctx_enc ) ); #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) - TEST_ASSERT( 0 == mbedtls_cipher_update_ad( &ctx_dec, NULL, 0 ) ); - TEST_ASSERT( 0 == mbedtls_cipher_update_ad( &ctx_enc, NULL, 0 ) ); + int expected = ( cipher_info->mode == MBEDTLS_MODE_GCM || + cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) ? + 0 : MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + + TEST_EQUAL( expected, mbedtls_cipher_update_ad( &ctx_dec, NULL, 0 ) ); + TEST_EQUAL( expected, mbedtls_cipher_update_ad( &ctx_enc, NULL, 0 ) ); #endif block_size = mbedtls_cipher_get_block_size( &ctx_enc ); @@ -795,7 +811,11 @@ void decrypt_test_vec( int cipher_id, int pad_mode, data_t * key, TEST_ASSERT( 0 == mbedtls_cipher_set_iv( &ctx, iv->x, iv->len ) ); TEST_ASSERT( 0 == mbedtls_cipher_reset( &ctx ) ); #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) - TEST_ASSERT( 0 == mbedtls_cipher_update_ad( &ctx, ad->x, ad->len ) ); + int expected = ( ctx.cipher_info->mode == MBEDTLS_MODE_GCM || + ctx.cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) ? + 0 : MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + + TEST_EQUAL( expected, mbedtls_cipher_update_ad( &ctx, ad->x, ad->len ) ); #endif /* decode buffer and check tag->x */ @@ -806,7 +826,11 @@ void decrypt_test_vec( int cipher_id, int pad_mode, data_t * key, &outlen ) ); total_len += outlen; #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) - TEST_ASSERT( tag_result == mbedtls_cipher_check_tag( &ctx, tag->x, tag->len ) ); + int tag_expected = ( ctx.cipher_info->mode == MBEDTLS_MODE_GCM || + ctx.cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) ? + tag_result : MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + + TEST_EQUAL( tag_expected, mbedtls_cipher_check_tag( &ctx, tag->x, tag->len ) ); #endif /* check plaintext only if everything went fine */ diff --git a/tests/suites/test_suite_pkcs7.data b/tests/suites/test_suite_pkcs7.data new file mode 100644 index 0000000000..4f81b6f283 --- /dev/null +++ b/tests/suites/test_suite_pkcs7.data @@ -0,0 +1,75 @@ +PKCS7 Signed Data Parse Pass SHA256 #1 +depends_on:MBEDTLS_SHA256_C:MBEDTLS_RSA_C +pkcs7_parse:"data_files/pkcs7_data_cert_signed_sha256.der":MBEDTLS_PKCS7_SIGNED_DATA + +PKCS7 Signed Data Parse Pass SHA1 #2 +depends_on:MBEDTLS_SHA1_C:MBEDTLS_SHA256_C:MBEDTLS_RSA_C +pkcs7_parse:"data_files/pkcs7_data_cert_signed_sha1.der":MBEDTLS_PKCS7_SIGNED_DATA + +PKCS7 Signed Data Parse Pass Without CERT #3 +depends_on:MBEDTLS_SHA256_C +pkcs7_parse:"data_files/pkcs7_data_without_cert_signed.der":MBEDTLS_PKCS7_SIGNED_DATA + +PKCS7 Signed Data Parse Fail with multiple certs #4 +depends_on:MBEDTLS_SHA256_C:MBEDTLS_RSA_C +pkcs7_parse:"data_files/pkcs7_data_multiple_certs_signed.der":MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE + +PKCS7 Signed Data Parse Fail with corrupted cert #5 +depends_on:MBEDTLS_SHA256_C:MBEDTLS_RSA_C +pkcs7_parse:"data_files/pkcs7_data_signed_badcert.der":MBEDTLS_ERR_PKCS7_INVALID_CERT + +PKCS7 Signed Data Parse Fail with corrupted signer info #6 +depends_on:MBEDTLS_SHA256_C:MBEDTLS_RSA_C +pkcs7_parse:"data_files/pkcs7_data_signed_badsigner.der":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO,MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) + +PKCS7 Signed Data Parse Fail Version other than 1 #7 +depends_on:MBEDTLS_SHA256_C +pkcs7_parse:"data_files/pkcs7_data_cert_signed_v2.der":MBEDTLS_ERR_PKCS7_INVALID_VERSION + +PKCS7 Signed Data Parse Fail Encrypted Content #8 +depends_on:MBEDTLS_SHA256_C +pkcs7_parse:"data_files/pkcs7_data_cert_encrypted.der":MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE + +PKCS7 Signed Data Verification Pass SHA256 #9 +depends_on:MBEDTLS_SHA256_C +pkcs7_verify:"data_files/pkcs7_data_cert_signed_sha256.der":"data_files/pkcs7-rsa-sha256-1.der":"data_files/pkcs7_data.bin":0:0 + +PKCS7 Signed Data Verification Pass SHA256 #9.1 +depends_on:MBEDTLS_SHA256_C +pkcs7_verify:"data_files/pkcs7_data_cert_signed_sha256.der":"data_files/pkcs7-rsa-sha256-1.der":"data_files/pkcs7_data.bin":MBEDTLS_MD_SHA256:0 + +PKCS7 Signed Data Verification Pass SHA1 #10 +depends_on:MBEDTLS_SHA1_C:MBEDTLS_SHA256_C +pkcs7_verify:"data_files/pkcs7_data_cert_signed_sha1.der":"data_files/pkcs7-rsa-sha256-1.der":"data_files/pkcs7_data.bin":0:0 + +PKCS7 Signed Data Verification Pass SHA512 #11 +depends_on:MBEDTLS_SHA512_C:MBEDTLS_SHA256_C +pkcs7_verify:"data_files/pkcs7_data_cert_signed_sha512.der":"data_files/pkcs7-rsa-sha256-1.der":"data_files/pkcs7_data.bin":0:0 + +PKCS7 Signed Data Verification Fail because of different certificate #12 +depends_on:MBEDTLS_SHA256_C +pkcs7_verify:"data_files/pkcs7_data_cert_signed_sha256.der":"data_files/pkcs7-rsa-sha256-2.der":"data_files/pkcs7_data.bin":0:MBEDTLS_ERR_RSA_VERIFY_FAILED + +PKCS7 Signed Data Verification Fail because of different data hash #13 +depends_on:MBEDTLS_SHA256_C +pkcs7_verify:"data_files/pkcs7_data_cert_signed_sha256.der":"data_files/pkcs7-rsa-sha256-1.der":"data_files/pkcs7_data_1.bin":0:MBEDTLS_ERR_RSA_VERIFY_FAILED + +PKCS7 Signed Data Parse Failure Corrupt signerInfo.issuer #15.1 +depends_on:MBEDTLS_SHA256_C +pkcs7_parse:"data_files/pkcs7_signerInfo_issuer_invalid_size.der":MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + +PKCS7 Signed Data Parse Failure Corrupt signerInfo.serial #15.2 +depends_on:MBEDTLS_SHA256_C +pkcs7_parse:"data_files/pkcs7_signerInfo_serial_invalid_size.der":MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + +PKCS7 Only Signed Data Parse Pass #15 +depends_on:MBEDTLS_SHA256_C:MBEDTLS_RSA_C +pkcs7_parse:"data_files/pkcs7_data_cert_signeddata_sha256.der":MBEDTLS_PKCS7_SIGNED_DATA + +PKCS7 Signed Data Verify with multiple signers #16 +depends_on:MBEDTLS_SHA256_C +pkcs7_verify_multiple_signers:"data_files/pkcs7_data_multiple_signed.der":"data_files/pkcs7-rsa-sha256-1.crt":"data_files/pkcs7-rsa-sha256-2.crt":"data_files/pkcs7_data.bin":0:0 + +PKCS7 Signed Data Hash Verify with multiple signers #17 +depends_on:MBEDTLS_SHA256_C +pkcs7_verify_multiple_signers:"data_files/pkcs7_data_multiple_signed.der":"data_files/pkcs7-rsa-sha256-1.crt":"data_files/pkcs7-rsa-sha256-2.crt":"data_files/pkcs7_data.bin":MBEDTLS_MD_SHA256:0 diff --git a/tests/suites/test_suite_pkcs7.function b/tests/suites/test_suite_pkcs7.function new file mode 100644 index 0000000000..e3961407d5 --- /dev/null +++ b/tests/suites/test_suite_pkcs7.function @@ -0,0 +1,194 @@ +/* BEGIN_HEADER */ +#include "mbedtls/bignum.h" +#include "mbedtls/pkcs7.h" +#include "mbedtls/x509.h" +#include "mbedtls/x509_crt.h" +#include "mbedtls/x509_crl.h" +#include "mbedtls/oid.h" +#include "sys/types.h" +#include "sys/stat.h" +/* END_HEADER */ + +/* BEGIN_DEPENDENCIES + * depends_on:MBEDTLS_PKCS7_C:MBEDTLS_RSA_C + * END_DEPENDENCIES + */ + +/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */ +void pkcs7_parse( char *pkcs7_file, int res_expect ) +{ + unsigned char *pkcs7_buf = NULL; + size_t buflen; + int res; + + mbedtls_pkcs7 pkcs7; + + mbedtls_pkcs7_init( &pkcs7 ); + + res = mbedtls_pk_load_file( pkcs7_file, &pkcs7_buf, &buflen ); + TEST_ASSERT( res == 0 ); + + res = mbedtls_pkcs7_parse_der( &pkcs7, pkcs7_buf, buflen ); + TEST_ASSERT( res == res_expect ); + +exit: + mbedtls_free( pkcs7_buf ); + mbedtls_pkcs7_free( &pkcs7 ); +} +/* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_PKCS1_V15:MBEDTLS_RSA_C */ +void pkcs7_verify( char *pkcs7_file, char *crt, char *filetobesigned, int do_hash_alg, int res_expect ) +{ + unsigned char *pkcs7_buf = NULL; + size_t buflen; + unsigned char *data = NULL; + unsigned char hash[32]; + struct stat st; + size_t datalen; + int res; + FILE *file; + const mbedtls_md_info_t *md_info; + mbedtls_md_type_t md_alg; + + mbedtls_pkcs7 pkcs7; + mbedtls_x509_crt x509; + + USE_PSA_INIT(); + + mbedtls_pkcs7_init( &pkcs7 ); + mbedtls_x509_crt_init( &x509 ); + + res = mbedtls_x509_crt_parse_file( &x509, crt ); + TEST_ASSERT( res == 0 ); + + res = mbedtls_pk_load_file( pkcs7_file, &pkcs7_buf, &buflen ); + TEST_ASSERT( res == 0 ); + + res = mbedtls_pkcs7_parse_der( &pkcs7, pkcs7_buf, buflen ); + TEST_ASSERT( res == MBEDTLS_PKCS7_SIGNED_DATA ); + + res = stat( filetobesigned, &st ); + TEST_ASSERT( res == 0 ); + + file = fopen( filetobesigned, "rb" ); + TEST_ASSERT( file != NULL ); + + datalen = st.st_size; + ASSERT_ALLOC( data, datalen ); + TEST_ASSERT( data != NULL ); + + buflen = fread( (void *)data , sizeof( unsigned char ), datalen, file ); + TEST_ASSERT( buflen == datalen ); + fclose( file ); + + if( do_hash_alg ) + { + res = mbedtls_oid_get_md_alg( &pkcs7.signed_data.digest_alg_identifiers, &md_alg ); + TEST_ASSERT( res == 0 ); + TEST_ASSERT( md_alg == (mbedtls_md_type_t) do_hash_alg ); + md_info = mbedtls_md_info_from_type( md_alg ); + + res = mbedtls_md( md_info, data, datalen, hash ); + TEST_ASSERT( res == 0 ); + + res = mbedtls_pkcs7_signed_hash_verify( &pkcs7, &x509, hash, sizeof(hash) ); + } + else + { + res = mbedtls_pkcs7_signed_data_verify( &pkcs7, &x509, data, datalen ); + } + TEST_ASSERT( res == res_expect ); + +exit: + mbedtls_x509_crt_free( &x509 ); + mbedtls_free( data ); + mbedtls_pkcs7_free( &pkcs7 ); + mbedtls_free( pkcs7_buf ); + USE_PSA_DONE(); +} +/* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_PKCS1_V15:MBEDTLS_RSA_C */ +void pkcs7_verify_multiple_signers( char *pkcs7_file, char *crt1, char *crt2, char *filetobesigned, int do_hash_alg, int res_expect ) +{ + unsigned char *pkcs7_buf = NULL; + size_t buflen; + unsigned char *data = NULL; + unsigned char hash[32]; + struct stat st; + size_t datalen; + int res; + FILE *file; + const mbedtls_md_info_t *md_info; + mbedtls_md_type_t md_alg; + + mbedtls_pkcs7 pkcs7; + mbedtls_x509_crt x509_1; + mbedtls_x509_crt x509_2; + + USE_PSA_INIT(); + + mbedtls_pkcs7_init( &pkcs7 ); + mbedtls_x509_crt_init( &x509_1 ); + mbedtls_x509_crt_init( &x509_2 ); + + res = mbedtls_pk_load_file( pkcs7_file, &pkcs7_buf, &buflen ); + TEST_ASSERT( res == 0 ); + + res = mbedtls_pkcs7_parse_der( &pkcs7, pkcs7_buf, buflen ); + TEST_ASSERT( res == MBEDTLS_PKCS7_SIGNED_DATA ); + + TEST_ASSERT( pkcs7.signed_data.no_of_signers == 2 ); + + res = mbedtls_x509_crt_parse_file( &x509_1, crt1 ); + TEST_ASSERT( res == 0 ); + + res = mbedtls_x509_crt_parse_file( &x509_2, crt2 ); + TEST_ASSERT( res == 0 ); + + res = stat( filetobesigned, &st ); + TEST_ASSERT( res == 0 ); + + file = fopen( filetobesigned, "rb" ); + TEST_ASSERT( file != NULL ); + + datalen = st.st_size; + ASSERT_ALLOC( data, datalen ); + buflen = fread( ( void * )data , sizeof( unsigned char ), datalen, file ); + TEST_ASSERT( buflen == datalen ); + + fclose( file ); + + if( do_hash_alg ) + { + res = mbedtls_oid_get_md_alg( &pkcs7.signed_data.digest_alg_identifiers, &md_alg ); + TEST_ASSERT( res == 0 ); + TEST_ASSERT( md_alg == MBEDTLS_MD_SHA256 ); + + md_info = mbedtls_md_info_from_type( md_alg ); + + res = mbedtls_md( md_info, data, datalen, hash ); + TEST_ASSERT( res == 0 ); + + res = mbedtls_pkcs7_signed_hash_verify( &pkcs7, &x509_1, hash, sizeof(hash) ); + TEST_ASSERT( res == res_expect ); + } + else + { + res = mbedtls_pkcs7_signed_data_verify( &pkcs7, &x509_1, data, datalen ); + TEST_ASSERT( res == res_expect ); + } + + res = mbedtls_pkcs7_signed_data_verify( &pkcs7, &x509_2, data, datalen ); + TEST_ASSERT( res == res_expect ); + +exit: + mbedtls_x509_crt_free( &x509_1 ); + mbedtls_x509_crt_free( &x509_2 ); + mbedtls_pkcs7_free( &pkcs7 ); + mbedtls_free( data ); + mbedtls_free( pkcs7_buf ); + USE_PSA_DONE(); +} +/* END_CASE */ diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index cce3fd0fe8..659205d529 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -6549,11 +6549,16 @@ ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_ PSA PAKE: ecjpake rounds depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS -ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":0 +ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":0:0 PSA PAKE: ecjpake rounds, client input first depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS -ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":1 +ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":1:0 + +# This test case relies on implementation (it may need to be adjusted in the future) +PSA PAKE: ecjpake rounds - key is destroyed after being passed to set_password_key +depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS +ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":0:1 PSA PAKE: ecjpake no input errors depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256 diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 779f594dca..1f3b3b64a6 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -4,6 +4,7 @@ #include "mbedtls/asn1.h" #include "mbedtls/asn1write.h" #include "mbedtls/oid.h" +#include "common.h" /* For MBEDTLS_CTR_DRBG_MAX_REQUEST, knowing that psa_generate_random() * uses mbedtls_ctr_drbg internally. */ @@ -31,6 +32,27 @@ #define ASSERT_OPERATION_IS_ACTIVE( operation ) TEST_ASSERT( operation.id != 0 ) #define ASSERT_OPERATION_IS_INACTIVE( operation ) TEST_ASSERT( operation.id == 0 ) +#if defined(PSA_WANT_ALG_JPAKE) +int ecjpake_operation_setup( psa_pake_operation_t *operation, + psa_pake_cipher_suite_t *cipher_suite, + psa_pake_role_t role, + mbedtls_svc_key_id_t key, + size_t key_available ) +{ + PSA_ASSERT( psa_pake_abort( operation ) ); + + PSA_ASSERT( psa_pake_setup( operation, cipher_suite ) ); + + PSA_ASSERT( psa_pake_set_role( operation, role) ); + + if( key_available ) + PSA_ASSERT( psa_pake_set_password_key( operation, key ) ); + return 0; +exit: + return 1; +} +#endif + /** An invalid export length that will never be set by psa_export_key(). */ static const size_t INVALID_EXPORT_LENGTH = ~0U; @@ -3962,7 +3984,7 @@ void cipher_alg_without_iv( int alg_arg, int key_type_arg, data_t *key_data, TEST_LE_U( length, output_buffer_size ); output_length += length; PSA_ASSERT( psa_cipher_finish( &operation, - output + output_length, + mbedtls_buffer_offset( output, output_length ), output_buffer_size - output_length, &length ) ); output_length += length; @@ -3980,7 +4002,7 @@ void cipher_alg_without_iv( int alg_arg, int key_type_arg, data_t *key_data, TEST_LE_U( length, output_buffer_size ); output_length += length; PSA_ASSERT( psa_cipher_finish( &operation, - output + output_length, + mbedtls_buffer_offset( output, output_length ), output_buffer_size - output_length, &length ) ); output_length += length; @@ -8740,7 +8762,6 @@ void ecjpake_setup( int alg_arg, int key_type_pw_arg, int key_usage_pw_arg, { psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init(); psa_pake_operation_t operation = psa_pake_operation_init(); - psa_pake_operation_t op_copy = psa_pake_operation_init(); psa_algorithm_t alg = alg_arg; psa_pake_primitive_t primitive = primitive_arg; psa_key_type_t key_type_pw = key_type_pw_arg; @@ -8839,22 +8860,25 @@ void ecjpake_setup( int alg_arg, int key_type_pw_arg, int key_usage_pw_arg, if( input_first ) { /* Invalid parameters (input) */ - op_copy = operation; - TEST_EQUAL( psa_pake_input( &op_copy, PSA_PAKE_STEP_ZK_PROOF, + TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PROOF, NULL, 0 ), PSA_ERROR_INVALID_ARGUMENT ); /* Invalid parameters (step) */ - op_copy = operation; - TEST_EQUAL( psa_pake_input( &op_copy, PSA_PAKE_STEP_ZK_PROOF + 10, + TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role, + key, pw_data->len ) , 0 ); + TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PROOF + 10, output_buffer, size_zk_proof ), PSA_ERROR_INVALID_ARGUMENT ); /* Invalid first step */ - op_copy = operation; - TEST_EQUAL( psa_pake_input( &op_copy, PSA_PAKE_STEP_ZK_PROOF, + TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role, + key, pw_data->len ), 0 ); + TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PROOF, output_buffer, size_zk_proof ), PSA_ERROR_BAD_STATE ); /* Possibly valid */ + TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role, + key, pw_data->len ), 0 ); TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_KEY_SHARE, output_buffer, size_key_share ), expected_status_input_output); @@ -8875,22 +8899,25 @@ void ecjpake_setup( int alg_arg, int key_type_pw_arg, int key_usage_pw_arg, else { /* Invalid parameters (output) */ - op_copy = operation; - TEST_EQUAL( psa_pake_output( &op_copy, PSA_PAKE_STEP_ZK_PROOF, + TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PROOF, NULL, 0, NULL ), PSA_ERROR_INVALID_ARGUMENT ); - op_copy = operation; /* Invalid parameters (step) */ - TEST_EQUAL( psa_pake_output( &op_copy, PSA_PAKE_STEP_ZK_PROOF + 10, + TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role, + key, pw_data->len ), 0 ); + TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PROOF + 10, output_buffer, buf_size, &output_len ), PSA_ERROR_INVALID_ARGUMENT ); /* Invalid first step */ - op_copy = operation; - TEST_EQUAL( psa_pake_output( &op_copy, PSA_PAKE_STEP_ZK_PROOF, + TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role, + key, pw_data->len ), 0 ); + TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PROOF, output_buffer, buf_size, &output_len ), PSA_ERROR_BAD_STATE ); /* Possibly valid */ + TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role, + key, pw_data->len ), 0 ); TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_KEY_SHARE, output_buffer, buf_size, &output_len ), expected_status_input_output ); @@ -8974,7 +9001,7 @@ exit: /* BEGIN_CASE depends_on:PSA_WANT_ALG_JPAKE */ void ecjpake_rounds( int alg_arg, int primitive_arg, int hash_arg, int derive_alg_arg, data_t *pw_data, - int client_input_first ) + int client_input_first, int destroy_key ) { psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init(); psa_pake_operation_t server = psa_pake_operation_init(); @@ -9025,6 +9052,9 @@ void ecjpake_rounds( int alg_arg, int primitive_arg, int hash_arg, PSA_ASSERT( psa_pake_set_password_key( &server, key ) ); PSA_ASSERT( psa_pake_set_password_key( &client, key ) ); + if( destroy_key == 1 ) + psa_destroy_key( key ); + TEST_EQUAL( psa_pake_get_implicit_key( &server, &server_derive ), PSA_ERROR_BAD_STATE ); TEST_EQUAL( psa_pake_get_implicit_key( &client, &client_derive ),