diff --git a/ChangeLog.d/8848.txt b/ChangeLog.d/8848.txt new file mode 100644 index 0000000000..71bb7e3a68 --- /dev/null +++ b/ChangeLog.d/8848.txt @@ -0,0 +1,6 @@ +Removals + * Temporary function mbedtls_pk_wrap_as_opaque() is removed. To mimic the + same behavior mbedtls_pk_get_psa_attributes() and + mbedtls_pk_import_into_psa() can be used to import a PK key into PSA, + while mbedtls_pk_setup_opaque() can be used to wrap a PSA key into a opaque + PK context. diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h index 534712b5ab..ff80290059 100644 --- a/include/mbedtls/pk.h +++ b/include/mbedtls/pk.h @@ -1213,33 +1213,6 @@ int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, const mbedtls_pk_context *key); #endif /* MBEDTLS_PK_WRITE_C */ -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/** - * \brief Turn an EC or RSA key into an opaque one. - * - * \warning This is a temporary utility function for tests. It might - * change or be removed at any time without notice. - * - * \param pk Input: the EC or RSA key to import to a PSA key. - * Output: a PK context wrapping that PSA key. - * \param key Output: a PSA key identifier. - * It's the caller's responsibility to call - * psa_destroy_key() on that key identifier after calling - * mbedtls_pk_free() on the PK context. - * \param alg The algorithm to allow for use with that key. - * \param usage The usage to allow for use with that key. - * \param alg2 The secondary algorithm to allow for use with that key. - * - * \return \c 0 if successful. - * \return An Mbed TLS error code otherwise. - */ -int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, - mbedtls_svc_key_id_t *key, - psa_algorithm_t alg, - psa_key_usage_t usage, - psa_algorithm_t alg2); -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - #ifdef __cplusplus } #endif diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 08c628a3a0..78395d2a67 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -734,6 +734,51 @@ typedef enum { } mbedtls_ssl_states; +/* + * Early data status, client side only. + */ + +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) +typedef enum { +/* + * The client has not sent the first ClientHello yet, it is unknown if the + * client will send an early data indication extension or not. + */ + MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN, + +/* + * See documentation of mbedtls_ssl_get_early_data_status(). + */ + MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT, + MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED, + MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED, + +/* + * The client has sent an early data indication extension in its first + * ClientHello, it has not received the response (ServerHello or + * HelloRetryRequest) from the server yet. The transform to protect early data + * is not set and early data cannot be sent yet. + */ + MBEDTLS_SSL_EARLY_DATA_STATUS_SENT, + +/* + * The client has sent an early data indication extension in its first + * ClientHello, it has not received the response (ServerHello or + * HelloRetryRequest) from the server yet. The transform to protect early data + * has been set and early data can be written now. + */ + MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE, + +/* + * The client has sent an early data indication extension in its first + * ClientHello, the server has accepted them and the client has received the + * server Finished message. It cannot send early data to the server anymore. + */ + MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED, +} mbedtls_ssl_early_data_status; + +#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */ + /** * \brief Callback type: send data on the network. * @@ -1673,33 +1718,29 @@ struct mbedtls_ssl_context { #endif /* MBEDTLS_SSL_RENEGOTIATION */ /** - * Maximum TLS version to be negotiated, then negotiated TLS version. + * Maximum TLS version to be negotiated, then negotiated TLS version. * - * It is initialized as the configured maximum TLS version to be - * negotiated by mbedtls_ssl_setup(). + * It is initialized as the configured maximum TLS version to be + * negotiated by mbedtls_ssl_setup(). * - * When renegotiating or resuming a session, it is overwritten in the - * ClientHello writing preparation stage with the previously negotiated - * TLS version. + * When renegotiating or resuming a session, it is overwritten in the + * ClientHello writing preparation stage with the previously negotiated + * TLS version. * - * On client side, it is updated to the TLS version selected by the server - * for the handshake when the ServerHello is received. + * On client side, it is updated to the TLS version selected by the server + * for the handshake when the ServerHello is received. * - * On server side, it is updated to the TLS version the server selects for - * the handshake when the ClientHello is received. + * On server side, it is updated to the TLS version the server selects for + * the handshake when the ClientHello is received. */ mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(tls_version); #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) /** - * Status of the negotiation of the use of early data. - * See the documentation of mbedtls_ssl_get_early_data_status() for more - * information. - * - * Reset to #MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT when the context is - * reset. + * Status of the negotiation of the use of early data. Reset to + * MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN when the context is reset. */ - int MBEDTLS_PRIVATE(early_data_status); + mbedtls_ssl_early_data_status MBEDTLS_PRIVATE(early_data_status); #endif unsigned MBEDTLS_PRIVATE(badmac_seen); /*!< records with a bad MAC received */ @@ -5150,10 +5191,6 @@ int mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_EARLY_DATA) -#define MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT 1 -#define MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED 2 -#define MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED 3 - #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Read at most 'len' bytes of early data @@ -5206,17 +5243,43 @@ int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl, * \brief Try to write exactly 'len' application data bytes while * performing the handshake (early data). * + * \warning Early data is defined in the TLS 1.3 specification, RFC 8446. + * IMPORTANT NOTE from section 2.3 of the specification: + * + * The security properties for 0-RTT data are weaker than + * those for other kinds of TLS data. Specifically: + * - This data is not forward secret, as it is encrypted + * solely under keys derived using the offered PSK. + * - There are no guarantees of non-replay between connections. + * Protection against replay for ordinary TLS 1.3 1-RTT data + * is provided via the server's Random value, but 0-RTT data + * does not depend on the ServerHello and therefore has + * weaker guarantees. This is especially relevant if the + * data is authenticated either with TLS client + * authentication or inside the application protocol. The + * same warnings apply to any use of the + * early_exporter_master_secret. + * * \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(). + * function and the present documentation is mainly restricted + * to the differences with mbedtls_ssl_write(). One noticeable + * difference though is that mbedtls_ssl_write() aims to + * complete the handshake before to write application data + * while mbedtls_ssl_write_early() aims to drive the handshake + * just past the point where it is not possible to send early + * data anymore. * * \param ssl SSL context * \param buf buffer holding the data * \param len how many bytes must be written * - * \return One additional specific return value: + * \return The (non-negative) number of bytes actually written if + * successful (may be less than \p len). + * + * \return One additional specific error code compared to + * mbedtls_ssl_write(): * #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA. * * #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA is returned when it @@ -5237,9 +5300,11 @@ int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl, * 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 + * \p ssl and any subsequent call to this API will return this + * error code. But this does not preclude for using it with * mbedtls_ssl_write(), mbedtls_ssl_read() or - * mbedtls_ssl_handshake(). + * mbedtls_ssl_handshake() and the handshake can be + * completed by calling one of these APIs. * * \note This function may write early data only if the SSL context * has been configured for the handshake with a PSK for which diff --git a/library/pk.c b/library/pk.c index 328bbe1eaa..003ef4aac2 100644 --- a/library/pk.c +++ b/library/pk.c @@ -1182,9 +1182,32 @@ int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type, } if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) { + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t psa_alg, psa_enrollment_alg, sign_alg; psa_status_t status; - status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS(psa_md_alg), + status = psa_get_key_attributes(ctx->priv_id, &key_attr); + if (status != PSA_SUCCESS) { + return PSA_PK_RSA_TO_MBEDTLS_ERR(status); + } + psa_alg = psa_get_key_algorithm(&key_attr); + psa_enrollment_alg = psa_get_key_enrollment_algorithm(&key_attr); + psa_reset_key_attributes(&key_attr); + + /* Since we're PK type is MBEDTLS_PK_RSASSA_PSS at least one between + * alg and enrollment alg should be of type RSA_PSS. */ + if (PSA_ALG_IS_RSA_PSS(psa_alg)) { + sign_alg = psa_alg; + } else if (PSA_ALG_IS_RSA_PSS(psa_enrollment_alg)) { + sign_alg = psa_enrollment_alg; + } else { + /* The opaque key has no RSA PSS algorithm associated. */ + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + /* Adjust the hashing algorithm. */ + sign_alg = (sign_alg & ~PSA_ALG_HASH_MASK) | PSA_ALG_GET_HASH(psa_md_alg); + + status = psa_sign_hash(ctx->priv_id, sign_alg, hash, hash_len, sig, sig_size, sig_len); return PSA_PK_RSA_TO_MBEDTLS_ERR(status); @@ -1351,123 +1374,4 @@ mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx) return ctx->pk_info->type; } -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/* - * Load the key to a PSA key slot, - * then turn the PK context into a wrapper for that key slot. - * - * Currently only works for EC & RSA private keys. - */ -int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, - mbedtls_svc_key_id_t *key, - psa_algorithm_t alg, - psa_key_usage_t usage, - psa_algorithm_t alg2) -{ -#if !defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_RSA_C) - ((void) pk); - ((void) key); - ((void) alg); - ((void) usage); - ((void) alg2); -#else /* !MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_RSA_C */ -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECKEY) { - size_t d_len; - psa_ecc_family_t curve_id; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_type_t key_type; - size_t bits; - psa_status_t status; - - /* export the private key material in the format PSA wants */ -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - unsigned char d[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH]; - status = psa_export_key(pk->priv_id, d, sizeof(d), &d_len); - if (status != PSA_SUCCESS) { - return psa_pk_status_to_mbedtls(status); - } - - curve_id = pk->ec_family; - bits = pk->ec_bits; -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ - unsigned char d[MBEDTLS_ECP_MAX_BYTES]; - mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk); - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if ((ret = mbedtls_ecp_write_key_ext(ec, &d_len, d, sizeof(d))) != 0) { - return ret; - } - - curve_id = mbedtls_ecc_group_to_psa(ec->grp.id, &bits); -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(curve_id); - - /* prepare the key attributes */ - psa_set_key_type(&attributes, key_type); - psa_set_key_bits(&attributes, bits); - psa_set_key_usage_flags(&attributes, usage); - psa_set_key_algorithm(&attributes, alg); - if (alg2 != PSA_ALG_NONE) { - psa_set_key_enrollment_algorithm(&attributes, alg2); - } - - /* import private key into PSA */ - status = psa_import_key(&attributes, d, d_len, key); - mbedtls_platform_zeroize(d, sizeof(d)); - if (status != PSA_SUCCESS) { - return PSA_PK_TO_MBEDTLS_ERR(status); - } - - /* make PK context wrap the key slot */ - mbedtls_pk_free(pk); - mbedtls_pk_init(pk); - - return mbedtls_pk_setup_opaque(pk, *key); - } else -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ -#if defined(MBEDTLS_RSA_C) - if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA) { - unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES]; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - int key_len; - psa_status_t status; - - /* export the private key material in the format PSA wants */ - key_len = mbedtls_pk_write_key_der(pk, buf, sizeof(buf)); - if (key_len <= 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - /* prepare the key attributes */ - psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); - psa_set_key_bits(&attributes, mbedtls_pk_get_bitlen(pk)); - psa_set_key_usage_flags(&attributes, usage); - psa_set_key_algorithm(&attributes, alg); - if (alg2 != PSA_ALG_NONE) { - psa_set_key_enrollment_algorithm(&attributes, alg2); - } - - /* import private key into PSA */ - status = psa_import_key(&attributes, - buf + sizeof(buf) - key_len, - key_len, key); - - mbedtls_platform_zeroize(buf, sizeof(buf)); - - if (status != PSA_SUCCESS) { - return PSA_PK_TO_MBEDTLS_ERR(status); - } - - /* make PK context wrap the key slot */ - mbedtls_pk_free(pk); - mbedtls_pk_init(pk); - - return mbedtls_pk_setup_opaque(pk, *key); - } else -#endif /* MBEDTLS_RSA_C */ -#endif /* !MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_RSA_C */ - return MBEDTLS_ERR_PK_TYPE_MISMATCH; -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_PK_C */ diff --git a/library/ssl_debug_helpers.h b/library/ssl_debug_helpers.h index 2b0e73772b..a8e31409f8 100644 --- a/library/ssl_debug_helpers.h +++ b/library/ssl_debug_helpers.h @@ -21,6 +21,10 @@ const char *mbedtls_ssl_states_str(mbedtls_ssl_states in); +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) +const char *mbedtls_ssl_early_data_status_str(mbedtls_ssl_early_data_status in); +#endif + const char *mbedtls_ssl_protocol_version_str(mbedtls_ssl_protocol_version in); const char *mbedtls_tls_prf_types_str(mbedtls_tls_prf_types in); diff --git a/library/ssl_misc.h b/library/ssl_misc.h index 942d4ad22f..d8844fcc32 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -665,21 +665,21 @@ struct mbedtls_ssl_handshake_params { #if defined(MBEDTLS_SSL_CLI_C) /** Minimum TLS version to be negotiated. * - * It is set up in the ClientHello writing preparation stage and used - * throughout the ClientHello writing. Not relevant anymore as soon as - * the protocol version has been negotiated thus as soon as the - * ServerHello is received. - * For a fresh handshake not linked to any previous handshake, it is - * equal to the configured minimum minor version to be negotiated. When - * renegotiating or resuming a session, it is equal to the previously - * negotiated minor version. + * It is set up in the ClientHello writing preparation stage and used + * throughout the ClientHello writing. Not relevant anymore as soon as + * the protocol version has been negotiated thus as soon as the + * ServerHello is received. + * For a fresh handshake not linked to any previous handshake, it is + * equal to the configured minimum minor version to be negotiated. When + * renegotiating or resuming a session, it is equal to the previously + * negotiated minor version. * - * There is no maximum TLS version field in this handshake context. - * From the start of the handshake, we need to define a current protocol - * version for the record layer which we define as the maximum TLS - * version to be negotiated. The `tls_version` field of the SSL context is - * used to store this maximum value until it contains the actual - * negotiated value. + * There is no maximum TLS version field in this handshake context. + * From the start of the handshake, we need to define a current protocol + * version for the record layer which we define as the maximum TLS + * version to be negotiated. The `tls_version` field of the SSL context is + * used to store this maximum value until it contains the actual + * negotiated value. */ mbedtls_ssl_protocol_version min_tls_version; #endif @@ -730,16 +730,21 @@ struct mbedtls_ssl_handshake_params { #if defined(MBEDTLS_SSL_PROTO_TLS1_3) uint8_t key_exchange_mode; /*!< Selected key exchange mode */ - /** Number of HelloRetryRequest messages received/sent from/to the server. */ - uint8_t hello_retry_request_count; + /** + * Flag indicating if, in the course of the current handshake, an + * HelloRetryRequest message has been sent by the server or received by + * the client (<> 0) or not (0). + */ + uint8_t hello_retry_request_flag; #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) /** - * Number of dummy change_cipher_spec (CCS) record sent. Used to send only - * one CCS per handshake without having to complicate the handshake state - * transitions. + * Flag indicating if, in the course of the current handshake, a dummy + * change_cipher_spec (CCS) record has already been sent. Used to send only + * one CCS per handshake while not complicating the handshake state + * transitions for that purpose. */ - uint8_t ccs_count; + uint8_t ccs_sent; #endif #if defined(MBEDTLS_SSL_SRV_C) @@ -2145,38 +2150,6 @@ int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *out_len); - -#if defined(MBEDTLS_SSL_CLI_C) -/* - * The client has not sent the first ClientHello yet, it is unknown if the - * client will send an early data indication extension or not. - */ -#define MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN 0 - -/* - * The client has sent an early data indication extension in its first - * ClientHello, it has not received the response (ServerHello or - * HelloRetryRequest) from the server yet. The transform to protect early data - * is not set and early data cannot be sent yet. - */ -#define MBEDTLS_SSL_EARLY_DATA_STATUS_SENT 4 - -/* - * The client has sent an early data indication extension in its first - * ClientHello, it has not received the response (ServerHello or - * HelloRetryRequest) from the server yet. The transform to protect early data - * has been set and early data can be written now. - */ -#define MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE 5 - -/* - * The client has sent an early data indication extension in its first - * ClientHello, the server has accepted them and the client has received the - * server Finished message. It cannot send early data to the server anymore. - */ -#define MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED 6 -#endif /* MBEDTLS_SSL_CLI_C */ - #endif /* MBEDTLS_SSL_EARLY_DATA */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ diff --git a/library/ssl_msg.c b/library/ssl_msg.c index c2e64c6096..2a6d4341be 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -6058,6 +6058,94 @@ int mbedtls_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t return ret; } +#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const struct mbedtls_ssl_config *conf; + int written_data_len = 0; + + MBEDTLS_SSL_DEBUG_MSG(2, ("=> write early_data")); + + if (ssl == NULL || (conf = ssl->conf) == NULL) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + if (conf->endpoint != MBEDTLS_SSL_IS_CLIENT) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + if ((!mbedtls_ssl_conf_is_tls13_enabled(conf)) || + (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) || + (conf->early_data_enabled != MBEDTLS_SSL_EARLY_DATA_ENABLED)) { + return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; + } + + if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) { + return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; + } + + /* + * If we are at the beginning of the handshake, the early data status being + * equal to MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN or + * MBEDTLS_SSL_EARLY_DATA_STATUS_SENT advance the handshake just + * enough to be able to send early data if possible. That way, we can + * guarantee that when starting the handshake with this function we will + * send at least one record of early data. Note that when the status is + * MBEDTLS_SSL_EARLY_DATA_STATUS_SENT and not yet + * MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE, we cannot send early data yet + * as the early data outbound transform has not been set as we may have to + * first send a dummy CCS in clear. + */ + if ((ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN) || + (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT)) { + while ((ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN) || + (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT)) { + ret = mbedtls_ssl_handshake_step(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake_step", ret); + return ret; + } + + ret = mbedtls_ssl_flush_output(ssl); + if (ret != 0) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flush_output", ret); + return ret; + } + } + } else { + /* + * If we are past the point where we can send early data, return + * immediatly. Otherwise, progress the handshake as much as possible to + * not delay it too much. If we reach a point where we can still send + * early data, then we will send some. + */ + if ((ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE) && + (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED)) { + return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; + } + + ret = mbedtls_ssl_handshake(ssl); + if ((ret != 0) && (ret != MBEDTLS_ERR_SSL_WANT_READ)) { + MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); + return ret; + } + } + + if ((ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE) && + (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED)) { + return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; + } + + written_data_len = ssl_write_real(ssl, buf, len); + + MBEDTLS_SSL_DEBUG_MSG(2, ("<= write early_data, len=%d", written_data_len)); + + return written_data_len; +} +#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */ + /* * Notify the peer that the connection is being closed */ diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c index 1e8df1b399..88d6c9e019 100644 --- a/library/ssl_tls13_client.c +++ b/library/ssl_tls13_client.c @@ -1180,7 +1180,15 @@ int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl, #endif #if defined(MBEDTLS_SSL_EARLY_DATA) - if (ssl->handshake->hello_retry_request_count == 0) { + /* In the first ClientHello, write the early data indication extension if + * necessary and update the early data status. + * If an HRR has been received and thus we are currently writing the + * second ClientHello, the second ClientHello must not contain an early + * data extension and the early data status must stay as it is: + * MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT or + * MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED. + */ + if (!ssl->handshake->hello_retry_request_flag) { if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) && ssl_tls13_early_data_has_valid_ticket(ssl) && ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) { @@ -1495,7 +1503,7 @@ static int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl, * to a HelloRetryRequest), it MUST abort the handshake with an * "unexpected_message" alert. */ - if (handshake->hello_retry_request_count > 0) { + if (handshake->hello_retry_request_flag) { MBEDTLS_SSL_DEBUG_MSG(1, ("Multiple HRRs received")); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, @@ -1517,7 +1525,7 @@ static int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl, return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } - handshake->hello_retry_request_count++; + handshake->hello_retry_request_flag = 1; break; } @@ -1672,7 +1680,7 @@ static int ssl_tls13_parse_server_hello(mbedtls_ssl_context *ssl, * proposed in the HRR, we abort the handshake and send an * "illegal_parameter" alert. */ - else if ((!is_hrr) && (handshake->hello_retry_request_count > 0) && + else if ((!is_hrr) && handshake->hello_retry_request_flag && (cipher_suite != ssl->session_negotiate->ciphersuite)) { fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; } @@ -2270,6 +2278,7 @@ cleanup: } +#if defined(MBEDTLS_SSL_EARLY_DATA) /* * Handler for MBEDTLS_SSL_END_OF_EARLY_DATA * @@ -2308,6 +2317,32 @@ cleanup: return ret; } +int mbedtls_ssl_get_early_data_status(mbedtls_ssl_context *ssl) +{ + if ((ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) || + (!mbedtls_ssl_is_handshake_over(ssl))) { + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + } + + switch (ssl->early_data_status) { + case MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT: + return MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT; + break; + + case MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED: + return MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED; + break; + + case MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED: + return MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED; + break; + + default: + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } +} +#endif /* MBEDTLS_SSL_EARLY_DATA */ + #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) /* * STATE HANDLING: CertificateRequest @@ -3030,9 +3065,11 @@ int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl) ret = ssl_tls13_process_server_finished(ssl); break; +#if defined(MBEDTLS_SSL_EARLY_DATA) case MBEDTLS_SSL_END_OF_EARLY_DATA: ret = ssl_tls13_write_end_of_early_data(ssl); break; +#endif case MBEDTLS_SSL_CLIENT_CERTIFICATE: ret = ssl_tls13_write_client_certificate(ssl); @@ -3061,23 +3098,17 @@ int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl) */ #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO: - ret = 0; - if (ssl->handshake->ccs_count == 0) { - ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); - if (ret != 0) { - break; - } + ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); + if (ret != 0) { + break; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); break; case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: - ret = 0; - if (ssl->handshake->ccs_count == 0) { - ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); - if (ret != 0) { - break; - } + ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); + if (ret != 0) { + break; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); break; diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index 064f6160df..bc737047a4 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -1379,6 +1379,12 @@ int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl) MBEDTLS_SSL_DEBUG_MSG(2, ("=> write change cipher spec")); + /* Only one CCS to send. */ + if (ssl->handshake->ccs_sent) { + ret = 0; + goto cleanup; + } + /* Write CCS message */ MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_change_cipher_spec_body( ssl, ssl->out_msg, @@ -1390,7 +1396,7 @@ int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl) /* Dispatch message */ MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_record(ssl, 0)); - ssl->handshake->ccs_count++; + ssl->handshake->ccs_sent = 1; cleanup: diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c index 141144675d..3a968aa964 100644 --- a/library/ssl_tls13_server.c +++ b/library/ssl_tls13_server.c @@ -1531,7 +1531,7 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl, const unsigned char *extension_data_end; uint32_t allowed_exts = MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH; - if (ssl->handshake->hello_retry_request_count > 0) { + if (ssl->handshake->hello_retry_request_flag) { /* Do not accept early data extension in 2nd ClientHello */ allowed_exts &= ~MBEDTLS_SSL_EXT_MASK(EARLY_DATA); } @@ -2427,7 +2427,7 @@ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_prepare_hello_retry_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if (ssl->handshake->hello_retry_request_count > 0) { + if (ssl->handshake->hello_retry_request_flag) { MBEDTLS_SSL_DEBUG_MSG(1, ("Too many HRRs")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); @@ -2474,7 +2474,7 @@ static int ssl_tls13_write_hello_retry_request(mbedtls_ssl_context *ssl) MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl, buf_len, msg_len)); - ssl->handshake->hello_retry_request_count++; + ssl->handshake->hello_retry_request_flag = 1; #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) /* The server sends a dummy change_cipher_spec record immediately @@ -3477,12 +3477,9 @@ int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl) break; case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO: - ret = 0; - if (ssl->handshake->ccs_count == 0) { - ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); - if (ret != 0) { - break; - } + ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); + if (ret != 0) { + break; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); break; diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 05bb2ffdd0..332befdf93 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -52,7 +52,7 @@ int main(void) #define DFL_KEY_OPAQUE 0 #define DFL_KEY_PWD "" #define DFL_PSK "" -#define DFL_EARLY_DATA "" +#define DFL_EARLY_DATA -1 #define DFL_PSK_OPAQUE 0 #define DFL_PSK_IDENTITY "Client_identity" #define DFL_ECJPAKE_PW NULL @@ -347,9 +347,8 @@ int main(void) #if defined(MBEDTLS_SSL_EARLY_DATA) #define USAGE_EARLY_DATA \ - " early_data=%%s The file path to read early data from\n" \ - " default: \"\" (do nothing)\n" \ - " option: a file path\n" + " early_data=%%d default: library default\n" \ + " options: 0 (disabled), 1 (enabled)\n" #else #define USAGE_EARLY_DATA "" #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_PROTO_TLS1_3 */ @@ -544,7 +543,7 @@ struct options { int reproducible; /* make communication reproducible */ int skip_close_notify; /* skip sending the close_notify alert */ #if defined(MBEDTLS_SSL_EARLY_DATA) - const char *early_data; /* the path of the file to read early data from */ + int early_data; /* early data enablement flag */ #endif int query_config_mode; /* whether to read config */ int use_srtp; /* Support SRTP */ @@ -717,9 +716,64 @@ exit: return ret; } +/* + * Build HTTP request + */ +static int build_http_request(unsigned char *buf, size_t buf_size, size_t *request_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len, tail_len, request_size; + + ret = mbedtls_snprintf((char *) buf, buf_size, GET_REQUEST, opt.request_page); + if (ret < 0) { + return ret; + } + + len = (size_t) ret; + tail_len = strlen(GET_REQUEST_END); + if (opt.request_size != DFL_REQUEST_SIZE) { + request_size = (size_t) opt.request_size; + } else { + request_size = len + tail_len; + } + + if (request_size > buf_size) { + return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + } + + /* Add padding to GET request to reach opt.request_size in length */ + if (opt.request_size != DFL_REQUEST_SIZE && + len + tail_len < request_size) { + memset(buf + len, 'A', request_size - len - tail_len); + len = request_size - tail_len; + } + + strncpy((char *) buf + len, GET_REQUEST_END, buf_size - len); + len += tail_len; + + /* Truncate if request size is smaller than the "natural" size */ + if (opt.request_size != DFL_REQUEST_SIZE && + len > request_size) { + len = request_size; + + /* Still end with \r\n unless that's really not possible */ + if (len >= 2) { + buf[len - 2] = '\r'; + } + if (len >= 1) { + buf[len - 1] = '\n'; + } + } + + *request_len = len; + + return 0; +} + int main(int argc, char *argv[]) { - int ret = 0, len, tail_len, i, written, frags, retry_left; + int ret = 0, i; + size_t len, written, frags, retry_left; int query_config_ret = 0; mbedtls_net_context server_fd; io_ctx_t io_ctx; @@ -742,10 +796,6 @@ int main(int argc, char *argv[]) size_t cid_renego_len = 0; #endif -#if defined(MBEDTLS_SSL_EARLY_DATA) - FILE *early_data_fp = NULL; -#endif /* MBEDTLS_SSL_EARLY_DATA */ - #if defined(MBEDTLS_SSL_ALPN) const char *alpn_list[ALPN_LIST_SIZE]; #endif @@ -1201,7 +1251,15 @@ usage: #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #if defined(MBEDTLS_SSL_EARLY_DATA) else if (strcmp(p, "early_data") == 0) { - opt.early_data = q; + switch (atoi(q)) { + case 0: + opt.early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED; + break; + case 1: + opt.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED; + break; + default: goto usage; + } } #endif /* MBEDTLS_SSL_EARLY_DATA */ @@ -1711,11 +1769,10 @@ usage: &psa_alg, &psa_alg2, &usage, mbedtls_pk_get_type(&pkey)) == 0) { - ret = mbedtls_pk_wrap_as_opaque(&pkey, &key_slot, psa_alg, - usage, psa_alg2); + ret = pk_wrap_as_opaque(&pkey, psa_alg, psa_alg2, usage, &key_slot); if (ret != 0) { mbedtls_printf(" failed\n ! " - "mbedtls_pk_wrap_as_opaque returned -0x%x\n\n", + "mbedtls_pk_get_psa_attributes returned -0x%x\n\n", (unsigned int) -ret); goto exit; } @@ -1968,16 +2025,9 @@ usage: } #if defined(MBEDTLS_SSL_EARLY_DATA) - int early_data_enabled = MBEDTLS_SSL_EARLY_DATA_DISABLED; - if (strlen(opt.early_data) > 0) { - if ((early_data_fp = fopen(opt.early_data, "rb")) == NULL) { - mbedtls_printf("failed\n ! Cannot open '%s' for reading.\n", - opt.early_data); - goto exit; - } - early_data_enabled = MBEDTLS_SSL_EARLY_DATA_ENABLED; + if (opt.early_data != DFL_EARLY_DATA) { + mbedtls_ssl_conf_early_data(&conf, opt.early_data); } - mbedtls_ssl_conf_early_data(&conf, early_data_enabled); #endif /* MBEDTLS_SSL_EARLY_DATA */ if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { @@ -2448,32 +2498,9 @@ send_request: mbedtls_printf(" > Write to server:"); fflush(stdout); - len = mbedtls_snprintf((char *) buf, sizeof(buf) - 1, GET_REQUEST, - opt.request_page); - tail_len = (int) strlen(GET_REQUEST_END); - - /* Add padding to GET request to reach opt.request_size in length */ - if (opt.request_size != DFL_REQUEST_SIZE && - len + tail_len < opt.request_size) { - memset(buf + len, 'A', opt.request_size - len - tail_len); - len += opt.request_size - len - tail_len; - } - - strncpy((char *) buf + len, GET_REQUEST_END, sizeof(buf) - len - 1); - len += tail_len; - - /* Truncate if request size is smaller than the "natural" size */ - if (opt.request_size != DFL_REQUEST_SIZE && - len > opt.request_size) { - len = opt.request_size; - - /* Still end with \r\n unless that's really not possible */ - if (len >= 2) { - buf[len - 2] = '\r'; - } - if (len >= 1) { - buf[len - 1] = '\n'; - } + ret = build_http_request(buf, sizeof(buf) - 1, &len); + if (ret != 0) { + goto exit; } if (opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM) { @@ -2545,8 +2572,11 @@ send_request: } buf[written] = '\0'; - mbedtls_printf(" %d bytes written in %d fragments\n\n%s\n", - written, frags, (char *) buf); + mbedtls_printf( + " %" MBEDTLS_PRINTF_SIZET " bytes written in %" MBEDTLS_PRINTF_SIZET " fragments\n\n%s\n", + written, + frags, + (char *) buf); /* Send a non-empty request if request_size == 0 */ if (len == 0) { @@ -2653,7 +2683,9 @@ send_request: len = ret; buf[len] = '\0'; - mbedtls_printf(" < Read from server: %d bytes read\n\n%s", len, (char *) buf); + mbedtls_printf(" < Read from server: %" MBEDTLS_PRINTF_SIZET " bytes read\n\n%s", + len, + (char *) buf); fflush(stdout); /* End of message should be detected according to the syntax of the * application protocol (eg HTTP), just use a dummy test here. */ @@ -2712,7 +2744,9 @@ send_request: len = ret; buf[len] = '\0'; - mbedtls_printf(" < Read from server: %d bytes read\n\n%s", len, (char *) buf); + mbedtls_printf(" < Read from server: %" MBEDTLS_PRINTF_SIZET " bytes read\n\n%s", + len, + (char *) buf); ret = 0; } @@ -3002,6 +3036,54 @@ reconnect: goto exit; } + ret = build_http_request(buf, sizeof(buf) - 1, &len); + if (ret != 0) { + goto exit; + } + +#if defined(MBEDTLS_SSL_EARLY_DATA) + if (ssl.conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) { + frags = 0; + written = 0; + do { + while ((ret = mbedtls_ssl_write_early_data(&ssl, buf + written, + len - written)) < 0) { + if (ret == MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA) { + goto end_of_early_data; + } + if (ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) { + mbedtls_printf(" failed\n ! mbedtls_ssl_write returned -0x%x\n\n", + (unsigned int) -ret); + goto exit; + } + + /* For event-driven IO, wait for socket to become available */ + if (opt.event == 1 /* level triggered IO */) { +#if defined(MBEDTLS_TIMING_C) + idle(&server_fd, &timer, ret); +#else + idle(&server_fd, ret); +#endif + } + } + + frags++; + written += ret; + } while (written < len); + } + +end_of_early_data: + + buf[written] = '\0'; + mbedtls_printf( + " %" MBEDTLS_PRINTF_SIZET " bytes of early data written in %" MBEDTLS_PRINTF_SIZET " fragments\n\n%s\n", + written, + frags, + (char *) buf); +#endif /* MBEDTLS_SSL_EARLY_DATA */ + while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && @@ -3035,12 +3117,6 @@ exit: mbedtls_ssl_config_free(&conf); mbedtls_ssl_session_free(&saved_session); -#if defined(MBEDTLS_SSL_EARLY_DATA) - if (early_data_fp != NULL) { - fclose(early_data_fp); - } -#endif - if (session_data != NULL) { mbedtls_platform_zeroize(session_data, session_data_len); } diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index abf33dec9d..f00a111fd1 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -2708,12 +2708,10 @@ usage: &psa_alg, &psa_alg2, &psa_usage, mbedtls_pk_get_type(&pkey)) == 0) { - ret = mbedtls_pk_wrap_as_opaque(&pkey, &key_slot, - psa_alg, psa_usage, psa_alg2); - + ret = pk_wrap_as_opaque(&pkey, psa_alg, psa_alg2, psa_usage, &key_slot); if (ret != 0) { mbedtls_printf(" failed\n ! " - "mbedtls_pk_wrap_as_opaque returned -0x%x\n\n", + "pk_wrap_as_opaque returned -0x%x\n\n", (unsigned int) -ret); goto exit; } @@ -2727,12 +2725,10 @@ usage: &psa_alg, &psa_alg2, &psa_usage, mbedtls_pk_get_type(&pkey2)) == 0) { - ret = mbedtls_pk_wrap_as_opaque(&pkey2, &key_slot2, - psa_alg, psa_usage, psa_alg2); - + ret = pk_wrap_as_opaque(&pkey2, psa_alg, psa_alg2, psa_usage, &key_slot2); if (ret != 0) { mbedtls_printf(" failed\n ! " - "mbedtls_pk_wrap_as_opaque returned -0x%x\n\n", + "mbedtls_pk_get_psa_attributes returned -0x%x\n\n", (unsigned int) -ret); goto exit; } diff --git a/programs/ssl/ssl_test_lib.c b/programs/ssl/ssl_test_lib.c index d3ac526f7e..17d36b7de6 100644 --- a/programs/ssl/ssl_test_lib.c +++ b/programs/ssl/ssl_test_lib.c @@ -274,6 +274,37 @@ int key_opaque_set_alg_usage(const char *alg1, const char *alg2, return 0; } + +#if defined(MBEDTLS_PK_C) +int pk_wrap_as_opaque(mbedtls_pk_context *pk, psa_algorithm_t psa_alg, psa_algorithm_t psa_alg2, + psa_key_usage_t psa_usage, mbedtls_svc_key_id_t *key_id) +{ + int ret; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + + ret = mbedtls_pk_get_psa_attributes(pk, PSA_KEY_USAGE_SIGN_HASH, &key_attr); + if (ret != 0) { + return ret; + } + psa_set_key_usage_flags(&key_attr, psa_usage); + psa_set_key_algorithm(&key_attr, psa_alg); + if (psa_alg2 != PSA_ALG_NONE) { + psa_set_key_enrollment_algorithm(&key_attr, psa_alg2); + } + ret = mbedtls_pk_import_into_psa(pk, &key_attr, key_id); + if (ret != 0) { + return ret; + } + mbedtls_pk_free(pk); + mbedtls_pk_init(pk); + ret = mbedtls_pk_setup_opaque(pk, *key_id); + if (ret != 0) { + return ret; + } + + return 0; +} +#endif /* MBEDTLS_PK_C */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) diff --git a/programs/ssl/ssl_test_lib.h b/programs/ssl/ssl_test_lib.h index d06e0997d1..1da2dfb488 100644 --- a/programs/ssl/ssl_test_lib.h +++ b/programs/ssl/ssl_test_lib.h @@ -235,6 +235,31 @@ int key_opaque_set_alg_usage(const char *alg1, const char *alg2, psa_algorithm_t *psa_alg2, psa_key_usage_t *usage, mbedtls_pk_type_t key_type); + +#if defined(MBEDTLS_PK_C) +/** Turn a non-opaque PK context into an opaque one with folowing steps: + * - extract the key data and attributes from the PK context. + * - import the key material into PSA. + * - free the provided PK context and re-initilize it as an opaque PK context + * wrapping the PSA key imported in the above step. + * + * \param[in/out] pk On input the non-opaque PK context which contains the + * key to be wrapped. On output the re-initialized PK + * context which represents the opaque version of the one + * provided as input. + * \param[in] psa_alg The primary algorithm that will be associated to the + * PSA key. + * \param[in] psa_alg2 The enrollment algorithm that will be associated to the + * PSA key. + * \param[in] psa_usage The PSA key usage policy. + * \param[out] key_id The PSA key identifier of the imported key. + * + * \return \c 0 on sucess. + * \return \c -1 on failure. + */ +int pk_wrap_as_opaque(mbedtls_pk_context *pk, psa_algorithm_t psa_alg, psa_algorithm_t psa_alg2, + psa_key_usage_t psa_usage, mbedtls_svc_key_id_t *key_id); +#endif /* MBEDTLS_PK_C */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) diff --git a/tests/include/test/ssl_helpers.h b/tests/include/test/ssl_helpers.h index 9a078f645a..5b071f75aa 100644 --- a/tests/include/test/ssl_helpers.h +++ b/tests/include/test/ssl_helpers.h @@ -608,9 +608,7 @@ int mbedtls_test_get_tls13_ticket( mbedtls_test_handshake_test_options *client_options, mbedtls_test_handshake_test_options *server_options, mbedtls_ssl_session *session); -#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SRV_C && - MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS && - MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ +#endif #define ECJPAKE_TEST_PWD "bla" diff --git a/tests/opt-testcases/tls13-misc.sh b/tests/opt-testcases/tls13-misc.sh index 4e6bf876dd..ad062dccfb 100755 --- a/tests/opt-testcases/tls13-misc.sh +++ b/tests/opt-testcases/tls13-misc.sh @@ -263,7 +263,7 @@ requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ run_test "TLS 1.3 m->G: EarlyData: basic check, good" \ "$G_NEXT_SRV -d 10 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:+ECDHE-PSK:+PSK \ --earlydata --maxearlydata 16384 --disable-client-cert" \ - "$P_CLI debug_level=4 early_data=$EARLY_DATA_INPUT reco_mode=1 reconnect=1 reco_delay=900" \ + "$P_CLI debug_level=4 early_data=1 reco_mode=1 reconnect=1 reco_delay=900" \ 0 \ -c "received max_early_data_size: 16384" \ -c "Reconnecting with saved session" \ @@ -277,6 +277,31 @@ run_test "TLS 1.3 m->G: EarlyData: basic check, good" \ -s "END OF EARLY DATA (5) was received." \ -s "early data accepted" +requires_gnutls_tls1_3 +requires_config_enabled MBEDTLS_DEBUG_C +requires_config_enabled MBEDTLS_SSL_CLI_C +requires_all_configs_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \ + MBEDTLS_SSL_EARLY_DATA +requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED +run_test "TLS 1.3 m->G: EarlyData: write early data, good" \ + "$G_NEXT_SRV -d 10 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:+ECDHE-PSK:+PSK --earlydata --disable-client-cert" \ + "$P_CLI debug_level=4 early_data=1 reco_mode=1 reconnect=1 reco_delay=900" \ + 0 \ + -c "Reconnecting with saved session" \ + -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 exists." \ + -c "<= write early_data" \ + -c "<= write EndOfEarlyData" \ + -s "Parsing extension 'Early Data/42' (0 bytes)" \ + -s "Sending extension Early Data/42 (0 bytes)" \ + -s "END OF EARLY DATA (5) was received." \ + -s "early data accepted" \ + -s "decrypted early data with length" + requires_gnutls_tls1_3 requires_config_enabled MBEDTLS_DEBUG_C requires_config_enabled MBEDTLS_SSL_CLI_C @@ -287,7 +312,7 @@ requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED run_test "TLS 1.3 m->G: EarlyData: no early_data in NewSessionTicket, good" \ "$G_NEXT_SRV -d 10 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:+ECDHE-PSK:+PSK --disable-client-cert" \ - "$P_CLI debug_level=4 early_data=$EARLY_DATA_INPUT reco_mode=1 reconnect=1" \ + "$P_CLI debug_level=4 early_data=1 reco_mode=1 reconnect=1" \ 0 \ -c "Reconnecting with saved session" \ -C "NewSessionTicket: early_data(42) extension received." \ diff --git a/tests/src/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c index 7a28bd8795..5d4cb1cf0d 100644 --- a/tests/src/test_helpers/ssl_helpers.c +++ b/tests/src/test_helpers/ssl_helpers.c @@ -685,9 +685,20 @@ int mbedtls_test_ssl_endpoint_certificate_init(mbedtls_test_ssl_endpoint *ep, #if defined(MBEDTLS_USE_PSA_CRYPTO) if (opaque_alg != 0) { - TEST_EQUAL(mbedtls_pk_wrap_as_opaque(cert->pkey, &key_slot, - opaque_alg, opaque_usage, - opaque_alg2), 0); + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + /* Use a fake key usage to get a successful initial guess for the PSA attributes. */ + TEST_EQUAL(mbedtls_pk_get_psa_attributes(cert->pkey, PSA_KEY_USAGE_SIGN_HASH, + &key_attr), 0); + /* Then manually usage, alg and alg2 as requested by the test. */ + psa_set_key_usage_flags(&key_attr, opaque_usage); + psa_set_key_algorithm(&key_attr, opaque_alg); + if (opaque_alg2 != PSA_ALG_NONE) { + psa_set_key_enrollment_algorithm(&key_attr, opaque_alg2); + } + TEST_EQUAL(mbedtls_pk_import_into_psa(cert->pkey, &key_attr, &key_slot), 0); + mbedtls_pk_free(cert->pkey); + mbedtls_pk_init(cert->pkey); + TEST_EQUAL(mbedtls_pk_setup_opaque(cert->pkey, key_slot), 0); } #else (void) opaque_alg; diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function index 180cf76394..3d75ad0e1c 100644 --- a/tests/suites/test_suite_pk.function +++ b/tests/suites/test_suite_pk.function @@ -434,7 +434,7 @@ exit: */ mbedtls_svc_key_id_t pk_psa_genkey_ecc(void) { - mbedtls_svc_key_id_t key; + mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; const psa_key_type_t type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1); @@ -456,7 +456,7 @@ exit: */ mbedtls_svc_key_id_t pk_psa_genkey_rsa(void) { - mbedtls_svc_key_id_t key; + mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; const psa_key_type_t type = PSA_KEY_TYPE_RSA_KEY_PAIR; const size_t bits = 1024; @@ -482,7 +482,7 @@ exit: void pk_psa_utils(int key_is_rsa) { mbedtls_pk_context pk, pk2; - mbedtls_svc_key_id_t key; + mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; const char * const name = "Opaque"; @@ -836,6 +836,7 @@ void mbedtls_pk_check_pair(char *pub_file, char *prv_file, int ret) mbedtls_pk_context pub, prv, alt; #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t opaque_key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t opaque_key_attr = PSA_KEY_ATTRIBUTES_INIT; #endif /* MBEDTLS_USE_PSA_CRYPTO */ mbedtls_pk_init(&pub); @@ -873,9 +874,13 @@ void mbedtls_pk_check_pair(char *pub_file, char *prv_file, int ret) #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) if (mbedtls_pk_get_type(&prv) == MBEDTLS_PK_ECKEY) { - TEST_EQUAL(mbedtls_pk_wrap_as_opaque(&prv, &opaque_key_id, - PSA_ALG_ANY_HASH, - PSA_KEY_USAGE_EXPORT, 0), 0); + /* Turn the prv PK context into an opaque one.*/ + TEST_EQUAL(mbedtls_pk_get_psa_attributes(&prv, PSA_KEY_USAGE_SIGN_HASH, + &opaque_key_attr), 0); + TEST_EQUAL(mbedtls_pk_import_into_psa(&prv, &opaque_key_attr, &opaque_key_id), 0); + mbedtls_pk_free(&prv); + mbedtls_pk_init(&prv); + TEST_EQUAL(mbedtls_pk_setup_opaque(&prv, opaque_key_id), 0); TEST_EQUAL(mbedtls_pk_check_pair(&pub, &prv, mbedtls_test_rnd_std_rand, NULL), ret); } @@ -1395,7 +1400,8 @@ void pk_wrap_rsa_decrypt_test_vec(data_t *cipher, int mod, mbedtls_mpi N, P, Q, E; mbedtls_rsa_context *rsa; mbedtls_pk_context pk; - mbedtls_svc_key_id_t key_id; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; size_t olen; mbedtls_pk_init(&pk); @@ -1422,10 +1428,11 @@ void pk_wrap_rsa_decrypt_test_vec(data_t *cipher, int mod, TEST_EQUAL(mbedtls_rsa_complete(rsa), 0); /* Turn PK context into an opaque one. */ - TEST_EQUAL(mbedtls_pk_wrap_as_opaque(&pk, &key_id, - PSA_ALG_RSA_PKCS1V15_CRYPT, - PSA_KEY_USAGE_DECRYPT, - PSA_ALG_NONE), 0); + TEST_EQUAL(mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_DECRYPT, &key_attr), 0); + TEST_EQUAL(mbedtls_pk_import_into_psa(&pk, &key_attr, &key_id), 0); + mbedtls_pk_free(&pk); + mbedtls_pk_init(&pk); + TEST_EQUAL(mbedtls_pk_setup_opaque(&pk, key_id), 0); TEST_EQUAL(mbedtls_pk_get_bitlen(&pk), mod); @@ -1635,10 +1642,9 @@ void pk_psa_sign(int curve_or_keybits, int psa_type, int expected_bits) unsigned char pkey_legacy[200]; unsigned char pkey_psa[200]; unsigned char *pkey_legacy_start, *pkey_psa_start; - psa_algorithm_t alg_psa; size_t sig_len, klen_legacy, klen_psa; int ret; - mbedtls_svc_key_id_t key_id; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; /* @@ -1660,7 +1666,6 @@ void pk_psa_sign(int curve_or_keybits, int psa_type, int expected_bits) TEST_ASSERT(mbedtls_rsa_gen_key(mbedtls_pk_rsa(pk), mbedtls_test_rnd_std_rand, NULL, curve_or_keybits, 3) == 0); - alg_psa = PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256); } else #endif /* MBEDTLS_RSA_C && MBEDTLS_GENPRIME */ #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) @@ -1671,8 +1676,6 @@ void pk_psa_sign(int curve_or_keybits, int psa_type, int expected_bits) TEST_ASSERT(mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) == 0); TEST_ASSERT(pk_genkey(&pk, grpid) == 0); - - alg_psa = PSA_ALG_ECDSA(PSA_ALG_SHA_256); } else #endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ { @@ -1699,9 +1702,11 @@ void pk_psa_sign(int curve_or_keybits, int psa_type, int expected_bits) #endif /* MBEDTLS_PK_WRITE_C */ /* Turn PK context into an opaque one. */ - TEST_ASSERT(mbedtls_pk_wrap_as_opaque(&pk, &key_id, alg_psa, - PSA_KEY_USAGE_SIGN_HASH, - PSA_ALG_NONE) == 0); + TEST_EQUAL(mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_SIGN_HASH, &attributes), 0); + TEST_EQUAL(mbedtls_pk_import_into_psa(&pk, &attributes, &key_id), 0); + mbedtls_pk_free(&pk); + mbedtls_pk_init(&pk); + TEST_EQUAL(mbedtls_pk_setup_opaque(&pk, key_id), 0); PSA_ASSERT(psa_get_key_attributes(key_id, &attributes)); TEST_EQUAL(psa_get_key_type(&attributes), (psa_key_type_t) psa_type); @@ -1821,13 +1826,13 @@ void pk_psa_wrap_sign_ext(int pk_type, int key_bits, int key_pk_type, int md_alg { mbedtls_pk_context pk; size_t sig_len, pkey_len; - mbedtls_svc_key_id_t key_id; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE]; unsigned char pkey[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE]; unsigned char *pkey_start; unsigned char hash[PSA_HASH_MAX_SIZE]; psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); - psa_algorithm_t psa_alg; size_t hash_len = PSA_HASH_LENGTH(psa_md_alg); void const *options = NULL; mbedtls_pk_rsassa_pss_options rsassa_pss_options; @@ -1844,6 +1849,10 @@ void pk_psa_wrap_sign_ext(int pk_type, int key_bits, int key_pk_type, int md_alg mbedtls_test_rnd_std_rand, NULL, key_bits, 3), 0); + if (key_pk_type == MBEDTLS_PK_RSASSA_PSS) { + mbedtls_rsa_set_padding(mbedtls_pk_rsa(pk), MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_NONE); + } + /* Export underlying public key for re-importing in a legacy context. */ ret = mbedtls_pk_write_pubkey_der(&pk, pkey, sizeof(pkey)); TEST_ASSERT(ret >= 0); @@ -1852,18 +1861,12 @@ void pk_psa_wrap_sign_ext(int pk_type, int key_bits, int key_pk_type, int md_alg /* mbedtls_pk_write_pubkey_der() writes backwards in the data buffer. */ pkey_start = pkey + sizeof(pkey) - pkey_len; - if (key_pk_type == MBEDTLS_PK_RSA) { - psa_alg = PSA_ALG_RSA_PKCS1V15_SIGN(psa_md_alg); - } else if (key_pk_type == MBEDTLS_PK_RSASSA_PSS) { - psa_alg = PSA_ALG_RSA_PSS(psa_md_alg); - } else { - TEST_ASSUME(!"PK key type not supported in this configuration"); - } - /* Turn PK context into an opaque one. */ - TEST_EQUAL(mbedtls_pk_wrap_as_opaque(&pk, &key_id, psa_alg, - PSA_KEY_USAGE_SIGN_HASH, - PSA_ALG_NONE), 0); + TEST_EQUAL(mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_SIGN_HASH, &key_attr), 0); + TEST_EQUAL(mbedtls_pk_import_into_psa(&pk, &key_attr, &key_id), 0); + mbedtls_pk_free(&pk); + mbedtls_pk_init(&pk); + TEST_EQUAL(mbedtls_pk_setup_opaque(&pk, key_id), 0); memset(hash, 0x2a, sizeof(hash)); memset(sig, 0, sizeof(sig)); diff --git a/tests/suites/test_suite_pkwrite.function b/tests/suites/test_suite_pkwrite.function index c7600903f1..735c12547c 100644 --- a/tests/suites/test_suite_pkwrite.function +++ b/tests/suites/test_suite_pkwrite.function @@ -75,6 +75,7 @@ static void pk_write_check_common(char *key_file, int is_public_key, int is_der) size_t buf_len, check_buf_len; #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t opaque_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; #endif /* MBEDTLS_USE_PSA_CRYPTO */ USE_PSA_INIT(); @@ -117,10 +118,13 @@ static void pk_write_check_common(char *key_file, int is_public_key, int is_der) /* Verify that pk_write works also for opaque private keys */ if (!is_public_key) { memset(buf, 0, check_buf_len); - TEST_EQUAL(mbedtls_pk_wrap_as_opaque(&key, &opaque_id, - PSA_ALG_NONE, - PSA_KEY_USAGE_EXPORT, - PSA_ALG_NONE), 0); + /* Turn the key PK context into an opaque one. + * Note: set some practical usage for the key to make get_psa_attributes() happy. */ + TEST_EQUAL(mbedtls_pk_get_psa_attributes(&key, PSA_KEY_USAGE_SIGN_MESSAGE, &key_attr), 0); + TEST_EQUAL(mbedtls_pk_import_into_psa(&key, &key_attr, &opaque_id), 0); + mbedtls_pk_free(&key); + mbedtls_pk_init(&key); + TEST_EQUAL(mbedtls_pk_setup_opaque(&key, opaque_id), 0); start_buf = buf; buf_len = check_buf_len; TEST_EQUAL(pk_write_any_key(&key, &start_buf, &buf_len, is_public_key, @@ -172,6 +176,7 @@ void pk_write_public_from_private(char *priv_key_file, char *pub_key_file) size_t pub_key_len = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t opaque_key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; #endif /* MBEDTLS_USE_PSA_CRYPTO */ mbedtls_pk_init(&priv_key); @@ -194,9 +199,12 @@ void pk_write_public_from_private(char *priv_key_file, char *pub_key_file) #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_platform_zeroize(derived_key_raw, derived_key_len); - TEST_EQUAL(mbedtls_pk_wrap_as_opaque(&priv_key, &opaque_key_id, - PSA_ALG_NONE, PSA_KEY_USAGE_EXPORT, - PSA_ALG_NONE), 0); + /* Turn the priv_key PK context into an opaque one. */ + TEST_EQUAL(mbedtls_pk_get_psa_attributes(&priv_key, PSA_KEY_USAGE_SIGN_HASH, &key_attr), 0); + TEST_EQUAL(mbedtls_pk_import_into_psa(&priv_key, &key_attr, &opaque_key_id), 0); + mbedtls_pk_free(&priv_key); + mbedtls_pk_init(&priv_key); + TEST_EQUAL(mbedtls_pk_setup_opaque(&priv_key, opaque_key_id), 0); TEST_EQUAL(mbedtls_pk_write_pubkey_der(&priv_key, derived_key_raw, derived_key_len), pub_key_len); diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 69ccf26ee7..385682ae12 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3274,14 +3274,17 @@ elliptic_curve_get_properties TLS 1.3 resume session with ticket tls13_resume_session_with_ticket -TLS 1.3 early data, early data accepted -tls13_early_data:TEST_EARLY_DATA_ACCEPTED +TLS 1.3 read early data, early data accepted +tls13_read_early_data:TEST_EARLY_DATA_ACCEPTED -TLS 1.3 early data, server rejects early data -tls13_early_data:TEST_EARLY_DATA_SERVER_REJECTS +TLS 1.3 read early data, no early data indication +tls13_read_early_data:TEST_EARLY_DATA_NO_INDICATION_SENT -TLS 1.3 early data, discard after HRR -tls13_early_data:TEST_EARLY_DATA_HRR +TLS 1.3 read early data, server rejects early data +tls13_read_early_data:TEST_EARLY_DATA_SERVER_REJECTS + +TLS 1.3 read early data, discard after HRR +tls13_read_early_data:TEST_EARLY_DATA_HRR TLS 1.3 cli, early data status, early data accepted tls13_cli_early_data_status:TEST_EARLY_DATA_ACCEPTED @@ -3294,3 +3297,15 @@ tls13_cli_early_data_status:TEST_EARLY_DATA_SERVER_REJECTS TLS 1.3 cli, early data status, hello retry request tls13_cli_early_data_status:TEST_EARLY_DATA_HRR + +TLS 1.3 write early data, early data accepted +tls13_write_early_data:TEST_EARLY_DATA_ACCEPTED + +TLS 1.3 write early data, no early data indication +tls13_write_early_data:TEST_EARLY_DATA_NO_INDICATION_SENT + +TLS 1.3 write early data, server rejects early data +tls13_write_early_data:TEST_EARLY_DATA_SERVER_REJECTS + +TLS 1.3 write early data, hello retry request +tls13_write_early_data:TEST_EARLY_DATA_HRR diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 0e798f4bca..d327828bcd 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -18,49 +18,6 @@ #define TEST_EARLY_DATA_SERVER_REJECTS 2 #define TEST_EARLY_DATA_HRR 3 -#if (!defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \ - defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) && \ - defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_DEBUG_C) && \ - defined(MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE) && \ - defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) && \ - defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) && \ - defined(MBEDTLS_MD_CAN_SHA256) && \ - defined(MBEDTLS_ECP_HAVE_SECP256R1) && defined(MBEDTLS_ECP_HAVE_SECP384R1) && \ - defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) && defined(MBEDTLS_SSL_SESSION_TICKETS) -/* - * The implementation of the function should be based on - * mbedtls_ssl_write_early_data() eventually. The current version aims at - * removing the dependency on mbedtls_ssl_write_early_data() for the - * development and testing of reading early data. - */ -static int write_early_data(mbedtls_ssl_context *ssl, - unsigned char *buf, size_t len) -{ - int ret = mbedtls_ssl_get_max_out_record_payload(ssl); - - TEST_ASSERT(ret > 0); - TEST_ASSERT(len <= (size_t) ret); - - ret = mbedtls_ssl_flush_output(ssl); - TEST_EQUAL(ret, 0); - TEST_EQUAL(ssl->out_left, 0); - - ssl->out_msglen = len; - ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; - if (len > 0) { - memcpy(ssl->out_msg, buf, len); - } - - ret = mbedtls_ssl_write_record(ssl, 1); - TEST_EQUAL(ret, 0); - - ret = len; - -exit: - return ret; -} -#endif - /* END_HEADER */ /* BEGIN_DEPENDENCIES @@ -3624,12 +3581,12 @@ exit: /* END_CASE */ /* - * The !MBEDTLS_SSL_PROTO_TLS1_2 dependency of tls13_early_data() below is + * The !MBEDTLS_SSL_PROTO_TLS1_2 dependency of tls13_read_early_data() below is * a temporary workaround to not run the test in Windows-2013 where there is * an issue with mbedtls_vsnprintf(). */ /* BEGIN_CASE depends_on:!MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_EARLY_DATA:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_DEBUG_C:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED:MBEDTLS_MD_CAN_SHA256:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_SSL_SESSION_TICKETS */ -void tls13_early_data(int scenario) +void tls13_read_early_data(int scenario) { int ret = -1; unsigned char buf[64]; @@ -3676,6 +3633,10 @@ void tls13_early_data(int scenario) case TEST_EARLY_DATA_ACCEPTED: break; + case TEST_EARLY_DATA_NO_INDICATION_SENT: + client_options.early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED; + break; + case TEST_EARLY_DATA_SERVER_REJECTS: mbedtls_debug_set_threshold(3); server_pattern.pattern = @@ -3723,12 +3684,16 @@ void tls13_early_data(int scenario) &(client_ep.ssl), &(server_ep.ssl), MBEDTLS_SSL_SERVER_HELLO), 0); - TEST_ASSERT(client_ep.ssl.early_data_status != - MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT); + ret = mbedtls_ssl_write_early_data(&(client_ep.ssl), + (unsigned char *) early_data, + early_data_len); - ret = write_early_data(&(client_ep.ssl), (unsigned char *) early_data, - early_data_len); - TEST_EQUAL(ret, early_data_len); + if (client_ep.ssl.early_data_status != + MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT) { + TEST_EQUAL(ret, early_data_len); + } else { + TEST_EQUAL(ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + } ret = mbedtls_test_move_handshake_to_state( &(server_ep.ssl), &(client_ep.ssl), @@ -3743,12 +3708,20 @@ void tls13_early_data(int scenario) TEST_MEMORY_COMPARE(buf, early_data_len, early_data, early_data_len); break; + case TEST_EARLY_DATA_NO_INDICATION_SENT: + TEST_EQUAL(ret, 0); + TEST_EQUAL(server_ep.ssl.handshake->early_data_accepted, 0); + break; + case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */ case TEST_EARLY_DATA_HRR: TEST_EQUAL(ret, 0); TEST_EQUAL(server_ep.ssl.handshake->early_data_accepted, 0); TEST_EQUAL(server_pattern.counter, 1); break; + + default: + TEST_FAIL("Unknown scenario."); } TEST_EQUAL(mbedtls_test_move_handshake_to_state( @@ -3869,6 +3842,11 @@ void tls13_cli_early_data_status(int scenario) (ret == MBEDTLS_ERR_SSL_WANT_WRITE)); } + if (client_ep.ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER) { + TEST_EQUAL(mbedtls_ssl_get_early_data_status(&(client_ep.ssl)), + MBEDTLS_ERR_SSL_BAD_INPUT_DATA); + } + switch (client_ep.ssl.state) { case MBEDTLS_SSL_CLIENT_HELLO: switch (scenario) { @@ -3880,7 +3858,7 @@ void tls13_cli_early_data_status(int scenario) break; case TEST_EARLY_DATA_HRR: - if (client_ep.ssl.handshake->hello_retry_request_count == 0) { + if (!client_ep.ssl.handshake->hello_retry_request_flag) { TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN); } else { @@ -3888,6 +3866,9 @@ void tls13_cli_early_data_status(int scenario) MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); } break; + + default: + TEST_FAIL("Unknown scenario."); } break; @@ -3905,7 +3886,7 @@ void tls13_cli_early_data_status(int scenario) break; case TEST_EARLY_DATA_HRR: - if (client_ep.ssl.handshake->hello_retry_request_count == 0) { + if (!client_ep.ssl.handshake->hello_retry_request_flag) { TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE); } else { @@ -3913,6 +3894,9 @@ void tls13_cli_early_data_status(int scenario) MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); } break; + + default: + TEST_FAIL("Unknown scenario."); } break; @@ -3933,6 +3917,9 @@ void tls13_cli_early_data_status(int scenario) TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); break; + + default: + TEST_FAIL("Unknown scenario."); } break; @@ -3953,6 +3940,9 @@ void tls13_cli_early_data_status(int scenario) TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); break; + + default: + TEST_FAIL("Unknown scenario."); } break; @@ -3979,6 +3969,9 @@ void tls13_cli_early_data_status(int scenario) TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); break; + + default: + TEST_FAIL("Unknown scenario."); } break; @@ -3999,12 +3992,14 @@ void tls13_cli_early_data_status(int scenario) TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); break; + + default: + TEST_FAIL("Unknown scenario."); } break; #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO: - TEST_ASSERT(scenario != TEST_EARLY_DATA_NO_INDICATION_SENT); switch (scenario) { case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */ case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */ @@ -4012,6 +4007,9 @@ void tls13_cli_early_data_status(int scenario) TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_SENT); break; + + default: + TEST_FAIL("Unexpected or unknown scenario."); } break; @@ -4022,7 +4020,6 @@ void tls13_cli_early_data_status(int scenario) break; case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: - TEST_ASSERT(scenario != TEST_EARLY_DATA_ACCEPTED); switch (scenario) { case TEST_EARLY_DATA_NO_INDICATION_SENT: TEST_EQUAL(client_ep.ssl.early_data_status, @@ -4034,6 +4031,9 @@ void tls13_cli_early_data_status(int scenario) TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); break; + + default: + TEST_FAIL("Unexpected or unknown scenario."); } break; #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ @@ -4057,6 +4057,9 @@ void tls13_cli_early_data_status(int scenario) TEST_EQUAL(client_ep.ssl.early_data_status, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); break; + + default: + TEST_FAIL("Unknown scenario."); } break; @@ -4065,8 +4068,30 @@ void tls13_cli_early_data_status(int scenario) } } while (client_ep.ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER); + ret = mbedtls_ssl_get_early_data_status(&(client_ep.ssl)); + switch (scenario) { + case TEST_EARLY_DATA_ACCEPTED: + TEST_EQUAL(ret, MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED); + break; + + case TEST_EARLY_DATA_NO_INDICATION_SENT: + TEST_EQUAL(ret, MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT); + break; + + case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */ + case TEST_EARLY_DATA_HRR: + TEST_EQUAL(ret, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED); + break; + + default: + TEST_FAIL("Unknown scenario."); + } + + ret = mbedtls_ssl_get_early_data_status(&(server_ep.ssl)); + TEST_EQUAL(ret, MBEDTLS_ERR_SSL_BAD_INPUT_DATA); + #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) - TEST_EQUAL(client_ep.ssl.handshake->ccs_count, 1); + TEST_EQUAL(client_ep.ssl.handshake->ccs_sent, 1); #endif exit: @@ -4078,3 +4103,348 @@ exit: PSA_DONE(); } /* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_SSL_EARLY_DATA:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED:MBEDTLS_MD_CAN_SHA256:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_SSL_SESSION_TICKETS */ +void tls13_write_early_data(int scenario) +{ + int ret = -1; + mbedtls_test_ssl_endpoint client_ep, server_ep; + mbedtls_test_handshake_test_options client_options; + mbedtls_test_handshake_test_options server_options; + mbedtls_ssl_session saved_session; + uint16_t group_list[3] = { + MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, + MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, + MBEDTLS_SSL_IANA_TLS_GROUP_NONE + }; + int beyond_first_hello = 0; + + mbedtls_platform_zeroize(&client_ep, sizeof(client_ep)); + mbedtls_platform_zeroize(&server_ep, sizeof(server_ep)); + mbedtls_test_init_handshake_options(&client_options); + mbedtls_test_init_handshake_options(&server_options); + mbedtls_ssl_session_init(&saved_session); + + PSA_INIT(); + + /* + * Run first handshake to get a ticket from the server. + */ + client_options.pk_alg = MBEDTLS_PK_ECDSA; + client_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED; + server_options.pk_alg = MBEDTLS_PK_ECDSA; + server_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED; + if (scenario == TEST_EARLY_DATA_HRR) { + client_options.group_list = group_list; + server_options.group_list = group_list; + } + + ret = mbedtls_test_get_tls13_ticket(&client_options, &server_options, + &saved_session); + TEST_EQUAL(ret, 0); + + /* + * Prepare for handshake with the ticket. + */ + switch (scenario) { + case TEST_EARLY_DATA_ACCEPTED: + break; + + case TEST_EARLY_DATA_NO_INDICATION_SENT: + client_options.early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED; + break; + + case TEST_EARLY_DATA_SERVER_REJECTS: + server_options.early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED; + break; + + case TEST_EARLY_DATA_HRR: + server_options.group_list = group_list + 1; + break; + + default: + TEST_FAIL("Unknown scenario."); + } + + ret = mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT, + &client_options, NULL, NULL, NULL); + TEST_EQUAL(ret, 0); + + ret = mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, + &server_options, NULL, NULL, NULL); + TEST_EQUAL(ret, 0); + + mbedtls_ssl_conf_session_tickets_cb(&server_ep.conf, + mbedtls_test_ticket_write, + mbedtls_test_ticket_parse, + NULL); + + ret = mbedtls_test_mock_socket_connect(&(client_ep.socket), + &(server_ep.socket), 1024); + TEST_EQUAL(ret, 0); + + ret = mbedtls_ssl_set_session(&(client_ep.ssl), &saved_session); + TEST_EQUAL(ret, 0); + + /* + * Run handshakes going one state further in the handshake sequence at each + * loop up to the point where we reach the MBEDTLS_SSL_HANDSHAKE_OVER + * state. For each reached handshake state, check the result of the call + * to mbedtls_ssl_write_early_data(), make sure we can complete the + * handshake successfully and then reset the connection to restart the + * handshake from scratch. + */ + do { + int client_state = client_ep.ssl.state; + int previous_client_state; + const char *early_data_string = "This is early data."; + const unsigned char *early_data = (const unsigned char *) early_data_string; + size_t early_data_len = strlen(early_data_string); + int write_early_data_ret, read_early_data_ret; + unsigned char read_buf[64]; + + write_early_data_ret = mbedtls_ssl_write_early_data(&(client_ep.ssl), + early_data, + early_data_len); + + if (scenario == TEST_EARLY_DATA_NO_INDICATION_SENT) { + TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, client_state); + goto complete_handshake; + } + + switch (client_state) { + case MBEDTLS_SSL_HELLO_REQUEST: /* Intentional fallthrough */ + case MBEDTLS_SSL_CLIENT_HELLO: + switch (scenario) { + case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */ + case TEST_EARLY_DATA_SERVER_REJECTS: + TEST_EQUAL(write_early_data_ret, early_data_len); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); + break; + + case TEST_EARLY_DATA_HRR: + if (!client_ep.ssl.handshake->hello_retry_request_flag) { + TEST_EQUAL(write_early_data_ret, early_data_len); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); + } else { + beyond_first_hello = 1; + TEST_EQUAL(write_early_data_ret, + MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_CLIENT_HELLO); + } + break; + + default: + TEST_FAIL("Unknown scenario."); + } + break; + + case MBEDTLS_SSL_SERVER_HELLO: + switch (scenario) { + case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */ + case TEST_EARLY_DATA_SERVER_REJECTS: + TEST_EQUAL(write_early_data_ret, early_data_len); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); + break; + + case TEST_EARLY_DATA_HRR: + if (!client_ep.ssl.handshake->hello_retry_request_flag) { + TEST_EQUAL(write_early_data_ret, early_data_len); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); + } else { + TEST_EQUAL(write_early_data_ret, + MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); + } + break; + + default: + TEST_FAIL("Unknown scenario."); + } + break; + + case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: + switch (scenario) { + case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */ + case TEST_EARLY_DATA_SERVER_REJECTS: + TEST_EQUAL(write_early_data_ret, early_data_len); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); + break; + + case TEST_EARLY_DATA_HRR: + TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); + break; + + default: + TEST_FAIL("Unknown scenario."); + } + break; + + case MBEDTLS_SSL_SERVER_FINISHED: + switch (scenario) { + case TEST_EARLY_DATA_ACCEPTED: + TEST_EQUAL(write_early_data_ret, early_data_len); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_FINISHED); + break; + + case TEST_EARLY_DATA_SERVER_REJECTS: + TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_FINISHED); + break; + + case TEST_EARLY_DATA_HRR: + TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_FINISHED); + break; + + default: + TEST_FAIL("Unknown scenario."); + } + break; + + case MBEDTLS_SSL_END_OF_EARLY_DATA: + TEST_EQUAL(scenario, TEST_EARLY_DATA_ACCEPTED); + TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_END_OF_EARLY_DATA); + break; + +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO: + switch (scenario) { + case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */ + case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */ + case TEST_EARLY_DATA_HRR: + TEST_EQUAL(write_early_data_ret, early_data_len); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_SERVER_HELLO); + break; + default: + TEST_FAIL("Unknown scenario."); + } + break; + + case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO: + TEST_EQUAL(scenario, TEST_EARLY_DATA_HRR); + TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO); + break; + + case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: + switch (scenario) { + case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */ + case TEST_EARLY_DATA_HRR: + TEST_EQUAL(write_early_data_ret, + MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, + MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED); + break; + default: + TEST_FAIL("Unexpected or unknown scenario."); + } + break; +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + + case MBEDTLS_SSL_CLIENT_CERTIFICATE: /* Intentional fallthrough */ + case MBEDTLS_SSL_CLIENT_FINISHED: /* Intentional fallthrough */ + case MBEDTLS_SSL_FLUSH_BUFFERS: /* Intentional fallthrough */ + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: /* Intentional fallthrough */ + case MBEDTLS_SSL_HANDSHAKE_OVER: + switch (scenario) { + case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */ + case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */ + case TEST_EARLY_DATA_HRR: + TEST_EQUAL(write_early_data_ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA); + TEST_EQUAL(client_ep.ssl.state, client_state); + break; + default: + TEST_FAIL("Unknown scenario."); + } + break; + + default: + TEST_FAIL("Unexpected state."); + } + +complete_handshake: + do { + ret = mbedtls_test_move_handshake_to_state( + &(server_ep.ssl), &(client_ep.ssl), + MBEDTLS_SSL_HANDSHAKE_OVER); + + if (ret == MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA) { + read_early_data_ret = mbedtls_ssl_read_early_data( + &(server_ep.ssl), read_buf, sizeof(read_buf)); + + TEST_EQUAL(read_early_data_ret, early_data_len); + } + } while (ret == MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA); + + TEST_EQUAL(ret, 0); + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + MBEDTLS_SSL_HANDSHAKE_OVER), 0); + + mbedtls_test_mock_socket_close(&(client_ep.socket)); + mbedtls_test_mock_socket_close(&(server_ep.socket)); + + ret = mbedtls_ssl_session_reset(&(client_ep.ssl)); + TEST_EQUAL(ret, 0); + + ret = mbedtls_ssl_set_session(&(client_ep.ssl), &saved_session); + TEST_EQUAL(ret, 0); + + ret = mbedtls_ssl_session_reset(&(server_ep.ssl)); + TEST_EQUAL(ret, 0); + + ret = mbedtls_test_mock_socket_connect(&(client_ep.socket), + &(server_ep.socket), 1024); + TEST_EQUAL(ret, 0); + + previous_client_state = client_state; + if (previous_client_state == MBEDTLS_SSL_HANDSHAKE_OVER) { + break; + } + + /* In case of HRR scenario, once we have been through it, move over + * the first ClientHello and ServerHello otherwise we just keep playing + * this first part of the handshake with HRR. + */ + if ((scenario == TEST_EARLY_DATA_HRR) && (beyond_first_hello)) { + TEST_ASSERT(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + MBEDTLS_SSL_SERVER_HELLO) == 0); + TEST_ASSERT(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + MBEDTLS_SSL_CLIENT_HELLO) == 0); + } + + TEST_EQUAL(mbedtls_test_move_handshake_to_state( + &(client_ep.ssl), &(server_ep.ssl), + previous_client_state), 0); + + /* Progress the handshake from at least one state */ + while (client_ep.ssl.state == previous_client_state) { + ret = mbedtls_ssl_handshake_step(&(client_ep.ssl)); + TEST_ASSERT((ret == 0) || + (ret == MBEDTLS_ERR_SSL_WANT_READ) || + (ret == MBEDTLS_ERR_SSL_WANT_WRITE)); + if (client_ep.ssl.state != previous_client_state) { + break; + } + ret = mbedtls_ssl_handshake_step(&(server_ep.ssl)); + TEST_ASSERT((ret == 0) || + (ret == MBEDTLS_ERR_SSL_WANT_READ) || + (ret == MBEDTLS_ERR_SSL_WANT_WRITE)); + } + } while (1); + +exit: + mbedtls_test_ssl_endpoint_free(&client_ep, NULL); + mbedtls_test_ssl_endpoint_free(&server_ep, NULL); + mbedtls_test_free_handshake_options(&client_options); + mbedtls_test_free_handshake_options(&server_options); + mbedtls_ssl_session_free(&saved_session); + PSA_DONE(); +} +/* END_CASE */ diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index 3d84c729fe..1db7e1cff2 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -284,7 +284,7 @@ void x509_csr_check_opaque(char *key_file, int md_type, int key_usage, { mbedtls_pk_context key; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; - psa_algorithm_t md_alg_psa, alg_psa; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; mbedtls_x509write_csr req; unsigned char buf[4096]; int ret; @@ -297,24 +297,16 @@ void x509_csr_check_opaque(char *key_file, int md_type, int key_usage, memset(&rnd_info, 0x2a, sizeof(mbedtls_test_rnd_pseudo_info)); - md_alg_psa = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) md_type); - TEST_ASSERT(md_alg_psa != MBEDTLS_MD_NONE); - mbedtls_pk_init(&key); TEST_ASSERT(mbedtls_pk_parse_keyfile(&key, key_file, NULL, mbedtls_test_rnd_std_rand, NULL) == 0); - if (mbedtls_pk_get_type(&key) == MBEDTLS_PK_ECKEY) { - alg_psa = PSA_ALG_ECDSA(md_alg_psa); - } else if (mbedtls_pk_get_type(&key) == MBEDTLS_PK_RSA) { - alg_psa = PSA_ALG_RSA_PKCS1V15_SIGN(md_alg_psa); - } else { - TEST_ASSUME(!"PK key type not supported in this configuration"); - } - - TEST_ASSERT(mbedtls_pk_wrap_as_opaque(&key, &key_id, alg_psa, - PSA_KEY_USAGE_SIGN_HASH, - PSA_ALG_NONE) == 0); + /* Turn the PK context into an opaque one. */ + TEST_EQUAL(mbedtls_pk_get_psa_attributes(&key, PSA_KEY_USAGE_SIGN_HASH, &key_attr), 0); + TEST_EQUAL(mbedtls_pk_import_into_psa(&key, &key_attr, &key_id), 0); + mbedtls_pk_free(&key); + mbedtls_pk_init(&key); + TEST_EQUAL(mbedtls_pk_setup_opaque(&key, key_id), 0); mbedtls_x509write_csr_set_md_alg(&req, md_type); mbedtls_x509write_csr_set_key(&req, &key); @@ -373,6 +365,7 @@ void x509_crt_check(char *subject_key_file, char *subject_pwd, mbedtls_test_rnd_pseudo_info rnd_info; #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; #endif mbedtls_pk_type_t issuer_key_type; mbedtls_x509_san_list san_ip; @@ -451,24 +444,14 @@ void x509_crt_check(char *subject_key_file, char *subject_pwd, #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) - /* For Opaque PK contexts, wrap key as an Opaque RSA context. */ + /* Turn the issuer PK context into an opaque one. */ if (pk_wrap == 2) { - psa_algorithm_t alg_psa, md_alg_psa; - - md_alg_psa = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) md_type); - TEST_ASSERT(md_alg_psa != MBEDTLS_MD_NONE); - - if (mbedtls_pk_get_type(&issuer_key) == MBEDTLS_PK_ECKEY) { - alg_psa = PSA_ALG_ECDSA(md_alg_psa); - } else if (mbedtls_pk_get_type(&issuer_key) == MBEDTLS_PK_RSA) { - alg_psa = PSA_ALG_RSA_PKCS1V15_SIGN(md_alg_psa); - } else { - TEST_ASSUME(!"PK key type not supported in this configuration"); - } - - TEST_ASSERT(mbedtls_pk_wrap_as_opaque(&issuer_key, &key_id, alg_psa, - PSA_KEY_USAGE_SIGN_HASH, - PSA_ALG_NONE) == 0); + TEST_EQUAL(mbedtls_pk_get_psa_attributes(&issuer_key, PSA_KEY_USAGE_SIGN_HASH, + &key_attr), 0); + TEST_EQUAL(mbedtls_pk_import_into_psa(&issuer_key, &key_attr, &key_id), 0); + mbedtls_pk_free(&issuer_key); + mbedtls_pk_init(&issuer_key); + TEST_EQUAL(mbedtls_pk_setup_opaque(&issuer_key, key_id), 0); } #endif /* MBEDTLS_USE_PSA_CRYPTO */