Merge pull request #4587 from TRodziewicz/remove_3DES_ciphersuites
Remove 3DES ciphersuites
diff --git a/ChangeLog.d/cipher-delayed-output.txt b/ChangeLog.d/cipher-delayed-output.txt
new file mode 100644
index 0000000..4ca3a0c
--- /dev/null
+++ b/ChangeLog.d/cipher-delayed-output.txt
@@ -0,0 +1,6 @@
+API changes
+ * For multi-part AEAD operations with the cipher module, calling
+ mbedtls_cipher_finish() is now mandatory. Previously the documentation
+ was unclear on this point, and this function happened to never do
+ anything with the currently implemented AEADs, so in practice it was
+ possible to skip calling it, which is no longer supported.
diff --git a/ChangeLog.d/issue4055.txt b/ChangeLog.d/issue4055.txt
new file mode 100644
index 0000000..e9bd1d1
--- /dev/null
+++ b/ChangeLog.d/issue4055.txt
@@ -0,0 +1,3 @@
+API changes
+ * The function mbedtls_x509write_csr_set_extension() has an extra parameter
+ which allows to mark an extension as critical. Fixes #4055.
diff --git a/ChangeLog.d/issue4286.txt b/ChangeLog.d/issue4286.txt
index 68eb667..813b2ec 100644
--- a/ChangeLog.d/issue4286.txt
+++ b/ChangeLog.d/issue4286.txt
@@ -1,9 +1,9 @@
Removals
* Remove the TLS 1.0, TLS 1.1 and DTLS 1.0 support by removing the following
- deprecated library constants: MBEDTLS_SSL_PROTO_TLS1,
+ library constants: MBEDTLS_SSL_PROTO_TLS1,
MBEDTLS_SSL_PROTO_TLS1_1, MBEDTLS_SSL_CBC_RECORD_SPLITTING,
MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED,
- MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED, MBEDTLS_SSL_RECORD_CHECKING,
+ MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED,
MBEDTLS_SSL_FALLBACK_SCSV, MBEDTLS_SSL_FALLBACK_SCSV_VALUE,
MBEDTLS_SSL_IS_FALLBACK, MBEDTLS_SSL_IS_NOT_FALLBACK, and functions:
mbedtls_ssl_conf_cbc_record_splitting(),
diff --git a/ChangeLog.d/relaxed-psk-semantics.txt b/ChangeLog.d/relaxed-psk-semantics.txt
new file mode 100644
index 0000000..418ff6f
--- /dev/null
+++ b/ChangeLog.d/relaxed-psk-semantics.txt
@@ -0,0 +1,7 @@
+API changes
+ * Modify semantics of `mbedtls_ssl_conf_[opaque_]psk()`:
+ In Mbed TLS 2.X, the API prescribes that later calls overwrite
+ the effect of earlier calls. In Mbed TLS 3.0, calling
+ `mbedtls_ssl_conf_[opaque_]psk()` more than once will fail,
+ leaving the PSK that was configured first intact.
+ Support for more than one PSK may be added in 3.X.
diff --git a/docs/3.0-migration-guide.d/ccm-alt.md b/docs/3.0-migration-guide.d/ccm-alt.md
new file mode 100644
index 0000000..1abac7a
--- /dev/null
+++ b/docs/3.0-migration-guide.d/ccm-alt.md
@@ -0,0 +1,9 @@
+CCM interface changes: impact for alternative implementations
+-------------------------------------------------------------
+
+The CCM interface has changed with the addition of support for
+multi-part operations. Five new API functions have been defined:
+mbedtls_ccm_starts(), mbedtls_ccm_set_lengths(),
+mbedtls_ccm_update_ad(), mbedtls_ccm_update() and mbedtls_ccm_finish().
+Alternative implementations of CCM (`MBEDTLS_CCM_ALT`) have now to
+implement those additional five API functions.
diff --git a/docs/3.0-migration-guide.d/cipher-delayed-output.md b/docs/3.0-migration-guide.d/cipher-delayed-output.md
new file mode 100644
index 0000000..18d3271
--- /dev/null
+++ b/docs/3.0-migration-guide.d/cipher-delayed-output.md
@@ -0,0 +1,15 @@
+Calling `mbedtls_cipher_finish()` is mandatory for all multi-part operations
+----------------------------------------------------------------------------
+
+This only affects people who use the cipher module to perform AEAD operations
+using the multi-part API.
+
+Previously, the documentation didn't state explicitly if it was OK to call
+`mbedtls_cipher_check_tag()` or `mbedtls_cipher_write_tag()` directly after
+the last call to `mbedtls_cipher_update()` - that is, without calling
+`mbedtls_cipher_finish()` in-between. If you code was missing that call,
+please add it and be prepared to get as much as 15 bytes of output.
+
+Currently the output is always 0 bytes, but it may be more when alternative
+implementations of the underlying primitives are in use, or with future
+versions of the library.
diff --git a/docs/3.0-migration-guide.d/csr-add-critical-extension.md b/docs/3.0-migration-guide.d/csr-add-critical-extension.md
new file mode 100644
index 0000000..ebcb343
--- /dev/null
+++ b/docs/3.0-migration-guide.d/csr-add-critical-extension.md
@@ -0,0 +1,9 @@
+Change the API to allow adding critical extensions to CSRs
+------------------------------------------------------------------
+
+This affects applications that call the `mbedtls_x509write_csr_set_extension`
+function.
+
+The API is changed to include the parameter `critical` which allow to mark an
+extension included in a CSR as critical. To get the previous behaviour pass
+`0`.
diff --git a/docs/3.0-migration-guide.d/relaxed-psk-semantics.md b/docs/3.0-migration-guide.d/relaxed-psk-semantics.md
new file mode 100644
index 0000000..6b0e794
--- /dev/null
+++ b/docs/3.0-migration-guide.d/relaxed-psk-semantics.md
@@ -0,0 +1,18 @@
+Relaxed semantics for PSK configuration
+-----------------------------------------------------------------
+
+This affects users which call the PSK configuration APIs
+`mbedtlsl_ssl_conf_psk()` and `mbedtls_ssl_conf_psk_opaque()`
+multiple times on the same SSL configuration.
+
+In Mbed TLS 2.x, users would observe later calls overwriting
+the effect of earlier calls, with the prevailing PSK being
+the one that has been configured last. In Mbed TLS 3.0,
+calling `mbedtls_ssl_conf_[opaque_]psk()` multiple times
+will return an error, leaving the first PSK intact.
+
+To achieve equivalent functionality when migrating to Mbed TLS 3.0,
+users calling `mbedtls_ssl_conf_[opaque_]psk()` multiple times should
+remove all but the last call, so that only one call to _either_
+`mbedtls_ssl_conf_psk()` _or_ `mbedtls_ssl_conf_psk_opaque()`
+remains.
diff --git a/include/mbedtls/ccm.h b/include/mbedtls/ccm.h
index f63e61b..ea03a35 100644
--- a/include/mbedtls/ccm.h
+++ b/include/mbedtls/ccm.h
@@ -55,6 +55,11 @@
#include "mbedtls/cipher.h"
+#define MBEDTLS_CCM_DECRYPT 0
+#define MBEDTLS_CCM_ENCRYPT 1
+#define MBEDTLS_CCM_STAR_DECRYPT 2
+#define MBEDTLS_CCM_STAR_ENCRYPT 3
+
#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */
#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */
@@ -133,10 +138,10 @@
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
- * \param add The additional data field. If \p add_len is greater than
- * zero, \p add must be a readable buffer of at least that
+ * \param ad The additional data field. If \p ad_len is greater than
+ * zero, \p ad must be a readable buffer of at least that
* length.
- * \param add_len The length of additional data in Bytes.
+ * \param ad_len The length of additional data in Bytes.
* This must be less than `2^16 - 2^8`.
* \param input The buffer holding the input data. If \p length is greater
* than zero, \p input must be a readable buffer of at least
@@ -154,7 +159,7 @@
*/
int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
- const unsigned char *add, size_t add_len,
+ const unsigned char *ad, size_t ad_len,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len );
@@ -179,9 +184,9 @@
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
- * \param add The additional data field. This must be a readable buffer of
- * at least \p add_len Bytes.
- * \param add_len The length of additional data in Bytes.
+ * \param ad The additional data field. This must be a readable buffer of
+ * at least \p ad_len Bytes.
+ * \param ad_len The length of additional data in Bytes.
* This must be less than 2^16 - 2^8.
* \param input The buffer holding the input data. If \p length is greater
* than zero, \p input must be a readable buffer of at least
@@ -202,7 +207,7 @@
*/
int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
- const unsigned char *add, size_t add_len,
+ const unsigned char *ad, size_t ad_len,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len );
@@ -218,9 +223,9 @@
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
- * \param add The additional data field. This must be a readable buffer
- * of at least that \p add_len Bytes..
- * \param add_len The length of additional data in Bytes.
+ * \param ad The additional data field. This must be a readable buffer
+ * of at least that \p ad_len Bytes..
+ * \param ad_len The length of additional data in Bytes.
* This must be less than 2^16 - 2^8.
* \param input The buffer holding the input data. If \p length is greater
* than zero, \p input must be a readable buffer of at least
@@ -239,7 +244,7 @@
*/
int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
- const unsigned char *add, size_t add_len,
+ const unsigned char *ad, size_t ad_len,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len );
@@ -260,9 +265,9 @@
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
- * \param add The additional data field. This must be a readable buffer of
- * at least that \p add_len Bytes.
- * \param add_len The length of additional data in Bytes.
+ * \param ad The additional data field. This must be a readable buffer of
+ * at least that \p ad_len Bytes.
+ * \param ad_len The length of additional data in Bytes.
* This must be less than 2^16 - 2^8.
* \param input The buffer holding the input data. If \p length is greater
* than zero, \p input must be a readable buffer of at least
@@ -284,10 +289,208 @@
*/
int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
- const unsigned char *add, size_t add_len,
+ const unsigned char *ad, size_t ad_len,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len );
+/**
+ * \brief This function starts a CCM encryption or decryption
+ * operation.
+ *
+ * This function and mbedtls_ccm_set_lengths() must be called
+ * before calling mbedtls_ccm_update_ad() or
+ * mbedtls_ccm_update(). This function can be called before
+ * or after mbedtls_ccm_set_lengths().
+ *
+ * \note This function is not implemented in Mbed TLS yet.
+ *
+ * \param ctx The CCM context. This must be initialized.
+ * \param mode The operation to perform: #MBEDTLS_CCM_ENCRYPT or
+ * #MBEDTLS_CCM_DECRYPT or #MBEDTLS_CCM_STAR_ENCRYPT or
+ * #MBEDTLS_CCM_STAR_DECRYPT.
+ * \param iv The initialization vector. This must be a readable buffer
+ * of at least \p iv_len Bytes.
+ * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
+ * or 13. The length L of the message length field is
+ * 15 - \p iv_len.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure:
+ * \p ctx is in an invalid state,
+ * \p mode is invalid,
+ * \p iv_len is invalid (lower than \c 7 or greater than
+ * \c 13).
+ */
+int mbedtls_ccm_starts( mbedtls_ccm_context *ctx,
+ int mode,
+ const unsigned char *iv,
+ size_t iv_len );
+
+/**
+ * \brief This function declares the lengths of the message
+ * and additional data for a CCM encryption or decryption
+ * operation.
+ *
+ * This function and mbedtls_ccm_starts() must be called
+ * before calling mbedtls_ccm_update_ad() or
+ * mbedtls_ccm_update(). This function can be called before
+ * or after mbedtls_ccm_starts().
+ *
+ * \note This function is not implemented in Mbed TLS yet.
+ *
+ * \param ctx The CCM context. This must be initialized.
+ * \param total_ad_len The total length of additional data in bytes.
+ * This must be less than `2^16 - 2^8`.
+ * \param plaintext_len The length in bytes of the plaintext to encrypt or
+ * result of the decryption (thus not encompassing the
+ * additional data that are not encrypted).
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure:
+ * \p ctx is in an invalid state,
+ * \p total_ad_len is greater than \c 0xFF00.
+ */
+int mbedtls_ccm_set_lengths( mbedtls_ccm_context *ctx,
+ size_t total_ad_len,
+ size_t plaintext_len );
+
+/**
+ * \brief This function feeds an input buffer as associated data
+ * (authenticated but not encrypted data) in a CCM
+ * encryption or decryption operation.
+ *
+ * You may call this function zero, one or more times
+ * to pass successive parts of the additional data. The
+ * lengths \p ad_len of the data parts should eventually add
+ * up exactly to the total length of additional data
+ * \c total_ad_len passed to mbedtls_ccm_set_lengths(). You
+ * may not call this function after calling
+ * mbedtls_ccm_update().
+ *
+ * \note This function is not implemented in Mbed TLS yet.
+ *
+ * \param ctx The CCM context. This must have been started with
+ * mbedtls_ccm_starts(), the lengths of the message and
+ * additional data must have been declared with
+ * mbedtls_ccm_set_lengths() and this must not have yet
+ * received any input with mbedtls_ccm_update().
+ * \param ad The buffer holding the additional data, or \c NULL
+ * if \p ad_len is \c 0.
+ * \param ad_len The length of the additional data. If \c 0,
+ * \p ad may be \c NULL.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure:
+ * \p ctx is in an invalid state,
+ * total input length too long.
+ */
+int mbedtls_ccm_update_ad( mbedtls_ccm_context *ctx,
+ const unsigned char *ad,
+ size_t ad_len );
+
+/**
+ * \brief This function feeds an input buffer into an ongoing CCM
+ * encryption or decryption operation.
+ *
+ * You may call this function zero, one or more times
+ * to pass successive parts of the input: the plaintext to
+ * encrypt, or the ciphertext (not including the tag) to
+ * decrypt. After the last part of the input, call
+ * mbedtls_ccm_finish(). The lengths \p input_len of the
+ * data parts should eventually add up exactly to the
+ * plaintext length \c plaintext_len passed to
+ * mbedtls_ccm_set_lengths().
+ *
+ * This function may produce output in one of the following
+ * ways:
+ * - Immediate output: the output length is always equal
+ * to the input length.
+ * - Buffered output: except for the last part of input data,
+ * the output consists of a whole number of 16-byte blocks.
+ * If the total input length so far (not including
+ * associated data) is 16 \* *B* + *A* with *A* < 16 then
+ * the total output length is 16 \* *B*.
+ * For the last part of input data, the output length is
+ * equal to the input length plus the number of bytes (*A*)
+ * buffered in the previous call to the function (if any).
+ * The function uses the plaintext length
+ * \c plaintext_len passed to mbedtls_ccm_set_lengths()
+ * to detect the last part of input data.
+ *
+ * In particular:
+ * - It is always correct to call this function with
+ * \p output_size >= \p input_len + 15.
+ * - If \p input_len is a multiple of 16 for all the calls
+ * to this function during an operation (not necessary for
+ * the last one) then it is correct to use \p output_size
+ * =\p input_len.
+ *
+ * \note This function is not implemented in Mbed TLS yet.
+ *
+ * \param ctx The CCM context. This must have been started with
+ * mbedtls_ccm_starts() and the lengths of the message and
+ * additional data must have been declared with
+ * mbedtls_ccm_set_lengths().
+ * \param input The buffer holding the input data. If \p input_len
+ * is greater than zero, this must be a readable buffer
+ * of at least \p input_len bytes.
+ * \param input_len The length of the input data in bytes.
+ * \param output The buffer for the output data. If \p output_size
+ * is greater than zero, this must be a writable buffer of
+ * at least \p output_size bytes.
+ * \param output_size The size of the output buffer in bytes.
+ * See the function description regarding the output size.
+ * \param output_len On success, \p *output_len contains the actual
+ * length of the output written in \p output.
+ * On failure, the content of \p *output_len is
+ * unspecified.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure:
+ * \p ctx is in an invalid state,
+ * total input length too long,
+ * or \p output_size too small.
+ */
+int mbedtls_ccm_update( mbedtls_ccm_context *ctx,
+ const unsigned char *input, size_t input_len,
+ unsigned char *output, size_t output_size,
+ size_t *output_len );
+
+/**
+ * \brief This function finishes the CCM operation and generates
+ * the authentication tag.
+ *
+ * It wraps up the CCM stream, and generates the
+ * tag. The tag can have a maximum length of 16 Bytes.
+ *
+ * \note This function is not implemented in Mbed TLS yet.
+ *
+ * \param ctx The CCM context. This must have been started with
+ * mbedtls_ccm_starts() and the lengths of the message and
+ * additional data must have been declared with
+ * mbedtls_ccm_set_lengths().
+ * \param tag The buffer for holding the tag. If \p tag_len is greater
+ * than zero, this must be a writable buffer of at least \p
+ * tag_len Bytes.
+ * \param tag_len The length of the tag to generate in Bytes:
+ * 4, 6, 8, 10, 12, 14 or 16.
+ * For CCM*, zero is also valid.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure:
+ * \p ctx is in an invalid state,
+ * invalid value of \p tag_len,
+ * the total amount of additional data passed to
+ * mbedtls_ccm_update_ad() was lower than the total length of
+ * additional data \c total_ad_len passed to
+ * mbedtls_ccm_set_lengths(),
+ * the total amount of input data passed to
+ * mbedtls_ccm_update() was lower than the plaintext length
+ * \c plaintext_len passed to mbedtls_ccm_set_lengths().
+ */
+int mbedtls_ccm_finish( mbedtls_ccm_context *ctx,
+ unsigned char *tag, size_t tag_len );
+
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/**
* \brief The CCM checkup routine.
diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h
index ffb20a6..06a29e7 100644
--- a/include/mbedtls/cipher.h
+++ b/include/mbedtls/cipher.h
@@ -437,10 +437,23 @@
/**
- * \brief This function initializes a cipher context for
+ * \brief This function prepares a cipher context for
* use with the given cipher primitive.
*
- * \param ctx The context to initialize. This must be initialized.
+ * \note After calling this function, you should call
+ * mbedtls_cipher_setkey() and, if the mode uses padding,
+ * mbedtls_cipher_set_padding_mode(), then for each
+ * message to encrypt or decrypt with this key, either:
+ * - mbedtls_cipher_crypt() for one-shot processing with
+ * non-AEAD modes;
+ * - mbedtls_cipher_auth_encrypt_ext() or
+ * mbedtls_cipher_auth_decrypt_ext() for one-shot
+ * processing with AEAD modes or NIST_KW;
+ * - for multi-part processing, see the documentation of
+ * mbedtls_cipher_reset().
+ *
+ * \param ctx The context to prepare. This must be initialized by
+ * a call to mbedtls_cipher_init() first.
* \param cipher_info The cipher to use.
*
* \return \c 0 on success.
@@ -448,10 +461,6 @@
* parameter-verification failure.
* \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the
* cipher-specific context fails.
- *
- * \internal Currently, the function also clears the structure.
- * In future versions, the caller will be required to call
- * mbedtls_cipher_init() on the structure first.
*/
int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx,
const mbedtls_cipher_info_t *cipher_info );
@@ -687,7 +696,30 @@
/**
* \brief This function resets the cipher state.
*
- * \param ctx The generic cipher context. This must be initialized.
+ * \note With non-AEAD ciphers, the order of calls for each message
+ * is as follows:
+ * 1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce.
+ * 2. mbedtls_cipher_reset()
+ * 3. mbedtls_cipher_update() one or more times
+ * 4. mbedtls_cipher_finish()
+ * .
+ * This sequence can be repeated to encrypt or decrypt multiple
+ * messages with the same key.
+ *
+ * \note With AEAD ciphers, the order of calls for each message
+ * is as follows:
+ * 1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce.
+ * 2. mbedtls_cipher_reset()
+ * 3. mbedtls_cipher_update_ad()
+ * 4. mbedtls_cipher_update() one or more times
+ * 5. mbedtls_cipher_finish()
+ * 6. mbedtls_cipher_check_tag() (for decryption) or
+ * mbedtls_cipher_write_tag() (for encryption).
+ * .
+ * This sequence can be repeated to encrypt or decrypt multiple
+ * messages with the same key.
+ *
+ * \param ctx The generic cipher context. This must be bound to a key.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 6a908f2..cf5ab8e 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -2712,8 +2712,14 @@
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
/**
- * \brief Configure a pre-shared key (PSK) and identity
- * to be used in PSK-based ciphersuites.
+ * \brief Configure pre-shared keys (PSKs) and their
+ * identities to be used in PSK-based ciphersuites.
+ *
+ * Only one PSK can be registered, through either
+ * mbedtls_ssl_conf_psk() or mbedtls_ssl_conf_psk_opaque().
+ * If you attempt to register more than one PSK, this function
+ * fails, though this may change in future versions, which
+ * may add support for multiple PSKs.
*
* \note This is mainly useful for clients. Servers will usually
* want to use \c mbedtls_ssl_conf_psk_cb() instead.
@@ -2721,13 +2727,6 @@
* \note A PSK set by \c mbedtls_ssl_set_hs_psk() in the PSK callback
* takes precedence over a PSK configured by this function.
*
- * \warning Currently, clients can only register a single pre-shared key.
- * Calling this function or mbedtls_ssl_conf_psk_opaque() more
- * than once will overwrite values configured in previous calls.
- * Support for setting multiple PSKs on clients and selecting
- * one based on the identity hint is not a planned feature,
- * but feedback is welcomed.
- *
* \param conf The SSL configuration to register the PSK with.
* \param psk The pointer to the pre-shared key to use.
* \param psk_len The length of the pre-shared key in bytes.
@@ -2740,7 +2739,9 @@
* of the SSL configuration.
*
* \return \c 0 if successful.
- * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure.
+ * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no more PSKs
+ * can be configured. In this case, the old PSK(s) remain intact.
+ * \return Another negative error code on other kinds of failure.
*/
int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf,
const unsigned char *psk, size_t psk_len,
@@ -2748,8 +2749,14 @@
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/**
- * \brief Configure an opaque pre-shared key (PSK) and identity
- * to be used in PSK-based ciphersuites.
+ * \brief Configure one or more opaque pre-shared keys (PSKs) and
+ * their identities to be used in PSK-based ciphersuites.
+ *
+ * Only one PSK can be registered, through either
+ * mbedtls_ssl_conf_psk() or mbedtls_ssl_conf_psk_opaque().
+ * If you attempt to register more than one PSK, this function
+ * fails, though this may change in future versions, which
+ * may add support for multiple PSKs.
*
* \note This is mainly useful for clients. Servers will usually
* want to use \c mbedtls_ssl_conf_psk_cb() instead.
@@ -2758,13 +2765,6 @@
* the PSK callback takes precedence over an opaque PSK
* configured by this function.
*
- * \warning Currently, clients can only register a single pre-shared key.
- * Calling this function or mbedtls_ssl_conf_psk() more than
- * once will overwrite values configured in previous calls.
- * Support for setting multiple PSKs on clients and selecting
- * one based on the identity hint is not a planned feature,
- * but feedback is welcomed.
- *
* \param conf The SSL configuration to register the PSK with.
* \param psk The identifier of the key slot holding the PSK.
* Until \p conf is destroyed or this function is successfully
@@ -2781,7 +2781,9 @@
* SSL configuration.
*
* \return \c 0 if successful.
- * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure.
+ * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no more PSKs
+ * can be configured. In this case, the old PSK(s) remain intact.
+ * \return Another negative error code on other kinds of failure.
*/
int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf,
psa_key_id_t psk,
diff --git a/include/mbedtls/x509_csr.h b/include/mbedtls/x509_csr.h
index 07a3717..4b8564c 100644
--- a/include/mbedtls/x509_csr.h
+++ b/include/mbedtls/x509_csr.h
@@ -235,6 +235,7 @@
* \param ctx CSR context to use
* \param oid OID of the extension
* \param oid_len length of the OID
+ * \param critical Set to 1 to mark the extension as critical, 0 otherwise.
* \param val value of the extension OCTET STRING
* \param val_len length of the value data
*
@@ -242,6 +243,7 @@
*/
int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx,
const char *oid, size_t oid_len,
+ int critical,
const unsigned char *val, size_t val_len );
/**
diff --git a/library/nist_kw.c b/library/nist_kw.c
index 04829a0..5054ca2 100644
--- a/library/nist_kw.c
+++ b/library/nist_kw.c
@@ -189,8 +189,6 @@
uint64_t t = 0;
unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
- unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
- unsigned char *A = output;
*out_len = 0;
/*
@@ -266,6 +264,9 @@
}
else
{
+ unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
+ unsigned char *A = output;
+
/*
* Do the wrapping function W, as defined in RFC 3394 section 2.2.1
*/
@@ -329,7 +330,7 @@
uint64_t t = 0;
unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
- unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
+ unsigned char *R = NULL;
*out_len = 0;
if( semiblocks < MIN_SEMIBLOCKS_COUNT )
@@ -339,6 +340,7 @@
memcpy( A, input, KW_SEMIBLOCK_LENGTH );
memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH );
+ R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
/* Calculate intermediate values */
for( t = s; t >= 1; t-- )
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index a7e5b4c..342832f 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -3721,6 +3721,19 @@
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+static int ssl_conf_psk_is_configured( mbedtls_ssl_config const *conf )
+{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( !mbedtls_svc_key_id_is_null( conf->psk_opaque ) )
+ return( 1 );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+ if( conf->psk != NULL )
+ return( 1 );
+
+ return( 0 );
+}
+
static void ssl_conf_remove_psk( mbedtls_ssl_config *conf )
{
/* Remove reference to existing PSK, if any. */
@@ -3786,8 +3799,10 @@
const unsigned char *psk_identity, size_t psk_identity_len )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- /* Remove opaque/raw PSK + PSK Identity */
- ssl_conf_remove_psk( conf );
+
+ /* We currently only support one PSK, raw or opaque. */
+ if( ssl_conf_psk_is_configured( conf ) )
+ return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
/* Check and set raw PSK */
if( psk == NULL )
@@ -3855,8 +3870,10 @@
size_t psk_identity_len )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- /* Clear opaque/raw PSK + PSK Identity, if present. */
- ssl_conf_remove_psk( conf );
+
+ /* We currently only support one PSK, raw or opaque. */
+ if( ssl_conf_psk_is_configured( conf ) )
+ return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
/* Check and set opaque PSK */
if( mbedtls_svc_key_id_is_null( psk ) )
diff --git a/library/x509write_csr.c b/library/x509write_csr.c
index afda950..9f0ad93 100644
--- a/library/x509write_csr.c
+++ b/library/x509write_csr.c
@@ -83,10 +83,11 @@
int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx,
const char *oid, size_t oid_len,
+ int critical,
const unsigned char *val, size_t val_len )
{
return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
- 0, val, val_len );
+ critical, val, val_len );
}
int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage )
@@ -103,7 +104,7 @@
ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
- c, (size_t)ret );
+ 0, c, (size_t)ret );
if( ret != 0 )
return( ret );
@@ -125,7 +126,7 @@
ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
- c, (size_t)ret );
+ 0, c, (size_t)ret );
if( ret != 0 )
return( ret );
diff --git a/tests/include/test/macros.h b/tests/include/test/macros.h
index 450bc2c..b7b6e8f 100644
--- a/tests/include/test/macros.h
+++ b/tests/include/test/macros.h
@@ -282,38 +282,6 @@
#define TEST_VALID_PARAM( TEST ) \
TEST_ASSERT( ( TEST, 1 ) );
-/** Allocate memory dynamically and fail the test case if this fails.
- *
- * You must set \p pointer to \c NULL before calling this macro and
- * put `mbedtls_free( pointer )` in the test's cleanup code.
- *
- * If \p length is zero, the resulting \p pointer will be \c NULL.
- * This is usually what we want in tests since API functions are
- * supposed to accept null pointers when a buffer size is zero.
- *
- * This macro expands to an instruction, not an expression.
- * It may jump to the \c exit label.
- *
- * \param pointer An lvalue where the address of the allocated buffer
- * will be stored.
- * This expression may be evaluated multiple times.
- * \param length Number of elements to allocate.
- * This expression may be evaluated multiple times.
- *
- */
-#define ASSERT_ALLOC( pointer, length ) \
- do \
- { \
- TEST_ASSERT( ( pointer ) == NULL ); \
- if( ( length ) != 0 ) \
- { \
- ( pointer ) = mbedtls_calloc( sizeof( *( pointer ) ), \
- ( length ) ); \
- TEST_ASSERT( ( pointer ) != NULL ); \
- } \
- } \
- while( 0 )
-
#define TEST_HELPER_ASSERT(a) if( !( a ) ) \
{ \
mbedtls_fprintf( stderr, "Assertion Failed at %s:%d - %s\n", \
diff --git a/tests/suites/test_suite_pkparse.data b/tests/suites/test_suite_pkparse.data
index 6a0b9b5..1f73aac 100644
--- a/tests/suites/test_suite_pkparse.data
+++ b/tests/suites/test_suite_pkparse.data
@@ -989,7 +989,7 @@
pk_parse_public_keyfile_ec:"data_files/ec_bp512_pub.pem":0
Parse EC Key #1 (SEC1 DER)
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED
pk_parse_keyfile_ec:"data_files/ec_prv.sec1.der":"NULL":0
Parse EC Key #2 (SEC1 PEM)
@@ -1005,15 +1005,15 @@
pk_parse_keyfile_ec:"data_files/ec_prv.pk8.der":"NULL":0
Parse EC Key #4a (PKCS8 DER, no public key)
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
pk_parse_keyfile_ec:"data_files/ec_prv.pk8nopub.der":"NULL":0
Parse EC Key #4b (PKCS8 DER, no public key, with parameters)
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
pk_parse_keyfile_ec:"data_files/ec_prv.pk8nopubparam.der":"NULL":0
Parse EC Key #4c (PKCS8 DER, with parameters)
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
pk_parse_keyfile_ec:"data_files/ec_prv.pk8param.der":"NULL":0
Parse EC Key #5 (PKCS8 PEM)
@@ -1069,7 +1069,7 @@
pk_parse_keyfile_ec:"data_files/ec_bp512_prv.pem":"NULL":0
Parse EC Key #15 (SEC1 DER, secp256k1, SpecifiedECDomain)
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256K1_ENABLED:MBEDTLS_PK_PARSE_EC_EXTENDED
+depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256K1_ENABLED:MBEDTLS_PK_PARSE_EC_EXTENDED
pk_parse_keyfile_ec:"data_files/ec_prv.specdom.der":"NULL":0
Key ASN1 (No data)
diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data
index ab00130..141f672 100644
--- a/tests/suites/test_suite_ssl.data
+++ b/tests/suites/test_suite_ssl.data
@@ -1,3 +1,15 @@
+Attempt to register multiple PSKs
+test_multiple_psks:
+
+Attempt to register multiple PSKS, incl. opaque PSK, #0
+test_multiple_psks_opaque:0
+
+Attempt to register multiple PSKs, incl. opaque PSK, #1
+test_multiple_psks_opaque:1
+
+Attempt to register multiple PSKs, incl. opaque PSK, #2
+test_multiple_psks_opaque:2
+
Test calback buffer sanity
test_callback_buffer_sanity:
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index d9261d1..16a9d9e 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -8,6 +8,8 @@
#include <ssl_tls13_keys.h>
#include "test/certs.h"
+#include <psa/crypto.h>
+
#include <ssl_invasive.h>
#include <test/constant_flow.h>
@@ -4535,3 +4537,109 @@
mbedtls_free( src );
}
/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+void test_multiple_psks()
+{
+ unsigned char psk0[10] = { 0 };
+ unsigned char psk0_identity[] = { 'f', 'o', 'o' };
+
+ unsigned char psk1[10] = { 0 };
+ unsigned char psk1_identity[] = { 'b', 'a', 'r' };
+
+ mbedtls_ssl_config conf;
+
+ mbedtls_ssl_config_init( &conf );
+
+ TEST_ASSERT( mbedtls_ssl_conf_psk( &conf,
+ psk0, sizeof( psk0 ),
+ psk0_identity, sizeof( psk0_identity ) ) == 0 );
+ TEST_ASSERT( mbedtls_ssl_conf_psk( &conf,
+ psk1, sizeof( psk1 ),
+ psk1_identity, sizeof( psk1_identity ) ) ==
+ MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+
+exit:
+
+ mbedtls_ssl_config_free( &conf );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED:MBEDTLS_USE_PSA_CRYPTO */
+void test_multiple_psks_opaque( int mode )
+{
+ /*
+ * Mode 0: Raw PSK, then opaque PSK
+ * Mode 1: Opaque PSK, then raw PSK
+ * Mode 2: 2x opaque PSK
+ */
+
+ unsigned char psk0_raw[10] = { 0 };
+ unsigned char psk0_raw_identity[] = { 'f', 'o', 'o' };
+
+ psa_key_id_t psk0_opaque = (psa_key_id_t) 1;
+ unsigned char psk0_opaque_identity[] = { 'f', 'o', 'o' };
+
+ unsigned char psk1_raw[10] = { 0 };
+ unsigned char psk1_raw_identity[] = { 'b', 'a', 'r' };
+
+ psa_key_id_t psk1_opaque = (psa_key_id_t) 2;
+ unsigned char psk1_opaque_identity[] = { 'b', 'a', 'r' };
+
+ mbedtls_ssl_config conf;
+
+ USE_PSA_INIT( );
+ mbedtls_ssl_config_init( &conf );
+
+ switch( mode )
+ {
+ case 0:
+
+ TEST_ASSERT( mbedtls_ssl_conf_psk( &conf,
+ psk0_raw, sizeof( psk0_raw ),
+ psk0_raw_identity, sizeof( psk0_raw_identity ) )
+ == 0 );
+ TEST_ASSERT( mbedtls_ssl_conf_psk_opaque( &conf,
+ psk1_opaque,
+ psk1_opaque_identity, sizeof( psk1_opaque_identity ) )
+ == MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ break;
+
+ case 1:
+
+ TEST_ASSERT( mbedtls_ssl_conf_psk_opaque( &conf,
+ psk0_opaque,
+ psk0_opaque_identity, sizeof( psk0_opaque_identity ) )
+ == 0 );
+ TEST_ASSERT( mbedtls_ssl_conf_psk( &conf,
+ psk1_raw, sizeof( psk1_raw ),
+ psk1_raw_identity, sizeof( psk1_raw_identity ) )
+ == MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+
+ break;
+
+ case 2:
+
+ TEST_ASSERT( mbedtls_ssl_conf_psk_opaque( &conf,
+ psk0_opaque,
+ psk0_opaque_identity, sizeof( psk0_opaque_identity ) )
+ == 0 );
+ TEST_ASSERT( mbedtls_ssl_conf_psk_opaque( &conf,
+ psk1_opaque,
+ psk1_opaque_identity, sizeof( psk1_opaque_identity ) )
+ == MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+
+ break;
+
+ default:
+ TEST_ASSERT( 0 );
+ break;
+ }
+
+exit:
+
+ mbedtls_ssl_config_free( &conf );
+ USE_PSA_DONE( );
+
+}
+/* END_CASE */