From b91fe62c96bdeb392a3083dfd35b0af43e1b0797 Mon Sep 17 00:00:00 2001 From: Darryl Green Date: Fri, 3 Apr 2020 14:09:48 +0100 Subject: [PATCH 1/7] Adjust Mbed TLS importer and config script Mbed Crypto has been remerged back into Mbed TLS. Update the Mbed TLS importer script with the relevant parts of the Mbed Crypto importer. Signed-off-by: Darryl Green --- features/mbedtls/importer/Makefile | 28 +++++++++++++++++++++- features/mbedtls/importer/adjust-config.sh | 2 ++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/features/mbedtls/importer/Makefile b/features/mbedtls/importer/Makefile index 6cb4094014..021db7bb6a 100644 --- a/features/mbedtls/importer/Makefile +++ b/features/mbedtls/importer/Makefile @@ -27,7 +27,7 @@ # # Set the mbed TLS release to import (this can/should be edited before import) -MBED_TLS_RELEASE ?= mbedtls-2.20.0d1 +MBED_TLS_RELEASE ?= mbedtls-2.22.0 MBED_TLS_REPO_URL ?= git@github.com:ARMmbed/mbedtls.git # Translate between mbed TLS namespace and mbed namespace @@ -36,9 +36,20 @@ TARGET_SRC:=$(TARGET_PREFIX)src TARGET_INC:=$(TARGET_PREFIX)inc TARGET_TESTS:=$(TARGET_PREFIX)TESTS +# A folder structure is introduced here for targets that have both a Secure +# Processing Environment (SPE) targets and Non-secure Processing Environment +# (NSPE). Documentation for each folder as follows: +# COMPONENT_PSA_SRV_IMPL - Include secure service implementation code. For +# example PSA Crypto or PSA Secure Time implementations +TARGET_SRV_IMPL:=$(TARGET_PREFIX)/platform/COMPONENT_PSA_SRV_IMPL +# COMPONENT_NSPE - Include code that compiles ONLY to the NSPE image and never +# compiles to the SPE image +TARGET_NSPE:=$(TARGET_SRV_IMPL)/COMPONENT_NSPE + # mbed TLS source directory - hidden from mbed via TARGET_IGNORE MBED_TLS_DIR:=TARGET_IGNORE/mbedtls MBED_TLS_API:=$(MBED_TLS_DIR)/include/mbedtls +CRYPTO_API:=$(MBED_TLS_DIR)/include/psa MBED_TLS_GIT_CFG=$(MBED_TLS_DIR)/.git/config .PHONY: all deploy deploy-tests rsync mbedtls clean update @@ -57,10 +68,24 @@ rsync: rm -rf $(TARGET_INC) mkdir -p $(TARGET_INC) rsync -a --delete $(MBED_TLS_API) $(TARGET_INC) + rsync -a --delete --exclude='crypto_struct.h' $(CRYPTO_API) $(TARGET_INC)/ # # Copying licenses cp $(MBED_TLS_DIR)/LICENSE $(TARGET_PREFIX) # + # Copying Mbed Crypto into Mbed OS... + rm -rf $(TARGET_SRV_IMPL) + + mkdir -p $(TARGET_SRV_IMPL) + mkdir -p $(TARGET_NSPE) + + rsync -a --delete $(CRYPTO_API)/crypto_struct.h $(TARGET_NSPE)/ + rsync -a --delete $(MBED_TLS_DIR)/library/psa_*.c $(TARGET_SRV_IMPL)/ + rsync -a --delete $(MBED_TLS_DIR)/library/psa_*.h $(TARGET_SRV_IMPL)/ + # + # Remove PSA-specific C & H files (they go into $(TARGET_SRV_IMPL)) + rm -rf $(TARGET_SRC)/psa_*.c + rm -rf $(TARGET_SRC)/psa_*.h deploy: rsync # @@ -110,3 +135,4 @@ clean: rm -rf $(TARGET_SRC) rm -rf $(TARGET_INC) rm -rf $(MBED_TLS_DIR) + rm -rf $(TARGET_SRV_IMPL) diff --git a/features/mbedtls/importer/adjust-config.sh b/features/mbedtls/importer/adjust-config.sh index 74d3a5b766..a68783cf93 100755 --- a/features/mbedtls/importer/adjust-config.sh +++ b/features/mbedtls/importer/adjust-config.sh @@ -79,6 +79,8 @@ conf unset MBEDTLS_TIMING_C # not supported on all targets with mbed OS, nor used by mbed Client conf unset MBEDTLS_HAVE_TIME_DATE conf unset MBEDTLS_FS_IO +conf unset MBEDTLS_PSA_ITS_FILE_C +conf unset MBEDTLS_PSA_CRYPTO_STORAGE_C conf set MBEDTLS_NO_PLATFORM_ENTROPY conf unset MBEDTLS_CIPHER_MODE_CFB From fc07e5ba93c52df95041b0efd3795a50135f93e5 Mon Sep 17 00:00:00 2001 From: Darryl Green Date: Fri, 3 Apr 2020 14:13:56 +0100 Subject: [PATCH 2/7] Update Mbed TLS to latest version As Mbed Crypto has been remerged into Mbed TLS, remove Mbed Crypto at the same time. Signed-off-by: Darryl Green --- features/mbedtls/LICENSE | 204 +- features/mbedtls/VERSION.txt | 2 +- .../{mbed-crypto => }/inc/mbedtls/aes.h | 0 .../{mbed-crypto => }/inc/mbedtls/aesni.h | 0 .../{mbed-crypto => }/inc/mbedtls/arc4.h | 0 .../{mbed-crypto => }/inc/mbedtls/aria.h | 0 .../{mbed-crypto => }/inc/mbedtls/asn1.h | 142 +- .../{mbed-crypto => }/inc/mbedtls/asn1write.h | 0 .../{mbed-crypto => }/inc/mbedtls/base64.h | 0 .../{mbed-crypto => }/inc/mbedtls/bignum.h | 0 .../{mbed-crypto => }/inc/mbedtls/blowfish.h | 0 .../{mbed-crypto => }/inc/mbedtls/bn_mul.h | 0 .../{mbed-crypto => }/inc/mbedtls/camellia.h | 0 .../{mbed-crypto => }/inc/mbedtls/ccm.h | 0 .../{mbed-crypto => }/inc/mbedtls/chacha20.h | 0 .../inc/mbedtls/chachapoly.h | 0 features/mbedtls/inc/mbedtls/check_config.h | 67 +- .../{mbed-crypto => }/inc/mbedtls/cipher.h | 0 .../inc/mbedtls/cipher_internal.h | 0 .../{mbed-crypto => }/inc/mbedtls/cmac.h | 0 features/mbedtls/inc/mbedtls/compat-1.3.h | 6 +- .../mbedtls/inc/mbedtls/config-no-entropy.h | 2 +- features/mbedtls/inc/mbedtls/config.h | 146 +- .../{mbed-crypto => }/inc/mbedtls/ctr_drbg.h | 0 .../{mbed-crypto => }/inc/mbedtls/des.h | 0 .../{mbed-crypto => }/inc/mbedtls/dhm.h | 9 +- .../{mbed-crypto => }/inc/mbedtls/ecdh.h | 0 .../{mbed-crypto => }/inc/mbedtls/ecdsa.h | 0 .../{mbed-crypto => }/inc/mbedtls/ecjpake.h | 0 .../{mbed-crypto => }/inc/mbedtls/ecp.h | 24 +- .../inc/mbedtls/ecp_internal.h | 0 .../{mbed-crypto => }/inc/mbedtls/entropy.h | 0 .../inc/mbedtls/entropy_poll.h | 0 .../{mbed-crypto => }/inc/mbedtls/gcm.h | 0 .../{mbed-crypto => }/inc/mbedtls/havege.h | 0 .../{mbed-crypto => }/inc/mbedtls/hkdf.h | 0 .../{mbed-crypto => }/inc/mbedtls/hmac_drbg.h | 0 .../{mbed-crypto => }/inc/mbedtls/md.h | 0 .../{mbed-crypto => }/inc/mbedtls/md2.h | 0 .../{mbed-crypto => }/inc/mbedtls/md4.h | 0 .../{mbed-crypto => }/inc/mbedtls/md5.h | 0 .../inc/mbedtls/md_internal.h | 2 + .../inc/mbedtls/memory_buffer_alloc.h | 0 .../{mbed-crypto => }/inc/mbedtls/nist_kw.h | 0 .../{mbed-crypto => }/inc/mbedtls/oid.h | 0 .../{mbed-crypto => }/inc/mbedtls/padlock.h | 0 .../{mbed-crypto => }/inc/mbedtls/pem.h | 0 .../{mbed-crypto => }/inc/mbedtls/pk.h | 0 .../inc/mbedtls/pk_internal.h | 0 features/mbedtls/inc/mbedtls/pkcs11.h | 121 +- .../{mbed-crypto => }/inc/mbedtls/pkcs12.h | 0 .../{mbed-crypto => }/inc/mbedtls/pkcs5.h | 0 .../{mbed-crypto => }/inc/mbedtls/platform.h | 0 .../inc/mbedtls/platform_time.h | 0 .../inc/mbedtls/platform_util.h | 0 .../{mbed-crypto => }/inc/mbedtls/poly1305.h | 0 .../{mbed-crypto => }/inc/mbedtls/psa_util.h | 194 +- .../{mbed-crypto => }/inc/mbedtls/ripemd160.h | 0 .../{mbed-crypto => }/inc/mbedtls/rsa.h | 0 .../inc/mbedtls/rsa_internal.h | 0 .../{mbed-crypto => }/inc/mbedtls/sha1.h | 0 .../{mbed-crypto => }/inc/mbedtls/sha256.h | 0 .../{mbed-crypto => }/inc/mbedtls/sha512.h | 18 +- features/mbedtls/inc/mbedtls/ssl.h | 144 +- .../mbedtls/inc/mbedtls/ssl_ciphersuites.h | 44 +- features/mbedtls/inc/mbedtls/ssl_internal.h | 97 +- .../{mbed-crypto => }/inc/mbedtls/threading.h | 0 .../{mbed-crypto => }/inc/mbedtls/timing.h | 0 features/mbedtls/inc/mbedtls/version.h | 10 +- .../{mbed-crypto => }/inc/mbedtls/xtea.h | 0 .../{mbed-crypto => }/inc/psa/crypto.h | 12 +- .../inc/psa/crypto_accel_driver.h | 0 features/mbedtls/inc/psa/crypto_compat.h | 196 + .../inc/psa/crypto_driver_common.h | 0 .../inc/psa/crypto_entropy_driver.h | 0 .../{mbed-crypto => }/inc/psa/crypto_extra.h | 52 +- .../inc/psa/crypto_platform.h | 0 .../inc/psa/crypto_se_driver.h | 0 .../{mbed-crypto => }/inc/psa/crypto_sizes.h | 41 - .../{mbed-crypto => }/inc/psa/crypto_types.h | 74 +- .../{mbed-crypto => }/inc/psa/crypto_values.h | 212 +- features/mbedtls/mbed-crypto/LICENSE | 2 - features/mbedtls/mbed-crypto/VERSION.txt | 1 - features/mbedtls/mbed-crypto/apache-2.0.txt | 202 - .../mbedtls/mbed-crypto/importer/Makefile | 131 - .../importer/TARGET_IGNORE/.gitignore | 1 - .../mbed-crypto/inc/psa/crypto_compat.h | 109 - .../mbed-crypto/platform/mbed_lib.json | 4 - .../COMPONENT_NSPE/crypto_struct.h | 4 +- .../COMPONENT_PSA_SRV_IMPL/psa_crypto.c | 249 +- .../COMPONENT_PSA_SRV_IMPL/psa_crypto_core.h | 0 .../psa_crypto_invasive.h | 0 .../COMPONENT_PSA_SRV_IMPL/psa_crypto_its.h | 0 .../COMPONENT_PSA_SRV_IMPL/psa_crypto_se.c | 0 .../COMPONENT_PSA_SRV_IMPL/psa_crypto_se.h | 0 .../psa_crypto_service_integration.h | 0 .../psa_crypto_slot_management.c | 0 .../psa_crypto_slot_management.h | 0 .../psa_crypto_storage.c | 13 +- .../psa_crypto_storage.h | 0 .../COMPONENT_PSA_SRV_IMPL/psa_its_file.c | 0 features/mbedtls/src/Makefile | 84 +- features/mbedtls/{mbed-crypto => }/src/aes.c | 0 .../mbedtls/{mbed-crypto => }/src/aesni.c | 0 features/mbedtls/{mbed-crypto => }/src/arc4.c | 0 features/mbedtls/{mbed-crypto => }/src/aria.c | 0 .../mbedtls/{mbed-crypto => }/src/asn1parse.c | 144 +- .../mbedtls/{mbed-crypto => }/src/asn1write.c | 0 .../mbedtls/{mbed-crypto => }/src/base64.c | 0 .../mbedtls/{mbed-crypto => }/src/bignum.c | 5 +- .../mbedtls/{mbed-crypto => }/src/blowfish.c | 0 .../mbedtls/{mbed-crypto => }/src/camellia.c | 0 features/mbedtls/{mbed-crypto => }/src/ccm.c | 0 .../mbedtls/{mbed-crypto => }/src/chacha20.c | 0 .../{mbed-crypto => }/src/chachapoly.c | 0 .../mbedtls/{mbed-crypto => }/src/cipher.c | 14 +- .../{mbed-crypto => }/src/cipher_wrap.c | 0 features/mbedtls/{mbed-crypto => }/src/cmac.c | 0 .../mbedtls/{mbed-crypto => }/src/ctr_drbg.c | 0 features/mbedtls/{mbed-crypto => }/src/des.c | 0 features/mbedtls/{mbed-crypto => }/src/dhm.c | 0 features/mbedtls/{mbed-crypto => }/src/ecdh.c | 0 .../mbedtls/{mbed-crypto => }/src/ecdsa.c | 4 +- .../mbedtls/{mbed-crypto => }/src/ecjpake.c | 0 features/mbedtls/{mbed-crypto => }/src/ecp.c | 30 +- .../{mbed-crypto => }/src/ecp_curves.c | 0 .../mbedtls/{mbed-crypto => }/src/entropy.c | 0 .../{mbed-crypto => }/src/entropy_poll.c | 0 features/mbedtls/src/error.c | 82 +- features/mbedtls/{mbed-crypto => }/src/gcm.c | 0 .../mbedtls/{mbed-crypto => }/src/havege.c | 0 features/mbedtls/{mbed-crypto => }/src/hkdf.c | 6 +- .../mbedtls/{mbed-crypto => }/src/hmac_drbg.c | 0 features/mbedtls/{mbed-crypto => }/src/md.c | 26 +- features/mbedtls/{mbed-crypto => }/src/md2.c | 0 features/mbedtls/{mbed-crypto => }/src/md4.c | 0 features/mbedtls/{mbed-crypto => }/src/md5.c | 0 .../src/memory_buffer_alloc.c | 0 .../mbedtls/{mbed-crypto => }/src/nist_kw.c | 0 features/mbedtls/{mbed-crypto => }/src/oid.c | 0 .../mbedtls/{mbed-crypto => }/src/padlock.c | 0 features/mbedtls/{mbed-crypto => }/src/pem.c | 0 features/mbedtls/{mbed-crypto => }/src/pk.c | 7 +- .../mbedtls/{mbed-crypto => }/src/pk_wrap.c | 10 +- .../mbedtls/{mbed-crypto => }/src/pkcs12.c | 0 .../mbedtls/{mbed-crypto => }/src/pkcs5.c | 0 .../mbedtls/{mbed-crypto => }/src/pkparse.c | 122 +- .../mbedtls/{mbed-crypto => }/src/pkwrite.c | 4 +- .../mbedtls/{mbed-crypto => }/src/platform.c | 0 .../{mbed-crypto => }/src/platform_util.c | 0 .../mbedtls/{mbed-crypto => }/src/poly1305.c | 0 .../mbedtls/{mbed-crypto => }/src/ripemd160.c | 0 features/mbedtls/{mbed-crypto => }/src/rsa.c | 11 +- .../{mbed-crypto => }/src/rsa_internal.c | 0 features/mbedtls/{mbed-crypto => }/src/sha1.c | 0 .../mbedtls/{mbed-crypto => }/src/sha256.c | 0 .../mbedtls/{mbed-crypto => }/src/sha512.c | 30 +- features/mbedtls/src/ssl_ciphersuites.c | 4 +- features/mbedtls/src/ssl_cli.c | 109 +- features/mbedtls/src/ssl_msg.c | 5738 ++++++++++++++++ features/mbedtls/src/ssl_srv.c | 103 +- features/mbedtls/src/ssl_tls.c | 5950 +---------------- .../mbedtls/{mbed-crypto => }/src/threading.c | 0 .../mbedtls/{mbed-crypto => }/src/timing.c | 0 features/mbedtls/src/version_features.c | 18 + features/mbedtls/src/x509.c | 2 +- features/mbedtls/src/x509_crl.c | 2 +- features/mbedtls/src/x509_crt.c | 2 +- features/mbedtls/src/x509write_csr.c | 4 +- features/mbedtls/{mbed-crypto => }/src/xtea.c | 0 170 files changed, 8075 insertions(+), 6971 deletions(-) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/aes.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/aesni.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/arc4.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/aria.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/asn1.h (71%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/asn1write.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/base64.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/bignum.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/blowfish.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/bn_mul.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/camellia.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/ccm.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/chacha20.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/chachapoly.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/cipher.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/cipher_internal.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/cmac.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/ctr_drbg.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/des.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/dhm.h (99%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/ecdh.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/ecdsa.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/ecjpake.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/ecp.h (98%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/ecp_internal.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/entropy.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/entropy_poll.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/gcm.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/havege.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/hkdf.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/hmac_drbg.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/md.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/md2.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/md4.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/md5.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/md_internal.h (98%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/memory_buffer_alloc.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/nist_kw.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/oid.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/padlock.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/pem.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/pk.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/pk_internal.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/pkcs12.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/pkcs5.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/platform.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/platform_time.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/platform_util.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/poly1305.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/psa_util.h (71%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/ripemd160.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/rsa.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/rsa_internal.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/sha1.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/sha256.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/sha512.h (93%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/threading.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/timing.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/mbedtls/xtea.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/psa/crypto.h (99%) rename features/mbedtls/{mbed-crypto => }/inc/psa/crypto_accel_driver.h (100%) create mode 100644 features/mbedtls/inc/psa/crypto_compat.h rename features/mbedtls/{mbed-crypto => }/inc/psa/crypto_driver_common.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/psa/crypto_entropy_driver.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/psa/crypto_extra.h (92%) rename features/mbedtls/{mbed-crypto => }/inc/psa/crypto_platform.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/psa/crypto_se_driver.h (100%) rename features/mbedtls/{mbed-crypto => }/inc/psa/crypto_sizes.h (93%) rename features/mbedtls/{mbed-crypto => }/inc/psa/crypto_types.h (80%) rename features/mbedtls/{mbed-crypto => }/inc/psa/crypto_values.h (91%) delete mode 100644 features/mbedtls/mbed-crypto/LICENSE delete mode 100644 features/mbedtls/mbed-crypto/VERSION.txt delete mode 100644 features/mbedtls/mbed-crypto/apache-2.0.txt delete mode 100644 features/mbedtls/mbed-crypto/importer/Makefile delete mode 100644 features/mbedtls/mbed-crypto/importer/TARGET_IGNORE/.gitignore delete mode 100644 features/mbedtls/mbed-crypto/inc/psa/crypto_compat.h delete mode 100644 features/mbedtls/mbed-crypto/platform/mbed_lib.json rename features/mbedtls/{mbed-crypto => }/platform/COMPONENT_PSA_SRV_IMPL/COMPONENT_NSPE/crypto_struct.h (99%) rename features/mbedtls/{mbed-crypto => }/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto.c (96%) rename features/mbedtls/{mbed-crypto => }/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_core.h (100%) rename features/mbedtls/{mbed-crypto => }/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_invasive.h (100%) rename features/mbedtls/{mbed-crypto => }/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_its.h (100%) rename features/mbedtls/{mbed-crypto => }/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_se.c (100%) rename features/mbedtls/{mbed-crypto => }/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_se.h (100%) rename features/mbedtls/{mbed-crypto => }/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_service_integration.h (100%) rename features/mbedtls/{mbed-crypto => }/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.c (100%) rename features/mbedtls/{mbed-crypto => }/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.h (100%) rename features/mbedtls/{mbed-crypto => }/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c (97%) rename features/mbedtls/{mbed-crypto => }/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.h (100%) rename features/mbedtls/{mbed-crypto => }/platform/COMPONENT_PSA_SRV_IMPL/psa_its_file.c (100%) rename features/mbedtls/{mbed-crypto => }/src/aes.c (100%) rename features/mbedtls/{mbed-crypto => }/src/aesni.c (100%) rename features/mbedtls/{mbed-crypto => }/src/arc4.c (100%) rename features/mbedtls/{mbed-crypto => }/src/aria.c (100%) rename features/mbedtls/{mbed-crypto => }/src/asn1parse.c (82%) rename features/mbedtls/{mbed-crypto => }/src/asn1write.c (100%) rename features/mbedtls/{mbed-crypto => }/src/base64.c (100%) rename features/mbedtls/{mbed-crypto => }/src/bignum.c (99%) rename features/mbedtls/{mbed-crypto => }/src/blowfish.c (100%) rename features/mbedtls/{mbed-crypto => }/src/camellia.c (100%) rename features/mbedtls/{mbed-crypto => }/src/ccm.c (100%) rename features/mbedtls/{mbed-crypto => }/src/chacha20.c (100%) rename features/mbedtls/{mbed-crypto => }/src/chachapoly.c (100%) rename features/mbedtls/{mbed-crypto => }/src/cipher.c (99%) rename features/mbedtls/{mbed-crypto => }/src/cipher_wrap.c (100%) rename features/mbedtls/{mbed-crypto => }/src/cmac.c (100%) rename features/mbedtls/{mbed-crypto => }/src/ctr_drbg.c (100%) rename features/mbedtls/{mbed-crypto => }/src/des.c (100%) rename features/mbedtls/{mbed-crypto => }/src/dhm.c (100%) rename features/mbedtls/{mbed-crypto => }/src/ecdh.c (100%) rename features/mbedtls/{mbed-crypto => }/src/ecdsa.c (99%) rename features/mbedtls/{mbed-crypto => }/src/ecjpake.c (100%) rename features/mbedtls/{mbed-crypto => }/src/ecp.c (98%) rename features/mbedtls/{mbed-crypto => }/src/ecp_curves.c (100%) rename features/mbedtls/{mbed-crypto => }/src/entropy.c (100%) rename features/mbedtls/{mbed-crypto => }/src/entropy_poll.c (100%) rename features/mbedtls/{mbed-crypto => }/src/gcm.c (100%) rename features/mbedtls/{mbed-crypto => }/src/havege.c (100%) rename features/mbedtls/{mbed-crypto => }/src/hkdf.c (97%) rename features/mbedtls/{mbed-crypto => }/src/hmac_drbg.c (100%) rename features/mbedtls/{mbed-crypto => }/src/md.c (97%) rename features/mbedtls/{mbed-crypto => }/src/md2.c (100%) rename features/mbedtls/{mbed-crypto => }/src/md4.c (100%) rename features/mbedtls/{mbed-crypto => }/src/md5.c (100%) rename features/mbedtls/{mbed-crypto => }/src/memory_buffer_alloc.c (100%) rename features/mbedtls/{mbed-crypto => }/src/nist_kw.c (100%) rename features/mbedtls/{mbed-crypto => }/src/oid.c (100%) rename features/mbedtls/{mbed-crypto => }/src/padlock.c (100%) rename features/mbedtls/{mbed-crypto => }/src/pem.c (100%) rename features/mbedtls/{mbed-crypto => }/src/pk.c (98%) rename features/mbedtls/{mbed-crypto => }/src/pk_wrap.c (99%) rename features/mbedtls/{mbed-crypto => }/src/pkcs12.c (100%) rename features/mbedtls/{mbed-crypto => }/src/pkcs5.c (100%) rename features/mbedtls/{mbed-crypto => }/src/pkparse.c (92%) rename features/mbedtls/{mbed-crypto => }/src/pkwrite.c (99%) rename features/mbedtls/{mbed-crypto => }/src/platform.c (100%) rename features/mbedtls/{mbed-crypto => }/src/platform_util.c (100%) rename features/mbedtls/{mbed-crypto => }/src/poly1305.c (100%) rename features/mbedtls/{mbed-crypto => }/src/ripemd160.c (100%) rename features/mbedtls/{mbed-crypto => }/src/rsa.c (99%) rename features/mbedtls/{mbed-crypto => }/src/rsa_internal.c (100%) rename features/mbedtls/{mbed-crypto => }/src/sha1.c (100%) rename features/mbedtls/{mbed-crypto => }/src/sha256.c (100%) rename features/mbedtls/{mbed-crypto => }/src/sha512.c (96%) create mode 100644 features/mbedtls/src/ssl_msg.c rename features/mbedtls/{mbed-crypto => }/src/threading.c (100%) rename features/mbedtls/{mbed-crypto => }/src/timing.c (100%) rename features/mbedtls/{mbed-crypto => }/src/xtea.c (100%) diff --git a/features/mbedtls/LICENSE b/features/mbedtls/LICENSE index 546a8e631f..d645695673 100644 --- a/features/mbedtls/LICENSE +++ b/features/mbedtls/LICENSE @@ -1,2 +1,202 @@ -Unless specifically indicated otherwise in a file, files are licensed -under the Apache 2.0 license, as can be found in: apache-2.0.txt + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/features/mbedtls/VERSION.txt b/features/mbedtls/VERSION.txt index b3a4b2d74c..4961d31884 100644 --- a/features/mbedtls/VERSION.txt +++ b/features/mbedtls/VERSION.txt @@ -1 +1 @@ -mbedtls-2.20.0d1 +mbedtls-2.22.0 diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/aes.h b/features/mbedtls/inc/mbedtls/aes.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/aes.h rename to features/mbedtls/inc/mbedtls/aes.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/aesni.h b/features/mbedtls/inc/mbedtls/aesni.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/aesni.h rename to features/mbedtls/inc/mbedtls/aesni.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/arc4.h b/features/mbedtls/inc/mbedtls/arc4.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/arc4.h rename to features/mbedtls/inc/mbedtls/arc4.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/aria.h b/features/mbedtls/inc/mbedtls/aria.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/aria.h rename to features/mbedtls/inc/mbedtls/aria.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/asn1.h b/features/mbedtls/inc/mbedtls/asn1.h similarity index 71% rename from features/mbedtls/mbed-crypto/inc/mbedtls/asn1.h rename to features/mbedtls/inc/mbedtls/asn1.h index 1c6683f63e..4c61b6e1c3 100644 --- a/features/mbedtls/mbed-crypto/inc/mbedtls/asn1.h +++ b/features/mbedtls/inc/mbedtls/asn1.h @@ -66,7 +66,7 @@ * - 0x02 -- tag indicating INTEGER * - 0x01 -- length in octets * - 0x05 -- value - * Such sequences are typically read into Mbed TLS's \c mbedtls_x509_buf. + * Such sequences are typically read into \c ::mbedtls_x509_buf. * \{ */ #define MBEDTLS_ASN1_BOOLEAN 0x01 @@ -90,6 +90,18 @@ #define MBEDTLS_ASN1_CONSTRUCTED 0x20 #define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 +/* Slightly smaller way to check if tag is a string tag + * compared to canonical implementation. */ +#define MBEDTLS_ASN1_IS_STRING_TAG( tag ) \ + ( ( tag ) < 32u && ( \ + ( ( 1u << ( tag ) ) & ( ( 1u << MBEDTLS_ASN1_BMP_STRING ) | \ + ( 1u << MBEDTLS_ASN1_UTF8_STRING ) | \ + ( 1u << MBEDTLS_ASN1_T61_STRING ) | \ + ( 1u << MBEDTLS_ASN1_IA5_STRING ) | \ + ( 1u << MBEDTLS_ASN1_UNIVERSAL_STRING ) | \ + ( 1u << MBEDTLS_ASN1_PRINTABLE_STRING ) | \ + ( 1u << MBEDTLS_ASN1_BIT_STRING ) ) ) != 0 ) ) + /* * Bit masks for each of the components of an ASN.1 tag as specified in * ITU X.690 (08/2015), section 8.1 "General rules for encoding", @@ -120,6 +132,10 @@ ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \ memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 ) +#define MBEDTLS_OID_CMP_RAW(oid_str, oid_buf, oid_buf_len) \ + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf_len) ) || \ + memcmp( (oid_str), (oid_buf), (oid_buf_len) ) != 0 ) + #ifdef __cplusplus extern "C" { #endif @@ -327,6 +343,9 @@ int mbedtls_asn1_get_bitstring_null( unsigned char **p, * \brief Parses and splits an ASN.1 "SEQUENCE OF ". * Updates the pointer to immediately behind the full sequence tag. * + * This function allocates memory for the sequence elements. You can free + * the allocated memory with mbedtls_asn1_sequence_free(). + * * \note On error, this function may return a partial list in \p cur. * You must set `cur->next = NULL` before calling this function! * Otherwise it is impossible to distinguish a previously non-null @@ -360,14 +379,133 @@ int mbedtls_asn1_get_bitstring_null( unsigned char **p, * \return 0 if successful. * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains * extra data after a valid SEQUENCE OF \p tag. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts with + * an ASN.1 SEQUENCE in which an element has a tag that + * is different from \p tag. * \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if a memory allocation failed. * \return An ASN.1 error code if the input does not start with - * a valid ASN.1 BIT STRING. + * a valid ASN.1 SEQUENCE. */ int mbedtls_asn1_get_sequence_of( unsigned char **p, const unsigned char *end, mbedtls_asn1_sequence *cur, int tag ); +/** + * \brief Free a heap-allocated linked list presentation of + * an ASN.1 sequence, including the first element. + * + * There are two common ways to manage the memory used for the representation + * of a parsed ASN.1 sequence: + * - Allocate a head node `mbedtls_asn1_sequence *head` with mbedtls_calloc(). + * Pass this node as the `cur` argument to mbedtls_asn1_get_sequence_of(). + * When you have finished processing the sequence, + * call mbedtls_asn1_sequence_free() on `head`. + * - Allocate a head node `mbedtls_asn1_sequence *head` in any manner, + * for example on the stack. Make sure that `head->next == NULL`. + * Pass `head` as the `cur` argument to mbedtls_asn1_get_sequence_of(). + * When you have finished processing the sequence, + * call mbedtls_asn1_sequence_free() on `head->cur`, + * then free `head` itself in the appropriate manner. + * + * \param seq The address of the first sequence component. This may + * be \c NULL, in which case this functions returns + * immediately. + */ +void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq ); + +/** + * \brief Traverse an ASN.1 SEQUENCE container and + * call a callback for each entry. + * + * This function checks that the input is a SEQUENCE of elements that + * each have a "must" tag, and calls a callback function on the elements + * that have a "may" tag. + * + * For example, to validate that the input is a SEQUENCE of `tag1` and call + * `cb` on each element, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0xff, tag1, 0, 0, cb, ctx); + * ``` + * + * To validate that the input is a SEQUENCE of ANY and call `cb` on + * each element, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0, 0, 0, 0, cb, ctx); + * ``` + * + * To validate that the input is a SEQUENCE of CHOICE {NULL, OCTET STRING} + * and call `cb` on each element that is an OCTET STRING, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0xfe, 0x04, 0xff, 0x04, cb, ctx); + * ``` + * + * The callback is called on the elements with a "may" tag from left to + * right. If the input is not a valid SEQUENCE of elements with a "must" tag, + * the callback is called on the elements up to the leftmost point where + * the input is invalid. + * + * \warning This function is still experimental and may change + * at any time. + * + * \param p The address of the pointer to the beginning of + * the ASN.1 SEQUENCE header. This is updated to + * point to the end of the ASN.1 SEQUENCE container + * on a successful invocation. + * \param end The end of the ASN.1 SEQUENCE container. + * \param tag_must_mask A mask to be applied to the ASN.1 tags found within + * the SEQUENCE before comparing to \p tag_must_value. + * \param tag_must_val The required value of each ASN.1 tag found in the + * SEQUENCE, after masking with \p tag_must_mask. + * Mismatching tags lead to an error. + * For example, a value of \c 0 for both \p tag_must_mask + * and \p tag_must_val means that every tag is allowed, + * while a value of \c 0xFF for \p tag_must_mask means + * that \p tag_must_val is the only allowed tag. + * \param tag_may_mask A mask to be applied to the ASN.1 tags found within + * the SEQUENCE before comparing to \p tag_may_value. + * \param tag_may_val The desired value of each ASN.1 tag found in the + * SEQUENCE, after masking with \p tag_may_mask. + * Mismatching tags will be silently ignored. + * For example, a value of \c 0 for \p tag_may_mask and + * \p tag_may_val means that any tag will be considered, + * while a value of \c 0xFF for \p tag_may_mask means + * that all tags with value different from \p tag_may_val + * will be ignored. + * \param cb The callback to trigger for each component + * in the ASN.1 SEQUENCE that matches \p tag_may_val. + * The callback function is called with the following + * parameters: + * - \p ctx. + * - The tag of the current element. + * - A pointer to the start of the current element's + * content inside the input. + * - The length of the content of the current element. + * If the callback returns a non-zero value, + * the function stops immediately, + * forwarding the callback's return value. + * \param ctx The context to be passed to the callback \p cb. + * + * \return \c 0 if successful the entire ASN.1 SEQUENCE + * was traversed without parsing or callback errors. + * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input + * contains extra data after a valid SEQUENCE + * of elements with an accepted tag. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts + * with an ASN.1 SEQUENCE in which an element has a tag + * that is not accepted. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 SEQUENCE. + * \return A non-zero error code forwarded from the callback + * \p cb in case the latter returns a non-zero value. + */ +int mbedtls_asn1_traverse_sequence_of( + unsigned char **p, + const unsigned char *end, + unsigned char tag_must_mask, unsigned char tag_must_val, + unsigned char tag_may_mask, unsigned char tag_may_val, + int (*cb)( void *ctx, int tag, + unsigned char* start, size_t len ), + void *ctx ); #if defined(MBEDTLS_BIGNUM_C) /** diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/asn1write.h b/features/mbedtls/inc/mbedtls/asn1write.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/asn1write.h rename to features/mbedtls/inc/mbedtls/asn1write.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/base64.h b/features/mbedtls/inc/mbedtls/base64.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/base64.h rename to features/mbedtls/inc/mbedtls/base64.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/bignum.h b/features/mbedtls/inc/mbedtls/bignum.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/bignum.h rename to features/mbedtls/inc/mbedtls/bignum.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/blowfish.h b/features/mbedtls/inc/mbedtls/blowfish.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/blowfish.h rename to features/mbedtls/inc/mbedtls/blowfish.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/bn_mul.h b/features/mbedtls/inc/mbedtls/bn_mul.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/bn_mul.h rename to features/mbedtls/inc/mbedtls/bn_mul.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/camellia.h b/features/mbedtls/inc/mbedtls/camellia.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/camellia.h rename to features/mbedtls/inc/mbedtls/camellia.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/ccm.h b/features/mbedtls/inc/mbedtls/ccm.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/ccm.h rename to features/mbedtls/inc/mbedtls/ccm.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/chacha20.h b/features/mbedtls/inc/mbedtls/chacha20.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/chacha20.h rename to features/mbedtls/inc/mbedtls/chacha20.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/chachapoly.h b/features/mbedtls/inc/mbedtls/chachapoly.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/chachapoly.h rename to features/mbedtls/inc/mbedtls/chachapoly.h diff --git a/features/mbedtls/inc/mbedtls/check_config.h b/features/mbedtls/inc/mbedtls/check_config.h index 7e0e3575c8..8db7825406 100644 --- a/features/mbedtls/inc/mbedtls/check_config.h +++ b/features/mbedtls/inc/mbedtls/check_config.h @@ -189,7 +189,7 @@ #endif #if defined(MBEDTLS_GCM_C) && ( \ - !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) ) + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) ) #error "MBEDTLS_GCM_C defined, but not all prerequisites" #endif @@ -292,7 +292,7 @@ #error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" #endif -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) && \ +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) && \ ( !defined(MBEDTLS_SHA256_C) && \ !defined(MBEDTLS_SHA512_C) && \ @@ -342,6 +342,14 @@ #error "MBEDTLS_PKCS11_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_PKCS11_C) +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "MBEDTLS_PKCS11_C is deprecated and will be removed in a future version of Mbed TLS" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "MBEDTLS_PKCS11_C is deprecated and will be removed in a future version of Mbed TLS" +#endif +#endif /* MBEDTLS_PKCS11_C */ + #if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" #endif @@ -545,6 +553,12 @@ #error "MBEDTLS_PSA_CRYPTO_SPM defined, but not all prerequisites" #endif +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) && \ + ! ( defined(MBEDTLS_PSA_CRYPTO_C) && \ + defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) ) +#error "MBEDTLS_PSA_CRYPTO_SE_C defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ ! defined(MBEDTLS_PSA_CRYPTO_C) #error "MBEDTLS_PSA_CRYPTO_STORAGE_C defined, but not all prerequisites" @@ -576,6 +590,10 @@ #error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" #endif +#if defined(MBEDTLS_SHA512_NO_SHA384) && !defined(MBEDTLS_SHA512_C) +#error "MBEDTLS_SHA512_NO_SHA384 defined without MBEDTLS_SHA512_C" +#endif + #if defined(MBEDTLS_SSL_PROTO_SSL3) && ( !defined(MBEDTLS_MD5_C) || \ !defined(MBEDTLS_SHA1_C) ) #error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites" @@ -596,6 +614,23 @@ #error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" #endif +#if (defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \ + !(defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) ) +#error "One or more versions of the TLS protocol are enabled " \ + "but no key exchange methods defined with MBEDTLS_KEY_EXCHANGE_xxxx" +#endif + #if defined(MBEDTLS_SSL_PROTO_DTLS) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_2) @@ -740,6 +775,10 @@ #error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_CERTS_C) && !defined(MBEDTLS_X509_USE_C) +#error "MBEDTLS_CERTS_C defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) #error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" #endif @@ -769,6 +808,30 @@ #error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" #endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "MBEDTLS_SSL_PROTO_SSL3 is deprecated and will be removed in a future version of Mbed TLS" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "MBEDTLS_SSL_PROTO_SSL3 is deprecated and will be removed in a future version of Mbed TLS" +#endif +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is deprecated and will be removed in a future version of Mbed TLS" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is deprecated and will be removed in a future version of Mbed TLS" +#endif +#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "MBEDTLS_SSL_HW_RECORD_ACCEL is deprecated and will be removed in a future version of Mbed TLS" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "MBEDTLS_SSL_HW_RECORD_ACCEL is deprecated and will be removed in a future version of Mbed TLS" +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + /* * Avoid warning from -pedantic. This is a convenient place for this * workaround since this is included by every single file before the diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/cipher.h b/features/mbedtls/inc/mbedtls/cipher.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/cipher.h rename to features/mbedtls/inc/mbedtls/cipher.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/cipher_internal.h b/features/mbedtls/inc/mbedtls/cipher_internal.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/cipher_internal.h rename to features/mbedtls/inc/mbedtls/cipher_internal.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/cmac.h b/features/mbedtls/inc/mbedtls/cmac.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/cmac.h rename to features/mbedtls/inc/mbedtls/cmac.h diff --git a/features/mbedtls/inc/mbedtls/compat-1.3.h b/features/mbedtls/inc/mbedtls/compat-1.3.h index 361cf569cf..b268734be0 100644 --- a/features/mbedtls/inc/mbedtls/compat-1.3.h +++ b/features/mbedtls/inc/mbedtls/compat-1.3.h @@ -1250,9 +1250,9 @@ #define POLARSSL_KEY_EXCHANGE_PSK MBEDTLS_KEY_EXCHANGE_PSK #define POLARSSL_KEY_EXCHANGE_RSA MBEDTLS_KEY_EXCHANGE_RSA #define POLARSSL_KEY_EXCHANGE_RSA_PSK MBEDTLS_KEY_EXCHANGE_RSA_PSK -#define POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED -#define POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED -#define POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED +#define POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED +#define POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED #define POLARSSL_KEY_LENGTH_DES MBEDTLS_KEY_LENGTH_DES #define POLARSSL_KEY_LENGTH_DES_EDE MBEDTLS_KEY_LENGTH_DES_EDE #define POLARSSL_KEY_LENGTH_DES_EDE3 MBEDTLS_KEY_LENGTH_DES_EDE3 diff --git a/features/mbedtls/inc/mbedtls/config-no-entropy.h b/features/mbedtls/inc/mbedtls/config-no-entropy.h index a0e979f0c2..ccdd75c63a 100644 --- a/features/mbedtls/inc/mbedtls/config-no-entropy.h +++ b/features/mbedtls/inc/mbedtls/config-no-entropy.h @@ -87,6 +87,6 @@ /* Miscellaneous options */ #define MBEDTLS_AES_ROM_TABLES -#include "check_config.h" +#include "mbedtls/check_config.h" #endif /* MBEDTLS_CONFIG_H */ diff --git a/features/mbedtls/inc/mbedtls/config.h b/features/mbedtls/inc/mbedtls/config.h index e6b459dc11..bdf7e5e19d 100644 --- a/features/mbedtls/inc/mbedtls/config.h +++ b/features/mbedtls/inc/mbedtls/config.h @@ -249,27 +249,27 @@ /** * \def MBEDTLS_DEPRECATED_WARNING * - * Mark deprecated functions so that they generate a warning if used. - * Functions deprecated in one version will usually be removed in the next - * version. You can enable this to help you prepare the transition to a new - * major version by making sure your code is not using these functions. + * Mark deprecated functions and features so that they generate a warning if + * used. Functionality deprecated in one version will usually be removed in the + * next version. You can enable this to help you prepare the transition to a + * new major version by making sure your code is not using this functionality. * * This only works with GCC and Clang. With other compilers, you may want to * use MBEDTLS_DEPRECATED_REMOVED * - * Uncomment to get warnings on using deprecated functions. + * Uncomment to get warnings on using deprecated functions and features. */ //#define MBEDTLS_DEPRECATED_WARNING /** * \def MBEDTLS_DEPRECATED_REMOVED * - * Remove deprecated functions so that they generate an error if used. - * Functions deprecated in one version will usually be removed in the next - * version. You can enable this to help you prepare the transition to a new - * major version by making sure your code is not using these functions. + * Remove deprecated functions and features so that they generate an error if + * used. Functionality deprecated in one version will usually be removed in the + * next version. You can enable this to help you prepare the transition to a + * new major version by making sure your code is not using this functionality. * - * Uncomment to get errors on using deprecated functions. + * Uncomment to get errors on using deprecated functions and features. */ //#define MBEDTLS_DEPRECATED_REMOVED @@ -457,6 +457,16 @@ * dependencies on them, and considering stronger message digests * and ciphers instead. * + * \warning If both MBEDTLS_ECDSA_SIGN_ALT and MBEDTLS_ECDSA_DETERMINISTIC are + * enabled, then the deterministic ECDH signature functions pass the + * the static HMAC-DRBG as RNG to mbedtls_ecdsa_sign(). Therefore + * alternative implementations should use the RNG only for generating + * the ephemeral key and nothing else. If this is not possible, then + * MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative + * implementation should be provided for mbedtls_ecdsa_sign_det_ext() + * (and for mbedtls_ecdsa_sign_det() too if backward compatibility is + * desirable). + * */ //#define MBEDTLS_MD2_PROCESS_ALT //#define MBEDTLS_MD4_PROCESS_ALT @@ -696,6 +706,13 @@ //#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN //#define MBEDTLS_CIPHER_PADDING_ZEROS +/** \def MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + * + * Uncomment this macro to use a 128-bit key in the CTR_DRBG module. + * By default, CTR_DRBG uses a 256-bit key. + */ +//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + /** * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES * @@ -1235,6 +1252,21 @@ */ //#define MBEDTLS_ENTROPY_NV_SEED +/* MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER + * + * In PSA key storage, encode the owner of the key. + * + * This is only meaningful when building the library as part of a + * multi-client service. When you activate this option, you must provide + * an implementation of the type psa_key_owner_id_t and a translation + * from psa_key_file_id_t to file name in all the storage backends that + * you wish to support. + * + * Note that this option is meant for internal use only and may be removed + * without notice. + */ +//#define MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER + /** * \def MBEDTLS_MEMORY_DEBUG * @@ -1352,6 +1384,28 @@ */ //#define MBEDTLS_SHA256_SMALLER +/** + * \def MBEDTLS_SHA512_SMALLER + * + * Enable an implementation of SHA-512 that has lower ROM footprint but also + * lower performance. + * + * Uncomment to enable the smaller implementation of SHA512. + */ +//#define MBEDTLS_SHA512_SMALLER + +/** + * \def MBEDTLS_SHA512_NO_SHA384 + * + * Disable the SHA-384 option of the SHA-512 module. Use this to save some + * code size on devices that don't use SHA-384. + * + * Requires: MBEDTLS_SHA512_C + * + * Uncomment to disable SHA-384 + */ +//#define MBEDTLS_SHA512_NO_SHA384 + /** * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES * @@ -1482,8 +1536,8 @@ /** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET * - * Enable support for Extended Master Secret, aka Session Hash - * (draft-ietf-tls-session-hash-02). + * Enable support for RFC 7627: Session Hash and Extended Master Secret + * Extension. * * This was introduced as "the proper fix" to the Triple Handshake familiy of * attacks, but it is recommended to always use it (even if you disable @@ -1501,7 +1555,8 @@ /** * \def MBEDTLS_SSL_FALLBACK_SCSV * - * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00). + * Enable support for RFC 7507: Fallback Signaling Cipher Suite Value (SCSV) + * for Preventing Protocol Downgrade Attacks. * * For servers, it is recommended to always enable this, unless you support * only one version of TLS, or know for sure that none of your clients @@ -1543,6 +1598,9 @@ * Enable hooking functions in SSL module for hardware acceleration of * individual records. * + * \deprecated This option is deprecated and will be removed in a future + * version of Mbed TLS. + * * Uncomment this macro to enable hooking functions. */ //#define MBEDTLS_SSL_HW_RECORD_ACCEL @@ -1587,6 +1645,9 @@ * Enable support for receiving and parsing SSLv2 Client Hello messages for the * SSL Server module (MBEDTLS_SSL_SRV_C). * + * \deprecated This option is deprecated and will be removed in a future + * version of Mbed TLS. + * * Uncomment this macro to enable support for SSLv2 Client Hello messages. */ //#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO @@ -1618,6 +1679,9 @@ * Requires: MBEDTLS_MD5_C * MBEDTLS_SHA1_C * + * \deprecated This option is deprecated and will be removed in a future + * version of Mbed TLS. + * * Comment this macro to disable support for SSL 3.0 */ //#define MBEDTLS_SSL_PROTO_SSL3 @@ -1791,8 +1855,8 @@ * * Fallback to old (pre-2.7), non-conforming implementation of the truncated * HMAC extension which also truncates the HMAC key. Note that this option is - * only meant for a transitory upgrade period and is likely to be removed in - * a future version of the library. + * only meant for a transitory upgrade period and will be removed in a future + * version of the library. * * \warning The old implementation is non-compliant and has a security weakness * (2^80 brute force attack on the HMAC key used for a single, @@ -1801,7 +1865,7 @@ * bandwidth, and (2) the peer is an Mbed TLS stack that doesn't use * the fixed implementation yet (pre-2.7). * - * \deprecated This option is deprecated and will likely be removed in a + * \deprecated This option is deprecated and will be removed in a * future version of Mbed TLS. * * Uncomment to fallback to old, non-compliant truncated HMAC implementation. @@ -1810,6 +1874,13 @@ */ //#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT +/** + * \def MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH + * + * Enable modifying the maximum I/O buffer size. + */ +//#define MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH + /** * \def MBEDTLS_THREADING_ALT * @@ -1838,8 +1909,8 @@ * Make the X.509 and TLS library use PSA for cryptographic operations, and * enable new APIs for using keys handled by PSA Crypto. * - * \note Development of this option is currently in progress, and parts - * of the X.509 and TLS modules are not ported to PSA yet. However, these parts + * \note Development of this option is currently in progress, and parts of Mbed + * TLS's X.509 and TLS modules are not ported to PSA yet. However, these parts * will still continue to work as usual, so enabling this option should not * break backwards compatibility. * @@ -2349,7 +2420,11 @@ * * 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. + * To use AES-128 instead, enable \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY above. + * + * \note To achieve a 256-bit security strength with CTR_DRBG, + * you must use AES-256 *and* use sufficient entropy. + * See ctr_drbg.h for more details. * * Module: library/ctr_drbg.c * Caller: @@ -2517,11 +2592,11 @@ /** * \def MBEDTLS_GCM_C * - * Enable the Galois/Counter Mode (GCM) for AES. + * Enable the Galois/Counter Mode (GCM). * * Module: library/gcm.c * - * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or MBEDTLS_ARIA_C * * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other * requisites are enabled as well. @@ -2828,7 +2903,10 @@ /** * \def MBEDTLS_PKCS11_C * - * Enable wrapper for PKCS#11 smartcard support. + * Enable wrapper for PKCS#11 smartcard support via the pkcs11-helper library. + * + * \deprecated This option is deprecated and will be removed in a future + * version of Mbed TLS. * * Module: library/pkcs11.c * Caller: library/pk.c @@ -2895,19 +2973,35 @@ * experiment using it, incompatible API changes are still possible, and some * parts may not have reached the same quality as the rest of Mbed TLS yet. * - * Module: crypto/library/psa_crypto.c + * Module: library/psa_crypto.c * * Requires: MBEDTLS_CTR_DRBG_C, MBEDTLS_ENTROPY_C * */ #define MBEDTLS_PSA_CRYPTO_C +/** + * \def MBEDTLS_PSA_CRYPTO_SE_C + * + * Enable secure element support in the Platform Security Architecture + * cryptography API. + * + * \warning This feature is not yet suitable for production. It is provided + * for API evaluation and testing purposes only. + * + * Module: library/psa_crypto_se.c + * + * Requires: MBEDTLS_PSA_CRYPTO_C, MBEDTLS_PSA_CRYPTO_STORAGE_C + * + */ +//#define MBEDTLS_PSA_CRYPTO_SE_C + /** * \def MBEDTLS_PSA_CRYPTO_STORAGE_C * * Enable the Platform Security Architecture persistent key storage. * - * Module: crypto/library/psa_crypto_storage.c + * Module: library/psa_crypto_storage.c * * Requires: MBEDTLS_PSA_CRYPTO_C, * either MBEDTLS_PSA_ITS_FILE_C or a native implementation of @@ -2921,10 +3015,9 @@ * Enable the emulation of the Platform Security Architecture * Internal Trusted Storage (PSA ITS) over files. * - * Module: crypto/library/psa_its_file.c + * Module: library/psa_its_file.c * * Requires: MBEDTLS_FS_IO - * */ //#define MBEDTLS_PSA_ITS_FILE_C @@ -3283,7 +3376,6 @@ //#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_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 */ //#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/ctr_drbg.h b/features/mbedtls/inc/mbedtls/ctr_drbg.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/ctr_drbg.h rename to features/mbedtls/inc/mbedtls/ctr_drbg.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/des.h b/features/mbedtls/inc/mbedtls/des.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/des.h rename to features/mbedtls/inc/mbedtls/des.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/dhm.h b/features/mbedtls/inc/mbedtls/dhm.h similarity index 99% rename from features/mbedtls/mbed-crypto/inc/mbedtls/dhm.h rename to features/mbedtls/inc/mbedtls/dhm.h index 831cfd74b8..6dcfadd82c 100644 --- a/features/mbedtls/mbed-crypto/inc/mbedtls/dhm.h +++ b/features/mbedtls/inc/mbedtls/dhm.h @@ -348,10 +348,11 @@ int mbedtls_dhm_self_test( int verbose ); #endif /** - * RFC 3526, RFC 5114 and RFC 7919 standardize a number of Diffie-Hellman - * groups, some of which are included here for use by Mbed TLS's SSL/TLS module - * and the user's convenience when configuring the Diffie-Hellman parameters by - * hand through Mbed TLS's \c mbedtls_ssl_conf_dh_param. + * RFC 3526, RFC 5114 and RFC 7919 standardize a number of + * Diffie-Hellman groups, some of which are included here + * for use within the SSL/TLS module and the user's convenience + * when configuring the Diffie-Hellman parameters by hand + * through \c mbedtls_ssl_conf_dh_param. * * The following lists the source of the above groups in the standards: * - RFC 5114 section 2.2: 2048-bit MODP Group with 224-bit Prime Order Subgroup diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/ecdh.h b/features/mbedtls/inc/mbedtls/ecdh.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/ecdh.h rename to features/mbedtls/inc/mbedtls/ecdh.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/ecdsa.h b/features/mbedtls/inc/mbedtls/ecdsa.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/ecdsa.h rename to features/mbedtls/inc/mbedtls/ecdsa.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/ecjpake.h b/features/mbedtls/inc/mbedtls/ecjpake.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/ecjpake.h rename to features/mbedtls/inc/mbedtls/ecjpake.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/ecp.h b/features/mbedtls/inc/mbedtls/ecp.h similarity index 98% rename from features/mbedtls/mbed-crypto/inc/mbedtls/ecp.h rename to features/mbedtls/inc/mbedtls/ecp.h index d04cc49b62..4c05b4fd0a 100644 --- a/features/mbedtls/mbed-crypto/inc/mbedtls/ecp.h +++ b/features/mbedtls/inc/mbedtls/ecp.h @@ -375,19 +375,19 @@ mbedtls_ecp_keypair; * 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 - * Mbed TLS 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 + * 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 - * Mbed TLS SSL module, restart is only enabled for specific - * sides and key exchanges (currently only for clients and - * ECDHE-ECDSA). + * 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). diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/ecp_internal.h b/features/mbedtls/inc/mbedtls/ecp_internal.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/ecp_internal.h rename to features/mbedtls/inc/mbedtls/ecp_internal.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/entropy.h b/features/mbedtls/inc/mbedtls/entropy.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/entropy.h rename to features/mbedtls/inc/mbedtls/entropy.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/entropy_poll.h b/features/mbedtls/inc/mbedtls/entropy_poll.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/entropy_poll.h rename to features/mbedtls/inc/mbedtls/entropy_poll.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/gcm.h b/features/mbedtls/inc/mbedtls/gcm.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/gcm.h rename to features/mbedtls/inc/mbedtls/gcm.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/havege.h b/features/mbedtls/inc/mbedtls/havege.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/havege.h rename to features/mbedtls/inc/mbedtls/havege.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/hkdf.h b/features/mbedtls/inc/mbedtls/hkdf.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/hkdf.h rename to features/mbedtls/inc/mbedtls/hkdf.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/hmac_drbg.h b/features/mbedtls/inc/mbedtls/hmac_drbg.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/hmac_drbg.h rename to features/mbedtls/inc/mbedtls/hmac_drbg.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/md.h b/features/mbedtls/inc/mbedtls/md.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/md.h rename to features/mbedtls/inc/mbedtls/md.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/md2.h b/features/mbedtls/inc/mbedtls/md2.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/md2.h rename to features/mbedtls/inc/mbedtls/md2.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/md4.h b/features/mbedtls/inc/mbedtls/md4.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/md4.h rename to features/mbedtls/inc/mbedtls/md4.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/md5.h b/features/mbedtls/inc/mbedtls/md5.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/md5.h rename to features/mbedtls/inc/mbedtls/md5.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/md_internal.h b/features/mbedtls/inc/mbedtls/md_internal.h similarity index 98% rename from features/mbedtls/mbed-crypto/inc/mbedtls/md_internal.h rename to features/mbedtls/inc/mbedtls/md_internal.h index bb876efc5b..0922dff9d3 100644 --- a/features/mbedtls/mbed-crypto/inc/mbedtls/md_internal.h +++ b/features/mbedtls/inc/mbedtls/md_internal.h @@ -79,7 +79,9 @@ extern const mbedtls_md_info_t mbedtls_sha224_info; extern const mbedtls_md_info_t mbedtls_sha256_info; #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) extern const mbedtls_md_info_t mbedtls_sha384_info; +#endif extern const mbedtls_md_info_t mbedtls_sha512_info; #endif diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/memory_buffer_alloc.h b/features/mbedtls/inc/mbedtls/memory_buffer_alloc.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/memory_buffer_alloc.h rename to features/mbedtls/inc/mbedtls/memory_buffer_alloc.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/nist_kw.h b/features/mbedtls/inc/mbedtls/nist_kw.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/nist_kw.h rename to features/mbedtls/inc/mbedtls/nist_kw.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/oid.h b/features/mbedtls/inc/mbedtls/oid.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/oid.h rename to features/mbedtls/inc/mbedtls/oid.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/padlock.h b/features/mbedtls/inc/mbedtls/padlock.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/padlock.h rename to features/mbedtls/inc/mbedtls/padlock.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/pem.h b/features/mbedtls/inc/mbedtls/pem.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/pem.h rename to features/mbedtls/inc/mbedtls/pem.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/pk.h b/features/mbedtls/inc/mbedtls/pk.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/pk.h rename to features/mbedtls/inc/mbedtls/pk.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/pk_internal.h b/features/mbedtls/inc/mbedtls/pk_internal.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/pk_internal.h rename to features/mbedtls/inc/mbedtls/pk_internal.h diff --git a/features/mbedtls/inc/mbedtls/pkcs11.h b/features/mbedtls/inc/mbedtls/pkcs11.h index d9f45db676..cf8d8c4297 100644 --- a/features/mbedtls/inc/mbedtls/pkcs11.h +++ b/features/mbedtls/inc/mbedtls/pkcs11.h @@ -47,6 +47,8 @@ extern "C" { #endif +#if defined(MBEDTLS_DEPRECATED_REMOVED) + /** * Context for PKCS #11 private keys. */ @@ -56,47 +58,71 @@ typedef struct mbedtls_pkcs11_context int len; } mbedtls_pkcs11_context; +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + /** * Initialize a mbedtls_pkcs11_context. * (Just making memory references valid.) + * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. */ -void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ); +MBEDTLS_DEPRECATED void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ); /** * Fill in a mbed TLS certificate, based on the given PKCS11 helper certificate. * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + * * \param cert X.509 certificate to fill * \param pkcs11h_cert PKCS #11 helper certificate * * \return 0 on success. */ -int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11h_cert ); +MBEDTLS_DEPRECATED int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, + pkcs11h_certificate_t pkcs11h_cert ); /** * Set up a mbedtls_pkcs11_context storing the given certificate. Note that the * mbedtls_pkcs11_context will take over control of the certificate, freeing it when * done. * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + * * \param priv_key Private key structure to fill. * \param pkcs11_cert PKCS #11 helper certificate * * \return 0 on success */ -int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key, - pkcs11h_certificate_t pkcs11_cert ); +MBEDTLS_DEPRECATED int mbedtls_pkcs11_priv_key_bind( + mbedtls_pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ); /** * Free the contents of the given private key context. Note that the structure * itself is not freed. * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + * * \param priv_key Private key structure to cleanup */ -void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ); +MBEDTLS_DEPRECATED void mbedtls_pkcs11_priv_key_free( + mbedtls_pkcs11_context *priv_key ); /** * \brief Do an RSA private key decrypt, then remove the message * padding * + * \deprecated This function is deprecated and will be removed in a future + * version of the library. + * * \param ctx PKCS #11 context * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature * \param input buffer holding the encrypted data @@ -110,15 +136,18 @@ void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ); * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise * an error is thrown. */ -int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ); +MBEDTLS_DEPRECATED int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); /** * \brief Do a private RSA to sign a message digest * + * \deprecated This function is deprecated and will be removed in a future + * version of the library. + * * \param ctx PKCS #11 context * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) @@ -132,28 +161,58 @@ int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, * \note The "sig" buffer must be as large as the size * of ctx->N (eg. 128 bytes if RSA-1024 is used). */ -int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); +MBEDTLS_DEPRECATED int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); /** * SSL/TLS wrappers for PKCS#11 functions + * + * \deprecated This function is deprecated and will be removed in a future + * version of the library. */ -static inline int mbedtls_ssl_pkcs11_decrypt( void *ctx, int mode, size_t *olen, - const unsigned char *input, unsigned char *output, - size_t output_max_len ) +MBEDTLS_DEPRECATED static inline int mbedtls_ssl_pkcs11_decrypt( void *ctx, + int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ) { return mbedtls_pkcs11_decrypt( (mbedtls_pkcs11_context *) ctx, mode, olen, input, output, output_max_len ); } -static inline int mbedtls_ssl_pkcs11_sign( void *ctx, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, - const unsigned char *hash, unsigned char *sig ) +/** + * \brief This function signs a message digest using RSA. + * + * \deprecated This function is deprecated and will be removed in a future + * version of the library. + * + * \param ctx The PKCS #11 context. + * \param f_rng The RNG function. This parameter is unused. + * \param p_rng The RNG context. This parameter is unused. + * \param mode The operation to run. This must be set to + * MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's + * signature. + * \param md_alg The message digest algorithm. One of the MBEDTLS_MD_XXX + * must be passed to this function and MBEDTLS_MD_NONE can be + * used for signing raw data. + * \param hashlen The message digest length (for MBEDTLS_MD_NONE only). + * \param hash The buffer holding the message digest. + * \param sig The buffer that will hold the ciphertext. + * + * \return \c 0 if the signing operation was successful. + * \return A non-zero error code on failure. + * + * \note The \p sig buffer must be as large as the size of + * ctx->N. For example, 128 bytes if RSA-1024 is + * used. + */ +MBEDTLS_DEPRECATED static inline int mbedtls_ssl_pkcs11_sign( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ) { ((void) f_rng); ((void) p_rng); @@ -161,11 +220,25 @@ static inline int mbedtls_ssl_pkcs11_sign( void *ctx, hashlen, hash, sig ); } -static inline size_t mbedtls_ssl_pkcs11_key_len( void *ctx ) +/** + * This function gets the length of the private key. + * + * \deprecated This function is deprecated and will be removed in a future + * version of the library. + * + * \param ctx The PKCS #11 context. + * + * \return The length of the private key. + */ +MBEDTLS_DEPRECATED static inline size_t mbedtls_ssl_pkcs11_key_len( void *ctx ) { return ( (mbedtls_pkcs11_context *) ctx )->len; } +#undef MBEDTLS_DEPRECATED + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + #ifdef __cplusplus } #endif diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/pkcs12.h b/features/mbedtls/inc/mbedtls/pkcs12.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/pkcs12.h rename to features/mbedtls/inc/mbedtls/pkcs12.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/pkcs5.h b/features/mbedtls/inc/mbedtls/pkcs5.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/pkcs5.h rename to features/mbedtls/inc/mbedtls/pkcs5.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/platform.h b/features/mbedtls/inc/mbedtls/platform.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/platform.h rename to features/mbedtls/inc/mbedtls/platform.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/platform_time.h b/features/mbedtls/inc/mbedtls/platform_time.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/platform_time.h rename to features/mbedtls/inc/mbedtls/platform_time.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/platform_util.h b/features/mbedtls/inc/mbedtls/platform_util.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/platform_util.h rename to features/mbedtls/inc/mbedtls/platform_util.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/poly1305.h b/features/mbedtls/inc/mbedtls/poly1305.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/poly1305.h rename to features/mbedtls/inc/mbedtls/poly1305.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/psa_util.h b/features/mbedtls/inc/mbedtls/psa_util.h similarity index 71% rename from features/mbedtls/mbed-crypto/inc/mbedtls/psa_util.h rename to features/mbedtls/inc/mbedtls/psa_util.h index 2e7393b3ce..513bc5feb7 100644 --- a/features/mbedtls/mbed-crypto/inc/mbedtls/psa_util.h +++ b/features/mbedtls/inc/mbedtls/psa_util.h @@ -160,81 +160,96 @@ static inline psa_algorithm_t mbedtls_psa_translate_md( mbedtls_md_type_t md_alg /* Translations for ECC. */ static inline int mbedtls_psa_get_ecc_oid_from_id( - psa_ecc_curve_t curve, char const **oid, size_t *oid_len ) + psa_ecc_curve_t curve, size_t bits, + char const **oid, size_t *oid_len ) { switch( curve ) { + case PSA_ECC_CURVE_SECP_R1: + switch( bits ) + { #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) - case PSA_ECC_CURVE_SECP192R1: - *oid = MBEDTLS_OID_EC_GRP_SECP192R1; - *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192R1 ); - return( 0 ); + case 192: + *oid = MBEDTLS_OID_EC_GRP_SECP192R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192R1 ); + return( 0 ); #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) - case PSA_ECC_CURVE_SECP224R1: - *oid = MBEDTLS_OID_EC_GRP_SECP224R1; - *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224R1 ); - return( 0 ); + case 224: + *oid = MBEDTLS_OID_EC_GRP_SECP224R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224R1 ); + return( 0 ); #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) - case PSA_ECC_CURVE_SECP256R1: - *oid = MBEDTLS_OID_EC_GRP_SECP256R1; - *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256R1 ); - return( 0 ); + case 256: + *oid = MBEDTLS_OID_EC_GRP_SECP256R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256R1 ); + return( 0 ); #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) - case PSA_ECC_CURVE_SECP384R1: - *oid = MBEDTLS_OID_EC_GRP_SECP384R1; - *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP384R1 ); - return( 0 ); + case 384: + *oid = MBEDTLS_OID_EC_GRP_SECP384R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP384R1 ); + return( 0 ); #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) - case PSA_ECC_CURVE_SECP521R1: - *oid = MBEDTLS_OID_EC_GRP_SECP521R1; - *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP521R1 ); - return( 0 ); + case 521: + *oid = MBEDTLS_OID_EC_GRP_SECP521R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP521R1 ); + return( 0 ); #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + } + break; + case PSA_ECC_CURVE_SECP_K1: + switch( bits ) + { #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) - case PSA_ECC_CURVE_SECP192K1: - *oid = MBEDTLS_OID_EC_GRP_SECP192K1; - *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192K1 ); - return( 0 ); + case 192: + *oid = MBEDTLS_OID_EC_GRP_SECP192K1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192K1 ); + return( 0 ); #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) - case PSA_ECC_CURVE_SECP224K1: - *oid = MBEDTLS_OID_EC_GRP_SECP224K1; - *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224K1 ); - return( 0 ); + case 224: + *oid = MBEDTLS_OID_EC_GRP_SECP224K1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224K1 ); + return( 0 ); #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) - case PSA_ECC_CURVE_SECP256K1: - *oid = MBEDTLS_OID_EC_GRP_SECP256K1; - *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256K1 ); - return( 0 ); + case 256: + *oid = MBEDTLS_OID_EC_GRP_SECP256K1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256K1 ); + return( 0 ); #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + } + break; + case PSA_ECC_CURVE_BRAINPOOL_P_R1: + switch( bits ) + { #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) - case PSA_ECC_CURVE_BRAINPOOL_P256R1: - *oid = MBEDTLS_OID_EC_GRP_BP256R1; - *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP256R1 ); - return( 0 ); + case 256: + *oid = MBEDTLS_OID_EC_GRP_BP256R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP256R1 ); + return( 0 ); #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) - case PSA_ECC_CURVE_BRAINPOOL_P384R1: - *oid = MBEDTLS_OID_EC_GRP_BP384R1; - *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP384R1 ); - return( 0 ); + case 384: + *oid = MBEDTLS_OID_EC_GRP_BP384R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP384R1 ); + return( 0 ); #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) - case PSA_ECC_CURVE_BRAINPOOL_P512R1: - *oid = MBEDTLS_OID_EC_GRP_BP512R1; - *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP512R1 ); - return( 0 ); + case 512: + *oid = MBEDTLS_OID_EC_GRP_BP512R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP512R1 ); + return( 0 ); #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ - default: - (void) oid; - (void) oid_len; - return( -1 ); + } + break; } + (void) oid; + (void) oid_len; + return( -1 ); } #define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH 1 @@ -317,67 +332,6 @@ static inline int mbedtls_psa_get_ecc_oid_from_id( #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ -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 ) @@ -411,13 +365,18 @@ static inline int mbedtls_psa_err_translate_pk( psa_status_t status ) /* This function transforms an ECC group identifier from * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 * into a PSA ECC group identifier. */ -static inline psa_ecc_curve_t mbedtls_psa_parse_tls_ecc_group( - uint16_t tls_ecc_grp_reg_id ) +#if defined(MBEDTLS_ECP_C) +static inline psa_key_type_t mbedtls_psa_parse_tls_ecc_group( + uint16_t tls_ecc_grp_reg_id, size_t *bits ) { - /* The PSA identifiers are currently aligned with those from - * the TLS Supported Groups registry, so no conversion is necessary. */ - return( (psa_ecc_curve_t) tls_ecc_grp_reg_id ); + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_tls_id( tls_ecc_grp_reg_id ); + if( curve_info == NULL ) + return( 0 ); + return( PSA_KEY_TYPE_ECC_KEY_PAIR( + mbedtls_ecc_group_to_psa( curve_info->grp_id, bits ) ) ); } +#endif /* MBEDTLS_ECP_C */ /* This function takes a buffer holding an EC public key * exported through psa_export_public_key(), and converts @@ -444,15 +403,12 @@ static inline int mbedtls_psa_tls_psa_ec_to_ecpoint( unsigned char *src, * exchanges) and converts it into a format that the PSA key * agreement API understands. */ -static inline int mbedtls_psa_tls_ecpoint_to_psa_ec( psa_ecc_curve_t curve, - unsigned char const *src, +static inline int mbedtls_psa_tls_ecpoint_to_psa_ec( unsigned char const *src, size_t srclen, unsigned char *dst, size_t dstlen, size_t *olen ) { - ((void) curve); - if( srclen > dstlen ) return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/ripemd160.h b/features/mbedtls/inc/mbedtls/ripemd160.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/ripemd160.h rename to features/mbedtls/inc/mbedtls/ripemd160.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/rsa.h b/features/mbedtls/inc/mbedtls/rsa.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/rsa.h rename to features/mbedtls/inc/mbedtls/rsa.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/rsa_internal.h b/features/mbedtls/inc/mbedtls/rsa_internal.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/rsa_internal.h rename to features/mbedtls/inc/mbedtls/rsa_internal.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/sha1.h b/features/mbedtls/inc/mbedtls/sha1.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/sha1.h rename to features/mbedtls/inc/mbedtls/sha1.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/sha256.h b/features/mbedtls/inc/mbedtls/sha256.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/sha256.h rename to features/mbedtls/inc/mbedtls/sha256.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/sha512.h b/features/mbedtls/inc/mbedtls/sha512.h similarity index 93% rename from features/mbedtls/mbed-crypto/inc/mbedtls/sha512.h rename to features/mbedtls/inc/mbedtls/sha512.h index 48923e5bc6..8e54ce01a7 100644 --- a/features/mbedtls/mbed-crypto/inc/mbedtls/sha512.h +++ b/features/mbedtls/inc/mbedtls/sha512.h @@ -59,8 +59,10 @@ typedef struct mbedtls_sha512_context uint64_t total[2]; /*!< The number of Bytes processed. */ uint64_t state[8]; /*!< The intermediate digest state. */ unsigned char buffer[128]; /*!< The data block being processed. */ +#if !defined(MBEDTLS_SHA512_NO_SHA384) int is384; /*!< Determines which function to use: 0: Use SHA-512, or 1: Use SHA-384. */ +#endif } mbedtls_sha512_context; @@ -101,7 +103,11 @@ void mbedtls_sha512_clone( mbedtls_sha512_context *dst, * * \param ctx The SHA-512 context to use. This must be initialized. * \param is384 Determines which function to use. This must be - * either \c for SHA-512, or \c 1 for SHA-384. + * either \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must + * be \c 0, or the function will return + * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. * * \return \c 0 on success. * \return A negative error code on failure. @@ -169,6 +175,9 @@ int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, * \param ctx The SHA-512 context to use. This must be initialized. * \param is384 Determines which function to use. This must be either * \c 0 for SHA-512 or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must + * be \c 0, or the function will fail to work. */ MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ); @@ -239,6 +248,10 @@ MBEDTLS_DEPRECATED void mbedtls_sha512_process( * \param is384 Determines which function to use. This must be either * \c 0 for SHA-512, or \c 1 for SHA-384. * + * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must + * be \c 0, or the function will return + * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. + * * \return \c 0 on success. * \return A negative error code on failure. */ @@ -273,6 +286,9 @@ int mbedtls_sha512_ret( const unsigned char *input, * be a writable buffer of length \c 64 Bytes. * \param is384 Determines which function to use. This must be either * \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must + * be \c 0, or the function will fail to work. */ MBEDTLS_DEPRECATED void mbedtls_sha512( const unsigned char *input, size_t ilen, diff --git a/features/mbedtls/inc/mbedtls/ssl.h b/features/mbedtls/inc/mbedtls/ssl.h index 655f59d328..1c98a5e5a8 100644 --- a/features/mbedtls/inc/mbedtls/ssl.h +++ b/features/mbedtls/inc/mbedtls/ssl.h @@ -825,7 +825,7 @@ typedef int mbedtls_ssl_async_resume_t( mbedtls_ssl_context *ssl, typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl ); #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) && \ +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) #define MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN 48 #if defined(MBEDTLS_SHA256_C) @@ -841,7 +841,7 @@ typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl ); /* This is already checked in check_config.h, but be sure. */ #error "Bad configuration - need SHA-1, SHA-256 or SHA-512 enabled to compute digest of peer CRT." #endif -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED && +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /* @@ -937,7 +937,7 @@ struct mbedtls_ssl_config void *p_vrfy; /*!< context for X.509 verify calllback */ #endif -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) /** Callback to retrieve PSK key from identity */ int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); void *p_psk; /*!< context for PSK callback */ @@ -1000,7 +1000,7 @@ struct mbedtls_ssl_config void *p_async_config_data; /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */ #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) const int *sig_hashes; /*!< allowed signature hashes */ #endif @@ -1013,7 +1013,7 @@ struct mbedtls_ssl_config mbedtls_mpi dhm_G; /*!< generator for DHM */ #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_handle_t psk_opaque; /*!< PSA key slot holding opaque PSK. @@ -1044,7 +1044,7 @@ struct mbedtls_ssl_config * 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 */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_SSL_ALPN) const char **alpn_list; /*!< ordered list of protocols */ @@ -1215,6 +1215,9 @@ struct mbedtls_ssl_context int in_msgtype; /*!< record header: message type */ size_t in_msglen; /*!< record header: message length */ size_t in_left; /*!< amount of data read so far */ +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len; /*!< length of input buffer */ +#endif #if defined(MBEDTLS_SSL_PROTO_DTLS) uint16_t in_epoch; /*!< DTLS epoch for incoming records */ size_t next_record_offset; /*!< offset of the next record in datagram @@ -1254,6 +1257,9 @@ struct mbedtls_ssl_context int out_msgtype; /*!< record header: message type */ size_t out_msglen; /*!< record header: message length */ size_t out_left; /*!< amount of data not yet written */ +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len; /*!< length of output buffer */ +#endif unsigned char cur_out_ctr[8]; /*!< Outgoing record sequence number. */ @@ -1323,21 +1329,40 @@ struct mbedtls_ssl_context #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) -#define MBEDTLS_SSL_CHANNEL_OUTBOUND 0 -#define MBEDTLS_SSL_CHANNEL_INBOUND 1 +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#define MBEDTLS_SSL_CHANNEL_OUTBOUND MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( 0 ) +#define MBEDTLS_SSL_CHANNEL_INBOUND MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( 1 ) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_WARNING */ + +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_init)( + mbedtls_ssl_context *ssl, + const unsigned char *key_enc, const unsigned char *key_dec, + size_t keylen, + const unsigned char *iv_enc, const unsigned char *iv_dec, + size_t ivlen, + const unsigned char *mac_enc, const unsigned char *mac_dec, + size_t maclen); +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_activate)( + mbedtls_ssl_context *ssl, + int direction ); +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_reset)( + mbedtls_ssl_context *ssl ); +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_write)( + mbedtls_ssl_context *ssl ); +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_read)( + mbedtls_ssl_context *ssl ); +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_finish)( + mbedtls_ssl_context *ssl ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ -extern int (*mbedtls_ssl_hw_record_init)(mbedtls_ssl_context *ssl, - const unsigned char *key_enc, const unsigned char *key_dec, - size_t keylen, - const unsigned char *iv_enc, const unsigned char *iv_dec, - size_t ivlen, - const unsigned char *mac_enc, const unsigned char *mac_dec, - size_t maclen); -extern int (*mbedtls_ssl_hw_record_activate)(mbedtls_ssl_context *ssl, int direction); -extern int (*mbedtls_ssl_hw_record_reset)(mbedtls_ssl_context *ssl); -extern int (*mbedtls_ssl_hw_record_write)(mbedtls_ssl_context *ssl); -extern int (*mbedtls_ssl_hw_record_read)(mbedtls_ssl_context *ssl); -extern int (*mbedtls_ssl_hw_record_finish)(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ /** @@ -2649,7 +2674,7 @@ int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, mbedtls_pk_context *pk_key ); #endif /* MBEDTLS_X509_CRT_PARSE_C */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) /** * \brief Configure a pre-shared key (PSK) and identity * to be used in PSK-based ciphersuites. @@ -2796,7 +2821,7 @@ void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t), void *p_psk ); -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) @@ -2901,7 +2926,7 @@ void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, const mbedtls_ecp_group_id *curves ); #endif /* MBEDTLS_ECP_C */ -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /** * \brief Set the allowed hashes for signatures during the handshake. * (Default: all available hashes except MD5.) @@ -2922,7 +2947,7 @@ void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, */ void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, const int *hashes ); -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /** @@ -3169,7 +3194,7 @@ void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems * \warning Use of RC4 in DTLS/TLS has been prohibited by RFC 7465 * for security reasons. Use at your own risk. * - * \note This function is deprecated and will likely be removed in + * \note This function is deprecated and will be removed in * a future version of the library. * RC4 is disabled by default at compile time and needs to be * actively enabled for use with legacy systems. @@ -3498,18 +3523,61 @@ int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) /** - * \brief Return the maximum fragment length (payload, in bytes). - * This is the value negotiated with peer if any, - * or the locally configured value. + * \brief Return the maximum fragment length (payload, in bytes) for + * the output buffer. For the client, this is the configured + * value. For the server, it is the minimum of two - the + * configured value and the negotiated one. * * \sa mbedtls_ssl_conf_max_frag_len() * \sa mbedtls_ssl_get_max_record_payload() * * \param ssl SSL context * - * \return Current maximum fragment length. + * \return Current maximum fragment length for the output buffer. */ -size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ); +size_t mbedtls_ssl_get_output_max_frag_len( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the maximum fragment length (payload, in bytes) for + * the input buffer. This is the negotiated maximum fragment + * length, or, if there is none, MBEDTLS_SSL_MAX_CONTENT_LEN. + * If it is not defined either, the value is 2^14. This function + * works as its predecessor, \c mbedtls_ssl_get_max_frag_len(). + * + * \sa mbedtls_ssl_conf_max_frag_len() + * \sa mbedtls_ssl_get_max_record_payload() + * + * \param ssl SSL context + * + * \return Current maximum fragment length for the output buffer. + */ +size_t mbedtls_ssl_get_input_max_frag_len( const mbedtls_ssl_context *ssl ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief This function is a deprecated approach to getting the max + * fragment length. Its an alias for + * \c mbedtls_ssl_get_output_max_frag_len(), as the behaviour + * is the same. See \c mbedtls_ssl_get_output_max_frag_len() for + * more detail. + * + * \sa mbedtls_ssl_get_input_max_frag_len() + * \sa mbedtls_ssl_get_output_max_frag_len() + * + * \param ssl SSL context + * + * \return Current maximum fragment length for the output buffer. + */ +MBEDTLS_DEPRECATED size_t mbedtls_ssl_get_max_frag_len( + const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ /** @@ -3530,7 +3598,8 @@ size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ); * when record compression is enabled. * * \sa mbedtls_ssl_set_mtu() - * \sa mbedtls_ssl_get_max_frag_len() + * \sa mbedtls_ssl_get_output_max_frag_len() + * \sa mbedtls_ssl_get_input_max_frag_len() * \sa mbedtls_ssl_get_record_expansion() * * \param ssl SSL context @@ -3714,7 +3783,14 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); * * \return The (positive) number of bytes read if successful. * \return \c 0 if the read end of the underlying transport was closed - * - in this case you must stop using the context (see below). + * without sending a CloseNotify beforehand, which might happen + * because of various reasons (internal error of an underlying + * stack, non-conformant peer not sending a CloseNotify and + * such) - in this case you must stop using the context + * (see below). + * \return #MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY if the underlying + * transport is still functional, but the peer has + * acknowledged to not send anything anymore. * \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 @@ -3831,8 +3907,8 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) * or negotiated with the peer), then: * - with TLS, less bytes than requested are written. * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. - * \c mbedtls_ssl_get_max_frag_len() may be used to query the - * active maximum fragment length. + * \c mbedtls_ssl_get_output_max_frag_len() may be used to + * query the active maximum fragment length. * * \note Attempting to write 0 bytes will result in an empty TLS * application record being sent. diff --git a/features/mbedtls/inc/mbedtls/ssl_ciphersuites.h b/features/mbedtls/inc/mbedtls/ssl_ciphersuites.h index 5505e52150..7fbafa48d4 100644 --- a/features/mbedtls/inc/mbedtls/ssl_ciphersuites.h +++ b/features/mbedtls/inc/mbedtls/ssl_ciphersuites.h @@ -312,7 +312,7 @@ typedef enum { defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED +#define MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED #endif /* Key exchanges allowing client certificate requests */ @@ -322,28 +322,28 @@ typedef enum { defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED +#define MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED #endif /* Key exchanges involving server signature in ServerKeyExchange */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED +#define MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED #endif /* Key exchanges using ECDH */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED +#define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED #endif /* Key exchanges that don't involve ephemeral keys */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED + defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED #endif /* Key exchanges that involve ephemeral keys */ @@ -353,7 +353,7 @@ typedef enum { defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED +#define MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED #endif /* Key exchanges using a PSK */ @@ -361,20 +361,20 @@ typedef enum { defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED +#define MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED #endif /* Key exchanges using DHE */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED +#define MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED #endif /* Key exchanges using ECDHE */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED +#define MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED #endif typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t; @@ -417,7 +417,7 @@ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphers int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ); int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ); -#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED) static inline int mbedtls_ssl_ciphersuite_has_pfs( const mbedtls_ssl_ciphersuite_t *info ) { switch( info->key_exchange ) @@ -434,9 +434,9 @@ static inline int mbedtls_ssl_ciphersuite_has_pfs( const mbedtls_ssl_ciphersuite return( 0 ); } } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) static inline int mbedtls_ssl_ciphersuite_no_pfs( const mbedtls_ssl_ciphersuite_t *info ) { switch( info->key_exchange ) @@ -452,9 +452,9 @@ static inline int mbedtls_ssl_ciphersuite_no_pfs( const mbedtls_ssl_ciphersuite_ return( 0 ); } } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) static inline int mbedtls_ssl_ciphersuite_uses_ecdh( const mbedtls_ssl_ciphersuite_t *info ) { switch( info->key_exchange ) @@ -467,7 +467,7 @@ static inline int mbedtls_ssl_ciphersuite_uses_ecdh( const mbedtls_ssl_ciphersui return( 0 ); } } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */ static inline int mbedtls_ssl_ciphersuite_cert_req_allowed( const mbedtls_ssl_ciphersuite_t *info ) { @@ -504,7 +504,7 @@ static inline int mbedtls_ssl_ciphersuite_uses_srv_cert( const mbedtls_ssl_ciphe } } -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) static inline int mbedtls_ssl_ciphersuite_uses_dhe( const mbedtls_ssl_ciphersuite_t *info ) { switch( info->key_exchange ) @@ -517,9 +517,9 @@ static inline int mbedtls_ssl_ciphersuite_uses_dhe( const mbedtls_ssl_ciphersuit return( 0 ); } } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) static inline int mbedtls_ssl_ciphersuite_uses_ecdhe( const mbedtls_ssl_ciphersuite_t *info ) { switch( info->key_exchange ) @@ -533,9 +533,9 @@ static inline int mbedtls_ssl_ciphersuite_uses_ecdhe( const mbedtls_ssl_ciphersu return( 0 ); } } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) */ -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) static inline int mbedtls_ssl_ciphersuite_uses_server_signature( const mbedtls_ssl_ciphersuite_t *info ) { switch( info->key_exchange ) @@ -549,7 +549,7 @@ static inline int mbedtls_ssl_ciphersuite_uses_server_signature( const mbedtls_s return( 0 ); } } -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ #ifdef __cplusplus } diff --git a/features/mbedtls/inc/mbedtls/ssl_internal.h b/features/mbedtls/inc/mbedtls/ssl_internal.h index f703da99b4..f83d01454f 100644 --- a/features/mbedtls/inc/mbedtls/ssl_internal.h +++ b/features/mbedtls/inc/mbedtls/ssl_internal.h @@ -113,7 +113,7 @@ defined(MBEDTLS_SSL_CLI_C) && \ defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -#define MBEDTLS_SSL__ECP_RESTARTABLE +#define MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED #endif #define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 @@ -238,7 +238,7 @@ implicit sequence number. */ #define MBEDTLS_SSL_HEADER_LEN 13 -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) #define MBEDTLS_SSL_IN_BUFFER_LEN \ ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_IN_PAYLOAD_LEN ) ) #else @@ -247,7 +247,7 @@ + ( MBEDTLS_SSL_CID_IN_LEN_MAX ) ) #endif -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) #define MBEDTLS_SSL_OUT_BUFFER_LEN \ ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_OUT_PAYLOAD_LEN ) ) #else @@ -256,6 +256,32 @@ + ( MBEDTLS_SSL_CID_OUT_LEN_MAX ) ) #endif +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) +static inline uint32_t mbedtls_ssl_get_output_buflen( const mbedtls_ssl_context *ctx ) +{ +#if defined (MBEDTLS_SSL_DTLS_CONNECTION_ID) + return (uint32_t) mbedtls_ssl_get_output_max_frag_len( ctx ) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD + + MBEDTLS_SSL_CID_OUT_LEN_MAX; +#else + return (uint32_t) mbedtls_ssl_get_output_max_frag_len( ctx ) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD; +#endif +} + +static inline uint32_t mbedtls_ssl_get_input_buflen( const mbedtls_ssl_context *ctx ) +{ +#if defined (MBEDTLS_SSL_DTLS_CONNECTION_ID) + return (uint32_t) mbedtls_ssl_get_input_max_frag_len( ctx ) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD + + MBEDTLS_SSL_CID_IN_LEN_MAX; +#else + return (uint32_t) mbedtls_ssl_get_input_max_frag_len( ctx ) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD; +#endif +} +#endif + #ifdef MBEDTLS_ZLIB_SUPPORT /* Compression buffer holds both IN and OUT buffers, so should be size of the larger */ #define MBEDTLS_SSL_COMPRESS_BUFFER_LEN ( \ @@ -278,7 +304,7 @@ extern "C" { #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* * Abstraction for a grid of allowed signature-hash-algorithm pairs. */ @@ -293,7 +319,7 @@ struct mbedtls_ssl_sig_hash_set_t mbedtls_md_type_t ecdsa; }; #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ typedef int mbedtls_ssl_tls_prf_cb( const unsigned char *secret, size_t slen, const char *label, @@ -309,7 +335,7 @@ struct mbedtls_ssl_handshake_params */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) mbedtls_ssl_sig_hash_set_t hash_algs; /*!< Set of suitable sig-hash pairs */ #endif #if defined(MBEDTLS_DHM_C) @@ -319,7 +345,8 @@ struct mbedtls_ssl_handshake_params mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */ #if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_ecc_curve_t ecdh_psa_curve; + psa_key_type_t ecdh_psa_type; + uint16_t ecdh_bits; psa_key_handle_t ecdh_psa_privkey; unsigned char ecdh_psa_peerkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; size_t ecdh_psa_peerkey_len; @@ -337,13 +364,13 @@ struct mbedtls_ssl_handshake_params defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */ #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_handle_t psk_opaque; /*!< Opaque PSK from the callback */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ unsigned char *psk; /*!< PSK from the callback */ size_t psk_len; /*!< Length of PSK from callback */ -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) @@ -353,7 +380,7 @@ struct mbedtls_ssl_handshake_params mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) 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 */ @@ -745,7 +772,7 @@ struct mbedtls_ssl_flight_item #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* Find an entry in a signature-hash set matching a given hash algorithm. */ mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, @@ -765,7 +792,7 @@ static inline void mbedtls_ssl_sig_hash_set_init( mbedtls_ssl_sig_hash_set_t *se } #endif /* MBEDTLS_SSL_PROTO_TLS1_2) && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ /** * \brief Free referenced items in an SSL transform context and clear @@ -892,7 +919,7 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ); void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *ciphersuite_info ); -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ); #endif @@ -910,7 +937,7 @@ int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ); int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ); #endif -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, mbedtls_md_type_t md ); #endif @@ -1062,4 +1089,46 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, mbedtls_ssl_transform *transform, mbedtls_record *rec ); +/* Length of the "epoch" field in the record header */ +static inline size_t mbedtls_ssl_ep_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 2 ); +#else + ((void) ssl); +#endif + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +void mbedtls_ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ); +int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_update_out_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ); +void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ); +#endif + +void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +size_t mbedtls_ssl_get_current_mtu( const mbedtls_ssl_context *ssl ); +void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + #endif /* ssl_internal.h */ diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/threading.h b/features/mbedtls/inc/mbedtls/threading.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/threading.h rename to features/mbedtls/inc/mbedtls/threading.h diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/timing.h b/features/mbedtls/inc/mbedtls/timing.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/timing.h rename to features/mbedtls/inc/mbedtls/timing.h diff --git a/features/mbedtls/inc/mbedtls/version.h b/features/mbedtls/inc/mbedtls/version.h index ae694eeda2..b89e36efd5 100644 --- a/features/mbedtls/inc/mbedtls/version.h +++ b/features/mbedtls/inc/mbedtls/version.h @@ -39,17 +39,17 @@ * Major, Minor, Patchlevel */ #define MBEDTLS_VERSION_MAJOR 2 -#define MBEDTLS_VERSION_MINOR 19 -#define MBEDTLS_VERSION_PATCH 1 +#define MBEDTLS_VERSION_MINOR 22 +#define MBEDTLS_VERSION_PATCH 0 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x02130100 -#define MBEDTLS_VERSION_STRING "2.19.1" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.19.1" +#define MBEDTLS_VERSION_NUMBER 0x02160000 +#define MBEDTLS_VERSION_STRING "2.22.0" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.22.0" #if defined(MBEDTLS_VERSION_C) diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/xtea.h b/features/mbedtls/inc/mbedtls/xtea.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/mbedtls/xtea.h rename to features/mbedtls/inc/mbedtls/xtea.h diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto.h b/features/mbedtls/inc/psa/crypto.h similarity index 99% rename from features/mbedtls/mbed-crypto/inc/psa/crypto.h rename to features/mbedtls/inc/psa/crypto.h index 9c610838e1..2b07b7471c 100644 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto.h +++ b/features/mbedtls/inc/psa/crypto.h @@ -932,7 +932,7 @@ psa_status_t psa_hash_compare(psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *hash, - const size_t hash_length); + size_t hash_length); /** The type of the state data structure for multipart hash operations. * @@ -1300,7 +1300,7 @@ psa_status_t psa_mac_verify(psa_key_handle_t handle, const uint8_t *input, size_t input_length, const uint8_t *mac, - const size_t mac_length); + size_t mac_length); /** The type of the state data structure for multipart MAC operations. * @@ -3502,10 +3502,10 @@ psa_status_t psa_key_derivation_output_bytes( * length is determined by the curve, and sets the mandatory bits * accordingly. That is: * - * - #PSA_ECC_CURVE_CURVE25519: draw a 32-byte string - * and process it as specified in RFC 7748 §5. - * - #PSA_ECC_CURVE_CURVE448: draw a 56-byte string - * and process it as specified in RFC 7748 §5. + * - Curve25519 (#PSA_ECC_CURVE_MONTGOMERY, 255 bits): draw a 32-byte + * string and process it as specified in RFC 7748 §5. + * - Curve448 (#PSA_ECC_CURVE_MONTGOMERY, 448 bits): draw a 56-byte + * string and process it as specified in RFC 7748 §5. * * - For key types for which the key is represented by a single sequence of * \p bits bits with constraints as to which bit sequences are acceptable, diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_accel_driver.h b/features/mbedtls/inc/psa/crypto_accel_driver.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/psa/crypto_accel_driver.h rename to features/mbedtls/inc/psa/crypto_accel_driver.h diff --git a/features/mbedtls/inc/psa/crypto_compat.h b/features/mbedtls/inc/psa/crypto_compat.h new file mode 100644 index 0000000000..1ed5f052b2 --- /dev/null +++ b/features/mbedtls/inc/psa/crypto_compat.h @@ -0,0 +1,196 @@ +/** + * \file psa/crypto_compat.h + * + * \brief PSA cryptography module: Backward compatibility aliases + * + * This header declares alternative names for macro and functions. + * New application code should not use these names. + * These names may be removed in a future version of Mbed Crypto. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + */ +/* + * Copyright (C) 2019, 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_COMPAT_H +#define PSA_CRYPTO_COMPAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +/* + * Mechanism for declaring deprecated values + */ +#if defined(MBEDTLS_DEPRECATED_WARNING) && !defined(MBEDTLS_PSA_DEPRECATED) +#define MBEDTLS_PSA_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_PSA_DEPRECATED +#endif + +typedef MBEDTLS_PSA_DEPRECATED size_t mbedtls_deprecated_size_t; +typedef MBEDTLS_PSA_DEPRECATED psa_status_t mbedtls_deprecated_psa_status_t; +typedef MBEDTLS_PSA_DEPRECATED psa_key_usage_t mbedtls_deprecated_psa_key_usage_t; +typedef MBEDTLS_PSA_DEPRECATED psa_ecc_curve_t mbedtls_deprecated_psa_ecc_curve_t; +typedef MBEDTLS_PSA_DEPRECATED psa_dh_group_t mbedtls_deprecated_psa_dh_group_t; + +#define MBEDTLS_DEPRECATED_CONSTANT( type, value ) \ + ( (mbedtls_deprecated_##type) ( value ) ) + +/* + * Deprecated PSA Crypto error code definitions (PSA Crypto API <= 1.0 beta2) + */ +#define PSA_ERROR_UNKNOWN_ERROR \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_GENERIC_ERROR ) +#define PSA_ERROR_OCCUPIED_SLOT \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_ALREADY_EXISTS ) +#define PSA_ERROR_EMPTY_SLOT \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_DOES_NOT_EXIST ) +#define PSA_ERROR_INSUFFICIENT_CAPACITY \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_INSUFFICIENT_DATA ) +#define PSA_ERROR_TAMPERING_DETECTED \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_CORRUPTION_DETECTED ) + +/* + * Deprecated PSA Crypto numerical encodings (PSA Crypto API <= 1.0 beta3) + */ +#define PSA_KEY_USAGE_SIGN \ + MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_SIGN_HASH ) +#define PSA_KEY_USAGE_VERIFY \ + MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_VERIFY_HASH ) + +/* + * Deprecated PSA Crypto size calculation macros (PSA Crypto API <= 1.0 beta3) + */ +#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \ + MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGNATURE_MAX_SIZE ) +#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) \ + MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) ) + +/* + * Deprecated PSA Crypto function names (PSA Crypto API <= 1.0 beta3) + */ +MBEDTLS_PSA_DEPRECATED static inline psa_status_t psa_asymmetric_sign( psa_key_handle_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ) +{ + return psa_sign_hash( key, alg, hash, hash_length, signature, signature_size, signature_length ); +} + +MBEDTLS_PSA_DEPRECATED static inline psa_status_t psa_asymmetric_verify( psa_key_handle_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ) +{ + return psa_verify_hash( key, alg, hash, hash_length, signature, signature_length ); +} + + + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* + * Size-specific elliptic curve and Diffie-Hellman group names + */ +#define PSA_ECC_CURVE_SECP160K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_K1 ) +#define PSA_ECC_CURVE_SECP192K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_K1 ) +#define PSA_ECC_CURVE_SECP224K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_K1 ) +#define PSA_ECC_CURVE_SECP256K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_K1 ) +#define PSA_ECC_CURVE_SECP160R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) +#define PSA_ECC_CURVE_SECP192R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) +#define PSA_ECC_CURVE_SECP224R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) +#define PSA_ECC_CURVE_SECP256R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) +#define PSA_ECC_CURVE_SECP384R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) +#define PSA_ECC_CURVE_SECP521R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 ) +#define PSA_ECC_CURVE_SECP160R2 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R2 ) +#define PSA_ECC_CURVE_SECT163K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) +#define PSA_ECC_CURVE_SECT233K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) +#define PSA_ECC_CURVE_SECT239K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) +#define PSA_ECC_CURVE_SECT283K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) +#define PSA_ECC_CURVE_SECT409K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) +#define PSA_ECC_CURVE_SECT571K1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 ) +#define PSA_ECC_CURVE_SECT163R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) +#define PSA_ECC_CURVE_SECT193R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) +#define PSA_ECC_CURVE_SECT233R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) +#define PSA_ECC_CURVE_SECT283R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) +#define PSA_ECC_CURVE_SECT409R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) +#define PSA_ECC_CURVE_SECT571R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 ) +#define PSA_ECC_CURVE_SECT163R2 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R2 ) +#define PSA_ECC_CURVE_SECT193R2 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R2 ) +#define PSA_ECC_CURVE_BRAINPOOL_P256R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_BRAINPOOL_P_R1 ) +#define PSA_ECC_CURVE_BRAINPOOL_P384R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_BRAINPOOL_P_R1 ) +#define PSA_ECC_CURVE_BRAINPOOL_P512R1 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_BRAINPOOL_P_R1 ) +#define PSA_ECC_CURVE_CURVE25519 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_MONTGOMERY ) +#define PSA_ECC_CURVE_CURVE448 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_MONTGOMERY ) + +#define PSA_DH_GROUP_FFDHE2048 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 ) +#define PSA_DH_GROUP_FFDHE3072 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 ) +#define PSA_DH_GROUP_FFDHE4096 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 ) +#define PSA_DH_GROUP_FFDHE6144 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 ) +#define PSA_DH_GROUP_FFDHE8192 \ + MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 ) + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_COMPAT_H */ diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_driver_common.h b/features/mbedtls/inc/psa/crypto_driver_common.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/psa/crypto_driver_common.h rename to features/mbedtls/inc/psa/crypto_driver_common.h diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_entropy_driver.h b/features/mbedtls/inc/psa/crypto_entropy_driver.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/psa/crypto_entropy_driver.h rename to features/mbedtls/inc/psa/crypto_entropy_driver.h diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h b/features/mbedtls/inc/psa/crypto_extra.h similarity index 92% rename from features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h rename to features/mbedtls/inc/psa/crypto_extra.h index 31e339c167..e9fa31189c 100644 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h +++ b/features/mbedtls/inc/psa/crypto_extra.h @@ -329,7 +329,7 @@ psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, * string. The length of the byte string is the length of the base prime `p` * in bytes. */ -#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x60020000) +#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x4002) /** DSA key pair (private and public key). * @@ -347,7 +347,7 @@ psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, * Add 1 to the resulting integer and use this as the private key *x*. * */ -#define PSA_KEY_TYPE_DSA_KEY_PAIR ((psa_key_type_t)0x70020000) +#define PSA_KEY_TYPE_DSA_KEY_PAIR ((psa_key_type_t)0x7002) /** Whether a key type is an DSA key (pair or public-only). */ #define PSA_KEY_TYPE_IS_DSA(type) \ @@ -418,9 +418,7 @@ psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_GROUP_CUSTOM), the group data comes * from domain parameters set by psa_set_key_domain_parameters(). */ -/* This value is a deprecated value meaning an explicit curve in the IANA - * registry. */ -#define PSA_DH_GROUP_CUSTOM ((psa_dh_group_t) 0xff01) +#define PSA_DH_GROUP_CUSTOM ((psa_dh_group_t) 0x7e) /** @@ -560,6 +558,50 @@ psa_status_t psa_get_key_domain_parameters( /**@}*/ +/** \defgroup psa_tls_helpers TLS helper functions + * @{ + */ + +#if defined(MBEDTLS_ECP_C) +#include + +/** Convert an ECC curve identifier from the Mbed TLS encoding to PSA. + * + * \note This function is provided solely for the convenience of + * Mbed TLS and may be removed at any time without notice. + * + * \param grpid An Mbed TLS elliptic curve identifier + * (`MBEDTLS_ECP_DP_xxx`). + * \param[out] bits On success, the bit size of the curve. + * + * \return The corresponding PSA elliptic curve identifier + * (`PSA_ECC_CURVE_xxx`). + * \return \c 0 on failure (\p grpid is not recognized). + */ +psa_ecc_curve_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid, + size_t *bits ); + +/** Convert an ECC curve identifier from the PSA encoding to Mbed TLS. + * + * \note This function is provided solely for the convenience of + * Mbed TLS and may be removed at any time without notice. + * + * \param curve A PSA elliptic curve identifier + * (`PSA_ECC_CURVE_xxx`). + * \param byte_length The byte-length of a private key on \p curve. + * + * \return The corresponding Mbed TLS elliptic curve identifier + * (`MBEDTLS_ECP_DP_xxx`). + * \return #MBEDTLS_ECP_DP_NONE if \c curve is not recognized. + * \return #MBEDTLS_ECP_DP_NONE if \p byte_length is not + * correct for \p curve. + */ +mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_curve_t curve, + size_t byte_length ); +#endif /* MBEDTLS_ECP_C */ + +/**@}*/ + #ifdef __cplusplus } #endif diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_platform.h b/features/mbedtls/inc/psa/crypto_platform.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/psa/crypto_platform.h rename to features/mbedtls/inc/psa/crypto_platform.h diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_se_driver.h b/features/mbedtls/inc/psa/crypto_se_driver.h similarity index 100% rename from features/mbedtls/mbed-crypto/inc/psa/crypto_se_driver.h rename to features/mbedtls/inc/psa/crypto_se_driver.h diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h b/features/mbedtls/inc/psa/crypto_sizes.h similarity index 93% rename from features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h rename to features/mbedtls/inc/psa/crypto_sizes.h index e7aef5580e..1f04222c24 100644 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h +++ b/features/mbedtls/inc/psa/crypto_sizes.h @@ -190,47 +190,6 @@ #define PSA_VENDOR_ECC_MAX_CURVE_BITS 0 #endif -/** Bit size associated with an elliptic curve. - * - * \param curve An elliptic curve (value of type #psa_ecc_curve_t). - * - * \return The size associated with \p curve, in bits. - * This may be 0 if the implementation does not support - * the specified curve. - */ -#define PSA_ECC_CURVE_BITS(curve) \ - ((curve) == PSA_ECC_CURVE_SECT163K1 ? 163 : \ - (curve) == PSA_ECC_CURVE_SECT163R1 ? 163 : \ - (curve) == PSA_ECC_CURVE_SECT163R2 ? 163 : \ - (curve) == PSA_ECC_CURVE_SECT193R1 ? 193 : \ - (curve) == PSA_ECC_CURVE_SECT193R2 ? 193 : \ - (curve) == PSA_ECC_CURVE_SECT233K1 ? 233 : \ - (curve) == PSA_ECC_CURVE_SECT233R1 ? 233 : \ - (curve) == PSA_ECC_CURVE_SECT239K1 ? 239 : \ - (curve) == PSA_ECC_CURVE_SECT283K1 ? 283 : \ - (curve) == PSA_ECC_CURVE_SECT283R1 ? 283 : \ - (curve) == PSA_ECC_CURVE_SECT409K1 ? 409 : \ - (curve) == PSA_ECC_CURVE_SECT409R1 ? 409 : \ - (curve) == PSA_ECC_CURVE_SECT571K1 ? 571 : \ - (curve) == PSA_ECC_CURVE_SECT571R1 ? 571 : \ - (curve) == PSA_ECC_CURVE_SECP160K1 ? 160 : \ - (curve) == PSA_ECC_CURVE_SECP160R1 ? 160 : \ - (curve) == PSA_ECC_CURVE_SECP160R2 ? 160 : \ - (curve) == PSA_ECC_CURVE_SECP192K1 ? 192 : \ - (curve) == PSA_ECC_CURVE_SECP192R1 ? 192 : \ - (curve) == PSA_ECC_CURVE_SECP224K1 ? 224 : \ - (curve) == PSA_ECC_CURVE_SECP224R1 ? 224 : \ - (curve) == PSA_ECC_CURVE_SECP256K1 ? 256 : \ - (curve) == PSA_ECC_CURVE_SECP256R1 ? 256 : \ - (curve) == PSA_ECC_CURVE_SECP384R1 ? 384 : \ - (curve) == PSA_ECC_CURVE_SECP521R1 ? 521 : \ - (curve) == PSA_ECC_CURVE_BRAINPOOL_P256R1 ? 256 : \ - (curve) == PSA_ECC_CURVE_BRAINPOOL_P384R1 ? 384 : \ - (curve) == PSA_ECC_CURVE_BRAINPOOL_P512R1 ? 512 : \ - (curve) == PSA_ECC_CURVE_CURVE25519 ? 255 : \ - (curve) == PSA_ECC_CURVE_CURVE448 ? 448 : \ - 0) - /** \def PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN * * This macro returns the maximum length of the PSK supported diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_types.h b/features/mbedtls/inc/psa/crypto_types.h similarity index 80% rename from features/mbedtls/mbed-crypto/inc/psa/crypto_types.h rename to features/mbedtls/inc/psa/crypto_types.h index c4f9acd460..d96c66e5c4 100644 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto_types.h +++ b/features/mbedtls/inc/psa/crypto_types.h @@ -63,85 +63,29 @@ typedef int32_t psa_status_t; /** \brief Encoding of a key type. */ -typedef uint32_t psa_key_type_t; +typedef uint16_t psa_key_type_t; -/** The type of PSA elliptic curve identifiers. +/** The type of PSA elliptic curve family identifiers. * * The curve identifier is required to create an ECC key using the * PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY() * macros. * - * The encoding of curve identifiers is taken from the - * TLS Supported Groups Registry (formerly known as the - * TLS EC Named Curve Registry) - * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 - * - * This specification defines identifiers for some of the curves in the IANA - * registry. Implementations that support other curves that are in the IANA - * registry should use the IANA value and a implementation-specific identifier. - * Implemenations that support non-IANA curves should use one of the following - * approaches for allocating a key type: - * - * 1. Select a ::psa_ecc_curve_t value in the range #PSA_ECC_CURVE_VENDOR_MIN to - * #PSA_ECC_CURVE_VENDOR_MAX, which is a subset of the IANA private use - * range. - * 2. Use a ::psa_key_type_t value that is vendor-defined. - * - * The first option is recommended. + * Values defined by this standard will never be in the range 0x80-0xff. + * Vendors who define additional families must use an encoding in this range. */ -typedef uint16_t psa_ecc_curve_t; +typedef uint8_t psa_ecc_curve_t; -/** The type of PSA Diffie-Hellman group identifiers. +/** The type of PSA Diffie-Hellman group family identifiers. * * The group identifier is required to create an Diffie-Hellman key using the * PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY() * macros. * - * The encoding of group identifiers is taken from the - * TLS Supported Groups Registry (formerly known as the - * TLS EC Named Curve Registry) - * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 - * - * This specification defines identifiers for some of the groups in the IANA - * registry. Implementations that support other groups that are in the IANA - * registry should use the IANA value and a implementation-specific identifier. - * Implemenations that support non-IANA groups should use one of the following - * approaches for allocating a key type: - * - * 1. Select a ::psa_dh_group_t value in the range #PSA_DH_GROUP_VENDOR_MIN to - * #PSA_DH_GROUP_VENDOR_MAX, which is a subset of the IANA private use - * range. - * 2. Select a ::psa_dh_group_t value from the named groups allocated for - * GREASE in the IETF draft specification. The GREASE specification and - * values are listed below. - * 3. Use a ::psa_key_type_t value that is vendor-defined. - * - * Option 1 or 2 are recommended. - * - * The current draft of the GREASE specification is - * https://datatracker.ietf.org/doc/draft-ietf-tls-grease - * - * The following GREASE values are allocated for named groups: - * \code - * 0x0A0A - * 0x1A1A - * 0x2A2A - * 0x3A3A - * 0x4A4A - * 0x5A5A - * 0x6A6A - * 0x7A7A - * 0x8A8A - * 0x9A9A - * 0xAAAA - * 0xBABA - * 0xCACA - * 0xDADA - * 0xEAEA - * 0xFAFA - * \endcode + * Values defined by this standard will never be in the range 0x80-0xff. + * Vendors who define additional families must use an encoding in this range. */ -typedef uint16_t psa_dh_group_t; +typedef uint8_t psa_dh_group_t; /** \brief Encoding of a cryptographic algorithm. * diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_values.h b/features/mbedtls/inc/psa/crypto_values.h similarity index 91% rename from features/mbedtls/mbed-crypto/inc/psa/crypto_values.h rename to features/mbedtls/inc/psa/crypto_values.h index dbe75ad85e..baaabff1e0 100644 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto_values.h +++ b/features/mbedtls/inc/psa/crypto_values.h @@ -282,7 +282,7 @@ * * Zero is not the encoding of any key type. */ -#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x00000000) +#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x0000) /** Vendor-defined key type flag. * @@ -291,15 +291,15 @@ * must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should * respect the bitwise structure used by standard encodings whenever practical. */ -#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x80000000) +#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x8000) -#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x70000000) -#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x40000000) -#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t)0x50000000) -#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t)0x60000000) -#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t)0x70000000) +#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x7000) +#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t)0x1000) +#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x2000) +#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t)0x4000) +#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t)0x7000) -#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x10000000) +#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x3000) /** Whether a key type is vendor-defined. * @@ -313,8 +313,8 @@ * This encompasses both symmetric keys and non-key data. */ #define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) \ - (((type) & PSA_KEY_TYPE_CATEGORY_MASK & ~(psa_key_type_t)0x10000000) == \ - PSA_KEY_TYPE_CATEGORY_SYMMETRIC) + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_RAW || \ + ((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC) /** Whether a key type is asymmetric: either a key pair or a public key. */ #define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \ @@ -357,7 +357,7 @@ * * A "key" of this type cannot be used for any cryptographic operation. * Applications may use this type to store arbitrary data in the keystore. */ -#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x50000001) +#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x1001) /** HMAC key. * @@ -367,21 +367,21 @@ * HMAC keys should generally have the same size as the underlying hash. * This size can be calculated with #PSA_HASH_SIZE(\c alg) where * \c alg is the HMAC algorithm or the underlying hash algorithm. */ -#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x51000000) +#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x1100) /** A secret for key derivation. * * The key policy determines which key derivation algorithm the key * can be used for. */ -#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x52000000) +#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x1200) /** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher. * * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or * 32 bytes (AES-256). */ -#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x40000001) +#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x2400) /** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES). * @@ -392,17 +392,17 @@ * deprecated and should only be used to decrypt legacy data. 3-key 3DES * is weak and deprecated and should only be used in legacy protocols. */ -#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x40000002) +#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x2301) /** Key for a cipher, AEAD or MAC algorithm based on the * Camellia block cipher. */ -#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x40000003) +#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x2403) /** Key for the RC4 stream cipher. * * Note that RC4 is weak and deprecated and should only be used in * legacy protocols. */ -#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x40000004) +#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x2002) /** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm. * @@ -411,19 +411,19 @@ * Implementations must support 12-byte nonces, may support 8-byte nonces, * and should reject other sizes. */ -#define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t)0x40000005) +#define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t)0x2004) /** RSA public key. */ -#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x60010000) +#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x4001) /** RSA key pair (private and public key). */ -#define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t)0x70010000) +#define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t)0x7001) /** Whether a key type is an RSA key (pair or public-only). */ #define PSA_KEY_TYPE_IS_RSA(type) \ (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) -#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x60030000) -#define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t)0x70030000) -#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x0000ffff) +#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x4100) +#define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t)0x7100) +#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x00ff) /** Elliptic curve key pair. * * \param curve A value of type ::psa_ecc_curve_t that identifies the @@ -458,70 +458,82 @@ ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \ 0)) -/* The encoding of curve identifiers is currently aligned with the - * TLS Supported Groups Registry (formerly known as the - * TLS EC Named Curve Registry) - * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 - * The values are defined by RFC 8422 and RFC 7027. */ -#define PSA_ECC_CURVE_SECT163K1 ((psa_ecc_curve_t) 0x0001) -#define PSA_ECC_CURVE_SECT163R1 ((psa_ecc_curve_t) 0x0002) -#define PSA_ECC_CURVE_SECT163R2 ((psa_ecc_curve_t) 0x0003) -#define PSA_ECC_CURVE_SECT193R1 ((psa_ecc_curve_t) 0x0004) -#define PSA_ECC_CURVE_SECT193R2 ((psa_ecc_curve_t) 0x0005) -#define PSA_ECC_CURVE_SECT233K1 ((psa_ecc_curve_t) 0x0006) -#define PSA_ECC_CURVE_SECT233R1 ((psa_ecc_curve_t) 0x0007) -#define PSA_ECC_CURVE_SECT239K1 ((psa_ecc_curve_t) 0x0008) -#define PSA_ECC_CURVE_SECT283K1 ((psa_ecc_curve_t) 0x0009) -#define PSA_ECC_CURVE_SECT283R1 ((psa_ecc_curve_t) 0x000a) -#define PSA_ECC_CURVE_SECT409K1 ((psa_ecc_curve_t) 0x000b) -#define PSA_ECC_CURVE_SECT409R1 ((psa_ecc_curve_t) 0x000c) -#define PSA_ECC_CURVE_SECT571K1 ((psa_ecc_curve_t) 0x000d) -#define PSA_ECC_CURVE_SECT571R1 ((psa_ecc_curve_t) 0x000e) -#define PSA_ECC_CURVE_SECP160K1 ((psa_ecc_curve_t) 0x000f) -#define PSA_ECC_CURVE_SECP160R1 ((psa_ecc_curve_t) 0x0010) -#define PSA_ECC_CURVE_SECP160R2 ((psa_ecc_curve_t) 0x0011) -#define PSA_ECC_CURVE_SECP192K1 ((psa_ecc_curve_t) 0x0012) -#define PSA_ECC_CURVE_SECP192R1 ((psa_ecc_curve_t) 0x0013) -#define PSA_ECC_CURVE_SECP224K1 ((psa_ecc_curve_t) 0x0014) -#define PSA_ECC_CURVE_SECP224R1 ((psa_ecc_curve_t) 0x0015) -#define PSA_ECC_CURVE_SECP256K1 ((psa_ecc_curve_t) 0x0016) -#define PSA_ECC_CURVE_SECP256R1 ((psa_ecc_curve_t) 0x0017) -#define PSA_ECC_CURVE_SECP384R1 ((psa_ecc_curve_t) 0x0018) -#define PSA_ECC_CURVE_SECP521R1 ((psa_ecc_curve_t) 0x0019) -#define PSA_ECC_CURVE_BRAINPOOL_P256R1 ((psa_ecc_curve_t) 0x001a) -#define PSA_ECC_CURVE_BRAINPOOL_P384R1 ((psa_ecc_curve_t) 0x001b) -#define PSA_ECC_CURVE_BRAINPOOL_P512R1 ((psa_ecc_curve_t) 0x001c) -/** Curve25519. +/** SEC Koblitz curves over prime fields. * - * This is the curve defined in Bernstein et al., - * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006. - * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve. + * This family comprises the following curves: + * secp192k1, secp224k1, secp256k1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf */ -#define PSA_ECC_CURVE_CURVE25519 ((psa_ecc_curve_t) 0x001d) -/** Curve448 - * - * This is the curve defined in Hamburg, - * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. - * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve. - */ -#define PSA_ECC_CURVE_CURVE448 ((psa_ecc_curve_t) 0x001e) +#define PSA_ECC_CURVE_SECP_K1 ((psa_ecc_curve_t) 0x17) -/** Minimum value for a vendor-defined ECC curve identifier +/** SEC random curves over prime fields. * - * The range for vendor-defined curve identifiers is a subset of the IANA - * registry private use range, `0xfe00` - `0xfeff`. + * This family comprises the following curves: + * secp192k1, secp224r1, secp256r1, secp384r1, secp521r1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf */ -#define PSA_ECC_CURVE_VENDOR_MIN ((psa_ecc_curve_t) 0xfe00) -/** Maximum value for a vendor-defined ECC curve identifier - * - * The range for vendor-defined curve identifiers is a subset of the IANA - * registry private use range, `0xfe00` - `0xfeff`. - */ -#define PSA_ECC_CURVE_VENDOR_MAX ((psa_ecc_curve_t) 0xfe7f) +#define PSA_ECC_CURVE_SECP_R1 ((psa_ecc_curve_t) 0x12) +/* SECP160R2 (SEC2 v1, obsolete) */ +#define PSA_ECC_CURVE_SECP_R2 ((psa_ecc_curve_t) 0x1b) -#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t)0x60040000) -#define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t)0x70040000) -#define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t)0x0000ffff) +/** SEC Koblitz curves over binary fields. + * + * This family comprises the following curves: + * sect163k1, sect233k1, sect239k1, sect283k1, sect409k1, sect571k1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_CURVE_SECT_K1 ((psa_ecc_curve_t) 0x27) + +/** SEC random curves over binary fields. + * + * This family comprises the following curves: + * sect163r1, sect233r1, sect283r1, sect409r1, sect571r1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_CURVE_SECT_R1 ((psa_ecc_curve_t) 0x22) + +/** SEC additional random curves over binary fields. + * + * This family comprises the following curve: + * sect163r2. + * It is defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_CURVE_SECT_R2 ((psa_ecc_curve_t) 0x2b) + +/** Brainpool P random curves. + * + * This family comprises the following curves: + * brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1, + * brainpoolP320r1, brainpoolP384r1, brainpoolP512r1. + * It is defined in RFC 5639. + */ +#define PSA_ECC_CURVE_BRAINPOOL_P_R1 ((psa_ecc_curve_t) 0x30) + +/** Curve25519 and Curve448. + * + * This family comprises the following Montgomery curves: + * - 255-bit: Bernstein et al., + * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006. + * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve. + * - 448-bit: Hamburg, + * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. + * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve. + */ +#define PSA_ECC_CURVE_MONTGOMERY ((psa_ecc_curve_t) 0x41) + +#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t)0x4200) +#define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t)0x7200) +#define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t)0x00ff) /** Diffie-Hellman key pair. * * \param group A value of type ::psa_dh_group_t that identifies the @@ -556,30 +568,16 @@ ((type) & PSA_KEY_TYPE_DH_GROUP_MASK) : \ 0)) -/* The encoding of group identifiers is currently aligned with the - * TLS Supported Groups Registry (formerly known as the - * TLS EC Named Curve Registry) - * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 - * The values are defined by RFC 7919. */ -#define PSA_DH_GROUP_FFDHE2048 ((psa_dh_group_t) 0x0100) -#define PSA_DH_GROUP_FFDHE3072 ((psa_dh_group_t) 0x0101) -#define PSA_DH_GROUP_FFDHE4096 ((psa_dh_group_t) 0x0102) -#define PSA_DH_GROUP_FFDHE6144 ((psa_dh_group_t) 0x0103) -#define PSA_DH_GROUP_FFDHE8192 ((psa_dh_group_t) 0x0104) - -/** Minimum value for a vendor-defined Diffie Hellman group identifier +/** Diffie-Hellman groups defined in RFC 7919 Appendix A. * - * The range for vendor-defined group identifiers is a subset of the IANA - * registry private use range, `0x01fc` - `0x01ff`. + * This family includes groups with the following key sizes (in bits): + * 2048, 3072, 4096, 6144, 8192. A given implementation may support + * all of these sizes or only a subset. */ -#define PSA_DH_GROUP_VENDOR_MIN ((psa_dh_group_t) 0x01fc) -/** Maximum value for a vendor-defined Diffie Hellman group identifier - * - * The range for vendor-defined group identifiers is a subset of the IANA - * registry private use range, `0x01fc` - `0x01ff`. - */ -#define PSA_DH_GROUP_VENDOR_MAX ((psa_dh_group_t) 0x01fd) +#define PSA_DH_GROUP_RFC7919 ((psa_dh_group_t) 0x03) +#define PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) \ + (((type) >> 8) & 7) /** The block size of a block cipher. * * \param type A cipher key type (value of type #psa_key_type_t). @@ -599,13 +597,9 @@ * \warning This macro may evaluate its argument multiple times. */ #define PSA_BLOCK_CIPHER_BLOCK_SIZE(type) \ - ( \ - (type) == PSA_KEY_TYPE_AES ? 16 : \ - (type) == PSA_KEY_TYPE_DES ? 8 : \ - (type) == PSA_KEY_TYPE_CAMELLIA ? 16 : \ - (type) == PSA_KEY_TYPE_ARC4 ? 1 : \ - (type) == PSA_KEY_TYPE_CHACHA20 ? 1 : \ - 0) + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \ + 1u << PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) : \ + 0u) /** Vendor-defined algorithm flag. * diff --git a/features/mbedtls/mbed-crypto/LICENSE b/features/mbedtls/mbed-crypto/LICENSE deleted file mode 100644 index 546a8e631f..0000000000 --- a/features/mbedtls/mbed-crypto/LICENSE +++ /dev/null @@ -1,2 +0,0 @@ -Unless specifically indicated otherwise in a file, files are licensed -under the Apache 2.0 license, as can be found in: apache-2.0.txt diff --git a/features/mbedtls/mbed-crypto/VERSION.txt b/features/mbedtls/mbed-crypto/VERSION.txt deleted file mode 100644 index 481f3641bd..0000000000 --- a/features/mbedtls/mbed-crypto/VERSION.txt +++ /dev/null @@ -1 +0,0 @@ -mbedcrypto-3.0.1 diff --git a/features/mbedtls/mbed-crypto/apache-2.0.txt b/features/mbedtls/mbed-crypto/apache-2.0.txt deleted file mode 100644 index d645695673..0000000000 --- a/features/mbedtls/mbed-crypto/apache-2.0.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/features/mbedtls/mbed-crypto/importer/Makefile b/features/mbedtls/mbed-crypto/importer/Makefile deleted file mode 100644 index 0964ab4e6d..0000000000 --- a/features/mbedtls/mbed-crypto/importer/Makefile +++ /dev/null @@ -1,131 +0,0 @@ -########################################################################### -# -# Copyright (c) 2016, 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. -# -########################################################################### - -# -# Use this file to import an Mbed Crypto release into Mbed OS as follows: -# -# 1) Set the CRYPTO_RELEASE variable to the required Mbed Crypto release -# tag -# 2) make update -# 3) make -# 4) commit and push changes via git -# - -# Set the Mbed Crypto release to import (this can/should be edited before -# import) -CRYPTO_RELEASE ?= mbedcrypto-3.0.1 -CRYPTO_REPO_URL ?= git@github.com:ARMmbed/mbed-crypto.git - -# Translate between Mbed Crypto namespace and Mbed OS namespace -TARGET_PREFIX:=.. -TARGET_INC:=$(TARGET_PREFIX)/inc -TARGET_SRC:=$(TARGET_PREFIX)/src - -TLS_SRC := \ - $(TARGET_SRC)/error.c \ - $(TARGET_SRC)/version.c \ - $(TARGET_SRC)/version_features.c \ - # end - -# A folder structure is introduced here for targets that have both a Secure -# Processing Environment (SPE) targets and Non-secure Processing Environment -# (NSPE). Documentation for each folder as follows: -# COMPONENT_PSA_SRV_IMPL - Include secure service implementation code. For -# example PSA Crypto or PSA Secure Time implementations -TARGET_SRV_IMPL:=$(TARGET_PREFIX)/platform/COMPONENT_PSA_SRV_IMPL -# COMPONENT_NSPE - Include code that compiles ONLY to the NSPE image and never -# compiles to the SPE image -TARGET_NSPE:=$(TARGET_SRV_IMPL)/COMPONENT_NSPE - -# Mbed Crypto source directory - hidden from mbed via TARGET_IGNORE -CRYPTO_DIR:=TARGET_IGNORE/mbed-crypto -CRYPTO_API:=$(CRYPTO_DIR)/include/psa -OLD_CRYPTO_API:=$(CRYPTO_DIR)/include/mbedtls -CRYPTO_GIT_CFG=$(CRYPTO_DIR)/.git/config - - -.PHONY: all rsync clean update - -all: rsync - -rsync: - # - # Copying Mbed Crypto headers to includes... - rm -rf $(TARGET_INC) - mkdir -p $(TARGET_INC) - rsync -a --delete --exclude='crypto_struct.h' $(CRYPTO_API) $(TARGET_INC)/ - # Copy legacy Mbed TLS crypto headers, excluding headers duplicated in - # Mbed TLS. - rsync -a --delete \ - --exclude='check_config.h' \ - --exclude='compat-1.3.h' \ - --exclude='config.h' \ - --exclude='error.h' \ - --exclude='version.h' \ - $(OLD_CRYPTO_API) $(TARGET_INC)/ - # - # Copying licenses - cp $(CRYPTO_DIR)/LICENSE $(TARGET_PREFIX)/ - # - # Copying Mbed Crypto into Mbed OS... - rm -rf $(TARGET_SRV_IMPL) - rm -rf $(TARGET_SRC) - - mkdir -p $(TARGET_SRV_IMPL) - mkdir -p $(TARGET_NSPE) - - rsync -a --delete $(CRYPTO_API)/crypto_struct.h $(TARGET_NSPE)/ - rsync -a --delete $(CRYPTO_DIR)/library/psa_*.c $(TARGET_SRV_IMPL)/ - rsync -a --delete $(CRYPTO_DIR)/library/psa_*.h $(TARGET_SRV_IMPL)/ - rsync -a --delete $(CRYPTO_DIR)/library/*.c $(TARGET_SRC)/ - # - # Remove PSA-specific C files (they go into $(TARGET_SRV_IMPL)) - rm -rf $(TARGET_SRC)/psa_*.c - # - # Remove files that duplicate Mbed TLS - rm -rf $(TLS_SRC) - -update: $(CRYPTO_GIT_CFG) - # - # Updating to the specified Mbed Crypto library version - # (If it is not an initial checkout we will start with the repository - # being in a detached head state) - git -C $(CRYPTO_DIR) fetch - # - # Checking out the required release - git -C $(CRYPTO_DIR) checkout $(CRYPTO_RELEASE) - # - # Update and checkout git submodules - git -C $(CRYPTO_DIR) submodule update --init --recursive - # - # Updating Mbed Crypto checked out version tag - git -C $(CRYPTO_DIR) describe --tags --abbrev=12 --dirty --always > $(TARGET_PREFIX)/VERSION.txt - -$(CRYPTO_GIT_CFG): - rm -rf $(CRYPTO_DIR) - git clone $(CRYPTO_REPO_URL) $(CRYPTO_DIR) - -clean: - rm -f $(TARGET_PREFIX)/LICENSE - rm -f $(TARGET_PREFIX)/VERSION.txt - rm -f $(TARGET_PREFIX)/AUTHORS.txt - rm -rf $(TARGET_INC) - rm -rf $(TARGET_SRC) - rm -rf $(CRYPTO_DIR) - rm -rf $(TARGET_SRV_IMPL) diff --git a/features/mbedtls/mbed-crypto/importer/TARGET_IGNORE/.gitignore b/features/mbedtls/mbed-crypto/importer/TARGET_IGNORE/.gitignore deleted file mode 100644 index 05fd348e28..0000000000 --- a/features/mbedtls/mbed-crypto/importer/TARGET_IGNORE/.gitignore +++ /dev/null @@ -1 +0,0 @@ -mbed-crypto diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_compat.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_compat.h deleted file mode 100644 index dc11da389f..0000000000 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto_compat.h +++ /dev/null @@ -1,109 +0,0 @@ -/** - * \file psa/crypto_compat.h - * - * \brief PSA cryptography module: Backward compatibility aliases - * - * This header declares alternative names for macro and functions. - * New application code should not use these names. - * These names may be removed in a future version of Mbed Crypto. - * - * \note This file may not be included directly. Applications must - * include psa/crypto.h. - */ -/* - * Copyright (C) 2019, 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_COMPAT_H -#define PSA_CRYPTO_COMPAT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) - -/* - * Mechanism for declaring deprecated values - */ -#if defined(MBEDTLS_DEPRECATED_WARNING) && !defined(MBEDTLS_PSA_DEPRECATED) -#define MBEDTLS_PSA_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_PSA_DEPRECATED -#endif - -typedef MBEDTLS_PSA_DEPRECATED size_t mbedtls_deprecated_size_t; -typedef MBEDTLS_PSA_DEPRECATED psa_status_t mbedtls_deprecated_psa_status_t; -typedef MBEDTLS_PSA_DEPRECATED psa_key_usage_t mbedtls_deprecated_psa_key_usage_t; - -#define MBEDTLS_DEPRECATED_CONSTANT( type, value ) \ - ( (mbedtls_deprecated_##type) ( value ) ) - -/* - * Deprecated PSA Crypto error code definitions (PSA Crypto API <= 1.0 beta2) - */ -#define PSA_ERROR_UNKNOWN_ERROR \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_GENERIC_ERROR ) -#define PSA_ERROR_OCCUPIED_SLOT \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_ALREADY_EXISTS ) -#define PSA_ERROR_EMPTY_SLOT \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_DOES_NOT_EXIST ) -#define PSA_ERROR_INSUFFICIENT_CAPACITY \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_INSUFFICIENT_DATA ) -#define PSA_ERROR_TAMPERING_DETECTED \ - MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_CORRUPTION_DETECTED ) - -/* - * Deprecated PSA Crypto numerical encodings (PSA Crypto API <= 1.0 beta3) - */ -#define PSA_KEY_USAGE_SIGN \ - MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_SIGN_HASH ) -#define PSA_KEY_USAGE_VERIFY \ - MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_VERIFY_HASH ) - -/* - * Deprecated PSA Crypto size calculation macros (PSA Crypto API <= 1.0 beta3) - */ -#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \ - MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGNATURE_MAX_SIZE ) -#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) \ - MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) ) - -/* - * Deprecated PSA Crypto function names (PSA Crypto API <= 1.0 beta3) - */ -/* Make these macros and not wrappers so that there is no cost to - * applications that don't use the deprecated names. - * - * Put backslash-newline after "#define" to bypass check-names.sh which - * would otherwise complain about lowercase macro names. - */ -#define \ - psa_asymmetric_sign( key, alg, hash, hash_length, signature, signature_size, signature_length ) \ - ( (mbedtls_deprecated_psa_status_t) psa_sign_hash( key, alg, hash, hash_length, signature, signature_size, signature_length ) ) -#define \ - psa_asymmetric_verify( key, alg, hash, hash_length, signature, signature_length ) \ - ( (mbedtls_deprecated_psa_status_t) psa_verify_hash( key, alg, hash, hash_length, signature, signature_length ) ) - -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - -#ifdef __cplusplus -} -#endif - -#endif /* PSA_CRYPTO_COMPAT_H */ diff --git a/features/mbedtls/mbed-crypto/platform/mbed_lib.json b/features/mbedtls/mbed-crypto/platform/mbed_lib.json deleted file mode 100644 index 2addde4c15..0000000000 --- a/features/mbedtls/mbed-crypto/platform/mbed_lib.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "mbed-crypto", - "macros": ["MBEDTLS_PSA_HAS_ITS_IO"] -} diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/COMPONENT_NSPE/crypto_struct.h b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/COMPONENT_NSPE/crypto_struct.h similarity index 99% rename from features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/COMPONENT_NSPE/crypto_struct.h rename to features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/COMPONENT_NSPE/crypto_struct.h index 9f55484e2f..938abd07b8 100644 --- a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/COMPONENT_NSPE/crypto_struct.h +++ b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/COMPONENT_NSPE/crypto_struct.h @@ -330,14 +330,14 @@ typedef uint16_t psa_key_attributes_flag_t; typedef struct { psa_key_type_t type; + psa_key_bits_t bits; psa_key_lifetime_t lifetime; psa_key_id_t id; psa_key_policy_t policy; - psa_key_bits_t bits; psa_key_attributes_flag_t flags; } psa_core_key_attributes_t; -#define PSA_CORE_KEY_ATTRIBUTES_INIT {0, 0, PSA_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0, 0} +#define PSA_CORE_KEY_ATTRIBUTES_INIT {PSA_KEY_TYPE_NONE, 0, PSA_KEY_LIFETIME_VOLATILE, PSA_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0} struct psa_key_attributes_s { diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto.c b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto.c similarity index 96% rename from features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto.c rename to features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto.c index 4450fdb56d..733a2e46c4 100644 --- a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto.c +++ b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto.c @@ -375,71 +375,118 @@ static inline int psa_key_slot_is_external( const psa_key_slot_t *slot ) #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #if defined(MBEDTLS_ECP_C) -static psa_ecc_curve_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid ) +psa_ecc_curve_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid, + size_t *bits ) { switch( grpid ) { case MBEDTLS_ECP_DP_SECP192R1: - return( PSA_ECC_CURVE_SECP192R1 ); + *bits = 192; + return( PSA_ECC_CURVE_SECP_R1 ); case MBEDTLS_ECP_DP_SECP224R1: - return( PSA_ECC_CURVE_SECP224R1 ); + *bits = 224; + return( PSA_ECC_CURVE_SECP_R1 ); case MBEDTLS_ECP_DP_SECP256R1: - return( PSA_ECC_CURVE_SECP256R1 ); + *bits = 256; + return( PSA_ECC_CURVE_SECP_R1 ); case MBEDTLS_ECP_DP_SECP384R1: - return( PSA_ECC_CURVE_SECP384R1 ); + *bits = 384; + return( PSA_ECC_CURVE_SECP_R1 ); case MBEDTLS_ECP_DP_SECP521R1: - return( PSA_ECC_CURVE_SECP521R1 ); + *bits = 521; + return( PSA_ECC_CURVE_SECP_R1 ); case MBEDTLS_ECP_DP_BP256R1: - return( PSA_ECC_CURVE_BRAINPOOL_P256R1 ); + *bits = 256; + return( PSA_ECC_CURVE_BRAINPOOL_P_R1 ); case MBEDTLS_ECP_DP_BP384R1: - return( PSA_ECC_CURVE_BRAINPOOL_P384R1 ); + *bits = 384; + return( PSA_ECC_CURVE_BRAINPOOL_P_R1 ); case MBEDTLS_ECP_DP_BP512R1: - return( PSA_ECC_CURVE_BRAINPOOL_P512R1 ); + *bits = 512; + return( PSA_ECC_CURVE_BRAINPOOL_P_R1 ); case MBEDTLS_ECP_DP_CURVE25519: - return( PSA_ECC_CURVE_CURVE25519 ); + *bits = 255; + return( PSA_ECC_CURVE_MONTGOMERY ); case MBEDTLS_ECP_DP_SECP192K1: - return( PSA_ECC_CURVE_SECP192K1 ); + *bits = 192; + return( PSA_ECC_CURVE_SECP_K1 ); case MBEDTLS_ECP_DP_SECP224K1: - return( PSA_ECC_CURVE_SECP224K1 ); + *bits = 224; + return( PSA_ECC_CURVE_SECP_K1 ); case MBEDTLS_ECP_DP_SECP256K1: - return( PSA_ECC_CURVE_SECP256K1 ); + *bits = 256; + return( PSA_ECC_CURVE_SECP_K1 ); case MBEDTLS_ECP_DP_CURVE448: - return( PSA_ECC_CURVE_CURVE448 ); + *bits = 448; + return( PSA_ECC_CURVE_MONTGOMERY ); default: return( 0 ); } } -static mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_curve_t curve ) +mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_curve_t curve, + size_t byte_length ) { switch( curve ) { - case PSA_ECC_CURVE_SECP192R1: - return( MBEDTLS_ECP_DP_SECP192R1 ); - case PSA_ECC_CURVE_SECP224R1: - return( MBEDTLS_ECP_DP_SECP224R1 ); - case PSA_ECC_CURVE_SECP256R1: - return( MBEDTLS_ECP_DP_SECP256R1 ); - case PSA_ECC_CURVE_SECP384R1: - return( MBEDTLS_ECP_DP_SECP384R1 ); - case PSA_ECC_CURVE_SECP521R1: - return( MBEDTLS_ECP_DP_SECP521R1 ); - case PSA_ECC_CURVE_BRAINPOOL_P256R1: - return( MBEDTLS_ECP_DP_BP256R1 ); - case PSA_ECC_CURVE_BRAINPOOL_P384R1: - return( MBEDTLS_ECP_DP_BP384R1 ); - case PSA_ECC_CURVE_BRAINPOOL_P512R1: - return( MBEDTLS_ECP_DP_BP512R1 ); - case PSA_ECC_CURVE_CURVE25519: - return( MBEDTLS_ECP_DP_CURVE25519 ); - case PSA_ECC_CURVE_SECP192K1: - return( MBEDTLS_ECP_DP_SECP192K1 ); - case PSA_ECC_CURVE_SECP224K1: - return( MBEDTLS_ECP_DP_SECP224K1 ); - case PSA_ECC_CURVE_SECP256K1: - return( MBEDTLS_ECP_DP_SECP256K1 ); - case PSA_ECC_CURVE_CURVE448: - return( MBEDTLS_ECP_DP_CURVE448 ); + case PSA_ECC_CURVE_SECP_R1: + switch( byte_length ) + { + case PSA_BITS_TO_BYTES( 192 ): + return( MBEDTLS_ECP_DP_SECP192R1 ); + case PSA_BITS_TO_BYTES( 224 ): + return( MBEDTLS_ECP_DP_SECP224R1 ); + case PSA_BITS_TO_BYTES( 256 ): + return( MBEDTLS_ECP_DP_SECP256R1 ); + case PSA_BITS_TO_BYTES( 384 ): + return( MBEDTLS_ECP_DP_SECP384R1 ); + case PSA_BITS_TO_BYTES( 521 ): + return( MBEDTLS_ECP_DP_SECP521R1 ); + default: + return( MBEDTLS_ECP_DP_NONE ); + } + break; + + case PSA_ECC_CURVE_BRAINPOOL_P_R1: + switch( byte_length ) + { + case PSA_BITS_TO_BYTES( 256 ): + return( MBEDTLS_ECP_DP_BP256R1 ); + case PSA_BITS_TO_BYTES( 384 ): + return( MBEDTLS_ECP_DP_BP384R1 ); + case PSA_BITS_TO_BYTES( 512 ): + return( MBEDTLS_ECP_DP_BP512R1 ); + default: + return( MBEDTLS_ECP_DP_NONE ); + } + break; + + case PSA_ECC_CURVE_MONTGOMERY: + switch( byte_length ) + { + case PSA_BITS_TO_BYTES( 255 ): + return( MBEDTLS_ECP_DP_CURVE25519 ); + case PSA_BITS_TO_BYTES( 448 ): + return( MBEDTLS_ECP_DP_CURVE448 ); + default: + return( MBEDTLS_ECP_DP_NONE ); + } + break; + + case PSA_ECC_CURVE_SECP_K1: + switch( byte_length ) + { + case PSA_BITS_TO_BYTES( 192 ): + return( MBEDTLS_ECP_DP_SECP192K1 ); + case PSA_BITS_TO_BYTES( 224 ): + return( MBEDTLS_ECP_DP_SECP224K1 ); + case PSA_BITS_TO_BYTES( 256 ): + return( MBEDTLS_ECP_DP_SECP256K1 ); + default: + return( MBEDTLS_ECP_DP_NONE ); + } + break; + default: return( MBEDTLS_ECP_DP_NONE ); } @@ -588,6 +635,8 @@ exit: #if defined(MBEDTLS_ECP_C) static psa_status_t psa_prepare_import_ec_key( psa_ecc_curve_t curve, + size_t data_length, + int is_public, mbedtls_ecp_keypair **p_ecp ) { mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE; @@ -596,8 +645,23 @@ static psa_status_t psa_prepare_import_ec_key( psa_ecc_curve_t curve, return( PSA_ERROR_INSUFFICIENT_MEMORY ); mbedtls_ecp_keypair_init( *p_ecp ); + if( is_public ) + { + /* A public key is represented as: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * So its data length is 2m+1 where n is the key size in bits. + */ + if( ( data_length & 1 ) == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + data_length = data_length / 2; + } + /* Load the group. */ - grp_id = mbedtls_ecc_group_of_psa( curve ); + grp_id = mbedtls_ecc_group_of_psa( curve, data_length ); + if( grp_id == MBEDTLS_ECP_DP_NONE ) + return( PSA_ERROR_INVALID_ARGUMENT ); return( mbedtls_to_psa_error( mbedtls_ecp_group_load( &( *p_ecp )->grp, grp_id ) ) ); } @@ -612,7 +676,7 @@ static psa_status_t psa_import_ec_public_key( psa_ecc_curve_t curve, psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_keypair *ecp = NULL; - status = psa_prepare_import_ec_key( curve, &ecp ); + status = psa_prepare_import_ec_key( curve, data_length, 1, &ecp ); if( status != PSA_SUCCESS ) goto exit; @@ -651,10 +715,7 @@ static psa_status_t psa_import_ec_private_key( psa_ecc_curve_t curve, psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_keypair *ecp = NULL; - if( PSA_BITS_TO_BYTES( PSA_ECC_CURVE_BITS( curve ) ) != data_length ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - status = psa_prepare_import_ec_key( curve, &ecp ); + status = psa_prepare_import_ec_key( curve, data_length, 0, &ecp ); if( status != PSA_SUCCESS ) goto exit; @@ -2037,8 +2098,10 @@ static const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg ) return( &mbedtls_sha256_info ); #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) case PSA_ALG_SHA_384: return( &mbedtls_sha384_info ); +#endif case PSA_ALG_SHA_512: return( &mbedtls_sha512_info ); #endif @@ -2089,7 +2152,9 @@ psa_status_t psa_hash_abort( psa_hash_operation_t *operation ) break; #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) case PSA_ALG_SHA_384: +#endif case PSA_ALG_SHA_512: mbedtls_sha512_free( &operation->ctx.sha512 ); break; @@ -2155,10 +2220,12 @@ psa_status_t psa_hash_setup( psa_hash_operation_t *operation, break; #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) case PSA_ALG_SHA_384: mbedtls_sha512_init( &operation->ctx.sha512 ); ret = mbedtls_sha512_starts_ret( &operation->ctx.sha512, 1 ); break; +#endif case PSA_ALG_SHA_512: mbedtls_sha512_init( &operation->ctx.sha512 ); ret = mbedtls_sha512_starts_ret( &operation->ctx.sha512, 0 ); @@ -2227,7 +2294,9 @@ psa_status_t psa_hash_update( psa_hash_operation_t *operation, break; #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) case PSA_ALG_SHA_384: +#endif case PSA_ALG_SHA_512: ret = mbedtls_sha512_update_ret( &operation->ctx.sha512, input, input_length ); @@ -2300,7 +2369,9 @@ psa_status_t psa_hash_finish( psa_hash_operation_t *operation, break; #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) case PSA_ALG_SHA_384: +#endif case PSA_ALG_SHA_512: ret = mbedtls_sha512_finish_ret( &operation->ctx.sha512, hash ); break; @@ -2341,6 +2412,58 @@ psa_status_t psa_hash_verify( psa_hash_operation_t *operation, return( PSA_SUCCESS ); } +psa_status_t psa_hash_compute( psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *hash, size_t hash_size, + size_t *hash_length ) +{ + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + *hash_length = hash_size; + status = psa_hash_setup( &operation, alg ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_hash_update( &operation, input, input_length ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_hash_finish( &operation, hash, hash_size, hash_length ); + if( status != PSA_SUCCESS ) + goto exit; + +exit: + if( status == PSA_SUCCESS ) + status = psa_hash_abort( &operation ); + else + psa_hash_abort( &operation ); + return( status ); +} + +psa_status_t psa_hash_compare( psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *hash, size_t hash_length ) +{ + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_hash_setup( &operation, alg ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_hash_update( &operation, input, input_length ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_hash_verify( &operation, hash, hash_length ); + if( status != PSA_SUCCESS ) + goto exit; + +exit: + if( status == PSA_SUCCESS ) + status = psa_hash_abort( &operation ); + else + psa_hash_abort( &operation ); + return( status ); +} + psa_status_t psa_hash_clone( const psa_hash_operation_t *source_operation, psa_hash_operation_t *target_operation ) { @@ -2389,7 +2512,9 @@ psa_status_t psa_hash_clone( const psa_hash_operation_t *source_operation, break; #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) case PSA_ALG_SHA_384: +#endif case PSA_ALG_SHA_512: mbedtls_sha512_clone( &target_operation->ctx.sha512, &source_operation->ctx.sha512 ); @@ -2673,14 +2798,8 @@ static psa_status_t psa_hmac_setup_internal( psa_hmac_internal_data *hmac, if( key_length > block_size ) { - status = psa_hash_setup( &hmac->hash_ctx, hash_alg ); - if( status != PSA_SUCCESS ) - goto cleanup; - status = psa_hash_update( &hmac->hash_ctx, key, key_length ); - if( status != PSA_SUCCESS ) - goto cleanup; - status = psa_hash_finish( &hmac->hash_ctx, - ipad, sizeof( ipad ), &key_length ); + status = psa_hash_compute( hash_alg, key, key_length, + ipad, sizeof( ipad ), &key_length ); if( status != PSA_SUCCESS ) goto cleanup; } @@ -3030,6 +3149,8 @@ psa_status_t psa_mac_verify_finish( psa_mac_operation_t *operation, status = psa_mac_finish_internal( operation, actual_mac, sizeof( actual_mac ) ); + if( status != PSA_SUCCESS ) + goto cleanup; if( safer_memcmp( mac, actual_mac, mac_length ) != 0 ) status = PSA_ERROR_INVALID_SIGNATURE; @@ -5193,12 +5314,13 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key, mbedtls_ecp_keypair *their_key = NULL; mbedtls_ecdh_context ecdh; psa_status_t status; + size_t bits = 0; + psa_ecc_curve_t curve = mbedtls_ecc_group_to_psa( our_key->grp.id, &bits ); mbedtls_ecdh_init( &ecdh ); - status = psa_import_ec_public_key( - mbedtls_ecc_group_to_psa( our_key->grp.id ), - peer_key, peer_key_length, - &their_key ); + status = psa_import_ec_public_key( curve, + peer_key, peer_key_length, + &their_key ); if( status != PSA_SUCCESS ) goto exit; @@ -5217,8 +5339,14 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key, shared_secret, shared_secret_size, mbedtls_ctr_drbg_random, &global_data.ctr_drbg ) ); + if( status != PSA_SUCCESS ) + goto exit; + if( PSA_BITS_TO_BYTES( bits ) != *shared_secret_length ) + status = PSA_ERROR_CORRUPTION_DETECTED; exit: + if( status != PSA_SUCCESS ) + mbedtls_platform_zeroize( shared_secret, shared_secret_size ); mbedtls_ecdh_free( &ecdh ); mbedtls_ecp_keypair_free( their_key ); mbedtls_free( their_key ); @@ -5501,7 +5629,8 @@ static psa_status_t psa_generate_key_internal( if ( PSA_KEY_TYPE_IS_ECC( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) { psa_ecc_curve_t curve = PSA_KEY_TYPE_GET_CURVE( type ); - mbedtls_ecp_group_id grp_id = mbedtls_ecc_group_of_psa( curve ); + mbedtls_ecp_group_id grp_id = + mbedtls_ecc_group_of_psa( curve, PSA_BITS_TO_BYTES( bits ) ); const mbedtls_ecp_curve_info *curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id ); mbedtls_ecp_keypair *ecp; diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_core.h b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_core.h similarity index 100% rename from features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_core.h rename to features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_core.h diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_invasive.h b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_invasive.h similarity index 100% rename from features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_invasive.h rename to features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_invasive.h diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_its.h b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_its.h similarity index 100% rename from features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_its.h rename to features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_its.h diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_se.c b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_se.c similarity index 100% rename from features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_se.c rename to features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_se.c diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_se.h b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_se.h similarity index 100% rename from features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_se.h rename to features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_se.h diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_service_integration.h b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_service_integration.h similarity index 100% rename from features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_service_integration.h rename to features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_service_integration.h diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.c b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.c similarity index 100% rename from features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.c rename to features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.c diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.h b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.h similarity index 100% rename from features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.h rename to features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.h diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c similarity index 97% rename from features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c rename to features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c index 1389fd4516..fa1214c86d 100644 --- a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c +++ b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c @@ -259,7 +259,9 @@ typedef struct { uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH]; uint8_t version[4]; uint8_t lifetime[sizeof( psa_key_lifetime_t )]; - uint8_t type[sizeof( psa_key_type_t )]; + uint8_t type[4]; /* Size=4 for a 2-byte type to keep the structure more + * regular and aligned and to make potential future + * extensibility easier. */ uint8_t policy[sizeof( psa_key_policy_t )]; uint8_t data_len[4]; uint8_t key_data[]; @@ -276,7 +278,7 @@ void psa_format_key_data_for_storage( const uint8_t *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( attr->lifetime, storage_format->lifetime, 0 ); - PUT_UINT32_LE( attr->type, storage_format->type, 0 ); + PUT_UINT32_LE( (uint32_t) attr->type, storage_format->type, 0 ); PUT_UINT32_LE( attr->policy.usage, storage_format->policy, 0 ); PUT_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) ); PUT_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) ); @@ -302,6 +304,7 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, const psa_persistent_key_storage_format *storage_format = (const psa_persistent_key_storage_format *)storage_data; uint32_t version; + uint32_t type; if( storage_data_length < sizeof(*storage_format) ) return( PSA_ERROR_STORAGE_FAILURE ); @@ -332,7 +335,11 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, } GET_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 ); - GET_UINT32_LE( attr->type, storage_format->type, 0 ); + GET_UINT32_LE( type, storage_format->type, 0 ); + if( type <= (psa_key_type_t) -1 ) + attr->type = (psa_key_type_t) type; + else + return( PSA_ERROR_STORAGE_FAILURE ); GET_UINT32_LE( attr->policy.usage, storage_format->policy, 0 ); GET_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) ); GET_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) ); diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.h b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.h similarity index 100% rename from features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.h rename to features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.h diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_its_file.c b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_its_file.c similarity index 100% rename from features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_its_file.c rename to features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_its_file.c diff --git a/features/mbedtls/src/Makefile b/features/mbedtls/src/Makefile index bc9363db22..f9cd468a5f 100644 --- a/features/mbedtls/src/Makefile +++ b/features/mbedtls/src/Makefile @@ -37,7 +37,7 @@ endif SOEXT_TLS=so.13 SOEXT_X509=so.1 -SOEXT_CRYPTO=so.3 +SOEXT_CRYPTO=so.4 # Set AR_DASH= (empty string) to use an ar implementation that does not accept # the - prefix for command line options (e.g. llvm-ar) @@ -63,12 +63,37 @@ DLEXT = dylib endif endif +OBJS_CRYPTO= aes.o aesni.o arc4.o \ + aria.o asn1parse.o asn1write.o \ + base64.o bignum.o blowfish.o \ + camellia.o ccm.o chacha20.o \ + chachapoly.o cipher.o cipher_wrap.o \ + cmac.o ctr_drbg.o des.o \ + dhm.o ecdh.o ecdsa.o \ + ecjpake.o ecp.o \ + ecp_curves.o entropy.o entropy_poll.o \ + error.o gcm.o havege.o \ + hkdf.o \ + hmac_drbg.o md.o md2.o \ + md4.o md5.o \ + memory_buffer_alloc.o nist_kw.o \ + oid.o padlock.o pem.o \ + pk.o pk_wrap.o pkcs12.o \ + pkcs5.o pkparse.o pkwrite.o \ + platform.o platform_util.o poly1305.o \ + psa_crypto.o psa_crypto_se.o \ + psa_crypto_slot_management.o \ + psa_crypto_storage.o \ + psa_its_file.o \ + ripemd160.o rsa_internal.o rsa.o \ + sha1.o sha256.o sha512.o \ + threading.o timing.o \ + version.o version_features.o \ + xtea.o - -# Look in crypto for libmbedcrypto. -LOCAL_LDFLAGS += -L../crypto/library -LOCAL_CFLAGS += -I../crypto/include -CRYPTO := ../crypto/library/ +include ../3rdparty/Makefile.inc +LOCAL_CFLAGS+=$(THIRDPARTY_INCLUDES) +OBJS_CRYPTO+=$(THIRDPARTY_CRYPTO_OBJECTS) OBJS_X509= certs.o pkcs11.o x509.o \ x509_create.o x509_crl.o x509_crt.o \ @@ -77,15 +102,10 @@ OBJS_X509= certs.o pkcs11.o x509.o \ OBJS_TLS= debug.o net_sockets.o \ ssl_cache.o ssl_ciphersuites.o \ ssl_cli.o ssl_cookie.o \ + ssl_msg.o \ ssl_srv.o ssl_ticket.o \ ssl_tls.o -INCLUDING_FROM_MBEDTLS:=1 -include ../crypto/3rdparty/Makefile.inc -LOCAL_CFLAGS += $(patsubst -I../3rdparty/%, -I../crypto/3rdparty/%, $(THIRDPARTY_INCLUDES)) -OBJS_CRYPTO += $(patsubst ../3rdparty/%, ../crypto/3rdparty/%, $(THIRDPARTY_CRYPTO_OBJECTS)) - - .SILENT: .PHONY: all static shared clean @@ -138,7 +158,7 @@ ifneq ($(APPLE_BUILD),0) endif endif -libmbedx509.$(SOEXT_X509): $(OBJS_X509) $(CRYPTO)libmbedcrypto.so +libmbedx509.$(SOEXT_X509): $(OBJS_X509) libmbedcrypto.so echo " LD $@" $(CC) -shared -Wl,-soname,$@ -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509) @@ -146,21 +166,40 @@ libmbedx509.so: libmbedx509.$(SOEXT_X509) echo " LN $@ -> $<" ln -sf $< $@ -libmbedx509.dylib: $(OBJS_X509) $(CRYPTO)libmbedcrypto.dylib +libmbedx509.dylib: $(OBJS_X509) libmbedcrypto.dylib echo " LD $@" $(CC) -dynamiclib -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509) -libmbedx509.dll: $(OBJS_X509) $(CRYPTO)libmbedcrypto.dll +libmbedx509.dll: $(OBJS_X509) libmbedcrypto.dll echo " LD $@" $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_X509) -lws2_32 -lwinmm -lgdi32 -L. -lmbedcrypto -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) -libmbedcrypto.%: - $(MAKE) CRYPTO_INCLUDES:="-I../../include -I../include" -C ../crypto/library $@ +# crypto +libmbedcrypto.a: $(OBJS_CRYPTO) + echo " AR $@" + $(AR) $(ARFLAGS) $@ $(OBJS_CRYPTO) +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) + echo " RL $@" + $(RL) $(RLFLAGS) $@ +endif +endif -libmbedcrypto.$(DLEXT): $(CRYPTO)libmbedcrypto.$(DLEXT) +libmbedcrypto.$(SOEXT_CRYPTO): $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_CRYPTO) -$(CRYPTO)libmbedcrypto.$(DLEXT): | libmbedcrypto.a - $(MAKE) CRYPTO_INCLUDES:="-I../../include -I../include" -C ../crypto/library libmbedcrypto.$(DLEXT) +libmbedcrypto.so: libmbedcrypto.$(SOEXT_CRYPTO) + echo " LN $@ -> $<" + ln -sf $< $@ + +libmbedcrypto.dylib: $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -dynamiclib $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_CRYPTO) + +libmbedcrypto.dll: $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_CRYPTO) -lws2_32 -lwinmm -lgdi32 -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) .c.o: echo " CC $<" @@ -168,9 +207,10 @@ $(CRYPTO)libmbedcrypto.$(DLEXT): | libmbedcrypto.a clean: ifndef WINDOWS - rm -f *.o libmbed* $(OBJS_CRYPTO) + rm -f *.o libmbed* + rm -f $(THIRDPARTY_CRYPTO_OBJECTS) else if exist *.o del /Q /F *.o if exist libmbed* del /Q /F libmbed* - if exist $(OBJS_CRYPTO) del /Q /F $(OBJS_CRYPTO) + del /Q /F del_errors_out_if_the_file_list_is_empty_but_not_if_a_file_does_not_exist $(subst /,\,$(THIRDPARTY_CRYPTO_OBJECTS)) endif diff --git a/features/mbedtls/mbed-crypto/src/aes.c b/features/mbedtls/src/aes.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/aes.c rename to features/mbedtls/src/aes.c diff --git a/features/mbedtls/mbed-crypto/src/aesni.c b/features/mbedtls/src/aesni.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/aesni.c rename to features/mbedtls/src/aesni.c diff --git a/features/mbedtls/mbed-crypto/src/arc4.c b/features/mbedtls/src/arc4.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/arc4.c rename to features/mbedtls/src/arc4.c diff --git a/features/mbedtls/mbed-crypto/src/aria.c b/features/mbedtls/src/aria.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/aria.c rename to features/mbedtls/src/aria.c diff --git a/features/mbedtls/mbed-crypto/src/asn1parse.c b/features/mbedtls/src/asn1parse.c similarity index 82% rename from features/mbedtls/mbed-crypto/src/asn1parse.c rename to features/mbedtls/src/asn1parse.c index e7e4d13f68..34c660775d 100644 --- a/features/mbedtls/mbed-crypto/src/asn1parse.c +++ b/features/mbedtls/src/asn1parse.c @@ -247,6 +247,58 @@ int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, return( 0 ); } +/* + * Traverse an ASN.1 "SEQUENCE OF " + * and call a callback for each entry found. + */ +int mbedtls_asn1_traverse_sequence_of( + unsigned char **p, + const unsigned char *end, + unsigned char tag_must_mask, unsigned char tag_must_val, + unsigned char tag_may_mask, unsigned char tag_may_val, + int (*cb)( void *ctx, int tag, + unsigned char *start, size_t len ), + void *ctx ) +{ + int ret; + size_t len; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( ret ); + } + + if( *p + len != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + unsigned char const tag = *(*p)++; + + if( ( tag & tag_must_mask ) != tag_must_val ) + return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = mbedtls_asn1_get_len( p, end, &len ) ) != 0 ) + return( ret ); + + if( ( tag & tag_may_mask ) == tag_may_val ) + { + if( cb != NULL ) + { + ret = cb( ctx, tag, *p, len ); + if( ret != 0 ) + return( ret ); + } + } + + *p += len; + } + + return( 0 ); +} + /* * Get a bit string without unused bits */ @@ -269,7 +321,51 @@ int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end return( 0 ); } +void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq ) +{ + while( seq != NULL ) + { + mbedtls_asn1_sequence *next = seq->next; + mbedtls_platform_zeroize( seq, sizeof( *seq ) ); + mbedtls_free( seq ); + seq = next; + } +} +typedef struct +{ + int tag; + mbedtls_asn1_sequence *cur; +} asn1_get_sequence_of_cb_ctx_t; + +static int asn1_get_sequence_of_cb( void *ctx, + int tag, + unsigned char *start, + size_t len ) +{ + asn1_get_sequence_of_cb_ctx_t *cb_ctx = + (asn1_get_sequence_of_cb_ctx_t *) ctx; + mbedtls_asn1_sequence *cur = + cb_ctx->cur; + + if( cur->buf.p != NULL ) + { + cur->next = + mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + + cur->buf.p = start; + cur->buf.len = len; + cur->buf.tag = tag; + + cb_ctx->cur = cur; + return( 0 ); +} /* * Parses and splits an ASN.1 "SEQUENCE OF " @@ -279,49 +375,11 @@ int mbedtls_asn1_get_sequence_of( unsigned char **p, mbedtls_asn1_sequence *cur, int tag) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - mbedtls_asn1_buf *buf; - - /* Get main sequence tag */ - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( ret ); - - if( *p + len != end ) - return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - while( *p < end ) - { - buf = &(cur->buf); - buf->tag = **p; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 ) - return( ret ); - - buf->p = *p; - *p += buf->len; - - /* Allocate and assign next pointer */ - if( *p < end ) - { - cur->next = (mbedtls_asn1_sequence*)mbedtls_calloc( 1, - sizeof( mbedtls_asn1_sequence ) ); - - if( cur->next == NULL ) - return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); - - cur = cur->next; - } - } - - /* Set final sequence entry's next pointer to NULL */ - cur->next = NULL; - - if( *p != end ) - return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); + asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur }; + memset( cur, 0, sizeof( mbedtls_asn1_sequence ) ); + return( mbedtls_asn1_traverse_sequence_of( + p, end, 0xFF, tag, 0, 0, + asn1_get_sequence_of_cb, &cb_ctx ) ); } int mbedtls_asn1_get_alg( unsigned char **p, diff --git a/features/mbedtls/mbed-crypto/src/asn1write.c b/features/mbedtls/src/asn1write.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/asn1write.c rename to features/mbedtls/src/asn1write.c diff --git a/features/mbedtls/mbed-crypto/src/base64.c b/features/mbedtls/src/base64.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/base64.c rename to features/mbedtls/src/base64.c diff --git a/features/mbedtls/mbed-crypto/src/bignum.c b/features/mbedtls/src/bignum.c similarity index 99% rename from features/mbedtls/mbed-crypto/src/bignum.c rename to features/mbedtls/src/bignum.c index 61d18101fb..d53aefd5b0 100644 --- a/features/mbedtls/mbed-crypto/src/bignum.c +++ b/features/mbedtls/src/bignum.c @@ -158,9 +158,10 @@ int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); - /* Actually resize up in this case */ + /* Actually resize up if there are currently fewer than nblimbs limbs. */ if( X->n <= nblimbs ) return( mbedtls_mpi_grow( X, nblimbs ) ); + /* After this point, then X->n > nblimbs and in particular X->n > 0. */ for( i = X->n - 1; i > 0; i-- ) if( X->p[i] != 0 ) @@ -199,7 +200,7 @@ int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) if( X == Y ) return( 0 ); - if( Y->p == NULL ) + if( Y->n == 0 ) { mbedtls_mpi_free( X ); return( 0 ); diff --git a/features/mbedtls/mbed-crypto/src/blowfish.c b/features/mbedtls/src/blowfish.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/blowfish.c rename to features/mbedtls/src/blowfish.c diff --git a/features/mbedtls/mbed-crypto/src/camellia.c b/features/mbedtls/src/camellia.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/camellia.c rename to features/mbedtls/src/camellia.c diff --git a/features/mbedtls/mbed-crypto/src/ccm.c b/features/mbedtls/src/ccm.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/ccm.c rename to features/mbedtls/src/ccm.c diff --git a/features/mbedtls/mbed-crypto/src/chacha20.c b/features/mbedtls/src/chacha20.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/chacha20.c rename to features/mbedtls/src/chacha20.c diff --git a/features/mbedtls/mbed-crypto/src/chachapoly.c b/features/mbedtls/src/chachapoly.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/chachapoly.c rename to features/mbedtls/src/chachapoly.c diff --git a/features/mbedtls/mbed-crypto/src/cipher.c b/features/mbedtls/src/cipher.c similarity index 99% rename from features/mbedtls/mbed-crypto/src/cipher.c rename to features/mbedtls/src/cipher.c index b62f1d5939..409c3fe674 100644 --- a/features/mbedtls/mbed-crypto/src/cipher.c +++ b/features/mbedtls/src/cipher.c @@ -527,6 +527,10 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i *olen = 0; block_size = mbedtls_cipher_get_block_size( ctx ); + if ( 0 == block_size ) + { + return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); + } if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) { @@ -562,11 +566,6 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i } #endif - if ( 0 == block_size ) - { - return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); - } - if( input == output && ( ctx->unprocessed_len != 0 || ilen % block_size ) ) { @@ -625,11 +624,6 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i */ if( 0 != ilen ) { - if( 0 == block_size ) - { - return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); - } - /* Encryption: only cache partial blocks * Decryption w/ padding: always keep at least one whole block * Decryption w/o padding: only cache partial blocks diff --git a/features/mbedtls/mbed-crypto/src/cipher_wrap.c b/features/mbedtls/src/cipher_wrap.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/cipher_wrap.c rename to features/mbedtls/src/cipher_wrap.c diff --git a/features/mbedtls/mbed-crypto/src/cmac.c b/features/mbedtls/src/cmac.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/cmac.c rename to features/mbedtls/src/cmac.c diff --git a/features/mbedtls/mbed-crypto/src/ctr_drbg.c b/features/mbedtls/src/ctr_drbg.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/ctr_drbg.c rename to features/mbedtls/src/ctr_drbg.c diff --git a/features/mbedtls/mbed-crypto/src/des.c b/features/mbedtls/src/des.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/des.c rename to features/mbedtls/src/des.c diff --git a/features/mbedtls/mbed-crypto/src/dhm.c b/features/mbedtls/src/dhm.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/dhm.c rename to features/mbedtls/src/dhm.c diff --git a/features/mbedtls/mbed-crypto/src/ecdh.c b/features/mbedtls/src/ecdh.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/ecdh.c rename to features/mbedtls/src/ecdh.c diff --git a/features/mbedtls/mbed-crypto/src/ecdsa.c b/features/mbedtls/src/ecdsa.c similarity index 99% rename from features/mbedtls/mbed-crypto/src/ecdsa.c rename to features/mbedtls/src/ecdsa.c index e9c4315bfd..5acd2d00e8 100644 --- a/features/mbedtls/mbed-crypto/src/ecdsa.c +++ b/features/mbedtls/src/ecdsa.c @@ -298,7 +298,7 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, *p_sign_tries = 0; do { - if( *p_sign_tries++ > 10 ) + if( (*p_sign_tries)++ > 10 ) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; @@ -311,7 +311,7 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, *p_key_tries = 0; do { - if( *p_key_tries++ > 10 ) + if( (*p_key_tries)++ > 10 ) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; diff --git a/features/mbedtls/mbed-crypto/src/ecjpake.c b/features/mbedtls/src/ecjpake.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/ecjpake.c rename to features/mbedtls/src/ecjpake.c diff --git a/features/mbedtls/mbed-crypto/src/ecp.c b/features/mbedtls/src/ecp.c similarity index 98% rename from features/mbedtls/mbed-crypto/src/ecp.c rename to features/mbedtls/src/ecp.c index e156fcbe2d..d3e42a94db 100644 --- a/features/mbedtls/mbed-crypto/src/ecp.c +++ b/features/mbedtls/src/ecp.c @@ -374,7 +374,7 @@ int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, * Curves are listed in order: largest curves first, and for a given size, * fastest curves first. This provides the default order for the SSL module. * - * Reminder: update profiles in Mbed TLS's x509_crt.c when adding new curves! + * Reminder: update profiles in x509_crt.c when adding a new curves! */ static const mbedtls_ecp_curve_info ecp_supported_curves[] = { @@ -2016,6 +2016,20 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, final_norm: #endif + /* + * Knowledge of the jacobian coordinates may leak the last few bits of the + * scalar [1], and since our MPI implementation isn't constant-flow, + * inversion (used for coordinate normalization) may leak the full value + * of its input via side-channels [2]. + * + * [1] https://eprint.iacr.org/2003/191 + * [2] https://eprint.iacr.org/2020/055 + * + * Avoid the leak by randomizing coordinates before we normalize them. + */ + if( f_rng != 0 ) + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) ); + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) ); @@ -2388,6 +2402,20 @@ static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); } + /* + * Knowledge of the projective coordinates may leak the last few bits of the + * scalar [1], and since our MPI implementation isn't constant-flow, + * inversion (used for coordinate normalization) may leak the full value + * of its input via side-channels [2]. + * + * [1] https://eprint.iacr.org/2003/191 + * [2] https://eprint.iacr.org/2020/055 + * + * Avoid the leak by randomizing coordinates before we normalize them. + */ + if( f_rng != NULL ) + MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) ); cleanup: diff --git a/features/mbedtls/mbed-crypto/src/ecp_curves.c b/features/mbedtls/src/ecp_curves.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/ecp_curves.c rename to features/mbedtls/src/ecp_curves.c diff --git a/features/mbedtls/mbed-crypto/src/entropy.c b/features/mbedtls/src/entropy.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/entropy.c rename to features/mbedtls/src/entropy.c diff --git a/features/mbedtls/mbed-crypto/src/entropy_poll.c b/features/mbedtls/src/entropy_poll.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/entropy_poll.c rename to features/mbedtls/src/entropy_poll.c diff --git a/features/mbedtls/src/error.c b/features/mbedtls/src/error.c index c451f4ddff..ee9c852b59 100644 --- a/features/mbedtls/src/error.c +++ b/features/mbedtls/src/error.c @@ -140,6 +140,10 @@ #include "mbedtls/md5.h" #endif +#if defined(MBEDTLS_NET_C) +#include "mbedtls/net_sockets.h" +#endif + #if defined(MBEDTLS_OID_C) #include "mbedtls/oid.h" #endif @@ -192,26 +196,22 @@ #include "mbedtls/sha512.h" #endif -#if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" -#endif - -#if defined(MBEDTLS_XTEA_C) -#include "mbedtls/xtea.h" -#endif - -#if defined(MBEDTLS_NET_C) -#include "mbedtls/net_sockets.h" -#endif - #if defined(MBEDTLS_SSL_TLS_C) #include "mbedtls/ssl.h" #endif +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) #include "mbedtls/x509.h" #endif +#if defined(MBEDTLS_XTEA_C) +#include "mbedtls/xtea.h" +#endif + void mbedtls_strerror( int ret, char *buf, size_t buflen ) { @@ -804,6 +804,35 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "MD5 - MD5 hardware accelerator failed" ); #endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_NET_C) + if( use_ret == -(MBEDTLS_ERR_NET_SOCKET_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Failed to open a socket" ); + if( use_ret == -(MBEDTLS_ERR_NET_CONNECT_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - The connection to the given server / port failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_BIND_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Binding of the socket failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_LISTEN_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Could not listen on the socket" ); + if( use_ret == -(MBEDTLS_ERR_NET_ACCEPT_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Could not accept the incoming connection" ); + if( use_ret == -(MBEDTLS_ERR_NET_RECV_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Reading information from the socket failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_SEND_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Sending information through the socket failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_CONN_RESET) ) + mbedtls_snprintf( buf, buflen, "NET - Connection was reset by peer" ); + if( use_ret == -(MBEDTLS_ERR_NET_UNKNOWN_HOST) ) + mbedtls_snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" ); + if( use_ret == -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "NET - Buffer is too small to hold the data" ); + if( use_ret == -(MBEDTLS_ERR_NET_INVALID_CONTEXT) ) + mbedtls_snprintf( buf, buflen, "NET - The context is invalid, eg because it was free()ed" ); + if( use_ret == -(MBEDTLS_ERR_NET_POLL_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Polling the net context failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "NET - Input invalid" ); +#endif /* MBEDTLS_NET_C */ + #if defined(MBEDTLS_OID_C) if( use_ret == -(MBEDTLS_ERR_OID_NOT_FOUND) ) mbedtls_snprintf( buf, buflen, "OID - OID is not found" ); @@ -873,35 +902,6 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) if( use_ret == -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED) ) mbedtls_snprintf( buf, buflen, "XTEA - XTEA hardware accelerator failed" ); #endif /* MBEDTLS_XTEA_C */ - -#if defined(MBEDTLS_NET_C) - if( use_ret == -(MBEDTLS_ERR_NET_SOCKET_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Failed to open a socket" ); - if( use_ret == -(MBEDTLS_ERR_NET_CONNECT_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - The connection to the given server / port failed" ); - if( use_ret == -(MBEDTLS_ERR_NET_BIND_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Binding of the socket failed" ); - if( use_ret == -(MBEDTLS_ERR_NET_LISTEN_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Could not listen on the socket" ); - if( use_ret == -(MBEDTLS_ERR_NET_ACCEPT_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Could not accept the incoming connection" ); - if( use_ret == -(MBEDTLS_ERR_NET_RECV_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Reading information from the socket failed" ); - if( use_ret == -(MBEDTLS_ERR_NET_SEND_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Sending information through the socket failed" ); - if( use_ret == -(MBEDTLS_ERR_NET_CONN_RESET) ) - mbedtls_snprintf( buf, buflen, "NET - Connection was reset by peer" ); - if( use_ret == -(MBEDTLS_ERR_NET_UNKNOWN_HOST) ) - mbedtls_snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" ); - if( use_ret == -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "NET - Buffer is too small to hold the data" ); - if( use_ret == -(MBEDTLS_ERR_NET_INVALID_CONTEXT) ) - mbedtls_snprintf( buf, buflen, "NET - The context is invalid, eg because it was free()ed" ); - if( use_ret == -(MBEDTLS_ERR_NET_POLL_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Polling the net context failed" ); - if( use_ret == -(MBEDTLS_ERR_NET_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "NET - Input invalid" ); -#endif /* MBEDTLS_NET_C */ // END generated code if( strlen( buf ) != 0 ) diff --git a/features/mbedtls/mbed-crypto/src/gcm.c b/features/mbedtls/src/gcm.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/gcm.c rename to features/mbedtls/src/gcm.c diff --git a/features/mbedtls/mbed-crypto/src/havege.c b/features/mbedtls/src/havege.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/havege.c rename to features/mbedtls/src/havege.c diff --git a/features/mbedtls/mbed-crypto/src/hkdf.c b/features/mbedtls/src/hkdf.c similarity index 97% rename from features/mbedtls/mbed-crypto/src/hkdf.c rename to features/mbedtls/src/hkdf.c index 379035ddbb..82df597a4c 100644 --- a/features/mbedtls/mbed-crypto/src/hkdf.c +++ b/features/mbedtls/src/hkdf.c @@ -115,7 +115,7 @@ int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, n = okm_len / hash_len; - if( (okm_len % hash_len) != 0 ) + if( okm_len % hash_len != 0 ) { n++; } @@ -131,11 +131,13 @@ int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, mbedtls_md_init( &ctx ); - if( (ret = mbedtls_md_setup( &ctx, md, 1) ) != 0 ) + if( ( ret = mbedtls_md_setup( &ctx, md, 1 ) ) != 0 ) { goto exit; } + memset( t, 0, hash_len ); + /* * Compute T = T(1) | T(2) | T(3) | ... | T(N) * Where T(N) is defined in RFC 5869 Section 2.3 diff --git a/features/mbedtls/mbed-crypto/src/hmac_drbg.c b/features/mbedtls/src/hmac_drbg.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/hmac_drbg.c rename to features/mbedtls/src/hmac_drbg.c diff --git a/features/mbedtls/mbed-crypto/src/md.c b/features/mbedtls/src/md.c similarity index 97% rename from features/mbedtls/mbed-crypto/src/md.c rename to features/mbedtls/src/md.c index b2352034b8..b56c2ddfe1 100644 --- a/features/mbedtls/mbed-crypto/src/md.c +++ b/features/mbedtls/src/md.c @@ -120,12 +120,14 @@ const mbedtls_md_info_t mbedtls_sha256_info = { #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) const mbedtls_md_info_t mbedtls_sha384_info = { "SHA384", MBEDTLS_MD_SHA384, 48, 128, }; +#endif const mbedtls_md_info_t mbedtls_sha512_info = { "SHA512", @@ -136,14 +138,16 @@ const mbedtls_md_info_t mbedtls_sha512_info = { #endif /* - * Reminder: update profiles in Mbed TLS's x509_crt.c when adding a new hash! + * Reminder: update profiles in x509_crt.c when adding a new hash! */ static const int supported_digests[] = { #if defined(MBEDTLS_SHA512_C) MBEDTLS_MD_SHA512, +#if !defined(MBEDTLS_SHA512_NO_SHA384) MBEDTLS_MD_SHA384, #endif +#endif #if defined(MBEDTLS_SHA256_C) MBEDTLS_MD_SHA256, @@ -211,8 +215,10 @@ const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ) return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) if( !strcmp( "SHA384", md_name ) ) return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 ); +#endif if( !strcmp( "SHA512", md_name ) ) return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); #endif @@ -250,8 +256,10 @@ const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ) return( &mbedtls_sha256_info ); #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) case MBEDTLS_MD_SHA384: return( &mbedtls_sha384_info ); +#endif case MBEDTLS_MD_SHA512: return( &mbedtls_sha512_info ); #endif @@ -306,7 +314,9 @@ void mbedtls_md_free( mbedtls_md_context_t *ctx ) break; #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) case MBEDTLS_MD_SHA384: +#endif case MBEDTLS_MD_SHA512: mbedtls_sha512_free( ctx->md_ctx ); break; @@ -372,7 +382,9 @@ int mbedtls_md_clone( mbedtls_md_context_t *dst, break; #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) case MBEDTLS_MD_SHA384: +#endif case MBEDTLS_MD_SHA512: mbedtls_sha512_clone( dst->md_ctx, src->md_ctx ); break; @@ -439,7 +451,9 @@ int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_inf break; #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) case MBEDTLS_MD_SHA384: +#endif case MBEDTLS_MD_SHA512: ALLOC( sha512 ); break; @@ -498,8 +512,10 @@ int mbedtls_md_starts( mbedtls_md_context_t *ctx ) return( mbedtls_sha256_starts_ret( ctx->md_ctx, 0 ) ); #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) case MBEDTLS_MD_SHA384: return( mbedtls_sha512_starts_ret( ctx->md_ctx, 1 ) ); +#endif case MBEDTLS_MD_SHA512: return( mbedtls_sha512_starts_ret( ctx->md_ctx, 0 ) ); #endif @@ -542,8 +558,10 @@ int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, si return( mbedtls_sha256_update_ret( ctx->md_ctx, input, ilen ) ); #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) case MBEDTLS_MD_SHA384: return( mbedtls_sha512_update_ret( ctx->md_ctx, input, ilen ) ); +#endif case MBEDTLS_MD_SHA512: return( mbedtls_sha512_update_ret( ctx->md_ctx, input, ilen ) ); #endif @@ -586,8 +604,10 @@ int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) return( mbedtls_sha256_finish_ret( ctx->md_ctx, output ) ); #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) case MBEDTLS_MD_SHA384: return( mbedtls_sha512_finish_ret( ctx->md_ctx, output ) ); +#endif case MBEDTLS_MD_SHA512: return( mbedtls_sha512_finish_ret( ctx->md_ctx, output ) ); #endif @@ -631,8 +651,10 @@ int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, si return( mbedtls_sha256_ret( input, ilen, output, 0 ) ); #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) case MBEDTLS_MD_SHA384: return( mbedtls_sha512_ret( input, ilen, output, 1 ) ); +#endif case MBEDTLS_MD_SHA512: return( mbedtls_sha512_ret( input, ilen, output, 0 ) ); #endif @@ -839,8 +861,10 @@ int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) return( mbedtls_internal_sha256_process( ctx->md_ctx, data ) ); #endif #if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) case MBEDTLS_MD_SHA384: return( mbedtls_internal_sha512_process( ctx->md_ctx, data ) ); +#endif case MBEDTLS_MD_SHA512: return( mbedtls_internal_sha512_process( ctx->md_ctx, data ) ); #endif diff --git a/features/mbedtls/mbed-crypto/src/md2.c b/features/mbedtls/src/md2.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/md2.c rename to features/mbedtls/src/md2.c diff --git a/features/mbedtls/mbed-crypto/src/md4.c b/features/mbedtls/src/md4.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/md4.c rename to features/mbedtls/src/md4.c diff --git a/features/mbedtls/mbed-crypto/src/md5.c b/features/mbedtls/src/md5.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/md5.c rename to features/mbedtls/src/md5.c diff --git a/features/mbedtls/mbed-crypto/src/memory_buffer_alloc.c b/features/mbedtls/src/memory_buffer_alloc.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/memory_buffer_alloc.c rename to features/mbedtls/src/memory_buffer_alloc.c diff --git a/features/mbedtls/mbed-crypto/src/nist_kw.c b/features/mbedtls/src/nist_kw.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/nist_kw.c rename to features/mbedtls/src/nist_kw.c diff --git a/features/mbedtls/mbed-crypto/src/oid.c b/features/mbedtls/src/oid.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/oid.c rename to features/mbedtls/src/oid.c diff --git a/features/mbedtls/mbed-crypto/src/padlock.c b/features/mbedtls/src/padlock.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/padlock.c rename to features/mbedtls/src/padlock.c diff --git a/features/mbedtls/mbed-crypto/src/pem.c b/features/mbedtls/src/pem.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/pem.c rename to features/mbedtls/src/pem.c diff --git a/features/mbedtls/mbed-crypto/src/pk.c b/features/mbedtls/src/pk.c similarity index 98% rename from features/mbedtls/mbed-crypto/src/pk.c rename to features/mbedtls/src/pk.c index 9d4100bb98..b83ba8e71d 100644 --- a/features/mbedtls/mbed-crypto/src/pk.c +++ b/features/mbedtls/src/pk.c @@ -605,6 +605,7 @@ int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk, psa_ecc_curve_t curve_id; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_type_t key_type; + size_t bits; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* export the private key material in the format PSA wants */ @@ -616,12 +617,12 @@ int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk, 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; - key_type = PSA_KEY_TYPE_ECC_KEY_PAIR( - mbedtls_psa_parse_tls_ecc_group ( curve_id ) ); + curve_id = mbedtls_ecc_group_to_psa( ec->grp.id, &bits ); + key_type = PSA_KEY_TYPE_ECC_KEY_PAIR( curve_id ); /* prepare the key attributes */ psa_set_key_type( &attributes, key_type ); + psa_set_key_bits( &attributes, bits ); psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH ); psa_set_key_algorithm( &attributes, PSA_ALG_ECDSA(hash_alg) ); diff --git a/features/mbedtls/mbed-crypto/src/pk_wrap.c b/features/mbedtls/src/pk_wrap.c similarity index 99% rename from features/mbedtls/mbed-crypto/src/pk_wrap.c rename to features/mbedtls/src/pk_wrap.c index 2c665af3c8..f736431495 100644 --- a/features/mbedtls/mbed-crypto/src/pk_wrap.c +++ b/features/mbedtls/src/pk_wrap.c @@ -542,10 +542,11 @@ static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end, return( 0 ); } -static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, +static int ecdsa_verify_wrap( void *ctx_arg, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len ) { + mbedtls_ecdsa_context *ctx = ctx_arg; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_handle_t key_handle = 0; @@ -557,9 +558,10 @@ static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, unsigned char *p; 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; + size_t curve_bits; + psa_ecc_curve_t curve = + mbedtls_ecc_group_to_psa( ctx->grp.id, &curve_bits ); + const size_t signature_part_size = ( ctx->grp.nbits + 7 ) / 8; if( curve == 0 ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); diff --git a/features/mbedtls/mbed-crypto/src/pkcs12.c b/features/mbedtls/src/pkcs12.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/pkcs12.c rename to features/mbedtls/src/pkcs12.c diff --git a/features/mbedtls/mbed-crypto/src/pkcs5.c b/features/mbedtls/src/pkcs5.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/pkcs5.c rename to features/mbedtls/src/pkcs5.c diff --git a/features/mbedtls/mbed-crypto/src/pkparse.c b/features/mbedtls/src/pkparse.c similarity index 92% rename from features/mbedtls/mbed-crypto/src/pkparse.c rename to features/mbedtls/src/pkparse.c index 596dae919f..1cbb8cc339 100644 --- a/features/mbedtls/mbed-crypto/src/pkparse.c +++ b/features/mbedtls/src/pkparse.c @@ -678,6 +678,32 @@ int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, } #if defined(MBEDTLS_RSA_C) +/* + * Wrapper around mbedtls_asn1_get_mpi() that rejects zero. + * + * The value zero is: + * - never a valid value for an RSA parameter + * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). + * + * Since values can't be omitted in PKCS#1, passing a zero value to + * rsa_complete() would be incorrect, so reject zero values early. + */ +static int asn1_get_nonzero_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ) +{ + int ret; + + ret = mbedtls_asn1_get_mpi( p, end, X ); + if( ret != 0 ) + return( ret ); + + if( mbedtls_mpi_cmp_int( X, 0 ) == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + return( 0 ); +} + /* * Parse a PKCS#1 encoded private RSA key */ @@ -730,54 +756,84 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, } /* Import N */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_INTEGER ) ) != 0 || - ( ret = mbedtls_rsa_import_raw( rsa, p, len, NULL, 0, NULL, 0, - NULL, 0, NULL, 0 ) ) != 0 ) + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, &T, NULL, NULL, + NULL, NULL ) ) != 0 ) goto cleanup; - p += len; /* Import E */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_INTEGER ) ) != 0 || - ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, - NULL, 0, p, len ) ) != 0 ) + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, + NULL, &T ) ) != 0 ) goto cleanup; - p += len; /* Import D */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_INTEGER ) ) != 0 || - ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, - p, len, NULL, 0 ) ) != 0 ) + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, + &T, NULL ) ) != 0 ) goto cleanup; - p += len; /* Import P */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_INTEGER ) ) != 0 || - ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, p, len, NULL, 0, - NULL, 0, NULL, 0 ) ) != 0 ) + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, &T, NULL, + NULL, NULL ) ) != 0 ) goto cleanup; - p += len; /* Import Q */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_INTEGER ) ) != 0 || - ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, p, len, - NULL, 0, NULL, 0 ) ) != 0 ) - goto cleanup; - p += len; - - /* Complete the RSA private key */ - if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 ) + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, &T, + NULL, NULL ) ) != 0 ) goto cleanup; - /* Check optional parameters */ - if( ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ) +#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) + /* + * The RSA CRT parameters DP, DQ and QP are nominally redundant, in + * that they can be easily recomputed from D, P and Q. However by + * parsing them from the PKCS1 structure it is possible to avoid + * recalculating them which both reduces the overhead of loading + * RSA private keys into memory and also avoids side channels which + * can arise when computing those values, since all of D, P, and Q + * are secret. See https://eprint.iacr.org/2020/055 for a + * description of one such attack. + */ + + /* Import DP */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->DP, &T ) ) != 0 ) + goto cleanup; + + /* Import DQ */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->DQ, &T ) ) != 0 ) + goto cleanup; + + /* Import QP */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->QP, &T ) ) != 0 ) + goto cleanup; + +#else + /* Verify existance of the CRT params */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ) + goto cleanup; +#endif + + /* rsa_complete() doesn't complete anything with the default + * implementation but is still called: + * - for the benefit of alternative implementation that may want to + * pre-compute stuff beyond what's provided (eg Montgomery factors) + * - as is also sanity-checks the key + * + * Furthermore, we also check the public part for consistency with + * mbedtls_pk_parse_pubkey(), as it includes size minima for example. + */ + if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 || + ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 ) + { goto cleanup; + } if( p != end ) { diff --git a/features/mbedtls/mbed-crypto/src/pkwrite.c b/features/mbedtls/src/pkwrite.c similarity index 99% rename from features/mbedtls/mbed-crypto/src/pkwrite.c rename to features/mbedtls/src/pkwrite.c index 49a21bf08b..b1b5f4685a 100644 --- a/features/mbedtls/mbed-crypto/src/pkwrite.c +++ b/features/mbedtls/src/pkwrite.c @@ -273,18 +273,20 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, si psa_key_type_t key_type; psa_key_handle_t handle; psa_ecc_curve_t curve; + size_t bits; handle = *((psa_key_handle_t*) key->pk_ctx ); if( PSA_SUCCESS != psa_get_key_attributes( handle, &attributes ) ) return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); key_type = psa_get_key_type( &attributes ); + bits = psa_get_key_bits( &attributes ); psa_reset_key_attributes( &attributes ); curve = PSA_KEY_TYPE_GET_CURVE( key_type ); if( curve == 0 ) return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); - ret = mbedtls_psa_get_ecc_oid_from_id( curve, &oid, &oid_len ); + ret = mbedtls_psa_get_ecc_oid_from_id( curve, bits, &oid, &oid_len ); if( ret != 0 ) return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); diff --git a/features/mbedtls/mbed-crypto/src/platform.c b/features/mbedtls/src/platform.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/platform.c rename to features/mbedtls/src/platform.c diff --git a/features/mbedtls/mbed-crypto/src/platform_util.c b/features/mbedtls/src/platform_util.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/platform_util.c rename to features/mbedtls/src/platform_util.c diff --git a/features/mbedtls/mbed-crypto/src/poly1305.c b/features/mbedtls/src/poly1305.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/poly1305.c rename to features/mbedtls/src/poly1305.c diff --git a/features/mbedtls/mbed-crypto/src/ripemd160.c b/features/mbedtls/src/ripemd160.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/ripemd160.c rename to features/mbedtls/src/ripemd160.c diff --git a/features/mbedtls/mbed-crypto/src/rsa.c b/features/mbedtls/src/rsa.c similarity index 99% rename from features/mbedtls/mbed-crypto/src/rsa.c rename to features/mbedtls/src/rsa.c index 3c2f31438c..6c457468ea 100644 --- a/features/mbedtls/mbed-crypto/src/rsa.c +++ b/features/mbedtls/src/rsa.c @@ -250,6 +250,9 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) { int ret = 0; int have_N, have_P, have_Q, have_D, have_E; +#if !defined(MBEDTLS_RSA_NO_CRT) + int have_DP, have_DQ, have_QP; +#endif int n_missing, pq_missing, d_missing, is_pub, is_priv; RSA_VALIDATE_RET( ctx != NULL ); @@ -260,6 +263,12 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 ); have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 ); +#if !defined(MBEDTLS_RSA_NO_CRT) + have_DP = ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) != 0 ); + have_DQ = ( mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) != 0 ); + have_QP = ( mbedtls_mpi_cmp_int( &ctx->QP, 0 ) != 0 ); +#endif + /* * Check whether provided parameters are enough * to deduce all others. The following incomplete @@ -325,7 +334,7 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) */ #if !defined(MBEDTLS_RSA_NO_CRT) - if( is_priv ) + if( is_priv && ! ( have_DP && have_DQ && have_QP ) ) { ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, &ctx->DP, &ctx->DQ, &ctx->QP ); diff --git a/features/mbedtls/mbed-crypto/src/rsa_internal.c b/features/mbedtls/src/rsa_internal.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/rsa_internal.c rename to features/mbedtls/src/rsa_internal.c diff --git a/features/mbedtls/mbed-crypto/src/sha1.c b/features/mbedtls/src/sha1.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/sha1.c rename to features/mbedtls/src/sha1.c diff --git a/features/mbedtls/mbed-crypto/src/sha256.c b/features/mbedtls/src/sha256.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/sha256.c rename to features/mbedtls/src/sha256.c diff --git a/features/mbedtls/mbed-crypto/src/sha512.c b/features/mbedtls/src/sha512.c similarity index 96% rename from features/mbedtls/mbed-crypto/src/sha512.c rename to features/mbedtls/src/sha512.c index fa4025653d..30dd719540 100644 --- a/features/mbedtls/mbed-crypto/src/sha512.c +++ b/features/mbedtls/src/sha512.c @@ -132,7 +132,11 @@ void mbedtls_sha512_clone( mbedtls_sha512_context *dst, int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ) { SHA512_VALIDATE_RET( ctx != NULL ); +#if !defined(MBEDTLS_SHA512_NO_SHA384) SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); +#else + SHA512_VALIDATE_RET( is384 == 0 ); +#endif ctx->total[0] = 0; ctx->total[1] = 0; @@ -151,6 +155,9 @@ int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ) } else { +#if defined(MBEDTLS_SHA512_NO_SHA384) + return( MBEDTLS_ERR_SHA512_BAD_INPUT_DATA ); +#else /* SHA-384 */ ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); ctx->state[1] = UL64(0x629A292A367CD507); @@ -160,9 +167,12 @@ int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ) ctx->state[5] = UL64(0x8EB44A8768581511); ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); ctx->state[7] = UL64(0x47B5481DBEFA4FA4); +#endif /* MBEDTLS_SHA512_NO_SHA384 */ } +#if !defined(MBEDTLS_SHA512_NO_SHA384) ctx->is384 = is384; +#endif return( 0 ); } @@ -437,7 +447,9 @@ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, sha512_put_uint64_be( ctx->state[4], output, 32 ); sha512_put_uint64_be( ctx->state[5], output, 40 ); +#if !defined(MBEDTLS_SHA512_NO_SHA384) if( ctx->is384 == 0 ) +#endif { sha512_put_uint64_be( ctx->state[6], output, 48 ); sha512_put_uint64_be( ctx->state[7], output, 56 ); @@ -467,7 +479,11 @@ int mbedtls_sha512_ret( const unsigned char *input, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_sha512_context ctx; +#if !defined(MBEDTLS_SHA512_NO_SHA384) SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); +#else + SHA512_VALIDATE_RET( is384 == 0 ); +#endif SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); @@ -516,8 +532,9 @@ static const size_t sha512_test_buflen[3] = 3, 112, 1000 }; -static const unsigned char sha512_test_sum[6][64] = +static const unsigned char sha512_test_sum[][64] = { +#if !defined(MBEDTLS_SHA512_NO_SHA384) /* * SHA-384 test vectors */ @@ -539,6 +556,7 @@ static const unsigned char sha512_test_sum[6][64] = 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }, +#endif /* !MBEDTLS_SHA512_NO_SHA384 */ /* * SHA-512 test vectors @@ -569,6 +587,8 @@ static const unsigned char sha512_test_sum[6][64] = 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } }; +#define ARRAY_LENGTH( a ) ( sizeof( a ) / sizeof( ( a )[0] ) ) + /* * Checkup routine */ @@ -590,10 +610,14 @@ int mbedtls_sha512_self_test( int verbose ) mbedtls_sha512_init( &ctx ); - for( i = 0; i < 6; i++ ) + for( i = 0; i < (int) ARRAY_LENGTH(sha512_test_sum); i++ ) { j = i % 3; +#if !defined(MBEDTLS_SHA512_NO_SHA384) k = i < 3; +#else + k = 0; +#endif if( verbose != 0 ) mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 ); @@ -649,6 +673,8 @@ exit: return( ret ); } +#undef ARRAY_LENGTH + #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SHA512_C */ diff --git a/features/mbedtls/src/ssl_ciphersuites.c b/features/mbedtls/src/ssl_ciphersuites.c index 518f7dde00..5da1294124 100644 --- a/features/mbedtls/src/ssl_ciphersuites.c +++ b/features/mbedtls/src/ssl_ciphersuites.c @@ -2353,7 +2353,7 @@ int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) } #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ) { switch( info->key_exchange ) @@ -2368,6 +2368,6 @@ int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ) return( 0 ); } } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #endif /* MBEDTLS_SSL_TLS_C */ diff --git a/features/mbedtls/src/ssl_cli.c b/features/mbedtls/src/ssl_cli.c index 1005bd97fa..553e2b6a31 100644 --- a/features/mbedtls/src/ssl_cli.c +++ b/features/mbedtls/src/ssl_cli.c @@ -56,7 +56,7 @@ #include "mbedtls/platform_util.h" #endif -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#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 || @@ -92,7 +92,7 @@ static int ssl_conf_has_static_raw_psk( mbedtls_ssl_config const *conf ) } #endif /* MBEDTLS_USE_PSA_CRYPTO */ -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, @@ -208,7 +208,7 @@ static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, * Only if we handle at least one key exchange that needs signatures. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen ) @@ -290,7 +290,7 @@ static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, *olen = 6 + sig_alg_len; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -846,13 +846,13 @@ static int ssl_validate_ciphersuite( const mbedtls_ssl_ciphersuite_t * suite_inf #endif /* Don't suggest PSK-based ciphersuite if no PSK is available. */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#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 */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ return( 0 ); } @@ -1112,7 +1112,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif @@ -1578,6 +1578,19 @@ static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) ); + /* Check that there is enough room for: + * - 2 bytes of version + * - 1 byte of cookie_len + */ + if( mbedtls_ssl_hs_hdr_len( ssl ) + 3 > ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "incoming HelloVerifyRequest message is too short" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + /* * struct { * ProtocolVersion server_version; @@ -1606,8 +1619,6 @@ static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl ) } cookie_len = *p++; - MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len ); - if( ( ssl->in_msg + ssl->in_msglen ) - p < cookie_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, @@ -1616,6 +1627,7 @@ static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } + MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len ); mbedtls_free( ssl->handshake->verify_cookie ); @@ -1923,7 +1935,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) { @@ -2244,6 +2256,7 @@ static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl, unsigned char *end ) { uint16_t tls_id; + size_t ecdh_bits = 0; uint8_t ecpoint_len; mbedtls_ssl_handshake_params *handshake = ssl->handshake; @@ -2264,11 +2277,14 @@ static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl, tls_id |= *(*p)++; /* Convert EC group to PSA key type. */ - if( ( handshake->ecdh_psa_curve = - mbedtls_psa_parse_tls_ecc_group( tls_id ) ) == 0 ) + if( ( handshake->ecdh_psa_type = + mbedtls_psa_parse_tls_ecc_group( tls_id, &ecdh_bits ) ) == 0 ) { return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } + if( ecdh_bits > 0xffff ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + handshake->ecdh_bits = (uint16_t) ecdh_bits; /* * Put peer's ECDH public key in the format understood by PSA. @@ -2278,7 +2294,7 @@ static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl, if( (size_t)( end - *p ) < ecpoint_len ) return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - if( mbedtls_psa_tls_ecpoint_to_psa_ec( handshake->ecdh_psa_curve, + if( mbedtls_psa_tls_ecpoint_to_psa_ec( *p, ecpoint_len, handshake->ecdh_psa_peerkey, sizeof( handshake->ecdh_psa_peerkey ), @@ -2315,7 +2331,7 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, (const unsigned char **) p, end ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret ); -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; #endif @@ -2334,13 +2350,13 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, unsigned char **p, unsigned char *end ) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - size_t len; + uint16_t len; ((void) ssl); /* @@ -2357,7 +2373,7 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, len = (*p)[0] << 8 | (*p)[1]; *p += 2; - if( end - (*p) < (int) len ) + if( end - (*p) < len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " "(psk_identity_hint length)" ) ); @@ -2374,7 +2390,7 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, return( ret ); } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) @@ -2623,7 +2639,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ssl->handshake->ecrs_enabled && ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing ) { @@ -2668,7 +2684,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ssl->handshake->ecrs_enabled ) ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing; @@ -2678,7 +2694,7 @@ start_processing: end = ssl->in_msg + ssl->in_hslen; MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p ); -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || @@ -2692,7 +2708,7 @@ start_processing: return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } /* FALLTROUGH */ -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) @@ -2775,7 +2791,7 @@ start_processing: return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) { size_t sig_len, hashlen; @@ -2913,7 +2929,7 @@ start_processing: return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); } -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ssl->handshake->ecrs_enabled ) rs_ctx = &ssl->handshake->ecrs_ctx.pk; #endif @@ -2921,13 +2937,13 @@ start_processing: if( ( ret = mbedtls_pk_verify_restartable( peer_pk, md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 ) { -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) #endif mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; #endif @@ -2941,7 +2957,7 @@ start_processing: mbedtls_pk_free( peer_pk ); #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ } -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ exit: ssl->state++; @@ -2951,7 +2967,7 @@ exit: return( 0 ); } -#if ! defined(MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED) +#if ! defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = @@ -2969,7 +2985,7 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } -#else /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ +#else /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -3132,7 +3148,7 @@ exit: return( 0 ); } -#endif /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) { @@ -3257,11 +3273,8 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) key_attributes = psa_key_attributes_init(); psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_DERIVE ); psa_set_key_algorithm( &key_attributes, PSA_ALG_ECDH ); - psa_set_key_type( &key_attributes, - PSA_KEY_TYPE_ECC_KEY_PAIR( handshake->ecdh_psa_curve ) - ); - psa_set_key_bits( &key_attributes, - PSA_ECC_CURVE_BITS( handshake->ecdh_psa_curve ) ); + psa_set_key_type( &key_attributes, handshake->ecdh_psa_type ); + psa_set_key_bits( &key_attributes, handshake->ecdh_bits ); /* Generate ECDH private key. */ status = psa_generate_key( &key_attributes, @@ -3327,7 +3340,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) */ header_len = 4; -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ssl->handshake->ecrs_enabled ) { if( ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret ) @@ -3344,7 +3357,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; #endif @@ -3354,7 +3367,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Q ); -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ssl->handshake->ecrs_enabled ) { ssl->handshake->ecrs_n = content_len; @@ -3372,7 +3385,7 @@ ecdh_calc_secret: ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; #endif @@ -3387,7 +3400,7 @@ ecdh_calc_secret: MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) if( mbedtls_ssl_ciphersuite_uses_psk( ciphersuite_info ) ) { /* @@ -3530,7 +3543,7 @@ ecdh_calc_secret: } } else -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) { @@ -3591,7 +3604,7 @@ ecdh_calc_secret: return( 0 ); } -#if !defined(MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED) +#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = @@ -3616,7 +3629,7 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } -#else /* !MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ +#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; @@ -3631,7 +3644,7 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ssl->handshake->ecrs_enabled && ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign ) { @@ -3668,7 +3681,7 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) /* * Make a signature of the handshake digests */ -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ssl->handshake->ecrs_enabled ) ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign; @@ -3749,7 +3762,7 @@ sign: return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ssl->handshake->ecrs_enabled ) rs_ctx = &ssl->handshake->ecrs_ctx.pk; #endif @@ -3760,7 +3773,7 @@ sign: ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; #endif @@ -3786,7 +3799,7 @@ sign: return( ret ); } -#endif /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) diff --git a/features/mbedtls/src/ssl_msg.c b/features/mbedtls/src/ssl_msg.c new file mode 100644 index 0000000000..976fc7b00b --- /dev/null +++ b/features/mbedtls/src/ssl_msg.c @@ -0,0 +1,5738 @@ +/* + * Generic SSL/TLS messaging layer functions + * (record layer + retransmission state machine) + * + * Copyright (C) 2006-2020, 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) + */ +/* + * The SSL 3.0 specification was drafted by Netscape in 1996, + * and became an IETF standard in 1999. + * + * http://wp.netscape.com/eng/ssl3/ + * http://www.ietf.org/rfc/rfc2246.txt + * http://www.ietf.org/rfc/rfc4346.txt + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/version.h" + +#include + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/psa_util.h" +#include "psa/crypto.h" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "mbedtls/oid.h" +#endif + +static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ); + +/* + * Start a timer. + * Passing millisecs = 0 cancels a running timer. + */ +void mbedtls_ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ) +{ + if( ssl->f_set_timer == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) ); + ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs ); +} + +/* + * Return -1 is timer is expired, 0 if it isn't. + */ +int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl ) +{ + if( ssl->f_get_timer == NULL ) + return( 0 ); + + if( ssl->f_get_timer( ssl->p_timer ) == 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) ); + return( -1 ); + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_RECORD_CHECKING) +static int ssl_parse_record_header( mbedtls_ssl_context const *ssl, + unsigned char *buf, + size_t len, + mbedtls_record *rec ); + +int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl, + unsigned char *buf, + size_t buflen ) +{ + int ret = 0; + MBEDTLS_SSL_DEBUG_MSG( 1, ( "=> mbedtls_ssl_check_record" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "record buffer", buf, buflen ); + + /* We don't support record checking in TLS because + * (a) there doesn't seem to be a usecase for it, and + * (b) In SSLv3 and TLS 1.0, CBC record decryption has state + * and we'd need to backup the transform here. + */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) + { + ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + goto exit; + } +#if defined(MBEDTLS_SSL_PROTO_DTLS) + else + { + mbedtls_record rec; + + ret = ssl_parse_record_header( ssl, buf, buflen, &rec ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 3, "ssl_parse_record_header", ret ); + goto exit; + } + + if( ssl->transform_in != NULL ) + { + ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in, &rec ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 3, "mbedtls_ssl_decrypt_buf", ret ); + goto exit; + } + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +exit: + /* On success, we have decrypted the buffer in-place, so make + * sure we don't leak any plaintext data. */ + mbedtls_platform_zeroize( buf, buflen ); + + /* For the purpose of this API, treat messages with unexpected CID + * as well as such from future epochs as unexpected. */ + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID || + ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "<= mbedtls_ssl_check_record" ) ); + return( ret ); +} +#endif /* MBEDTLS_SSL_RECORD_CHECKING */ + +#define SSL_DONT_FORCE_FLUSH 0 +#define SSL_FORCE_FLUSH 1 + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +/* Forward declarations for functions related to message buffering. */ +static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, + uint8_t slot ); +static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ); +static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ); +static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ); +static int ssl_buffer_message( mbedtls_ssl_context *ssl ); +static int ssl_buffer_future_record( mbedtls_ssl_context *ssl, + mbedtls_record const *rec ); +static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ); + +static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl ) +{ + size_t mtu = mbedtls_ssl_get_current_mtu( ssl ); +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len; +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + + if( mtu != 0 && mtu < out_buf_len ) + return( mtu ); + + return( out_buf_len ); +} + +static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl ) +{ + size_t const bytes_written = ssl->out_left; + size_t const mtu = ssl_get_maximum_datagram_size( ssl ); + + /* Double-check that the write-index hasn't gone + * past what we can transmit in a single datagram. */ + if( bytes_written > mtu ) + { + /* Should never happen... */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( (int) ( mtu - bytes_written ) ); +} + +static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t remaining, expansion; + size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_output_max_frag_len( ssl ); + + if( max_len > mfl ) + max_len = mfl; + + /* By the standard (RFC 6066 Sect. 4), the MFL extension + * only limits the maximum record payload size, so in theory + * we would be allowed to pack multiple records of payload size + * MFL into a single datagram. However, this would mean that there's + * no way to explicitly communicate MTU restrictions to the peer. + * + * The following reduction of max_len makes sure that we never + * write datagrams larger than MFL + Record Expansion Overhead. + */ + if( max_len <= ssl->out_left ) + return( 0 ); + + max_len -= ssl->out_left; +#endif + + ret = ssl_get_remaining_space_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + remaining = (size_t) ret; + + ret = mbedtls_ssl_get_record_expansion( ssl ); + if( ret < 0 ) + return( ret ); + expansion = (size_t) ret; + + if( remaining <= expansion ) + return( 0 ); + + remaining -= expansion; + if( remaining >= max_len ) + remaining = max_len; + + return( (int) remaining ); +} + +/* + * Double the retransmit timeout value, within the allowed range, + * returning -1 if the maximum value has already been reached. + */ +static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ) +{ + uint32_t new_timeout; + + if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max ) + return( -1 ); + + /* Implement the final paragraph of RFC 6347 section 4.1.1.1 + * in the following way: after the initial transmission and a first + * retransmission, back off to a temporary estimated MTU of 508 bytes. + * This value is guaranteed to be deliverable (if not guaranteed to be + * delivered) of any compliant IPv4 (and IPv6) network, and should work + * on most non-IP stacks too. */ + if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min ) + { + ssl->handshake->mtu = 508; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) ); + } + + new_timeout = 2 * ssl->handshake->retransmit_timeout; + + /* Avoid arithmetic overflow and range overflow */ + if( new_timeout < ssl->handshake->retransmit_timeout || + new_timeout > ssl->conf->hs_timeout_max ) + { + new_timeout = ssl->conf->hs_timeout_max; + } + + ssl->handshake->retransmit_timeout = new_timeout; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", + ssl->handshake->retransmit_timeout ) ); + + return( 0 ); +} + +static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl ) +{ + ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", + ssl->handshake->retransmit_timeout ) ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) +int (*mbedtls_ssl_hw_record_init)( mbedtls_ssl_context *ssl, + const unsigned char *key_enc, const unsigned char *key_dec, + size_t keylen, + const unsigned char *iv_enc, const unsigned char *iv_dec, + size_t ivlen, + const unsigned char *mac_enc, const unsigned char *mac_dec, + size_t maclen ) = NULL; +int (*mbedtls_ssl_hw_record_activate)( mbedtls_ssl_context *ssl, int direction) = NULL; +int (*mbedtls_ssl_hw_record_reset)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_write)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_read)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_finish)( mbedtls_ssl_context *ssl ) = NULL; +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +/* The function below is only used in the Lucky 13 counter-measure in + * mbedtls_ssl_decrypt_buf(). These are the defines that guard the call site. */ +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) && \ + ( defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) ) +/* This function makes sure every byte in the memory region is accessed + * (in ascending addresses order) */ +static void ssl_read_memory( unsigned char *p, size_t len ) +{ + unsigned char acc = 0; + volatile unsigned char force; + + for( ; len != 0; p++, len-- ) + acc ^= *p; + + force = acc; + (void) force; +} +#endif /* SSL_SOME_MODES_USE_MAC && ( TLS1 || TLS1_1 || TLS1_2 ) */ + +/* + * Encryption/decryption functions + */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +/* This functions transforms a DTLS plaintext fragment and a record content + * type into an instance of the DTLSInnerPlaintext structure: + * + * struct { + * opaque content[DTLSPlaintext.length]; + * ContentType real_type; + * uint8 zeros[length_of_padding]; + * } DTLSInnerPlaintext; + * + * Input: + * - `content`: The beginning of the buffer holding the + * plaintext to be wrapped. + * - `*content_size`: The length of the plaintext in Bytes. + * - `max_len`: The number of Bytes available starting from + * `content`. This must be `>= *content_size`. + * - `rec_type`: The desired record content type. + * + * Output: + * - `content`: The beginning of the resulting DTLSInnerPlaintext structure. + * - `*content_size`: The length of the resulting DTLSInnerPlaintext structure. + * + * Returns: + * - `0` on success. + * - A negative error code if `max_len` didn't offer enough space + * for the expansion. + */ +static int ssl_cid_build_inner_plaintext( unsigned char *content, + size_t *content_size, + size_t remaining, + uint8_t rec_type ) +{ + size_t len = *content_size; + size_t pad = ( MBEDTLS_SSL_CID_PADDING_GRANULARITY - + ( len + 1 ) % MBEDTLS_SSL_CID_PADDING_GRANULARITY ) % + MBEDTLS_SSL_CID_PADDING_GRANULARITY; + + /* Write real content type */ + if( remaining == 0 ) + return( -1 ); + content[ len ] = rec_type; + len++; + remaining--; + + if( remaining < pad ) + return( -1 ); + memset( content + len, 0, pad ); + len += pad; + remaining -= pad; + + *content_size = len; + return( 0 ); +} + +/* This function parses a DTLSInnerPlaintext structure. + * See ssl_cid_build_inner_plaintext() for details. */ +static int ssl_cid_parse_inner_plaintext( unsigned char const *content, + size_t *content_size, + uint8_t *rec_type ) +{ + size_t remaining = *content_size; + + /* Determine length of padding by skipping zeroes from the back. */ + do + { + if( remaining == 0 ) + return( -1 ); + remaining--; + } while( content[ remaining ] == 0 ); + + *content_size = remaining; + *rec_type = content[ remaining ]; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +/* `add_data` must have size 13 Bytes if the CID extension is disabled, + * and 13 + 1 + CID-length Bytes if the CID extension is enabled. */ +static void ssl_extract_add_data_from_record( unsigned char* add_data, + size_t *add_data_len, + mbedtls_record *rec ) +{ + /* Quoting RFC 5246 (TLS 1.2): + * + * additional_data = seq_num + TLSCompressed.type + + * TLSCompressed.version + TLSCompressed.length; + * + * For the CID extension, this is extended as follows + * (quoting draft-ietf-tls-dtls-connection-id-05, + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05): + * + * additional_data = seq_num + DTLSPlaintext.type + + * DTLSPlaintext.version + + * cid + + * cid_length + + * length_of_DTLSInnerPlaintext; + */ + + memcpy( add_data, rec->ctr, sizeof( rec->ctr ) ); + add_data[8] = rec->type; + memcpy( add_data + 9, rec->ver, sizeof( rec->ver ) ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( rec->cid_len != 0 ) + { + memcpy( add_data + 11, rec->cid, rec->cid_len ); + add_data[11 + rec->cid_len + 0] = rec->cid_len; + add_data[11 + rec->cid_len + 1] = ( rec->data_len >> 8 ) & 0xFF; + add_data[11 + rec->cid_len + 2] = ( rec->data_len >> 0 ) & 0xFF; + *add_data_len = 13 + 1 + rec->cid_len; + } + else +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + { + add_data[11 + 0] = ( rec->data_len >> 8 ) & 0xFF; + add_data[11 + 1] = ( rec->data_len >> 0 ) & 0xFF; + *add_data_len = 13; + } +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + +#define SSL3_MAC_MAX_BYTES 20 /* MD-5 or SHA-1 */ + +/* + * SSLv3.0 MAC functions + */ +static void ssl_mac( mbedtls_md_context_t *md_ctx, + const unsigned char *secret, + const unsigned char *buf, size_t len, + const unsigned char *ctr, int type, + unsigned char out[SSL3_MAC_MAX_BYTES] ) +{ + unsigned char header[11]; + unsigned char padding[48]; + int padlen; + int md_size = mbedtls_md_get_size( md_ctx->md_info ); + int md_type = mbedtls_md_get_type( md_ctx->md_info ); + + /* Only MD5 and SHA-1 supported */ + if( md_type == MBEDTLS_MD_MD5 ) + padlen = 48; + else + padlen = 40; + + memcpy( header, ctr, 8 ); + header[ 8] = (unsigned char) type; + header[ 9] = (unsigned char)( len >> 8 ); + header[10] = (unsigned char)( len ); + + memset( padding, 0x36, padlen ); + mbedtls_md_starts( md_ctx ); + mbedtls_md_update( md_ctx, secret, md_size ); + mbedtls_md_update( md_ctx, padding, padlen ); + mbedtls_md_update( md_ctx, header, 11 ); + mbedtls_md_update( md_ctx, buf, len ); + mbedtls_md_finish( md_ctx, out ); + + memset( padding, 0x5C, padlen ); + mbedtls_md_starts( md_ctx ); + mbedtls_md_update( md_ctx, secret, md_size ); + mbedtls_md_update( md_ctx, padding, padlen ); + mbedtls_md_update( md_ctx, out, md_size ); + mbedtls_md_finish( md_ctx, out ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform, + mbedtls_record *rec, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + mbedtls_cipher_mode_t mode; + int auth_done = 0; + unsigned char * data; + unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_OUT_LEN_MAX ]; + size_t add_data_len; + size_t post_avail; + + /* The SSL context is only used for debugging purposes! */ +#if !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for debug */ + ((void) ssl); +#endif + + /* The PRNG is used for dynamic IV generation that's used + * for CBC transformations in TLS 1.1 and TLS 1.2. */ +#if !( defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || \ + defined(MBEDTLS_ARIA_C) || \ + defined(MBEDTLS_CAMELLIA_C) ) && \ + ( defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) ) ) + ((void) f_rng); + ((void) p_rng); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); + + if( transform == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no transform provided to encrypt_buf" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + if( rec == NULL + || rec->buf == NULL + || rec->buf_len < rec->data_offset + || rec->buf_len - rec->data_offset < rec->data_len +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + || rec->cid_len != 0 +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to encrypt_buf" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + data = rec->buf + rec->data_offset; + post_avail = rec->buf_len - ( rec->data_len + rec->data_offset ); + MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload", + data, rec->data_len ); + + mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ); + + if( rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d", + (unsigned) rec->data_len, + MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* + * Add CID information + */ + rec->cid_len = transform->out_cid_len; + memcpy( rec->cid, transform->out_cid, transform->out_cid_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "CID", rec->cid, rec->cid_len ); + + if( rec->cid_len != 0 ) + { + /* + * Wrap plaintext into DTLSInnerPlaintext structure. + * See ssl_cid_build_inner_plaintext() for more information. + * + * Note that this changes `rec->data_len`, and hence + * `post_avail` needs to be recalculated afterwards. + */ + if( ssl_cid_build_inner_plaintext( data, + &rec->data_len, + post_avail, + rec->type ) != 0 ) + { + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + rec->type = MBEDTLS_SSL_MSG_CID; + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + post_avail = rec->buf_len - ( rec->data_len + rec->data_offset ); + + /* + * Add MAC before if needed + */ +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + if( mode == MBEDTLS_MODE_STREAM || + ( mode == MBEDTLS_MODE_CBC +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + && transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED +#endif + ) ) + { + if( post_avail < transform->maclen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + unsigned char mac[SSL3_MAC_MAX_BYTES]; + ssl_mac( &transform->md_ctx_enc, transform->mac_enc, + data, rec->data_len, rec->ctr, rec->type, mac ); + memcpy( data + rec->data_len, mac, transform->maclen ); + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + + ssl_extract_add_data_from_record( add_data, &add_data_len, rec ); + + mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data, + add_data_len ); + mbedtls_md_hmac_update( &transform->md_ctx_enc, + data, rec->data_len ); + mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac ); + mbedtls_md_hmac_reset( &transform->md_ctx_enc ); + + memcpy( data + rec->data_len, mac, transform->maclen ); + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", data + rec->data_len, + transform->maclen ); + + rec->data_len += transform->maclen; + post_avail -= transform->maclen; + auth_done++; + } +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ + + /* + * Encrypt + */ +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) + if( mode == MBEDTLS_MODE_STREAM ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of padding", + rec->data_len, 0 ) ); + + if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc, + transform->iv_enc, transform->ivlen, + data, rec->data_len, + data, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( rec->data_len != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ + +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if( mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char iv[12]; + size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen; + + /* Check that there's space for both the authentication tag + * and the explicit IV before and after the record content. */ + if( post_avail < transform->taglen || + rec->data_offset < explicit_iv_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + /* + * Generate IV + */ + if( transform->ivlen == 12 && transform->fixed_ivlen == 4 ) + { + /* GCM and CCM: fixed || explicit (=seqnum) */ + memcpy( iv, transform->iv_enc, transform->fixed_ivlen ); + memcpy( iv + transform->fixed_ivlen, rec->ctr, + explicit_iv_len ); + /* Prefix record content with explicit IV. */ + memcpy( data - explicit_iv_len, rec->ctr, explicit_iv_len ); + } + else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 ) + { + /* ChachaPoly: fixed XOR sequence number */ + unsigned char i; + + memcpy( iv, transform->iv_enc, transform->fixed_ivlen ); + + for( i = 0; i < 8; i++ ) + iv[i+4] ^= rec->ctr[i]; + } + else + { + /* Reminder if we ever add an AEAD mode with a different size */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl_extract_add_data_from_record( add_data, &add_data_len, rec ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)", + iv, transform->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)", + data - explicit_iv_len, explicit_iv_len ); + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, add_data_len ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including 0 bytes of padding", + rec->data_len ) ); + + /* + * Encrypt and authenticate + */ + + if( ( ret = mbedtls_cipher_auth_encrypt( &transform->cipher_ctx_enc, + iv, transform->ivlen, + add_data, add_data_len, /* add data */ + data, rec->data_len, /* source */ + data, &rec->data_len, /* destination */ + data + rec->data_len, transform->taglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag", + data + rec->data_len, transform->taglen ); + + rec->data_len += transform->taglen + explicit_iv_len; + rec->data_offset -= explicit_iv_len; + post_avail -= transform->taglen; + auth_done++; + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) ) + if( mode == MBEDTLS_MODE_CBC ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t padlen, i; + size_t olen; + + /* Currently we're always using minimal padding + * (up to 255 bytes would be allowed). */ + padlen = transform->ivlen - ( rec->data_len + 1 ) % transform->ivlen; + if( padlen == transform->ivlen ) + padlen = 0; + + /* Check there's enough space in the buffer for the padding. */ + if( post_avail < padlen + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + for( i = 0; i <= padlen; i++ ) + data[rec->data_len + i] = (unsigned char) padlen; + + rec->data_len += padlen + 1; + post_avail -= padlen + 1; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Prepend per-record IV for block cipher in TLS v1.1 and up as per + * Method 1 (6.2.3.2. in RFC4346 and RFC5246) + */ + if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + if( f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "No PRNG provided to encrypt_record routine" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( rec->data_offset < transform->ivlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + /* + * Generate IV + */ + ret = f_rng( p_rng, transform->iv_enc, transform->ivlen ); + if( ret != 0 ) + return( ret ); + + memcpy( data - transform->ivlen, transform->iv_enc, + transform->ivlen ); + + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " + "including %d bytes of IV and %d bytes of padding", + rec->data_len, transform->ivlen, + padlen + 1 ) ); + + if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc, + transform->iv_enc, + transform->ivlen, + data, rec->data_len, + data, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( rec->data_len != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( transform->iv_enc, transform->cipher_ctx_enc.iv, + transform->ivlen ); + } + else +#endif + { + data -= transform->ivlen; + rec->data_offset -= transform->ivlen; + rec->data_len += transform->ivlen; + } + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( auth_done == 0 ) + { + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + + /* + * MAC(MAC_write_key, seq_num + + * TLSCipherText.type + + * TLSCipherText.version + + * length_of( (IV +) ENC(...) ) + + * IV + // except for TLS 1.0 + * ENC(content + padding + padding_length)); + */ + + if( post_avail < transform->maclen) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl_extract_add_data_from_record( add_data, &add_data_len, rec ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data, + add_data_len ); + + mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data, + add_data_len ); + mbedtls_md_hmac_update( &transform->md_ctx_enc, + data, rec->data_len ); + mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac ); + mbedtls_md_hmac_reset( &transform->md_ctx_enc ); + + memcpy( data + rec->data_len, mac, transform->maclen ); + + rec->data_len += transform->maclen; + post_avail -= transform->maclen; + auth_done++; + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + } + else +#endif /* MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); + + return( 0 ); +} + +int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, + mbedtls_ssl_transform *transform, + mbedtls_record *rec ) +{ + size_t olen; + mbedtls_cipher_mode_t mode; + int ret, auth_done = 0; +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + size_t padlen = 0, correct = 1; +#endif + unsigned char* data; + unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_IN_LEN_MAX ]; + size_t add_data_len; + +#if !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for debug */ + ((void) ssl); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) ); + if( rec == NULL || + rec->buf == NULL || + rec->buf_len < rec->data_offset || + rec->buf_len - rec->data_offset < rec->data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to decrypt_buf" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + data = rec->buf + rec->data_offset; + mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_dec ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* + * Match record's CID with incoming CID. + */ + if( rec->cid_len != transform->in_cid_len || + memcmp( rec->cid, transform->in_cid, rec->cid_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_UNEXPECTED_CID ); + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) + if( mode == MBEDTLS_MODE_STREAM ) + { + padlen = 0; + if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec, + transform->iv_dec, + transform->ivlen, + data, rec->data_len, + data, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( rec->data_len != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if( mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY ) + { + unsigned char iv[12]; + size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen; + + /* + * Prepare IV from explicit and implicit data. + */ + + /* Check that there's enough space for the explicit IV + * (at the beginning of the record) and the MAC (at the + * end of the record). */ + if( rec->data_len < explicit_iv_len + transform->taglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) " + "+ taglen (%d)", rec->data_len, + explicit_iv_len, transform->taglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) + if( transform->ivlen == 12 && transform->fixed_ivlen == 4 ) + { + /* GCM and CCM: fixed || explicit */ + + /* Fixed */ + memcpy( iv, transform->iv_dec, transform->fixed_ivlen ); + /* Explicit */ + memcpy( iv + transform->fixed_ivlen, data, 8 ); + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if( transform->ivlen == 12 && transform->fixed_ivlen == 12 ) + { + /* ChachaPoly: fixed XOR sequence number */ + unsigned char i; + + memcpy( iv, transform->iv_dec, transform->fixed_ivlen ); + + for( i = 0; i < 8; i++ ) + iv[i+4] ^= rec->ctr[i]; + } + else +#endif /* MBEDTLS_CHACHAPOLY_C */ + { + /* Reminder if we ever add an AEAD mode with a different size */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Group changes to data, data_len, and add_data, because + * add_data depends on data_len. */ + data += explicit_iv_len; + rec->data_offset += explicit_iv_len; + rec->data_len -= explicit_iv_len + transform->taglen; + + ssl_extract_add_data_from_record( add_data, &add_data_len, rec ); + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, add_data_len ); + + /* Because of the check above, we know that there are + * explicit_iv_len Bytes preceeding data, and taglen + * bytes following data + data_len. This justifies + * the debug message and the invocation of + * mbedtls_cipher_auth_decrypt() below. */ + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", data + rec->data_len, + transform->taglen ); + + /* + * Decrypt and authenticate + */ + if( ( ret = mbedtls_cipher_auth_decrypt( &transform->cipher_ctx_dec, + iv, transform->ivlen, + add_data, add_data_len, + data, rec->data_len, + data, &olen, + data + rec->data_len, + transform->taglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt", ret ); + + if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + + return( ret ); + } + auth_done++; + + /* Double-check that AEAD decryption doesn't change content length. */ + if( olen != rec->data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) ) + if( mode == MBEDTLS_MODE_CBC ) + { + size_t minlen = 0; + + /* + * Check immediate ciphertext sanity + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* The ciphertext is prefixed with the CBC IV. */ + minlen += transform->ivlen; + } +#endif + + /* Size considerations: + * + * - The CBC cipher text must not be empty and hence + * at least of size transform->ivlen. + * + * Together with the potential IV-prefix, this explains + * the first of the two checks below. + * + * - The record must contain a MAC, either in plain or + * encrypted, depending on whether Encrypt-then-MAC + * is used or not. + * - If it is, the message contains the IV-prefix, + * the CBC ciphertext, and the MAC. + * - If it is not, the padded plaintext, and hence + * the CBC ciphertext, has at least length maclen + 1 + * because there is at least the padding length byte. + * + * As the CBC ciphertext is not empty, both cases give the + * lower bound minlen + maclen + 1 on the record size, which + * we test for in the second check below. + */ + if( rec->data_len < minlen + transform->ivlen || + rec->data_len < minlen + transform->maclen + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) " + "+ 1 ) ( + expl IV )", rec->data_len, + transform->ivlen, + transform->maclen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + + /* + * Authenticate before decrypt if enabled + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( transform->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + { + unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + + /* Update data_len in tandem with add_data. + * + * The subtraction is safe because of the previous check + * data_len >= minlen + maclen + 1. + * + * Afterwards, we know that data + data_len is followed by at + * least maclen Bytes, which justifies the call to + * mbedtls_ssl_safer_memcmp() below. + * + * Further, we still know that data_len > minlen */ + rec->data_len -= transform->maclen; + ssl_extract_add_data_from_record( add_data, &add_data_len, rec ); + + /* Calculate expected MAC. */ + MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data, + add_data_len ); + mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data, + add_data_len ); + mbedtls_md_hmac_update( &transform->md_ctx_dec, + data, rec->data_len ); + mbedtls_md_hmac_finish( &transform->md_ctx_dec, mac_expect ); + mbedtls_md_hmac_reset( &transform->md_ctx_dec ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", data + rec->data_len, + transform->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, + transform->maclen ); + + /* Compare expected MAC with MAC at the end of the record. */ + if( mbedtls_ssl_safer_memcmp( data + rec->data_len, mac_expect, + transform->maclen ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + auth_done++; + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + + /* + * Check length sanity + */ + + /* We know from above that data_len > minlen >= 0, + * so the following check in particular implies that + * data_len >= minlen + ivlen ( = minlen or 2 * minlen ). */ + if( rec->data_len % transform->ivlen != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0", + rec->data_len, transform->ivlen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Initialize for prepended IV for block cipher in TLS v1.1 and up + */ + if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */ + memcpy( transform->iv_dec, data, transform->ivlen ); + + data += transform->ivlen; + rec->data_offset += transform->ivlen; + rec->data_len -= transform->ivlen; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* We still have data_len % ivlen == 0 and data_len >= ivlen here. */ + + if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec, + transform->iv_dec, transform->ivlen, + data, rec->data_len, data, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + /* Double-check that length hasn't changed during decryption. */ + if( rec->data_len != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1, where CBC decryption of consecutive + * records is equivalent to CBC decryption of the concatenation + * of the records; in other words, IVs are maintained across + * record decryptions. + */ + memcpy( transform->iv_dec, transform->cipher_ctx_dec.iv, + transform->ivlen ); + } +#endif + + /* Safe since data_len >= minlen + maclen + 1, so after having + * subtracted at most minlen and maclen up to this point, + * data_len > 0 (because of data_len % ivlen == 0, it's actually + * >= ivlen ). */ + padlen = data[rec->data_len - 1]; + + if( auth_done == 1 ) + { + correct *= ( rec->data_len >= padlen + 1 ); + padlen *= ( rec->data_len >= padlen + 1 ); + } + else + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( rec->data_len < transform->maclen + padlen + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)", + rec->data_len, + transform->maclen, + padlen + 1 ) ); + } +#endif + + correct *= ( rec->data_len >= transform->maclen + padlen + 1 ); + padlen *= ( rec->data_len >= transform->maclen + padlen + 1 ); + } + + padlen++; + + /* Regardless of the validity of the padding, + * we have data_len >= padlen here. */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( padlen > transform->ivlen ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, " + "should be no more than %d", + padlen, transform->ivlen ) ); +#endif + correct = 0; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* The padding check involves a series of up to 256 + * consecutive memory reads at the end of the record + * plaintext buffer. In order to hide the length and + * validity of the padding, always perform exactly + * `min(256,plaintext_len)` reads (but take into account + * only the last `padlen` bytes for the padding check). */ + size_t pad_count = 0; + size_t real_count = 0; + volatile unsigned char* const check = data; + + /* Index of first padding byte; it has been ensured above + * that the subtraction is safe. */ + size_t const padding_idx = rec->data_len - padlen; + size_t const num_checks = rec->data_len <= 256 ? rec->data_len : 256; + size_t const start_idx = rec->data_len - num_checks; + size_t idx; + + for( idx = start_idx; idx < rec->data_len; idx++ ) + { + real_count |= ( idx >= padding_idx ); + pad_count += real_count * ( check[idx] == padlen - 1 ); + } + correct &= ( pad_count == padlen ); + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( padlen > 0 && correct == 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) ); +#endif + padlen &= correct * 0x1FF; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* If the padding was found to be invalid, padlen == 0 + * and the subtraction is safe. If the padding was found valid, + * padlen hasn't been changed and the previous assertion + * data_len >= padlen still holds. */ + rec->data_len -= padlen; + } + else +#endif /* MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", + data, rec->data_len ); +#endif + + /* + * Authenticate if not done yet. + * Compute the MAC regardless of the padding result (RFC4346, CBCTIME). + */ +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + if( auth_done == 0 ) + { + unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; + + /* If the initial value of padlen was such that + * data_len < maclen + padlen + 1, then padlen + * got reset to 1, and the initial check + * data_len >= minlen + maclen + 1 + * guarantees that at this point we still + * have at least data_len >= maclen. + * + * If the initial value of padlen was such that + * data_len >= maclen + padlen + 1, then we have + * subtracted either padlen + 1 (if the padding was correct) + * or 0 (if the padding was incorrect) since then, + * hence data_len >= maclen in any case. + */ + rec->data_len -= transform->maclen; + ssl_extract_add_data_from_record( add_data, &add_data_len, rec ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl_mac( &transform->md_ctx_dec, + transform->mac_dec, + data, rec->data_len, + rec->ctr, rec->type, + mac_expect ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* + * Process MAC and always update for padlen afterwards to make + * total time independent of padlen. + * + * Known timing attacks: + * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf) + * + * To compensate for different timings for the MAC calculation + * depending on how much padding was removed (which is determined + * by padlen), process extra_run more blocks through the hash + * function. + * + * The formula in the paper is + * extra_run = ceil( (L1-55) / 64 ) - ceil( (L2-55) / 64 ) + * where L1 is the size of the header plus the decrypted message + * plus CBC padding and L2 is the size of the header plus the + * decrypted message. This is for an underlying hash function + * with 64-byte blocks. + * We use ( (Lx+8) / 64 ) to handle 'negative Lx' values + * correctly. We round down instead of up, so -56 is the correct + * value for our calculations instead of -55. + * + * Repeat the formula rather than defining a block_size variable. + * This avoids requiring division by a variable at runtime + * (which would be marginally less efficient and would require + * linking an extra division function in some builds). + */ + size_t j, extra_run = 0; + unsigned char tmp[MBEDTLS_MD_MAX_BLOCK_SIZE]; + + /* + * The next two sizes are the minimum and maximum values of + * in_msglen over all padlen values. + * + * They're independent of padlen, since we previously did + * data_len -= padlen. + * + * Note that max_len + maclen is never more than the buffer + * length, as we previously did in_msglen -= maclen too. + */ + const size_t max_len = rec->data_len + padlen; + const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0; + + memset( tmp, 0, sizeof( tmp ) ); + + switch( mbedtls_md_get_type( transform->md_ctx_dec.md_info ) ) + { +#if defined(MBEDTLS_MD5_C) || defined(MBEDTLS_SHA1_C) || \ + defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_MD5: + case MBEDTLS_MD_SHA1: + case MBEDTLS_MD_SHA256: + /* 8 bytes of message size, 64-byte compression blocks */ + extra_run = + ( add_data_len + rec->data_len + padlen + 8 ) / 64 - + ( add_data_len + rec->data_len + 8 ) / 64; + break; +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + /* 16 bytes of message size, 128-byte compression blocks */ + extra_run = + ( add_data_len + rec->data_len + padlen + 16 ) / 128 - + ( add_data_len + rec->data_len + 16 ) / 128; + break; +#endif + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + extra_run &= correct * 0xFF; + + mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data, + add_data_len ); + mbedtls_md_hmac_update( &transform->md_ctx_dec, data, + rec->data_len ); + /* Make sure we access everything even when padlen > 0. This + * makes the synchronisation requirements for just-in-time + * Prime+Probe attacks much tighter and hopefully impractical. */ + ssl_read_memory( data + rec->data_len, padlen ); + mbedtls_md_hmac_finish( &transform->md_ctx_dec, mac_expect ); + + /* Call mbedtls_md_process at least once due to cache attacks + * that observe whether md_process() was called of not */ + for( j = 0; j < extra_run + 1; j++ ) + mbedtls_md_process( &transform->md_ctx_dec, tmp ); + + mbedtls_md_hmac_reset( &transform->md_ctx_dec ); + + /* Make sure we access all the memory that could contain the MAC, + * before we check it in the next code block. This makes the + * synchronisation requirements for just-in-time Prime+Probe + * attacks much tighter and hopefully impractical. */ + ssl_read_memory( data + min_len, + max_len - min_len + transform->maclen ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, transform->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", data + rec->data_len, transform->maclen ); +#endif + + if( mbedtls_ssl_safer_memcmp( data + rec->data_len, mac_expect, + transform->maclen ) != 0 ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); +#endif + correct = 0; + } + auth_done++; + } + + /* + * Finally check the correct flag + */ + if( correct == 0 ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( rec->cid_len != 0 ) + { + ret = ssl_cid_parse_inner_plaintext( data, &rec->data_len, + &rec->type ); + if( ret != 0 ) + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) ); + + return( 0 ); +} + +#undef MAC_NONE +#undef MAC_PLAINTEXT +#undef MAC_CIPHERTEXT + +#if defined(MBEDTLS_ZLIB_SUPPORT) +/* + * Compression/decompression functions + */ +static int ssl_compress_buf( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *msg_post = ssl->out_msg; + ptrdiff_t bytes_written = ssl->out_msg - ssl->out_buf; + size_t len_pre = ssl->out_msglen; + unsigned char *msg_pre = ssl->compress_buf; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len; +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> compress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->out_msg, len_pre ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ", + ssl->out_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + ssl->transform_out->ctx_deflate.next_in = msg_pre; + ssl->transform_out->ctx_deflate.avail_in = len_pre; + ssl->transform_out->ctx_deflate.next_out = msg_post; + ssl->transform_out->ctx_deflate.avail_out = out_buf_len - bytes_written; + + ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->out_msglen = out_buf_len - + ssl->transform_out->ctx_deflate.avail_out - bytes_written; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ", + ssl->out_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= compress buf" ) ); + + return( 0 ); +} + +static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *msg_post = ssl->in_msg; + ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf; + size_t len_pre = ssl->in_msglen; + unsigned char *msg_pre = ssl->compress_buf; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->in_msg, len_pre ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ", + ssl->in_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + ssl->transform_in->ctx_inflate.next_in = msg_pre; + ssl->transform_in->ctx_inflate.avail_in = len_pre; + ssl->transform_in->ctx_inflate.next_out = msg_post; + ssl->transform_in->ctx_inflate.avail_out = in_buf_len - header_bytes; + + ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->in_msglen = in_buf_len - + ssl->transform_in->ctx_inflate.avail_out - header_bytes; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ", + ssl->in_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_ZLIB_SUPPORT */ + +/* + * Fill the input message buffer by appending data to it. + * The amount of data already fetched is in ssl->in_left. + * + * If we return 0, is it guaranteed that (at least) nb_want bytes are + * available (from this read and/or a previous one). Otherwise, an error code + * is returned (possibly EOF or WANT_READ). + * + * With stream transport (TLS) on success ssl->in_left == nb_want, but + * with datagram transport (DTLS) on success ssl->in_left >= nb_want, + * since we always read a whole datagram at once. + * + * For DTLS, it is up to the caller to set ssl->next_record_offset when + * they're done reading a record. + */ +int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) ); + + if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " + "or mbedtls_ssl_set_bio()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( nb_want > in_buf_len - (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + uint32_t timeout; + + /* Just to be sure */ + if( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use " + "mbedtls_ssl_set_timer_cb() for DTLS" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * The point is, we need to always read a full datagram at once, so we + * sometimes read more then requested, and handle the additional data. + * It could be the rest of the current record (while fetching the + * header) and/or some other records in the same datagram. + */ + + /* + * Move to the next record in the already read datagram if applicable + */ + if( ssl->next_record_offset != 0 ) + { + if( ssl->in_left < ssl->next_record_offset ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_left -= ssl->next_record_offset; + + if( ssl->in_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %d", + ssl->next_record_offset ) ); + memmove( ssl->in_hdr, + ssl->in_hdr + ssl->next_record_offset, + ssl->in_left ); + } + + ssl->next_record_offset = 0; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + + /* + * Done if we already have enough data. + */ + if( nb_want <= ssl->in_left) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + return( 0 ); + } + + /* + * A record can't be split across datagrams. If we need to read but + * are not at the beginning of a new record, the caller did something + * wrong. + */ + if( ssl->in_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Don't even try to read if time's out already. + * This avoids by-passing the timer when repeatedly receiving messages + * that will end up being dropped. + */ + if( mbedtls_ssl_check_timer( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) ); + ret = MBEDTLS_ERR_SSL_TIMEOUT; + } + else + { + len = in_buf_len - ( ssl->in_hdr - ssl->in_buf ); + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + timeout = ssl->handshake->retransmit_timeout; + else + timeout = ssl->conf->read_timeout; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %u ms", timeout ) ); + + if( ssl->f_recv_timeout != NULL ) + ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len, + timeout ); + else + ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); + + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_CONN_EOF ); + } + + if( ret == MBEDTLS_ERR_SSL_TIMEOUT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) ); + mbedtls_ssl_set_timer( ssl, 0 ); + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ssl_double_retransmit_timeout( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) ); + return( MBEDTLS_ERR_SSL_TIMEOUT ); + } + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request", + ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ + } + + if( ret < 0 ) + return( ret ); + + ssl->in_left = ret; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + + while( ssl->in_left < nb_want ) + { + len = nb_want - ssl->in_left; + + if( mbedtls_ssl_check_timer( ssl ) != 0 ) + ret = MBEDTLS_ERR_SSL_TIMEOUT; + else + { + if( ssl->f_recv_timeout != NULL ) + { + ret = ssl->f_recv_timeout( ssl->p_bio, + ssl->in_hdr + ssl->in_left, len, + ssl->conf->read_timeout ); + } + else + { + ret = ssl->f_recv( ssl->p_bio, + ssl->in_hdr + ssl->in_left, len ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", + ssl->in_left, nb_want ) ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); + + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_CONN_EOF ); + + if( ret < 0 ) + return( ret ); + + if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > SIZE_MAX ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "f_recv returned %d bytes but only %lu were requested", + ret, (unsigned long)len ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_left += ret; + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + + return( 0 ); +} + +/* + * Flush any data not yet written + */ +int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); + + if( ssl->f_send == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " + "or mbedtls_ssl_set_bio()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* Avoid incrementing counter if data is flushed */ + if( ssl->out_left == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + return( 0 ); + } + + while( ssl->out_left > 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d", + mbedtls_ssl_out_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) ); + + buf = ssl->out_hdr - ssl->out_left; + ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret ); + + if( ret <= 0 ) + return( ret ); + + if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > SIZE_MAX ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "f_send returned %d bytes but only %lu bytes were sent", + ret, (unsigned long)ssl->out_left ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_left -= ret; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + } + else +#endif + { + ssl->out_hdr = ssl->out_buf + 8; + } + mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + + return( 0 ); +} + +/* + * Functions to handle the DTLS retransmission state machine + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * Append current handshake message to current outgoing flight + */ +static int ssl_flight_append( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_flight_item *msg; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight", + ssl->out_msg, ssl->out_msglen ); + + /* Allocate space for current message */ + if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", + sizeof( mbedtls_ssl_flight_item ) ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", ssl->out_msglen ) ); + mbedtls_free( msg ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Copy current handshake message with headers */ + memcpy( msg->p, ssl->out_msg, ssl->out_msglen ); + msg->len = ssl->out_msglen; + msg->type = ssl->out_msgtype; + msg->next = NULL; + + /* Append to the current flight */ + if( ssl->handshake->flight == NULL ) + ssl->handshake->flight = msg; + else + { + mbedtls_ssl_flight_item *cur = ssl->handshake->flight; + while( cur->next != NULL ) + cur = cur->next; + cur->next = msg; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) ); + return( 0 ); +} + +/* + * Free the current flight of handshake messages + */ +void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight ) +{ + mbedtls_ssl_flight_item *cur = flight; + mbedtls_ssl_flight_item *next; + + while( cur != NULL ) + { + next = cur->next; + + mbedtls_free( cur->p ); + mbedtls_free( cur ); + + cur = next; + } +} + +/* + * Swap transform_out and out_ctr with the alternative ones + */ +static int ssl_swap_epochs( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_transform *tmp_transform; + unsigned char tmp_out_ctr[8]; + + if( ssl->transform_out == ssl->handshake->alt_transform_out ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) ); + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) ); + + /* Swap transforms */ + tmp_transform = ssl->transform_out; + ssl->transform_out = ssl->handshake->alt_transform_out; + ssl->handshake->alt_transform_out = tmp_transform; + + /* Swap epoch + sequence_number */ + memcpy( tmp_out_ctr, ssl->cur_out_ctr, 8 ); + memcpy( ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, 8 ); + memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 ); + + /* Adjust to the newly activated transform */ + mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + int ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + return( 0 ); +} + +/* + * Retransmit the current flight of messages. + */ +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); + + ret = mbedtls_ssl_flight_transmit( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) ); + + return( ret ); +} + +/* + * Transmit or retransmit the current flight of messages. + * + * Need to remember the current message in case flush_output returns + * WANT_WRITE, causing us to exit this function and come back later. + * This function must be called until state is no longer SENDING. + */ +int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) ); + + if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) ); + + ssl->handshake->cur_msg = ssl->handshake->flight; + ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12; + ret = ssl_swap_epochs( ssl ); + if( ret != 0 ) + return( ret ); + + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; + } + + while( ssl->handshake->cur_msg != NULL ) + { + size_t max_frag_len; + const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg; + + int const is_finished = + ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && + cur->p[0] == MBEDTLS_SSL_HS_FINISHED ); + + uint8_t const force_flush = ssl->disable_datagram_packing == 1 ? + SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH; + + /* Swap epochs before sending Finished: we can't do it after + * sending ChangeCipherSpec, in case write returns WANT_READ. + * Must be done before copying, may change out_msg pointer */ + if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) ); + ret = ssl_swap_epochs( ssl ); + if( ret != 0 ) + return( ret ); + } + + ret = ssl_get_remaining_payload_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + max_frag_len = (size_t) ret; + + /* CCS is copied as is, while HS messages may need fragmentation */ + if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + if( max_frag_len == 0 ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + continue; + } + + memcpy( ssl->out_msg, cur->p, cur->len ); + ssl->out_msglen = cur->len; + ssl->out_msgtype = cur->type; + + /* Update position inside current message */ + ssl->handshake->cur_msg_p += cur->len; + } + else + { + const unsigned char * const p = ssl->handshake->cur_msg_p; + const size_t hs_len = cur->len - 12; + const size_t frag_off = p - ( cur->p + 12 ); + const size_t rem_len = hs_len - frag_off; + size_t cur_hs_frag_len, max_hs_frag_len; + + if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) ) + { + if( is_finished ) + { + ret = ssl_swap_epochs( ssl ); + if( ret != 0 ) + return( ret ); + } + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + continue; + } + max_hs_frag_len = max_frag_len - 12; + + cur_hs_frag_len = rem_len > max_hs_frag_len ? + max_hs_frag_len : rem_len; + + if( frag_off == 0 && cur_hs_frag_len != hs_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)", + (unsigned) cur_hs_frag_len, + (unsigned) max_hs_frag_len ) ); + } + + /* Messages are stored with handshake headers as if not fragmented, + * copy beginning of headers then fill fragmentation fields. + * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */ + memcpy( ssl->out_msg, cur->p, 6 ); + + ssl->out_msg[6] = ( ( frag_off >> 16 ) & 0xff ); + ssl->out_msg[7] = ( ( frag_off >> 8 ) & 0xff ); + ssl->out_msg[8] = ( ( frag_off ) & 0xff ); + + ssl->out_msg[ 9] = ( ( cur_hs_frag_len >> 16 ) & 0xff ); + ssl->out_msg[10] = ( ( cur_hs_frag_len >> 8 ) & 0xff ); + ssl->out_msg[11] = ( ( cur_hs_frag_len ) & 0xff ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 ); + + /* Copy the handshake message content and set records fields */ + memcpy( ssl->out_msg + 12, p, cur_hs_frag_len ); + ssl->out_msglen = cur_hs_frag_len + 12; + ssl->out_msgtype = cur->type; + + /* Update position inside current message */ + ssl->handshake->cur_msg_p += cur_hs_frag_len; + } + + /* If done with the current message move to the next one if any */ + if( ssl->handshake->cur_msg_p >= cur->p + cur->len ) + { + if( cur->next != NULL ) + { + ssl->handshake->cur_msg = cur->next; + ssl->handshake->cur_msg_p = cur->next->p + 12; + } + else + { + ssl->handshake->cur_msg = NULL; + ssl->handshake->cur_msg_p = NULL; + } + } + + /* Actually send the message out */ + if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + } + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + /* Update state and set timer */ + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + else + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; + mbedtls_ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) ); + + return( 0 ); +} + +/* + * To be called when the last message of an incoming flight is received. + */ +void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ) +{ + /* We won't need to resend that one any more */ + mbedtls_ssl_flight_free( ssl->handshake->flight ); + ssl->handshake->flight = NULL; + ssl->handshake->cur_msg = NULL; + + /* The next incoming flight will start with this msg_seq */ + ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq; + + /* We don't want to remember CCS's across flight boundaries. */ + ssl->handshake->buffering.seen_ccs = 0; + + /* Clear future message buffering structure. */ + mbedtls_ssl_buffering_free( ssl ); + + /* Cancel timer */ + mbedtls_ssl_set_timer( ssl, 0 ); + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + } + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; +} + +/* + * To be called when the last message of an outgoing flight is send. + */ +void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ) +{ + ssl_reset_retransmit_timeout( ssl ); + mbedtls_ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + } + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +/* + * Handshake layer functions + */ + +/* + * Write (DTLS: or queue) current handshake (including CCS) message. + * + * - fill in handshake headers + * - update handshake checksum + * - DTLS: save message for resending + * - then pass to the record layer + * + * DTLS: except for HelloRequest, messages are only queued, and will only be + * actually sent when calling flight_transmit() or resend(). + * + * Inputs: + * - ssl->out_msglen: 4 + actual handshake message len + * (4 is the size of handshake headers for TLS) + * - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc) + * - ssl->out_msg + 4: the handshake message body + * + * Outputs, ie state before passing to flight_append() or write_record(): + * - ssl->out_msglen: the length of the record contents + * (including handshake headers but excluding record headers) + * - ssl->out_msg: the record contents (handshake headers + content) + */ +int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const size_t hs_len = ssl->out_msglen - 4; + const unsigned char hs_type = ssl->out_msg[0]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) ); + + /* + * Sanity checks + */ + if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + /* In SSLv3, the client might send a NoCertificate alert. */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) + if( ! ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->out_msgtype == MBEDTLS_SSL_MSG_ALERT && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) ) +#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + + /* Whenever we send anything different from a + * HelloRequest we should be in a handshake - double check. */ + if( ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) && + ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } +#endif + + /* Double-check that we did not exceed the bounds + * of the outgoing record buffer. + * This should never fail as the various message + * writing functions must obey the bounds of the + * outgoing record buffer, but better be safe. + * + * Note: We deliberately do not check for the MTU or MFL here. + */ + if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: " + "size %u, maximum %u", + (unsigned) ssl->out_msglen, + (unsigned) MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Fill handshake headers + */ + if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + ssl->out_msg[1] = (unsigned char)( hs_len >> 16 ); + ssl->out_msg[2] = (unsigned char)( hs_len >> 8 ); + ssl->out_msg[3] = (unsigned char)( hs_len ); + + /* + * DTLS has additional fields in the Handshake layer, + * between the length field and the actual payload: + * uint16 message_seq; + * uint24 fragment_offset; + * uint24 fragment_length; + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Make room for the additional DTLS fields */ + if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: " + "size %u, maximum %u", + (unsigned) ( hs_len ), + (unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len ); + ssl->out_msglen += 8; + + /* Write message_seq and update it, except for HelloRequest */ + if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + { + ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF; + ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF; + ++( ssl->handshake->out_msg_seq ); + } + else + { + ssl->out_msg[4] = 0; + ssl->out_msg[5] = 0; + } + + /* Handshake hashes are computed without fragmentation, + * so set frag_offset = 0 and frag_len = hs_len for now */ + memset( ssl->out_msg + 6, 0x00, 3 ); + memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Update running hashes of handshake messages seen */ + if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen ); + } + + /* Either send now, or just save to be sent (and resent) later */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) ) + { + if( ( ret = ssl_flight_append( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret ); + return( ret ); + } + } + else +#endif + { + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) ); + + return( 0 ); +} + +/* + * Record layer functions + */ + +/* + * Write current record. + * + * Uses: + * - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS) + * - ssl->out_msglen: length of the record content (excl headers) + * - ssl->out_msg: record content + */ +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ) +{ + int ret, done = 0; + size_t len = ssl->out_msglen; + uint8_t flush = force_flush; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->transform_out != NULL && + ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_compress_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + } +#endif /*MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_write != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) ); + + ret = mbedtls_ssl_hw_record_write( ssl ); + if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + if( !done ) + { + unsigned i; + size_t protected_record_size; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len; +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + /* Skip writing the record content type to after the encryption, + * as it may change when using the CID extension. */ + + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, ssl->out_hdr + 1 ); + + memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 ); + ssl->out_len[0] = (unsigned char)( len >> 8 ); + ssl->out_len[1] = (unsigned char)( len ); + + if( ssl->transform_out != NULL ) + { + mbedtls_record rec; + + rec.buf = ssl->out_iv; + rec.buf_len = out_buf_len - ( ssl->out_iv - ssl->out_buf ); + rec.data_len = ssl->out_msglen; + rec.data_offset = ssl->out_msg - rec.buf; + + memcpy( &rec.ctr[0], ssl->out_ctr, 8 ); + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, rec.ver ); + rec.type = ssl->out_msgtype; + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* The CID is set by mbedtls_ssl_encrypt_buf(). */ + rec.cid_len = 0; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + if( ( ret = mbedtls_ssl_encrypt_buf( ssl, ssl->transform_out, &rec, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret ); + return( ret ); + } + + if( rec.data_offset != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Update the record content type and CID. */ + ssl->out_msgtype = rec.type; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID ) + memcpy( ssl->out_cid, rec.cid, rec.cid_len ); +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->out_msglen = len = rec.data_len; + ssl->out_len[0] = (unsigned char)( rec.data_len >> 8 ); + ssl->out_len[1] = (unsigned char)( rec.data_len ); + } + + protected_record_size = len + mbedtls_ssl_out_hdr_len( ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* In case of DTLS, double-check that we don't exceed + * the remaining space in the datagram. */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ret = ssl_get_remaining_space_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + + if( protected_record_size > (size_t) ret ) + { + /* Should never happen */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Now write the potentially updated record content type. */ + ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " + "version = [%d:%d], msglen = %d", + ssl->out_hdr[0], ssl->out_hdr[1], + ssl->out_hdr[2], len ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_hdr, protected_record_size ); + + ssl->out_left += protected_record_size; + ssl->out_hdr += protected_record_size; + mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out ); + + for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- ) + if( ++ssl->cur_out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == mbedtls_ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + flush == SSL_DONT_FORCE_FLUSH ) + { + size_t remaining; + ret = ssl_get_remaining_payload_in_datagram( ssl ); + if( ret < 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram", + ret ); + return( ret ); + } + + remaining = (size_t) ret; + if( remaining == 0 ) + { + flush = SSL_FORCE_FLUSH; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( ( flush == SSL_FORCE_FLUSH ) && + ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen < ssl->in_hslen || + memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || + memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 ) + { + return( 1 ); + } + return( 0 ); +} + +static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[9] << 16 ) | + ( ssl->in_msg[10] << 8 ) | + ssl->in_msg[11] ); +} + +static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[6] << 16 ) | + ( ssl->in_msg[7] << 8 ) | + ssl->in_msg[8] ); +} + +static int ssl_check_hs_header( mbedtls_ssl_context const *ssl ) +{ + uint32_t msg_len, frag_off, frag_len; + + msg_len = ssl_get_hs_total_len( ssl ); + frag_off = ssl_get_hs_frag_off( ssl ); + frag_len = ssl_get_hs_frag_len( ssl ); + + if( frag_off > msg_len ) + return( -1 ); + + if( frag_len > msg_len - frag_off ) + return( -1 ); + + if( frag_len + 12 > ssl->in_msglen ) + return( -1 ); + + return( 0 ); +} + +/* + * Mark bits in bitmask (used for DTLS HS reassembly) + */ +static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len ) +{ + unsigned int start_bits, end_bits; + + start_bits = 8 - ( offset % 8 ); + if( start_bits != 8 ) + { + size_t first_byte_idx = offset / 8; + + /* Special case */ + if( len <= start_bits ) + { + for( ; len != 0; len-- ) + mask[first_byte_idx] |= 1 << ( start_bits - len ); + + /* Avoid potential issues with offset or len becoming invalid */ + return; + } + + offset += start_bits; /* Now offset % 8 == 0 */ + len -= start_bits; + + for( ; start_bits != 0; start_bits-- ) + mask[first_byte_idx] |= 1 << ( start_bits - 1 ); + } + + end_bits = len % 8; + if( end_bits != 0 ) + { + size_t last_byte_idx = ( offset + len ) / 8; + + len -= end_bits; /* Now len % 8 == 0 */ + + for( ; end_bits != 0; end_bits-- ) + mask[last_byte_idx] |= 1 << ( 8 - end_bits ); + } + + memset( mask + offset / 8, 0xFF, len / 8 ); +} + +/* + * Check that bitmask is full + */ +static int ssl_bitmask_check( unsigned char *mask, size_t len ) +{ + size_t i; + + for( i = 0; i < len / 8; i++ ) + if( mask[i] != 0xFF ) + return( -1 ); + + for( i = 0; i < len % 8; i++ ) + if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 ) + return( -1 ); + + return( 0 ); +} + +/* msg_len does not include the handshake header */ +static size_t ssl_get_reassembly_buffer_size( size_t msg_len, + unsigned add_bitmap ) +{ + size_t alloc_len; + + alloc_len = 12; /* Handshake header */ + alloc_len += msg_len; /* Content buffer */ + + if( add_bitmap ) + alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap */ + + return( alloc_len ); +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[1] << 16 ) | + ( ssl->in_msg[2] << 8 ) | + ssl->in_msg[3] ); +} + +int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" + " %d, type = %d, hslen = %d", + ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + + if( ssl_check_hs_header( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->handshake != NULL && + ( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && + recv_msg_seq != ssl->handshake->in_msg_seq ) || + ( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) ) + { + if( recv_msg_seq > ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)", + recv_msg_seq, + ssl->handshake->in_msg_seq ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + + /* Retransmit only on last message from previous flight, to avoid + * too many retransmissions. + * Besides, No sane server ever retransmits HelloVerifyRequest */ + if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 && + ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, " + "message_seq = %d, start_of_flight = %d", + recv_msg_seq, + ssl->handshake->in_flight_start_seq ) ); + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: " + "message_seq = %d, expected = %d", + recv_msg_seq, + ssl->handshake->in_msg_seq ) ); + } + + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + } + /* Wait until message completion to increment in_msg_seq */ + + /* Message reassembly is handled alongside buffering of future + * messages; the commonality is that both handshake fragments and + * future messages cannot be forwarded immediately to the + * handshake logic layer. */ + if( ssl_hs_is_proper_fragment( ssl ) == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + /* With TLS we don't handle fragmentation (for now) */ + if( ssl->in_msglen < ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} + +void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL ) + { + ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); + } + + /* Handshake message is complete, increment counter */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL ) + { + unsigned offset; + mbedtls_ssl_hs_buffer *hs_buf; + + /* Increment handshake sequence number */ + hs->in_msg_seq++; + + /* + * Clear up handshake buffering and reassembly structure. + */ + + /* Free first entry */ + ssl_buffering_free_slot( ssl, 0 ); + + /* Shift all other entries */ + for( offset = 0, hs_buf = &hs->buffering.hs[0]; + offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS; + offset++, hs_buf++ ) + { + *hs_buf = *(hs_buf + 1); + } + + /* Create a fresh last entry */ + memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); + } +#endif +} + +/* + * DTLS anti-replay: RFC 6347 4.1.2.6 + * + * in_window is a field of bits numbered from 0 (lsb) to 63 (msb). + * Bit n is set iff record number in_window_top - n has been seen. + * + * Usually, in_window_top is the last record number seen and the lsb of + * in_window is set. The only exception is the initial state (record number 0 + * not seen yet). + */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ) +{ + ssl->in_window_top = 0; + ssl->in_window = 0; +} + +static inline uint64_t ssl_load_six_bytes( unsigned char *buf ) +{ + return( ( (uint64_t) buf[0] << 40 ) | + ( (uint64_t) buf[1] << 32 ) | + ( (uint64_t) buf[2] << 24 ) | + ( (uint64_t) buf[3] << 16 ) | + ( (uint64_t) buf[4] << 8 ) | + ( (uint64_t) buf[5] ) ); +} + +static int mbedtls_ssl_dtls_record_replay_check( mbedtls_ssl_context *ssl, uint8_t *record_in_ctr ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *original_in_ctr; + + // save original in_ctr + original_in_ctr = ssl->in_ctr; + + // use counter from record + ssl->in_ctr = record_in_ctr; + + ret = mbedtls_ssl_dtls_replay_check( (mbedtls_ssl_context const *) ssl ); + + // restore the counter + ssl->in_ctr = original_in_ctr; + + return ret; +} + +/* + * Return 0 if sequence number is acceptable, -1 otherwise + */ +int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + uint64_t bit; + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return( 0 ); + + if( rec_seqnum > ssl->in_window_top ) + return( 0 ); + + bit = ssl->in_window_top - rec_seqnum; + + if( bit >= 64 ) + return( -1 ); + + if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 ) + return( -1 ); + + return( 0 ); +} + +/* + * Update replay window on new validated record + */ +void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return; + + if( rec_seqnum > ssl->in_window_top ) + { + /* Update window_top and the contents of the window */ + uint64_t shift = rec_seqnum - ssl->in_window_top; + + if( shift >= 64 ) + ssl->in_window = 1; + else + { + ssl->in_window <<= shift; + ssl->in_window |= 1; + } + + ssl->in_window_top = rec_seqnum; + } + else + { + /* Mark that number as seen in the current window */ + uint64_t bit = ssl->in_window_top - rec_seqnum; + + if( bit < 64 ) /* Always true, but be extra sure */ + ssl->in_window |= (uint64_t) 1 << bit; + } +} +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) +/* + * Without any SSL context, check if a datagram looks like a ClientHello with + * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message. + * Both input and output include full DTLS headers. + * + * - if cookie is valid, return 0 + * - if ClientHello looks superficially valid but cookie is not, + * fill obuf and set olen, then + * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED + * - otherwise return a specific error code + */ +static int ssl_check_dtls_clihlo_cookie( + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie, + const unsigned char *cli_id, size_t cli_id_len, + const unsigned char *in, size_t in_len, + unsigned char *obuf, size_t buf_len, size_t *olen ) +{ + size_t sid_len, cookie_len; + unsigned char *p; + + /* + * Structure of ClientHello with record and handshake headers, + * and expected values. We don't need to check a lot, more checks will be + * done when actually parsing the ClientHello - skipping those checks + * avoids code duplication and does not make cookie forging any easier. + * + * 0-0 ContentType type; copied, must be handshake + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied, must be 0 + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; (ignored) + * + * 13-13 HandshakeType msg_type; (ignored) + * 14-16 uint24 length; (ignored) + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied, must be 0 + * 22-24 uint24 fragment_length; (ignored) + * + * 25-26 ProtocolVersion client_version; (ignored) + * 27-58 Random random; (ignored) + * 59-xx SessionID session_id; 1 byte len + sid_len content + * 60+ opaque cookie<0..2^8-1>; 1 byte len + content + * ... + * + * Minimum length is 61 bytes. + */ + if( in_len < 61 || + in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || + in[3] != 0 || in[4] != 0 || + in[19] != 0 || in[20] != 0 || in[21] != 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + sid_len = in[59]; + if( sid_len > in_len - 61 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + cookie_len = in[60 + sid_len]; + if( cookie_len > in_len - 60 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len, + cli_id, cli_id_len ) == 0 ) + { + /* Valid cookie */ + return( 0 ); + } + + /* + * If we get here, we've got an invalid cookie, let's prepare HVR. + * + * 0-0 ContentType type; copied + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; olen - 13 + * + * 13-13 HandshakeType msg_type; hello_verify_request + * 14-16 uint24 length; olen - 25 + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied + * 22-24 uint24 fragment_length; olen - 25 + * + * 25-26 ProtocolVersion server_version; 0xfe 0xff + * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie + * + * Minimum length is 28. + */ + if( buf_len < 28 ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + /* Copy most fields and adapt others */ + memcpy( obuf, in, 25 ); + obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + obuf[25] = 0xfe; + obuf[26] = 0xff; + + /* Generate and write actual cookie */ + p = obuf + 28; + if( f_cookie_write( p_cookie, + &p, obuf + buf_len, cli_id, cli_id_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + *olen = p - obuf; + + /* Go back and fill length fields */ + obuf[27] = (unsigned char)( *olen - 28 ); + + obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 ); + obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >> 8 ); + obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 ) ); + + obuf[11] = (unsigned char)( ( *olen - 13 ) >> 8 ); + obuf[12] = (unsigned char)( ( *olen - 13 ) ); + + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +} + +/* + * Handle possible client reconnect with the same UDP quadruplet + * (RFC 6347 Section 4.2.8). + * + * Called by ssl_parse_record_header() in case we receive an epoch 0 record + * that looks like a ClientHello. + * + * - if the input looks like a ClientHello without cookies, + * send back HelloVerifyRequest, then return 0 + * - if the input looks like a ClientHello with a valid cookie, + * reset the session of the current context, and + * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * - if anything goes wrong, return a specific error code + * + * This function is called (through ssl_check_client_reconnect()) when an + * unexpected record is found in ssl_get_next_record(), which will discard the + * record if we return 0, and bubble up the return value otherwise (this + * includes the case of MBEDTLS_ERR_SSL_CLIENT_RECONNECT and of unexpected + * errors, and is the right thing to do in both cases). + */ +static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ssl->conf->f_cookie_write == NULL || + ssl->conf->f_cookie_check == NULL ) + { + /* If we can't use cookies to verify reachability of the peer, + * drop the record. */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no cookie callbacks, " + "can't check reconnect validity" ) ); + return( 0 ); + } + + ret = ssl_check_dtls_clihlo_cookie( + ssl->conf->f_cookie_write, + ssl->conf->f_cookie_check, + ssl->conf->p_cookie, + ssl->cli_id, ssl->cli_id_len, + ssl->in_buf, ssl->in_left, + ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); + + if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) + { + int send_ret; + MBEDTLS_SSL_DEBUG_MSG( 1, ( "sending HelloVerifyRequest" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_buf, len ); + /* Don't check write errors as we can't do anything here. + * If the error is permanent we'll catch it later, + * if it's not, then hopefully it'll work next time. */ + send_ret = ssl->f_send( ssl->p_bio, ssl->out_buf, len ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", send_ret ); + (void) send_ret; + + return( 0 ); + } + + if( ret == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cookie is valid, resetting context" ) ); + if( ( ret = mbedtls_ssl_session_reset_int( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + +static int ssl_check_record_type( uint8_t record_type ) +{ + if( record_type != MBEDTLS_SSL_MSG_HANDSHAKE && + record_type != MBEDTLS_SSL_MSG_ALERT && + record_type != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && + record_type != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + return( 0 ); +} + +/* + * ContentType type; + * ProtocolVersion version; + * uint16 epoch; // DTLS only + * uint48 sequence_number; // DTLS only + * uint16 length; + * + * Return 0 if header looks sane (and, for DTLS, the record is expected) + * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad, + * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected. + * + * With DTLS, mbedtls_ssl_read_record() will: + * 1. proceed with the record if this function returns 0 + * 2. drop only the current record if this function returns UNEXPECTED_RECORD + * 3. return CLIENT_RECONNECT if this function return that value + * 4. drop the whole datagram if this function returns anything else. + * Point 2 is needed when the peer is resending, and we have already received + * the first record from a datagram but are still waiting for the others. + */ +static int ssl_parse_record_header( mbedtls_ssl_context const *ssl, + unsigned char *buf, + size_t len, + mbedtls_record *rec ) +{ + int major_ver, minor_ver; + + size_t const rec_hdr_type_offset = 0; + size_t const rec_hdr_type_len = 1; + + size_t const rec_hdr_version_offset = rec_hdr_type_offset + + rec_hdr_type_len; + size_t const rec_hdr_version_len = 2; + + size_t const rec_hdr_ctr_len = 8; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint32_t rec_epoch; + size_t const rec_hdr_ctr_offset = rec_hdr_version_offset + + rec_hdr_version_len; + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + size_t const rec_hdr_cid_offset = rec_hdr_ctr_offset + + rec_hdr_ctr_len; + size_t rec_hdr_cid_len = 0; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + size_t rec_hdr_len_offset; /* To be determined */ + size_t const rec_hdr_len_len = 2; + + /* + * Check minimum lengths for record header. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + rec_hdr_len_offset = rec_hdr_ctr_offset + rec_hdr_ctr_len; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + rec_hdr_len_offset = rec_hdr_version_offset + rec_hdr_version_len; + } + + if( len < rec_hdr_len_offset + rec_hdr_len_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header of length %u", + (unsigned) len, + (unsigned)( rec_hdr_len_len + rec_hdr_len_len ) ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* + * Parse and validate record content type + */ + + rec->type = buf[ rec_hdr_type_offset ]; + + /* Check record content type */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + rec->cid_len = 0; + + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->conf->cid_len != 0 && + rec->type == MBEDTLS_SSL_MSG_CID ) + { + /* Shift pointers to account for record header including CID + * struct { + * ContentType special_type = tls12_cid; + * ProtocolVersion version; + * uint16 epoch; + * uint48 sequence_number; + * opaque cid[cid_length]; // Additional field compared to + * // default DTLS record format + * uint16 length; + * opaque enc_content[DTLSCiphertext.length]; + * } DTLSCiphertext; + */ + + /* So far, we only support static CID lengths + * fixed in the configuration. */ + rec_hdr_cid_len = ssl->conf->cid_len; + rec_hdr_len_offset += rec_hdr_cid_len; + + if( len < rec_hdr_len_offset + rec_hdr_len_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header including CID, length %u", + (unsigned) len, + (unsigned)( rec_hdr_len_offset + rec_hdr_len_len ) ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* configured CID len is guaranteed at most 255, see + * MBEDTLS_SSL_CID_OUT_LEN_MAX in check_config.h */ + rec->cid_len = (uint8_t) rec_hdr_cid_len; + memcpy( rec->cid, buf + rec_hdr_cid_offset, rec_hdr_cid_len ); + } + else +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + { + if( ssl_check_record_type( rec->type ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type %u", + (unsigned) rec->type ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + + /* + * Parse and validate record version + */ + + rec->ver[0] = buf[ rec_hdr_version_offset + 0 ]; + rec->ver[1] = buf[ rec_hdr_version_offset + 1 ]; + mbedtls_ssl_read_version( &major_ver, &minor_ver, + ssl->conf->transport, + &rec->ver[0] ); + + if( major_ver != ssl->major_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* + * Parse/Copy record sequence number. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Copy explicit record sequence number from input buffer. */ + memcpy( &rec->ctr[0], buf + rec_hdr_ctr_offset, + rec_hdr_ctr_len ); + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + /* Copy implicit record sequence number from SSL context structure. */ + memcpy( &rec->ctr[0], ssl->in_ctr, rec_hdr_ctr_len ); + } + + /* + * Parse record length. + */ + + rec->data_offset = rec_hdr_len_offset + rec_hdr_len_len; + rec->data_len = ( (size_t) buf[ rec_hdr_len_offset + 0 ] << 8 ) | + ( (size_t) buf[ rec_hdr_len_offset + 1 ] << 0 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", buf, rec->data_offset ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, " + "version = [%d:%d], msglen = %d", + rec->type, + major_ver, minor_ver, rec->data_len ) ); + + rec->buf = buf; + rec->buf_len = rec->data_offset + rec->data_len; + + if( rec->data_len == 0 ) + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + + /* + * DTLS-related tests. + * Check epoch before checking length constraint because + * the latter varies with the epoch. E.g., if a ChangeCipherSpec + * message gets duplicated before the corresponding Finished message, + * the second ChangeCipherSpec should be discarded because it belongs + * to an old epoch, but not because its length is shorter than + * the minimum record length for packets using the new record transform. + * Note that these two kinds of failures are handled differently, + * as an unexpected record is silently skipped but an invalid + * record leads to the entire datagram being dropped. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + rec_epoch = ( rec->ctr[0] << 8 ) | rec->ctr[1]; + + /* Check that the datagram is large enough to contain a record + * of the advertised length. */ + if( len < rec->data_offset + rec->data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Datagram of length %u too small to contain record of advertised length %u.", + (unsigned) len, + (unsigned)( rec->data_offset + rec->data_len ) ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* Records from other, non-matching epochs are silently discarded. + * (The case of same-port Client reconnects must be considered in + * the caller). */ + if( rec_epoch != ssl->in_epoch ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: " + "expected %d, received %d", + ssl->in_epoch, rec_epoch ) ); + + /* Records from the next epoch are considered for buffering + * (concretely: early Finished messages). */ + if( rec_epoch == (unsigned) ssl->in_epoch + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + /* For records from the correct epoch, check whether their + * sequence number has been seen before. */ + else if( mbedtls_ssl_dtls_record_replay_check( (mbedtls_ssl_context *) ssl, + &rec->ctr[0] ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } +#endif + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + return( 0 ); +} + + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) +static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl ) +{ + unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1]; + + /* + * Check for an epoch 0 ClientHello. We can't use in_msg here to + * access the first byte of record content (handshake type), as we + * have an active transform (possibly iv_len != 0), so use the + * fact that the record header len is 13 instead. + */ + if( rec_epoch == 0 && + ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_left > 13 && + ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect " + "from the same port" ) ); + return( ssl_handle_possible_reconnect( ssl ) ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + +/* + * If applicable, decrypt record content + */ +static int ssl_prepare_record_content( mbedtls_ssl_context *ssl, + mbedtls_record *rec ) +{ + int ret, done = 0; + + MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network", + rec->buf, rec->buf_len ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_read != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_read()" ) ); + + ret = mbedtls_ssl_hw_record_read( ssl ); + if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_read", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + if( !done && ssl->transform_in != NULL ) + { + unsigned char const old_msg_type = rec->type; + + if( ( ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in, + rec ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID && + ssl->conf->ignore_unexpected_cid + == MBEDTLS_SSL_UNEXPECTED_CID_IGNORE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ignoring unexpected CID" ) ); + ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + return( ret ); + } + + if( old_msg_type != rec->type ) + { + MBEDTLS_SSL_DEBUG_MSG( 4, ( "record type after decrypt (before %d): %d", + old_msg_type, rec->type ) ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt", + rec->buf + rec->data_offset, rec->data_len ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* We have already checked the record content type + * in ssl_parse_record_header(), failing or silently + * dropping the record in the case of an unknown type. + * + * Since with the use of CIDs, the record content type + * might change during decryption, re-check the record + * content type, but treat a failure as fatal this time. */ + if( ssl_check_record_type( rec->type ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + if( rec->data_len == 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 + && rec->type != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* TLS v1.2 explicitly disallows zero-length messages which are not application data */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + ssl->nb_zero++; + + /* + * Three or more empty messages may be a DoS attack + * (excessive CPU consumption). + */ + if( ssl->nb_zero > 3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty " + "messages, possible DoS attack" ) ); + /* Treat the records as if they were not properly authenticated, + * thereby failing the connection if we see more than allowed + * by the configured bad MAC threshold. */ + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + } + else + ssl->nb_zero = 0; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ; /* in_ctr read from peer, not maintained internally */ + } + else +#endif + { + unsigned i; + for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- ) + if( ++ssl->in_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == mbedtls_ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + + } + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + mbedtls_ssl_dtls_replay_update( ssl ); + } +#endif + + /* Check actual (decrypted) record content length against + * configured maximum. */ + if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + return( 0 ); +} + +/* + * Read a record. + * + * Silently ignore non-fatal alert (and for DTLS, invalid records as well, + * RFC 6347 4.1.2.7) and continue reading until a valid record is found. + * + */ + +/* Helper functions for mbedtls_ssl_read_record(). */ +static int ssl_consume_current_message( mbedtls_ssl_context *ssl ); +static int ssl_get_next_record( mbedtls_ssl_context *ssl ); +static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, + unsigned update_hs_digest ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) ); + + if( ssl->keep_current_message == 0 ) + { + do { + + ret = ssl_consume_current_message( ssl ); + if( ret != 0 ) + return( ret ); + + if( ssl_record_is_in_progress( ssl ) == 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + int have_buffered = 0; + + /* We only check for buffered messages if the + * current datagram is fully consumed. */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl_next_record_is_in_datagram( ssl ) == 0 ) + { + if( ssl_load_buffered_message( ssl ) == 0 ) + have_buffered = 1; + } + + if( have_buffered == 0 ) +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + ret = ssl_get_next_record( ssl ); + if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ) + continue; + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret ); + return( ret ); + } + } + } + + ret = mbedtls_ssl_handle_message_type( ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + /* Buffer future message */ + ret = ssl_buffer_message( ssl ); + if( ret != 0 ) + return( ret ); + + ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + } while( MBEDTLS_ERR_SSL_NON_FATAL == ret || + MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret ); + + if( 0 != ret ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); + return( ret ); + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + update_hs_digest == 1 ) + { + mbedtls_ssl_update_handshake_status( ssl ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) ); + ssl->keep_current_message = 0; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_left > ssl->next_record_offset ) + return( 1 ); + + return( 0 ); +} + +static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + mbedtls_ssl_hs_buffer * hs_buf; + int ret = 0; + + if( hs == NULL ) + return( -1 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) ); + + if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC || + ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + /* Check if we have seen a ChangeCipherSpec before. + * If yes, synthesize a CCS record. */ + if( !hs->buffering.seen_ccs ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) ); + ret = -1; + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) ); + ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->in_msglen = 1; + ssl->in_msg[0] = 1; + + /* As long as they are equal, the exact value doesn't matter. */ + ssl->in_left = 0; + ssl->next_record_offset = 0; + + hs->buffering.seen_ccs = 0; + goto exit; + } + +#if defined(MBEDTLS_DEBUG_C) + /* Debug only */ + { + unsigned offset; + for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) + { + hs_buf = &hs->buffering.hs[offset]; + if( hs_buf->is_valid == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.", + hs->in_msg_seq + offset, + hs_buf->is_complete ? "fully" : "partially" ) ); + } + } + } +#endif /* MBEDTLS_DEBUG_C */ + + /* Check if we have buffered and/or fully reassembled the + * next handshake message. */ + hs_buf = &hs->buffering.hs[0]; + if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) ) + { + /* Synthesize a record containing the buffered HS message. */ + size_t msg_len = ( hs_buf->data[1] << 16 ) | + ( hs_buf->data[2] << 8 ) | + hs_buf->data[3]; + + /* Double-check that we haven't accidentally buffered + * a message that doesn't fit into the input buffer. */ + if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)", + hs_buf->data, msg_len + 12 ); + + ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->in_hslen = msg_len + 12; + ssl->in_msglen = msg_len + 12; + memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen ); + + ret = 0; + goto exit; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered", + hs->in_msg_seq ) ); + } + + ret = -1; + +exit: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) ); + return( ret ); +} + +static int ssl_buffer_make_space( mbedtls_ssl_context *ssl, + size_t desired ) +{ + int offset; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available", + (unsigned) desired ) ); + + /* Get rid of future records epoch first, if such exist. */ + ssl_free_buffered_record( ssl ); + + /* Check if we have enough space available now. */ + if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) ); + return( 0 ); + } + + /* We don't have enough space to buffer the next expected handshake + * message. Remove buffers used for future messages to gain space, + * starting with the most distant one. */ + for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1; + offset >= 0; offset-- ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message", + offset ) ); + + ssl_buffering_free_slot( ssl, (uint8_t) offset ); + + /* Check if we have enough space available now. */ + if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) ); + return( 0 ); + } + } + + return( -1 ); +} + +static int ssl_buffer_message( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( hs == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) ); + + switch( ssl->in_msgtype ) + { + case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) ); + + hs->buffering.seen_ccs = 1; + break; + + case MBEDTLS_SSL_MSG_HANDSHAKE: + { + unsigned recv_msg_seq_offset; + unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + mbedtls_ssl_hs_buffer *hs_buf; + size_t msg_len = ssl->in_hslen - 12; + + /* We should never receive an old handshake + * message - double-check nonetheless. */ + if( recv_msg_seq < ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq; + if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS ) + { + /* Silently ignore -- message too far in the future */ + MBEDTLS_SSL_DEBUG_MSG( 2, + ( "Ignore future HS message with sequence number %u, " + "buffering window %u - %u", + recv_msg_seq, ssl->handshake->in_msg_seq, + ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) ); + + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ", + recv_msg_seq, recv_msg_seq_offset ) ); + + hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ]; + + /* Check if the buffering for this seq nr has already commenced. */ + if( !hs_buf->is_valid ) + { + size_t reassembly_buf_sz; + + hs_buf->is_fragmented = + ( ssl_hs_is_proper_fragment( ssl ) == 1 ); + + /* We copy the message back into the input buffer + * after reassembly, so check that it's not too large. + * This is an implementation-specific limitation + * and not one from the standard, hence it is not + * checked in ssl_check_hs_header(). */ + if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + /* Ignore message */ + goto exit; + } + + /* Check if we have enough space to buffer the message. */ + if( hs->buffering.total_bytes_buffered > + MBEDTLS_SSL_DTLS_MAX_BUFFERING ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len, + hs_buf->is_fragmented ); + + if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + if( recv_msg_seq_offset > 0 ) + { + /* If we can't buffer a future message because + * of space limitations -- ignore. */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n", + (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + goto exit; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- attempt to make space by freeing buffered future messages\n", + (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + } + + if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %u (%u with bitmap) would exceed the compile-time limit %u (already %u bytes buffered) -- fail\n", + (unsigned) msg_len, + (unsigned) reassembly_buf_sz, + MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + goto exit; + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", + msg_len ) ); + + hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz ); + if( hs_buf->data == NULL ) + { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + hs_buf->data_len = reassembly_buf_sz; + + /* Prepare final header: copy msg_type, length and message_seq, + * then add standardised fragment_offset and fragment_length */ + memcpy( hs_buf->data, ssl->in_msg, 6 ); + memset( hs_buf->data + 6, 0, 3 ); + memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 ); + + hs_buf->is_valid = 1; + + hs->buffering.total_bytes_buffered += reassembly_buf_sz; + } + else + { + /* Make sure msg_type and length are consistent */ + if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) ); + /* Ignore */ + goto exit; + } + } + + if( !hs_buf->is_complete ) + { + size_t frag_len, frag_off; + unsigned char * const msg = hs_buf->data + 12; + + /* + * Check and copy current fragment + */ + + /* Validation of header fields already done in + * mbedtls_ssl_prepare_handshake_record(). */ + frag_off = ssl_get_hs_frag_off( ssl ); + frag_len = ssl_get_hs_frag_len( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d", + frag_off, frag_len ) ); + memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); + + if( hs_buf->is_fragmented ) + { + unsigned char * const bitmask = msg + msg_len; + ssl_bitmask_set( bitmask, frag_off, frag_len ); + hs_buf->is_complete = ( ssl_bitmask_check( bitmask, + msg_len ) == 0 ); + } + else + { + hs_buf->is_complete = 1; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete", + hs_buf->is_complete ? "" : "not yet " ) ); + } + + break; + } + + default: + /* We don't buffer other types of messages. */ + break; + } + +exit: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) ); + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_consume_current_message( mbedtls_ssl_context *ssl ) +{ + /* + * Consume last content-layer message and potentially + * update in_msglen which keeps track of the contents' + * consumption state. + * + * (1) Handshake messages: + * Remove last handshake message, move content + * and adapt in_msglen. + * + * (2) Alert messages: + * Consume whole record content, in_msglen = 0. + * + * (3) Change cipher spec: + * Consume whole record content, in_msglen = 0. + * + * (4) Application data: + * Don't do anything - the record layer provides + * the application data as a stream transport + * and consumes through mbedtls_ssl_read only. + * + */ + + /* Case (1): Handshake messages */ + if( ssl->in_hslen != 0 ) + { + /* Hard assertion to be sure that no application data + * is in flight, as corrupting ssl->in_msglen during + * ssl->in_offt != NULL is fatal. */ + if( ssl->in_offt != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Get next Handshake message in the current record + */ + + /* Notes: + * (1) in_hslen is not necessarily the size of the + * current handshake content: If DTLS handshake + * fragmentation is used, that's the fragment + * size instead. Using the total handshake message + * size here is faulty and should be changed at + * some point. + * (2) While it doesn't seem to cause problems, one + * has to be very careful not to assume that in_hslen + * is always <= in_msglen in a sensible communication. + * Again, it's wrong for DTLS handshake fragmentation. + * The following check is therefore mandatory, and + * should not be treated as a silently corrected assertion. + * Additionally, ssl->in_hslen might be arbitrarily out of + * bounds after handling a DTLS message with an unexpected + * sequence number, see mbedtls_ssl_prepare_handshake_record. + */ + if( ssl->in_hslen < ssl->in_msglen ) + { + ssl->in_msglen -= ssl->in_hslen; + memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, + ssl->in_msglen ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record", + ssl->in_msg, ssl->in_msglen ); + } + else + { + ssl->in_msglen = 0; + } + + ssl->in_hslen = 0; + } + /* Case (4): Application data */ + else if( ssl->in_offt != NULL ) + { + return( 0 ); + } + /* Everything else (CCS & Alerts) */ + else + { + ssl->in_msglen = 0; + } + + return( 0 ); +} + +static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen > 0 ) + return( 1 ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + if( hs == NULL ) + return; + + if( hs->buffering.future_record.data != NULL ) + { + hs->buffering.total_bytes_buffered -= + hs->buffering.future_record.len; + + mbedtls_free( hs->buffering.future_record.data ); + hs->buffering.future_record.data = NULL; + } +} + +static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + unsigned char * rec; + size_t rec_len; + unsigned rec_epoch; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; +#endif + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 0 ); + + if( hs == NULL ) + return( 0 ); + + rec = hs->buffering.future_record.data; + rec_len = hs->buffering.future_record.len; + rec_epoch = hs->buffering.future_record.epoch; + + if( rec == NULL ) + return( 0 ); + + /* Only consider loading future records if the + * input buffer is empty. */ + if( ssl_next_record_is_in_datagram( ssl ) == 1 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) ); + + if( rec_epoch != ssl->in_epoch ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) ); + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) ); + + /* Double-check that the record is not too large */ + if( rec_len > in_buf_len - (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( ssl->in_hdr, rec, rec_len ); + ssl->in_left = rec_len; + ssl->next_record_offset = 0; + + ssl_free_buffered_record( ssl ); + +exit: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) ); + return( 0 ); +} + +static int ssl_buffer_future_record( mbedtls_ssl_context *ssl, + mbedtls_record const *rec ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + /* Don't buffer future records outside handshakes. */ + if( hs == NULL ) + return( 0 ); + + /* Only buffer handshake records (we are only interested + * in Finished messages). */ + if( rec->type != MBEDTLS_SSL_MSG_HANDSHAKE ) + return( 0 ); + + /* Don't buffer more than one future epoch record. */ + if( hs->buffering.future_record.data != NULL ) + return( 0 ); + + /* Don't buffer record if there's not enough buffering space remaining. */ + if( rec->buf_len > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n", + (unsigned) rec->buf_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + return( 0 ); + } + + /* Buffer record */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u", + ssl->in_epoch + 1 ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", rec->buf, rec->buf_len ); + + /* ssl_parse_record_header() only considers records + * of the next epoch as candidates for buffering. */ + hs->buffering.future_record.epoch = ssl->in_epoch + 1; + hs->buffering.future_record.len = rec->buf_len; + + hs->buffering.future_record.data = + mbedtls_calloc( 1, hs->buffering.future_record.len ); + if( hs->buffering.future_record.data == NULL ) + { + /* If we run out of RAM trying to buffer a + * record from the next epoch, just ignore. */ + return( 0 ); + } + + memcpy( hs->buffering.future_record.data, rec->buf, rec->buf_len ); + + hs->buffering.total_bytes_buffered += rec->buf_len; + return( 0 ); +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_get_next_record( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_record rec; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* We might have buffered a future record; if so, + * and if the epoch matches now, load it. + * On success, this call will set ssl->in_left to + * the length of the buffered record, so that + * the calls to ssl_fetch_input() below will + * essentially be no-ops. */ + ret = ssl_load_buffered_record( ssl ); + if( ret != 0 ) + return( ret ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Ensure that we have enough space available for the default form + * of TLS / DTLS record headers (5 Bytes for TLS, 13 Bytes for DTLS, + * with no space for CIDs counted in). */ + ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_in_hdr_len( ssl ) ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + ret = ssl_parse_record_header( ssl, ssl->in_hdr, ssl->in_left, &rec ); + if( ret != 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + ret = ssl_buffer_future_record( ssl, &rec ); + if( ret != 0 ) + return( ret ); + + /* Fall through to handling of unexpected records */ + ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; + } + + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ) + { +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) + /* Reset in pointers to default state for TLS/DTLS records, + * assuming no CID and no offset between record content and + * record plaintext. */ + mbedtls_ssl_update_in_pointers( ssl ); + + /* Setup internal message pointers from record structure. */ + ssl->in_msgtype = rec.type; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->in_len = ssl->in_cid + rec.cid_len; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_iv = ssl->in_msg = ssl->in_len + 2; + ssl->in_msglen = rec.data_len; + + ret = ssl_check_client_reconnect( ssl ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_client_reconnect", ret ); + if( ret != 0 ) + return( ret ); +#endif + + /* Skip unexpected record (but not whole datagram) */ + ssl->next_record_offset = rec.buf_len; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record " + "(header)" ) ); + } + else + { + /* Skip invalid record and the rest of the datagram */ + ssl->next_record_offset = 0; + ssl->in_left = 0; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record " + "(header)" ) ); + } + + /* Get next record */ + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + } + else +#endif + { + return( ret ); + } + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Remember offset of next record within datagram. */ + ssl->next_record_offset = rec.buf_len; + if( ssl->next_record_offset < ssl->in_left ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) ); + } + } + else +#endif + { + /* + * Fetch record contents from underlying transport. + */ + ret = mbedtls_ssl_fetch_input( ssl, rec.buf_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + ssl->in_left = 0; + } + + /* + * Decrypt record contents. + */ + + if( ( ret = ssl_prepare_record_content( ssl, &rec ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Silently discard invalid records */ + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + /* Except when waiting for Finished as a bad mac here + * probably means something went wrong in the handshake + * (eg wrong psk used, mitm downgrade attempt, etc.) */ + if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED || + ssl->state == MBEDTLS_SSL_SERVER_FINISHED ) + { +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + return( ret ); + } + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + if( ssl->conf->badmac_limit != 0 && + ++ssl->badmac_seen >= ssl->conf->badmac_limit ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } +#endif + + /* As above, invalid records cause + * dismissal of the whole datagram. */ + + ssl->next_record_offset = 0; + ssl->in_left = 0; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) ); + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + } + + return( ret ); + } + else +#endif + { + /* Error out (and send alert) on invalid records */ +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + return( ret ); + } + } + + + /* Reset in pointers to default state for TLS/DTLS records, + * assuming no CID and no offset between record content and + * record plaintext. */ + mbedtls_ssl_update_in_pointers( ssl ); +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->in_len = ssl->in_cid + rec.cid_len; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_iv = ssl->in_len + 2; + + /* The record content type may change during decryption, + * so re-read it. */ + ssl->in_msgtype = rec.type; + /* Also update the input buffer, because unfortunately + * the server-side ssl_parse_client_hello() reparses the + * record header when receiving a ClientHello initiating + * a renegotiation. */ + ssl->in_hdr[0] = rec.type; + ssl->in_msg = rec.buf + rec.data_offset; + ssl->in_msglen = rec.data_len; + ssl->in_len[0] = (unsigned char)( rec.data_len >> 8 ); + ssl->in_len[1] = (unsigned char)( rec.data_len ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->transform_in != NULL && + ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_decompress_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret ); + return( ret ); + } + + /* Check actual (decompress) record content length against + * configured maximum. */ + if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } +#endif /* MBEDTLS_ZLIB_SUPPORT */ + + return( 0 ); +} + +int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * Handle particular types of records + */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 ) + { + return( ret ); + } + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + if( ssl->in_msglen != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->in_msg[0] != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x", + ssl->in_msg[0] ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && + ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + if( ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } +#endif + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) + { + if( ssl->in_msglen != 2 ) + { + /* Note: Standard allows for more than one 2 byte alert + to be packed in a single message, but Mbed TLS doesn't + currently support this. */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]", + ssl->in_msg[0], ssl->in_msg[1] ) ); + + /* + * Ignore non-fatal alerts, except close_notify and no_renegotiation + */ + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)", + ssl->in_msg[1] ) ); + return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE ); + } + + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) ); + return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED) + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no renegotiation alert" ) ); + /* Will be handled when trying to parse ServerHello */ + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); + /* Will be handled in mbedtls_ssl_parse_certificate() */ + return( 0 ); + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ + + /* Silently ignore: fetch new message */ + return MBEDTLS_ERR_SSL_NON_FATAL; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Drop unexpected ApplicationData records, + * except at the beginning of renegotiations */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && + ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->state == MBEDTLS_SSL_SERVER_HELLO ) +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) ); + return( MBEDTLS_ERR_SSL_NON_FATAL ); + } + + if( ssl->handshake != NULL && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + return( 0 ); +} + +int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ); +} + +int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, + unsigned char level, + unsigned char message ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message )); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl->out_msglen = 2; + ssl->out_msg[0] = level; + ssl->out_msg[1] = message; + + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); + + return( 0 ); +} + +int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->out_msglen = 1; + ssl->out_msg[0] = 1; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); + + return( 0 ); +} + +int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* CCS records are only accepted if they have length 1 and content '1', + * so we don't need to check this here. */ + + /* + * Switch to our negotiated transform and session parameters for inbound + * data. + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) ); + ssl->transform_in = ssl->transform_negotiate; + ssl->session_in = ssl->session_negotiate; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + mbedtls_ssl_dtls_replay_reset( ssl ); +#endif + + /* Increment epoch */ + if( ++ssl->in_epoch == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + /* This is highly unlikely to happen for legitimate reasons, so + treat it as an attack and don't send an alert. */ + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + memset( ssl->in_ctr, 0, 8 ); + + mbedtls_ssl_update_in_pointers( ssl ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) ); + + return( 0 ); +} + +/* Once ssl->out_hdr as the address of the beginning of the + * next outgoing record is set, deduce the other pointers. + * + * Note: For TLS, we save the implicit record sequence number + * (entering MAC computation) in the 8 bytes before ssl->out_hdr, + * and the caller has to make sure there's space for this. + */ + +void mbedtls_ssl_update_out_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_ctr = ssl->out_hdr + 3; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->out_cid = ssl->out_ctr + 8; + ssl->out_len = ssl->out_cid; + if( transform != NULL ) + ssl->out_len += transform->out_cid_len; +#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->out_len = ssl->out_ctr + 8; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->out_iv = ssl->out_len + 2; + } + else +#endif + { + ssl->out_ctr = ssl->out_hdr - 8; + ssl->out_len = ssl->out_hdr + 3; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->out_cid = ssl->out_len; +#endif + ssl->out_iv = ssl->out_hdr + 5; + } + + /* Adjust out_msg to make space for explicit IV, if used. */ + if( transform != NULL && + ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->out_msg = ssl->out_iv + transform->ivlen - transform->fixed_ivlen; + } + else + ssl->out_msg = ssl->out_iv; +} + +/* Once ssl->in_hdr as the address of the beginning of the + * next incoming record is set, deduce the other pointers. + * + * Note: For TLS, we save the implicit record sequence number + * (entering MAC computation) in the 8 bytes before ssl->in_hdr, + * and the caller has to make sure there's space for this. + */ + +void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl ) +{ + /* This function sets the pointers to match the case + * of unprotected TLS/DTLS records, with both ssl->in_iv + * and ssl->in_msg pointing to the beginning of the record + * content. + * + * When decrypting a protected record, ssl->in_msg + * will be shifted to point to the beginning of the + * record plaintext. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* This sets the header pointers to match records + * without CID. When we receive a record containing + * a CID, the fields are shifted accordingly in + * ssl_parse_record_header(). */ + ssl->in_ctr = ssl->in_hdr + 3; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->in_cid = ssl->in_ctr + 8; + ssl->in_len = ssl->in_cid; /* Default: no CID */ +#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_len = ssl->in_ctr + 8; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_iv = ssl->in_len + 2; + } + else +#endif + { + ssl->in_ctr = ssl->in_hdr - 8; + ssl->in_len = ssl->in_hdr + 3; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->in_cid = ssl->in_len; +#endif + ssl->in_iv = ssl->in_hdr + 5; + } + + /* This will be adjusted at record decryption time. */ + ssl->in_msg = ssl->in_iv; +} + +/* + * Setup an SSL context + */ + +void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ) +{ + /* Set the incoming and outgoing record pointers. */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + ssl->in_hdr = ssl->in_buf; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + ssl->out_hdr = ssl->out_buf + 8; + ssl->in_hdr = ssl->in_buf + 8; + } + + /* Derive other internal pointers. */ + mbedtls_ssl_update_out_pointers( ssl, NULL /* no transform enabled */ ); + mbedtls_ssl_update_in_pointers ( ssl ); +} + +/* + * SSL get accessors + */ +size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ) +{ + return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); +} + +int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl ) +{ + /* + * Case A: We're currently holding back + * a message for further processing. + */ + + if( ssl->keep_current_message == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: record held back for processing" ) ); + return( 1 ); + } + + /* + * Case B: Further records are pending in the current datagram. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->in_left > ssl->next_record_offset ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more records within current datagram" ) ); + return( 1 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Case C: A handshake message is being processed. + */ + + if( ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more handshake messages within current record" ) ); + return( 1 ); + } + + /* + * Case D: An application data message is being processed + */ + if( ssl->in_offt != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: application data record is being processed" ) ); + return( 1 ); + } + + /* + * In all other cases, the rest of the message can be dropped. + * As in ssl_get_next_record, this needs to be adapted if + * we implement support for multiple alerts in single records. + */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: nothing pending" ) ); + return( 0 ); +} + + +int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) +{ + size_t transform_expansion = 0; + const mbedtls_ssl_transform *transform = ssl->transform_out; + unsigned block_size; + + size_t out_hdr_len = mbedtls_ssl_out_hdr_len( ssl ); + + if( transform == NULL ) + return( (int) out_hdr_len ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + + switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) ) + { + case MBEDTLS_MODE_GCM: + case MBEDTLS_MODE_CCM: + case MBEDTLS_MODE_CHACHAPOLY: + case MBEDTLS_MODE_STREAM: + transform_expansion = transform->minlen; + break; + + case MBEDTLS_MODE_CBC: + + block_size = mbedtls_cipher_get_block_size( + &transform->cipher_ctx_enc ); + + /* Expansion due to the addition of the MAC. */ + transform_expansion += transform->maclen; + + /* Expansion due to the addition of CBC padding; + * Theoretically up to 256 bytes, but we never use + * more than the block size of the underlying cipher. */ + transform_expansion += block_size; + + /* For TLS 1.1 or higher, an explicit IV is added + * after the record header. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + transform_expansion += block_size; +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( transform->out_cid_len != 0 ) + transform_expansion += MBEDTLS_SSL_MAX_CID_EXPANSION; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + return( (int)( out_hdr_len + transform_expansion ) ); +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/* + * Check record counters and renegotiate if they're above the limit. + */ +static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) +{ + size_t ep_len = mbedtls_ssl_ep_len( ssl ); + int in_ctr_cmp; + int out_ctr_cmp; + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || + ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ) + { + return( 0 ); + } + + in_ctr_cmp = memcmp( ssl->in_ctr + ep_len, + ssl->conf->renego_period + ep_len, 8 - ep_len ); + out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len, + ssl->conf->renego_period + ep_len, 8 - ep_len ); + + if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 ) + { + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) ); + return( mbedtls_ssl_renegotiate( ssl ) ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Receive application data decrypted from the SSL layer + */ +int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + if( ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + return( ret ); + } + } +#endif + + /* + * Check if renegotiation is necessary and/or handshake is + * in process. If yes, perform/continue, and fall through + * if an unexpected packet is received while the client + * is waiting for the ServerHello. + * + * (There is no equivalent to the last condition on + * the server-side as it is not treated as within + * a handshake while waiting for the ClientHello + * after a renegotiation request.) + */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ret = ssl_check_ctr_renegotiate( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ret = mbedtls_ssl_handshake( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } + + /* Loop as long as no application data record is available */ + while( ssl->in_offt == NULL ) + { + /* Start timer if not already running */ + if( ssl->f_get_timer != NULL && + ssl->f_get_timer( ssl->p_timer ) == -1 ) + { + mbedtls_ssl_set_timer( ssl, ssl->conf->read_timeout ); + } + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msglen == 0 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* + * OpenSSL sends empty messages to randomize the IV + */ + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); + + /* + * - For client-side, expect SERVER_HELLO_REQUEST. + * - For server-side, expect CLIENT_HELLO. + * - Fail (TLS) or silently drop record (DTLS) in other cases. + */ + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + continue; + } +#endif + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } +#endif /* MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) ); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + continue; + } +#endif + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + /* Determine whether renegotiation attempt should be accepted */ + if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || + ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) ) + { + /* + * Accept renegotiation request + */ + + /* DTLS clients need to know renego is server-initiated */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + } +#endif + ret = mbedtls_ssl_start_renegotiation( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation", + ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + /* + * Refuse renegotiation + */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* SSLv3 does not have a "no_renegotiation" warning, so + we send a fatal alert and abort the connection. */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 ) + { + return( ret ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + + /* At this point, we don't know whether the renegotiation has been + * completed or not. The cases to consider are the following: + * 1) The renegotiation is complete. In this case, no new record + * has been read yet. + * 2) The renegotiation is incomplete because the client received + * an application data record while awaiting the ServerHello. + * 3) The renegotiation is incomplete because the client received + * a non-handshake, non-application data message while awaiting + * the ServerHello. + * In each of these case, looping will be the proper action: + * - For 1), the next iteration will read a new record and check + * if it's application data. + * - For 2), the loop condition isn't satisfied as application data + * is present, hence continue is the same as break + * - For 3), the loop condition is satisfied and read_record + * will re-deliver the message that was held back by the client + * when expecting the ServerHello. + */ + continue; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ssl->conf->renego_max_records >= 0 ) + { + if( ++ssl->renego_records_seen > ssl->conf->renego_max_records ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " + "but not honored by client" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + } + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) ); + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->in_offt = ssl->in_msg; + + /* We're going to return something now, cancel timer, + * except if handshake (renegotiation) is in progress */ + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + mbedtls_ssl_set_timer( ssl, 0 ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* If we requested renego but received AppData, resend HelloRequest. + * Do it now, after setting in_offt, to avoid taking this branch + * again if ssl_write_hello_request() returns WANT_WRITE */ +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request", + ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + } + + n = ( len < ssl->in_msglen ) + ? len : ssl->in_msglen; + + memcpy( buf, ssl->in_offt, n ); + ssl->in_msglen -= n; + + if( ssl->in_msglen == 0 ) + { + /* all bytes consumed */ + ssl->in_offt = NULL; + ssl->keep_current_message = 0; + } + else + { + /* more data available */ + ssl->in_offt += n; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) ); + + return( (int) n ); +} + +/* + * Send application data to be encrypted by the SSL layer, taking care of max + * fragment length and buffer size. + * + * According to RFC 5246 Section 6.2.1: + * + * Zero-length fragments of Application data MAY be sent as they are + * potentially useful as a traffic analysis countermeasure. + * + * Therefore, it is possible that the input message length is 0 and the + * corresponding return code is 0 on success. + */ +static int ssl_write_real( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret = mbedtls_ssl_get_max_out_record_payload( ssl ); + const size_t max_len = (size_t) ret; + + if( ret < 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret ); + return( ret ); + } + + if( len > max_len ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) " + "maximum fragment length: %d > %d", + len, max_len ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + else +#endif + len = max_len; + } + + if( ssl->out_left != 0 ) + { + /* + * The user has previously tried to send the data and + * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially + * written. In this case, we expect the high-level write function + * (e.g. mbedtls_ssl_write()) to be called with the same parameters + */ + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + } + else + { + /* + * The user is trying to send a message the first time, so we need to + * copy the data into the internal buffers and setup the data structure + * to keep track of partial writes + */ + ssl->out_msglen = len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; + memcpy( ssl->out_msg, buf, len ); + + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + } + + return( (int) len ); +} + +/* + * Write application data, doing 1/n-1 splitting if necessary. + * + * With non-blocking I/O, ssl_write_real() may return WANT_WRITE, + * then the caller will call us again with the same arguments, so + * remember whether we already did the split or not. + */ +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +static int ssl_write_split( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl->conf->cbc_record_splitting == + MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED || + len <= 1 || + ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 || + mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ) + != MBEDTLS_MODE_CBC ) + { + return( ssl_write_real( ssl, buf, len ) ); + } + + if( ssl->split_done == 0 ) + { + if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 ) + return( ret ); + ssl->split_done = 1; + } + + if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 ) + return( ret ); + ssl->split_done = 0; + + return( ret + 1 ); +} +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + +/* + * Write application data (public-facing wrapper) + */ +int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) ); + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + ret = ssl_write_split( ssl, buf, len ); +#else + ret = ssl_write_real( ssl, buf, len ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) ); + + return( ret ); +} + +/* + * Notify the peer that the connection is being closed + */ +int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); + + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) ); + + return( 0 ); +} + +void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ) +{ + if( transform == NULL ) + return; + +#if defined(MBEDTLS_ZLIB_SUPPORT) + deflateEnd( &transform->ctx_deflate ); + inflateEnd( &transform->ctx_inflate ); +#endif + + mbedtls_cipher_free( &transform->cipher_ctx_enc ); + mbedtls_cipher_free( &transform->cipher_ctx_dec ); + +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + mbedtls_md_free( &transform->md_ctx_enc ); + mbedtls_md_free( &transform->md_ctx_dec ); +#endif + + mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl ) +{ + unsigned offset; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( hs == NULL ) + return; + + ssl_free_buffered_record( ssl ); + + for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) + ssl_buffering_free_slot( ssl, offset ); +} + +static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, + uint8_t slot ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot]; + + if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS ) + return; + + if( hs_buf->is_valid == 1 ) + { + hs->buffering.total_bytes_buffered -= hs_buf->data_len; + mbedtls_platform_zeroize( hs_buf->data, hs_buf->data_len ); + mbedtls_free( hs_buf->data ); + memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); + } +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +/* + * Convert version numbers to/from wire format + * and, for DTLS, to/from TLS equivalent. + * + * For TLS this is the identity. + * For DTLS, use 1's complement (v -> 255 - v, and then map as follows: + * 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1) + * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) + */ +void mbedtls_ssl_write_version( int major, int minor, int transport, + unsigned char ver[2] ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( minor == MBEDTLS_SSL_MINOR_VERSION_2 ) + --minor; /* DTLS 1.0 stored as TLS 1.1 internally */ + + ver[0] = (unsigned char)( 255 - ( major - 2 ) ); + ver[1] = (unsigned char)( 255 - ( minor - 1 ) ); + } + else +#else + ((void) transport); +#endif + { + ver[0] = (unsigned char) major; + ver[1] = (unsigned char) minor; + } +} + +void mbedtls_ssl_read_version( int *major, int *minor, int transport, + const unsigned char ver[2] ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + *major = 255 - ver[0] + 2; + *minor = 255 - ver[1] + 1; + + if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 ) + ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */ + } + else +#else + ((void) transport); +#endif + { + *major = ver[0]; + *minor = ver[1]; + } +} + +#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/features/mbedtls/src/ssl_srv.c b/features/mbedtls/src/ssl_srv.c index b0b09cd97f..006bc69c30 100644 --- a/features/mbedtls/src/ssl_srv.c +++ b/features/mbedtls/src/ssl_srv.c @@ -150,7 +150,7 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#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 ) @@ -190,7 +190,7 @@ static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl ) return( 0 ); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, const unsigned char *buf, @@ -229,7 +229,7 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* * Status of the implementation of signature-algorithms extension: @@ -317,7 +317,7 @@ static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, return( 0 ); } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -840,6 +840,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl, for( cur = list; cur != NULL; cur = cur->next ) { + flags = 0; MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate", cur->cert ); @@ -921,7 +922,7 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, const mbedtls_ssl_ciphersuite_t *suite_info; #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) mbedtls_pk_type_t sig_type; #endif @@ -978,7 +979,7 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, } #endif -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) /* If the ciphersuite requires a pre-shared key and we don't * have one, skip it now rather than failing later */ if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && @@ -990,7 +991,7 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* If the ciphersuite requires signing, check whether * a suitable hash algorithm is present. */ if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) @@ -1006,7 +1007,7 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /* @@ -1316,10 +1317,10 @@ static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) * we need to fall back to the default values for allowed * signature-hash pairs. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) int sig_hash_alg_ext_present = 0; #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); @@ -1832,7 +1833,7 @@ read_record_header: break; #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) case MBEDTLS_TLS_EXT_SIG_ALG: MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) ); @@ -1843,7 +1844,7 @@ read_record_header: sig_hash_alg_ext_present = 1; break; #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -1990,7 +1991,7 @@ read_record_header: #endif /* MBEDTLS_SSL_FALLBACK_SCSV */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* * Try to fall back to default hash SHA1 if the client @@ -2007,7 +2008,7 @@ read_record_header: } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ /* * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV @@ -2134,7 +2135,7 @@ have_ciphersuite: /* Debugging-only output for testsuite */ #if defined(MBEDTLS_DEBUG_C) && \ defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) { mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg( ciphersuite_info ); @@ -2816,7 +2817,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) return( ret ); } -#if !defined(MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED) +#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = @@ -2834,7 +2835,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } -#else /* !MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ +#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; @@ -3002,7 +3003,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) return( ret ); } -#endif /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) @@ -3029,7 +3030,7 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \ +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \ defined(MBEDTLS_SSL_ASYNC_PRIVATE) static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl, size_t *signature_len ) @@ -3052,7 +3053,7 @@ static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_RET( 2, "ssl_resume_server_key_exchange", ret ); return( ret ); } -#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && +#endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ /* Prepare the ServerKeyExchange message, up to and including @@ -3064,16 +3065,16 @@ static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; -#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) unsigned char *dig_signed = NULL; -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ -#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */ (void) ciphersuite_info; /* unused in some configurations */ -#if !defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) +#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) (void) signature_len; -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */ @@ -3126,7 +3127,7 @@ static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, /* * - DHE key exchanges */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -3165,7 +3166,7 @@ static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, return( ret ); } -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) dig_signed = ssl->out_msg + ssl->out_msglen; #endif @@ -3176,12 +3177,12 @@ static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED */ /* * - ECDHE key exchanges */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) if( mbedtls_ssl_ciphersuite_uses_ecdhe( ciphersuite_info ) ) { /* @@ -3229,7 +3230,7 @@ curve_matching_done: return( ret ); } -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) dig_signed = ssl->out_msg + ssl->out_msglen; #endif @@ -3238,7 +3239,7 @@ curve_matching_done: MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Q ); } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */ /* * @@ -3246,7 +3247,7 @@ curve_matching_done: * exchange parameters, compute and add the signature here. * */ -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) { size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed; @@ -3414,7 +3415,7 @@ curve_matching_done: return( ret ); } } -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ return( 0 ); } @@ -3427,26 +3428,26 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t signature_len = 0; -#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; -#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); -#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) /* Extract static ECDH parameters and abort if ServerKeyExchange * is not needed. */ if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) ) { /* For suites involving ECDH, extract DH parameters * from certificate at this point. */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) ) { ssl_get_ecdh_params_from_cert( ssl ); } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */ /* Key exchanges not involving ephemeral keys don't use * ServerKeyExchange, so end here. */ @@ -3454,9 +3455,9 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) ssl->state++; return( 0 ); } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \ +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \ defined(MBEDTLS_SSL_ASYNC_PRIVATE) /* If we have already prepared the message and there is an ongoing * signature operation, resume signing. */ @@ -3466,7 +3467,7 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) ret = ssl_resume_server_key_exchange( ssl, &signature_len ); } else -#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && +#endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ { /* ServerKeyExchange is needed. Prepare the message. */ @@ -3489,7 +3490,7 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) /* If there is a signature, write its length. * ssl_prepare_server_key_exchange already wrote the signature * itself at its proper place in the output buffer. */ -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) if( signature_len != 0 ) { ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len >> 8 ); @@ -3502,7 +3503,7 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) /* Skip over the already-written signature */ ssl->out_msglen += signature_len; } -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ /* Add header and send. */ ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; @@ -3806,12 +3807,12 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p, const unsigned char *end ) { int ret = 0; - size_t n; + uint16_t n; if( ssl_conf_has_psk_or_cb( ssl->conf ) == 0 ) { @@ -3831,7 +3832,7 @@ static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned cha n = ( (*p)[0] << 8 ) | (*p)[1]; *p += 2; - if( n < 1 || n > 65535 || n > (size_t) ( end - *p ) ) + if( n == 0 || n > end - *p ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); @@ -3865,7 +3866,7 @@ static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned cha return( 0 ); } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) { @@ -4172,7 +4173,7 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) return( 0 ); } -#if !defined(MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED) +#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = @@ -4190,7 +4191,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } -#else /* !MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ +#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; @@ -4381,7 +4382,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) return( ret ); } -#endif /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) diff --git a/features/mbedtls/src/ssl_tls.c b/features/mbedtls/src/ssl_tls.c index 6cf7781f2a..d0adfd9515 100644 --- a/features/mbedtls/src/ssl_tls.c +++ b/features/mbedtls/src/ssl_tls.c @@ -61,124 +61,6 @@ #include "mbedtls/oid.h" #endif -static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ); -static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ); - -/* Length of the "epoch" field in the record header */ -static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl ) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( 2 ); -#else - ((void) ssl); -#endif - return( 0 ); -} - -/* - * Start a timer. - * Passing millisecs = 0 cancels a running timer. - */ -static void ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ) -{ - if( ssl->f_set_timer == NULL ) - return; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) ); - ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs ); -} - -/* - * Return -1 is timer is expired, 0 if it isn't. - */ -static int ssl_check_timer( mbedtls_ssl_context *ssl ) -{ - if( ssl->f_get_timer == NULL ) - return( 0 ); - - if( ssl->f_get_timer( ssl->p_timer ) == 2 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) ); - return( -1 ); - } - - return( 0 ); -} - -static void ssl_update_out_pointers( mbedtls_ssl_context *ssl, - mbedtls_ssl_transform *transform ); -static void ssl_update_in_pointers( mbedtls_ssl_context *ssl ); - -#if defined(MBEDTLS_SSL_RECORD_CHECKING) -static int ssl_parse_record_header( mbedtls_ssl_context const *ssl, - unsigned char *buf, - size_t len, - mbedtls_record *rec ); - -int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl, - unsigned char *buf, - size_t buflen ) -{ - int ret = 0; - MBEDTLS_SSL_DEBUG_MSG( 1, ( "=> mbedtls_ssl_check_record" ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "record buffer", buf, buflen ); - - /* We don't support record checking in TLS because - * (a) there doesn't seem to be a usecase for it, and - * (b) In SSLv3 and TLS 1.0, CBC record decryption has state - * and we'd need to backup the transform here. - */ - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) - { - ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - goto exit; - } -#if defined(MBEDTLS_SSL_PROTO_DTLS) - else - { - mbedtls_record rec; - - ret = ssl_parse_record_header( ssl, buf, buflen, &rec ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 3, "ssl_parse_record_header", ret ); - goto exit; - } - - if( ssl->transform_in != NULL ) - { - ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in, &rec ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 3, "mbedtls_ssl_decrypt_buf", ret ); - goto exit; - } - } - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -exit: - /* On success, we have decrypted the buffer in-place, so make - * sure we don't leak any plaintext data. */ - mbedtls_platform_zeroize( buf, buflen ); - - /* For the purpose of this API, treat messages with unexpected CID - * as well as such from future epochs as unexpected. */ - if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID || - ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) - { - ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "<= mbedtls_ssl_check_record" ) ); - return( ret ); -} -#endif /* MBEDTLS_SSL_RECORD_CHECKING */ - -#define SSL_DONT_FORCE_FLUSH 0 -#define SSL_FORCE_FLUSH 1 - #if defined(MBEDTLS_SSL_PROTO_DTLS) #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) @@ -274,137 +156,6 @@ int mbedtls_ssl_get_peer_cid( mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ -/* Forward declarations for functions related to message buffering. */ -static void ssl_buffering_free( mbedtls_ssl_context *ssl ); -static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, - uint8_t slot ); -static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ); -static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ); -static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ); -static int ssl_buffer_message( mbedtls_ssl_context *ssl ); -static int ssl_buffer_future_record( mbedtls_ssl_context *ssl, - mbedtls_record const *rec ); -static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ); - -static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl ); -static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl ) -{ - size_t mtu = ssl_get_current_mtu( ssl ); - - if( mtu != 0 && mtu < MBEDTLS_SSL_OUT_BUFFER_LEN ) - return( mtu ); - - return( MBEDTLS_SSL_OUT_BUFFER_LEN ); -} - -static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl ) -{ - size_t const bytes_written = ssl->out_left; - size_t const mtu = ssl_get_maximum_datagram_size( ssl ); - - /* Double-check that the write-index hasn't gone - * past what we can transmit in a single datagram. */ - if( bytes_written > mtu ) - { - /* Should never happen... */ - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - return( (int) ( mtu - bytes_written ) ); -} - -static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t remaining, expansion; - size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl ); - - if( max_len > mfl ) - max_len = mfl; - - /* By the standard (RFC 6066 Sect. 4), the MFL extension - * only limits the maximum record payload size, so in theory - * we would be allowed to pack multiple records of payload size - * MFL into a single datagram. However, this would mean that there's - * no way to explicitly communicate MTU restrictions to the peer. - * - * The following reduction of max_len makes sure that we never - * write datagrams larger than MFL + Record Expansion Overhead. - */ - if( max_len <= ssl->out_left ) - return( 0 ); - - max_len -= ssl->out_left; -#endif - - ret = ssl_get_remaining_space_in_datagram( ssl ); - if( ret < 0 ) - return( ret ); - remaining = (size_t) ret; - - ret = mbedtls_ssl_get_record_expansion( ssl ); - if( ret < 0 ) - return( ret ); - expansion = (size_t) ret; - - if( remaining <= expansion ) - return( 0 ); - - remaining -= expansion; - if( remaining >= max_len ) - remaining = max_len; - - return( (int) remaining ); -} - -/* - * Double the retransmit timeout value, within the allowed range, - * returning -1 if the maximum value has already been reached. - */ -static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ) -{ - uint32_t new_timeout; - - if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max ) - return( -1 ); - - /* Implement the final paragraph of RFC 6347 section 4.1.1.1 - * in the following way: after the initial transmission and a first - * retransmission, back off to a temporary estimated MTU of 508 bytes. - * This value is guaranteed to be deliverable (if not guaranteed to be - * delivered) of any compliant IPv4 (and IPv6) network, and should work - * on most non-IP stacks too. */ - if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min ) - { - ssl->handshake->mtu = 508; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) ); - } - - new_timeout = 2 * ssl->handshake->retransmit_timeout; - - /* Avoid arithmetic overflow and range overflow */ - if( new_timeout < ssl->handshake->retransmit_timeout || - new_timeout > ssl->conf->hs_timeout_max ) - { - new_timeout = ssl->conf->hs_timeout_max; - } - - ssl->handshake->retransmit_timeout = new_timeout; - MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", - ssl->handshake->retransmit_timeout ) ); - - return( 0 ); -} - -static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl ) -{ - ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min; - MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", - ssl->handshake->retransmit_timeout ) ); -} #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) @@ -494,20 +245,28 @@ int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst, return( 0 ); } -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) -int (*mbedtls_ssl_hw_record_init)( mbedtls_ssl_context *ssl, - const unsigned char *key_enc, const unsigned char *key_dec, - size_t keylen, - const unsigned char *iv_enc, const unsigned char *iv_dec, - size_t ivlen, - const unsigned char *mac_enc, const unsigned char *mac_dec, - size_t maclen ) = NULL; -int (*mbedtls_ssl_hw_record_activate)( mbedtls_ssl_context *ssl, int direction) = NULL; -int (*mbedtls_ssl_hw_record_reset)( mbedtls_ssl_context *ssl ) = NULL; -int (*mbedtls_ssl_hw_record_write)( mbedtls_ssl_context *ssl ) = NULL; -int (*mbedtls_ssl_hw_record_read)( mbedtls_ssl_context *ssl ) = NULL; -int (*mbedtls_ssl_hw_record_finish)( mbedtls_ssl_context *ssl ) = NULL; -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) +static int resize_buffer( unsigned char **buffer, size_t len_new, size_t *len_old ) +{ + unsigned char* resized_buffer = mbedtls_calloc( 1, len_new ); + if( resized_buffer == NULL ) + return -1; + + /* We want to copy len_new bytes when downsizing the buffer, and + * len_old bytes when upsizing, so we choose the smaller of two sizes, + * to fit one buffer into another. Size checks, ensuring that no data is + * lost, are done outside of this function. */ + memcpy( resized_buffer, *buffer, + ( len_new < *len_old ) ? len_new : *len_old ); + mbedtls_platform_zeroize( *buffer, *len_old ); + mbedtls_free( *buffer ); + + *buffer = resized_buffer; + *len_old = len_new; + + return 0; +} +#endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */ /* * Key material generation @@ -1068,7 +827,7 @@ typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *, * - [in] minor_ver: SSL/TLS minor version * - [in] endpoint: client or server * - [in] ssl: optionally used for: - * - MBEDTLS_SSL_HW_RECORD_ACCEL: whole context + * - MBEDTLS_SSL_HW_RECORD_ACCEL: whole context (non-const) * - MBEDTLS_SSL_EXPORT_KEYS: ssl->conf->{f,p}_export_keys * - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg */ @@ -1090,7 +849,10 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, const unsigned char randbytes[64], int minor_ver, unsigned endpoint, - const mbedtls_ssl_context *ssl ) +#if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + const +#endif + mbedtls_ssl_context *ssl ) { int ret = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) @@ -1880,7 +1642,7 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) /* Allocate compression buffer */ #if defined(MBEDTLS_ZLIB_SUPPORT) - if( session->compression == MBEDTLS_SSL_COMPRESS_DEFLATE && + if( ssl->session_negotiate->compression == MBEDTLS_SSL_COMPRESS_DEFLATE && ssl->compress_buf == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); @@ -2083,7 +1845,7 @@ void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SHA512_C */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ) { unsigned char *p = ssl->handshake->premaster; @@ -2205,1363 +1967,13 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch return( 0 ); } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ - -#if defined(MBEDTLS_SSL_PROTO_SSL3) -/* - * SSLv3.0 MAC functions - */ -#define SSL_MAC_MAX_BYTES 20 /* MD-5 or SHA-1 */ -static void ssl_mac( mbedtls_md_context_t *md_ctx, - const unsigned char *secret, - const unsigned char *buf, size_t len, - const unsigned char *ctr, int type, - unsigned char out[SSL_MAC_MAX_BYTES] ) -{ - unsigned char header[11]; - unsigned char padding[48]; - int padlen; - int md_size = mbedtls_md_get_size( md_ctx->md_info ); - int md_type = mbedtls_md_get_type( md_ctx->md_info ); - - /* Only MD5 and SHA-1 supported */ - if( md_type == MBEDTLS_MD_MD5 ) - padlen = 48; - else - padlen = 40; - - memcpy( header, ctr, 8 ); - header[ 8] = (unsigned char) type; - header[ 9] = (unsigned char)( len >> 8 ); - header[10] = (unsigned char)( len ); - - memset( padding, 0x36, padlen ); - mbedtls_md_starts( md_ctx ); - mbedtls_md_update( md_ctx, secret, md_size ); - mbedtls_md_update( md_ctx, padding, padlen ); - mbedtls_md_update( md_ctx, header, 11 ); - mbedtls_md_update( md_ctx, buf, len ); - mbedtls_md_finish( md_ctx, out ); - - memset( padding, 0x5C, padlen ); - mbedtls_md_starts( md_ctx ); - mbedtls_md_update( md_ctx, secret, md_size ); - mbedtls_md_update( md_ctx, padding, padlen ); - mbedtls_md_update( md_ctx, out, md_size ); - mbedtls_md_finish( md_ctx, out ); -} -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - -/* The function below is only used in the Lucky 13 counter-measure in - * mbedtls_ssl_decrypt_buf(). These are the defines that guard the call site. */ -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) && \ - ( defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) ) -/* This function makes sure every byte in the memory region is accessed - * (in ascending addresses order) */ -static void ssl_read_memory( unsigned char *p, size_t len ) -{ - unsigned char acc = 0; - volatile unsigned char force; - - for( ; len != 0; p++, len-- ) - acc ^= *p; - - force = acc; - (void) force; -} -#endif /* SSL_SOME_MODES_USE_MAC && ( TLS1 || TLS1_1 || TLS1_2 ) */ - -/* - * Encryption/decryption functions - */ - -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) -/* This functions transforms a DTLS plaintext fragment and a record content - * type into an instance of the DTLSInnerPlaintext structure: - * - * struct { - * opaque content[DTLSPlaintext.length]; - * ContentType real_type; - * uint8 zeros[length_of_padding]; - * } DTLSInnerPlaintext; - * - * Input: - * - `content`: The beginning of the buffer holding the - * plaintext to be wrapped. - * - `*content_size`: The length of the plaintext in Bytes. - * - `max_len`: The number of Bytes available starting from - * `content`. This must be `>= *content_size`. - * - `rec_type`: The desired record content type. - * - * Output: - * - `content`: The beginning of the resulting DTLSInnerPlaintext structure. - * - `*content_size`: The length of the resulting DTLSInnerPlaintext structure. - * - * Returns: - * - `0` on success. - * - A negative error code if `max_len` didn't offer enough space - * for the expansion. - */ -static int ssl_cid_build_inner_plaintext( unsigned char *content, - size_t *content_size, - size_t remaining, - uint8_t rec_type ) -{ - size_t len = *content_size; - size_t pad = ( MBEDTLS_SSL_CID_PADDING_GRANULARITY - - ( len + 1 ) % MBEDTLS_SSL_CID_PADDING_GRANULARITY ) % - MBEDTLS_SSL_CID_PADDING_GRANULARITY; - - /* Write real content type */ - if( remaining == 0 ) - return( -1 ); - content[ len ] = rec_type; - len++; - remaining--; - - if( remaining < pad ) - return( -1 ); - memset( content + len, 0, pad ); - len += pad; - remaining -= pad; - - *content_size = len; - return( 0 ); -} - -/* This function parses a DTLSInnerPlaintext structure. - * See ssl_cid_build_inner_plaintext() for details. */ -static int ssl_cid_parse_inner_plaintext( unsigned char const *content, - size_t *content_size, - uint8_t *rec_type ) -{ - size_t remaining = *content_size; - - /* Determine length of padding by skipping zeroes from the back. */ - do - { - if( remaining == 0 ) - return( -1 ); - remaining--; - } while( content[ remaining ] == 0 ); - - *content_size = remaining; - *rec_type = content[ remaining ]; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - -/* `add_data` must have size 13 Bytes if the CID extension is disabled, - * and 13 + 1 + CID-length Bytes if the CID extension is enabled. */ -static void ssl_extract_add_data_from_record( unsigned char* add_data, - size_t *add_data_len, - mbedtls_record *rec ) -{ - /* Quoting RFC 5246 (TLS 1.2): - * - * additional_data = seq_num + TLSCompressed.type + - * TLSCompressed.version + TLSCompressed.length; - * - * For the CID extension, this is extended as follows - * (quoting draft-ietf-tls-dtls-connection-id-05, - * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05): - * - * additional_data = seq_num + DTLSPlaintext.type + - * DTLSPlaintext.version + - * cid + - * cid_length + - * length_of_DTLSInnerPlaintext; - */ - - memcpy( add_data, rec->ctr, sizeof( rec->ctr ) ); - add_data[8] = rec->type; - memcpy( add_data + 9, rec->ver, sizeof( rec->ver ) ); - -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - if( rec->cid_len != 0 ) - { - memcpy( add_data + 11, rec->cid, rec->cid_len ); - add_data[11 + rec->cid_len + 0] = rec->cid_len; - add_data[11 + rec->cid_len + 1] = ( rec->data_len >> 8 ) & 0xFF; - add_data[11 + rec->cid_len + 2] = ( rec->data_len >> 0 ) & 0xFF; - *add_data_len = 13 + 1 + rec->cid_len; - } - else -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - { - add_data[11 + 0] = ( rec->data_len >> 8 ) & 0xFF; - add_data[11 + 1] = ( rec->data_len >> 0 ) & 0xFF; - *add_data_len = 13; - } -} - -int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl, - mbedtls_ssl_transform *transform, - mbedtls_record *rec, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - mbedtls_cipher_mode_t mode; - int auth_done = 0; - unsigned char * data; - unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_OUT_LEN_MAX ]; - size_t add_data_len; - size_t post_avail; - - /* The SSL context is only used for debugging purposes! */ -#if !defined(MBEDTLS_DEBUG_C) - ssl = NULL; /* make sure we don't use it except for debug */ - ((void) ssl); -#endif - - /* The PRNG is used for dynamic IV generation that's used - * for CBC transformations in TLS 1.1 and TLS 1.2. */ -#if !( defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || \ - defined(MBEDTLS_ARIA_C) || \ - defined(MBEDTLS_CAMELLIA_C) ) && \ - ( defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) ) ) - ((void) f_rng); - ((void) p_rng); -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); - - if( transform == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "no transform provided to encrypt_buf" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - if( rec == NULL - || rec->buf == NULL - || rec->buf_len < rec->data_offset - || rec->buf_len - rec->data_offset < rec->data_len -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - || rec->cid_len != 0 -#endif - ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to encrypt_buf" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - data = rec->buf + rec->data_offset; - post_avail = rec->buf_len - ( rec->data_len + rec->data_offset ); - MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload", - data, rec->data_len ); - - mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ); - - if( rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d", - (unsigned) rec->data_len, - MBEDTLS_SSL_OUT_CONTENT_LEN ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - /* - * Add CID information - */ - rec->cid_len = transform->out_cid_len; - memcpy( rec->cid, transform->out_cid, transform->out_cid_len ); - MBEDTLS_SSL_DEBUG_BUF( 3, "CID", rec->cid, rec->cid_len ); - - if( rec->cid_len != 0 ) - { - /* - * Wrap plaintext into DTLSInnerPlaintext structure. - * See ssl_cid_build_inner_plaintext() for more information. - * - * Note that this changes `rec->data_len`, and hence - * `post_avail` needs to be recalculated afterwards. - */ - if( ssl_cid_build_inner_plaintext( data, - &rec->data_len, - post_avail, - rec->type ) != 0 ) - { - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } - - rec->type = MBEDTLS_SSL_MSG_CID; - } -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - - post_avail = rec->buf_len - ( rec->data_len + rec->data_offset ); - - /* - * Add MAC before if needed - */ -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) - if( mode == MBEDTLS_MODE_STREAM || - ( mode == MBEDTLS_MODE_CBC -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - && transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED -#endif - ) ) - { - if( post_avail < transform->maclen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - unsigned char mac[SSL_MAC_MAX_BYTES]; - ssl_mac( &transform->md_ctx_enc, transform->mac_enc, - data, rec->data_len, rec->ctr, rec->type, mac ); - memcpy( data + rec->data_len, mac, transform->maclen ); - } - else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) - { - unsigned char mac[MBEDTLS_SSL_MAC_ADD]; - - ssl_extract_add_data_from_record( add_data, &add_data_len, rec ); - - mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data, - add_data_len ); - mbedtls_md_hmac_update( &transform->md_ctx_enc, - data, rec->data_len ); - mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac ); - mbedtls_md_hmac_reset( &transform->md_ctx_enc ); - - memcpy( data + rec->data_len, mac, transform->maclen ); - } - else -#endif - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", data + rec->data_len, - transform->maclen ); - - rec->data_len += transform->maclen; - post_avail -= transform->maclen; - auth_done++; - } -#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ - - /* - * Encrypt - */ -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) - if( mode == MBEDTLS_MODE_STREAM ) - { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t olen; - MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " - "including %d bytes of padding", - rec->data_len, 0 ) ); - - if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc, - transform->iv_enc, transform->ivlen, - data, rec->data_len, - data, &olen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); - return( ret ); - } - - if( rec->data_len != olen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - else -#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ - -#if defined(MBEDTLS_GCM_C) || \ - defined(MBEDTLS_CCM_C) || \ - defined(MBEDTLS_CHACHAPOLY_C) - if( mode == MBEDTLS_MODE_GCM || - mode == MBEDTLS_MODE_CCM || - mode == MBEDTLS_MODE_CHACHAPOLY ) - { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char iv[12]; - size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen; - - /* Check that there's space for both the authentication tag - * and the explicit IV before and after the record content. */ - if( post_avail < transform->taglen || - rec->data_offset < explicit_iv_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } - - /* - * Generate IV - */ - if( transform->ivlen == 12 && transform->fixed_ivlen == 4 ) - { - /* GCM and CCM: fixed || explicit (=seqnum) */ - memcpy( iv, transform->iv_enc, transform->fixed_ivlen ); - memcpy( iv + transform->fixed_ivlen, rec->ctr, - explicit_iv_len ); - /* Prefix record content with explicit IV. */ - memcpy( data - explicit_iv_len, rec->ctr, explicit_iv_len ); - } - else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 ) - { - /* ChachaPoly: fixed XOR sequence number */ - unsigned char i; - - memcpy( iv, transform->iv_enc, transform->fixed_ivlen ); - - for( i = 0; i < 8; i++ ) - iv[i+4] ^= rec->ctr[i]; - } - else - { - /* Reminder if we ever add an AEAD mode with a different size */ - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - ssl_extract_add_data_from_record( add_data, &add_data_len, rec ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)", - iv, transform->ivlen ); - MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)", - data - explicit_iv_len, explicit_iv_len ); - MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", - add_data, add_data_len ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " - "including 0 bytes of padding", - rec->data_len ) ); - - /* - * Encrypt and authenticate - */ - - if( ( ret = mbedtls_cipher_auth_encrypt( &transform->cipher_ctx_enc, - iv, transform->ivlen, - add_data, add_data_len, /* add data */ - data, rec->data_len, /* source */ - data, &rec->data_len, /* destination */ - data + rec->data_len, transform->taglen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag", - data + rec->data_len, transform->taglen ); - - rec->data_len += transform->taglen + explicit_iv_len; - rec->data_offset -= explicit_iv_len; - post_avail -= transform->taglen; - auth_done++; - } - else -#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ -#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) ) - if( mode == MBEDTLS_MODE_CBC ) - { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t padlen, i; - size_t olen; - - /* Currently we're always using minimal padding - * (up to 255 bytes would be allowed). */ - padlen = transform->ivlen - ( rec->data_len + 1 ) % transform->ivlen; - if( padlen == transform->ivlen ) - padlen = 0; - - /* Check there's enough space in the buffer for the padding. */ - if( post_avail < padlen + 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } - - for( i = 0; i <= padlen; i++ ) - data[rec->data_len + i] = (unsigned char) padlen; - - rec->data_len += padlen + 1; - post_avail -= padlen + 1; - -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) - /* - * Prepend per-record IV for block cipher in TLS v1.1 and up as per - * Method 1 (6.2.3.2. in RFC4346 and RFC5246) - */ - if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - if( f_rng == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "No PRNG provided to encrypt_record routine" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - if( rec->data_offset < transform->ivlen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } - - /* - * Generate IV - */ - ret = f_rng( p_rng, transform->iv_enc, transform->ivlen ); - if( ret != 0 ) - return( ret ); - - memcpy( data - transform->ivlen, transform->iv_enc, - transform->ivlen ); - - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " - "including %d bytes of IV and %d bytes of padding", - rec->data_len, transform->ivlen, - padlen + 1 ) ); - - if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc, - transform->iv_enc, - transform->ivlen, - data, rec->data_len, - data, &olen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); - return( ret ); - } - - if( rec->data_len != olen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) - if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) - { - /* - * Save IV in SSL3 and TLS1 - */ - memcpy( transform->iv_enc, transform->cipher_ctx_enc.iv, - transform->ivlen ); - } - else -#endif - { - data -= transform->ivlen; - rec->data_offset -= transform->ivlen; - rec->data_len += transform->ivlen; - } - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - if( auth_done == 0 ) - { - unsigned char mac[MBEDTLS_SSL_MAC_ADD]; - - /* - * MAC(MAC_write_key, seq_num + - * TLSCipherText.type + - * TLSCipherText.version + - * length_of( (IV +) ENC(...) ) + - * IV + // except for TLS 1.0 - * ENC(content + padding + padding_length)); - */ - - if( post_avail < transform->maclen) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } - - ssl_extract_add_data_from_record( add_data, &add_data_len, rec ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); - MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data, - add_data_len ); - - mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data, - add_data_len ); - mbedtls_md_hmac_update( &transform->md_ctx_enc, - data, rec->data_len ); - mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac ); - mbedtls_md_hmac_reset( &transform->md_ctx_enc ); - - memcpy( data + rec->data_len, mac, transform->maclen ); - - rec->data_len += transform->maclen; - post_avail -= transform->maclen; - auth_done++; - } -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - } - else -#endif /* MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* Make extra sure authentication was performed, exactly once */ - if( auth_done != 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); - - return( 0 ); -} - -int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, - mbedtls_ssl_transform *transform, - mbedtls_record *rec ) -{ - size_t olen; - mbedtls_cipher_mode_t mode; - int ret, auth_done = 0; -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) - size_t padlen = 0, correct = 1; -#endif - unsigned char* data; - unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_IN_LEN_MAX ]; - size_t add_data_len; - -#if !defined(MBEDTLS_DEBUG_C) - ssl = NULL; /* make sure we don't use it except for debug */ - ((void) ssl); -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) ); - if( rec == NULL || - rec->buf == NULL || - rec->buf_len < rec->data_offset || - rec->buf_len - rec->data_offset < rec->data_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to decrypt_buf" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - data = rec->buf + rec->data_offset; - mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_dec ); - -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - /* - * Match record's CID with incoming CID. - */ - if( rec->cid_len != transform->in_cid_len || - memcmp( rec->cid, transform->in_cid, rec->cid_len ) != 0 ) - { - return( MBEDTLS_ERR_SSL_UNEXPECTED_CID ); - } -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) - if( mode == MBEDTLS_MODE_STREAM ) - { - padlen = 0; - if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec, - transform->iv_dec, - transform->ivlen, - data, rec->data_len, - data, &olen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); - return( ret ); - } - - if( rec->data_len != olen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - else -#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ -#if defined(MBEDTLS_GCM_C) || \ - defined(MBEDTLS_CCM_C) || \ - defined(MBEDTLS_CHACHAPOLY_C) - if( mode == MBEDTLS_MODE_GCM || - mode == MBEDTLS_MODE_CCM || - mode == MBEDTLS_MODE_CHACHAPOLY ) - { - unsigned char iv[12]; - size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen; - - /* - * Prepare IV from explicit and implicit data. - */ - - /* Check that there's enough space for the explicit IV - * (at the beginning of the record) and the MAC (at the - * end of the record). */ - if( rec->data_len < explicit_iv_len + transform->taglen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) " - "+ taglen (%d)", rec->data_len, - explicit_iv_len, transform->taglen ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - -#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) - if( transform->ivlen == 12 && transform->fixed_ivlen == 4 ) - { - /* GCM and CCM: fixed || explicit */ - - /* Fixed */ - memcpy( iv, transform->iv_dec, transform->fixed_ivlen ); - /* Explicit */ - memcpy( iv + transform->fixed_ivlen, data, 8 ); - } - else -#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ -#if defined(MBEDTLS_CHACHAPOLY_C) - if( transform->ivlen == 12 && transform->fixed_ivlen == 12 ) - { - /* ChachaPoly: fixed XOR sequence number */ - unsigned char i; - - memcpy( iv, transform->iv_dec, transform->fixed_ivlen ); - - for( i = 0; i < 8; i++ ) - iv[i+4] ^= rec->ctr[i]; - } - else -#endif /* MBEDTLS_CHACHAPOLY_C */ - { - /* Reminder if we ever add an AEAD mode with a different size */ - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* Group changes to data, data_len, and add_data, because - * add_data depends on data_len. */ - data += explicit_iv_len; - rec->data_offset += explicit_iv_len; - rec->data_len -= explicit_iv_len + transform->taglen; - - ssl_extract_add_data_from_record( add_data, &add_data_len, rec ); - MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", - add_data, add_data_len ); - - /* Because of the check above, we know that there are - * explicit_iv_len Bytes preceeding data, and taglen - * bytes following data + data_len. This justifies - * the debug message and the invocation of - * mbedtls_cipher_auth_decrypt() below. */ - - MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen ); - MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", data + rec->data_len, - transform->taglen ); - - /* - * Decrypt and authenticate - */ - if( ( ret = mbedtls_cipher_auth_decrypt( &transform->cipher_ctx_dec, - iv, transform->ivlen, - add_data, add_data_len, - data, rec->data_len, - data, &olen, - data + rec->data_len, - transform->taglen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt", ret ); - - if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - - return( ret ); - } - auth_done++; - - /* Double-check that AEAD decryption doesn't change content length. */ - if( olen != rec->data_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - else -#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ -#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) ) - if( mode == MBEDTLS_MODE_CBC ) - { - size_t minlen = 0; - - /* - * Check immediate ciphertext sanity - */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - /* The ciphertext is prefixed with the CBC IV. */ - minlen += transform->ivlen; - } -#endif - - /* Size considerations: - * - * - The CBC cipher text must not be empty and hence - * at least of size transform->ivlen. - * - * Together with the potential IV-prefix, this explains - * the first of the two checks below. - * - * - The record must contain a MAC, either in plain or - * encrypted, depending on whether Encrypt-then-MAC - * is used or not. - * - If it is, the message contains the IV-prefix, - * the CBC ciphertext, and the MAC. - * - If it is not, the padded plaintext, and hence - * the CBC ciphertext, has at least length maclen + 1 - * because there is at least the padding length byte. - * - * As the CBC ciphertext is not empty, both cases give the - * lower bound minlen + maclen + 1 on the record size, which - * we test for in the second check below. - */ - if( rec->data_len < minlen + transform->ivlen || - rec->data_len < minlen + transform->maclen + 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) " - "+ 1 ) ( + expl IV )", rec->data_len, - transform->ivlen, - transform->maclen ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - - /* - * Authenticate before decrypt if enabled - */ -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - if( transform->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) - { - unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); - - /* Update data_len in tandem with add_data. - * - * The subtraction is safe because of the previous check - * data_len >= minlen + maclen + 1. - * - * Afterwards, we know that data + data_len is followed by at - * least maclen Bytes, which justifies the call to - * mbedtls_ssl_safer_memcmp() below. - * - * Further, we still know that data_len > minlen */ - rec->data_len -= transform->maclen; - ssl_extract_add_data_from_record( add_data, &add_data_len, rec ); - - /* Calculate expected MAC. */ - MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data, - add_data_len ); - mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data, - add_data_len ); - mbedtls_md_hmac_update( &transform->md_ctx_dec, - data, rec->data_len ); - mbedtls_md_hmac_finish( &transform->md_ctx_dec, mac_expect ); - mbedtls_md_hmac_reset( &transform->md_ctx_dec ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", data + rec->data_len, - transform->maclen ); - MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, - transform->maclen ); - - /* Compare expected MAC with MAC at the end of the record. */ - if( mbedtls_ssl_safer_memcmp( data + rec->data_len, mac_expect, - transform->maclen ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - auth_done++; - } -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - - /* - * Check length sanity - */ - - /* We know from above that data_len > minlen >= 0, - * so the following check in particular implies that - * data_len >= minlen + ivlen ( = minlen or 2 * minlen ). */ - if( rec->data_len % transform->ivlen != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0", - rec->data_len, transform->ivlen ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) - /* - * Initialize for prepended IV for block cipher in TLS v1.1 and up - */ - if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */ - memcpy( transform->iv_dec, data, transform->ivlen ); - - data += transform->ivlen; - rec->data_offset += transform->ivlen; - rec->data_len -= transform->ivlen; - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ - - /* We still have data_len % ivlen == 0 and data_len >= ivlen here. */ - - if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec, - transform->iv_dec, transform->ivlen, - data, rec->data_len, data, &olen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); - return( ret ); - } - - /* Double-check that length hasn't changed during decryption. */ - if( rec->data_len != olen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) - if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) - { - /* - * Save IV in SSL3 and TLS1, where CBC decryption of consecutive - * records is equivalent to CBC decryption of the concatenation - * of the records; in other words, IVs are maintained across - * record decryptions. - */ - memcpy( transform->iv_dec, transform->cipher_ctx_dec.iv, - transform->ivlen ); - } -#endif - - /* Safe since data_len >= minlen + maclen + 1, so after having - * subtracted at most minlen and maclen up to this point, - * data_len > 0 (because of data_len % ivlen == 0, it's actually - * >= ivlen ). */ - padlen = data[rec->data_len - 1]; - - if( auth_done == 1 ) - { - correct *= ( rec->data_len >= padlen + 1 ); - padlen *= ( rec->data_len >= padlen + 1 ); - } - else - { -#if defined(MBEDTLS_SSL_DEBUG_ALL) - if( rec->data_len < transform->maclen + padlen + 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)", - rec->data_len, - transform->maclen, - padlen + 1 ) ); - } -#endif - - correct *= ( rec->data_len >= transform->maclen + padlen + 1 ); - padlen *= ( rec->data_len >= transform->maclen + padlen + 1 ); - } - - padlen++; - - /* Regardless of the validity of the padding, - * we have data_len >= padlen here. */ - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - if( padlen > transform->ivlen ) - { -#if defined(MBEDTLS_SSL_DEBUG_ALL) - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, " - "should be no more than %d", - padlen, transform->ivlen ) ); -#endif - correct = 0; - } - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) - { - /* The padding check involves a series of up to 256 - * consecutive memory reads at the end of the record - * plaintext buffer. In order to hide the length and - * validity of the padding, always perform exactly - * `min(256,plaintext_len)` reads (but take into account - * only the last `padlen` bytes for the padding check). */ - size_t pad_count = 0; - size_t real_count = 0; - volatile unsigned char* const check = data; - - /* Index of first padding byte; it has been ensured above - * that the subtraction is safe. */ - size_t const padding_idx = rec->data_len - padlen; - size_t const num_checks = rec->data_len <= 256 ? rec->data_len : 256; - size_t const start_idx = rec->data_len - num_checks; - size_t idx; - - for( idx = start_idx; idx < rec->data_len; idx++ ) - { - real_count |= ( idx >= padding_idx ); - pad_count += real_count * ( check[idx] == padlen - 1 ); - } - correct &= ( pad_count == padlen ); - -#if defined(MBEDTLS_SSL_DEBUG_ALL) - if( padlen > 0 && correct == 0 ) - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) ); -#endif - padlen &= correct * 0x1FF; - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* If the padding was found to be invalid, padlen == 0 - * and the subtraction is safe. If the padding was found valid, - * padlen hasn't been changed and the previous assertion - * data_len >= padlen still holds. */ - rec->data_len -= padlen; - } - else -#endif /* MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - -#if defined(MBEDTLS_SSL_DEBUG_ALL) - MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", - data, rec->data_len ); -#endif - - /* - * Authenticate if not done yet. - * Compute the MAC regardless of the padding result (RFC4346, CBCTIME). - */ -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) - if( auth_done == 0 ) - { - unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; - - /* If the initial value of padlen was such that - * data_len < maclen + padlen + 1, then padlen - * got reset to 1, and the initial check - * data_len >= minlen + maclen + 1 - * guarantees that at this point we still - * have at least data_len >= maclen. - * - * If the initial value of padlen was such that - * data_len >= maclen + padlen + 1, then we have - * subtracted either padlen + 1 (if the padding was correct) - * or 0 (if the padding was incorrect) since then, - * hence data_len >= maclen in any case. - */ - rec->data_len -= transform->maclen; - ssl_extract_add_data_from_record( add_data, &add_data_len, rec ); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - ssl_mac( &transform->md_ctx_dec, - transform->mac_dec, - data, rec->data_len, - rec->ctr, rec->type, - mac_expect ); - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) - { - /* - * Process MAC and always update for padlen afterwards to make - * total time independent of padlen. - * - * Known timing attacks: - * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf) - * - * To compensate for different timings for the MAC calculation - * depending on how much padding was removed (which is determined - * by padlen), process extra_run more blocks through the hash - * function. - * - * The formula in the paper is - * extra_run = ceil( (L1-55) / 64 ) - ceil( (L2-55) / 64 ) - * where L1 is the size of the header plus the decrypted message - * plus CBC padding and L2 is the size of the header plus the - * decrypted message. This is for an underlying hash function - * with 64-byte blocks. - * We use ( (Lx+8) / 64 ) to handle 'negative Lx' values - * correctly. We round down instead of up, so -56 is the correct - * value for our calculations instead of -55. - * - * Repeat the formula rather than defining a block_size variable. - * This avoids requiring division by a variable at runtime - * (which would be marginally less efficient and would require - * linking an extra division function in some builds). - */ - size_t j, extra_run = 0; - unsigned char tmp[MBEDTLS_MD_MAX_BLOCK_SIZE]; - - /* - * The next two sizes are the minimum and maximum values of - * in_msglen over all padlen values. - * - * They're independent of padlen, since we previously did - * data_len -= padlen. - * - * Note that max_len + maclen is never more than the buffer - * length, as we previously did in_msglen -= maclen too. - */ - const size_t max_len = rec->data_len + padlen; - const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0; - - memset( tmp, 0, sizeof( tmp ) ); - - switch( mbedtls_md_get_type( transform->md_ctx_dec.md_info ) ) - { -#if defined(MBEDTLS_MD5_C) || defined(MBEDTLS_SHA1_C) || \ - defined(MBEDTLS_SHA256_C) - case MBEDTLS_MD_MD5: - case MBEDTLS_MD_SHA1: - case MBEDTLS_MD_SHA256: - /* 8 bytes of message size, 64-byte compression blocks */ - extra_run = - ( add_data_len + rec->data_len + padlen + 8 ) / 64 - - ( add_data_len + rec->data_len + 8 ) / 64; - break; -#endif -#if defined(MBEDTLS_SHA512_C) - case MBEDTLS_MD_SHA384: - /* 16 bytes of message size, 128-byte compression blocks */ - extra_run = - ( add_data_len + rec->data_len + padlen + 16 ) / 128 - - ( add_data_len + rec->data_len + 16 ) / 128; - break; -#endif - default: - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - extra_run &= correct * 0xFF; - - mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data, - add_data_len ); - mbedtls_md_hmac_update( &transform->md_ctx_dec, data, - rec->data_len ); - /* Make sure we access everything even when padlen > 0. This - * makes the synchronisation requirements for just-in-time - * Prime+Probe attacks much tighter and hopefully impractical. */ - ssl_read_memory( data + rec->data_len, padlen ); - mbedtls_md_hmac_finish( &transform->md_ctx_dec, mac_expect ); - - /* Call mbedtls_md_process at least once due to cache attacks - * that observe whether md_process() was called of not */ - for( j = 0; j < extra_run + 1; j++ ) - mbedtls_md_process( &transform->md_ctx_dec, tmp ); - - mbedtls_md_hmac_reset( &transform->md_ctx_dec ); - - /* Make sure we access all the memory that could contain the MAC, - * before we check it in the next code block. This makes the - * synchronisation requirements for just-in-time Prime+Probe - * attacks much tighter and hopefully impractical. */ - ssl_read_memory( data + min_len, - max_len - min_len + transform->maclen ); - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - -#if defined(MBEDTLS_SSL_DEBUG_ALL) - MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, transform->maclen ); - MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", data + rec->data_len, transform->maclen ); -#endif - - if( mbedtls_ssl_safer_memcmp( data + rec->data_len, mac_expect, - transform->maclen ) != 0 ) - { -#if defined(MBEDTLS_SSL_DEBUG_ALL) - MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); -#endif - correct = 0; - } - auth_done++; - } - - /* - * Finally check the correct flag - */ - if( correct == 0 ) - return( MBEDTLS_ERR_SSL_INVALID_MAC ); -#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ - - /* Make extra sure authentication was performed, exactly once */ - if( auth_done != 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - if( rec->cid_len != 0 ) - { - ret = ssl_cid_parse_inner_plaintext( data, &rec->data_len, - &rec->type ); - if( ret != 0 ) - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) ); - - return( 0 ); -} - -#undef MAC_NONE -#undef MAC_PLAINTEXT -#undef MAC_CIPHERTEXT - -#if defined(MBEDTLS_ZLIB_SUPPORT) -/* - * Compression/decompression functions - */ -static int ssl_compress_buf( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char *msg_post = ssl->out_msg; - ptrdiff_t bytes_written = ssl->out_msg - ssl->out_buf; - size_t len_pre = ssl->out_msglen; - unsigned char *msg_pre = ssl->compress_buf; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> compress buf" ) ); - - if( len_pre == 0 ) - return( 0 ); - - memcpy( msg_pre, ssl->out_msg, len_pre ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ", - ssl->out_msglen ) ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload", - ssl->out_msg, ssl->out_msglen ); - - ssl->transform_out->ctx_deflate.next_in = msg_pre; - ssl->transform_out->ctx_deflate.avail_in = len_pre; - ssl->transform_out->ctx_deflate.next_out = msg_post; - ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_OUT_BUFFER_LEN - bytes_written; - - ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); - if( ret != Z_OK ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) ); - return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); - } - - ssl->out_msglen = MBEDTLS_SSL_OUT_BUFFER_LEN - - ssl->transform_out->ctx_deflate.avail_out - bytes_written; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ", - ssl->out_msglen ) ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload", - ssl->out_msg, ssl->out_msglen ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= compress buf" ) ); - - return( 0 ); -} - -static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char *msg_post = ssl->in_msg; - ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf; - size_t len_pre = ssl->in_msglen; - unsigned char *msg_pre = ssl->compress_buf; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) ); - - if( len_pre == 0 ) - return( 0 ); - - memcpy( msg_pre, ssl->in_msg, len_pre ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ", - ssl->in_msglen ) ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload", - ssl->in_msg, ssl->in_msglen ); - - ssl->transform_in->ctx_inflate.next_in = msg_pre; - ssl->transform_in->ctx_inflate.avail_in = len_pre; - ssl->transform_in->ctx_inflate.next_out = msg_post; - ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_IN_BUFFER_LEN - - header_bytes; - - ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); - if( ret != Z_OK ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) ); - return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); - } - - ssl->in_msglen = MBEDTLS_SSL_IN_BUFFER_LEN - - ssl->transform_in->ctx_inflate.avail_out - header_bytes; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ", - ssl->in_msglen ) ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload", - ssl->in_msg, ssl->in_msglen ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_ZLIB_SUPPORT */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) static int ssl_write_hello_request( mbedtls_ssl_context *ssl ); #if defined(MBEDTLS_SSL_PROTO_DTLS) -static int ssl_resend_hello_request( mbedtls_ssl_context *ssl ) +int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl ) { /* If renegotiation is not enforced, retransmit until we would reach max * timeout if we were using the usual handshake doubling scheme */ @@ -3588,3058 +2000,6 @@ static int ssl_resend_hello_request( mbedtls_ssl_context *ssl ) #endif #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ -/* - * Fill the input message buffer by appending data to it. - * The amount of data already fetched is in ssl->in_left. - * - * If we return 0, is it guaranteed that (at least) nb_want bytes are - * available (from this read and/or a previous one). Otherwise, an error code - * is returned (possibly EOF or WANT_READ). - * - * With stream transport (TLS) on success ssl->in_left == nb_want, but - * with datagram transport (DTLS) on success ssl->in_left >= nb_want, - * since we always read a whole datagram at once. - * - * For DTLS, it is up to the caller to set ssl->next_record_offset when - * they're done reading a record. - */ -int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) ); - - if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " - "or mbedtls_ssl_set_bio()" ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - if( nb_want > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - uint32_t timeout; - - /* Just to be sure */ - if( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use " - "mbedtls_ssl_set_timer_cb() for DTLS" ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - /* - * The point is, we need to always read a full datagram at once, so we - * sometimes read more then requested, and handle the additional data. - * It could be the rest of the current record (while fetching the - * header) and/or some other records in the same datagram. - */ - - /* - * Move to the next record in the already read datagram if applicable - */ - if( ssl->next_record_offset != 0 ) - { - if( ssl->in_left < ssl->next_record_offset ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - ssl->in_left -= ssl->next_record_offset; - - if( ssl->in_left != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %d", - ssl->next_record_offset ) ); - memmove( ssl->in_hdr, - ssl->in_hdr + ssl->next_record_offset, - ssl->in_left ); - } - - ssl->next_record_offset = 0; - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", - ssl->in_left, nb_want ) ); - - /* - * Done if we already have enough data. - */ - if( nb_want <= ssl->in_left) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); - return( 0 ); - } - - /* - * A record can't be split across datagrams. If we need to read but - * are not at the beginning of a new record, the caller did something - * wrong. - */ - if( ssl->in_left != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* - * Don't even try to read if time's out already. - * This avoids by-passing the timer when repeatedly receiving messages - * that will end up being dropped. - */ - if( ssl_check_timer( ssl ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) ); - ret = MBEDTLS_ERR_SSL_TIMEOUT; - } - else - { - len = MBEDTLS_SSL_IN_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf ); - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - timeout = ssl->handshake->retransmit_timeout; - else - timeout = ssl->conf->read_timeout; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %u ms", timeout ) ); - - if( ssl->f_recv_timeout != NULL ) - ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len, - timeout ); - else - ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len ); - - MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); - - if( ret == 0 ) - return( MBEDTLS_ERR_SSL_CONN_EOF ); - } - - if( ret == MBEDTLS_ERR_SSL_TIMEOUT ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) ); - ssl_set_timer( ssl, 0 ); - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - { - if( ssl_double_retransmit_timeout( ssl ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) ); - return( MBEDTLS_ERR_SSL_TIMEOUT ); - } - - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); - return( ret ); - } - - return( MBEDTLS_ERR_SSL_WANT_READ ); - } -#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) - else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) - { - if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret ); - return( ret ); - } - - return( MBEDTLS_ERR_SSL_WANT_READ ); - } -#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ - } - - if( ret < 0 ) - return( ret ); - - ssl->in_left = ret; - } - else -#endif - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", - ssl->in_left, nb_want ) ); - - while( ssl->in_left < nb_want ) - { - len = nb_want - ssl->in_left; - - if( ssl_check_timer( ssl ) != 0 ) - ret = MBEDTLS_ERR_SSL_TIMEOUT; - else - { - if( ssl->f_recv_timeout != NULL ) - { - ret = ssl->f_recv_timeout( ssl->p_bio, - ssl->in_hdr + ssl->in_left, len, - ssl->conf->read_timeout ); - } - else - { - ret = ssl->f_recv( ssl->p_bio, - ssl->in_hdr + ssl->in_left, len ); - } - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", - ssl->in_left, nb_want ) ); - MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); - - if( ret == 0 ) - return( MBEDTLS_ERR_SSL_CONN_EOF ); - - if( ret < 0 ) - return( ret ); - - if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > SIZE_MAX ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, - ( "f_recv returned %d bytes but only %lu were requested", - ret, (unsigned long)len ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - ssl->in_left += ret; - } - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); - - return( 0 ); -} - -/* - * Flush any data not yet written - */ -int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char *buf; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); - - if( ssl->f_send == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " - "or mbedtls_ssl_set_bio()" ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - /* Avoid incrementing counter if data is flushed */ - if( ssl->out_left == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); - return( 0 ); - } - - while( ssl->out_left > 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d", - mbedtls_ssl_out_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) ); - - buf = ssl->out_hdr - ssl->out_left; - ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left ); - - MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret ); - - if( ret <= 0 ) - return( ret ); - - if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > SIZE_MAX ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, - ( "f_send returned %d bytes but only %lu bytes were sent", - ret, (unsigned long)ssl->out_left ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - ssl->out_left -= ret; - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - ssl->out_hdr = ssl->out_buf; - } - else -#endif - { - ssl->out_hdr = ssl->out_buf + 8; - } - ssl_update_out_pointers( ssl, ssl->transform_out ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); - - return( 0 ); -} - -/* - * Functions to handle the DTLS retransmission state machine - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) -/* - * Append current handshake message to current outgoing flight - */ -static int ssl_flight_append( mbedtls_ssl_context *ssl ) -{ - mbedtls_ssl_flight_item *msg; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) ); - MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight", - ssl->out_msg, ssl->out_msglen ); - - /* Allocate space for current message */ - if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", - sizeof( mbedtls_ssl_flight_item ) ) ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", ssl->out_msglen ) ); - mbedtls_free( msg ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - /* Copy current handshake message with headers */ - memcpy( msg->p, ssl->out_msg, ssl->out_msglen ); - msg->len = ssl->out_msglen; - msg->type = ssl->out_msgtype; - msg->next = NULL; - - /* Append to the current flight */ - if( ssl->handshake->flight == NULL ) - ssl->handshake->flight = msg; - else - { - mbedtls_ssl_flight_item *cur = ssl->handshake->flight; - while( cur->next != NULL ) - cur = cur->next; - cur->next = msg; - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) ); - return( 0 ); -} - -/* - * Free the current flight of handshake messages - */ -static void ssl_flight_free( mbedtls_ssl_flight_item *flight ) -{ - mbedtls_ssl_flight_item *cur = flight; - mbedtls_ssl_flight_item *next; - - while( cur != NULL ) - { - next = cur->next; - - mbedtls_free( cur->p ); - mbedtls_free( cur ); - - cur = next; - } -} - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ); -#endif - -/* - * Swap transform_out and out_ctr with the alternative ones - */ -static void ssl_swap_epochs( mbedtls_ssl_context *ssl ) -{ - mbedtls_ssl_transform *tmp_transform; - unsigned char tmp_out_ctr[8]; - - if( ssl->transform_out == ssl->handshake->alt_transform_out ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) ); - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) ); - - /* Swap transforms */ - tmp_transform = ssl->transform_out; - ssl->transform_out = ssl->handshake->alt_transform_out; - ssl->handshake->alt_transform_out = tmp_transform; - - /* Swap epoch + sequence_number */ - memcpy( tmp_out_ctr, ssl->cur_out_ctr, 8 ); - memcpy( ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, 8 ); - memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 ); - - /* Adjust to the newly activated transform */ - ssl_update_out_pointers( ssl, ssl->transform_out ); - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_activate != NULL ) - { - if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - } -#endif -} - -/* - * Retransmit the current flight of messages. - */ -int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) -{ - int ret = 0; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); - - ret = mbedtls_ssl_flight_transmit( ssl ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) ); - - return( ret ); -} - -/* - * Transmit or retransmit the current flight of messages. - * - * Need to remember the current message in case flush_output returns - * WANT_WRITE, causing us to exit this function and come back later. - * This function must be called until state is no longer SENDING. - */ -int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) ); - - if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) ); - - ssl->handshake->cur_msg = ssl->handshake->flight; - ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12; - ssl_swap_epochs( ssl ); - - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; - } - - while( ssl->handshake->cur_msg != NULL ) - { - size_t max_frag_len; - const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg; - - int const is_finished = - ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && - cur->p[0] == MBEDTLS_SSL_HS_FINISHED ); - - uint8_t const force_flush = ssl->disable_datagram_packing == 1 ? - SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH; - - /* Swap epochs before sending Finished: we can't do it after - * sending ChangeCipherSpec, in case write returns WANT_READ. - * Must be done before copying, may change out_msg pointer */ - if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) ); - ssl_swap_epochs( ssl ); - } - - ret = ssl_get_remaining_payload_in_datagram( ssl ); - if( ret < 0 ) - return( ret ); - max_frag_len = (size_t) ret; - - /* CCS is copied as is, while HS messages may need fragmentation */ - if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) - { - if( max_frag_len == 0 ) - { - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - return( ret ); - - continue; - } - - memcpy( ssl->out_msg, cur->p, cur->len ); - ssl->out_msglen = cur->len; - ssl->out_msgtype = cur->type; - - /* Update position inside current message */ - ssl->handshake->cur_msg_p += cur->len; - } - else - { - const unsigned char * const p = ssl->handshake->cur_msg_p; - const size_t hs_len = cur->len - 12; - const size_t frag_off = p - ( cur->p + 12 ); - const size_t rem_len = hs_len - frag_off; - size_t cur_hs_frag_len, max_hs_frag_len; - - if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) ) - { - if( is_finished ) - ssl_swap_epochs( ssl ); - - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - return( ret ); - - continue; - } - max_hs_frag_len = max_frag_len - 12; - - cur_hs_frag_len = rem_len > max_hs_frag_len ? - max_hs_frag_len : rem_len; - - if( frag_off == 0 && cur_hs_frag_len != hs_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)", - (unsigned) cur_hs_frag_len, - (unsigned) max_hs_frag_len ) ); - } - - /* Messages are stored with handshake headers as if not fragmented, - * copy beginning of headers then fill fragmentation fields. - * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */ - memcpy( ssl->out_msg, cur->p, 6 ); - - ssl->out_msg[6] = ( ( frag_off >> 16 ) & 0xff ); - ssl->out_msg[7] = ( ( frag_off >> 8 ) & 0xff ); - ssl->out_msg[8] = ( ( frag_off ) & 0xff ); - - ssl->out_msg[ 9] = ( ( cur_hs_frag_len >> 16 ) & 0xff ); - ssl->out_msg[10] = ( ( cur_hs_frag_len >> 8 ) & 0xff ); - ssl->out_msg[11] = ( ( cur_hs_frag_len ) & 0xff ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 ); - - /* Copy the handshake message content and set records fields */ - memcpy( ssl->out_msg + 12, p, cur_hs_frag_len ); - ssl->out_msglen = cur_hs_frag_len + 12; - ssl->out_msgtype = cur->type; - - /* Update position inside current message */ - ssl->handshake->cur_msg_p += cur_hs_frag_len; - } - - /* If done with the current message move to the next one if any */ - if( ssl->handshake->cur_msg_p >= cur->p + cur->len ) - { - if( cur->next != NULL ) - { - ssl->handshake->cur_msg = cur->next; - ssl->handshake->cur_msg_p = cur->next->p + 12; - } - else - { - ssl->handshake->cur_msg = NULL; - ssl->handshake->cur_msg_p = NULL; - } - } - - /* Actually send the message out */ - if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - } - - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - return( ret ); - - /* Update state and set timer */ - if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; - else - { - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; - ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) ); - - return( 0 ); -} - -/* - * To be called when the last message of an incoming flight is received. - */ -void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ) -{ - /* We won't need to resend that one any more */ - ssl_flight_free( ssl->handshake->flight ); - ssl->handshake->flight = NULL; - ssl->handshake->cur_msg = NULL; - - /* The next incoming flight will start with this msg_seq */ - ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq; - - /* We don't want to remember CCS's across flight boundaries. */ - ssl->handshake->buffering.seen_ccs = 0; - - /* Clear future message buffering structure. */ - ssl_buffering_free( ssl ); - - /* Cancel timer */ - ssl_set_timer( ssl, 0 ); - - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) - { - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; - } - else - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; -} - -/* - * To be called when the last message of an outgoing flight is send. - */ -void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ) -{ - ssl_reset_retransmit_timeout( ssl ); - ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); - - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) - { - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; - } - else - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; -} -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -/* - * Handshake layer functions - */ - -/* - * Write (DTLS: or queue) current handshake (including CCS) message. - * - * - fill in handshake headers - * - update handshake checksum - * - DTLS: save message for resending - * - then pass to the record layer - * - * DTLS: except for HelloRequest, messages are only queued, and will only be - * actually sent when calling flight_transmit() or resend(). - * - * Inputs: - * - ssl->out_msglen: 4 + actual handshake message len - * (4 is the size of handshake headers for TLS) - * - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc) - * - ssl->out_msg + 4: the handshake message body - * - * Outputs, ie state before passing to flight_append() or write_record(): - * - ssl->out_msglen: the length of the record contents - * (including handshake headers but excluding record headers) - * - ssl->out_msg: the record contents (handshake headers + content) - */ -int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const size_t hs_len = ssl->out_msglen - 4; - const unsigned char hs_type = ssl->out_msg[0]; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) ); - - /* - * Sanity checks - */ - if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) - { - /* In SSLv3, the client might send a NoCertificate alert. */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) - if( ! ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && - ssl->out_msgtype == MBEDTLS_SSL_MSG_ALERT && - ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) ) -#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - - /* Whenever we send anything different from a - * HelloRequest we should be in a handshake - double check. */ - if( ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) && - ssl->handshake == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake != NULL && - ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } -#endif - - /* Double-check that we did not exceed the bounds - * of the outgoing record buffer. - * This should never fail as the various message - * writing functions must obey the bounds of the - * outgoing record buffer, but better be safe. - * - * Note: We deliberately do not check for the MTU or MFL here. - */ - if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: " - "size %u, maximum %u", - (unsigned) ssl->out_msglen, - (unsigned) MBEDTLS_SSL_OUT_CONTENT_LEN ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* - * Fill handshake headers - */ - if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) - { - ssl->out_msg[1] = (unsigned char)( hs_len >> 16 ); - ssl->out_msg[2] = (unsigned char)( hs_len >> 8 ); - ssl->out_msg[3] = (unsigned char)( hs_len ); - - /* - * DTLS has additional fields in the Handshake layer, - * between the length field and the actual payload: - * uint16 message_seq; - * uint24 fragment_offset; - * uint24 fragment_length; - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - /* Make room for the additional DTLS fields */ - if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: " - "size %u, maximum %u", - (unsigned) ( hs_len ), - (unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len ); - ssl->out_msglen += 8; - - /* Write message_seq and update it, except for HelloRequest */ - if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) - { - ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF; - ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF; - ++( ssl->handshake->out_msg_seq ); - } - else - { - ssl->out_msg[4] = 0; - ssl->out_msg[5] = 0; - } - - /* Handshake hashes are computed without fragmentation, - * so set frag_offset = 0 and frag_len = hs_len for now */ - memset( ssl->out_msg + 6, 0x00, 3 ); - memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 ); - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - /* Update running hashes of handshake messages seen */ - if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) - ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen ); - } - - /* Either send now, or just save to be sent (and resent) later */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) ) - { - if( ( ret = ssl_flight_append( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret ); - return( ret ); - } - } - else -#endif - { - if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret ); - return( ret ); - } - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) ); - - return( 0 ); -} - -/* - * Record layer functions - */ - -/* - * Write current record. - * - * Uses: - * - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS) - * - ssl->out_msglen: length of the record content (excl headers) - * - ssl->out_msg: record content - */ -int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ) -{ - int ret, done = 0; - size_t len = ssl->out_msglen; - uint8_t flush = force_flush; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); - -#if defined(MBEDTLS_ZLIB_SUPPORT) - if( ssl->transform_out != NULL && - ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) - { - if( ( ret = ssl_compress_buf( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret ); - return( ret ); - } - - len = ssl->out_msglen; - } -#endif /*MBEDTLS_ZLIB_SUPPORT */ - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_write != NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) ); - - ret = mbedtls_ssl_hw_record_write( ssl ); - if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - - if( ret == 0 ) - done = 1; - } -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ - if( !done ) - { - unsigned i; - size_t protected_record_size; - - /* Skip writing the record content type to after the encryption, - * as it may change when using the CID extension. */ - - mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, - ssl->conf->transport, ssl->out_hdr + 1 ); - - memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 ); - ssl->out_len[0] = (unsigned char)( len >> 8 ); - ssl->out_len[1] = (unsigned char)( len ); - - if( ssl->transform_out != NULL ) - { - mbedtls_record rec; - - rec.buf = ssl->out_iv; - rec.buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - - ( ssl->out_iv - ssl->out_buf ); - rec.data_len = ssl->out_msglen; - rec.data_offset = ssl->out_msg - rec.buf; - - memcpy( &rec.ctr[0], ssl->out_ctr, 8 ); - mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, - ssl->conf->transport, rec.ver ); - rec.type = ssl->out_msgtype; - -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - /* The CID is set by mbedtls_ssl_encrypt_buf(). */ - rec.cid_len = 0; -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - - if( ( ret = mbedtls_ssl_encrypt_buf( ssl, ssl->transform_out, &rec, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret ); - return( ret ); - } - - if( rec.data_offset != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* Update the record content type and CID. */ - ssl->out_msgtype = rec.type; -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID ) - memcpy( ssl->out_cid, rec.cid, rec.cid_len ); -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - ssl->out_msglen = len = rec.data_len; - ssl->out_len[0] = (unsigned char)( rec.data_len >> 8 ); - ssl->out_len[1] = (unsigned char)( rec.data_len ); - } - - protected_record_size = len + mbedtls_ssl_out_hdr_len( ssl ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - /* In case of DTLS, double-check that we don't exceed - * the remaining space in the datagram. */ - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - ret = ssl_get_remaining_space_in_datagram( ssl ); - if( ret < 0 ) - return( ret ); - - if( protected_record_size > (size_t) ret ) - { - /* Should never happen */ - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - /* Now write the potentially updated record content type. */ - ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " - "version = [%d:%d], msglen = %d", - ssl->out_hdr[0], ssl->out_hdr[1], - ssl->out_hdr[2], len ) ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", - ssl->out_hdr, protected_record_size ); - - ssl->out_left += protected_record_size; - ssl->out_hdr += protected_record_size; - ssl_update_out_pointers( ssl, ssl->transform_out ); - - for( i = 8; i > ssl_ep_len( ssl ); i-- ) - if( ++ssl->cur_out_ctr[i - 1] != 0 ) - break; - - /* The loop goes to its end iff the counter is wrapping */ - if( i == ssl_ep_len( ssl ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); - return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); - } - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - flush == SSL_DONT_FORCE_FLUSH ) - { - size_t remaining; - ret = ssl_get_remaining_payload_in_datagram( ssl ); - if( ret < 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram", - ret ); - return( ret ); - } - - remaining = (size_t) ret; - if( remaining == 0 ) - { - flush = SSL_FORCE_FLUSH; - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) ); - } - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - if( ( flush == SSL_FORCE_FLUSH ) && - ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) ); - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - -static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl ) -{ - if( ssl->in_msglen < ssl->in_hslen || - memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || - memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 ) - { - return( 1 ); - } - return( 0 ); -} - -static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl ) -{ - return( ( ssl->in_msg[9] << 16 ) | - ( ssl->in_msg[10] << 8 ) | - ssl->in_msg[11] ); -} - -static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl ) -{ - return( ( ssl->in_msg[6] << 16 ) | - ( ssl->in_msg[7] << 8 ) | - ssl->in_msg[8] ); -} - -static int ssl_check_hs_header( mbedtls_ssl_context const *ssl ) -{ - uint32_t msg_len, frag_off, frag_len; - - msg_len = ssl_get_hs_total_len( ssl ); - frag_off = ssl_get_hs_frag_off( ssl ); - frag_len = ssl_get_hs_frag_len( ssl ); - - if( frag_off > msg_len ) - return( -1 ); - - if( frag_len > msg_len - frag_off ) - return( -1 ); - - if( frag_len + 12 > ssl->in_msglen ) - return( -1 ); - - return( 0 ); -} - -/* - * Mark bits in bitmask (used for DTLS HS reassembly) - */ -static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len ) -{ - unsigned int start_bits, end_bits; - - start_bits = 8 - ( offset % 8 ); - if( start_bits != 8 ) - { - size_t first_byte_idx = offset / 8; - - /* Special case */ - if( len <= start_bits ) - { - for( ; len != 0; len-- ) - mask[first_byte_idx] |= 1 << ( start_bits - len ); - - /* Avoid potential issues with offset or len becoming invalid */ - return; - } - - offset += start_bits; /* Now offset % 8 == 0 */ - len -= start_bits; - - for( ; start_bits != 0; start_bits-- ) - mask[first_byte_idx] |= 1 << ( start_bits - 1 ); - } - - end_bits = len % 8; - if( end_bits != 0 ) - { - size_t last_byte_idx = ( offset + len ) / 8; - - len -= end_bits; /* Now len % 8 == 0 */ - - for( ; end_bits != 0; end_bits-- ) - mask[last_byte_idx] |= 1 << ( 8 - end_bits ); - } - - memset( mask + offset / 8, 0xFF, len / 8 ); -} - -/* - * Check that bitmask is full - */ -static int ssl_bitmask_check( unsigned char *mask, size_t len ) -{ - size_t i; - - for( i = 0; i < len / 8; i++ ) - if( mask[i] != 0xFF ) - return( -1 ); - - for( i = 0; i < len % 8; i++ ) - if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 ) - return( -1 ); - - return( 0 ); -} - -/* msg_len does not include the handshake header */ -static size_t ssl_get_reassembly_buffer_size( size_t msg_len, - unsigned add_bitmap ) -{ - size_t alloc_len; - - alloc_len = 12; /* Handshake header */ - alloc_len += msg_len; /* Content buffer */ - - if( add_bitmap ) - alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap */ - - return( alloc_len ); -} - -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ) -{ - return( ( ssl->in_msg[1] << 16 ) | - ( ssl->in_msg[2] << 8 ) | - ssl->in_msg[3] ); -} - -int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) -{ - if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %d", - ssl->in_msglen ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" - " %d, type = %d, hslen = %d", - ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; - - if( ssl_check_hs_header( ssl ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - if( ssl->handshake != NULL && - ( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && - recv_msg_seq != ssl->handshake->in_msg_seq ) || - ( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && - ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) ) - { - if( recv_msg_seq > ssl->handshake->in_msg_seq ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)", - recv_msg_seq, - ssl->handshake->in_msg_seq ) ); - return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); - } - - /* Retransmit only on last message from previous flight, to avoid - * too many retransmissions. - * Besides, No sane server ever retransmits HelloVerifyRequest */ - if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 && - ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, " - "message_seq = %d, start_of_flight = %d", - recv_msg_seq, - ssl->handshake->in_flight_start_seq ) ); - - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); - return( ret ); - } - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: " - "message_seq = %d, expected = %d", - recv_msg_seq, - ssl->handshake->in_msg_seq ) ); - } - - return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); - } - /* Wait until message completion to increment in_msg_seq */ - - /* Message reassembly is handled alongside buffering of future - * messages; the commonality is that both handshake fragments and - * future messages cannot be forwarded immediately to the - * handshake logic layer. */ - if( ssl_hs_is_proper_fragment( ssl ) == 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) ); - return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); - } - } - else -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - /* With TLS we don't handle fragmentation (for now) */ - if( ssl->in_msglen < ssl->in_hslen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - return( 0 ); -} - -void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) -{ - mbedtls_ssl_handshake_params * const hs = ssl->handshake; - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL ) - { - ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); - } - - /* Handshake message is complete, increment counter */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake != NULL ) - { - unsigned offset; - mbedtls_ssl_hs_buffer *hs_buf; - - /* Increment handshake sequence number */ - hs->in_msg_seq++; - - /* - * Clear up handshake buffering and reassembly structure. - */ - - /* Free first entry */ - ssl_buffering_free_slot( ssl, 0 ); - - /* Shift all other entries */ - for( offset = 0, hs_buf = &hs->buffering.hs[0]; - offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS; - offset++, hs_buf++ ) - { - *hs_buf = *(hs_buf + 1); - } - - /* Create a fresh last entry */ - memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); - } -#endif -} - -/* - * DTLS anti-replay: RFC 6347 4.1.2.6 - * - * in_window is a field of bits numbered from 0 (lsb) to 63 (msb). - * Bit n is set iff record number in_window_top - n has been seen. - * - * Usually, in_window_top is the last record number seen and the lsb of - * in_window is set. The only exception is the initial state (record number 0 - * not seen yet). - */ -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ) -{ - ssl->in_window_top = 0; - ssl->in_window = 0; -} - -static inline uint64_t ssl_load_six_bytes( unsigned char *buf ) -{ - return( ( (uint64_t) buf[0] << 40 ) | - ( (uint64_t) buf[1] << 32 ) | - ( (uint64_t) buf[2] << 24 ) | - ( (uint64_t) buf[3] << 16 ) | - ( (uint64_t) buf[4] << 8 ) | - ( (uint64_t) buf[5] ) ); -} - -static int mbedtls_ssl_dtls_record_replay_check( mbedtls_ssl_context *ssl, uint8_t *record_in_ctr ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char *original_in_ctr; - - // save original in_ctr - original_in_ctr = ssl->in_ctr; - - // use counter from record - ssl->in_ctr = record_in_ctr; - - ret = mbedtls_ssl_dtls_replay_check( (mbedtls_ssl_context const *) ssl ); - - // restore the counter - ssl->in_ctr = original_in_ctr; - - return ret; -} - -/* - * Return 0 if sequence number is acceptable, -1 otherwise - */ -int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl ) -{ - uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); - uint64_t bit; - - if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) - return( 0 ); - - if( rec_seqnum > ssl->in_window_top ) - return( 0 ); - - bit = ssl->in_window_top - rec_seqnum; - - if( bit >= 64 ) - return( -1 ); - - if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 ) - return( -1 ); - - return( 0 ); -} - -/* - * Update replay window on new validated record - */ -void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ) -{ - uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); - - if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) - return; - - if( rec_seqnum > ssl->in_window_top ) - { - /* Update window_top and the contents of the window */ - uint64_t shift = rec_seqnum - ssl->in_window_top; - - if( shift >= 64 ) - ssl->in_window = 1; - else - { - ssl->in_window <<= shift; - ssl->in_window |= 1; - } - - ssl->in_window_top = rec_seqnum; - } - else - { - /* Mark that number as seen in the current window */ - uint64_t bit = ssl->in_window_top - rec_seqnum; - - if( bit < 64 ) /* Always true, but be extra sure */ - ssl->in_window |= (uint64_t) 1 << bit; - } -} -#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ - -#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) -/* Forward declaration */ -static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ); - -/* - * Without any SSL context, check if a datagram looks like a ClientHello with - * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message. - * Both input and output include full DTLS headers. - * - * - if cookie is valid, return 0 - * - if ClientHello looks superficially valid but cookie is not, - * fill obuf and set olen, then - * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED - * - otherwise return a specific error code - */ -static int ssl_check_dtls_clihlo_cookie( - mbedtls_ssl_cookie_write_t *f_cookie_write, - mbedtls_ssl_cookie_check_t *f_cookie_check, - void *p_cookie, - const unsigned char *cli_id, size_t cli_id_len, - const unsigned char *in, size_t in_len, - unsigned char *obuf, size_t buf_len, size_t *olen ) -{ - size_t sid_len, cookie_len; - unsigned char *p; - - /* - * Structure of ClientHello with record and handshake headers, - * and expected values. We don't need to check a lot, more checks will be - * done when actually parsing the ClientHello - skipping those checks - * avoids code duplication and does not make cookie forging any easier. - * - * 0-0 ContentType type; copied, must be handshake - * 1-2 ProtocolVersion version; copied - * 3-4 uint16 epoch; copied, must be 0 - * 5-10 uint48 sequence_number; copied - * 11-12 uint16 length; (ignored) - * - * 13-13 HandshakeType msg_type; (ignored) - * 14-16 uint24 length; (ignored) - * 17-18 uint16 message_seq; copied - * 19-21 uint24 fragment_offset; copied, must be 0 - * 22-24 uint24 fragment_length; (ignored) - * - * 25-26 ProtocolVersion client_version; (ignored) - * 27-58 Random random; (ignored) - * 59-xx SessionID session_id; 1 byte len + sid_len content - * 60+ opaque cookie<0..2^8-1>; 1 byte len + content - * ... - * - * Minimum length is 61 bytes. - */ - if( in_len < 61 || - in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || - in[3] != 0 || in[4] != 0 || - in[19] != 0 || in[20] != 0 || in[21] != 0 ) - { - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - sid_len = in[59]; - if( sid_len > in_len - 61 ) - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - - cookie_len = in[60 + sid_len]; - if( cookie_len > in_len - 60 ) - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - - if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len, - cli_id, cli_id_len ) == 0 ) - { - /* Valid cookie */ - return( 0 ); - } - - /* - * If we get here, we've got an invalid cookie, let's prepare HVR. - * - * 0-0 ContentType type; copied - * 1-2 ProtocolVersion version; copied - * 3-4 uint16 epoch; copied - * 5-10 uint48 sequence_number; copied - * 11-12 uint16 length; olen - 13 - * - * 13-13 HandshakeType msg_type; hello_verify_request - * 14-16 uint24 length; olen - 25 - * 17-18 uint16 message_seq; copied - * 19-21 uint24 fragment_offset; copied - * 22-24 uint24 fragment_length; olen - 25 - * - * 25-26 ProtocolVersion server_version; 0xfe 0xff - * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie - * - * Minimum length is 28. - */ - if( buf_len < 28 ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - - /* Copy most fields and adapt others */ - memcpy( obuf, in, 25 ); - obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; - obuf[25] = 0xfe; - obuf[26] = 0xff; - - /* Generate and write actual cookie */ - p = obuf + 28; - if( f_cookie_write( p_cookie, - &p, obuf + buf_len, cli_id, cli_id_len ) != 0 ) - { - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - *olen = p - obuf; - - /* Go back and fill length fields */ - obuf[27] = (unsigned char)( *olen - 28 ); - - obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 ); - obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >> 8 ); - obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 ) ); - - obuf[11] = (unsigned char)( ( *olen - 13 ) >> 8 ); - obuf[12] = (unsigned char)( ( *olen - 13 ) ); - - return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); -} - -/* - * Handle possible client reconnect with the same UDP quadruplet - * (RFC 6347 Section 4.2.8). - * - * Called by ssl_parse_record_header() in case we receive an epoch 0 record - * that looks like a ClientHello. - * - * - if the input looks like a ClientHello without cookies, - * send back HelloVerifyRequest, then - * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED - * - if the input looks like a ClientHello with a valid cookie, - * reset the session of the current context, and - * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT - * - if anything goes wrong, return a specific error code - * - * mbedtls_ssl_read_record() will ignore the record if anything else than - * MBEDTLS_ERR_SSL_CLIENT_RECONNECT or 0 is returned, although this function - * cannot not return 0. - */ -static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - - if( ssl->conf->f_cookie_write == NULL || - ssl->conf->f_cookie_check == NULL ) - { - /* If we can't use cookies to verify reachability of the peer, - * drop the record. */ - return( 0 ); - } - - ret = ssl_check_dtls_clihlo_cookie( - ssl->conf->f_cookie_write, - ssl->conf->f_cookie_check, - ssl->conf->p_cookie, - ssl->cli_id, ssl->cli_id_len, - ssl->in_buf, ssl->in_left, - ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len ); - - MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); - - if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) - { - /* Don't check write errors as we can't do anything here. - * If the error is permanent we'll catch it later, - * if it's not, then hopefully it'll work next time. */ - (void) ssl->f_send( ssl->p_bio, ssl->out_buf, len ); - ret = 0; - } - - if( ret == 0 ) - { - /* Got a valid cookie, partially reset context */ - if( ( ret = ssl_session_reset_int( ssl, 1 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret ); - return( ret ); - } - - return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT ); - } - - return( ret ); -} -#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ - -static int ssl_check_record_type( uint8_t record_type ) -{ - if( record_type != MBEDTLS_SSL_MSG_HANDSHAKE && - record_type != MBEDTLS_SSL_MSG_ALERT && - record_type != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && - record_type != MBEDTLS_SSL_MSG_APPLICATION_DATA ) - { - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - return( 0 ); -} - -/* - * ContentType type; - * ProtocolVersion version; - * uint16 epoch; // DTLS only - * uint48 sequence_number; // DTLS only - * uint16 length; - * - * Return 0 if header looks sane (and, for DTLS, the record is expected) - * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad, - * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected. - * - * With DTLS, mbedtls_ssl_read_record() will: - * 1. proceed with the record if this function returns 0 - * 2. drop only the current record if this function returns UNEXPECTED_RECORD - * 3. return CLIENT_RECONNECT if this function return that value - * 4. drop the whole datagram if this function returns anything else. - * Point 2 is needed when the peer is resending, and we have already received - * the first record from a datagram but are still waiting for the others. - */ -static int ssl_parse_record_header( mbedtls_ssl_context const *ssl, - unsigned char *buf, - size_t len, - mbedtls_record *rec ) -{ - int major_ver, minor_ver; - - size_t const rec_hdr_type_offset = 0; - size_t const rec_hdr_type_len = 1; - - size_t const rec_hdr_version_offset = rec_hdr_type_offset + - rec_hdr_type_len; - size_t const rec_hdr_version_len = 2; - - size_t const rec_hdr_ctr_len = 8; -#if defined(MBEDTLS_SSL_PROTO_DTLS) - uint32_t rec_epoch; - size_t const rec_hdr_ctr_offset = rec_hdr_version_offset + - rec_hdr_version_len; - -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - size_t const rec_hdr_cid_offset = rec_hdr_ctr_offset + - rec_hdr_ctr_len; - size_t rec_hdr_cid_len = 0; -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - size_t rec_hdr_len_offset; /* To be determined */ - size_t const rec_hdr_len_len = 2; - - /* - * Check minimum lengths for record header. - */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - rec_hdr_len_offset = rec_hdr_ctr_offset + rec_hdr_ctr_len; - } - else -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - { - rec_hdr_len_offset = rec_hdr_version_offset + rec_hdr_version_len; - } - - if( len < rec_hdr_len_offset + rec_hdr_len_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header of length %u", - (unsigned) len, - (unsigned)( rec_hdr_len_len + rec_hdr_len_len ) ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - /* - * Parse and validate record content type - */ - - rec->type = buf[ rec_hdr_type_offset ]; - - /* Check record content type */ -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - rec->cid_len = 0; - - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->conf->cid_len != 0 && - rec->type == MBEDTLS_SSL_MSG_CID ) - { - /* Shift pointers to account for record header including CID - * struct { - * ContentType special_type = tls12_cid; - * ProtocolVersion version; - * uint16 epoch; - * uint48 sequence_number; - * opaque cid[cid_length]; // Additional field compared to - * // default DTLS record format - * uint16 length; - * opaque enc_content[DTLSCiphertext.length]; - * } DTLSCiphertext; - */ - - /* So far, we only support static CID lengths - * fixed in the configuration. */ - rec_hdr_cid_len = ssl->conf->cid_len; - rec_hdr_len_offset += rec_hdr_cid_len; - - if( len < rec_hdr_len_offset + rec_hdr_len_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header including CID, length %u", - (unsigned) len, - (unsigned)( rec_hdr_len_offset + rec_hdr_len_len ) ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - /* configured CID len is guaranteed at most 255, see - * MBEDTLS_SSL_CID_OUT_LEN_MAX in check_config.h */ - rec->cid_len = (uint8_t) rec_hdr_cid_len; - memcpy( rec->cid, buf + rec_hdr_cid_offset, rec_hdr_cid_len ); - } - else -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - { - if( ssl_check_record_type( rec->type ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type %u", - (unsigned) rec->type ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - } - - /* - * Parse and validate record version - */ - - rec->ver[0] = buf[ rec_hdr_version_offset + 0 ]; - rec->ver[1] = buf[ rec_hdr_version_offset + 1 ]; - mbedtls_ssl_read_version( &major_ver, &minor_ver, - ssl->conf->transport, - &rec->ver[0] ); - - if( major_ver != ssl->major_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - if( minor_ver > ssl->conf->max_minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - /* - * Parse/Copy record sequence number. - */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - /* Copy explicit record sequence number from input buffer. */ - memcpy( &rec->ctr[0], buf + rec_hdr_ctr_offset, - rec_hdr_ctr_len ); - } - else -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - { - /* Copy implicit record sequence number from SSL context structure. */ - memcpy( &rec->ctr[0], ssl->in_ctr, rec_hdr_ctr_len ); - } - - /* - * Parse record length. - */ - - rec->data_offset = rec_hdr_len_offset + rec_hdr_len_len; - rec->data_len = ( (size_t) buf[ rec_hdr_len_offset + 0 ] << 8 ) | - ( (size_t) buf[ rec_hdr_len_offset + 1 ] << 0 ); - MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", buf, rec->data_offset ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, " - "version = [%d:%d], msglen = %d", - rec->type, - major_ver, minor_ver, rec->data_len ) ); - - rec->buf = buf; - rec->buf_len = rec->data_offset + rec->data_len; - - if( rec->data_len == 0 ) - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - - /* - * DTLS-related tests. - * Check epoch before checking length constraint because - * the latter varies with the epoch. E.g., if a ChangeCipherSpec - * message gets duplicated before the corresponding Finished message, - * the second ChangeCipherSpec should be discarded because it belongs - * to an old epoch, but not because its length is shorter than - * the minimum record length for packets using the new record transform. - * Note that these two kinds of failures are handled differently, - * as an unexpected record is silently skipped but an invalid - * record leads to the entire datagram being dropped. - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - rec_epoch = ( rec->ctr[0] << 8 ) | rec->ctr[1]; - - /* Check that the datagram is large enough to contain a record - * of the advertised length. */ - if( len < rec->data_offset + rec->data_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Datagram of length %u too small to contain record of advertised length %u.", - (unsigned) len, - (unsigned)( rec->data_offset + rec->data_len ) ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - /* Records from other, non-matching epochs are silently discarded. - * (The case of same-port Client reconnects must be considered in - * the caller). */ - if( rec_epoch != ssl->in_epoch ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: " - "expected %d, received %d", - ssl->in_epoch, rec_epoch ) ); - - /* Records from the next epoch are considered for buffering - * (concretely: early Finished messages). */ - if( rec_epoch == (unsigned) ssl->in_epoch + 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) ); - return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); - } - - return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); - } -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - /* For records from the correct epoch, check whether their - * sequence number has been seen before. */ - else if( mbedtls_ssl_dtls_record_replay_check( (mbedtls_ssl_context *) ssl, - &rec->ctr[0] ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); - } -#endif - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - return( 0 ); -} - - -#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) -static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl ) -{ - unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1]; - - /* - * Check for an epoch 0 ClientHello. We can't use in_msg here to - * access the first byte of record content (handshake type), as we - * have an active transform (possibly iv_len != 0), so use the - * fact that the record header len is 13 instead. - */ - if( rec_epoch == 0 && - ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && - ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_left > 13 && - ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect " - "from the same port" ) ); - return( ssl_handle_possible_reconnect( ssl ) ); - } - - return( 0 ); -} -#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ - -/* - * If applicable, decrypt (and decompress) record content - */ -static int ssl_prepare_record_content( mbedtls_ssl_context *ssl, - mbedtls_record *rec ) -{ - int ret, done = 0; - - MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network", - rec->buf, rec->buf_len ); - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_read != NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_read()" ) ); - - ret = mbedtls_ssl_hw_record_read( ssl ); - if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_read", ret ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - - if( ret == 0 ) - done = 1; - } -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ - if( !done && ssl->transform_in != NULL ) - { - unsigned char const old_msg_type = rec->type; - - if( ( ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in, - rec ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret ); - -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID && - ssl->conf->ignore_unexpected_cid - == MBEDTLS_SSL_UNEXPECTED_CID_IGNORE ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ignoring unexpected CID" ) ); - ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; - } -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - - return( ret ); - } - - if( old_msg_type != rec->type ) - { - MBEDTLS_SSL_DEBUG_MSG( 4, ( "record type after decrypt (before %d): %d", - old_msg_type, rec->type ) ); - } - - MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt", - rec->buf + rec->data_offset, rec->data_len ); - -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - /* We have already checked the record content type - * in ssl_parse_record_header(), failing or silently - * dropping the record in the case of an unknown type. - * - * Since with the use of CIDs, the record content type - * might change during decryption, re-check the record - * content type, but treat a failure as fatal this time. */ - if( ssl_check_record_type( rec->type ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - - if( rec->data_len == 0 ) - { -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 - && rec->type != MBEDTLS_SSL_MSG_APPLICATION_DATA ) - { - /* TLS v1.2 explicitly disallows zero-length messages which are not application data */ - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - - ssl->nb_zero++; - - /* - * Three or more empty messages may be a DoS attack - * (excessive CPU consumption). - */ - if( ssl->nb_zero > 3 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty " - "messages, possible DoS attack" ) ); - /* Treat the records as if they were not properly authenticated, - * thereby failing the connection if we see more than allowed - * by the configured bad MAC threshold. */ - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - } - else - ssl->nb_zero = 0; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - ; /* in_ctr read from peer, not maintained internally */ - } - else -#endif - { - unsigned i; - for( i = 8; i > ssl_ep_len( ssl ); i-- ) - if( ++ssl->in_ctr[i - 1] != 0 ) - break; - - /* The loop goes to its end iff the counter is wrapping */ - if( i == ssl_ep_len( ssl ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) ); - return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); - } - } - - } - -#if defined(MBEDTLS_ZLIB_SUPPORT) - if( ssl->transform_in != NULL && - ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) - { - if( ( ret = ssl_decompress_buf( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret ); - return( ret ); - } - } -#endif /* MBEDTLS_ZLIB_SUPPORT */ - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - mbedtls_ssl_dtls_replay_update( ssl ); - } -#endif - - /* Check actual (decrypted) record content length against - * configured maximum. */ - if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - return( 0 ); -} - -static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ); - -/* - * Read a record. - * - * Silently ignore non-fatal alert (and for DTLS, invalid records as well, - * RFC 6347 4.1.2.7) and continue reading until a valid record is found. - * - */ - -/* Helper functions for mbedtls_ssl_read_record(). */ -static int ssl_consume_current_message( mbedtls_ssl_context *ssl ); -static int ssl_get_next_record( mbedtls_ssl_context *ssl ); -static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ); - -int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, - unsigned update_hs_digest ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) ); - - if( ssl->keep_current_message == 0 ) - { - do { - - ret = ssl_consume_current_message( ssl ); - if( ret != 0 ) - return( ret ); - - if( ssl_record_is_in_progress( ssl ) == 0 ) - { -#if defined(MBEDTLS_SSL_PROTO_DTLS) - int have_buffered = 0; - - /* We only check for buffered messages if the - * current datagram is fully consumed. */ - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl_next_record_is_in_datagram( ssl ) == 0 ) - { - if( ssl_load_buffered_message( ssl ) == 0 ) - have_buffered = 1; - } - - if( have_buffered == 0 ) -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - { - ret = ssl_get_next_record( ssl ); - if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ) - continue; - - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret ); - return( ret ); - } - } - } - - ret = mbedtls_ssl_handle_message_type( ssl ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) - { - /* Buffer future message */ - ret = ssl_buffer_message( ssl ); - if( ret != 0 ) - return( ret ); - - ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - } while( MBEDTLS_ERR_SSL_NON_FATAL == ret || - MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret ); - - if( 0 != ret ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); - return( ret ); - } - - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - update_hs_digest == 1 ) - { - mbedtls_ssl_update_handshake_status( ssl ); - } - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) ); - ssl->keep_current_message = 0; - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) ); - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ) -{ - if( ssl->in_left > ssl->next_record_offset ) - return( 1 ); - - return( 0 ); -} - -static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ) -{ - mbedtls_ssl_handshake_params * const hs = ssl->handshake; - mbedtls_ssl_hs_buffer * hs_buf; - int ret = 0; - - if( hs == NULL ) - return( -1 ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) ); - - if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC || - ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) - { - /* Check if we have seen a ChangeCipherSpec before. - * If yes, synthesize a CCS record. */ - if( !hs->buffering.seen_ccs ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) ); - ret = -1; - goto exit; - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) ); - ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; - ssl->in_msglen = 1; - ssl->in_msg[0] = 1; - - /* As long as they are equal, the exact value doesn't matter. */ - ssl->in_left = 0; - ssl->next_record_offset = 0; - - hs->buffering.seen_ccs = 0; - goto exit; - } - -#if defined(MBEDTLS_DEBUG_C) - /* Debug only */ - { - unsigned offset; - for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) - { - hs_buf = &hs->buffering.hs[offset]; - if( hs_buf->is_valid == 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.", - hs->in_msg_seq + offset, - hs_buf->is_complete ? "fully" : "partially" ) ); - } - } - } -#endif /* MBEDTLS_DEBUG_C */ - - /* Check if we have buffered and/or fully reassembled the - * next handshake message. */ - hs_buf = &hs->buffering.hs[0]; - if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) ) - { - /* Synthesize a record containing the buffered HS message. */ - size_t msg_len = ( hs_buf->data[1] << 16 ) | - ( hs_buf->data[2] << 8 ) | - hs_buf->data[3]; - - /* Double-check that we haven't accidentally buffered - * a message that doesn't fit into the input buffer. */ - if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)", - hs_buf->data, msg_len + 12 ); - - ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->in_hslen = msg_len + 12; - ssl->in_msglen = msg_len + 12; - memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen ); - - ret = 0; - goto exit; - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered", - hs->in_msg_seq ) ); - } - - ret = -1; - -exit: - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) ); - return( ret ); -} - -static int ssl_buffer_make_space( mbedtls_ssl_context *ssl, - size_t desired ) -{ - int offset; - mbedtls_ssl_handshake_params * const hs = ssl->handshake; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available", - (unsigned) desired ) ); - - /* Get rid of future records epoch first, if such exist. */ - ssl_free_buffered_record( ssl ); - - /* Check if we have enough space available now. */ - if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - - hs->buffering.total_bytes_buffered ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) ); - return( 0 ); - } - - /* We don't have enough space to buffer the next expected handshake - * message. Remove buffers used for future messages to gain space, - * starting with the most distant one. */ - for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1; - offset >= 0; offset-- ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message", - offset ) ); - - ssl_buffering_free_slot( ssl, (uint8_t) offset ); - - /* Check if we have enough space available now. */ - if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - - hs->buffering.total_bytes_buffered ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) ); - return( 0 ); - } - } - - return( -1 ); -} - -static int ssl_buffer_message( mbedtls_ssl_context *ssl ) -{ - int ret = 0; - mbedtls_ssl_handshake_params * const hs = ssl->handshake; - - if( hs == NULL ) - return( 0 ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) ); - - switch( ssl->in_msgtype ) - { - case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC: - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) ); - - hs->buffering.seen_ccs = 1; - break; - - case MBEDTLS_SSL_MSG_HANDSHAKE: - { - unsigned recv_msg_seq_offset; - unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; - mbedtls_ssl_hs_buffer *hs_buf; - size_t msg_len = ssl->in_hslen - 12; - - /* We should never receive an old handshake - * message - double-check nonetheless. */ - if( recv_msg_seq < ssl->handshake->in_msg_seq ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq; - if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS ) - { - /* Silently ignore -- message too far in the future */ - MBEDTLS_SSL_DEBUG_MSG( 2, - ( "Ignore future HS message with sequence number %u, " - "buffering window %u - %u", - recv_msg_seq, ssl->handshake->in_msg_seq, - ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) ); - - goto exit; - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ", - recv_msg_seq, recv_msg_seq_offset ) ); - - hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ]; - - /* Check if the buffering for this seq nr has already commenced. */ - if( !hs_buf->is_valid ) - { - size_t reassembly_buf_sz; - - hs_buf->is_fragmented = - ( ssl_hs_is_proper_fragment( ssl ) == 1 ); - - /* We copy the message back into the input buffer - * after reassembly, so check that it's not too large. - * This is an implementation-specific limitation - * and not one from the standard, hence it is not - * checked in ssl_check_hs_header(). */ - if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) - { - /* Ignore message */ - goto exit; - } - - /* Check if we have enough space to buffer the message. */ - if( hs->buffering.total_bytes_buffered > - MBEDTLS_SSL_DTLS_MAX_BUFFERING ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len, - hs_buf->is_fragmented ); - - if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - - hs->buffering.total_bytes_buffered ) ) - { - if( recv_msg_seq_offset > 0 ) - { - /* If we can't buffer a future message because - * of space limitations -- ignore. */ - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n", - (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, - (unsigned) hs->buffering.total_bytes_buffered ) ); - goto exit; - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- attempt to make space by freeing buffered future messages\n", - (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, - (unsigned) hs->buffering.total_bytes_buffered ) ); - } - - if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %u (%u with bitmap) would exceed the compile-time limit %u (already %u bytes buffered) -- fail\n", - (unsigned) msg_len, - (unsigned) reassembly_buf_sz, - MBEDTLS_SSL_DTLS_MAX_BUFFERING, - (unsigned) hs->buffering.total_bytes_buffered ) ); - ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; - goto exit; - } - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", - msg_len ) ); - - hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz ); - if( hs_buf->data == NULL ) - { - ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; - goto exit; - } - hs_buf->data_len = reassembly_buf_sz; - - /* Prepare final header: copy msg_type, length and message_seq, - * then add standardised fragment_offset and fragment_length */ - memcpy( hs_buf->data, ssl->in_msg, 6 ); - memset( hs_buf->data + 6, 0, 3 ); - memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 ); - - hs_buf->is_valid = 1; - - hs->buffering.total_bytes_buffered += reassembly_buf_sz; - } - else - { - /* Make sure msg_type and length are consistent */ - if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) ); - /* Ignore */ - goto exit; - } - } - - if( !hs_buf->is_complete ) - { - size_t frag_len, frag_off; - unsigned char * const msg = hs_buf->data + 12; - - /* - * Check and copy current fragment - */ - - /* Validation of header fields already done in - * mbedtls_ssl_prepare_handshake_record(). */ - frag_off = ssl_get_hs_frag_off( ssl ); - frag_len = ssl_get_hs_frag_len( ssl ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d", - frag_off, frag_len ) ); - memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); - - if( hs_buf->is_fragmented ) - { - unsigned char * const bitmask = msg + msg_len; - ssl_bitmask_set( bitmask, frag_off, frag_len ); - hs_buf->is_complete = ( ssl_bitmask_check( bitmask, - msg_len ) == 0 ); - } - else - { - hs_buf->is_complete = 1; - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete", - hs_buf->is_complete ? "" : "not yet " ) ); - } - - break; - } - - default: - /* We don't buffer other types of messages. */ - break; - } - -exit: - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) ); - return( ret ); -} -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -static int ssl_consume_current_message( mbedtls_ssl_context *ssl ) -{ - /* - * Consume last content-layer message and potentially - * update in_msglen which keeps track of the contents' - * consumption state. - * - * (1) Handshake messages: - * Remove last handshake message, move content - * and adapt in_msglen. - * - * (2) Alert messages: - * Consume whole record content, in_msglen = 0. - * - * (3) Change cipher spec: - * Consume whole record content, in_msglen = 0. - * - * (4) Application data: - * Don't do anything - the record layer provides - * the application data as a stream transport - * and consumes through mbedtls_ssl_read only. - * - */ - - /* Case (1): Handshake messages */ - if( ssl->in_hslen != 0 ) - { - /* Hard assertion to be sure that no application data - * is in flight, as corrupting ssl->in_msglen during - * ssl->in_offt != NULL is fatal. */ - if( ssl->in_offt != NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* - * Get next Handshake message in the current record - */ - - /* Notes: - * (1) in_hslen is not necessarily the size of the - * current handshake content: If DTLS handshake - * fragmentation is used, that's the fragment - * size instead. Using the total handshake message - * size here is faulty and should be changed at - * some point. - * (2) While it doesn't seem to cause problems, one - * has to be very careful not to assume that in_hslen - * is always <= in_msglen in a sensible communication. - * Again, it's wrong for DTLS handshake fragmentation. - * The following check is therefore mandatory, and - * should not be treated as a silently corrected assertion. - * Additionally, ssl->in_hslen might be arbitrarily out of - * bounds after handling a DTLS message with an unexpected - * sequence number, see mbedtls_ssl_prepare_handshake_record. - */ - if( ssl->in_hslen < ssl->in_msglen ) - { - ssl->in_msglen -= ssl->in_hslen; - memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, - ssl->in_msglen ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record", - ssl->in_msg, ssl->in_msglen ); - } - else - { - ssl->in_msglen = 0; - } - - ssl->in_hslen = 0; - } - /* Case (4): Application data */ - else if( ssl->in_offt != NULL ) - { - return( 0 ); - } - /* Everything else (CCS & Alerts) */ - else - { - ssl->in_msglen = 0; - } - - return( 0 ); -} - -static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ) -{ - if( ssl->in_msglen > 0 ) - return( 1 ); - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - -static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ) -{ - mbedtls_ssl_handshake_params * const hs = ssl->handshake; - if( hs == NULL ) - return; - - if( hs->buffering.future_record.data != NULL ) - { - hs->buffering.total_bytes_buffered -= - hs->buffering.future_record.len; - - mbedtls_free( hs->buffering.future_record.data ); - hs->buffering.future_record.data = NULL; - } -} - -static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ) -{ - mbedtls_ssl_handshake_params * const hs = ssl->handshake; - unsigned char * rec; - size_t rec_len; - unsigned rec_epoch; - - if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( 0 ); - - if( hs == NULL ) - return( 0 ); - - rec = hs->buffering.future_record.data; - rec_len = hs->buffering.future_record.len; - rec_epoch = hs->buffering.future_record.epoch; - - if( rec == NULL ) - return( 0 ); - - /* Only consider loading future records if the - * input buffer is empty. */ - if( ssl_next_record_is_in_datagram( ssl ) == 1 ) - return( 0 ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) ); - - if( rec_epoch != ssl->in_epoch ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) ); - goto exit; - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) ); - - /* Double-check that the record is not too large */ - if( rec_len > MBEDTLS_SSL_IN_BUFFER_LEN - - (size_t)( ssl->in_hdr - ssl->in_buf ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - memcpy( ssl->in_hdr, rec, rec_len ); - ssl->in_left = rec_len; - ssl->next_record_offset = 0; - - ssl_free_buffered_record( ssl ); - -exit: - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) ); - return( 0 ); -} - -static int ssl_buffer_future_record( mbedtls_ssl_context *ssl, - mbedtls_record const *rec ) -{ - mbedtls_ssl_handshake_params * const hs = ssl->handshake; - - /* Don't buffer future records outside handshakes. */ - if( hs == NULL ) - return( 0 ); - - /* Only buffer handshake records (we are only interested - * in Finished messages). */ - if( rec->type != MBEDTLS_SSL_MSG_HANDSHAKE ) - return( 0 ); - - /* Don't buffer more than one future epoch record. */ - if( hs->buffering.future_record.data != NULL ) - return( 0 ); - - /* Don't buffer record if there's not enough buffering space remaining. */ - if( rec->buf_len > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - - hs->buffering.total_bytes_buffered ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n", - (unsigned) rec->buf_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, - (unsigned) hs->buffering.total_bytes_buffered ) ); - return( 0 ); - } - - /* Buffer record */ - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u", - ssl->in_epoch + 1 ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", rec->buf, rec->buf_len ); - - /* ssl_parse_record_header() only considers records - * of the next epoch as candidates for buffering. */ - hs->buffering.future_record.epoch = ssl->in_epoch + 1; - hs->buffering.future_record.len = rec->buf_len; - - hs->buffering.future_record.data = - mbedtls_calloc( 1, hs->buffering.future_record.len ); - if( hs->buffering.future_record.data == NULL ) - { - /* If we run out of RAM trying to buffer a - * record from the next epoch, just ignore. */ - return( 0 ); - } - - memcpy( hs->buffering.future_record.data, rec->buf, rec->buf_len ); - - hs->buffering.total_bytes_buffered += rec->buf_len; - return( 0 ); -} - -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -static int ssl_get_next_record( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_record rec; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - /* We might have buffered a future record; if so, - * and if the epoch matches now, load it. - * On success, this call will set ssl->in_left to - * the length of the buffered record, so that - * the calls to ssl_fetch_input() below will - * essentially be no-ops. */ - ret = ssl_load_buffered_record( ssl ); - if( ret != 0 ) - return( ret ); -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - /* Ensure that we have enough space available for the default form - * of TLS / DTLS record headers (5 Bytes for TLS, 13 Bytes for DTLS, - * with no space for CIDs counted in). */ - ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_in_hdr_len( ssl ) ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); - return( ret ); - } - - ret = ssl_parse_record_header( ssl, ssl->in_hdr, ssl->in_left, &rec ); - if( ret != 0 ) - { -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) - { - ret = ssl_buffer_future_record( ssl, &rec ); - if( ret != 0 ) - return( ret ); - - /* Fall through to handling of unexpected records */ - ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; - } - - if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ) - { -#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) - /* Reset in pointers to default state for TLS/DTLS records, - * assuming no CID and no offset between record content and - * record plaintext. */ - ssl_update_in_pointers( ssl ); - - /* Setup internal message pointers from record structure. */ - ssl->in_msgtype = rec.type; -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - ssl->in_len = ssl->in_cid + rec.cid_len; -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - ssl->in_iv = ssl->in_msg = ssl->in_len + 2; - ssl->in_msglen = rec.data_len; - - ret = ssl_check_client_reconnect( ssl ); - if( ret != 0 ) - return( ret ); -#endif - - /* Skip unexpected record (but not whole datagram) */ - ssl->next_record_offset = rec.buf_len; - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record " - "(header)" ) ); - } - else - { - /* Skip invalid record and the rest of the datagram */ - ssl->next_record_offset = 0; - ssl->in_left = 0; - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record " - "(header)" ) ); - } - - /* Get next record */ - return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); - } - else -#endif - { - return( ret ); - } - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - /* Remember offset of next record within datagram. */ - ssl->next_record_offset = rec.buf_len; - if( ssl->next_record_offset < ssl->in_left ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) ); - } - } - else -#endif - { - /* - * Fetch record contents from underlying transport. - */ - ret = mbedtls_ssl_fetch_input( ssl, rec.buf_len ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); - return( ret ); - } - - ssl->in_left = 0; - } - - /* - * Decrypt record contents. - */ - - if( ( ret = ssl_prepare_record_content( ssl, &rec ) ) != 0 ) - { -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - /* Silently discard invalid records */ - if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) - { - /* Except when waiting for Finished as a bad mac here - * probably means something went wrong in the handshake - * (eg wrong psk used, mitm downgrade attempt, etc.) */ - if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED || - ssl->state == MBEDTLS_SSL_SERVER_FINISHED ) - { -#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) - if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) - { - mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); - } -#endif - return( ret ); - } - -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) - if( ssl->conf->badmac_limit != 0 && - ++ssl->badmac_seen >= ssl->conf->badmac_limit ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } -#endif - - /* As above, invalid records cause - * dismissal of the whole datagram. */ - - ssl->next_record_offset = 0; - ssl->in_left = 0; - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) ); - return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); - } - - return( ret ); - } - else -#endif - { - /* Error out (and send alert) on invalid records */ -#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) - if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) - { - mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); - } -#endif - return( ret ); - } - } - - - /* Reset in pointers to default state for TLS/DTLS records, - * assuming no CID and no offset between record content and - * record plaintext. */ - ssl_update_in_pointers( ssl ); -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - ssl->in_len = ssl->in_cid + rec.cid_len; -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - ssl->in_iv = ssl->in_len + 2; - - /* The record content type may change during decryption, - * so re-read it. */ - ssl->in_msgtype = rec.type; - /* Also update the input buffer, because unfortunately - * the server-side ssl_parse_client_hello() reparses the - * record header when receiving a ClientHello initiating - * a renegotiation. */ - ssl->in_hdr[0] = rec.type; - ssl->in_msg = rec.buf + rec.data_offset; - ssl->in_msglen = rec.data_len; - ssl->in_len[0] = (unsigned char)( rec.data_len >> 8 ); - ssl->in_len[1] = (unsigned char)( rec.data_len ); - - return( 0 ); -} - -int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - /* - * Handle particular types of records - */ - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) - { - if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 ) - { - return( ret ); - } - } - - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) - { - if( ssl->in_msglen != 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %d", - ssl->in_msglen ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - if( ssl->in_msg[0] != 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x", - ssl->in_msg[0] ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && - ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) - { - if( ssl->handshake == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) ); - return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); - } -#endif - } - - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) - { - if( ssl->in_msglen != 2 ) - { - /* Note: Standard allows for more than one 2 byte alert - to be packed in a single message, but Mbed TLS doesn't - currently support this. */ - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %d", - ssl->in_msglen ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]", - ssl->in_msg[0], ssl->in_msg[1] ) ); - - /* - * Ignore non-fatal alerts, except close_notify and no_renegotiation - */ - if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)", - ssl->in_msg[1] ) ); - return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE ); - } - - if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && - ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) ); - return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ); - } - -#if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED) - if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && - ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no renegotiation alert" ) ); - /* Will be handled when trying to parse ServerHello */ - return( 0 ); - } -#endif - -#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && - ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && - ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); - /* Will be handled in mbedtls_ssl_parse_certificate() */ - return( 0 ); - } -#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ - - /* Silently ignore: fetch new message */ - return MBEDTLS_ERR_SSL_NON_FATAL; - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - /* Drop unexpected ApplicationData records, - * except at the beginning of renegotiations */ - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && - ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER -#if defined(MBEDTLS_SSL_RENEGOTIATION) - && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->state == MBEDTLS_SSL_SERVER_HELLO ) -#endif - ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) ); - return( MBEDTLS_ERR_SSL_NON_FATAL ); - } - - if( ssl->handshake != NULL && - ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) - { - ssl_handshake_wrapup_free_hs_transform( ssl ); - } - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - return( 0 ); -} - -int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ) -{ - return( mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ); -} - -int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, - unsigned char level, - unsigned char message ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message )); - - ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; - ssl->out_msglen = 2; - ssl->out_msg[0] = level; - ssl->out_msg[1] = message; - - if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); - - return( 0 ); -} - #if defined(MBEDTLS_X509_CRT_PARSE_C) static void ssl_clear_peer_cert( mbedtls_ssl_session *session ) { @@ -6666,7 +2026,7 @@ static void ssl_clear_peer_cert( mbedtls_ssl_session *session ) /* * Handshake functions */ -#if !defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* No certificate support -> dummy functions */ int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) { @@ -6704,7 +2064,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } -#else /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ +#else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ /* Some certificate support -> implement write and parse */ int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) @@ -7184,7 +2544,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); } -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ); #endif @@ -7362,7 +2722,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) goto exit; } -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ssl->handshake->ecrs_enabled && ssl->handshake->ecrs_state == ssl_ecrs_crt_verify ) { @@ -7416,7 +2776,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) if( ret != 0 ) goto exit; -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ssl->handshake->ecrs_enabled) ssl->handshake->ecrs_state = ssl_ecrs_crt_verify; @@ -7473,7 +2833,7 @@ exit: if( ret == 0 ) ssl->state++; -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) { ssl->handshake->ecrs_peer_cert = chain; @@ -7489,103 +2849,7 @@ exit: return( ret ); } -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - -int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); - - ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; - ssl->out_msglen = 1; - ssl->out_msg[0] = 1; - - ssl->state++; - - if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); - - return( 0 ); -} - -int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); - - if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - /* CCS records are only accepted if they have length 1 and content '1', - * so we don't need to check this here. */ - - /* - * Switch to our negotiated transform and session parameters for inbound - * data. - */ - MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) ); - ssl->transform_in = ssl->transform_negotiate; - ssl->session_in = ssl->session_negotiate; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - ssl_dtls_replay_reset( ssl ); -#endif - - /* Increment epoch */ - if( ++ssl->in_epoch == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); - /* This is highly unlikely to happen for legitimate reasons, so - treat it as an attack and don't send an alert. */ - return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); - } - } - else -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - memset( ssl->in_ctr, 0, 8 ); - - ssl_update_in_pointers( ssl ); - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_activate != NULL ) - { - if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - } -#endif - - ssl->state++; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) ); - - return( 0 ); -} +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *ciphersuite_info ) @@ -8002,7 +3266,7 @@ static void ssl_calc_finished_tls_sha384( #endif /* MBEDTLS_SHA512_C */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ) +void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup: final free" ) ); @@ -8074,7 +3338,7 @@ void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) ssl->handshake->flight != NULL ) { /* Cancel handshake timer */ - ssl_set_timer( ssl, 0 ); + mbedtls_ssl_set_timer( ssl, 0 ); /* Keep last flight around in case we need to resend it: * we need the handshake and transform structures for that */ @@ -8082,7 +3346,7 @@ void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) } else #endif - ssl_handshake_wrapup_free_hs_transform( ssl ); + mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl ); ssl->state++; @@ -8095,7 +3359,7 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); - ssl_update_out_pointers( ssl, ssl->transform_negotiate ); + mbedtls_ssl_update_out_pointers( ssl, ssl->transform_negotiate ); ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint ); @@ -8327,7 +3591,7 @@ static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) handshake->update_checksum = ssl_update_checksum_start; #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) mbedtls_ssl_sig_hash_set_init( &handshake->hash_algs ); #endif @@ -8345,7 +3609,7 @@ static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) #endif #endif -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) mbedtls_x509_crt_restart_init( &handshake->ecrs_ctx ); #endif @@ -8405,6 +3669,58 @@ static int ssl_handshake_init( mbedtls_ssl_context *ssl ) { ssl->handshake = mbedtls_calloc( 1, sizeof(mbedtls_ssl_handshake_params) ); } +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + /* If the buffers are too small - reallocate */ + { + int modified = 0; + size_t written_in = 0; + size_t written_out = 0; + if( ssl->in_buf != NULL ) + { + written_in = ssl->in_msg - ssl->in_buf; + if( ssl->in_buf_len < MBEDTLS_SSL_IN_BUFFER_LEN ) + { + if( resize_buffer( &ssl->in_buf, MBEDTLS_SSL_IN_BUFFER_LEN, + &ssl->in_buf_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "input buffer resizing failed - out of memory" ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating in_buf to %d", MBEDTLS_SSL_IN_BUFFER_LEN ) ); + modified = 1; + } + } + } + + if( ssl->out_buf != NULL ) + { + written_out = ssl->out_msg - ssl->out_buf; + if( ssl->out_buf_len < MBEDTLS_SSL_OUT_BUFFER_LEN ) + { + if( resize_buffer( &ssl->out_buf, MBEDTLS_SSL_OUT_BUFFER_LEN, + &ssl->out_buf_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "output buffer resizing failed - out of memory" ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating out_buf to %d", MBEDTLS_SSL_OUT_BUFFER_LEN ) ); + modified = 1; + } + } + } + if( modified ) + { + /* Update pointers here to avoid doing it twice. */ + mbedtls_ssl_reset_in_out_pointers( ssl ); + /* Fields below might not be properly updated with record + * splitting, so they are manually updated here. */ + ssl->out_msg = ssl->out_buf + written_out; + ssl->in_msg = ssl->in_buf + written_in; + } + } +#endif /* All pointers should exist and can be directly freed without issue */ if( ssl->handshake == NULL || @@ -8439,7 +3755,7 @@ static int ssl_handshake_init( mbedtls_ssl_context *ssl ) else ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; - ssl_set_timer( ssl, 0 ); + mbedtls_ssl_set_timer( ssl, 0 ); } #endif @@ -8475,103 +3791,6 @@ static int ssl_cookie_check_dummy( void *ctx, } #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ -/* Once ssl->out_hdr as the address of the beginning of the - * next outgoing record is set, deduce the other pointers. - * - * Note: For TLS, we save the implicit record sequence number - * (entering MAC computation) in the 8 bytes before ssl->out_hdr, - * and the caller has to make sure there's space for this. - */ - -static void ssl_update_out_pointers( mbedtls_ssl_context *ssl, - mbedtls_ssl_transform *transform ) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - ssl->out_ctr = ssl->out_hdr + 3; -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - ssl->out_cid = ssl->out_ctr + 8; - ssl->out_len = ssl->out_cid; - if( transform != NULL ) - ssl->out_len += transform->out_cid_len; -#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - ssl->out_len = ssl->out_ctr + 8; -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - ssl->out_iv = ssl->out_len + 2; - } - else -#endif - { - ssl->out_ctr = ssl->out_hdr - 8; - ssl->out_len = ssl->out_hdr + 3; -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - ssl->out_cid = ssl->out_len; -#endif - ssl->out_iv = ssl->out_hdr + 5; - } - - /* Adjust out_msg to make space for explicit IV, if used. */ - if( transform != NULL && - ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - ssl->out_msg = ssl->out_iv + transform->ivlen - transform->fixed_ivlen; - } - else - ssl->out_msg = ssl->out_iv; -} - -/* Once ssl->in_hdr as the address of the beginning of the - * next incoming record is set, deduce the other pointers. - * - * Note: For TLS, we save the implicit record sequence number - * (entering MAC computation) in the 8 bytes before ssl->in_hdr, - * and the caller has to make sure there's space for this. - */ - -static void ssl_update_in_pointers( mbedtls_ssl_context *ssl ) -{ - /* This function sets the pointers to match the case - * of unprotected TLS/DTLS records, with both ssl->in_iv - * and ssl->in_msg pointing to the beginning of the record - * content. - * - * When decrypting a protected record, ssl->in_msg - * will be shifted to point to the beginning of the - * record plaintext. - */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - /* This sets the header pointers to match records - * without CID. When we receive a record containing - * a CID, the fields are shifted accordingly in - * ssl_parse_record_header(). */ - ssl->in_ctr = ssl->in_hdr + 3; -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - ssl->in_cid = ssl->in_ctr + 8; - ssl->in_len = ssl->in_cid; /* Default: no CID */ -#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - ssl->in_len = ssl->in_ctr + 8; -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - ssl->in_iv = ssl->in_len + 2; - } - else -#endif - { - ssl->in_ctr = ssl->in_hdr - 8; - ssl->in_len = ssl->in_hdr + 3; -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - ssl->in_cid = ssl->in_len; -#endif - ssl->in_iv = ssl->in_hdr + 5; - } - - /* This will be adjusted at record decryption time. */ - ssl->in_msg = ssl->in_iv; -} - /* * Initialize an SSL context */ @@ -8584,31 +3803,12 @@ void mbedtls_ssl_init( mbedtls_ssl_context *ssl ) * Setup an SSL context */ -static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ) -{ - /* Set the incoming and outgoing record pointers. */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - ssl->out_hdr = ssl->out_buf; - ssl->in_hdr = ssl->in_buf; - } - else -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - { - ssl->out_hdr = ssl->out_buf + 8; - ssl->in_hdr = ssl->in_buf + 8; - } - - /* Derive other internal pointers. */ - ssl_update_out_pointers( ssl, NULL /* no transform enabled */ ); - ssl_update_in_pointers ( ssl ); -} - int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, const mbedtls_ssl_config *conf ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; ssl->conf = conf; @@ -8619,23 +3819,29 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, /* Set to NULL in case of an error condition */ ssl->out_buf = NULL; - ssl->in_buf = mbedtls_calloc( 1, MBEDTLS_SSL_IN_BUFFER_LEN ); +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + ssl->in_buf_len = in_buf_len; +#endif + ssl->in_buf = mbedtls_calloc( 1, in_buf_len ); if( ssl->in_buf == NULL ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_IN_BUFFER_LEN) ); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", in_buf_len ) ); ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto error; } - ssl->out_buf = mbedtls_calloc( 1, MBEDTLS_SSL_OUT_BUFFER_LEN ); +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + ssl->out_buf_len = out_buf_len; +#endif + ssl->out_buf = mbedtls_calloc( 1, out_buf_len ); if( ssl->out_buf == NULL ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_OUT_BUFFER_LEN) ); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", out_buf_len ) ); ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto error; } - ssl_reset_in_out_pointers( ssl ); + mbedtls_ssl_reset_in_out_pointers( ssl ); if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) goto error; @@ -8648,6 +3854,10 @@ error: ssl->conf = NULL; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + ssl->in_buf_len = 0; + ssl->out_buf_len = 0; +#endif ssl->in_buf = NULL; ssl->out_buf = NULL; @@ -8673,9 +3883,16 @@ error: * If partial is non-zero, keep data in the input buffer and client ID. * (Use when a DTLS client reconnects from the same port.) */ -static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) +int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; + size_t out_buf_len = ssl->out_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif #if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || \ !defined(MBEDTLS_SSL_SRV_C) @@ -8685,7 +3902,7 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ssl->state = MBEDTLS_SSL_HELLO_REQUEST; /* Cancel any possibly running timer */ - ssl_set_timer( ssl, 0 ); + mbedtls_ssl_set_timer( ssl, 0 ); #if defined(MBEDTLS_SSL_RENEGOTIATION) ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE; @@ -8698,7 +3915,7 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; ssl->in_offt = NULL; - ssl_reset_in_out_pointers( ssl ); + mbedtls_ssl_reset_in_out_pointers( ssl ); ssl->in_msgtype = 0; ssl->in_msglen = 0; @@ -8707,7 +3924,7 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ssl->in_epoch = 0; #endif #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - ssl_dtls_replay_reset( ssl ); + mbedtls_ssl_dtls_replay_reset( ssl ); #endif ssl->in_hslen = 0; @@ -8731,14 +3948,14 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ssl->session_in = NULL; ssl->session_out = NULL; - memset( ssl->out_buf, 0, MBEDTLS_SSL_OUT_BUFFER_LEN ); + memset( ssl->out_buf, 0, out_buf_len ); #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) if( partial == 0 ) #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ { ssl->in_left = 0; - memset( ssl->in_buf, 0, MBEDTLS_SSL_IN_BUFFER_LEN ); + memset( ssl->in_buf, 0, in_buf_len ); } #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) @@ -8794,7 +4011,7 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) */ int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) { - return( ssl_session_reset_int( ssl, 0 ) ); + return( mbedtls_ssl_session_reset_int( ssl, 0 ) ); } /* @@ -8905,7 +4122,7 @@ void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, ssl->f_get_timer = f_get_timer; /* Make sure we start with no timer running */ - ssl_set_timer( ssl, 0 ); + mbedtls_ssl_set_timer( ssl, 0 ); } #if defined(MBEDTLS_SSL_SRV_C) @@ -9101,7 +4318,7 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) static void ssl_conf_remove_psk( mbedtls_ssl_config *conf ) { @@ -9274,7 +4491,7 @@ void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, conf->f_psk = f_psk; conf->p_psk = p_psk; } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) @@ -9339,7 +4556,7 @@ void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, } #endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* * Set allowed/preferred hashes for handshake signatures */ @@ -9348,7 +4565,7 @@ void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, { conf->sig_hashes = hashes; } -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_ECP_C) /* @@ -9629,66 +4846,6 @@ void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl, /* * SSL get accessors */ -size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ) -{ - return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); -} - -int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl ) -{ - /* - * Case A: We're currently holding back - * a message for further processing. - */ - - if( ssl->keep_current_message == 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: record held back for processing" ) ); - return( 1 ); - } - - /* - * Case B: Further records are pending in the current datagram. - */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->in_left > ssl->next_record_offset ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more records within current datagram" ) ); - return( 1 ); - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - /* - * Case C: A handshake message is being processed. - */ - - if( ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more handshake messages within current record" ) ); - return( 1 ); - } - - /* - * Case D: An application data message is being processed - */ - if( ssl->in_offt != NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: application data record is being processed" ) ); - return( 1 ); - } - - /* - * In all other cases, the rest of the message can be dropped. - * As in ssl_get_next_record, this needs to be adapted if - * we implement support for multiple alerts in single records. - */ - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: nothing pending" ) ); - return( 0 ); -} - uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ) { if( ssl->session != NULL ) @@ -9746,68 +4903,43 @@ const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ) } } -int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +size_t mbedtls_ssl_get_input_max_frag_len( const mbedtls_ssl_context *ssl ) { - size_t transform_expansion = 0; - const mbedtls_ssl_transform *transform = ssl->transform_out; - unsigned block_size; + size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t read_mfl; - size_t out_hdr_len = mbedtls_ssl_out_hdr_len( ssl ); - - if( transform == NULL ) - return( (int) out_hdr_len ); - -#if defined(MBEDTLS_ZLIB_SUPPORT) - if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL ) - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); -#endif - - switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) ) + /* Use the configured MFL for the client if we're past SERVER_HELLO_DONE */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ssl->state >= MBEDTLS_SSL_SERVER_HELLO_DONE ) { - case MBEDTLS_MODE_GCM: - case MBEDTLS_MODE_CCM: - case MBEDTLS_MODE_CHACHAPOLY: - case MBEDTLS_MODE_STREAM: - transform_expansion = transform->minlen; - break; - - case MBEDTLS_MODE_CBC: - - block_size = mbedtls_cipher_get_block_size( - &transform->cipher_ctx_enc ); - - /* Expansion due to the addition of the MAC. */ - transform_expansion += transform->maclen; - - /* Expansion due to the addition of CBC padding; - * Theoretically up to 256 bytes, but we never use - * more than the block size of the underlying cipher. */ - transform_expansion += block_size; - - /* For TLS 1.1 or higher, an explicit IV is added - * after the record header. */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - transform_expansion += block_size; -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ - - break; - - default: - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + return ssl_mfl_code_to_length( ssl->conf->mfl_code ); } -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) - if( transform->out_cid_len != 0 ) - transform_expansion += MBEDTLS_SSL_MAX_CID_EXPANSION; -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + /* Check if a smaller max length was negotiated */ + if( ssl->session_out != NULL ) + { + read_mfl = ssl_mfl_code_to_length( ssl->session_out->mfl_code ); + if( read_mfl < max_len ) + { + max_len = read_mfl; + } + } - return( (int)( out_hdr_len + transform_expansion ) ); + // During a handshake, use the value being negotiated + if( ssl->session_negotiate != NULL ) + { + read_mfl = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ); + if( read_mfl < max_len ) + { + max_len = read_mfl; + } + } + + return( max_len ); } -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) +size_t mbedtls_ssl_get_output_max_frag_len( const mbedtls_ssl_context *ssl ) { size_t max_len; @@ -9832,10 +4964,17 @@ size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) return( max_len ); } + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) +{ + return mbedtls_ssl_get_output_max_frag_len( ssl ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_PROTO_DTLS) -static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl ) +size_t mbedtls_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 && @@ -9864,16 +5003,16 @@ int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ) #endif #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_output_max_frag_len( ssl ); if( max_len > mfl ) max_len = mfl; #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl_get_current_mtu( ssl ) != 0 ) + if( mbedtls_ssl_get_current_mtu( ssl ) != 0 ) { - const size_t mtu = ssl_get_current_mtu( ssl ); + const size_t mtu = mbedtls_ssl_get_current_mtu( ssl ); const int ret = mbedtls_ssl_get_record_expansion( ssl ); const size_t overhead = (size_t) ret; @@ -10579,7 +5718,7 @@ static int ssl_write_hello_request( mbedtls_ssl_context *ssl ) * If the handshake doesn't complete due to waiting for I/O, it will continue * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively. */ -static int ssl_start_renegotiation( mbedtls_ssl_context *ssl ) +int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; @@ -10653,9 +5792,9 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ) if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_start_renegotiation( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation", ret ); return( ret ); } } @@ -10671,546 +5810,8 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ) return( ret ); } - -/* - * Check record counters and renegotiate if they're above the limit. - */ -static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) -{ - size_t ep_len = ssl_ep_len( ssl ); - int in_ctr_cmp; - int out_ctr_cmp; - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || - ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ) - { - return( 0 ); - } - - in_ctr_cmp = memcmp( ssl->in_ctr + ep_len, - ssl->conf->renego_period + ep_len, 8 - ep_len ); - out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len, - ssl->conf->renego_period + ep_len, 8 - ep_len ); - - if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 ) - { - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) ); - return( mbedtls_ssl_renegotiate( ssl ) ); -} #endif /* MBEDTLS_SSL_RENEGOTIATION */ -/* - * Receive application data decrypted from the SSL layer - */ -int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - return( ret ); - - if( ssl->handshake != NULL && - ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) - { - if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) - return( ret ); - } - } -#endif - - /* - * Check if renegotiation is necessary and/or handshake is - * in process. If yes, perform/continue, and fall through - * if an unexpected packet is received while the client - * is waiting for the ServerHello. - * - * (There is no equivalent to the last condition on - * the server-side as it is not treated as within - * a handshake while waiting for the ClientHello - * after a renegotiation request.) - */ - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ret = ssl_check_ctr_renegotiate( ssl ); - if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && - ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); - return( ret ); - } -#endif - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - { - ret = mbedtls_ssl_handshake( ssl ); - if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && - ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); - return( ret ); - } - } - - /* Loop as long as no application data record is available */ - while( ssl->in_offt == NULL ) - { - /* Start timer if not already running */ - if( ssl->f_get_timer != NULL && - ssl->f_get_timer( ssl->p_timer ) == -1 ) - { - ssl_set_timer( ssl, ssl->conf->read_timeout ); - } - - if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) - return( 0 ); - - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msglen == 0 && - ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA ) - { - /* - * OpenSSL sends empty messages to randomize the IV - */ - if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) - return( 0 ); - - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - } - - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); - - /* - * - For client-side, expect SERVER_HELLO_REQUEST. - * - For server-side, expect CLIENT_HELLO. - * - Fail (TLS) or silently drop record (DTLS) in other cases. - */ - -#if defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && - ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || - ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); - - /* With DTLS, drop the packet (probably from last handshake) */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - continue; - } -#endif - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } -#endif /* MBEDTLS_SSL_CLI_C */ - -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) ); - - /* With DTLS, drop the packet (probably from last handshake) */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - continue; - } -#endif - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } -#endif /* MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - /* Determine whether renegotiation attempt should be accepted */ - if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || - ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == - MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) ) - { - /* - * Accept renegotiation request - */ - - /* DTLS clients need to know renego is server-initiated */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - { - ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; - } -#endif - ret = ssl_start_renegotiation( ssl ); - if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && - ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - { - /* - * Refuse renegotiation - */ - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) ); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - /* SSLv3 does not have a "no_renegotiation" warning, so - we send a fatal alert and abort the connection. */ - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) - { - if( ( ret = mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_WARNING, - MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 ) - { - return( ret ); - } - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || - MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - - /* At this point, we don't know whether the renegotiation has been - * completed or not. The cases to consider are the following: - * 1) The renegotiation is complete. In this case, no new record - * has been read yet. - * 2) The renegotiation is incomplete because the client received - * an application data record while awaiting the ServerHello. - * 3) The renegotiation is incomplete because the client received - * a non-handshake, non-application data message while awaiting - * the ServerHello. - * In each of these case, looping will be the proper action: - * - For 1), the next iteration will read a new record and check - * if it's application data. - * - For 2), the loop condition isn't satisfied as application data - * is present, hence continue is the same as break - * - For 3), the loop condition is satisfied and read_record - * will re-deliver the message that was held back by the client - * when expecting the ServerHello. - */ - continue; - } -#if defined(MBEDTLS_SSL_RENEGOTIATION) - else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) - { - if( ssl->conf->renego_max_records >= 0 ) - { - if( ++ssl->renego_records_seen > ssl->conf->renego_max_records ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " - "but not honored by client" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - } - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - - /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */ - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) ); - return( MBEDTLS_ERR_SSL_WANT_READ ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - ssl->in_offt = ssl->in_msg; - - /* We're going to return something now, cancel timer, - * except if handshake (renegotiation) is in progress */ - if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) - ssl_set_timer( ssl, 0 ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - /* If we requested renego but received AppData, resend HelloRequest. - * Do it now, after setting in_offt, to avoid taking this branch - * again if ssl_write_hello_request() returns WANT_WRITE */ -#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) - { - if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret ); - return( ret ); - } - } -#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - } - - n = ( len < ssl->in_msglen ) - ? len : ssl->in_msglen; - - memcpy( buf, ssl->in_offt, n ); - ssl->in_msglen -= n; - - if( ssl->in_msglen == 0 ) - { - /* all bytes consumed */ - ssl->in_offt = NULL; - ssl->keep_current_message = 0; - } - else - { - /* more data available */ - ssl->in_offt += n; - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) ); - - return( (int) n ); -} - -/* - * Send application data to be encrypted by the SSL layer, taking care of max - * fragment length and buffer size. - * - * According to RFC 5246 Section 6.2.1: - * - * Zero-length fragments of Application data MAY be sent as they are - * potentially useful as a traffic analysis countermeasure. - * - * Therefore, it is possible that the input message length is 0 and the - * corresponding return code is 0 on success. - */ -static int ssl_write_real( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - int ret = mbedtls_ssl_get_max_out_record_payload( ssl ); - const size_t max_len = (size_t) ret; - - if( ret < 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret ); - return( ret ); - } - - if( len > max_len ) - { -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) " - "maximum fragment length: %d > %d", - len, max_len ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - else -#endif - len = max_len; - } - - if( ssl->out_left != 0 ) - { - /* - * The user has previously tried to send the data and - * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially - * written. In this case, we expect the high-level write function - * (e.g. mbedtls_ssl_write()) to be called with the same parameters - */ - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); - return( ret ); - } - } - else - { - /* - * The user is trying to send a message the first time, so we need to - * copy the data into the internal buffers and setup the data structure - * to keep track of partial writes - */ - ssl->out_msglen = len; - ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; - memcpy( ssl->out_msg, buf, len ); - - if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - } - - return( (int) len ); -} - -/* - * Write application data, doing 1/n-1 splitting if necessary. - * - * With non-blocking I/O, ssl_write_real() may return WANT_WRITE, - * then the caller will call us again with the same arguments, so - * remember whether we already did the split or not. - */ -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) -static int ssl_write_split( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if( ssl->conf->cbc_record_splitting == - MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED || - len <= 1 || - ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 || - mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ) - != MBEDTLS_MODE_CBC ) - { - return( ssl_write_real( ssl, buf, len ) ); - } - - if( ssl->split_done == 0 ) - { - if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 ) - return( ret ); - ssl->split_done = 1; - } - - if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 ) - return( ret ); - ssl->split_done = 0; - - return( ret + 1 ); -} -#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ - -/* - * Write application data (public-facing wrapper) - */ -int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) ); - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); - return( ret ); - } -#endif - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - { - if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); - return( ret ); - } - } - -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - ret = ssl_write_split( ssl, buf, len ); -#else - ret = ssl_write_real( ssl, buf, len ); -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) ); - - return( ret ); -} - -/* - * Notify the peer that the connection is being closed - */ -int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); - - if( ssl->out_left != 0 ) - return( mbedtls_ssl_flush_output( ssl ) ); - - if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) - { - if( ( ret = mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_WARNING, - MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret ); - return( ret ); - } - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) ); - - return( 0 ); -} - -void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ) -{ - if( transform == NULL ) - return; - -#if defined(MBEDTLS_ZLIB_SUPPORT) - deflateEnd( &transform->ctx_deflate ); - inflateEnd( &transform->ctx_inflate ); -#endif - - mbedtls_cipher_free( &transform->cipher_ctx_enc ); - mbedtls_cipher_free( &transform->cipher_ctx_dec ); - -#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) - mbedtls_md_free( &transform->md_ctx_enc ); - mbedtls_md_free( &transform->md_ctx_dec ); -#endif - - mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) ); -} - #if defined(MBEDTLS_X509_CRT_PARSE_C) static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert ) { @@ -11225,42 +5826,6 @@ static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert ) } #endif /* MBEDTLS_X509_CRT_PARSE_C */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - -static void ssl_buffering_free( mbedtls_ssl_context *ssl ) -{ - unsigned offset; - mbedtls_ssl_handshake_params * const hs = ssl->handshake; - - if( hs == NULL ) - return; - - ssl_free_buffered_record( ssl ); - - for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) - ssl_buffering_free_slot( ssl, offset ); -} - -static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, - uint8_t slot ) -{ - mbedtls_ssl_handshake_params * const hs = ssl->handshake; - mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot]; - - if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS ) - return; - - if( hs_buf->is_valid == 1 ) - { - hs->buffering.total_bytes_buffered -= hs_buf->data_len; - mbedtls_platform_zeroize( hs_buf->data, hs_buf->data_len ); - mbedtls_free( hs_buf->data ); - memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); - } -} - -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) { mbedtls_ssl_handshake_params *handshake = ssl->handshake; @@ -11319,7 +5884,7 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) mbedtls_free( (void *) handshake->curves ); #endif -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) if( handshake->psk != NULL ) { mbedtls_platform_zeroize( handshake->psk, handshake->psk_len ); @@ -11346,7 +5911,7 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) mbedtls_x509_crt_restart_free( &handshake->ecrs_ctx ); if( handshake->ecrs_peer_cert != NULL ) { @@ -11362,8 +5927,8 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_PROTO_DTLS) mbedtls_free( handshake->verify_cookie ); - ssl_flight_free( handshake->flight ); - ssl_buffering_free( ssl ); + mbedtls_ssl_flight_free( handshake->flight ); + mbedtls_ssl_buffering_free( ssl ); #endif #if defined(MBEDTLS_ECDH_C) && \ @@ -11373,6 +5938,65 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) mbedtls_platform_zeroize( handshake, sizeof( mbedtls_ssl_handshake_params ) ); + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + /* If the buffers are too big - reallocate. Because of the way Mbed TLS + * processes datagrams and the fact that a datagram is allowed to have + * several records in it, it is possible that the I/O buffers are not + * empty at this stage */ + { + int modified = 0; + uint32_t buf_len = mbedtls_ssl_get_input_buflen( ssl ); + size_t written_in = 0; + size_t written_out = 0; + if( ssl->in_buf != NULL ) + { + written_in = ssl->in_msg - ssl->in_buf; + if( ssl->in_buf_len > buf_len && ssl->in_left < buf_len ) + { + written_in = ssl->in_msg - ssl->in_buf; + if( resize_buffer( &ssl->in_buf, buf_len, &ssl->in_buf_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "input buffer resizing failed - out of memory" ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating in_buf to %d", buf_len ) ); + modified = 1; + } + } + } + + + buf_len = mbedtls_ssl_get_output_buflen( ssl ); + if(ssl->out_buf != NULL ) + { + written_out = ssl->out_msg - ssl->out_buf; + if( ssl->out_buf_len > mbedtls_ssl_get_output_buflen( ssl ) && + ssl->out_left < buf_len ) + { + if( resize_buffer( &ssl->out_buf, buf_len, &ssl->out_buf_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "output buffer resizing failed - out of memory" ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating out_buf to %d", buf_len ) ); + modified = 1; + } + } + } + if( modified ) + { + /* Update pointers here to avoid doing it twice. */ + mbedtls_ssl_reset_in_out_pointers( ssl ); + /* Fields below might not be properly updated with record + * splitting, so they are manually updated here. */ + ssl->out_msg = ssl->out_buf + written_out; + ssl->in_msg = ssl->in_buf + written_in; + } + } +#endif } void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) @@ -11709,7 +6333,7 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_BUF( 4, "saved context", buf, used ); - return( ssl_session_reset_int( ssl, 0 ) ); + return( mbedtls_ssl_session_reset_int( ssl, 0 ) ); } /* @@ -11806,7 +6430,7 @@ static int ssl_context_load( mbedtls_ssl_context *ssl, p += 4; /* This has been allocated by ssl_handshake_init(), called by - * by either ssl_session_reset_int() or mbedtls_ssl_setup(). */ + * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */ ssl->session = ssl->session_negotiate; ssl->session_in = ssl->session; ssl->session_out = ssl->session; @@ -11829,7 +6453,7 @@ static int ssl_context_load( mbedtls_ssl_context *ssl, */ /* This has been allocated by ssl_handshake_init(), called by - * by either ssl_session_reset_int() or mbedtls_ssl_setup(). */ + * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */ ssl->transform = ssl->transform_negotiate; ssl->transform_in = ssl->transform; ssl->transform_out = ssl->transform; @@ -11990,7 +6614,7 @@ static int ssl_context_load( mbedtls_ssl_context *ssl, /* Adjust pointers for header fields of outgoing records to * the given transform, accounting for explicit IV and CID. */ - ssl_update_out_pointers( ssl, ssl->transform ); + mbedtls_ssl_update_out_pointers( ssl, ssl->transform ); #if defined(MBEDTLS_SSL_PROTO_DTLS) ssl->in_epoch = 1; @@ -11998,7 +6622,8 @@ static int ssl_context_load( mbedtls_ssl_context *ssl, /* mbedtls_ssl_reset() leaves the handshake sub-structure allocated, * which we don't want - otherwise we'd end up freeing the wrong transform - * by calling ssl_handshake_wrapup_free_hs_transform() inappropriately. */ + * by calling mbedtls_ssl_handshake_wrapup_free_hs_transform() + * inappropriately. */ if( ssl->handshake != NULL ) { mbedtls_ssl_handshake_free( ssl ); @@ -12036,6 +6661,14 @@ int mbedtls_ssl_context_load( mbedtls_ssl_context *context, */ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) { +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; + size_t out_buf_len = ssl->out_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + if( ssl == NULL ) return; @@ -12043,14 +6676,16 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) if( ssl->out_buf != NULL ) { - mbedtls_platform_zeroize( ssl->out_buf, MBEDTLS_SSL_OUT_BUFFER_LEN ); + mbedtls_platform_zeroize( ssl->out_buf, out_buf_len ); mbedtls_free( ssl->out_buf ); + ssl->out_buf = NULL; } if( ssl->in_buf != NULL ) { - mbedtls_platform_zeroize( ssl->in_buf, MBEDTLS_SSL_IN_BUFFER_LEN ); + mbedtls_platform_zeroize( ssl->in_buf, in_buf_len ); mbedtls_free( ssl->in_buf ); + ssl->in_buf = NULL; } #if defined(MBEDTLS_ZLIB_SUPPORT) @@ -12118,7 +6753,7 @@ void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ) memset( conf, 0, sizeof( mbedtls_ssl_config ) ); } -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) static int ssl_preset_default_hashes[] = { #if defined(MBEDTLS_SHA512_C) MBEDTLS_MD_SHA512, @@ -12141,7 +6776,7 @@ static int ssl_preset_suiteb_ciphersuites[] = { 0 }; -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) static int ssl_preset_suiteb_hashes[] = { MBEDTLS_MD_SHA256, MBEDTLS_MD_SHA384, @@ -12270,7 +6905,7 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, conf->cert_profile = &mbedtls_x509_crt_profile_suiteb; #endif -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) conf->sig_hashes = ssl_preset_suiteb_hashes; #endif @@ -12309,7 +6944,7 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, conf->cert_profile = &mbedtls_x509_crt_profile_default; #endif -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) conf->sig_hashes = ssl_preset_default_hashes; #endif @@ -12335,7 +6970,7 @@ void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ) mbedtls_mpi_free( &conf->dhm_G ); #endif -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) if( conf->psk != NULL ) { mbedtls_platform_zeroize( conf->psk, conf->psk_len ); @@ -12410,7 +7045,7 @@ mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ) #endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_ECDSA_C ) */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* Find an entry in a signature-hash set matching a given hash algorithm. */ mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, @@ -12458,7 +7093,7 @@ void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, } #endif /* MBEDTLS_SSL_PROTO_TLS1_2) && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ /* * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX @@ -12544,7 +7179,7 @@ int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_i } #endif /* MBEDTLS_ECP_C */ -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* * Check if a hash proposed by the peer is in our list. * Return 0 if we're willing to use it, -1 otherwise. @@ -12563,7 +7198,7 @@ int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, return( -1 ); } -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_X509_CRT_PARSE_C) int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, @@ -12656,59 +7291,6 @@ int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, } #endif /* MBEDTLS_X509_CRT_PARSE_C */ -/* - * Convert version numbers to/from wire format - * and, for DTLS, to/from TLS equivalent. - * - * For TLS this is the identity. - * For DTLS, use 1's complement (v -> 255 - v, and then map as follows: - * 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1) - * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) - */ -void mbedtls_ssl_write_version( int major, int minor, int transport, - unsigned char ver[2] ) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - if( minor == MBEDTLS_SSL_MINOR_VERSION_2 ) - --minor; /* DTLS 1.0 stored as TLS 1.1 internally */ - - ver[0] = (unsigned char)( 255 - ( major - 2 ) ); - ver[1] = (unsigned char)( 255 - ( minor - 1 ) ); - } - else -#else - ((void) transport); -#endif - { - ver[0] = (unsigned char) major; - ver[1] = (unsigned char) minor; - } -} - -void mbedtls_ssl_read_version( int *major, int *minor, int transport, - const unsigned char ver[2] ) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - *major = 255 - ver[0] + 2; - *minor = 255 - ver[1] + 1; - - if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 ) - ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */ - } - else -#else - ((void) transport); -#endif - { - *major = ver[0]; - *minor = ver[1]; - } -} - int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) diff --git a/features/mbedtls/mbed-crypto/src/threading.c b/features/mbedtls/src/threading.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/threading.c rename to features/mbedtls/src/threading.c diff --git a/features/mbedtls/mbed-crypto/src/timing.c b/features/mbedtls/src/timing.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/timing.c rename to features/mbedtls/src/timing.c diff --git a/features/mbedtls/src/version_features.c b/features/mbedtls/src/version_features.c index cc47dacc94..d16ad1bacd 100644 --- a/features/mbedtls/src/version_features.c +++ b/features/mbedtls/src/version_features.c @@ -300,6 +300,9 @@ static const char * const features[] = { #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) "MBEDTLS_CIPHER_PADDING_ZEROS", #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) + "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY", +#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ #if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) "MBEDTLS_ENABLE_WEAK_CIPHERSUITES", #endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ @@ -417,6 +420,9 @@ static const char * const features[] = { #if defined(MBEDTLS_ENTROPY_NV_SEED) "MBEDTLS_ENTROPY_NV_SEED", #endif /* MBEDTLS_ENTROPY_NV_SEED */ +#if defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER) + "MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER", +#endif /* MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER */ #if defined(MBEDTLS_MEMORY_DEBUG) "MBEDTLS_MEMORY_DEBUG", #endif /* MBEDTLS_MEMORY_DEBUG */ @@ -447,6 +453,12 @@ static const char * const features[] = { #if defined(MBEDTLS_SHA256_SMALLER) "MBEDTLS_SHA256_SMALLER", #endif /* MBEDTLS_SHA256_SMALLER */ +#if defined(MBEDTLS_SHA512_SMALLER) + "MBEDTLS_SHA512_SMALLER", +#endif /* MBEDTLS_SHA512_SMALLER */ +#if defined(MBEDTLS_SHA512_NO_SHA384) + "MBEDTLS_SHA512_NO_SHA384", +#endif /* MBEDTLS_SHA512_NO_SHA384 */ #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) "MBEDTLS_SSL_ALL_ALERT_MESSAGES", #endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ @@ -540,6 +552,9 @@ static const char * const features[] = { #if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT", #endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */ +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH", +#endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */ #if defined(MBEDTLS_THREADING_ALT) "MBEDTLS_THREADING_ALT", #endif /* MBEDTLS_THREADING_ALT */ @@ -723,6 +738,9 @@ static const char * const features[] = { #if defined(MBEDTLS_PSA_CRYPTO_C) "MBEDTLS_PSA_CRYPTO_C", #endif /* MBEDTLS_PSA_CRYPTO_C */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + "MBEDTLS_PSA_CRYPTO_SE_C", +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) "MBEDTLS_PSA_CRYPTO_STORAGE_C", #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ diff --git a/features/mbedtls/src/x509.c b/features/mbedtls/src/x509.c index 7f8181be27..c451332c28 100644 --- a/features/mbedtls/src/x509.c +++ b/features/mbedtls/src/x509.c @@ -1064,7 +1064,7 @@ cleanup: mbedtls_x509_crt_free( &clicert ); #else ((void) verbose); -#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA256_C */ return( ret ); } diff --git a/features/mbedtls/src/x509_crl.c b/features/mbedtls/src/x509_crl.c index d1176fcef3..371c446be5 100644 --- a/features/mbedtls/src/x509_crl.c +++ b/features/mbedtls/src/x509_crl.c @@ -541,7 +541,7 @@ int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, s { #if defined(MBEDTLS_PEM_PARSE_C) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t use_len; + size_t use_len = 0; mbedtls_pem_context pem; int is_pem = 0; diff --git a/features/mbedtls/src/x509_crt.c b/features/mbedtls/src/x509_crt.c index 38e69cc550..1e472303b1 100644 --- a/features/mbedtls/src/x509_crt.c +++ b/features/mbedtls/src/x509_crt.c @@ -2538,7 +2538,7 @@ static int x509_crt_find_parent_in( { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_x509_crt *parent, *fallback_parent; - int signature_is_good, fallback_signature_is_good; + int signature_is_good = 0, fallback_signature_is_good; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* did we have something in progress? */ diff --git a/features/mbedtls/src/x509write_csr.c b/features/mbedtls/src/x509write_csr.c index 0c3c39672d..7c5179862c 100644 --- a/features/mbedtls/src/x509write_csr.c +++ b/features/mbedtls/src/x509write_csr.c @@ -214,7 +214,9 @@ int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, s return( MBEDTLS_ERR_X509_FATAL_ERROR ); } #else /* MBEDTLS_USE_PSA_CRYPTO */ - mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); + ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); + if( ret != 0 ) + return( ret ); #endif if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, f_rng, p_rng ) ) != 0 ) diff --git a/features/mbedtls/mbed-crypto/src/xtea.c b/features/mbedtls/src/xtea.c similarity index 100% rename from features/mbedtls/mbed-crypto/src/xtea.c rename to features/mbedtls/src/xtea.c From 53260ebd7753ed845fd90fc98300c3401d0ea067 Mon Sep 17 00:00:00 2001 From: Darryl Green Date: Thu, 26 Mar 2020 17:12:03 +0000 Subject: [PATCH 3/7] Use updated ECC curve macros Signed-off-by: Darryl Green --- TESTS/psa/attestation/main.cpp | 2 +- .../COMPONENT_PSA_SRV_IMPL/attest_crypto_keys.c | 13 ++----------- .../frameworks/TARGET_PSA/pal/pal_mbed_os_intf.cpp | 2 +- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/TESTS/psa/attestation/main.cpp b/TESTS/psa/attestation/main.cpp index 52430eea28..4bba662405 100755 --- a/TESTS/psa/attestation/main.cpp +++ b/TESTS/psa/attestation/main.cpp @@ -98,7 +98,7 @@ static void check_initial_attestation_get_token() TEST_ASSERT_EQUAL(status, PSA_SUCCESS); status = psa_attestation_inject_key(private_key_data, sizeof(private_key_data), - PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1), + PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1), exported, sizeof(exported), &exported_length); diff --git a/components/TARGET_PSA/services/attestation/COMPONENT_PSA_SRV_IMPL/attest_crypto_keys.c b/components/TARGET_PSA/services/attestation/COMPONENT_PSA_SRV_IMPL/attest_crypto_keys.c index e3b19a0749..e67227c8ff 100755 --- a/components/TARGET_PSA/services/attestation/COMPONENT_PSA_SRV_IMPL/attest_crypto_keys.c +++ b/components/TARGET_PSA/services/attestation/COMPONENT_PSA_SRV_IMPL/attest_crypto_keys.c @@ -48,21 +48,12 @@ static psa_status_t get_curve(psa_key_type_t type, enum ecc_curve_t *curve_type) { psa_ecc_curve_t curve = PSA_KEY_TYPE_GET_CURVE(type); switch (curve) { - case PSA_ECC_CURVE_SECP256R1: + case PSA_ECC_CURVE_SECP_R1: *curve_type = P_256; break; - case PSA_ECC_CURVE_SECP384R1: - *curve_type = P_384; - break; - case PSA_ECC_CURVE_SECP521R1: - *curve_type = P_521; - break; - case PSA_ECC_CURVE_CURVE25519: + case PSA_ECC_CURVE_MONTGOMERY: *curve_type = X25519; break; - case PSA_ECC_CURVE_CURVE448: - *curve_type = X448; - break; default: return (PSA_ERROR_NOT_SUPPORTED); } diff --git a/features/frameworks/TARGET_PSA/pal/pal_mbed_os_intf.cpp b/features/frameworks/TARGET_PSA/pal/pal_mbed_os_intf.cpp index 435f882642..d33fa900d0 100644 --- a/features/frameworks/TARGET_PSA/pal/pal_mbed_os_intf.cpp +++ b/features/frameworks/TARGET_PSA/pal/pal_mbed_os_intf.cpp @@ -63,7 +63,7 @@ static void psa_attestation_inject_key_for_test(void) psa_attestation_destroy_key_for_test(); psa_attestation_inject_key(private_key_data, sizeof(private_key_data), - PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1), + PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1), exported, sizeof(exported), &exported_length); From d64c9e53c8085b325dc6d2b1805e6a0a5fb4f8f8 Mon Sep 17 00:00:00 2001 From: Darryl Green Date: Fri, 3 Apr 2020 14:19:47 +0100 Subject: [PATCH 4/7] Move Mbed Crypto Greentea tests to Mbed TLS Signed-off-by: Darryl Green --- TESTS/{mbed-crypto => mbedtls}/sanity/main.cpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename TESTS/{mbed-crypto => mbedtls}/sanity/main.cpp (100%) diff --git a/TESTS/mbed-crypto/sanity/main.cpp b/TESTS/mbedtls/sanity/main.cpp similarity index 100% rename from TESTS/mbed-crypto/sanity/main.cpp rename to TESTS/mbedtls/sanity/main.cpp From 0d16ca4d8a73f22296fc9458db70fc08a0cfc60f Mon Sep 17 00:00:00 2001 From: Darryl Green Date: Thu, 2 Apr 2020 15:12:49 +0100 Subject: [PATCH 5/7] Remove references to mbed-crypto Signed-off-by: Darryl Green --- TESTS/configs/baremetal.json | 1 - UNITTESTS/CMakeLists.txt | 1 - UNITTESTS/empty_baseline/unittest.cmake | 2 +- .../TARGET_PSA/services/COMPONENT_PSA_SRV_IMPL/mbed_lib.json | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/TESTS/configs/baremetal.json b/TESTS/configs/baremetal.json index ceaef136d7..c6a83768d5 100644 --- a/TESTS/configs/baremetal.json +++ b/TESTS/configs/baremetal.json @@ -5,7 +5,6 @@ "utest", "unity", "psa", - "mbed-crypto", "mbedtls", "psa-compliance-framework", "filesystem", diff --git a/UNITTESTS/CMakeLists.txt b/UNITTESTS/CMakeLists.txt index 52f46f5f9d..b6b1d6b6af 100644 --- a/UNITTESTS/CMakeLists.txt +++ b/UNITTESTS/CMakeLists.txt @@ -144,7 +144,6 @@ set(unittest-includes-base "${PROJECT_SOURCE_DIR}/../features/lorawan/system" "${PROJECT_SOURCE_DIR}/../features/mbedtls" "${PROJECT_SOURCE_DIR}/../features/mbedtls/inc" - "${PROJECT_SOURCE_DIR}/../features/mbedtls/mbed-crypto/inc" "${PROJECT_SOURCE_DIR}/../features/storage/kvstore/conf" ) diff --git a/UNITTESTS/empty_baseline/unittest.cmake b/UNITTESTS/empty_baseline/unittest.cmake index 78bb6577db..6c0a6d96f9 100644 --- a/UNITTESTS/empty_baseline/unittest.cmake +++ b/UNITTESTS/empty_baseline/unittest.cmake @@ -6,7 +6,7 @@ set(unittest-includes ${unittest-includes} . .. - ../features/mbedtls/mbed-crypto/inc/mbedtls/ + ../features/mbedtls/inc/mbedtls/ ../features/mbedtls/platform/inc/ ../features/frameworks/mbed-trace/mbed-trace/ ) diff --git a/components/TARGET_PSA/services/COMPONENT_PSA_SRV_IMPL/mbed_lib.json b/components/TARGET_PSA/services/COMPONENT_PSA_SRV_IMPL/mbed_lib.json index 9e4db97006..ac6c485773 100644 --- a/components/TARGET_PSA/services/COMPONENT_PSA_SRV_IMPL/mbed_lib.json +++ b/components/TARGET_PSA/services/COMPONENT_PSA_SRV_IMPL/mbed_lib.json @@ -4,7 +4,6 @@ "drivers", "platform", "mbedtls", - "mbed-crypto", "storage", "flashiap-block-device", "tdbstore", From 1a6a8495efcaefea0df7dc3b1cd50c8c0984568a Mon Sep 17 00:00:00 2001 From: Darryl Green Date: Fri, 24 Apr 2020 15:21:14 +0100 Subject: [PATCH 6/7] Define mbedtls_ecc_group_to_psa inline for NS world Signed-off-by: Darryl Green --- features/mbedtls/inc/psa/crypto_extra.h | 50 ++++++++++++++++++- .../COMPONENT_PSA_SRV_IMPL/psa_crypto.c | 49 ------------------ 2 files changed, 48 insertions(+), 51 deletions(-) diff --git a/features/mbedtls/inc/psa/crypto_extra.h b/features/mbedtls/inc/psa/crypto_extra.h index e9fa31189c..64ab1bfe65 100644 --- a/features/mbedtls/inc/psa/crypto_extra.h +++ b/features/mbedtls/inc/psa/crypto_extra.h @@ -578,8 +578,54 @@ psa_status_t psa_get_key_domain_parameters( * (`PSA_ECC_CURVE_xxx`). * \return \c 0 on failure (\p grpid is not recognized). */ -psa_ecc_curve_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid, - size_t *bits ); +static inline psa_ecc_curve_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid, + size_t *bits ) +{ + switch( grpid ) + { + case MBEDTLS_ECP_DP_SECP192R1: + *bits = 192; + return( PSA_ECC_CURVE_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP224R1: + *bits = 224; + return( PSA_ECC_CURVE_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP256R1: + *bits = 256; + return( PSA_ECC_CURVE_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP384R1: + *bits = 384; + return( PSA_ECC_CURVE_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP521R1: + *bits = 521; + return( PSA_ECC_CURVE_SECP_R1 ); + case MBEDTLS_ECP_DP_BP256R1: + *bits = 256; + return( PSA_ECC_CURVE_BRAINPOOL_P_R1 ); + case MBEDTLS_ECP_DP_BP384R1: + *bits = 384; + return( PSA_ECC_CURVE_BRAINPOOL_P_R1 ); + case MBEDTLS_ECP_DP_BP512R1: + *bits = 512; + return( PSA_ECC_CURVE_BRAINPOOL_P_R1 ); + case MBEDTLS_ECP_DP_CURVE25519: + *bits = 255; + return( PSA_ECC_CURVE_MONTGOMERY ); + case MBEDTLS_ECP_DP_SECP192K1: + *bits = 192; + return( PSA_ECC_CURVE_SECP_K1 ); + case MBEDTLS_ECP_DP_SECP224K1: + *bits = 224; + return( PSA_ECC_CURVE_SECP_K1 ); + case MBEDTLS_ECP_DP_SECP256K1: + *bits = 256; + return( PSA_ECC_CURVE_SECP_K1 ); + case MBEDTLS_ECP_DP_CURVE448: + *bits = 448; + return( PSA_ECC_CURVE_MONTGOMERY ); + default: + return( 0 ); + } +} /** Convert an ECC curve identifier from the PSA encoding to Mbed TLS. * diff --git a/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto.c b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto.c index 733a2e46c4..69323184d0 100644 --- a/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto.c +++ b/features/mbedtls/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto.c @@ -375,55 +375,6 @@ static inline int psa_key_slot_is_external( const psa_key_slot_t *slot ) #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #if defined(MBEDTLS_ECP_C) -psa_ecc_curve_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid, - size_t *bits ) -{ - switch( grpid ) - { - case MBEDTLS_ECP_DP_SECP192R1: - *bits = 192; - return( PSA_ECC_CURVE_SECP_R1 ); - case MBEDTLS_ECP_DP_SECP224R1: - *bits = 224; - return( PSA_ECC_CURVE_SECP_R1 ); - case MBEDTLS_ECP_DP_SECP256R1: - *bits = 256; - return( PSA_ECC_CURVE_SECP_R1 ); - case MBEDTLS_ECP_DP_SECP384R1: - *bits = 384; - return( PSA_ECC_CURVE_SECP_R1 ); - case MBEDTLS_ECP_DP_SECP521R1: - *bits = 521; - return( PSA_ECC_CURVE_SECP_R1 ); - case MBEDTLS_ECP_DP_BP256R1: - *bits = 256; - return( PSA_ECC_CURVE_BRAINPOOL_P_R1 ); - case MBEDTLS_ECP_DP_BP384R1: - *bits = 384; - return( PSA_ECC_CURVE_BRAINPOOL_P_R1 ); - case MBEDTLS_ECP_DP_BP512R1: - *bits = 512; - return( PSA_ECC_CURVE_BRAINPOOL_P_R1 ); - case MBEDTLS_ECP_DP_CURVE25519: - *bits = 255; - return( PSA_ECC_CURVE_MONTGOMERY ); - case MBEDTLS_ECP_DP_SECP192K1: - *bits = 192; - return( PSA_ECC_CURVE_SECP_K1 ); - case MBEDTLS_ECP_DP_SECP224K1: - *bits = 224; - return( PSA_ECC_CURVE_SECP_K1 ); - case MBEDTLS_ECP_DP_SECP256K1: - *bits = 256; - return( PSA_ECC_CURVE_SECP_K1 ); - case MBEDTLS_ECP_DP_CURVE448: - *bits = 448; - return( PSA_ECC_CURVE_MONTGOMERY ); - default: - return( 0 ); - } -} - mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_curve_t curve, size_t byte_length ) { From 7fbc143b0556956142231410816918d6b3c67c7b Mon Sep 17 00:00:00 2001 From: Darryl Green Date: Tue, 28 Apr 2020 16:40:55 +0100 Subject: [PATCH 7/7] Fix assertation ordering in tests Signed-off-by: Darryl Green --- TESTS/psa/attestation/main.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/TESTS/psa/attestation/main.cpp b/TESTS/psa/attestation/main.cpp index 4bba662405..c7305cae25 100755 --- a/TESTS/psa/attestation/main.cpp +++ b/TESTS/psa/attestation/main.cpp @@ -95,7 +95,7 @@ static void check_initial_attestation_get_token() uint32_t token_size; status = psa_crypto_init(); - TEST_ASSERT_EQUAL(status, PSA_SUCCESS); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); status = psa_attestation_inject_key(private_key_data, sizeof(private_key_data), PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1), @@ -103,21 +103,21 @@ static void check_initial_attestation_get_token() sizeof(exported), &exported_length); - TEST_ASSERT_EQUAL(status, PSA_SUCCESS); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); TEST_ASSERT_EQUAL(sizeof(public_key_data), exported_length); - TEST_ASSERT_EQUAL(memcmp(public_key_data, exported, exported_length), 0); + TEST_ASSERT_EQUAL(0, memcmp(public_key_data, exported, exported_length)); attest_err = psa_initial_attest_get_token_size(TEST_CHALLENGE_OBJ_SIZE, &token_size); - TEST_ASSERT_EQUAL(attest_err, PSA_ATTEST_ERR_SUCCESS); + TEST_ASSERT_EQUAL(PSA_ATTEST_ERR_SUCCESS, attest_err); attest_err = psa_initial_attest_get_token(challenge_buffer, TEST_CHALLENGE_OBJ_SIZE, token_buffer, &token_size); - TEST_ASSERT_EQUAL(attest_err, PSA_ATTEST_ERR_SUCCESS); + TEST_ASSERT_EQUAL(PSA_ATTEST_ERR_SUCCESS, attest_err); } /***************************************************************************************/