diff --git a/TESTS/configs/baremetal.json b/TESTS/configs/baremetal.json index ceaef136d72..c6a83768d5c 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/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 diff --git a/TESTS/psa/attestation/main.cpp b/TESTS/psa/attestation/main.cpp index 52430eea28c..c7305cae254 100755 --- a/TESTS/psa/attestation/main.cpp +++ b/TESTS/psa/attestation/main.cpp @@ -95,29 +95,29 @@ 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_SECP256R1), + PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1), exported, 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); } /***************************************************************************************/ diff --git a/UNITTESTS/CMakeLists.txt b/UNITTESTS/CMakeLists.txt index 52f46f5f9d7..b6b1d6b6af7 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 78bb6577dbd..6c0a6d96f95 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 9e4db970062..ac6c4857730 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", 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 e3b19a07491..e67227c8ff7 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 435f8826423..d33fa900d0a 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); diff --git a/features/mbedtls/LICENSE b/features/mbedtls/LICENSE index 546a8e631f5..d6456956733 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 b3a4b2d74cc..4961d31884b 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/importer/Makefile b/features/mbedtls/importer/Makefile index 6cb40940140..021db7bb6a3 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 74d3a5b7665..a68783cf936 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 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 1c6683f63e4..4c61b6e1c33 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 7e0e3575c81..8db78254061 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 361cf569cf8..b268734be0c 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 a0e979f0c2a..ccdd75c63a3 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 e6b459dc110..bdf7e5e19da 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 831cfd74b8a..6dcfadd82cc 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 d04cc49b62b..4c05b4fd0aa 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 bb876efc5bd..0922dff9d34 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 d9f45db6768..cf8d8c42978 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 2e7393b3ce8..513bc5feb78 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 48923e5bc6a..8e54ce01a77 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 655f59d328c..1c98a5e5a88 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 - -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); +#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 */ + #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 for the output buffer. + */ +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. + * \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_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 5505e521506..7fbafa48d43 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 f703da99b43..f83d01454fd 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 ae694eeda23..b89e36efd55 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 9c610838e1b..2b07b7471c6 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 00000000000..1ed5f052b2a --- /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 86% rename from features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h rename to features/mbedtls/inc/psa/crypto_extra.h index 31e339c1671..64ab1bfe65c 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,96 @@ 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). + */ +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. + * + * \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 e7aef5580e1..1f04222c249 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 c4f9acd4609..d96c66e5c4a 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 dbe75ad85e4..baaabff1e0d 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. - * - * 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. - */ -#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) - -/** Minimum 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_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_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 prime fields. + * + * 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_SECP_K1 ((psa_ecc_curve_t) 0x17) + +/** SEC random curves over prime fields. + * + * 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_SECP_R1 ((psa_ecc_curve_t) 0x12) +/* SECP160R2 (SEC2 v1, obsolete) */ +#define PSA_ECC_CURVE_SECP_R2 ((psa_ecc_curve_t) 0x1b) + +/** 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 546a8e631f5..00000000000 --- 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 481f3641bd7..00000000000 --- 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 d6456956733..00000000000 --- 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 0964ab4e6d6..00000000000 --- 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 05fd348e289..00000000000 --- 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 dc11da389f5..00000000000 --- 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 2addde4c150..00000000000 --- 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 9f55484e2fe..938abd07b89 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 97% 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 4450fdb56d6..69323184d0f 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,69 @@ 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 ) -{ - switch( grpid ) - { - case MBEDTLS_ECP_DP_SECP192R1: - return( PSA_ECC_CURVE_SECP192R1 ); - case MBEDTLS_ECP_DP_SECP224R1: - return( PSA_ECC_CURVE_SECP224R1 ); - case MBEDTLS_ECP_DP_SECP256R1: - return( PSA_ECC_CURVE_SECP256R1 ); - case MBEDTLS_ECP_DP_SECP384R1: - return( PSA_ECC_CURVE_SECP384R1 ); - case MBEDTLS_ECP_DP_SECP521R1: - return( PSA_ECC_CURVE_SECP521R1 ); - case MBEDTLS_ECP_DP_BP256R1: - return( PSA_ECC_CURVE_BRAINPOOL_P256R1 ); - case MBEDTLS_ECP_DP_BP384R1: - return( PSA_ECC_CURVE_BRAINPOOL_P384R1 ); - case MBEDTLS_ECP_DP_BP512R1: - return( PSA_ECC_CURVE_BRAINPOOL_P512R1 ); - case MBEDTLS_ECP_DP_CURVE25519: - return( PSA_ECC_CURVE_CURVE25519 ); - case MBEDTLS_ECP_DP_SECP192K1: - return( PSA_ECC_CURVE_SECP192K1 ); - case MBEDTLS_ECP_DP_SECP224K1: - return( PSA_ECC_CURVE_SECP224K1 ); - case MBEDTLS_ECP_DP_SECP256K1: - return( PSA_ECC_CURVE_SECP256K1 ); - case MBEDTLS_ECP_DP_CURVE448: - return( PSA_ECC_CURVE_CURVE448 ); - 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 +586,8 @@ static psa_status_t psa_import_rsa_key( psa_key_type_t type, #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 +596,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 +627,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 +666,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 +2049,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 +2103,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 +2171,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 +2245,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 +2320,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 +2363,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 +2463,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 +2749,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 +3100,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 +5265,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 +5290,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 +5580,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 1389fd45166..fa1214c86d2 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 bc9363db22d..f9cd468a5fc 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 - - -# Look in crypto for libmbedcrypto. -LOCAL_LDFLAGS += -L../crypto/library -LOCAL_CFLAGS += -I../crypto/include -CRYPTO := ../crypto/library/ +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 + +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.$(SOEXT_CRYPTO): $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_CRYPTO) -libmbedcrypto.$(DLEXT): $(CRYPTO)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) -$(CRYPTO)libmbedcrypto.$(DLEXT): | libmbedcrypto.a - $(MAKE) CRYPTO_INCLUDES:="-I../../include -I../include" -C ../crypto/library libmbedcrypto.$(DLEXT) +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 e7e4d13f68e..34c660775d6 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,61 +321,67 @@ int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end return( 0 ); } - - -/* - * Parses and splits an ASN.1 "SEQUENCE OF " - */ -int mbedtls_asn1_get_sequence_of( unsigned char **p, - const unsigned char *end, - mbedtls_asn1_sequence *cur, - int tag) +void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq ) { - 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 ) + while( seq != NULL ) { - buf = &(cur->buf); - buf->tag = **p; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 ) - return( ret ); + mbedtls_asn1_sequence *next = seq->next; + mbedtls_platform_zeroize( seq, sizeof( *seq ) ); + mbedtls_free( seq ); + seq = next; + } +} - buf->p = *p; - *p += buf->len; +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; - /* Allocate and assign next pointer */ - if( *p < end ) - { - cur->next = (mbedtls_asn1_sequence*)mbedtls_calloc( 1, - sizeof( mbedtls_asn1_sequence ) ); + if( cur->buf.p != NULL ) + { + cur->next = + mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); - if( cur->next == NULL ) - return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + if( cur->next == NULL ) + return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); - cur = cur->next; - } + cur = cur->next; } - /* Set final sequence entry's next pointer to NULL */ - cur->next = NULL; - - if( *p != end ) - return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + 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 " + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag) +{ + 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, const unsigned char *end, mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ) 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 61d18101fb0..d53aefd5b07 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 b62f1d5939b..409c3fe6742 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 e9c4315bfd0..5acd2d00e88 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 e156fcbe2de..d3e42a94db9 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 c451f4ddff8..ee9c852b597 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 379035ddbb5..82df597a4c6 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 b2352034b89..b56c2ddfe1a 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 9d4100bb986..b83ba8e71d4 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 2c665af3c8b..f736431495f 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 596dae919f3..1cbb8cc339e 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 ) + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, &T, + NULL, NULL ) ) != 0 ) goto cleanup; - p += len; - /* Complete the RSA private key */ - if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 ) - goto cleanup; +#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 - /* 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 ) + /* 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 49a21bf08b1..b1b5f4685a2 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 3c2f31438cc..6c457468ead 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 fa4025653dd..30dd719540c 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 @@ int mbedtls_sha512_self_test( int verbose ) 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 518f7dde00f..5da12941240 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 1005bd97fa8..553e2b6a31e 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 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) 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 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) 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 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) 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 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) 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 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) 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 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) 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 @@ static int ssl_parse_server_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_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 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) 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 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) 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 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) 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 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) } } 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 @@ static int ssl_write_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_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 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) 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 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) 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 @@ static int ssl_write_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_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 00000000000..976fc7b00b0 --- /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 b0b09cd97fa..006bc69c300 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 @@ static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) 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 @@ static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) 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 @@ static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) #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 @@ static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) } #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 @@ static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) /* 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 @@ 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 @@ -3238,7 +3239,7 @@ static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, 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 @@ static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, * 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 @@ static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, 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 6cf7781f2ac..d0adfd9515d 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,4707 +1967,305 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch return( 0 ); } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#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 */ +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) +static int ssl_write_hello_request( mbedtls_ssl_context *ssl ); -/* 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 ) +#if defined(MBEDTLS_SSL_PROTO_DTLS) +int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl ) { - 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 renegotiation is not enforced, retransmit until we would reach max + * timeout if we were using the usual handshake doubling scheme */ + if( ssl->conf->renego_max_records < 0 ) + { + uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1; + unsigned char doublings = 1; -#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--; + while( ratio != 0 ) + { + ++doublings; + ratio >>= 1; + } - if( remaining < pad ) - return( -1 ); - memset( content + len, 0, pad ); - len += pad; - remaining -= pad; + if( ++ssl->renego_records_seen > doublings ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "no longer retransmitting hello request" ) ); + return( 0 ); + } + } - *content_size = len; - return( 0 ); + return( ssl_write_hello_request( ssl ) ); } +#endif +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ -/* 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 ) +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void ssl_clear_peer_cert( mbedtls_ssl_session *session ) { - size_t remaining = *content_size; - - /* Determine length of padding by skipping zeroes from the back. */ - do +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + if( session->peer_cert != NULL ) { - if( remaining == 0 ) - return( -1 ); - remaining--; - } while( content[ remaining ] == 0 ); - - *content_size = remaining; - *rec_type = content[ remaining ]; - - return( 0 ); + mbedtls_x509_crt_free( session->peer_cert ); + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( session->peer_cert_digest != NULL ) + { + /* Zeroization is not necessary. */ + mbedtls_free( session->peer_cert_digest ); + session->peer_cert_digest = NULL; + session->peer_cert_digest_type = MBEDTLS_MD_NONE; + session->peer_cert_digest_len = 0; + } +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ } -#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ -/* `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 ) +/* + * Handshake functions + */ +#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* No certificate support -> dummy functions */ +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) { - /* 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; - */ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; - memcpy( add_data, rec->ctr, sizeof( rec->ctr ) ); - add_data[8] = rec->type; - memcpy( add_data + 9, rec->ver, sizeof( rec->ver ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); -#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 */ + if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) { - add_data[11 + 0] = ( rec->data_len >> 8 ) & 0xFF; - add_data[11 + 1] = ( rec->data_len >> 0 ) & 0xFF; - *add_data_len = 13; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } -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 ) +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) { - 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 + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); - 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 - ) + if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to encrypt_buf" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); } - 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 ); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} - mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ); +#else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ +/* Some certificate support -> implement write and parse */ - 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 ); - } +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, n; + const mbedtls_x509_crt *crt; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; -#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 ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); - if( rec->cid_len != 0 ) + if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) { - /* - * 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; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); } -#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 defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) { - if( post_avail < transform->maclen ) + if( ssl->client_auth == 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); } #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 ) + /* + * If using SSLv3 and got no cert, send an Alert message + * (otherwise an empty Certificate message will be sent). + */ + if( mbedtls_ssl_own_cert( ssl ) == NULL && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) { - 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 ); + ssl->out_msglen = 2; + ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl->out_msg[0] = MBEDTLS_SSL_ALERT_LEVEL_WARNING; + ssl->out_msg[1] = MBEDTLS_SSL_ALERT_MSG_NO_CERT; - 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_MSG( 2, ( "got no certificate to send" ) ); + goto write_msg; } - - 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_PROTO_SSL3 */ } -#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ - - /* - * Encrypt - */ -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) - if( mode == MBEDTLS_MODE_STREAM ) +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) { - 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 ) + if( mbedtls_ssl_own_cert( ssl ) == NULL ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) ); + return( MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED ); } } - 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 ); +#endif - 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 ) ); + MBEDTLS_SSL_DEBUG_CRT( 3, "own certificate", mbedtls_ssl_own_cert( ssl ) ); - /* - * Encrypt and authenticate - */ + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 6 length of all certs + * 7 . 9 length of cert. 1 + * 10 . n-1 peer certificate + * n . n+2 length of cert. 2 + * n+3 . ... upper level cert, etc. + */ + i = 7; + crt = mbedtls_ssl_own_cert( ssl ); - 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 ) + while( crt != NULL ) + { + n = crt->raw.len; + if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret ); - return( ret ); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", + i + 3 + n, MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ); } - MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag", - data + rec->data_len, transform->taglen ); + ssl->out_msg[i ] = (unsigned char)( n >> 16 ); + ssl->out_msg[i + 1] = (unsigned char)( n >> 8 ); + ssl->out_msg[i + 2] = (unsigned char)( n ); - rec->data_len += transform->taglen + explicit_iv_len; - rec->data_offset -= explicit_iv_len; - post_avail -= transform->taglen; - auth_done++; + i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n ); + i += n; crt = crt->next; } - 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 ); - } + ssl->out_msg[4] = (unsigned char)( ( i - 7 ) >> 16 ); + ssl->out_msg[5] = (unsigned char)( ( i - 7 ) >> 8 ); + ssl->out_msg[6] = (unsigned char)( ( i - 7 ) ); - for( i = 0; i <= padlen; i++ ) - data[rec->data_len + i] = (unsigned char) padlen; + ssl->out_msglen = i; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; - rec->data_len += padlen + 1; - post_avail -= padlen + 1; +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) +write_msg: +#endif -#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 ); - } + ssl->state++; - 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 ); - } + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } - /* - * Generate IV - */ - ret = f_rng( p_rng, transform->iv_enc, transform->ivlen ); - if( ret != 0 ) - return( ret ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate" ) ); - memcpy( data - transform->ivlen, transform->iv_enc, - transform->ivlen ); + return( ret ); +} - } -#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 defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) - if( rec->data_len != olen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl, + unsigned char *crt_buf, + size_t crt_buf_len ) +{ + mbedtls_x509_crt const * const peer_crt = ssl->session->peer_cert; -#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( peer_crt == NULL ) + return( -1 ); -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - if( auth_done == 0 ) - { - unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + if( peer_crt->raw.len != crt_buf_len ) + return( -1 ); - /* - * 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)); - */ + return( memcmp( peer_crt->raw.p, crt_buf, peer_crt->raw.len ) ); +} +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl, + unsigned char *crt_buf, + size_t crt_buf_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char const * const peer_cert_digest = + ssl->session->peer_cert_digest; + mbedtls_md_type_t const peer_cert_digest_type = + ssl->session->peer_cert_digest_type; + mbedtls_md_info_t const * const digest_info = + mbedtls_md_info_from_type( peer_cert_digest_type ); + unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN]; + size_t digest_len; - 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( peer_cert_digest == NULL || digest_info == NULL ) + return( -1 ); - ssl_extract_add_data_from_record( add_data, &add_data_len, rec ); + digest_len = mbedtls_md_get_size( digest_info ); + if( digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN ) + return( -1 ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); - MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data, - add_data_len ); + ret = mbedtls_md( digest_info, crt_buf, crt_buf_len, tmp_digest ); + if( ret != 0 ) + return( -1 ); - 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 ); + return( memcmp( tmp_digest, peer_cert_digest, digest_len ) ); +} +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ - memcpy( data + rec->data_len, mac, transform->maclen ); +/* + * Once the certificate message is read, parse it into a cert chain and + * perform basic checks, but leave actual verification to the caller + */ +static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *chain ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + int crt_cnt=0; +#endif + size_t i, n; + uint8_t alert; - 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 ) */ + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } - /* Make extra sure authentication was performed, exactly once */ - if( auth_done != 1 ) + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE || + ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); } - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); + i = mbedtls_ssl_hs_hdr_len( ssl ); - 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 */ - -#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 ) -{ - /* If renegotiation is not enforced, retransmit until we would reach max - * timeout if we were using the usual handshake doubling scheme */ - if( ssl->conf->renego_max_records < 0 ) - { - uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1; - unsigned char doublings = 1; - - while( ratio != 0 ) - { - ++doublings; - ratio >>= 1; - } - - if( ++ssl->renego_records_seen > doublings ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "no longer retransmitting hello request" ) ); - return( 0 ); - } - } - - return( ssl_write_hello_request( 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 ) -{ -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - if( session->peer_cert != NULL ) - { - mbedtls_x509_crt_free( session->peer_cert ); - mbedtls_free( session->peer_cert ); - session->peer_cert = NULL; - } -#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - if( session->peer_cert_digest != NULL ) - { - /* Zeroization is not necessary. */ - mbedtls_free( session->peer_cert_digest ); - session->peer_cert_digest = NULL; - session->peer_cert_digest_type = MBEDTLS_MD_NONE; - session->peer_cert_digest_len = 0; - } -#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -/* - * Handshake functions - */ -#if !defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -/* No certificate support -> dummy functions */ -int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) -{ - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->handshake->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); - - if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); - ssl->state++; - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); -} - -int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) -{ - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->handshake->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); - - if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - ssl->state++; - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); -} - -#else /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ -/* Some certificate support -> implement write and parse */ - -int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - size_t i, n; - const mbedtls_x509_crt *crt; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->handshake->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); - - if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); - ssl->state++; - return( 0 ); - } - -#if defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - { - if( ssl->client_auth == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); - ssl->state++; - return( 0 ); - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - /* - * If using SSLv3 and got no cert, send an Alert message - * (otherwise an empty Certificate message will be sent). - */ - if( mbedtls_ssl_own_cert( ssl ) == NULL && - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - ssl->out_msglen = 2; - ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; - ssl->out_msg[0] = MBEDTLS_SSL_ALERT_LEVEL_WARNING; - ssl->out_msg[1] = MBEDTLS_SSL_ALERT_MSG_NO_CERT; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) ); - goto write_msg; - } -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - } -#endif /* MBEDTLS_SSL_CLI_C */ -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - { - if( mbedtls_ssl_own_cert( ssl ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) ); - return( MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED ); - } - } -#endif - - MBEDTLS_SSL_DEBUG_CRT( 3, "own certificate", mbedtls_ssl_own_cert( ssl ) ); - - /* - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 6 length of all certs - * 7 . 9 length of cert. 1 - * 10 . n-1 peer certificate - * n . n+2 length of cert. 2 - * n+3 . ... upper level cert, etc. - */ - i = 7; - crt = mbedtls_ssl_own_cert( ssl ); - - while( crt != NULL ) - { - n = crt->raw.len; - if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", - i + 3 + n, MBEDTLS_SSL_OUT_CONTENT_LEN ) ); - return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ); - } - - ssl->out_msg[i ] = (unsigned char)( n >> 16 ); - ssl->out_msg[i + 1] = (unsigned char)( n >> 8 ); - ssl->out_msg[i + 2] = (unsigned char)( n ); - - i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n ); - i += n; crt = crt->next; - } - - ssl->out_msg[4] = (unsigned char)( ( i - 7 ) >> 16 ); - ssl->out_msg[5] = (unsigned char)( ( i - 7 ) >> 8 ); - ssl->out_msg[6] = (unsigned char)( ( i - 7 ) ); - - ssl->out_msglen = i; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; - -#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) -write_msg: -#endif - - 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 certificate" ) ); - - return( ret ); -} - -#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) - -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) -static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl, - unsigned char *crt_buf, - size_t crt_buf_len ) -{ - mbedtls_x509_crt const * const peer_crt = ssl->session->peer_cert; - - if( peer_crt == NULL ) - return( -1 ); - - if( peer_crt->raw.len != crt_buf_len ) - return( -1 ); - - return( memcmp( peer_crt->raw.p, crt_buf, peer_crt->raw.len ) ); -} -#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl, - unsigned char *crt_buf, - size_t crt_buf_len ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char const * const peer_cert_digest = - ssl->session->peer_cert_digest; - mbedtls_md_type_t const peer_cert_digest_type = - ssl->session->peer_cert_digest_type; - mbedtls_md_info_t const * const digest_info = - mbedtls_md_info_from_type( peer_cert_digest_type ); - unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN]; - size_t digest_len; - - if( peer_cert_digest == NULL || digest_info == NULL ) - return( -1 ); - - digest_len = mbedtls_md_get_size( digest_info ); - if( digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN ) - return( -1 ); - - ret = mbedtls_md( digest_info, crt_buf, crt_buf_len, tmp_digest ); - if( ret != 0 ) - return( -1 ); - - return( memcmp( tmp_digest, peer_cert_digest, digest_len ) ); -} -#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ - -/* - * Once the certificate message is read, parse it into a cert chain and - * perform basic checks, but leave actual verification to the caller - */ -static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl, - mbedtls_x509_crt *chain ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; -#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) - int crt_cnt=0; -#endif - size_t i, n; - uint8_t alert; - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE || - ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - i = mbedtls_ssl_hs_hdr_len( ssl ); - - /* - * Same message structure as in mbedtls_ssl_write_certificate() - */ - n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2]; + /* + * Same message structure as in mbedtls_ssl_write_certificate() + */ + n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2]; if( ssl->in_msg[i] != 0 || ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( 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 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) 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 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) 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 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, 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 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, * 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 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 + size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t read_mfl; - 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; + return ssl_mfl_code_to_length( ssl->conf->mfl_code ); + } - default: - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + /* 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; + } } -#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 */ + // 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( (int)( out_hdr_len + transform_expansion ) ); + 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; @@ -10193,1023 +5332,485 @@ static int ssl_session_save( const mbedtls_ssl_session *session, { *p++ = (unsigned char)( ( session->ticket_len >> 16 ) & 0xFF ); *p++ = (unsigned char)( ( session->ticket_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( session->ticket_len ) & 0xFF ); - - if( session->ticket != NULL ) - { - memcpy( p, session->ticket, session->ticket_len ); - p += session->ticket_len; - } - - *p++ = (unsigned char)( ( session->ticket_lifetime >> 24 ) & 0xFF ); - *p++ = (unsigned char)( ( session->ticket_lifetime >> 16 ) & 0xFF ); - *p++ = (unsigned char)( ( session->ticket_lifetime >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( session->ticket_lifetime ) & 0xFF ); - } -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ - - /* - * Misc extension-related info - */ -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - used += 1; - - if( used <= buf_len ) - *p++ = session->mfl_code; -#endif - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - used += 1; - - if( used <= buf_len ) - *p++ = (unsigned char)( ( session->trunc_hmac ) & 0xFF ); -#endif - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - used += 1; - - if( used <= buf_len ) - *p++ = (unsigned char)( ( session->encrypt_then_mac ) & 0xFF ); -#endif - - /* Done */ - *olen = used; - - if( used > buf_len ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - - return( 0 ); -} - -/* - * Public wrapper for ssl_session_save() - */ -int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, - unsigned char *buf, - size_t buf_len, - size_t *olen ) -{ - return( ssl_session_save( session, 0, buf, buf_len, olen ) ); -} - -/* - * Deserialize session, see mbedtls_ssl_session_save() for format. - * - * This internal version is wrapped by a public function that cleans up in - * case of error, and has an extra option omit_header. - */ -static int ssl_session_load( mbedtls_ssl_session *session, - unsigned char omit_header, - const unsigned char *buf, - size_t len ) -{ - const unsigned char *p = buf; - const unsigned char * const end = buf + len; -#if defined(MBEDTLS_HAVE_TIME) - uint64_t start; -#endif -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - size_t cert_len; -#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - if( !omit_header ) - { - /* - * Check version identifier - */ - - if( (size_t)( end - p ) < sizeof( ssl_serialized_session_header ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( memcmp( p, ssl_serialized_session_header, - sizeof( ssl_serialized_session_header ) ) != 0 ) - { - return( MBEDTLS_ERR_SSL_VERSION_MISMATCH ); - } - p += sizeof( ssl_serialized_session_header ); - } - - /* - * Time - */ -#if defined(MBEDTLS_HAVE_TIME) - if( 8 > (size_t)( end - p ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - start = ( (uint64_t) p[0] << 56 ) | - ( (uint64_t) p[1] << 48 ) | - ( (uint64_t) p[2] << 40 ) | - ( (uint64_t) p[3] << 32 ) | - ( (uint64_t) p[4] << 24 ) | - ( (uint64_t) p[5] << 16 ) | - ( (uint64_t) p[6] << 8 ) | - ( (uint64_t) p[7] ); - p += 8; - - session->start = (time_t) start; -#endif /* MBEDTLS_HAVE_TIME */ - - /* - * Basic mandatory fields - */ - if( 2 + 1 + 1 + 32 + 48 + 4 > (size_t)( end - p ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - session->ciphersuite = ( p[0] << 8 ) | p[1]; - p += 2; - - session->compression = *p++; - - session->id_len = *p++; - memcpy( session->id, p, 32 ); - p += 32; - - memcpy( session->master, p, 48 ); - p += 48; - - session->verify_result = ( (uint32_t) p[0] << 24 ) | - ( (uint32_t) p[1] << 16 ) | - ( (uint32_t) p[2] << 8 ) | - ( (uint32_t) p[3] ); - p += 4; - - /* Immediately clear invalid pointer values that have been read, in case - * we exit early before we replaced them with valid ones. */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - session->peer_cert = NULL; -#else - session->peer_cert_digest = NULL; -#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) - session->ticket = NULL; -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ - - /* - * Peer certificate - */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - /* Deserialize CRT from the end of the ticket. */ - if( 3 > (size_t)( end - p ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; - p += 3; - - if( cert_len != 0 ) - { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if( cert_len > (size_t)( end - p ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); - - if( session->peer_cert == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - mbedtls_x509_crt_init( session->peer_cert ); - - if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, - p, cert_len ) ) != 0 ) - { - mbedtls_x509_crt_free( session->peer_cert ); - mbedtls_free( session->peer_cert ); - session->peer_cert = NULL; - return( ret ); - } - - p += cert_len; - } -#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - /* Deserialize CRT digest from the end of the ticket. */ - if( 2 > (size_t)( end - p ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - session->peer_cert_digest_type = (mbedtls_md_type_t) *p++; - session->peer_cert_digest_len = (size_t) *p++; - - if( session->peer_cert_digest_len != 0 ) - { - const mbedtls_md_info_t *md_info = - mbedtls_md_info_from_type( session->peer_cert_digest_type ); - if( md_info == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - if( session->peer_cert_digest_len != mbedtls_md_get_size( md_info ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( session->peer_cert_digest_len > (size_t)( end - p ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - session->peer_cert_digest = - mbedtls_calloc( 1, session->peer_cert_digest_len ); - if( session->peer_cert_digest == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - memcpy( session->peer_cert_digest, p, - session->peer_cert_digest_len ); - p += session->peer_cert_digest_len; - } -#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - /* - * Session ticket and associated data - */ -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) - if( 3 > (size_t)( end - p ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - session->ticket_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; - p += 3; - - if( session->ticket_len != 0 ) - { - if( session->ticket_len > (size_t)( end - p ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + *p++ = (unsigned char)( ( session->ticket_len ) & 0xFF ); - session->ticket = mbedtls_calloc( 1, session->ticket_len ); - if( session->ticket == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + if( session->ticket != NULL ) + { + memcpy( p, session->ticket, session->ticket_len ); + p += session->ticket_len; + } - memcpy( session->ticket, p, session->ticket_len ); - p += session->ticket_len; + *p++ = (unsigned char)( ( session->ticket_lifetime >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_lifetime >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_lifetime >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_lifetime ) & 0xFF ); } - - if( 4 > (size_t)( end - p ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - session->ticket_lifetime = ( (uint32_t) p[0] << 24 ) | - ( (uint32_t) p[1] << 16 ) | - ( (uint32_t) p[2] << 8 ) | - ( (uint32_t) p[3] ); - p += 4; #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ /* * Misc extension-related info */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - if( 1 > (size_t)( end - p ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + used += 1; - session->mfl_code = *p++; + if( used <= buf_len ) + *p++ = session->mfl_code; #endif #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - if( 1 > (size_t)( end - p ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + used += 1; - session->trunc_hmac = *p++; + if( used <= buf_len ) + *p++ = (unsigned char)( ( session->trunc_hmac ) & 0xFF ); #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - if( 1 > (size_t)( end - p ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + used += 1; - session->encrypt_then_mac = *p++; + if( used <= buf_len ) + *p++ = (unsigned char)( ( session->encrypt_then_mac ) & 0xFF ); #endif - /* Done, should have consumed entire buffer */ - if( p != end ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + /* Done */ + *olen = used; + + if( used > buf_len ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); return( 0 ); } /* - * Deserialize session: public wrapper for error cleaning + * Public wrapper for ssl_session_save() */ -int mbedtls_ssl_session_load( mbedtls_ssl_session *session, - const unsigned char *buf, - size_t len ) +int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len, + size_t *olen ) { - int ret = ssl_session_load( session, 0, buf, len ); - - if( ret != 0 ) - mbedtls_ssl_session_free( session ); - - return( ret ); + return( ssl_session_save( session, 0, buf, buf_len, olen ) ); } /* - * Perform a single step of the SSL handshake + * Deserialize session, see mbedtls_ssl_session_save() for format. + * + * This internal version is wrapped by a public function that cleans up in + * case of error, and has an extra option omit_header. */ -int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ) +static int ssl_session_load( mbedtls_ssl_session *session, + unsigned char omit_header, + const unsigned char *buf, + size_t len ) { - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - -#if defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - ret = mbedtls_ssl_handshake_client_step( ssl ); -#endif -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - ret = mbedtls_ssl_handshake_server_step( ssl ); + const unsigned char *p = buf; + const unsigned char * const end = buf + len; +#if defined(MBEDTLS_HAVE_TIME) + uint64_t start; #endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + size_t cert_len; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ - return( ret ); -} - -/* - * Perform the SSL handshake - */ -int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ) -{ - int ret = 0; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); - - while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + if( !omit_header ) { - ret = mbedtls_ssl_handshake_step( ssl ); - - if( ret != 0 ) - break; - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= handshake" ) ); - - return( ret ); -} - -#if defined(MBEDTLS_SSL_RENEGOTIATION) -#if defined(MBEDTLS_SSL_SRV_C) -/* - * Write HelloRequest to request renegotiation on server - */ -static int ssl_write_hello_request( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello request" ) ); + /* + * Check version identifier + */ - ssl->out_msglen = 4; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; + if( (size_t)( end - p ) < sizeof( ssl_serialized_session_header ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); - return( ret ); + if( memcmp( p, ssl_serialized_session_header, + sizeof( ssl_serialized_session_header ) ) != 0 ) + { + return( MBEDTLS_ERR_SSL_VERSION_MISMATCH ); + } + p += sizeof( ssl_serialized_session_header ); } - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello request" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_SRV_C */ + /* + * Time + */ +#if defined(MBEDTLS_HAVE_TIME) + if( 8 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); -/* - * Actually renegotiate current connection, triggered by either: - * - any side: calling mbedtls_ssl_renegotiate(), - * - client: receiving a HelloRequest during mbedtls_ssl_read(), - * - server: receiving any handshake message on server during mbedtls_ssl_read() after - * the initial handshake is completed. - * 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 ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + start = ( (uint64_t) p[0] << 56 ) | + ( (uint64_t) p[1] << 48 ) | + ( (uint64_t) p[2] << 40 ) | + ( (uint64_t) p[3] << 32 ) | + ( (uint64_t) p[4] << 24 ) | + ( (uint64_t) p[5] << 16 ) | + ( (uint64_t) p[6] << 8 ) | + ( (uint64_t) p[7] ); + p += 8; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) ); + session->start = (time_t) start; +#endif /* MBEDTLS_HAVE_TIME */ - if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) - return( ret ); + /* + * Basic mandatory fields + */ + if( 2 + 1 + 1 + 32 + 48 + 4 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and - * the ServerHello will have message_seq = 1" */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) - { - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - ssl->handshake->out_msg_seq = 1; - else - ssl->handshake->in_msg_seq = 1; - } -#endif + session->ciphersuite = ( p[0] << 8 ) | p[1]; + p += 2; - ssl->state = MBEDTLS_SSL_HELLO_REQUEST; - ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; + session->compression = *p++; - if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); - return( ret ); - } + session->id_len = *p++; + memcpy( session->id, p, 32 ); + p += 32; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) ); + memcpy( session->master, p, 48 ); + p += 48; - return( 0 ); -} + session->verify_result = ( (uint32_t) p[0] << 24 ) | + ( (uint32_t) p[1] << 16 ) | + ( (uint32_t) p[2] << 8 ) | + ( (uint32_t) p[3] ); + p += 4; -/* - * Renegotiate current connection on client, - * or request renegotiation on server - */ -int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + /* Immediately clear invalid pointer values that have been read, in case + * we exit early before we replaced them with valid ones. */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + session->peer_cert = NULL; +#else + session->peer_cert_digest = NULL; +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + session->ticket = NULL; +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ - if( ssl == NULL || ssl->conf == NULL ) + /* + * Peer certificate + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* Deserialize CRT from the end of the ticket. */ + if( 3 > (size_t)( end - p ) ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); -#if defined(MBEDTLS_SSL_SRV_C) - /* On server, just send the request */ - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; + p += 3; + + if( cert_len != 0 ) { - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + if( cert_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - /* Did we already try/start sending HelloRequest? */ - if( ssl->out_left != 0 ) - return( mbedtls_ssl_flush_output( ssl ) ); + session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); - return( ssl_write_hello_request( ssl ) ); - } -#endif /* MBEDTLS_SSL_SRV_C */ + if( session->peer_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); -#if defined(MBEDTLS_SSL_CLI_C) - /* - * On client, either start the renegotiation process or, - * if already in progress, continue the handshake - */ - if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - { - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + mbedtls_x509_crt_init( session->peer_cert ); - if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); - return( ret ); - } - } - else - { - if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, + p, cert_len ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + mbedtls_x509_crt_free( session->peer_cert ); + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; return( ret ); } - } -#endif /* MBEDTLS_SSL_CLI_C */ - - 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 ); + p += cert_len; } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + /* Deserialize CRT digest from the end of the ticket. */ + if( 2 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - 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 ); + session->peer_cert_digest_type = (mbedtls_md_type_t) *p++; + session->peer_cert_digest_len = (size_t) *p++; - if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 ) + if( session->peer_cert_digest_len != 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 ); + const mbedtls_md_info_t *md_info = + mbedtls_md_info_from_type( session->peer_cert_digest_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( session->peer_cert_digest_len != mbedtls_md_get_size( md_info ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) ); + if( session->peer_cert_digest_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - return( ret ); + session->peer_cert_digest = + mbedtls_calloc( 1, session->peer_cert_digest_len ); + if( session->peer_cert_digest == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - if( ssl->handshake != NULL && - ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) - { - if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) - return( ret ); - } + memcpy( session->peer_cert_digest, p, + session->peer_cert_digest_len ); + p += session->peer_cert_digest_len; } -#endif +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ /* - * 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.) + * Session ticket and associated data */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if( 3 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); -#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 ); - } - } + session->ticket_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; + p += 3; - /* Loop as long as no application data record is available */ - while( ssl->in_offt == NULL ) + if( session->ticket_len != 0 ) { - /* 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( session->ticket_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - 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 ); + session->ticket = mbedtls_calloc( 1, session->ticket_len ); + if( session->ticket == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - } + memcpy( session->ticket, p, session->ticket_len ); + p += session->ticket_len; + } - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); + if( 4 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - /* - * - For client-side, expect SERVER_HELLO_REQUEST. - * - For server-side, expect CLIENT_HELLO. - * - Fail (TLS) or silently drop record (DTLS) in other cases. - */ + session->ticket_lifetime = ( (uint32_t) p[0] << 24 ) | + ( (uint32_t) p[1] << 16 ) | + ( (uint32_t) p[2] << 8 ) | + ( (uint32_t) p[3] ); + p += 4; +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ -#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)" ) ); + /* + * Misc extension-related info + */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if( 1 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - /* With DTLS, drop the packet (probably from last handshake) */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - continue; - } + session->mfl_code = *p++; #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)" ) ); +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + if( 1 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - /* With DTLS, drop the packet (probably from last handshake) */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - continue; - } + session->trunc_hmac = *p++; #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 - */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( 1 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - /* 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; - } + session->encrypt_then_mac = *p++; #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 ); - } + /* Done, should have consumed entire buffer */ + if( p != end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - ssl->in_offt = ssl->in_msg; + return( 0 ); +} - /* 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 ); +/* + * Deserialize session: public wrapper for error cleaning + */ +int mbedtls_ssl_session_load( mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len ) +{ + int ret = ssl_session_load( session, 0, buf, len ); -#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 */ - } + if( ret != 0 ) + mbedtls_ssl_session_free( session ); - n = ( len < ssl->in_msglen ) - ? len : ssl->in_msglen; + return( ret ); +} - memcpy( buf, ssl->in_offt, n ); - ssl->in_msglen -= n; +/* + * Perform a single step of the SSL handshake + */ +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - 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; - } + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) ); +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ret = mbedtls_ssl_handshake_client_step( ssl ); +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ret = mbedtls_ssl_handshake_server_step( ssl ); +#endif - return( (int) n ); + return( ret ); } /* - * 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. + * Perform the SSL handshake */ -static int ssl_write_real( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ) { - int ret = mbedtls_ssl_get_max_out_record_payload( ssl ); - const size_t max_len = (size_t) ret; + int ret = 0; - if( ret < 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret ); - return( ret ); - } + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - 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; - } + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); - 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 + while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) { - /* - * 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 ); + ret = mbedtls_ssl_handshake_step( ssl ); - if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } + if( ret != 0 ) + break; } - return( (int) len ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= handshake" ) ); + + return( ret ); } +#if defined(MBEDTLS_SSL_RENEGOTIATION) +#if defined(MBEDTLS_SSL_SRV_C) /* - * 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. + * Write HelloRequest to request renegotiation on server */ -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) -static int ssl_write_split( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) +static int ssl_write_hello_request( mbedtls_ssl_context *ssl ) { 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 ) ); - } + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello request" ) ); - if( ssl->split_done == 0 ) + ssl->out_msglen = 4; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 ) - return( ret ); - ssl->split_done = 1; + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); } - if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 ) - return( ret ); - ssl->split_done = 0; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello request" ) ); - return( ret + 1 ); + return( 0 ); } -#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ +#endif /* MBEDTLS_SSL_SRV_C */ /* - * Write application data (public-facing wrapper) + * Actually renegotiate current connection, triggered by either: + * - any side: calling mbedtls_ssl_renegotiate(), + * - client: receiving a HelloRequest during mbedtls_ssl_read(), + * - server: receiving any handshake message on server during mbedtls_ssl_read() after + * the initial handshake is completed. + * 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. */ -int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) +int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) ); - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) + /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and + * the ServerHello will have message_seq = 1" */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); - return( ret ); + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->handshake->out_msg_seq = 1; + else + ssl->handshake->in_msg_seq = 1; } #endif - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; + + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) { - if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); - return( ret ); - } + 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" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) ); - return( ret ); + return( 0 ); } /* - * Notify the peer that the connection is being closed + * Renegotiate current connection on client, + * or request renegotiation on server */ -int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ) +int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; if( ssl == NULL || ssl->conf == NULL ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); +#if defined(MBEDTLS_SSL_SRV_C) + /* On server, just send the request */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; - if( ssl->out_left != 0 ) - return( mbedtls_ssl_flush_output( ssl ) ); + /* Did we already try/start sending HelloRequest? */ + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + + return( ssl_write_hello_request( ssl ) ); + } +#endif /* MBEDTLS_SSL_SRV_C */ - if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) +#if defined(MBEDTLS_SSL_CLI_C) + /* + * On client, either start the renegotiation process or, + * if already in progress, continue the handshake + */ + if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) { - if( ( ret = mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_WARNING, - MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 ) + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ssl_start_renegotiation( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation", ret ); return( ret ); } } + else + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_CLI_C */ - 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 ) ); + return( ret ); } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ #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 cc47dacc947..d16ad1bacdb 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 7f8181be273..c451332c287 100644 --- a/features/mbedtls/src/x509.c +++ b/features/mbedtls/src/x509.c @@ -1064,7 +1064,7 @@ int mbedtls_x509_self_test( int verbose ) 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 d1176fcef37..371c446be58 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 38e69cc550c..1e472303b16 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 0c3c39672db..7c5179862c1 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