Merge pull request #8859 from Patater/dev/Patater/import-mbed-tls-and-crypto

Import Mbed TLS v2.15.0 with Mbed Crypto
pull/8863/head
Martin Kojtal 2018-11-24 21:35:19 +01:00 committed by GitHub
commit 860e4befd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
89 changed files with 18022 additions and 1331 deletions

View File

@ -1 +1,2 @@
mbedtls-2.13.1 mbedtls-2.15.0
mbedcrypto-0.1.0b

View File

@ -27,20 +27,39 @@
# #
# Set the mbed TLS release to import (this can/should be edited before import) # Set the mbed TLS release to import (this can/should be edited before import)
MBED_TLS_RELEASE ?= mbedtls-2.13.1 MBED_TLS_RELEASE ?= mbedtls-2.15.0
# Translate between mbed TLS namespace and mbed namespace # Translate between mbed TLS namespace and mbed namespace
TARGET_PREFIX:=../ TARGET_PREFIX:=../
TARGET_PREFIX_CRYPTO:=../mbed-crypto/
TARGET_SRC:=$(TARGET_PREFIX)src TARGET_SRC:=$(TARGET_PREFIX)src
TARGET_INC:=$(TARGET_PREFIX)inc TARGET_INC:=$(TARGET_PREFIX)inc
TARGET_TESTS:=$(TARGET_PREFIX)TESTS TARGET_TESTS:=$(TARGET_PREFIX)TESTS
# New folder structure is introduced here for targets with Secured-Partition-Environment
# and Non-Secured-Partition-Environment, below documentation for each folder:
# COMPONENT_PSA_SRV_IMPL - include secure service business logic implementation
# code. For example Mbed Crypto or secure time core logic
TARGET_SRV_IMPL:=$(TARGET_PREFIX_CRYPTO)/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL
# COMPONENT_SPE - include code that compiles ONLY to secure image and never
# compiles to non-secure image
TARGET_SPE:=$(TARGET_PREFIX_CRYPTO)/platform/TARGET_PSA/COMPONENT_SPE
# The folder contain specific target implementation using hardware.
TARGET_PSA_DRIVERS:=$(TARGET_PREFIX_CRYPTO)/targets
# COMPONENT_NSPE - include code that compiles ONLY to non-secure image and
# never compiles to secure image
TARGET_NSPE:=$(TARGET_SRV_IMPL)/COMPONENT_NSPE
# mbed TLS source directory - hidden from mbed via TARGET_IGNORE # mbed TLS source directory - hidden from mbed via TARGET_IGNORE
MBED_TLS_URL:=git@github.com:ARMmbed/mbedtls-restricted.git MBED_TLS_URL:=git@github.com:ARMmbed/mbedtls-restricted.git
MBED_TLS_DIR:=TARGET_IGNORE/mbedtls MBED_TLS_DIR:=TARGET_IGNORE/mbedtls
MBED_TLS_API:=$(MBED_TLS_DIR)/include/mbedtls MBED_TLS_API:=$(MBED_TLS_DIR)/include/mbedtls
MBED_TLS_GIT_CFG=$(MBED_TLS_DIR)/.git/config MBED_TLS_GIT_CFG=$(MBED_TLS_DIR)/.git/config
# Mbed Crypto directory - hidden from mbed via TARGET_IGNORE
MBED_CRYPTO_DIR:=$(MBED_TLS_DIR)/crypto
MBED_CRYPTO_API:=$(MBED_CRYPTO_DIR)/include/psa
.PHONY: all deploy deploy-tests rsync mbedtls clean update .PHONY: all deploy deploy-tests rsync mbedtls clean update
all: mbedtls all: mbedtls
@ -62,6 +81,23 @@ rsync:
cp $(MBED_TLS_DIR)/LICENSE $(TARGET_PREFIX) cp $(MBED_TLS_DIR)/LICENSE $(TARGET_PREFIX)
cp $(MBED_TLS_DIR)/apache-2.0.txt $(TARGET_PREFIX) cp $(MBED_TLS_DIR)/apache-2.0.txt $(TARGET_PREFIX)
# #
# Create Mbed Crypto target folder
mkdir -p $(TARGET_PREFIX_CRYPTO)
#
# Copying Mbed Crypto into Mbed OS..
rm -rf $(TARGET_SRV_IMPL)
rm -rf $(TARGET_SPE)
mkdir -p $(TARGET_SRV_IMPL)
mkdir -p $(TARGET_SPE)
mkdir -p $(TARGET_NSPE)
mkdir -p $(TARGET_PSA_DRIVERS)
rsync -a --delete --exclude='crypto_struct.h' $(MBED_CRYPTO_API) $(TARGET_INC)
rsync -a --delete $(MBED_CRYPTO_API)/crypto_struct.h $(TARGET_NSPE)
rsync -a --delete $(MBED_CRYPTO_API)/crypto_struct.h $(TARGET_SPE)/crypto_struct_spe.h
rsync -a --delete $(MBED_CRYPTO_DIR)/library/psa_*.c $(TARGET_SRV_IMPL)
rsync -a --delete $(MBED_CRYPTO_DIR)/library/psa_*.h $(TARGET_SRV_IMPL)
deploy: rsync deploy: rsync
# #
@ -92,8 +128,14 @@ update: $(MBED_TLS_GIT_CFG) $(MBED_TLS_HA_GIT_CFG)
# Checking out the required release # Checking out the required release
git -C $(MBED_TLS_DIR) checkout $(MBED_TLS_RELEASE) git -C $(MBED_TLS_DIR) checkout $(MBED_TLS_RELEASE)
# #
# Update and checkout git submodules
git -C $(MBED_TLS_DIR) submodule update --init --recursive
#
# Updating checked out version tag # Updating checked out version tag
echo $(MBED_TLS_RELEASE) > $(TARGET_PREFIX)VERSION.txt echo $(MBED_TLS_RELEASE) > $(TARGET_PREFIX)VERSION.txt
#
# Updating Mbed Crypto checked out version tag
git -C $(MBED_CRYPTO_DIR) describe --tags --abbrev=12 --dirty --always >> $(TARGET_PREFIX)VERSION.txt
$(MBED_TLS_GIT_CFG): $(MBED_TLS_GIT_CFG):
rm -rf $(MBED_TLS_DIR) rm -rf $(MBED_TLS_DIR)
@ -107,4 +149,5 @@ clean:
rm -rf $(TARGET_SRC) rm -rf $(TARGET_SRC)
rm -rf $(TARGET_INC) rm -rf $(TARGET_INC)
rm -rf $(MBED_TLS_DIR) rm -rf $(MBED_TLS_DIR)
rm -rf $(TARGET_SRV_IMPL)
rm -rf $(TARGET_SPE)

View File

@ -22,7 +22,7 @@ SCRIPT=$1
FILE=$2 FILE=$2
conf() { conf() {
$SCRIPT -f $FILE $@ $SCRIPT -f $FILE --force $@
} }
add_code() { add_code() {
@ -140,3 +140,8 @@ conf unset MBEDTLS_SSL_TRUNCATED_HMAC
conf unset MBEDTLS_PLATFORM_TIME_TYPE_MACRO conf unset MBEDTLS_PLATFORM_TIME_TYPE_MACRO
# The following configurations are a needed for Mbed Crypto submodule.
# They are related to the persistent key storage feature.
conf set MBEDTLS_PSA_CRYPTO_STORAGE_C
conf set MBEDTLS_PSA_CRYPTO_STORAGE_ITS_C
conf unset MBEDTLS_PSA_CRYPTO_STORAGE_FILE_C

View File

@ -60,7 +60,11 @@
/* Error codes in range 0x0021-0x0025 */ /* Error codes in range 0x0021-0x0025 */
#define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */ #define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */
/* MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE is deprecated and should not be used. */
#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */ #define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */
/* MBEDTLS_ERR_AES_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */ #define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \

View File

@ -36,6 +36,7 @@
#include <stddef.h> #include <stddef.h>
/* MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 /**< ARC4 hardware accelerator failed. */ #define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 /**< ARC4 hardware accelerator failed. */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -48,7 +48,12 @@
#define MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH -0x005C /**< Invalid key length. */ #define MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH -0x005C /**< Invalid key length. */
#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E /**< Invalid data input length. */ #define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E /**< Invalid data input length. */
/* MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE is deprecated and should not be used.
*/
#define MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE -0x005A /**< Feature not available. For example, an unsupported ARIA key size. */ #define MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE -0x005A /**< Feature not available. For example, an unsupported ARIA key size. */
/* MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED -0x0058 /**< ARIA hardware accelerator failed. */ #define MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED -0x0058 /**< ARIA hardware accelerator failed. */
#if !defined(MBEDTLS_ARIA_ALT) #if !defined(MBEDTLS_ARIA_ALT)

View File

@ -26,188 +26,269 @@
#include "asn1.h" #include "asn1.h"
#define MBEDTLS_ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else \ #define MBEDTLS_ASN1_CHK_ADD(g, f) \
g += ret; } while( 0 ) do { \
if( ( ret = f ) < 0 ) \
return( ret ); \
else \
g += ret; \
} while( 0 )
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/** /**
* \brief Write a length field in ASN.1 format * \brief Write a length field in ASN.1 format.
* Note: function works backwards in data buffer
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param len the length to write
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param len The length value to write.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ); int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start,
size_t len );
/** /**
* \brief Write a ASN.1 tag in ASN.1 format * \brief Write an ASN.1 tag in ASN.1 format.
* Note: function works backwards in data buffer
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param tag the tag to write
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param tag The tag to write.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start,
unsigned char tag ); unsigned char tag );
/** /**
* \brief Write raw buffer data * \brief Write raw buffer data.
* Note: function works backwards in data buffer
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param buf data buffer to write
* \param size length of the data buffer
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param buf The data buffer to write.
* \param size The length of the data buffer.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t size ); const unsigned char *buf, size_t size );
#if defined(MBEDTLS_BIGNUM_C) #if defined(MBEDTLS_BIGNUM_C)
/** /**
* \brief Write a big number (MBEDTLS_ASN1_INTEGER) in ASN.1 format * \brief Write a arbitrary-precision number (#MBEDTLS_ASN1_INTEGER)
* Note: function works backwards in data buffer * in ASN.1 format.
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param X the MPI to write
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param X The MPI to write.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ); int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start,
const mbedtls_mpi *X );
#endif /* MBEDTLS_BIGNUM_C */ #endif /* MBEDTLS_BIGNUM_C */
/** /**
* \brief Write a NULL tag (MBEDTLS_ASN1_NULL) with zero data in ASN.1 format * \brief Write a NULL tag (#MBEDTLS_ASN1_NULL) with zero data
* Note: function works backwards in data buffer * in ASN.1 format.
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ); int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start );
/** /**
* \brief Write an OID tag (MBEDTLS_ASN1_OID) and data in ASN.1 format * \brief Write an OID tag (#MBEDTLS_ASN1_OID) and data
* Note: function works backwards in data buffer * in ASN.1 format.
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param oid the OID to write
* \param oid_len length of the OID
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param oid The OID to write.
* \param oid_len The length of the OID.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start,
const char *oid, size_t oid_len ); const char *oid, size_t oid_len );
/** /**
* \brief Write an AlgorithmIdentifier sequence in ASN.1 format * \brief Write an AlgorithmIdentifier sequence in ASN.1 format.
* Note: function works backwards in data buffer
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking) *
* \param oid the OID of the algorithm * \param p The reference to the current position pointer.
* \param oid_len length of the OID * \param start The start of the buffer, for bounds-checking.
* \param par_len length of parameters, which must be already written. * \param oid The OID of the algorithm to write.
* \param oid_len The length of the algorithm's OID.
* \param par_len The length of the parameters, which must be already written.
* If 0, NULL parameters are added * If 0, NULL parameters are added
* *
* \return the length written or a negative error code * \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, int mbedtls_asn1_write_algorithm_identifier( unsigned char **p,
unsigned char *start,
const char *oid, size_t oid_len, const char *oid, size_t oid_len,
size_t par_len ); size_t par_len );
/** /**
* \brief Write a boolean tag (MBEDTLS_ASN1_BOOLEAN) and value in ASN.1 format * \brief Write a boolean tag (#MBEDTLS_ASN1_BOOLEAN) and value
* Note: function works backwards in data buffer * in ASN.1 format.
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param boolean 0 or 1
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param boolean The boolean value to write, either \c 0 or \c 1.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ); int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start,
int boolean );
/** /**
* \brief Write an int tag (MBEDTLS_ASN1_INTEGER) and value in ASN.1 format * \brief Write an int tag (#MBEDTLS_ASN1_INTEGER) and value
* Note: function works backwards in data buffer * in ASN.1 format.
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param val the integer value
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param val The integer value to write.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ); int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val );
/** /**
* \brief Write a printable string tag (MBEDTLS_ASN1_PRINTABLE_STRING) and * \brief Write a string in ASN.1 format using a specific
* value in ASN.1 format * string encoding tag.
* Note: function works backwards in data buffer
* \note This function works backwards in data buffer.
* *
* \param p reference to current position pointer * \param p The reference to the current position pointer.
* \param start start of the buffer (for bounds-checking) * \param start The start of the buffer, for bounds-checking.
* \param text the text to write * \param tag The string encoding tag to write, e.g.
* \param text_len length of the text * #MBEDTLS_ASN1_UTF8_STRING.
* \param text The string to write.
* \param text_len The length of \p text in bytes (which might
* be strictly larger than the number of characters).
* *
* \return the length written or a negative error code * \return The number of bytes written to \p p on success.
* \return A negative error code on failure.
*/ */
int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start,
int tag, const char *text,
size_t text_len );
/**
* \brief Write a string in ASN.1 format using the PrintableString
* string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING).
*
* \note This function works backwards in data buffer.
*
* \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param text The string to write.
* \param text_len The length of \p text in bytes (which might
* be strictly larger than the number of characters).
*
* \return The number of bytes written to \p p on success.
* \return A negative error code on failure.
*/
int mbedtls_asn1_write_printable_string( unsigned char **p,
unsigned char *start,
const char *text, size_t text_len ); const char *text, size_t text_len );
/** /**
* \brief Write an IA5 string tag (MBEDTLS_ASN1_IA5_STRING) and * \brief Write a UTF8 string in ASN.1 format using the UTF8String
* value in ASN.1 format * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING).
* Note: function works backwards in data buffer
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param text the text to write
* \param text_len length of the text
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param text The string to write.
* \param text_len The length of \p text in bytes (which might
* be strictly larger than the number of characters).
*
* \return The number of bytes written to \p p on success.
* \return A negative error code on failure.
*/
int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start,
const char *text, size_t text_len );
/**
* \brief Write a string in ASN.1 format using the IA5String
* string encoding tag (#MBEDTLS_ASN1_IA5_STRING).
*
* \note This function works backwards in data buffer.
*
* \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param text The string to write.
* \param text_len The length of \p text in bytes (which might
* be strictly larger than the number of characters).
*
* \return The number of bytes written to \p p on success.
* \return A negative error code on failure.
*/ */
int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
const char *text, size_t text_len ); const char *text, size_t text_len );
/** /**
* \brief Write a bitstring tag (MBEDTLS_ASN1_BIT_STRING) and * \brief Write a bitstring tag (#MBEDTLS_ASN1_BIT_STRING) and
* value in ASN.1 format * value in ASN.1 format.
* Note: function works backwards in data buffer
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param buf the bitstring
* \param bits the total number of bits in the bitstring
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param buf The bitstring to write.
* \param bits The total number of bits in the bitstring.
*
* \return The number of bytes written to \p p on success.
* \return A negative error code on failure.
*/ */
int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t bits ); const unsigned char *buf, size_t bits );
/** /**
* \brief Write an octet string tag (MBEDTLS_ASN1_OCTET_STRING) and * \brief Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING)
* value in ASN.1 format * and value in ASN.1 format.
* Note: function works backwards in data buffer
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param buf data buffer to write
* \param size length of the data buffer
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param buf The buffer holding the data to write.
* \param size The length of the data buffer \p buf.
*
* \return The number of bytes written to \p p on success.
* \return A negative error code on failure.
*/ */
int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t size ); const unsigned char *buf, size_t size );
@ -218,15 +299,16 @@ int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
* a new entry is added to the head of the list. * a new entry is added to the head of the list.
* Warning: Destructive behaviour for the val data! * Warning: Destructive behaviour for the val data!
* *
* \param list Pointer to the location of the head of the list to seek * \param list The pointer to the location of the head of the list to seek
* through (will be updated in case of a new entry) * through (will be updated in case of a new entry).
* \param oid The OID to look for * \param oid The OID to look for.
* \param oid_len Size of the OID * \param oid_len The size of the OID.
* \param val Data to store (can be NULL if you want to fill it by hand) * \param val The data to store (can be \c NULL if you want to fill
* \param val_len Minimum length of the data buffer needed * it by hand).
* \param val_len The minimum length of the data buffer needed.
* *
* \return NULL if if there was a memory allocation error, or a pointer * \return A pointer to the new / existing entry on success.
* to the new / existing entry. * \return \c NULL if if there was a memory allocation error.
*/ */
mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list, mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list,
const char *oid, size_t oid_len, const char *oid, size_t oid_len,

View File

@ -725,8 +725,18 @@ int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B
*/ */
int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ); int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N );
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else
#define MBEDTLS_DEPRECATED
#endif
/** /**
* \brief Miller-Rabin primality test * \brief Miller-Rabin primality test with error probability of
* 2<sup>-80</sup>
*
* \deprecated Superseded by mbedtls_mpi_is_prime_ext() which allows
* specifying the number of Miller-Rabin rounds.
* *
* \param X MPI to check * \param X MPI to check
* \param f_rng RNG function * \param f_rng RNG function
@ -736,9 +746,48 @@ int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime
*/ */
int mbedtls_mpi_is_prime( const mbedtls_mpi *X, MBEDTLS_DEPRECATED int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng ); void *p_rng );
#undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
/**
* \brief Miller-Rabin primality test.
*
* \warning If \p X is potentially generated by an adversary, for example
* when validating cryptographic parameters that you didn't
* generate yourself and that are supposed to be prime, then
* \p rounds should be at least the half of the security
* strength of the cryptographic algorithm. On the other hand,
* if \p X is chosen uniformly or non-adversially (as is the
* case when mbedtls_mpi_gen_prime calls this function), then
* \p rounds can be much lower.
*
* \param X MPI to check
* \param rounds Number of bases to perform Miller-Rabin primality test for.
* The probability of returning 0 on a composite is at most
* 2<sup>-2*\p rounds</sup>.
* \param f_rng RNG function
* \param p_rng RNG parameter
*
* \return 0 if successful (probably prime),
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime
*/
int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief Flags for mbedtls_mpi_gen_prime()
*
* Each of these flags is a constraint on the result X returned by
* mbedtls_mpi_gen_prime().
*/
typedef enum {
MBEDTLS_MPI_GEN_PRIME_FLAG_DH = 0x0001, /**< (X-1)/2 is prime too */
MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR = 0x0002, /**< lower error rate from 2<sup>-80</sup> to 2<sup>-128</sup> */
} mbedtls_mpi_gen_prime_flag_t;
/** /**
* \brief Prime number generation * \brief Prime number generation
@ -746,7 +795,7 @@ int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
* \param X Destination MPI * \param X Destination MPI
* \param nbits Required size of X in bits * \param nbits Required size of X in bits
* ( 3 <= nbits <= MBEDTLS_MPI_MAX_BITS ) * ( 3 <= nbits <= MBEDTLS_MPI_MAX_BITS )
* \param dh_flag If 1, then (X-1)/2 will be prime too * \param flags Mask of flags of type #mbedtls_mpi_gen_prime_flag_t
* \param f_rng RNG function * \param f_rng RNG function
* \param p_rng RNG parameter * \param p_rng RNG parameter
* *
@ -754,7 +803,7 @@ int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
* MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
*/ */
int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng ); void *p_rng );

View File

@ -41,7 +41,11 @@
#define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */ #define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */
#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH -0x0016 /**< Invalid key length. */ #define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH -0x0016 /**< Invalid key length. */
/* MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED is deprecated and should not be used.
*/
#define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 /**< Blowfish hardware accelerator failed. */ #define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 /**< Blowfish hardware accelerator failed. */
#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */ #define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -565,9 +565,8 @@
#endif /* TriCore */ #endif /* TriCore */
/* /*
* gcc -O0 by default uses r7 for the frame pointer, so it complains about our * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about
* use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately, * our use of r7 below, unless -fomit-frame-pointer is passed.
* passing that option is not easy when building with yotta.
* *
* On the other hand, -fomit-frame-pointer is implied by any -Ox options with * On the other hand, -fomit-frame-pointer is implied by any -Ox options with
* x !=0, which we can detect using __OPTIMIZE__ (which is also defined by * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by
@ -637,6 +636,23 @@
"r6", "r7", "r8", "r9", "cc" \ "r6", "r7", "r8", "r9", "cc" \
); );
#elif defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)
#define MULADDC_INIT \
asm(
#define MULADDC_CORE \
"ldr r0, [%0], #4 \n\t" \
"ldr r1, [%1] \n\t" \
"umaal r1, %2, %3, r0 \n\t" \
"str r1, [%1], #4 \n\t"
#define MULADDC_STOP \
: "=r" (s), "=r" (d), "=r" (c) \
: "r" (b), "0" (s), "1" (d), "2" (c) \
: "r0", "r1", "memory" \
);
#else #else
#define MULADDC_INIT \ #define MULADDC_INIT \

View File

@ -38,6 +38,9 @@
#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */ #define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */
#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ #define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */
/* MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED is deprecated and should not be used.
*/
#define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 /**< Camellia hardware accelerator failed. */ #define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 /**< Camellia hardware accelerator failed. */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -53,6 +53,8 @@
#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */ #define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */
#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ #define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */
/* MBEDTLS_ERR_CCM_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */ #define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */

View File

@ -43,7 +43,13 @@
#include <stddef.h> #include <stddef.h>
#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 /**< Invalid input parameter(s). */ #define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 /**< Invalid input parameter(s). */
/* MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE is deprecated and should not be
* used. */
#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE -0x0053 /**< Feature not available. For example, s part of the API is not implemented. */ #define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE -0x0053 /**< Feature not available. For example, s part of the API is not implemented. */
/* MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED is deprecated and should not be used.
*/
#define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED -0x0055 /**< Chacha20 hardware accelerator failed. */ #define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED -0x0055 /**< Chacha20 hardware accelerator failed. */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -108,6 +108,16 @@
#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" #error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites"
#endif #endif
#if defined(MBEDTLS_ECP_RESTARTABLE) && \
( defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \
defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \
defined(MBEDTLS_ECDSA_SIGN_ALT) || \
defined(MBEDTLS_ECDSA_VERIFY_ALT) || \
defined(MBEDTLS_ECDSA_GENKEY_ALT) || \
defined(MBEDTLS_ECP_ALT) )
#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative ECP implementation"
#endif
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) #if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C)
#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" #error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites"
#endif #endif
@ -486,6 +496,12 @@
#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" #error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously"
#endif #endif
#if defined(MBEDTLS_PSA_CRYPTO_C) && \
!( defined(MBEDTLS_CTR_DRBG_C) && \
defined(MBEDTLS_ENTROPY_C) )
#error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ #if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \
!defined(MBEDTLS_OID_C) ) !defined(MBEDTLS_OID_C) )
#error "MBEDTLS_RSA_C defined, but not all prerequisites" #error "MBEDTLS_RSA_C defined, but not all prerequisites"
@ -628,6 +644,10 @@
#endif #endif
#undef MBEDTLS_THREADING_IMPL #undef MBEDTLS_THREADING_IMPL
#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_C)
#error "MBEDTLS_USE_PSA_CRYPTO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) #if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C)
#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" #error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites"
#endif #endif

View File

@ -62,6 +62,8 @@
#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ #define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */
#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ #define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */
#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid. For example, because it was freed. */ #define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid. For example, because it was freed. */
/* MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 /**< Cipher hardware accelerator failed. */ #define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 /**< Cipher hardware accelerator failed. */
#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */ #define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */
@ -319,14 +321,32 @@ typedef struct mbedtls_cipher_context_t
/** CMAC-specific context. */ /** CMAC-specific context. */
mbedtls_cmac_context_t *cmac_ctx; mbedtls_cmac_context_t *cmac_ctx;
#endif #endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/** Indicates whether the cipher operations should be performed
* by Mbed TLS' own crypto library or an external implementation
* of the PSA Crypto API.
* This is unset if the cipher context was established through
* mbedtls_cipher_setup(), and set if it was established through
* mbedtls_cipher_setup_psa().
*/
unsigned char psa_enabled;
#endif /* MBEDTLS_USE_PSA_CRYPTO */
} mbedtls_cipher_context_t; } mbedtls_cipher_context_t;
/** /**
* \brief This function retrieves the list of ciphers supported by the generic * \brief This function retrieves the list of ciphers supported
* cipher module. * by the generic cipher module.
* *
* \return A statically-allocated array of ciphers. The last entry * For any cipher identifier in the returned list, you can
* is zero. * obtain the corresponding generic cipher information structure
* via mbedtls_cipher_info_from_type(), which can then be used
* to prepare a cipher context via mbedtls_cipher_setup().
*
*
* \return A statically-allocated array of cipher identifiers
* of type cipher_type_t. The last entry is zero.
*/ */
const int *mbedtls_cipher_list( void ); const int *mbedtls_cipher_list( void );
@ -386,9 +406,8 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx );
/** /**
* \brief This function initializes and fills the cipher-context * \brief This function initializes a cipher context for
* structure with the appropriate values. It also clears * use with the given cipher primitive.
* the structure.
* *
* \param ctx The context to initialize. May not be NULL. * \param ctx The context to initialize. May not be NULL.
* \param cipher_info The cipher to use. * \param cipher_info The cipher to use.
@ -403,7 +422,35 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx );
* In future versions, the caller will be required to call * In future versions, the caller will be required to call
* mbedtls_cipher_init() on the structure first. * mbedtls_cipher_init() on the structure first.
*/ */
int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ); int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx,
const mbedtls_cipher_info_t *cipher_info );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/**
* \brief This function initializes a cipher context for
* PSA-based use with the given cipher primitive.
*
* \note See #MBEDTLS_USE_PSA_CRYPTO for information on PSA.
*
* \param ctx The context to initialize. May not be \c NULL.
* \param cipher_info The cipher to use.
* \param taglen For AEAD ciphers, the length in bytes of the
* authentication tag to use. Subsequent uses of
* mbedtls_cipher_auth_encrypt() or
* mbedtls_cipher_auth_decrypt() must provide
* the same tag length.
* For non-AEAD ciphers, the value must be \c 0.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
* parameter-verification failure.
* \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the
* cipher-specific context fails.
*/
int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx,
const mbedtls_cipher_info_t *cipher_info,
size_t taglen );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/** /**
* \brief This function returns the block size of the given cipher. * \brief This function returns the block size of the given cipher.
@ -413,7 +460,8 @@ int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_in
* \return The size of the blocks of the cipher. * \return The size of the blocks of the cipher.
* \return 0 if \p ctx has not been initialized. * \return 0 if \p ctx has not been initialized.
*/ */
static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx ) static inline unsigned int mbedtls_cipher_get_block_size(
const mbedtls_cipher_context_t *ctx )
{ {
if( NULL == ctx || NULL == ctx->cipher_info ) if( NULL == ctx || NULL == ctx->cipher_info )
return 0; return 0;
@ -430,7 +478,8 @@ static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_c
* \return The mode of operation. * \return The mode of operation.
* \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized. * \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized.
*/ */
static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx ) static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode(
const mbedtls_cipher_context_t *ctx )
{ {
if( NULL == ctx || NULL == ctx->cipher_info ) if( NULL == ctx || NULL == ctx->cipher_info )
return MBEDTLS_MODE_NONE; return MBEDTLS_MODE_NONE;
@ -448,7 +497,8 @@ static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtl
* \return \c 0 for ciphers not using an IV or a nonce. * \return \c 0 for ciphers not using an IV or a nonce.
* \return The actual size if an IV has been set. * \return The actual size if an IV has been set.
*/ */
static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx ) static inline int mbedtls_cipher_get_iv_size(
const mbedtls_cipher_context_t *ctx )
{ {
if( NULL == ctx || NULL == ctx->cipher_info ) if( NULL == ctx || NULL == ctx->cipher_info )
return 0; return 0;
@ -467,7 +517,8 @@ static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ct
* \return The type of the cipher. * \return The type of the cipher.
* \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized. * \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized.
*/ */
static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx ) static inline mbedtls_cipher_type_t mbedtls_cipher_get_type(
const mbedtls_cipher_context_t *ctx )
{ {
if( NULL == ctx || NULL == ctx->cipher_info ) if( NULL == ctx || NULL == ctx->cipher_info )
return MBEDTLS_CIPHER_NONE; return MBEDTLS_CIPHER_NONE;
@ -484,7 +535,8 @@ static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_ciphe
* \return The name of the cipher. * \return The name of the cipher.
* \return NULL if \p ctx has not been not initialized. * \return NULL if \p ctx has not been not initialized.
*/ */
static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx ) static inline const char *mbedtls_cipher_get_name(
const mbedtls_cipher_context_t *ctx )
{ {
if( NULL == ctx || NULL == ctx->cipher_info ) if( NULL == ctx || NULL == ctx->cipher_info )
return 0; return 0;
@ -501,7 +553,8 @@ static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_
* \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been * \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been
* initialized. * initialized.
*/ */
static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx ) static inline int mbedtls_cipher_get_key_bitlen(
const mbedtls_cipher_context_t *ctx )
{ {
if( NULL == ctx || NULL == ctx->cipher_info ) if( NULL == ctx || NULL == ctx->cipher_info )
return MBEDTLS_KEY_LENGTH_NONE; return MBEDTLS_KEY_LENGTH_NONE;
@ -517,7 +570,8 @@ static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t
* \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. * \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT.
* \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized. * \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized.
*/ */
static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx ) static inline mbedtls_operation_t mbedtls_cipher_get_operation(
const mbedtls_cipher_context_t *ctx )
{ {
if( NULL == ctx || NULL == ctx->cipher_info ) if( NULL == ctx || NULL == ctx->cipher_info )
return MBEDTLS_OPERATION_NONE; return MBEDTLS_OPERATION_NONE;
@ -541,8 +595,10 @@ static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_ci
* parameter-verification failure. * parameter-verification failure.
* \return A cipher-specific error code on failure. * \return A cipher-specific error code on failure.
*/ */
int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx,
int key_bitlen, const mbedtls_operation_t operation ); const unsigned char *key,
int key_bitlen,
const mbedtls_operation_t operation );
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
/** /**
@ -560,7 +616,8 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *k
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode
* does not support padding. * does not support padding.
*/ */
int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ); int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx,
mbedtls_cipher_padding_t mode );
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
/** /**
@ -641,8 +698,10 @@ int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
* unsupported mode for a cipher. * unsupported mode for a cipher.
* \return A cipher-specific error code on failure. * \return A cipher-specific error code on failure.
*/ */
int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx,
size_t ilen, unsigned char *output, size_t *olen ); const unsigned char *input,
size_t ilen, unsigned char *output,
size_t *olen );
/** /**
* \brief The generic cipher finalization function. If data still * \brief The generic cipher finalization function. If data still

View File

@ -34,6 +34,10 @@
#include "cipher.h" #include "cipher.h"
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -114,6 +118,30 @@ typedef struct
const mbedtls_cipher_info_t *info; const mbedtls_cipher_info_t *info;
} mbedtls_cipher_definition_t; } mbedtls_cipher_definition_t;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
typedef enum
{
MBEDTLS_CIPHER_PSA_KEY_UNSET = 0,
MBEDTLS_CIPHER_PSA_KEY_OWNED, /* Used for PSA-based cipher contexts which */
/* use raw key material internally imported */
/* into a allocated key slot, and which */
/* hence need to destroy that key slot */
/* when they are no longer needed. */
MBEDTLS_CIPHER_PSA_KEY_NOT_OWNED, /* Used for PSA-based cipher contexts */
/* which use a key from a key slot */
/* provided by the user, and which */
/* hence should not be destroyed when */
/* the context is no longer needed. */
} mbedtls_cipher_psa_key_ownership;
typedef struct
{
psa_algorithm_t alg;
psa_key_slot_t slot;
mbedtls_cipher_psa_key_ownership slot_state;
} mbedtls_cipher_context_psa;
#endif /* MBEDTLS_USE_PSA_CRYPTO */
extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[]; extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[];
extern int mbedtls_cipher_supported[]; extern int mbedtls_cipher_supported[];

View File

@ -34,6 +34,7 @@
extern "C" { extern "C" {
#endif #endif
/* MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A /**< CMAC hardware accelerator failed. */ #define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A /**< CMAC hardware accelerator failed. */
#define MBEDTLS_AES_BLOCK_SIZE 16 #define MBEDTLS_AES_BLOCK_SIZE 16

View File

@ -34,7 +34,8 @@
* Only use features that do not require an entropy source when * Only use features that do not require an entropy source when
* DEVICE_ENTROPY_SOURCE is not defined in mbed OS. * DEVICE_ENTROPY_SOURCE is not defined in mbed OS.
*/ */
#if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) && !defined(MBEDTLS_TEST_NULL_ENTROPY) #if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) && !defined(MBEDTLS_TEST_NULL_ENTROPY) && \
!defined(MBEDTLS_ENTROPY_NV_SEED)
#include "mbedtls/config-no-entropy.h" #include "mbedtls/config-no-entropy.h"
#if defined(MBEDTLS_USER_CONFIG_FILE) #if defined(MBEDTLS_USER_CONFIG_FILE)
@ -692,6 +693,30 @@
*/ */
#define MBEDTLS_ECP_NIST_OPTIM #define MBEDTLS_ECP_NIST_OPTIM
/**
* \def MBEDTLS_ECP_RESTARTABLE
*
* Enable "non-blocking" ECC operations that can return early and be resumed.
*
* This allows various functions to pause by returning
* #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module,
* #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in
* order to further progress and eventually complete their operation. This is
* controlled through mbedtls_ecp_set_max_ops() which limits the maximum
* number of ECC operations a function may perform before pausing; see
* mbedtls_ecp_set_max_ops() for more information.
*
* This is useful in non-threaded environments if you want to avoid blocking
* for too long on ECC (and, hence, X.509 or SSL/TLS) operations.
*
* Uncomment this macro to enable restartable ECC computations.
*
* \note This option only works with the default software implementation of
* elliptic curve functionality. It is incompatible with
* MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT and MBEDTLS_ECDSA_XXX_ALT.
*/
//#define MBEDTLS_ECP_RESTARTABLE
/** /**
* \def MBEDTLS_ECDSA_DETERMINISTIC * \def MBEDTLS_ECDSA_DETERMINISTIC
* *
@ -1303,7 +1328,7 @@
/** /**
* \def MBEDTLS_SSL_RENEGOTIATION * \def MBEDTLS_SSL_RENEGOTIATION
* *
* Disable support for TLS renegotiation. * Enable support for TLS renegotiation.
* *
* The two main uses of renegotiation are (1) refresh keys on long-lived * The two main uses of renegotiation are (1) refresh keys on long-lived
* connections and (2) client authentication after the initial handshake. * connections and (2) client authentication after the initial handshake.
@ -1573,6 +1598,24 @@
*/ */
//#define MBEDTLS_THREADING_PTHREAD //#define MBEDTLS_THREADING_PTHREAD
/**
* \def MBEDTLS_USE_PSA_CRYPTO
*
* Make the X.509 and TLS library use PSA for cryptographic operations, see
* #MBEDTLS_PSA_CRYPTO_C.
*
* Note: this option is still in progress, the full X.509 and TLS modules are
* not covered yet, but parts that are not ported to PSA yet will still work
* as usual, so enabling this option should not break backwards compatibility.
*
* \warning Support for PSA is still an experimental feature.
* Any public API that depends on this option may change
* at any time until this warning is removed.
*
* Requires: MBEDTLS_PSA_CRYPTO_C.
*/
//#define MBEDTLS_USE_PSA_CRYPTO
/** /**
* \def MBEDTLS_VERSION_FEATURES * \def MBEDTLS_VERSION_FEATURES
* *
@ -2042,14 +2085,16 @@
/** /**
* \def MBEDTLS_CTR_DRBG_C * \def MBEDTLS_CTR_DRBG_C
* *
* Enable the CTR_DRBG AES-256-based random generator. * Enable the CTR_DRBG AES-based random generator.
* The CTR_DRBG generator uses AES-256 by default.
* To use AES-128 instead, enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY below.
* *
* Module: library/ctr_drbg.c * Module: library/ctr_drbg.c
* Caller: * Caller:
* *
* Requires: MBEDTLS_AES_C * Requires: MBEDTLS_AES_C
* *
* This module provides the CTR_DRBG AES-256 random number generator. * This module provides the CTR_DRBG AES random number generator.
*/ */
#define MBEDTLS_CTR_DRBG_C #define MBEDTLS_CTR_DRBG_C
@ -2579,6 +2624,25 @@
*/ */
#define MBEDTLS_POLY1305_C #define MBEDTLS_POLY1305_C
/**
* \def MBEDTLS_PSA_CRYPTO_C
*
* Enable the Platform Security Architecture cryptography API.
*
* \note This option only has an effect when the build option
* USE_CRYPTO_SUBMODULE is also in use.
*
* \warning This feature is experimental and available on an opt-in basis only.
* PSA APIs are subject to change at any time. The implementation comes with
* less assurance and support than the rest of Mbed TLS.
*
* Module: crypto/library/psa_crypto.c
*
* Requires: MBEDTLS_CTR_DRBG_C, MBEDTLS_ENTROPY_C
*
*/
//#define MBEDTLS_PSA_CRYPTO_C
/** /**
* \def MBEDTLS_RIPEMD160_C * \def MBEDTLS_RIPEMD160_C
* *
@ -2934,6 +2998,7 @@
//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ //#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ //#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ //#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY /**< Use 128-bit key for CTR_DRBG - may reduce security (see ctr_drbg.h) */
/* HMAC_DRBG options */ /* HMAC_DRBG options */
//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ //#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
@ -3145,29 +3210,18 @@
/* \} name SECTION: Customisation configuration options */ /* \} name SECTION: Customisation configuration options */
/* Target and application specific configurations */ /* Target and application specific configurations
//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "target_config.h" *
#if defined(TARGET_LIKE_MBED) && defined(YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE)
#include YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE
#endif
/*
* Allow user to override any previous default. * Allow user to override any previous default.
* *
* Use two macro names for that, as:
* - with yotta the prefix YOTTA_CFG_ is forced
* - without yotta is looks weird to have a YOTTA prefix.
*/ */
#if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE) #if defined(MBEDTLS_USER_CONFIG_FILE)
#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE
#elif defined(MBEDTLS_USER_CONFIG_FILE)
#include MBEDTLS_USER_CONFIG_FILE #include MBEDTLS_USER_CONFIG_FILE
#endif #endif
#include "check_config.h" #include "check_config.h"
#endif /* !MBEDTLS_ENTROPY_HARDWARE_ALT && !MBEDTLS_TEST_NULL_ENTROPY */ #endif /* !MBEDTLS_ENTROPY_HARDWARE_ALT && !MBEDTLS_TEST_NULL_ENTROPY && !MBEDTLS_ENTROPY_NV_SEED */
#if defined(MBEDTLS_TEST_NULL_ENTROPY) #if defined(MBEDTLS_TEST_NULL_ENTROPY)
#warning "MBEDTLS_TEST_NULL_ENTROPY has been enabled. This " \ #warning "MBEDTLS_TEST_NULL_ENTROPY has been enabled. This " \
@ -3181,3 +3235,5 @@
#endif #endif
#endif /* MBEDTLS_CONFIG_H */ #endif /* MBEDTLS_CONFIG_H */
#define MBEDTLS_PSA_CRYPTO_STORAGE_C
#define MBEDTLS_PSA_CRYPTO_STORAGE_ITS_C

View File

@ -8,8 +8,11 @@
* Recommendation for Random Number Generation Using Deterministic Random * Recommendation for Random Number Generation Using Deterministic Random
* Bit Generators</em>. * Bit Generators</em>.
* *
* The Mbed TLS implementation of CTR_DRBG uses AES-256 as the underlying * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128
* block cipher. * as the underlying block cipher.
*
* \warning Using 128-bit keys for CTR_DRBG limits the security of generated
* keys and operations that use random values generated to 128-bit security.
*/ */
/* /*
* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
@ -45,7 +48,13 @@
#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read or write error in file. */ #define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read or write error in file. */
#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */ #define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */
#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher. */
#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
#define MBEDTLS_CTR_DRBG_KEYSIZE 16 /**< The key size used by the cipher (compile-time choice: 128 bits). */
#else
#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher (compile-time choice: 256 bits). */
#endif
#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */ #define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */
#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */ #define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */

View File

@ -42,6 +42,8 @@
#define MBEDTLS_DES_DECRYPT 0 #define MBEDTLS_DES_DECRYPT 0
#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ #define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */
/* MBEDTLS_ERR_DES_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_DES_HW_ACCEL_FAILED -0x0033 /**< DES hardware accelerator failed. */ #define MBEDTLS_ERR_DES_HW_ACCEL_FAILED -0x0033 /**< DES hardware accelerator failed. */
#define MBEDTLS_DES_KEY_SIZE 8 #define MBEDTLS_DES_KEY_SIZE 8

View File

@ -84,7 +84,10 @@
#define MBEDTLS_ERR_DHM_INVALID_FORMAT -0x3380 /**< The ASN.1 data is not formatted correctly. */ #define MBEDTLS_ERR_DHM_INVALID_FORMAT -0x3380 /**< The ASN.1 data is not formatted correctly. */
#define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 /**< Allocation of memory failed. */ #define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 /**< Allocation of memory failed. */
#define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 /**< Read or write of file failed. */ #define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 /**< Read or write of file failed. */
/* MBEDTLS_ERR_DHM_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_DHM_HW_ACCEL_FAILED -0x3500 /**< DHM hardware accelerator failed. */ #define MBEDTLS_ERR_DHM_HW_ACCEL_FAILED -0x3500 /**< DHM hardware accelerator failed. */
#define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 /**< Setting the modulus and generator failed. */ #define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 /**< Setting the modulus and generator failed. */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -50,6 +50,10 @@ typedef enum
} mbedtls_ecdh_side; } mbedtls_ecdh_side;
/** /**
*
* \warning Performing multiple operations concurrently on the same
* ECDSA context is not supported; objects of this type
* should not be shared between multiple threads.
* \brief The ECDH context structure. * \brief The ECDH context structure.
*/ */
typedef struct mbedtls_ecdh_context typedef struct mbedtls_ecdh_context
@ -63,6 +67,10 @@ typedef struct mbedtls_ecdh_context
mbedtls_ecp_point Vi; /*!< The blinding value. */ mbedtls_ecp_point Vi; /*!< The blinding value. */
mbedtls_ecp_point Vf; /*!< The unblinding value. */ mbedtls_ecp_point Vf; /*!< The unblinding value. */
mbedtls_mpi _d; /*!< The previous \p d. */ mbedtls_mpi _d; /*!< The previous \p d. */
#if defined(MBEDTLS_ECP_RESTARTABLE)
int restart_enabled; /*!< The flag for restartable mode. */
mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */
#endif
} }
mbedtls_ecdh_context; mbedtls_ecdh_context;
@ -83,9 +91,8 @@ mbedtls_ecdh_context;
* \param p_rng The RNG context. * \param p_rng The RNG context.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX or * \return Another \c MBEDTLS_ERR_ECP_XXX or
* \c MBEDTLS_MPI_XXX error code on failure. * \c MBEDTLS_MPI_XXX error code on failure.
*
*/ */
int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
@ -112,7 +119,7 @@ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp
* \param p_rng The RNG context. * \param p_rng The RNG context.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX or * \return Another \c MBEDTLS_ERR_ECP_XXX or
* \c MBEDTLS_MPI_XXX error code on failure. * \c MBEDTLS_MPI_XXX error code on failure.
*/ */
int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
@ -155,7 +162,9 @@ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx );
* \param p_rng The RNG context. * \param p_rng The RNG context.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
* \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
*/ */
int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen, unsigned char *buf, size_t blen,
@ -197,7 +206,7 @@ int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
* 0: The key of the peer. * 0: The key of the peer.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
* *
*/ */
int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key,
@ -220,7 +229,9 @@ int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypai
* \param p_rng The RNG context. * \param p_rng The RNG context.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
* \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
*/ */
int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen, unsigned char *buf, size_t blen,
@ -266,13 +277,31 @@ int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
* \param p_rng The RNG context. * \param p_rng The RNG context.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
* \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
*/ */
int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen, unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng ); void *p_rng );
#if defined(MBEDTLS_ECP_RESTARTABLE)
/**
* \brief This function enables restartable EC computations for this
* context. (Default: disabled.)
*
* \see \c mbedtls_ecp_set_max_ops()
*
* \note It is not possible to safely disable restartable
* computations once enabled, except by free-ing the context,
* which cancels possible in-progress operations.
*
* \param ctx The ECDH context.
*/
void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx );
#endif /* MBEDTLS_ECP_RESTARTABLE */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -35,35 +35,90 @@
#include "ecp.h" #include "ecp.h"
#include "md.h" #include "md.h"
/* /**
* RFC-4492 page 20: * \brief Maximum ECDSA signature size for a given curve bit size
* *
* \param bits Curve size in bits
* \return Maximum signature size in bytes
*
* \note This macro returns a compile-time constant if its argument
* is one. It may evaluate its argument multiple times.
*/
/*
* Ecdsa-Sig-Value ::= SEQUENCE { * Ecdsa-Sig-Value ::= SEQUENCE {
* r INTEGER, * r INTEGER,
* s INTEGER * s INTEGER
* } * }
* *
* Size is at most * For each of r and s, the value (V) may include an extra initial "0" bit.
* 1 (tag) + 1 (len) + 1 (initial 0) + ECP_MAX_BYTES for each of r and s,
* twice that + 1 (tag) + 2 (len) for the sequence
* (assuming ECP_MAX_BYTES is less than 126 for r and s,
* and less than 124 (total len <= 255) for the sequence)
*/ */
#if MBEDTLS_ECP_MAX_BYTES > 124 #define MBEDTLS_ECDSA_MAX_SIG_LEN( bits ) \
#error "MBEDTLS_ECP_MAX_BYTES bigger than expected, please fix MBEDTLS_ECDSA_MAX_LEN" ( /*T,L of SEQUENCE*/ ( ( bits ) >= 61 * 8 ? 3 : 2 ) + \
#endif /*T,L of r,s*/ 2 * ( ( ( bits ) >= 127 * 8 ? 3 : 2 ) + \
/** The maximal size of an ECDSA signature in Bytes. */ /*V of r,s*/ ( ( bits ) + 8 ) / 8 ) )
#define MBEDTLS_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) )
/** /** The maximal size of an ECDSA signature in Bytes. */
* \brief The ECDSA context structure. #define MBEDTLS_ECDSA_MAX_LEN MBEDTLS_ECDSA_MAX_SIG_LEN( MBEDTLS_ECP_MAX_BITS )
*/
typedef mbedtls_ecp_keypair mbedtls_ecdsa_context;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/**
* \brief The ECDSA context structure.
*
* \warning Performing multiple operations concurrently on the same
* ECDSA context is not supported; objects of this type
* should not be shared between multiple threads.
*/
typedef mbedtls_ecp_keypair mbedtls_ecdsa_context;
#if defined(MBEDTLS_ECP_RESTARTABLE)
/**
* \brief Internal restart context for ecdsa_verify()
*
* \note Opaque struct, defined in ecdsa.c
*/
typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx;
/**
* \brief Internal restart context for ecdsa_sign()
*
* \note Opaque struct, defined in ecdsa.c
*/
typedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx;
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
/**
* \brief Internal restart context for ecdsa_sign_det()
*
* \note Opaque struct, defined in ecdsa.c
*/
typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx;
#endif
/**
* \brief General context for resuming ECDSA operations
*/
typedef struct
{
mbedtls_ecp_restart_ctx ecp; /*!< base context for ECP restart and
shared administrative info */
mbedtls_ecdsa_restart_ver_ctx *ver; /*!< ecdsa_verify() sub-context */
mbedtls_ecdsa_restart_sig_ctx *sig; /*!< ecdsa_sign() sub-context */
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
mbedtls_ecdsa_restart_det_ctx *det; /*!< ecdsa_sign_det() sub-context */
#endif
} mbedtls_ecdsa_restart_ctx;
#else /* MBEDTLS_ECP_RESTARTABLE */
/* Now we can declare functions that take a pointer to that */
typedef void mbedtls_ecdsa_restart_ctx;
#endif /* MBEDTLS_ECP_RESTARTABLE */
/** /**
* \brief This function computes the ECDSA signature of a * \brief This function computes the ECDSA signature of a
* previously-hashed message. * previously-hashed message.
@ -205,6 +260,40 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng ); void *p_rng );
/**
* \brief This function computes the ECDSA signature and writes it
* to a buffer, in a restartable way.
*
* \see \c mbedtls_ecdsa_write_signature()
*
* \note This function is like \c mbedtls_ecdsa_write_signature()
* but it can return early and restart according to the limit
* set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
*
* \param ctx The ECDSA context.
* \param md_alg The message digest that was used to hash the message.
* \param hash The message hash.
* \param hlen The length of the hash.
* \param sig The buffer that holds the signature.
* \param slen The length of the signature written.
* \param f_rng The RNG function.
* \param p_rng The RNG context.
* \param rs_ctx The restart context (NULL disables restart).
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
* \return Another \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or
* \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/
int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t *slen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
mbedtls_ecdsa_restart_ctx *rs_ctx );
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
#if ! defined(MBEDTLS_DEPRECATED_REMOVED) #if ! defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING) #if defined(MBEDTLS_DEPRECATED_WARNING)
@ -288,6 +377,37 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
const unsigned char *hash, size_t hlen, const unsigned char *hash, size_t hlen,
const unsigned char *sig, size_t slen ); const unsigned char *sig, size_t slen );
/**
* \brief This function reads and verifies an ECDSA signature,
* in a restartable way.
*
* \see \c mbedtls_ecdsa_read_signature()
*
* \note This function is like \c mbedtls_ecdsa_read_signature()
* but it can return early and restart according to the limit
* set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
*
* \param ctx The ECDSA context.
* \param hash The message hash.
* \param hlen The size of the hash.
* \param sig The signature to read and verify.
* \param slen The size of \p sig.
* \param rs_ctx The restart context (NULL disables restart).
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid.
* \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid
* signature in \p sig, but its length is less than \p siglen.
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
* \return Another \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX
* error code on failure for any other reason.
*/
int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx,
const unsigned char *hash, size_t hlen,
const unsigned char *sig, size_t slen,
mbedtls_ecdsa_restart_ctx *rs_ctx );
/** /**
* \brief This function generates an ECDSA keypair on the given curve. * \brief This function generates an ECDSA keypair on the given curve.
* *
@ -332,6 +452,18 @@ void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx );
*/ */
void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ); void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx );
#if defined(MBEDTLS_ECP_RESTARTABLE)
/**
* \brief Initialize a restart context
*/
void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx );
/**
* \brief Free the components of a restart context
*/
void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx );
#endif /* MBEDTLS_ECP_RESTARTABLE */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -49,8 +49,12 @@
#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as ephemeral key, failed. */ #define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as ephemeral key, failed. */
#define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ #define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */
#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< The buffer contains a valid signature followed by more data. */ #define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< The buffer contains a valid signature followed by more data. */
/* MBEDTLS_ERR_ECP_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< The ECP hardware accelerator failed. */ #define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< The ECP hardware accelerator failed. */
#define MBEDTLS_ERR_ECP_IN_PROGRESS -0x4B00 /**< Operation in progress, call again with the same parameters to continue. */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -181,6 +185,70 @@ typedef struct mbedtls_ecp_group
} }
mbedtls_ecp_group; mbedtls_ecp_group;
#if defined(MBEDTLS_ECP_RESTARTABLE)
/**
* \brief Internal restart context for multiplication
*
* \note Opaque struct
*/
typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx;
/**
* \brief Internal restart context for ecp_muladd()
*
* \note Opaque struct
*/
typedef struct mbedtls_ecp_restart_muladd mbedtls_ecp_restart_muladd_ctx;
/**
* \brief General context for resuming ECC operations
*/
typedef struct
{
unsigned ops_done; /*!< current ops count */
unsigned depth; /*!< call depth (0 = top-level) */
mbedtls_ecp_restart_mul_ctx *rsm; /*!< ecp_mul_comb() sub-context */
mbedtls_ecp_restart_muladd_ctx *ma; /*!< ecp_muladd() sub-context */
} mbedtls_ecp_restart_ctx;
/*
* Operation counts for restartable functions
*/
#define MBEDTLS_ECP_OPS_CHK 3 /*!< basic ops count for ecp_check_pubkey() */
#define MBEDTLS_ECP_OPS_DBL 8 /*!< basic ops count for ecp_double_jac() */
#define MBEDTLS_ECP_OPS_ADD 11 /*!< basic ops count for see ecp_add_mixed() */
#define MBEDTLS_ECP_OPS_INV 120 /*!< empirical equivalent for mpi_mod_inv() */
/**
* \brief Internal; for restartable functions in other modules.
* Check and update basic ops budget.
*
* \param grp Group structure
* \param rs_ctx Restart context
* \param ops Number of basic ops to do
*
* \return \c 0 if doing \p ops basic ops is still allowed,
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS otherwise.
*/
int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp,
mbedtls_ecp_restart_ctx *rs_ctx,
unsigned ops );
/* Utility macro for checking and updating ops budget */
#define MBEDTLS_ECP_BUDGET( ops ) \
MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, rs_ctx, \
(unsigned) (ops) ) );
#else /* MBEDTLS_ECP_RESTARTABLE */
#define MBEDTLS_ECP_BUDGET( ops ) /* no-op; for compatibility */
/* We want to declare restartable versions of existing functions anyway */
typedef void mbedtls_ecp_restart_ctx;
#endif /* MBEDTLS_ECP_RESTARTABLE */
/** /**
* \name SECTION: Module settings * \name SECTION: Module settings
* *
@ -270,6 +338,75 @@ mbedtls_ecp_keypair;
*/ */
#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< The named_curve of ECCurveType. */ #define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< The named_curve of ECCurveType. */
#if defined(MBEDTLS_ECP_RESTARTABLE)
/**
* \brief Set the maximum number of basic operations done in a row.
*
* If more operations are needed to complete a computation,
* #MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the
* function performing the computation. It is then the
* caller's responsibility to either call again with the same
* parameters until it returns 0 or an error code; or to free
* the restart context if the operation is to be aborted.
*
* It is strictly required that all input parameters and the
* restart context be the same on successive calls for the
* same operation, but output parameters need not be the
* same; they must not be used until the function finally
* returns 0.
*
* This only applies to functions whose documentation
* mentions they may return #MBEDTLS_ERR_ECP_IN_PROGRESS (or
* #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS for functions in the
* SSL module). For functions that accept a "restart context"
* argument, passing NULL disables restart and makes the
* function equivalent to the function with the same name
* with \c _restartable removed. For functions in the ECDH
* module, restart is disabled unless the function accepts
* an "ECDH context" argument and
* mbedtls_ecdh_enable_restart() was previously called on
* that context. For function in the SSL module, restart is
* only enabled for specific sides and key exchanges
* (currently only for clients and ECDHE-ECDSA).
*
* \param max_ops Maximum number of basic operations done in a row.
* Default: 0 (unlimited).
* Lower (non-zero) values mean ECC functions will block for
* a lesser maximum amount of time.
*
* \note A "basic operation" is defined as a rough equivalent of a
* multiplication in GF(p) for the NIST P-256 curve.
* As an indication, with default settings, a scalar
* multiplication (full run of \c mbedtls_ecp_mul()) is:
* - about 3300 basic operations for P-256
* - about 9400 basic operations for P-384
*
* \note Very low values are not always respected: sometimes
* functions need to block for a minimum number of
* operations, and will do so even if max_ops is set to a
* lower value. That minimum depends on the curve size, and
* can be made lower by decreasing the value of
* \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, here is the
* lowest effective value for various curves and values of
* that parameter (w for short):
* w=6 w=5 w=4 w=3 w=2
* P-256 208 208 160 136 124
* P-384 682 416 320 272 248
* P-521 1364 832 640 544 496
*
* \note This setting is currently ignored by Curve25519.
*/
void mbedtls_ecp_set_max_ops( unsigned max_ops );
/**
* \brief Check if restart is enabled (max_ops != 0)
*
* \return \c 0 if \c max_ops == 0 (restart disabled)
* \return \c 1 otherwise (restart enabled)
*/
int mbedtls_ecp_restart_is_enabled( void );
#endif /* MBEDTLS_ECP_RESTARTABLE */
/** /**
* \brief This function retrieves the information defined in * \brief This function retrieves the information defined in
* mbedtls_ecp_curve_info() for all supported curves in order * mbedtls_ecp_curve_info() for all supported curves in order
@ -366,6 +503,18 @@ void mbedtls_ecp_group_free( mbedtls_ecp_group *grp );
*/ */
void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key );
#if defined(MBEDTLS_ECP_RESTARTABLE)
/**
* \brief Initialize a restart context
*/
void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx );
/**
* \brief Free the components of a restart context
*/
void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx );
#endif /* MBEDTLS_ECP_RESTARTABLE */
/** /**
* \brief This function copies the contents of point \p Q into * \brief This function copies the contents of point \p Q into
* point \p P. * point \p P.
@ -597,6 +746,36 @@ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *m, const mbedtls_ecp_point *P,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
/**
* \brief This function performs multiplication of a point by
* an integer: \p R = \p m * \p P in a restartable way.
*
* \see mbedtls_ecp_mul()
*
* \note This function does the same as \c mbedtls_ecp_mul(), but
* it can return early and restart according to the limit set
* with \c mbedtls_ecp_set_max_ops() to reduce blocking.
*
* \param grp The ECP group.
* \param R The destination point.
* \param m The integer by which to multiply.
* \param P The point to multiply.
* \param f_rng The RNG function.
* \param p_rng The RNG context.
* \param rs_ctx The restart context (NULL disables restart).
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private
* key, or \p P is not a valid public key.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
*/
int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_mpi *m, const mbedtls_ecp_point *P,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
mbedtls_ecp_restart_ctx *rs_ctx );
/** /**
* \brief This function performs multiplication and addition of two * \brief This function performs multiplication and addition of two
* points by integers: \p R = \p m * \p P + \p n * \p Q * points by integers: \p R = \p m * \p P + \p n * \p Q
@ -623,6 +802,39 @@ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *m, const mbedtls_ecp_point *P,
const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); const mbedtls_mpi *n, const mbedtls_ecp_point *Q );
/**
* \brief This function performs multiplication and addition of two
* points by integers: \p R = \p m * \p P + \p n * \p Q in a
* restartable way.
*
* \see \c mbedtls_ecp_muladd()
*
* \note This function works the same as \c mbedtls_ecp_muladd(),
* but it can return early and restart according to the limit
* set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
*
* \param grp The ECP group.
* \param R The destination point.
* \param m The integer by which to multiply \p P.
* \param P The point to multiply by \p m.
* \param n The integer by which to multiply \p Q.
* \param Q The point to be multiplied by \p n.
* \param rs_ctx The restart context (NULL disables restart).
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not
* valid private keys, or \p P or \p Q are not valid public
* keys.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
*/
int mbedtls_ecp_muladd_restartable(
mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_mpi *m, const mbedtls_ecp_point *P,
const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
mbedtls_ecp_restart_ctx *rs_ctx );
/** /**
* \brief This function checks that a point is a valid public key * \brief This function checks that a point is a valid public key
* on this curve. * on this curve.
@ -665,6 +877,23 @@ int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_po
*/ */
int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ); int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d );
/**
* \brief This function generates a private key.
*
* \param grp The ECP group.
* \param d The destination MPI (secret part).
* \param f_rng The RNG function.
* \param p_rng The RNG parameter.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code
* on failure.
*/
int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
mbedtls_mpi *d,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/** /**
* \brief This function generates a keypair with a configurable base * \brief This function generates a keypair with a configurable base
* point. * point.

View File

@ -80,6 +80,7 @@
* CHACHA20 3 0x0051-0x0055 * CHACHA20 3 0x0051-0x0055
* POLY1305 3 0x0057-0x005B * POLY1305 3 0x0057-0x005B
* CHACHAPOLY 2 0x0054-0x0056 * CHACHAPOLY 2 0x0054-0x0056
* PLATFORM 1 0x0070-0x0072
* *
* High-level module nr (3 bits - 0x0...-0x7...) * High-level module nr (3 bits - 0x0...-0x7...)
* Name ID Nr of Errors * Name ID Nr of Errors
@ -90,12 +91,12 @@
* DHM 3 11 * DHM 3 11
* PK 3 15 (Started from top) * PK 3 15 (Started from top)
* RSA 4 11 * RSA 4 11
* ECP 4 9 (Started from top) * ECP 4 10 (Started from top)
* MD 5 5 * MD 5 5
* HKDF 5 1 (Started from top) * HKDF 5 1 (Started from top)
* CIPHER 6 8 * CIPHER 6 8
* SSL 6 22 (Started from top) * SSL 6 23 (Started from top)
* SSL 7 31 * SSL 7 32
* *
* Module dependent error code (5 bits 0x.00.-0x.F8.) * Module dependent error code (5 bits 0x.00.-0x.F8.)
*/ */

View File

@ -41,7 +41,10 @@
#define MBEDTLS_GCM_DECRYPT 0 #define MBEDTLS_GCM_DECRYPT 0
#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ #define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */
/* MBEDTLS_ERR_GCM_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED -0x0013 /**< GCM hardware accelerator failed. */ #define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED -0x0013 /**< GCM hardware accelerator failed. */
#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ #define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */
#ifdef __cplusplus #ifdef __cplusplus
@ -146,9 +149,9 @@ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
* \return \c 0 if the encryption or decryption was performed * \return \c 0 if the encryption or decryption was performed
* successfully. Note that in #MBEDTLS_GCM_DECRYPT mode, * successfully. Note that in #MBEDTLS_GCM_DECRYPT mode,
* this does not indicate that the data is authentic. * this does not indicate that the data is authentic.
* \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid. * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid or
* \return #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific * a cipher-specific error code if the encryption
* error code if the encryption or decryption failed. * or decryption failed.
*/ */
int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
int mode, int mode,
@ -185,9 +188,8 @@ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
* *
* \return \c 0 if successful and authenticated. * \return \c 0 if successful and authenticated.
* \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match.
* \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid. * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid or
* \return #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific * a cipher-specific error code if the decryption failed.
* error code if the decryption failed.
*/ */
int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
size_t length, size_t length,

View File

@ -39,6 +39,8 @@
#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ #define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */
#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ #define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */
#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ #define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */
/* MBEDTLS_ERR_MD_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_MD_HW_ACCEL_FAILED -0x5280 /**< MD hardware accelerator failed. */ #define MBEDTLS_ERR_MD_HW_ACCEL_FAILED -0x5280 /**< MD hardware accelerator failed. */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -37,6 +37,7 @@
#include <stddef.h> #include <stddef.h>
/* MBEDTLS_ERR_MD2_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED -0x002B /**< MD2 hardware accelerator failed */ #define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED -0x002B /**< MD2 hardware accelerator failed */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -38,6 +38,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
/* MBEDTLS_ERR_MD4_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED -0x002D /**< MD4 hardware accelerator failed */ #define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED -0x002D /**< MD4 hardware accelerator failed */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -37,6 +37,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
/* MBEDTLS_ERR_MD5_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */ #define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -45,6 +45,10 @@
#include "ecdsa.h" #include "ecdsa.h"
#endif #endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#endif
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
!defined(inline) && !defined(__cplusplus) !defined(inline) && !defined(__cplusplus)
#define inline __inline #define inline __inline
@ -64,6 +68,8 @@
#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ #define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */
#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ #define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */
#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The buffer contains a valid signature followed by more data. */ #define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The buffer contains a valid signature followed by more data. */
/* MBEDTLS_ERR_PK_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 /**< PK hardware accelerator failed. */ #define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 /**< PK hardware accelerator failed. */
#ifdef __cplusplus #ifdef __cplusplus
@ -81,6 +87,7 @@ typedef enum {
MBEDTLS_PK_ECDSA, MBEDTLS_PK_ECDSA,
MBEDTLS_PK_RSA_ALT, MBEDTLS_PK_RSA_ALT,
MBEDTLS_PK_RSASSA_PSS, MBEDTLS_PK_RSASSA_PSS,
MBEDTLS_PK_OPAQUE,
} mbedtls_pk_type_t; } mbedtls_pk_type_t;
/** /**
@ -127,10 +134,24 @@ typedef struct mbedtls_pk_info_t mbedtls_pk_info_t;
*/ */
typedef struct mbedtls_pk_context typedef struct mbedtls_pk_context
{ {
const mbedtls_pk_info_t * pk_info; /**< Public key informations */ const mbedtls_pk_info_t * pk_info; /**< Public key information */
void * pk_ctx; /**< Underlying public key context */ void * pk_ctx; /**< Underlying public key context */
} mbedtls_pk_context; } mbedtls_pk_context;
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/**
* \brief Context for resuming operations
*/
typedef struct
{
const mbedtls_pk_info_t * pk_info; /**< Public key information */
void * rs_ctx; /**< Underlying restart context */
} mbedtls_pk_restart_ctx;
#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
/* Now we can declare functions that take a pointer to that */
typedef void mbedtls_pk_restart_ctx;
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
/** /**
* Quick access to an RSA context inside a PK context. * Quick access to an RSA context inside a PK context.
@ -187,9 +208,26 @@ void mbedtls_pk_init( mbedtls_pk_context *ctx );
/** /**
* \brief Free a mbedtls_pk_context * \brief Free a mbedtls_pk_context
*
* \note For contexts that have been set up with
* mbedtls_pk_setup_opaque(), this does not free the underlying
* key slot and you still need to call psa_destroy_key()
* independently if you want to destroy that key.
*/ */
void mbedtls_pk_free( mbedtls_pk_context *ctx ); void mbedtls_pk_free( mbedtls_pk_context *ctx );
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/**
* \brief Initialize a restart context
*/
void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx );
/**
* \brief Free the components of a restart context
*/
void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx );
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
/** /**
* \brief Initialize a PK context with the information given * \brief Initialize a PK context with the information given
* and allocates the type-specific PK subcontext. * and allocates the type-specific PK subcontext.
@ -206,6 +244,38 @@ void mbedtls_pk_free( mbedtls_pk_context *ctx );
*/ */
int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/**
* \brief Initialize a PK context to wrap a PSA key slot.
*
* \note This function replaces mbedtls_pk_setup() for contexts
* that wrap a (possibly opaque) PSA key slot instead of
* storing and manipulating the key material directly.
*
* \param ctx The context to initialize. It must be empty (type NONE).
* \param key The PSA key slot to wrap, which must hold an ECC key pair
* (see notes below).
*
* \note The wrapped key slot must remain valid as long as the
* wrapping PK context is in use, that is at least between
* the point this function is called and the point
* mbedtls_pk_free() is called on this context. The wrapped
* key slot might then be independently used or destroyed.
*
* \note This function is currently only available for ECC key
* pairs (that is, ECC keys containing private key material).
* Support for other key types may be added later.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input
* (context already used, invalid key slot).
* \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an
* ECC key pair.
* \return #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure.
*/
int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx, const psa_key_slot_t key );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
/** /**
* \brief Initialize an RSA-alt context * \brief Initialize an RSA-alt context
@ -286,6 +356,32 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len, const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len ); const unsigned char *sig, size_t sig_len );
/**
* \brief Restartable version of \c mbedtls_pk_verify()
*
* \note Performs the same job as \c mbedtls_pk_verify(), but can
* return early and restart according to the limit set with
* \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC
* operations. For RSA, same as \c mbedtls_pk_verify().
*
* \param ctx PK context to use
* \param md_alg Hash algorithm used (see notes)
* \param hash Hash of the message to sign
* \param hash_len Hash length or 0 (see notes)
* \param sig Signature to verify
* \param sig_len Signature length
* \param rs_ctx Restart context (NULL to disable restart)
*
* \return See \c mbedtls_pk_verify(), or
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
*/
int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len,
mbedtls_pk_restart_ctx *rs_ctx );
/** /**
* \brief Verify signature, with options. * \brief Verify signature, with options.
* (Includes verification of the padding depending on type.) * (Includes verification of the padding depending on type.)
@ -349,6 +445,35 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
unsigned char *sig, size_t *sig_len, unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
/**
* \brief Restartable version of \c mbedtls_pk_sign()
*
* \note Performs the same job as \c mbedtls_pk_sign(), but can
* return early and restart according to the limit set with
* \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC
* operations. For RSA, same as \c mbedtls_pk_sign().
*
* \param ctx PK context to use - must hold a private key
* \param md_alg Hash algorithm used (see notes)
* \param hash Hash of the message to sign
* \param hash_len Hash length or 0 (see notes)
* \param sig Place to write the signature
* \param sig_len Number of bytes written
* \param f_rng RNG function
* \param p_rng RNG parameter
* \param rs_ctx Restart context (NULL to disable restart)
*
* \return See \c mbedtls_pk_sign(), or
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
*/
int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
mbedtls_pk_restart_ctx *rs_ctx );
/** /**
* \brief Decrypt message (including padding if relevant). * \brief Decrypt message (including padding if relevant).
* *
@ -397,7 +522,11 @@ int mbedtls_pk_encrypt( mbedtls_pk_context *ctx,
* \param pub Context holding a public key. * \param pub Context holding a public key.
* \param prv Context holding a private (and public) key. * \param prv Context holding a private (and public) key.
* *
* \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA * \return \c 0 on success (keys were checked and match each other).
* \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not
* be checked - in that case they may or may not match.
* \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid.
* \return Another non-zero value if the keys do not match.
*/ */
int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ); int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv );
@ -611,6 +740,31 @@ int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ); int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n );
#endif #endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/**
* \brief Turn an EC key into an Opaque one
*
* \warning This is a temporary utility function for tests. It might
* change or be removed at any time without notice.
*
* \note Only ECDSA keys are supported so far. Signing with the
* specified hash is the only allowed use of that key.
*
* \param pk Input: the EC key to transfer to a PSA key slot.
* Output: a PK context wrapping that PSA key slot.
* \param slot Output: the chosen slot for storing the key.
* It's the caller's responsibility to destroy that slot
* after calling mbedtls_pk_free() on the PK context.
* \param hash_alg The hash algorithm to allow for use with that key.
*
* \return \c 0 if successful.
* \return An Mbed TLS error code otherwise.
*/
int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk,
psa_key_slot_t *slot,
psa_algorithm_t hash_alg );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -59,6 +59,21 @@ struct mbedtls_pk_info_t
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng ); void *p_rng );
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/** Verify signature (restartable) */
int (*verify_rs_func)( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len,
void *rs_ctx );
/** Make signature (restartable) */
int (*sign_rs_func)( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng, void *rs_ctx );
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
/** Decrypt message */ /** Decrypt message */
int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen, size_t osize, unsigned char *output, size_t *olen, size_t osize,
@ -80,6 +95,14 @@ struct mbedtls_pk_info_t
/** Free the given context */ /** Free the given context */
void (*ctx_free_func)( void *ctx ); void (*ctx_free_func)( void *ctx );
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/** Allocate the restart context */
void * (*rs_alloc_func)( void );
/** Free the restart context */
void (*rs_free_func)( void *rs_ctx );
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
/** Interface with the debug module */ /** Interface with the debug module */
void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items );
@ -112,4 +135,8 @@ extern const mbedtls_pk_info_t mbedtls_ecdsa_info;
extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; extern const mbedtls_pk_info_t mbedtls_rsa_alt_info;
#endif #endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
extern const mbedtls_pk_info_t mbedtls_pk_opaque_info;
#endif
#endif /* MBEDTLS_PK_WRAP_H */ #endif /* MBEDTLS_PK_WRAP_H */

View File

@ -43,6 +43,9 @@
#include "platform_time.h" #include "platform_time.h"
#endif #endif
#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 /**< Hardware accelerator failed */
#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 /**< The requested feature is not supported by the platform */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View File

@ -43,7 +43,13 @@
#include <stddef.h> #include <stddef.h>
#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 /**< Invalid input parameter(s). */ #define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 /**< Invalid input parameter(s). */
/* MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE is deprecated and should not be
* used. */
#define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE -0x0059 /**< Feature not available. For example, s part of the API is not implemented. */ #define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE -0x0059 /**< Feature not available. For example, s part of the API is not implemented. */
/* MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED is deprecated and should not be used.
*/
#define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED -0x005B /**< Poly1305 hardware accelerator failed. */ #define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED -0x005B /**< Poly1305 hardware accelerator failed. */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -0,0 +1,264 @@
/**
* \file psa_util.h
*
* \brief Utility functions for the use of the PSA Crypto library.
*
* \warning This function is not part of the public API and may
* change at any time.
*/
/*
* Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_PSA_UTIL_H
#define MBEDTLS_PSA_UTIL_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#include "ecp.h"
#include "md.h"
#include "pk.h"
/* Slot allocation */
static inline psa_status_t mbedtls_psa_get_free_key_slot( psa_key_slot_t *key )
{
for( psa_key_slot_t slot = 1; slot <= 32; slot++ )
{
if( psa_get_key_information( slot, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT )
{
*key = slot;
return( PSA_SUCCESS );
}
}
return( PSA_ERROR_INSUFFICIENT_MEMORY );
}
/* Translations for symmetric crypto. */
static inline psa_key_type_t mbedtls_psa_translate_cipher_type(
mbedtls_cipher_type_t cipher )
{
switch( cipher )
{
case MBEDTLS_CIPHER_AES_128_CCM:
case MBEDTLS_CIPHER_AES_192_CCM:
case MBEDTLS_CIPHER_AES_256_CCM:
case MBEDTLS_CIPHER_AES_128_GCM:
case MBEDTLS_CIPHER_AES_192_GCM:
case MBEDTLS_CIPHER_AES_256_GCM:
case MBEDTLS_CIPHER_AES_128_CBC:
case MBEDTLS_CIPHER_AES_192_CBC:
case MBEDTLS_CIPHER_AES_256_CBC:
return( PSA_KEY_TYPE_AES );
/* ARIA not yet supported in PSA. */
/* case MBEDTLS_CIPHER_ARIA_128_CCM:
case MBEDTLS_CIPHER_ARIA_192_CCM:
case MBEDTLS_CIPHER_ARIA_256_CCM:
case MBEDTLS_CIPHER_ARIA_128_GCM:
case MBEDTLS_CIPHER_ARIA_192_GCM:
case MBEDTLS_CIPHER_ARIA_256_GCM:
case MBEDTLS_CIPHER_ARIA_128_CBC:
case MBEDTLS_CIPHER_ARIA_192_CBC:
case MBEDTLS_CIPHER_ARIA_256_CBC:
return( PSA_KEY_TYPE_ARIA ); */
default:
return( 0 );
}
}
static inline psa_algorithm_t mbedtls_psa_translate_cipher_mode(
mbedtls_cipher_mode_t mode, size_t taglen )
{
switch( mode )
{
case MBEDTLS_MODE_GCM:
return( PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, taglen ) );
case MBEDTLS_MODE_CCM:
return( PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, taglen ) );
case MBEDTLS_MODE_CBC:
if( taglen == 0 )
return( PSA_ALG_CBC_NO_PADDING );
/* Intentional fallthrough for taglen != 0 */
default:
return( 0 );
}
}
static inline psa_key_usage_t mbedtls_psa_translate_cipher_operation(
mbedtls_operation_t op )
{
switch( op )
{
case MBEDTLS_ENCRYPT:
return( PSA_KEY_USAGE_ENCRYPT );
case MBEDTLS_DECRYPT:
return( PSA_KEY_USAGE_DECRYPT );
default:
return( 0 );
}
}
/* Translations for hashing. */
static inline psa_algorithm_t mbedtls_psa_translate_md( mbedtls_md_type_t md_alg )
{
switch( md_alg )
{
#if defined(MBEDTLS_MD2_C)
case MBEDTLS_MD_MD2:
return( PSA_ALG_MD2 );
#endif
#if defined(MBEDTLS_MD4_C)
case MBEDTLS_MD_MD4:
return( PSA_ALG_MD4 );
#endif
#if defined(MBEDTLS_MD5_C)
case MBEDTLS_MD_MD5:
return( PSA_ALG_MD5 );
#endif
#if defined(MBEDTLS_SHA1_C)
case MBEDTLS_MD_SHA1:
return( PSA_ALG_SHA_1 );
#endif
#if defined(MBEDTLS_SHA256_C)
case MBEDTLS_MD_SHA224:
return( PSA_ALG_SHA_224 );
case MBEDTLS_MD_SHA256:
return( PSA_ALG_SHA_256 );
#endif
#if defined(MBEDTLS_SHA512_C)
case MBEDTLS_MD_SHA384:
return( PSA_ALG_SHA_384 );
case MBEDTLS_MD_SHA512:
return( PSA_ALG_SHA_512 );
#endif
#if defined(MBEDTLS_RIPEMD160_C)
case MBEDTLS_MD_RIPEMD160:
return( PSA_ALG_RIPEMD160 );
#endif
case MBEDTLS_MD_NONE: /* Intentional fallthrough */
default:
return( 0 );
}
}
/* Translations for ECC. */
static inline psa_ecc_curve_t mbedtls_psa_translate_ecc_group( mbedtls_ecp_group_id grpid )
{
switch( grpid )
{
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
case MBEDTLS_ECP_DP_SECP192R1:
return( PSA_ECC_CURVE_SECP192R1 );
#endif
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
case MBEDTLS_ECP_DP_SECP224R1:
return( PSA_ECC_CURVE_SECP224R1 );
#endif
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
case MBEDTLS_ECP_DP_SECP256R1:
return( PSA_ECC_CURVE_SECP256R1 );
#endif
#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
case MBEDTLS_ECP_DP_SECP384R1:
return( PSA_ECC_CURVE_SECP384R1 );
#endif
#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
case MBEDTLS_ECP_DP_SECP521R1:
return( PSA_ECC_CURVE_SECP521R1 );
#endif
#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
case MBEDTLS_ECP_DP_BP256R1:
return( PSA_ECC_CURVE_BRAINPOOL_P256R1 );
#endif
#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
case MBEDTLS_ECP_DP_BP384R1:
return( PSA_ECC_CURVE_BRAINPOOL_P384R1 );
#endif
#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
case MBEDTLS_ECP_DP_BP512R1:
return( PSA_ECC_CURVE_BRAINPOOL_P512R1 );
#endif
#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
case MBEDTLS_ECP_DP_CURVE25519:
return( PSA_ECC_CURVE_CURVE25519 );
#endif
#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
case MBEDTLS_ECP_DP_SECP192K1:
return( PSA_ECC_CURVE_SECP192K1 );
#endif
#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
case MBEDTLS_ECP_DP_SECP224K1:
return( PSA_ECC_CURVE_SECP224K1 );
#endif
#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
case MBEDTLS_ECP_DP_SECP256K1:
return( PSA_ECC_CURVE_SECP256K1 );
#endif
#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
case MBEDTLS_ECP_DP_CURVE448:
return( PSA_ECC_CURVE_CURVE448 );
#endif
default:
return( 0 );
}
}
/* Translations for PK layer */
static inline int mbedtls_psa_err_translate_pk( psa_status_t status )
{
switch( status )
{
case PSA_SUCCESS:
return( 0 );
case PSA_ERROR_NOT_SUPPORTED:
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
case PSA_ERROR_INSUFFICIENT_MEMORY:
return( MBEDTLS_ERR_PK_ALLOC_FAILED );
case PSA_ERROR_INSUFFICIENT_ENTROPY:
return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
case PSA_ERROR_BAD_STATE:
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
/* All other failures */
case PSA_ERROR_COMMUNICATION_FAILURE:
case PSA_ERROR_HARDWARE_FAILURE:
case PSA_ERROR_TAMPERING_DETECTED:
return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
default: /* We return the same as for the 'other failures',
* but list them separately nonetheless to indicate
* which failure conditions we have considered. */
return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
}
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_PSA_UTIL_H */

View File

@ -33,6 +33,8 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
/* MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED is deprecated and should not be used.
*/
#define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED -0x0031 /**< RIPEMD160 hardware accelerator failed */ #define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED -0x0031 /**< RIPEMD160 hardware accelerator failed */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -55,7 +55,12 @@
#define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ #define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */
#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ #define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */
#define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ #define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */
/* MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION is deprecated and should not be used.
*/
#define MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION -0x4500 /**< The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */ #define MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION -0x4500 /**< The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */
/* MBEDTLS_ERR_RSA_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_RSA_HW_ACCEL_FAILED -0x4580 /**< RSA hardware accelerator failed. */ #define MBEDTLS_ERR_RSA_HW_ACCEL_FAILED -0x4580 /**< RSA hardware accelerator failed. */
/* /*
@ -281,7 +286,7 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx );
* zero Bytes. * zero Bytes.
* *
* Possible reasons for returning * Possible reasons for returning
* #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION:<ul> * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:<ul>
* <li>An alternative RSA implementation is in use, which * <li>An alternative RSA implementation is in use, which
* stores the key externally, and either cannot or should * stores the key externally, and either cannot or should
* not export it into RAM.</li> * not export it into RAM.</li>
@ -301,7 +306,7 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx );
* \param E The MPI to hold the public exponent, or NULL. * \param E The MPI to hold the public exponent, or NULL.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the
* requested parameters cannot be done due to missing * requested parameters cannot be done due to missing
* functionality or because of security policies. * functionality or because of security policies.
* \return A non-zero return code on any other failure. * \return A non-zero return code on any other failure.
@ -321,7 +326,7 @@ int mbedtls_rsa_export( const mbedtls_rsa_context *ctx,
* zero Bytes. * zero Bytes.
* *
* Possible reasons for returning * Possible reasons for returning
* #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION:<ul> * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:<ul>
* <li>An alternative RSA implementation is in use, which * <li>An alternative RSA implementation is in use, which
* stores the key externally, and either cannot or should * stores the key externally, and either cannot or should
* not export it into RAM.</li> * not export it into RAM.</li>
@ -350,7 +355,7 @@ int mbedtls_rsa_export( const mbedtls_rsa_context *ctx,
* \param E_len The size of the buffer for the public exponent. * \param E_len The size of the buffer for the public exponent.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the
* requested parameters cannot be done due to missing * requested parameters cannot be done due to missing
* functionality or because of security policies. * functionality or because of security policies.
* \return A non-zero return code on any other failure. * \return A non-zero return code on any other failure.
@ -563,7 +568,7 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
* *
* \note Alternative implementations of RSA need not support * \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PRIVATE and might instead * mode being set to #MBEDTLS_RSA_PRIVATE and might instead
* return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
* *
* \param ctx The RSA context. * \param ctx The RSA context.
* \param f_rng The RNG function. Needed for padding, PKCS#1 v2.1 * \param f_rng The RNG function. Needed for padding, PKCS#1 v2.1
@ -598,7 +603,7 @@ int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx,
* *
* \note Alternative implementations of RSA need not support * \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PRIVATE and might instead * mode being set to #MBEDTLS_RSA_PRIVATE and might instead
* return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
* *
* \param ctx The RSA context. * \param ctx The RSA context.
* \param f_rng The RNG function. Needed for padding and * \param f_rng The RNG function. Needed for padding and
@ -633,7 +638,7 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx,
* *
* \note Alternative implementations of RSA need not support * \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PRIVATE and might instead * mode being set to #MBEDTLS_RSA_PRIVATE and might instead
* return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
* *
* \param ctx The RSA context. * \param ctx The RSA context.
* \param f_rng The RNG function. Needed for padding and PKCS#1 v2.1 * \param f_rng The RNG function. Needed for padding and PKCS#1 v2.1
@ -682,7 +687,7 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx,
* *
* \note Alternative implementations of RSA need not support * \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PUBLIC and might instead * mode being set to #MBEDTLS_RSA_PUBLIC and might instead
* return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
* *
* \param ctx The RSA context. * \param ctx The RSA context.
* \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE.
@ -725,7 +730,7 @@ int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx,
* *
* \note Alternative implementations of RSA need not support * \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PUBLIC and might instead * mode being set to #MBEDTLS_RSA_PUBLIC and might instead
* return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
* *
* \param ctx The RSA context. * \param ctx The RSA context.
* \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE.
@ -770,7 +775,7 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
* *
* \note Alternative implementations of RSA need not support * \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PUBLIC and might instead * mode being set to #MBEDTLS_RSA_PUBLIC and might instead
* return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
* *
* \param ctx The RSA context. * \param ctx The RSA context.
* \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE.
@ -817,7 +822,7 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx,
* *
* \note Alternative implementations of RSA need not support * \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PUBLIC and might instead * mode being set to #MBEDTLS_RSA_PUBLIC and might instead
* return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
* *
* \param ctx The RSA context. * \param ctx The RSA context.
* \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for
@ -856,7 +861,7 @@ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx,
* *
* \note Alternative implementations of RSA need not support * \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PUBLIC and might instead * mode being set to #MBEDTLS_RSA_PUBLIC and might instead
* return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
* *
* \param ctx The RSA context. * \param ctx The RSA context.
* \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE.
@ -894,6 +899,16 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx,
* Specifications</em> it is advised to keep both hashes the * Specifications</em> it is advised to keep both hashes the
* same. * same.
* *
* \note This function always uses the maximum possible salt size,
* up to the length of the payload hash. This choice of salt
* size complies with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1
* v2.2) §9.1.1 step 3. Furthermore this function enforces a
* minimum salt size which is the hash size minus 2 bytes. If
* this minimum size is too large given the key size (the salt
* size, plus the hash size, plus 2 bytes must be no more than
* the key size in bytes), this function returns
* #MBEDTLS_ERR_RSA_BAD_INPUT_DATA.
*
* \deprecated It is deprecated and discouraged to call this function * \deprecated It is deprecated and discouraged to call this function
* in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library
* are likely to remove the \p mode argument and have it * are likely to remove the \p mode argument and have it
@ -901,7 +916,7 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx,
* *
* \note Alternative implementations of RSA need not support * \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PUBLIC and might instead * mode being set to #MBEDTLS_RSA_PUBLIC and might instead
* return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
* *
* \param ctx The RSA context. * \param ctx The RSA context.
* \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for
@ -947,7 +962,7 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
* *
* \note Alternative implementations of RSA need not support * \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PRIVATE and might instead * mode being set to #MBEDTLS_RSA_PRIVATE and might instead
* return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
* *
* \param ctx The RSA public key context. * \param ctx The RSA public key context.
* \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE.
@ -985,7 +1000,7 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx,
* *
* \note Alternative implementations of RSA need not support * \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PRIVATE and might instead * mode being set to #MBEDTLS_RSA_PRIVATE and might instead
* return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
* *
* \param ctx The RSA public key context. * \param ctx The RSA public key context.
* \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE.
@ -1034,7 +1049,7 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx,
* *
* \note Alternative implementations of RSA need not support * \note Alternative implementations of RSA need not support
* mode being set to #MBEDTLS_RSA_PRIVATE and might instead * mode being set to #MBEDTLS_RSA_PRIVATE and might instead
* return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
* *
* \param ctx The RSA public key context. * \param ctx The RSA public key context.
* \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE.

View File

@ -40,6 +40,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
/* MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED -0x0035 /**< SHA-1 hardware accelerator failed */ #define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED -0x0035 /**< SHA-1 hardware accelerator failed */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -36,6 +36,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
/* MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */ #define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -35,6 +35,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
/* MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED -0x0039 /**< SHA-512 hardware accelerator failed */ #define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED -0x0039 /**< SHA-512 hardware accelerator failed */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -65,6 +65,10 @@
#include "platform_time.h" #include "platform_time.h"
#endif #endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/* /*
* SSL Error codes * SSL Error codes
*/ */
@ -122,6 +126,7 @@
#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /**< Internal-only message signaling that further message-processing should be done */ #define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /**< Internal-only message signaling that further message-processing should be done */
#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /**< The asynchronous operation is not completed yet. */ #define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /**< The asynchronous operation is not completed yet. */
#define MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480 /**< Internal-only message signaling that a message arrived early. */ #define MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480 /**< Internal-only message signaling that a message arrived early. */
#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 /**< A cryptographic operation is in progress. Try again later. */
/* /*
* Various constants * Various constants
@ -922,19 +927,37 @@ struct mbedtls_ssl_config
#endif #endif
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
unsigned char *psk; /*!< pre-shared key. This field should
only be set via #if defined(MBEDTLS_USE_PSA_CRYPTO)
mbedtls_ssl_conf_psk() */ psa_key_slot_t psk_opaque; /*!< PSA key slot holding opaque PSK.
size_t psk_len; /*!< length of the pre-shared key. This * This field should only be set via
field should only be set via * mbedtls_ssl_conf_psk_opaque().
mbedtls_ssl_conf_psk() */ * If either no PSK or a raw PSK have
unsigned char *psk_identity; /*!< identity for PSK negotiation. This * been configured, this has value \c 0. */
field should only be set via #endif /* MBEDTLS_USE_PSA_CRYPTO */
mbedtls_ssl_conf_psk() */
size_t psk_identity_len;/*!< length of identity. This field should unsigned char *psk; /*!< The raw pre-shared key. This field should
only be set via * only be set via mbedtls_ssl_conf_psk().
mbedtls_ssl_conf_psk() */ * If either no PSK or an opaque PSK
#endif * have been configured, this has value NULL. */
size_t psk_len; /*!< The length of the raw pre-shared key.
* This field should only be set via
* mbedtls_ssl_conf_psk().
* Its value is non-zero if and only if
* \c psk is not \c NULL. */
unsigned char *psk_identity; /*!< The PSK identity for PSK negotiation.
* This field should only be set via
* mbedtls_ssl_conf_psk().
* This is set if and only if either
* \c psk or \c psk_opaque are set. */
size_t psk_identity_len;/*!< The length of PSK identity.
* This field should only be set via
* mbedtls_ssl_conf_psk().
* Its value is non-zero if and only if
* \c psk is not \c NULL or \c psk_opaque
* is not \c 0. */
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
#if defined(MBEDTLS_SSL_ALPN) #if defined(MBEDTLS_SSL_ALPN)
const char **alpn_list; /*!< ordered list of protocols */ const char **alpn_list; /*!< ordered list of protocols */
@ -2056,68 +2079,146 @@ int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf,
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
/** /**
* \brief Set the Pre Shared Key (PSK) and the expected identity name * \brief Configure a pre-shared key (PSK) and identity
* to be used in PSK-based ciphersuites.
* *
* \note This is mainly useful for clients. Servers will usually * \note This is mainly useful for clients. Servers will usually
* want to use \c mbedtls_ssl_conf_psk_cb() instead. * want to use \c mbedtls_ssl_conf_psk_cb() instead.
* *
* \note Currently clients can only register one pre-shared key. * \warning Currently, clients can only register a single pre-shared key.
* In other words, the servers' identity hint is ignored. * 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 * Support for setting multiple PSKs on clients and selecting
* one based on the identity hint is not a planned feature but * one based on the identity hint is not a planned feature,
* feedback is welcomed. * but feedback is welcomed.
* *
* \param conf SSL configuration * \param conf The SSL configuration to register the PSK with.
* \param psk pointer to the pre-shared key * \param psk The pointer to the pre-shared key to use.
* \param psk_len pre-shared key length * \param psk_len The length of the pre-shared key in bytes.
* \param psk_identity pointer to the pre-shared key identity * \param psk_identity The pointer to the pre-shared key identity.
* \param psk_identity_len identity key length * \param psk_identity_len The length of the pre-shared key identity
* in bytes.
* *
* \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED * \note The PSK and its identity are copied internally and
* hence need not be preserved by the caller for the lifetime
* of the SSL configuration.
*
* \return \c 0 if successful.
* \return An \c MBEDTLS_ERR_SSL_XXX error code on failure.
*/ */
int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf,
const unsigned char *psk, size_t psk_len, const unsigned char *psk, size_t psk_len,
const unsigned char *psk_identity, size_t psk_identity_len ); const unsigned char *psk_identity, size_t psk_identity_len );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/**
* \brief Configure an opaque pre-shared key (PSK) and identity
* to be used in PSK-based ciphersuites.
*
* \note This is mainly useful for clients. Servers will usually
* want to use \c mbedtls_ssl_conf_psk_cb() instead.
*
* \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
* called again, the key slot \p psk must be populated with a
* key of type #PSA_ALG_CATEGORY_KEY_DERIVATION whose policy
* allows its use for the key derivation algorithm applied
* in the handshake.
* \param psk_identity The pointer to the pre-shared key identity.
* \param psk_identity_len The length of the pre-shared key identity
* in bytes.
*
* \note The PSK identity hint is copied internally and hence need
* not be preserved by the caller for the lifetime of the
* SSL configuration.
*
* \return \c 0 if successful.
* \return An \c MBEDTLS_ERR_SSL_XXX error code on failure.
*/
int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf,
psa_key_slot_t psk,
const unsigned char *psk_identity,
size_t psk_identity_len );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/** /**
* \brief Set the Pre Shared Key (PSK) for the current handshake * \brief Set the pre-shared Key (PSK) for the current handshake.
* *
* \note This should only be called inside the PSK callback, * \note This should only be called inside the PSK callback,
* ie the function passed to \c mbedtls_ssl_conf_psk_cb(). * i.e. the function passed to \c mbedtls_ssl_conf_psk_cb().
* *
* \param ssl SSL context * \param ssl The SSL context to configure a PSK for.
* \param psk pointer to the pre-shared key * \param psk The pointer to the pre-shared key.
* \param psk_len pre-shared key length * \param psk_len The length of the pre-shared key in bytes.
* *
* \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED * \return \c 0 if successful.
* \return An \c MBEDTLS_ERR_SSL_XXX error code on failure.
*/ */
int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl,
const unsigned char *psk, size_t psk_len ); const unsigned char *psk, size_t psk_len );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/**
* \brief Set an opaque pre-shared Key (PSK) for the current handshake.
*
* \note This should only be called inside the PSK callback,
* i.e. the function passed to \c mbedtls_ssl_conf_psk_cb().
*
* \param ssl The SSL context to configure a PSK for.
* \param psk The identifier of the key slot holding the PSK.
* For the duration of the current handshake, the key slot
* must be populated with a key of type
* #PSA_ALG_CATEGORY_KEY_DERIVATION whose policy allows its
* use for the key derivation algorithm
* applied in the handshake.
*
* \return \c 0 if successful.
* \return An \c MBEDTLS_ERR_SSL_XXX error code on failure.
*/
int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl,
psa_key_slot_t psk );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/** /**
* \brief Set the PSK callback (server-side only). * \brief Set the PSK callback (server-side only).
* *
* If set, the PSK callback is called for each * If set, the PSK callback is called for each
* handshake where a PSK ciphersuite was negotiated. * handshake where a PSK-based ciphersuite was negotiated.
* The caller provides the identity received and wants to * The caller provides the identity received and wants to
* receive the actual PSK data and length. * receive the actual PSK data and length.
* *
* The callback has the following parameters: (void *parameter, * The callback has the following parameters:
* mbedtls_ssl_context *ssl, const unsigned char *psk_identity, * - \c void*: The opaque pointer \p p_psk.
* size_t identity_len) * - \c mbedtls_ssl_context*: The SSL context to which
* the operation applies.
* - \c const unsigned char*: The PSK identity
* selected by the client.
* - \c size_t: The length of the PSK identity
* selected by the client.
*
* If a valid PSK identity is found, the callback should use * If a valid PSK identity is found, the callback should use
* \c mbedtls_ssl_set_hs_psk() on the ssl context to set the * \c mbedtls_ssl_set_hs_psk() or
* correct PSK and return 0. * \c mbedtls_ssl_set_hs_psk_opaque()
* on the SSL context to set the correct PSK and return \c 0.
* Any other return value will result in a denied PSK identity. * Any other return value will result in a denied PSK identity.
* *
* \note If you set a PSK callback using this function, then you * \note If you set a PSK callback using this function, then you
* don't need to set a PSK key and identity using * don't need to set a PSK key and identity using
* \c mbedtls_ssl_conf_psk(). * \c mbedtls_ssl_conf_psk().
* *
* \param conf SSL configuration * \param conf The SSL configuration to register the callback with.
* \param f_psk PSK identity function * \param f_psk The callback for selecting and setting the PSK based
* \param p_psk PSK identity parameter * in the PSK identity chosen by the client.
* \param p_psk A pointer to an opaque structure to be passed to
* the callback, for example a PSK store.
*/ */
void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf,
int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *,
@ -2773,13 +2874,14 @@ size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl );
/** /**
* \brief Return the result of the certificate verification * \brief Return the result of the certificate verification
* *
* \param ssl SSL context * \param ssl The SSL context to use.
* *
* \return 0 if successful, * \return \c 0 if the certificate verification was successful.
* -1 if result is not available (eg because the handshake was * \return \c -1u if the result is not available. This may happen
* aborted too early), or * e.g. if the handshake aborts early, or a verification
* a combination of BADCERT_xxx and BADCRL_xxx flags, see * callback returned a fatal error.
* x509.h * \return A bitwise combination of \c MBEDTLS_X509_BADCERT_XXX
* and \c MBEDTLS_X509_BADCRL_XXX failure flags; see x509.h.
*/ */
uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ); uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl );
@ -2913,35 +3015,50 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session
* *
* \param ssl SSL context * \param ssl SSL context
* *
* \return 0 if successful, or * \return \c 0 if successful.
* MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE
* MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or * if the handshake is incomplete and waiting for data to
* a specific SSL error code. * be available for reading from or writing to the underlying
* transport - in this case you must call this function again
* when the underlying transport is ready for the operation.
* \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous
* operation is in progress (see
* mbedtls_ssl_conf_async_private_cb()) - in this case you
* must call this function again when the operation is ready.
* \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic
* operation is in progress (see mbedtls_ecp_set_max_ops()) -
* in this case you must call this function again to complete
* the handshake when you're done attending other tasks.
* \return #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use
* and the client did not demonstrate reachability yet - in
* this case you must stop using the context (see below).
* \return Another SSL error code - in this case you must stop using
* the context (see below).
* *
* If this function returns MBEDTLS_ERR_SSL_WANT_READ, the * \warning If this function returns something other than
* handshake is unfinished and no further data is available * \c 0,
* from the underlying transport. In this case, you must call * #MBEDTLS_ERR_SSL_WANT_READ,
* the function again at some later stage. * #MBEDTLS_ERR_SSL_WANT_WRITE,
* #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
* #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS,
* you must stop using the SSL context for reading or writing,
* and either free it or call \c mbedtls_ssl_session_reset()
* on it before re-using it for a new connection; the current
* connection must be closed.
*
* \note If DTLS is in use, then you may choose to handle
* #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging
* purposes, as it is an expected return value rather than an
* actual error, but you still need to reset/free the context.
* *
* \note Remarks regarding event-driven DTLS: * \note Remarks regarding event-driven DTLS:
* If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram * If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram
* from the underlying transport layer is currently being processed, * from the underlying transport layer is currently being processed,
* and it is safe to idle until the timer or the underlying transport * and it is safe to idle until the timer or the underlying transport
* signal a new event. This is not true for a successful handshake, * signal a new event. This is not true for a successful handshake,
* in which case the datagram of the underlying transport that is * in which case the datagram of the underlying transport that is
* currently being processed might or might not contain further * currently being processed might or might not contain further
* DTLS records. * DTLS records.
*
* \note If this function returns something other than 0 or
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
* the SSL context for reading or writing, and either free it or
* call \c mbedtls_ssl_session_reset() on it before re-using it
* for a new connection; the current connection must be closed.
*
* \note If DTLS is in use, then you may choose to handle
* MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging
* purposes, as it is an expected return value rather than an
* actual error, but you still need to reset/free the context.
*/ */
int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl );
@ -2949,20 +3066,21 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl );
* \brief Perform a single step of the SSL handshake * \brief Perform a single step of the SSL handshake
* *
* \note The state of the context (ssl->state) will be at * \note The state of the context (ssl->state) will be at
* the next state after execution of this function. Do not * the next state after this function returns \c 0. Do not
* call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER.
* *
* \note If this function returns something other than 0 or
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
* the SSL context for reading or writing, and either free it or
* call \c mbedtls_ssl_session_reset() on it before re-using it
* for a new connection; the current connection must be closed.
*
* \param ssl SSL context * \param ssl SSL context
* *
* \return 0 if successful, or * \return See mbedtls_ssl_handshake().
* MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or *
* a specific SSL error code. * \warning If this function returns something other than \c 0,
* #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE,
* #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
* #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using
* the SSL context for reading or writing, and either free it
* or call \c mbedtls_ssl_session_reset() on it before
* re-using it for a new connection; the current connection
* must be closed.
*/ */
int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl );
@ -2977,13 +3095,18 @@ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl );
* \param ssl SSL context * \param ssl SSL context
* *
* \return 0 if successful, or any mbedtls_ssl_handshake() return * \return 0 if successful, or any mbedtls_ssl_handshake() return
* value. * value except #MBEDTLS_ERR_SSL_CLIENT_RECONNECT that can't
* happen during a renegotiation.
*
* \warning If this function returns something other than \c 0,
* #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE,
* #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
* #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using
* the SSL context for reading or writing, and either free it
* or call \c mbedtls_ssl_session_reset() on it before
* re-using it for a new connection; the current connection
* must be closed.
* *
* \note If this function returns something other than 0 or
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
* the SSL context for reading or writing, and either free it or
* call \c mbedtls_ssl_session_reset() on it before re-using it
* for a new connection; the current connection must be closed.
*/ */
int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_SSL_RENEGOTIATION */ #endif /* MBEDTLS_SSL_RENEGOTIATION */
@ -2995,42 +3118,56 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl );
* \param buf buffer that will hold the data * \param buf buffer that will hold the data
* \param len maximum number of bytes to read * \param len maximum number of bytes to read
* *
* \return One of the following: * \return The (positive) number of bytes read if successful.
* - 0 if the read end of the underlying transport was closed, * \return \c 0 if the read end of the underlying transport was closed
* - the (positive) number of bytes read, or * - in this case you must stop using the context (see below).
* - a negative error code on failure. * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE
* if the handshake is incomplete and waiting for data to
* be available for reading from or writing to the underlying
* transport - in this case you must call this function again
* when the underlying transport is ready for the operation.
* \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous
* operation is in progress (see
* mbedtls_ssl_conf_async_private_cb()) - in this case you
* must call this function again when the operation is ready.
* \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic
* operation is in progress (see mbedtls_ecp_set_max_ops()) -
* in this case you must call this function again to complete
* the handshake when you're done attending other tasks.
* \return #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server
* side of a DTLS connection and the client is initiating a
* new connection using the same source port. See below.
* \return Another SSL error code - in this case you must stop using
* the context (see below).
* *
* If MBEDTLS_ERR_SSL_WANT_READ is returned, no application data * \warning If this function returns something other than
* is available from the underlying transport. In this case, * a positive value,
* the function needs to be called again at some later stage. * #MBEDTLS_ERR_SSL_WANT_READ,
* #MBEDTLS_ERR_SSL_WANT_WRITE,
* #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS,
* #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or
* #MBEDTLS_ERR_SSL_CLIENT_RECONNECT,
* you must stop using the SSL context for reading or writing,
* and either free it or call \c mbedtls_ssl_session_reset()
* on it before re-using it for a new connection; the current
* connection must be closed.
* *
* If MBEDTLS_ERR_SSL_WANT_WRITE is returned, a write is pending * \note When this function returns #MBEDTLS_ERR_SSL_CLIENT_RECONNECT
* but the underlying transport isn't available for writing. In this
* case, the function needs to be called again at some later stage.
*
* When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
* (which can only happen server-side), it means that a client * (which can only happen server-side), it means that a client
* is initiating a new connection using the same source port. * is initiating a new connection using the same source port.
* You can either treat that as a connection close and wait * You can either treat that as a connection close and wait
* for the client to resend a ClientHello, or directly * for the client to resend a ClientHello, or directly
* continue with \c mbedtls_ssl_handshake() with the same * continue with \c mbedtls_ssl_handshake() with the same
* context (as it has beeen reset internally). Either way, you * context (as it has been reset internally). Either way, you
* should make sure this is seen by the application as a new * must make sure this is seen by the application as a new
* connection: application state, if any, should be reset, and * connection: application state, if any, should be reset, and
* most importantly the identity of the client must be checked * most importantly the identity of the client must be checked
* again. WARNING: not validating the identity of the client * again. WARNING: not validating the identity of the client
* again, or not transmitting the new identity to the * again, or not transmitting the new identity to the
* application layer, would allow authentication bypass! * application layer, would allow authentication bypass!
* *
* \note If this function returns something other than a positive value
* or MBEDTLS_ERR_SSL_WANT_READ/WRITE or MBEDTLS_ERR_SSL_CLIENT_RECONNECT,
* you must stop using the SSL context for reading or writing,
* and either free it or call \c mbedtls_ssl_session_reset() on it
* before re-using it for a new connection; the current connection
* must be closed.
*
* \note Remarks regarding event-driven DTLS: * \note Remarks regarding event-driven DTLS:
* - If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram * - If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram
* from the underlying transport layer is currently being processed, * from the underlying transport layer is currently being processed,
* and it is safe to idle until the timer or the underlying transport * and it is safe to idle until the timer or the underlying transport
* signal a new event. * signal a new event.
@ -3059,21 +3196,39 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
* \param buf buffer holding the data * \param buf buffer holding the data
* \param len how many bytes must be written * \param len how many bytes must be written
* *
* \return the number of bytes actually written (may be less than len), * \return The (non-negative) number of bytes actually written if
* or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ, * successful (may be less than \p len).
* or another negative error code. * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE
* if the handshake is incomplete and waiting for data to
* be available for reading from or writing to the underlying
* transport - in this case you must call this function again
* when the underlying transport is ready for the operation.
* \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous
* operation is in progress (see
* mbedtls_ssl_conf_async_private_cb()) - in this case you
* must call this function again when the operation is ready.
* \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic
* operation is in progress (see mbedtls_ecp_set_max_ops()) -
* in this case you must call this function again to complete
* the handshake when you're done attending other tasks.
* \return Another SSL error code - in this case you must stop using
* the context (see below).
* *
* \note If this function returns something other than 0, a positive * \warning If this function returns something other than
* value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop * a non-negative value,
* using the SSL context for reading or writing, and either * #MBEDTLS_ERR_SSL_WANT_READ,
* free it or call \c mbedtls_ssl_session_reset() on it before * #MBEDTLS_ERR_SSL_WANT_WRITE,
* re-using it for a new connection; the current connection * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
* must be closed. * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS,
* you must stop using the SSL context for reading or writing,
* and either free it or call \c mbedtls_ssl_session_reset()
* on it before re-using it for a new connection; the current
* connection must be closed.
* *
* \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ, * \note When this function returns #MBEDTLS_ERR_SSL_WANT_WRITE/READ,
* it must be called later with the *same* arguments, * it must be called later with the *same* arguments,
* until it returns a value greater that or equal to 0. When * until it returns a value greater that or equal to 0. When
* the function returns MBEDTLS_ERR_SSL_WANT_WRITE there may be * the function returns #MBEDTLS_ERR_SSL_WANT_WRITE there may be
* some partial data in the output buffer, however this is not * some partial data in the output buffer, however this is not
* yet sent. * yet sent.
* *

View File

@ -93,6 +93,14 @@
#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_1 */
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
/* Shorthand for restartable ECC */
#if defined(MBEDTLS_ECP_RESTARTABLE) && \
defined(MBEDTLS_SSL_CLI_C) && \
defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
#define MBEDTLS_SSL__ECP_RESTARTABLE
#endif
#define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 #define MBEDTLS_SSL_INITIAL_HANDSHAKE 0
#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ #define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */
#define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ #define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */
@ -275,9 +283,12 @@ struct mbedtls_ssl_handshake_params
const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */ const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */
#endif #endif
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
#if defined(MBEDTLS_USE_PSA_CRYPTO)
psa_key_slot_t psk_opaque; /*!< Opaque PSK from the callback */
#endif /* MBEDTLS_USE_PSA_CRYPTO */
unsigned char *psk; /*!< PSK from the callback */ unsigned char *psk; /*!< PSK from the callback */
size_t psk_len; /*!< Length of PSK from callback */ size_t psk_len; /*!< Length of PSK from callback */
#endif #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
#if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
@ -287,7 +298,18 @@ struct mbedtls_ssl_handshake_params
mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
#endif /* MBEDTLS_X509_CRT_PARSE_C */ #endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
int ecrs_enabled; /*!< Handshake supports EC restart? */
mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */
enum { /* this complements ssl->state with info on intra-state operations */
ssl_ecrs_none = 0, /*!< nothing going on (yet) */
ssl_ecrs_crt_verify, /*!< Certificate: crt_verify() */
ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: pk_verify() */
ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */
ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */
} ecrs_state; /*!< current (or last) operation */
size_t ecrs_n; /*!< place for saving a length */
#endif
#if defined(MBEDTLS_SSL_PROTO_DTLS) #if defined(MBEDTLS_SSL_PROTO_DTLS)
unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */
unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ unsigned int in_msg_seq; /*!< Incoming handshake sequence number */

View File

@ -36,7 +36,10 @@
extern "C" { extern "C" {
#endif #endif
/* MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE is deprecated and should not be
* used. */
#define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */ #define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */
#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */ #define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */
#define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */ #define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */

View File

@ -39,17 +39,17 @@
* Major, Minor, Patchlevel * Major, Minor, Patchlevel
*/ */
#define MBEDTLS_VERSION_MAJOR 2 #define MBEDTLS_VERSION_MAJOR 2
#define MBEDTLS_VERSION_MINOR 13 #define MBEDTLS_VERSION_MINOR 15
#define MBEDTLS_VERSION_PATCH 1 #define MBEDTLS_VERSION_PATCH 0
/** /**
* The single version number has the following structure: * The single version number has the following structure:
* MMNNPP00 * MMNNPP00
* Major version | Minor version | Patch version * Major version | Minor version | Patch version
*/ */
#define MBEDTLS_VERSION_NUMBER 0x020D0100 #define MBEDTLS_VERSION_NUMBER 0x020F0000
#define MBEDTLS_VERSION_STRING "2.13.1" #define MBEDTLS_VERSION_STRING "2.15.0"
#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.13.1" #define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.15.0"
#if defined(MBEDTLS_VERSION_C) #if defined(MBEDTLS_VERSION_C)

View File

@ -143,6 +143,63 @@ typedef struct mbedtls_x509write_cert
} }
mbedtls_x509write_cert; mbedtls_x509write_cert;
/**
* Item in a verification chain: cert and flags for it
*/
typedef struct {
mbedtls_x509_crt *crt;
uint32_t flags;
} mbedtls_x509_crt_verify_chain_item;
/**
* Max size of verification chain: end-entity + intermediates + trusted root
*/
#define MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 )
/**
* Verification chain as built by \c mbedtls_crt_verify_chain()
*/
typedef struct
{
mbedtls_x509_crt_verify_chain_item items[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE];
unsigned len;
} mbedtls_x509_crt_verify_chain;
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/**
* \brief Context for resuming X.509 verify operations
*/
typedef struct
{
/* for check_signature() */
mbedtls_pk_restart_ctx pk;
/* for find_parent_in() */
mbedtls_x509_crt *parent; /* non-null iff parent_in in progress */
mbedtls_x509_crt *fallback_parent;
int fallback_signature_is_good;
/* for find_parent() */
int parent_is_trusted; /* -1 if find_parent is not in progress */
/* for verify_chain() */
enum {
x509_crt_rs_none,
x509_crt_rs_find_parent,
} in_progress; /* none if no operation is in progress */
int self_cnt;
mbedtls_x509_crt_verify_chain ver_chain;
} mbedtls_x509_crt_restart_ctx;
#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
/* Now we can declare functions that take a pointer to that */
typedef void mbedtls_x509_crt_restart_ctx;
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
#if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_X509_CRT_PARSE_C)
/** /**
* Default security profile. Should provide a good balance between security * Default security profile. Should provide a good balance between security
@ -353,6 +410,37 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
void *p_vrfy ); void *p_vrfy );
/**
* \brief Restartable version of \c mbedtls_crt_verify_with_profile()
*
* \note Performs the same job as \c mbedtls_crt_verify_with_profile()
* but can return early and restart according to the limit
* set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
*
* \param crt a certificate (chain) to be verified
* \param trust_ca the list of trusted CAs
* \param ca_crl the list of CRLs for trusted CAs
* \param profile security profile for verification
* \param cn expected Common Name (can be set to
* NULL if the CN must not be verified)
* \param flags result of the verification
* \param f_vrfy verification function
* \param p_vrfy verification parameter
* \param rs_ctx restart context (NULL to disable restart)
*
* \return See \c mbedtls_crt_verify_with_profile(), or
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
*/
int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
mbedtls_x509_crt *trust_ca,
mbedtls_x509_crl *ca_crl,
const mbedtls_x509_crt_profile *profile,
const char *cn, uint32_t *flags,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
void *p_vrfy,
mbedtls_x509_crt_restart_ctx *rs_ctx );
#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
/** /**
* \brief Check usage of certificate against keyUsage extension. * \brief Check usage of certificate against keyUsage extension.
@ -424,6 +512,18 @@ void mbedtls_x509_crt_init( mbedtls_x509_crt *crt );
* \param crt Certificate chain to free * \param crt Certificate chain to free
*/ */
void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ); void mbedtls_x509_crt_free( mbedtls_x509_crt *crt );
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/**
* \brief Initialize a restart context
*/
void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx );
/**
* \brief Free the components of a restart context
*/
void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx );
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
#endif /* MBEDTLS_X509_CRT_PARSE_C */ #endif /* MBEDTLS_X509_CRT_PARSE_C */
/* \} name */ /* \} name */

View File

@ -37,6 +37,8 @@
#define MBEDTLS_XTEA_DECRYPT 0 #define MBEDTLS_XTEA_DECRYPT 0
#define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */ #define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */
/* MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED -0x0029 /**< XTEA hardware accelerator failed. */ #define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED -0x0029 /**< XTEA hardware accelerator failed. */
#ifdef __cplusplus #ifdef __cplusplus

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,128 @@
/**
* \file psa/crypto_extra.h
*
* \brief PSA cryptography module: Mbed TLS vendor extensions
*
* \note This file may not be included directly. Applications must
* include psa/crypto.h.
*
* This file is reserved for vendor-specific definitions.
*/
/*
* Copyright (C) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef PSA_CRYPTO_EXTRA_H
#define PSA_CRYPTO_EXTRA_H
#ifdef __cplusplus
extern "C" {
#endif
/* UID for secure storage seed */
#define PSA_CRYPTO_ITS_RANDOM_SEED_UID 0xFFFFFF52
/**
* \brief Library deinitialization.
*
* This function clears all data associated with the PSA layer,
* including the whole key store.
*
* This is an Mbed TLS extension.
*/
void mbedtls_psa_crypto_free( void );
/**
* \brief Inject an initial entropy seed for the random generator into
* secure storage.
*
* This function injects data to be used as a seed for the random generator
* used by the PSA Crypto implementation. On devices that lack a trusted
* entropy source (preferably a hardware random number generator),
* the Mbed PSA Crypto implementation uses this value to seed its
* random generator.
*
* On devices without a trusted entropy source, this function must be
* called exactly once in the lifetime of the device. On devices with
* a trusted entropy source, calling this function is optional.
* In all cases, this function may only be called before calling any
* other function in the PSA Crypto API, including psa_crypto_init().
*
* When this function returns successfully, it populates a file in
* persistent storage. Once the file has been created, this function
* can no longer succeed.
*
* If any error occurs, this function does not change the system state.
* You can call this function again after correcting the reason for the
* error if possible.
*
* \warning This function **can** fail! Callers MUST check the return status.
*
* \warning If you use this function, you should use it as part of a
* factory provisioning process. The value of the injected seed
* is critical to the security of the device. It must be
* *secret*, *unpredictable* and (statistically) *unique per device*.
* You should be generate it randomly using a cryptographically
* secure random generator seeded from trusted entropy sources.
* You should transmit it securely to the device and ensure
* that its value is not leaked or stored anywhere beyond the
* needs of transmitting it from the point of generation to
* the call of this function, and erase all copies of the value
* once this function returns.
*
* This is an Mbed TLS extension.
*
* \note This function is only available on the following platforms:
* * If the compile-time options MBEDTLS_ENTROPY_NV_SEED and
* MBEDTLS_PSA_HAS_ITS_IO are both enabled. Note that you
* must provide compatible implementations of mbedtls_nv_seed_read
* and mbedtls_nv_seed_write.
* * In a client-server integration of PSA Cryptography, on the client side,
* if the server supports this feature.
* \param[in] seed Buffer containing the seed value to inject.
* \param[in] seed_size Size of the \p seed buffer.
* The size of the seed in bytes must be greater
* or equal to both #MBEDTLS_ENTROPY_MIN_PLATFORM
* and #MBEDTLS_ENTROPY_BLOCK_SIZE.
* It must be less or equal to
* #MBEDTLS_ENTROPY_MAX_SEED_SIZE.
*
* \retval #PSA_SUCCESS
* The seed value was injected successfully. The random generator
* of the PSA Crypto implementation is now ready for use.
* You may now call psa_crypto_init() and use the PSA Crypto
* implementation.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \p seed_size is out of range.
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval `PSA_ITS_ERROR_XXX`
* There was a failure reading or writing from storage.
* \retval #PSA_ERROR_NOT_PERMITTED
* The library has already been initialized. It is no longer
* possible to call this function.
*/
psa_status_t mbedtls_psa_inject_entropy(const unsigned char *seed,
size_t seed_size);
#ifdef __cplusplus
}
#endif
#endif /* PSA_CRYPTO_EXTRA_H */

View File

@ -0,0 +1,52 @@
/**
* \file psa/crypto_platform.h
*
* \brief PSA cryptography module: Mbed TLS platfom definitions
*
* \note This file may not be included directly. Applications must
* include psa/crypto.h.
*
* This file contains platform-dependent type definitions.
*
* In implementations with isolation between the application and the
* cryptography module, implementers should take care to ensure that
* the definitions that are exposed to applications match what the
* module implements.
*/
/*
* Copyright (C) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef PSA_CRYPTO_PLATFORM_H
#define PSA_CRYPTO_PLATFORM_H
/* Include the Mbed TLS configuration file, the way Mbed TLS does it
* in each of its header files. */
#if !defined(MBEDTLS_CONFIG_FILE)
#include "../mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
/* PSA requires several types which C99 provides in stdint.h. */
#include <stdint.h>
/* Integral type representing a key slot number. */
typedef uint16_t psa_key_slot_t;
#endif /* PSA_CRYPTO_PLATFORM_H */

View File

@ -0,0 +1,527 @@
/**
* \file psa/crypto_sizes.h
*
* \brief PSA cryptography module: Mbed TLS buffer size macros
*
* \note This file may not be included directly. Applications must
* include psa/crypto.h.
*
* This file contains the definitions of macros that are useful to
* compute buffer sizes. The signatures and semantics of these macros
* are standardized, but the definitions are not, because they depend on
* the available algorithms and, in some cases, on permitted tolerances
* on buffer sizes.
*
* In implementations with isolation between the application and the
* cryptography module, implementers should take care to ensure that
* the definitions that are exposed to applications match what the
* module implements.
*
* Macros that compute sizes whose values do not depend on the
* implementation are in crypto.h.
*/
/*
* Copyright (C) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef PSA_CRYPTO_SIZES_H
#define PSA_CRYPTO_SIZES_H
/* Include the Mbed TLS configuration file, the way Mbed TLS does it
* in each of its header files. */
#if !defined(MBEDTLS_CONFIG_FILE)
#include "../mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
/** \def PSA_HASH_MAX_SIZE
*
* Maximum size of a hash.
*
* This macro must expand to a compile-time constant integer. This value
* should be the maximum size of a hash supported by the implementation,
* in bytes, and must be no smaller than this maximum.
*/
/* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-226,
* 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for
* HMAC-SHA3-512. */
#if defined(MBEDTLS_SHA512_C)
#define PSA_HASH_MAX_SIZE 64
#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128
#else
#define PSA_HASH_MAX_SIZE 32
#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64
#endif
/** \def PSA_MAC_MAX_SIZE
*
* Maximum size of a MAC.
*
* This macro must expand to a compile-time constant integer. This value
* should be the maximum size of a MAC supported by the implementation,
* in bytes, and must be no smaller than this maximum.
*/
/* All non-HMAC MACs have a maximum size that's smaller than the
* minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */
/* Note that the encoding of truncated MAC algorithms limits this value
* to 64 bytes.
*/
#define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE
/* The maximum size of an RSA key on this implementation, in bits.
* This is a vendor-specific macro.
*
* Mbed TLS does not set a hard limit on the size of RSA keys: any key
* whose parameters fit in a bignum is accepted. However large keys can
* induce a large memory usage and long computation times. Unlike other
* auxiliary macros in this file and in crypto.h, which reflect how the
* library is configured, this macro defines how the library is
* configured. This implementation refuses to import or generate an
* RSA key whose size is larger than the value defined here.
*
* Note that an implementation may set different size limits for different
* operations, and does not need to accept all key sizes up to the limit. */
#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096
/* The maximum size of an ECC key on this implementation, in bits.
* This is a vendor-specific macro. */
#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521
#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
#define PSA_VENDOR_ECC_MAX_CURVE_BITS 512
#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
#define PSA_VENDOR_ECC_MAX_CURVE_BITS 448
#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384
#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384
#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256
#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256
#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256
#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
#define PSA_VENDOR_ECC_MAX_CURVE_BITS 255
#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224
#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224
#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192
#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192
#else
#define PSA_VENDOR_ECC_MAX_CURVE_BITS 0
#endif
/** \def PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN
*
* This macro returns the maximum length of the PSK supported
* by the TLS-1.2 PSK-to-MS key derivation.
*
* Quoting RFC 4279, Sect 5.3:
* TLS implementations supporting these ciphersuites MUST support
* arbitrary PSK identities up to 128 octets in length, and arbitrary
* PSKs up to 64 octets in length. Supporting longer identities and
* keys is RECOMMENDED.
*
* Therefore, no implementation should define a value smaller than 64
* for #PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN.
*/
#define PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN 128
/** \def PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE
*
* Maximum size of an asymmetric signature.
*
* This macro must expand to a compile-time constant integer. This value
* should be the maximum size of a MAC supported by the implementation,
* in bytes, and must be no smaller than this maximum.
*/
#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \
PSA_BITS_TO_BYTES( \
PSA_VENDOR_RSA_MAX_KEY_BITS > PSA_VENDOR_ECC_MAX_CURVE_BITS ? \
PSA_VENDOR_RSA_MAX_KEY_BITS : \
PSA_VENDOR_ECC_MAX_CURVE_BITS \
)
/** The maximum size of a block cipher supported by the implementation. */
#define PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE 16
/** The size of the output of psa_mac_sign_finish(), in bytes.
*
* This is also the MAC size that psa_mac_verify_finish() expects.
*
* \param key_type The type of the MAC key.
* \param key_bits The size of the MAC key in bits.
* \param alg A MAC algorithm (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_MAC(alg) is true).
*
* \return The MAC size for the specified algorithm with
* the specified key parameters.
* \return 0 if the MAC algorithm is not recognized.
* \return Either 0 or the correct size for a MAC algorithm that
* the implementation recognizes, but does not support.
* \return Unspecified if the key parameters are not consistent
* with the algorithm.
*/
#define PSA_MAC_FINAL_SIZE(key_type, key_bits, alg) \
((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) : \
PSA_ALG_IS_HMAC(alg) ? PSA_HASH_SIZE(PSA_ALG_HMAC_GET_HASH(alg)) : \
PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \
((void)(key_type), (void)(key_bits), 0))
/** The maximum size of the output of psa_aead_encrypt(), in bytes.
*
* If the size of the ciphertext buffer is at least this large, it is
* guaranteed that psa_aead_encrypt() will not fail due to an
* insufficient buffer size. Depending on the algorithm, the actual size of
* the ciphertext may be smaller.
*
* \param alg An AEAD algorithm
* (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_AEAD(alg) is true).
* \param plaintext_length Size of the plaintext in bytes.
*
* \return The AEAD ciphertext size for the specified
* algorithm.
* If the AEAD algorithm is not recognized, return 0.
* An implementation may return either 0 or a
* correct size for an AEAD algorithm that it
* recognizes, but does not support.
*/
#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length) \
(PSA_AEAD_TAG_LENGTH(alg) != 0 ? \
(plaintext_length) + PSA_AEAD_TAG_LENGTH(alg) : \
0)
/** The maximum size of the output of psa_aead_decrypt(), in bytes.
*
* If the size of the plaintext buffer is at least this large, it is
* guaranteed that psa_aead_decrypt() will not fail due to an
* insufficient buffer size. Depending on the algorithm, the actual size of
* the plaintext may be smaller.
*
* \param alg An AEAD algorithm
* (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_AEAD(alg) is true).
* \param ciphertext_length Size of the plaintext in bytes.
*
* \return The AEAD ciphertext size for the specified
* algorithm.
* If the AEAD algorithm is not recognized, return 0.
* An implementation may return either 0 or a
* correct size for an AEAD algorithm that it
* recognizes, but does not support.
*/
#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length) \
(PSA_AEAD_TAG_LENGTH(alg) != 0 ? \
(plaintext_length) - PSA_AEAD_TAG_LENGTH(alg) : \
0)
/** Safe signature buffer size for psa_asymmetric_sign().
*
* This macro returns a safe buffer size for a signature using a key
* of the specified type and size, with the specified algorithm.
* Note that the actual size of the signature may be smaller
* (some algorithms produce a variable-size signature).
*
* \warning This function may call its arguments multiple times or
* zero times, so you should not pass arguments that contain
* side effects.
*
* \param key_type An asymmetric key type (this may indifferently be a
* key pair type or a public key type).
* \param key_bits The size of the key in bits.
* \param alg The signature algorithm.
*
* \return If the parameters are valid and supported, return
* a buffer size in bytes that guarantees that
* psa_asymmetric_sign() 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 either shall return either a
* sensible size or 0.
* If the parameters are not valid, the
* return value is unspecified.
*/
#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \
(PSA_KEY_TYPE_IS_RSA(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \
PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \
((void)alg, 0))
/** Safe output buffer size for psa_asymmetric_encrypt().
*
* This macro returns a safe buffer size for a ciphertext produced using
* a key of the specified type and size, with the specified algorithm.
* Note that the actual size of the ciphertext may be smaller, depending
* on the algorithm.
*
* \warning This function may call its arguments multiple times or
* zero times, so you should not pass arguments that contain
* side effects.
*
* \param key_type An asymmetric key type (this may indifferently be a
* key pair type or a public key type).
* \param key_bits The size of the key in bits.
* \param alg The signature algorithm.
*
* \return If the parameters are valid and supported, return
* a buffer size in bytes that guarantees that
* psa_asymmetric_encrypt() 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 either shall return either a
* sensible size or 0.
* If the parameters are not valid, the
* return value is unspecified.
*/
#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \
(PSA_KEY_TYPE_IS_RSA(key_type) ? \
((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \
0)
/** Safe output buffer size for psa_asymmetric_decrypt().
*
* This macro returns a safe buffer size for a ciphertext produced using
* a key of the specified type and size, with the specified algorithm.
* Note that the actual size of the ciphertext may be smaller, depending
* on the algorithm.
*
* \warning This function may call its arguments multiple times or
* zero times, so you should not pass arguments that contain
* side effects.
*
* \param key_type An asymmetric key type (this may indifferently be a
* key pair type or a public key type).
* \param key_bits The size of the key in bits.
* \param alg The signature algorithm.
*
* \return If the parameters are valid and supported, return
* a buffer size in bytes that guarantees that
* psa_asymmetric_decrypt() 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 either shall return either a
* sensible size or 0.
* If the parameters are not valid, the
* return value is unspecified.
*/
#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \
(PSA_KEY_TYPE_IS_RSA(key_type) ? \
PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \
0)
/* Maximum size of the ASN.1 encoding of an INTEGER with the specified
* number of bits.
*
* This definition assumes that bits <= 2^19 - 9 so that the length field
* is at most 3 bytes. The length of the encoding is the length of the
* bit string padded to a whole number of bytes plus:
* - 1 type byte;
* - 1 to 3 length bytes;
* - 0 to 1 bytes of leading 0 due to the sign bit.
*/
#define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits) \
((bits) / 8 + 5)
/* Maximum size of the export encoding of an RSA public key.
* Assumes that the public exponent is less than 2^32.
*
* SubjectPublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING } -- contains RSAPublicKey
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters NULL }
* RSAPublicKey ::= SEQUENCE {
* modulus INTEGER, -- n
* publicExponent INTEGER } -- e
*
* - 3 * 4 bytes of SEQUENCE overhead;
* - 1 + 1 + 9 bytes of algorithm (RSA OID);
* - 2 bytes of NULL;
* - 4 bytes of BIT STRING overhead;
* - n : INTEGER;
* - 7 bytes for the public exponent.
*/
#define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) \
(PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 36)
/* Maximum size of the export encoding of an RSA key pair.
* Assumes thatthe public exponent is less than 2^32 and that the size
* difference between the two primes is at most 1 bit.
*
* RSAPrivateKey ::= SEQUENCE {
* version Version, -- 0
* modulus INTEGER, -- N-bit
* publicExponent INTEGER, -- 32-bit
* privateExponent INTEGER, -- N-bit
* prime1 INTEGER, -- N/2-bit
* prime2 INTEGER, -- N/2-bit
* exponent1 INTEGER, -- N/2-bit
* exponent2 INTEGER, -- N/2-bit
* coefficient INTEGER, -- N/2-bit
* }
*
* - 4 bytes of SEQUENCE overhead;
* - 3 bytes of version;
* - 7 half-size INTEGERs plus 2 full-size INTEGERs,
* overapproximated as 9 half-size INTEGERS;
* - 7 bytes for the public exponent.
*/
#define PSA_KEY_EXPORT_RSA_KEYPAIR_MAX_SIZE(key_bits) \
(9 * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2 + 1) + 14)
/* Maximum size of the export encoding of a DSA public key.
*
* SubjectPublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING } -- contains DSAPublicKey
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters Dss-Parms } -- SEQUENCE of 3 INTEGERs
* DSAPublicKey ::= INTEGER -- public key, Y
*
* - 3 * 4 bytes of SEQUENCE overhead;
* - 1 + 1 + 7 bytes of algorithm (DSA OID);
* - 4 bytes of BIT STRING overhead;
* - 3 full-size INTEGERs (p, g, y);
* - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits).
*/
#define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) \
(PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 59)
/* Maximum size of the export encoding of a DSA key pair.
*
* DSAPrivateKey ::= SEQUENCE {
* version Version, -- 0
* prime INTEGER, -- p
* subprime INTEGER, -- q
* generator INTEGER, -- g
* public INTEGER, -- y
* private INTEGER, -- x
* }
*
* - 4 bytes of SEQUENCE overhead;
* - 3 bytes of version;
* - 3 full-size INTEGERs (p, g, y);
* - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits).
*/
#define PSA_KEY_EXPORT_DSA_KEYPAIR_MAX_SIZE(key_bits) \
(PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 75)
/* Maximum size of the export encoding of an ECC public key.
*
* SubjectPublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING } -- contains ECPoint
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters OBJECT IDENTIFIER } -- namedCurve
* ECPoint ::= ...
* -- first 8 bits: 0x04;
* -- then x_P as a `ceiling(m/8)`-byte string, big endian;
* -- then y_P as a `ceiling(m/8)`-byte string, big endian;
* -- where `m` is the bit size associated with the curve.
*
* - 2 * 4 bytes of SEQUENCE overhead;
* - 1 + 1 + 7 bytes of algorithm (id-ecPublicKey OID);
* - 1 + 1 + 12 bytes of namedCurve OID;
* - 4 bytes of BIT STRING overhead;
* - 1 byte + 2 * point size in ECPoint.
*/
#define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \
(2 * PSA_BITS_TO_BYTES(key_bits) + 36)
/* Maximum size of the export encoding of an ECC key pair.
*
* An ECC key pair is represented by the secret value.
*/
#define PSA_KEY_EXPORT_ECC_KEYPAIR_MAX_SIZE(key_bits) \
(PSA_BITS_TO_BYTES(key_bits))
/** Safe output buffer size for psa_export_key() or psa_export_public_key().
*
* 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.
*
* The following code illustrates how to allocate enough memory to export
* a key by querying the key type and size at runtime.
* \code{c}
* psa_key_type_t key_type;
* size_t key_bits;
* psa_status_t status;
* status = psa_get_key_information(key, &key_type, &key_bits);
* if (status != PSA_SUCCESS) handle_error(...);
* size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits);
* unsigned char *buffer = malloc(buffer_size);
* if (buffer != NULL) handle_error(...);
* size_t buffer_length;
* status = psa_export_key(key, buffer, buffer_size, &buffer_length);
* if (status != PSA_SUCCESS) handle_error(...);
* \endcode
*
* For psa_export_public_key(), calculate the buffer size from the
* public key type. You can use the macro #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR
* to convert a key pair type to the corresponding public key type.
* \code{c}
* psa_key_type_t key_type;
* size_t key_bits;
* psa_status_t status;
* status = psa_get_key_information(key, &key_type, &key_bits);
* if (status != PSA_SUCCESS) handle_error(...);
* psa_key_type_t public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(key_type);
* size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(public_key_type, key_bits);
* unsigned char *buffer = malloc(buffer_size);
* if (buffer != NULL) handle_error(...);
* size_t buffer_length;
* status = psa_export_public_key(key, buffer, buffer_size, &buffer_length);
* if (status != PSA_SUCCESS) handle_error(...);
* \endcode
*
* \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_asymmetric_sign() 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 either shall return either a
* sensible size or 0.
* If the parameters are not valid, the
* return value is unspecified.
*/
#define PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits) \
(PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \
(key_type) == PSA_KEY_TYPE_RSA_KEYPAIR ? PSA_KEY_EXPORT_RSA_KEYPAIR_MAX_SIZE(key_bits) : \
(key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \
(key_type) == PSA_KEY_TYPE_DSA_KEYPAIR ? PSA_KEY_EXPORT_DSA_KEYPAIR_MAX_SIZE(key_bits) : \
(key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \
PSA_KEY_TYPE_IS_ECC_KEYPAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEYPAIR_MAX_SIZE(key_bits) : \
PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \
0)
#endif /* PSA_CRYPTO_SIZES_H */

View File

@ -0,0 +1,211 @@
/**
* \file psa/crypto_struct.h
*
* \brief PSA cryptography module: Mbed TLS structured type implementations
*
* \note This file may not be included directly. Applications must
* include psa/crypto.h.
*
* This file contains the definitions of some data structures with
* implementation-specific definitions.
*
* In implementations with isolation between the application and the
* cryptography module, it is expected that the front-end and the back-end
* would have different versions of this file.
*/
/*
* Copyright (C) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef PSA_CRYPTO_STRUCT_H
#define PSA_CRYPTO_STRUCT_H
/* Include the Mbed TLS configuration file, the way Mbed TLS does it
* in each of its header files. */
#if !defined(MBEDTLS_CONFIG_FILE)
#include "../mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/cipher.h"
#include "mbedtls/cmac.h"
#include "mbedtls/gcm.h"
#include "mbedtls/md.h"
#include "mbedtls/md2.h"
#include "mbedtls/md4.h"
#include "mbedtls/md5.h"
#include "mbedtls/ripemd160.h"
#include "mbedtls/sha1.h"
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
struct psa_hash_operation_s
{
psa_algorithm_t alg;
union
{
unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
#if defined(MBEDTLS_MD2_C)
mbedtls_md2_context md2;
#endif
#if defined(MBEDTLS_MD4_C)
mbedtls_md4_context md4;
#endif
#if defined(MBEDTLS_MD5_C)
mbedtls_md5_context md5;
#endif
#if defined(MBEDTLS_RIPEMD160_C)
mbedtls_ripemd160_context ripemd160;
#endif
#if defined(MBEDTLS_SHA1_C)
mbedtls_sha1_context sha1;
#endif
#if defined(MBEDTLS_SHA256_C)
mbedtls_sha256_context sha256;
#endif
#if defined(MBEDTLS_SHA512_C)
mbedtls_sha512_context sha512;
#endif
} ctx;
};
#if defined(MBEDTLS_MD_C)
typedef struct
{
/** The hash context. */
struct psa_hash_operation_s hash_ctx;
/** The HMAC part of the context. */
uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
} psa_hmac_internal_data;
#endif /* MBEDTLS_MD_C */
struct psa_mac_operation_s
{
psa_algorithm_t alg;
unsigned int key_set : 1;
unsigned int iv_required : 1;
unsigned int iv_set : 1;
unsigned int has_input : 1;
unsigned int is_sign : 1;
uint8_t mac_size;
union
{
unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
#if defined(MBEDTLS_MD_C)
psa_hmac_internal_data hmac;
#endif
#if defined(MBEDTLS_CMAC_C)
mbedtls_cipher_context_t cmac;
#endif
} ctx;
};
struct psa_cipher_operation_s
{
psa_algorithm_t alg;
unsigned int key_set : 1;
unsigned int iv_required : 1;
unsigned int iv_set : 1;
uint8_t iv_size;
uint8_t block_size;
union
{
mbedtls_cipher_context_t cipher;
} ctx;
};
#if defined(MBEDTLS_MD_C)
typedef struct
{
uint8_t *info;
size_t info_length;
psa_hmac_internal_data hmac;
uint8_t prk[PSA_HASH_MAX_SIZE];
uint8_t output_block[PSA_HASH_MAX_SIZE];
#if PSA_HASH_MAX_SIZE > 0xff
#error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
#endif
uint8_t offset_in_block;
uint8_t block_number;
} psa_hkdf_generator_t;
#endif /* MBEDTLS_MD_C */
#if defined(MBEDTLS_MD_C)
typedef struct psa_tls12_prf_generator_s
{
/* The TLS 1.2 PRF uses the key for each HMAC iteration,
* hence we must store it for the lifetime of the generator.
* This is different from HKDF, where the key is only used
* in the extraction phase, but not during expansion. */
unsigned char *key;
size_t key_len;
/* `A(i) + seed` in the notation of RFC 5246, Sect. 5 */
uint8_t *Ai_with_seed;
size_t Ai_with_seed_len;
/* `HMAC_hash( prk, A(i) + seed )` in the notation of RFC 5246, Sect. 5. */
uint8_t output_block[PSA_HASH_MAX_SIZE];
#if PSA_HASH_MAX_SIZE > 0xff
#error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
#endif
/* Indicates how many bytes in the current HMAC block have
* already been read by the user. */
uint8_t offset_in_block;
/* The 1-based number of the block. */
uint8_t block_number;
} psa_tls12_prf_generator_t;
#endif /* MBEDTLS_MD_C */
struct psa_crypto_generator_s
{
psa_algorithm_t alg;
size_t capacity;
union
{
struct
{
uint8_t *data;
size_t size;
} buffer;
#if defined(MBEDTLS_MD_C)
psa_hkdf_generator_t hkdf;
psa_tls12_prf_generator_t tls12_prf;
#endif
} ctx;
};
#define PSA_CRYPTO_GENERATOR_INIT {0, 0, {{0, 0}}}
static inline struct psa_crypto_generator_s psa_crypto_generator_init( void )
{
const struct psa_crypto_generator_s v = PSA_CRYPTO_GENERATOR_INIT;
return( v );
}
struct psa_key_policy_s
{
psa_key_usage_t usage;
psa_algorithm_t alg;
};
#endif /* PSA_CRYPTO_STRUCT_H */

View File

@ -0,0 +1,219 @@
/*
* PSA persistent key storage
*/
/* Copyright (C) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#if defined(MBEDTLS_CONFIG_FILE)
#include MBEDTLS_CONFIG_FILE
#else
#include "mbedtls/config.h"
#endif
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
#include <stdlib.h>
#include <string.h>
#include "psa/crypto.h"
#include "psa_crypto_storage.h"
#include "psa_crypto_storage_backend.h"
#include "mbedtls/platform_util.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
/*
* 32-bit integer manipulation macros (little endian)
*/
#ifndef GET_UINT32_LE
#define GET_UINT32_LE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] ) \
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
| ( (uint32_t) (b)[(i) + 2] << 16 ) \
| ( (uint32_t) (b)[(i) + 3] << 24 ); \
}
#endif
#ifndef PUT_UINT32_LE
#define PUT_UINT32_LE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
(b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
(b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
(b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
}
#endif
/**
* Persistent key storage magic header.
*/
#define PSA_KEY_STORAGE_MAGIC_HEADER "PSA\0KEY"
#define PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ( sizeof( PSA_KEY_STORAGE_MAGIC_HEADER ) )
typedef struct {
uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH];
uint8_t version[4];
uint8_t type[sizeof( psa_key_type_t )];
uint8_t policy[sizeof( psa_key_policy_t )];
uint8_t data_len[4];
uint8_t key_data[];
} psa_persistent_key_storage_format;
void psa_format_key_data_for_storage( const uint8_t *data,
const size_t data_length,
const psa_key_type_t type,
const psa_key_policy_t *policy,
uint8_t *storage_data )
{
psa_persistent_key_storage_format *storage_format =
(psa_persistent_key_storage_format *) storage_data;
memcpy( storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH );
PUT_UINT32_LE(0, storage_format->version, 0);
PUT_UINT32_LE(type, storage_format->type, 0);
PUT_UINT32_LE(policy->usage, storage_format->policy, 0);
PUT_UINT32_LE(policy->alg, storage_format->policy, sizeof( uint32_t ));
PUT_UINT32_LE(data_length, storage_format->data_len, 0);
memcpy( storage_format->key_data, data, data_length );
}
static psa_status_t check_magic_header( const uint8_t *data )
{
if( memcmp( data, PSA_KEY_STORAGE_MAGIC_HEADER,
PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ) != 0 )
return( PSA_ERROR_STORAGE_FAILURE );
return( PSA_SUCCESS );
}
psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
size_t storage_data_length,
uint8_t **key_data,
size_t *key_data_length,
psa_key_type_t *type,
psa_key_policy_t *policy )
{
psa_status_t status;
const psa_persistent_key_storage_format *storage_format =
(const psa_persistent_key_storage_format *)storage_data;
uint32_t version;
if( storage_data_length < sizeof(*storage_format) )
return( PSA_ERROR_STORAGE_FAILURE );
status = check_magic_header( storage_data );
if( status != PSA_SUCCESS )
return( status );
GET_UINT32_LE(version, storage_format->version, 0);
if( version != 0 )
return( PSA_ERROR_STORAGE_FAILURE );
GET_UINT32_LE(*key_data_length, storage_format->data_len, 0);
if( *key_data_length > ( storage_data_length - sizeof(*storage_format) ) ||
*key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE )
return( PSA_ERROR_STORAGE_FAILURE );
*key_data = mbedtls_calloc( 1, *key_data_length );
if( *key_data == NULL )
return( PSA_ERROR_INSUFFICIENT_MEMORY );
GET_UINT32_LE(*type, storage_format->type, 0);
GET_UINT32_LE(policy->usage, storage_format->policy, 0);
GET_UINT32_LE(policy->alg, storage_format->policy, sizeof( uint32_t ));
memcpy( *key_data, storage_format->key_data, *key_data_length );
return( PSA_SUCCESS );
}
psa_status_t psa_save_persistent_key( const psa_key_slot_t key,
const psa_key_type_t type,
const psa_key_policy_t *policy,
const uint8_t *data,
const size_t data_length )
{
size_t storage_data_length;
uint8_t *storage_data;
psa_status_t status;
if( data_length > PSA_CRYPTO_MAX_STORAGE_SIZE )
return PSA_ERROR_INSUFFICIENT_STORAGE;
storage_data_length = data_length + sizeof( psa_persistent_key_storage_format );
storage_data = mbedtls_calloc( 1, storage_data_length );
if( storage_data == NULL )
return( PSA_ERROR_INSUFFICIENT_MEMORY );
psa_format_key_data_for_storage( data, data_length, type, policy,
storage_data );
status = psa_crypto_storage_store( key,
storage_data, storage_data_length );
mbedtls_free( storage_data );
return( status );
}
void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length )
{
if( key_data != NULL )
{
mbedtls_platform_zeroize( key_data, key_data_length );
}
mbedtls_free( key_data );
}
psa_status_t psa_load_persistent_key( psa_key_slot_t key,
psa_key_type_t *type,
psa_key_policy_t *policy,
uint8_t **data,
size_t *data_length )
{
psa_status_t status = PSA_SUCCESS;
uint8_t *loaded_data;
size_t storage_data_length = 0;
status = psa_crypto_storage_get_data_length( key, &storage_data_length );
if( status != PSA_SUCCESS )
return( status );
loaded_data = mbedtls_calloc( 1, storage_data_length );
if( loaded_data == NULL )
return( PSA_ERROR_INSUFFICIENT_MEMORY );
status = psa_crypto_storage_load( key, loaded_data, storage_data_length );
if( status != PSA_SUCCESS )
goto exit;
status = psa_parse_key_data_from_storage( loaded_data, storage_data_length,
data, data_length, type, policy );
exit:
mbedtls_free( loaded_data );
return( status );
}
#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */

View File

@ -0,0 +1,177 @@
/**
* \file psa_crypto_storage.h
*
* \brief PSA cryptography module: Mbed TLS key storage
*/
/*
* Copyright (C) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef PSA_CRYPTO_STORAGE_H
#define PSA_CRYPTO_STORAGE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Include the Mbed TLS configuration file, the way Mbed TLS does it
* in each of its header files. */
#if defined(MBEDTLS_CONFIG_FILE)
#include MBEDTLS_CONFIG_FILE
#else
#include "mbedtls/config.h"
#endif
#include "psa/crypto.h"
#include <stdint.h>
/* Limit the maximum key size to 30kB (just in case someone tries to
* inadvertently store an obscene amount of data) */
#define PSA_CRYPTO_MAX_STORAGE_SIZE ( 30 * 1024 )
/**
* \brief Format key data and metadata and save to a location for given key
* slot.
*
* This function formats the key data and metadata and saves it to a
* persistent storage backend. The storage location corresponding to the
* key slot must be empty, otherwise this function will fail. This function
* should be called after psa_import_key_into_slot() to ensure the
* persistent key is not saved into a storage location corresponding to an
* already occupied non-persistent key, as well as validating the key data.
*
*
* \param key Slot number of the key to be stored. This must be a
* valid slot for a key of the chosen type. This should be
* an occupied key slot with an unoccupied corresponding
* storage location.
* \param type Key type (a \c PSA_KEY_TYPE_XXX value).
* \param[in] policy The key policy to save.
* \param[in] data Buffer containing the key data.
* \param data_length The number of bytes that make up the key data.
*
* \retval PSA_SUCCESS
* \retval PSA_ERROR_INSUFFICIENT_STORAGE
* \retval PSA_ERROR_STORAGE_FAILURE
*/
psa_status_t psa_save_persistent_key( const psa_key_slot_t key,
const psa_key_type_t type,
const psa_key_policy_t *policy,
const uint8_t *data,
const size_t data_length );
/**
* \brief Parses key data and metadata and load persistent key for given
* key slot number.
*
* This function reads from a storage backend, parses the key data and
* metadata and writes them to the appropriate output parameters.
*
* Note: This function allocates a buffer and returns a pointer to it through
* the data parameter. psa_free_persistent_key_data() must be called after
* this function to zeroize and free this buffer, regardless of whether this
* function succeeds or fails.
*
* \param key Slot number whose content is to be loaded. This
* must be an unoccupied key slot with an occupied
* corresponding storage location. The key slot
* lifetime must be set to persistent.
* \param[out] type On success, the key type (a \c PSA_KEY_TYPE_XXX
* value).
* \param[out] policy On success, the key's policy.
* \param[out] data Pointer to an allocated key data buffer on return.
* \param[out] data_length The number of bytes that make up the key data.
*
* \retval PSA_SUCCESS
* \retval PSA_ERROR_INSUFFICIENT_MEMORY
* \retval PSA_ERROR_STORAGE_FAILURE
*/
psa_status_t psa_load_persistent_key( psa_key_slot_t key,
psa_key_type_t *type,
psa_key_policy_t *policy,
uint8_t **data,
size_t *data_length );
/**
* \brief Remove persistent data for the given key slot number.
*
* \param key Slot number whose content is to be removed
* from persistent storage.
*
* \retval PSA_SUCCESS
* \retval PSA_ERROR_STORAGE_FAILURE
*/
psa_status_t psa_destroy_persistent_key( const psa_key_slot_t key );
/**
* \brief Zeroizes and frees the given buffer.
*
* This function must be called at some point after psa_load_persistent_key()
* to zeroize and free the memory allocated to the buffer in that function.
*
* \param key_data Buffer for the key data.
* \param key_data_length Size of the key data buffer.
*
*/
void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length );
/**
* \brief Formats key data and metadata for persistent storage
*
* \param[in] data Buffer for the key data.
* \param data_length Length of the key data buffer.
* \param type Key type (a \c PSA_KEY_TYPE_XXX value).
* \param policy The key policy.
* \param[out] storage_data Output buffer for the formatted data.
*
*/
void psa_format_key_data_for_storage( const uint8_t *data,
const size_t data_length,
const psa_key_type_t type,
const psa_key_policy_t *policy,
uint8_t *storage_data );
/**
* \brief Parses persistent storage data into key data and metadata
*
* \param[in] storage_data Buffer for the storage data.
* \param storage_data_length Length of the storage data buffer
* \param[out] key_data On output, pointer to a newly allocated buffer
* containing the key data. This must be freed
* using psa_free_persistent_key_data()
* \param[out] key_data_length Length of the key data buffer
* \param[out] type Key type (a \c PSA_KEY_TYPE_XXX value).
* \param[out] policy The key policy.
*
* \retval PSA_SUCCESS
* \retval PSA_ERROR_INSUFFICIENT_STORAGE
* \retval PSA_ERROR_INSUFFICIENT_MEMORY
* \retval PSA_ERROR_STORAGE_FAILURE
*/
psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
size_t storage_data_length,
uint8_t **key_data,
size_t *key_data_length,
psa_key_type_t *type,
psa_key_policy_t *policy );
#ifdef __cplusplus
}
#endif
#endif /* PSA_CRYPTO_STORAGE_H */

View File

@ -0,0 +1,112 @@
/**
* \file psa_crypto_storage_backend.h
*
* \brief PSA cryptography module: Mbed TLS key storage backend
*/
/*
* Copyright (C) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef PSA_CRYPTO_STORAGE_BACKEND_H
#define PSA_CRYPTO_STORAGE_BACKEND_H
#ifdef __cplusplus
extern "C" {
#endif
/* Include the Mbed TLS configuration file, the way Mbed TLS does it
* in each of its header files. */
#if defined(MBEDTLS_CONFIG_FILE)
#include MBEDTLS_CONFIG_FILE
#else
#include "mbedtls/config.h"
#endif
#include "psa/crypto.h"
#include "psa_crypto_storage.h"
#include <stdint.h>
/**
* \brief Load persistent data for the given key slot number.
*
* This function reads data from a storage backend and returns the data in a
* buffer.
*
* \param key Slot number whose content is to be loaded. This must
* be a key slot whose lifetime is set to persistent.
* \param[out] data Buffer where the data is to be written.
* \param data_size Size of the \c data buffer in bytes.
*
* \retval PSA_SUCCESS
* \retval PSA_ERROR_STORAGE_FAILURE
*/
psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data,
size_t data_size );
/**
* \brief Store persistent data for the given key slot number.
*
* This function stores the given data buffer to a persistent storage.
*
* \param key Slot number whose content is to be stored.
* \param[in] data Buffer containing the data to be stored.
* \param data_length The number of bytes
* that make up the data.
*
* \retval PSA_SUCCESS
* \retval PSA_ERROR_INSUFFICIENT_STORAGE
* \retval PSA_ERROR_STORAGE_FAILURE
*/
psa_status_t psa_crypto_storage_store( const psa_key_slot_t key,
const uint8_t *data,
size_t data_length );
/**
* \brief Checks if persistent data is stored for the given key slot number
*
* This function checks if any key data or metadata exists for the key slot in
* the persistent storage.
*
* \param key Slot number whose content is to be checked.
*
* \retval 0
* No persistent data present for slot number
* \retval 1
* Persistent data present for slot number
*/
int psa_is_key_present_in_storage( const psa_key_slot_t key );
/**
* \brief Get data length for given key slot number.
*
* \param key Slot number whose stored data length is to be obtained.
* \param[out] data_length The number of bytes
* that make up the data.
*
* \retval PSA_SUCCESS
* \retval PSA_ERROR_STORAGE_FAILURE
*/
psa_status_t psa_crypto_storage_get_data_length( const psa_key_slot_t key,
size_t *data_length );
#ifdef __cplusplus
}
#endif
#endif /* PSA_CRYPTO_STORAGE_H */

View File

@ -0,0 +1,218 @@
/*
* PSA file storage backend for persistent keys
*/
/* Copyright (C) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#if defined(MBEDTLS_CONFIG_FILE)
#include MBEDTLS_CONFIG_FILE
#else
#include "mbedtls/config.h"
#endif
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_FILE_C)
#include <string.h>
#include "psa/crypto.h"
#include "psa_crypto_storage_backend.h"
#include "mbedtls/platform_util.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#define mbedtls_snprintf snprintf
#endif
/* This option sets where files are to be stored. If this is left unset,
* the files by default will be stored in the same location as the program,
* which may not be desired or possible. */
#if !defined(CRYPTO_STORAGE_FILE_LOCATION)
#define CRYPTO_STORAGE_FILE_LOCATION ""
#endif
enum { MAX_LOCATION_LEN = sizeof(CRYPTO_STORAGE_FILE_LOCATION) + 40 };
static void key_slot_to_location( const psa_key_slot_t key,
char *location,
size_t location_size )
{
mbedtls_snprintf( location, location_size,
CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_%d", key );
}
psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data,
size_t data_size )
{
psa_status_t status = PSA_SUCCESS;
FILE *file;
size_t num_read;
char slot_location[MAX_LOCATION_LEN];
key_slot_to_location( key, slot_location, MAX_LOCATION_LEN );
file = fopen( slot_location, "rb" );
if( file == NULL )
{
status = PSA_ERROR_STORAGE_FAILURE;
goto exit;
}
num_read = fread( data, 1, data_size, file );
if( num_read != data_size )
status = PSA_ERROR_STORAGE_FAILURE;
exit:
if( file != NULL )
fclose( file );
return( status );
}
int psa_is_key_present_in_storage( const psa_key_slot_t key )
{
char slot_location[MAX_LOCATION_LEN];
FILE *file;
key_slot_to_location( key, slot_location, MAX_LOCATION_LEN );
file = fopen( slot_location, "r" );
if( file == NULL )
{
/* File doesn't exist */
return( 0 );
}
fclose( file );
return( 1 );
}
psa_status_t psa_crypto_storage_store( const psa_key_slot_t key,
const uint8_t *data,
size_t data_length )
{
psa_status_t status = PSA_SUCCESS;
int ret;
size_t num_written;
char slot_location[MAX_LOCATION_LEN];
FILE *file;
/* The storage location corresponding to "key slot 0" is used as a
* temporary location in order to make the apparition of the actual slot
* file atomic. 0 is not a valid key slot number, so this should not
* affect actual keys. */
const char *temp_location = CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_0";
key_slot_to_location( key, slot_location, MAX_LOCATION_LEN );
if( psa_is_key_present_in_storage( key ) == 1 )
return( PSA_ERROR_OCCUPIED_SLOT );
file = fopen( temp_location, "wb" );
if( file == NULL )
{
status = PSA_ERROR_STORAGE_FAILURE;
goto exit;
}
num_written = fwrite( data, 1, data_length, file );
if( num_written != data_length )
{
status = PSA_ERROR_STORAGE_FAILURE;
goto exit;
}
ret = fclose( file );
file = NULL;
if( ret != 0 )
{
status = PSA_ERROR_STORAGE_FAILURE;
goto exit;
}
if( rename( temp_location, slot_location ) != 0 )
{
status = PSA_ERROR_STORAGE_FAILURE;
goto exit;
}
exit:
if( file != NULL )
fclose( file );
remove( temp_location );
return( status );
}
psa_status_t psa_destroy_persistent_key( const psa_key_slot_t key )
{
FILE *file;
char slot_location[MAX_LOCATION_LEN];
key_slot_to_location( key, slot_location, MAX_LOCATION_LEN );
/* Only try remove the file if it exists */
file = fopen( slot_location, "rb" );
if( file != NULL )
{
fclose( file );
if( remove( slot_location ) != 0 )
return( PSA_ERROR_STORAGE_FAILURE );
}
return( PSA_SUCCESS );
}
psa_status_t psa_crypto_storage_get_data_length( const psa_key_slot_t key,
size_t *data_length )
{
psa_status_t status = PSA_SUCCESS;
FILE *file;
long file_size;
char slot_location[MAX_LOCATION_LEN];
key_slot_to_location( key, slot_location, MAX_LOCATION_LEN );
file = fopen( slot_location, "rb" );
if( file == NULL )
return( PSA_ERROR_EMPTY_SLOT );
if( fseek( file, 0, SEEK_END ) != 0 )
{
status = PSA_ERROR_STORAGE_FAILURE;
goto exit;
}
file_size = ftell( file );
if( file_size < 0 )
{
status = PSA_ERROR_STORAGE_FAILURE;
goto exit;
}
#if LONG_MAX > SIZE_MAX
if( (unsigned long) file_size > SIZE_MAX )
{
status = PSA_ERROR_STORAGE_FAILURE;
goto exit;
}
#endif
*data_length = (size_t) file_size;
exit:
fclose( file );
return( status );
}
#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_FILE_C */

View File

@ -0,0 +1,184 @@
/*
* PSA storage backend for persistent keys using psa_its APIs.
*/
/* Copyright (C) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#if defined(MBEDTLS_CONFIG_FILE)
#include MBEDTLS_CONFIG_FILE
#else
#include "mbedtls/config.h"
#endif
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_ITS_C)
#include "psa/crypto.h"
#include "psa_crypto_storage_backend.h"
#include "psa_prot_internal_storage.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#endif
static psa_status_t its_to_psa_error( psa_its_status_t ret )
{
switch( ret )
{
case PSA_ITS_SUCCESS:
return( PSA_SUCCESS );
case PSA_ITS_ERROR_KEY_NOT_FOUND:
return( PSA_ERROR_EMPTY_SLOT );
case PSA_ITS_ERROR_STORAGE_FAILURE:
return( PSA_ERROR_STORAGE_FAILURE );
case PSA_ITS_ERROR_INSUFFICIENT_SPACE:
return( PSA_ERROR_INSUFFICIENT_STORAGE );
case PSA_ITS_ERROR_INVALID_KEY:
case PSA_PS_ERROR_OFFSET_INVALID:
case PSA_ITS_ERROR_INCORRECT_SIZE:
case PSA_ITS_ERROR_BAD_POINTER:
return( PSA_ERROR_INVALID_ARGUMENT );
case PSA_ITS_ERROR_FLAGS_NOT_SUPPORTED:
return( PSA_ERROR_NOT_SUPPORTED );
case PSA_ITS_ERROR_WRITE_ONCE:
return( PSA_ERROR_OCCUPIED_SLOT );
default:
return( PSA_ERROR_UNKNOWN_ERROR );
}
}
static uint32_t psa_its_identifier_of_slot( psa_key_slot_t key )
{
return( key );
}
psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data,
size_t data_size )
{
psa_its_status_t ret;
psa_status_t status;
uint32_t data_identifier = psa_its_identifier_of_slot( key );
struct psa_its_info_t data_identifier_info;
ret = psa_its_get_info( data_identifier, &data_identifier_info );
status = its_to_psa_error( ret );
if( status != PSA_SUCCESS )
return( status );
ret = psa_its_get( data_identifier, 0, data_size, data );
status = its_to_psa_error( ret );
return( status );
}
int psa_is_key_present_in_storage( const psa_key_slot_t key )
{
psa_its_status_t ret;
uint32_t data_identifier = psa_its_identifier_of_slot( key );
struct psa_its_info_t data_identifier_info;
ret = psa_its_get_info( data_identifier, &data_identifier_info );
if( ret == PSA_ITS_ERROR_KEY_NOT_FOUND )
return( 0 );
return( 1 );
}
psa_status_t psa_crypto_storage_store( const psa_key_slot_t key,
const uint8_t *data,
size_t data_length )
{
psa_its_status_t ret;
psa_status_t status;
uint32_t data_identifier = psa_its_identifier_of_slot( key );
struct psa_its_info_t data_identifier_info;
if( psa_is_key_present_in_storage( key ) == 1 )
return( PSA_ERROR_OCCUPIED_SLOT );
ret = psa_its_set( data_identifier, data_length, data, 0 );
status = its_to_psa_error( ret );
if( status != PSA_SUCCESS )
{
return( PSA_ERROR_STORAGE_FAILURE );
}
ret = psa_its_get_info( data_identifier, &data_identifier_info );
status = its_to_psa_error( ret );
if( status != PSA_SUCCESS )
{
goto exit;
}
if( data_identifier_info.size != data_length )
{
status = PSA_ERROR_STORAGE_FAILURE;
goto exit;
}
exit:
if( status != PSA_SUCCESS )
psa_its_remove( data_identifier );
return( status );
}
psa_status_t psa_destroy_persistent_key( const psa_key_slot_t key )
{
psa_its_status_t ret;
uint32_t data_identifier = psa_its_identifier_of_slot( key );
struct psa_its_info_t data_identifier_info;
ret = psa_its_get_info( data_identifier, &data_identifier_info );
if( ret == PSA_ITS_ERROR_KEY_NOT_FOUND )
return( PSA_SUCCESS );
if( psa_its_remove( data_identifier ) != PSA_ITS_SUCCESS )
return( PSA_ERROR_STORAGE_FAILURE );
ret = psa_its_get_info( data_identifier, &data_identifier_info );
if( ret != PSA_ITS_ERROR_KEY_NOT_FOUND )
return( PSA_ERROR_STORAGE_FAILURE );
return( PSA_SUCCESS );
}
psa_status_t psa_crypto_storage_get_data_length( const psa_key_slot_t key,
size_t *data_length )
{
psa_its_status_t ret;
psa_status_t status;
uint32_t data_identifier = psa_its_identifier_of_slot( key );
struct psa_its_info_t data_identifier_info;
ret = psa_its_get_info( data_identifier, &data_identifier_info );
status = its_to_psa_error( ret );
if( status != PSA_SUCCESS )
return( status );
*data_length = (size_t) data_identifier_info.size;
return( PSA_SUCCESS );
}
#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_ITS_C */

View File

@ -0,0 +1,211 @@
/**
* \file psa/crypto_struct.h
*
* \brief PSA cryptography module: Mbed TLS structured type implementations
*
* \note This file may not be included directly. Applications must
* include psa/crypto.h.
*
* This file contains the definitions of some data structures with
* implementation-specific definitions.
*
* In implementations with isolation between the application and the
* cryptography module, it is expected that the front-end and the back-end
* would have different versions of this file.
*/
/*
* Copyright (C) 2018, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef PSA_CRYPTO_STRUCT_H
#define PSA_CRYPTO_STRUCT_H
/* Include the Mbed TLS configuration file, the way Mbed TLS does it
* in each of its header files. */
#if !defined(MBEDTLS_CONFIG_FILE)
#include "../mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/cipher.h"
#include "mbedtls/cmac.h"
#include "mbedtls/gcm.h"
#include "mbedtls/md.h"
#include "mbedtls/md2.h"
#include "mbedtls/md4.h"
#include "mbedtls/md5.h"
#include "mbedtls/ripemd160.h"
#include "mbedtls/sha1.h"
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
struct psa_hash_operation_s
{
psa_algorithm_t alg;
union
{
unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
#if defined(MBEDTLS_MD2_C)
mbedtls_md2_context md2;
#endif
#if defined(MBEDTLS_MD4_C)
mbedtls_md4_context md4;
#endif
#if defined(MBEDTLS_MD5_C)
mbedtls_md5_context md5;
#endif
#if defined(MBEDTLS_RIPEMD160_C)
mbedtls_ripemd160_context ripemd160;
#endif
#if defined(MBEDTLS_SHA1_C)
mbedtls_sha1_context sha1;
#endif
#if defined(MBEDTLS_SHA256_C)
mbedtls_sha256_context sha256;
#endif
#if defined(MBEDTLS_SHA512_C)
mbedtls_sha512_context sha512;
#endif
} ctx;
};
#if defined(MBEDTLS_MD_C)
typedef struct
{
/** The hash context. */
struct psa_hash_operation_s hash_ctx;
/** The HMAC part of the context. */
uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
} psa_hmac_internal_data;
#endif /* MBEDTLS_MD_C */
struct psa_mac_operation_s
{
psa_algorithm_t alg;
unsigned int key_set : 1;
unsigned int iv_required : 1;
unsigned int iv_set : 1;
unsigned int has_input : 1;
unsigned int is_sign : 1;
uint8_t mac_size;
union
{
unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
#if defined(MBEDTLS_MD_C)
psa_hmac_internal_data hmac;
#endif
#if defined(MBEDTLS_CMAC_C)
mbedtls_cipher_context_t cmac;
#endif
} ctx;
};
struct psa_cipher_operation_s
{
psa_algorithm_t alg;
unsigned int key_set : 1;
unsigned int iv_required : 1;
unsigned int iv_set : 1;
uint8_t iv_size;
uint8_t block_size;
union
{
mbedtls_cipher_context_t cipher;
} ctx;
};
#if defined(MBEDTLS_MD_C)
typedef struct
{
uint8_t *info;
size_t info_length;
psa_hmac_internal_data hmac;
uint8_t prk[PSA_HASH_MAX_SIZE];
uint8_t output_block[PSA_HASH_MAX_SIZE];
#if PSA_HASH_MAX_SIZE > 0xff
#error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
#endif
uint8_t offset_in_block;
uint8_t block_number;
} psa_hkdf_generator_t;
#endif /* MBEDTLS_MD_C */
#if defined(MBEDTLS_MD_C)
typedef struct psa_tls12_prf_generator_s
{
/* The TLS 1.2 PRF uses the key for each HMAC iteration,
* hence we must store it for the lifetime of the generator.
* This is different from HKDF, where the key is only used
* in the extraction phase, but not during expansion. */
unsigned char *key;
size_t key_len;
/* `A(i) + seed` in the notation of RFC 5246, Sect. 5 */
uint8_t *Ai_with_seed;
size_t Ai_with_seed_len;
/* `HMAC_hash( prk, A(i) + seed )` in the notation of RFC 5246, Sect. 5. */
uint8_t output_block[PSA_HASH_MAX_SIZE];
#if PSA_HASH_MAX_SIZE > 0xff
#error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
#endif
/* Indicates how many bytes in the current HMAC block have
* already been read by the user. */
uint8_t offset_in_block;
/* The 1-based number of the block. */
uint8_t block_number;
} psa_tls12_prf_generator_t;
#endif /* MBEDTLS_MD_C */
struct psa_crypto_generator_s
{
psa_algorithm_t alg;
size_t capacity;
union
{
struct
{
uint8_t *data;
size_t size;
} buffer;
#if defined(MBEDTLS_MD_C)
psa_hkdf_generator_t hkdf;
psa_tls12_prf_generator_t tls12_prf;
#endif
} ctx;
};
#define PSA_CRYPTO_GENERATOR_INIT {0, 0, {{0, 0}}}
static inline struct psa_crypto_generator_s psa_crypto_generator_init( void )
{
const struct psa_crypto_generator_s v = PSA_CRYPTO_GENERATOR_INIT;
return( v );
}
struct psa_key_policy_s
{
psa_key_usage_t usage;
psa_algorithm_t alg;
};
#endif /* PSA_CRYPTO_STRUCT_H */

View File

@ -0,0 +1,4 @@
{
"name": "mbed-crypto",
"macros": ["MBEDTLS_PSA_HAS_ITS_IO"]
}

View File

@ -63,6 +63,13 @@ DLEXT = dylib
endif endif
endif endif
ifdef USE_CRYPTO_SUBMODULE
# Look in crypto for libmbedcrypto.
LOCAL_LDFLAGS += -L../crypto/library
LOCAL_CFLAGS += -I../crypto/include
CRYPTO := ../crypto/library/
else
OBJS_CRYPTO= aes.o aesni.o arc4.o \ OBJS_CRYPTO= aes.o aesni.o arc4.o \
aria.o asn1parse.o asn1write.o \ aria.o asn1parse.o asn1write.o \
base64.o bignum.o blowfish.o \ base64.o bignum.o blowfish.o \
@ -85,6 +92,8 @@ OBJS_CRYPTO= aes.o aesni.o arc4.o \
sha1.o sha256.o sha512.o \ sha1.o sha256.o sha512.o \
threading.o timing.o version.o \ threading.o timing.o version.o \
version_features.o xtea.o version_features.o xtea.o
CRYPTO :=
endif
OBJS_X509= certs.o pkcs11.o x509.o \ OBJS_X509= certs.o pkcs11.o x509.o \
x509_create.o x509_crl.o x509_crt.o \ x509_create.o x509_crl.o x509_crt.o \
@ -148,7 +157,7 @@ ifneq ($(APPLE_BUILD),0)
endif endif
endif endif
libmbedx509.$(SOEXT_X509): $(OBJS_X509) libmbedcrypto.so libmbedx509.$(SOEXT_X509): $(OBJS_X509) $(CRYPTO)libmbedcrypto.so
echo " LD $@" echo " LD $@"
$(CC) -shared -Wl,-soname,$@ -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509) $(CC) -shared -Wl,-soname,$@ -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509)
@ -165,6 +174,10 @@ libmbedx509.dll: $(OBJS_X509) libmbedcrypto.dll
$(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_X509) -lws2_32 -lwinmm -lgdi32 -L. -lmbedcrypto -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_X509) -lws2_32 -lwinmm -lgdi32 -L. -lmbedcrypto -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS)
# crypto # crypto
ifdef USE_CRYPTO_SUBMODULE
libmbedcrypto.%:
$(MAKE) CRYPTO_INCLUDES:="-I../../include -I../include" -C ../crypto/library $@
else
libmbedcrypto.a: $(OBJS_CRYPTO) libmbedcrypto.a: $(OBJS_CRYPTO)
echo " AR $@" echo " AR $@"
$(AR) $(ARFLAGS) $@ $(OBJS_CRYPTO) $(AR) $(ARFLAGS) $@ $(OBJS_CRYPTO)
@ -190,6 +203,7 @@ libmbedcrypto.dylib: $(OBJS_CRYPTO)
libmbedcrypto.dll: $(OBJS_CRYPTO) libmbedcrypto.dll: $(OBJS_CRYPTO)
echo " LD $@" echo " LD $@"
$(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_CRYPTO) -lws2_32 -lwinmm -lgdi32 -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_CRYPTO) -lws2_32 -lwinmm -lgdi32 -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS)
endif
.c.o: .c.o:
echo " CC $<" echo " CC $<"

View File

@ -36,6 +36,7 @@
#include <string.h> #include <string.h>
#include "mbedtls/aes.h" #include "mbedtls/aes.h"
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h" #include "mbedtls/platform_util.h"
#if defined(MBEDTLS_PADLOCK_C) #if defined(MBEDTLS_PADLOCK_C)
#include "mbedtls/padlock.h" #include "mbedtls/padlock.h"
@ -1142,11 +1143,11 @@ int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
unsigned char prev_tweak[16]; unsigned char prev_tweak[16];
unsigned char tmp[16]; unsigned char tmp[16];
/* Sectors must be at least 16 bytes. */ /* Data units must be at least 16 bytes long. */
if( length < 16 ) if( length < 16 )
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
/* NIST SP 80-38E disallows data units larger than 2**20 blocks. */ /* NIST SP 800-38E disallows data units larger than 2**20 blocks. */
if( length > ( 1 << 20 ) * 16 ) if( length > ( 1 << 20 ) * 16 )
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
@ -1757,7 +1758,7 @@ int mbedtls_aes_self_test( int verbose )
* there is an alternative underlying implementation i.e. when * there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined. * MBEDTLS_AES_ALT is defined.
*/ */
if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 )
{ {
mbedtls_printf( "skipped\n" ); mbedtls_printf( "skipped\n" );
continue; continue;
@ -1821,7 +1822,7 @@ int mbedtls_aes_self_test( int verbose )
* there is an alternative underlying implementation i.e. when * there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined. * MBEDTLS_AES_ALT is defined.
*/ */
if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 )
{ {
mbedtls_printf( "skipped\n" ); mbedtls_printf( "skipped\n" );
continue; continue;
@ -1886,7 +1887,7 @@ int mbedtls_aes_self_test( int verbose )
* there is an alternative underlying implementation i.e. when * there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined. * MBEDTLS_AES_ALT is defined.
*/ */
if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 )
{ {
mbedtls_printf( "skipped\n" ); mbedtls_printf( "skipped\n" );
continue; continue;
@ -1949,7 +1950,7 @@ int mbedtls_aes_self_test( int verbose )
* there is an alternative underlying implementation i.e. when * there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined. * MBEDTLS_AES_ALT is defined.
*/ */
if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 )
{ {
mbedtls_printf( "skipped\n" ); mbedtls_printf( "skipped\n" );
continue; continue;

View File

@ -257,7 +257,7 @@ int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
return( (int) len ); return( (int) len );
} }
int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag,
const char *text, size_t text_len ) const char *text, size_t text_len )
{ {
int ret; int ret;
@ -267,24 +267,27 @@ int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start
(const unsigned char *) text, text_len ) ); (const unsigned char *) text, text_len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_PRINTABLE_STRING ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
return( (int) len ); return( (int) len );
} }
int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start,
const char *text, size_t text_len )
{
return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) );
}
int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start,
const char *text, size_t text_len )
{
return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) );
}
int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
const char *text, size_t text_len ) const char *text, size_t text_len )
{ {
int ret; return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) );
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
(const unsigned char *) text, text_len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_IA5_STRING ) );
return( (int) len );
} }
int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,

View File

@ -2056,12 +2056,12 @@ cleanup:
/* /*
* Miller-Rabin pseudo-primality test (HAC 4.24) * Miller-Rabin pseudo-primality test (HAC 4.24)
*/ */
static int mpi_miller_rabin( const mbedtls_mpi *X, static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng ) void *p_rng )
{ {
int ret, count; int ret, count;
size_t i, j, k, n, s; size_t i, j, k, s;
mbedtls_mpi W, R, T, A, RR; mbedtls_mpi W, R, T, A, RR;
mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
@ -2077,27 +2077,12 @@ static int mpi_miller_rabin( const mbedtls_mpi *X,
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
i = mbedtls_mpi_bitlen( X ); i = mbedtls_mpi_bitlen( X );
/*
* HAC, table 4.4
*/
n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
for( i = 0; i < n; i++ ) for( i = 0; i < rounds; i++ )
{ {
/* /*
* pick a random A, 1 < A < |X| - 1 * pick a random A, 1 < A < |X| - 1
*/ */
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
{
j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
}
A.p[0] |= 3;
count = 0; count = 0;
do { do {
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
@ -2105,7 +2090,7 @@ static int mpi_miller_rabin( const mbedtls_mpi *X,
j = mbedtls_mpi_bitlen( &A ); j = mbedtls_mpi_bitlen( &A );
k = mbedtls_mpi_bitlen( &W ); k = mbedtls_mpi_bitlen( &W );
if (j > k) { if (j > k) {
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) ); A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
} }
if (count++ > 30) { if (count++ > 30) {
@ -2160,7 +2145,7 @@ cleanup:
/* /*
* Pseudo-primality test: small factors, then Miller-Rabin * Pseudo-primality test: small factors, then Miller-Rabin
*/ */
int mbedtls_mpi_is_prime( const mbedtls_mpi *X, int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng ) void *p_rng )
{ {
@ -2186,17 +2171,34 @@ int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
return( ret ); return( ret );
} }
return( mpi_miller_rabin( &XX, f_rng, p_rng ) ); return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
/*
* Pseudo-primality test, error probability 2^-80
*/
int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
/*
* In the past our key generation aimed for an error rate of at most
* 2^-80. Since this function is deprecated, aim for the same certainty
* here as well.
*/
return mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng );
}
#endif
/* /*
* Prime number generation * Prime number generation
* *
* If dh_flag is 0 and nbits is at least 1024, then the procedure * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
* follows the RSA probably-prime generation method of FIPS 186-4. * be either 1024 bits or 1536 bits long, and flags must contain
* NB. FIPS 186-4 only allows the specific bit lengths of 1024 and 1536. * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
*/ */
int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng ) void *p_rng )
{ {
@ -2209,6 +2211,7 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
#endif #endif
int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
size_t k, n; size_t k, n;
int rounds;
mbedtls_mpi_uint r; mbedtls_mpi_uint r;
mbedtls_mpi Y; mbedtls_mpi Y;
@ -2219,6 +2222,27 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
n = BITS_TO_LIMBS( nbits ); n = BITS_TO_LIMBS( nbits );
if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
{
/*
* 2^-80 error probability, number of rounds chosen per HAC, table 4.4
*/
rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
}
else
{
/*
* 2^-100 error probability, number of rounds computed based on HAC,
* fact 4.48
*/
rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 :
( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 :
( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 :
( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 );
}
while( 1 ) while( 1 )
{ {
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
@ -2229,9 +2253,9 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) ); if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
X->p[0] |= 1; X->p[0] |= 1;
if( dh_flag == 0 ) if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
{ {
ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ); ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
goto cleanup; goto cleanup;
@ -2264,8 +2288,10 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
*/ */
if( ( ret = mpi_check_small_factors( X ) ) == 0 && if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
( ret = mpi_check_small_factors( &Y ) ) == 0 && ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 && ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) == 0 &&
( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
== 0 )
goto cleanup; goto cleanup;
if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )

View File

@ -218,12 +218,13 @@ const size_t mbedtls_test_ca_key_rsa_len = sizeof( mbedtls_test_ca_key_rsa );
const char mbedtls_test_ca_pwd_rsa[] = "PolarSSLTest"; const char mbedtls_test_ca_pwd_rsa[] = "PolarSSLTest";
const size_t mbedtls_test_ca_pwd_rsa_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; const size_t mbedtls_test_ca_pwd_rsa_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1;
/* tests/data_files/server2.crt */
const char mbedtls_test_srv_crt_rsa[] = const char mbedtls_test_srv_crt_rsa[] =
"-----BEGIN CERTIFICATE-----\r\n" "-----BEGIN CERTIFICATE-----\r\n"
"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" "MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" "MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n"
"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" "A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n"
"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" "AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n"
"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" "owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n"
"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" "NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n"
@ -231,16 +232,17 @@ const char mbedtls_test_srv_crt_rsa[] =
"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" "hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n"
"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" "HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n"
"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" "VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n"
"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJxnXClY\r\n" "FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAAFzC0rF\r\n"
"oHkbp70cqBrsGXLybA74czbO5RdLEgFs7rHVS9r+c293luS/KdliLScZqAzYVylw\r\n" "y6De8WMcdgQrEw3AhBHFjzqnxZw1ene4IBSC7lTw8rBSy3jOWQdPUWn+0y/pCeeF\r\n"
"UfRWvKMoWhHYKp3dEIS4xTXk6/5zXxhv9Rw8SGc8qn6vITHk1S1mPevtekgasY5Y\r\n" "kti6sevFdl1hLemGtd4q+T9TKEKGg3ND4ARfB5AUZZ9uEHq8WBkiwus5clGS17Qd\r\n"
"iWQuM3h4YVlRH3HHEMAD1TnAexfXHHDFQGe+Bd1iAbz1/sH9H8l4StwX6egvTK3M\r\n" "dS/TOisB59tQruLx1E1bPLtBKyqk4koC5WAULJwfpswGSyWJTpYwIpxcWE3D2tBu\r\n"
"wXRwkKkvjKaEDA9ATbZx0mI8LGsxSuCqe9r9dyjmttd47J1p1Rulz3CLzaRcVIuS\r\n" "UB6MZfXZFzWmWEOyKbeoXjXe8GBCGgHLywvYDsGQ36HSGtEsAvR2QaTLSxWYcfk1\r\n"
"RRQfaD8neM9c1S/iJ/amTVqJxA1KOdOS5780WhPfSArA+g4qAmSjelc3p4wWpha8\r\n" "fbDn4jSWkb4yZy1r01UEigFQtONieGwRFaUqEcFJHJvEEGVgh9keaVlOj2vrwf5r\r\n"
"zhuYwjVuX6JHG0c=\r\n" "4mN4lW7gLdenN6g=\r\n"
"-----END CERTIFICATE-----\r\n"; "-----END CERTIFICATE-----\r\n";
const size_t mbedtls_test_srv_crt_rsa_len = sizeof( mbedtls_test_srv_crt_rsa ); const size_t mbedtls_test_srv_crt_rsa_len = sizeof( mbedtls_test_srv_crt_rsa );
/* tests/data_files/server2.key */
const char mbedtls_test_srv_key_rsa[] = const char mbedtls_test_srv_key_rsa[] =
"-----BEGIN RSA PRIVATE KEY-----\r\n" "-----BEGIN RSA PRIVATE KEY-----\r\n"
"MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" "MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n"
@ -271,11 +273,12 @@ const char mbedtls_test_srv_key_rsa[] =
"-----END RSA PRIVATE KEY-----\r\n"; "-----END RSA PRIVATE KEY-----\r\n";
const size_t mbedtls_test_srv_key_rsa_len = sizeof( mbedtls_test_srv_key_rsa ); const size_t mbedtls_test_srv_key_rsa_len = sizeof( mbedtls_test_srv_key_rsa );
/* tests/data_files/cli-rsa-sha256.crt */
const char mbedtls_test_cli_crt_rsa[] = const char mbedtls_test_cli_crt_rsa[] =
"-----BEGIN CERTIFICATE-----\r\n" "-----BEGIN CERTIFICATE-----\r\n"
"MIIDhTCCAm2gAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" "MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n"
"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
"MTcwNTA1MTMwNzU5WhcNMjcwNTA2MTMwNzU5WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" "MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n"
"A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" "A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n"
"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n"
"M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" "M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n"
@ -283,18 +286,18 @@ const char mbedtls_test_cli_crt_rsa[] =
"MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n" "MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n"
"4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" "4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n"
"/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" "/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n"
"o4GSMIGPMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITBjBgNVHSMEXDBa\r\n" "o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n"
"gBS0WuSls97SUva51aaVD+s+vMf9/6E/pD0wOzELMAkGA1UEBhMCTkwxETAPBgNV\r\n" "BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQsFAAOC\r\n"
"BAoMCFBvbGFyU1NMMRkwFwYDVQQDDBBQb2xhclNTTCBUZXN0IENBggEAMAkGA1Ud\r\n" "AQEAlHabem2Tu69VUN7EipwnQn1dIHdgvT5i+iQHpSxY1crPnBbAeSdAXwsVEqLQ\r\n"
"EwQCMAAwDQYJKoZIhvcNAQELBQADggEBAC7yO786NvcHpK8UovKIG9cB32oSQQom\r\n" "gOOIAQD5VIITNuoGgo4i+4OpNh9u7ZkpRHla+/swsfrFWRRbBNP5Bcu74AGLstwU\r\n"
"LoR0eHDRzdqEkoq7yGZufHFiRAAzbMqJfogRtxlrWAeB4y/jGaMBV25IbFOIcH2W\r\n" "zM8gIkBiyfM1Q1qDQISV9trlCG6O8vh8dp/rbI3rfzo99BOHXgFCrzXjCuW4vDsF\r\n"
"iCEaMMbG+VQLKNvuC63kmw/Zewc9ThM6Pa1Hcy0axT0faf1B/U01j0FIcw/6mTfK\r\n" "r+Dao26bX3sJ6UnEWg1H3o2x6PpUcvQ36h71/bz4TEbbUUEpe02V4QWuL+wrhHJL\r\n"
"D8w48OIwc1yr0JtutCVjig5DC0yznGMt32RyseOLcUe+lfq005v2PAiCozr5X8rE\r\n" "U7o3SVE3Og7jPF8sat0a50YUWhwEFI256m02KAXLg89ueUyYKEr6rNwhcvXJpvU9\r\n"
"ofGZpiM2NqRPePgYy+Vc75Zk28xkRQq1ncprgQb3S4vTsZdScpM9hLf+eMlrgqlj\r\n" "giIVvd0Sbjjnn7NC4VDbcXV8vw==\r\n"
"c5PLSkXBeLE5+fedkyfTaLxxQlgCpuoOhKBm04/R1pWNzUHyqagjO9Q=\r\n"
"-----END CERTIFICATE-----\r\n"; "-----END CERTIFICATE-----\r\n";
const size_t mbedtls_test_cli_crt_rsa_len = sizeof( mbedtls_test_cli_crt_rsa ); const size_t mbedtls_test_cli_crt_rsa_len = sizeof( mbedtls_test_cli_crt_rsa );
/* tests/data_files/cli-rsa.key */
const char mbedtls_test_cli_key_rsa[] = const char mbedtls_test_cli_key_rsa[] =
"-----BEGIN RSA PRIVATE KEY-----\r\n" "-----BEGIN RSA PRIVATE KEY-----\r\n"
"MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" "MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n"

View File

@ -58,6 +58,11 @@
#include "mbedtls/cmac.h" #include "mbedtls/cmac.h"
#endif #endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#include "mbedtls/psa_util.h"
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_PLATFORM_C) #if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#else #else
@ -71,7 +76,8 @@
* a non-zero value. * a non-zero value.
* This is currently only used by GCM and ChaCha20+Poly1305. * This is currently only used by GCM and ChaCha20+Poly1305.
*/ */
static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t len ) static int mbedtls_constant_time_memcmp( const void *v1, const void *v2,
size_t len )
{ {
const unsigned char *p1 = (const unsigned char*) v1; const unsigned char *p1 = (const unsigned char*) v1;
const unsigned char *p2 = (const unsigned char*) v2; const unsigned char *p2 = (const unsigned char*) v2;
@ -108,7 +114,8 @@ const int *mbedtls_cipher_list( void )
return( mbedtls_cipher_supported ); return( mbedtls_cipher_supported );
} }
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ) const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type(
const mbedtls_cipher_type_t cipher_type )
{ {
const mbedtls_cipher_definition_t *def; const mbedtls_cipher_definition_t *def;
@ -119,7 +126,8 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher
return( NULL ); return( NULL );
} }
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ) const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string(
const char *cipher_name )
{ {
const mbedtls_cipher_definition_t *def; const mbedtls_cipher_definition_t *def;
@ -133,7 +141,8 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher
return( NULL ); return( NULL );
} }
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(
const mbedtls_cipher_id_t cipher_id,
int key_bitlen, int key_bitlen,
const mbedtls_cipher_mode_t mode ) const mbedtls_cipher_mode_t mode )
{ {
@ -158,6 +167,29 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx )
if( ctx == NULL ) if( ctx == NULL )
return; return;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ctx->psa_enabled == 1 )
{
if( ctx->cipher_ctx != NULL )
{
mbedtls_cipher_context_psa * const cipher_psa =
(mbedtls_cipher_context_psa *) ctx->cipher_ctx;
if( cipher_psa->slot_state == MBEDTLS_CIPHER_PSA_KEY_OWNED )
{
/* xxx_free() doesn't allow to return failures. */
(void) psa_destroy_key( cipher_psa->slot );
}
mbedtls_platform_zeroize( cipher_psa, sizeof( *cipher_psa ) );
mbedtls_free( cipher_psa );
}
mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) );
return;
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_CMAC_C) #if defined(MBEDTLS_CMAC_C)
if( ctx->cmac_ctx ) if( ctx->cmac_ctx )
{ {
@ -173,7 +205,8 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx )
mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) );
} }
int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx,
const mbedtls_cipher_info_t *cipher_info )
{ {
if( NULL == cipher_info || NULL == ctx ) if( NULL == cipher_info || NULL == ctx )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
@ -199,12 +232,119 @@ int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_in
return( 0 ); return( 0 );
} }
int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, #if defined(MBEDTLS_USE_PSA_CRYPTO)
int key_bitlen, const mbedtls_operation_t operation ) int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx,
const mbedtls_cipher_info_t *cipher_info,
size_t taglen )
{ {
if( NULL == ctx || NULL == ctx->cipher_info ) psa_algorithm_t alg;
mbedtls_cipher_context_psa *cipher_psa;
if( NULL == cipher_info || NULL == ctx )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
/* Check that the underlying cipher mode and cipher type are
* supported by the underlying PSA Crypto implementation. */
alg = mbedtls_psa_translate_cipher_mode( cipher_info->mode, taglen );
if( alg == 0 )
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
if( mbedtls_psa_translate_cipher_type( cipher_info->type ) == 0 )
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
cipher_psa = mbedtls_calloc( 1, sizeof(mbedtls_cipher_context_psa ) );
if( cipher_psa == NULL )
return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
cipher_psa->alg = alg;
ctx->cipher_ctx = cipher_psa;
ctx->cipher_info = cipher_info;
ctx->psa_enabled = 1;
return( 0 );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx,
const unsigned char *key,
int key_bitlen,
const mbedtls_operation_t operation )
{
if( NULL == ctx || NULL == ctx->cipher_info ||
NULL == ctx->cipher_ctx )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
if( operation != MBEDTLS_DECRYPT &&
operation != MBEDTLS_ENCRYPT )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ctx->psa_enabled == 1 )
{
mbedtls_cipher_context_psa * const cipher_psa =
(mbedtls_cipher_context_psa *) ctx->cipher_ctx;
size_t const key_bytelen = ( (size_t) key_bitlen + 7 ) / 8;
psa_status_t status;
psa_key_type_t key_type;
psa_key_usage_t key_usage;
psa_key_policy_t key_policy;
/* PSA Crypto API only accepts byte-aligned keys. */
if( key_bitlen % 8 != 0 )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
/* Don't allow keys to be set multiple times. */
if( cipher_psa->slot_state != MBEDTLS_CIPHER_PSA_KEY_UNSET )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
/* Find a fresh key slot to use. */
status = mbedtls_psa_get_free_key_slot( &cipher_psa->slot );
if( status != PSA_SUCCESS )
return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
/* Indicate that we own the key slot and need to
* destroy it in mbedtls_cipher_free(). */
cipher_psa->slot_state = MBEDTLS_CIPHER_PSA_KEY_OWNED;
/* From that point on, the responsibility for destroying the
* key slot is on mbedtls_cipher_free(). This includes the case
* where the policy setup or key import below fail, as
* mbedtls_cipher_free() needs to be called in any case. */
/* Setup policy for the new key slot. */
psa_key_policy_init( &key_policy );
/* Mbed TLS' cipher layer doesn't enforce the mode of operation
* (encrypt vs. decrypt): it is possible to setup a key for encryption
* and use it for AEAD decryption. Until tests relying on this
* are changed, allow any usage in PSA. */
/* key_usage = mbedtls_psa_translate_cipher_operation( operation ); */
key_usage = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT;
psa_key_policy_set_usage( &key_policy, key_usage, cipher_psa->alg );
status = psa_set_key_policy( cipher_psa->slot, &key_policy );
if( status != PSA_SUCCESS )
return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
/* Populate new key slot. */
key_type = mbedtls_psa_translate_cipher_type(
ctx->cipher_info->type );
if( key_type == 0 )
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
status = psa_import_key( cipher_psa->slot,
key_type, key, key_bytelen );
if( status != PSA_SUCCESS )
return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
ctx->key_bitlen = key_bitlen;
ctx->operation = operation;
return( 0 );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 &&
(int) ctx->cipher_info->key_bitlen != key_bitlen ) (int) ctx->cipher_info->key_bitlen != key_bitlen )
{ {
@ -230,6 +370,7 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *k
return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
ctx->key_bitlen ); ctx->key_bitlen );
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
} }
@ -237,9 +378,23 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len ) const unsigned char *iv, size_t iv_len )
{ {
size_t actual_iv_size; size_t actual_iv_size;
if( NULL == ctx || NULL == ctx->cipher_info )
if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
else if( NULL == iv && iv_len != 0 )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ctx->psa_enabled == 1 )
{
/* While PSA Crypto has an API for multipart
* operations, we currently don't make it
* accessible through the cipher layer. */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( NULL == iv && iv_len == 0 )
ctx->iv_size = 0;
/* avoid buffer overflow in ctx->iv */ /* avoid buffer overflow in ctx->iv */
if( iv_len > MBEDTLS_MAX_IV_LENGTH ) if( iv_len > MBEDTLS_MAX_IV_LENGTH )
@ -268,8 +423,11 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
} }
#endif #endif
if ( actual_iv_size != 0 )
{
memcpy( ctx->iv, iv, actual_iv_size ); memcpy( ctx->iv, iv, actual_iv_size );
ctx->iv_size = actual_iv_size; ctx->iv_size = actual_iv_size;
}
return( 0 ); return( 0 );
} }
@ -279,6 +437,15 @@ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx )
if( NULL == ctx || NULL == ctx->cipher_info ) if( NULL == ctx || NULL == ctx->cipher_info )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ctx->psa_enabled == 1 )
{
/* We don't support resetting PSA-based
* cipher contexts, yet. */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
ctx->unprocessed_len = 0; ctx->unprocessed_len = 0;
return( 0 ); return( 0 );
@ -291,6 +458,16 @@ int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
if( NULL == ctx || NULL == ctx->cipher_info ) if( NULL == ctx || NULL == ctx->cipher_info )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ctx->psa_enabled == 1 )
{
/* While PSA Crypto has an API for multipart
* operations, we currently don't make it
* accessible through the cipher layer. */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_GCM_C) #if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{ {
@ -335,6 +512,16 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
} }
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ctx->psa_enabled == 1 )
{
/* While PSA Crypto has an API for multipart
* operations, we currently don't make it
* accessible through the cipher layer. */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
*olen = 0; *olen = 0;
block_size = mbedtls_cipher_get_block_size( ctx ); block_size = mbedtls_cipher_get_block_size( ctx );
@ -741,6 +928,16 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ctx->psa_enabled == 1 )
{
/* While PSA Crypto has an API for multipart
* operations, we currently don't make it
* accessible through the cipher layer. */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
*olen = 0; *olen = 0;
if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
@ -823,7 +1020,8 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
} }
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ) int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx,
mbedtls_cipher_padding_t mode )
{ {
if( NULL == ctx || if( NULL == ctx ||
MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) MBEDTLS_MODE_CBC != ctx->cipher_info->mode )
@ -831,6 +1029,19 @@ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_ciph
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
} }
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ctx->psa_enabled == 1 )
{
/* While PSA Crypto knows about CBC padding
* schemes, we currently don't make them
* accessible through the cipher layer. */
if( mode != MBEDTLS_PADDING_NONE )
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
return( 0 );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
switch( mode ) switch( mode )
{ {
#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) #if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
@ -880,9 +1091,22 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
if( MBEDTLS_ENCRYPT != ctx->operation ) if( MBEDTLS_ENCRYPT != ctx->operation )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ctx->psa_enabled == 1 )
{
/* While PSA Crypto has an API for multipart
* operations, we currently don't make it
* accessible through the cipher layer. */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
return( 0 );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_GCM_C) #if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len ); return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx,
tag, tag_len ) );
#endif #endif
#if defined(MBEDTLS_CHACHAPOLY_C) #if defined(MBEDTLS_CHACHAPOLY_C)
@ -892,8 +1116,8 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
if ( tag_len != 16U ) if ( tag_len != 16U )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
return mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, return( mbedtls_chachapoly_finish(
tag ); (mbedtls_chachapoly_context*) ctx->cipher_ctx, tag ) );
} }
#endif #endif
@ -912,13 +1136,24 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
} }
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ctx->psa_enabled == 1 )
{
/* While PSA Crypto has an API for multipart
* operations, we currently don't make it
* accessible through the cipher layer. */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_GCM_C) #if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{ {
if( tag_len > sizeof( check_tag ) ) if( tag_len > sizeof( check_tag ) )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
if( 0 != ( ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, if( 0 != ( ret = mbedtls_gcm_finish(
(mbedtls_gcm_context *) ctx->cipher_ctx,
check_tag, tag_len ) ) ) check_tag, tag_len ) ) )
{ {
return( ret ); return( ret );
@ -939,8 +1174,8 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
if ( tag_len != sizeof( check_tag ) ) if ( tag_len != sizeof( check_tag ) )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, ret = mbedtls_chachapoly_finish(
check_tag ); (mbedtls_chachapoly_context*) ctx->cipher_ctx, check_tag );
if ( ret != 0 ) if ( ret != 0 )
{ {
return( ret ); return( ret );
@ -969,16 +1204,76 @@ int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
int ret; int ret;
size_t finish_olen; size_t finish_olen;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ctx->psa_enabled == 1 )
{
/* As in the non-PSA case, we don't check that
* a key has been set. If not, the key slot will
* still be in its default state of 0, which is
* guaranteed to be invalid, hence the PSA-call
* below will gracefully fail. */
mbedtls_cipher_context_psa * const cipher_psa =
(mbedtls_cipher_context_psa *) ctx->cipher_ctx;
psa_status_t status;
psa_cipher_operation_t cipher_op;
size_t part_len;
if( ctx->operation == MBEDTLS_DECRYPT )
{
status = psa_cipher_decrypt_setup( &cipher_op,
cipher_psa->slot,
cipher_psa->alg );
}
else if( ctx->operation == MBEDTLS_ENCRYPT )
{
status = psa_cipher_encrypt_setup( &cipher_op,
cipher_psa->slot,
cipher_psa->alg );
}
else
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
/* In the following, we can immediately return on an error,
* because the PSA Crypto API guarantees that cipher operations
* are terminated by unsuccessful calls to psa_cipher_update(),
* and by any call to psa_cipher_finish(). */
if( status != PSA_SUCCESS )
return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
status = psa_cipher_set_iv( &cipher_op, iv, iv_len );
if( status != PSA_SUCCESS )
return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
status = psa_cipher_update( &cipher_op,
input, ilen,
output, ilen, olen );
if( status != PSA_SUCCESS )
return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
status = psa_cipher_finish( &cipher_op,
output + *olen, ilen - *olen,
&part_len );
if( status != PSA_SUCCESS )
return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
*olen += part_len;
return( 0 );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 )
return( ret ); return( ret );
if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 )
return( ret ); return( ret );
if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 ) if( ( ret = mbedtls_cipher_update( ctx, input, ilen,
output, olen ) ) != 0 )
return( ret ); return( ret );
if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 ) if( ( ret = mbedtls_cipher_finish( ctx, output + *olen,
&finish_olen ) ) != 0 )
return( ret ); return( ret );
*olen += finish_olen; *olen += finish_olen;
@ -997,13 +1292,45 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx,
unsigned char *output, size_t *olen, unsigned char *output, size_t *olen,
unsigned char *tag, size_t tag_len ) unsigned char *tag, size_t tag_len )
{ {
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ctx->psa_enabled == 1 )
{
/* As in the non-PSA case, we don't check that
* a key has been set. If not, the key slot will
* still be in its default state of 0, which is
* guaranteed to be invalid, hence the PSA-call
* below will gracefully fail. */
mbedtls_cipher_context_psa * const cipher_psa =
(mbedtls_cipher_context_psa *) ctx->cipher_ctx;
psa_status_t status;
/* PSA Crypto API always writes the authentication tag
* at the end of the encrypted message. */
if( tag != output + ilen )
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
status = psa_aead_encrypt( cipher_psa->slot,
cipher_psa->alg,
iv, iv_len,
ad, ad_len,
input, ilen,
output, ilen + tag_len, olen );
if( status != PSA_SUCCESS )
return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
*olen -= tag_len;
return( 0 );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_GCM_C) #if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{ {
*olen = ilen; *olen = ilen;
return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen, return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT,
iv, iv_len, ad, ad_len, input, output, ilen, iv, iv_len, ad, ad_len,
tag_len, tag ) ); input, output, tag_len, tag ) );
} }
#endif /* MBEDTLS_GCM_C */ #endif /* MBEDTLS_GCM_C */
#if defined(MBEDTLS_CCM_C) #if defined(MBEDTLS_CCM_C)
@ -1044,6 +1371,39 @@ int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
unsigned char *output, size_t *olen, unsigned char *output, size_t *olen,
const unsigned char *tag, size_t tag_len ) const unsigned char *tag, size_t tag_len )
{ {
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ctx->psa_enabled == 1 )
{
/* As in the non-PSA case, we don't check that
* a key has been set. If not, the key slot will
* still be in its default state of 0, which is
* guaranteed to be invalid, hence the PSA-call
* below will gracefully fail. */
mbedtls_cipher_context_psa * const cipher_psa =
(mbedtls_cipher_context_psa *) ctx->cipher_ctx;
psa_status_t status;
/* PSA Crypto API always writes the authentication tag
* at the end of the encrypted message. */
if( tag != input + ilen )
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
status = psa_aead_decrypt( cipher_psa->slot,
cipher_psa->alg,
iv, iv_len,
ad, ad_len,
input, ilen + tag_len,
output, ilen, olen );
if( status == PSA_ERROR_INVALID_SIGNATURE )
return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
else if( status != PSA_SUCCESS )
return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
return( 0 );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_GCM_C) #if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{ {

View File

@ -258,7 +258,7 @@ static const mbedtls_cipher_info_t aes_128_ecb_info = {
MBEDTLS_MODE_ECB, MBEDTLS_MODE_ECB,
128, 128,
"AES-128-ECB", "AES-128-ECB",
16, 0,
0, 0,
16, 16,
&aes_info &aes_info
@ -269,7 +269,7 @@ static const mbedtls_cipher_info_t aes_192_ecb_info = {
MBEDTLS_MODE_ECB, MBEDTLS_MODE_ECB,
192, 192,
"AES-192-ECB", "AES-192-ECB",
16, 0,
0, 0,
16, 16,
&aes_info &aes_info
@ -280,7 +280,7 @@ static const mbedtls_cipher_info_t aes_256_ecb_info = {
MBEDTLS_MODE_ECB, MBEDTLS_MODE_ECB,
256, 256,
"AES-256-ECB", "AES-256-ECB",
16, 0,
0, 0,
16, 16,
&aes_info &aes_info
@ -2266,7 +2266,8 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] =
{ MBEDTLS_CIPHER_NONE, NULL } { MBEDTLS_CIPHER_NONE, NULL }
}; };
#define NUM_CIPHERS sizeof mbedtls_cipher_definitions / sizeof mbedtls_cipher_definitions[0] #define NUM_CIPHERS ( sizeof(mbedtls_cipher_definitions) / \
sizeof(mbedtls_cipher_definitions[0]) )
int mbedtls_cipher_supported[NUM_CIPHERS]; int mbedtls_cipher_supported[NUM_CIPHERS];
#endif /* MBEDTLS_CIPHER_C */ #endif /* MBEDTLS_CIPHER_C */

View File

@ -66,6 +66,18 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
* Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
* NIST tests to succeed (which require known length fixed entropy) * NIST tests to succeed (which require known length fixed entropy)
*/ */
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
* mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
* custom, len, entropy_len)
* implements
* CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
* security_strength) -> initial_working_state
* with inputs
* custom[:len] = nonce || personalization_string
* where entropy_input comes from f_entropy for entropy_len bytes
* and with outputs
* ctx = initial_working_state
*/
int mbedtls_ctr_drbg_seed_entropy_len( int mbedtls_ctr_drbg_seed_entropy_len(
mbedtls_ctr_drbg_context *ctx, mbedtls_ctr_drbg_context *ctx,
int (*f_entropy)(void *, unsigned char *, size_t), int (*f_entropy)(void *, unsigned char *, size_t),
@ -256,6 +268,14 @@ exit:
return( ret ); return( ret );
} }
/* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
* ctr_drbg_update_internal(ctx, provided_data)
* implements
* CTR_DRBG_Update(provided_data, Key, V)
* with inputs and outputs
* ctx->aes_ctx = Key
* ctx->counter = V
*/
static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
{ {
@ -301,6 +321,18 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
return( 0 ); return( 0 );
} }
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
* mbedtls_ctr_drbg_update(ctx, additional, add_len)
* implements
* CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
* security_strength) -> initial_working_state
* with inputs
* ctx->counter = all-bits-0
* ctx->aes_ctx = context from all-bits-0 key
* additional[:add_len] = entropy_input || nonce || personalization_string
* and with outputs
* ctx = initial_working_state
*/
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional, size_t add_len ) const unsigned char *additional, size_t add_len )
{ {
@ -318,6 +350,18 @@ void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
} }
} }
/* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
* mbedtls_ctr_drbg_reseed(ctx, additional, len)
* implements
* CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
* -> new_working_state
* with inputs
* ctx contains working_state
* additional[:len] = additional_input
* and entropy_input comes from calling ctx->f_entropy
* and with output
* ctx contains new_working_state
*/
int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional, size_t len ) const unsigned char *additional, size_t len )
{ {
@ -371,6 +415,25 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
return( 0 ); return( 0 );
} }
/* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
* mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
* implements
* CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
* -> working_state_after_reseed
* if required, then
* CTR_DRBG_Generate(working_state_after_reseed,
* requested_number_of_bits, additional_input)
* -> status, returned_bits, new_working_state
* with inputs
* ctx contains working_state
* requested_number_of_bits = 8 * output_len
* additional[:add_len] = additional_input
* and entropy_input comes from calling ctx->f_entropy
* and with outputs
* status = SUCCESS (this function does the reseed internally)
* returned_bits = output[:output_len]
* ctx contains new_working_state
*/
int mbedtls_ctr_drbg_random_with_add( void *p_rng, int mbedtls_ctr_drbg_random_with_add( void *p_rng,
unsigned char *output, size_t output_len, unsigned char *output, size_t output_len,
const unsigned char *additional, size_t add_len ) const unsigned char *additional, size_t add_len )

View File

@ -40,36 +40,62 @@
#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
/* /*
* Generate public key: simple wrapper around mbedtls_ecp_gen_keypair * Generate public key (restartable version)
*
* Note: this internal function relies on its caller preserving the value of
* the output parameter 'd' across continuation calls. This would not be
* acceptable for a public function but is OK here as we control call sites.
*/
static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
mbedtls_mpi *d, mbedtls_ecp_point *Q,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
mbedtls_ecp_restart_ctx *rs_ctx )
{
int ret;
/* If multiplication is in progress, we already generated a privkey */
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx == NULL || rs_ctx->rsm == NULL )
#endif
MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,
f_rng, p_rng, rs_ctx ) );
cleanup:
return( ret );
}
/*
* Generate public key
*/ */
int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng ) void *p_rng )
{ {
return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng ); return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) );
} }
#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */ #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
/* /*
* Compute shared secret (SEC1 3.3.1) * Compute shared secret (SEC1 3.3.1)
*/ */
int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp,
mbedtls_mpi *z,
const mbedtls_ecp_point *Q, const mbedtls_mpi *d, const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng ) void *p_rng,
mbedtls_ecp_restart_ctx *rs_ctx )
{ {
int ret; int ret;
mbedtls_ecp_point P; mbedtls_ecp_point P;
mbedtls_ecp_point_init( &P ); mbedtls_ecp_point_init( &P );
/* MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q,
* Make sure Q is a valid pubkey before using it f_rng, p_rng, rs_ctx ) );
*/
MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) );
if( mbedtls_ecp_is_zero( &P ) ) if( mbedtls_ecp_is_zero( &P ) )
{ {
@ -84,14 +110,39 @@ cleanup:
return( ret ); return( ret );
} }
#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
/*
* Compute shared secret (SEC1 3.3.1)
*/
int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
return( ecdh_compute_shared_restartable( grp, z, Q, d,
f_rng, p_rng, NULL ) );
}
#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
/* /*
* Initialize context * Initialize context
*/ */
void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
{ {
memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); mbedtls_ecp_group_init( &ctx->grp );
mbedtls_mpi_init( &ctx->d );
mbedtls_ecp_point_init( &ctx->Q );
mbedtls_ecp_point_init( &ctx->Qp );
mbedtls_mpi_init( &ctx->z );
ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
mbedtls_ecp_point_init( &ctx->Vi );
mbedtls_ecp_point_init( &ctx->Vf );
mbedtls_mpi_init( &ctx->_d );
#if defined(MBEDTLS_ECP_RESTARTABLE)
ctx->restart_enabled = 0;
mbedtls_ecp_restart_init( &ctx->rs );
#endif
} }
/* /*
@ -103,15 +154,29 @@ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
return; return;
mbedtls_ecp_group_free( &ctx->grp ); mbedtls_ecp_group_free( &ctx->grp );
mbedtls_mpi_free( &ctx->d );
mbedtls_ecp_point_free( &ctx->Q ); mbedtls_ecp_point_free( &ctx->Q );
mbedtls_ecp_point_free( &ctx->Qp ); mbedtls_ecp_point_free( &ctx->Qp );
mbedtls_mpi_free( &ctx->z );
mbedtls_ecp_point_free( &ctx->Vi ); mbedtls_ecp_point_free( &ctx->Vi );
mbedtls_ecp_point_free( &ctx->Vf ); mbedtls_ecp_point_free( &ctx->Vf );
mbedtls_mpi_free( &ctx->d );
mbedtls_mpi_free( &ctx->z );
mbedtls_mpi_free( &ctx->_d ); mbedtls_mpi_free( &ctx->_d );
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_free( &ctx->rs );
#endif
} }
#if defined(MBEDTLS_ECP_RESTARTABLE)
/*
* Enable restartable operations for context
*/
void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx )
{
ctx->restart_enabled = 1;
}
#endif
/* /*
* Setup and write the ServerKeyExhange parameters (RFC 4492) * Setup and write the ServerKeyExhange parameters (RFC 4492)
* struct { * struct {
@ -126,13 +191,28 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
{ {
int ret; int ret;
size_t grp_len, pt_len; size_t grp_len, pt_len;
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
#endif
if( ctx == NULL || ctx->grp.pbits == 0 ) if( ctx == NULL || ctx->grp.pbits == 0 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) #if defined(MBEDTLS_ECP_RESTARTABLE)
!= 0 ) if( ctx->restart_enabled )
rs_ctx = &ctx->rs;
#endif
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
f_rng, p_rng, rs_ctx ) ) != 0 )
return( ret ); return( ret );
#else
if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
f_rng, p_rng ) ) != 0 )
return( ret );
#endif /* MBEDTLS_ECP_RESTARTABLE */
if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) ) if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) )
!= 0 ) != 0 )
@ -206,13 +286,27 @@ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
void *p_rng ) void *p_rng )
{ {
int ret; int ret;
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
#endif
if( ctx == NULL || ctx->grp.pbits == 0 ) if( ctx == NULL || ctx->grp.pbits == 0 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) #if defined(MBEDTLS_ECP_RESTARTABLE)
!= 0 ) if( ctx->restart_enabled )
rs_ctx = &ctx->rs;
#endif
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
f_rng, p_rng, rs_ctx ) ) != 0 )
return( ret ); return( ret );
#else
if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
f_rng, p_rng ) ) != 0 )
return( ret );
#endif /* MBEDTLS_ECP_RESTARTABLE */
return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
olen, buf, blen ); olen, buf, blen );
@ -248,15 +342,31 @@ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
void *p_rng ) void *p_rng )
{ {
int ret; int ret;
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
#endif
if( ctx == NULL ) if( ctx == NULL || ctx->grp.pbits == 0 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, #if defined(MBEDTLS_ECP_RESTARTABLE)
f_rng, p_rng ) ) != 0 ) if( ctx->restart_enabled )
rs_ctx = &ctx->rs;
#endif
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( ( ret = ecdh_compute_shared_restartable( &ctx->grp,
&ctx->z, &ctx->Qp, &ctx->d, f_rng, p_rng, rs_ctx ) ) != 0 )
{ {
return( ret ); return( ret );
} }
#else
if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp,
&ctx->d, f_rng, p_rng ) ) != 0 )
{
return( ret );
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
if( mbedtls_mpi_size( &ctx->z ) > blen ) if( mbedtls_mpi_size( &ctx->z ) > blen )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );

View File

@ -42,6 +42,178 @@
#include "mbedtls/hmac_drbg.h" #include "mbedtls/hmac_drbg.h"
#endif #endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#if defined(MBEDTLS_ECP_RESTARTABLE)
/*
* Sub-context for ecdsa_verify()
*/
struct mbedtls_ecdsa_restart_ver
{
mbedtls_mpi u1, u2; /* intermediate values */
enum { /* what to do next? */
ecdsa_ver_init = 0, /* getting started */
ecdsa_ver_muladd, /* muladd step */
} state;
};
/*
* Init verify restart sub-context
*/
static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx )
{
mbedtls_mpi_init( &ctx->u1 );
mbedtls_mpi_init( &ctx->u2 );
ctx->state = ecdsa_ver_init;
}
/*
* Free the components of a verify restart sub-context
*/
static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx )
{
if( ctx == NULL )
return;
mbedtls_mpi_free( &ctx->u1 );
mbedtls_mpi_free( &ctx->u2 );
ecdsa_restart_ver_init( ctx );
}
/*
* Sub-context for ecdsa_sign()
*/
struct mbedtls_ecdsa_restart_sig
{
int sign_tries;
int key_tries;
mbedtls_mpi k; /* per-signature random */
mbedtls_mpi r; /* r value */
enum { /* what to do next? */
ecdsa_sig_init = 0, /* getting started */
ecdsa_sig_mul, /* doing ecp_mul() */
ecdsa_sig_modn, /* mod N computations */
} state;
};
/*
* Init verify sign sub-context
*/
static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx )
{
ctx->sign_tries = 0;
ctx->key_tries = 0;
mbedtls_mpi_init( &ctx->k );
mbedtls_mpi_init( &ctx->r );
ctx->state = ecdsa_sig_init;
}
/*
* Free the components of a sign restart sub-context
*/
static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx )
{
if( ctx == NULL )
return;
mbedtls_mpi_free( &ctx->k );
mbedtls_mpi_free( &ctx->r );
}
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
/*
* Sub-context for ecdsa_sign_det()
*/
struct mbedtls_ecdsa_restart_det
{
mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */
enum { /* what to do next? */
ecdsa_det_init = 0, /* getting started */
ecdsa_det_sign, /* make signature */
} state;
};
/*
* Init verify sign_det sub-context
*/
static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx )
{
mbedtls_hmac_drbg_init( &ctx->rng_ctx );
ctx->state = ecdsa_det_init;
}
/*
* Free the components of a sign_det restart sub-context
*/
static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx )
{
if( ctx == NULL )
return;
mbedtls_hmac_drbg_free( &ctx->rng_ctx );
ecdsa_restart_det_init( ctx );
}
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
#define ECDSA_RS_ECP &rs_ctx->ecp
/* Utility macro for checking and updating ops budget */
#define ECDSA_BUDGET( ops ) \
MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, &rs_ctx->ecp, ops ) );
/* Call this when entering a function that needs its own sub-context */
#define ECDSA_RS_ENTER( SUB ) do { \
/* reset ops count for this call if top-level */ \
if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 ) \
rs_ctx->ecp.ops_done = 0; \
\
/* set up our own sub-context if needed */ \
if( mbedtls_ecp_restart_is_enabled() && \
rs_ctx != NULL && rs_ctx->SUB == NULL ) \
{ \
rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \
if( rs_ctx->SUB == NULL ) \
return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \
\
ecdsa_restart_## SUB ##_init( rs_ctx->SUB ); \
} \
} while( 0 )
/* Call this when leaving a function that needs its own sub-context */
#define ECDSA_RS_LEAVE( SUB ) do { \
/* clear our sub-context when not in progress (done or error) */ \
if( rs_ctx != NULL && rs_ctx->SUB != NULL && \
ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \
{ \
ecdsa_restart_## SUB ##_free( rs_ctx->SUB ); \
mbedtls_free( rs_ctx->SUB ); \
rs_ctx->SUB = NULL; \
} \
\
if( rs_ctx != NULL ) \
rs_ctx->ecp.depth--; \
} while( 0 )
#else /* MBEDTLS_ECP_RESTARTABLE */
#define ECDSA_RS_ECP NULL
#define ECDSA_BUDGET( ops ) /* no-op; for compatibility */
#define ECDSA_RS_ENTER( SUB ) (void) rs_ctx
#define ECDSA_RS_LEAVE( SUB ) (void) rs_ctx
#endif /* MBEDTLS_ECP_RESTARTABLE */
/* /*
* Derive a suitable integer for group grp from a buffer of length len * Derive a suitable integer for group grp from a buffer of length len
* SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
@ -70,13 +242,17 @@ cleanup:
* Compute ECDSA signature of a hashed message (SEC1 4.1.3) * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
* Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
*/ */
int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, static int ecdsa_sign_restartable( mbedtls_ecp_group *grp,
mbedtls_mpi *r, mbedtls_mpi *s,
const mbedtls_mpi *d, const unsigned char *buf, size_t blen, const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
mbedtls_ecdsa_restart_ctx *rs_ctx )
{ {
int ret, key_tries, sign_tries, blind_tries; int ret, key_tries, sign_tries;
int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries;
mbedtls_ecp_point R; mbedtls_ecp_point R;
mbedtls_mpi k, e, t; mbedtls_mpi k, e, t;
mbedtls_mpi *pk = &k, *pr = r;
/* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
if( grp->N.p == NULL ) if( grp->N.p == NULL )
@ -89,26 +265,72 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
mbedtls_ecp_point_init( &R ); mbedtls_ecp_point_init( &R );
mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t );
sign_tries = 0; ECDSA_RS_ENTER( sig );
do
{
/*
* Steps 1-3: generate a suitable ephemeral keypair
* and set r = xR mod n
*/
key_tries = 0;
do
{
MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) );
if( key_tries++ > 10 ) #if defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && rs_ctx->sig != NULL )
{
/* redirect to our context */
p_sign_tries = &rs_ctx->sig->sign_tries;
p_key_tries = &rs_ctx->sig->key_tries;
pk = &rs_ctx->sig->k;
pr = &rs_ctx->sig->r;
/* jump to current step */
if( rs_ctx->sig->state == ecdsa_sig_mul )
goto mul;
if( rs_ctx->sig->state == ecdsa_sig_modn )
goto modn;
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
*p_sign_tries = 0;
do
{
if( *p_sign_tries++ > 10 )
{ {
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
goto cleanup; goto cleanup;
} }
/*
* Steps 1-3: generate a suitable ephemeral keypair
* and set r = xR mod n
*/
*p_key_tries = 0;
do
{
if( *p_key_tries++ > 10 )
{
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
goto cleanup;
} }
while( mbedtls_mpi_cmp_int( r, 0 ) == 0 );
MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) );
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && rs_ctx->sig != NULL )
rs_ctx->sig->state = ecdsa_sig_mul;
mul:
#endif
MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G,
f_rng, p_rng, ECDSA_RS_ECP ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) );
}
while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 );
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && rs_ctx->sig != NULL )
rs_ctx->sig->state = ecdsa_sig_modn;
modn:
#endif
/*
* Accounting for everything up to the end of the loop
* (step 6, but checking now avoids saving e and t)
*/
ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 );
/* /*
* Step 5: derive MPI from hashed message * Step 5: derive MPI from hashed message
@ -119,57 +341,60 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
* Generate a random value to blind inv_mod in next step, * Generate a random value to blind inv_mod in next step,
* avoiding a potential timing leak. * avoiding a potential timing leak.
*/ */
blind_tries = 0; MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng, p_rng ) );
do
{
size_t n_size = ( grp->nbits + 7 ) / 8;
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) );
/* See mbedtls_ecp_gen_keypair() */
if( ++blind_tries > 30 )
return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
}
while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 ||
mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 );
/* /*
* Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
*/ */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) );
if( sign_tries++ > 10 )
{
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
goto cleanup;
}
} }
while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); while( mbedtls_mpi_cmp_int( s, 0 ) == 0 );
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && rs_ctx->sig != NULL )
mbedtls_mpi_copy( r, pr );
#endif
cleanup: cleanup:
mbedtls_ecp_point_free( &R ); mbedtls_ecp_point_free( &R );
mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t );
ECDSA_RS_LEAVE( sig );
return( ret ); return( ret );
} }
#endif /* MBEDTLS_ECDSA_SIGN_ALT */
/*
* Compute ECDSA signature of a hashed message
*/
int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
return( ecdsa_sign_restartable( grp, r, s, d, buf, blen,
f_rng, p_rng, NULL ) );
}
#endif /* !MBEDTLS_ECDSA_SIGN_ALT */
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
/* /*
* Deterministic signature wrapper * Deterministic signature wrapper
*/ */
int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp,
mbedtls_mpi *r, mbedtls_mpi *s,
const mbedtls_mpi *d, const unsigned char *buf, size_t blen, const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
mbedtls_md_type_t md_alg ) mbedtls_md_type_t md_alg,
mbedtls_ecdsa_restart_ctx *rs_ctx )
{ {
int ret; int ret;
mbedtls_hmac_drbg_context rng_ctx; mbedtls_hmac_drbg_context rng_ctx;
mbedtls_hmac_drbg_context *p_rng = &rng_ctx;
unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
size_t grp_len = ( grp->nbits + 7 ) / 8; size_t grp_len = ( grp->nbits + 7 ) / 8;
const mbedtls_md_info_t *md_info; const mbedtls_md_info_t *md_info;
@ -181,21 +406,58 @@ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi
mbedtls_mpi_init( &h ); mbedtls_mpi_init( &h );
mbedtls_hmac_drbg_init( &rng_ctx ); mbedtls_hmac_drbg_init( &rng_ctx );
ECDSA_RS_ENTER( det );
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && rs_ctx->det != NULL )
{
/* redirect to our context */
p_rng = &rs_ctx->det->rng_ctx;
/* jump to current step */
if( rs_ctx->det->state == ecdsa_det_sign )
goto sign;
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
/* Use private key and message hash (reduced) to initialize HMAC_DRBG */ /* Use private key and message hash (reduced) to initialize HMAC_DRBG */
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) );
MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) );
mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len ); mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len );
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && rs_ctx->det != NULL )
rs_ctx->det->state = ecdsa_det_sign;
sign:
#endif
#if defined(MBEDTLS_ECDSA_SIGN_ALT)
ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen,
mbedtls_hmac_drbg_random, &rng_ctx ); mbedtls_hmac_drbg_random, p_rng );
#else
ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen,
mbedtls_hmac_drbg_random, p_rng, rs_ctx );
#endif /* MBEDTLS_ECDSA_SIGN_ALT */
cleanup: cleanup:
mbedtls_hmac_drbg_free( &rng_ctx ); mbedtls_hmac_drbg_free( &rng_ctx );
mbedtls_mpi_free( &h ); mbedtls_mpi_free( &h );
ECDSA_RS_LEAVE( det );
return( ret ); return( ret );
} }
/*
* Deterministic signature wrapper
*/
int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
mbedtls_md_type_t md_alg )
{
return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, NULL ) );
}
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
#if !defined(MBEDTLS_ECDSA_VERIFY_ALT) #if !defined(MBEDTLS_ECDSA_VERIFY_ALT)
@ -203,21 +465,40 @@ cleanup:
* Verify ECDSA signature of hashed message (SEC1 4.1.4) * Verify ECDSA signature of hashed message (SEC1 4.1.4)
* Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
*/ */
int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, static int ecdsa_verify_restartable( mbedtls_ecp_group *grp,
const unsigned char *buf, size_t blen, const unsigned char *buf, size_t blen,
const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s) const mbedtls_ecp_point *Q,
const mbedtls_mpi *r, const mbedtls_mpi *s,
mbedtls_ecdsa_restart_ctx *rs_ctx )
{ {
int ret; int ret;
mbedtls_mpi e, s_inv, u1, u2; mbedtls_mpi e, s_inv, u1, u2;
mbedtls_ecp_point R; mbedtls_ecp_point R;
mbedtls_mpi *pu1 = &u1, *pu2 = &u2;
mbedtls_ecp_point_init( &R ); mbedtls_ecp_point_init( &R );
mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv );
mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
/* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
if( grp->N.p == NULL ) if( grp->N.p == NULL )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
ECDSA_RS_ENTER( ver );
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && rs_ctx->ver != NULL )
{
/* redirect to our context */
pu1 = &rs_ctx->ver->u1;
pu2 = &rs_ctx->ver->u2;
/* jump to current step */
if( rs_ctx->ver->state == ecdsa_ver_muladd )
goto muladd;
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
/* /*
* Step 1: make sure r and s are in range 1..n-1 * Step 1: make sure r and s are in range 1..n-1
*/ */
@ -228,11 +509,6 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
goto cleanup; goto cleanup;
} }
/*
* Additional precaution: make sure Q is valid
*/
MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
/* /*
* Step 3: derive MPI from hashed message * Step 3: derive MPI from hashed message
*/ */
@ -241,21 +517,27 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
/* /*
* Step 4: u1 = e / s mod n, u2 = r / s mod n * Step 4: u1 = e / s mod n, u2 = r / s mod n
*/ */
ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 );
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) );
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && rs_ctx->ver != NULL )
rs_ctx->ver->state = ecdsa_ver_muladd;
muladd:
#endif
/* /*
* Step 5: R = u1 G + u2 Q * Step 5: R = u1 G + u2 Q
*
* Since we're not using any secret data, no need to pass a RNG to
* mbedtls_ecp_mul() for countermesures.
*/ */
MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) ); MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp,
&R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) );
if( mbedtls_ecp_is_zero( &R ) ) if( mbedtls_ecp_is_zero( &R ) )
{ {
@ -280,11 +562,24 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
cleanup: cleanup:
mbedtls_ecp_point_free( &R ); mbedtls_ecp_point_free( &R );
mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv );
mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 );
ECDSA_RS_LEAVE( ver );
return( ret ); return( ret );
} }
#endif /* MBEDTLS_ECDSA_VERIFY_ALT */
/*
* Verify ECDSA signature of hashed message
*/
int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
const unsigned char *buf, size_t blen,
const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s)
{
return( ecdsa_verify_restartable( grp, buf, blen, Q, r, s, NULL ) );
}
#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */
/* /*
* Convert a signature (given by context) to ASN.1 * Convert a signature (given by context) to ASN.1
@ -313,11 +608,13 @@ static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
/* /*
* Compute and write signature * Compute and write signature
*/ */
int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hlen, const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t *slen, unsigned char *sig, size_t *slen,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng ) void *p_rng,
mbedtls_ecdsa_restart_ctx *rs_ctx )
{ {
int ret; int ret;
mbedtls_mpi r, s; mbedtls_mpi r, s;
@ -329,14 +626,19 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t
(void) f_rng; (void) f_rng;
(void) p_rng; (void) p_rng;
MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d, MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d,
hash, hlen, md_alg ) ); hash, hlen, md_alg, rs_ctx ) );
#else #else
(void) md_alg; (void) md_alg;
#if defined(MBEDTLS_ECDSA_SIGN_ALT)
MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
hash, hlen, f_rng, p_rng ) ); hash, hlen, f_rng, p_rng ) );
#endif #else
MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d,
hash, hlen, f_rng, p_rng, rs_ctx ) );
#endif /* MBEDTLS_ECDSA_SIGN_ALT */
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) );
@ -347,7 +649,20 @@ cleanup:
return( ret ); return( ret );
} }
#if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \ /*
* Compute and write signature
*/
int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t *slen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
return( mbedtls_ecdsa_write_signature_restartable(
ctx, md_alg, hash, hlen, sig, slen, f_rng, p_rng, NULL ) );
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED) && \
defined(MBEDTLS_ECDSA_DETERMINISTIC) defined(MBEDTLS_ECDSA_DETERMINISTIC)
int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx,
const unsigned char *hash, size_t hlen, const unsigned char *hash, size_t hlen,
@ -365,6 +680,18 @@ int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx,
int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
const unsigned char *hash, size_t hlen, const unsigned char *hash, size_t hlen,
const unsigned char *sig, size_t slen ) const unsigned char *sig, size_t slen )
{
return( mbedtls_ecdsa_read_signature_restartable(
ctx, hash, hlen, sig, slen, NULL ) );
}
/*
* Restartable read and check signature
*/
int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx,
const unsigned char *hash, size_t hlen,
const unsigned char *sig, size_t slen,
mbedtls_ecdsa_restart_ctx *rs_ctx )
{ {
int ret; int ret;
unsigned char *p = (unsigned char *) sig; unsigned char *p = (unsigned char *) sig;
@ -395,10 +722,15 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
goto cleanup; goto cleanup;
} }
#if defined(MBEDTLS_ECDSA_VERIFY_ALT)
if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen,
&ctx->Q, &r, &s ) ) != 0 ) &ctx->Q, &r, &s ) ) != 0 )
goto cleanup; goto cleanup;
#else
if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen,
&ctx->Q, &r, &s, rs_ctx ) ) != 0 )
goto cleanup;
#endif /* MBEDTLS_ECDSA_VERIFY_ALT */
/* At this point we know that the buffer starts with a valid signature. /* At this point we know that the buffer starts with a valid signature.
* Return 0 if the buffer just contains the signature, and a specific * Return 0 if the buffer just contains the signature, and a specific
@ -423,7 +755,7 @@ int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
return( mbedtls_ecp_group_load( &ctx->grp, gid ) || return( mbedtls_ecp_group_load( &ctx->grp, gid ) ||
mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ); mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) );
} }
#endif /* MBEDTLS_ECDSA_GENKEY_ALT */ #endif /* !MBEDTLS_ECDSA_GENKEY_ALT */
/* /*
* Set context from an mbedtls_ecp_keypair * Set context from an mbedtls_ecp_keypair
@ -458,4 +790,42 @@ void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx )
mbedtls_ecp_keypair_free( ctx ); mbedtls_ecp_keypair_free( ctx );
} }
#if defined(MBEDTLS_ECP_RESTARTABLE)
/*
* Initialize a restart context
*/
void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx )
{
mbedtls_ecp_restart_init( &ctx->ecp );
ctx->ver = NULL;
ctx->sig = NULL;
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
ctx->det = NULL;
#endif
}
/*
* Free the components of a restart context
*/
void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx )
{
mbedtls_ecp_restart_free( &ctx->ecp );
ecdsa_restart_ver_free( ctx->ver );
mbedtls_free( ctx->ver );
ctx->ver = NULL;
ecdsa_restart_sig_free( ctx->sig );
mbedtls_free( ctx->sig );
ctx->sig = NULL;
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
ecdsa_restart_det_free( ctx->det );
mbedtls_free( ctx->det );
ctx->det = NULL;
#endif
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
#endif /* MBEDTLS_ECDSA_C */ #endif /* MBEDTLS_ECDSA_C */

File diff suppressed because it is too large Load Diff

View File

@ -165,6 +165,10 @@
#include "mbedtls/pkcs5.h" #include "mbedtls/pkcs5.h"
#endif #endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#endif
#if defined(MBEDTLS_POLY1305_C) #if defined(MBEDTLS_POLY1305_C)
#include "mbedtls/poly1305.h" #include "mbedtls/poly1305.h"
#endif #endif
@ -289,6 +293,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "ECP - The buffer contains a valid signature followed by more data" ); mbedtls_snprintf( buf, buflen, "ECP - The buffer contains a valid signature followed by more data" );
if( use_ret == -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED) ) if( use_ret == -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "ECP - The ECP hardware accelerator failed" ); mbedtls_snprintf( buf, buflen, "ECP - The ECP hardware accelerator failed" );
if( use_ret == -(MBEDTLS_ERR_ECP_IN_PROGRESS) )
mbedtls_snprintf( buf, buflen, "ECP - Operation in progress, call again with the same parameters to continue" );
#endif /* MBEDTLS_ECP_C */ #endif /* MBEDTLS_ECP_C */
#if defined(MBEDTLS_MD_C) #if defined(MBEDTLS_MD_C)
@ -517,6 +523,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "SSL - The asynchronous operation is not completed yet" ); mbedtls_snprintf( buf, buflen, "SSL - The asynchronous operation is not completed yet" );
if( use_ret == -(MBEDTLS_ERR_SSL_EARLY_MESSAGE) ) if( use_ret == -(MBEDTLS_ERR_SSL_EARLY_MESSAGE) )
mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that a message arrived early" ); mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that a message arrived early" );
if( use_ret == -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) )
mbedtls_snprintf( buf, buflen, "SSL - A cryptographic operation is in progress. Try again later" );
#endif /* MBEDTLS_SSL_TLS_C */ #endif /* MBEDTLS_SSL_TLS_C */
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
@ -823,6 +831,13 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" ); mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" );
#endif /* MBEDTLS_PADLOCK_C */ #endif /* MBEDTLS_PADLOCK_C */
#if defined(MBEDTLS_PLATFORM_C)
if( use_ret == -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "PLATFORM - Hardware accelerator failed" );
if( use_ret == -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED) )
mbedtls_snprintf( buf, buflen, "PLATFORM - The requested feature is not supported by the platform" );
#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_POLY1305_C) #if defined(MBEDTLS_POLY1305_C)
if( use_ret == -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) ) if( use_ret == -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) )
mbedtls_snprintf( buf, buflen, "POLY1305 - Invalid input parameter(s)" ); mbedtls_snprintf( buf, buflen, "POLY1305 - Invalid input parameter(s)" );

View File

@ -48,9 +48,8 @@
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
#include "mbedtls/aes.h" #include "mbedtls/aes.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#else #if !defined(MBEDTLS_PLATFORM_C)
#include <stdio.h> #include <stdio.h>
#define mbedtls_printf printf #define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_PLATFORM_C */
@ -764,7 +763,7 @@ int mbedtls_gcm_self_test( int verbose )
* there is an alternative underlying implementation i.e. when * there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined. * MBEDTLS_AES_ALT is defined.
*/ */
if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && key_len == 192 ) if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192 )
{ {
mbedtls_printf( "skipped\n" ); mbedtls_printf( "skipped\n" );
break; break;

View File

@ -41,6 +41,10 @@
#include "mbedtls/ecdsa.h" #include "mbedtls/ecdsa.h"
#endif #endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "mbedtls/psa_util.h"
#endif
#include <limits.h> #include <limits.h>
#include <stdint.h> #include <stdint.h>
@ -69,6 +73,34 @@ void mbedtls_pk_free( mbedtls_pk_context *ctx )
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) ); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) );
} }
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/*
* Initialize a restart context
*/
void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx )
{
ctx->pk_info = NULL;
ctx->rs_ctx = NULL;
}
/*
* Free the components of a restart context
*/
void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx )
{
if( ctx == NULL || ctx->pk_info == NULL ||
ctx->pk_info->rs_free_func == NULL )
{
return;
}
ctx->pk_info->rs_free_func( ctx->rs_ctx );
ctx->pk_info = NULL;
ctx->rs_ctx = NULL;
}
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
/* /*
* Get pk_info structure from type * Get pk_info structure from type
*/ */
@ -111,6 +143,38 @@ int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info )
return( 0 ); return( 0 );
} }
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/*
* Initialise a PSA-wrapping context
*/
int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx, const psa_key_slot_t key )
{
const mbedtls_pk_info_t * const info = &mbedtls_pk_opaque_info;
psa_key_slot_t *pk_ctx;
psa_key_type_t type;
if( ctx == NULL || ctx->pk_info != NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if( PSA_SUCCESS != psa_get_key_information( key, &type, NULL ) )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
/* Current implementation of can_do() relies on this. */
if( ! PSA_KEY_TYPE_IS_ECC_KEYPAIR( type ) )
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ;
if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
return( MBEDTLS_ERR_PK_ALLOC_FAILED );
ctx->pk_info = info;
pk_ctx = (psa_key_slot_t *) ctx->pk_ctx;
*pk_ctx = key;
return( 0 );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
/* /*
* Initialize an RSA-alt context * Initialize an RSA-alt context
@ -171,6 +235,73 @@ static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len
return( 0 ); return( 0 );
} }
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/*
* Helper to set up a restart context if needed
*/
static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx,
const mbedtls_pk_info_t *info )
{
/* Don't do anything if already set up or invalid */
if( ctx == NULL || ctx->pk_info != NULL )
return( 0 );
/* Should never happen when we're called */
if( info->rs_alloc_func == NULL || info->rs_free_func == NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL )
return( MBEDTLS_ERR_PK_ALLOC_FAILED );
ctx->pk_info = info;
return( 0 );
}
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
/*
* Verify a signature (restartable)
*/
int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len,
mbedtls_pk_restart_ctx *rs_ctx )
{
if( ctx == NULL || ctx->pk_info == NULL ||
pk_hashlen_helper( md_alg, &hash_len ) != 0 )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/* optimization: use non-restartable version if restart disabled */
if( rs_ctx != NULL &&
mbedtls_ecp_restart_is_enabled() &&
ctx->pk_info->verify_rs_func != NULL )
{
int ret;
if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
return( ret );
ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx,
md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx );
if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
mbedtls_pk_restart_free( rs_ctx );
return( ret );
}
#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
(void) rs_ctx;
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
if( ctx->pk_info->verify_func == NULL )
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len,
sig, sig_len ) );
}
/* /*
* Verify a signature * Verify a signature
*/ */
@ -178,15 +309,8 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len, const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len ) const unsigned char *sig, size_t sig_len )
{ {
if( ctx == NULL || ctx->pk_info == NULL || return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len,
pk_hashlen_helper( md_alg, &hash_len ) != 0 ) sig, sig_len, NULL ) );
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if( ctx->pk_info->verify_func == NULL )
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len,
sig, sig_len ) );
} }
/* /*
@ -247,6 +371,50 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) );
} }
/*
* Make a signature (restartable)
*/
int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
mbedtls_pk_restart_ctx *rs_ctx )
{
if( ctx == NULL || ctx->pk_info == NULL ||
pk_hashlen_helper( md_alg, &hash_len ) != 0 )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/* optimization: use non-restartable version if restart disabled */
if( rs_ctx != NULL &&
mbedtls_ecp_restart_is_enabled() &&
ctx->pk_info->sign_rs_func != NULL )
{
int ret;
if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
return( ret );
ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg,
hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx->rs_ctx );
if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
mbedtls_pk_restart_free( rs_ctx );
return( ret );
}
#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
(void) rs_ctx;
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
if( ctx->pk_info->sign_func == NULL )
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len,
sig, sig_len, f_rng, p_rng ) );
}
/* /*
* Make a signature * Make a signature
*/ */
@ -255,15 +423,8 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
unsigned char *sig, size_t *sig_len, unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{ {
if( ctx == NULL || ctx->pk_info == NULL || return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len,
pk_hashlen_helper( md_alg, &hash_len ) != 0 ) sig, sig_len, f_rng, p_rng, NULL ) );
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if( ctx->pk_info->sign_func == NULL )
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len,
sig, sig_len, f_rng, p_rng ) );
} }
/* /*
@ -308,12 +469,14 @@ int mbedtls_pk_encrypt( mbedtls_pk_context *ctx,
int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ) int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv )
{ {
if( pub == NULL || pub->pk_info == NULL || if( pub == NULL || pub->pk_info == NULL ||
prv == NULL || prv->pk_info == NULL || prv == NULL || prv->pk_info == NULL )
prv->pk_info->check_pair_func == NULL )
{ {
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
} }
if( prv->pk_info->check_pair_func == NULL )
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT ) if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT )
{ {
if( pub->pk_info->type != MBEDTLS_PK_RSA ) if( pub->pk_info->type != MBEDTLS_PK_RSA )
@ -376,4 +539,65 @@ mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx )
return( ctx->pk_info->type ); return( ctx->pk_info->type );
} }
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/*
* Load the key to a PSA key slot,
* then turn the PK context into a wrapper for that key slot.
*
* Currently only works for EC private keys.
*/
int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk,
psa_key_slot_t *slot,
psa_algorithm_t hash_alg )
{
#if !defined(MBEDTLS_ECP_C)
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
#else
psa_key_slot_t key;
const mbedtls_ecp_keypair *ec;
unsigned char d[MBEDTLS_ECP_MAX_BYTES];
size_t d_len;
psa_ecc_curve_t curve_id;
psa_key_type_t key_type;
psa_key_policy_t policy;
int ret;
/* export the private key material in the format PSA wants */
if( mbedtls_pk_get_type( pk ) != MBEDTLS_PK_ECKEY )
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
ec = mbedtls_pk_ec( *pk );
d_len = ( ec->grp.nbits + 7 ) / 8;
if( ( ret = mbedtls_mpi_write_binary( &ec->d, d, d_len ) ) != 0 )
return( ret );
curve_id = mbedtls_ecp_curve_info_from_grp_id( ec->grp.id )->tls_id;
/* find a free key slot */
if( PSA_SUCCESS != mbedtls_psa_get_free_key_slot( &key ) )
return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
/* set policy */
psa_key_policy_init( &policy );
psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_SIGN,
PSA_ALG_ECDSA(hash_alg) );
if( PSA_SUCCESS != psa_set_key_policy( key, &policy ) )
return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
/* import private key in slot */
key_type = PSA_KEY_TYPE_ECC_KEYPAIR(curve_id);
if( PSA_SUCCESS != psa_import_key( key, key_type, d, d_len ) )
return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
/* remember slot number to be destroyed later by caller */
*slot = key;
/* make PK context wrap the key slot */
mbedtls_pk_free( pk );
mbedtls_pk_init( pk );
return( mbedtls_pk_setup_opaque( pk, key ) );
#endif /* MBEDTLS_ECP_C */
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_PK_C */ #endif /* MBEDTLS_PK_C */

View File

@ -41,10 +41,20 @@
#include "mbedtls/ecdsa.h" #include "mbedtls/ecdsa.h"
#endif #endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "mbedtls/asn1write.h"
#endif
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
#include "mbedtls/platform_util.h" #include "mbedtls/platform_util.h"
#endif #endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#include "mbedtls/psa_util.h"
#include "mbedtls/asn1.h"
#endif
#if defined(MBEDTLS_PLATFORM_C) #if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#else #else
@ -190,11 +200,19 @@ const mbedtls_pk_info_t mbedtls_rsa_info = {
rsa_can_do, rsa_can_do,
rsa_verify_wrap, rsa_verify_wrap,
rsa_sign_wrap, rsa_sign_wrap,
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
NULL,
NULL,
#endif
rsa_decrypt_wrap, rsa_decrypt_wrap,
rsa_encrypt_wrap, rsa_encrypt_wrap,
rsa_check_pair_wrap, rsa_check_pair_wrap,
rsa_alloc_wrap, rsa_alloc_wrap,
rsa_free_wrap, rsa_free_wrap,
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
NULL,
NULL,
#endif
rsa_debug, rsa_debug,
}; };
#endif /* MBEDTLS_RSA_C */ #endif /* MBEDTLS_RSA_C */
@ -262,6 +280,110 @@ static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
return( ret ); return( ret );
} }
#if defined(MBEDTLS_ECP_RESTARTABLE)
/* Forward declarations */
static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len,
void *rs_ctx );
static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
void *rs_ctx );
/*
* Restart context for ECDSA operations with ECKEY context
*
* We need to store an actual ECDSA context, as we need to pass the same to
* the underlying ecdsa function, so we can't create it on the fly every time.
*/
typedef struct
{
mbedtls_ecdsa_restart_ctx ecdsa_rs;
mbedtls_ecdsa_context ecdsa_ctx;
} eckey_restart_ctx;
static void *eckey_rs_alloc( void )
{
eckey_restart_ctx *rs_ctx;
void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) );
if( ctx != NULL )
{
rs_ctx = ctx;
mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs );
mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx );
}
return( ctx );
}
static void eckey_rs_free( void *ctx )
{
eckey_restart_ctx *rs_ctx;
if( ctx == NULL)
return;
rs_ctx = ctx;
mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs );
mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx );
mbedtls_free( ctx );
}
static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len,
void *rs_ctx )
{
int ret;
eckey_restart_ctx *rs = rs_ctx;
/* Should never happen */
if( rs == NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
/* set up our own sub-context if needed (that is, on first run) */
if( rs->ecdsa_ctx.grp.pbits == 0 )
MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) );
MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx,
md_alg, hash, hash_len,
sig, sig_len, &rs->ecdsa_rs ) );
cleanup:
return( ret );
}
static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
void *rs_ctx )
{
int ret;
eckey_restart_ctx *rs = rs_ctx;
/* Should never happen */
if( rs == NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
/* set up our own sub-context if needed (that is, on first run) */
if( rs->ecdsa_ctx.grp.pbits == 0 )
MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) );
MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg,
hash, hash_len, sig, sig_len,
f_rng, p_rng, &rs->ecdsa_rs ) );
cleanup:
return( ret );
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
#endif /* MBEDTLS_ECDSA_C */ #endif /* MBEDTLS_ECDSA_C */
static int eckey_check_pair( const void *pub, const void *prv ) static int eckey_check_pair( const void *pub, const void *prv )
@ -301,15 +423,23 @@ const mbedtls_pk_info_t mbedtls_eckey_info = {
#if defined(MBEDTLS_ECDSA_C) #if defined(MBEDTLS_ECDSA_C)
eckey_verify_wrap, eckey_verify_wrap,
eckey_sign_wrap, eckey_sign_wrap,
#else #if defined(MBEDTLS_ECP_RESTARTABLE)
NULL, eckey_verify_rs_wrap,
NULL, eckey_sign_rs_wrap,
#endif #endif
#else /* MBEDTLS_ECDSA_C */
NULL,
NULL,
#endif /* MBEDTLS_ECDSA_C */
NULL, NULL,
NULL, NULL,
eckey_check_pair, eckey_check_pair,
eckey_alloc_wrap, eckey_alloc_wrap,
eckey_free_wrap, eckey_free_wrap,
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
eckey_rs_alloc,
eckey_rs_free,
#endif
eckey_debug, eckey_debug,
}; };
@ -329,11 +459,19 @@ const mbedtls_pk_info_t mbedtls_eckeydh_info = {
eckeydh_can_do, eckeydh_can_do,
NULL, NULL,
NULL, NULL,
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
NULL,
NULL,
#endif
NULL, NULL,
NULL, NULL,
eckey_check_pair, eckey_check_pair,
eckey_alloc_wrap, /* Same underlying key structure */ eckey_alloc_wrap, /* Same underlying key structure */
eckey_free_wrap, /* Same underlying key structure */ eckey_free_wrap, /* Same underlying key structure */
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
NULL,
NULL,
#endif
eckey_debug, /* Same underlying key structure */ eckey_debug, /* Same underlying key structure */
}; };
#endif /* MBEDTLS_ECP_C */ #endif /* MBEDTLS_ECP_C */
@ -344,6 +482,154 @@ static int ecdsa_can_do( mbedtls_pk_type_t type )
return( type == MBEDTLS_PK_ECDSA ); return( type == MBEDTLS_PK_ECDSA );
} }
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/*
* An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of
* those integers and convert it to the fixed-length encoding expected by PSA.
*/
static int extract_ecdsa_sig_int( unsigned char **from, const unsigned char *end,
unsigned char *to, size_t to_len )
{
int ret;
size_t unpadded_len, padding_len;
if( ( ret = mbedtls_asn1_get_tag( from, end, &unpadded_len,
MBEDTLS_ASN1_INTEGER ) ) != 0 )
{
return( ret );
}
while( unpadded_len > 0 && **from == 0x00 )
{
( *from )++;
unpadded_len--;
}
if( unpadded_len > to_len || unpadded_len == 0 )
return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
padding_len = to_len - unpadded_len;
memset( to, 0x00, padding_len );
memcpy( to + padding_len, *from, unpadded_len );
( *from ) += unpadded_len;
return( 0 );
}
/*
* Convert a signature from an ASN.1 sequence of two integers
* to a raw {r,s} buffer. Note: the provided sig buffer must be at least
* twice as big as int_size.
*/
static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end,
unsigned char *sig, size_t int_size )
{
int ret;
size_t tmp_size;
if( ( ret = mbedtls_asn1_get_tag( p, end, &tmp_size,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
return( ret );
/* Extract r */
if( ( ret = extract_ecdsa_sig_int( p, end, sig, int_size ) ) != 0 )
return( ret );
/* Extract s */
if( ( ret = extract_ecdsa_sig_int( p, end, sig + int_size, int_size ) ) != 0 )
return( ret );
return( 0 );
}
static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len )
{
int ret;
psa_key_slot_t key_slot;
psa_key_policy_t policy;
psa_key_type_t psa_type;
mbedtls_pk_context key;
int key_len;
/* see ECP_PUB_DER_MAX_BYTES in pkwrite.c */
unsigned char buf[30 + 2 * MBEDTLS_ECP_MAX_BYTES];
unsigned char *p = (unsigned char*) sig;
mbedtls_pk_info_t pk_info = mbedtls_eckey_info;
psa_algorithm_t psa_sig_md, psa_md;
psa_ecc_curve_t curve = mbedtls_psa_translate_ecc_group(
( (mbedtls_ecdsa_context *) ctx )->grp.id );
const size_t signature_part_size = ( ( (mbedtls_ecdsa_context *) ctx )->grp.nbits + 7 ) / 8;
if( curve == 0 )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
/* mbedlts_pk_write_pubkey_der() expects a full PK context,
* re-construct one to make it happy */
key.pk_info = &pk_info;
key.pk_ctx = ctx;
key_len = mbedtls_pk_write_pubkey_der( &key, buf, sizeof( buf ) );
if( key_len <= 0 )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if( ( ret = mbedtls_psa_get_free_key_slot( &key_slot ) ) != PSA_SUCCESS )
return( mbedtls_psa_err_translate_pk( ret ) );
psa_md = mbedtls_psa_translate_md( md_alg );
if( psa_md == 0 )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
psa_sig_md = PSA_ALG_ECDSA( psa_md );
psa_type = PSA_KEY_TYPE_ECC_PUBLIC_KEY( curve );
psa_key_policy_init( &policy );
psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_VERIFY, psa_sig_md );
if( ( ret = psa_set_key_policy( key_slot, &policy ) ) != PSA_SUCCESS )
{
ret = mbedtls_psa_err_translate_pk( ret );
goto cleanup;
}
if( psa_import_key( key_slot, psa_type, buf + sizeof( buf ) - key_len, key_len )
!= PSA_SUCCESS )
{
ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
goto cleanup;
}
/* We don't need the exported key anymore and can
* reuse its buffer for signature extraction. */
if( 2 * signature_part_size > sizeof( buf ) )
{
ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
goto cleanup;
}
if( ( ret = extract_ecdsa_sig( &p, sig + sig_len, buf,
signature_part_size ) ) != 0 )
{
goto cleanup;
}
if( psa_asymmetric_verify( key_slot, psa_sig_md,
hash, hash_len,
buf, 2 * signature_part_size )
!= PSA_SUCCESS )
{
ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
goto cleanup;
}
if( p != sig + sig_len )
{
ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
goto cleanup;
}
ret = 0;
cleanup:
psa_destroy_key( key_slot );
return( ret );
}
#else /* MBEDTLS_USE_PSA_CRYPTO */
static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len, const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len ) const unsigned char *sig, size_t sig_len )
@ -359,6 +645,7 @@ static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
return( ret ); return( ret );
} }
#endif /* MBEDTLS_USE_PSA_CRYPTO */
static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len, const unsigned char *hash, size_t hash_len,
@ -369,6 +656,40 @@ static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) );
} }
#if defined(MBEDTLS_ECP_RESTARTABLE)
static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len,
void *rs_ctx )
{
int ret;
((void) md_alg);
ret = mbedtls_ecdsa_read_signature_restartable(
(mbedtls_ecdsa_context *) ctx,
hash, hash_len, sig, sig_len,
(mbedtls_ecdsa_restart_ctx *) rs_ctx );
if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH )
return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
return( ret );
}
static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
void *rs_ctx )
{
return( mbedtls_ecdsa_write_signature_restartable(
(mbedtls_ecdsa_context *) ctx,
md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng,
(mbedtls_ecdsa_restart_ctx *) rs_ctx ) );
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
static void *ecdsa_alloc_wrap( void ) static void *ecdsa_alloc_wrap( void )
{ {
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) );
@ -385,6 +706,24 @@ static void ecdsa_free_wrap( void *ctx )
mbedtls_free( ctx ); mbedtls_free( ctx );
} }
#if defined(MBEDTLS_ECP_RESTARTABLE)
static void *ecdsa_rs_alloc( void )
{
void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) );
if( ctx != NULL )
mbedtls_ecdsa_restart_init( ctx );
return( ctx );
}
static void ecdsa_rs_free( void *ctx )
{
mbedtls_ecdsa_restart_free( ctx );
mbedtls_free( ctx );
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
const mbedtls_pk_info_t mbedtls_ecdsa_info = { const mbedtls_pk_info_t mbedtls_ecdsa_info = {
MBEDTLS_PK_ECDSA, MBEDTLS_PK_ECDSA,
"ECDSA", "ECDSA",
@ -392,11 +731,19 @@ const mbedtls_pk_info_t mbedtls_ecdsa_info = {
ecdsa_can_do, ecdsa_can_do,
ecdsa_verify_wrap, ecdsa_verify_wrap,
ecdsa_sign_wrap, ecdsa_sign_wrap,
#if defined(MBEDTLS_ECP_RESTARTABLE)
ecdsa_verify_rs_wrap,
ecdsa_sign_rs_wrap,
#endif
NULL, NULL,
NULL, NULL,
eckey_check_pair, /* Compatible key structures */ eckey_check_pair, /* Compatible key structures */
ecdsa_alloc_wrap, ecdsa_alloc_wrap,
ecdsa_free_wrap, ecdsa_free_wrap,
#if defined(MBEDTLS_ECP_RESTARTABLE)
ecdsa_rs_alloc,
ecdsa_rs_free,
#endif
eckey_debug, /* Compatible key structures */ eckey_debug, /* Compatible key structures */
}; };
#endif /* MBEDTLS_ECDSA_C */ #endif /* MBEDTLS_ECDSA_C */
@ -506,6 +853,10 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = {
rsa_alt_can_do, rsa_alt_can_do,
NULL, NULL,
rsa_alt_sign_wrap, rsa_alt_sign_wrap,
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
NULL,
NULL,
#endif
rsa_alt_decrypt_wrap, rsa_alt_decrypt_wrap,
NULL, NULL,
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
@ -515,9 +866,191 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = {
#endif #endif
rsa_alt_alloc_wrap, rsa_alt_alloc_wrap,
rsa_alt_free_wrap, rsa_alt_free_wrap,
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
NULL,
NULL,
#endif
NULL, NULL,
}; };
#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
#if defined(MBEDTLS_USE_PSA_CRYPTO)
static void *pk_opaque_alloc_wrap( void )
{
void *ctx = mbedtls_calloc( 1, sizeof( psa_key_slot_t ) );
/* no _init() function to call, an calloc() already zeroized */
return( ctx );
}
static void pk_opaque_free_wrap( void *ctx )
{
mbedtls_platform_zeroize( ctx, sizeof( psa_key_slot_t ) );
mbedtls_free( ctx );
}
static size_t pk_opaque_get_bitlen( const void *ctx )
{
const psa_key_slot_t *key = (const psa_key_slot_t *) ctx;
size_t bits;
if( PSA_SUCCESS != psa_get_key_information( *key, NULL, &bits ) )
return( 0 );
return( bits );
}
static int pk_opaque_can_do( mbedtls_pk_type_t type )
{
/* For now opaque PSA keys can only wrap ECC keypairs,
* as checked by setup_psa().
* Also, ECKEY_DH does not really make sense with the current API. */
return( type == MBEDTLS_PK_ECKEY ||
type == MBEDTLS_PK_ECDSA );
}
/*
* Simultaneously convert and move raw MPI from the beginning of a buffer
* to an ASN.1 MPI at the end of the buffer.
* See also mbedtls_asn1_write_mpi().
*
* p: pointer to the end of the output buffer
* start: start of the output buffer, and also of the mpi to write at the end
* n_len: length of the mpi to read from start
*/
static int asn1_write_mpibuf( unsigned char **p, unsigned char *start,
size_t n_len )
{
int ret;
size_t len = 0;
if( (size_t)( *p - start ) < n_len )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
len = n_len;
*p -= len;
memmove( *p, start, len );
/* ASN.1 DER encoding requires minimal length, so skip leading 0s.
* Neither r nor s should be 0, but as a failsafe measure, still detect
* that rather than overflowing the buffer in case of a PSA error. */
while( len > 0 && **p == 0x00 )
{
++(*p);
--len;
}
/* this is only reached if the signature was invalid */
if( len == 0 )
return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
/* if the msb is 1, ASN.1 requires that we prepend a 0.
* Neither r nor s can be 0, so we can assume len > 0 at all times. */
if( **p & 0x80 )
{
if( *p - start < 1 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = 0x00;
len += 1;
}
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
MBEDTLS_ASN1_INTEGER ) );
return( (int) len );
}
/* Transcode signature from PSA format to ASN.1 sequence.
* See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of
* MPIs, and in-place.
*
* [in/out] sig: the signature pre- and post-transcoding
* [in/out] sig_len: signature length pre- and post-transcoding
* [int] buf_len: the available size the in/out buffer
*/
static int pk_ecdsa_sig_asn1_from_psa( unsigned char *sig, size_t *sig_len,
size_t buf_len )
{
int ret;
size_t len = 0;
const size_t rs_len = *sig_len / 2;
unsigned char *p = sig + buf_len;
MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig + rs_len, rs_len ) );
MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig, rs_len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, sig, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, sig,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
memmove( sig, p, len );
*sig_len = len;
return( 0 );
}
static int pk_opaque_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
const psa_key_slot_t *key = (const psa_key_slot_t *) ctx;
psa_algorithm_t alg = PSA_ALG_ECDSA( mbedtls_psa_translate_md( md_alg ) );
size_t bits, buf_len;
psa_status_t status;
/* PSA has its own RNG */
(void) f_rng;
(void) p_rng;
/* PSA needs an output buffer of known size, but our API doesn't provide
* that information. Assume that the buffer is large enough for a
* maximal-length signature with that key (otherwise the application is
* buggy anyway). */
status = psa_get_key_information( *key, NULL, &bits );
if( status != PSA_SUCCESS )
return( mbedtls_psa_err_translate_pk( status ) );
buf_len = MBEDTLS_ECDSA_MAX_SIG_LEN( bits );
/* make the signature */
status = psa_asymmetric_sign( *key, alg, hash, hash_len,
sig, buf_len, sig_len );
if( status != PSA_SUCCESS )
return( mbedtls_psa_err_translate_pk( status ) );
/* transcode it to ASN.1 sequence */
return( pk_ecdsa_sig_asn1_from_psa( sig, sig_len, buf_len ) );
}
const mbedtls_pk_info_t mbedtls_pk_opaque_info = {
MBEDTLS_PK_OPAQUE,
"Opaque",
pk_opaque_get_bitlen,
pk_opaque_can_do,
NULL, /* verify - will be done later */
pk_opaque_sign_wrap,
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
NULL, /* restartable verify - not relevant */
NULL, /* restartable sign - not relevant */
#endif
NULL, /* decrypt - will be done later */
NULL, /* encrypt - will be done later */
NULL, /* check_pair - could be done later or left NULL */
pk_opaque_alloc_wrap,
pk_opaque_free_wrap,
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
NULL, /* restart alloc - not relevant */
NULL, /* restart free - not relevant */
#endif
NULL, /* debug - could be done later, or even left NULL */
};
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_PK_C */ #endif /* MBEDTLS_PK_C */

View File

@ -1295,6 +1295,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
return( 0 ); return( 0 );
mbedtls_pk_free( pk ); mbedtls_pk_free( pk );
mbedtls_pk_init( pk );
if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH )
{ {
@ -1306,39 +1307,42 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
return( 0 ); return( 0 );
mbedtls_pk_free( pk ); mbedtls_pk_free( pk );
mbedtls_pk_init( pk );
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA );
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || if( mbedtls_pk_setup( pk, pk_info ) == 0 &&
( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 )
key, keylen ) ) != 0 )
{
mbedtls_pk_free( pk );
}
else
{ {
return( 0 ); return( 0 );
} }
mbedtls_pk_free( pk );
mbedtls_pk_init( pk );
#endif /* MBEDTLS_RSA_C */ #endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_C)
pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY );
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || if( mbedtls_pk_setup( pk, pk_info ) == 0 &&
( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
key, keylen ) ) != 0 ) key, keylen ) == 0 )
{
mbedtls_pk_free( pk );
}
else
{ {
return( 0 ); return( 0 );
} }
mbedtls_pk_free( pk );
#endif /* MBEDTLS_ECP_C */ #endif /* MBEDTLS_ECP_C */
/* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't,
* it is ok to leave the PK context initialized but not
* freed: It is the caller's responsibility to call pk_init()
* before calling this function, and to call pk_free()
* when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C
* isn't, this leads to mbedtls_pk_free() being called
* twice, once here and once by the caller, but this is
* also ok and in line with the mbedtls_pk_free() calls
* on failed PEM parsing attempts. */
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
} }

View File

@ -46,6 +46,9 @@
#include "mbedtls/pem.h" #include "mbedtls/pem.h"
#endif #endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#endif
#if defined(MBEDTLS_PLATFORM_C) #if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#else #else
@ -161,6 +164,28 @@ int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) ); MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) );
else else
#endif #endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_OPAQUE )
{
size_t buffer_size;
psa_key_slot_t* key_slot = (psa_key_slot_t*) key->pk_ctx;
if ( *p < start )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
buffer_size = (size_t)( *p - start );
if ( psa_export_public_key( *key_slot, start, buffer_size, &len )
!= PSA_SUCCESS )
{
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
}
else
{
memmove( *p - len, start, len );
}
}
else
#endif /* MBEDTLS_USE_PSA_CRYPTO */
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
return( (int) len ); return( (int) len );
@ -177,6 +202,10 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, si
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) );
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_OPAQUE )
{
return( (int) len );
}
if( c - buf < 1 ) if( c - buf < 1 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );

View File

@ -30,7 +30,14 @@
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#include "mbedtls/platform_util.h" #include "mbedtls/platform_util.h"
#if defined(MBEDTLS_PLATFORM_MEMORY) /* The compile time configuration of memory allocation via the macros
* MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime
* configuration via mbedtls_platform_set_calloc_free(). So, omit everything
* related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */
#if defined(MBEDTLS_PLATFORM_MEMORY) && \
!( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \
defined(MBEDTLS_PLATFORM_FREE_MACRO) )
#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) #if !defined(MBEDTLS_PLATFORM_STD_CALLOC)
static void *platform_calloc_uninit( size_t n, size_t size ) static void *platform_calloc_uninit( size_t n, size_t size )
{ {
@ -71,7 +78,9 @@ int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ),
mbedtls_free_func = free_func; mbedtls_free_func = free_func;
return( 0 ); return( 0 );
} }
#endif /* MBEDTLS_PLATFORM_MEMORY */ #endif /* MBEDTLS_PLATFORM_MEMORY &&
!( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&
defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */
#if defined(_WIN32) #if defined(_WIN32)
#include <stdarg.h> #include <stdarg.h>

View File

@ -502,6 +502,7 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
{ {
int ret; int ret;
mbedtls_mpi H, G, L; mbedtls_mpi H, G, L;
int prime_quality = 0;
if( f_rng == NULL || nbits < 128 || exponent < 3 ) if( f_rng == NULL || nbits < 128 || exponent < 3 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@ -509,6 +510,14 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
if( nbits % 2 ) if( nbits % 2 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
/*
* If the modulus is 1024 bit long or shorter, then the security strength of
* the RSA algorithm is less than or equal to 80 bits and therefore an error
* rate of 2^-80 is sufficient.
*/
if( nbits > 1024 )
prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR;
mbedtls_mpi_init( &H ); mbedtls_mpi_init( &H );
mbedtls_mpi_init( &G ); mbedtls_mpi_init( &G );
mbedtls_mpi_init( &L ); mbedtls_mpi_init( &L );
@ -523,11 +532,11 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
do do
{ {
MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, 0, MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1,
f_rng, p_rng ) ); prime_quality, f_rng, p_rng ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0, MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1,
f_rng, p_rng ) ); prime_quality, f_rng, p_rng ) );
/* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */ /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) );
@ -1521,7 +1530,7 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
size_t olen; size_t olen;
unsigned char *p = sig; unsigned char *p = sig;
unsigned char salt[MBEDTLS_MD_MAX_SIZE]; unsigned char salt[MBEDTLS_MD_MAX_SIZE];
unsigned int slen, hlen, offset = 0; size_t slen, min_slen, hlen, offset = 0;
int ret; int ret;
size_t msb; size_t msb;
const mbedtls_md_info_t *md_info; const mbedtls_md_info_t *md_info;
@ -1550,10 +1559,20 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
hlen = mbedtls_md_get_size( md_info ); hlen = mbedtls_md_get_size( md_info );
slen = hlen;
if( olen < hlen + slen + 2 ) /* Calculate the largest possible salt length. Normally this is the hash
* length, which is the maximum length the salt can have. If there is not
* enough room, use the maximum salt length that fits. The constraint is
* that the hash length plus the salt length plus 2 bytes must be at most
* the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017
* (PKCS#1 v2.2) §9.1.1 step 3. */
min_slen = hlen - 2;
if( olen < hlen + min_slen + 2 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
else if( olen >= hlen + hlen + 2 )
slen = hlen;
else
slen = olen - hlen - 2;
memset( sig, 0, olen ); memset( sig, 0, olen );
@ -1563,7 +1582,7 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
/* Note: EMSA-PSS encoding is over the length of N - 1 bits */ /* Note: EMSA-PSS encoding is over the length of N - 1 bits */
msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
p += olen - hlen * 2 - 2; p += olen - hlen - slen - 2;
*p++ = 0x01; *p++ = 0x01;
memcpy( p, salt, slen ); memcpy( p, salt, slen );
p += slen; p += slen;

View File

@ -351,15 +351,20 @@ int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P,
*/ */
#if defined(MBEDTLS_GENPRIME) #if defined(MBEDTLS_GENPRIME)
/*
* When generating keys, the strongest security we support aims for an error
* rate of at most 2^-100 and we are aiming for the same certainty here as
* well.
*/
if( f_rng != NULL && P != NULL && if( f_rng != NULL && P != NULL &&
( ret = mbedtls_mpi_is_prime( P, f_rng, p_rng ) ) != 0 ) ( ret = mbedtls_mpi_is_prime_ext( P, 50, f_rng, p_rng ) ) != 0 )
{ {
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup; goto cleanup;
} }
if( f_rng != NULL && Q != NULL && if( f_rng != NULL && Q != NULL &&
( ret = mbedtls_mpi_is_prime( Q, f_rng, p_rng ) ) != 0 ) ( ret = mbedtls_mpi_is_prime_ext( Q, 50, f_rng, p_rng ) ) != 0 )
{ {
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup; goto cleanup;

View File

@ -51,6 +51,44 @@
#include "mbedtls/platform_util.h" #include "mbedtls/platform_util.h"
#endif #endif
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
static int ssl_conf_has_static_psk( mbedtls_ssl_config const *conf )
{
if( conf->psk_identity == NULL ||
conf->psk_identity_len == 0 )
{
return( 0 );
}
if( conf->psk != NULL && conf->psk_len != 0 )
return( 1 );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( conf->psk_opaque != 0 )
return( 1 );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
return( 0 );
}
#if defined(MBEDTLS_USE_PSA_CRYPTO)
static int ssl_conf_has_static_raw_psk( mbedtls_ssl_config const *conf )
{
if( conf->psk_identity == NULL ||
conf->psk_identity_len == 0 )
{
return( 0 );
}
if( conf->psk != NULL && conf->psk_len != 0 )
return( 1 );
return( 0 );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
unsigned char *buf, unsigned char *buf,
@ -754,6 +792,15 @@ static int ssl_validate_ciphersuite( const mbedtls_ssl_ciphersuite_t * suite_inf
return( 1 ); return( 1 );
#endif #endif
/* Don't suggest PSK-based ciphersuite if no PSK is available. */
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) &&
ssl_conf_has_static_psk( ssl->conf ) == 0 )
{
return( 1 );
}
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
return( 0 ); return( 0 );
} }
@ -1763,6 +1810,14 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) );
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA &&
ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{
ssl->handshake->ecrs_enabled = 1;
}
#endif
if( comp != MBEDTLS_SSL_COMPRESS_NULL if( comp != MBEDTLS_SSL_COMPRESS_NULL
#if defined(MBEDTLS_ZLIB_SUPPORT) #if defined(MBEDTLS_ZLIB_SUPPORT)
&& comp != MBEDTLS_SSL_COMPRESS_DEFLATE && comp != MBEDTLS_SSL_COMPRESS_DEFLATE
@ -2068,6 +2123,10 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
(const unsigned char **) p, end ) ) != 0 ) (const unsigned char **) p, end ) ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret ); MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret );
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
#endif
return( ret ); return( ret );
} }
@ -2097,7 +2156,7 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
* *
* opaque psk_identity_hint<0..2^16-1>; * opaque psk_identity_hint<0..2^16-1>;
*/ */
if( (*p) > end - 2 ) if( end - (*p) < 2 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message "
"(psk_identity_hint length)" ) ); "(psk_identity_hint length)" ) );
@ -2106,7 +2165,7 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
len = (*p)[0] << 8 | (*p)[1]; len = (*p)[0] << 8 | (*p)[1];
*p += 2; *p += 2;
if( (*p) > end - len ) if( end - (*p) < (int) len )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message "
"(psk_identity_hint length)" ) ); "(psk_identity_hint length)" ) );
@ -2349,6 +2408,14 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ssl->handshake->ecrs_enabled &&
ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing )
{
goto start_processing;
}
#endif
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
@ -2386,6 +2453,12 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
} }
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ssl->handshake->ecrs_enabled )
ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing;
start_processing:
#endif
p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
end = ssl->in_msg + ssl->in_hslen; end = ssl->in_msg + ssl->in_hslen;
MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p ); MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p );
@ -2478,6 +2551,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
size_t params_len = p - params; size_t params_len = p - params;
void *rs_ctx = NULL;
/* /*
* Handle the digitally-signed structure * Handle the digitally-signed structure
@ -2600,12 +2674,25 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
} }
if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, #if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
md_alg, hash, hashlen, p, sig_len ) ) != 0 ) if( ssl->handshake->ecrs_enabled )
rs_ctx = &ssl->handshake->ecrs_ctx.pk;
#endif
if( ( ret = mbedtls_pk_verify_restartable(
&ssl->session_negotiate->peer_cert->pk,
md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 )
{ {
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
#endif
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR );
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret );
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
#endif
return( ret ); return( ret );
} }
} }
@ -2903,6 +2990,16 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
*/ */
i = 4; i = 4;
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ssl->handshake->ecrs_enabled )
{
if( ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret )
goto ecdh_calc_secret;
mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx );
}
#endif
ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx,
&n, &n,
&ssl->out_msg[i], 1000, &ssl->out_msg[i], 1000,
@ -2910,11 +3007,26 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
if( ret != 0 ) if( ret != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret );
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
#endif
return( ret ); return( ret );
} }
MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q );
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ssl->handshake->ecrs_enabled )
{
ssl->handshake->ecrs_n = n;
ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret;
}
ecdh_calc_secret:
if( ssl->handshake->ecrs_enabled )
n = ssl->handshake->ecrs_n;
#endif
if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
&ssl->handshake->pmslen, &ssl->handshake->pmslen,
ssl->handshake->premaster, ssl->handshake->premaster,
@ -2922,6 +3034,10 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret );
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
#endif
return( ret ); return( ret );
} }
@ -2938,10 +3054,12 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
/* /*
* opaque psk_identity<0..2^16-1>; * opaque psk_identity<0..2^16-1>;
*/ */
if( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL ) if( ssl_conf_has_static_psk( ssl->conf ) == 0 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for PSK" ) ); /* We don't offer PSK suites if we don't have a PSK,
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); * and we check that the server's choice is among the
* ciphersuites we offered, so this should never happen. */
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
} }
i = 4; i = 4;
@ -2970,6 +3088,12 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
{ {
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only suites. */
if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 ) if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 )
return( ret ); return( ret );
} }
@ -2978,6 +3102,12 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK )
{ {
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only suites. */
if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/* /*
* ClientDiffieHellmanPublic public (DHM send G^X mod P) * ClientDiffieHellmanPublic public (DHM send G^X mod P)
*/ */
@ -3008,6 +3138,12 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
{ {
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only suites. */
if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/* /*
* ClientECDiffieHellmanPublic public; * ClientECDiffieHellmanPublic public;
*/ */
@ -3029,6 +3165,17 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
} }
#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK &&
ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 &&
ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "skip PMS generation for opaque PSK" ) );
}
else
#endif /* MBEDTLS_USE_PSA_CRYPTO &&
MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
ciphersuite_info->key_exchange ) ) != 0 ) ciphersuite_info->key_exchange ) ) != 0 )
{ {
@ -3140,9 +3287,18 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
unsigned char *hash_start = hash; unsigned char *hash_start = hash;
mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
unsigned int hashlen; unsigned int hashlen;
void *rs_ctx = NULL;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ssl->handshake->ecrs_enabled &&
ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign )
{
goto sign;
}
#endif
if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
@ -3174,8 +3330,15 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
} }
/* /*
* Make an RSA signature of the handshake digests * Make a signature of the handshake digests
*/ */
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ssl->handshake->ecrs_enabled )
ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign;
sign:
#endif
ssl->handshake->calc_verify( ssl, hash ); ssl->handshake->calc_verify( ssl, hash );
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
@ -3252,11 +3415,21 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
} }
if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash_start, hashlen, #if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ssl->handshake->ecrs_enabled )
rs_ctx = &ssl->handshake->ecrs_ctx.pk;
#endif
if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ),
md_alg, hash_start, hashlen,
ssl->out_msg + 6 + offset, &n, ssl->out_msg + 6 + offset, &n,
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret );
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
#endif
return( ret ); return( ret );
} }

View File

@ -149,6 +149,48 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
} }
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
static int ssl_conf_has_psk_or_cb( mbedtls_ssl_config const *conf )
{
if( conf->f_psk != NULL )
return( 1 );
if( conf->psk_identity_len == 0 || conf->psk_identity == NULL )
return( 0 );
if( conf->psk != NULL && conf->psk_len != 0 )
return( 1 );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( conf->psk_opaque != 0 )
return( 1 );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
return( 0 );
}
#if defined(MBEDTLS_USE_PSA_CRYPTO)
static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl )
{
if( ssl->conf->f_psk != NULL )
{
/* If we've used a callback to select the PSK,
* the static configuration is irrelevant. */
if( ssl->handshake->psk_opaque != 0 )
return( 1 );
return( 0 );
}
if( ssl->conf->psk_opaque != 0 )
return( 1 );
return( 0 );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
const unsigned char *buf, const unsigned char *buf,
size_t len ) size_t len )
@ -867,9 +909,7 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id,
/* If the ciphersuite requires a pre-shared key and we don't /* If the ciphersuite requires a pre-shared key and we don't
* have one, skip it now rather than failing later */ * have one, skip it now rather than failing later */
if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) &&
ssl->conf->f_psk == NULL && ssl_conf_has_psk_or_cb( ssl->conf ) == 0 )
( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL ||
ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) )
{ {
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) );
return( 0 ); return( 0 );
@ -3648,9 +3688,7 @@ static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned cha
int ret = 0; int ret = 0;
size_t n; size_t n;
if( ssl->conf->f_psk == NULL && if( ssl_conf_has_psk_or_cb( ssl->conf ) == 0 )
( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL ||
ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) );
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
@ -3828,6 +3866,13 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
} }
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* For opaque PSKs, we perform the PSK-to-MS derivation atomatically
* and skip the intermediate PMS. */
if( ssl_use_opaque_psk( ssl ) == 1 )
MBEDTLS_SSL_DEBUG_MSG( 1, ( "skip PMS generation for opaque PSK" ) );
else
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
ciphersuite_info->key_exchange ) ) != 0 ) ciphersuite_info->key_exchange ) ) != 0 )
{ {
@ -3859,6 +3904,12 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
return( ret ); return( ret );
} }
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only. */
if( ssl_use_opaque_psk( ssl ) == 1 )
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
#endif
if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 ) if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret ); MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret );
@ -3888,6 +3939,12 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
return( ret ); return( ret );
} }
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only. */
if( ssl_use_opaque_psk( ssl ) == 1 )
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
#endif
if( p != end ) if( p != end )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) );
@ -3919,6 +3976,12 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP );
} }
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only. */
if( ssl_use_opaque_psk( ssl ) == 1 )
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
#endif
MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp );
if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,

View File

@ -54,6 +54,19 @@ void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx )
#define MAX_KEY_BYTES 32 /* 256 bits */ #define MAX_KEY_BYTES 32 /* 256 bits */
#define TICKET_KEY_NAME_BYTES 4
#define TICKET_IV_BYTES 12
#define TICKET_CRYPT_LEN_BYTES 2
#define TICKET_AUTH_TAG_BYTES 16
#define TICKET_MIN_LEN ( TICKET_KEY_NAME_BYTES + \
TICKET_IV_BYTES + \
TICKET_CRYPT_LEN_BYTES + \
TICKET_AUTH_TAG_BYTES )
#define TICKET_ADD_DATA_LEN ( TICKET_KEY_NAME_BYTES + \
TICKET_IV_BYTES + \
TICKET_CRYPT_LEN_BYTES )
/* /*
* Generate/update a key * Generate/update a key
*/ */
@ -97,7 +110,7 @@ static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx )
uint32_t current_time = (uint32_t) mbedtls_time( NULL ); uint32_t current_time = (uint32_t) mbedtls_time( NULL );
uint32_t key_time = ctx->keys[ctx->active].generation_time; uint32_t key_time = ctx->keys[ctx->active].generation_time;
if( current_time > key_time && if( current_time >= key_time &&
current_time - key_time < ctx->ticket_lifetime ) current_time - key_time < ctx->ticket_lifetime )
{ {
return( 0 ); return( 0 );
@ -141,11 +154,27 @@ int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx,
if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES ) if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 || #if defined(MBEDTLS_USE_PSA_CRYPTO)
( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 ) ret = mbedtls_cipher_setup_psa( &ctx->keys[0].ctx,
{ cipher_info, TICKET_AUTH_TAG_BYTES );
if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
return( ret );
/* We don't yet expect to support all ciphers through PSA,
* so allow fallback to ordinary mbedtls_cipher_setup(). */
if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 )
return( ret );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
ret = mbedtls_cipher_setup_psa( &ctx->keys[1].ctx,
cipher_info, TICKET_AUTH_TAG_BYTES );
if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
return( ret );
if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 )
return( ret ); return( ret );
}
if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 || if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 ||
( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 ) ( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 )
@ -278,6 +307,7 @@ static int ssl_load_session( mbedtls_ssl_session *session,
* The key_name, iv, and length of encrypted_state are the additional * The key_name, iv, and length of encrypted_state are the additional
* authenticated data. * authenticated data.
*/ */
int mbedtls_ssl_ticket_write( void *p_ticket, int mbedtls_ssl_ticket_write( void *p_ticket,
const mbedtls_ssl_session *session, const mbedtls_ssl_session *session,
unsigned char *start, unsigned char *start,
@ -289,9 +319,9 @@ int mbedtls_ssl_ticket_write( void *p_ticket,
mbedtls_ssl_ticket_context *ctx = p_ticket; mbedtls_ssl_ticket_context *ctx = p_ticket;
mbedtls_ssl_ticket_key *key; mbedtls_ssl_ticket_key *key;
unsigned char *key_name = start; unsigned char *key_name = start;
unsigned char *iv = start + 4; unsigned char *iv = start + TICKET_KEY_NAME_BYTES;
unsigned char *state_len_bytes = iv + 12; unsigned char *state_len_bytes = iv + TICKET_IV_BYTES;
unsigned char *state = state_len_bytes + 2; unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES;
unsigned char *tag; unsigned char *tag;
size_t clear_len, ciph_len; size_t clear_len, ciph_len;
@ -302,7 +332,7 @@ int mbedtls_ssl_ticket_write( void *p_ticket,
/* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag, /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag,
* in addition to session itself, that will be checked when writing it. */ * in addition to session itself, that will be checked when writing it. */
if( end - start < 4 + 12 + 2 + 16 ) if( end - start < TICKET_MIN_LEN )
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
@ -317,9 +347,9 @@ int mbedtls_ssl_ticket_write( void *p_ticket,
*ticket_lifetime = ctx->ticket_lifetime; *ticket_lifetime = ctx->ticket_lifetime;
memcpy( key_name, key->name, 4 ); memcpy( key_name, key->name, TICKET_KEY_NAME_BYTES );
if( ( ret = ctx->f_rng( ctx->p_rng, iv, 12 ) ) != 0 ) if( ( ret = ctx->f_rng( ctx->p_rng, iv, TICKET_IV_BYTES ) ) != 0 )
goto cleanup; goto cleanup;
/* Dump session state */ /* Dump session state */
@ -335,8 +365,11 @@ int mbedtls_ssl_ticket_write( void *p_ticket,
/* Encrypt and authenticate */ /* Encrypt and authenticate */
tag = state + clear_len; tag = state + clear_len;
if( ( ret = mbedtls_cipher_auth_encrypt( &key->ctx, if( ( ret = mbedtls_cipher_auth_encrypt( &key->ctx,
iv, 12, key_name, 4 + 12 + 2, iv, TICKET_IV_BYTES,
state, clear_len, state, &ciph_len, tag, 16 ) ) != 0 ) /* Additional data: key name, IV and length */
key_name, TICKET_ADD_DATA_LEN,
state, clear_len, state, &ciph_len,
tag, TICKET_AUTH_TAG_BYTES ) ) != 0 )
{ {
goto cleanup; goto cleanup;
} }
@ -346,7 +379,7 @@ int mbedtls_ssl_ticket_write( void *p_ticket,
goto cleanup; goto cleanup;
} }
*tlen = 4 + 12 + 2 + 16 + ciph_len; *tlen = TICKET_MIN_LEN + ciph_len;
cleanup: cleanup:
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
@ -385,17 +418,16 @@ int mbedtls_ssl_ticket_parse( void *p_ticket,
mbedtls_ssl_ticket_context *ctx = p_ticket; mbedtls_ssl_ticket_context *ctx = p_ticket;
mbedtls_ssl_ticket_key *key; mbedtls_ssl_ticket_key *key;
unsigned char *key_name = buf; unsigned char *key_name = buf;
unsigned char *iv = buf + 4; unsigned char *iv = buf + TICKET_KEY_NAME_BYTES;
unsigned char *enc_len_p = iv + 12; unsigned char *enc_len_p = iv + TICKET_IV_BYTES;
unsigned char *ticket = enc_len_p + 2; unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES;
unsigned char *tag; unsigned char *tag;
size_t enc_len, clear_len; size_t enc_len, clear_len;
if( ctx == NULL || ctx->f_rng == NULL ) if( ctx == NULL || ctx->f_rng == NULL )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
/* See mbedtls_ssl_ticket_write() */ if( len < TICKET_MIN_LEN )
if( len < 4 + 12 + 2 + 16 )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
@ -409,7 +441,7 @@ int mbedtls_ssl_ticket_parse( void *p_ticket,
enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1]; enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1];
tag = ticket + enc_len; tag = ticket + enc_len;
if( len != 4 + 12 + 2 + enc_len + 16 ) if( len != TICKET_MIN_LEN + enc_len )
{ {
ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
goto cleanup; goto cleanup;
@ -425,9 +457,13 @@ int mbedtls_ssl_ticket_parse( void *p_ticket,
} }
/* Decrypt and authenticate */ /* Decrypt and authenticate */
if( ( ret = mbedtls_cipher_auth_decrypt( &key->ctx, iv, 12, if( ( ret = mbedtls_cipher_auth_decrypt( &key->ctx,
key_name, 4 + 12 + 2, ticket, enc_len, iv, TICKET_IV_BYTES,
ticket, &clear_len, tag, 16 ) ) != 0 ) /* Additional data: key name, IV and length */
key_name, TICKET_ADD_DATA_LEN,
ticket, enc_len,
ticket, &clear_len,
tag, TICKET_AUTH_TAG_BYTES ) ) != 0 )
{ {
if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED )
ret = MBEDTLS_ERR_SSL_INVALID_MAC; ret = MBEDTLS_ERR_SSL_INVALID_MAC;

View File

@ -151,7 +151,7 @@ static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl
{ {
int ret; int ret;
size_t remaining, expansion; size_t remaining, expansion;
size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN; size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl ); const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl );
@ -212,7 +212,10 @@ static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl )
* delivered) of any compliant IPv4 (and IPv6) network, and should work * delivered) of any compliant IPv4 (and IPv6) network, and should work
* on most non-IP stacks too. */ * on most non-IP stacks too. */
if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min ) if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min )
{
ssl->handshake->mtu = 508; ssl->handshake->mtu = 508;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) );
}
new_timeout = 2 * ssl->handshake->retransmit_timeout; new_timeout = 2 * ssl->handshake->retransmit_timeout;
@ -604,9 +607,34 @@ static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *
#endif #endif
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && \
defined(MBEDTLS_USE_PSA_CRYPTO)
static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl )
{
if( ssl->conf->f_psk != NULL )
{
/* If we've used a callback to select the PSK,
* the static configuration is irrelevant. */
if( ssl->handshake->psk_opaque != 0 )
return( 1 );
return( 0 );
}
if( ssl->conf->psk_opaque != 0 )
return( 1 );
return( 0 );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO &&
MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
{ {
int ret = 0; int ret = 0;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
int psa_fallthrough;
#endif /* MBEDTLS_USE_PSA_CRYPTO */
unsigned char tmp[64]; unsigned char tmp[64];
unsigned char keyblk[256]; unsigned char keyblk[256];
unsigned char *key1; unsigned char *key1;
@ -615,9 +643,18 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
unsigned char *mac_dec; unsigned char *mac_dec;
size_t mac_key_len; size_t mac_key_len;
size_t iv_copy_len; size_t iv_copy_len;
size_t taglen = 0;
const mbedtls_cipher_info_t *cipher_info; const mbedtls_cipher_info_t *cipher_info;
const mbedtls_md_info_t *md_info; const mbedtls_md_info_t *md_info;
/* cf. RFC 5246, Section 8.1:
* "The master secret is always exactly 48 bytes in length." */
size_t const master_secret_len = 48;
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
unsigned char session_hash[48];
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
mbedtls_ssl_session *session = ssl->session_negotiate; mbedtls_ssl_session *session = ssl->session_negotiate;
mbedtls_ssl_transform *transform = ssl->transform_negotiate; mbedtls_ssl_transform *transform = ssl->transform_negotiate;
mbedtls_ssl_handshake_params *handshake = ssl->handshake; mbedtls_ssl_handshake_params *handshake = ssl->handshake;
@ -697,68 +734,127 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
* TLSv1+: * TLSv1+:
* master = PRF( premaster, "master secret", randbytes )[0..47] * master = PRF( premaster, "master secret", randbytes )[0..47]
*/ */
if( handshake->resume == 0 ) if( handshake->resume != 0 )
{ {
MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster, MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) );
handshake->pmslen ); }
else
{
/* The label for the KDF used for key expansion.
* This is either "master secret" or "extended master secret"
* depending on whether the Extended Master Secret extension
* is used. */
char const *lbl = "master secret";
/* The salt for the KDF used for key expansion.
* - If the Extended Master Secret extension is not used,
* this is ClientHello.Random + ServerHello.Random
* (see Sect. 8.1 in RFC 5246).
* - If the Extended Master Secret extension is used,
* this is the transcript of the handshake so far.
* (see Sect. 4 in RFC 7627). */
unsigned char const *salt = handshake->randbytes;
size_t salt_len = 64;
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
mbedtls_md_type_t const md_type = ciphersuite_info->mac;
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED )
{ {
unsigned char session_hash[48];
size_t hash_len;
MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) );
lbl = "extended master secret";
salt = session_hash;
ssl->handshake->calc_verify( ssl, session_hash ); ssl->handshake->calc_verify( ssl, session_hash );
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{ {
#if defined(MBEDTLS_SHA512_C) #if defined(MBEDTLS_SHA512_C)
if( ssl->transform_negotiate->ciphersuite_info->mac == if( md_type == MBEDTLS_MD_SHA384 )
MBEDTLS_MD_SHA384 ) salt_len = 48;
{
hash_len = 48;
}
else else
#endif #endif /* MBEDTLS_SHA512_C */
hash_len = 32; salt_len = 32;
} }
else else
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
hash_len = 36; salt_len = 36;
MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, hash_len ); MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, salt_len );
}
#endif /* MBEDTLS_SSL_EXTENDED_MS_ENABLED */
ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, #if defined(MBEDTLS_USE_PSA_CRYPTO) && \
"extended master secret", defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
session_hash, hash_len, if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK &&
session->master, 48 ); ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 &&
if( ret != 0 ) ssl_use_opaque_psk( ssl ) == 1 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); /* Perform PSK-to-MS expansion in a single step. */
return( ret ); psa_status_t status;
psa_algorithm_t alg;
psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
psa_key_slot_t psk;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "perform PSA-based PSK-to-MS expansion" ) );
psk = ssl->conf->psk_opaque;
if( ssl->handshake->psk_opaque != 0 )
psk = ssl->handshake->psk_opaque;
if( md_type == MBEDTLS_MD_SHA384 )
alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384);
else
alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256);
status = psa_key_derivation( &generator, psk, alg,
salt, salt_len,
(unsigned char const *) lbl,
(size_t) strlen( lbl ),
master_secret_len );
if( status != PSA_SUCCESS )
{
psa_generator_abort( &generator );
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
} }
status = psa_generator_read( &generator, session->master,
master_secret_len );
if( status != PSA_SUCCESS )
{
psa_generator_abort( &generator );
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
}
status = psa_generator_abort( &generator );
if( status != PSA_SUCCESS )
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
} }
else else
#endif #endif
{
ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, ret = handshake->tls_prf( handshake->premaster, handshake->pmslen,
"master secret", lbl, salt, salt_len,
handshake->randbytes, 64, session->master,
session->master, 48 ); master_secret_len );
if( ret != 0 ) if( ret != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret );
return( ret ); return( ret );
} }
MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret",
handshake->premaster,
handshake->pmslen );
mbedtls_platform_zeroize( handshake->premaster, mbedtls_platform_zeroize( handshake->premaster,
sizeof(handshake->premaster) ); sizeof(handshake->premaster) );
} }
else }
MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) );
/* /*
* Swap the client and server random values. * Swap the client and server random values.
@ -807,7 +903,7 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
cipher_info->mode == MBEDTLS_MODE_CCM || cipher_info->mode == MBEDTLS_MODE_CCM ||
cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY ) cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY )
{ {
size_t taglen, explicit_ivlen; size_t explicit_ivlen;
transform->maclen = 0; transform->maclen = 0;
mac_key_len = 0; mac_key_len = 0;
@ -1027,6 +1123,43 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
} }
#endif #endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Only use PSA-based ciphers for TLS-1.2.
* That's relevant at least for TLS-1.0, where
* we assume that mbedtls_cipher_crypt() updates
* the structure field for the IV, which the PSA-based
* implementation currently doesn't. */
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{
ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_enc,
cipher_info, taglen );
if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret );
return( ret );
}
if( ret == 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Successfully setup PSA-based encryption cipher context" ) );
psa_fallthrough = 0;
}
else
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record encryption - fall through to default setup." ) );
psa_fallthrough = 1;
}
}
else
psa_fallthrough = 1;
#else
psa_fallthrough = 1;
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
if( psa_fallthrough == 1 )
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc, if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc,
cipher_info ) ) != 0 ) cipher_info ) ) != 0 )
{ {
@ -1034,6 +1167,42 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
return( ret ); return( ret );
} }
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Only use PSA-based ciphers for TLS-1.2.
* That's relevant at least for TLS-1.0, where
* we assume that mbedtls_cipher_crypt() updates
* the structure field for the IV, which the PSA-based
* implementation currently doesn't. */
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{
ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_dec,
cipher_info, taglen );
if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret );
return( ret );
}
if( ret == 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Successfully setup PSA-based decryption cipher context" ) );
psa_fallthrough = 0;
}
else
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record decryption - fall through to default setup." ) );
psa_fallthrough = 1;
}
}
else
psa_fallthrough = 1;
#else
psa_fallthrough = 1;
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
if( psa_fallthrough == 1 )
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec, if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec,
cipher_info ) ) != 0 ) cipher_info ) ) != 0 )
{ {
@ -2304,13 +2473,13 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
correct = 0; correct = 0;
} }
auth_done++; auth_done++;
}
/* /*
* Finally check the correct flag * Finally check the correct flag
*/ */
if( correct == 0 ) if( correct == 0 )
return( MBEDTLS_ERR_SSL_INVALID_MAC ); return( MBEDTLS_ERR_SSL_INVALID_MAC );
}
#endif /* SSL_SOME_MODES_USE_MAC */ #endif /* SSL_SOME_MODES_USE_MAC */
/* Make extra sure authentication was performed, exactly once */ /* Make extra sure authentication was performed, exactly once */
@ -5429,60 +5598,16 @@ write_msg:
return( ret ); return( ret );
} }
int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) /*
* Once the certificate message is read, parse it into a cert chain and
* perform basic checks, but leave actual verification to the caller
*/
static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl )
{ {
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; int ret;
size_t i, n; size_t i, n;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
int authmode = ssl->conf->authmode;
uint8_t alert; uint8_t alert;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
ssl->state++;
return( 0 );
}
#if defined(MBEDTLS_SSL_SRV_C)
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
ssl->state++;
return( 0 );
}
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET )
authmode = ssl->handshake->sni_authmode;
#endif
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
authmode == MBEDTLS_SSL_VERIFY_NONE )
{
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
ssl->state++;
return( 0 );
}
#endif
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
/* mbedtls_ssl_read_record may have sent an alert already. We
let it decide whether to alert. */
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
}
ssl->state++;
#if defined(MBEDTLS_SSL_SRV_C) #if defined(MBEDTLS_SSL_SRV_C)
#if defined(MBEDTLS_SSL_PROTO_SSL3) #if defined(MBEDTLS_SSL_PROTO_SSL3)
/* /*
@ -5502,9 +5627,6 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
one. The client should know what's going on, so we one. The client should know what's going on, so we
don't send an alert. */ don't send an alert. */
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
return( 0 );
else
return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
} }
} }
@ -5526,9 +5648,6 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
one. The client should know what's going on, so we one. The client should know what's going on, so we
don't send an alert. */ don't send an alert. */
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
return( 0 );
else
return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
} }
} }
@ -5679,6 +5798,94 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
} }
#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ #endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
return( 0 );
}
int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
{
int ret;
const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
? ssl->handshake->sni_authmode
: ssl->conf->authmode;
#else
const int authmode = ssl->conf->authmode;
#endif
void *rs_ctx = NULL;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
ssl->state++;
return( 0 );
}
#if defined(MBEDTLS_SSL_SRV_C)
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
ssl->state++;
return( 0 );
}
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
authmode == MBEDTLS_SSL_VERIFY_NONE )
{
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
ssl->state++;
return( 0 );
}
#endif
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ssl->handshake->ecrs_enabled &&
ssl->handshake->ecrs_state == ssl_ecrs_crt_verify )
{
goto crt_verify;
}
#endif
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
/* mbedtls_ssl_read_record may have sent an alert already. We
let it decide whether to alert. */
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
return( ret );
}
if( ( ret = ssl_parse_certificate_chain( ssl ) ) != 0 )
{
#if defined(MBEDTLS_SSL_SRV_C)
if( ret == MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE &&
authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
{
ret = 0;
}
#endif
ssl->state++;
return( ret );
}
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ssl->handshake->ecrs_enabled)
ssl->handshake->ecrs_state = ssl_ecrs_crt_verify;
crt_verify:
if( ssl->handshake->ecrs_enabled)
rs_ctx = &ssl->handshake->ecrs_ctx;
#endif
if( authmode != MBEDTLS_SSL_VERIFY_NONE ) if( authmode != MBEDTLS_SSL_VERIFY_NONE )
{ {
mbedtls_x509_crt *ca_chain; mbedtls_x509_crt *ca_chain;
@ -5700,19 +5907,24 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
/* /*
* Main check: verify certificate * Main check: verify certificate
*/ */
ret = mbedtls_x509_crt_verify_with_profile( ret = mbedtls_x509_crt_verify_restartable(
ssl->session_negotiate->peer_cert, ssl->session_negotiate->peer_cert,
ca_chain, ca_crl, ca_chain, ca_crl,
ssl->conf->cert_profile, ssl->conf->cert_profile,
ssl->hostname, ssl->hostname,
&ssl->session_negotiate->verify_result, &ssl->session_negotiate->verify_result,
ssl->conf->f_vrfy, ssl->conf->p_vrfy ); ssl->conf->f_vrfy, ssl->conf->p_vrfy, rs_ctx );
if( ret != 0 ) if( ret != 0 )
{ {
MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
} }
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS );
#endif
/* /*
* Secondary checks: always done, but change 'ret' only if it was 0 * Secondary checks: always done, but change 'ret' only if it was 0
*/ */
@ -5765,6 +5977,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
if( ret != 0 ) if( ret != 0 )
{ {
uint8_t alert;
/* The certificate may have been rejected for several reasons. /* The certificate may have been rejected for several reasons.
Pick one and send the corresponding alert. Which alert to send Pick one and send the corresponding alert. Which alert to send
may be a subject of debate in some cases. */ may be a subject of debate in some cases. */
@ -5807,6 +6021,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_DEBUG_C */ #endif /* MBEDTLS_DEBUG_C */
} }
ssl->state++;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
return( ret ); return( ret );
@ -6584,6 +6800,10 @@ static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake )
#endif #endif
#endif #endif
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
mbedtls_x509_crt_restart_init( &handshake->ecrs_ctx );
#endif
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET;
#endif #endif
@ -7272,23 +7492,23 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf,
const unsigned char *psk, size_t psk_len, static void ssl_conf_remove_psk( mbedtls_ssl_config *conf )
const unsigned char *psk_identity, size_t psk_identity_len )
{ {
if( psk == NULL || psk_identity == NULL ) /* Remove reference to existing PSK, if any. */
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); #if defined(MBEDTLS_USE_PSA_CRYPTO)
if( conf->psk_opaque != 0 )
if( psk_len > MBEDTLS_PSK_MAX_LEN )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
/* Identity len will be encoded on two bytes */
if( ( psk_identity_len >> 16 ) != 0 ||
psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
{ {
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); /* The maintenance of the PSK key slot is the
* user's responsibility. */
conf->psk_opaque = 0;
} }
/* This and the following branch should never
* be taken simultaenously as we maintain the
* invariant that raw and opaque PSKs are never
* configured simultaneously. As a safeguard,
* though, `else` is omitted here. */
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( conf->psk != NULL ) if( conf->psk != NULL )
{ {
mbedtls_platform_zeroize( conf->psk, conf->psk_len ); mbedtls_platform_zeroize( conf->psk, conf->psk_len );
@ -7297,32 +7517,84 @@ int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf,
conf->psk = NULL; conf->psk = NULL;
conf->psk_len = 0; conf->psk_len = 0;
} }
/* Remove reference to PSK identity, if any. */
if( conf->psk_identity != NULL ) if( conf->psk_identity != NULL )
{ {
mbedtls_free( conf->psk_identity ); mbedtls_free( conf->psk_identity );
conf->psk_identity = NULL; conf->psk_identity = NULL;
conf->psk_identity_len = 0; conf->psk_identity_len = 0;
} }
}
if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL || /* This function assumes that PSK identity in the SSL config is unset.
( conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ) ) == NULL ) * It checks that the provided identity is well-formed and attempts
* to make a copy of it in the SSL config.
* On failure, the PSK identity in the config remains unset. */
static int ssl_conf_set_psk_identity( mbedtls_ssl_config *conf,
unsigned char const *psk_identity,
size_t psk_identity_len )
{
/* Identity len will be encoded on two bytes */
if( psk_identity == NULL ||
( psk_identity_len >> 16 ) != 0 ||
psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
{ {
mbedtls_free( conf->psk ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
mbedtls_free( conf->psk_identity );
conf->psk = NULL;
conf->psk_identity = NULL;
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
} }
conf->psk_len = psk_len; conf->psk_identity = mbedtls_calloc( 1, psk_identity_len );
conf->psk_identity_len = psk_identity_len; if( conf->psk_identity == NULL )
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
memcpy( conf->psk, psk, conf->psk_len ); conf->psk_identity_len = psk_identity_len;
memcpy( conf->psk_identity, psk_identity, conf->psk_identity_len ); memcpy( conf->psk_identity, psk_identity, conf->psk_identity_len );
return( 0 ); return( 0 );
} }
int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf,
const unsigned char *psk, size_t psk_len,
const unsigned char *psk_identity, size_t psk_identity_len )
{
int ret;
/* Remove opaque/raw PSK + PSK Identity */
ssl_conf_remove_psk( conf );
/* Check and set raw PSK */
if( psk == NULL || psk_len > MBEDTLS_PSK_MAX_LEN )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL )
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
conf->psk_len = psk_len;
memcpy( conf->psk, psk, conf->psk_len );
/* Check and set PSK Identity */
ret = ssl_conf_set_psk_identity( conf, psk_identity, psk_identity_len );
if( ret != 0 )
ssl_conf_remove_psk( conf );
return( ret );
}
static void ssl_remove_psk( mbedtls_ssl_context *ssl )
{
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ssl->handshake->psk_opaque != 0 )
{
ssl->handshake->psk_opaque = 0;
}
else
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( ssl->handshake->psk != NULL )
{
mbedtls_platform_zeroize( ssl->handshake->psk,
ssl->handshake->psk_len );
mbedtls_free( ssl->handshake->psk );
ssl->handshake->psk_len = 0;
}
}
int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl,
const unsigned char *psk, size_t psk_len ) const unsigned char *psk, size_t psk_len )
{ {
@ -7332,13 +7604,7 @@ int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl,
if( psk_len > MBEDTLS_PSK_MAX_LEN ) if( psk_len > MBEDTLS_PSK_MAX_LEN )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
if( ssl->handshake->psk != NULL ) ssl_remove_psk( ssl );
{
mbedtls_platform_zeroize( ssl->handshake->psk,
ssl->handshake->psk_len );
mbedtls_free( ssl->handshake->psk );
ssl->handshake->psk_len = 0;
}
if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL )
return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
@ -7349,6 +7615,42 @@ int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl,
return( 0 ); return( 0 );
} }
#if defined(MBEDTLS_USE_PSA_CRYPTO)
int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf,
psa_key_slot_t psk_slot,
const unsigned char *psk_identity,
size_t psk_identity_len )
{
int ret;
/* Clear opaque/raw PSK + PSK Identity, if present. */
ssl_conf_remove_psk( conf );
/* Check and set opaque PSK */
if( psk_slot == 0 )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
conf->psk_opaque = psk_slot;
/* Check and set PSK Identity */
ret = ssl_conf_set_psk_identity( conf, psk_identity,
psk_identity_len );
if( ret != 0 )
ssl_conf_remove_psk( conf );
return( ret );
}
int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl,
psa_key_slot_t psk_slot )
{
if( psk_slot == 0 || ssl->handshake == NULL )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
ssl_remove_psk( ssl );
ssl->handshake->psk_opaque = psk_slot;
return( 0 );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf,
int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *,
size_t), size_t),
@ -7905,6 +8207,12 @@ size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_SSL_PROTO_DTLS) #if defined(MBEDTLS_SSL_PROTO_DTLS)
static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl ) static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl )
{ {
/* Return unlimited mtu for client hello messages to avoid fragmentation. */
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
( ssl->state == MBEDTLS_SSL_CLIENT_HELLO ||
ssl->state == MBEDTLS_SSL_SERVER_HELLO ) )
return ( 0 );
if( ssl->handshake == NULL || ssl->handshake->mtu == 0 ) if( ssl->handshake == NULL || ssl->handshake->mtu == 0 )
return( ssl->mtu ); return( ssl->mtu );
@ -8741,6 +9049,7 @@ static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
if( hs_buf->is_valid == 1 ) if( hs_buf->is_valid == 1 )
{ {
hs->buffering.total_bytes_buffered -= hs_buf->data_len; hs->buffering.total_bytes_buffered -= hs_buf->data_len;
mbedtls_platform_zeroize( hs_buf->data, hs_buf->data_len );
mbedtls_free( hs_buf->data ); mbedtls_free( hs_buf->data );
memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
} }
@ -8825,6 +9134,10 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
} }
#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
mbedtls_x509_crt_restart_free( &handshake->ecrs_ctx );
#endif
#if defined(MBEDTLS_SSL_PROTO_DTLS) #if defined(MBEDTLS_SSL_PROTO_DTLS)
mbedtls_free( handshake->verify_cookie ); mbedtls_free( handshake->verify_cookie );
ssl_flight_free( handshake->flight ); ssl_flight_free( handshake->flight );

View File

@ -52,6 +52,7 @@
#include <windows.h> #include <windows.h>
#include <winbase.h> #include <winbase.h>
#include <process.h>
struct _hr_time struct _hr_time
{ {
@ -267,18 +268,17 @@ unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int
/* It's OK to use a global because alarm() is supposed to be global anyway */ /* It's OK to use a global because alarm() is supposed to be global anyway */
static DWORD alarmMs; static DWORD alarmMs;
static DWORD WINAPI TimerProc( LPVOID TimerContext ) static void TimerProc( void *TimerContext )
{ {
((void) TimerContext); (void) TimerContext;
Sleep( alarmMs ); Sleep( alarmMs );
mbedtls_timing_alarmed = 1; mbedtls_timing_alarmed = 1;
return( TRUE ); /* _endthread will be called implicitly on return
* That ensures execution of thread funcition's epilogue */
} }
void mbedtls_set_alarm( int seconds ) void mbedtls_set_alarm( int seconds )
{ {
DWORD ThreadId;
if( seconds == 0 ) if( seconds == 0 )
{ {
/* No need to create a thread for this simple case. /* No need to create a thread for this simple case.
@ -289,7 +289,7 @@ void mbedtls_set_alarm( int seconds )
mbedtls_timing_alarmed = 0; mbedtls_timing_alarmed = 0;
alarmMs = seconds * 1000; alarmMs = seconds * 1000;
CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) ); (void) _beginthread( TimerProc, 0, NULL );
} }
#else /* _WIN32 && !EFIX64 && !EFI32 */ #else /* _WIN32 && !EFIX64 && !EFI32 */

View File

@ -339,6 +339,9 @@ static const char *features[] = {
#if defined(MBEDTLS_ECP_NIST_OPTIM) #if defined(MBEDTLS_ECP_NIST_OPTIM)
"MBEDTLS_ECP_NIST_OPTIM", "MBEDTLS_ECP_NIST_OPTIM",
#endif /* MBEDTLS_ECP_NIST_OPTIM */ #endif /* MBEDTLS_ECP_NIST_OPTIM */
#if defined(MBEDTLS_ECP_RESTARTABLE)
"MBEDTLS_ECP_RESTARTABLE",
#endif /* MBEDTLS_ECP_RESTARTABLE */
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
"MBEDTLS_ECDSA_DETERMINISTIC", "MBEDTLS_ECDSA_DETERMINISTIC",
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
@ -510,6 +513,9 @@ static const char *features[] = {
#if defined(MBEDTLS_THREADING_PTHREAD) #if defined(MBEDTLS_THREADING_PTHREAD)
"MBEDTLS_THREADING_PTHREAD", "MBEDTLS_THREADING_PTHREAD",
#endif /* MBEDTLS_THREADING_PTHREAD */ #endif /* MBEDTLS_THREADING_PTHREAD */
#if defined(MBEDTLS_USE_PSA_CRYPTO)
"MBEDTLS_USE_PSA_CRYPTO",
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_VERSION_FEATURES) #if defined(MBEDTLS_VERSION_FEATURES)
"MBEDTLS_VERSION_FEATURES", "MBEDTLS_VERSION_FEATURES",
#endif /* MBEDTLS_VERSION_FEATURES */ #endif /* MBEDTLS_VERSION_FEATURES */
@ -678,6 +684,9 @@ static const char *features[] = {
#if defined(MBEDTLS_POLY1305_C) #if defined(MBEDTLS_POLY1305_C)
"MBEDTLS_POLY1305_C", "MBEDTLS_POLY1305_C",
#endif /* MBEDTLS_POLY1305_C */ #endif /* MBEDTLS_POLY1305_C */
#if defined(MBEDTLS_PSA_CRYPTO_C)
"MBEDTLS_PSA_CRYPTO_C",
#endif /* MBEDTLS_PSA_CRYPTO_C */
#if defined(MBEDTLS_RIPEMD160_C) #if defined(MBEDTLS_RIPEMD160_C)
"MBEDTLS_RIPEMD160_C", "MBEDTLS_RIPEMD160_C",
#endif /* MBEDTLS_RIPEMD160_C */ #endif /* MBEDTLS_RIPEMD160_C */

View File

@ -33,48 +33,84 @@
#include <string.h> #include <string.h>
/* Structure linking OIDs for X.509 DN AttributeTypes to their
* string representations and default string encodings used by Mbed TLS. */
typedef struct { typedef struct {
const char *name; const char *name; /* String representation of AttributeType, e.g.
size_t name_len; * "CN" or "emailAddress". */
const char*oid; size_t name_len; /* Length of 'name', without trailing 0 byte. */
const char *oid; /* String representation of OID of AttributeType,
* as per RFC 5280, Appendix A.1. */
int default_tag; /* The default character encoding used for the
* given attribute type, e.g.
* MBEDTLS_ASN1_UTF8_STRING for UTF-8. */
} x509_attr_descriptor_t; } x509_attr_descriptor_t;
#define ADD_STRLEN( s ) s, sizeof( s ) - 1 #define ADD_STRLEN( s ) s, sizeof( s ) - 1
/* X.509 DN attributes from RFC 5280, Appendix A.1. */
static const x509_attr_descriptor_t x509_attrs[] = static const x509_attr_descriptor_t x509_attrs[] =
{ {
{ ADD_STRLEN( "CN" ), MBEDTLS_OID_AT_CN }, { ADD_STRLEN( "CN" ),
{ ADD_STRLEN( "commonName" ), MBEDTLS_OID_AT_CN }, MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "C" ), MBEDTLS_OID_AT_COUNTRY }, { ADD_STRLEN( "commonName" ),
{ ADD_STRLEN( "countryName" ), MBEDTLS_OID_AT_COUNTRY }, MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "O" ), MBEDTLS_OID_AT_ORGANIZATION }, { ADD_STRLEN( "C" ),
{ ADD_STRLEN( "organizationName" ), MBEDTLS_OID_AT_ORGANIZATION }, MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING },
{ ADD_STRLEN( "L" ), MBEDTLS_OID_AT_LOCALITY }, { ADD_STRLEN( "countryName" ),
{ ADD_STRLEN( "locality" ), MBEDTLS_OID_AT_LOCALITY }, MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING },
{ ADD_STRLEN( "R" ), MBEDTLS_OID_PKCS9_EMAIL }, { ADD_STRLEN( "O" ),
{ ADD_STRLEN( "OU" ), MBEDTLS_OID_AT_ORG_UNIT }, MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "organizationalUnitName" ), MBEDTLS_OID_AT_ORG_UNIT }, { ADD_STRLEN( "organizationName" ),
{ ADD_STRLEN( "ST" ), MBEDTLS_OID_AT_STATE }, MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "stateOrProvinceName" ), MBEDTLS_OID_AT_STATE }, { ADD_STRLEN( "L" ),
{ ADD_STRLEN( "emailAddress" ), MBEDTLS_OID_PKCS9_EMAIL }, MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "serialNumber" ), MBEDTLS_OID_AT_SERIAL_NUMBER }, { ADD_STRLEN( "locality" ),
{ ADD_STRLEN( "postalAddress" ), MBEDTLS_OID_AT_POSTAL_ADDRESS }, MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "postalCode" ), MBEDTLS_OID_AT_POSTAL_CODE }, { ADD_STRLEN( "R" ),
{ ADD_STRLEN( "dnQualifier" ), MBEDTLS_OID_AT_DN_QUALIFIER }, MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING },
{ ADD_STRLEN( "title" ), MBEDTLS_OID_AT_TITLE }, { ADD_STRLEN( "OU" ),
{ ADD_STRLEN( "surName" ), MBEDTLS_OID_AT_SUR_NAME }, MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "SN" ), MBEDTLS_OID_AT_SUR_NAME }, { ADD_STRLEN( "organizationalUnitName" ),
{ ADD_STRLEN( "givenName" ), MBEDTLS_OID_AT_GIVEN_NAME }, MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "GN" ), MBEDTLS_OID_AT_GIVEN_NAME }, { ADD_STRLEN( "ST" ),
{ ADD_STRLEN( "initials" ), MBEDTLS_OID_AT_INITIALS }, MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "pseudonym" ), MBEDTLS_OID_AT_PSEUDONYM }, { ADD_STRLEN( "stateOrProvinceName" ),
{ ADD_STRLEN( "generationQualifier" ), MBEDTLS_OID_AT_GENERATION_QUALIFIER }, MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "domainComponent" ), MBEDTLS_OID_DOMAIN_COMPONENT }, { ADD_STRLEN( "emailAddress" ),
{ ADD_STRLEN( "DC" ), MBEDTLS_OID_DOMAIN_COMPONENT }, MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING },
{ NULL, 0, NULL } { ADD_STRLEN( "serialNumber" ),
MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING },
{ ADD_STRLEN( "postalAddress" ),
MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING },
{ ADD_STRLEN( "postalCode" ),
MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING },
{ ADD_STRLEN( "dnQualifier" ),
MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING },
{ ADD_STRLEN( "title" ),
MBEDTLS_OID_AT_TITLE, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "surName" ),
MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "SN" ),
MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "givenName" ),
MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "GN" ),
MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "initials" ),
MBEDTLS_OID_AT_INITIALS, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "pseudonym" ),
MBEDTLS_OID_AT_PSEUDONYM, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "generationQualifier" ),
MBEDTLS_OID_AT_GENERATION_QUALIFIER, MBEDTLS_ASN1_UTF8_STRING },
{ ADD_STRLEN( "domainComponent" ),
MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING },
{ ADD_STRLEN( "DC" ),
MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING },
{ NULL, 0, NULL, MBEDTLS_ASN1_NULL }
}; };
static const char *x509_at_oid_from_name( const char *name, size_t name_len ) static const x509_attr_descriptor_t *x509_attr_descr_from_name( const char *name, size_t name_len )
{ {
const x509_attr_descriptor_t *cur; const x509_attr_descriptor_t *cur;
@ -83,7 +119,10 @@ static const char *x509_at_oid_from_name( const char *name, size_t name_len )
strncmp( cur->name, name, name_len ) == 0 ) strncmp( cur->name, name, name_len ) == 0 )
break; break;
return( cur->oid ); if ( cur->name == NULL )
return( NULL );
return( cur );
} }
int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ) int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name )
@ -92,6 +131,7 @@ int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *na
const char *s = name, *c = s; const char *s = name, *c = s;
const char *end = s + strlen( s ); const char *end = s + strlen( s );
const char *oid = NULL; const char *oid = NULL;
const x509_attr_descriptor_t* attr_descr = NULL;
int in_tag = 1; int in_tag = 1;
char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; char data[MBEDTLS_X509_MAX_DN_NAME_SIZE];
char *d = data; char *d = data;
@ -103,12 +143,13 @@ int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *na
{ {
if( in_tag && *c == '=' ) if( in_tag && *c == '=' )
{ {
if( ( oid = x509_at_oid_from_name( s, c - s ) ) == NULL ) if( ( attr_descr = x509_attr_descr_from_name( s, c - s ) ) == NULL )
{ {
ret = MBEDTLS_ERR_X509_UNKNOWN_OID; ret = MBEDTLS_ERR_X509_UNKNOWN_OID;
goto exit; goto exit;
} }
oid = attr_descr->oid;
s = c + 1; s = c + 1;
in_tag = 0; in_tag = 0;
d = data; d = data;
@ -127,13 +168,19 @@ int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *na
} }
else if( !in_tag && ( *c == ',' || c == end ) ) else if( !in_tag && ( *c == ',' || c == end ) )
{ {
if( mbedtls_asn1_store_named_data( head, oid, strlen( oid ), mbedtls_asn1_named_data* cur =
mbedtls_asn1_store_named_data( head, oid, strlen( oid ),
(unsigned char *) data, (unsigned char *) data,
d - data ) == NULL ) d - data );
if(cur == NULL )
{ {
return( MBEDTLS_ERR_X509_ALLOC_FAILED ); return( MBEDTLS_ERR_X509_ALLOC_FAILED );
} }
// set tagType
cur->val.tag = attr_descr->default_tag;
while( c < end && *(c + 1) == ' ' ) while( c < end && *(c + 1) == ' ' )
c++; c++;
@ -192,39 +239,33 @@ int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid,
* *
* AttributeValue ::= ANY DEFINED BY AttributeType * AttributeValue ::= ANY DEFINED BY AttributeType
*/ */
static int x509_write_name( unsigned char **p, unsigned char *start, static int x509_write_name( unsigned char **p, unsigned char *start, mbedtls_asn1_named_data* cur_name)
const char *oid, size_t oid_len,
const unsigned char *name, size_t name_len )
{ {
int ret; int ret;
size_t len = 0; size_t len = 0;
const char *oid = (const char*)cur_name->oid.p;
size_t oid_len = cur_name->oid.len;
const unsigned char *name = cur_name->val.p;
size_t name_len = cur_name->val.len;
// Write PrintableString for all except MBEDTLS_OID_PKCS9_EMAIL // Write correct string tag and value
// MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tagged_string( p, start,
if( MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_EMAIL ) == oid_len && cur_name->val.tag,
memcmp( oid, MBEDTLS_OID_PKCS9_EMAIL, oid_len ) == 0 )
{
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_ia5_string( p, start,
(const char *) name, (const char *) name,
name_len ) ); name_len ) );
}
else
{
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_printable_string( p, start,
(const char *) name,
name_len ) );
}
// Write OID // Write OID
// //
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid,
oid_len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE ) ); MBEDTLS_ASN1_SEQUENCE ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SET ) ); MBEDTLS_ASN1_SET ) );
return( (int) len ); return( (int) len );
@ -239,9 +280,7 @@ int mbedtls_x509_write_names( unsigned char **p, unsigned char *start,
while( cur != NULL ) while( cur != NULL )
{ {
MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p, MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, cur ) );
cur->oid.len,
cur->val.p, cur->val.len ) );
cur = cur->next; cur = cur->next;
} }

View File

@ -43,16 +43,21 @@
#include "mbedtls/oid.h" #include "mbedtls/oid.h"
#include "mbedtls/platform_util.h" #include "mbedtls/platform_util.h"
#include <stdio.h>
#include <string.h> #include <string.h>
#if defined(MBEDTLS_PEM_PARSE_C) #if defined(MBEDTLS_PEM_PARSE_C)
#include "mbedtls/pem.h" #include "mbedtls/pem.h"
#endif #endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#include "mbedtls/psa_util.h"
#endif
#if defined(MBEDTLS_PLATFORM_C) #if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#else #else
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#define mbedtls_free free #define mbedtls_free free
#define mbedtls_calloc calloc #define mbedtls_calloc calloc
@ -227,6 +232,153 @@ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile,
return( -1 ); return( -1 );
} }
/*
* Like memcmp, but case-insensitive and always returns -1 if different
*/
static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
{
size_t i;
unsigned char diff;
const unsigned char *n1 = s1, *n2 = s2;
for( i = 0; i < len; i++ )
{
diff = n1[i] ^ n2[i];
if( diff == 0 )
continue;
if( diff == 32 &&
( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
{
continue;
}
return( -1 );
}
return( 0 );
}
/*
* Return 0 if name matches wildcard, -1 otherwise
*/
static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name )
{
size_t i;
size_t cn_idx = 0, cn_len = strlen( cn );
/* We can't have a match if there is no wildcard to match */
if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
return( -1 );
for( i = 0; i < cn_len; ++i )
{
if( cn[i] == '.' )
{
cn_idx = i;
break;
}
}
if( cn_idx == 0 )
return( -1 );
if( cn_len - cn_idx == name->len - 1 &&
x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
{
return( 0 );
}
return( -1 );
}
/*
* Compare two X.509 strings, case-insensitive, and allowing for some encoding
* variations (but not all).
*
* Return 0 if equal, -1 otherwise.
*/
static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
{
if( a->tag == b->tag &&
a->len == b->len &&
memcmp( a->p, b->p, b->len ) == 0 )
{
return( 0 );
}
if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
a->len == b->len &&
x509_memcasecmp( a->p, b->p, b->len ) == 0 )
{
return( 0 );
}
return( -1 );
}
/*
* Compare two X.509 Names (aka rdnSequence).
*
* See RFC 5280 section 7.1, though we don't implement the whole algorithm:
* we sometimes return unequal when the full algorithm would return equal,
* but never the other way. (In particular, we don't do Unicode normalisation
* or space folding.)
*
* Return 0 if equal, -1 otherwise.
*/
static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
{
/* Avoid recursion, it might not be optimised by the compiler */
while( a != NULL || b != NULL )
{
if( a == NULL || b == NULL )
return( -1 );
/* type */
if( a->oid.tag != b->oid.tag ||
a->oid.len != b->oid.len ||
memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
{
return( -1 );
}
/* value */
if( x509_string_cmp( &a->val, &b->val ) != 0 )
return( -1 );
/* structure of the list of sets */
if( a->next_merged != b->next_merged )
return( -1 );
a = a->next;
b = b->next;
}
/* a == NULL == b */
return( 0 );
}
/*
* Reset (init or clear) a verify_chain
*/
static void x509_crt_verify_chain_reset(
mbedtls_x509_crt_verify_chain *ver_chain )
{
size_t i;
for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ )
{
ver_chain->items[i].crt = NULL;
ver_chain->items[i].flags = -1;
}
ver_chain->len = 0;
}
/* /*
* Version ::= INTEGER { v1(0), v2(1), v3(2) } * Version ::= INTEGER { v1(0), v2(1), v3(2) }
*/ */
@ -1667,9 +1819,7 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
while( crl_list != NULL ) while( crl_list != NULL )
{ {
if( crl_list->version == 0 || if( crl_list->version == 0 ||
crl_list->issuer_raw.len != ca->subject_raw.len || x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 )
memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
crl_list->issuer_raw.len ) != 0 )
{ {
crl_list = crl_list->next; crl_list = crl_list->next;
continue; continue;
@ -1679,7 +1829,8 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
* Check if the CA is configured to sign CRLs * Check if the CA is configured to sign CRLs
*/ */
#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) if( mbedtls_x509_crt_check_key_usage( ca,
MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
{ {
flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
break; break;
@ -1739,160 +1890,60 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
} }
#endif /* MBEDTLS_X509_CRL_PARSE_C */ #endif /* MBEDTLS_X509_CRL_PARSE_C */
/*
* Like memcmp, but case-insensitive and always returns -1 if different
*/
static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
{
size_t i;
unsigned char diff;
const unsigned char *n1 = s1, *n2 = s2;
for( i = 0; i < len; i++ )
{
diff = n1[i] ^ n2[i];
if( diff == 0 )
continue;
if( diff == 32 &&
( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
{
continue;
}
return( -1 );
}
return( 0 );
}
/*
* Return 0 if name matches wildcard, -1 otherwise
*/
static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name )
{
size_t i;
size_t cn_idx = 0, cn_len = strlen( cn );
/* We can't have a match if there is no wildcard to match */
if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
return( -1 );
for( i = 0; i < cn_len; ++i )
{
if( cn[i] == '.' )
{
cn_idx = i;
break;
}
}
if( cn_idx == 0 )
return( -1 );
if( cn_len - cn_idx == name->len - 1 &&
x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
{
return( 0 );
}
return( -1 );
}
/*
* Compare two X.509 strings, case-insensitive, and allowing for some encoding
* variations (but not all).
*
* Return 0 if equal, -1 otherwise.
*/
static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
{
if( a->tag == b->tag &&
a->len == b->len &&
memcmp( a->p, b->p, b->len ) == 0 )
{
return( 0 );
}
if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
a->len == b->len &&
x509_memcasecmp( a->p, b->p, b->len ) == 0 )
{
return( 0 );
}
return( -1 );
}
/*
* Compare two X.509 Names (aka rdnSequence).
*
* See RFC 5280 section 7.1, though we don't implement the whole algorithm:
* we sometimes return unequal when the full algorithm would return equal,
* but never the other way. (In particular, we don't do Unicode normalisation
* or space folding.)
*
* Return 0 if equal, -1 otherwise.
*/
static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
{
/* Avoid recursion, it might not be optimised by the compiler */
while( a != NULL || b != NULL )
{
if( a == NULL || b == NULL )
return( -1 );
/* type */
if( a->oid.tag != b->oid.tag ||
a->oid.len != b->oid.len ||
memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
{
return( -1 );
}
/* value */
if( x509_string_cmp( &a->val, &b->val ) != 0 )
return( -1 );
/* structure of the list of sets */
if( a->next_merged != b->next_merged )
return( -1 );
a = a->next;
b = b->next;
}
/* a == NULL == b */
return( 0 );
}
/* /*
* Check the signature of a certificate by its parent * Check the signature of a certificate by its parent
*/ */
static int x509_crt_check_signature( const mbedtls_x509_crt *child, static int x509_crt_check_signature( const mbedtls_x509_crt *child,
mbedtls_x509_crt *parent ) mbedtls_x509_crt *parent,
mbedtls_x509_crt_restart_ctx *rs_ctx )
{ {
const mbedtls_md_info_t *md_info;
unsigned char hash[MBEDTLS_MD_MAX_SIZE]; unsigned char hash[MBEDTLS_MD_MAX_SIZE];
size_t hash_len;
#if !defined(MBEDTLS_USE_PSA_CRYPTO)
const mbedtls_md_info_t *md_info;
md_info = mbedtls_md_info_from_type( child->sig_md ); md_info = mbedtls_md_info_from_type( child->sig_md );
hash_len = mbedtls_md_get_size( md_info );
/* Note: hash errors can happen only after an internal error */
if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 ) if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 )
{
/* Note: this can't happen except after an internal error */
return( -1 ); return( -1 );
} #else
psa_hash_operation_t hash_operation;
psa_algorithm_t hash_alg = mbedtls_psa_translate_md( child->sig_md );
if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, if( psa_hash_setup( &hash_operation, hash_alg ) != PSA_SUCCESS )
child->sig_md, hash, mbedtls_md_get_size( md_info ), return( -1 );
child->sig.p, child->sig.len ) != 0 )
if( psa_hash_update( &hash_operation, child->tbs.p, child->tbs.len )
!= PSA_SUCCESS )
{ {
return( -1 ); return( -1 );
} }
return( 0 ); if( psa_hash_finish( &hash_operation, hash, sizeof( hash ), &hash_len )
!= PSA_SUCCESS )
{
return( -1 );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/* Skip expensive computation on obvious mismatch */
if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) )
return( -1 );
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA )
{
return( mbedtls_pk_verify_restartable( &parent->pk,
child->sig_md, hash, hash_len,
child->sig.p, child->sig.len, &rs_ctx->pk ) );
}
#else
(void) rs_ctx;
#endif
return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
child->sig_md, hash, hash_len,
child->sig.p, child->sig.len ) );
} }
/* /*
@ -1939,6 +1990,7 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child,
* 1. subject name matches child's issuer * 1. subject name matches child's issuer
* 2. if necessary, the CA bit is set and key usage allows signing certs * 2. if necessary, the CA bit is set and key usage allows signing certs
* 3. for trusted roots, the signature is correct * 3. for trusted roots, the signature is correct
* (for intermediates, the signature is checked and the result reported)
* 4. pathlen constraints are satisfied * 4. pathlen constraints are satisfied
* *
* If there's a suitable candidate which is also time-valid, return the first * If there's a suitable candidate which is also time-valid, return the first
@ -1961,23 +2013,54 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child,
* Arguments: * Arguments:
* - [in] child: certificate for which we're looking for a parent * - [in] child: certificate for which we're looking for a parent
* - [in] candidates: chained list of potential parents * - [in] candidates: chained list of potential parents
* - [out] r_parent: parent found (or NULL)
* - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0
* - [in] top: 1 if candidates consists of trusted roots, ie we're at the top * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top
* of the chain, 0 otherwise * of the chain, 0 otherwise
* - [in] path_cnt: number of intermediates seen so far * - [in] path_cnt: number of intermediates seen so far
* - [in] self_cnt: number of self-signed intermediates seen so far * - [in] self_cnt: number of self-signed intermediates seen so far
* (will never be greater than path_cnt) * (will never be greater than path_cnt)
* - [in-out] rs_ctx: context for restarting operations
* *
* Return value: * Return value:
* - the first suitable parent found (see above regarding time-validity) * - 0 on success
* - NULL if no suitable parent was found * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
*/ */
static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child, static int x509_crt_find_parent_in(
mbedtls_x509_crt *child,
mbedtls_x509_crt *candidates, mbedtls_x509_crt *candidates,
mbedtls_x509_crt **r_parent,
int *r_signature_is_good,
int top, int top,
size_t path_cnt, unsigned path_cnt,
size_t self_cnt ) unsigned self_cnt,
mbedtls_x509_crt_restart_ctx *rs_ctx )
{ {
mbedtls_x509_crt *parent, *badtime_parent = NULL; int ret;
mbedtls_x509_crt *parent, *fallback_parent;
int signature_is_good, fallback_signature_is_good;
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/* did we have something in progress? */
if( rs_ctx != NULL && rs_ctx->parent != NULL )
{
/* restore saved state */
parent = rs_ctx->parent;
fallback_parent = rs_ctx->fallback_parent;
fallback_signature_is_good = rs_ctx->fallback_signature_is_good;
/* clear saved state */
rs_ctx->parent = NULL;
rs_ctx->fallback_parent = NULL;
rs_ctx->fallback_signature_is_good = 0;
/* resume where we left */
goto check_signature;
}
#endif
fallback_parent = NULL;
fallback_signature_is_good = 0;
for( parent = candidates; parent != NULL; parent = parent->next ) for( parent = candidates; parent != NULL; parent = parent->next )
{ {
@ -1993,17 +2076,38 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
} }
/* Signature */ /* Signature */
if( top && x509_crt_check_signature( child, parent ) != 0 ) #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
check_signature:
#endif
ret = x509_crt_check_signature( child, parent, rs_ctx );
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
{ {
continue; /* save state */
rs_ctx->parent = parent;
rs_ctx->fallback_parent = fallback_parent;
rs_ctx->fallback_signature_is_good = fallback_signature_is_good;
return( ret );
} }
#else
(void) ret;
#endif
signature_is_good = ret == 0;
if( top && ! signature_is_good )
continue;
/* optional time check */ /* optional time check */
if( mbedtls_x509_time_is_past( &parent->valid_to ) || if( mbedtls_x509_time_is_past( &parent->valid_to ) ||
mbedtls_x509_time_is_future( &parent->valid_from ) ) mbedtls_x509_time_is_future( &parent->valid_from ) )
{ {
if( badtime_parent == NULL ) if( fallback_parent == NULL )
badtime_parent = parent; {
fallback_parent = parent;
fallback_signature_is_good = signature_is_good;
}
continue; continue;
} }
@ -2011,10 +2115,18 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
break; break;
} }
if( parent == NULL ) if( parent != NULL )
parent = badtime_parent; {
*r_parent = parent;
*r_signature_is_good = signature_is_good;
}
else
{
*r_parent = fallback_parent;
*r_signature_is_good = fallback_signature_is_good;
}
return( parent ); return( 0 );
} }
/* /*
@ -2026,34 +2138,78 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child,
* Arguments: * Arguments:
* - [in] child: certificate for which we're looking for a parent, followed * - [in] child: certificate for which we're looking for a parent, followed
* by a chain of possible intermediates * by a chain of possible intermediates
* - [in] trust_ca: locally trusted CAs * - [in] trust_ca: list of locally trusted certificates
* - [out] 1 if parent was found in trust_ca, 0 if found in provided chain * - [out] parent: parent found (or NULL)
* - [in] path_cnt: number of intermediates seen so far * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0
* - [in] self_cnt: number of self-signed intermediates seen so far * - [out] signature_is_good: 1 if child signature by parent is valid, or 0
* - [in] path_cnt: number of links in the chain so far (EE -> ... -> child)
* - [in] self_cnt: number of self-signed certs in the chain so far
* (will always be no greater than path_cnt) * (will always be no greater than path_cnt)
* - [in-out] rs_ctx: context for restarting operations
* *
* Return value: * Return value:
* - the first suitable parent found (see find_parent_in() for "suitable") * - 0 on success
* - NULL if no suitable parent was found * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise
*/ */
static mbedtls_x509_crt *x509_crt_find_parent( mbedtls_x509_crt *child, static int x509_crt_find_parent(
mbedtls_x509_crt *child,
mbedtls_x509_crt *trust_ca, mbedtls_x509_crt *trust_ca,
mbedtls_x509_crt **parent,
int *parent_is_trusted, int *parent_is_trusted,
size_t path_cnt, int *signature_is_good,
size_t self_cnt ) unsigned path_cnt,
unsigned self_cnt,
mbedtls_x509_crt_restart_ctx *rs_ctx )
{ {
mbedtls_x509_crt *parent; int ret;
mbedtls_x509_crt *search_list;
/* Look for a parent in trusted CAs */
*parent_is_trusted = 1; *parent_is_trusted = 1;
parent = x509_crt_find_parent_in( child, trust_ca, 1, path_cnt, self_cnt );
if( parent != NULL ) #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
return( parent ); /* restore then clear saved state if we have some stored */
if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 )
{
*parent_is_trusted = rs_ctx->parent_is_trusted;
rs_ctx->parent_is_trusted = -1;
}
#endif
/* Look for a parent upwards the chain */ while( 1 ) {
search_list = *parent_is_trusted ? trust_ca : child->next;
ret = x509_crt_find_parent_in( child, search_list,
parent, signature_is_good,
*parent_is_trusted,
path_cnt, self_cnt, rs_ctx );
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
{
/* save state */
rs_ctx->parent_is_trusted = *parent_is_trusted;
return( ret );
}
#else
(void) ret;
#endif
/* stop here if found or already in second iteration */
if( *parent != NULL || *parent_is_trusted == 0 )
break;
/* prepare second iteration */
*parent_is_trusted = 0; *parent_is_trusted = 0;
return( x509_crt_find_parent_in( child, child->next, 0, path_cnt, self_cnt ) ); }
/* extra precaution against mistakes in the caller */
if( parent == NULL )
{
*parent_is_trusted = 0;
*signature_is_good = 0;
}
return( 0 );
} }
/* /*
@ -2102,11 +2258,24 @@ static int x509_crt_check_ee_locally_trusted(
* - EE, Ci1, ..., Ciq cannot be continued with a trusted root * - EE, Ci1, ..., Ciq cannot be continued with a trusted root
* -> return that chain with NOT_TRUSTED set on Ciq * -> return that chain with NOT_TRUSTED set on Ciq
* *
* Tests for (aspects of) this function should include at least:
* - trusted EE
* - EE -> trusted root
* - EE -> intermedate CA -> trusted root
* - if relevant: EE untrusted
* - if relevant: EE -> intermediate, untrusted
* with the aspect under test checked at each relevant level (EE, int, root).
* For some aspects longer chains are required, but usually length 2 is
* enough (but length 1 is not in general).
*
* Arguments: * Arguments:
* - [in] crt: the cert list EE, C1, ..., Cn * - [in] crt: the cert list EE, C1, ..., Cn
* - [in] trust_ca: the trusted list R1, ..., Rp * - [in] trust_ca: the trusted list R1, ..., Rp
* - [in] ca_crl, profile: as in verify_with_profile() * - [in] ca_crl, profile: as in verify_with_profile()
* - [out] ver_chain, chain_len: the built and verified chain * - [out] ver_chain: the built and verified chain
* Only valid when return value is 0, may contain garbage otherwise!
* Restart note: need not be the same when calling again to resume.
* - [in-out] rs_ctx: context for restarting operations
* *
* Return value: * Return value:
* - non-zero if the chain could not be fully built and examined * - non-zero if the chain could not be fully built and examined
@ -2118,24 +2287,50 @@ static int x509_crt_verify_chain(
mbedtls_x509_crt *trust_ca, mbedtls_x509_crt *trust_ca,
mbedtls_x509_crl *ca_crl, mbedtls_x509_crl *ca_crl,
const mbedtls_x509_crt_profile *profile, const mbedtls_x509_crt_profile *profile,
x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE], mbedtls_x509_crt_verify_chain *ver_chain,
size_t *chain_len ) mbedtls_x509_crt_restart_ctx *rs_ctx )
{ {
/* Don't initialize any of those variables here, so that the compiler can
* catch potential issues with jumping ahead when restarting */
int ret;
uint32_t *flags; uint32_t *flags;
mbedtls_x509_crt_verify_chain_item *cur;
mbedtls_x509_crt *child; mbedtls_x509_crt *child;
mbedtls_x509_crt *parent; mbedtls_x509_crt *parent;
int parent_is_trusted = 0; int parent_is_trusted;
int child_is_trusted = 0; int child_is_trusted;
size_t self_cnt = 0; int signature_is_good;
unsigned self_cnt;
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/* resume if we had an operation in progress */
if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent )
{
/* restore saved state */
*ver_chain = rs_ctx->ver_chain; /* struct copy */
self_cnt = rs_ctx->self_cnt;
/* restore derived state */
cur = &ver_chain->items[ver_chain->len - 1];
child = cur->crt;
flags = &cur->flags;
goto find_parent;
}
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
child = crt; child = crt;
*chain_len = 0; self_cnt = 0;
parent_is_trusted = 0;
child_is_trusted = 0;
while( 1 ) { while( 1 ) {
/* Add certificate to the verification chain */ /* Add certificate to the verification chain */
ver_chain[*chain_len].crt = child; cur = &ver_chain->items[ver_chain->len];
flags = &ver_chain[*chain_len].flags; cur->crt = child;
++*chain_len; cur->flags = 0;
ver_chain->len++;
flags = &cur->flags;
/* Check time-validity (all certificates) */ /* Check time-validity (all certificates) */
if( mbedtls_x509_time_is_past( &child->valid_to ) ) if( mbedtls_x509_time_is_past( &child->valid_to ) )
@ -2156,15 +2351,33 @@ static int x509_crt_verify_chain(
*flags |= MBEDTLS_X509_BADCERT_BAD_PK; *flags |= MBEDTLS_X509_BADCERT_BAD_PK;
/* Special case: EE certs that are locally trusted */ /* Special case: EE certs that are locally trusted */
if( *chain_len == 1 && if( ver_chain->len == 1 &&
x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 ) x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 )
{ {
return( 0 ); return( 0 );
} }
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
find_parent:
#endif
/* Look for a parent in trusted CAs or up the chain */ /* Look for a parent in trusted CAs or up the chain */
parent = x509_crt_find_parent( child, trust_ca, &parent_is_trusted, ret = x509_crt_find_parent( child, trust_ca, &parent,
*chain_len - 1, self_cnt ); &parent_is_trusted, &signature_is_good,
ver_chain->len - 1, self_cnt, rs_ctx );
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
{
/* save state */
rs_ctx->in_progress = x509_crt_rs_find_parent;
rs_ctx->self_cnt = self_cnt;
rs_ctx->ver_chain = *ver_chain; /* struct copy */
return( ret );
}
#else
(void) ret;
#endif
/* No parent? We're done here */ /* No parent? We're done here */
if( parent == NULL ) if( parent == NULL )
@ -2176,7 +2389,7 @@ static int x509_crt_verify_chain(
/* Count intermediate self-issued (not necessarily self-signed) certs. /* Count intermediate self-issued (not necessarily self-signed) certs.
* These can occur with some strategies for key rollover, see [SIRO], * These can occur with some strategies for key rollover, see [SIRO],
* and should be excluded from max_pathlen checks. */ * and should be excluded from max_pathlen checks. */
if( *chain_len != 1 && if( ver_chain->len != 1 &&
x509_name_cmp( &child->issuer, &child->subject ) == 0 ) x509_name_cmp( &child->issuer, &child->subject ) == 0 )
{ {
self_cnt++; self_cnt++;
@ -2185,14 +2398,14 @@ static int x509_crt_verify_chain(
/* path_cnt is 0 for the first intermediate CA, /* path_cnt is 0 for the first intermediate CA,
* and if parent is trusted it's not an intermediate CA */ * and if parent is trusted it's not an intermediate CA */
if( ! parent_is_trusted && if( ! parent_is_trusted &&
*chain_len > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA )
{ {
/* return immediately to avoid overflow the chain array */ /* return immediately to avoid overflow the chain array */
return( MBEDTLS_ERR_X509_FATAL_ERROR ); return( MBEDTLS_ERR_X509_FATAL_ERROR );
} }
/* if parent is trusted, the signature was checked by find_parent() */ /* signature was checked while searching parent */
if( ! parent_is_trusted && x509_crt_check_signature( child, parent ) != 0 ) if( ! signature_is_good )
*flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
/* check size of signing key */ /* check size of signing key */
@ -2210,6 +2423,7 @@ static int x509_crt_verify_chain(
child = parent; child = parent;
parent = NULL; parent = NULL;
child_is_trusted = parent_is_trusted; child_is_trusted = parent_is_trusted;
signature_is_good = 0;
} }
} }
@ -2278,21 +2492,22 @@ static void x509_crt_verify_name( const mbedtls_x509_crt *crt,
*/ */
static int x509_crt_merge_flags_with_cb( static int x509_crt_merge_flags_with_cb(
uint32_t *flags, uint32_t *flags,
x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE], const mbedtls_x509_crt_verify_chain *ver_chain,
size_t chain_len,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
void *p_vrfy ) void *p_vrfy )
{ {
int ret; int ret;
size_t i; unsigned i;
uint32_t cur_flags; uint32_t cur_flags;
const mbedtls_x509_crt_verify_chain_item *cur;
for( i = chain_len; i != 0; --i ) for( i = ver_chain->len; i != 0; --i )
{ {
cur_flags = ver_chain[i-1].flags; cur = &ver_chain->items[i-1];
cur_flags = cur->flags;
if( NULL != f_vrfy ) if( NULL != f_vrfy )
if( ( ret = f_vrfy( p_vrfy, ver_chain[i-1].crt, (int) i-1, &cur_flags ) ) != 0 ) if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 )
return( ret ); return( ret );
*flags |= cur_flags; *flags |= cur_flags;
@ -2302,7 +2517,7 @@ static int x509_crt_merge_flags_with_cb(
} }
/* /*
* Verify the certificate validity * Verify the certificate validity (default profile, not restartable)
*/ */
int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
mbedtls_x509_crt *trust_ca, mbedtls_x509_crt *trust_ca,
@ -2311,19 +2526,13 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
void *p_vrfy ) void *p_vrfy )
{ {
return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl, return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
&mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) ); &mbedtls_x509_crt_profile_default, cn, flags,
f_vrfy, p_vrfy, NULL ) );
} }
/* /*
* Verify the certificate validity, with profile * Verify the certificate validity (user-chosen profile, not restartable)
*
* This function:
* - checks the requested CN (if any)
* - checks the type and size of the EE cert's key,
* as that isn't done as part of chain building/verification currently
* - builds and verifies the chain
* - then calls the callback and merges the flags
*/ */
int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
mbedtls_x509_crt *trust_ca, mbedtls_x509_crt *trust_ca,
@ -2332,16 +2541,38 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
const char *cn, uint32_t *flags, const char *cn, uint32_t *flags,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
void *p_vrfy ) void *p_vrfy )
{
return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
profile, cn, flags, f_vrfy, p_vrfy, NULL ) );
}
/*
* Verify the certificate validity, with profile, restartable version
*
* This function:
* - checks the requested CN (if any)
* - checks the type and size of the EE cert's key,
* as that isn't done as part of chain building/verification currently
* - builds and verifies the chain
* - then calls the callback and merges the flags
*/
int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
mbedtls_x509_crt *trust_ca,
mbedtls_x509_crl *ca_crl,
const mbedtls_x509_crt_profile *profile,
const char *cn, uint32_t *flags,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
void *p_vrfy,
mbedtls_x509_crt_restart_ctx *rs_ctx )
{ {
int ret; int ret;
mbedtls_pk_type_t pk_type; mbedtls_pk_type_t pk_type;
x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE]; mbedtls_x509_crt_verify_chain ver_chain;
size_t chain_len; uint32_t ee_flags;
uint32_t *ee_flags = &ver_chain[0].flags;
*flags = 0; *flags = 0;
memset( ver_chain, 0, sizeof( ver_chain ) ); ee_flags = 0;
chain_len = 0; x509_crt_verify_chain_reset( &ver_chain );
if( profile == NULL ) if( profile == NULL )
{ {
@ -2351,28 +2582,36 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
/* check name if requested */ /* check name if requested */
if( cn != NULL ) if( cn != NULL )
x509_crt_verify_name( crt, cn, ee_flags ); x509_crt_verify_name( crt, cn, &ee_flags );
/* Check the type and size of the key */ /* Check the type and size of the key */
pk_type = mbedtls_pk_get_type( &crt->pk ); pk_type = mbedtls_pk_get_type( &crt->pk );
if( x509_profile_check_pk_alg( profile, pk_type ) != 0 ) if( x509_profile_check_pk_alg( profile, pk_type ) != 0 )
*ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK;
if( x509_profile_check_key( profile, &crt->pk ) != 0 ) if( x509_profile_check_key( profile, &crt->pk ) != 0 )
*ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
/* Check the chain */ /* Check the chain */
ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile, ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile,
ver_chain, &chain_len ); &ver_chain, rs_ctx );
if( ret != 0 ) if( ret != 0 )
goto exit; goto exit;
/* Merge end-entity flags */
ver_chain.items[0].flags |= ee_flags;
/* Build final flags, calling callback on the way if any */ /* Build final flags, calling callback on the way if any */
ret = x509_crt_merge_flags_with_cb( flags, ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy );
ver_chain, chain_len, f_vrfy, p_vrfy );
exit: exit:
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
mbedtls_x509_crt_restart_free( rs_ctx );
#endif
/* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by
* the SSL module for authmode optional, but non-zero return from the * the SSL module for authmode optional, but non-zero return from the
* callback means a fatal error so it shouldn't be ignored */ * callback means a fatal error so it shouldn't be ignored */
@ -2483,4 +2722,36 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt )
while( cert_cur != NULL ); while( cert_cur != NULL );
} }
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/*
* Initialize a restart context
*/
void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx )
{
mbedtls_pk_restart_init( &ctx->pk );
ctx->parent = NULL;
ctx->fallback_parent = NULL;
ctx->fallback_signature_is_good = 0;
ctx->parent_is_trusted = -1;
ctx->in_progress = x509_crt_rs_none;
ctx->self_cnt = 0;
x509_crt_verify_chain_reset( &ctx->ver_chain );
}
/*
* Free the components of a restart context
*/
void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx )
{
if( ctx == NULL )
return;
mbedtls_pk_restart_free( &ctx->pk );
mbedtls_x509_crt_restart_init( ctx );
}
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
#endif /* MBEDTLS_X509_CRT_PARSE_C */ #endif /* MBEDTLS_X509_CRT_PARSE_C */

View File

@ -37,6 +37,11 @@
#include "mbedtls/asn1write.h" #include "mbedtls/asn1write.h"
#include "mbedtls/platform_util.h" #include "mbedtls/platform_util.h"
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#include "mbedtls/psa_util.h"
#endif
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -136,7 +141,11 @@ int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, s
size_t pub_len = 0, sig_and_oid_len = 0, sig_len; size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
size_t len = 0; size_t len = 0;
mbedtls_pk_type_t pk_alg; mbedtls_pk_type_t pk_alg;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
psa_hash_operation_t hash_operation;
size_t hash_len;
psa_algorithm_t hash_alg = mbedtls_psa_translate_md( ctx->md_alg );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/* /*
* Prepare data to be signed in tmp_buf * Prepare data to be signed in tmp_buf
*/ */
@ -187,9 +196,23 @@ int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, s
/* /*
* Prepare signature * Prepare signature
* Note: hash errors can happen only after an internal error
*/ */
mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); #if defined(MBEDTLS_USE_PSA_CRYPTO)
if( psa_hash_setup( &hash_operation, hash_alg ) != PSA_SUCCESS )
return( MBEDTLS_ERR_X509_FATAL_ERROR );
if( psa_hash_update( &hash_operation, c, len ) != PSA_SUCCESS )
return( MBEDTLS_ERR_X509_FATAL_ERROR );
if( psa_hash_finish( &hash_operation, hash, sizeof( hash ), &hash_len )
!= PSA_SUCCESS )
{
return( MBEDTLS_ERR_X509_FATAL_ERROR );
}
#else /* MBEDTLS_USE_PSA_CRYPTO */
mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash );
#endif
if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
f_rng, p_rng ) ) != 0 ) f_rng, p_rng ) ) != 0 )
{ {