Merge pull request #8864 from valeriosetti/issue8848
Deprecate or remove mbedtls_pk_wrap_as_opaque
diff --git a/ChangeLog.d/domain_parameters.txt b/ChangeLog.d/domain_parameters.txt
new file mode 100644
index 0000000..d860cc4
--- /dev/null
+++ b/ChangeLog.d/domain_parameters.txt
@@ -0,0 +1,9 @@
+New deprecations
+ * In the PSA API, domain parameters are no longer used for anything.
+ They are deprecated and will be removed in a future version of the
+ library.
+
+Removals
+ * In the PSA API, the experimental way to encode the public exponent of
+ an RSA key as a domain parameter is no longer supported. Use
+ psa_generate_key_ext() instead.
diff --git a/ChangeLog.d/psa_generate_key_ext.txt b/ChangeLog.d/psa_generate_key_ext.txt
new file mode 100644
index 0000000..8340f01
--- /dev/null
+++ b/ChangeLog.d/psa_generate_key_ext.txt
@@ -0,0 +1,3 @@
+Features
+ * The new function psa_generate_key_ext() allows generating an RSA
+ key pair with a custom public exponent.
diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h
index 76aef32..0201963 100644
--- a/include/mbedtls/ecp.h
+++ b/include/mbedtls/ecp.h
@@ -1330,17 +1330,41 @@
/**
* \brief This function exports an elliptic curve private key.
*
+ * \note Note that although this function accepts an output
+ * buffer that is smaller or larger than the key, most key
+ * import interfaces require the output to have exactly
+ * key's nominal length. It is generally simplest to
+ * pass the key's nominal length as \c buflen, after
+ * checking that the output buffer is large enough.
+ * See the description of the \p buflen parameter for
+ * how to calculate the nominal length.
+ *
+ * \note If the private key was not set in \p key,
+ * the output is unspecified. Future versions
+ * may return an error in that case.
+ *
* \param key The private key.
* \param buf The output buffer for containing the binary representation
- * of the key. (Big endian integer for Weierstrass curves, byte
- * string for Montgomery curves.)
+ * of the key.
+ * For Weierstrass curves, this is the big-endian
+ * representation, padded with null bytes at the beginning
+ * to reach \p buflen bytes.
+ * For Montgomery curves, this is the standard byte string
+ * representation (which is little-endian), padded with
+ * null bytes at the end to reach \p buflen bytes.
* \param buflen The total length of the buffer in bytes.
+ * The length of the output is
+ * (`grp->nbits` + 7) / 8 bytes
+ * where `grp->nbits` is the private key size in bits.
+ * For Weierstrass keys, if the output buffer is smaller,
+ * leading zeros are trimmed to fit if possible. For
+ * Montgomery keys, the output buffer must always be large
+ * enough for the nominal length.
*
* \return \c 0 on success.
- * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the \p key
- representation is larger than the available space in \p buf.
- * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for
- * the group is not implemented.
+ * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL or
+ * #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the \p key
+ * representation is larger than the available space in \p buf.
* \return Another negative error code on different kinds of failure.
*/
int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key,
@@ -1349,6 +1373,10 @@
/**
* \brief This function exports an elliptic curve public key.
*
+ * \note If the public key was not set in \p key,
+ * the output is unspecified. Future versions
+ * may return an error in that case.
+ *
* \param key The public key.
* \param format The point format. This must be either
* #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED.
@@ -1431,6 +1459,10 @@
* Each of the output parameters can be a null pointer
* if you do not need that parameter.
*
+ * \note If the private key or the public key was not set in \p key,
+ * the corresponding output is unspecified. Future versions
+ * may return an error in that case.
+ *
* \param key The key pair to export from.
* \param grp Slot for exported ECP group.
* It must either be null or point to an initialized ECP group.
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 08c628a..78395d2 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -734,6 +734,51 @@
}
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 @@
#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 @@
#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 @@
* \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 @@
* 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/include/mbedtls/x509.h b/include/mbedtls/x509.h
index be63612..453f598 100644
--- a/include/mbedtls/x509.h
+++ b/include/mbedtls/x509.h
@@ -322,9 +322,151 @@
*/
int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn);
+/**
+ * \brief Convert the certificate DN string \p name into
+ * a linked list of mbedtls_x509_name (equivalent to
+ * mbedtls_asn1_named_data).
+ *
+ * \note This function allocates a linked list, and places the head
+ * pointer in \p head. This list must later be freed by a
+ * call to mbedtls_asn1_free_named_data_list().
+ *
+ * \param[out] head Address in which to store the pointer to the head of the
+ * allocated list of mbedtls_x509_name
+ * \param[in] name The string representation of a DN to convert
+ *
+ * \return 0 on success, or a negative error code.
+ */
int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name);
/**
+ * \brief Return the next relative DN in an X509 name.
+ *
+ * \note Intended use is to compare function result to dn->next
+ * in order to detect boundaries of multi-valued RDNs.
+ *
+ * \param dn Current node in the X509 name
+ *
+ * \return Pointer to the first attribute-value pair of the
+ * next RDN in sequence, or NULL if end is reached.
+ */
+static inline mbedtls_x509_name *mbedtls_x509_dn_get_next(
+ mbedtls_x509_name *dn)
+{
+ while (dn->MBEDTLS_PRIVATE(next_merged) && dn->next != NULL) {
+ dn = dn->next;
+ }
+ return dn->next;
+}
+
+/**
+ * \brief Store the certificate serial in printable form into buf;
+ * no more than size characters will be written.
+ *
+ * \param buf Buffer to write to
+ * \param size Maximum size of buffer
+ * \param serial The X509 serial to represent
+ *
+ * \return The length of the string written (not including the
+ * terminated nul byte), or a negative error code.
+ */
+int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial);
+
+/**
+ * \brief Compare pair of mbedtls_x509_time.
+ *
+ * \param t1 mbedtls_x509_time to compare
+ * \param t2 mbedtls_x509_time to compare
+ *
+ * \return < 0 if t1 is before t2
+ * 0 if t1 equals t2
+ * > 0 if t1 is after t2
+ */
+int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1, const mbedtls_x509_time *t2);
+
+#if defined(MBEDTLS_HAVE_TIME_DATE)
+/**
+ * \brief Fill mbedtls_x509_time with provided mbedtls_time_t.
+ *
+ * \param tt mbedtls_time_t to convert
+ * \param now mbedtls_x509_time to fill with converted mbedtls_time_t
+ *
+ * \return \c 0 on success
+ * \return A non-zero return value on failure.
+ */
+int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now);
+#endif /* MBEDTLS_HAVE_TIME_DATE */
+
+/**
+ * \brief Check a given mbedtls_x509_time against the system time
+ * and tell if it's in the past.
+ *
+ * \note Intended usage is "if( is_past( valid_to ) ) ERROR".
+ * Hence the return value of 1 if on internal errors.
+ *
+ * \param to mbedtls_x509_time to check
+ *
+ * \return 1 if the given time is in the past or an error occurred,
+ * 0 otherwise.
+ */
+int mbedtls_x509_time_is_past(const mbedtls_x509_time *to);
+
+/**
+ * \brief Check a given mbedtls_x509_time against the system time
+ * and tell if it's in the future.
+ *
+ * \note Intended usage is "if( is_future( valid_from ) ) ERROR".
+ * Hence the return value of 1 if on internal errors.
+ *
+ * \param from mbedtls_x509_time to check
+ *
+ * \return 1 if the given time is in the future or an error occurred,
+ * 0 otherwise.
+ */
+int mbedtls_x509_time_is_future(const mbedtls_x509_time *from);
+
+/**
+ * \brief This function parses an item in the SubjectAlternativeNames
+ * extension. Please note that this function might allocate
+ * additional memory for a subject alternative name, thus
+ * mbedtls_x509_free_subject_alt_name has to be called
+ * to dispose of this additional memory afterwards.
+ *
+ * \param san_buf The buffer holding the raw data item of the subject
+ * alternative name.
+ * \param san The target structure to populate with the parsed presentation
+ * of the subject alternative name encoded in \p san_buf.
+ *
+ * \note Supported GeneralName types, as defined in RFC 5280:
+ * "rfc822Name", "dnsName", "directoryName",
+ * "uniformResourceIdentifier" and "hardware_module_name"
+ * of type "otherName", as defined in RFC 4108.
+ *
+ * \note This function should be called on a single raw data of
+ * subject alternative name. For example, after successful
+ * certificate parsing, one must iterate on every item in the
+ * \c crt->subject_alt_names sequence, and pass it to
+ * this function.
+ *
+ * \warning The target structure contains pointers to the raw data of the
+ * parsed certificate, and its lifetime is restricted by the
+ * lifetime of the certificate.
+ *
+ * \return \c 0 on success
+ * \return #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported
+ * SAN type.
+ * \return Another negative value for any other failure.
+ */
+int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
+ mbedtls_x509_subject_alternative_name *san);
+/**
+ * \brief Unallocate all data related to subject alternative name
+ *
+ * \param san SAN structure - extra memory owned by this structure will be freed
+ */
+void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san);
+
+/**
* \brief This function parses a CN string as an IP address.
*
* \param cn The CN string to parse. CN string MUST be null-terminated.
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index fe10ee0..73889e0 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -119,8 +119,9 @@
* value in the structure.
* The persistent key will be written to storage when the attribute
* structure is passed to a key creation function such as
- * psa_import_key(), psa_generate_key(),
- * psa_key_derivation_output_key() or psa_copy_key().
+ * psa_import_key(), psa_generate_key(), psa_generate_key_ext(),
+ * psa_key_derivation_output_key(), psa_key_derivation_output_key_ext()
+ * or psa_copy_key().
*
* This function may be declared as `static` (i.e. without external
* linkage). This function may be provided as a function-like macro,
@@ -163,8 +164,9 @@
* value in the structure.
* The persistent key will be written to storage when the attribute
* structure is passed to a key creation function such as
- * psa_import_key(), psa_generate_key(),
- * psa_key_derivation_output_key() or psa_copy_key().
+ * psa_import_key(), psa_generate_key(), psa_generate_key_ext(),
+ * psa_key_derivation_output_key(), psa_key_derivation_output_key_ext()
+ * or psa_copy_key().
*
* This function may be declared as `static` (i.e. without external
* linkage). This function may be provided as a function-like macro,
@@ -3226,7 +3228,8 @@
* psa_key_derivation_set_capacity(). You may do this before, in the middle
* of or after providing inputs. For some algorithms, this step is mandatory
* because the output depends on the maximum capacity.
- * -# To derive a key, call psa_key_derivation_output_key().
+ * -# To derive a key, call psa_key_derivation_output_key() or
+ * psa_key_derivation_output_key_ext().
* To derive a byte string for a different purpose, call
* psa_key_derivation_output_bytes().
* Successive calls to these functions use successive output bytes
@@ -3449,7 +3452,8 @@
* \note Once all inputs steps are completed, the operations will allow:
* - psa_key_derivation_output_bytes() if each input was either a direct input
* or a key with #PSA_KEY_USAGE_DERIVE set;
- * - psa_key_derivation_output_key() if the input for step
+ * - psa_key_derivation_output_key() or psa_key_derivation_output_key_ext()
+ * if the input for step
* #PSA_KEY_DERIVATION_INPUT_SECRET or #PSA_KEY_DERIVATION_INPUT_PASSWORD
* was from a key slot with #PSA_KEY_USAGE_DERIVE and each other input was
* either a direct input or a key with #PSA_KEY_USAGE_DERIVE set;
@@ -3697,6 +3701,11 @@
* Future versions of this specification may include additional restrictions
* on the derived key based on the attributes and strength of the secret key.
*
+ * \note This function is equivalent to calling
+ * psa_key_derivation_output_key_ext()
+ * with the production parameters #PSA_KEY_PRODUCTION_PARAMETERS_INIT
+ * and `params_data_length == 0` (i.e. `params->data` is empty).
+ *
* \param[in] attributes The attributes for the new key.
* If the key type to be created is
* #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in
@@ -3750,6 +3759,83 @@
psa_key_derivation_operation_t *operation,
mbedtls_svc_key_id_t *key);
+/** Derive a key from an ongoing key derivation operation with custom
+ * production parameters.
+ *
+ * See the description of psa_key_derivation_out_key() for the operation of
+ * this function with the default production parameters.
+ * Mbed TLS currently does not currently support any non-default production
+ * parameters.
+ *
+ * \note This function is experimental and may change in future minor
+ * versions of Mbed TLS.
+ *
+ * \param[in] attributes The attributes for the new key.
+ * If the key type to be created is
+ * #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in
+ * the policy must be the same as in the current
+ * operation.
+ * \param[in,out] operation The key derivation operation object to read from.
+ * \param[in] params Customization parameters for the key derivation.
+ * When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT
+ * with \p params_data_length = 0,
+ * this function is equivalent to
+ * psa_key_derivation_output_key().
+ * Mbed TLS currently only supports the default
+ * production parameters, i.e.
+ * #PSA_KEY_PRODUCTION_PARAMETERS_INIT,
+ * for all key types.
+ * \param params_data_length
+ * Length of `params->data` in bytes.
+ * \param[out] key On success, an identifier for the newly created
+ * key. For persistent keys, this is the key
+ * identifier defined in \p attributes.
+ * \c 0 on failure.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * If the key is persistent, the key material and the key's metadata
+ * have been saved to persistent storage.
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ * This is an attempt to create a persistent key, and there is
+ * already a persistent key with the given identifier.
+ * \retval #PSA_ERROR_INSUFFICIENT_DATA
+ * There was not enough data to create the desired key.
+ * Note that in this case, no output is written to the output buffer.
+ * The operation's capacity is set to 0, thus subsequent calls to
+ * this function will not succeed, even with a smaller output buffer.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * The key type or key size is not supported, either by the
+ * implementation in general or in this particular location.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The provided key attributes are not valid for the operation.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * The #PSA_KEY_DERIVATION_INPUT_SECRET or
+ * #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a
+ * key; or one of the inputs was a key whose policy didn't allow
+ * #PSA_KEY_USAGE_DERIVE.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ * The operation state is not valid (it must be active and completed
+ * all required input steps), or the library has not been previously
+ * initialized by psa_crypto_init().
+ * It is implementation-dependent whether a failure to initialize
+ * results in this error code.
+ */
+psa_status_t psa_key_derivation_output_key_ext(
+ const psa_key_attributes_t *attributes,
+ psa_key_derivation_operation_t *operation,
+ const psa_key_production_parameters_t *params,
+ size_t params_data_length,
+ mbedtls_svc_key_id_t *key);
+
/** Compare output data from a key derivation operation to an expected value.
*
* This function calculates output bytes from a key derivation algorithm and
@@ -3835,7 +3921,8 @@
* and the permitted algorithm must match the
* operation. The value of this key was likely
* computed by a previous call to
- * psa_key_derivation_output_key().
+ * psa_key_derivation_output_key() or
+ * psa_key_derivation_output_key_ext().
*
* \retval #PSA_SUCCESS \emptydescription
* \retval #PSA_ERROR_INVALID_SIGNATURE
@@ -4003,6 +4090,10 @@
* between 2^{n-1} and 2^n where n is the bit size specified in the
* attributes.
*
+ * \note This function is equivalent to calling psa_generate_key_ext()
+ * with the production parameters #PSA_KEY_PRODUCTION_PARAMETERS_INIT
+ * and `params_data_length == 0` (i.e. `params->data` is empty).
+ *
* \param[in] attributes The attributes for the new key.
* \param[out] key On success, an identifier for the newly created
* key. For persistent keys, this is the key
@@ -4035,6 +4126,60 @@
psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
mbedtls_svc_key_id_t *key);
+/**
+ * \brief Generate a key or key pair using custom production parameters.
+ *
+ * See the description of psa_generate_key() for the operation of this
+ * function with the default production parameters. In addition, this function
+ * supports the following production customizations, described in more detail
+ * in the documentation of ::psa_key_production_parameters_t:
+ *
+ * - RSA keys: generation with a custom public exponent.
+ *
+ * \note This function is experimental and may change in future minor
+ * versions of Mbed TLS.
+ *
+ * \param[in] attributes The attributes for the new key.
+ * \param[in] params Customization parameters for the key generation.
+ * When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT
+ * with \p params_data_length = 0,
+ * this function is equivalent to
+ * psa_generate_key().
+ * \param params_data_length
+ * Length of `params->data` in bytes.
+ * \param[out] key On success, an identifier for the newly created
+ * key. For persistent keys, this is the key
+ * identifier defined in \p attributes.
+ * \c 0 on failure.
+ *
+ * \retval #PSA_SUCCESS
+ * Success.
+ * If the key is persistent, the key material and the key's metadata
+ * have been saved to persistent storage.
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ * This is an attempt to create a persistent key, and there is
+ * already a persistent key with the given identifier.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ * The library has not been previously initialized by psa_crypto_init().
+ * It is implementation-dependent whether a failure to initialize
+ * results in this error code.
+ */
+psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes,
+ const psa_key_production_parameters_t *params,
+ size_t params_data_length,
+ mbedtls_svc_key_id_t *key);
+
/**@}*/
/** \defgroup interruptible_hash Interruptible sign/verify hash
diff --git a/include/psa/crypto_compat.h b/include/psa/crypto_compat.h
index f896fae..2a226c0 100644
--- a/include/psa/crypto_compat.h
+++ b/include/psa/crypto_compat.h
@@ -146,6 +146,83 @@
*/
psa_status_t psa_close_key(psa_key_handle_t handle);
+/** \addtogroup attributes
+ * @{
+ */
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+/** Custom Diffie-Hellman group.
+ *
+ * Mbed TLS does not support custom DH groups.
+ *
+ * \deprecated This value is not useful, so this macro will be removed in
+ * a future version of the library.
+ */
+#define PSA_DH_FAMILY_CUSTOM \
+ ((psa_dh_family_t) MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(0x7e))
+
+/**
+ * \brief Set domain parameters for a key.
+ *
+ * \deprecated Mbed TLS no longer supports any domain parameters.
+ * This function only does the equivalent of
+ * psa_set_key_type() and will be removed in a future version
+ * of the library.
+ *
+ * \param[in,out] attributes Attribute structure where \p type will be set.
+ * \param type Key type (a \c PSA_KEY_TYPE_XXX value).
+ * \param[in] data Ignored.
+ * \param data_length Must be 0.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ */
+static inline psa_status_t MBEDTLS_DEPRECATED psa_set_key_domain_parameters(
+ psa_key_attributes_t *attributes,
+ psa_key_type_t type, const uint8_t *data, size_t data_length)
+{
+ (void) data;
+ if (data_length != 0) {
+ return PSA_ERROR_NOT_SUPPORTED;
+ }
+ psa_set_key_type(attributes, type);
+ return PSA_SUCCESS;
+}
+
+/**
+ * \brief Get domain parameters for a key.
+ *
+ * \deprecated Mbed TLS no longer supports any domain parameters.
+ * This function alwaya has an empty output and will be
+ * removed in a future version of the library.
+
+ * \param[in] attributes Ignored.
+ * \param[out] data Ignored.
+ * \param data_size Ignored.
+ * \param[out] data_length Set to 0.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ */
+static inline psa_status_t MBEDTLS_DEPRECATED psa_get_key_domain_parameters(
+ const psa_key_attributes_t *attributes,
+ uint8_t *data, size_t data_size, size_t *data_length)
+{
+ (void) attributes;
+ (void) data;
+ (void) data_size;
+ *data_length = 0;
+ return PSA_SUCCESS;
+}
+
+/** Safe output buffer size for psa_get_key_domain_parameters().
+ *
+ */
+#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits) \
+ MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(1u)
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
+/**@}*/
+
#ifdef __cplusplus
}
#endif
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
index 10a23f6..ac21e3e 100644
--- a/include/psa/crypto_extra.h
+++ b/include/psa/crypto_extra.h
@@ -409,140 +409,11 @@
* @{
*/
-/** Custom Diffie-Hellman group.
- *
- * For keys of type #PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_FAMILY_CUSTOM) or
- * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_FAMILY_CUSTOM), the group data comes
- * from domain parameters set by psa_set_key_domain_parameters().
- */
-#define PSA_DH_FAMILY_CUSTOM ((psa_dh_family_t) 0x7e)
-
/** PAKE operation stages. */
#define PSA_PAKE_OPERATION_STAGE_SETUP 0
#define PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS 1
#define PSA_PAKE_OPERATION_STAGE_COMPUTATION 2
-/**
- * \brief Set domain parameters for a key.
- *
- * Some key types require additional domain parameters in addition to
- * the key type identifier and the key size. Use this function instead
- * of psa_set_key_type() when you need to specify domain parameters.
- *
- * The format for the required domain parameters varies based on the key type.
- * Mbed TLS supports the following key type with domain parameters:
- *
- * - For RSA keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY or #PSA_KEY_TYPE_RSA_KEY_PAIR),
- * the domain parameter data consists of the public exponent,
- * represented as a big-endian integer with no leading zeros.
- * This information is used when generating an RSA key pair.
- * When importing a key, the public exponent is read from the imported
- * key data and the exponent recorded in the attribute structure is ignored.
- * As an exception, the public exponent 65537 is represented by an empty
- * byte string.
- *
- * \note This function may allocate memory or other resources.
- * Once you have called this function on an attribute structure,
- * you must call psa_reset_key_attributes() to free these resources.
- *
- * \note This is an experimental extension to the interface. It may change
- * in future versions of the library.
- *
- * \note Due to an implementation limitation, domain parameters are ignored
- * for keys that are managed by a driver.
- *
- * \param[in,out] attributes Attribute structure where the specified domain
- * parameters will be stored.
- * If this function fails, the content of
- * \p attributes is not modified.
- * \param type Key type (a \c PSA_KEY_TYPE_XXX value).
- * \param[in] data Buffer containing the key domain parameters.
- * The content of this buffer is interpreted
- * according to \p type as described above.
- * \param data_length Size of the \p data buffer in bytes.
- *
- * \retval #PSA_SUCCESS \emptydescription
- * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
- * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
- */
-#if !defined(PSA_SET_KEY_DOMAIN_PARAMETERS)
-#define PSA_SET_KEY_DOMAIN_PARAMETERS
-psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes,
- psa_key_type_t type,
- const uint8_t *data,
- size_t data_length);
-#endif /* PSA_SET_KEY_DOMAIN_PARAMETERS */
-
-/**
- * \brief Get domain parameters for a key.
- *
- * Get the domain parameters for a key with this function, if any. The format
- * of the domain parameters written to \p data is specified in the
- * documentation for psa_set_key_domain_parameters().
- *
- * \note This is an experimental extension to the interface. It may change
- * in future versions of the library.
- *
- * \note Due to an implementation limitation, domain parameters are not
- * supported with keys that are managed by a driver.
- *
- * \param[in] attributes The key attribute structure to query.
- * \param[out] data On success, the key domain parameters.
- * \param data_size Size of the \p data buffer in bytes.
- * The buffer is guaranteed to be large
- * enough if its size in bytes is at least
- * the value given by
- * PSA_KEY_DOMAIN_PARAMETERS_SIZE().
- * \param[out] data_length On success, the number of bytes
- * that make up the key domain parameters data.
- *
- * \retval #PSA_SUCCESS \emptydescription
- * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * The key is managed by a driver.
- */
-psa_status_t psa_get_key_domain_parameters(
- const psa_key_attributes_t *attributes,
- uint8_t *data,
- size_t data_size,
- size_t *data_length);
-
-/** Safe output buffer size for psa_get_key_domain_parameters().
- *
- * This macro returns a compile-time constant if its arguments are
- * compile-time constants.
- *
- * \warning This function may call its arguments multiple times or
- * zero times, so you should not pass arguments that contain
- * side effects.
- *
- * \note This is an experimental extension to the interface. It may change
- * in future versions of the library.
- *
- * \param key_type A supported key type.
- * \param key_bits The size of the key in bits.
- *
- * \return If the parameters are valid and supported, return
- * a buffer size in bytes that guarantees that
- * psa_get_key_domain_parameters() will not fail with
- * #PSA_ERROR_BUFFER_TOO_SMALL.
- * If the parameters are a valid combination that is not supported
- * by the implementation, this macro shall return either a
- * sensible size or 0.
- * If the parameters are not valid, the
- * return value is unspecified.
- */
-#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits) \
- (PSA_KEY_TYPE_IS_RSA(key_type) ? sizeof(int) : \
- PSA_KEY_TYPE_IS_DH(key_type) ? PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \
- PSA_KEY_TYPE_IS_DSA(key_type) ? PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \
- 0)
-#define PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \
- (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 3 /*without optional parts*/)
-#define PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \
- (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 2 /*p, g*/ + 34 /*q*/)
-
/**@}*/
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index 34d072b..683d841 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -223,6 +223,22 @@
return v;
}
+struct psa_key_production_parameters_s {
+ /* Future versions may add other fields in this structure. */
+ uint32_t flags;
+ uint8_t data[];
+};
+
+/** The default production parameters for key generation or key derivation.
+ *
+ * Calling psa_generate_key_ext() or psa_key_derivation_output_key_ext()
+ * with `params=PSA_KEY_PRODUCTION_PARAMETERS_INIT` and
+ * `params_data_length == 0` is equivalent to
+ * calling psa_generate_key() or psa_key_derivation_output_key()
+ * respectively.
+ */
+#define PSA_KEY_PRODUCTION_PARAMETERS_INIT { 0 }
+
struct psa_key_policy_s {
psa_key_usage_t MBEDTLS_PRIVATE(usage);
psa_algorithm_t MBEDTLS_PRIVATE(alg);
@@ -302,20 +318,6 @@
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
psa_key_slot_number_t MBEDTLS_PRIVATE(slot_number);
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
- /* Unlike normal buffers, there are three cases for domain_parameters
- * and domain_parameters_size:
- * - domain_parameters_size == SIZE_MAX && domain_parameters == NULL:
- * Access to domain parameters is not supported for this key.
- * This is a hack which should not exist, intended for keys managed
- * by a driver, because drivers don't support domain parameters.
- * - domain_parameters_size == 0 && domain_parameters == NULL:
- * The domain parameters are empty.
- * - domain_parameters_size > 0 &&
- * domain_parameters == valid pointer to domain_parameters_size bytes:
- * The domain parameters are non-empty.
- */
- void *MBEDTLS_PRIVATE(domain_parameters);
- size_t MBEDTLS_PRIVATE(domain_parameters_size);
/* With client/service separation, struct psa_key_attributes_s is
* marshalled through a transport channel between the client and
* service side implementation of the PSA Crypto APIs, thus having
@@ -326,9 +328,9 @@
};
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-#define PSA_KEY_ATTRIBUTES_INIT { 0, NULL, 0, PSA_CORE_KEY_ATTRIBUTES_INIT }
+#define PSA_KEY_ATTRIBUTES_INIT { 0, PSA_CORE_KEY_ATTRIBUTES_INIT }
#else
-#define PSA_KEY_ATTRIBUTES_INIT { NULL, 0, PSA_CORE_KEY_ATTRIBUTES_INIT }
+#define PSA_KEY_ATTRIBUTES_INIT { PSA_CORE_KEY_ATTRIBUTES_INIT }
#endif
static inline struct psa_key_attributes_s psa_key_attributes_init(void)
@@ -421,29 +423,10 @@
return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg);
}
-/* This function is declared in crypto_extra.h, which comes after this
- * header file, but we need the function here, so repeat the declaration. */
-#if !defined(PSA_SET_KEY_DOMAIN_PARAMETERS)
-#define PSA_SET_KEY_DOMAIN_PARAMETERS
-psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes,
- psa_key_type_t type,
- const uint8_t *data,
- size_t data_length);
-#endif /* PSA_SET_KEY_DOMAIN_PARAMETERS */
-
static inline void psa_set_key_type(psa_key_attributes_t *attributes,
psa_key_type_t type)
{
- if (attributes->MBEDTLS_PRIVATE(domain_parameters) == NULL) {
- /* Common case: quick path */
- attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(type) = type;
- } else {
- /* Call the bigger function to free the old domain parameters.
- * Ignore any errors which may arise due to type requiring
- * non-default domain parameters, since this function can't
- * report errors. */
- (void) psa_set_key_domain_parameters(attributes, type, NULL, 0);
- }
+ attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(type) = type;
}
static inline psa_key_type_t psa_get_key_type(
diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h
index e2ebd8a..31ea686 100644
--- a/include/psa/crypto_types.h
+++ b/include/psa/crypto_types.h
@@ -455,6 +455,30 @@
*/
typedef uint16_t psa_key_derivation_step_t;
+/** \brief Custom parameters for key generation or key derivation.
+ *
+ * This is a structure type with at least the following fields:
+ *
+ * - \c flags: an unsigned integer type. 0 for the default production parameters.
+ * - \c data: a flexible array of bytes.
+ *
+ * The interpretation of this structure depend on the type of the
+ * created key.
+ *
+ * - #PSA_KEY_TYPE_RSA_KEY_PAIR:
+ * - \c flags: must be 0.
+ * - \c data: the public exponent, in little-endian order.
+ * This must be an odd integer and must not be 1.
+ * Implementations must support 65535, should support 3 and may
+ * support other values.
+ * When not using a driver, Mbed TLS supports values up to \c INT_MAX.
+ * If this is empty or if the custom production parameters are omitted
+ * altogether, the default value 65537 is used.
+ * - Other key types: reserved for future use. \c flags must be 0.
+ *
+ */
+typedef struct psa_key_production_parameters_s psa_key_production_parameters_t;
+
/**@}*/
#endif /* PSA_CRYPTO_TYPES_H */
diff --git a/library/ecp.c b/library/ecp.c
index 758d54b..66b3dc1 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -3305,7 +3305,7 @@
int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key,
unsigned char *buf, size_t buflen)
{
- int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index b472cfb..846175e 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -306,7 +306,7 @@
psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
- psa_md_alg = mbedtls_md_psa_alg_from_type(mbedtls_rsa_get_md_alg(rsa));
+ psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa));
decrypt_alg = PSA_ALG_RSA_OAEP(psa_md_alg);
} else {
decrypt_alg = PSA_ALG_RSA_PKCS1V15_CRYPT;
@@ -388,7 +388,7 @@
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
- psa_md_alg = mbedtls_md_psa_alg_from_type(mbedtls_rsa_get_md_alg(rsa));
+ psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa));
psa_set_key_algorithm(&attributes, PSA_ALG_RSA_OAEP(psa_md_alg));
} else {
psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 87444e1..ca01e76 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -1211,58 +1211,12 @@
return overall_status;
}
-#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
- defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
-static psa_status_t psa_get_rsa_public_exponent(
- const mbedtls_rsa_context *rsa,
- psa_key_attributes_t *attributes)
-{
- mbedtls_mpi mpi;
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- uint8_t *buffer = NULL;
- size_t buflen;
- mbedtls_mpi_init(&mpi);
-
- ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &mpi);
- if (ret != 0) {
- goto exit;
- }
- if (mbedtls_mpi_cmp_int(&mpi, 65537) == 0) {
- /* It's the default value, which is reported as an empty string,
- * so there's nothing to do. */
- goto exit;
- }
-
- buflen = mbedtls_mpi_size(&mpi);
- buffer = mbedtls_calloc(1, buflen);
- if (buffer == NULL) {
- ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
- goto exit;
- }
- ret = mbedtls_mpi_write_binary(&mpi, buffer, buflen);
- if (ret != 0) {
- goto exit;
- }
- attributes->domain_parameters = buffer;
- attributes->domain_parameters_size = buflen;
-
-exit:
- mbedtls_mpi_free(&mpi);
- if (ret != 0) {
- mbedtls_free(buffer);
- }
- return mbedtls_to_psa_error(ret);
-}
-#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) ||
- * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
-
/** Retrieve all the publicly-accessible attributes of a key.
*/
psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key,
psa_key_attributes_t *attributes)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
- psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot;
psa_reset_key_attributes(attributes);
@@ -1283,55 +1237,7 @@
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
- switch (slot->attr.type) {
-#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \
- defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \
- defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
- case PSA_KEY_TYPE_RSA_KEY_PAIR:
- case PSA_KEY_TYPE_RSA_PUBLIC_KEY:
- /* TODO: This is a temporary situation where domain parameters are deprecated,
- * but we need it for namely generating an RSA key with a non-default exponent.
- * This would be improved after https://github.com/Mbed-TLS/mbedtls/issues/6494.
- */
- if (!psa_key_lifetime_is_external(slot->attr.lifetime)) {
- mbedtls_rsa_context *rsa = NULL;
-
- status = mbedtls_psa_rsa_load_representation(
- slot->attr.type,
- slot->key.data,
- slot->key.bytes,
- &rsa);
- if (status != PSA_SUCCESS) {
- break;
- }
-
- status = psa_get_rsa_public_exponent(rsa,
- attributes);
- mbedtls_rsa_free(rsa);
- mbedtls_free(rsa);
- }
- break;
-#else
- case PSA_KEY_TYPE_RSA_KEY_PAIR:
- case PSA_KEY_TYPE_RSA_PUBLIC_KEY:
- attributes->domain_parameters = NULL;
- attributes->domain_parameters_size = SIZE_MAX;
- break;
-#endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \
- * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) ||
- * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
- default:
- /* Nothing else to do. */
- break;
- }
-
- if (status != PSA_SUCCESS) {
- psa_reset_key_attributes(attributes);
- }
-
- unlock_status = psa_unregister_read_under_mutex(slot);
-
- return (status == PSA_SUCCESS) ? unlock_status : status;
+ return psa_unregister_read_under_mutex(slot);
}
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
@@ -1959,57 +1865,6 @@
}
}
- if (attributes->domain_parameters_size != 0) {
-#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \
- defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \
- defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
- if (PSA_KEY_TYPE_IS_RSA(slot->attr.type)) {
- mbedtls_rsa_context *rsa = NULL;
- mbedtls_mpi actual, required;
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
- psa_status_t status = mbedtls_psa_rsa_load_representation(
- slot->attr.type,
- slot->key.data,
- slot->key.bytes,
- &rsa);
- if (status != PSA_SUCCESS) {
- return status;
- }
-
- mbedtls_mpi_init(&actual);
- mbedtls_mpi_init(&required);
- ret = mbedtls_rsa_export(rsa,
- NULL, NULL, NULL, NULL, &actual);
- mbedtls_rsa_free(rsa);
- mbedtls_free(rsa);
- if (ret != 0) {
- goto rsa_exit;
- }
- ret = mbedtls_mpi_read_binary(&required,
- attributes->domain_parameters,
- attributes->domain_parameters_size);
- if (ret != 0) {
- goto rsa_exit;
- }
- if (mbedtls_mpi_cmp_mpi(&actual, &required) != 0) {
- ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
- }
-rsa_exit:
- mbedtls_mpi_free(&actual);
- mbedtls_mpi_free(&required);
- if (ret != 0) {
- return mbedtls_to_psa_error(ret);
- }
- } else
-#endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) &&
- * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) ||
- * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
- {
- return PSA_ERROR_INVALID_ARGUMENT;
- }
- }
-
if (attributes->core.bits != 0) {
if (attributes->core.bits != slot->attr.bits) {
return PSA_ERROR_INVALID_ARGUMENT;
@@ -6066,9 +5921,28 @@
return status;
}
-psa_status_t psa_key_derivation_output_key(const psa_key_attributes_t *attributes,
- psa_key_derivation_operation_t *operation,
- mbedtls_svc_key_id_t *key)
+static const psa_key_production_parameters_t default_production_parameters =
+ PSA_KEY_PRODUCTION_PARAMETERS_INIT;
+
+int psa_key_production_parameters_are_default(
+ const psa_key_production_parameters_t *params,
+ size_t params_data_length)
+{
+ if (params->flags != 0) {
+ return 0;
+ }
+ if (params_data_length != 0) {
+ return 0;
+ }
+ return 1;
+}
+
+psa_status_t psa_key_derivation_output_key_ext(
+ const psa_key_attributes_t *attributes,
+ psa_key_derivation_operation_t *operation,
+ const psa_key_production_parameters_t *params,
+ size_t params_data_length,
+ mbedtls_svc_key_id_t *key)
{
psa_status_t status;
psa_key_slot_t *slot = NULL;
@@ -6082,6 +5956,10 @@
return PSA_ERROR_INVALID_ARGUMENT;
}
+ if (!psa_key_production_parameters_are_default(params, params_data_length)) {
+ return PSA_ERROR_INVALID_ARGUMENT;
+ }
+
if (operation->alg == PSA_ALG_NONE) {
return PSA_ERROR_BAD_STATE;
}
@@ -6113,6 +5991,15 @@
return status;
}
+psa_status_t psa_key_derivation_output_key(
+ const psa_key_attributes_t *attributes,
+ psa_key_derivation_operation_t *operation,
+ mbedtls_svc_key_id_t *key)
+{
+ return psa_key_derivation_output_key_ext(attributes, operation,
+ &default_production_parameters, 0,
+ key);
+}
/****************************************************************/
@@ -7509,15 +7396,15 @@
psa_status_t psa_generate_key_internal(
const psa_key_attributes_t *attributes,
+ const psa_key_production_parameters_t *params, size_t params_data_length,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_type_t type = attributes->core.type;
- if ((attributes->domain_parameters == NULL) &&
- (attributes->domain_parameters_size != 0)) {
- return PSA_ERROR_INVALID_ARGUMENT;
- }
+ /* Only used for RSA */
+ (void) params;
+ (void) params_data_length;
if (key_type_is_raw_bytes(type)) {
status = psa_generate_random(key_buffer, key_buffer_size);
@@ -7535,6 +7422,7 @@
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
return mbedtls_psa_rsa_generate_key(attributes,
+ params, params_data_length,
key_buffer,
key_buffer_size,
key_buffer_length);
@@ -7566,8 +7454,10 @@
return PSA_SUCCESS;
}
-psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
- mbedtls_svc_key_id_t *key)
+psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes,
+ const psa_key_production_parameters_t *params,
+ size_t params_data_length,
+ mbedtls_svc_key_id_t *key)
{
psa_status_t status;
psa_key_slot_t *slot = NULL;
@@ -7587,6 +7477,17 @@
return PSA_ERROR_INVALID_ARGUMENT;
}
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+ if (attributes->core.type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
+ if (params->flags != 0) {
+ return PSA_ERROR_INVALID_ARGUMENT;
+ }
+ } else
+#endif
+ if (!psa_key_production_parameters_are_default(params, params_data_length)) {
+ return PSA_ERROR_INVALID_ARGUMENT;
+ }
+
status = psa_start_key_creation(PSA_KEY_CREATION_GENERATE, attributes,
&slot, &driver);
if (status != PSA_SUCCESS) {
@@ -7624,8 +7525,9 @@
}
status = psa_driver_wrapper_generate_key(attributes,
- slot->key.data, slot->key.bytes, &slot->key.bytes);
-
+ params, params_data_length,
+ slot->key.data, slot->key.bytes,
+ &slot->key.bytes);
if (status != PSA_SUCCESS) {
psa_remove_key_data_from_memory(slot);
}
@@ -7641,6 +7543,14 @@
return status;
}
+psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
+ mbedtls_svc_key_id_t *key)
+{
+ return psa_generate_key_ext(attributes,
+ &default_production_parameters, 0,
+ key);
+}
+
/****************************************************************/
/* Module setup */
/****************************************************************/
diff --git a/library/psa_crypto_client.c b/library/psa_crypto_client.c
index 472d3d3..72f671d 100644
--- a/library/psa_crypto_client.c
+++ b/library/psa_crypto_client.c
@@ -16,57 +16,7 @@
void psa_reset_key_attributes(psa_key_attributes_t *attributes)
{
- mbedtls_free(attributes->domain_parameters);
memset(attributes, 0, sizeof(*attributes));
}
-psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes,
- psa_key_type_t type,
- const uint8_t *data,
- size_t data_length)
-{
- uint8_t *copy = NULL;
-
- if (data_length != 0) {
- copy = mbedtls_calloc(1, data_length);
- if (copy == NULL) {
- return PSA_ERROR_INSUFFICIENT_MEMORY;
- }
- memcpy(copy, data, data_length);
- }
- /* After this point, this function is guaranteed to succeed, so it
- * can start modifying `*attributes`. */
-
- if (attributes->domain_parameters != NULL) {
- mbedtls_free(attributes->domain_parameters);
- attributes->domain_parameters = NULL;
- attributes->domain_parameters_size = 0;
- }
-
- attributes->domain_parameters = copy;
- attributes->domain_parameters_size = data_length;
- attributes->core.type = type;
- return PSA_SUCCESS;
-}
-
-psa_status_t psa_get_key_domain_parameters(
- const psa_key_attributes_t *attributes,
- uint8_t *data, size_t data_size, size_t *data_length)
-{
- if (attributes->domain_parameters == NULL &&
- attributes->domain_parameters_size == SIZE_MAX) {
- return PSA_ERROR_NOT_SUPPORTED;
- }
-
- if (attributes->domain_parameters_size > data_size) {
- return PSA_ERROR_BUFFER_TOO_SMALL;
- }
- *data_length = attributes->domain_parameters_size;
- if (attributes->domain_parameters_size != 0) {
- memcpy(data, attributes->domain_parameters,
- attributes->domain_parameters_size);
- }
- return PSA_SUCCESS;
-}
-
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
index 0d7322c..afa8659 100644
--- a/library/psa_crypto_core.h
+++ b/library/psa_crypto_core.h
@@ -398,6 +398,18 @@
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length);
+/** Whether a key production parameters structure is the default.
+ *
+ * Calls to a key generation driver with non-default production parameters
+ * require a driver supporting custom production parameters.
+ *
+ * \param[in] params The key production parameters to check.
+ * \param params_data_length Size of `params->data` in bytes.
+ */
+int psa_key_production_parameters_are_default(
+ const psa_key_production_parameters_t *params,
+ size_t params_data_length);
+
/**
* \brief Generate a key.
*
@@ -405,6 +417,9 @@
* entry point.
*
* \param[in] attributes The attributes for the key to generate.
+ * \param[in] params The production parameters from
+ * psa_generate_key_ext().
+ * \param params_data_length The size of `params->data` in bytes.
* \param[out] key_buffer Buffer where the key data is to be written.
* \param[in] key_buffer_size Size of \p key_buffer in bytes.
* \param[out] key_buffer_length On success, the number of bytes written in
@@ -419,6 +434,8 @@
* The size of \p key_buffer is too small.
*/
psa_status_t psa_generate_key_internal(const psa_key_attributes_t *attributes,
+ const psa_key_production_parameters_t *params,
+ size_t params_data_length,
uint8_t *key_buffer,
size_t key_buffer_size,
size_t *key_buffer_length);
diff --git a/library/psa_crypto_ecp.c b/library/psa_crypto_ecp.c
index db08541..7edea81 100644
--- a/library/psa_crypto_ecp.c
+++ b/library/psa_crypto_ecp.c
@@ -345,10 +345,6 @@
mbedtls_ecp_curve_info_from_grp_id(grp_id);
mbedtls_ecp_keypair ecp;
- if (attributes->domain_parameters_size != 0) {
- return PSA_ERROR_NOT_SUPPORTED;
- }
-
if (grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL) {
return PSA_ERROR_NOT_SUPPORTED;
}
diff --git a/library/psa_crypto_rsa.c b/library/psa_crypto_rsa.c
index 4a574d1..84a8667 100644
--- a/library/psa_crypto_rsa.c
+++ b/library/psa_crypto_rsa.c
@@ -216,26 +216,21 @@
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
-static psa_status_t psa_rsa_read_exponent(const uint8_t *domain_parameters,
- size_t domain_parameters_size,
+static psa_status_t psa_rsa_read_exponent(const uint8_t *e_bytes,
+ size_t e_length,
int *exponent)
{
size_t i;
uint32_t acc = 0;
- if (domain_parameters_size == 0) {
- *exponent = 65537;
- return PSA_SUCCESS;
- }
-
/* Mbed TLS encodes the public exponent as an int. For simplicity, only
* support values that fit in a 32-bit integer, which is larger than
* int on just about every platform anyway. */
- if (domain_parameters_size > sizeof(acc)) {
+ if (e_length > sizeof(acc)) {
return PSA_ERROR_NOT_SUPPORTED;
}
- for (i = 0; i < domain_parameters_size; i++) {
- acc = (acc << 8) | domain_parameters[i];
+ for (i = 0; i < e_length; i++) {
+ acc = (acc << 8) | e_bytes[i];
}
if (acc > INT_MAX) {
return PSA_ERROR_NOT_SUPPORTED;
@@ -246,18 +241,20 @@
psa_status_t mbedtls_psa_rsa_generate_key(
const psa_key_attributes_t *attributes,
+ const psa_key_production_parameters_t *params, size_t params_data_length,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
{
psa_status_t status;
mbedtls_rsa_context rsa;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- int exponent;
+ int exponent = 65537;
- status = psa_rsa_read_exponent(attributes->domain_parameters,
- attributes->domain_parameters_size,
- &exponent);
- if (status != PSA_SUCCESS) {
- return status;
+ if (params_data_length != 0) {
+ status = psa_rsa_read_exponent(params->data, params_data_length,
+ &exponent);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
}
mbedtls_rsa_init(&rsa);
diff --git a/library/psa_crypto_rsa.h b/library/psa_crypto_rsa.h
index e4c5caf..ffeef26 100644
--- a/library/psa_crypto_rsa.h
+++ b/library/psa_crypto_rsa.h
@@ -109,6 +109,15 @@
* entry point.
*
* \param[in] attributes The attributes for the RSA key to generate.
+ * \param[in] params Production parameters for the key
+ * generation. This function only uses
+ * `params->data`,
+ * which contains the public exponent.
+ * This can be a null pointer if
+ * \c params_data_length is 0.
+ * \param params_data_length Length of `params->data` in bytes.
+ * This can be 0, in which case the
+ * public exponent will be 65537.
* \param[out] key_buffer Buffer where the key data is to be written.
* \param[in] key_buffer_size Size of \p key_buffer in bytes.
* \param[out] key_buffer_length On success, the number of bytes written in
@@ -123,6 +132,7 @@
*/
psa_status_t mbedtls_psa_rsa_generate_key(
const psa_key_attributes_t *attributes,
+ const psa_key_production_parameters_t *params, size_t params_data_length,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);
/** Sign an already-calculated hash with an RSA private key.
diff --git a/library/ssl_debug_helpers.h b/library/ssl_debug_helpers.h
index 2b0e737..a8e3140 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 942d4ad..d8844fc 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -665,21 +665,21 @@
#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 @@
#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 @@
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 c2e64c6..2a6d434 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -6058,6 +6058,94 @@
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 1e8df1b..88d6c9e 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -1180,7 +1180,15 @@
#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 @@
* 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 @@
return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
}
- handshake->hello_retry_request_count++;
+ handshake->hello_retry_request_flag = 1;
break;
}
@@ -1672,7 +1680,7 @@
* 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 @@
}
+#if defined(MBEDTLS_SSL_EARLY_DATA)
/*
* Handler for MBEDTLS_SSL_END_OF_EARLY_DATA
*
@@ -2308,6 +2317,32 @@
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 @@
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 @@
*/
#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 064f616..bc73704 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -1379,6 +1379,12 @@
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 @@
/* 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 1411446..3a968aa 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -1531,7 +1531,7 @@
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 @@
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 @@
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 @@
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/library/x509_internal.h b/library/x509_internal.h
index 15e097a..8a2d2ed 100644
--- a/library/x509_internal.h
+++ b/library/x509_internal.h
@@ -21,133 +21,6 @@
#include "mbedtls/rsa.h"
#endif
-/**
- * \brief Return the next relative DN in an X509 name.
- *
- * \note Intended use is to compare function result to dn->next
- * in order to detect boundaries of multi-valued RDNs.
- *
- * \param dn Current node in the X509 name
- *
- * \return Pointer to the first attribute-value pair of the
- * next RDN in sequence, or NULL if end is reached.
- */
-static inline mbedtls_x509_name *mbedtls_x509_dn_get_next(
- mbedtls_x509_name *dn)
-{
- while (dn->MBEDTLS_PRIVATE(next_merged) && dn->next != NULL) {
- dn = dn->next;
- }
- return dn->next;
-}
-
-/**
- * \brief Store the certificate serial in printable form into buf;
- * no more than size characters will be written.
- *
- * \param buf Buffer to write to
- * \param size Maximum size of buffer
- * \param serial The X509 serial to represent
- *
- * \return The length of the string written (not including the
- * terminated nul byte), or a negative error code.
- */
-int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial);
-
-/**
- * \brief Compare pair of mbedtls_x509_time.
- *
- * \param t1 mbedtls_x509_time to compare
- * \param t2 mbedtls_x509_time to compare
- *
- * \return < 0 if t1 is before t2
- * 0 if t1 equals t2
- * > 0 if t1 is after t2
- */
-int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1, const mbedtls_x509_time *t2);
-
-#if defined(MBEDTLS_HAVE_TIME_DATE)
-/**
- * \brief Fill mbedtls_x509_time with provided mbedtls_time_t.
- *
- * \param tt mbedtls_time_t to convert
- * \param now mbedtls_x509_time to fill with converted mbedtls_time_t
- *
- * \return \c 0 on success
- * \return A non-zero return value on failure.
- */
-int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now);
-#endif /* MBEDTLS_HAVE_TIME_DATE */
-
-/**
- * \brief Check a given mbedtls_x509_time against the system time
- * and tell if it's in the past.
- *
- * \note Intended usage is "if( is_past( valid_to ) ) ERROR".
- * Hence the return value of 1 if on internal errors.
- *
- * \param to mbedtls_x509_time to check
- *
- * \return 1 if the given time is in the past or an error occurred,
- * 0 otherwise.
- */
-int mbedtls_x509_time_is_past(const mbedtls_x509_time *to);
-
-/**
- * \brief Check a given mbedtls_x509_time against the system time
- * and tell if it's in the future.
- *
- * \note Intended usage is "if( is_future( valid_from ) ) ERROR".
- * Hence the return value of 1 if on internal errors.
- *
- * \param from mbedtls_x509_time to check
- *
- * \return 1 if the given time is in the future or an error occurred,
- * 0 otherwise.
- */
-int mbedtls_x509_time_is_future(const mbedtls_x509_time *from);
-
-/**
- * \brief This function parses an item in the SubjectAlternativeNames
- * extension. Please note that this function might allocate
- * additional memory for a subject alternative name, thus
- * mbedtls_x509_free_subject_alt_name has to be called
- * to dispose of this additional memory afterwards.
- *
- * \param san_buf The buffer holding the raw data item of the subject
- * alternative name.
- * \param san The target structure to populate with the parsed presentation
- * of the subject alternative name encoded in \p san_buf.
- *
- * \note Supported GeneralName types, as defined in RFC 5280:
- * "rfc822Name", "dnsName", "directoryName",
- * "uniformResourceIdentifier" and "hardware_module_name"
- * of type "otherName", as defined in RFC 4108.
- *
- * \note This function should be called on a single raw data of
- * subject alternative name. For example, after successful
- * certificate parsing, one must iterate on every item in the
- * \c crt->subject_alt_names sequence, and pass it to
- * this function.
- *
- * \warning The target structure contains pointers to the raw data of the
- * parsed certificate, and its lifetime is restricted by the
- * lifetime of the certificate.
- *
- * \return \c 0 on success
- * \return #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported
- * SAN type.
- * \return Another negative value for any other failure.
- */
-int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
- mbedtls_x509_subject_alternative_name *san);
-/**
- * \brief Unallocate all data related to subject alternative name
- *
- * \param san SAN structure - extra memory owned by this structure will be freed
- */
-void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san);
-
int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,
mbedtls_x509_name *cur);
int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end,
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index f5768b1..332befd 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -52,7 +52,7 @@
#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 @@
#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 @@
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 @@
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 @@
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 @@
#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 */
@@ -1967,16 +2025,9 @@
}
#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) {
@@ -2447,32 +2498,9 @@
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) {
@@ -2544,8 +2572,11 @@
}
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) {
@@ -2652,7 +2683,9 @@
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. */
@@ -2711,7 +2744,9 @@
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;
}
@@ -3001,6 +3036,54 @@
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 &&
@@ -3034,12 +3117,6 @@
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/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja
index 924b08c..4f9764d 100644
--- a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja
+++ b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja
@@ -731,12 +731,27 @@
static inline psa_status_t psa_driver_wrapper_generate_key(
const psa_key_attributes_t *attributes,
+ const psa_key_production_parameters_t *params, size_t params_data_length,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_location_t location =
PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime);
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+ int is_default_production =
+ psa_key_production_parameters_are_default(params, params_data_length);
+ if( location != PSA_KEY_LOCATION_LOCAL_STORAGE && !is_default_production )
+ {
+ /* We don't support passing custom production parameters
+ * to drivers yet. */
+ return PSA_ERROR_NOT_SUPPORTED;
+ }
+#else
+ int is_default_production = 1;
+ (void) is_default_production;
+#endif
+
/* Try dynamically-registered SE interface first */
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
const psa_drv_se_t *drv;
@@ -762,8 +777,11 @@
{
case PSA_KEY_LOCATION_LOCAL_STORAGE:
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
- /* Transparent drivers are limited to generating asymmetric keys */
- if( PSA_KEY_TYPE_IS_ASYMMETRIC( attributes->core.type ) )
+ /* Transparent drivers are limited to generating asymmetric keys. */
+ /* We don't support passing custom production parameters
+ * to drivers yet. */
+ if( PSA_KEY_TYPE_IS_ASYMMETRIC( attributes->core.type ) &&
+ is_default_production )
{
/* Cycle through all known transparent accelerators */
#if defined(PSA_CRYPTO_DRIVER_TEST)
@@ -793,7 +811,8 @@
/* Software fallback */
status = psa_generate_key_internal(
- attributes, key_buffer, key_buffer_size, key_buffer_length );
+ attributes, params, params_data_length,
+ key_buffer, key_buffer_size, key_buffer_length );
break;
/* Add cases for opaque driver here */
diff --git a/tests/include/test/ssl_helpers.h b/tests/include/test/ssl_helpers.h
index 9a078f6..5b071f7 100644
--- a/tests/include/test/ssl_helpers.h
+++ b/tests/include/test/ssl_helpers.h
@@ -608,9 +608,7 @@
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 4e6bf87..ad062dc 100755
--- a/tests/opt-testcases/tls13-misc.sh
+++ b/tests/opt-testcases/tls13-misc.sh
@@ -263,7 +263,7 @@
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" \
@@ -285,9 +285,34 @@
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
+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: 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/scripts/analyze_outcomes.py b/tests/scripts/analyze_outcomes.py
index 2a29f71..5b4deb6 100755
--- a/tests/scripts/analyze_outcomes.py
+++ b/tests/scripts/analyze_outcomes.py
@@ -570,6 +570,11 @@
re.compile(r'mbedtls_ct_zeroize_if .*'),
re.compile(r'mbedtls_ct_memmove_left .*')
],
+ 'test_suite_psa_crypto': [
+ # We don't support generate_key_ext entry points
+ # in drivers yet.
+ re.compile(r'PSA generate key ext: RSA, e=.*'),
+ ],
}
}
},
diff --git a/tests/src/drivers/test_driver_key_management.c b/tests/src/drivers/test_driver_key_management.c
index a3d532d..866b31e 100644
--- a/tests/src/drivers/test_driver_key_management.c
+++ b/tests/src/drivers/test_driver_key_management.c
@@ -225,10 +225,13 @@
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
return libtestdriver1_mbedtls_psa_rsa_generate_key(
(const libtestdriver1_psa_key_attributes_t *) attributes,
+ NULL, 0, /* We don't support custom e in the test driver yet */
key, key_size, key_length);
#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
return mbedtls_psa_rsa_generate_key(
- attributes, key, key_size, key_length);
+ attributes,
+ NULL, 0, /* We don't support custom e in the test driver yet */
+ key, key_size, key_length);
#endif
} else if (PSA_KEY_TYPE_IS_DH(psa_get_key_type(attributes))
&& PSA_KEY_TYPE_IS_KEY_PAIR(psa_get_key_type(attributes))) {
diff --git a/tests/src/helpers.c b/tests/src/helpers.c
index b9233be..2433422 100644
--- a/tests/src/helpers.c
+++ b/tests/src/helpers.c
@@ -31,7 +31,16 @@
#endif /* MBEDTLS_THREADING_C */
/*----------------------------------------------------------------------------*/
-/* Mbedtls Test Info accessors */
+/* Mbedtls Test Info accessors
+ *
+ * NOTE - there are two types of accessors here: public accessors and internal
+ * accessors. The public accessors have prototypes in helpers.h and lock
+ * mbedtls_test_info_mutex (if mutexes are enabled). The _internal accessors,
+ * which are expected to be used from this module *only*, do not lock the mutex.
+ * These are designed to be called from within public functions which already
+ * hold the mutex. The main reason for this difference is the need to set
+ * multiple test data values atomically (without releasing the mutex) to prevent
+ * race conditions. */
mbedtls_test_result_t mbedtls_test_get_result(void)
{
@@ -50,8 +59,8 @@
return result;
}
-void mbedtls_test_set_result(mbedtls_test_result_t result, const char *test,
- int line_no, const char *filename)
+static void mbedtls_test_set_result_internal(mbedtls_test_result_t result, const char *test,
+ int line_no, const char *filename)
{
/* Internal function only - mbedtls_test_info_mutex should be held prior
* to calling this function. */
@@ -144,7 +153,7 @@
return step;
}
-void mbedtls_test_reset_step(void)
+static void mbedtls_test_reset_step_internal(void)
{
/* Internal function only - mbedtls_test_info_mutex should be held prior
* to calling this function. */
@@ -178,7 +187,7 @@
#endif /* MBEDTLS_THREADING_C */
}
-void mbedtls_test_set_line1(const char *line)
+static void mbedtls_test_set_line1_internal(const char *line)
{
/* Internal function only - mbedtls_test_info_mutex should be held prior
* to calling this function. */
@@ -203,7 +212,7 @@
#endif /* MBEDTLS_THREADING_C */
}
-void mbedtls_test_set_line2(const char *line)
+static void mbedtls_test_set_line2_internal(const char *line)
{
/* Internal function only - mbedtls_test_info_mutex should be held prior
* to calling this function. */
@@ -219,7 +228,19 @@
#if defined(MBEDTLS_TEST_MUTEX_USAGE)
const char *mbedtls_test_get_mutex_usage_error(void)
{
- return mbedtls_test_info.mutex_usage_error;
+ const char *usage_error;
+
+#ifdef MBEDTLS_THREADING_C
+ mbedtls_mutex_lock(&mbedtls_test_info_mutex);
+#endif /* MBEDTLS_THREADING_C */
+
+ usage_error = mbedtls_test_info.mutex_usage_error;
+
+#ifdef MBEDTLS_THREADING_C
+ mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
+#endif /* MBEDTLS_THREADING_C */
+
+ return usage_error;
}
void mbedtls_test_set_mutex_usage_error(const char *msg)
@@ -255,7 +276,7 @@
return test_case_uses_negative_0;
}
-void mbedtls_test_set_case_uses_negative_0(unsigned uses)
+static void mbedtls_test_set_case_uses_negative_0_internal(unsigned uses)
{
/* Internal function only - mbedtls_test_info_mutex should be held prior
* to calling this function. */
@@ -350,7 +371,7 @@
if (mbedtls_test_info.result != MBEDTLS_TEST_RESULT_FAILED) {
/* If we have already recorded the test as having failed then don't
* overwrite any previous information about the failure. */
- mbedtls_test_set_result(MBEDTLS_TEST_RESULT_FAILED, test, line_no, filename);
+ mbedtls_test_set_result_internal(MBEDTLS_TEST_RESULT_FAILED, test, line_no, filename);
}
}
@@ -373,7 +394,7 @@
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
- mbedtls_test_set_result(MBEDTLS_TEST_RESULT_SKIPPED, test, line_no, filename);
+ mbedtls_test_set_result_internal(MBEDTLS_TEST_RESULT_SKIPPED, test, line_no, filename);
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
@@ -386,13 +407,13 @@
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
- mbedtls_test_set_result(MBEDTLS_TEST_RESULT_SUCCESS, 0, 0, 0);
- mbedtls_test_reset_step();
- mbedtls_test_set_line1(NULL);
- mbedtls_test_set_line2(NULL);
+ mbedtls_test_set_result_internal(MBEDTLS_TEST_RESULT_SUCCESS, 0, 0, 0);
+ mbedtls_test_reset_step_internal();
+ mbedtls_test_set_line1_internal(NULL);
+ mbedtls_test_set_line2_internal(NULL);
#if defined(MBEDTLS_BIGNUM_C)
- mbedtls_test_set_case_uses_negative_0(0);
+ mbedtls_test_set_case_uses_negative_0_internal(0);
#endif
#ifdef MBEDTLS_THREADING_C
@@ -424,11 +445,11 @@
(void) mbedtls_snprintf(buf, sizeof(buf),
"lhs = 0x%016llx = %lld",
value1, (long long) value1);
- mbedtls_test_set_line1(buf);
+ mbedtls_test_set_line1_internal(buf);
(void) mbedtls_snprintf(buf, sizeof(buf),
"rhs = 0x%016llx = %lld",
value2, (long long) value2);
- mbedtls_test_set_line2(buf);
+ mbedtls_test_set_line2_internal(buf);
}
#ifdef MBEDTLS_THREADING_C
@@ -462,11 +483,11 @@
(void) mbedtls_snprintf(buf, sizeof(buf),
"lhs = 0x%016llx = %llu",
value1, value1);
- mbedtls_test_set_line1(buf);
+ mbedtls_test_set_line1_internal(buf);
(void) mbedtls_snprintf(buf, sizeof(buf),
"rhs = 0x%016llx = %llu",
value2, value2);
- mbedtls_test_set_line2(buf);
+ mbedtls_test_set_line2_internal(buf);
}
#ifdef MBEDTLS_THREADING_C
@@ -500,11 +521,11 @@
(void) mbedtls_snprintf(buf, sizeof(buf),
"lhs = 0x%016llx = %lld",
(unsigned long long) value1, value1);
- mbedtls_test_set_line1(buf);
+ mbedtls_test_set_line1_internal(buf);
(void) mbedtls_snprintf(buf, sizeof(buf),
"rhs = 0x%016llx = %lld",
(unsigned long long) value2, value2);
- mbedtls_test_set_line2(buf);
+ mbedtls_test_set_line2_internal(buf);
}
#ifdef MBEDTLS_THREADING_C
diff --git a/tests/src/threading_helpers.c b/tests/src/threading_helpers.c
index ff0c712..c1686c2 100644
--- a/tests/src/threading_helpers.c
+++ b/tests/src/threading_helpers.c
@@ -317,22 +317,26 @@
void mbedtls_test_mutex_usage_check(void)
{
- if (live_mutexes != 0) {
- /* A positive number (more init than free) means that a mutex resource
- * is leaking (on platforms where a mutex consumes more than the
- * mbedtls_threading_mutex_t object itself). The rare case of a
- * negative number means a missing init somewhere. */
- mbedtls_fprintf(stdout, "[mutex: %d leaked] ", live_mutexes);
- live_mutexes = 0;
- mbedtls_test_set_mutex_usage_error("missing free");
+ if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) {
+ if (live_mutexes != 0) {
+ /* A positive number (more init than free) means that a mutex resource
+ * is leaking (on platforms where a mutex consumes more than the
+ * mbedtls_threading_mutex_t object itself). The (hopefully) rare
+ * case of a negative number means a missing init somewhere. */
+ mbedtls_fprintf(stdout, "[mutex: %d leaked] ", live_mutexes);
+ live_mutexes = 0;
+ mbedtls_test_set_mutex_usage_error("missing free");
+ }
+ if (mbedtls_test_get_mutex_usage_error() != NULL &&
+ mbedtls_test_get_result() != MBEDTLS_TEST_RESULT_FAILED) {
+ /* Functionally, the test passed. But there was a mutex usage error,
+ * so mark the test as failed after all. */
+ mbedtls_test_fail("Mutex usage error", __LINE__, __FILE__);
+ }
+ mbedtls_test_set_mutex_usage_error(NULL);
+
+ mutex_functions.unlock(&mbedtls_test_mutex_mutex);
}
- if (mbedtls_test_get_mutex_usage_error() != NULL &&
- mbedtls_test_get_result() != MBEDTLS_TEST_RESULT_FAILED) {
- /* Functionally, the test passed. But there was a mutex usage error,
- * so mark the test as failed after all. */
- mbedtls_test_fail("Mutex usage error", __LINE__, __FILE__);
- }
- mbedtls_test_set_mutex_usage_error(NULL);
}
void mbedtls_test_mutex_usage_end(void)
diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data
index 01fdc47..1dd963a 100644
--- a/tests/suites/test_suite_ecp.data
+++ b/tests/suites/test_suite_ecp.data
@@ -736,6 +736,158 @@
depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
mbedtls_ecp_read_key:MBEDTLS_ECP_DP_CURVE25519:"70076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c6a":0:1
+ECP write key: secp256r1, nominal
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":32:0
+
+ECP write key: secp256r1, output longer by 1
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":33:0
+
+ECP write key: secp256r1, output longer by 32
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":64:0
+
+ECP write key: secp256r1, output longer by 33
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":65:0
+
+ECP write key: secp256r1, output short by 1
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":31:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
+
+ECP write key: secp256r1, output_size=1
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":1:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
+
+ECP write key: secp256r1, output_size=0
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":0:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
+
+ECP write key: secp256r1, top byte = 0, output_size=32
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":32:0
+
+ECP write key: secp256r1, top byte = 0, output_size=31 (fits)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":31:0
+
+ECP write key: secp256r1, top byte = 0, output_size=30 (too small)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":30:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
+
+ECP write key: secp256r1, mostly-0 key, output_size=32
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"0000000000000000000000000000000000000000000000000000000000000001":32:0
+
+ECP write key: secp256r1, mostly-0 key, output_size=31 (fits)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"0000000000000000000000000000000000000000000000000000000000000001":31:0
+
+ECP write key: secp256r1, mostly-0 key, output_size=1 (fits)
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP256R1:"0000000000000000000000000000000000000000000000000000000000000001":1:0
+
+ECP write key: secp384r1, nominal
+depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":48:0
+
+ECP write key: secp384r1, output longer by 1
+depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":49:0
+
+ECP write key: secp384r1, output longer by 48
+depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":96:0
+
+ECP write key: secp384r1, output longer by 49
+depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":97:0
+
+ECP write key: secp384r1, output short by 1
+depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":47:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
+
+ECP write key: secp384r1, output_size=1
+depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":1:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
+
+ECP write key: secp384r1, output_size=0
+depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_SECP384R1:"d27335ea71664af244dd14e9fd1260715dfd8a7965571c48d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1":0:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
+
+ECP write key: Curve25519, nominal
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":32:0
+
+ECP write key: Curve25519, output longer by 1
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":33:0
+
+ECP write key: Curve25519, output longer by 32
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":64:0
+
+ECP write key: Curve25519, output longer by 33
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":65:0
+
+ECP write key: Curve25519, output short by 1
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":31:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
+
+ECP write key: Curve25519, output_size=1
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":1:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
+
+ECP write key: Curve25519, output_size=0
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"a046e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449a44":0:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
+
+ECP write key: Curve25519, mostly-0 key, output_size=32
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"0000000000000000000000000000000000000000000000000000000000000040":32:0
+
+ECP write key: Curve25519, mostly-0 key, output_size=31
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE25519:"0000000000000000000000000000000000000000000000000000000000000040":31:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
+
+ECP write key: Curve448, nominal
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":56:0
+
+ECP write key: Curve448, output longer by 1
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":57:0
+
+ECP write key: Curve448, output longer by 32
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":112:0
+
+ECP write key: Curve448, output longer by 33
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":113:0
+
+ECP write key: Curve448, output short by 1
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":55:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
+
+ECP write key: Curve448, output_size=1
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":1:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
+
+ECP write key: Curve448, output_size=0
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"3c262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3":0:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
+
+ECP write key: Curve448, mostly-0 key, output_size=56
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080":56:0
+
+ECP write key: Curve448, mostly-0 key, output_size=55
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_write_key:MBEDTLS_ECP_DP_CURVE448:"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080":55:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
+
ECP mod p192 small (more than 192 bits, less limbs than 2 * 192 bits)
depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_ECP_NIST_OPTIM
ecp_fast_mod:MBEDTLS_ECP_DP_SECP192R1:"0100000000000103010000000000010201000000000001010100000000000100"
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index 295fe7f..9cf0ce1 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -1236,6 +1236,66 @@
}
/* END_CASE */
+/* BEGIN_CASE */
+void ecp_write_key(int grp_id, data_t *in_key,
+ int exported_size, int expected_ret)
+{
+ mbedtls_ecp_keypair key;
+ mbedtls_ecp_keypair_init(&key);
+ unsigned char *exported = NULL;
+
+ TEST_EQUAL(mbedtls_ecp_read_key(grp_id, &key, in_key->x, in_key->len), 0);
+
+ TEST_CALLOC(exported, exported_size);
+ TEST_EQUAL(mbedtls_ecp_write_key(&key, exported, exported_size),
+ expected_ret);
+
+ if (expected_ret == 0) {
+ size_t length = (key.grp.nbits + 7) / 8;
+ const unsigned char *key_start = NULL;
+ const unsigned char *zeros_start = NULL;
+ switch (mbedtls_ecp_get_type(&key.grp)) {
+ case MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS:
+ if ((size_t) exported_size < length) {
+ length = exported_size;
+ }
+ key_start = exported + exported_size - length;
+ zeros_start = exported;
+ break;
+ case MBEDTLS_ECP_TYPE_MONTGOMERY:
+ TEST_LE_U(length, exported_size);
+ key_start = exported;
+ zeros_start = exported + length;
+ break;
+ default:
+ TEST_FAIL("Unknown ECP curve type");
+ break;
+ }
+
+ if (length < in_key->len) {
+ /* Shorter output (only possible with Weierstrass keys) */
+ for (size_t i = 0; i < in_key->len - length; i++) {
+ mbedtls_test_set_step(i);
+ TEST_EQUAL(in_key->x[i], 0);
+ }
+ TEST_MEMORY_COMPARE(in_key->x + in_key->len - length, length,
+ key_start, length);
+ } else {
+ TEST_MEMORY_COMPARE(in_key->x, in_key->len,
+ key_start, length);
+ for (size_t i = 0; i < exported_size - length; i++) {
+ mbedtls_test_set_step(i);
+ TEST_EQUAL(zeros_start[i], 0);
+ }
+ }
+ }
+
+exit:
+ mbedtls_ecp_keypair_free(&key);
+ mbedtls_free(exported);
+}
+/* END_CASE */
+
/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS:MBEDTLS_ECP_MONTGOMERY_ENABLED:MBEDTLS_ECP_LIGHT */
void genkey_mx_known_answer(int bits, data_t *seed, data_t *expected)
{
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index 38e4046..c55af03 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -6870,6 +6870,18 @@
depends_on:PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH
derive_key_type:PSA_ALG_PBKDF2_AES_CMAC_PRF_128:"706173737764":"01":"73616c74":PSA_KEY_TYPE_AES:256:"28e288c6345bb5ecf7ca70274208a3ba0f1148b5868537d5e09d3ee6813b1f52"
+PSA key derivation: default params -> AES-128
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_AES
+derive_key_ext:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_AES:128:0:"":PSA_SUCCESS:"3cb25f25faacd57a90434f64d0362f2a"
+
+PSA key derivation: params.flags=1 -> AES-128
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_AES
+derive_key_ext:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_AES:128:1:"":PSA_ERROR_INVALID_ARGUMENT:""
+
+PSA key derivation: params.data non-empty -> AES-128
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_AES
+derive_key_ext:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_AES:128:0:"2a":PSA_ERROR_INVALID_ARGUMENT:""
+
PSA key derivation: invalid type (0)
depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_NONE:128:PSA_ERROR_NOT_SUPPORTED:0
@@ -7419,24 +7431,6 @@
depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_MONTGOMERY_448
generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):448:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_SUCCESS:0
-PSA generate key: RSA, default e
-generate_key_rsa:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:"":PSA_SUCCESS
-
-PSA generate key: RSA, e=3
-generate_key_rsa:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:"03":PSA_SUCCESS
-
-PSA generate key: RSA, e=65537
-generate_key_rsa:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:"010001":PSA_SUCCESS
-
-PSA generate key: RSA, e=513
-generate_key_rsa:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:"0201":PSA_SUCCESS
-
-PSA generate key: RSA, e=1
-generate_key_rsa:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:"01":PSA_ERROR_INVALID_ARGUMENT
-
-PSA generate key: RSA, e=2
-generate_key_rsa:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:"02":PSA_ERROR_INVALID_ARGUMENT
-
PSA generate key: FFDH, 2048 bits, good
depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE:PSA_WANT_DH_RFC7919_2048
generate_key:PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919):2048:PSA_KEY_USAGE_EXPORT:PSA_ALG_FFDH:PSA_SUCCESS:0
@@ -7461,6 +7455,86 @@
depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE
generate_key:PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919):1024:PSA_KEY_USAGE_EXPORT:PSA_ALG_FFDH:PSA_ERROR_NOT_SUPPORTED:0
+PSA generate key ext: RSA, params.flags=1
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:1:"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA generate key ext: RSA, empty e
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:0:"":PSA_SUCCESS
+
+PSA generate key ext: RSA, e=3
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:0:"03":PSA_SUCCESS
+
+PSA generate key ext: RSA, e=3 with leading zeros
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:0:"000003":PSA_SUCCESS
+
+# TODO: currently errors with NOT_SUPPORTED because e is converted to an int
+# and the conversion errors out if there are too many digits without checking
+# for leading zeros. This is a very minor bug. Re-enable this test when this
+# bug is fixed.
+#PSA generate key ext: RSA, e=3 with many leading zeros
+#depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+#generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:0:"0000000000000000000000000000000003":PSA_SUCCESS
+
+PSA generate key ext: RSA, e=513
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:0:"0201":PSA_SUCCESS
+
+PSA generate key ext: RSA, e=65537
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:0:"010001":PSA_SUCCESS
+
+PSA generate key ext: RSA, e=2^31-1
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:INT_MAX>=0x7fffffff
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:0:"7fffffff":PSA_SUCCESS
+
+PSA generate key ext: RSA, e=2^31+3 (too large for built-in RSA)
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE:!MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE:INT_MAX<=0x7fffffff
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:0:"80000003":PSA_ERROR_NOT_SUPPORTED
+
+PSA generate key ext: RSA, e=2^64+3 (too large for built-in RSA)
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE:!MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE:INT_MAX<=0xffffffffffffffff
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:0:"010000000000000003":PSA_ERROR_NOT_SUPPORTED
+
+PSA generate key ext: RSA, e=1
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:0:"01":PSA_ERROR_INVALID_ARGUMENT
+
+PSA generate key ext: RSA, e=0
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:0:"00":PSA_ERROR_INVALID_ARGUMENT
+
+PSA generate key ext: RSA, e=2
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:0:"02":PSA_ERROR_INVALID_ARGUMENT
+
+# Check that with a driver, we reject a custom e as unsupported,
+# as opposed to silently using the default e.
+# When we add proper driver support, remove this test case and remove
+# the dependency on MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE from
+# the positive/invalid_argument test cases.
+PSA generate key ext: RSA, e=3 with driver and no fallback (not yet supported)
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:!MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:0:"03":PSA_ERROR_NOT_SUPPORTED
+
+PSA generate key ext: ECC, flags=0
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_ECDH
+generate_key_ext:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:0:"":PSA_SUCCESS
+
+PSA generate key ext: ECC, flags=1
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_ECDH
+generate_key_ext:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:1:"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA generate key ext: ECC, params.data non-empty
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_ECDH
+generate_key_ext:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:0:"2a":PSA_ERROR_INVALID_ARGUMENT
+
+Key production parameters initializers
+key_production_parameters_init:
+
PSA import persistent key: raw data, 8 bits
depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
persistent_key_load_key_from_storage:"2a":PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:IMPORT_KEY
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 95e7a2d..09874a1 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -1255,6 +1255,84 @@
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+static int rsa_test_e(mbedtls_svc_key_id_t key,
+ size_t bits,
+ const data_t *e_arg)
+{
+ uint8_t *exported = NULL;
+ size_t exported_size =
+ PSA_EXPORT_KEY_OUTPUT_SIZE(PSA_KEY_TYPE_RSA_PUBLIC_KEY, bits);
+ size_t exported_length = SIZE_MAX;
+ int ok = 0;
+
+ TEST_CALLOC(exported, exported_size);
+ PSA_ASSERT(psa_export_public_key(key,
+ exported, exported_size,
+ &exported_length));
+ uint8_t *p = exported;
+ uint8_t *end = exported + exported_length;
+ size_t len;
+ /* RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER } -- e
+ */
+ TEST_EQUAL(0, mbedtls_asn1_get_tag(&p, end, &len,
+ MBEDTLS_ASN1_SEQUENCE |
+ MBEDTLS_ASN1_CONSTRUCTED));
+ TEST_ASSERT(mbedtls_test_asn1_skip_integer(&p, end, bits, bits, 1));
+ TEST_EQUAL(0, mbedtls_asn1_get_tag(&p, end, &len,
+ MBEDTLS_ASN1_INTEGER));
+ if (len >= 1 && p[0] == 0) {
+ ++p;
+ --len;
+ }
+ if (e_arg->len == 0) {
+ TEST_EQUAL(len, 3);
+ TEST_EQUAL(p[0], 1);
+ TEST_EQUAL(p[1], 0);
+ TEST_EQUAL(p[2], 1);
+ } else {
+ const uint8_t *expected = e_arg->x;
+ size_t expected_len = e_arg->len;
+ while (expected_len > 0 && *expected == 0) {
+ ++expected;
+ --expected_len;
+ }
+ TEST_MEMORY_COMPARE(p, len, expected, expected_len);
+ }
+ ok = 1;
+
+exit:
+ mbedtls_free(exported);
+ return ok;
+}
+#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE */
+
+static int setup_key_production_parameters(
+ psa_key_production_parameters_t **params, size_t *params_data_length,
+ int flags_arg, const data_t *params_data)
+{
+ *params_data_length = params_data->len;
+ /* If there are N bytes of padding at the end of
+ * psa_key_production_parameters_t, then it's enough to allocate
+ * MIN(sizeof(psa_key_production_parameters_t),
+ * offsetof(psa_key_production_parameters_t, data) + params_data_length).
+ *
+ * For simplicity, here, we allocate up to N more bytes than necessary.
+ * In practice, the current layout of psa_key_production_parameters_t
+ * makes padding extremely unlikely, so we don't worry about testing
+ * that the library code doesn't try to access these extra N bytes.
+ */
+ *params = mbedtls_calloc(1, sizeof(**params) + *params_data_length);
+ TEST_ASSERT(*params != NULL);
+ (*params)->flags = (uint32_t) flags_arg;
+ memcpy((*params)->data, params_data->x, params_data->len);
+ return 1;
+exit:
+ return 0;
+}
+
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@@ -9255,6 +9333,81 @@
/* END_CASE */
/* BEGIN_CASE */
+void derive_key_ext(int alg_arg,
+ data_t *key_data,
+ data_t *input1,
+ data_t *input2,
+ int key_type_arg, int bits_arg,
+ int flags_arg,
+ data_t *params_data,
+ psa_status_t expected_status,
+ data_t *expected_export)
+{
+ mbedtls_svc_key_id_t base_key = MBEDTLS_SVC_KEY_ID_INIT;
+ mbedtls_svc_key_id_t derived_key = MBEDTLS_SVC_KEY_ID_INIT;
+ const psa_algorithm_t alg = alg_arg;
+ const psa_key_type_t key_type = key_type_arg;
+ const size_t bits = bits_arg;
+ psa_key_production_parameters_t *params = NULL;
+ size_t params_data_length = 0;
+ psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
+ const size_t export_buffer_size =
+ PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, bits);
+ uint8_t *export_buffer = NULL;
+ psa_key_attributes_t base_attributes = PSA_KEY_ATTRIBUTES_INIT;
+ psa_key_attributes_t derived_attributes = PSA_KEY_ATTRIBUTES_INIT;
+ size_t export_length;
+
+ TEST_CALLOC(export_buffer, export_buffer_size);
+ PSA_ASSERT(psa_crypto_init());
+
+ psa_set_key_usage_flags(&base_attributes, PSA_KEY_USAGE_DERIVE);
+ psa_set_key_algorithm(&base_attributes, alg);
+ psa_set_key_type(&base_attributes, PSA_KEY_TYPE_DERIVE);
+ PSA_ASSERT(psa_import_key(&base_attributes, key_data->x, key_data->len,
+ &base_key));
+
+ if (mbedtls_test_psa_setup_key_derivation_wrap(
+ &operation, base_key, alg,
+ input1->x, input1->len,
+ input2->x, input2->len,
+ PSA_KEY_DERIVATION_UNLIMITED_CAPACITY) == 0) {
+ goto exit;
+ }
+
+ psa_set_key_usage_flags(&derived_attributes, PSA_KEY_USAGE_EXPORT);
+ psa_set_key_algorithm(&derived_attributes, 0);
+ psa_set_key_type(&derived_attributes, key_type);
+ psa_set_key_bits(&derived_attributes, bits);
+ if (!setup_key_production_parameters(¶ms, ¶ms_data_length,
+ flags_arg, params_data)) {
+ goto exit;
+ }
+
+ TEST_EQUAL(psa_key_derivation_output_key_ext(&derived_attributes, &operation,
+ params, params_data_length,
+ &derived_key),
+ expected_status);
+
+ if (expected_status == PSA_SUCCESS) {
+ PSA_ASSERT(psa_export_key(derived_key,
+ export_buffer, export_buffer_size,
+ &export_length));
+ TEST_MEMORY_COMPARE(export_buffer, export_length,
+ expected_export->x, expected_export->len);
+ }
+
+exit:
+ mbedtls_free(export_buffer);
+ mbedtls_free(params);
+ psa_key_derivation_abort(&operation);
+ psa_destroy_key(base_key);
+ psa_destroy_key(derived_key);
+ PSA_DONE();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
void derive_key(int alg_arg,
data_t *key_data, data_t *input1, data_t *input2,
int type_arg, int bits_arg,
@@ -9687,71 +9840,57 @@
}
/* END_CASE */
-/* BEGIN_CASE depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN */
-void generate_key_rsa(int bits_arg,
- data_t *e_arg,
+/* BEGIN_CASE */
+void generate_key_ext(int type_arg,
+ int bits_arg,
+ int usage_arg,
+ int alg_arg,
+ int flags_arg,
+ data_t *params_data,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
- psa_key_type_t type = PSA_KEY_TYPE_RSA_KEY_PAIR;
+ psa_key_type_t type = type_arg;
+ psa_key_usage_t usage = usage_arg;
size_t bits = bits_arg;
- psa_key_usage_t usage = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT;
- psa_algorithm_t alg = PSA_ALG_RSA_PKCS1V15_SIGN_RAW;
+ psa_algorithm_t alg = alg_arg;
psa_status_t expected_status = expected_status_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
- uint8_t *exported = NULL;
- size_t exported_size =
- PSA_EXPORT_KEY_OUTPUT_SIZE(PSA_KEY_TYPE_RSA_PUBLIC_KEY, bits);
- size_t exported_length = SIZE_MAX;
- uint8_t *e_read_buffer = NULL;
- int is_default_public_exponent = 0;
- size_t e_read_size = PSA_KEY_DOMAIN_PARAMETERS_SIZE(type, bits);
- size_t e_read_length = SIZE_MAX;
-
- if (e_arg->len == 0 ||
- (e_arg->len == 3 &&
- e_arg->x[0] == 1 && e_arg->x[1] == 0 && e_arg->x[2] == 1)) {
- is_default_public_exponent = 1;
- e_read_size = 0;
- }
- TEST_CALLOC(e_read_buffer, e_read_size);
- TEST_CALLOC(exported, exported_size);
+ psa_key_production_parameters_t *params = NULL;
+ size_t params_data_length = 0;
+ psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, usage);
psa_set_key_algorithm(&attributes, alg);
- PSA_ASSERT(psa_set_key_domain_parameters(&attributes, type,
- e_arg->x, e_arg->len));
+ psa_set_key_type(&attributes, type);
psa_set_key_bits(&attributes, bits);
+ if (!setup_key_production_parameters(¶ms, ¶ms_data_length,
+ flags_arg, params_data)) {
+ goto exit;
+ }
+
/* Generate a key */
- TEST_EQUAL(psa_generate_key(&attributes, &key), expected_status);
+ psa_status_t status = psa_generate_key_ext(&attributes,
+ params, params_data_length,
+ &key);
+
+ TEST_EQUAL(status, expected_status);
if (expected_status != PSA_SUCCESS) {
goto exit;
}
/* Test the key information */
- PSA_ASSERT(psa_get_key_attributes(key, &attributes));
- TEST_EQUAL(psa_get_key_type(&attributes), type);
- TEST_EQUAL(psa_get_key_bits(&attributes), bits);
- psa_status_t status = psa_get_key_domain_parameters(&attributes,
- e_read_buffer, e_read_size,
- &e_read_length);
+ PSA_ASSERT(psa_get_key_attributes(key, &got_attributes));
+ TEST_EQUAL(psa_get_key_type(&got_attributes), type);
+ TEST_EQUAL(psa_get_key_bits(&got_attributes), bits);
-
-#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \
- defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \
- defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
- if (is_default_public_exponent) {
- TEST_EQUAL(e_read_length, 0);
- } else {
- TEST_EQUAL(status, PSA_SUCCESS);
- TEST_MEMORY_COMPARE(e_read_buffer, e_read_length, e_arg->x, e_arg->len);
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+ if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
+ TEST_ASSERT(rsa_test_e(key, bits, params_data));
}
-#else
- (void) is_default_public_exponent;
- TEST_EQUAL(status, PSA_ERROR_NOT_SUPPORTED);
#endif
/* Do something with the key according to its type and permitted usage. */
@@ -9759,49 +9898,27 @@
goto exit;
}
- /* Export the key and check the public exponent. */
- PSA_ASSERT(psa_export_public_key(key,
- exported, exported_size,
- &exported_length));
- {
- uint8_t *p = exported;
- uint8_t *end = exported + exported_length;
- size_t len;
- /* RSAPublicKey ::= SEQUENCE {
- * modulus INTEGER, -- n
- * publicExponent INTEGER } -- e
- */
- TEST_EQUAL(0, mbedtls_asn1_get_tag(&p, end, &len,
- MBEDTLS_ASN1_SEQUENCE |
- MBEDTLS_ASN1_CONSTRUCTED));
- TEST_ASSERT(mbedtls_test_asn1_skip_integer(&p, end, bits, bits, 1));
- TEST_EQUAL(0, mbedtls_asn1_get_tag(&p, end, &len,
- MBEDTLS_ASN1_INTEGER));
- if (len >= 1 && p[0] == 0) {
- ++p;
- --len;
- }
- if (e_arg->len == 0) {
- TEST_EQUAL(len, 3);
- TEST_EQUAL(p[0], 1);
- TEST_EQUAL(p[1], 0);
- TEST_EQUAL(p[2], 1);
- } else {
- TEST_MEMORY_COMPARE(p, len, e_arg->x, e_arg->len);
- }
- }
-
exit:
/*
- * Key attributes may have been returned by psa_get_key_attributes() or
- * set by psa_set_key_domain_parameters() thus reset them as required.
+ * Key attributes may have been returned by psa_get_key_attributes()
+ * thus reset them as required.
*/
- psa_reset_key_attributes(&attributes);
-
+ psa_reset_key_attributes(&got_attributes);
+ mbedtls_free(params);
psa_destroy_key(key);
PSA_DONE();
- mbedtls_free(e_read_buffer);
- mbedtls_free(exported);
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void key_production_parameters_init()
+{
+ psa_key_production_parameters_t init = PSA_KEY_PRODUCTION_PARAMETERS_INIT;
+ psa_key_production_parameters_t zero;
+ memset(&zero, 0, sizeof(zero));
+
+ TEST_EQUAL(init.flags, 0);
+ TEST_EQUAL(zero.flags, 0);
}
/* END_CASE */
diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data
index 69ccf26..385682a 100644
--- a/tests/suites/test_suite_ssl.data
+++ b/tests/suites/test_suite_ssl.data
@@ -3274,14 +3274,17 @@
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 @@
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 0e798f4..d327828 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 @@
/* 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 @@
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 @@
&(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 @@
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 @@
(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 @@
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 @@
MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
}
break;
+
+ default:
+ TEST_FAIL("Unknown scenario.");
}
break;
@@ -3905,7 +3886,7 @@
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 @@
MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
}
break;
+
+ default:
+ TEST_FAIL("Unknown scenario.");
}
break;
@@ -3933,6 +3917,9 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
} 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 @@
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 */