Squashed commit upgrading to mbedtls-2.22.0
Squash merging branch import/mbedtls-2.22.0
5cab03377186 ("mk/clang.mk: define libgcc$(sm)")
3607a5386a72 ("core: mbedtls: enable MBEDTLS_ECDH_LEGACY_CONTEXT")
896c8845bbda ("mbedtls: remove file md_wrap.c from build")
400b2af54fa0 ("libmbedtls: mbedtls_mpi_exp_mod(): optimize mempool usage")
777827c7af3d ("libmbedtls: mbedtls_mpi_exp_mod(): reduce stack usage")
549e4600678e ("libmbedtls: preserve mempool usage on reinit")
02d636083fe2 ("libmbedtls: mbedtls_mpi_exp_mod() initialize W")
d2ac2b3c92bf ("libmbedtls: fix no CRT issue")
f550879d5be2 ("libmbedtls: add interfaces in mbedtls for context memory operation")
219173d807ce ("libmedtls: mpi_miller_rabin: increase count limit")
7930b0b6b5e4 ("libmbedtls: add mbedtls_mpi_init_mempool()")
78af9fdc120f ("libmbedtls: make mbedtls_mpi_mont*() available")
8f7357271cc2 ("libmbedtls: refine mbedtls license header")
c5993878881f ("mbedtls: configure mbedtls to reach for config")
6f9c587783af ("mbedtls: remove default include/mbedtls/config.h")
3d3bd3b12752 ("Import mbedtls-2.22.0")
Signed-off-by: Jerome Forissier <jerome@forissier.org>
Acked-by: Jens Wiklander <jens.wiklander@linaro.org>
diff --git a/lib/libmbedtls/mbedtls/CONTRIBUTING.md b/lib/libmbedtls/mbedtls/CONTRIBUTING.md
index 18851db..c1ae452 100644
--- a/lib/libmbedtls/mbedtls/CONTRIBUTING.md
+++ b/lib/libmbedtls/mbedtls/CONTRIBUTING.md
@@ -5,11 +5,6 @@
- As with any open source project, contributions will be reviewed by the project team and community and may need some modifications to be accepted.
- The contribution should not break API or ABI, unless there is a real justification for that. If there is an API change, the contribution, if accepted, will be merged only when there will be a major release.
-Contributor License Agreement (CLA)
------------------------------------
-- All contributions, whether large or small, require a Contributor's License Agreement (CLA) to be accepted. This is because source code can possibly fall under copyright law and we need your consent to share in the ownership of the copyright.
-- To accept the Contributor’s License Agreement (CLA), individual contributors can do this by creating an Mbed account and [accepting the online agreement here with a click through](https://developer.mbed.org/contributor_agreement/). Alternatively, for contributions from corporations, or those that do not wish to create an Mbed account, a slightly different agreement can be found [here](https://www.mbed.com/en/about-mbed/contributor-license-agreements/). This agreement should be signed and returned to Arm as described in the instructions given.
-
Coding Standards
----------------
- We would ask that contributions conform to [our coding standards](https://tls.mbed.org/kb/development/mbedtls-coding-standards), and that contributions are fully tested before submission, as mentioned in the [Tests](#tests) and [Continuous Integration](#continuous-integration-tests) sections.
@@ -24,7 +19,8 @@
1. Write a test which shows that the bug was fixed or that the feature works as expected.
1. Send a pull request (PR) and work with us until it gets merged and published. Contributions may need some modifications, so a few rounds of review and fixing may be necessary. We will include your name in the ChangeLog :)
1. For quick merging, the contribution should be short, and concentrated on a single feature or topic. The larger the contribution is, the longer it would take to review it and merge it.
-1. Mbed TLS is released under the Apache license, and as such, all the added files should include the Apache license header.
+1. All new files should include the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) standard license header where possible.
+1. Ensure that each commit has at least one `Signed-off-by:` line from the committer. If anyone else contributes to the commit, they should also add their own `Signed-off-by:` line. By adding this line, contributor(s) certify that the contribution is made under the terms of the [Developer Certificate of Origin](dco.txt). The contribution licensing is described in the [License section of the README](README.md#License).
API/ABI Compatibility
---------------------
@@ -46,18 +42,14 @@
When backporting to these branches please observe the following rules:
- 1. Any change to the library which changes the API or ABI cannot be backported.
-
- 2. All bug fixes that correct a defect that is also present in an LTS branch must be backported to that LTS branch. If a bug fix introduces a change to the API such as a new function, the fix should be reworked to avoid the API change. API changes without very strong justification are unlikely to be accepted.
-
- 3. If a contribution is a new feature or enhancement, no backporting is required. Exceptions to this may be additional test cases or quality improvements such as changes to build or test scripts.
+1. Any change to the library which changes the API or ABI cannot be backported.
+1. All bug fixes that correct a defect that is also present in an LTS branch must be backported to that LTS branch. If a bug fix introduces a change to the API such as a new function, the fix should be reworked to avoid the API change. API changes without very strong justification are unlikely to be accepted.
+1. If a contribution is a new feature or enhancement, no backporting is required. Exceptions to this may be additional test cases or quality improvements such as changes to build or test scripts.
It would be highly appreciated if contributions are backported to LTS branches in addition to the [development branch](https://github.com/ARMmbed/mbedtls/tree/development) by contributors.
Currently maintained LTS branches are:
-
1. [mbedtls-2.7](https://github.com/ARMmbed/mbedtls/tree/mbedtls-2.7)
-
1. [mbedtls-2.16](https://github.com/ARMmbed/mbedtls/tree/mbedtls-2.16)
@@ -84,12 +76,7 @@
Mbed TLS is well documented, but if you think documentation is needed, speak out!
1. All interfaces should be documented through Doxygen. New APIs should introduce Doxygen documentation.
-
-2. Complex parts in the code should include comments.
-
-3. If needed, a Readme file is advised.
-
-4. If a [Knowledge Base (KB)](https://tls.mbed.org/kb) article should be added, write this as a comment in the PR description.
-
-5. A [ChangeLog](https://github.com/ARMmbed/mbedtls/blob/development/ChangeLog) entry should be added for this contribution.
-
+1. Complex parts in the code should include comments.
+1. If needed, a Readme file is advised.
+1. If a [Knowledge Base (KB)](https://tls.mbed.org/kb) article should be added, write this as a comment in the PR description.
+1. A [ChangeLog](https://github.com/ARMmbed/mbedtls/blob/development/ChangeLog) entry should be added for this contribution.
diff --git a/lib/libmbedtls/mbedtls/ChangeLog b/lib/libmbedtls/mbedtls/ChangeLog
index 7a27fde..062a1ad 100644
--- a/lib/libmbedtls/mbedtls/ChangeLog
+++ b/lib/libmbedtls/mbedtls/ChangeLog
@@ -1,6 +1,61 @@
mbed TLS ChangeLog (Sorted per branch, date)
-= mbed TLS 2.16.5 branch released 2020-02-20
+= mbed TLS 2.22.0 branch released 2020-04-14
+
+New deprecations
+ * Deprecate MBEDTLS_SSL_HW_RECORD_ACCEL that enables function hooks in the
+ SSL module for hardware acceleration of individual records.
+ * Deprecate mbedtls_ssl_get_max_frag_len() in favour of
+ mbedtls_ssl_get_output_max_frag_len() and
+ mbedtls_ssl_get_input_max_frag_len() to be more precise about which max
+ fragment length is desired.
+
+Security
+ * Fix issue in DTLS handling of new associations with the same parameters
+ (RFC 6347 section 4.2.8): an attacker able to send forged UDP packets to
+ the server could cause it to drop established associations with
+ legitimate clients, resulting in a Denial of Service. This could only
+ happen when MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE was enabled in config.h
+ (which it is by default).
+ * Fix side channel in ECC code that allowed an adversary with access to
+ precise enough timing and memory access information (typically an
+ untrusted operating system attacking a secure enclave) to fully recover
+ an ECDSA private key. Found and reported by Alejandro Cabrera Aldaya,
+ Billy Brumley and Cesar Pereida Garcia. CVE-2020-10932
+ * Fix a potentially remotely exploitable buffer overread in a
+ DTLS client when parsing the Hello Verify Request message.
+
+Features
+ * The new build option MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH automatically
+ resizes the I/O buffers before and after handshakes, reducing the memory
+ consumption during application data transfer.
+
+Bugfix
+ * Fix compilation failure when both MBEDTLS_SSL_PROTO_DTLS and
+ MBEDTLS_SSL_HW_RECORD_ACCEL are enabled.
+ * Remove a spurious check in ssl_parse_client_psk_identity that triggered
+ a warning with some compilers. Fix contributed by irwir in #2856.
+ * Fix a function name in a debug message. Contributed by Ercan Ozturk in
+ #3013.
+
+Changes
+ * Mbed Crypto is no longer a Git submodule. The crypto part of the library
+ is back directly in the present repository.
+ * Split mbedtls_ssl_get_max_frag_len() into
+ mbedtls_ssl_get_output_max_frag_len() and
+ mbedtls_ssl_get_input_max_frag_len() to ensure that a sufficient input
+ buffer is allocated by the server (if MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH
+ is defined), regardless of what MFL was configured for it.
+
+= mbed TLS 2.21.0 branch released 2020-02-20
+
+New deprecations
+ * Deprecate MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO that enables parsing
+ SSLv2 ClientHello messages.
+ * Deprecate MBEDTLS_SSL_PROTO_SSL3 that enables support for SSLv3.
+ * Deprecate for MBEDTLS_PKCS11_C, the wrapper around the pkcs11-helper
+ library which allows TLS authentication to use keys stored in a
+ PKCS#11 token such as a smartcard.
Security
* Fix potential memory overread when performing an ECDSA signature
@@ -15,22 +70,49 @@
Brumley. Reported and fix contributed by Jack Lloyd.
ARMmbed/mbed-crypto#352
+Features
+ * The new build option MBEDTLS_SHA512_NO_SHA384 allows building SHA-512
+ support without SHA-384.
+
+API changes
+ * Change the encoding of key types and curves in the PSA API. The new
+ values are aligned with the upcoming release of the PSA Crypto API
+ specification version 1.0.0. The main change which may break some
+ existing code is that elliptic curve key types no longer encode the
+ exact curve: a psa_ecc_curve_t or psa_key_type_t value only encodes
+ a curve family and the key size determines the exact curve (for example,
+ PSA_ECC_CURVE_SECP_R1 with 256 bits is P256R1). ARMmbed/mbed-crypto#330
+
Bugfix
* Fix an unchecked call to mbedtls_md() in the x509write module.
+ * Fix build failure with MBEDTLS_ZLIB_SUPPORT enabled. Reported by
+ Jack Lloyd in #2859. Fix submitted by jiblime in #2963.
+ * Fix some false-positive uninitialized variable warnings in X.509. Fix
+ contributed by apple-ihack-geek in #2663.
+ * Fix a possible error code mangling in psa_mac_verify_finish() when
+ a cryptographic accelerator fails. ARMmbed/mbed-crypto#345
* Fix a bug in mbedtls_pk_parse_key() that would cause it to accept some
RSA keys that would later be rejected by functions expecting private
keys. Found by Catena cyber using oss-fuzz (issue 20467).
- * Fix a bug in mbedtls_pk_parse_key() that would cause it to accept some
- RSA keys with invalid values by silently fixing those values.
+ * Fix a bug in mbedtls_pk_parse_key() that would cause it to
+ accept some RSA keys with invalid values by silently fixing those values.
-= mbed TLS 2.16.4 branch released 2020-01-15
+= mbed TLS 2.20.0 branch released 2020-01-15
+
+Default behavior changes
+ * The initial seeding of a CTR_DRBG instance makes a second call to the
+ entropy function to obtain entropy for a nonce if the entropy size is less
+ than 3/2 times the key size. In case you want to disable the extra call to
+ grab entropy, you can call mbedtls_ctr_drbg_set_nonce_len() to force the
+ nonce length to 0.
Security
- * Fix side channel vulnerability in ECDSA. Our bignum implementation is not
- constant time/constant trace, so side channel attacks can retrieve the
- blinded value, factor it (as it is smaller than RSA keys and not guaranteed
- to have only large prime factors), and then, by brute force, recover the
- key. Reported by Alejandro Cabrera Aldaya and Billy Brumley.
+ * Enforce that mbedtls_entropy_func() gathers a total of
+ MBEDTLS_ENTROPY_BLOCK_SIZE bytes or more from strong sources. In the
+ default configuration, on a platform with a single entropy source, the
+ entropy module formerly only grabbed 32 bytes, which is good enough for
+ security if the source is genuinely strong, but less than the expected 64
+ bytes (size of the entropy accumulator).
* Zeroize local variables in mbedtls_internal_aes_encrypt() and
mbedtls_internal_aes_decrypt() before exiting the function. The value of
these variables can be used to recover the last round key. To follow best
@@ -39,6 +121,11 @@
Issue reported by Tuba Yavuz, Farhaan Fowze, Ken (Yihang) Bai,
Grant Hernandez, and Kevin Butler (University of Florida) and
Dave Tian (Purdue University).
+ * Fix side channel vulnerability in ECDSA. Our bignum implementation is not
+ constant time/constant trace, so side channel attacks can retrieve the
+ blinded value, factor it (as it is smaller than RSA keys and not guaranteed
+ to have only large prime factors), and then, by brute force, recover the
+ key. Reported by Alejandro Cabrera Aldaya and Billy Brumley.
* Fix side channel vulnerability in ECDSA key generation. Obtaining precise
timings on the comparison in the key generation enabled the attacker to
learn leading bits of the ephemeral key used during ECDSA signatures and to
@@ -48,62 +135,159 @@
reported and fix proposed by Johan Uppman Bruce and Christoffer Lauri,
Sectra.
+Features
+ * Key derivation inputs in the PSA API can now either come from a key object
+ or from a buffer regardless of the step type.
+ * The CTR_DRBG module can grab a nonce from the entropy source during the
+ initial seeding. The default nonce length is chosen based on the key size
+ to achieve the security strength defined by NIST SP 800-90A. You can
+ change it with mbedtls_ctr_drbg_set_nonce_len().
+ * Add ENUMERATED tag support to the ASN.1 module. Contributed by
+ msopiha-linaro in ARMmbed/mbed-crypto#307.
+
+API changes
+ * In the PSA API, forbid zero-length keys. To pass a zero-length input to a
+ key derivation function, use a buffer instead (this is now always
+ possible).
+ * Rename psa_asymmetric_sign() to psa_sign_hash() and
+ psa_asymmetric_verify() to psa_verify_hash().
+
Bugfix
- * Remove redundant line for getting the bitlen of a bignum, since the variable
- holding the returned value is overwritten a line after.
- Found by irwir in #2377.
- * Support mbedtls_hmac_drbg_set_entropy_len() and
- mbedtls_ctr_drbg_set_entropy_len() before the DRBG is seeded. Before,
- the initial seeding always reset the entropy length to the compile-time
- default.
+ * Fix an incorrect size in a debugging message. Reported and fix
+ submitted by irwir. Fixes #2717.
+ * Fix an unused variable warning when compiling without DTLS.
+ Reported and fix submitted by irwir. Fixes #2800.
+ * Remove a useless assignment. Reported and fix submitted by irwir.
+ Fixes #2801.
+ * Fix a buffer overflow in the PSA HMAC code when using a long key with an
+ unsupported algorithm. Fixes ARMmbed/mbed-crypto#254.
+ * Fix mbedtls_asn1_get_int to support any number of leading zeros. Credit
+ to OSS-Fuzz for finding a bug in an intermediate version of the fix.
+ * Fix mbedtls_asn1_get_bitstring_null to correctly parse bitstrings of at
+ most 2 bytes.
+ * mbedtls_ctr_drbg_set_entropy_len() and
+ mbedtls_hmac_drbg_set_entropy_len() now work if you call them before
+ mbedtls_ctr_drbg_seed() or mbedtls_hmac_drbg_seed().
Changes
- * Add unit tests for AES-GCM when called through mbedtls_cipher_auth_xxx()
- from the cipher abstraction layer. Fixes #2198.
- * Clarify how the interface of the CTR_DRBG and HMAC modules relates to
- NIST SP 800-90A. In particular CTR_DRBG requires an explicit nonce
- to achieve a 256-bit strength if MBEDTLS_ENTROPY_FORCE_SHA256 is set.
+ * Remove the technical possibility to define custom mbedtls_md_info
+ structures, which was exposed only in an internal header.
+ * psa_close_key(0) and psa_destroy_key(0) now succeed (doing nothing, as
+ before).
+ * Variables containing error codes are now initialized to an error code
+ rather than success, so that coding mistakes or memory corruption tends to
+ cause functions to return this error code rather than a success. There are
+ no known instances where this changes the behavior of the library: this is
+ merely a robustness improvement. ARMmbed/mbed-crypto#323
+ * Remove a useless call to mbedtls_ecp_group_free(). Contributed by
+ Alexander Krizhanovsky in ARMmbed/mbed-crypto#210.
+ * Speed up PBKDF2 by caching the digest calculation. Contributed by Jack
+ Lloyd and Fortanix Inc in ARMmbed/mbed-crypto#277.
+ * Small performance improvement of mbedtls_mpi_div_mpi(). Contributed by
+ Alexander Krizhanovsky in ARMmbed/mbed-crypto#308.
-= mbed TLS 2.16.3 branch released 2019-09-06
+= mbed TLS 2.19.1 branch released 2019-09-16
+
+Features
+ * Declare include headers as PUBLIC to propagate to CMake project consumers
+ Contributed by Zachary J. Fields in PR #2949.
+ * Add nss_keylog to ssl_client2 and ssl_server2, enabling easier analysis of
+ TLS sessions with tools like Wireshark.
+
+API Changes
+ * Make client_random and server_random const in
+ mbedtls_ssl_export_keys_ext_t, so that the key exporter is discouraged
+ from modifying the client/server hello.
+
+Bugfix
+ * Fix some false-positive uninitialized variable warnings in crypto. Fix
+ contributed by apple-ihack-geek in #2663.
+
+= mbed TLS 2.19.0 branch released 2019-09-06
Security
* Fix a missing error detection in ECJPAKE. This could have caused a
predictable shared secret if a hardware accelerator failed and the other
side of the key exchange had a similar bug.
- * The deterministic ECDSA calculation reused the scheme's HMAC-DRBG to
- implement blinding. Because of this for the same key and message the same
- blinding value was generated. This reduced the effectiveness of the
- countermeasure and leaked information about the private key through side
- channels. Reported by Jack Lloyd.
* When writing a private EC key, use a constant size for the private
value, as specified in RFC 5915. Previously, the value was written
as an ASN.1 INTEGER, which caused the size of the key to leak
about 1 bit of information on average and could cause the value to be
1 byte too large for the output buffer.
+ * The deterministic ECDSA calculation reused the scheme's HMAC-DRBG to
+ implement blinding. Because of this for the same key and message the same
+ blinding value was generated. This reduced the effectiveness of the
+ countermeasure and leaked information about the private key through side
+ channels. Reported by Jack Lloyd.
+
+Features
+ * Add new API functions mbedtls_ssl_session_save() and
+ mbedtls_ssl_session_load() to allow serializing a session, for example to
+ store it in non-volatile storage, and later using it for TLS session
+ resumption.
+ * Add a new API function mbedtls_ssl_check_record() to allow checking that
+ an incoming record is valid, authentic and has not been seen before. This
+ feature can be used alongside Connection ID and SSL context serialisation.
+ The feature is enabled at compile-time by MBEDTLS_SSL_RECORD_CHECKING
+ option.
+ * New implementation of X25519 (ECDH using Curve25519) from Project Everest
+ (https://project-everest.github.io/). It can be enabled at compile time
+ with MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED. This implementation is formally
+ verified and significantly faster, but is only supported on x86 platforms
+ (32-bit and 64-bit) using GCC, Clang or Visual Studio. Contributed by
+ Christoph Wintersteiger from Microsoft Research.
+ * Add mbedtls_net_close(), enabling the building of forking servers where
+ the parent process closes the client socket and continue accepting, and
+ the child process closes the listening socket and handles the client
+ socket. Contributed by Robert Larsen in #2803.
API Changes
+ * Add DER-encoded test CRTs to library/certs.c, allowing
+ the example programs ssl_server2 and ssl_client2 to be run
+ if MBEDTLS_FS_IO and MBEDTLS_PEM_PARSE_C are unset. Fixes #2254.
+ * The HAVEGE state type now uses uint32_t elements instead of int.
+ * The functions mbedtls_ecp_curve_list() and mbedtls_ecp_grp_id_list() now
+ list all curves for which at least one of ECDH or ECDSA is supported, not
+ just curves for which both are supported. Call mbedtls_ecdsa_can_do() or
+ mbedtls_ecdh_can_do() on each result to check whether each algorithm is
+ supported.
* The new function mbedtls_ecdsa_sign_det_ext() is similar to
mbedtls_ecdsa_sign_det() but allows passing an external RNG for the
purpose of blinding.
+New deprecations
+ * Deprecate mbedtls_ecdsa_sign_det() in favor of a functions that can take an
+ RNG function as an input.
+ * Calling mbedtls_ecdsa_write_signature() with NULL as the f_rng argument
+ is now deprecated.
+
Bugfix
+ * Fix missing bounds checks in X.509 parsing functions that could
+ lead to successful parsing of ill-formed X.509 CRTs. Fixes #2437.
+ * Fix multiple X.509 functions previously returning ASN.1 low-level error
+ codes to always wrap these codes into X.509 high level error codes before
+ returning. Fixes #2431.
* Fix to allow building test suites with any warning that detects unused
functions. Fixes #1628.
* Fix typo in net_would_block(). Fixes #528 reported by github-monoculture.
* Remove redundant include file in timing.c. Fixes #2640 reported by irwir.
+ * Fix build failure when building with mingw on Windows by including
+ stdarg.h where needed. Fixes #2656.
* Fix Visual Studio Release x64 build configuration by inheriting
PlatformToolset from the project configuration. Fixes #1430 reported by
irwir.
* Enable Suite B with subset of ECP curves. Make sure the code compiles even
if some curves are not defined. Fixes #1591 reported by dbedev.
* Fix misuse of signed arithmetic in the HAVEGE module. #2598
+ * Avoid use of statically sized stack buffers for certificate writing.
+ This previously limited the maximum size of DER encoded certificates
+ in mbedtls_x509write_crt_der() to 2Kb. Reported by soccerGB in #2631.
+ * Fix partial zeroing in x509_get_other_name. Found and fixed by ekse, #2716.
* Update test certificates that were about to expire. Reported by
Bernhard M. Wiedemann in #2357.
* Fix the build on ARMv5TE in ARM mode to not use assembly instructions
that are only available in Thumb mode. Fix contributed by Aurelien Jarno
in #2169.
- * Fix undefined memset(NULL) call in test_suite_nist_kw.
- * Make NV seed test support MBEDTLS_ENTROPY_FORCE_SHA256.
* Fix propagation of restart contexts in restartable EC operations.
This could previously lead to segmentation faults in builds using an
address-sanitizer and enabling but not using MBEDTLS_ECP_RESTARTABLE.
@@ -112,35 +296,77 @@
* Improve code clarity in x509_crt module, removing false-positive
uninitialized variable warnings on some recent toolchains (GCC8, etc).
Discovered and fixed by Andy Gross (Linaro), #2392.
- * Zero length buffer check for undefined behavior in
- mbedtls_platform_zeroize(). Fixes ARMmbed/mbed-crypto#49.
* Fix bug in endianness conversion in bignum module. This lead to
functionally incorrect code on bigendian systems which don't have
__BYTE_ORDER__ defined. Reported by Brendan Shanks. Fixes #2622.
Changes
+ * Replace multiple uses of MD2 by SHA-256 in X.509 test suite. Fixes #821.
* Make it easier to define MBEDTLS_PARAM_FAILED as assert (which config.h
suggests). #2671
* Make `make clean` clean all programs always. Fixes #1862.
+ * Add a Dockerfile and helper scripts (all-in-docker.sh, basic-in-docker.sh,
+ docker-env.sh) to simplify running test suites on a Linux host. Contributed
+ by Peter Kolbus (Garmin).
+ * Add `reproducible` option to `ssl_client2` and `ssl_server2` to enable
+ test runs without variability. Contributed by Philippe Antoine (Catena
+ cyber) in #2681.
+ * Extended .gitignore to ignore Visual Studio artifacts. Fixed by ConfusedSushi.
+ * Adds fuzz targets, especially for continuous fuzzing with OSS-Fuzz.
+ Contributed by Philippe Antoine (Catena cyber).
+ * Remove the crypto part of the library from Mbed TLS. The crypto
+ code and tests are now only available via Mbed Crypto, which
+ Mbed TLS references as a Git submodule.
-= mbed TLS 2.16.2 branch released 2019-06-11
-
-Security
- * Make mbedtls_ecdh_get_params return an error if the second key
- belongs to a different group from the first. Before, if an application
- passed keys that belonged to different group, the first key's data was
- interpreted according to the second group, which could lead to either
- an error or a meaningless output from mbedtls_ecdh_get_params. In the
- latter case, this could expose at most 5 bits of the private key.
+= mbed TLS 2.18.1 branch released 2019-07-12
Bugfix
- * Server's RSA certificate in certs.c was SHA-1 signed. In the default
- mbedTLS configuration only SHA-2 signed certificates are accepted.
- This certificate is used in the demo server programs, which lead the
- client programs to fail at the peer's certificate verification
- due to an unacceptable hash signature. The certificate has been
- updated to one that is SHA-256 signed. Fix contributed by
- Illya Gerasymchuk.
+ * Fix build failure when building with mingw on Windows by including
+ stdarg.h where needed. Fixes #2656.
+
+Changes
+ * Enable building of Mbed TLS as a CMake subproject. Suggested and fixed by
+ Ashley Duncan in #2609.
+
+= mbed TLS 2.18.0 branch released 2019-06-11
+
+Features
+ * Add the Any Policy certificate policy oid, as defined in
+ rfc 5280 section 4.2.1.4.
+ * It is now possible to use NIST key wrap mode via the mbedtls_cipher API.
+ Contributed by Jack Lloyd and Fortanix Inc.
+ * Add the Wi-SUN Field Area Network (FAN) device extended key usage.
+ * Add the oid certificate policy x509 extension.
+ * It is now possible to perform RSA PKCS v1.5 signatures with RIPEMD-160 digest.
+ Contributed by Jack Lloyd and Fortanix Inc.
+ * Extend the MBEDTLS_SSL_EXPORT_KEYS to export the handshake randbytes,
+ and the used tls-prf.
+ * Add public API for tls-prf function, according to requested enum.
+ * Add support for parsing otherName entries in the Subject Alternative Name
+ X.509 certificate extension, specifically type hardware module name,
+ as defined in RFC 4108 section 5.
+ * Add support for parsing certificate policies extension, as defined in
+ RFC 5280 section 4.2.1.4. Currently, only the "Any Policy" policy is
+ supported.
+ * List all SAN types in the subject_alt_names field of the certificate.
+ Resolves #459.
+ * Add support for draft-05 of the Connection ID extension, as specified
+ in https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05.
+ The Connection ID extension allows to keep DTLS connections beyond the
+ lifetime of the underlying transport by adding a connection identifier
+ to the DTLS record header. This identifier can be used to associated an
+ incoming record with the correct connection data even after the peer has
+ changed its IP or port. The feature is enabled at compile-time by setting
+ MBEDTLS_SSL_DTLS_CONNECTION_ID (disabled by default), and at run-time
+ through the new APIs mbedtls_ssl_conf_cid() and mbedtls_ssl_set_cid().
+
+
+API Changes
+ * Extend the MBEDTLS_SSL_EXPORT_KEYS to export the handshake randbytes,
+ and the used tls-prf.
+ * Add public API for tls-prf function, according to requested enum.
+
+Bugfix
* Fix private key DER output in the key_app_writer example. File contents
were shifted by one byte, creating an invalid ASN.1 tag. Fixed by
Christian Walther in #2239.
@@ -155,22 +381,26 @@
GCM and CCM were not affected. Fixed by Jack Lloyd.
* Fix incorrect default port number in ssl_mail_client example's usage.
Found and fixed by irwir. #2337
+ * Add psa_util.h to test/cpp_dummy_build to fix build_default_make_gcc_and_cxx.
+ Fixed by Peter Kolbus (Garmin). #2579
* Add missing parentheses around parameters in the definition of the
public macro MBEDTLS_X509_ID_FLAG. This could lead to invalid evaluation
in case operators binding less strongly than subtraction were used
for the parameter.
* Add a check for MBEDTLS_X509_CRL_PARSE_C in ssl_server2, guarding the crl
sni entry parameter. Reported by inestlerode in #560.
- * Add DER-encoded test CRTs to library/certs.c, allowing
- the example programs ssl_server2 and ssl_client2 to be run
- if MBEDTLS_FS_IO and MBEDTLS_PEM_PARSE_C are unset. Fixes #2254.
- * Fix missing bounds checks in X.509 parsing functions that could
- lead to successful parsing of ill-formed X.509 CRTs. Fixes #2437.
- * Fix multiple X.509 functions previously returning ASN.1 low-level error
- codes to always wrap these codes into X.509 high level error codes before
- returning. Fixes #2431.
+ * Set the next sequence of the subject_alt_name to NULL when deleting
+ sequence on failure. Found and fix suggested by Philippe Antoine.
+ Credit to OSS-Fuzz.
Changes
+ * Server's RSA certificate in certs.c was SHA-1 signed. In the default
+ mbedTLS configuration only SHA-2 signed certificates are accepted.
+ This certificate is used in the demo server programs, which lead the
+ client programs to fail at the peer's certificate verification
+ due to an unacceptable hash signature. The certificate has been
+ updated to one that is SHA-256 signed. Fix contributed by
+ Illya Gerasymchuk.
* Return from various debugging routines immediately if the
provided SSL context is unset.
* Remove dead code from bignum.c in the default configuration.
@@ -179,15 +409,39 @@
Contributed by Peter Kolbus (Garmin).
* Change wording in the `mbedtls_ssl_conf_max_frag_len()`'s documentation to
improve clarity. Fixes #2258.
- * Replace multiple uses of MD2 by SHA-256 in X.509 test suite. Fixes #821.
-= mbed TLS 2.16.1 branch released 2019-03-19
+= mbed TLS 2.17.0 branch released 2019-03-19
Features
+ * Add a new X.509 API call `mbedtls_x509_parse_der_nocopy()`
+ which allows copy-less parsing of DER encoded X.509 CRTs,
+ at the cost of additional lifetime constraints on the input
+ buffer, but at the benefit of reduced RAM consumption.
+ * Add a new function mbedtls_asn1_write_named_bitstring() to write ASN.1
+ named bitstring in DER as required by RFC 5280 Appendix B.
* Add MBEDTLS_REMOVE_3DES_CIPHERSUITES to allow removing 3DES ciphersuites
from the default list (enabled by default). See
https://sweet32.info/SWEET32_CCS16.pdf.
+API Changes
+ * Add a new X.509 API call `mbedtls_x509_parse_der_nocopy()`.
+ See the Features section for more information.
+ * Allow to opt in to the removal the API mbedtls_ssl_get_peer_cert()
+ for the benefit of saving RAM, by disabling the new compile-time
+ option MBEDTLS_SSL_KEEP_PEER_CERTIFICATE (enabled by default for
+ API stability). Disabling this option makes mbedtls_ssl_get_peer_cert()
+ always return NULL, and removes the peer_cert field from the
+ mbedtls_ssl_session structure which otherwise stores the peer's
+ certificate.
+
+Security
+ * Make mbedtls_ecdh_get_params return an error if the second key
+ belongs to a different group from the first. Before, if an application
+ passed keys that belonged to different group, the first key's data was
+ interpreted according to the second group, which could lead to either
+ an error or a meaningless output from mbedtls_ecdh_get_params. In the
+ latter case, this could expose at most 5 bits of the private key.
+
Bugfix
* Fix a compilation issue with mbedtls_ecp_restart_ctx not being defined
when MBEDTLS_ECP_ALT is defined. Reported by jwhui. Fixes #2242.
@@ -197,19 +451,14 @@
previously lead to a stack overflow on constrained targets.
* Add `MBEDTLS_SELF_TEST` for the mbedtls_self_test functions
in the header files, which missed the precompilation check. #971
- * Fix clobber list in MIPS assembly for large integer multiplication.
- Previously, this could lead to functionally incorrect assembly being
- produced by some optimizing compilers, showing up as failures in
- e.g. RSA or ECC signature operations. Reported in #1722, fix suggested
- by Aurelien Jarno and submitted by Jeffrey Martin.
+ * Fix returning the value 1 when mbedtls_ecdsa_genkey failed.
+ * Remove a duplicate #include in a sample program. Fixed by Masashi Honma #2326.
+ * Remove the mbedtls namespacing from the header file, to fix a "file not found"
+ build error. Fixed by Haijun Gu #2319.
* Fix signed-to-unsigned integer conversion warning
in X.509 module. Fixes #2212.
* Reduce stack usage of `mpi_write_hlp()` by eliminating recursion.
Fixes #2190.
- * Remove a duplicate #include in a sample program. Fixed by Masashi Honma #2326.
- * Remove the mbedtls namespacing from the header file, to fix a "file not found"
- build error. Fixed by Haijun Gu #2319.
- * Fix returning the value 1 when mbedtls_ecdsa_genkey failed.
* Fix false failure in all.sh when backup files exist in include/mbedtls
(e.g. config.h.bak). Fixed by Peter Kolbus (Garmin) #2407.
* Ensure that unused bits are zero when writing ASN.1 bitstrings when using
@@ -220,15 +469,26 @@
leading content octet. Fixes #1610.
Changes
+ * Reduce RAM consumption during session renegotiation by not storing
+ the peer CRT chain and session ticket twice.
* Include configuration file in all header files that use configuration,
instead of relying on other header files that they include.
Inserted as an enhancement for #1371
* Add support for alternative CSR headers, as used by Microsoft and defined
in RFC 7468. Found by Michael Ernst. Fixes #767.
- * Fix configuration queries in ssl-opt.h. #2030
- * Ensure that ssl-opt.h can be run in OS X. #2029
+ * Correct many misspellings. Fixed by MisterDA #2371.
+ * Provide an abstraction of vsnprintf to allow alternative implementations
+ for platforms that don't provide it. Based on contributions by Joris Aerts
+ and Nathaniel Wesley Filardo.
+ * Fix clobber list in MIPS assembly for large integer multiplication.
+ Previously, this could lead to functionally incorrect assembly being
+ produced by some optimizing compilers, showing up as failures in
+ e.g. RSA or ECC signature operations. Reported in #1722, fix suggested
+ by Aurelien Jarno and submitted by Jeffrey Martin.
* Reduce the complexity of the timing tests. They were assuming more than the
underlying OS actually guarantees.
+ * Fix configuration queries in ssl-opt.h. #2030
+ * Ensure that ssl-opt.h can be run in OS X. #2029
* Re-enable certain interoperability tests in ssl-opt.sh which had previously
been disabled for lack of a sufficiently recent version of GnuTLS on the CI.
* Ciphersuites based on 3DES now have the lowest priority by default when
@@ -291,6 +551,24 @@
* Clarify documentation of mbedtls_ssl_set_own_cert() regarding the absence
of check for certificate/key matching. Reported by Attila Molnar, #507.
+ = mbed TLS 2.15.1 branch released 2018-11-30
+
+ Changes
+ * Update the Mbed Crypto submodule to version 0.1.0b2.
+
+ = mbed TLS 2.15.0 branch released 2018-11-23
+
+ Features
+ * Add an experimental build option, USE_CRYPTO_SUBMODULE, to enable use of
+ Mbed Crypto as the source of the cryptography implementation.
+ * Add an experimental configuration option, MBEDTLS_PSA_CRYPTO_C, to enable
+ the PSA Crypto API from Mbed Crypto when additionally used with the
+ USE_CRYPTO_SUBMODULE build option.
+
+ Changes
+ * Add unit tests for AES-GCM when called through mbedtls_cipher_auth_xxx()
+ from the cipher abstraction layer. Fixes #2198.
+
= mbed TLS 2.14.1 branch released 2018-11-30
Security
diff --git a/lib/libmbedtls/mbedtls/LICENSE b/lib/libmbedtls/mbedtls/LICENSE
index 546a8e6..d645695 100644
--- a/lib/libmbedtls/mbedtls/LICENSE
+++ b/lib/libmbedtls/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/lib/libmbedtls/mbedtls/README.md b/lib/libmbedtls/mbedtls/README.md
index 62dd4e2..f868a0a 100644
--- a/lib/libmbedtls/mbedtls/README.md
+++ b/lib/libmbedtls/mbedtls/README.md
@@ -1,13 +1,30 @@
README for Mbed TLS
===================
+Mbed TLS is a C library that implements cryptographic primitives, X.509 certificate manipulation and the SSL/TLS and DTLS protocols. Its small code footprint makes it suitable for embedded systems.
+
+Mbed TLS includes a reference implementation of the [PSA Cryptography API](#psa-cryptography-api). This is currently a preview for evaluation purposes only.
+
Configuration
-------------
-Mbed TLS should build out of the box on most systems. Some platform specific options are available in the fully documented configuration file `include/mbedtls/config.h`, which is also the place where features can be selected. This file can be edited manually, or in a more programmatic way using the Perl script `scripts/config.pl` (use `--help` for usage instructions).
+Mbed TLS should build out of the box on most systems. Some platform specific options are available in the fully documented configuration file `include/mbedtls/config.h`, which is also the place where features can be selected. This file can be edited manually, or in a more programmatic way using the Python 3 script `scripts/config.py` (use `--help` for usage instructions).
Compiler options can be set using conventional environment variables such as `CC` and `CFLAGS` when using the Make and CMake build system (see below).
+We provide some non-standard configurations focused on specific use cases in the `configs/` directory. You can read more about those in `configs/README.txt`
+
+Documentation
+-------------
+
+Documentation for the Mbed TLS interfaces in the default library configuration is available as part of the [Mbed TLS documentation](https://tls.mbed.org/api/).
+
+To generate a local copy of the library documentation in HTML format, tailored to your compile-time configuration:
+
+1. Make sure that [Doxygen](http://www.doxygen.nl/) is installed. We use version 1.8.11 but slightly older or more recent versions should work.
+1. Run `make apidoc`.
+1. Browse `apidoc/index.html` or `apidoc/modules.html`.
+
Compiling
---------
@@ -15,12 +32,21 @@
- GNU Make
- CMake
-- Microsoft Visual Studio (Microsoft Visual Studio 2010 or later)
+- Microsoft Visual Studio (Microsoft Visual Studio 2013 or later)
The main systems used for development are CMake and GNU Make. Those systems are always complete and up-to-date. The others should reflect all changes present in the CMake and Make build system, although features may not be ported there automatically.
The Make and CMake build systems create three libraries: libmbedcrypto, libmbedx509, and libmbedtls. Note that libmbedtls depends on libmbedx509 and libmbedcrypto, and libmbedx509 depends on libmbedcrypto. As a result, some linkers will expect flags to be in a specific order, for example the GNU linker wants `-lmbedtls -lmbedx509 -lmbedcrypto`. Also, when loading shared libraries using dlopen(), you'll need to load libmbedcrypto first, then libmbedx509, before you can load libmbedtls.
+### Tool versions
+
+You need the following tools to build the library with the provided makefiles:
+
+* GNU Make or a build tool that CMake supports.
+* A C99 toolchain (compiler, linker, archiver). We actively test with GCC 5.4, Clang 3.8, IAR8 and Visual Studio 2013. More recent versions should work. Slightly older versions may work.
+* Python 3 to generate the test code.
+* Perl to run the tests.
+
### Make
We require GNU Make. To build the library and the sample programs, GNU Make and a C compiler are sufficient. Some of the more advanced build targets require some Unix/Linux tools.
@@ -47,7 +73,7 @@
Setting the variable `SHARED` in your environment will build shared libraries in addition to the static libraries. Setting `DEBUG` gives you a debug build. You can override `CFLAGS` and `LDFLAGS` by setting them in your environment or on the make command line; compiler warning options may be overridden separately using `WARNING_CFLAGS`. Some directory-specific options (for example, `-I` directives) are still preserved.
-Please note that setting `CFLAGS` overrides its default value of `-O2` and setting `WARNING_CFLAGS` overrides its default value (starting with `-Wall -W`), so if you just want to add some warning options to the default ones, you can do so by setting `CFLAGS=-O2 -Werror` for example. Setting `WARNING_CFLAGS` is useful when you want to get rid of its default content (for example because your compiler doesn't accept `-Wall` as an option). Directory-specific options cannot be overridden from the command line.
+Please note that setting `CFLAGS` overrides its default value of `-O2` and setting `WARNING_CFLAGS` overrides its default value (starting with `-Wall -Wextra`), so if you just want to add some warning options to the default ones, you can do so by setting `CFLAGS=-O2 -Werror` for example. Setting `WARNING_CFLAGS` is useful when you want to get rid of its default content (for example because your compiler doesn't accept `-Wall` as an option). Directory-specific options cannot be overridden from the command line.
Depending on your platform, you might run into some issues. Please check the Makefiles in `library/`, `programs/` and `tests/` for options to manually add or remove for specific platforms. You can also check [the Mbed TLS Knowledge Base](https://tls.mbed.org/kb) for articles on your platform or issue.
@@ -129,6 +155,12 @@
your value of CFLAGS doesn't override the content provided by cmake (depending
on the build mode as seen above), it's merely prepended to it.
+#### Mbed TLS as a subproject
+
+Mbed TLS supports being built as a CMake subproject. One can
+use `add_subdirectory()` from a parent CMake project to include Mbed TLS as a
+subproject.
+
### Microsoft Visual Studio
The build files for Microsoft Visual Studio are generated for Visual Studio 2010.
@@ -138,7 +170,8 @@
Example programs
----------------
-We've included example programs for a lot of different features and uses in [`programs/`](programs/README.md). Most programs only focus on a single feature or usage scenario, so keep that in mind when copying parts of the code.
+We've included example programs for a lot of different features and uses in [`programs/`](programs/README.md).
+Please note that the goal of these sample programs is to demonstrate specific features of the library, and the code may need to be adapted to build a real-world application.
Tests
-----
@@ -153,11 +186,6 @@
- `tests/scripts/key-exchanges.pl` test builds in configurations with a single key exchange enabled
- `tests/scripts/all.sh` runs a combination of the above tests, plus some more, with various build options (such as ASan, full `config.h`, etc).
-Configurations
---------------
-
-We provide some non-standard configurations focused on specific use cases in the `configs/` directory. You can read more about those in `configs/README.txt`
-
Porting Mbed TLS
----------------
@@ -167,21 +195,53 @@
- [What external dependencies does Mbed TLS rely on?](https://tls.mbed.org/kb/development/what-external-dependencies-does-mbedtls-rely-on)
- [How do I configure Mbed TLS](https://tls.mbed.org/kb/compiling-and-building/how-do-i-configure-mbedtls)
+PSA cryptography API
+--------------------
+
+### PSA API design
+
+Arm's [Platform Security Architecture (PSA)](https://developer.arm.com/architectures/security-architectures/platform-security-architecture) is a holistic set of threat models, security analyses, hardware and firmware architecture specifications, and an open source firmware reference implementation. PSA provides a recipe, based on industry best practice, that allows security to be consistently designed in, at both a hardware and firmware level.
+
+The [PSA cryptography API](https://armmbed.github.io/mbed-crypto/psa/#application-programming-interface) provides access to a set of cryptographic primitives. It has a dual purpose. First, it can be used in a PSA-compliant platform to build services, such as secure boot, secure storage and secure communication. Second, it can also be used independently of other PSA components on any platform.
+
+The design goals of the PSA cryptography API include:
+
+* The API distinguishes caller memory from internal memory, which allows the library to be implemented in an isolated space for additional security. Library calls can be implemented as direct function calls if isolation is not desired, and as remote procedure calls if isolation is desired.
+* The structure of internal data is hidden to the application, which allows substituting alternative implementations at build time or run time, for example, in order to take advantage of hardware accelerators.
+* All access to the keys happens through handles, which allows support for external cryptoprocessors that is transparent to applications.
+* The interface to algorithms is generic, favoring algorithm agility.
+* The interface is designed to be easy to use and hard to accidentally misuse.
+
+Arm welcomes feedback on the design of the API. If you think something could be improved, please open an issue on our Github repository. Alternatively, if you prefer to provide your feedback privately, please email us at [`mbed-crypto@arm.com`](mailto:mbed-crypto@arm.com). All feedback received by email is treated confidentially.
+
+### PSA API documentation
+
+A browsable copy of the PSA Cryptography API documents is available on the [PSA cryptography interfaces documentation portal](https://armmbed.github.io/mbed-crypto/psa/#application-programming-interface) in [PDF](https://armmbed.github.io/mbed-crypto/PSA_Cryptography_API_Specification.pdf) and [HTML](https://armmbed.github.io/mbed-crypto/html/index.html) formats.
+
+### PSA implementation in Mbed TLS
+
+Mbed TLS includes a reference implementation of the PSA Cryptography API.
+This implementation is not yet as mature as the rest of the library. Some parts of the code have not been reviewed as thoroughly, and some parts of the PSA implementation are not yet well optimized for code size.
+
+The X.509 and TLS code can use PSA cryptography for a limited subset of operations. To enable this support, activate the compilation option `MBEDTLS_USE_PSA_CRYPTO` in `config.h`.
+
+There are currently a few deviations where the library does not yet implement the latest version of the specification. Please refer to the [compliance issues on Github](https://github.com/ARMmbed/mbed-crypto/labels/compliance) for an up-to-date list.
+
+### Upcoming features
+
+Future releases of this library will include:
+
+* A driver programming interface, which makes it possible to use hardware accelerators instead of the default software implementation for chosen algorithms.
+* Support for external keys to be stored and manipulated exclusively in a separate cryptoprocessor.
+* A configuration mechanism to compile only the algorithms you need for your application.
+* A wider set of cryptographic algorithms.
+
+License
+-------
+
+Unless specifically indicated otherwise in a file, Mbed TLS files are provided under the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license. See the [LICENSE](LICENSE) file for the full text of this license. Contributors must accept that their contributions are made under both the Apache-2.0 AND [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) licenses. This enables LTS (Long Term Support) branches of the software to be provided under either the Apache-2.0 OR GPL-2.0-or-later licenses.
+
Contributing
------------
-We gratefully accept bug reports and contributions from the community. There are some requirements we need to fulfill in order to be able to integrate contributions:
-
-- All contributions, whether large or small require a Contributor's License Agreement (CLA) to be accepted. This is because source code can possibly fall under copyright law and we need your consent to share in the ownership of the copyright.
-- We would ask that contributions conform to [our coding standards](https://tls.mbed.org/kb/development/mbedtls-coding-standards), and that contributions should be fully tested before submission.
-- As with any open source project, contributions will be reviewed by the project team and community and may need some modifications to be accepted.
-
-To accept the Contributor’s Licence Agreement (CLA), individual contributors can do this by creating an Mbed account and [accepting the online agreement here with a click through](https://os.mbed.com/contributor_agreement/). Alternatively, for contributions from corporations, or those that do not wish to create an Mbed account, a slightly different agreement can be found [here](https://www.mbed.com/en/about-mbed/contributor-license-agreements/). This agreement should be signed and returned to Arm as described in the instructions given.
-
-### Making a Contribution
-
-1. [Check for open issues](https://github.com/ARMmbed/mbedtls/issues) or [start a discussion](https://forums.mbed.com/c/mbed-tls) around a feature idea or a bug.
-2. Fork the [Mbed TLS repository on GitHub](https://github.com/ARMmbed/mbedtls) to start making your changes. As a general rule, you should use the "development" branch as a basis.
-3. Write a test which shows that the bug was fixed or that the feature works as expected.
-4. Send a pull request and bug us until it gets merged and published. Contributions may need some modifications, so work with us to get your change accepted. We will include your name in the ChangeLog :)
-
+We gratefully accept bug reports and contributions from the community. Please see the [contributing guidelines](CONTRIBUTING.md) for details on how to do this.
diff --git a/lib/libmbedtls/mbedtls/apache-2.0.txt b/lib/libmbedtls/mbedtls/apache-2.0.txt
deleted file mode 100644
index d645695..0000000
--- a/lib/libmbedtls/mbedtls/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/lib/libmbedtls/mbedtls/dco.txt b/lib/libmbedtls/mbedtls/dco.txt
new file mode 100644
index 0000000..8201f99
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/dco.txt
@@ -0,0 +1,37 @@
+Developer Certificate of Origin
+Version 1.1
+
+Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
+1 Letterman Drive
+Suite D4700
+San Francisco, CA, 94129
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+
+
+Developer's Certificate of Origin 1.1
+
+By making a contribution to this project, I certify that:
+
+(a) The contribution was created in whole or in part by me and I
+ have the right to submit it under the open source license
+ indicated in the file; or
+
+(b) The contribution is based upon previous work that, to the best
+ of my knowledge, is covered under an appropriate open source
+ license and I have the right under that license to submit that
+ work with modifications, whether created in whole or in part
+ by me, under the same open source license (unless I am
+ permitted to submit under a different license), as indicated
+ in the file; or
+
+(c) The contribution was provided directly to me by some other
+ person who certified (a), (b) or (c) and I have not modified
+ it.
+
+(d) I understand and agree that this project and the contribution
+ are public and that a record of the contribution (including all
+ personal information I submit with it, including my sign-off) is
+ maintained indefinitely and may be redistributed consistent with
+ this project or the open source license(s) involved.
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/aes.h b/lib/libmbedtls/mbedtls/include/mbedtls/aes.h
index 21f0d56..a429c86 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/aes.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/aes.h
@@ -42,7 +42,7 @@
#define MBEDTLS_AES_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/aesni.h b/lib/libmbedtls/mbedtls/include/mbedtls/aesni.h
index cc766d4..1bdee2d 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/aesni.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/aesni.h
@@ -28,12 +28,12 @@
#define MBEDTLS_AESNI_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "aes.h"
+#include "mbedtls/aes.h"
#define MBEDTLS_AESNI_AES 0x02000000u
#define MBEDTLS_AESNI_CLMUL 0x00000002u
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/arc4.h b/lib/libmbedtls/mbedtls/include/mbedtls/arc4.h
index 698c52a..d6e9da9 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/arc4.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/arc4.h
@@ -29,7 +29,7 @@
#define MBEDTLS_ARC4_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/aria.h b/lib/libmbedtls/mbedtls/include/mbedtls/aria.h
index 1e8956e..a72a8c2 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/aria.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/aria.h
@@ -31,7 +31,7 @@
#define MBEDTLS_ARIA_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
@@ -39,7 +39,7 @@
#include <stddef.h>
#include <stdint.h>
-#include "platform_util.h"
+#include "mbedtls/platform_util.h"
#define MBEDTLS_ARIA_ENCRYPT 1 /**< ARIA encryption. */
#define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h b/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h
index b1ff1fe..993a1f5 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h
@@ -25,7 +25,7 @@
#define MBEDTLS_ASN1_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
@@ -33,7 +33,7 @@
#include <stddef.h>
#if defined(MBEDTLS_BIGNUM_C)
-#include "bignum.h"
+#include "mbedtls/bignum.h"
#endif
/**
@@ -52,7 +52,7 @@
#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */
#define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */
#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */
-#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */
+#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. */
#define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A /**< Memory allocation failed */
#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */
@@ -75,6 +75,7 @@
#define MBEDTLS_ASN1_OCTET_STRING 0x04
#define MBEDTLS_ASN1_NULL 0x05
#define MBEDTLS_ASN1_OID 0x06
+#define MBEDTLS_ASN1_ENUMERATED 0x0A
#define MBEDTLS_ASN1_UTF8_STRING 0x0C
#define MBEDTLS_ASN1_SEQUENCE 0x10
#define MBEDTLS_ASN1_SET 0x11
@@ -89,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",
@@ -119,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
@@ -176,119 +193,342 @@
* \brief Get the length of an ASN.1 element.
* Updates the pointer to immediately behind the length.
*
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param len The variable that will receive the value
+ * \param p On entry, \c *p points to the first byte of the length,
+ * i.e. immediately after the tag.
+ * On successful completion, \c *p points to the first byte
+ * after the length, i.e. the first byte of the content.
+ * On error, the value of \c *p is undefined.
+ * \param end End of data.
+ * \param len On successful completion, \c *len contains the length
+ * read from the ASN.1 input.
*
- * \return 0 if successful, MBEDTLS_ERR_ASN1_OUT_OF_DATA on reaching
- * end of data, MBEDTLS_ERR_ASN1_INVALID_LENGTH if length is
- * unparseable.
+ * \return 0 if successful.
+ * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element
+ * would end beyond \p end.
+ * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable.
*/
int mbedtls_asn1_get_len( unsigned char **p,
- const unsigned char *end,
- size_t *len );
+ const unsigned char *end,
+ size_t *len );
/**
- * \brief Get the tag and length of the tag. Check for the requested tag.
+ * \brief Get the tag and length of the element.
+ * Check for the requested tag.
* Updates the pointer to immediately behind the tag and length.
*
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param len The variable that will receive the length
- * \param tag The expected tag
+ * \param p On entry, \c *p points to the start of the ASN.1 element.
+ * On successful completion, \c *p points to the first byte
+ * after the length, i.e. the first byte of the content.
+ * On error, the value of \c *p is undefined.
+ * \param end End of data.
+ * \param len On successful completion, \c *len contains the length
+ * read from the ASN.1 input.
+ * \param tag The expected tag.
*
- * \return 0 if successful, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if tag did
- * not match requested tag, or another specific ASN.1 error code.
+ * \return 0 if successful.
+ * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the data does not start
+ * with the requested tag.
+ * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element
+ * would end beyond \p end.
+ * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable.
*/
int mbedtls_asn1_get_tag( unsigned char **p,
- const unsigned char *end,
- size_t *len, int tag );
+ const unsigned char *end,
+ size_t *len, int tag );
/**
* \brief Retrieve a boolean ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
*
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param val The variable that will receive the value
+ * \param p On entry, \c *p points to the start of the ASN.1 element.
+ * On successful completion, \c *p points to the first byte
+ * beyond the ASN.1 element.
+ * On error, the value of \c *p is undefined.
+ * \param end End of data.
+ * \param val On success, the parsed value (\c 0 or \c 1).
*
- * \return 0 if successful or a specific ASN.1 error code.
+ * \return 0 if successful.
+ * \return An ASN.1 error code if the input does not start with
+ * a valid ASN.1 BOOLEAN.
*/
int mbedtls_asn1_get_bool( unsigned char **p,
- const unsigned char *end,
- int *val );
+ const unsigned char *end,
+ int *val );
/**
* \brief Retrieve an integer ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
*
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param val The variable that will receive the value
+ * \param p On entry, \c *p points to the start of the ASN.1 element.
+ * On successful completion, \c *p points to the first byte
+ * beyond the ASN.1 element.
+ * On error, the value of \c *p is undefined.
+ * \param end End of data.
+ * \param val On success, the parsed value.
*
- * \return 0 if successful or a specific ASN.1 error code.
+ * \return 0 if successful.
+ * \return An ASN.1 error code if the input does not start with
+ * a valid ASN.1 INTEGER.
+ * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
+ * not fit in an \c int.
*/
int mbedtls_asn1_get_int( unsigned char **p,
- const unsigned char *end,
- int *val );
+ const unsigned char *end,
+ int *val );
+
+/**
+ * \brief Retrieve an enumerated ASN.1 tag and its value.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p On entry, \c *p points to the start of the ASN.1 element.
+ * On successful completion, \c *p points to the first byte
+ * beyond the ASN.1 element.
+ * On error, the value of \c *p is undefined.
+ * \param end End of data.
+ * \param val On success, the parsed value.
+ *
+ * \return 0 if successful.
+ * \return An ASN.1 error code if the input does not start with
+ * a valid ASN.1 ENUMERATED.
+ * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
+ * not fit in an \c int.
+ */
+int mbedtls_asn1_get_enum( unsigned char **p,
+ const unsigned char *end,
+ int *val );
/**
* \brief Retrieve a bitstring ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
*
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param bs The variable that will receive the value
+ * \param p On entry, \c *p points to the start of the ASN.1 element.
+ * On successful completion, \c *p is equal to \p end.
+ * On error, the value of \c *p is undefined.
+ * \param end End of data.
+ * \param bs On success, ::mbedtls_asn1_bitstring information about
+ * the parsed value.
*
- * \return 0 if successful or a specific ASN.1 error code.
+ * \return 0 if successful.
+ * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains
+ * extra data after a valid BIT STRING.
+ * \return An ASN.1 error code if the input does not start with
+ * a valid ASN.1 BIT STRING.
*/
int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
- mbedtls_asn1_bitstring *bs);
+ mbedtls_asn1_bitstring *bs );
/**
* \brief Retrieve a bitstring ASN.1 tag without unused bits and its
* value.
* Updates the pointer to the beginning of the bit/octet string.
*
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param len Length of the actual bit/octect string in bytes
+ * \param p On entry, \c *p points to the start of the ASN.1 element.
+ * On successful completion, \c *p points to the first byte
+ * of the content of the BIT STRING.
+ * On error, the value of \c *p is undefined.
+ * \param end End of data.
+ * \param len On success, \c *len is the length of the content in bytes.
*
- * \return 0 if successful or a specific ASN.1 error code.
+ * \return 0 if successful.
+ * \return #MBEDTLS_ERR_ASN1_INVALID_DATA if the input starts with
+ * a valid BIT STRING with a nonzero number of unused bits.
+ * \return An ASN.1 error code if the input does not start with
+ * a valid ASN.1 BIT STRING.
*/
-int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
- size_t *len );
+int mbedtls_asn1_get_bitstring_null( unsigned char **p,
+ const unsigned char *end,
+ size_t *len );
/**
- * \brief Parses and splits an ASN.1 "SEQUENCE OF <tag>"
- * Updated the pointer to immediately behind the full sequence tag.
+ * \brief Parses and splits an ASN.1 "SEQUENCE OF <tag>".
+ * Updates the pointer to immediately behind the full sequence tag.
*
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param cur First variable in the chain to fill
- * \param tag Type of sequence
+ * This function allocates memory for the sequence elements. You can free
+ * the allocated memory with mbedtls_asn1_sequence_free().
*
- * \return 0 if successful or a specific ASN.1 error code.
+ * \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
+ * pointer from a pointer to an object allocated by this function.
+ *
+ * \note If the sequence is empty, this function does not modify
+ * \c *cur. If the sequence is valid and non-empty, this
+ * function sets `cur->buf.tag` to \p tag. This allows
+ * callers to distinguish between an empty sequence and
+ * a one-element sequence.
+ *
+ * \param p On entry, \c *p points to the start of the ASN.1 element.
+ * On successful completion, \c *p is equal to \p end.
+ * On error, the value of \c *p is undefined.
+ * \param end End of data.
+ * \param cur A ::mbedtls_asn1_sequence which this function fills.
+ * When this function returns, \c *cur is the head of a linked
+ * list. Each node in this list is allocated with
+ * mbedtls_calloc() apart from \p cur itself, and should
+ * therefore be freed with mbedtls_free().
+ * The list describes the content of the sequence.
+ * The head of the list (i.e. \c *cur itself) describes the
+ * first element, `*cur->next` describes the second element, etc.
+ * For each element, `buf.tag == tag`, `buf.len` is the length
+ * of the content of the content of the element, and `buf.p`
+ * points to the first byte of the content (i.e. immediately
+ * past the length of the element).
+ * Note that list elements may be allocated even on error.
+ * \param tag Each element of the sequence must have this tag.
+ *
+ * \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 SEQUENCE.
*/
int mbedtls_asn1_get_sequence_of( unsigned char **p,
- const unsigned char *end,
- mbedtls_asn1_sequence *cur,
- int tag);
+ 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)
/**
- * \brief Retrieve a MPI value from an integer ASN.1 tag.
+ * \brief Retrieve an integer ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
*
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param X The MPI that will receive the value
+ * \param p On entry, \c *p points to the start of the ASN.1 element.
+ * On successful completion, \c *p points to the first byte
+ * beyond the ASN.1 element.
+ * On error, the value of \c *p is undefined.
+ * \param end End of data.
+ * \param X On success, the parsed value.
*
- * \return 0 if successful or a specific ASN.1 or MPI error code.
+ * \return 0 if successful.
+ * \return An ASN.1 error code if the input does not start with
+ * a valid ASN.1 INTEGER.
+ * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
+ * not fit in an \c int.
+ * \return An MPI error code if the parsed value is too large.
*/
int mbedtls_asn1_get_mpi( unsigned char **p,
- const unsigned char *end,
- mbedtls_mpi *X );
+ const unsigned char *end,
+ mbedtls_mpi *X );
#endif /* MBEDTLS_BIGNUM_C */
/**
@@ -296,10 +536,14 @@
* Updates the pointer to immediately behind the full
* AlgorithmIdentifier.
*
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param alg The buffer to receive the OID
- * \param params The buffer to receive the params (if any)
+ * \param p On entry, \c *p points to the start of the ASN.1 element.
+ * On successful completion, \c *p points to the first byte
+ * beyond the AlgorithmIdentifier element.
+ * On error, the value of \c *p is undefined.
+ * \param end End of data.
+ * \param alg The buffer to receive the OID.
+ * \param params The buffer to receive the parameters.
+ * This is zeroized if there are no parameters.
*
* \return 0 if successful or a specific ASN.1 or MPI error code.
*/
@@ -313,9 +557,12 @@
* Updates the pointer to immediately behind the full
* AlgorithmIdentifier.
*
- * \param p The position in the ASN.1 data
- * \param end End of data
- * \param alg The buffer to receive the OID
+ * \param p On entry, \c *p points to the start of the ASN.1 element.
+ * On successful completion, \c *p points to the first byte
+ * beyond the AlgorithmIdentifier element.
+ * On error, the value of \c *p is undefined.
+ * \param end End of data.
+ * \param alg The buffer to receive the OID.
*
* \return 0 if successful or a specific ASN.1 or MPI error code.
*/
@@ -339,15 +586,19 @@
/**
* \brief Free a mbedtls_asn1_named_data entry
*
- * \param entry The named data entry to free
+ * \param entry The named data entry to free.
+ * This function calls mbedtls_free() on
+ * `entry->oid.p` and `entry->val.p`.
*/
void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry );
/**
- * \brief Free all entries in a mbedtls_asn1_named_data list
- * Head will be set to NULL
+ * \brief Free all entries in a mbedtls_asn1_named_data list.
*
- * \param head Pointer to the head of the list of named data entries to free
+ * \param head Pointer to the head of the list of named data entries to free.
+ * This function calls mbedtls_asn1_free_named_data() and
+ * mbedtls_free() on each list element and
+ * sets \c *head to \c NULL.
*/
void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head );
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h b/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h
index 1f9ff89..12b1369 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h
@@ -25,12 +25,12 @@
#define MBEDTLS_ASN1_WRITE_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "asn1.h"
+#include "mbedtls/asn1.h"
#define MBEDTLS_ASN1_CHK_ADD(g, f) \
do \
@@ -100,6 +100,7 @@
* \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param X The MPI to write.
+ * It must be non-negative.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
@@ -184,6 +185,7 @@
* \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param val The integer value to write.
+ * It must be non-negative.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
@@ -191,6 +193,21 @@
int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val );
/**
+ * \brief Write an enum tag (#MBEDTLS_ASN1_ENUMERATED) and value
+ * in ASN.1 format.
+ *
+ * \note This function works backwards in data buffer.
+ *
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param val The integer value to write.
+ *
+ * \return The number of bytes written to \p p on success.
+ * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
+ */
+int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val );
+
+/**
* \brief Write a string in ASN.1 format using a specific
* string encoding tag.
@@ -232,7 +249,7 @@
/**
* \brief Write a UTF8 string in ASN.1 format using the UTF8String
- * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING).
+ * string encoding tag (#MBEDTLS_ASN1_UTF8_STRING).
*
* \note This function works backwards in data buffer.
*
@@ -284,6 +301,28 @@
const unsigned char *buf, size_t bits );
/**
+ * \brief This function writes a named bitstring tag
+ * (#MBEDTLS_ASN1_BIT_STRING) and value in ASN.1 format.
+ *
+ * As stated in RFC 5280 Appendix B, trailing zeroes are
+ * omitted when encoding named bitstrings in DER.
+ *
+ * \note This function works backwards within the data buffer.
+ *
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer which is used for bounds-checking.
+ * \param buf The bitstring to write.
+ * \param bits The total number of bits in the bitstring.
+ *
+ * \return The number of bytes written to \p p on success.
+ * \return A negative error code on failure.
+ */
+int mbedtls_asn1_write_named_bitstring( unsigned char **p,
+ unsigned char *start,
+ const unsigned char *buf,
+ size_t bits );
+
+/**
* \brief Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING)
* and value in ASN.1 format.
*
@@ -310,9 +349,13 @@
* through (will be updated in case of a new entry).
* \param oid The OID to look for.
* \param oid_len The size of the OID.
- * \param val The data to store (can be \c NULL if you want to fill
- * it by hand).
+ * \param val The associated data to store. If this is \c NULL,
+ * no data is copied to the new or existing buffer.
* \param val_len The minimum length of the data buffer needed.
+ * If this is 0, do not allocate a buffer for the associated
+ * data.
+ * If the OID was already present, enlarge, shrink or free
+ * the existing buffer to fit \p val_len.
*
* \return A pointer to the new / existing entry on success.
* \return \c NULL if if there was a memory allocation error.
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/base64.h b/lib/libmbedtls/mbedtls/include/mbedtls/base64.h
index dfd6c21..4586171 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/base64.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/base64.h
@@ -25,7 +25,7 @@
#define MBEDTLS_BASE64_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h b/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h
index 045f236..4b4ca3d 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h
@@ -25,7 +25,7 @@
#define MBEDTLS_BIGNUM_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
@@ -129,7 +129,8 @@
defined(__ppc64__) || defined(__powerpc64__) || \
defined(__ia64__) || defined(__alpha__) || \
( defined(__sparc__) && defined(__arch64__) ) || \
- defined(__s390x__) || defined(__mips64) )
+ defined(__s390x__) || defined(__mips64) || \
+ defined(__aarch64__) )
#if !defined(MBEDTLS_HAVE_INT64)
#define MBEDTLS_HAVE_INT64
#endif /* MBEDTLS_HAVE_INT64 */
@@ -499,8 +500,24 @@
size_t buflen );
/**
- * \brief Export an MPI into unsigned big endian binary data
- * of fixed size.
+ * \brief Import X from unsigned binary data, little endian
+ *
+ * \param X The destination MPI. This must point to an initialized MPI.
+ * \param buf The input buffer. This must be a readable buffer of length
+ * \p buflen Bytes.
+ * \param buflen The length of the input buffer \p p in Bytes.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
+ * \return Another negative error code on different kinds of failure.
+ */
+int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
+ const unsigned char *buf, size_t buflen );
+
+/**
+ * \brief Export X into unsigned binary data, big endian.
+ * Always fills the whole buffer, which will start with zeros
+ * if the number is smaller.
*
* \param X The source MPI. This must point to an initialized MPI.
* \param buf The output buffer. This must be a writable buffer of length
@@ -516,6 +533,24 @@
size_t buflen );
/**
+ * \brief Export X into unsigned binary data, little endian.
+ * Always fills the whole buffer, which will end with zeros
+ * if the number is smaller.
+ *
+ * \param X The source MPI. This must point to an initialized MPI.
+ * \param buf The output buffer. This must be a writable buffer of length
+ * \p buflen Bytes.
+ * \param buflen The size of the output buffer \p buf in Bytes.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't
+ * large enough to hold the value of \p X.
+ * \return Another negative error code on different kinds of failure.
+ */
+int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
+ unsigned char *buf, size_t buflen );
+
+/**
* \brief Perform a left-shift on an MPI: X <<= count
*
* \param X The MPI to shift. This must point to an initialized MPI.
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/blowfish.h b/lib/libmbedtls/mbedtls/include/mbedtls/blowfish.h
index bc518c2..7882110 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/blowfish.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/blowfish.h
@@ -25,7 +25,7 @@
#define MBEDTLS_BLOWFISH_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
@@ -33,7 +33,7 @@
#include <stddef.h>
#include <stdint.h>
-#include "platform_util.h"
+#include "mbedtls/platform_util.h"
#define MBEDTLS_BLOWFISH_ENCRYPT 1
#define MBEDTLS_BLOWFISH_DECRYPT 0
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/bn_mul.h b/lib/libmbedtls/mbedtls/include/mbedtls/bn_mul.h
index 2b808ad..9076c21 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/bn_mul.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/bn_mul.h
@@ -39,12 +39,12 @@
#define MBEDTLS_BN_MUL_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "bignum.h"
+#include "mbedtls/bignum.h"
#if defined(MBEDTLS_HAVE_ASM)
@@ -198,6 +198,30 @@
#endif /* AMD64 */
+#if defined(__aarch64__)
+
+#define MULADDC_INIT \
+ asm(
+
+#define MULADDC_CORE \
+ "ldr x4, [%2], #8 \n\t" \
+ "ldr x5, [%1] \n\t" \
+ "mul x6, x4, %3 \n\t" \
+ "umulh x7, x4, %3 \n\t" \
+ "adds x5, x5, x6 \n\t" \
+ "adc x7, x7, xzr \n\t" \
+ "adds x5, x5, %0 \n\t" \
+ "adc %0, x7, xzr \n\t" \
+ "str x5, [%1], #8 \n\t"
+
+#define MULADDC_STOP \
+ : "+r" (c), "+r" (d), "+r" (s) \
+ : "r" (b) \
+ : "x4", "x5", "x6", "x7", "cc" \
+ );
+
+#endif /* Aarch64 */
+
#if defined(__mc68020__) || defined(__mcpu32__)
#define MULADDC_INIT \
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h b/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h
index 6c0a734..1697141 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h
@@ -25,7 +25,7 @@
#define MBEDTLS_CAMELLIA_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
@@ -33,7 +33,7 @@
#include <stddef.h>
#include <stdint.h>
-#include "platform_util.h"
+#include "mbedtls/platform_util.h"
#define MBEDTLS_CAMELLIA_ENCRYPT 1
#define MBEDTLS_CAMELLIA_DECRYPT 0
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h b/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h
index 228d866..c3fb759 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h
@@ -50,12 +50,12 @@
#define MBEDTLS_CCM_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "cipher.h"
+#include "mbedtls/cipher.h"
#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */
#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/certs.h b/lib/libmbedtls/mbedtls/include/mbedtls/certs.h
index 343aa38..ce4aa5f 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/certs.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/certs.h
@@ -25,7 +25,7 @@
#define MBEDTLS_CERTS_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h b/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h
index 5257b99..a8c155e 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h
@@ -34,7 +34,7 @@
#define MBEDTLS_CHACHA20_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h b/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h
index b2103ca..766cebe 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h
@@ -34,13 +34,13 @@
#define MBEDTLS_CHACHAPOLY_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
/* for shared error codes */
-#include "poly1305.h"
+#include "mbedtls/poly1305.h"
#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE -0x0054 /**< The requested operation is not permitted in the current state. */
#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED -0x0056 /**< Authenticated decryption failed: data was not authentic. */
@@ -58,7 +58,7 @@
#if !defined(MBEDTLS_CHACHAPOLY_ALT)
-#include "chacha20.h"
+#include "mbedtls/chacha20.h"
typedef struct mbedtls_chachapoly_context
{
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h b/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h
index d6028c6..e2bc10a 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h
@@ -45,11 +45,16 @@
#endif
/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as
- * it would confuse config.pl. */
+ * it would confuse config.py. */
#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \
!defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO)
#define MBEDTLS_PLATFORM_SNPRINTF_ALT
#endif
+
+#if !defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && \
+ !defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO)
+#define MBEDTLS_PLATFORM_VSNPRINTF_ALT
+#endif
#endif /* _WIN32 */
#if defined(TARGET_LIKE_MBED) && \
@@ -109,14 +114,25 @@
#endif
#if defined(MBEDTLS_ECP_RESTARTABLE) && \
- ( defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \
+ ( defined(MBEDTLS_USE_PSA_CRYPTO) || \
+ defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \
defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \
defined(MBEDTLS_ECDSA_SIGN_ALT) || \
defined(MBEDTLS_ECDSA_VERIFY_ALT) || \
defined(MBEDTLS_ECDSA_GENKEY_ALT) || \
defined(MBEDTLS_ECP_INTERNAL_ALT) || \
defined(MBEDTLS_ECP_ALT) )
-#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative ECP implementation"
+#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative or PSA-based ECP implementation"
+#endif
+
+#if defined(MBEDTLS_ECP_RESTARTABLE) && \
+ ! defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+#error "MBEDTLS_ECP_RESTARTABLE defined, but not MBEDTLS_ECDH_LEGACY_CONTEXT"
+#endif
+
+#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) && \
+ defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+#error "MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED defined, but MBEDTLS_ECDH_LEGACY_CONTEXT not disabled"
#endif
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C)
@@ -173,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
@@ -276,6 +292,14 @@
#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites"
#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \
+ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) && \
+ ( !defined(MBEDTLS_SHA256_C) && \
+ !defined(MBEDTLS_SHA512_C) && \
+ !defined(MBEDTLS_SHA1_C) )
+#error "!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE requires MBEDTLS_SHA512_C, MBEDTLS_SHA256_C or MBEDTLS_SHA1_C"
+#endif
+
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \
( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) )
#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites"
@@ -318,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
@@ -511,6 +543,43 @@
#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously"
#endif
+#if defined(MBEDTLS_PSA_CRYPTO_C) && \
+ !( defined(MBEDTLS_CTR_DRBG_C) && \
+ defined(MBEDTLS_ENTROPY_C) )
+#error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_SPM) && !defined(MBEDTLS_PSA_CRYPTO_C)
+#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"
+#endif
+
+#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \
+ !( defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \
+ defined(MBEDTLS_ENTROPY_NV_SEED) )
+#error "MBEDTLS_PSA_INJECT_ENTROPY defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \
+ !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
+#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with actual entropy sources"
+#endif
+
+#if defined(MBEDTLS_PSA_ITS_FILE_C) && \
+ !defined(MBEDTLS_FS_IO)
+#error "MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites"
+#endif
+
#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \
!defined(MBEDTLS_OID_C) )
#error "MBEDTLS_RSA_C defined, but not all prerequisites"
@@ -526,6 +595,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"
@@ -546,6 +619,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)
@@ -601,6 +691,23 @@
#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites"
#endif
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
+ ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) )
+#error "MBEDTLS_SSL_DTLS_CONNECTION_ID defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
+ defined(MBEDTLS_SSL_CID_IN_LEN_MAX) && \
+ MBEDTLS_SSL_CID_IN_LEN_MAX > 255
+#error "MBEDTLS_SSL_CID_IN_LEN_MAX too large (max 255)"
+#endif
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
+ defined(MBEDTLS_SSL_CID_OUT_LEN_MAX) && \
+ MBEDTLS_SSL_CID_OUT_LEN_MAX > 255
+#error "MBEDTLS_SSL_CID_OUT_LEN_MAX too large (max 255)"
+#endif
+
#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \
( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) )
#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites"
@@ -653,6 +760,10 @@
#endif
#undef MBEDTLS_THREADING_IMPL
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_C)
+#error "MBEDTLS_USE_PSA_CRYPTO defined, but not all prerequisites"
+#endif
+
#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C)
#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites"
#endif
@@ -669,6 +780,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
@@ -698,6 +813,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/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h b/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h
index de4374f..1c4f371 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h
@@ -30,13 +30,13 @@
#define MBEDTLS_CIPHER_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h>
-#include "platform_util.h"
+#include "mbedtls/platform_util.h"
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
#define MBEDTLS_CIPHER_MODE_AEAD
@@ -176,21 +176,29 @@
MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */
MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */
MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */
+ MBEDTLS_CIPHER_AES_128_KW, /**< AES cipher with 128-bit NIST KW mode. */
+ MBEDTLS_CIPHER_AES_192_KW, /**< AES cipher with 192-bit NIST KW mode. */
+ MBEDTLS_CIPHER_AES_256_KW, /**< AES cipher with 256-bit NIST KW mode. */
+ MBEDTLS_CIPHER_AES_128_KWP, /**< AES cipher with 128-bit NIST KWP mode. */
+ MBEDTLS_CIPHER_AES_192_KWP, /**< AES cipher with 192-bit NIST KWP mode. */
+ MBEDTLS_CIPHER_AES_256_KWP, /**< AES cipher with 256-bit NIST KWP mode. */
} mbedtls_cipher_type_t;
/** Supported cipher modes. */
typedef enum {
- MBEDTLS_MODE_NONE = 0, /**< None. */
- MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */
- MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */
- MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */
- MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */
- MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */
- MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */
- MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */
- MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */
- MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */
+ MBEDTLS_MODE_NONE = 0, /**< None. */
+ MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */
+ MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */
+ MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */
+ MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */
+ MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */
+ MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */
+ MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */
+ MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */
+ MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */
MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */
+ MBEDTLS_MODE_KW, /**< The SP800-38F KW mode */
+ MBEDTLS_MODE_KWP, /**< The SP800-38F KWP mode */
} mbedtls_cipher_mode_t;
/** Supported cipher padding types. */
@@ -322,14 +330,32 @@
/** CMAC-specific context. */
mbedtls_cmac_context_t *cmac_ctx;
#endif
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ /** Indicates whether the cipher operations should be performed
+ * by Mbed TLS' own crypto library or an external implementation
+ * of the PSA Crypto API.
+ * This is unset if the cipher context was established through
+ * mbedtls_cipher_setup(), and set if it was established through
+ * mbedtls_cipher_setup_psa().
+ */
+ unsigned char psa_enabled;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
} mbedtls_cipher_context_t;
/**
- * \brief This function retrieves the list of ciphers supported by the generic
- * cipher module.
+ * \brief This function retrieves the list of ciphers supported
+ * by the generic cipher module.
*
- * \return A statically-allocated array of ciphers. The last entry
- * is zero.
+ * For any cipher identifier in the returned list, you can
+ * obtain the corresponding generic cipher information structure
+ * via mbedtls_cipher_info_from_type(), which can then be used
+ * to prepare a cipher context via mbedtls_cipher_setup().
+ *
+ *
+ * \return A statically-allocated array of cipher identifiers
+ * of type cipher_type_t. The last entry is zero.
*/
const int *mbedtls_cipher_list( void );
@@ -410,9 +436,8 @@
const mbedtls_cipher_context_t *src );
/**
- * \brief This function initializes and fills the cipher-context
- * structure with the appropriate values. It also clears
- * the structure.
+ * \brief This function initializes a cipher context for
+ * use with the given cipher primitive.
*
* \param ctx The context to initialize. This must be initialized.
* \param cipher_info The cipher to use.
@@ -430,6 +455,33 @@
int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx,
const mbedtls_cipher_info_t *cipher_info );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/**
+ * \brief This function initializes a cipher context for
+ * PSA-based use with the given cipher primitive.
+ *
+ * \note See #MBEDTLS_USE_PSA_CRYPTO for information on PSA.
+ *
+ * \param ctx The context to initialize. May not be \c NULL.
+ * \param cipher_info The cipher to use.
+ * \param taglen For AEAD ciphers, the length in bytes of the
+ * authentication tag to use. Subsequent uses of
+ * mbedtls_cipher_auth_encrypt() or
+ * mbedtls_cipher_auth_decrypt() must provide
+ * the same tag length.
+ * For non-AEAD ciphers, the value must be \c 0.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
+ * parameter-verification failure.
+ * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the
+ * cipher-specific context fails.
+ */
+int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx,
+ const mbedtls_cipher_info_t *cipher_info,
+ size_t taglen );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
/**
* \brief setup the cipher info structure.
*
@@ -663,7 +715,7 @@
* \param ctx The generic cipher context. This must be initialized.
* \param ad The additional data to use. This must be a readable
* buffer of at least \p ad_len Bytes.
- * \param ad_len the Length of \p ad Bytes.
+ * \param ad_len The length of \p ad in Bytes.
*
* \return \c 0 on success.
* \return A specific error code on failure.
@@ -706,8 +758,10 @@
* unsupported mode for a cipher.
* \return A cipher-specific error code on failure.
*/
-int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
- size_t ilen, unsigned char *output, size_t *olen );
+int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx,
+ const unsigned char *input,
+ size_t ilen, unsigned char *output,
+ size_t *olen );
/**
* \brief The generic cipher finalization function. If data still
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/cipher_internal.h b/lib/libmbedtls/mbedtls/include/mbedtls/cipher_internal.h
index dc08f20..6089241 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/cipher_internal.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/cipher_internal.h
@@ -27,12 +27,16 @@
#define MBEDTLS_CIPHER_WRAP_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "cipher.h"
+#include "mbedtls/cipher.h"
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
#ifdef __cplusplus
extern "C" {
@@ -117,6 +121,29 @@
const mbedtls_cipher_info_t *info;
} mbedtls_cipher_definition_t;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+typedef enum
+{
+ MBEDTLS_CIPHER_PSA_KEY_UNSET = 0,
+ MBEDTLS_CIPHER_PSA_KEY_OWNED, /* Used for PSA-based cipher contexts which */
+ /* use raw key material internally imported */
+ /* as a volatile key, and which hence need */
+ /* to destroy that key when the context is */
+ /* freed. */
+ MBEDTLS_CIPHER_PSA_KEY_NOT_OWNED, /* Used for PSA-based cipher contexts */
+ /* which use a key provided by the */
+ /* user, and which hence will not be */
+ /* destroyed when the context is freed. */
+} mbedtls_cipher_psa_key_ownership;
+
+typedef struct
+{
+ psa_algorithm_t alg;
+ psa_key_handle_t slot;
+ mbedtls_cipher_psa_key_ownership slot_state;
+} mbedtls_cipher_context_psa;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[];
extern int mbedtls_cipher_supported[];
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h b/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h
index 30e3736..1759f2e 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h
@@ -29,12 +29,12 @@
#define MBEDTLS_CMAC_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "cipher.h"
+#include "mbedtls/cipher.h"
#ifdef __cplusplus
extern "C" {
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/compat-1.3.h b/lib/libmbedtls/mbedtls/include/mbedtls/compat-1.3.h
index 0818acd..c64d06e 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/compat-1.3.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/compat-1.3.h
@@ -26,7 +26,7 @@
*/
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
@@ -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/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h b/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h
index 1742c47..b80ee96 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h
@@ -13,30 +13,14 @@
* The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128
* (if \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time)
* as the underlying block cipher, with a derivation function.
- * The initial seeding grabs #MBEDTLS_CTR_DRBG_ENTROPY_LEN bytes of entropy.
- * See the documentation of mbedtls_ctr_drbg_seed() for more details.
*
- * Based on NIST SP 800-90A §10.2.1 table 3 and NIST SP 800-57 part 1 table 2,
- * here are the security strengths achieved in typical configuration:
- * - 256 bits under the default configuration of the library, with AES-256
- * and with #MBEDTLS_CTR_DRBG_ENTROPY_LEN set to 48 or more.
- * - 256 bits if AES-256 is used, #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set
- * to 32 or more, and the DRBG is initialized with an explicit
- * nonce in the \c custom parameter to mbedtls_ctr_drbg_seed().
- * - 128 bits if AES-256 is used but #MBEDTLS_CTR_DRBG_ENTROPY_LEN is
- * between 24 and 47 and the DRBG is not initialized with an explicit
- * nonce (see mbedtls_ctr_drbg_seed()).
- * - 128 bits if AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled)
- * and #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set to 24 or more (which is
- * always the case unless it is explicitly set to a different value
- * in config.h).
- *
- * Note that the value of #MBEDTLS_CTR_DRBG_ENTROPY_LEN defaults to:
- * - \c 48 if the module \c MBEDTLS_SHA512_C is enabled and the symbol
- * \c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled at compile time.
- * This is the default configuration of the library.
- * - \c 32 if the module \c MBEDTLS_SHA512_C is disabled at compile time.
- * - \c 32 if \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled at compile time.
+ * The security strength as defined in NIST SP 800-90A is
+ * 128 bits when AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled)
+ * and 256 bits otherwise, provided that #MBEDTLS_CTR_DRBG_ENTROPY_LEN is
+ * kept at its default value (and not overridden in config.h) and that the
+ * DRBG instance is set up with default parameters.
+ * See the documentation of mbedtls_ctr_drbg_seed() for more
+ * information.
*/
/*
* Copyright (C) 2006-2019, Arm Limited (or its affiliates), All Rights Reserved
@@ -60,15 +44,15 @@
#define MBEDTLS_CTR_DRBG_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "aes.h"
+#include "mbedtls/aes.h"
#if defined(MBEDTLS_THREADING_C)
-#include "threading.h"
+#include "mbedtls/threading.h"
#endif
#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */
@@ -163,20 +147,49 @@
extern "C" {
#endif
+#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2
+/** The default length of the nonce read from the entropy source.
+ *
+ * This is \c 0 because a single read from the entropy source is sufficient
+ * to include a nonce.
+ * See the documentation of mbedtls_ctr_drbg_seed() for more information.
+ */
+#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN 0
+#else
+/** The default length of the nonce read from the entropy source.
+ *
+ * This is half of the default entropy length because a single read from
+ * the entropy source does not provide enough material to form a nonce.
+ * See the documentation of mbedtls_ctr_drbg_seed() for more information.
+ */
+#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN ( MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1 ) / 2
+#endif
+
/**
* \brief The CTR_DRBG context structure.
*/
typedef struct mbedtls_ctr_drbg_context
{
unsigned char counter[16]; /*!< The counter (V). */
- int reseed_counter; /*!< The reseed counter. */
+ int reseed_counter; /*!< The reseed counter.
+ * This is the number of requests that have
+ * been made since the last (re)seeding,
+ * minus one.
+ * Before the initial seeding, this field
+ * contains the amount of entropy in bytes
+ * to use as a nonce for the initial seeding,
+ * or -1 if no nonce length has been explicitly
+ * set (see mbedtls_ctr_drbg_set_nonce_len()).
+ */
int prediction_resistance; /*!< This determines whether prediction
resistance is enabled, that is
whether to systematically reseed before
each random generation. */
size_t entropy_len; /*!< The amount of entropy grabbed on each
- seed or reseed operation. */
- int reseed_interval; /*!< The reseed interval. */
+ seed or reseed operation, in bytes. */
+ int reseed_interval; /*!< The reseed interval.
+ * This is the maximum number of requests
+ * that can be made between reseedings. */
mbedtls_aes_context aes_ctx; /*!< The AES context. */
@@ -217,37 +230,55 @@
* The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default.
* You can override it by calling mbedtls_ctr_drbg_set_entropy_len().
*
- * You can provide a personalization string in addition to the
- * entropy source, to make this instantiation as unique as possible.
+ * The entropy nonce length is:
+ * - \c 0 if the entropy length is at least 3/2 times the entropy length,
+ * which guarantees that the security strength is the maximum permitted
+ * by the key size and entropy length according to NIST SP 800-90A §10.2.1;
+ * - Half the entropy length otherwise.
+ * You can override it by calling mbedtls_ctr_drbg_set_nonce_len().
+ * With the default entropy length, the entropy nonce length is
+ * #MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN.
*
- * \note The _seed_material_ value passed to the derivation
- * function in the CTR_DRBG Instantiate Process
- * described in NIST SP 800-90A §10.2.1.3.2
- * is the concatenation of the string obtained from
- * calling \p f_entropy and the \p custom string.
- * The origin of the nonce depends on the value of
- * the entropy length relative to the security strength.
- * - If the entropy length is at least 1.5 times the
- * security strength then the nonce is taken from the
- * string obtained with \p f_entropy.
- * - If the entropy length is less than the security
- * strength, then the nonce is taken from \p custom.
- * In this case, for compliance with SP 800-90A,
- * you must pass a unique value of \p custom at
- * each invocation. See SP 800-90A §8.6.7 for more
- * details.
+ * You can provide a nonce and personalization string in addition to the
+ * entropy source, to make this instantiation as unique as possible.
+ * See SP 800-90A §8.6.7 for more details about nonces.
+ *
+ * The _seed_material_ value passed to the derivation function in
+ * the CTR_DRBG Instantiate Process described in NIST SP 800-90A §10.2.1.3.2
+ * is the concatenation of the following strings:
+ * - A string obtained by calling \p f_entropy function for the entropy
+ * length.
*/
-#if MBEDTLS_CTR_DRBG_ENTROPY_LEN < MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2
-/** \warning When #MBEDTLS_CTR_DRBG_ENTROPY_LEN is less than
- * #MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2, to achieve the
- * maximum security strength permitted by CTR_DRBG,
- * you must pass a value of \p custom that is a nonce:
- * this value must never be repeated in subsequent
- * runs of the same application or on a different
- * device.
+#if MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN == 0
+/**
+ * - If mbedtls_ctr_drbg_set_nonce_len() has been called, a string
+ * obtained by calling \p f_entropy function for the specified length.
+ */
+#else
+/**
+ * - A string obtained by calling \p f_entropy function for the entropy nonce
+ * length. If the entropy nonce length is \c 0, this function does not
+ * make a second call to \p f_entropy.
*/
#endif
/**
+ * - The \p custom string.
+ *
+ * \note To achieve the nominal security strength permitted
+ * by CTR_DRBG, the entropy length must be:
+ * - at least 16 bytes for a 128-bit strength
+ * (maximum achievable strength when using AES-128);
+ * - at least 32 bytes for a 256-bit strength
+ * (maximum achievable strength when using AES-256).
+ *
+ * In addition, if you do not pass a nonce in \p custom,
+ * the sum of the entropy length
+ * and the entropy nonce length must be:
+ * - at least 24 bytes for a 128-bit strength
+ * (maximum achievable strength when using AES-128);
+ * - at least 48 bytes for a 256-bit strength
+ * (maximum achievable strength when using AES-256).
+ *
* \param ctx The CTR_DRBG context to seed.
* It must have been initialized with
* mbedtls_ctr_drbg_init().
@@ -260,7 +291,7 @@
* \p p_entropy context, the buffer to fill, and the
* length of the buffer.
* \p f_entropy is always called with a buffer size
- * equal to the entropy length.
+ * less than or equal to the entropy length.
* \param p_entropy The entropy context to pass to \p f_entropy.
* \param custom The personalization string.
* This can be \c NULL, in which case the personalization
@@ -322,12 +353,36 @@
*
* \param ctx The CTR_DRBG context.
* \param len The amount of entropy to grab, in bytes.
- * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
+ * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
+ * and at most the maximum length accepted by the
+ * entropy function that is set in the context.
*/
void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
size_t len );
/**
+ * \brief This function sets the amount of entropy grabbed
+ * as a nonce for the initial seeding.
+ *
+ * Call this function before calling mbedtls_ctr_drbg_seed() to read
+ * a nonce from the entropy source during the initial seeding.
+ *
+ * \param ctx The CTR_DRBG context.
+ * \param len The amount of entropy to grab for the nonce, in bytes.
+ * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
+ * and at most the maximum length accepted by the
+ * entropy function that is set in the context.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if \p len is
+ * more than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
+ * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
+ * if the initial seeding has already taken place.
+ */
+int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
+ size_t len );
+
+/**
* \brief This function sets the reseed interval.
*
* The reseed interval is the number of calls to mbedtls_ctr_drbg_random()
@@ -500,11 +555,6 @@
#endif /* MBEDTLS_SELF_TEST */
-/* Internal functions (do not call directly) */
-int mbedtls_ctr_drbg_seed_entropy_len( mbedtls_ctr_drbg_context *,
- int (*)(void *, unsigned char *, size_t), void *,
- const unsigned char *, size_t, size_t );
-
#ifdef __cplusplus
}
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/debug.h b/lib/libmbedtls/mbedtls/include/mbedtls/debug.h
index d51a94c..7ce28d6 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/debug.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/debug.h
@@ -25,15 +25,15 @@
#define MBEDTLS_DEBUG_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "ssl.h"
+#include "mbedtls/ssl.h"
#if defined(MBEDTLS_ECP_C)
-#include "ecp.h"
+#include "mbedtls/ecp.h"
#endif
#if defined(MBEDTLS_DEBUG_C)
@@ -262,4 +262,3 @@
#endif
#endif /* debug.h */
-
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/des.h b/lib/libmbedtls/mbedtls/include/mbedtls/des.h
index ad18b59..fa0f0bb 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/des.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/des.h
@@ -30,7 +30,7 @@
#define MBEDTLS_DES_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h b/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h
index 3c987fb..cc4d652 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h
@@ -66,11 +66,11 @@
#define MBEDTLS_DHM_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "bignum.h"
+#include "mbedtls/bignum.h"
/*
* DHM Error codes
@@ -298,7 +298,6 @@
void mbedtls_dhm_free( mbedtls_dhm_context *ctx );
#if defined(MBEDTLS_ASN1_PARSE_C)
-/** \ingroup x509_module */
/**
* \brief This function parses DHM parameters in PEM or DER format.
*
@@ -317,7 +316,6 @@
size_t dhminlen );
#if defined(MBEDTLS_FS_IO)
-/** \ingroup x509_module */
/**
* \brief This function loads and parses DHM parameters from a file.
*
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h b/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h
index af9e62d..02de74f 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h
@@ -35,24 +35,17 @@
#define MBEDTLS_ECDH_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "ecp.h"
+#include "mbedtls/ecp.h"
-/*
- * Use a backward compatible ECDH context.
- *
- * This flag is always enabled for now and future versions might add a
- * configuration option that conditionally undefines this flag.
- * The configuration option in question may have a different name.
- *
- * Features undefining this flag, must have a warning in their description in
- * config.h stating that the feature breaks backward compatibility.
- */
-#define MBEDTLS_ECDH_LEGACY_CONTEXT
+#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+#undef MBEDTLS_ECDH_LEGACY_CONTEXT
+#include "everest/everest.h"
+#endif
#ifdef __cplusplus
extern "C" {
@@ -78,6 +71,9 @@
{
MBEDTLS_ECDH_VARIANT_NONE = 0, /*!< Implementation not defined. */
MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0,/*!< The default Mbed TLS implementation */
+#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+ MBEDTLS_ECDH_VARIANT_EVEREST /*!< Everest implementation */
+#endif
} mbedtls_ecdh_variant;
/**
@@ -131,6 +127,9 @@
union
{
mbedtls_ecdh_context_mbed mbed_ecdh;
+#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+ mbedtls_ecdh_context_everest everest_ecdh;
+#endif
} ctx; /*!< Implementation-specific context. The
context in use is specified by the \c var
field. */
@@ -146,6 +145,15 @@
mbedtls_ecdh_context;
/**
+ * \brief Check whether a given group can be used for ECDH.
+ *
+ * \param gid The ECP group ID to check.
+ *
+ * \return \c 1 if the group can be used, \c 0 otherwise
+ */
+int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid );
+
+/**
* \brief This function generates an ECDH keypair on an elliptic
* curve.
*
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h b/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h
index dd8bdbd..aa1ddd0 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h
@@ -33,33 +33,38 @@
#define MBEDTLS_ECDSA_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "ecp.h"
-#include "md.h"
+#include "mbedtls/ecp.h"
+#include "mbedtls/md.h"
-/*
- * RFC-4492 page 20:
+/**
+ * \brief Maximum ECDSA signature size for a given curve bit size
*
+ * \param bits Curve size in bits
+ * \return Maximum signature size in bytes
+ *
+ * \note This macro returns a compile-time constant if its argument
+ * is one. It may evaluate its argument multiple times.
+ */
+/*
* Ecdsa-Sig-Value ::= SEQUENCE {
* r INTEGER,
* s INTEGER
* }
*
- * Size is at most
- * 1 (tag) + 1 (len) + 1 (initial 0) + ECP_MAX_BYTES for each of r and s,
- * twice that + 1 (tag) + 2 (len) for the sequence
- * (assuming ECP_MAX_BYTES is less than 126 for r and s,
- * and less than 124 (total len <= 255) for the sequence)
+ * For each of r and s, the value (V) may include an extra initial "0" bit.
*/
-#if MBEDTLS_ECP_MAX_BYTES > 124
-#error "MBEDTLS_ECP_MAX_BYTES bigger than expected, please fix MBEDTLS_ECDSA_MAX_LEN"
-#endif
+#define MBEDTLS_ECDSA_MAX_SIG_LEN( bits ) \
+ ( /*T,L of SEQUENCE*/ ( ( bits ) >= 61 * 8 ? 3 : 2 ) + \
+ /*T,L of r,s*/ 2 * ( ( ( bits ) >= 127 * 8 ? 3 : 2 ) + \
+ /*V of r,s*/ ( ( bits ) + 8 ) / 8 ) )
+
/** The maximal size of an ECDSA signature in Bytes. */
-#define MBEDTLS_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) )
+#define MBEDTLS_ECDSA_MAX_LEN MBEDTLS_ECDSA_MAX_SIG_LEN( MBEDTLS_ECP_MAX_BITS )
#ifdef __cplusplus
extern "C" {
@@ -121,6 +126,16 @@
#endif /* MBEDTLS_ECP_RESTARTABLE */
/**
+ * \brief This function checks whether a given group can be used
+ * for ECDSA.
+ *
+ * \param gid The ECP group ID to check.
+ *
+ * \return \c 1 if the group can be used, \c 0 otherwise
+ */
+int mbedtls_ecdsa_can_do( mbedtls_ecp_group_id gid );
+
+/**
* \brief This function computes the ECDSA signature of a
* previously-hashed message.
*
@@ -161,6 +176,12 @@
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+#if ! defined(MBEDTLS_DEPRECATED_REMOVED)
+#if defined(MBEDTLS_DEPRECATED_WARNING)
+#define MBEDTLS_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDTLS_DEPRECATED
+#endif
/**
* \brief This function computes the ECDSA signature of a
* previously-hashed message, deterministic version.
@@ -212,7 +233,10 @@
int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r,
mbedtls_mpi *s, const mbedtls_mpi *d,
const unsigned char *buf, size_t blen,
- mbedtls_md_type_t md_alg );
+ mbedtls_md_type_t md_alg ) MBEDTLS_DEPRECATED;
+#undef MBEDTLS_DEPRECATED
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
/**
* \brief This function computes the ECDSA signature of a
* previously-hashed message, deterministic version.
@@ -253,12 +277,11 @@
* error code on failure.
*/
int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r,
- mbedtls_mpi *s, const mbedtls_mpi *d,
- const unsigned char *buf, size_t blen,
- mbedtls_md_type_t md_alg,
- int (*f_rng_blind)(void *, unsigned char *,
- size_t),
- void *p_rng_blind );
+ mbedtls_mpi *s, const mbedtls_mpi *d,
+ const unsigned char *buf, size_t blen,
+ mbedtls_md_type_t md_alg,
+ int (*f_rng_blind)(void *, unsigned char *, size_t),
+ void *p_rng_blind );
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
/**
@@ -337,7 +360,8 @@
* the signature written. Must not be \c NULL.
* \param f_rng The RNG function. This must not be \c NULL if
* #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise,
- * it is unused and may be set to \c NULL.
+ * it is used only for blinding and may be set to \c NULL, but
+ * doing so is DEPRECATED.
* \param p_rng The RNG context to be passed to \p f_rng. This may be
* \c NULL if \p f_rng is \c NULL or doesn't use a context.
*
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h b/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h
index 9792e58..afb8ba7 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h
@@ -41,13 +41,13 @@
* also be use outside TLS.
*/
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "ecp.h"
-#include "md.h"
+#include "mbedtls/ecp.h"
+#include "mbedtls/md.h"
#ifdef __cplusplus
extern "C" {
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h b/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h
index c037cd7..35de01f 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h
@@ -37,12 +37,12 @@
#define MBEDTLS_ECP_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "bignum.h"
+#include "mbedtls/bignum.h"
/*
* ECP error codes
@@ -99,6 +99,16 @@
*/
#define MBEDTLS_ECP_DP_MAX 12
+/*
+ * Curve types
+ */
+typedef enum
+{
+ MBEDTLS_ECP_TYPE_NONE = 0,
+ MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
+ MBEDTLS_ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
+} mbedtls_ecp_curve_type;
+
/**
* Curve information, for use by other modules.
*/
@@ -417,11 +427,22 @@
int mbedtls_ecp_restart_is_enabled( void );
#endif /* MBEDTLS_ECP_RESTARTABLE */
+/*
+ * Get the type of a curve
+ */
+mbedtls_ecp_curve_type mbedtls_ecp_get_type( const mbedtls_ecp_group *grp );
+
/**
* \brief This function retrieves the information defined in
* mbedtls_ecp_curve_info() for all supported curves in order
* of preference.
*
+ * \note This function returns information about all curves
+ * supported by the library. Some curves may not be
+ * supported for all algorithms. Call mbedtls_ecdh_can_do()
+ * or mbedtls_ecdsa_can_do() to check if a curve is
+ * supported for ECDH or ECDSA.
+ *
* \return A statically allocated array. The last entry is 0.
*/
const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void );
@@ -431,6 +452,12 @@
* identifiers of all supported curves in the order of
* preference.
*
+ * \note This function returns information about all curves
+ * supported by the library. Some curves may not be
+ * supported for all algorithms. Call mbedtls_ecdh_can_do()
+ * or mbedtls_ecdsa_can_do() to check if a curve is
+ * supported for ECDH or ECDSA.
+ *
* \return A statically allocated array,
* terminated with MBEDTLS_ECP_DP_NONE.
*/
@@ -626,6 +653,9 @@
* \param P The point to export. This must be initialized.
* \param format The point format. This must be either
* #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED.
+ * (For groups without these formats, this parameter is
+ * ignored. But it still has to be either of the above
+ * values.)
* \param olen The address at which to store the length of
* the output in Bytes. This must not be \c NULL.
* \param buf The output buffer. This must be a writable buffer
@@ -635,11 +665,14 @@
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer
* is too small to hold the point.
+ * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format
+ * or the export for the given group is not implemented.
* \return Another negative error code on other kinds of failure.
*/
-int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P,
- int format, size_t *olen,
- unsigned char *buf, size_t buflen );
+int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp,
+ const mbedtls_ecp_point *P,
+ int format, size_t *olen,
+ unsigned char *buf, size_t buflen );
/**
* \brief This function imports a point from unsigned binary data.
@@ -660,8 +693,8 @@
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
- * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format
- * is not implemented.
+ * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the import for the
+ * given group is not implemented.
*/
int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *P,
@@ -1094,6 +1127,26 @@
void *p_rng );
/**
+ * \brief This function reads an elliptic curve private key.
+ *
+ * \param grp_id The ECP group identifier.
+ * \param key The destination key.
+ * \param buf The the buffer containing the binary representation of the
+ * key. (Big endian integer for Weierstrass curves, byte
+ * string for Montgomery curves.)
+ * \param buflen The length of the buffer in bytes.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_ECP_INVALID_KEY error if the key is
+ * invalid.
+ * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
+ * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for
+ * the group is not implemented.
+ * \return Another negative error code on different kinds of failure.
+ */
+int mbedtls_ecp_read_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
+ const unsigned char *buf, size_t buflen );
+/**
* \brief This function checks that the keypair objects
* \p pub and \p prv have the same group and the
* same public point, and that the private key in
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ecp_internal.h b/lib/libmbedtls/mbedtls/include/mbedtls/ecp_internal.h
index a80611f..a580f1e 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ecp_internal.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ecp_internal.h
@@ -62,7 +62,7 @@
#define MBEDTLS_ECP_INTERNAL_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h b/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h
index cdf476d..1625764 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h
@@ -25,7 +25,7 @@
#define MBEDTLS_ENTROPY_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
@@ -33,21 +33,21 @@
#include <stddef.h>
#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256)
-#include "sha512.h"
+#include "mbedtls/sha512.h"
#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR
#else
#if defined(MBEDTLS_SHA256_C)
#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR
-#include "sha256.h"
+#include "mbedtls/sha256.h"
#endif
#endif
#if defined(MBEDTLS_THREADING_C)
-#include "threading.h"
+#include "mbedtls/threading.h"
#endif
#if defined(MBEDTLS_HAVEGE_C)
-#include "havege.h"
+#include "mbedtls/havege.h"
#endif
#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/entropy_poll.h b/lib/libmbedtls/mbedtls/include/mbedtls/entropy_poll.h
index b95d27f..a076e23 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/entropy_poll.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/entropy_poll.h
@@ -25,7 +25,7 @@
#define MBEDTLS_ENTROPY_POLL_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/error.h b/lib/libmbedtls/mbedtls/include/mbedtls/error.h
index 6da7deb..5d06436 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/error.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/error.h
@@ -25,7 +25,7 @@
#define MBEDTLS_ERROR_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
@@ -52,9 +52,10 @@
* For historical reasons, low-level error codes are divided in even and odd,
* even codes were assigned first, and -1 is reserved for other errors.
*
- * Low-level module errors (0x0002-0x007E, 0x0003-0x007F)
+ * Low-level module errors (0x0002-0x007E, 0x0001-0x007F)
*
* Module Nr Codes assigned
+ * ERROR 2 0x006E 0x0001
* MPI 7 0x0002-0x0010
* GCM 3 0x0012-0x0014 0x0013-0x0013
* BLOWFISH 3 0x0016-0x0018 0x0017-0x0017
@@ -86,7 +87,7 @@
* CHACHA20 3 0x0051-0x0055
* POLY1305 3 0x0057-0x005B
* CHACHAPOLY 2 0x0054-0x0056
- * PLATFORM 1 0x0070-0x0072
+ * PLATFORM 2 0x0070-0x0072
*
* High-level module nr (3 bits - 0x0...-0x7...)
* Name ID Nr of Errors
@@ -100,8 +101,9 @@
* ECP 4 10 (Started from top)
* MD 5 5
* HKDF 5 1 (Started from top)
- * CIPHER 6 8
- * SSL 6 23 (Started from top)
+ * SSL 5 1 (Started from 0x5F00)
+ * CIPHER 6 8 (Started from 0x6080)
+ * SSL 6 24 (Started from top, plus 0x6000)
* SSL 7 32
*
* Module dependent error code (5 bits 0x.00.-0x.F8.)
@@ -111,6 +113,9 @@
extern "C" {
#endif
+#define MBEDTLS_ERR_ERROR_GENERIC_ERROR -0x0001 /**< Generic error */
+#define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E /**< This is a bug in the library */
+
/**
* \brief Translate a mbed TLS error code into a string representation,
* Result is truncated if necessary and always includes a terminating
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h b/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h
index 336391e..3e1ab68 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h
@@ -34,12 +34,12 @@
#define MBEDTLS_GCM_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "cipher.h"
+#include "mbedtls/cipher.h"
#include <stdint.h>
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/havege.h b/lib/libmbedtls/mbedtls/include/mbedtls/havege.h
index 7677289..86c2a9e 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/havege.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/havege.h
@@ -25,12 +25,13 @@
#define MBEDTLS_HAVEGE_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h>
+#include <stdint.h>
#define MBEDTLS_HAVEGE_COLLECT_SIZE 1024
@@ -43,9 +44,9 @@
*/
typedef struct mbedtls_havege_state
{
- int PT1, PT2, offset[2];
- int pool[MBEDTLS_HAVEGE_COLLECT_SIZE];
- int WALK[8192];
+ uint32_t PT1, PT2, offset[2];
+ uint32_t pool[MBEDTLS_HAVEGE_COLLECT_SIZE];
+ uint32_t WALK[8192];
}
mbedtls_havege_state;
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h b/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h
index bcafe42..77a99ab 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h
@@ -7,7 +7,7 @@
* specified by RFC 5869.
*/
/*
- * Copyright (C) 2016-2019, ARM Limited, All Rights Reserved
+ * Copyright (C) 2018-2019, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -28,12 +28,12 @@
#define MBEDTLS_HKDF_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "md.h"
+#include "mbedtls/md.h"
/**
* \name HKDF Error codes
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h b/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h
index 9b49141..2361de1 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h
@@ -29,15 +29,15 @@
#define MBEDTLS_HMAC_DRBG_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "md.h"
+#include "mbedtls/md.h"
#if defined(MBEDTLS_THREADING_C)
-#include "threading.h"
+#include "mbedtls/threading.h"
#endif
/*
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/md.h b/lib/libmbedtls/mbedtls/include/mbedtls/md.h
index 01f3266..cbe4b56 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/md.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/md.h
@@ -30,7 +30,7 @@
#include <stddef.h>
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
@@ -74,6 +74,12 @@
#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */
#endif
+#if defined(MBEDTLS_SHA512_C)
+#define MBEDTLS_MD_MAX_BLOCK_SIZE 128
+#else
+#define MBEDTLS_MD_MAX_BLOCK_SIZE 64
+#endif
+
/**
* Opaque struct defined in md_internal.h.
*/
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/md2.h b/lib/libmbedtls/mbedtls/include/mbedtls/md2.h
index c9f92be..4d540a2 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/md2.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/md2.h
@@ -30,7 +30,7 @@
#define MBEDTLS_MD2_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/md4.h b/lib/libmbedtls/mbedtls/include/mbedtls/md4.h
index fb1835b..7d5790c 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/md4.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/md4.h
@@ -30,7 +30,7 @@
#define MBEDTLS_MD4_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/md5.h b/lib/libmbedtls/mbedtls/include/mbedtls/md5.h
index 957b045..4fc3154 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/md5.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/md5.h
@@ -29,7 +29,7 @@
#define MBEDTLS_MD5_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/md_internal.h b/lib/libmbedtls/mbedtls/include/mbedtls/md_internal.h
index a93aacf..434b847 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/md_internal.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/md_internal.h
@@ -29,12 +29,12 @@
#define MBEDTLS_MD_WRAP_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "md.h"
+#include "mbedtls/md.h"
#ifdef __cplusplus
extern "C" {
@@ -46,42 +46,17 @@
*/
struct mbedtls_md_info_t
{
- /** Digest identifier */
- mbedtls_md_type_t type;
-
/** Name of the message digest */
const char * name;
+ /** Digest identifier */
+ mbedtls_md_type_t type;
+
/** Output length of the digest function in bytes */
- int size;
+ unsigned char size;
/** Block length of the digest function in bytes */
- int block_size;
-
- /** Digest initialisation function */
- int (*starts_func)( void *ctx );
-
- /** Digest update function */
- int (*update_func)( void *ctx, const unsigned char *input, size_t ilen );
-
- /** Digest finalisation function */
- int (*finish_func)( void *ctx, unsigned char *output );
-
- /** Generic digest function */
- int (*digest_func)( const unsigned char *input, size_t ilen,
- unsigned char *output );
-
- /** Allocate a new context */
- void * (*ctx_alloc_func)( void );
-
- /** Free the given context */
- void (*ctx_free_func)( void *ctx );
-
- /** Clone state from a context */
- void (*clone_func)( void *dst, const void *src );
-
- /** Internal use only */
- int (*process_func)( void *ctx, const unsigned char *input );
+ unsigned char block_size;
};
#if defined(MBEDTLS_MD2_C)
@@ -104,7 +79,9 @@
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/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h b/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h
index 0566178..738a55b 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h
@@ -25,7 +25,7 @@
#define MBEDTLS_MEMORY_BUFFER_ALLOC_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/net.h b/lib/libmbedtls/mbedtls/include/mbedtls/net.h
index 416e7b5..788efd7 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/net.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/net.h
@@ -24,13 +24,13 @@
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-#include "net_sockets.h"
+#include "mbedtls/net_sockets.h"
#if defined(MBEDTLS_DEPRECATED_WARNING)
#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h"
#endif /* MBEDTLS_DEPRECATED_WARNING */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h b/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h
index 8ed4f49..dc29d82 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h
@@ -41,12 +41,12 @@
#define MBEDTLS_NET_SOCKETS_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "ssl.h"
+#include "mbedtls/ssl.h"
#include <stddef.h>
#include <stdint.h>
@@ -258,6 +258,13 @@
uint32_t timeout );
/**
+ * \brief Closes down the connection and free associated data
+ *
+ * \param ctx The context to close
+ */
+void mbedtls_net_close( mbedtls_net_context *ctx );
+
+/**
* \brief Gracefully shutdown the connection and free associated data
*
* \param ctx The context to free
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h b/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h
index 3b67b59..b39406f 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h
@@ -38,12 +38,12 @@
#define MBEDTLS_NIST_KW_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "cipher.h"
+#include "mbedtls/cipher.h"
#ifdef __cplusplus
extern "C" {
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/oid.h b/lib/libmbedtls/mbedtls/include/mbedtls/oid.h
index d175e2f..de927cb 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/oid.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/oid.h
@@ -25,31 +25,49 @@
#define MBEDTLS_OID_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "asn1.h"
-#include "pk.h"
+#include "mbedtls/asn1.h"
+#include "mbedtls/pk.h"
#include <stddef.h>
#if defined(MBEDTLS_CIPHER_C)
-#include "cipher.h"
+#include "mbedtls/cipher.h"
#endif
#if defined(MBEDTLS_MD_C)
-#include "md.h"
-#endif
-
-#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
-#include "x509.h"
+#include "mbedtls/md.h"
#endif
#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */
#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B /**< output buffer is too small */
+/* This is for the benefit of X.509, but defined here in order to avoid
+ * having a "backwards" include of x.509.h here */
+/*
+ * X.509 extension types (internal, arbitrary values for bitsets)
+ */
+#define MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0)
+#define MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1)
+#define MBEDTLS_OID_X509_EXT_KEY_USAGE (1 << 2)
+#define MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES (1 << 3)
+#define MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS (1 << 4)
+#define MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME (1 << 5)
+#define MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME (1 << 6)
+#define MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7)
+#define MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS (1 << 8)
+#define MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS (1 << 9)
+#define MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS (1 << 10)
+#define MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE (1 << 11)
+#define MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12)
+#define MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13)
+#define MBEDTLS_OID_X509_EXT_FRESHEST_CRL (1 << 14)
+#define MBEDTLS_OID_X509_EXT_NS_CERT_TYPE (1 << 16)
+
/*
* Top level OID tuples
*/
@@ -104,7 +122,8 @@
* { iso(1) identified-organization(3) dod(6) internet(1)
* security(5) mechanisms(5) pkix(7) }
*/
-#define MBEDTLS_OID_PKIX MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01\x05\x05\x07"
+#define MBEDTLS_OID_INTERNET MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01"
+#define MBEDTLS_OID_PKIX MBEDTLS_OID_INTERNET "\x05\x05\x07"
/*
* Arc for standard naming attributes
@@ -150,6 +169,11 @@
#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */
/*
+ * Certificate policies
+ */
+#define MBEDTLS_OID_ANY_POLICY MBEDTLS_OID_CERTIFICATE_POLICIES "\x00" /**< anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } */
+
+/*
* Netscape certificate extensions
*/
#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01"
@@ -183,6 +207,16 @@
#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */
#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */
+/**
+ * Wi-SUN Alliance Field Area Network
+ * { iso(1) identified-organization(3) dod(6) internet(1)
+ * private(4) enterprise(1) WiSUN(45605) FieldAreaNetwork(1) }
+ */
+#define MBEDTLS_OID_WISUN_FAN MBEDTLS_OID_INTERNET "\x04\x01\x82\xe4\x25\x01"
+
+#define MBEDTLS_OID_ON MBEDTLS_OID_PKIX "\x08" /**< id-on OBJECT IDENTIFIER ::= { id-pkix 8 } */
+#define MBEDTLS_OID_ON_HW_MODULE_NAME MBEDTLS_OID_ON "\x04" /**< id-on-hardwareModuleName OBJECT IDENTIFIER ::= { id-on 4 } */
+
/*
* PKCS definition OIDs
*/
@@ -228,6 +262,8 @@
#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */
+#define MBEDTLS_OID_DIGEST_ALG_RIPEMD160 MBEDTLS_OID_TELETRUST "\x03\x02\x01" /**< id-ripemd160 OBJECT IDENTIFIER :: { iso(1) identified-organization(3) teletrust(36) algorithm(3) hashAlgorithm(2) ripemd160(1) } */
+
#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */
#define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */
@@ -424,7 +460,6 @@
*/
int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_buf *oid );
-#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
/**
* \brief Translate an X.509 extension OID into local values
*
@@ -434,7 +469,6 @@
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/
int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type );
-#endif
/**
* \brief Translate an X.509 attribute type OID into the short name
@@ -561,6 +595,16 @@
int mbedtls_oid_get_extended_key_usage( const mbedtls_asn1_buf *oid, const char **desc );
/**
+ * \brief Translate certificate policies OID into description
+ *
+ * \param oid OID to use
+ * \param desc place to store string pointer
+ *
+ * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
+ */
+int mbedtls_oid_get_certificate_policies( const mbedtls_asn1_buf *oid, const char **desc );
+
+/**
* \brief Translate md_type into hash algorithm OID
*
* \param md_alg message digest algorithm
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/padlock.h b/lib/libmbedtls/mbedtls/include/mbedtls/padlock.h
index 4ddacb3..951c6ea 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/padlock.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/padlock.h
@@ -29,12 +29,12 @@
#define MBEDTLS_PADLOCK_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "aes.h"
+#include "mbedtls/aes.h"
#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/pem.h b/lib/libmbedtls/mbedtls/include/mbedtls/pem.h
index 8181fa0..421f57c 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/pem.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/pem.h
@@ -25,7 +25,7 @@
#define MBEDTLS_PEM_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
@@ -112,17 +112,27 @@
* \brief Write a buffer of PEM information from a DER encoded
* buffer.
*
- * \param header header string to write
- * \param footer footer string to write
- * \param der_data DER data to write
- * \param der_len length of the DER data
- * \param buf buffer to write to
- * \param buf_len length of output buffer
- * \param olen total length written / required (if buf_len is not enough)
+ * \param header The header string to write.
+ * \param footer The footer string to write.
+ * \param der_data The DER data to encode.
+ * \param der_len The length of the DER data \p der_data in Bytes.
+ * \param buf The buffer to write to.
+ * \param buf_len The length of the output buffer \p buf in Bytes.
+ * \param olen The address at which to store the total length written
+ * or required (if \p buf_len is not enough).
*
- * \return 0 on success, or a specific PEM or BASE64 error code. On
- * MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL olen is the required
- * size.
+ * \note You may pass \c NULL for \p buf and \c 0 for \p buf_len
+ * to request the length of the resulting PEM buffer in
+ * `*olen`.
+ *
+ * \note This function may be called with overlapping \p der_data
+ * and \p buf buffers.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL if \p buf isn't large
+ * enough to hold the PEM buffer. In this case, `*olen` holds
+ * the required minimum size of \p buf.
+ * \return Another PEM or BASE64 error code on other kinds of failure.
*/
int mbedtls_pem_write_buffer( const char *header, const char *footer,
const unsigned char *der_data, size_t der_len,
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/pk.h b/lib/libmbedtls/mbedtls/include/mbedtls/pk.h
index 4cebc16..283219b 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/pk.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/pk.h
@@ -26,23 +26,27 @@
#define MBEDTLS_PK_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "md.h"
+#include "mbedtls/md.h"
#if defined(MBEDTLS_RSA_C)
-#include "rsa.h"
+#include "mbedtls/rsa.h"
#endif
#if defined(MBEDTLS_ECP_C)
-#include "ecp.h"
+#include "mbedtls/ecp.h"
#endif
#if defined(MBEDTLS_ECDSA_C)
-#include "ecdsa.h"
+#include "mbedtls/ecdsa.h"
+#endif
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
#endif
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
@@ -83,6 +87,7 @@
MBEDTLS_PK_ECDSA,
MBEDTLS_PK_RSA_ALT,
MBEDTLS_PK_RSASSA_PSS,
+ MBEDTLS_PK_OPAQUE,
} mbedtls_pk_type_t;
/**
@@ -97,6 +102,58 @@
} mbedtls_pk_rsassa_pss_options;
/**
+ * \brief Maximum size of a signature made by mbedtls_pk_sign().
+ */
+/* We need to set MBEDTLS_PK_SIGNATURE_MAX_SIZE to the maximum signature
+ * size among the supported signature types. Do it by starting at 0,
+ * then incrementally increasing to be large enough for each supported
+ * signature mechanism.
+ *
+ * The resulting value can be 0, for example if MBEDTLS_ECDH_C is enabled
+ * (which allows the pk module to be included) but neither MBEDTLS_ECDSA_C
+ * nor MBEDTLS_RSA_C nor any opaque signature mechanism (PSA or RSA_ALT).
+ */
+#define MBEDTLS_PK_SIGNATURE_MAX_SIZE 0
+
+#if ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_RSA_ALT_SUPPORT) ) && \
+ MBEDTLS_MPI_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE
+/* For RSA, the signature can be as large as the bignum module allows.
+ * For RSA_ALT, the signature size is not necessarily tied to what the
+ * bignum module can do, but in the absence of any specific setting,
+ * we use that (rsa_alt_sign_wrap in pk_wrap will check). */
+#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE
+#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
+#endif
+
+#if defined(MBEDTLS_ECDSA_C) && \
+ MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_PK_SIGNATURE_MAX_SIZE
+/* For ECDSA, the ecdsa module exports a constant for the maximum
+ * signature size. */
+#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE
+#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
+#endif
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if PSA_SIGNATURE_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE
+/* PSA_SIGNATURE_MAX_SIZE is the maximum size of a signature made
+ * through the PSA API in the PSA representation. */
+#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE
+#define MBEDTLS_PK_SIGNATURE_MAX_SIZE PSA_SIGNATURE_MAX_SIZE
+#endif
+
+#if PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 > MBEDTLS_PK_SIGNATURE_MAX_SIZE
+/* The Mbed TLS representation is different for ECDSA signatures:
+ * PSA uses the raw concatenation of r and s,
+ * whereas Mbed TLS uses the ASN.1 representation (SEQUENCE of two INTEGERs).
+ * Add the overhead of ASN.1: up to (1+2) + 2 * (1+2+1) for the
+ * types, lengths (represented by up to 2 bytes), and potential leading
+ * zeros of the INTEGERs and the SEQUENCE. */
+#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE
+#define MBEDTLS_PK_SIGNATURE_MAX_SIZE ( PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 )
+#endif
+#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */
+
+/**
* \brief Types for interfacing with the debug module
*/
typedef enum
@@ -209,6 +266,11 @@
*
* \param ctx The context to clear. It must have been initialized.
* If this is \c NULL, this function does nothing.
+ *
+ * \note For contexts that have been set up with
+ * mbedtls_pk_setup_opaque(), this does not free the underlying
+ * PSA key and you still need to call psa_destroy_key()
+ * independently if you want to destroy that key.
*/
void mbedtls_pk_free( mbedtls_pk_context *ctx );
@@ -247,6 +309,38 @@
*/
int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/**
+ * \brief Initialize a PK context to wrap a PSA key.
+ *
+ * \note This function replaces mbedtls_pk_setup() for contexts
+ * that wrap a (possibly opaque) PSA key instead of
+ * storing and manipulating the key material directly.
+ *
+ * \param ctx The context to initialize. It must be empty (type NONE).
+ * \param key The PSA key to wrap, which must hold an ECC key pair
+ * (see notes below).
+ *
+ * \note The wrapped key must remain valid as long as the
+ * wrapping PK context is in use, that is at least between
+ * the point this function is called and the point
+ * mbedtls_pk_free() is called on this context. The wrapped
+ * key might then be independently used or destroyed.
+ *
+ * \note This function is currently only available for ECC key
+ * pairs (that is, ECC keys containing private key material).
+ * Support for other key types may be added later.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input
+ * (context already used, invalid key handle).
+ * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an
+ * ECC key pair.
+ * \return #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure.
+ */
+int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx, const psa_key_handle_t key );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
/**
* \brief Initialize an RSA-alt context
@@ -400,8 +494,13 @@
* \param md_alg Hash algorithm used (see notes)
* \param hash Hash of the message to sign
* \param hash_len Hash length or 0 (see notes)
- * \param sig Place to write the signature
- * \param sig_len Number of bytes written
+ * \param sig Place to write the signature.
+ * It must have enough room for the signature.
+ * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough.
+ * You may use a smaller buffer if it is large enough
+ * given the key type.
+ * \param sig_len On successful return,
+ * the number of bytes written to \p sig.
* \param f_rng RNG function
* \param p_rng RNG parameter
*
@@ -416,10 +515,6 @@
*
* \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0.
* For ECDSA, md_alg may never be MBEDTLS_MD_NONE.
- *
- * \note In order to ensure enough space for the signature, the
- * \p sig buffer size must be of at least
- * `max(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)` bytes.
*/
int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
@@ -434,22 +529,23 @@
* \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC
* operations. For RSA, same as \c mbedtls_pk_sign().
*
- * \note In order to ensure enough space for the signature, the
- * \p sig buffer size must be of at least
- * `max(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)` bytes.
- *
* \param ctx The PK context to use. It must have been set up
* with a private key.
- * \param md_alg Hash algorithm used (see notes)
+ * \param md_alg Hash algorithm used (see notes for mbedtls_pk_sign())
* \param hash Hash of the message to sign
- * \param hash_len Hash length or 0 (see notes)
- * \param sig Place to write the signature
- * \param sig_len Number of bytes written
+ * \param hash_len Hash length or 0 (see notes for mbedtls_pk_sign())
+ * \param sig Place to write the signature.
+ * It must have enough room for the signature.
+ * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough.
+ * You may use a smaller buffer if it is large enough
+ * given the key type.
+ * \param sig_len On successful return,
+ * the number of bytes written to \p sig.
* \param f_rng RNG function
* \param p_rng RNG parameter
* \param rs_ctx Restart context (NULL to disable restart)
*
- * \return See \c mbedtls_pk_sign(), or
+ * \return See \c mbedtls_pk_sign().
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
*/
@@ -509,7 +605,11 @@
* \param pub Context holding a public key.
* \param prv Context holding a private (and public) key.
*
- * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA
+ * \return \c 0 on success (keys were checked and match each other).
+ * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not
+ * be checked - in that case they may or may not match.
+ * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid.
+ * \return Another non-zero value if the keys do not match.
*/
int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv );
@@ -748,6 +848,32 @@
int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n );
#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/**
+ * \brief Turn an EC key into an opaque one.
+ *
+ * \warning This is a temporary utility function for tests. It might
+ * change or be removed at any time without notice.
+ *
+ * \note Only ECDSA keys are supported so far. Signing with the
+ * specified hash is the only allowed use of that key.
+ *
+ * \param pk Input: the EC key to import to a PSA key.
+ * Output: a PK context wrapping that PSA key.
+ * \param handle Output: a PSA key handle.
+ * It's the caller's responsibility to call
+ * psa_destroy_key() on that handle after calling
+ * mbedtls_pk_free() on the PK context.
+ * \param hash_alg The hash algorithm to allow for use with that key.
+ *
+ * \return \c 0 if successful.
+ * \return An Mbed TLS error code otherwise.
+ */
+int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk,
+ psa_key_handle_t *handle,
+ psa_algorithm_t hash_alg );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/pk_internal.h b/lib/libmbedtls/mbedtls/include/mbedtls/pk_internal.h
index 9234e9f..50ff69a 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/pk_internal.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/pk_internal.h
@@ -26,12 +26,12 @@
#define MBEDTLS_PK_WRAP_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "pk.h"
+#include "mbedtls/pk.h"
struct mbedtls_pk_info_t
{
@@ -135,4 +135,8 @@
extern const mbedtls_pk_info_t mbedtls_rsa_alt_info;
#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+extern const mbedtls_pk_info_t mbedtls_pk_opaque_info;
+#endif
+
#endif /* MBEDTLS_PK_WRAP_H */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/pkcs11.h b/lib/libmbedtls/mbedtls/include/mbedtls/pkcs11.h
index ab31c58..f5f2779 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/pkcs11.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/pkcs11.h
@@ -27,14 +27,14 @@
#define MBEDTLS_PKCS11_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_PKCS11_C)
-#include "x509_crt.h"
+#include "mbedtls/x509_crt.h"
#include <pkcs11-helper-1.0/pkcs11h-certificate.h>
@@ -47,6 +47,8 @@
extern "C" {
#endif
+#if defined(MBEDTLS_DEPRECATED_REMOVED)
+
/**
* Context for PKCS #11 private keys.
*/
@@ -56,47 +58,71 @@
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 @@
* 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 @@
* \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
+ * <code>ctx->N</code>. 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 @@
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/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h b/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h
index 07c7721..e7d4e36 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h
@@ -25,14 +25,14 @@
#define MBEDTLS_PKCS12_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "md.h"
-#include "cipher.h"
-#include "asn1.h"
+#include "mbedtls/md.h"
+#include "mbedtls/cipher.h"
+#include "mbedtls/asn1.h"
#include <stddef.h>
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h b/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h
index 1b8c49e..9eb759d 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h
@@ -27,13 +27,13 @@
#define MBEDTLS_PKCS5_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "asn1.h"
-#include "md.h"
+#include "mbedtls/asn1.h"
+#include "mbedtls/md.h"
#include <stddef.h>
#include <stdint.h>
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/platform.h b/lib/libmbedtls/mbedtls/include/mbedtls/platform.h
index 234414e..c8b72f7 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/platform.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/platform.h
@@ -34,13 +34,13 @@
#define MBEDTLS_PLATFORM_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_HAVE_TIME)
-#include "platform_time.h"
+#include "mbedtls/platform_time.h"
#endif
#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 /**< Hardware accelerator failed */
@@ -58,17 +58,33 @@
* \{
*/
+/* The older Microsoft Windows common runtime provides non-conforming
+ * implementations of some standard library functions, including snprintf
+ * and vsnprintf. This affects MSVC and MinGW builds.
+ */
+#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900)
+#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF
+#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF
+#endif
+
#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF)
-#if defined(_WIN32)
+#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF)
#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */
#else
#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< The default \c snprintf function to use. */
#endif
#endif
+#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF)
+#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF)
+#define MBEDTLS_PLATFORM_STD_VSNPRINTF mbedtls_platform_win32_vsnprintf /**< The default \c vsnprintf function to use. */
+#else
+#define MBEDTLS_PLATFORM_STD_VSNPRINTF vsnprintf /**< The default \c vsnprintf function to use. */
+#endif
+#endif
#if !defined(MBEDTLS_PLATFORM_STD_PRINTF)
#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< The default \c printf function to use. */
#endif
@@ -204,7 +220,7 @@
* - however it is acceptable to return -1 instead of the required length when
* the destination buffer is too short.
*/
-#if defined(_WIN32)
+#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF)
/* For Windows (inc. MSYS2), we provide our own fixed implementation */
int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... );
#endif
@@ -231,6 +247,42 @@
#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
/*
+ * The function pointers for vsnprintf
+ *
+ * The vsnprintf implementation should conform to C99:
+ * - it *must* always correctly zero-terminate the buffer
+ * (except when n == 0, then it must leave the buffer untouched)
+ * - however it is acceptable to return -1 instead of the required length when
+ * the destination buffer is too short.
+ */
+#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF)
+#include <stdarg.h>
+/* For Older Windows (inc. MSYS2), we provide our own fixed implementation */
+int mbedtls_platform_win32_vsnprintf( char *s, size_t n, const char *fmt, va_list arg );
+#endif
+
+#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT)
+#include <stdarg.h>
+extern int (*mbedtls_vsnprintf)( char * s, size_t n, const char * format, va_list arg );
+
+/**
+ * \brief Set your own snprintf function pointer
+ *
+ * \param vsnprintf_func The \c vsnprintf function implementation
+ *
+ * \return \c 0
+ */
+int mbedtls_platform_set_vsnprintf( int (*vsnprintf_func)( char * s, size_t n,
+ const char * format, va_list arg ) );
+#else /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */
+#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO)
+#define mbedtls_vsnprintf MBEDTLS_PLATFORM_VSNPRINTF_MACRO
+#else
+#define mbedtls_vsnprintf vsnprintf
+#endif /* MBEDTLS_PLATFORM_VSNPRINTF_MACRO */
+#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */
+
+/*
* The function pointers for exit
*/
#if defined(MBEDTLS_PLATFORM_EXIT_ALT)
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h b/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h
index 1a71856..b5f0119 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h
@@ -25,7 +25,7 @@
#define MBEDTLS_PLATFORM_TIME_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h b/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h
index 09d0965..cf0130a 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h
@@ -26,14 +26,14 @@
#define MBEDTLS_PLATFORM_UTIL_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h>
#if defined(MBEDTLS_HAVE_TIME_DATE)
-#include "platform_time.h"
+#include "mbedtls/platform_time.h"
#include <time.h>
#endif /* MBEDTLS_HAVE_TIME_DATE */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h b/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h
index f0ec44c..05866a2 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h
@@ -34,7 +34,7 @@
#define MBEDTLS_POLY1305_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h b/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h
new file mode 100644
index 0000000..513bc5f
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h
@@ -0,0 +1,422 @@
+/**
+ * \file psa_util.h
+ *
+ * \brief Utility functions for the use of the PSA Crypto library.
+ *
+ * \warning This function is not part of the public API and may
+ * change at any time.
+ */
+/*
+ * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef MBEDTLS_PSA_UTIL_H
+#define MBEDTLS_PSA_UTIL_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+
+#include "psa/crypto.h"
+
+#include "mbedtls/ecp.h"
+#include "mbedtls/md.h"
+#include "mbedtls/pk.h"
+#include "mbedtls/oid.h"
+
+#include <string.h>
+
+/* Translations for symmetric crypto. */
+
+static inline psa_key_type_t mbedtls_psa_translate_cipher_type(
+ mbedtls_cipher_type_t cipher )
+{
+ switch( cipher )
+ {
+ case MBEDTLS_CIPHER_AES_128_CCM:
+ case MBEDTLS_CIPHER_AES_192_CCM:
+ case MBEDTLS_CIPHER_AES_256_CCM:
+ case MBEDTLS_CIPHER_AES_128_GCM:
+ case MBEDTLS_CIPHER_AES_192_GCM:
+ case MBEDTLS_CIPHER_AES_256_GCM:
+ case MBEDTLS_CIPHER_AES_128_CBC:
+ case MBEDTLS_CIPHER_AES_192_CBC:
+ case MBEDTLS_CIPHER_AES_256_CBC:
+ return( PSA_KEY_TYPE_AES );
+
+ /* ARIA not yet supported in PSA. */
+ /* case MBEDTLS_CIPHER_ARIA_128_CCM:
+ case MBEDTLS_CIPHER_ARIA_192_CCM:
+ case MBEDTLS_CIPHER_ARIA_256_CCM:
+ case MBEDTLS_CIPHER_ARIA_128_GCM:
+ case MBEDTLS_CIPHER_ARIA_192_GCM:
+ case MBEDTLS_CIPHER_ARIA_256_GCM:
+ case MBEDTLS_CIPHER_ARIA_128_CBC:
+ case MBEDTLS_CIPHER_ARIA_192_CBC:
+ case MBEDTLS_CIPHER_ARIA_256_CBC:
+ return( PSA_KEY_TYPE_ARIA ); */
+
+ default:
+ return( 0 );
+ }
+}
+
+static inline psa_algorithm_t mbedtls_psa_translate_cipher_mode(
+ mbedtls_cipher_mode_t mode, size_t taglen )
+{
+ switch( mode )
+ {
+ case MBEDTLS_MODE_GCM:
+ return( PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, taglen ) );
+ case MBEDTLS_MODE_CCM:
+ return( PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, taglen ) );
+ case MBEDTLS_MODE_CBC:
+ if( taglen == 0 )
+ return( PSA_ALG_CBC_NO_PADDING );
+ /* Intentional fallthrough for taglen != 0 */
+ /* fallthrough */
+ default:
+ return( 0 );
+ }
+}
+
+static inline psa_key_usage_t mbedtls_psa_translate_cipher_operation(
+ mbedtls_operation_t op )
+{
+ switch( op )
+ {
+ case MBEDTLS_ENCRYPT:
+ return( PSA_KEY_USAGE_ENCRYPT );
+ case MBEDTLS_DECRYPT:
+ return( PSA_KEY_USAGE_DECRYPT );
+ default:
+ return( 0 );
+ }
+}
+
+/* Translations for hashing. */
+
+static inline psa_algorithm_t mbedtls_psa_translate_md( mbedtls_md_type_t md_alg )
+{
+ switch( md_alg )
+ {
+#if defined(MBEDTLS_MD2_C)
+ case MBEDTLS_MD_MD2:
+ return( PSA_ALG_MD2 );
+#endif
+#if defined(MBEDTLS_MD4_C)
+ case MBEDTLS_MD_MD4:
+ return( PSA_ALG_MD4 );
+#endif
+#if defined(MBEDTLS_MD5_C)
+ case MBEDTLS_MD_MD5:
+ return( PSA_ALG_MD5 );
+#endif
+#if defined(MBEDTLS_SHA1_C)
+ case MBEDTLS_MD_SHA1:
+ return( PSA_ALG_SHA_1 );
+#endif
+#if defined(MBEDTLS_SHA256_C)
+ case MBEDTLS_MD_SHA224:
+ return( PSA_ALG_SHA_224 );
+ case MBEDTLS_MD_SHA256:
+ return( PSA_ALG_SHA_256 );
+#endif
+#if defined(MBEDTLS_SHA512_C)
+ case MBEDTLS_MD_SHA384:
+ return( PSA_ALG_SHA_384 );
+ case MBEDTLS_MD_SHA512:
+ return( PSA_ALG_SHA_512 );
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+ case MBEDTLS_MD_RIPEMD160:
+ return( PSA_ALG_RIPEMD160 );
+#endif
+ case MBEDTLS_MD_NONE: /* Intentional fallthrough */
+ default:
+ return( 0 );
+ }
+}
+
+/* Translations for ECC. */
+
+static inline int mbedtls_psa_get_ecc_oid_from_id(
+ 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 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 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 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 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 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 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 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 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 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 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 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 */
+ }
+ break;
+ }
+ (void) oid;
+ (void) oid_len;
+ return( -1 );
+}
+
+#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH 1
+
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 192 + 7 ) / 8 ) + 1 )
+#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH
+#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 192 + 7 ) / 8 ) + 1 )
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 224 + 7 ) / 8 ) + 1 )
+#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH
+#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 224 + 7 ) / 8 ) + 1 )
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 256 + 7 ) / 8 ) + 1 )
+#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH
+#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 256 + 7 ) / 8 ) + 1 )
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 384 + 7 ) / 8 ) + 1 )
+#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH
+#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 384 + 7 ) / 8 ) + 1 )
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 521 + 7 ) / 8 ) + 1 )
+#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH
+#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 521 + 7 ) / 8 ) + 1 )
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
+#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 192 + 7 ) / 8 ) + 1 )
+#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH
+#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 192 + 7 ) / 8 ) + 1 )
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
+#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 224 + 7 ) / 8 ) + 1 )
+#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH
+#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 224 + 7 ) / 8 ) + 1 )
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 256 + 7 ) / 8 ) + 1 )
+#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH
+#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 256 + 7 ) / 8 ) + 1 )
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
+#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 256 + 7 ) / 8 ) + 1 )
+#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH
+#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 256 + 7 ) / 8 ) + 1 )
+#endif
+#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
+#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 384 + 7 ) / 8 ) + 1 )
+#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH
+#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 384 + 7 ) / 8 ) + 1 )
+#endif
+#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
+#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 512 + 7 ) / 8 ) + 1 )
+#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH
+#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 512 + 7 ) / 8 ) + 1 )
+#endif
+#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
+
+
+/* Translations for PK layer */
+
+static inline int mbedtls_psa_err_translate_pk( psa_status_t status )
+{
+ switch( status )
+ {
+ case PSA_SUCCESS:
+ return( 0 );
+ case PSA_ERROR_NOT_SUPPORTED:
+ return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
+ case PSA_ERROR_INSUFFICIENT_MEMORY:
+ return( MBEDTLS_ERR_PK_ALLOC_FAILED );
+ case PSA_ERROR_INSUFFICIENT_ENTROPY:
+ return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
+ case PSA_ERROR_BAD_STATE:
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+ /* All other failures */
+ case PSA_ERROR_COMMUNICATION_FAILURE:
+ case PSA_ERROR_HARDWARE_FAILURE:
+ case PSA_ERROR_CORRUPTION_DETECTED:
+ return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
+ default: /* We return the same as for the 'other failures',
+ * but list them separately nonetheless to indicate
+ * which failure conditions we have considered. */
+ return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
+ }
+}
+
+/* Translations for ECC */
+
+/* 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. */
+#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 )
+{
+ 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
+ * it into an ECPoint structure to be put into a ClientKeyExchange
+ * message in an ECDHE exchange.
+ *
+ * Both the present and the foreseeable future format of EC public keys
+ * used by PSA have the ECPoint structure contained in the exported key
+ * as a subbuffer, and the function merely selects this subbuffer instead
+ * of making a copy.
+ */
+static inline int mbedtls_psa_tls_psa_ec_to_ecpoint( unsigned char *src,
+ size_t srclen,
+ unsigned char **dst,
+ size_t *dstlen )
+{
+ *dst = src;
+ *dstlen = srclen;
+ return( 0 );
+}
+
+/* This function takes a buffer holding an ECPoint structure
+ * (as contained in a TLS ServerKeyExchange message for ECDHE
+ * exchanges) and converts it into a format that the PSA key
+ * agreement API understands.
+ */
+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 )
+{
+ if( srclen > dstlen )
+ return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
+
+ memcpy( dst, src, srclen );
+ *olen = srclen;
+ return( 0 );
+}
+
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#endif /* MBEDTLS_PSA_UTIL_H */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h b/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h
index 508a7c7..b5d8e20 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h
@@ -25,7 +25,7 @@
#define MBEDTLS_RIPEMD160_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
@@ -57,7 +57,7 @@
mbedtls_ripemd160_context;
#else /* MBEDTLS_RIPEMD160_ALT */
-#include "ripemd160.h"
+#include "ripemd160_alt.h"
#endif /* MBEDTLS_RIPEMD160_ALT */
/**
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h b/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h
index e969287..c47ef0f 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h
@@ -31,16 +31,16 @@
#define MBEDTLS_RSA_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "bignum.h"
-#include "md.h"
+#include "mbedtls/bignum.h"
+#include "mbedtls/md.h"
#if defined(MBEDTLS_THREADING_C)
-#include "threading.h"
+#include "mbedtls/threading.h"
#endif
/*
@@ -601,7 +601,8 @@
* #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated).
* \param ilen The length of the plaintext in Bytes.
* \param input The input data to encrypt. This must be a readable
- * buffer of size \p ilen Bytes. This must not be \c NULL.
+ * buffer of size \p ilen Bytes. It may be \c NULL if
+ * `ilen == 0`.
* \param output The output buffer. This must be a writable buffer
* of length \c ctx->len Bytes. For example, \c 256 Bytes
* for an 2048-bit RSA modulus.
@@ -641,7 +642,8 @@
* #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated).
* \param ilen The length of the plaintext in Bytes.
* \param input The input data to encrypt. This must be a readable
- * buffer of size \p ilen Bytes. This must not be \c NULL.
+ * buffer of size \p ilen Bytes. It may be \c NULL if
+ * `ilen == 0`.
* \param output The output buffer. This must be a writable buffer
* of length \c ctx->len Bytes. For example, \c 256 Bytes
* for an 2048-bit RSA modulus.
@@ -685,7 +687,8 @@
* \param label_len The length of the label in Bytes.
* \param ilen The length of the plaintext buffer \p input in Bytes.
* \param input The input data to encrypt. This must be a readable
- * buffer of size \p ilen Bytes. This must not be \c NULL.
+ * buffer of size \p ilen Bytes. It may be \c NULL if
+ * `ilen == 0`.
* \param output The output buffer. This must be a writable buffer
* of length \c ctx->len Bytes. For example, \c 256 Bytes
* for an 2048-bit RSA modulus.
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/rsa_internal.h b/lib/libmbedtls/mbedtls/include/mbedtls/rsa_internal.h
index 53abd3c..c1c844e 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/rsa_internal.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/rsa_internal.h
@@ -58,12 +58,12 @@
#define MBEDTLS_RSA_INTERNAL_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "bignum.h"
+#include "mbedtls/bignum.h"
#ifdef __cplusplus
extern "C" {
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h b/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h
index bbea19f..b51d873 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h
@@ -32,7 +32,7 @@
#define MBEDTLS_SHA1_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h b/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h
index df39e74..0a77767 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h
@@ -28,7 +28,7 @@
#define MBEDTLS_SHA256_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h b/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h
index e407813..f288623 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h
@@ -27,7 +27,7 @@
#define MBEDTLS_SHA512_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
@@ -59,8 +59,10 @@
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 @@
*
* \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 @@
* \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 @@
* \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 @@
* 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/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h b/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h
index 4cb8116..b76b9bb 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h
@@ -25,27 +25,27 @@
#define MBEDTLS_SSL_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "bignum.h"
-#include "ecp.h"
+#include "mbedtls/bignum.h"
+#include "mbedtls/ecp.h"
-#include "ssl_ciphersuites.h"
+#include "mbedtls/ssl_ciphersuites.h"
#if defined(MBEDTLS_X509_CRT_PARSE_C)
-#include "x509_crt.h"
-#include "x509_crl.h"
+#include "mbedtls/x509_crt.h"
+#include "mbedtls/x509_crl.h"
#endif
#if defined(MBEDTLS_DHM_C)
-#include "dhm.h"
+#include "mbedtls/dhm.h"
#endif
#if defined(MBEDTLS_ECDH_C)
-#include "ecdh.h"
+#include "mbedtls/ecdh.h"
#endif
#if defined(MBEDTLS_ZLIB_SUPPORT)
@@ -62,9 +62,13 @@
#endif
#if defined(MBEDTLS_HAVE_TIME)
-#include "platform_time.h"
+#include "mbedtls/platform_time.h"
#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
/*
* SSL Error codes
*/
@@ -122,6 +126,8 @@
#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /**< Internal-only message signaling that further message-processing should be done */
#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /**< The asynchronous operation is not completed yet. */
#define MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480 /**< Internal-only message signaling that a message arrived early. */
+#define MBEDTLS_ERR_SSL_UNEXPECTED_CID -0x6000 /**< An encrypted DTLS-frame with an unexpected CID was received. */
+#define MBEDTLS_ERR_SSL_VERSION_MISMATCH -0x5F00 /**< An operation failed due to an unexpected version or configuration. */
#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 /**< A cryptographic operation is in progress. Try again later. */
/*
@@ -156,6 +162,9 @@
#define MBEDTLS_SSL_EXTENDED_MS_DISABLED 0
#define MBEDTLS_SSL_EXTENDED_MS_ENABLED 1
+#define MBEDTLS_SSL_CID_DISABLED 0
+#define MBEDTLS_SSL_CID_ENABLED 1
+
#define MBEDTLS_SSL_ETM_DISABLED 0
#define MBEDTLS_SSL_ETM_ENABLED 1
@@ -252,6 +261,21 @@
#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768
#endif
+/*
+ * Maximum length of CIDs for incoming and outgoing messages.
+ */
+#if !defined(MBEDTLS_SSL_CID_IN_LEN_MAX)
+#define MBEDTLS_SSL_CID_IN_LEN_MAX 32
+#endif
+
+#if !defined(MBEDTLS_SSL_CID_OUT_LEN_MAX)
+#define MBEDTLS_SSL_CID_OUT_LEN_MAX 32
+#endif
+
+#if !defined(MBEDTLS_SSL_CID_PADDING_GRANULARITY)
+#define MBEDTLS_SSL_CID_PADDING_GRANULARITY 16
+#endif
+
/* \} name SECTION: Module settings */
/*
@@ -299,6 +323,7 @@
#define MBEDTLS_SSL_MSG_ALERT 21
#define MBEDTLS_SSL_MSG_HANDSHAKE 22
#define MBEDTLS_SSL_MSG_APPLICATION_DATA 23
+#define MBEDTLS_SSL_MSG_CID 25
#define MBEDTLS_SSL_ALERT_LEVEL_WARNING 1
#define MBEDTLS_SSL_ALERT_LEVEL_FATAL 2
@@ -368,6 +393,11 @@
#define MBEDTLS_TLS_EXT_SESSION_TICKET 35
+/* The value of the CID extension is still TBD as of
+ * draft-ietf-tls-dtls-connection-id-05
+ * (https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05) */
+#define MBEDTLS_TLS_EXT_CID 254 /* TBD */
+
#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */
#define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01
@@ -446,6 +476,18 @@
}
mbedtls_ssl_states;
+/*
+ * The tls_prf function types.
+ */
+typedef enum
+{
+ MBEDTLS_SSL_TLS_PRF_NONE,
+ MBEDTLS_SSL_TLS_PRF_SSL3,
+ MBEDTLS_SSL_TLS_PRF_TLS1,
+ MBEDTLS_SSL_TLS_PRF_SHA384,
+ MBEDTLS_SSL_TLS_PRF_SHA256
+}
+mbedtls_tls_prf_types;
/**
* \brief Callback type: send data on the network.
*
@@ -783,8 +825,35 @@
typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+#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)
+#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA256
+#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 32
+#elif defined(MBEDTLS_SHA512_C)
+#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA384
+#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 48
+#elif defined(MBEDTLS_SHA1_C)
+#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA1
+#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 20
+#else
+/* 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 &&
+ !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
/*
* This structure is used for storing current session data.
+ *
+ * Note: when changing this definition, we need to check and update:
+ * - in tests/suites/test_suite_ssl.function:
+ * ssl_populate_session() and ssl_serialize_session_save_load()
+ * - in library/ssl_tls.c:
+ * mbedtls_ssl_session_init() and mbedtls_ssl_session_free()
+ * mbedtls_ssl_session_save() and ssl_session_load()
+ * ssl_session_copy()
*/
struct mbedtls_ssl_session
{
@@ -798,7 +867,15 @@
unsigned char master[48]; /*!< the master secret */
#if defined(MBEDTLS_X509_CRT_PARSE_C)
- mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+ /*! The digest of the peer's end-CRT. This must be kept to detect CRT
+ * changes during renegotiation, mitigating the triple handshake attack. */
+ unsigned char *peer_cert_digest;
+ size_t peer_cert_digest_len;
+ mbedtls_md_type_t peer_cert_digest_type;
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
uint32_t verify_result; /*!< verification result */
@@ -860,7 +937,7 @@
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 */
@@ -889,14 +966,28 @@
/** Callback to export key block and master secret */
int (*f_export_keys)( void *, const unsigned char *,
const unsigned char *, size_t, size_t, size_t );
+ /** Callback to export key block, master secret,
+ * tls_prf and random bytes. Should replace f_export_keys */
+ int (*f_export_keys_ext)( void *, const unsigned char *,
+ const unsigned char *, size_t, size_t, size_t,
+ const unsigned char[32], const unsigned char[32],
+ mbedtls_tls_prf_types );
void *p_export_keys; /*!< context for key export callback */
#endif
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ size_t cid_len; /*!< The length of CIDs for incoming DTLS records. */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
#if defined(MBEDTLS_X509_CRT_PARSE_C)
const mbedtls_x509_crt_profile *cert_profile; /*!< verification profile */
mbedtls_ssl_key_cert *key_cert; /*!< own certificate/key pair(s) */
mbedtls_x509_crt *ca_chain; /*!< trusted CAs */
mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+ mbedtls_x509_crt_ca_cb_t f_ca_cb;
+ void *p_ca_cb;
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
@@ -909,7 +1000,7 @@
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
@@ -922,20 +1013,38 @@
mbedtls_mpi dhm_G; /*!< generator for DHM */
#endif
-#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
- unsigned char *psk; /*!< pre-shared key. This field should
- only be set via
- mbedtls_ssl_conf_psk() */
- size_t psk_len; /*!< length of the pre-shared key. This
- field should only be set via
- mbedtls_ssl_conf_psk() */
- unsigned char *psk_identity; /*!< identity for PSK negotiation. This
- field should only be set via
- mbedtls_ssl_conf_psk() */
- size_t psk_identity_len;/*!< length of identity. This field should
- only be set via
- mbedtls_ssl_conf_psk() */
-#endif
+#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.
+ * This field should only be set via
+ * mbedtls_ssl_conf_psk_opaque().
+ * If either no PSK or a raw PSK have
+ * been configured, this has value \c 0. */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+ unsigned char *psk; /*!< The raw pre-shared key. This field should
+ * only be set via mbedtls_ssl_conf_psk().
+ * If either no PSK or an opaque PSK
+ * have been configured, this has value NULL. */
+ size_t psk_len; /*!< The length of the raw pre-shared key.
+ * This field should only be set via
+ * mbedtls_ssl_conf_psk().
+ * Its value is non-zero if and only if
+ * \c psk is not \c NULL. */
+
+ unsigned char *psk_identity; /*!< The PSK identity for PSK negotiation.
+ * This field should only be set via
+ * mbedtls_ssl_conf_psk().
+ * This is set if and only if either
+ * \c psk or \c psk_opaque are set. */
+ size_t psk_identity_len;/*!< The length of PSK identity.
+ * This field should only be set via
+ * mbedtls_ssl_conf_psk().
+ * Its value is non-zero if and only if
+ * \c psk is not \c NULL or \c psk_opaque
+ * is not \c 0. */
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#if defined(MBEDTLS_SSL_ALPN)
const char **alpn_list; /*!< ordered list of protocols */
@@ -1016,6 +1125,11 @@
unsigned int cert_req_ca_list : 1; /*!< enable sending CA list in
Certificate Request messages? */
#endif
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ unsigned int ignore_unexpected_cid : 1; /*!< Determines whether DTLS
+ * record with unexpected CID
+ * should lead to failure. */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
};
@@ -1041,6 +1155,12 @@
unsigned badmac_seen; /*!< records with a bad MAC received */
#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+ /** Callback to customize X.509 certificate chain verification */
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *);
+ void *p_vrfy; /*!< context for X.509 verify callback */
+#endif
+
mbedtls_ssl_send_t *f_send; /*!< Callback for network send */
mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */
mbedtls_ssl_recv_timeout_t *f_recv_timeout;
@@ -1083,6 +1203,10 @@
TLS: maintained by us
DTLS: read from peer */
unsigned char *in_hdr; /*!< start of record header */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ unsigned char *in_cid; /*!< The start of the CID;
+ * (the end is marked by in_len). */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
unsigned char *in_len; /*!< two-bytes message length field */
unsigned char *in_iv; /*!< ivlen-byte IV */
unsigned char *in_msg; /*!< message contents (in_iv+ivlen) */
@@ -1091,6 +1215,9 @@
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
@@ -1119,6 +1246,10 @@
unsigned char *out_buf; /*!< output buffer */
unsigned char *out_ctr; /*!< 64-bit outgoing message counter */
unsigned char *out_hdr; /*!< start of record header */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ unsigned char *out_cid; /*!< The start of the CID;
+ * (the end is marked by in_len). */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
unsigned char *out_len; /*!< two-bytes message length field */
unsigned char *out_iv; /*!< ivlen-byte IV */
unsigned char *out_msg; /*!< message contents (out_iv+ivlen) */
@@ -1126,6 +1257,9 @@
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. */
@@ -1176,25 +1310,59 @@
char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */
char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */
#endif /* MBEDTLS_SSL_RENEGOTIATION */
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ /* CID configuration to use in subsequent handshakes. */
+
+ /*! The next incoming CID, chosen by the user and applying to
+ * all subsequent handshakes. This may be different from the
+ * CID currently used in case the user has re-configured the CID
+ * after an initial handshake. */
+ unsigned char own_cid[ MBEDTLS_SSL_CID_IN_LEN_MAX ];
+ uint8_t own_cid_len; /*!< The length of \c own_cid. */
+ uint8_t negotiate_cid; /*!< This indicates whether the CID extension should
+ * be negotiated in the next handshake or not.
+ * Possible values are #MBEDTLS_SSL_CID_ENABLED
+ * and #MBEDTLS_SSL_CID_DISABLED. */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
};
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
-#define MBEDTLS_SSL_CHANNEL_OUTBOUND 0
-#define MBEDTLS_SSL_CHANNEL_INBOUND 1
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-extern int (*mbedtls_ssl_hw_record_init)(mbedtls_ssl_context *ssl,
- const unsigned char *key_enc, const unsigned char *key_dec,
- size_t keylen,
- const unsigned char *iv_enc, const unsigned char *iv_dec,
- size_t ivlen,
- const unsigned char *mac_enc, const unsigned char *mac_dec,
- size_t maclen);
-extern int (*mbedtls_ssl_hw_record_activate)(mbedtls_ssl_context *ssl, int direction);
-extern int (*mbedtls_ssl_hw_record_reset)(mbedtls_ssl_context *ssl);
-extern int (*mbedtls_ssl_hw_record_write)(mbedtls_ssl_context *ssl);
-extern int (*mbedtls_ssl_hw_record_read)(mbedtls_ssl_context *ssl);
-extern int (*mbedtls_ssl_hw_record_finish)(mbedtls_ssl_context *ssl);
+#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 */
/**
@@ -1317,13 +1485,17 @@
/**
* \brief Set the verification callback (Optional).
*
- * If set, the verify callback is called for each
- * certificate in the chain. For implementation
- * information, please see \c mbedtls_x509_crt_verify()
+ * If set, the provided verify callback is called for each
+ * certificate in the peer's CRT chain, including the trusted
+ * root. For more information, please see the documentation of
+ * \c mbedtls_x509_crt_verify().
*
- * \param conf SSL configuration
- * \param f_vrfy verification function
- * \param p_vrfy verification parameter
+ * \note For per context callbacks and contexts, please use
+ * mbedtls_ssl_set_verify() instead.
+ *
+ * \param conf The SSL configuration to use.
+ * \param f_vrfy The verification callback to use during CRT verification.
+ * \param p_vrfy The opaque context to be passed to the callback.
*/
void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
@@ -1396,6 +1568,142 @@
mbedtls_ssl_recv_timeout_t *f_recv_timeout );
#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+
+
+/**
+ * \brief Configure the use of the Connection ID (CID)
+ * extension in the next handshake.
+ *
+ * Reference: draft-ietf-tls-dtls-connection-id-05
+ * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05
+ *
+ * The DTLS CID extension allows the reliable association of
+ * DTLS records to DTLS connections across changes in the
+ * underlying transport (changed IP and Port metadata) by
+ * adding explicit connection identifiers (CIDs) to the
+ * headers of encrypted DTLS records. The desired CIDs are
+ * configured by the application layer and are exchanged in
+ * new `ClientHello` / `ServerHello` extensions during the
+ * handshake, where each side indicates the CID it wants the
+ * peer to use when writing encrypted messages. The CIDs are
+ * put to use once records get encrypted: the stack discards
+ * any incoming records that don't include the configured CID
+ * in their header, and adds the peer's requested CID to the
+ * headers of outgoing messages.
+ *
+ * This API enables or disables the use of the CID extension
+ * in the next handshake and sets the value of the CID to
+ * be used for incoming messages.
+ *
+ * \param ssl The SSL context to configure. This must be initialized.
+ * \param enable This value determines whether the CID extension should
+ * be used or not. Possible values are:
+ * - MBEDTLS_SSL_CID_ENABLED to enable the use of the CID.
+ * - MBEDTLS_SSL_CID_DISABLED (default) to disable the use
+ * of the CID.
+ * \param own_cid The address of the readable buffer holding the CID we want
+ * the peer to use when sending encrypted messages to us.
+ * This may be \c NULL if \p own_cid_len is \c 0.
+ * This parameter is unused if \p enabled is set to
+ * MBEDTLS_SSL_CID_DISABLED.
+ * \param own_cid_len The length of \p own_cid.
+ * This parameter is unused if \p enabled is set to
+ * MBEDTLS_SSL_CID_DISABLED.
+ *
+ * \note The value of \p own_cid_len must match the value of the
+ * \c len parameter passed to mbedtls_ssl_conf_cid()
+ * when configuring the ::mbedtls_ssl_config that \p ssl
+ * is bound to.
+ *
+ * \note This CID configuration applies to subsequent handshakes
+ * performed on the SSL context \p ssl, but does not trigger
+ * one. You still have to call `mbedtls_ssl_handshake()`
+ * (for the initial handshake) or `mbedtls_ssl_renegotiate()`
+ * (for a renegotiation handshake) explicitly after a
+ * successful call to this function to run the handshake.
+ *
+ * \note This call cannot guarantee that the use of the CID
+ * will be successfully negotiated in the next handshake,
+ * because the peer might not support it. Specifically:
+ * - On the Client, enabling the use of the CID through
+ * this call implies that the `ClientHello` in the next
+ * handshake will include the CID extension, thereby
+ * offering the use of the CID to the server. Only if
+ * the `ServerHello` contains the CID extension, too,
+ * the CID extension will actually be put to use.
+ * - On the Server, enabling the use of the CID through
+ * this call implies that that the server will look for
+ * the CID extension in a `ClientHello` from the client,
+ * and, if present, reply with a CID extension in its
+ * `ServerHello`.
+ *
+ * \note To check whether the use of the CID was negotiated
+ * after the subsequent handshake has completed, please
+ * use the API mbedtls_ssl_get_peer_cid().
+ *
+ * \warning If the use of the CID extension is enabled in this call
+ * and the subsequent handshake negotiates its use, Mbed TLS
+ * will silently drop every packet whose CID does not match
+ * the CID configured in \p own_cid. It is the responsibility
+ * of the user to adapt the underlying transport to take care
+ * of CID-based demultiplexing before handing datagrams to
+ * Mbed TLS.
+ *
+ * \return \c 0 on success. In this case, the CID configuration
+ * applies to the next handshake.
+ * \return A negative error code on failure.
+ */
+int mbedtls_ssl_set_cid( mbedtls_ssl_context *ssl,
+ int enable,
+ unsigned char const *own_cid,
+ size_t own_cid_len );
+
+/**
+ * \brief Get information about the use of the CID extension
+ * in the current connection.
+ *
+ * \param ssl The SSL context to query.
+ * \param enabled The address at which to store whether the CID extension
+ * is currently in use or not. If the CID is in use,
+ * `*enabled` is set to MBEDTLS_SSL_CID_ENABLED;
+ * otherwise, it is set to MBEDTLS_SSL_CID_DISABLED.
+ * \param peer_cid The address of the buffer in which to store the CID
+ * chosen by the peer (if the CID extension is used).
+ * This may be \c NULL in case the value of peer CID
+ * isn't needed. If it is not \c NULL, \p peer_cid_len
+ * must not be \c NULL.
+ * \param peer_cid_len The address at which to store the size of the CID
+ * chosen by the peer (if the CID extension is used).
+ * This is also the number of Bytes in \p peer_cid that
+ * have been written.
+ * This may be \c NULL in case the length of the peer CID
+ * isn't needed. If it is \c NULL, \p peer_cid must be
+ * \c NULL, too.
+ *
+ * \note This applies to the state of the CID negotiated in
+ * the last complete handshake. If a handshake is in
+ * progress, this function will attempt to complete
+ * the handshake first.
+ *
+ * \note If CID extensions have been exchanged but both client
+ * and server chose to use an empty CID, this function
+ * sets `*enabled` to #MBEDTLS_SSL_CID_DISABLED
+ * (the rationale for this is that the resulting
+ * communication is the same as if the CID extensions
+ * hadn't been used).
+ *
+ * \return \c 0 on success.
+ * \return A negative error code on failure.
+ */
+int mbedtls_ssl_get_peer_cid( mbedtls_ssl_context *ssl,
+ int *enabled,
+ unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ],
+ size_t *peer_cid_len );
+
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
/**
* \brief Set the Maximum Tranport Unit (MTU).
* Special value: 0 means unset (no limit).
@@ -1441,6 +1749,30 @@
void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu );
#endif /* MBEDTLS_SSL_PROTO_DTLS */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+/**
+ * \brief Set a connection-specific verification callback (optional).
+ *
+ * If set, the provided verify callback is called for each
+ * certificate in the peer's CRT chain, including the trusted
+ * root. For more information, please see the documentation of
+ * \c mbedtls_x509_crt_verify().
+ *
+ * \note This call is analogous to mbedtls_ssl_conf_verify() but
+ * binds the verification callback and context to an SSL context
+ * as opposed to an SSL configuration.
+ * If mbedtls_ssl_conf_verify() and mbedtls_ssl_set_verify()
+ * are both used, mbedtls_ssl_set_verify() takes precedence.
+ *
+ * \param ssl The SSL context to use.
+ * \param f_vrfy The verification callback to use during CRT verification.
+ * \param p_vrfy The opaque context to be passed to the callback.
+ */
+void mbedtls_ssl_set_verify( mbedtls_ssl_context *ssl,
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+ void *p_vrfy );
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
/**
* \brief Set the timeout period for mbedtls_ssl_read()
* (Default: no timeout.)
@@ -1459,6 +1791,56 @@
*/
void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout );
+#if defined(MBEDTLS_SSL_RECORD_CHECKING)
+/**
+ * \brief Check whether a buffer contains a valid and authentic record
+ * that has not been seen before. (DTLS only).
+ *
+ * This function does not change the user-visible state
+ * of the SSL context. Its sole purpose is to provide
+ * an indication of the legitimacy of an incoming record.
+ *
+ * This can be useful e.g. in distributed server environments
+ * using the DTLS Connection ID feature, in which connections
+ * might need to be passed between service instances on a change
+ * of peer address, but where such disruptive operations should
+ * only happen after the validity of incoming records has been
+ * confirmed.
+ *
+ * \param ssl The SSL context to use.
+ * \param buf The address of the buffer holding the record to be checked.
+ * This must be a read/write buffer of length \p buflen Bytes.
+ * \param buflen The length of \p buf in Bytes.
+ *
+ * \note This routine only checks whether the provided buffer begins
+ * with a valid and authentic record that has not been seen
+ * before, but does not check potential data following the
+ * initial record. In particular, it is possible to pass DTLS
+ * datagrams containing multiple records, in which case only
+ * the first record is checked.
+ *
+ * \note This function modifies the input buffer \p buf. If you need
+ * to preserve the original record, you have to maintain a copy.
+ *
+ * \return \c 0 if the record is valid and authentic and has not been
+ * seen before.
+ * \return MBEDTLS_ERR_SSL_INVALID_MAC if the check completed
+ * successfully but the record was found to be not authentic.
+ * \return MBEDTLS_ERR_SSL_INVALID_RECORD if the check completed
+ * successfully but the record was found to be invalid for
+ * a reason different from authenticity checking.
+ * \return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD if the check completed
+ * successfully but the record was found to be unexpected
+ * in the state of the SSL context, including replayed records.
+ * \return Another negative error code on different kinds of failure.
+ * In this case, the SSL context becomes unusable and needs
+ * to be freed or reset before reuse.
+ */
+int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl,
+ unsigned char *buf,
+ size_t buflen );
+#endif /* MBEDTLS_SSL_RECORD_CHECKING */
+
/**
* \brief Set the timer callbacks (Mandatory for DTLS.)
*
@@ -1537,6 +1919,41 @@
size_t maclen,
size_t keylen,
size_t ivlen );
+
+/**
+ * \brief Callback type: Export key block, master secret,
+ * handshake randbytes and the tls_prf function
+ * used to derive keys.
+ *
+ * \note This is required for certain uses of TLS, e.g. EAP-TLS
+ * (RFC 5216) and Thread. The key pointers are ephemeral and
+ * therefore must not be stored. The master secret and keys
+ * should not be used directly except as an input to a key
+ * derivation function.
+ *
+ * \param p_expkey Context for the callback.
+ * \param ms Pointer to master secret (fixed length: 48 bytes).
+ * \param kb Pointer to key block, see RFC 5246 section 6.3.
+ * (variable length: 2 * maclen + 2 * keylen + 2 * ivlen).
+ * \param maclen MAC length.
+ * \param keylen Key length.
+ * \param ivlen IV length.
+ * \param client_random The client random bytes.
+ * \param server_random The server random bytes.
+ * \param tls_prf_type The tls_prf enum type.
+ *
+ * \return 0 if successful, or
+ * a specific MBEDTLS_ERR_XXX code.
+ */
+typedef int mbedtls_ssl_export_keys_ext_t( void *p_expkey,
+ const unsigned char *ms,
+ const unsigned char *kb,
+ size_t maclen,
+ size_t keylen,
+ size_t ivlen,
+ const unsigned char client_random[32],
+ const unsigned char server_random[32],
+ mbedtls_tls_prf_types tls_prf_type );
#endif /* MBEDTLS_SSL_EXPORT_KEYS */
/**
@@ -1602,6 +2019,20 @@
void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf,
mbedtls_ssl_export_keys_t *f_export_keys,
void *p_export_keys );
+
+/**
+ * \brief Configure extended key export callback.
+ * (Default: none.)
+ *
+ * \note See \c mbedtls_ssl_export_keys_ext_t.
+ *
+ * \param conf SSL configuration context
+ * \param f_export_keys_ext Callback for exporting keys
+ * \param p_export_keys Context for the callback
+ */
+void mbedtls_ssl_conf_export_keys_ext_cb( mbedtls_ssl_config *conf,
+ mbedtls_ssl_export_keys_ext_t *f_export_keys_ext,
+ void *p_export_keys );
#endif /* MBEDTLS_SSL_EXPORT_KEYS */
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
@@ -1953,6 +2384,90 @@
#endif /* MBEDTLS_SSL_CLI_C */
/**
+ * \brief Load serialized session data into a session structure.
+ * On client, this can be used for loading saved sessions
+ * before resuming them with mbedstls_ssl_set_session().
+ * On server, this can be used for alternative implementations
+ * of session cache or session tickets.
+ *
+ * \warning If a peer certificate chain is associated with the session,
+ * the serialized state will only contain the peer's
+ * end-entity certificate and the result of the chain
+ * verification (unless verification was disabled), but not
+ * the rest of the chain.
+ *
+ * \see mbedtls_ssl_session_save()
+ * \see mbedtls_ssl_set_session()
+ *
+ * \param session The session structure to be populated. It must have been
+ * initialised with mbedtls_ssl_session_init() but not
+ * populated yet.
+ * \param buf The buffer holding the serialized session data. It must be a
+ * readable buffer of at least \p len bytes.
+ * \param len The size of the serialized data in bytes.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed.
+ * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid.
+ * \return #MBEDTLS_ERR_SSL_VERSION_MISMATCH if the serialized data
+ * was generated in a different version or configuration of
+ * Mbed TLS.
+ * \return Another negative value for other kinds of errors (for
+ * example, unsupported features in the embedded certificate).
+ */
+int mbedtls_ssl_session_load( mbedtls_ssl_session *session,
+ const unsigned char *buf,
+ size_t len );
+
+/**
+ * \brief Save session structure as serialized data in a buffer.
+ * On client, this can be used for saving session data,
+ * potentially in non-volatile storage, for resuming later.
+ * On server, this can be used for alternative implementations
+ * of session cache or session tickets.
+ *
+ * \see mbedtls_ssl_session_load()
+ * \see mbedtls_ssl_get_session_pointer()
+ *
+ * \param session The session structure to be saved.
+ * \param buf The buffer to write the serialized data to. It must be a
+ * writeable buffer of at least \p len bytes, or may be \c
+ * NULL if \p len is \c 0.
+ * \param buf_len The number of bytes available for writing in \p buf.
+ * \param olen The size in bytes of the data that has been or would have
+ * been written. It must point to a valid \c size_t.
+ *
+ * \note \p olen is updated to the correct value regardless of
+ * whether \p buf_len was large enough. This makes it possible
+ * to determine the necessary size by calling this function
+ * with \p buf set to \c NULL and \p buf_len to \c 0.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small.
+ */
+int mbedtls_ssl_session_save( const mbedtls_ssl_session *session,
+ unsigned char *buf,
+ size_t buf_len,
+ size_t *olen );
+
+/**
+ * \brief Get a pointer to the current session structure, for example
+ * to serialize it.
+ *
+ * \warning Ownership of the session remains with the SSL context, and
+ * the returned pointer is only guaranteed to be valid until
+ * the next API call operating on the same \p ssl context.
+ *
+ * \see mbedtls_ssl_session_save()
+ *
+ * \param ssl The SSL context.
+ *
+ * \return A pointer to the current session if successful.
+ * \return \c NULL if no session is active.
+ */
+const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_context *ssl );
+
+/**
* \brief Set the list of allowed ciphersuites and the preference
* order. First in the list has the highest preference.
* (Overrides all version-specific lists)
@@ -1970,6 +2485,45 @@
void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf,
const int *ciphersuites );
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+#define MBEDTLS_SSL_UNEXPECTED_CID_IGNORE 0
+#define MBEDTLS_SSL_UNEXPECTED_CID_FAIL 1
+/**
+ * \brief Specify the length of Connection IDs for incoming
+ * encrypted DTLS records, as well as the behaviour
+ * on unexpected CIDs.
+ *
+ * By default, the CID length is set to \c 0,
+ * and unexpected CIDs are silently ignored.
+ *
+ * \param conf The SSL configuration to modify.
+ * \param len The length in Bytes of the CID fields in encrypted
+ * DTLS records using the CID mechanism. This must
+ * not be larger than #MBEDTLS_SSL_CID_OUT_LEN_MAX.
+ * \param ignore_other_cids This determines the stack's behaviour when
+ * receiving a record with an unexpected CID.
+ * Possible values are:
+ * - #MBEDTLS_SSL_UNEXPECTED_CID_IGNORE
+ * In this case, the record is silently ignored.
+ * - #MBEDTLS_SSL_UNEXPECTED_CID_FAIL
+ * In this case, the stack fails with the specific
+ * error code #MBEDTLS_ERR_SSL_UNEXPECTED_CID.
+ *
+ * \note The CID specification allows implementations to either
+ * use a common length for all incoming connection IDs or
+ * allow variable-length incoming IDs. Mbed TLS currently
+ * requires a common length for all connections sharing the
+ * same SSL configuration; this allows simpler parsing of
+ * record headers.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if \p own_cid_len
+ * is too large.
+ */
+int mbedtls_ssl_conf_cid( mbedtls_ssl_config *conf, size_t len,
+ int ignore_other_cids );
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
/**
* \brief Set the list of allowed ciphersuites and the
* preference order for a specific version of the protocol.
@@ -2022,6 +2576,63 @@
mbedtls_x509_crt *ca_chain,
mbedtls_x509_crl *ca_crl );
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+/**
+ * \brief Set the trusted certificate callback.
+ *
+ * This API allows to register the set of trusted certificates
+ * through a callback, instead of a linked list as configured
+ * by mbedtls_ssl_conf_ca_chain().
+ *
+ * This is useful for example in contexts where a large number
+ * of CAs are used, and the inefficiency of maintaining them
+ * in a linked list cannot be tolerated. It is also useful when
+ * the set of trusted CAs needs to be modified frequently.
+ *
+ * See the documentation of `mbedtls_x509_crt_ca_cb_t` for
+ * more information.
+ *
+ * \param conf The SSL configuration to register the callback with.
+ * \param f_ca_cb The trusted certificate callback to use when verifying
+ * certificate chains.
+ * \param p_ca_cb The context to be passed to \p f_ca_cb (for example,
+ * a reference to a trusted CA database).
+ *
+ * \note This API is incompatible with mbedtls_ssl_conf_ca_chain():
+ * Any call to this function overwrites the values set through
+ * earlier calls to mbedtls_ssl_conf_ca_chain() or
+ * mbedtls_ssl_conf_ca_cb().
+ *
+ * \note This API is incompatible with CA indication in
+ * CertificateRequest messages: A server-side SSL context which
+ * is bound to an SSL configuration that uses a CA callback
+ * configured via mbedtls_ssl_conf_ca_cb(), and which requires
+ * client authentication, will send an empty CA list in the
+ * corresponding CertificateRequest message.
+ *
+ * \note This API is incompatible with mbedtls_ssl_set_hs_ca_chain():
+ * If an SSL context is bound to an SSL configuration which uses
+ * CA callbacks configured via mbedtls_ssl_conf_ca_cb(), then
+ * calls to mbedtls_ssl_set_hs_ca_chain() have no effect.
+ *
+ * \note The use of this API disables the use of restartable ECC
+ * during X.509 CRT signature verification (but doesn't affect
+ * other uses).
+ *
+ * \warning This API is incompatible with the use of CRLs. Any call to
+ * mbedtls_ssl_conf_ca_cb() unsets CRLs configured through
+ * earlier calls to mbedtls_ssl_conf_ca_chain().
+ *
+ * \warning In multi-threaded environments, the callback \p f_ca_cb
+ * must be thread-safe, and it is the user's responsibility
+ * to guarantee this (for example through a mutex
+ * contained in the callback context pointed to by \p p_ca_cb).
+ */
+void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf,
+ mbedtls_x509_crt_ca_cb_t f_ca_cb,
+ void *p_ca_cb );
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
+
/**
* \brief Set own certificate chain and private key
*
@@ -2063,76 +2674,154 @@
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 Set the Pre Shared Key (PSK) and the expected identity name
+ * \brief Configure a pre-shared key (PSK) and identity
+ * to be used in PSK-based ciphersuites.
*
* \note This is mainly useful for clients. Servers will usually
* want to use \c mbedtls_ssl_conf_psk_cb() instead.
*
- * \note Currently clients can only register one pre-shared key.
- * In other words, the servers' identity hint is ignored.
+ * \warning Currently, clients can only register a single pre-shared key.
+ * Calling this function or mbedtls_ssl_conf_psk_opaque() more
+ * than once will overwrite values configured in previous calls.
* Support for setting multiple PSKs on clients and selecting
- * one based on the identity hint is not a planned feature but
- * feedback is welcomed.
+ * one based on the identity hint is not a planned feature,
+ * but feedback is welcomed.
*
- * \param conf SSL configuration
- * \param psk pointer to the pre-shared key
- * \param psk_len pre-shared key length
- * \param psk_identity pointer to the pre-shared key identity
- * \param psk_identity_len identity key length
+ * \param conf The SSL configuration to register the PSK with.
+ * \param psk The pointer to the pre-shared key to use.
+ * \param psk_len The length of the pre-shared key in bytes.
+ * \param psk_identity The pointer to the pre-shared key identity.
+ * \param psk_identity_len The length of the pre-shared key identity
+ * in bytes.
*
- * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED
+ * \note The PSK and its identity are copied internally and
+ * hence need not be preserved by the caller for the lifetime
+ * of the SSL configuration.
+ *
+ * \return \c 0 if successful.
+ * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure.
*/
int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf,
const unsigned char *psk, size_t psk_len,
const unsigned char *psk_identity, size_t psk_identity_len );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/**
+ * \brief Configure an opaque pre-shared key (PSK) and identity
+ * to be used in PSK-based ciphersuites.
+ *
+ * \note This is mainly useful for clients. Servers will usually
+ * want to use \c mbedtls_ssl_conf_psk_cb() instead.
+ *
+ * \warning Currently, clients can only register a single pre-shared key.
+ * Calling this function or mbedtls_ssl_conf_psk() more than
+ * once will overwrite values configured in previous calls.
+ * Support for setting multiple PSKs on clients and selecting
+ * one based on the identity hint is not a planned feature,
+ * but feedback is welcomed.
+ *
+ * \param conf The SSL configuration to register the PSK with.
+ * \param psk The identifier of the key slot holding the PSK.
+ * Until \p conf is destroyed or this function is successfully
+ * called again, the key slot \p psk must be populated with a
+ * key of type PSA_ALG_CATEGORY_KEY_DERIVATION whose policy
+ * allows its use for the key derivation algorithm applied
+ * in the handshake.
+ * \param psk_identity The pointer to the pre-shared key identity.
+ * \param psk_identity_len The length of the pre-shared key identity
+ * in bytes.
+ *
+ * \note The PSK identity hint is copied internally and hence need
+ * not be preserved by the caller for the lifetime of the
+ * SSL configuration.
+ *
+ * \return \c 0 if successful.
+ * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure.
+ */
+int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf,
+ psa_key_handle_t psk,
+ const unsigned char *psk_identity,
+ size_t psk_identity_len );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
/**
- * \brief Set the Pre Shared Key (PSK) for the current handshake
+ * \brief Set the pre-shared Key (PSK) for the current handshake.
*
* \note This should only be called inside the PSK callback,
- * ie the function passed to \c mbedtls_ssl_conf_psk_cb().
+ * i.e. the function passed to \c mbedtls_ssl_conf_psk_cb().
*
- * \param ssl SSL context
- * \param psk pointer to the pre-shared key
- * \param psk_len pre-shared key length
+ * \param ssl The SSL context to configure a PSK for.
+ * \param psk The pointer to the pre-shared key.
+ * \param psk_len The length of the pre-shared key in bytes.
*
- * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED
+ * \return \c 0 if successful.
+ * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure.
*/
int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl,
const unsigned char *psk, size_t psk_len );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/**
+ * \brief Set an opaque pre-shared Key (PSK) for the current handshake.
+ *
+ * \note This should only be called inside the PSK callback,
+ * i.e. the function passed to \c mbedtls_ssl_conf_psk_cb().
+ *
+ * \param ssl The SSL context to configure a PSK for.
+ * \param psk The identifier of the key slot holding the PSK.
+ * For the duration of the current handshake, the key slot
+ * must be populated with a key of type
+ * PSA_ALG_CATEGORY_KEY_DERIVATION whose policy allows its
+ * use for the key derivation algorithm
+ * applied in the handshake.
+ *
+ * \return \c 0 if successful.
+ * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure.
+ */
+int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl,
+ psa_key_handle_t psk );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
/**
* \brief Set the PSK callback (server-side only).
*
* If set, the PSK callback is called for each
- * handshake where a PSK ciphersuite was negotiated.
+ * handshake where a PSK-based ciphersuite was negotiated.
* The caller provides the identity received and wants to
* receive the actual PSK data and length.
*
- * The callback has the following parameters: (void *parameter,
- * mbedtls_ssl_context *ssl, const unsigned char *psk_identity,
- * size_t identity_len)
+ * The callback has the following parameters:
+ * - \c void*: The opaque pointer \p p_psk.
+ * - \c mbedtls_ssl_context*: The SSL context to which
+ * the operation applies.
+ * - \c const unsigned char*: The PSK identity
+ * selected by the client.
+ * - \c size_t: The length of the PSK identity
+ * selected by the client.
+ *
* If a valid PSK identity is found, the callback should use
- * \c mbedtls_ssl_set_hs_psk() on the ssl context to set the
- * correct PSK and return 0.
+ * \c mbedtls_ssl_set_hs_psk() or
+ * \c mbedtls_ssl_set_hs_psk_opaque()
+ * on the SSL context to set the correct PSK and return \c 0.
* Any other return value will result in a denied PSK identity.
*
* \note If you set a PSK callback using this function, then you
* don't need to set a PSK key and identity using
* \c mbedtls_ssl_conf_psk().
*
- * \param conf SSL configuration
- * \param f_psk PSK identity function
- * \param p_psk PSK identity parameter
+ * \param conf The SSL configuration to register the callback with.
+ * \param f_psk The callback for selecting and setting the PSK based
+ * in the PSK identity chosen by the client.
+ * \param p_psk A pointer to an opaque structure to be passed to
+ * the callback, for example a PSK store.
*/
void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf,
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)
@@ -2237,7 +2926,7 @@
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.)
@@ -2258,7 +2947,7 @@
*/
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)
/**
@@ -2505,7 +3194,7 @@
* \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.
@@ -2546,14 +3235,14 @@
* been set via this function to a value different than
* #MBEDTLS_SSL_MAX_FRAG_LEN_NONE.
*
- * \note This sets the maximum length for a record's payload,
- * excluding record overhead that will be added to it, see
- * \c mbedtls_ssl_get_record_expansion().
- *
* \note With TLS, this currently only affects ApplicationData (sent
* with \c mbedtls_ssl_read()), not handshake messages.
* With DTLS, this affects both ApplicationData and handshake.
*
+ * \note This sets the maximum length for a record's payload,
+ * excluding record overhead that will be added to it, see
+ * \c mbedtls_ssl_get_record_expansion().
+ *
* \note For DTLS, it is also possible to set a limit for the total
* size of daragrams passed to the transport layer, including
* record overhead, see \c mbedtls_ssl_set_mtu().
@@ -2704,7 +3393,7 @@
* (Default: 2^48 - 1)
*
* Renegotiation is automatically triggered when a record
- * counter (outgoing or ingoing) crosses the defined
+ * counter (outgoing or incoming) crosses the defined
* threshold. The default value is meant to prevent the
* connection from being closed when the counter is about to
* reached its maximal value (it is not allowed to wrap).
@@ -2834,18 +3523,61 @@
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
/**
- * \brief Return the maximum fragment length (payload, in bytes).
- * This is the value negotiated with peer if any,
- * or the locally configured value.
+ * \brief Return the maximum fragment length (payload, in bytes) for
+ * the output buffer. For the client, this is the configured
+ * value. For the server, it is the minimum of two - the
+ * configured value and the negotiated one.
*
* \sa mbedtls_ssl_conf_max_frag_len()
* \sa mbedtls_ssl_get_max_record_payload()
*
* \param ssl SSL context
*
- * \return Current maximum fragment length.
+ * \return Current maximum fragment length for the output buffer.
*/
-size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl );
+size_t mbedtls_ssl_get_output_max_frag_len( const mbedtls_ssl_context *ssl );
+
+/**
+ * \brief Return the maximum fragment length (payload, in bytes) for
+ * the input buffer. This is the negotiated maximum fragment
+ * length, or, if there is none, MBEDTLS_SSL_MAX_CONTENT_LEN.
+ * If it is not defined either, the value is 2^14. This function
+ * works as its predecessor, \c mbedtls_ssl_get_max_frag_len().
+ *
+ * \sa mbedtls_ssl_conf_max_frag_len()
+ * \sa mbedtls_ssl_get_max_record_payload()
+ *
+ * \param ssl SSL context
+ *
+ * \return Current maximum fragment length for the output buffer.
+ */
+size_t mbedtls_ssl_get_input_max_frag_len( const mbedtls_ssl_context *ssl );
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+
+#if defined(MBEDTLS_DEPRECATED_WARNING)
+#define MBEDTLS_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDTLS_DEPRECATED
+#endif
+
+/**
+ * \brief This function is a deprecated approach to getting the max
+ * fragment length. Its an alias for
+ * \c mbedtls_ssl_get_output_max_frag_len(), as the behaviour
+ * is the same. See \c mbedtls_ssl_get_output_max_frag_len() for
+ * more detail.
+ *
+ * \sa mbedtls_ssl_get_input_max_frag_len()
+ * \sa mbedtls_ssl_get_output_max_frag_len()
+ *
+ * \param ssl SSL context
+ *
+ * \return Current maximum fragment length for the output buffer.
+ */
+MBEDTLS_DEPRECATED size_t mbedtls_ssl_get_max_frag_len(
+ const mbedtls_ssl_context *ssl );
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
/**
@@ -2866,7 +3598,8 @@
* 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
@@ -2878,18 +3611,34 @@
#if defined(MBEDTLS_X509_CRT_PARSE_C)
/**
- * \brief Return the peer certificate from the current connection
+ * \brief Return the peer certificate from the current connection.
*
- * Note: Can be NULL in case no certificate was sent during
- * the handshake. Different calls for the same connection can
- * return the same or different pointers for the same
- * certificate and even a different certificate altogether.
- * The peer cert CAN change in a single connection if
- * renegotiation is performed.
+ * \param ssl The SSL context to use. This must be initialized and setup.
*
- * \param ssl SSL context
+ * \return The current peer certificate, if available.
+ * The returned certificate is owned by the SSL context and
+ * is valid only until the next call to the SSL API.
+ * \return \c NULL if no peer certificate is available. This might
+ * be because the chosen ciphersuite doesn't use CRTs
+ * (PSK-based ciphersuites, for example), or because
+ * #MBEDTLS_SSL_KEEP_PEER_CERTIFICATE has been disabled,
+ * allowing the stack to free the peer's CRT to save memory.
*
- * \return the current peer certificate
+ * \note For one-time inspection of the peer's certificate during
+ * the handshake, consider registering an X.509 CRT verification
+ * callback through mbedtls_ssl_conf_verify() instead of calling
+ * this function. Using mbedtls_ssl_conf_verify() also comes at
+ * the benefit of allowing you to influence the verification
+ * process, for example by masking expected and tolerated
+ * verification failures.
+ *
+ * \warning You must not use the pointer returned by this function
+ * after any further call to the SSL API, including
+ * mbedtls_ssl_read() and mbedtls_ssl_write(); this is
+ * because the pointer might change during renegotiation,
+ * which happens transparently to the user.
+ * If you want to use the certificate across API calls,
+ * you must make a copy.
*/
const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_X509_CRT_PARSE_C */
@@ -3034,7 +3783,14 @@
*
* \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
@@ -3151,8 +3907,8 @@
* 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.
@@ -3200,6 +3956,130 @@
*/
void mbedtls_ssl_free( mbedtls_ssl_context *ssl );
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+/**
+ * \brief Save an active connection as serialized data in a buffer.
+ * This allows the freeing or re-using of the SSL context
+ * while still picking up the connection later in a way that
+ * it entirely transparent to the peer.
+ *
+ * \see mbedtls_ssl_context_load()
+ *
+ * \note This feature is currently only available under certain
+ * conditions, see the documentation of the return value
+ * #MBEDTLS_ERR_SSL_BAD_INPUT_DATA for details.
+ *
+ * \note When this function succeeds, it calls
+ * mbedtls_ssl_session_reset() on \p ssl which as a result is
+ * no longer associated with the connection that has been
+ * serialized. This avoids creating copies of the connection
+ * state. You're then free to either re-use the context
+ * structure for a different connection, or call
+ * mbedtls_ssl_free() on it. See the documentation of
+ * mbedtls_ssl_session_reset() for more details.
+ *
+ * \param ssl The SSL context to save. On success, it is no longer
+ * associated with the connection that has been serialized.
+ * \param buf The buffer to write the serialized data to. It must be a
+ * writeable buffer of at least \p buf_len bytes, or may be \c
+ * NULL if \p buf_len is \c 0.
+ * \param buf_len The number of bytes available for writing in \p buf.
+ * \param olen The size in bytes of the data that has been or would have
+ * been written. It must point to a valid \c size_t.
+ *
+ * \note \p olen is updated to the correct value regardless of
+ * whether \p buf_len was large enough. This makes it possible
+ * to determine the necessary size by calling this function
+ * with \p buf set to \c NULL and \p buf_len to \c 0. However,
+ * the value of \p olen is only guaranteed to be correct when
+ * the function returns #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL or
+ * \c 0. If the return value is different, then the value of
+ * \p olen is undefined.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small.
+ * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed
+ * while reseting the context.
+ * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handshake is in
+ * progress, or there is pending data for reading or sending,
+ * or the connection does not use DTLS 1.2 with an AEAD
+ * ciphersuite, or renegotiation is enabled.
+ */
+int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl,
+ unsigned char *buf,
+ size_t buf_len,
+ size_t *olen );
+
+/**
+ * \brief Load serialized connection data to an SSL context.
+ *
+ * \see mbedtls_ssl_context_save()
+ *
+ * \warning The same serialized data must never be loaded into more
+ * that one context. In order to ensure that, after
+ * successfully loading serialized data to an SSL context, you
+ * should immediately destroy or invalidate all copies of the
+ * serialized data that was loaded. Loading the same data in
+ * more than one context would cause severe security failures
+ * including but not limited to loss of confidentiality.
+ *
+ * \note Before calling this function, the SSL context must be
+ * prepared in one of the two following ways. The first way is
+ * to take a context freshly initialised with
+ * mbedtls_ssl_init() and call mbedtls_ssl_setup() on it with
+ * the same ::mbedtls_ssl_config structure that was used in
+ * the original connection. The second way is to
+ * call mbedtls_ssl_session_reset() on a context that was
+ * previously prepared as above but used in the meantime.
+ * Either way, you must not use the context to perform a
+ * handshake between calling mbedtls_ssl_setup() or
+ * mbedtls_ssl_session_reset() and calling this function. You
+ * may however call other setter functions in that time frame
+ * as indicated in the note below.
+ *
+ * \note Before or after calling this function successfully, you
+ * also need to configure some connection-specific callbacks
+ * and settings before you can use the connection again
+ * (unless they were already set before calling
+ * mbedtls_ssl_session_reset() and the values are suitable for
+ * the present connection). Specifically, you want to call
+ * at least mbedtls_ssl_set_bio() and
+ * mbedtls_ssl_set_timer_cb(). All other SSL setter functions
+ * are not necessary to call, either because they're only used
+ * in handshakes, or because the setting is already saved. You
+ * might choose to call them anyway, for example in order to
+ * share code between the cases of establishing a new
+ * connection and the case of loading an already-established
+ * connection.
+ *
+ * \note If you have new information about the path MTU, you want to
+ * call mbedtls_ssl_set_mtu() after calling this function, as
+ * otherwise this function would overwrite your
+ * newly-configured value with the value that was active when
+ * the context was saved.
+ *
+ * \note When this function returns an error code, it calls
+ * mbedtls_ssl_free() on \p ssl. In this case, you need to
+ * prepare the context with the usual sequence starting with a
+ * call to mbedtls_ssl_init() if you want to use it again.
+ *
+ * \param ssl The SSL context structure to be populated. It must have
+ * been prepared as described in the note above.
+ * \param buf The buffer holding the serialized connection data. It must
+ * be a readable buffer of at least \p len bytes.
+ * \param len The size of the serialized data in bytes.
+ *
+ * \return \c 0 if successful.
+ * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed.
+ * \return #MBEDTLS_ERR_SSL_VERSION_MISMATCH if the serialized data
+ * comes from a different Mbed TLS version or build.
+ * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid.
+ */
+int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl,
+ const unsigned char *buf,
+ size_t len );
+#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
+
/**
* \brief Initialize an SSL configuration context
* Just makes the context ready for
@@ -3255,6 +4135,27 @@
*/
void mbedtls_ssl_session_free( mbedtls_ssl_session *session );
+/**
+ * \brief TLS-PRF function for key derivation.
+ *
+ * \param prf The tls_prf type funtion type to be used.
+ * \param secret Secret for the key derivation function.
+ * \param slen Length of the secret.
+ * \param label String label for the key derivation function,
+ * terminated with null character.
+ * \param random Random bytes.
+ * \param rlen Length of the random bytes buffer.
+ * \param dstbuf The buffer holding the derived key.
+ * \param dlen Length of the output buffer.
+ *
+ * \return 0 on sucess. An SSL specific error on failure.
+ */
+int mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf,
+ const unsigned char *secret, size_t slen,
+ const char *label,
+ const unsigned char *random, size_t rlen,
+ unsigned char *dstbuf, size_t dlen );
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h
index 8b557bc..8df68f1 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h
@@ -25,15 +25,15 @@
#define MBEDTLS_SSL_CACHE_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "ssl.h"
+#include "mbedtls/ssl.h"
#if defined(MBEDTLS_THREADING_C)
-#include "threading.h"
+#include "mbedtls/threading.h"
#endif
/**
@@ -70,7 +70,8 @@
mbedtls_time_t timestamp; /*!< entry timestamp */
#endif
mbedtls_ssl_session session; /*!< entry session */
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+ defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
mbedtls_x509_buf peer_cert; /*!< entry peer_cert */
#endif
mbedtls_ssl_cache_entry *next; /*!< chain pointer */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h
index c5df7b4..0ddbd68 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h
@@ -25,14 +25,14 @@
#define MBEDTLS_SSL_CIPHERSUITES_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "pk.h"
-#include "cipher.h"
-#include "md.h"
+#include "mbedtls/pk.h"
+#include "mbedtls/cipher.h"
+#include "mbedtls/md.h"
#ifdef __cplusplus
extern "C" {
@@ -312,7 +312,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 )
{
@@ -486,7 +486,25 @@
}
}
-#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED)
+static inline int mbedtls_ssl_ciphersuite_uses_srv_cert( const mbedtls_ssl_ciphersuite_t *info )
+{
+ switch( info->key_exchange )
+ {
+ case MBEDTLS_KEY_EXCHANGE_RSA:
+ case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
+ case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
+ return( 1 );
+
+ default:
+ return( 0 );
+ }
+}
+
+#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 )
@@ -499,9 +517,9 @@
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 )
@@ -515,9 +533,9 @@
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 )
@@ -531,7 +549,7 @@
return( 0 );
}
}
-#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */
#ifdef __cplusplus
}
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h
index 8e13bda..3800e2c 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h
@@ -25,15 +25,15 @@
#define MBEDTLS_SSL_COOKIE_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "ssl.h"
+#include "mbedtls/ssl.h"
#if defined(MBEDTLS_THREADING_C)
-#include "threading.h"
+#include "mbedtls/threading.h"
#endif
/**
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_internal.h b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_internal.h
index 581a7f8..5b9f4c1 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_internal.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_internal.h
@@ -25,34 +25,43 @@
#define MBEDTLS_SSL_INTERNAL_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "ssl.h"
-#include "cipher.h"
+#include "mbedtls/ssl.h"
+#include "mbedtls/cipher.h"
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
+#endif
#if defined(MBEDTLS_MD5_C)
-#include "md5.h"
+#include "mbedtls/md5.h"
#endif
#if defined(MBEDTLS_SHA1_C)
-#include "sha1.h"
+#include "mbedtls/sha1.h"
#endif
#if defined(MBEDTLS_SHA256_C)
-#include "sha256.h"
+#include "mbedtls/sha256.h"
#endif
#if defined(MBEDTLS_SHA512_C)
-#include "sha512.h"
+#include "mbedtls/sha512.h"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-#include "ecjpake.h"
+#include "mbedtls/ecjpake.h"
#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
!defined(inline) && !defined(__cplusplus)
#define inline __inline
@@ -104,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
@@ -137,7 +146,16 @@
#define MBEDTLS_SSL_COMPRESSION_ADD 0
#endif
-#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_MODE_CBC)
+#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \
+ ( defined(MBEDTLS_CIPHER_MODE_CBC) && \
+ ( defined(MBEDTLS_AES_C) || \
+ defined(MBEDTLS_CAMELLIA_C) || \
+ defined(MBEDTLS_ARIA_C) || \
+ defined(MBEDTLS_DES_C) ) )
+#define MBEDTLS_SSL_SOME_MODES_USE_MAC
+#endif
+
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
/* Ciphersuites using HMAC */
#if defined(MBEDTLS_SHA512_C)
#define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */
@@ -146,7 +164,7 @@
#else
#define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */
#endif
-#else
+#else /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */
#define MBEDTLS_SSL_MAC_ADD 16
#endif
@@ -157,10 +175,17 @@
#define MBEDTLS_SSL_PADDING_ADD 0
#endif
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+#define MBEDTLS_SSL_MAX_CID_EXPANSION MBEDTLS_SSL_CID_PADDING_GRANULARITY
+#else
+#define MBEDTLS_SSL_MAX_CID_EXPANSION 0
+#endif
+
#define MBEDTLS_SSL_PAYLOAD_OVERHEAD ( MBEDTLS_SSL_COMPRESSION_ADD + \
MBEDTLS_MAX_IV_LENGTH + \
MBEDTLS_SSL_MAC_ADD + \
- MBEDTLS_SSL_PADDING_ADD \
+ MBEDTLS_SSL_PADDING_ADD + \
+ MBEDTLS_SSL_MAX_CID_EXPANSION \
)
#define MBEDTLS_SSL_IN_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \
@@ -213,11 +238,49 @@
implicit sequence number. */
#define MBEDTLS_SSL_HEADER_LEN 13
+#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
#define MBEDTLS_SSL_IN_BUFFER_LEN \
( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_IN_PAYLOAD_LEN ) )
+#else
+#define MBEDTLS_SSL_IN_BUFFER_LEN \
+ ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_IN_PAYLOAD_LEN ) \
+ + ( MBEDTLS_SSL_CID_IN_LEN_MAX ) )
+#endif
+#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
#define MBEDTLS_SSL_OUT_BUFFER_LEN \
( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_OUT_PAYLOAD_LEN ) )
+#else
+#define MBEDTLS_SSL_OUT_BUFFER_LEN \
+ ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_OUT_PAYLOAD_LEN ) \
+ + ( 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 */
@@ -241,7 +304,7 @@
#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.
*/
@@ -256,8 +319,12 @@
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,
+ const unsigned char *random, size_t rlen,
+ unsigned char *dstbuf, size_t dlen );
/*
* This structure contains the parameters only needed during handshake.
*/
@@ -268,7 +335,7 @@
*/
#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)
@@ -276,7 +343,16 @@
#endif
#if defined(MBEDTLS_ECDH_C)
mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */
-#endif
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ 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;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_ECDH_C */
+
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */
#if defined(MBEDTLS_SSL_CLI_C)
@@ -288,10 +364,13 @@
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
+#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)
@@ -301,7 +380,7 @@
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 */
@@ -311,8 +390,13 @@
ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */
ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */
} ecrs_state; /*!< current (or last) operation */
+ mbedtls_x509_crt *ecrs_peer_cert; /*!< The peer's CRT chain. */
size_t ecrs_n; /*!< place for saving a length */
#endif
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ mbedtls_pk_context peer_pubkey; /*!< The public key from the peer. */
+#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */
unsigned int in_msg_seq; /*!< Incoming handshake sequence number */
@@ -334,6 +418,18 @@
unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter
for resending messages */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ /* The state of CID configuration in this handshake. */
+
+ uint8_t cid_in_use; /*!< This indicates whether the use of the CID extension
+ * has been negotiated. Possible values are
+ * #MBEDTLS_SSL_CID_ENABLED and
+ * #MBEDTLS_SSL_CID_DISABLED. */
+ unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ]; /*! The peer's CID */
+ uint8_t peer_cid_len; /*!< The length of
+ * \c peer_cid. */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
struct
{
size_t total_bytes_buffered; /*!< Cumulative size of heap allocated
@@ -373,19 +469,27 @@
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ psa_hash_operation_t fin_sha256_psa;
+#else
mbedtls_sha256_context fin_sha256;
#endif
+#endif
#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ psa_hash_operation_t fin_sha384_psa;
+#else
mbedtls_sha512_context fin_sha512;
#endif
+#endif
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t);
- void (*calc_verify)(mbedtls_ssl_context *, unsigned char *);
+ void (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *);
void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int);
- int (*tls_prf)(const unsigned char *, size_t, const char *,
- const unsigned char *, size_t,
- unsigned char *, size_t);
+ mbedtls_ssl_tls_prf_cb *tls_prf;
+
+ mbedtls_ssl_ciphersuite_t const *ciphersuite_info;
size_t pmslen; /*!< premaster length */
@@ -422,25 +526,116 @@
typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer;
/*
- * This structure contains a full set of runtime transform parameters
- * either in negotiation or active.
+ * Representation of decryption/encryption transformations on records
+ *
+ * There are the following general types of record transformations:
+ * - Stream transformations (TLS versions <= 1.2 only)
+ * Transformation adding a MAC and applying a stream-cipher
+ * to the authenticated message.
+ * - CBC block cipher transformations ([D]TLS versions <= 1.2 only)
+ * In addition to the distinction of the order of encryption and
+ * authentication, there's a fundamental difference between the
+ * handling in SSL3 & TLS 1.0 and TLS 1.1 and TLS 1.2: For SSL3
+ * and TLS 1.0, the final IV after processing a record is used
+ * as the IV for the next record. No explicit IV is contained
+ * in an encrypted record. The IV for the first record is extracted
+ * at key extraction time. In contrast, for TLS 1.1 and 1.2, no
+ * IV is generated at key extraction time, but every encrypted
+ * record is explicitly prefixed by the IV with which it was encrypted.
+ * - AEAD transformations ([D]TLS versions >= 1.2 only)
+ * These come in two fundamentally different versions, the first one
+ * used in TLS 1.2, excluding ChaChaPoly ciphersuites, and the second
+ * one used for ChaChaPoly ciphersuites in TLS 1.2 as well as for TLS 1.3.
+ * In the first transformation, the IV to be used for a record is obtained
+ * as the concatenation of an explicit, static 4-byte IV and the 8-byte
+ * record sequence number, and explicitly prepending this sequence number
+ * to the encrypted record. In contrast, in the second transformation
+ * the IV is obtained by XOR'ing a static IV obtained at key extraction
+ * time with the 8-byte record sequence number, without prepending the
+ * latter to the encrypted record.
+ *
+ * In addition to type and version, the following parameters are relevant:
+ * - The symmetric cipher algorithm to be used.
+ * - The (static) encryption/decryption keys for the cipher.
+ * - For stream/CBC, the type of message digest to be used.
+ * - For stream/CBC, (static) encryption/decryption keys for the digest.
+ * - For AEAD transformations, the size (potentially 0) of an explicit,
+ * random initialization vector placed in encrypted records.
+ * - For some transformations (currently AEAD and CBC in SSL3 and TLS 1.0)
+ * an implicit IV. It may be static (e.g. AEAD) or dynamic (e.g. CBC)
+ * and (if present) is combined with the explicit IV in a transformation-
+ * dependent way (e.g. appending in TLS 1.2 and XOR'ing in TLS 1.3).
+ * - For stream/CBC, a flag determining the order of encryption and MAC.
+ * - The details of the transformation depend on the SSL/TLS version.
+ * - The length of the authentication tag.
+ *
+ * Note: Except for CBC in SSL3 and TLS 1.0, these parameters are
+ * constant across multiple encryption/decryption operations.
+ * For CBC, the implicit IV needs to be updated after each
+ * operation.
+ *
+ * The struct below refines this abstract view as follows:
+ * - The cipher underlying the transformation is managed in
+ * cipher contexts cipher_ctx_{enc/dec}, which must have the
+ * same cipher type. The mode of these cipher contexts determines
+ * the type of the transformation in the sense above: e.g., if
+ * the type is MBEDTLS_CIPHER_AES_256_CBC resp. MBEDTLS_CIPHER_AES_192_GCM
+ * then the transformation has type CBC resp. AEAD.
+ * - The cipher keys are never stored explicitly but
+ * are maintained within cipher_ctx_{enc/dec}.
+ * - For stream/CBC transformations, the message digest contexts
+ * used for the MAC's are stored in md_ctx_{enc/dec}. These contexts
+ * are unused for AEAD transformations.
+ * - For stream/CBC transformations and versions > SSL3, the
+ * MAC keys are not stored explicitly but maintained within
+ * md_ctx_{enc/dec}.
+ * - For stream/CBC transformations and version SSL3, the MAC
+ * keys are stored explicitly in mac_enc, mac_dec and have
+ * a fixed size of 20 bytes. These fields are unused for
+ * AEAD transformations or transformations >= TLS 1.0.
+ * - For transformations using an implicit IV maintained within
+ * the transformation context, its contents are stored within
+ * iv_{enc/dec}.
+ * - The value of ivlen indicates the length of the IV.
+ * This is redundant in case of stream/CBC transformations
+ * which always use 0 resp. the cipher's block length as the
+ * IV length, but is needed for AEAD ciphers and may be
+ * different from the underlying cipher's block length
+ * in this case.
+ * - The field fixed_ivlen is nonzero for AEAD transformations only
+ * and indicates the length of the static part of the IV which is
+ * constant throughout the communication, and which is stored in
+ * the first fixed_ivlen bytes of the iv_{enc/dec} arrays.
+ * Note: For CBC in SSL3 and TLS 1.0, the fields iv_{enc/dec}
+ * still store IV's for continued use across multiple transformations,
+ * so it is not true that fixed_ivlen == 0 means that iv_{enc/dec} are
+ * not being used!
+ * - minor_ver denotes the SSL/TLS version
+ * - For stream/CBC transformations, maclen denotes the length of the
+ * authentication tag, while taglen is unused and 0.
+ * - For AEAD transformations, taglen denotes the length of the
+ * authentication tag, while maclen is unused and 0.
+ * - For CBC transformations, encrypt_then_mac determines the
+ * order of encryption and authentication. This field is unused
+ * in other transformations.
+ *
*/
struct mbedtls_ssl_transform
{
/*
* Session specific crypto layer
*/
- const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
- /*!< Chosen cipersuite_info */
- unsigned int keylen; /*!< symmetric key length (bytes) */
size_t minlen; /*!< min. ciphertext length */
size_t ivlen; /*!< IV length */
size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */
- size_t maclen; /*!< MAC length */
+ size_t maclen; /*!< MAC(CBC) len */
+ size_t taglen; /*!< TAG(AEAD) len */
unsigned char iv_enc[16]; /*!< IV (encryption) */
unsigned char iv_dec[16]; /*!< IV (decryption) */
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
+
#if defined(MBEDTLS_SSL_PROTO_SSL3)
/* Needed only for SSL v3.0 secret */
unsigned char mac_enc[20]; /*!< SSL v3.0 secret (enc) */
@@ -450,8 +645,22 @@
mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */
mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+ int encrypt_then_mac; /*!< flag for EtM activation */
+#endif
+
+#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
+
mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */
mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */
+ int minor_ver;
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ uint8_t in_cid_len;
+ uint8_t out_cid_len;
+ unsigned char in_cid [ MBEDTLS_SSL_CID_OUT_LEN_MAX ];
+ unsigned char out_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ];
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
/*
* Session specific compression layer
@@ -460,8 +669,83 @@
z_stream ctx_deflate; /*!< compression context */
z_stream ctx_inflate; /*!< decompression context */
#endif
+
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+ /* We need the Hello random bytes in order to re-derive keys from the
+ * Master Secret and other session info, see ssl_populate_transform() */
+ unsigned char randbytes[64]; /*!< ServerHello.random+ClientHello.random */
+#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
};
+/*
+ * Return 1 if the transform uses an AEAD cipher, 0 otherwise.
+ * Equivalently, return 0 if a separate MAC is used, 1 otherwise.
+ */
+static inline int mbedtls_ssl_transform_uses_aead(
+ const mbedtls_ssl_transform *transform )
+{
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
+ return( transform->maclen == 0 && transform->taglen != 0 );
+#else
+ (void) transform;
+ return( 1 );
+#endif
+}
+
+/*
+ * Internal representation of record frames
+ *
+ * Instances come in two flavors:
+ * (1) Encrypted
+ * These always have data_offset = 0
+ * (2) Unencrypted
+ * These have data_offset set to the amount of
+ * pre-expansion during record protection. Concretely,
+ * this is the length of the fixed part of the explicit IV
+ * used for encryption, or 0 if no explicit IV is used
+ * (e.g. for CBC in TLS 1.0, or stream ciphers).
+ *
+ * The reason for the data_offset in the unencrypted case
+ * is to allow for in-place conversion of an unencrypted to
+ * an encrypted record. If the offset wasn't included, the
+ * encrypted content would need to be shifted afterwards to
+ * make space for the fixed IV.
+ *
+ */
+#if MBEDTLS_SSL_CID_OUT_LEN_MAX > MBEDTLS_SSL_CID_IN_LEN_MAX
+#define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_OUT_LEN_MAX
+#else
+#define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_IN_LEN_MAX
+#endif
+
+typedef struct
+{
+ uint8_t ctr[8]; /* In TLS: The implicit record sequence number.
+ * In DTLS: The 2-byte epoch followed by
+ * the 6-byte sequence number.
+ * This is stored as a raw big endian byte array
+ * as opposed to a uint64_t because we rarely
+ * need to perform arithmetic on this, but do
+ * need it as a Byte array for the purpose of
+ * MAC computations. */
+ uint8_t type; /* The record content type. */
+ uint8_t ver[2]; /* SSL/TLS version as present on the wire.
+ * Convert to internal presentation of versions
+ * using mbedtls_ssl_read_version() and
+ * mbedtls_ssl_write_version().
+ * Keep wire-format for MAC computations. */
+
+ unsigned char *buf; /* Memory buffer enclosing the record content */
+ size_t buf_len; /* Buffer length */
+ size_t data_offset; /* Offset of record content */
+ size_t data_len; /* Length of record content */
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ uint8_t cid_len; /* Length of the CID (0 if not present) */
+ unsigned char cid[ MBEDTLS_SSL_CID_LEN_MAX ]; /* The CID */
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+} mbedtls_record;
+
#if defined(MBEDTLS_X509_CRT_PARSE_C)
/*
* List of certificate + private key pairs
@@ -488,7 +772,7 @@
#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,
@@ -508,7 +792,7 @@
}
#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
@@ -635,7 +919,7 @@
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
@@ -653,7 +937,7 @@
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
@@ -703,15 +987,27 @@
void mbedtls_ssl_read_version( int *major, int *minor, int transport,
const unsigned char ver[2] );
-static inline size_t mbedtls_ssl_hdr_len( const mbedtls_ssl_context *ssl )
+static inline size_t mbedtls_ssl_in_hdr_len( const mbedtls_ssl_context *ssl )
{
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- return( 13 );
-#else
+#if !defined(MBEDTLS_SSL_PROTO_DTLS)
((void) ssl);
#endif
- return( 5 );
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ return( 13 );
+ }
+ else
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+ {
+ return( 5 );
+ }
+}
+
+static inline size_t mbedtls_ssl_out_hdr_len( const mbedtls_ssl_context *ssl )
+{
+ return( (size_t) ( ssl->out_iv - ssl->out_hdr ) );
}
static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl )
@@ -734,10 +1030,13 @@
/* Visible for testing purposes only */
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl );
+int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl );
void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl );
#endif
+int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst,
+ const mbedtls_ssl_session *src );
+
/* constant-time buffer comparison */
static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t n )
{
@@ -768,6 +1067,7 @@
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_2)
+/* The hash buffer must have at least MBEDTLS_MD_MAX_SIZE bytes of length. */
int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
unsigned char *hash, size_t *hashlen,
unsigned char *data, size_t data_len,
@@ -779,4 +1079,56 @@
}
#endif
+void mbedtls_ssl_transform_init( mbedtls_ssl_transform *transform );
+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_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/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h
index 54a4fae..6e13444 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h
@@ -25,7 +25,7 @@
#define MBEDTLS_SSL_TICKET_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
@@ -36,11 +36,11 @@
* secrecy, when MBEDTLS_HAVE_TIME is defined.
*/
-#include "ssl.h"
-#include "cipher.h"
+#include "mbedtls/ssl.h"
+#include "mbedtls/cipher.h"
#if defined(MBEDTLS_THREADING_C)
-#include "threading.h"
+#include "mbedtls/threading.h"
#endif
#ifdef __cplusplus
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/threading.h b/lib/libmbedtls/mbedtls/include/mbedtls/threading.h
index ceb712a..555c36b 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/threading.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/threading.h
@@ -25,7 +25,7 @@
#define MBEDTLS_THREADING_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/timing.h b/lib/libmbedtls/mbedtls/include/mbedtls/timing.h
index 339279a..2f22929 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/timing.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/timing.h
@@ -25,7 +25,7 @@
#define MBEDTLS_TIMING_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/version.h b/lib/libmbedtls/mbedtls/include/mbedtls/version.h
index ee67353..250b291 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/version.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/version.h
@@ -29,7 +29,7 @@
#define MBEDTLS_VERSION_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
@@ -39,17 +39,17 @@
* Major, Minor, Patchlevel
*/
#define MBEDTLS_VERSION_MAJOR 2
-#define MBEDTLS_VERSION_MINOR 16
-#define MBEDTLS_VERSION_PATCH 5
+#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 0x02100500
-#define MBEDTLS_VERSION_STRING "2.16.5"
-#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.5"
+#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/lib/libmbedtls/mbedtls/include/mbedtls/x509.h b/lib/libmbedtls/mbedtls/include/mbedtls/x509.h
index 9649402..752516d 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/x509.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/x509.h
@@ -25,16 +25,16 @@
#define MBEDTLS_X509_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "asn1.h"
-#include "pk.h"
+#include "mbedtls/asn1.h"
+#include "mbedtls/pk.h"
#if defined(MBEDTLS_RSA_C)
-#include "rsa.h"
+#include "mbedtls/rsa.h"
#endif
/**
@@ -110,6 +110,28 @@
/* \} addtogroup x509_module */
/*
+ * X.509 v3 Subject Alternative Name types.
+ * otherName [0] OtherName,
+ * rfc822Name [1] IA5String,
+ * dNSName [2] IA5String,
+ * x400Address [3] ORAddress,
+ * directoryName [4] Name,
+ * ediPartyName [5] EDIPartyName,
+ * uniformResourceIdentifier [6] IA5String,
+ * iPAddress [7] OCTET STRING,
+ * registeredID [8] OBJECT IDENTIFIER
+ */
+#define MBEDTLS_X509_SAN_OTHER_NAME 0
+#define MBEDTLS_X509_SAN_RFC822_NAME 1
+#define MBEDTLS_X509_SAN_DNS_NAME 2
+#define MBEDTLS_X509_SAN_X400_ADDRESS_NAME 3
+#define MBEDTLS_X509_SAN_DIRECTORY_NAME 4
+#define MBEDTLS_X509_SAN_EDI_PARTY_NAME 5
+#define MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER 6
+#define MBEDTLS_X509_SAN_IP_ADDRESS 7
+#define MBEDTLS_X509_SAN_REGISTERED_ID 8
+
+/*
* X.509 v3 Key Usage Extension flags
* Reminder: update x509_info_key_usage() when adding new flags.
*/
@@ -142,24 +164,26 @@
*
* Comments refer to the status for using certificates. Status can be
* different for writing certificates or reading CRLs or CSRs.
+ *
+ * Those are defined in oid.h as oid.c needs them in a data structure. Since
+ * these were previously defined here, let's have aliases for compatibility.
*/
-#define MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0)
-#define MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1)
-#define MBEDTLS_X509_EXT_KEY_USAGE (1 << 2)
-#define MBEDTLS_X509_EXT_CERTIFICATE_POLICIES (1 << 3)
-#define MBEDTLS_X509_EXT_POLICY_MAPPINGS (1 << 4)
-#define MBEDTLS_X509_EXT_SUBJECT_ALT_NAME (1 << 5) /* Supported (DNS) */
-#define MBEDTLS_X509_EXT_ISSUER_ALT_NAME (1 << 6)
-#define MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7)
-#define MBEDTLS_X509_EXT_BASIC_CONSTRAINTS (1 << 8) /* Supported */
-#define MBEDTLS_X509_EXT_NAME_CONSTRAINTS (1 << 9)
-#define MBEDTLS_X509_EXT_POLICY_CONSTRAINTS (1 << 10)
-#define MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE (1 << 11)
-#define MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12)
-#define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13)
-#define MBEDTLS_X509_EXT_FRESHEST_CRL (1 << 14)
-
-#define MBEDTLS_X509_EXT_NS_CERT_TYPE (1 << 16)
+#define MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER
+#define MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER
+#define MBEDTLS_X509_EXT_KEY_USAGE MBEDTLS_OID_X509_EXT_KEY_USAGE
+#define MBEDTLS_X509_EXT_CERTIFICATE_POLICIES MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES
+#define MBEDTLS_X509_EXT_POLICY_MAPPINGS MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS
+#define MBEDTLS_X509_EXT_SUBJECT_ALT_NAME MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME /* Supported (DNS) */
+#define MBEDTLS_X509_EXT_ISSUER_ALT_NAME MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME
+#define MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS
+#define MBEDTLS_X509_EXT_BASIC_CONSTRAINTS MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS /* Supported */
+#define MBEDTLS_X509_EXT_NAME_CONSTRAINTS MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS
+#define MBEDTLS_X509_EXT_POLICY_CONSTRAINTS MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS
+#define MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE
+#define MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS
+#define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY
+#define MBEDTLS_X509_EXT_FRESHEST_CRL MBEDTLS_OID_X509_EXT_FRESHEST_CRL
+#define MBEDTLS_X509_EXT_NS_CERT_TYPE MBEDTLS_OID_X509_EXT_NS_CERT_TYPE
/*
* Storage format identifiers
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h b/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h
index 6990881..3ec874e 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h
@@ -25,12 +25,12 @@
#define MBEDTLS_X509_CRL_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "x509.h"
+#include "mbedtls/x509.h"
#ifdef __cplusplus
extern "C" {
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h b/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h
index 3d77d03..9d52665 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h
@@ -25,13 +25,14 @@
#define MBEDTLS_X509_CRT_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "x509.h"
-#include "x509_crl.h"
+#include "mbedtls/x509.h"
+#include "mbedtls/x509_crl.h"
+#include "mbedtls/bignum.h"
/**
* \addtogroup x509_module
@@ -52,6 +53,8 @@
*/
typedef struct mbedtls_x509_crt
{
+ int own_buffer; /**< Indicates if \c raw is owned
+ * by the structure or not. */
mbedtls_x509_buf raw; /**< The raw certificate data (DER). */
mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */
@@ -68,12 +71,15 @@
mbedtls_x509_time valid_from; /**< Start time of certificate validity. */
mbedtls_x509_time valid_to; /**< End time of certificate validity. */
+ mbedtls_x509_buf pk_raw;
mbedtls_pk_context pk; /**< Container for the public key context. */
mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */
mbedtls_x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */
mbedtls_x509_buf v3_ext; /**< Optional X.509 v3 extensions. */
- mbedtls_x509_sequence subject_alt_names; /**< Optional list of Subject Alternative Names (Only dNSName supported). */
+ mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension (currently only dNSName and OtherName are listed). */
+
+ mbedtls_x509_sequence certificate_policies; /**< Optional list of certificate policies (Only anyPolicy is printed and enforced, however the rest of the policies are still listed). */
int ext_types; /**< Bit string containing detected and parsed extensions */
int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */
@@ -95,6 +101,53 @@
mbedtls_x509_crt;
/**
+ * From RFC 5280 section 4.2.1.6:
+ * OtherName ::= SEQUENCE {
+ * type-id OBJECT IDENTIFIER,
+ * value [0] EXPLICIT ANY DEFINED BY type-id }
+ */
+typedef struct mbedtls_x509_san_other_name
+{
+ /**
+ * The type_id is an OID as deifned in RFC 5280.
+ * To check the value of the type id, you should use
+ * \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf.
+ */
+ mbedtls_x509_buf type_id; /**< The type id. */
+ union
+ {
+ /**
+ * From RFC 4108 section 5:
+ * HardwareModuleName ::= SEQUENCE {
+ * hwType OBJECT IDENTIFIER,
+ * hwSerialNum OCTET STRING }
+ */
+ struct
+ {
+ mbedtls_x509_buf oid; /**< The object identifier. */
+ mbedtls_x509_buf val; /**< The named value. */
+ }
+ hardware_module_name;
+ }
+ value;
+}
+mbedtls_x509_san_other_name;
+
+/**
+ * A structure for holding the parsed Subject Alternative Name, according to type
+ */
+typedef struct mbedtls_x509_subject_alternative_name
+{
+ int type; /**< The SAN type, value of MBEDTLS_X509_SAN_XXX. */
+ union {
+ mbedtls_x509_san_other_name other_name; /**< The otherName supported type. */
+ mbedtls_x509_buf unstructured_name; /**< The buffer for the un constructed types. Only dnsName currently supported */
+ }
+ san; /**< A union of the supported SAN types */
+}
+mbedtls_x509_subject_alternative_name;
+
+/**
* Build flag from an algorithm/curve identifier (pk, md, ecp)
* Since 0 is always XXX_NONE, ignore it.
*/
@@ -163,6 +216,14 @@
{
mbedtls_x509_crt_verify_chain_item items[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE];
unsigned len;
+
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+ /* This stores the list of potential trusted signers obtained from
+ * the CA callback used for the CRT verification, if configured.
+ * We must track it somewhere because the callback passes its
+ * ownership to the caller. */
+ mbedtls_x509_crt *trust_ca_cb_result;
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
} mbedtls_x509_crt_verify_chain;
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
@@ -220,16 +281,58 @@
/**
* \brief Parse a single DER formatted certificate and add it
- * to the chained list.
+ * to the end of the provided chained list.
*
- * \param chain points to the start of the chain
- * \param buf buffer holding the certificate DER data
- * \param buflen size of the buffer
+ * \param chain The pointer to the start of the CRT chain to attach to.
+ * When parsing the first CRT in a chain, this should point
+ * to an instance of ::mbedtls_x509_crt initialized through
+ * mbedtls_x509_crt_init().
+ * \param buf The buffer holding the DER encoded certificate.
+ * \param buflen The size in Bytes of \p buf.
*
- * \return 0 if successful, or a specific X509 or PEM error code
+ * \note This function makes an internal copy of the CRT buffer
+ * \p buf. In particular, \p buf may be destroyed or reused
+ * after this call returns. To avoid duplicating the CRT
+ * buffer (at the cost of stricter lifetime constraints),
+ * use mbedtls_x509_crt_parse_der_nocopy() instead.
+ *
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
*/
-int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf,
- size_t buflen );
+int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain,
+ const unsigned char *buf,
+ size_t buflen );
+
+/**
+ * \brief Parse a single DER formatted certificate and add it
+ * to the end of the provided chained list. This is a
+ * variant of mbedtls_x509_crt_parse_der() which takes
+ * temporary ownership of the CRT buffer until the CRT
+ * is destroyed.
+ *
+ * \param chain The pointer to the start of the CRT chain to attach to.
+ * When parsing the first CRT in a chain, this should point
+ * to an instance of ::mbedtls_x509_crt initialized through
+ * mbedtls_x509_crt_init().
+ * \param buf The address of the readable buffer holding the DER encoded
+ * certificate to use. On success, this buffer must be
+ * retained and not be changed for the liftetime of the
+ * CRT chain \p chain, that is, until \p chain is destroyed
+ * through a call to mbedtls_x509_crt_free().
+ * \param buflen The size in Bytes of \p buf.
+ *
+ * \note This call is functionally equivalent to
+ * mbedtls_x509_crt_parse_der(), but it avoids creating a
+ * copy of the input buffer at the cost of stronger lifetime
+ * constraints. This is useful in constrained environments
+ * where duplication of the CRT cannot be tolerated.
+ *
+ * \return \c 0 if successful.
+ * \return A negative error code on failure.
+ */
+int mbedtls_x509_crt_parse_der_nocopy( mbedtls_x509_crt *chain,
+ const unsigned char *buf,
+ size_t buflen );
/**
* \brief Parse one DER-encoded or one or more concatenated PEM-encoded
@@ -293,8 +396,37 @@
* if partly successful or a specific X509 or PEM error code
*/
int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path );
-#endif /* MBEDTLS_FS_IO */
+#endif /* MBEDTLS_FS_IO */
+/**
+ * \brief This function parses an item in the SubjectAlternativeNames
+ * extension.
+ *
+ * \param san_buf The buffer holding the raw data item of the subject
+ * alternative name.
+ * \param san The target structure to populate with the parsed presentation
+ * of the subject alternative name encoded in \p san_raw.
+ *
+ * \note Only "dnsName" and "otherName" of type hardware_module_name
+ * as defined in RFC 4180 is supported.
+ *
+ * \note This function should be called on a single raw data of
+ * subject alternative name. For example, after successful
+ * certificate parsing, one must iterate on every item in the
+ * \p crt->subject_alt_names sequence, and pass it to
+ * this function.
+ *
+ * \warning The target structure contains pointers to the raw data of the
+ * parsed certificate, and its lifetime is restricted by the
+ * lifetime of the certificate.
+ *
+ * \return \c 0 on success
+ * \return #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported
+ * SAN type.
+ * \return Another negative value for any other failure.
+ */
+int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf,
+ mbedtls_x509_subject_alternative_name *san );
/**
* \brief Returns an informational string about the
* certificate.
@@ -326,7 +458,7 @@
uint32_t flags );
/**
- * \brief Verify the certificate signature
+ * \brief Verify a chain of certificates.
*
* The verify callback is a user-supplied callback that
* can clear / modify / add flags for a certificate. If set,
@@ -366,22 +498,27 @@
* specific peers you know) - in that case, the self-signed
* certificate doesn't need to have the CA bit set.
*
- * \param crt a certificate (chain) to be verified
- * \param trust_ca the list of trusted CAs (see note above)
- * \param ca_crl the list of CRLs for trusted CAs (see note above)
- * \param cn expected Common Name (can be set to
- * NULL if the CN must not be verified)
- * \param flags result of the verification
- * \param f_vrfy verification function
- * \param p_vrfy verification parameter
+ * \param crt The certificate chain to be verified.
+ * \param trust_ca The list of trusted CAs.
+ * \param ca_crl The list of CRLs for trusted CAs.
+ * \param cn The expected Common Name. This may be \c NULL if the
+ * CN need not be verified.
+ * \param flags The address at which to store the result of the verification.
+ * If the verification couldn't be completed, the flag value is
+ * set to (uint32_t) -1.
+ * \param f_vrfy The verification callback to use. See the documentation
+ * of mbedtls_x509_crt_verify() for more information.
+ * \param p_vrfy The context to be passed to \p f_vrfy.
*
- * \return 0 (and flags set to 0) if the chain was verified and valid,
- * MBEDTLS_ERR_X509_CERT_VERIFY_FAILED if the chain was verified
- * but found to be invalid, in which case *flags will have one
- * or more MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX
- * flags set, or another error (and flags set to 0xffffffff)
- * in case of a fatal error encountered during the
- * verification process.
+ * \return \c 0 if the chain is valid with respect to the
+ * passed CN, CAs, CRLs and security profile.
+ * \return #MBEDTLS_ERR_X509_CERT_VERIFY_FAILED in case the
+ * certificate chain verification failed. In this case,
+ * \c *flags will have one or more
+ * \c MBEDTLS_X509_BADCERT_XXX or \c MBEDTLS_X509_BADCRL_XXX
+ * flags set.
+ * \return Another negative error code in case of a fatal error
+ * encountered during the verification process.
*/
int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
mbedtls_x509_crt *trust_ca,
@@ -391,7 +528,8 @@
void *p_vrfy );
/**
- * \brief Verify the certificate signature according to profile
+ * \brief Verify a chain of certificates with respect to
+ * a configurable security profile.
*
* \note Same as \c mbedtls_x509_crt_verify(), but with explicit
* security profile.
@@ -400,22 +538,28 @@
* for ECDSA) apply to all certificates: trusted root,
* intermediate CAs if any, and end entity certificate.
*
- * \param crt a certificate (chain) to be verified
- * \param trust_ca the list of trusted CAs
- * \param ca_crl the list of CRLs for trusted CAs
- * \param profile security profile for verification
- * \param cn expected Common Name (can be set to
- * NULL if the CN must not be verified)
- * \param flags result of the verification
- * \param f_vrfy verification function
- * \param p_vrfy verification parameter
+ * \param crt The certificate chain to be verified.
+ * \param trust_ca The list of trusted CAs.
+ * \param ca_crl The list of CRLs for trusted CAs.
+ * \param profile The security profile to use for the verification.
+ * \param cn The expected Common Name. This may be \c NULL if the
+ * CN need not be verified.
+ * \param flags The address at which to store the result of the verification.
+ * If the verification couldn't be completed, the flag value is
+ * set to (uint32_t) -1.
+ * \param f_vrfy The verification callback to use. See the documentation
+ * of mbedtls_x509_crt_verify() for more information.
+ * \param p_vrfy The context to be passed to \p f_vrfy.
*
- * \return 0 if successful or MBEDTLS_ERR_X509_CERT_VERIFY_FAILED
- * in which case *flags will have one or more
- * MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX flags
- * set,
- * or another error in case of a fatal error encountered
- * during the verification process.
+ * \return \c 0 if the chain is valid with respect to the
+ * passed CN, CAs, CRLs and security profile.
+ * \return #MBEDTLS_ERR_X509_CERT_VERIFY_FAILED in case the
+ * certificate chain verification failed. In this case,
+ * \c *flags will have one or more
+ * \c MBEDTLS_X509_BADCERT_XXX or \c MBEDTLS_X509_BADCRL_XXX
+ * flags set.
+ * \return Another negative error code in case of a fatal error
+ * encountered during the verification process.
*/
int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
mbedtls_x509_crt *trust_ca,
@@ -432,16 +576,20 @@
* but can return early and restart according to the limit
* set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
*
- * \param crt a certificate (chain) to be verified
- * \param trust_ca the list of trusted CAs
- * \param ca_crl the list of CRLs for trusted CAs
- * \param profile security profile for verification
- * \param cn expected Common Name (can be set to
- * NULL if the CN must not be verified)
- * \param flags result of the verification
- * \param f_vrfy verification function
- * \param p_vrfy verification parameter
- * \param rs_ctx restart context (NULL to disable restart)
+ * \param crt The certificate chain to be verified.
+ * \param trust_ca The list of trusted CAs.
+ * \param ca_crl The list of CRLs for trusted CAs.
+ * \param profile The security profile to use for the verification.
+ * \param cn The expected Common Name. This may be \c NULL if the
+ * CN need not be verified.
+ * \param flags The address at which to store the result of the verification.
+ * If the verification couldn't be completed, the flag value is
+ * set to (uint32_t) -1.
+ * \param f_vrfy The verification callback to use. See the documentation
+ * of mbedtls_x509_crt_verify() for more information.
+ * \param p_vrfy The context to be passed to \p f_vrfy.
+ * \param rs_ctx The restart context to use. This may be set to \c NULL
+ * to disable restartable ECC.
*
* \return See \c mbedtls_crt_verify_with_profile(), or
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
@@ -456,6 +604,73 @@
void *p_vrfy,
mbedtls_x509_crt_restart_ctx *rs_ctx );
+/**
+ * \brief The type of trusted certificate callbacks.
+ *
+ * Callbacks of this type are passed to and used by the CRT
+ * verification routine mbedtls_x509_crt_verify_with_ca_cb()
+ * when looking for trusted signers of a given certificate.
+ *
+ * On success, the callback returns a list of trusted
+ * certificates to be considered as potential signers
+ * for the input certificate.
+ *
+ * \param p_ctx An opaque context passed to the callback.
+ * \param child The certificate for which to search a potential signer.
+ * This will point to a readable certificate.
+ * \param candidate_cas The address at which to store the address of the first
+ * entry in the generated linked list of candidate signers.
+ * This will not be \c NULL.
+ *
+ * \note The callback must only return a non-zero value on a
+ * fatal error. If, in contrast, the search for a potential
+ * signer completes without a single candidate, the
+ * callback must return \c 0 and set \c *candidate_cas
+ * to \c NULL.
+ *
+ * \return \c 0 on success. In this case, \c *candidate_cas points
+ * to a heap-allocated linked list of instances of
+ * ::mbedtls_x509_crt, and ownership of this list is passed
+ * to the caller.
+ * \return A negative error code on failure.
+ */
+typedef int (*mbedtls_x509_crt_ca_cb_t)( void *p_ctx,
+ mbedtls_x509_crt const *child,
+ mbedtls_x509_crt **candidate_cas );
+
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+/**
+ * \brief Version of \c mbedtls_x509_crt_verify_with_profile() which
+ * uses a callback to acquire the list of trusted CA
+ * certificates.
+ *
+ * \param crt The certificate chain to be verified.
+ * \param f_ca_cb The callback to be used to query for potential signers
+ * of a given child certificate. See the documentation of
+ * ::mbedtls_x509_crt_ca_cb_t for more information.
+ * \param p_ca_cb The opaque context to be passed to \p f_ca_cb.
+ * \param profile The security profile for the verification.
+ * \param cn The expected Common Name. This may be \c NULL if the
+ * CN need not be verified.
+ * \param flags The address at which to store the result of the verification.
+ * If the verification couldn't be completed, the flag value is
+ * set to (uint32_t) -1.
+ * \param f_vrfy The verification callback to use. See the documentation
+ * of mbedtls_x509_crt_verify() for more information.
+ * \param p_vrfy The context to be passed to \p f_vrfy.
+ *
+ * \return See \c mbedtls_crt_verify_with_profile().
+ */
+int mbedtls_x509_crt_verify_with_ca_cb( mbedtls_x509_crt *crt,
+ mbedtls_x509_crt_ca_cb_t f_ca_cb,
+ void *p_ca_cb,
+ const mbedtls_x509_crt_profile *profile,
+ const char *cn, uint32_t *flags,
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+ void *p_vrfy );
+
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
+
#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
/**
* \brief Check usage of certificate against keyUsage extension.
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h b/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h
index 87205e4..c5a7cad 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h
@@ -25,12 +25,12 @@
#define MBEDTLS_X509_CSR_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
-#include "x509.h"
+#include "mbedtls/x509.h"
#ifdef __cplusplus
extern "C" {
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/xtea.h b/lib/libmbedtls/mbedtls/include/mbedtls/xtea.h
index 78417a1..b607547 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/xtea.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/xtea.h
@@ -25,7 +25,7 @@
#define MBEDTLS_XTEA_H
#if !defined(MBEDTLS_CONFIG_FILE)
-#include "config.h"
+#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
diff --git a/lib/libmbedtls/mbedtls/library/aes.c b/lib/libmbedtls/mbedtls/library/aes.c
index 4df987a..c6a45f3 100644
--- a/lib/libmbedtls/mbedtls/library/aes.c
+++ b/lib/libmbedtls/mbedtls/library/aes.c
@@ -38,6 +38,7 @@
#include "mbedtls/aes.h"
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#if defined(MBEDTLS_PADLOCK_C)
#include "mbedtls/padlock.h"
#endif
@@ -766,7 +767,7 @@
const unsigned char *key,
unsigned int keybits)
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
@@ -791,7 +792,7 @@
const unsigned char *key,
unsigned int keybits)
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
@@ -1199,7 +1200,7 @@
const unsigned char *input,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t blocks = length / 16;
size_t leftover = length % 16;
unsigned char tweak[16];
diff --git a/lib/libmbedtls/mbedtls/library/asn1parse.c b/lib/libmbedtls/mbedtls/library/asn1parse.c
index 3ad77a1..cb15b97 100644
--- a/lib/libmbedtls/mbedtls/library/asn1parse.c
+++ b/lib/libmbedtls/mbedtls/library/asn1parse.c
@@ -29,6 +29,7 @@
#include "mbedtls/asn1.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -124,7 +125,7 @@
const unsigned char *end,
int *val )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 )
@@ -139,21 +140,41 @@
return( 0 );
}
-int mbedtls_asn1_get_int( unsigned char **p,
- const unsigned char *end,
- int *val )
+static int asn1_get_tagged_int( unsigned char **p,
+ const unsigned char *end,
+ int tag, int *val )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
- if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
+ if( ( ret = mbedtls_asn1_get_tag( p, end, &len, tag ) ) != 0 )
return( ret );
- if( len == 0 || len > sizeof( int ) || ( **p & 0x80 ) != 0 )
+ /*
+ * len==0 is malformed (0 must be represented as 020100 for INTEGER,
+ * or 0A0100 for ENUMERATED tags
+ */
+ if( len == 0 )
+ return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+ /* This is a cryptography library. Reject negative integers. */
+ if( ( **p & 0x80 ) != 0 )
+ return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+
+ /* Skip leading zeros. */
+ while( len > 0 && **p == 0 )
+ {
+ ++( *p );
+ --len;
+ }
+
+ /* Reject integers that don't fit in an int. This code assumes that
+ * the int type has no padding bit. */
+ if( len > sizeof( int ) )
+ return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
+ if( len == sizeof( int ) && ( **p & 0x80 ) != 0 )
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
*val = 0;
-
while( len-- > 0 )
{
*val = ( *val << 8 ) | **p;
@@ -163,12 +184,26 @@
return( 0 );
}
+int mbedtls_asn1_get_int( unsigned char **p,
+ const unsigned char *end,
+ int *val )
+{
+ return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_INTEGER, val) );
+}
+
+int mbedtls_asn1_get_enum( unsigned char **p,
+ const unsigned char *end,
+ int *val )
+{
+ return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_ENUMERATED, val) );
+}
+
#if defined(MBEDTLS_BIGNUM_C)
int mbedtls_asn1_get_mpi( unsigned char **p,
const unsigned char *end,
mbedtls_mpi *X )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
@@ -185,7 +220,7 @@
int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
mbedtls_asn1_bitstring *bs)
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* Certificate type is a single byte bitstring */
if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 )
@@ -213,23 +248,124 @@
}
/*
+ * Traverse an ASN.1 "SEQUENCE OF <tag>"
+ * 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
*/
int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
size_t *len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 )
return( ret );
- if( (*len)-- < 2 || *(*p)++ != 0 )
+ if( *len == 0 )
return( MBEDTLS_ERR_ASN1_INVALID_DATA );
+ --( *len );
+
+ if( **p != 0 )
+ return( MBEDTLS_ERR_ASN1_INVALID_DATA );
+ ++( *p );
return( 0 );
}
+void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq )
+{
+ while( seq != NULL )
+ {
+ mbedtls_asn1_sequence *next = seq->next;
+ mbedtls_platform_zeroize( seq, sizeof( *seq ) );
+ mbedtls_free( seq );
+ seq = next;
+ }
+}
+typedef struct
+{
+ int tag;
+ mbedtls_asn1_sequence *cur;
+} asn1_get_sequence_of_cb_ctx_t;
+
+static int asn1_get_sequence_of_cb( void *ctx,
+ int tag,
+ unsigned char *start,
+ size_t len )
+{
+ asn1_get_sequence_of_cb_ctx_t *cb_ctx =
+ (asn1_get_sequence_of_cb_ctx_t *) ctx;
+ mbedtls_asn1_sequence *cur =
+ cb_ctx->cur;
+
+ if( cur->buf.p != NULL )
+ {
+ cur->next =
+ mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
+
+ if( cur->next == NULL )
+ return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
+
+ cur = cur->next;
+ }
+
+ cur->buf.p = start;
+ cur->buf.len = len;
+ cur->buf.tag = tag;
+
+ cb_ctx->cur = cur;
+ return( 0 );
+}
/*
* Parses and splits an ASN.1 "SEQUENCE OF <tag>"
@@ -239,56 +375,18 @@
mbedtls_asn1_sequence *cur,
int tag)
{
- int ret;
- size_t len;
- mbedtls_asn1_buf *buf;
-
- /* Get main sequence tag */
- if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
- MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
- return( ret );
-
- if( *p + len != end )
- return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-
- while( *p < end )
- {
- buf = &(cur->buf);
- buf->tag = **p;
-
- if( ( ret = mbedtls_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
- return( ret );
-
- buf->p = *p;
- *p += buf->len;
-
- /* Allocate and assign next pointer */
- if( *p < end )
- {
- cur->next = (mbedtls_asn1_sequence*)mbedtls_calloc( 1,
- sizeof( mbedtls_asn1_sequence ) );
-
- if( cur->next == NULL )
- return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
-
- cur = cur->next;
- }
- }
-
- /* Set final sequence entry's next pointer to NULL */
- cur->next = NULL;
-
- if( *p != end )
- return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-
- return( 0 );
+ asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };
+ memset( cur, 0, sizeof( mbedtls_asn1_sequence ) );
+ return( mbedtls_asn1_traverse_sequence_of(
+ p, end, 0xFF, tag, 0, 0,
+ asn1_get_sequence_of_cb, &cb_ctx ) );
}
int mbedtls_asn1_get_alg( unsigned char **p,
const unsigned char *end,
mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
@@ -332,7 +430,7 @@
const unsigned char *end,
mbedtls_asn1_buf *alg )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_asn1_buf params;
memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) );
diff --git a/lib/libmbedtls/mbedtls/library/asn1write.c b/lib/libmbedtls/mbedtls/library/asn1write.c
index aba3675..43d1321 100644
--- a/lib/libmbedtls/mbedtls/library/asn1write.c
+++ b/lib/libmbedtls/mbedtls/library/asn1write.c
@@ -28,6 +28,7 @@
#if defined(MBEDTLS_ASN1_WRITE_C)
#include "mbedtls/asn1write.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -131,7 +132,7 @@
#if defined(MBEDTLS_BIGNUM_C)
int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
// Write the MPI
@@ -168,7 +169,7 @@
int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
// Write NULL
@@ -182,7 +183,7 @@
int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start,
const char *oid, size_t oid_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
@@ -197,7 +198,7 @@
const char *oid, size_t oid_len,
size_t par_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
if( par_len == 0 )
@@ -216,7 +217,7 @@
int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
if( *p - start < 1 )
@@ -231,36 +232,49 @@
return( (int) len );
}
-int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
+static int asn1_write_tagged_int( unsigned char **p, unsigned char *start, int val, int tag )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
- if( *p - start < 1 )
- return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
-
- len += 1;
- *--(*p) = val;
-
- if( val > 0 && **p & 0x80 )
+ do
{
if( *p - start < 1 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+ len += 1;
+ *--(*p) = val & 0xff;
+ val >>= 8;
+ }
+ while( val > 0 );
+ if( **p & 0x80 )
+ {
+ if( *p - start < 1 )
+ return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = 0x00;
len += 1;
}
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
return( (int) len );
}
+int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
+{
+ return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_INTEGER ) );
+}
+
+int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val )
+{
+ return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_ENUMERATED ) );
+}
+
int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag,
const char *text, size_t text_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
@@ -290,10 +304,53 @@
return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) );
}
+int mbedtls_asn1_write_named_bitstring( unsigned char **p,
+ unsigned char *start,
+ const unsigned char *buf,
+ size_t bits )
+{
+ size_t unused_bits, byte_len;
+ const unsigned char *cur_byte;
+ unsigned char cur_byte_shifted;
+ unsigned char bit;
+
+ byte_len = ( bits + 7 ) / 8;
+ unused_bits = ( byte_len * 8 ) - bits;
+
+ /*
+ * Named bitstrings require that trailing 0s are excluded in the encoding
+ * of the bitstring. Trailing 0s are considered part of the 'unused' bits
+ * when encoding this value in the first content octet
+ */
+ if( bits != 0 )
+ {
+ cur_byte = buf + byte_len - 1;
+ cur_byte_shifted = *cur_byte >> unused_bits;
+
+ for( ; ; )
+ {
+ bit = cur_byte_shifted & 0x1;
+ cur_byte_shifted >>= 1;
+
+ if( bit != 0 )
+ break;
+
+ bits--;
+ if( bits == 0 )
+ break;
+
+ if( bits % 8 == 0 )
+ cur_byte_shifted = *--cur_byte;
+ }
+ }
+
+ return( mbedtls_asn1_write_bitstring( p, start, buf, bits ) );
+}
+
int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t bits )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
size_t unused_bits, byte_len;
@@ -326,7 +383,7 @@
int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) );
@@ -386,18 +443,26 @@
memcpy( cur->oid.p, oid, oid_len );
cur->val.len = val_len;
- cur->val.p = mbedtls_calloc( 1, val_len );
- if( cur->val.p == NULL )
+ if( val_len != 0 )
{
- mbedtls_free( cur->oid.p );
- mbedtls_free( cur );
- return( NULL );
+ cur->val.p = mbedtls_calloc( 1, val_len );
+ if( cur->val.p == NULL )
+ {
+ mbedtls_free( cur->oid.p );
+ mbedtls_free( cur );
+ return( NULL );
+ }
}
cur->next = *head;
*head = cur;
}
- else if( cur->val.len < val_len )
+ else if( val_len == 0 )
+ {
+ mbedtls_free( cur->val.p );
+ cur->val.p = NULL;
+ }
+ else if( cur->val.len != val_len )
{
/*
* Enlarge existing value buffer if needed
diff --git a/lib/libmbedtls/mbedtls/library/bignum.c b/lib/libmbedtls/mbedtls/library/bignum.c
index f11255b..58de6d0 100644
--- a/lib/libmbedtls/mbedtls/library/bignum.c
+++ b/lib/libmbedtls/mbedtls/library/bignum.c
@@ -46,6 +46,7 @@
#include "mbedtls/bignum.h"
#include "mbedtls/bn_mul.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -362,7 +363,7 @@
*/
int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MPI_VALIDATE_RET( X != NULL );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
@@ -505,7 +506,7 @@
*/
int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, j, slen, n;
mbedtls_mpi_uint d;
mbedtls_mpi T;
@@ -580,7 +581,7 @@
static int mpi_write_hlp( mbedtls_mpi *X, int radix,
char **p, const size_t buflen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi_uint r;
size_t length = 0;
char *p_end = *p + buflen;
@@ -745,7 +746,7 @@
*/
int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n, slen, plen;
/*
* Buffer should have space for (short) label and decimal formatted MPI,
@@ -875,11 +876,44 @@
}
/*
+ * Import X from unsigned binary data, little endian
+ */
+int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
+ const unsigned char *buf, size_t buflen )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t i;
+ size_t const limbs = CHARS_TO_LIMBS( buflen );
+
+ /* Ensure that target MPI has exactly the necessary number of limbs */
+ if( X->n != limbs )
+ {
+ mbedtls_mpi_free( X );
+ mbedtls_mpi_init( X );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
+ }
+
+ MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
+
+ for( i = 0; i < buflen; i++ )
+ X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
+
+cleanup:
+
+ /*
+ * This function is also used to import keys. However, wiping the buffers
+ * upon failure is not necessary because failure only can happen before any
+ * input is copied.
+ */
+ return( ret );
+}
+
+/*
* Import X from unsigned binary data, big endian
*/
int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t const limbs = CHARS_TO_LIMBS( buflen );
size_t const overhead = ( limbs * ciL ) - buflen;
unsigned char *Xp;
@@ -910,10 +944,54 @@
cleanup:
+ /*
+ * This function is also used to import keys. However, wiping the buffers
+ * upon failure is not necessary because failure only can happen before any
+ * input is copied.
+ */
return( ret );
}
/*
+ * Export X into unsigned binary data, little endian
+ */
+int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
+ unsigned char *buf, size_t buflen )
+{
+ size_t stored_bytes = X->n * ciL;
+ size_t bytes_to_copy;
+ size_t i;
+
+ if( stored_bytes < buflen )
+ {
+ bytes_to_copy = stored_bytes;
+ }
+ else
+ {
+ bytes_to_copy = buflen;
+
+ /* The output buffer is smaller than the allocated size of X.
+ * However X may fit if its leading bytes are zero. */
+ for( i = bytes_to_copy; i < stored_bytes; i++ )
+ {
+ if( GET_BYTE( X, i ) != 0 )
+ return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
+ }
+ }
+
+ for( i = 0; i < bytes_to_copy; i++ )
+ buf[i] = GET_BYTE( X, i );
+
+ if( stored_bytes < buflen )
+ {
+ /* Write trailing 0 bytes */
+ memset( buf + stored_bytes, 0, buflen - stored_bytes );
+ }
+
+ return( 0 );
+}
+
+/*
* Export X into unsigned binary data, big endian
*/
int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
@@ -964,7 +1042,7 @@
*/
int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, v0, t1;
mbedtls_mpi_uint r0 = 0, r1;
MPI_VALIDATE_RET( X != NULL );
@@ -1244,7 +1322,7 @@
*/
int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, j;
mbedtls_mpi_uint *o, *p, c, tmp;
MPI_VALIDATE_RET( X != NULL );
@@ -1325,7 +1403,7 @@
int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
mbedtls_mpi TB;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( A != NULL );
@@ -1548,7 +1626,7 @@
*/
int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, j;
mbedtls_mpi TA, TB;
MPI_VALIDATE_RET( X != NULL );
@@ -1703,9 +1781,10 @@
int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
const mbedtls_mpi *B )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, n, t, k;
mbedtls_mpi X, Y, Z, T1, T2;
+ mbedtls_mpi_uint TP2[3];
MPI_VALIDATE_RET( A != NULL );
MPI_VALIDATE_RET( B != NULL );
@@ -1714,7 +1793,16 @@
mbedtls_mpi_init_mempool( &X ); mbedtls_mpi_init_mempool( &Y );
mbedtls_mpi_init_mempool( &Z ); mbedtls_mpi_init_mempool( &T1 );
- mbedtls_mpi_init_mempool( &T2 );
+ /*
+ * Avoid dynamic memory allocations for constant-size T2.
+ *
+ * T2 is used for comparison only and the 3 limbs are assigned explicitly,
+ * so nobody increase the size of the MPI and we're safe to use an on-stack
+ * buffer.
+ */
+ T2.s = 1;
+ T2.n = sizeof( TP2 ) / sizeof( *TP2 );
+ T2.p = TP2;
if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
{
@@ -1730,7 +1818,6 @@
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
k = mbedtls_mpi_bitlen( &Y ) % biL;
if( k < biL - 1 )
@@ -1762,6 +1849,10 @@
Y.p[t], NULL);
}
+ T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
+ T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
+ T2.p[2] = X.p[i];
+
Z.p[i - t - 1]++;
do
{
@@ -1771,11 +1862,6 @@
T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
T1.p[1] = Y.p[t];
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
-
- MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
- T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
- T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
- T2.p[2] = X.p[i];
}
while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
@@ -1811,7 +1897,8 @@
cleanup:
mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
- mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
+ mbedtls_mpi_free( &T1 );
+ mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
return( ret );
}
@@ -1840,7 +1927,7 @@
*/
int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MPI_VALIDATE_RET( R != NULL );
MPI_VALIDATE_RET( A != NULL );
MPI_VALIDATE_RET( B != NULL );
@@ -2003,7 +2090,7 @@
const mbedtls_mpi *E, const mbedtls_mpi *N,
mbedtls_mpi *_RR )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t wbits, wsize, one = 1;
size_t i, j, nblimbs;
size_t bufsize, nbits;
@@ -2231,16 +2318,15 @@
*/
int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t lz, lzt;
- mbedtls_mpi TG, TA, TB;
+ mbedtls_mpi TA, TB;
MPI_VALIDATE_RET( G != NULL );
MPI_VALIDATE_RET( A != NULL );
MPI_VALIDATE_RET( B != NULL );
- mbedtls_mpi_init_mempool( &TG ); mbedtls_mpi_init_mempool( &TA );
- mbedtls_mpi_init_mempool( &TB );
+ mbedtls_mpi_init_mempool( &TA ); mbedtls_mpi_init_mempool( &TB );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
@@ -2278,7 +2364,7 @@
cleanup:
- mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
+ mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
return( ret );
}
@@ -2294,7 +2380,7 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t const limbs = CHARS_TO_LIMBS( size );
size_t const overhead = ( limbs * ciL ) - size;
unsigned char *Xp;
@@ -2325,7 +2411,7 @@
*/
int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( A != NULL );
@@ -2580,7 +2666,7 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi XX;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( f_rng != NULL );
diff --git a/lib/libmbedtls/mbedtls/library/ccm.c b/lib/libmbedtls/mbedtls/library/ccm.c
index f824205..4c070ab 100644
--- a/lib/libmbedtls/mbedtls/library/ccm.c
+++ b/lib/libmbedtls/mbedtls/library/ccm.c
@@ -38,6 +38,7 @@
#include "mbedtls/ccm.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -74,13 +75,14 @@
const unsigned char *key,
unsigned int keybits )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_cipher_info_t *cipher_info;
CCM_VALIDATE_RET( ctx != NULL );
CCM_VALIDATE_RET( key != NULL );
- cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB );
+ cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
+ MBEDTLS_MODE_ECB );
if( cipher_info == NULL )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
@@ -155,7 +157,7 @@
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char i;
unsigned char q;
size_t len_left, olen;
@@ -365,7 +367,7 @@
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char check_tag[16];
unsigned char i;
int diff;
@@ -429,34 +431,34 @@
/*
* The data is the same for all tests, only the used length changes
*/
-static const unsigned char key[] = {
+static const unsigned char key_test_data[] = {
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
};
-static const unsigned char iv[] = {
+static const unsigned char iv_test_data[] = {
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b
};
-static const unsigned char ad[] = {
+static const unsigned char ad_test_data[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13
};
-static const unsigned char msg[CCM_SELFTEST_PT_MAX_LEN] = {
+static const unsigned char msg_test_data[CCM_SELFTEST_PT_MAX_LEN] = {
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
};
-static const size_t iv_len [NB_TESTS] = { 7, 8, 12 };
-static const size_t add_len[NB_TESTS] = { 8, 16, 20 };
-static const size_t msg_len[NB_TESTS] = { 4, 16, 24 };
-static const size_t tag_len[NB_TESTS] = { 4, 6, 8 };
+static const size_t iv_len_test_data [NB_TESTS] = { 7, 8, 12 };
+static const size_t add_len_test_data[NB_TESTS] = { 8, 16, 20 };
+static const size_t msg_len_test_data[NB_TESTS] = { 4, 16, 24 };
+static const size_t tag_len_test_data[NB_TESTS] = { 4, 6, 8 };
-static const unsigned char res[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = {
+static const unsigned char res_test_data[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = {
{ 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
{ 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
@@ -478,11 +480,12 @@
unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN];
unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN];
size_t i;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ccm_init( &ctx );
- if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 )
+ if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key_test_data,
+ 8 * sizeof key_test_data ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( " CCM: setup failed" );
@@ -497,15 +500,18 @@
memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN );
memset( ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN );
- memcpy( plaintext, msg, msg_len[i] );
+ memcpy( plaintext, msg_test_data, msg_len_test_data[i] );
- ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i],
- iv, iv_len[i], ad, add_len[i],
+ ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len_test_data[i],
+ iv_test_data, iv_len_test_data[i],
+ ad_test_data, add_len_test_data[i],
plaintext, ciphertext,
- ciphertext + msg_len[i], tag_len[i] );
+ ciphertext + msg_len_test_data[i],
+ tag_len_test_data[i] );
if( ret != 0 ||
- memcmp( ciphertext, res[i], msg_len[i] + tag_len[i] ) != 0 )
+ memcmp( ciphertext, res_test_data[i],
+ msg_len_test_data[i] + tag_len_test_data[i] ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
@@ -514,13 +520,15 @@
}
memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN );
- ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i],
- iv, iv_len[i], ad, add_len[i],
+ ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len_test_data[i],
+ iv_test_data, iv_len_test_data[i],
+ ad_test_data, add_len_test_data[i],
ciphertext, plaintext,
- ciphertext + msg_len[i], tag_len[i] );
+ ciphertext + msg_len_test_data[i],
+ tag_len_test_data[i] );
if( ret != 0 ||
- memcmp( plaintext, msg, msg_len[i] ) != 0 )
+ memcmp( plaintext, msg_test_data, msg_len_test_data[i] ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
diff --git a/lib/libmbedtls/mbedtls/library/certs.c b/lib/libmbedtls/mbedtls/library/certs.c
index d37a32c..1d879a1 100644
--- a/lib/libmbedtls/mbedtls/library/certs.c
+++ b/lib/libmbedtls/mbedtls/library/certs.c
@@ -254,7 +254,7 @@
"-----BEGIN CERTIFICATE-----\r\n" \
"MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \
"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \
- "MTkwMjEwMTQ0NDAwWhcNMjkwMjEwMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \
+ "MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \
"A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \
"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \
"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \
@@ -264,88 +264,88 @@
"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \
"UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/\r\n" \
"MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBBQUA\r\n" \
- "A4IBAQB0ZiNRFdia6kskaPnhrqejIRq8YMEGAf2oIPnyZ78xoyERgc35lHGyMtsL\r\n" \
- "hWicNjP4d/hS9As4j5KA2gdNGi5ETA1X7SowWOGsryivSpMSHVy1+HdfWlsYQOzm\r\n" \
- "8o+faQNUm8XzPVmttfAVspxeHSxJZ36Oo+QWZ5wZlCIEyjEdLUId+Tm4Bz3B5jRD\r\n" \
- "zZa/SaqDokq66N2zpbgKKAl3GU2O++fBqP2dSkdQykmTxhLLWRN8FJqhYATyQntZ\r\n" \
- "0QSi3W9HfSZPnFTcPIXeoiPd2pLlxt1hZu8dws2LTXE63uP6MM4LHvWxiuJaWkP/\r\n" \
- "mtxyUALj2pQxRitopORFQdn7AOY5\r\n" \
+ "A4IBAQABE3OEPfEd/bcJW5ZdU3/VgPNS4tMzh8gnJP/V2FcvFtGylMpQq6YnEBYI\r\n" \
+ "yBHAL4DRvlMY5rnXGBp3ODR8MpqHC6AquRTCLzjS57iYff//4QFQqW9n92zctspv\r\n" \
+ "czkaPKgjqo1No3Uq0Xaz10rcxyTUPrf5wNVRZ2V0KvllvAAVSzbI4mpdUXztjhST\r\n" \
+ "S5A2BeWQAAOr0zq1F7TSRVJpJs7jmB2ai/igkh1IAjcuwV6VwlP+sbw0gjQ0NpGM\r\n" \
+ "iHpnlzRAi/tIbtOvMIGOBU2TIfax/5jq1agUx5aPmT5TWAiJPOOP6l5xXnDwxeYS\r\n" \
+ "NWqiX9GyusBZjezaCaHabjDLU0qQ\r\n" \
"-----END CERTIFICATE-----\r\n"
/* END FILE */
/* This is taken from tests/data_files/test-ca-sha1.crt.der. */
/* BEGIN FILE binary macro TEST_CA_CRT_RSA_SHA1_DER tests/data_files/test-ca-sha1.crt.der */
#define TEST_CA_CRT_RSA_SHA1_DER { \
- 0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01, \
- 0x02, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \
- 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \
- 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \
- 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \
- 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \
- 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \
- 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \
- 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, \
- 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \
- 0x34, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \
- 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \
- 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \
- 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \
- 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65, \
- 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, \
- 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, \
- 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, \
- 0x01, 0x00, 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, \
- 0x86, 0xde, 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, \
- 0x99, 0xd4, 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, \
- 0x9b, 0xc5, 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, \
- 0xc0, 0x8d, 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, \
- 0x93, 0xe8, 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, \
- 0xe7, 0x40, 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, \
- 0xf9, 0x3e, 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, \
- 0x29, 0x00, 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, \
- 0xbd, 0x83, 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, \
- 0x60, 0xc3, 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, \
- 0x32, 0xbe, 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, \
- 0xfb, 0xf5, 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, \
- 0xee, 0xe2, 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, \
- 0x47, 0xb1, 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, \
- 0xf1, 0x79, 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, \
- 0x6f, 0x27, 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, \
- 0xa1, 0x30, 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, \
- 0x28, 0xd1, 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, \
- 0x09, 0xea, 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, \
- 0xc9, 0xab, 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, \
- 0x9e, 0x99, 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, \
- 0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, \
- 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, \
- 0x04, 0x16, 0x04, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, \
- 0xf6, 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, \
- 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, \
- 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, \
- 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, \
- 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, \
- 0x03, 0x82, 0x01, 0x01, 0x00, 0x74, 0x66, 0x23, 0x51, 0x15, 0xd8, 0x9a, \
- 0xea, 0x4b, 0x24, 0x68, 0xf9, 0xe1, 0xae, 0xa7, 0xa3, 0x21, 0x1a, 0xbc, \
- 0x60, 0xc1, 0x06, 0x01, 0xfd, 0xa8, 0x20, 0xf9, 0xf2, 0x67, 0xbf, 0x31, \
- 0xa3, 0x21, 0x11, 0x81, 0xcd, 0xf9, 0x94, 0x71, 0xb2, 0x32, 0xdb, 0x0b, \
- 0x85, 0x68, 0x9c, 0x36, 0x33, 0xf8, 0x77, 0xf8, 0x52, 0xf4, 0x0b, 0x38, \
- 0x8f, 0x92, 0x80, 0xda, 0x07, 0x4d, 0x1a, 0x2e, 0x44, 0x4c, 0x0d, 0x57, \
- 0xed, 0x2a, 0x30, 0x58, 0xe1, 0xac, 0xaf, 0x28, 0xaf, 0x4a, 0x93, 0x12, \
- 0x1d, 0x5c, 0xb5, 0xf8, 0x77, 0x5f, 0x5a, 0x5b, 0x18, 0x40, 0xec, 0xe6, \
- 0xf2, 0x8f, 0x9f, 0x69, 0x03, 0x54, 0x9b, 0xc5, 0xf3, 0x3d, 0x59, 0xad, \
- 0xb5, 0xf0, 0x15, 0xb2, 0x9c, 0x5e, 0x1d, 0x2c, 0x49, 0x67, 0x7e, 0x8e, \
- 0xa3, 0xe4, 0x16, 0x67, 0x9c, 0x19, 0x94, 0x22, 0x04, 0xca, 0x31, 0x1d, \
- 0x2d, 0x42, 0x1d, 0xf9, 0x39, 0xb8, 0x07, 0x3d, 0xc1, 0xe6, 0x34, 0x43, \
- 0xcd, 0x96, 0xbf, 0x49, 0xaa, 0x83, 0xa2, 0x4a, 0xba, 0xe8, 0xdd, 0xb3, \
- 0xa5, 0xb8, 0x0a, 0x28, 0x09, 0x77, 0x19, 0x4d, 0x8e, 0xfb, 0xe7, 0xc1, \
- 0xa8, 0xfd, 0x9d, 0x4a, 0x47, 0x50, 0xca, 0x49, 0x93, 0xc6, 0x12, 0xcb, \
- 0x59, 0x13, 0x7c, 0x14, 0x9a, 0xa1, 0x60, 0x04, 0xf2, 0x42, 0x7b, 0x59, \
- 0xd1, 0x04, 0xa2, 0xdd, 0x6f, 0x47, 0x7d, 0x26, 0x4f, 0x9c, 0x54, 0xdc, \
- 0x3c, 0x85, 0xde, 0xa2, 0x23, 0xdd, 0xda, 0x92, 0xe5, 0xc6, 0xdd, 0x61, \
- 0x66, 0xef, 0x1d, 0xc2, 0xcd, 0x8b, 0x4d, 0x71, 0x3a, 0xde, 0xe3, 0xfa, \
- 0x30, 0xce, 0x0b, 0x1e, 0xf5, 0xb1, 0x8a, 0xe2, 0x5a, 0x5a, 0x43, 0xff, \
- 0x9a, 0xdc, 0x72, 0x50, 0x02, 0xe3, 0xda, 0x94, 0x31, 0x46, 0x2b, 0x68, \
- 0xa4, 0xe4, 0x45, 0x41, 0xd9, 0xfb, 0x00, 0xe6, 0x39 \
+ 0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01, \
+ 0x02, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \
+ 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \
+ 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \
+ 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \
+ 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \
+ 0x31, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, \
+ 0x5a, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, \
+ 0x34, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \
+ 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \
+ 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \
+ 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65, \
+ 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, \
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, \
+ 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, \
+ 0x01, 0x00, 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, \
+ 0x86, 0xde, 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, \
+ 0x99, 0xd4, 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, \
+ 0x9b, 0xc5, 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, \
+ 0xc0, 0x8d, 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, \
+ 0x93, 0xe8, 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, \
+ 0xe7, 0x40, 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, \
+ 0xf9, 0x3e, 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, \
+ 0x29, 0x00, 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, \
+ 0xbd, 0x83, 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, \
+ 0x60, 0xc3, 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, \
+ 0x32, 0xbe, 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, \
+ 0xfb, 0xf5, 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, \
+ 0xee, 0xe2, 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, \
+ 0x47, 0xb1, 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, \
+ 0xf1, 0x79, 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, \
+ 0x6f, 0x27, 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, \
+ 0xa1, 0x30, 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, \
+ 0x28, 0xd1, 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, \
+ 0x09, 0xea, 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, \
+ 0xc9, 0xab, 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, \
+ 0x9e, 0x99, 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, \
+ 0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, \
+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, \
+ 0x04, 0x16, 0x04, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, \
+ 0xf6, 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, \
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, \
+ 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, \
+ 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, \
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, \
+ 0x03, 0x82, 0x01, 0x01, 0x00, 0x01, 0x13, 0x73, 0x84, 0x3d, 0xf1, 0x1d, \
+ 0xfd, 0xb7, 0x09, 0x5b, 0x96, 0x5d, 0x53, 0x7f, 0xd5, 0x80, 0xf3, 0x52, \
+ 0xe2, 0xd3, 0x33, 0x87, 0xc8, 0x27, 0x24, 0xff, 0xd5, 0xd8, 0x57, 0x2f, \
+ 0x16, 0xd1, 0xb2, 0x94, 0xca, 0x50, 0xab, 0xa6, 0x27, 0x10, 0x16, 0x08, \
+ 0xc8, 0x11, 0xc0, 0x2f, 0x80, 0xd1, 0xbe, 0x53, 0x18, 0xe6, 0xb9, 0xd7, \
+ 0x18, 0x1a, 0x77, 0x38, 0x34, 0x7c, 0x32, 0x9a, 0x87, 0x0b, 0xa0, 0x2a, \
+ 0xb9, 0x14, 0xc2, 0x2f, 0x38, 0xd2, 0xe7, 0xb8, 0x98, 0x7d, 0xff, 0xff, \
+ 0xe1, 0x01, 0x50, 0xa9, 0x6f, 0x67, 0xf7, 0x6c, 0xdc, 0xb6, 0xca, 0x6f, \
+ 0x73, 0x39, 0x1a, 0x3c, 0xa8, 0x23, 0xaa, 0x8d, 0x4d, 0xa3, 0x75, 0x2a, \
+ 0xd1, 0x76, 0xb3, 0xd7, 0x4a, 0xdc, 0xc7, 0x24, 0xd4, 0x3e, 0xb7, 0xf9, \
+ 0xc0, 0xd5, 0x51, 0x67, 0x65, 0x74, 0x2a, 0xf9, 0x65, 0xbc, 0x00, 0x15, \
+ 0x4b, 0x36, 0xc8, 0xe2, 0x6a, 0x5d, 0x51, 0x7c, 0xed, 0x8e, 0x14, 0x93, \
+ 0x4b, 0x90, 0x36, 0x05, 0xe5, 0x90, 0x00, 0x03, 0xab, 0xd3, 0x3a, 0xb5, \
+ 0x17, 0xb4, 0xd2, 0x45, 0x52, 0x69, 0x26, 0xce, 0xe3, 0x98, 0x1d, 0x9a, \
+ 0x8b, 0xf8, 0xa0, 0x92, 0x1d, 0x48, 0x02, 0x37, 0x2e, 0xc1, 0x5e, 0x95, \
+ 0xc2, 0x53, 0xfe, 0xb1, 0xbc, 0x34, 0x82, 0x34, 0x34, 0x36, 0x91, 0x8c, \
+ 0x88, 0x7a, 0x67, 0x97, 0x34, 0x40, 0x8b, 0xfb, 0x48, 0x6e, 0xd3, 0xaf, \
+ 0x30, 0x81, 0x8e, 0x05, 0x4d, 0x93, 0x21, 0xf6, 0xb1, 0xff, 0x98, 0xea, \
+ 0xd5, 0xa8, 0x14, 0xc7, 0x96, 0x8f, 0x99, 0x3e, 0x53, 0x58, 0x08, 0x89, \
+ 0x3c, 0xe3, 0x8f, 0xea, 0x5e, 0x71, 0x5e, 0x70, 0xf0, 0xc5, 0xe6, 0x12, \
+ 0x35, 0x6a, 0xa2, 0x5f, 0xd1, 0xb2, 0xba, 0xc0, 0x59, 0x8d, 0xec, 0xda, \
+ 0x09, 0xa1, 0xda, 0x6e, 0x30, 0xcb, 0x53, 0x4a, 0x90 \
}
/* END FILE */
@@ -705,101 +705,101 @@
/* This is taken from tests/data_files/server2.crt. */
/* BEGIN FILE string macro TEST_SRV_CRT_RSA_SHA1_PEM tests/data_files/server2.crt */
-#define TEST_SRV_CRT_RSA_SHA1_PEM \
- "-----BEGIN CERTIFICATE-----\r\n" \
- "MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \
- "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \
- "MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \
- "A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" \
- "AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" \
- "owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" \
- "NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" \
- "tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" \
- "hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" \
- "HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" \
- "VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" \
- "FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJklg3Q4\r\n" \
- "cB7v7BzsxM/vLyKccO6op0/gZzM4ghuLq2Y32kl0sM6kSNUUmduuq3u/+GmUZN2A\r\n" \
- "O/7c+Hw7hDFEIvZk98aBGjCLqn3DmgHIv8ToQ67nellQxx2Uj309PdgjNi/r9HOc\r\n" \
- "KNAYPbBcg6MJGWWj2TI6vNaceios/DhOYx5V0j5nfqSJ/pnU0g9Ign2LAhgYpGJE\r\n" \
- "iEM9wW7hEMkwmk0h/sqZsrJsGH5YsF/VThSq/JVO1e2mZH2vruyZKJVBq+8tDNYp\r\n" \
- "HkK6tSyVYQhzIt3StMJWKMl/o5k2AYz6tSC164+1oG+ML3LWg8XrGKa91H4UOKap\r\n" \
- "Awgk0+4m0T25cNs=\r\n" \
- "-----END CERTIFICATE-----\r\n"
+#define TEST_SRV_CRT_RSA_SHA1_PEM \
+"-----BEGIN CERTIFICATE-----\r\n" \
+"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \
+"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \
+"MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \
+"A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" \
+"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" \
+"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" \
+"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" \
+"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" \
+"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" \
+"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" \
+"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" \
+"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJklg3Q4\r\n" \
+"cB7v7BzsxM/vLyKccO6op0/gZzM4ghuLq2Y32kl0sM6kSNUUmduuq3u/+GmUZN2A\r\n" \
+"O/7c+Hw7hDFEIvZk98aBGjCLqn3DmgHIv8ToQ67nellQxx2Uj309PdgjNi/r9HOc\r\n" \
+"KNAYPbBcg6MJGWWj2TI6vNaceios/DhOYx5V0j5nfqSJ/pnU0g9Ign2LAhgYpGJE\r\n" \
+"iEM9wW7hEMkwmk0h/sqZsrJsGH5YsF/VThSq/JVO1e2mZH2vruyZKJVBq+8tDNYp\r\n" \
+"HkK6tSyVYQhzIt3StMJWKMl/o5k2AYz6tSC164+1oG+ML3LWg8XrGKa91H4UOKap\r\n" \
+"Awgk0+4m0T25cNs=\r\n" \
+"-----END CERTIFICATE-----\r\n"
/* END FILE */
/* This is taken from tests/data_files/server2.crt.der. */
/* BEGIN FILE binary macro TEST_SRV_CRT_RSA_SHA1_DER tests/data_files/server2.crt.der */
#define TEST_SRV_CRT_RSA_SHA1_DER { \
- 0x30, 0x82, 0x03, 0x37, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, \
- 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \
- 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \
- 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \
- 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \
- 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \
- 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \
- 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \
- 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \
- 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \
- 0x34, 0x30, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \
- 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \
- 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \
- 0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \
- 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, \
- 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, \
- 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, \
- 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, \
- 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, 0xb8, 0x99, 0xac, 0x0e, 0x78, \
- 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, 0x16, 0xd0, 0x5a, 0xe4, 0xcd, \
- 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, 0x96, 0xa7, 0x52, 0xb4, 0x90, \
- 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, 0xfc, 0xb6, 0x34, 0xac, 0x24, \
- 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, 0xb0, 0x28, 0x7d, 0xa1, 0xda, \
- 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, 0xfe, 0xc1, 0x04, 0x52, 0xb3, \
- 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, 0xd8, 0x90, 0xc1, 0x61, 0xb4, \
- 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, 0xab, 0x74, 0x5e, 0x07, 0x7d, \
- 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, 0xd9, 0x0d, 0x1c, 0x2d, 0x49, \
- 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, 0x0b, 0x8a, 0x4f, 0x69, 0x0c, \
- 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, 0x66, 0x7d, 0xae, 0x54, 0x2b, \
- 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, 0xc3, 0xcd, 0x40, 0x49, 0x08, \
- 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, 0x46, 0xbf, 0xd0, 0xb8, 0xaa, \
- 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, 0x1e, 0x44, 0x18, 0x0f, 0x0f, \
- 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, 0x18, 0xc6, 0x62, 0x2f, 0xc7, \
- 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, 0x27, 0x89, 0x29, 0x01, 0xc5, \
- 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, 0x4a, 0x0e, 0xef, 0xd6, 0xde, \
- 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, 0x7a, 0xc4, 0x02, 0x3c, 0x9a, \
- 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, 0xcb, 0x73, 0x4b, 0x52, 0x96, \
- 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, 0x39, 0x5a, 0xd3, 0x0f, 0xb0, \
- 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, 0x12, 0x01, 0x30, 0x97, 0x02, \
- 0x03, 0x01, 0x00, 0x01, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, \
- 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, \
- 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa5, 0x05, 0xe8, 0x64, 0xb8, 0xdc, \
- 0xdf, 0x60, 0x0f, 0x50, 0x12, 0x4d, 0x60, 0xa8, 0x64, 0xaf, 0x4d, 0x8b, \
- 0x43, 0x93, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, \
- 0x16, 0x80, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, \
- 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, \
- 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, \
- 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x99, 0x25, 0x83, 0x74, 0x38, \
- 0x70, 0x1e, 0xef, 0xec, 0x1c, 0xec, 0xc4, 0xcf, 0xef, 0x2f, 0x22, 0x9c, \
- 0x70, 0xee, 0xa8, 0xa7, 0x4f, 0xe0, 0x67, 0x33, 0x38, 0x82, 0x1b, 0x8b, \
- 0xab, 0x66, 0x37, 0xda, 0x49, 0x74, 0xb0, 0xce, 0xa4, 0x48, 0xd5, 0x14, \
- 0x99, 0xdb, 0xae, 0xab, 0x7b, 0xbf, 0xf8, 0x69, 0x94, 0x64, 0xdd, 0x80, \
- 0x3b, 0xfe, 0xdc, 0xf8, 0x7c, 0x3b, 0x84, 0x31, 0x44, 0x22, 0xf6, 0x64, \
- 0xf7, 0xc6, 0x81, 0x1a, 0x30, 0x8b, 0xaa, 0x7d, 0xc3, 0x9a, 0x01, 0xc8, \
- 0xbf, 0xc4, 0xe8, 0x43, 0xae, 0xe7, 0x7a, 0x59, 0x50, 0xc7, 0x1d, 0x94, \
- 0x8f, 0x7d, 0x3d, 0x3d, 0xd8, 0x23, 0x36, 0x2f, 0xeb, 0xf4, 0x73, 0x9c, \
- 0x28, 0xd0, 0x18, 0x3d, 0xb0, 0x5c, 0x83, 0xa3, 0x09, 0x19, 0x65, 0xa3, \
- 0xd9, 0x32, 0x3a, 0xbc, 0xd6, 0x9c, 0x7a, 0x2a, 0x2c, 0xfc, 0x38, 0x4e, \
- 0x63, 0x1e, 0x55, 0xd2, 0x3e, 0x67, 0x7e, 0xa4, 0x89, 0xfe, 0x99, 0xd4, \
- 0xd2, 0x0f, 0x48, 0x82, 0x7d, 0x8b, 0x02, 0x18, 0x18, 0xa4, 0x62, 0x44, \
- 0x88, 0x43, 0x3d, 0xc1, 0x6e, 0xe1, 0x10, 0xc9, 0x30, 0x9a, 0x4d, 0x21, \
- 0xfe, 0xca, 0x99, 0xb2, 0xb2, 0x6c, 0x18, 0x7e, 0x58, 0xb0, 0x5f, 0xd5, \
- 0x4e, 0x14, 0xaa, 0xfc, 0x95, 0x4e, 0xd5, 0xed, 0xa6, 0x64, 0x7d, 0xaf, \
- 0xae, 0xec, 0x99, 0x28, 0x95, 0x41, 0xab, 0xef, 0x2d, 0x0c, 0xd6, 0x29, \
- 0x1e, 0x42, 0xba, 0xb5, 0x2c, 0x95, 0x61, 0x08, 0x73, 0x22, 0xdd, 0xd2, \
- 0xb4, 0xc2, 0x56, 0x28, 0xc9, 0x7f, 0xa3, 0x99, 0x36, 0x01, 0x8c, 0xfa, \
- 0xb5, 0x20, 0xb5, 0xeb, 0x8f, 0xb5, 0xa0, 0x6f, 0x8c, 0x2f, 0x72, 0xd6, \
- 0x83, 0xc5, 0xeb, 0x18, 0xa6, 0xbd, 0xd4, 0x7e, 0x14, 0x38, 0xa6, 0xa9, \
- 0x03, 0x08, 0x24, 0xd3, 0xee, 0x26, 0xd1, 0x3d, 0xb9, 0x70, 0xdb \
+ 0x30, 0x82, 0x03, 0x37, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, \
+ 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \
+ 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \
+ 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \
+ 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \
+ 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \
+ 0x31, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \
+ 0x5a, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, \
+ 0x34, 0x30, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \
+ 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \
+ 0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \
+ 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, \
+ 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, \
+ 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, \
+ 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, \
+ 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, 0xb8, 0x99, 0xac, 0x0e, 0x78, \
+ 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, 0x16, 0xd0, 0x5a, 0xe4, 0xcd, \
+ 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, 0x96, 0xa7, 0x52, 0xb4, 0x90, \
+ 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, 0xfc, 0xb6, 0x34, 0xac, 0x24, \
+ 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, 0xb0, 0x28, 0x7d, 0xa1, 0xda, \
+ 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, 0xfe, 0xc1, 0x04, 0x52, 0xb3, \
+ 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, 0xd8, 0x90, 0xc1, 0x61, 0xb4, \
+ 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, 0xab, 0x74, 0x5e, 0x07, 0x7d, \
+ 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, 0xd9, 0x0d, 0x1c, 0x2d, 0x49, \
+ 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, 0x0b, 0x8a, 0x4f, 0x69, 0x0c, \
+ 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, 0x66, 0x7d, 0xae, 0x54, 0x2b, \
+ 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, 0xc3, 0xcd, 0x40, 0x49, 0x08, \
+ 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, 0x46, 0xbf, 0xd0, 0xb8, 0xaa, \
+ 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, 0x1e, 0x44, 0x18, 0x0f, 0x0f, \
+ 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, 0x18, 0xc6, 0x62, 0x2f, 0xc7, \
+ 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, 0x27, 0x89, 0x29, 0x01, 0xc5, \
+ 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, 0x4a, 0x0e, 0xef, 0xd6, 0xde, \
+ 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, 0x7a, 0xc4, 0x02, 0x3c, 0x9a, \
+ 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, 0xcb, 0x73, 0x4b, 0x52, 0x96, \
+ 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, 0x39, 0x5a, 0xd3, 0x0f, 0xb0, \
+ 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, 0x12, 0x01, 0x30, 0x97, 0x02, \
+ 0x03, 0x01, 0x00, 0x01, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, \
+ 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, \
+ 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa5, 0x05, 0xe8, 0x64, 0xb8, 0xdc, \
+ 0xdf, 0x60, 0x0f, 0x50, 0x12, 0x4d, 0x60, 0xa8, 0x64, 0xaf, 0x4d, 0x8b, \
+ 0x43, 0x93, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, \
+ 0x16, 0x80, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, \
+ 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, \
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, \
+ 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x01, 0x73, 0x0b, 0x4a, 0xc5, \
+ 0xcb, 0xa0, 0xde, 0xf1, 0x63, 0x1c, 0x76, 0x04, 0x2b, 0x13, 0x0d, 0xc0, \
+ 0x84, 0x11, 0xc5, 0x8f, 0x3a, 0xa7, 0xc5, 0x9c, 0x35, 0x7a, 0x77, 0xb8, \
+ 0x20, 0x14, 0x82, 0xee, 0x54, 0xf0, 0xf2, 0xb0, 0x52, 0xcb, 0x78, 0xce, \
+ 0x59, 0x07, 0x4f, 0x51, 0x69, 0xfe, 0xd3, 0x2f, 0xe9, 0x09, 0xe7, 0x85, \
+ 0x92, 0xd8, 0xba, 0xb1, 0xeb, 0xc5, 0x76, 0x5d, 0x61, 0x2d, 0xe9, 0x86, \
+ 0xb5, 0xde, 0x2a, 0xf9, 0x3f, 0x53, 0x28, 0x42, 0x86, 0x83, 0x73, 0x43, \
+ 0xe0, 0x04, 0x5f, 0x07, 0x90, 0x14, 0x65, 0x9f, 0x6e, 0x10, 0x7a, 0xbc, \
+ 0x58, 0x19, 0x22, 0xc2, 0xeb, 0x39, 0x72, 0x51, 0x92, 0xd7, 0xb4, 0x1d, \
+ 0x75, 0x2f, 0xd3, 0x3a, 0x2b, 0x01, 0xe7, 0xdb, 0x50, 0xae, 0xe2, 0xf1, \
+ 0xd4, 0x4d, 0x5b, 0x3c, 0xbb, 0x41, 0x2b, 0x2a, 0xa4, 0xe2, 0x4a, 0x02, \
+ 0xe5, 0x60, 0x14, 0x2c, 0x9c, 0x1f, 0xa6, 0xcc, 0x06, 0x4b, 0x25, 0x89, \
+ 0x4e, 0x96, 0x30, 0x22, 0x9c, 0x5c, 0x58, 0x4d, 0xc3, 0xda, 0xd0, 0x6e, \
+ 0x50, 0x1e, 0x8c, 0x65, 0xf5, 0xd9, 0x17, 0x35, 0xa6, 0x58, 0x43, 0xb2, \
+ 0x29, 0xb7, 0xa8, 0x5e, 0x35, 0xde, 0xf0, 0x60, 0x42, 0x1a, 0x01, 0xcb, \
+ 0xcb, 0x0b, 0xd8, 0x0e, 0xc1, 0x90, 0xdf, 0xa1, 0xd2, 0x1a, 0xd1, 0x2c, \
+ 0x02, 0xf4, 0x76, 0x41, 0xa4, 0xcb, 0x4b, 0x15, 0x98, 0x71, 0xf9, 0x35, \
+ 0x7d, 0xb0, 0xe7, 0xe2, 0x34, 0x96, 0x91, 0xbe, 0x32, 0x67, 0x2d, 0x6b, \
+ 0xd3, 0x55, 0x04, 0x8a, 0x01, 0x50, 0xb4, 0xe3, 0x62, 0x78, 0x6c, 0x11, \
+ 0x15, 0xa5, 0x2a, 0x11, 0xc1, 0x49, 0x1c, 0x9b, 0xc4, 0x10, 0x65, 0x60, \
+ 0x87, 0xd9, 0x1e, 0x69, 0x59, 0x4e, 0x8f, 0x6b, 0xeb, 0xc1, 0xfe, 0x6b, \
+ 0xe2, 0x63, 0x78, 0x95, 0x6e, 0xe0, 0x2d, 0xd7, 0xa7, 0x37, 0xa8 \
}
/* END FILE */
@@ -968,54 +968,54 @@
"IwQYMBaAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8MAwGCCqGSM49BAMCBQADaAAwZQIx\r\n" \
"AMqme4DKMldUlplDET9Q6Eptre7uUWKhsLOF+zPkKDlfzpIkJYEFgcloDHGYw80u\r\n" \
"IgIwNftyPXsabTqMM7iEHgVpX/GRozKklY9yQI/5eoA6gGW7Y+imuGR/oao5ySOb\r\n" \
- "a9Vk\r\n" \
+ "a9Vk\r\n" \
"-----END CERTIFICATE-----\r\n"
/* END FILE */
/* This is generated from tests/data_files/cli2.crt.der using `xxd -i`. */
/* BEGIN FILE binary macro TEST_CLI_CRT_EC_DER tests/data_files/cli2.crt.der */
#define TEST_CLI_CRT_EC_DER { \
- 0x30, 0x82, 0x01, 0xdf, 0x30, 0x82, 0x01, 0x63, 0xa0, 0x03, 0x02, 0x01, \
- 0x02, 0x02, 0x01, 0x0d, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \
- 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, \
- 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \
- 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \
- 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, \
- 0x03, 0x0c, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, \
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, \
- 0x17, 0x0d, 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, \
- 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, \
- 0x34, 0x34, 0x34, 0x30, 0x30, 0x5a, 0x30, 0x41, 0x31, 0x0b, 0x30, 0x09, \
- 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \
- 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \
- 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, \
- 0x03, 0x0c, 0x16, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, \
- 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, \
- 0x32, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, \
- 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, \
- 0x03, 0x42, 0x00, 0x04, 0x57, 0xe5, 0xae, 0xb1, 0x73, 0xdf, 0xd3, 0xac, \
- 0xbb, 0x93, 0xb8, 0x81, 0xff, 0x12, 0xae, 0xee, 0xe6, 0x53, 0xac, 0xce, \
- 0x55, 0x53, 0xf6, 0x34, 0x0e, 0xcc, 0x2e, 0xe3, 0x63, 0x25, 0x0b, 0xdf, \
- 0x98, 0xe2, 0xf3, 0x5c, 0x60, 0x36, 0x96, 0xc0, 0xd5, 0x18, 0x14, 0x70, \
- 0xe5, 0x7f, 0x9f, 0xd5, 0x4b, 0x45, 0x18, 0xe5, 0xb0, 0x6c, 0xd5, 0x5c, \
- 0xf8, 0x96, 0x8f, 0x87, 0x70, 0xa3, 0xe4, 0xc7, 0xa3, 0x4d, 0x30, 0x4b, \
- 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, \
- 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x7a, 0x00, \
- 0x5f, 0x86, 0x64, 0xfc, 0xe0, 0x5d, 0xe5, 0x11, 0x10, 0x3b, 0xb2, 0xe6, \
- 0x3b, 0xc4, 0x26, 0x3f, 0xcf, 0xe2, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, \
- 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, \
- 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, \
- 0xfb, 0x36, 0x7c, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \
- 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x31, \
- 0x00, 0xca, 0xa6, 0x7b, 0x80, 0xca, 0x32, 0x57, 0x54, 0x96, 0x99, 0x43, \
- 0x11, 0x3f, 0x50, 0xe8, 0x4a, 0x6d, 0xad, 0xee, 0xee, 0x51, 0x62, 0xa1, \
- 0xb0, 0xb3, 0x85, 0xfb, 0x33, 0xe4, 0x28, 0x39, 0x5f, 0xce, 0x92, 0x24, \
- 0x25, 0x81, 0x05, 0x81, 0xc9, 0x68, 0x0c, 0x71, 0x98, 0xc3, 0xcd, 0x2e, \
- 0x22, 0x02, 0x30, 0x35, 0xfb, 0x72, 0x3d, 0x7b, 0x1a, 0x6d, 0x3a, 0x8c, \
- 0x33, 0xb8, 0x84, 0x1e, 0x05, 0x69, 0x5f, 0xf1, 0x91, 0xa3, 0x32, 0xa4, \
- 0x95, 0x8f, 0x72, 0x40, 0x8f, 0xf9, 0x7a, 0x80, 0x3a, 0x80, 0x65, 0xbb, \
- 0x63, 0xe8, 0xa6, 0xb8, 0x64, 0x7f, 0xa1, 0xaa, 0x39, 0xc9, 0x23, 0x9b, \
- 0x6b, 0xd5, 0x64 \
+ 0x30, 0x82, 0x01, 0xdf, 0x30, 0x82, 0x01, 0x63, 0xa0, 0x03, 0x02, 0x01, \
+ 0x02, 0x02, 0x01, 0x0d, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \
+ 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, \
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \
+ 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \
+ 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, \
+ 0x03, 0x0c, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, \
+ 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, \
+ 0x17, 0x0d, 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, \
+ 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, \
+ 0x34, 0x34, 0x34, 0x30, 0x30, 0x5a, 0x30, 0x41, 0x31, 0x0b, 0x30, 0x09, \
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \
+ 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \
+ 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, \
+ 0x03, 0x0c, 0x16, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, \
+ 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, \
+ 0x32, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, \
+ 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, \
+ 0x03, 0x42, 0x00, 0x04, 0x57, 0xe5, 0xae, 0xb1, 0x73, 0xdf, 0xd3, 0xac, \
+ 0xbb, 0x93, 0xb8, 0x81, 0xff, 0x12, 0xae, 0xee, 0xe6, 0x53, 0xac, 0xce, \
+ 0x55, 0x53, 0xf6, 0x34, 0x0e, 0xcc, 0x2e, 0xe3, 0x63, 0x25, 0x0b, 0xdf, \
+ 0x98, 0xe2, 0xf3, 0x5c, 0x60, 0x36, 0x96, 0xc0, 0xd5, 0x18, 0x14, 0x70, \
+ 0xe5, 0x7f, 0x9f, 0xd5, 0x4b, 0x45, 0x18, 0xe5, 0xb0, 0x6c, 0xd5, 0x5c, \
+ 0xf8, 0x96, 0x8f, 0x87, 0x70, 0xa3, 0xe4, 0xc7, 0xa3, 0x4d, 0x30, 0x4b, \
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, \
+ 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x7a, 0x00, \
+ 0x5f, 0x86, 0x64, 0xfc, 0xe0, 0x5d, 0xe5, 0x11, 0x10, 0x3b, 0xb2, 0xe6, \
+ 0x3b, 0xc4, 0x26, 0x3f, 0xcf, 0xe2, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, \
+ 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, \
+ 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, \
+ 0xfb, 0x36, 0x7c, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \
+ 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x31, \
+ 0x00, 0xca, 0xa6, 0x7b, 0x80, 0xca, 0x32, 0x57, 0x54, 0x96, 0x99, 0x43, \
+ 0x11, 0x3f, 0x50, 0xe8, 0x4a, 0x6d, 0xad, 0xee, 0xee, 0x51, 0x62, 0xa1, \
+ 0xb0, 0xb3, 0x85, 0xfb, 0x33, 0xe4, 0x28, 0x39, 0x5f, 0xce, 0x92, 0x24, \
+ 0x25, 0x81, 0x05, 0x81, 0xc9, 0x68, 0x0c, 0x71, 0x98, 0xc3, 0xcd, 0x2e, \
+ 0x22, 0x02, 0x30, 0x35, 0xfb, 0x72, 0x3d, 0x7b, 0x1a, 0x6d, 0x3a, 0x8c, \
+ 0x33, 0xb8, 0x84, 0x1e, 0x05, 0x69, 0x5f, 0xf1, 0x91, 0xa3, 0x32, 0xa4, \
+ 0x95, 0x8f, 0x72, 0x40, 0x8f, 0xf9, 0x7a, 0x80, 0x3a, 0x80, 0x65, 0xbb, \
+ 0x63, 0xe8, 0xa6, 0xb8, 0x64, 0x7f, 0xa1, 0xaa, 0x39, 0xc9, 0x23, 0x9b, \
+ 0x6b, 0xd5, 0x64 \
}
/* END FILE */
@@ -1075,76 +1075,76 @@
using `xxd -i.` */
/* BEGIN FILE binary macro TEST_CLI_CRT_RSA_DER tests/data_files/cli-rsa-sha256.crt.der */
#define TEST_CLI_CRT_RSA_DER { \
- 0x30, 0x82, 0x03, 0x3f, 0x30, 0x82, 0x02, 0x27, 0xa0, 0x03, 0x02, 0x01, \
- 0x02, 0x02, 0x01, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \
- 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \
- 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \
- 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \
- 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \
- 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \
- 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \
- 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \
- 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \
- 0x34, 0x30, 0x36, 0x5a, 0x30, 0x3c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \
- 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \
- 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \
- 0x53, 0x4c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \
- 0x11, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x6c, \
- 0x69, 0x65, 0x6e, 0x74, 0x20, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, \
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, \
- 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, \
- 0x01, 0x01, 0x00, 0xc8, 0x74, 0xc4, 0xcc, 0xb9, 0xf9, 0xb5, 0x79, 0xe9, \
- 0x45, 0xd9, 0x14, 0x60, 0xb0, 0x7d, 0xbb, 0x93, 0xf2, 0x6b, 0x1e, 0x9f, \
- 0x33, 0xad, 0x0d, 0x8f, 0x8a, 0x3c, 0x56, 0x65, 0xe5, 0xdc, 0x44, 0xd9, \
- 0xcc, 0x66, 0x85, 0x07, 0xd5, 0xf8, 0x27, 0xb0, 0x4a, 0x35, 0xd0, 0x63, \
- 0x9e, 0x0a, 0x6e, 0x1b, 0xb7, 0xda, 0xf0, 0x7e, 0xab, 0xee, 0x0c, 0x10, \
- 0x93, 0x86, 0x49, 0x18, 0x34, 0xf3, 0xa8, 0x2a, 0xd2, 0x57, 0xf5, 0x2e, \
- 0xd4, 0x2f, 0x77, 0x29, 0x84, 0x61, 0x4d, 0x82, 0x50, 0x8f, 0xa7, 0x95, \
- 0x48, 0x70, 0xf5, 0x6e, 0x4d, 0xb2, 0xd5, 0x13, 0xc3, 0xd2, 0x1a, 0xed, \
- 0xe6, 0x43, 0xea, 0x42, 0x14, 0xeb, 0x74, 0xea, 0xc0, 0xed, 0x1f, 0xd4, \
- 0x57, 0x4e, 0xa9, 0xf3, 0xa8, 0xed, 0xd2, 0xe0, 0xc1, 0x30, 0x71, 0x30, \
- 0x32, 0x30, 0xd5, 0xd3, 0xf6, 0x08, 0xd0, 0x56, 0x4f, 0x46, 0x8e, 0xf2, \
- 0x5f, 0xf9, 0x3d, 0x67, 0x91, 0x88, 0x30, 0x2e, 0x42, 0xb2, 0xdf, 0x7d, \
- 0xfb, 0xe5, 0x0c, 0x77, 0xff, 0xec, 0x31, 0xc0, 0x78, 0x8f, 0xbf, 0xc2, \
- 0x7f, 0xca, 0xad, 0x6c, 0x21, 0xd6, 0x8d, 0xd9, 0x8b, 0x6a, 0x8e, 0x6f, \
- 0xe0, 0x9b, 0xf8, 0x10, 0x56, 0xcc, 0xb3, 0x8e, 0x13, 0x15, 0xe6, 0x34, \
- 0x04, 0x66, 0xc7, 0xee, 0xf9, 0x36, 0x0e, 0x6a, 0x95, 0xf6, 0x09, 0x9a, \
- 0x06, 0x67, 0xf4, 0x65, 0x71, 0xf8, 0xca, 0xa4, 0xb1, 0x25, 0xe0, 0xfe, \
- 0x3c, 0x8b, 0x35, 0x04, 0x67, 0xba, 0xe0, 0x4f, 0x76, 0x85, 0xfc, 0x7f, \
- 0xfc, 0x36, 0x6b, 0xb5, 0xe9, 0xcd, 0x2d, 0x03, 0x62, 0x4e, 0xb3, 0x3d, \
- 0x00, 0xcf, 0xaf, 0x76, 0xa0, 0x69, 0x56, 0x83, 0x6a, 0xd2, 0xa8, 0xd4, \
- 0xe7, 0x50, 0x71, 0xe6, 0xb5, 0x36, 0x05, 0x77, 0x05, 0x6d, 0x7b, 0xc8, \
- 0xe4, 0xc4, 0xfd, 0x4c, 0xd5, 0x21, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01, \
- 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, \
- 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, \
- 0x04, 0x14, 0x71, 0xa1, 0x00, 0x73, 0x72, 0x40, 0x2f, 0x54, 0x76, 0x5e, \
- 0x33, 0xfc, 0x52, 0x8f, 0xbc, 0xf1, 0xdd, 0x6b, 0x46, 0x21, 0x30, 0x1f, \
- 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xb4, \
- 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, 0xa6, 0x95, \
- 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, \
- 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, \
- 0x01, 0x01, 0x00, 0x5e, 0x27, 0x6f, 0xd5, 0xde, 0x29, 0x2e, 0x50, 0x62, \
- 0x29, 0x61, 0x03, 0xf7, 0x9a, 0xcc, 0xc9, 0xc0, 0x5d, 0x80, 0x37, 0x20, \
- 0xc8, 0xda, 0x89, 0xc5, 0xa9, 0x05, 0x91, 0x17, 0xd1, 0xc8, 0x0d, 0xb2, \
- 0xd6, 0x69, 0x72, 0x4e, 0x7e, 0xee, 0x05, 0x74, 0x64, 0x34, 0xb6, 0x39, \
- 0x64, 0x5c, 0xca, 0xf3, 0x61, 0x82, 0x8e, 0x4d, 0x90, 0xd8, 0xe0, 0xf8, \
- 0x45, 0x94, 0x82, 0x3c, 0x02, 0x49, 0xa8, 0xba, 0x47, 0x1d, 0x4d, 0xf8, \
- 0xb7, 0xbd, 0x5c, 0x89, 0xf7, 0xef, 0xcb, 0x62, 0x8a, 0xf3, 0x56, 0x2f, \
- 0xaf, 0x17, 0x33, 0x46, 0x13, 0x00, 0x13, 0xae, 0x22, 0xfa, 0xa9, 0xda, \
- 0xc8, 0xfd, 0xd3, 0x77, 0x65, 0xee, 0x58, 0x94, 0x74, 0xe4, 0xf5, 0x4f, \
- 0xa1, 0x27, 0xa6, 0xb0, 0xd1, 0x0b, 0xb3, 0xd8, 0x16, 0xb6, 0xd7, 0x67, \
- 0x63, 0x2d, 0xdc, 0x7b, 0xe1, 0x18, 0xd9, 0x8d, 0x27, 0xed, 0x1b, 0x22, \
- 0xef, 0xdf, 0x36, 0x11, 0xe2, 0xc8, 0x00, 0x0e, 0xc7, 0xe9, 0xc6, 0xb8, \
- 0xd8, 0x4b, 0x3f, 0x35, 0x41, 0xff, 0xfc, 0x96, 0x49, 0x4f, 0x7d, 0x8e, \
- 0x3f, 0x47, 0x68, 0x33, 0x17, 0x83, 0x44, 0x0f, 0xaf, 0xa6, 0x59, 0x0a, \
- 0xa9, 0x32, 0xcb, 0x59, 0xfe, 0xdd, 0x5f, 0x6e, 0x8b, 0x22, 0xb8, 0x81, \
- 0x90, 0x16, 0x91, 0x0a, 0x04, 0x79, 0x62, 0xff, 0x4b, 0x04, 0xf1, 0x5c, \
- 0x34, 0xeb, 0x69, 0xce, 0xef, 0xcb, 0x6e, 0xb6, 0x3b, 0x40, 0x55, 0xca, \
- 0x24, 0xc2, 0x3e, 0x25, 0x70, 0xee, 0x74, 0x2b, 0x0e, 0x9f, 0xc2, 0x82, \
- 0x9a, 0x20, 0x38, 0x77, 0xa1, 0x26, 0x8a, 0xca, 0x9f, 0x87, 0x75, 0x77, \
- 0xe3, 0xce, 0x65, 0xec, 0x71, 0x10, 0x35, 0xcb, 0xcb, 0x4f, 0x19, 0x43, \
- 0xeb, 0x30, 0xd0, 0xca, 0x2d, 0x3f, 0xca, 0x46, 0x14, 0x61, 0x99, 0x30, \
- 0x41, 0x32, 0xb5, 0x37, 0x63, 0x6f, 0x97 \
+ 0x30, 0x82, 0x03, 0x3f, 0x30, 0x82, 0x02, 0x27, 0xa0, 0x03, 0x02, 0x01, \
+ 0x02, 0x02, 0x01, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \
+ 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \
+ 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \
+ 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \
+ 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \
+ 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \
+ 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \
+ 0x34, 0x30, 0x36, 0x5a, 0x30, 0x3c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \
+ 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \
+ 0x53, 0x4c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \
+ 0x11, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x6c, \
+ 0x69, 0x65, 0x6e, 0x74, 0x20, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, \
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, \
+ 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, \
+ 0x01, 0x01, 0x00, 0xc8, 0x74, 0xc4, 0xcc, 0xb9, 0xf9, 0xb5, 0x79, 0xe9, \
+ 0x45, 0xd9, 0x14, 0x60, 0xb0, 0x7d, 0xbb, 0x93, 0xf2, 0x6b, 0x1e, 0x9f, \
+ 0x33, 0xad, 0x0d, 0x8f, 0x8a, 0x3c, 0x56, 0x65, 0xe5, 0xdc, 0x44, 0xd9, \
+ 0xcc, 0x66, 0x85, 0x07, 0xd5, 0xf8, 0x27, 0xb0, 0x4a, 0x35, 0xd0, 0x63, \
+ 0x9e, 0x0a, 0x6e, 0x1b, 0xb7, 0xda, 0xf0, 0x7e, 0xab, 0xee, 0x0c, 0x10, \
+ 0x93, 0x86, 0x49, 0x18, 0x34, 0xf3, 0xa8, 0x2a, 0xd2, 0x57, 0xf5, 0x2e, \
+ 0xd4, 0x2f, 0x77, 0x29, 0x84, 0x61, 0x4d, 0x82, 0x50, 0x8f, 0xa7, 0x95, \
+ 0x48, 0x70, 0xf5, 0x6e, 0x4d, 0xb2, 0xd5, 0x13, 0xc3, 0xd2, 0x1a, 0xed, \
+ 0xe6, 0x43, 0xea, 0x42, 0x14, 0xeb, 0x74, 0xea, 0xc0, 0xed, 0x1f, 0xd4, \
+ 0x57, 0x4e, 0xa9, 0xf3, 0xa8, 0xed, 0xd2, 0xe0, 0xc1, 0x30, 0x71, 0x30, \
+ 0x32, 0x30, 0xd5, 0xd3, 0xf6, 0x08, 0xd0, 0x56, 0x4f, 0x46, 0x8e, 0xf2, \
+ 0x5f, 0xf9, 0x3d, 0x67, 0x91, 0x88, 0x30, 0x2e, 0x42, 0xb2, 0xdf, 0x7d, \
+ 0xfb, 0xe5, 0x0c, 0x77, 0xff, 0xec, 0x31, 0xc0, 0x78, 0x8f, 0xbf, 0xc2, \
+ 0x7f, 0xca, 0xad, 0x6c, 0x21, 0xd6, 0x8d, 0xd9, 0x8b, 0x6a, 0x8e, 0x6f, \
+ 0xe0, 0x9b, 0xf8, 0x10, 0x56, 0xcc, 0xb3, 0x8e, 0x13, 0x15, 0xe6, 0x34, \
+ 0x04, 0x66, 0xc7, 0xee, 0xf9, 0x36, 0x0e, 0x6a, 0x95, 0xf6, 0x09, 0x9a, \
+ 0x06, 0x67, 0xf4, 0x65, 0x71, 0xf8, 0xca, 0xa4, 0xb1, 0x25, 0xe0, 0xfe, \
+ 0x3c, 0x8b, 0x35, 0x04, 0x67, 0xba, 0xe0, 0x4f, 0x76, 0x85, 0xfc, 0x7f, \
+ 0xfc, 0x36, 0x6b, 0xb5, 0xe9, 0xcd, 0x2d, 0x03, 0x62, 0x4e, 0xb3, 0x3d, \
+ 0x00, 0xcf, 0xaf, 0x76, 0xa0, 0x69, 0x56, 0x83, 0x6a, 0xd2, 0xa8, 0xd4, \
+ 0xe7, 0x50, 0x71, 0xe6, 0xb5, 0x36, 0x05, 0x77, 0x05, 0x6d, 0x7b, 0xc8, \
+ 0xe4, 0xc4, 0xfd, 0x4c, 0xd5, 0x21, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01, \
+ 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, \
+ 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, \
+ 0x04, 0x14, 0x71, 0xa1, 0x00, 0x73, 0x72, 0x40, 0x2f, 0x54, 0x76, 0x5e, \
+ 0x33, 0xfc, 0x52, 0x8f, 0xbc, 0xf1, 0xdd, 0x6b, 0x46, 0x21, 0x30, 0x1f, \
+ 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xb4, \
+ 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, 0xa6, 0x95, \
+ 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, \
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, \
+ 0x01, 0x01, 0x00, 0x5e, 0x27, 0x6f, 0xd5, 0xde, 0x29, 0x2e, 0x50, 0x62, \
+ 0x29, 0x61, 0x03, 0xf7, 0x9a, 0xcc, 0xc9, 0xc0, 0x5d, 0x80, 0x37, 0x20, \
+ 0xc8, 0xda, 0x89, 0xc5, 0xa9, 0x05, 0x91, 0x17, 0xd1, 0xc8, 0x0d, 0xb2, \
+ 0xd6, 0x69, 0x72, 0x4e, 0x7e, 0xee, 0x05, 0x74, 0x64, 0x34, 0xb6, 0x39, \
+ 0x64, 0x5c, 0xca, 0xf3, 0x61, 0x82, 0x8e, 0x4d, 0x90, 0xd8, 0xe0, 0xf8, \
+ 0x45, 0x94, 0x82, 0x3c, 0x02, 0x49, 0xa8, 0xba, 0x47, 0x1d, 0x4d, 0xf8, \
+ 0xb7, 0xbd, 0x5c, 0x89, 0xf7, 0xef, 0xcb, 0x62, 0x8a, 0xf3, 0x56, 0x2f, \
+ 0xaf, 0x17, 0x33, 0x46, 0x13, 0x00, 0x13, 0xae, 0x22, 0xfa, 0xa9, 0xda, \
+ 0xc8, 0xfd, 0xd3, 0x77, 0x65, 0xee, 0x58, 0x94, 0x74, 0xe4, 0xf5, 0x4f, \
+ 0xa1, 0x27, 0xa6, 0xb0, 0xd1, 0x0b, 0xb3, 0xd8, 0x16, 0xb6, 0xd7, 0x67, \
+ 0x63, 0x2d, 0xdc, 0x7b, 0xe1, 0x18, 0xd9, 0x8d, 0x27, 0xed, 0x1b, 0x22, \
+ 0xef, 0xdf, 0x36, 0x11, 0xe2, 0xc8, 0x00, 0x0e, 0xc7, 0xe9, 0xc6, 0xb8, \
+ 0xd8, 0x4b, 0x3f, 0x35, 0x41, 0xff, 0xfc, 0x96, 0x49, 0x4f, 0x7d, 0x8e, \
+ 0x3f, 0x47, 0x68, 0x33, 0x17, 0x83, 0x44, 0x0f, 0xaf, 0xa6, 0x59, 0x0a, \
+ 0xa9, 0x32, 0xcb, 0x59, 0xfe, 0xdd, 0x5f, 0x6e, 0x8b, 0x22, 0xb8, 0x81, \
+ 0x90, 0x16, 0x91, 0x0a, 0x04, 0x79, 0x62, 0xff, 0x4b, 0x04, 0xf1, 0x5c, \
+ 0x34, 0xeb, 0x69, 0xce, 0xef, 0xcb, 0x6e, 0xb6, 0x3b, 0x40, 0x55, 0xca, \
+ 0x24, 0xc2, 0x3e, 0x25, 0x70, 0xee, 0x74, 0x2b, 0x0e, 0x9f, 0xc2, 0x82, \
+ 0x9a, 0x20, 0x38, 0x77, 0xa1, 0x26, 0x8a, 0xca, 0x9f, 0x87, 0x75, 0x77, \
+ 0xe3, 0xce, 0x65, 0xec, 0x71, 0x10, 0x35, 0xcb, 0xcb, 0x4f, 0x19, 0x43, \
+ 0xeb, 0x30, 0xd0, 0xca, 0x2d, 0x3f, 0xca, 0x46, 0x14, 0x61, 0x99, 0x30, \
+ 0x41, 0x32, 0xb5, 0x37, 0x63, 0x6f, 0x97 \
}
/* END FILE */
@@ -1618,7 +1618,6 @@
#define TEST_CLI_KEY TEST_CLI_KEY_EC
#define TEST_CLI_PWD TEST_CLI_PWD_EC
#define TEST_CLI_CRT TEST_CLI_CRT_EC
-
#endif /* MBEDTLS_RSA_C */
/* API stability forces us to declare
diff --git a/lib/libmbedtls/mbedtls/library/chacha20.c b/lib/libmbedtls/mbedtls/library/chacha20.c
index 2c9042a..f991b21 100644
--- a/lib/libmbedtls/mbedtls/library/chacha20.c
+++ b/lib/libmbedtls/mbedtls/library/chacha20.c
@@ -33,6 +33,7 @@
#include "mbedtls/chacha20.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <stddef.h>
#include <string.h>
@@ -325,7 +326,7 @@
unsigned char* output )
{
mbedtls_chacha20_context ctx;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
CHACHA20_VALIDATE_RET( key != NULL );
CHACHA20_VALIDATE_RET( nonce != NULL );
@@ -536,7 +537,7 @@
{
unsigned char output[381];
unsigned i;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
for( i = 0U; i < 2U; i++ )
{
diff --git a/lib/libmbedtls/mbedtls/library/chachapoly.c b/lib/libmbedtls/mbedtls/library/chachapoly.c
index 2599b2a..117521f 100644
--- a/lib/libmbedtls/mbedtls/library/chachapoly.c
+++ b/lib/libmbedtls/mbedtls/library/chachapoly.c
@@ -30,6 +30,7 @@
#include "mbedtls/chachapoly.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -122,7 +123,7 @@
int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
const unsigned char key[32] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( key != NULL );
@@ -135,7 +136,7 @@
const unsigned char nonce[12],
mbedtls_chachapoly_mode_t mode )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char poly1305_key[64];
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( nonce != NULL );
@@ -191,7 +192,7 @@
const unsigned char *input,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL );
CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL );
@@ -240,7 +241,7 @@
int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
unsigned char mac[16] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char len_block[16];
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( mac != NULL );
@@ -304,7 +305,7 @@
unsigned char *output,
unsigned char tag[16] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
if( ret != 0 )
@@ -354,7 +355,7 @@
const unsigned char *input,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char check_tag[16];
size_t i;
int diff;
@@ -492,7 +493,7 @@
{
mbedtls_chachapoly_context ctx;
unsigned i;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char output[200];
unsigned char mac[16];
diff --git a/lib/libmbedtls/mbedtls/library/cipher.c b/lib/libmbedtls/mbedtls/library/cipher.c
index 31123c5..21235ff 100644
--- a/lib/libmbedtls/mbedtls/library/cipher.c
+++ b/lib/libmbedtls/mbedtls/library/cipher.c
@@ -34,6 +34,7 @@
#include "mbedtls/cipher.h"
#include "mbedtls/cipher_internal.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <stdlib.h>
#include <string.h>
@@ -58,6 +59,15 @@
#include "mbedtls/cmac.h"
#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_NIST_KW_C)
+#include "mbedtls/nist_kw.h"
+#endif
+
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
@@ -76,7 +86,8 @@
* a non-zero value.
* This is currently only used by GCM and ChaCha20+Poly1305.
*/
-static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t len )
+static int mbedtls_constant_time_memcmp( const void *v1, const void *v2,
+ size_t len )
{
const unsigned char *p1 = (const unsigned char*) v1;
const unsigned char *p2 = (const unsigned char*) v2;
@@ -113,7 +124,8 @@
return( mbedtls_cipher_supported );
}
-const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type )
+const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type(
+ const mbedtls_cipher_type_t cipher_type )
{
const mbedtls_cipher_definition_t *def;
@@ -124,7 +136,8 @@
return( NULL );
}
-const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name )
+const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string(
+ const char *cipher_name )
{
const mbedtls_cipher_definition_t *def;
@@ -138,9 +151,10 @@
return( NULL );
}
-const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id,
- int key_bitlen,
- const mbedtls_cipher_mode_t mode )
+const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(
+ const mbedtls_cipher_id_t cipher_id,
+ int key_bitlen,
+ const mbedtls_cipher_mode_t mode )
{
const mbedtls_cipher_definition_t *def;
@@ -164,6 +178,29 @@
if( ctx == NULL )
return;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( ctx->psa_enabled == 1 )
+ {
+ if( ctx->cipher_ctx != NULL )
+ {
+ mbedtls_cipher_context_psa * const cipher_psa =
+ (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
+
+ if( cipher_psa->slot_state == MBEDTLS_CIPHER_PSA_KEY_OWNED )
+ {
+ /* xxx_free() doesn't allow to return failures. */
+ (void) psa_destroy_key( cipher_psa->slot );
+ }
+
+ mbedtls_platform_zeroize( cipher_psa, sizeof( *cipher_psa ) );
+ mbedtls_free( cipher_psa );
+ }
+
+ mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) );
+ return;
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
#if defined(MBEDTLS_CMAC_C)
if( ctx->cmac_ctx )
{
@@ -209,7 +246,8 @@
return( 0 );
}
-int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info )
+int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx,
+ const mbedtls_cipher_info_t *cipher_info )
{
CIPHER_VALIDATE_RET( ctx != NULL );
if( cipher_info == NULL )
@@ -236,6 +274,38 @@
return( 0 );
}
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx,
+ const mbedtls_cipher_info_t *cipher_info,
+ size_t taglen )
+{
+ psa_algorithm_t alg;
+ mbedtls_cipher_context_psa *cipher_psa;
+
+ if( NULL == cipher_info || NULL == ctx )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ /* Check that the underlying cipher mode and cipher type are
+ * supported by the underlying PSA Crypto implementation. */
+ alg = mbedtls_psa_translate_cipher_mode( cipher_info->mode, taglen );
+ if( alg == 0 )
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+ if( mbedtls_psa_translate_cipher_type( cipher_info->type ) == 0 )
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+
+ memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
+
+ cipher_psa = mbedtls_calloc( 1, sizeof(mbedtls_cipher_context_psa ) );
+ if( cipher_psa == NULL )
+ return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
+ cipher_psa->alg = alg;
+ ctx->cipher_ctx = cipher_psa;
+ ctx->cipher_info = cipher_info;
+ ctx->psa_enabled = 1;
+ return( 0 );
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
int mbedtls_cipher_setup_info( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info )
{
if( NULL == cipher_info || NULL == ctx )
@@ -257,6 +327,64 @@
if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( ctx->psa_enabled == 1 )
+ {
+ mbedtls_cipher_context_psa * const cipher_psa =
+ (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
+
+ size_t const key_bytelen = ( (size_t) key_bitlen + 7 ) / 8;
+
+ psa_status_t status;
+ psa_key_type_t key_type;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ /* PSA Crypto API only accepts byte-aligned keys. */
+ if( key_bitlen % 8 != 0 )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ /* Don't allow keys to be set multiple times. */
+ if( cipher_psa->slot_state != MBEDTLS_CIPHER_PSA_KEY_UNSET )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ key_type = mbedtls_psa_translate_cipher_type(
+ ctx->cipher_info->type );
+ if( key_type == 0 )
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+ psa_set_key_type( &attributes, key_type );
+
+ /* Mbed TLS' cipher layer doesn't enforce the mode of operation
+ * (encrypt vs. decrypt): it is possible to setup a key for encryption
+ * and use it for AEAD decryption. Until tests relying on this
+ * are changed, allow any usage in PSA. */
+ psa_set_key_usage_flags( &attributes,
+ /* mbedtls_psa_translate_cipher_operation( operation ); */
+ PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
+ psa_set_key_algorithm( &attributes, cipher_psa->alg );
+
+ status = psa_import_key( &attributes, key, key_bytelen,
+ &cipher_psa->slot );
+ switch( status )
+ {
+ case PSA_SUCCESS:
+ break;
+ case PSA_ERROR_INSUFFICIENT_MEMORY:
+ return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
+ case PSA_ERROR_NOT_SUPPORTED:
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+ default:
+ return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
+ }
+ /* Indicate that we own the key slot and need to
+ * destroy it in mbedtls_cipher_free(). */
+ cipher_psa->slot_state = MBEDTLS_CIPHER_PSA_KEY_OWNED;
+
+ ctx->key_bitlen = key_bitlen;
+ ctx->operation = operation;
+ return( 0 );
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 &&
(int) ctx->cipher_info->key_bitlen != key_bitlen )
{
@@ -295,6 +423,15 @@
CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( ctx->psa_enabled == 1 )
+ {
+ /* While PSA Crypto has an API for multipart
+ * operations, we currently don't make it
+ * accessible through the cipher layer. */
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
/* avoid buffer overflow in ctx->iv */
if( iv_len > MBEDTLS_MAX_IV_LENGTH )
@@ -338,6 +475,15 @@
if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( ctx->psa_enabled == 1 )
+ {
+ /* We don't support resetting PSA-based
+ * cipher contexts, yet. */
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
ctx->unprocessed_len = 0;
return( 0 );
@@ -352,6 +498,16 @@
if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( ctx->psa_enabled == 1 )
+ {
+ /* While PSA Crypto has an API for multipart
+ * operations, we currently don't make it
+ * accessible through the cipher layer. */
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
@@ -388,7 +544,7 @@
int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
size_t ilen, unsigned char *output, size_t *olen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t block_size;
CIPHER_VALIDATE_RET( ctx != NULL );
@@ -398,6 +554,16 @@
if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( ctx->psa_enabled == 1 )
+ {
+ /* While PSA Crypto has an API for multipart
+ * operations, we currently don't make it
+ * accessible through the cipher layer. */
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
*olen = 0;
block_size = mbedtls_cipher_get_block_size( ctx );
if ( 0 == block_size )
@@ -801,6 +967,16 @@
if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( ctx->psa_enabled == 1 )
+ {
+ /* While PSA Crypto has an API for multipart
+ * operations, we currently don't make it
+ * accessible through the cipher layer. */
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
*olen = 0;
if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
@@ -893,6 +1069,19 @@
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( ctx->psa_enabled == 1 )
+ {
+ /* While PSA Crypto knows about CBC padding
+ * schemes, we currently don't make them
+ * accessible through the cipher layer. */
+ if( mode != MBEDTLS_PADDING_NONE )
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+
+ return( 0 );
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
switch( mode )
{
#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
@@ -944,6 +1133,16 @@
if( MBEDTLS_ENCRYPT != ctx->operation )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( ctx->psa_enabled == 1 )
+ {
+ /* While PSA Crypto has an API for multipart
+ * operations, we currently don't make it
+ * accessible through the cipher layer. */
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx,
@@ -957,8 +1156,8 @@
if ( tag_len != 16U )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
- return( mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
- tag ) );
+ return( mbedtls_chachapoly_finish(
+ (mbedtls_chachapoly_context*) ctx->cipher_ctx, tag ) );
}
#endif
@@ -969,7 +1168,7 @@
const unsigned char *tag, size_t tag_len )
{
unsigned char check_tag[16];
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
CIPHER_VALIDATE_RET( ctx != NULL );
CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
@@ -981,14 +1180,25 @@
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( ctx->psa_enabled == 1 )
+ {
+ /* While PSA Crypto has an API for multipart
+ * operations, we currently don't make it
+ * accessible through the cipher layer. */
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
if( tag_len > sizeof( check_tag ) )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
- if( 0 != ( ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx,
- check_tag, tag_len ) ) )
+ if( 0 != ( ret = mbedtls_gcm_finish(
+ (mbedtls_gcm_context *) ctx->cipher_ctx,
+ check_tag, tag_len ) ) )
{
return( ret );
}
@@ -1008,8 +1218,8 @@
if ( tag_len != sizeof( check_tag ) )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
- ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx,
- check_tag );
+ ret = mbedtls_chachapoly_finish(
+ (mbedtls_chachapoly_context*) ctx->cipher_ctx, check_tag );
if ( ret != 0 )
{
return( ret );
@@ -1035,7 +1245,7 @@
const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t finish_olen;
CIPHER_VALIDATE_RET( ctx != NULL );
@@ -1044,16 +1254,76 @@
CIPHER_VALIDATE_RET( output != NULL );
CIPHER_VALIDATE_RET( olen != NULL );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( ctx->psa_enabled == 1 )
+ {
+ /* As in the non-PSA case, we don't check that
+ * a key has been set. If not, the key slot will
+ * still be in its default state of 0, which is
+ * guaranteed to be invalid, hence the PSA-call
+ * below will gracefully fail. */
+ mbedtls_cipher_context_psa * const cipher_psa =
+ (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
+
+ psa_status_t status;
+ psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT;
+ size_t part_len;
+
+ if( ctx->operation == MBEDTLS_DECRYPT )
+ {
+ status = psa_cipher_decrypt_setup( &cipher_op,
+ cipher_psa->slot,
+ cipher_psa->alg );
+ }
+ else if( ctx->operation == MBEDTLS_ENCRYPT )
+ {
+ status = psa_cipher_encrypt_setup( &cipher_op,
+ cipher_psa->slot,
+ cipher_psa->alg );
+ }
+ else
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
+ /* In the following, we can immediately return on an error,
+ * because the PSA Crypto API guarantees that cipher operations
+ * are terminated by unsuccessful calls to psa_cipher_update(),
+ * and by any call to psa_cipher_finish(). */
+ if( status != PSA_SUCCESS )
+ return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
+
+ status = psa_cipher_set_iv( &cipher_op, iv, iv_len );
+ if( status != PSA_SUCCESS )
+ return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
+
+ status = psa_cipher_update( &cipher_op,
+ input, ilen,
+ output, ilen, olen );
+ if( status != PSA_SUCCESS )
+ return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
+
+ status = psa_cipher_finish( &cipher_op,
+ output + *olen, ilen - *olen,
+ &part_len );
+ if( status != PSA_SUCCESS )
+ return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
+
+ *olen += part_len;
+ return( 0 );
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 )
return( ret );
if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 )
return( ret );
- if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 )
+ if( ( ret = mbedtls_cipher_update( ctx, input, ilen,
+ output, olen ) ) != 0 )
return( ret );
- if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 )
+ if( ( ret = mbedtls_cipher_finish( ctx, output + *olen,
+ &finish_olen ) ) != 0 )
return( ret );
*olen += finish_olen;
@@ -1080,13 +1350,45 @@
CIPHER_VALIDATE_RET( olen != NULL );
CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( ctx->psa_enabled == 1 )
+ {
+ /* As in the non-PSA case, we don't check that
+ * a key has been set. If not, the key slot will
+ * still be in its default state of 0, which is
+ * guaranteed to be invalid, hence the PSA-call
+ * below will gracefully fail. */
+ mbedtls_cipher_context_psa * const cipher_psa =
+ (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
+
+ psa_status_t status;
+
+ /* PSA Crypto API always writes the authentication tag
+ * at the end of the encrypted message. */
+ if( tag != output + ilen )
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+
+ status = psa_aead_encrypt( cipher_psa->slot,
+ cipher_psa->alg,
+ iv, iv_len,
+ ad, ad_len,
+ input, ilen,
+ output, ilen + tag_len, olen );
+ if( status != PSA_SUCCESS )
+ return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
+
+ *olen -= tag_len;
+ return( 0 );
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
*olen = ilen;
- return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen,
- iv, iv_len, ad, ad_len, input, output,
- tag_len, tag ) );
+ return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT,
+ ilen, iv, iv_len, ad, ad_len,
+ input, output, tag_len, tag ) );
}
#endif /* MBEDTLS_GCM_C */
#if defined(MBEDTLS_CCM_C)
@@ -1113,6 +1415,22 @@
ilen, iv, ad, ad_len, input, output, tag ) );
}
#endif /* MBEDTLS_CHACHAPOLY_C */
+#if defined(MBEDTLS_NIST_KW_C)
+ if( MBEDTLS_MODE_KW == ctx->cipher_info->mode ||
+ MBEDTLS_MODE_KWP == ctx->cipher_info->mode )
+ {
+ mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ?
+ MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP;
+
+ /* There is no iv, tag or ad associated with KW and KWP, these length should be 0 */
+ if( iv_len != 0 || tag_len != 0 || ad_len != 0 )
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ return( mbedtls_nist_kw_wrap( ctx->cipher_ctx, mode, input, ilen, output, olen, SIZE_MAX ) );
+ }
+#endif /* MBEDTLS_NIST_KW_C */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
@@ -1135,10 +1453,43 @@
CIPHER_VALIDATE_RET( olen != NULL );
CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( ctx->psa_enabled == 1 )
+ {
+ /* As in the non-PSA case, we don't check that
+ * a key has been set. If not, the key slot will
+ * still be in its default state of 0, which is
+ * guaranteed to be invalid, hence the PSA-call
+ * below will gracefully fail. */
+ mbedtls_cipher_context_psa * const cipher_psa =
+ (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
+
+ psa_status_t status;
+
+ /* PSA Crypto API always writes the authentication tag
+ * at the end of the encrypted message. */
+ if( tag != input + ilen )
+ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+
+ status = psa_aead_decrypt( cipher_psa->slot,
+ cipher_psa->alg,
+ iv, iv_len,
+ ad, ad_len,
+ input, ilen + tag_len,
+ output, ilen, olen );
+ if( status == PSA_ERROR_INVALID_SIGNATURE )
+ return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
+ else if( status != PSA_SUCCESS )
+ return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
+
+ return( 0 );
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
*olen = ilen;
ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen,
@@ -1154,7 +1505,7 @@
#if defined(MBEDTLS_CCM_C)
if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
*olen = ilen;
ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen,
@@ -1170,7 +1521,7 @@
#if defined(MBEDTLS_CHACHAPOLY_C)
if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* ChachaPoly has fixed length nonce and MAC (tag) */
if ( ( iv_len != ctx->cipher_info->iv_size ) ||
@@ -1189,6 +1540,22 @@
return( ret );
}
#endif /* MBEDTLS_CHACHAPOLY_C */
+#if defined(MBEDTLS_NIST_KW_C)
+ if( MBEDTLS_MODE_KW == ctx->cipher_info->mode ||
+ MBEDTLS_MODE_KWP == ctx->cipher_info->mode )
+ {
+ mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ?
+ MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP;
+
+ /* There is no iv, tag or ad associated with KW and KWP, these length should be 0 */
+ if( iv_len != 0 || tag_len != 0 || ad_len != 0 )
+ {
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+ }
+
+ return( mbedtls_nist_kw_unwrap( ctx->cipher_ctx, mode, input, ilen, output, olen, SIZE_MAX ) );
+ }
+#endif /* MBEDTLS_NIST_KW_C */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
diff --git a/lib/libmbedtls/mbedtls/library/cipher_wrap.c b/lib/libmbedtls/mbedtls/library/cipher_wrap.c
index df55bbd..f0c3614 100644
--- a/lib/libmbedtls/mbedtls/library/cipher_wrap.c
+++ b/lib/libmbedtls/mbedtls/library/cipher_wrap.c
@@ -34,6 +34,7 @@
#if defined(MBEDTLS_CIPHER_C)
#include "mbedtls/cipher_internal.h"
+#include "mbedtls/error.h"
#if defined(MBEDTLS_CHACHAPOLY_C)
#include "mbedtls/chachapoly.h"
@@ -75,6 +76,10 @@
#include "mbedtls/ccm.h"
#endif
+#if defined(MBEDTLS_NIST_KW_C)
+#include "mbedtls/nist_kw.h"
+#endif
+
#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
#include <string.h>
#endif
@@ -1965,7 +1970,7 @@
const unsigned char *input,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ret = mbedtls_chacha20_update( ctx, length, input, output );
if( ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
@@ -2179,6 +2184,131 @@
};
#endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */
+#if defined(MBEDTLS_NIST_KW_C)
+static void *kw_ctx_alloc( void )
+{
+ void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_nist_kw_context ) );
+
+ if( ctx != NULL )
+ mbedtls_nist_kw_init( (mbedtls_nist_kw_context *) ctx );
+
+ return( ctx );
+}
+
+static void kw_ctx_free( void *ctx )
+{
+ mbedtls_nist_kw_free( ctx );
+ mbedtls_free( ctx );
+}
+
+static int kw_aes_setkey_wrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedtls_nist_kw_setkey( (mbedtls_nist_kw_context *) ctx,
+ MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 1 );
+}
+
+static int kw_aes_setkey_unwrap( void *ctx, const unsigned char *key,
+ unsigned int key_bitlen )
+{
+ return mbedtls_nist_kw_setkey( (mbedtls_nist_kw_context *) ctx,
+ MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 0 );
+}
+
+static const mbedtls_cipher_base_t kw_aes_info = {
+ MBEDTLS_CIPHER_ID_AES,
+ NULL,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+ NULL,
+#endif
+ kw_aes_setkey_wrap,
+ kw_aes_setkey_unwrap,
+ kw_ctx_alloc,
+ kw_ctx_free,
+};
+
+static const mbedtls_cipher_info_t aes_128_nist_kw_info = {
+ MBEDTLS_CIPHER_AES_128_KW,
+ MBEDTLS_MODE_KW,
+ 128,
+ "AES-128-KW",
+ 0,
+ 0,
+ 16,
+ &kw_aes_info
+};
+
+static const mbedtls_cipher_info_t aes_192_nist_kw_info = {
+ MBEDTLS_CIPHER_AES_192_KW,
+ MBEDTLS_MODE_KW,
+ 192,
+ "AES-192-KW",
+ 0,
+ 0,
+ 16,
+ &kw_aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_nist_kw_info = {
+ MBEDTLS_CIPHER_AES_256_KW,
+ MBEDTLS_MODE_KW,
+ 256,
+ "AES-256-KW",
+ 0,
+ 0,
+ 16,
+ &kw_aes_info
+};
+
+static const mbedtls_cipher_info_t aes_128_nist_kwp_info = {
+ MBEDTLS_CIPHER_AES_128_KWP,
+ MBEDTLS_MODE_KWP,
+ 128,
+ "AES-128-KWP",
+ 0,
+ 0,
+ 16,
+ &kw_aes_info
+};
+
+static const mbedtls_cipher_info_t aes_192_nist_kwp_info = {
+ MBEDTLS_CIPHER_AES_192_KWP,
+ MBEDTLS_MODE_KWP,
+ 192,
+ "AES-192-KWP",
+ 0,
+ 0,
+ 16,
+ &kw_aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_nist_kwp_info = {
+ MBEDTLS_CIPHER_AES_256_KWP,
+ MBEDTLS_MODE_KWP,
+ 256,
+ "AES-256-KWP",
+ 0,
+ 0,
+ 16,
+ &kw_aes_info
+};
+#endif /* MBEDTLS_NIST_KW_C */
+
const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] =
{
#if defined(MBEDTLS_AES_C)
@@ -2319,6 +2449,15 @@
{ MBEDTLS_CIPHER_CHACHA20_POLY1305, &chachapoly_info },
#endif
+#if defined(MBEDTLS_NIST_KW_C)
+ { MBEDTLS_CIPHER_AES_128_KW, &aes_128_nist_kw_info },
+ { MBEDTLS_CIPHER_AES_192_KW, &aes_192_nist_kw_info },
+ { MBEDTLS_CIPHER_AES_256_KW, &aes_256_nist_kw_info },
+ { MBEDTLS_CIPHER_AES_128_KWP, &aes_128_nist_kwp_info },
+ { MBEDTLS_CIPHER_AES_192_KWP, &aes_192_nist_kwp_info },
+ { MBEDTLS_CIPHER_AES_256_KWP, &aes_256_nist_kwp_info },
+#endif
+
#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
{ MBEDTLS_CIPHER_NULL, &null_cipher_info },
#endif /* MBEDTLS_CIPHER_NULL_CIPHER */
@@ -2326,7 +2465,8 @@
{ MBEDTLS_CIPHER_NONE, NULL }
};
-#define NUM_CIPHERS sizeof mbedtls_cipher_definitions / sizeof mbedtls_cipher_definitions[0]
+#define NUM_CIPHERS ( sizeof(mbedtls_cipher_definitions) / \
+ sizeof(mbedtls_cipher_definitions[0]) )
int mbedtls_cipher_supported[NUM_CIPHERS];
#endif /* MBEDTLS_CIPHER_C */
diff --git a/lib/libmbedtls/mbedtls/library/cmac.c b/lib/libmbedtls/mbedtls/library/cmac.c
index 9a9b6a2..c879674 100644
--- a/lib/libmbedtls/mbedtls/library/cmac.c
+++ b/lib/libmbedtls/mbedtls/library/cmac.c
@@ -50,6 +50,7 @@
#include "mbedtls/cmac.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -135,7 +136,7 @@
static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx,
unsigned char* K1, unsigned char* K2 )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX];
size_t olen, block_size;
@@ -323,7 +324,7 @@
unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX];
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t olen, block_size;
if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
@@ -401,7 +402,7 @@
unsigned char *output )
{
mbedtls_cipher_context_t ctx;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( cipher_info == NULL || key == NULL || input == NULL || output == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
@@ -435,7 +436,7 @@
const unsigned char *input, size_t in_len,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_cipher_info_t *cipher_info;
unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE];
unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE];
@@ -902,7 +903,7 @@
static int test_aes128_cmac_prf( int verbose )
{
int i;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char output[MBEDTLS_AES_BLOCK_SIZE];
for( i = 0; i < NB_PRF_TESTS; i++ )
@@ -929,7 +930,7 @@
int mbedtls_cmac_self_test( int verbose )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_AES_C)
/* AES-128 */
diff --git a/lib/libmbedtls/mbedtls/library/ctr_drbg.c b/lib/libmbedtls/mbedtls/library/ctr_drbg.c
index f9bdcc4..ca96171 100644
--- a/lib/libmbedtls/mbedtls/library/ctr_drbg.c
+++ b/lib/libmbedtls/mbedtls/library/ctr_drbg.c
@@ -34,6 +34,7 @@
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -56,6 +57,9 @@
void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
+ /* Indicate that the entropy nonce length is not set explicitly.
+ * See mbedtls_ctr_drbg_set_nonce_len(). */
+ ctx->reseed_counter = -1;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init( &ctx->mutex );
@@ -74,17 +78,46 @@
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
}
-void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance )
+void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
+ int resistance )
{
ctx->prediction_resistance = resistance;
}
-void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len )
+void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
+ size_t len )
{
ctx->entropy_len = len;
}
-void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval )
+int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
+ size_t len )
+{
+ /* If mbedtls_ctr_drbg_seed() has already been called, it's
+ * too late. Return the error code that's closest to making sense. */
+ if( ctx->f_entropy != NULL )
+ return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
+
+ if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
+ return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+#if SIZE_MAX > INT_MAX
+ /* This shouldn't be an issue because
+ * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
+ * configuration, but make sure anyway. */
+ if( len > INT_MAX )
+ return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+#endif
+
+ /* For backward compatibility with Mbed TLS <= 2.19, store the
+ * entropy nonce length in a field that already exists, but isn't
+ * used until after the initial seeding. */
+ /* Due to the capping of len above, the value fits in an int. */
+ ctx->reseed_counter = (int) len;
+ return( 0 );
+}
+
+void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
+ int interval )
{
ctx->reseed_interval = interval;
}
@@ -92,7 +125,8 @@
static int block_cipher_df( unsigned char *output,
const unsigned char *data, size_t data_len )
{
- unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
+ unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
+ MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
@@ -106,7 +140,8 @@
if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
- memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
+ memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
+ MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
mbedtls_aes_init( &aes_ctx );
/*
@@ -131,7 +166,8 @@
for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
key[i] = i;
- if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
+ if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
+ MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
{
goto exit;
}
@@ -153,7 +189,8 @@
use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
- if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 )
+ if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
+ chain, chain ) ) != 0 )
{
goto exit;
}
@@ -170,7 +207,8 @@
/*
* Do final encryption with reduced data
*/
- if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
+ if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
+ MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
{
goto exit;
}
@@ -179,7 +217,8 @@
for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
{
- if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 )
+ if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
+ iv, iv ) ) != 0 )
{
goto exit;
}
@@ -215,7 +254,7 @@
* ctx->counter = V
*/
static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
- const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
+ const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
{
unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
unsigned char *p = tmp;
@@ -236,8 +275,11 @@
/*
* Crypt counter block
*/
- if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
+ if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
+ ctx->counter, p ) ) != 0 )
+ {
goto exit;
+ }
p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
}
@@ -248,9 +290,13 @@
/*
* Update key and counter
*/
- if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
+ if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
+ MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
+ {
goto exit;
- memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
+ }
+ memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
+ MBEDTLS_CTR_DRBG_BLOCKSIZE );
exit:
mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
@@ -274,7 +320,7 @@
size_t add_len )
{
unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( add_len == 0 )
return( 0 );
@@ -303,7 +349,7 @@
#endif /* MBEDTLS_DEPRECATED_REMOVED */
/* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2)
- * mbedtls_ctr_drbg_reseed(ctx, additional, len)
+ * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
* implements
* CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
* -> new_working_state
@@ -311,51 +357,57 @@
* ctx contains working_state
* additional[:len] = additional_input
* and entropy_input comes from calling ctx->f_entropy
+ * for (ctx->entropy_len + nonce_len) bytes
* and with output
* ctx contains new_working_state
*/
-int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
- const unsigned char *additional, size_t len )
+static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
+ const unsigned char *additional,
+ size_t len,
+ size_t nonce_len )
{
unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
size_t seedlen = 0;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
- len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
+ if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
+ return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+ if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
+ return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+ if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
- /*
- * Gather entropy_len bytes of entropy to seed state
- */
- if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
- ctx->entropy_len ) )
+ /* Gather entropy_len bytes of entropy to seed state. */
+ if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
{
return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
}
-
seedlen += ctx->entropy_len;
- /*
- * Add additional data
- */
- if( additional && len )
+ /* Gather entropy for a nonce if requested. */
+ if( nonce_len != 0 )
+ {
+ if( 0 != ctx->f_entropy( ctx->p_entropy, seed, nonce_len ) )
+ {
+ return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
+ }
+ seedlen += nonce_len;
+ }
+
+ /* Add additional data if provided. */
+ if( additional != NULL && len != 0 )
{
memcpy( seed + seedlen, additional, len );
seedlen += len;
}
- /*
- * Reduce to 384 bits
- */
+ /* Reduce to 384 bits. */
if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
goto exit;
- /*
- * Update state
- */
+ /* Update state. */
if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
goto exit;
ctx->reseed_counter = 1;
@@ -365,6 +417,25 @@
return( ret );
}
+int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
+ const unsigned char *additional, size_t len )
+{
+ return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
+}
+
+/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
+ * is sufficient to achieve the maximum security strength given the key
+ * size and entropy length. If there is enough entropy in the initial
+ * call to the entropy function to serve as both the entropy input and
+ * the nonce, don't make a second call to get a nonce. */
+static size_t good_nonce_len( size_t entropy_len )
+{
+ if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
+ return( 0 );
+ else
+ return( ( entropy_len + 1 ) / 2 );
+}
+
/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
* mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
* implements
@@ -382,8 +453,9 @@
const unsigned char *custom,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
+ size_t nonce_len;
memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
@@ -394,34 +466,32 @@
if( ctx->entropy_len == 0 )
ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
+ /* ctx->reseed_counter contains the desired amount of entropy to
+ * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
+ * If it's -1, indicating that the entropy nonce length was not set
+ * explicitly, use a sufficiently large nonce for security. */
+ nonce_len = ( ctx->reseed_counter >= 0 ?
+ (size_t) ctx->reseed_counter :
+ good_nonce_len( ctx->entropy_len ) );
+
ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
- /*
- * Initialize with an empty key
- */
- if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
+ /* Initialize with an empty key. */
+ if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
+ MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
{
return( ret );
}
- if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
+ /* Do the initial seeding. */
+ if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
+ nonce_len ) ) != 0 )
{
return( ret );
}
return( 0 );
}
-/* Backward compatibility wrapper */
-int mbedtls_ctr_drbg_seed_entropy_len(
- mbedtls_ctr_drbg_context *ctx,
- int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy,
- const unsigned char *custom, size_t len,
- size_t entropy_len )
-{
- mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len );
- return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) );
-}
-
/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2)
* mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
* implements
@@ -491,11 +561,14 @@
/*
* Crypt counter block
*/
- if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
+ if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
+ ctx->counter, tmp ) ) != 0 )
+ {
goto exit;
+ }
- use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
- output_len;
+ use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
+ ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
/*
* Copy random block to destination
*/
@@ -515,9 +588,10 @@
return( ret );
}
-int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
+int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
+ size_t output_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
#if defined(MBEDTLS_THREADING_C)
@@ -536,7 +610,8 @@
}
#if defined(MBEDTLS_FS_IO)
-int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
+int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
+ const char *path )
{
int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
FILE *f;
@@ -545,13 +620,19 @@
if( ( f = fopen( path, "wb" ) ) == NULL )
return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
- if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
+ if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
+ MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
goto exit;
- if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT )
+ if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
+ MBEDTLS_CTR_DRBG_MAX_INPUT )
+ {
ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
+ }
else
+ {
ret = 0;
+ }
exit:
mbedtls_platform_zeroize( buf, sizeof( buf ) );
@@ -560,7 +641,8 @@
return( ret );
}
-int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path )
+int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
+ const char *path )
{
int ret = 0;
FILE *f = NULL;
@@ -631,6 +713,15 @@
{ 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
+#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
+static const unsigned char result_pr[16] =
+ { 0x95, 0x3c, 0xa5, 0xbd, 0x44, 0x1, 0x34, 0xb7,
+ 0x13, 0x58, 0x3e, 0x6a, 0x6c, 0x7e, 0x88, 0x8a };
+
+static const unsigned char result_nopr[16] =
+ { 0x6c, 0x25, 0x27, 0x95, 0xa3, 0x62, 0xd6, 0xdb,
+ 0x90, 0xfd, 0x69, 0xb5, 0x42, 0x9, 0x4b, 0x84 };
+#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
static const unsigned char result_pr[16] =
{ 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
@@ -638,6 +729,7 @@
static const unsigned char result_nopr[16] =
{ 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
+#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
static size_t test_offset;
static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
@@ -674,6 +766,7 @@
test_offset = 0;
mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
+ mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
CHK( mbedtls_ctr_drbg_seed( &ctx,
ctr_drbg_self_test_entropy,
(void *) entropy_source_pr,
@@ -698,6 +791,7 @@
test_offset = 0;
mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
+ mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
CHK( mbedtls_ctr_drbg_seed( &ctx,
ctr_drbg_self_test_entropy,
(void *) entropy_source_nopr,
diff --git a/lib/libmbedtls/mbedtls/library/debug.c b/lib/libmbedtls/mbedtls/library/debug.c
index c939ab5..46b6f6e 100644
--- a/lib/libmbedtls/mbedtls/library/debug.c
+++ b/lib/libmbedtls/mbedtls/library/debug.c
@@ -35,9 +35,11 @@
#define mbedtls_free free
#define mbedtls_time_t time_t
#define mbedtls_snprintf snprintf
+#define mbedtls_vsnprintf vsnprintf
#endif
#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
#include <stdarg.h>
#include <stdio.h>
@@ -84,7 +86,7 @@
{
va_list argp;
char str[DEBUG_BUF_SIZE];
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( NULL == ssl ||
NULL == ssl->conf ||
@@ -95,20 +97,7 @@
}
va_start( argp, format );
-#if defined(_WIN32)
-#if defined(_TRUNCATE) && !defined(__MINGW32__)
- ret = _vsnprintf_s( str, DEBUG_BUF_SIZE, _TRUNCATE, format, argp );
-#else
- ret = _vsnprintf( str, DEBUG_BUF_SIZE, format, argp );
- if( ret < 0 || (size_t) ret == DEBUG_BUF_SIZE )
- {
- str[DEBUG_BUF_SIZE-1] = '\0';
- ret = -1;
- }
-#endif
-#else
- ret = vsnprintf( str, DEBUG_BUF_SIZE, format, argp );
-#endif
+ ret = mbedtls_vsnprintf( str, DEBUG_BUF_SIZE, format, argp );
va_end( argp );
if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 )
diff --git a/lib/libmbedtls/mbedtls/library/des.c b/lib/libmbedtls/mbedtls/library/des.c
index 7951a8f..90f8642 100644
--- a/lib/libmbedtls/mbedtls/library/des.c
+++ b/lib/libmbedtls/mbedtls/library/des.c
@@ -834,16 +834,16 @@
static const unsigned char des3_test_ecb_dec[3][8] =
{
- { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D },
- { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB },
- { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A }
+ { 0x37, 0x2B, 0x98, 0xBF, 0x52, 0x65, 0xB0, 0x59 },
+ { 0xC2, 0x10, 0x19, 0x9C, 0x38, 0x5A, 0x65, 0xA1 },
+ { 0xA2, 0x70, 0x56, 0x68, 0x69, 0xE5, 0x15, 0x1D }
};
static const unsigned char des3_test_ecb_enc[3][8] =
{
- { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B },
- { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 },
- { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 }
+ { 0x1C, 0xD5, 0x97, 0xEA, 0x84, 0x26, 0x73, 0xFB },
+ { 0xB3, 0x92, 0x4D, 0xF3, 0xC5, 0xB5, 0x42, 0x93 },
+ { 0xDA, 0x37, 0x64, 0x41, 0xBA, 0x6F, 0x62, 0x6F }
};
#if defined(MBEDTLS_CIPHER_MODE_CBC)
@@ -854,16 +854,16 @@
static const unsigned char des3_test_cbc_dec[3][8] =
{
- { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 },
- { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 },
- { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C }
+ { 0x58, 0xD9, 0x48, 0xEF, 0x85, 0x14, 0x65, 0x9A },
+ { 0x5F, 0xC8, 0x78, 0xD4, 0xD7, 0x92, 0xD9, 0x54 },
+ { 0x25, 0xF9, 0x75, 0x85, 0xA8, 0x1E, 0x48, 0xBF }
};
static const unsigned char des3_test_cbc_enc[3][8] =
{
- { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 },
- { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D },
- { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 }
+ { 0x91, 0x1C, 0x6D, 0xCF, 0x48, 0xA7, 0xC3, 0x4D },
+ { 0x60, 0x1A, 0x76, 0x8F, 0xA1, 0xF9, 0x66, 0xF1 },
+ { 0xA1, 0x50, 0x0F, 0x99, 0xB2, 0xCD, 0x64, 0x76 }
};
#endif /* MBEDTLS_CIPHER_MODE_CBC */
@@ -928,7 +928,7 @@
return( 1 );
}
- for( j = 0; j < 10000; j++ )
+ for( j = 0; j < 100; j++ )
{
if( u == 0 )
mbedtls_des_crypt_ecb( &ctx, buf, buf );
@@ -1005,7 +1005,7 @@
if( v == MBEDTLS_DES_DECRYPT )
{
- for( j = 0; j < 10000; j++ )
+ for( j = 0; j < 100; j++ )
{
if( u == 0 )
mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
@@ -1015,7 +1015,7 @@
}
else
{
- for( j = 0; j < 10000; j++ )
+ for( j = 0; j < 100; j++ )
{
unsigned char tmp[8];
diff --git a/lib/libmbedtls/mbedtls/library/dhm.c b/lib/libmbedtls/mbedtls/library/dhm.c
index 08870a8..9a76fc5 100644
--- a/lib/libmbedtls/mbedtls/library/dhm.c
+++ b/lib/libmbedtls/mbedtls/library/dhm.c
@@ -37,6 +37,7 @@
#include "mbedtls/dhm.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -137,7 +138,7 @@
unsigned char **p,
const unsigned char *end )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( p != NULL && *p != NULL );
DHM_VALIDATE_RET( end != NULL );
@@ -239,7 +240,7 @@
const mbedtls_mpi *P,
const mbedtls_mpi *G )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( P != NULL );
DHM_VALIDATE_RET( G != NULL );
@@ -260,7 +261,7 @@
int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
const unsigned char *input, size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( input != NULL );
@@ -396,7 +397,7 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi GYb;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( output != NULL );
@@ -473,7 +474,7 @@
int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
size_t dhminlen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
unsigned char *p, *end;
#if defined(MBEDTLS_PEM_PARSE_C)
@@ -627,7 +628,7 @@
*/
int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
unsigned char *buf;
DHM_VALIDATE_RET( dhm != NULL );
@@ -679,7 +680,7 @@
*/
int mbedtls_dhm_self_test( int verbose )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_dhm_context dhm;
mbedtls_dhm_init( &dhm );
diff --git a/lib/libmbedtls/mbedtls/library/ecdh.c b/lib/libmbedtls/mbedtls/library/ecdh.c
index c569016..d196852 100644
--- a/lib/libmbedtls/mbedtls/library/ecdh.c
+++ b/lib/libmbedtls/mbedtls/library/ecdh.c
@@ -36,6 +36,7 @@
#include "mbedtls/ecdh.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -59,6 +60,13 @@
#endif
}
+int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid )
+{
+ /* At this time, all groups support ECDH. */
+ (void) gid;
+ return( 1 );
+}
+
#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
/*
* Generate public key (restartable version)
@@ -73,7 +81,7 @@
void *p_rng,
mbedtls_ecp_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* If multiplication is in progress, we already generated a privkey */
#if defined(MBEDTLS_ECP_RESTARTABLE)
@@ -114,7 +122,7 @@
void *p_rng,
mbedtls_ecp_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point P;
mbedtls_ecp_point_init( &P );
@@ -192,7 +200,7 @@
static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx,
mbedtls_ecp_group_id grp_id )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ret = mbedtls_ecp_group_load( &ctx->grp, grp_id );
if( ret != 0 )
@@ -215,6 +223,13 @@
#else
switch( grp_id )
{
+#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+ case MBEDTLS_ECP_DP_CURVE25519:
+ ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
+ ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
+ ctx->grp_id = grp_id;
+ return( mbedtls_everest_setup( &ctx->ctx.everest_ecdh, grp_id ) );
+#endif
default:
ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
@@ -266,6 +281,11 @@
#else
switch( ctx->var )
{
+#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+ case MBEDTLS_ECDH_VARIANT_EVEREST:
+ mbedtls_everest_free( &ctx->ctx.everest_ecdh );
+ break;
+#endif
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
ecdh_free_internal( &ctx->ctx.mbed_ecdh );
break;
@@ -288,7 +308,7 @@
void *p_rng,
int restart_enabled )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t grp_len, pt_len;
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
@@ -331,7 +351,7 @@
}
/*
- * Setup and write the ServerKeyExhange parameters (RFC 4492)
+ * Setup and write the ServerKeyExchange parameters (RFC 4492)
* struct {
* ECParameters curve_params;
* ECPoint public;
@@ -360,6 +380,11 @@
#else
switch( ctx->var )
{
+#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+ case MBEDTLS_ECDH_VARIANT_EVEREST:
+ return( mbedtls_everest_make_params( &ctx->ctx.everest_ecdh, olen,
+ buf, blen, f_rng, p_rng ) );
+#endif
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen,
ctx->point_format, buf, blen,
@@ -390,7 +415,7 @@
const unsigned char **buf,
const unsigned char *end )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_group_id grp_id;
ECDH_VALIDATE_RET( ctx != NULL );
ECDH_VALIDATE_RET( buf != NULL );
@@ -409,6 +434,11 @@
#else
switch( ctx->var )
{
+#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+ case MBEDTLS_ECDH_VARIANT_EVEREST:
+ return( mbedtls_everest_read_params( &ctx->ctx.everest_ecdh,
+ buf, end) );
+#endif
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh,
buf, end ) );
@@ -422,7 +452,7 @@
const mbedtls_ecp_keypair *key,
mbedtls_ecdh_side side )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* If it's not our key, just import the public part as Qp */
if( side == MBEDTLS_ECDH_THEIRS )
@@ -446,7 +476,7 @@
const mbedtls_ecp_keypair *key,
mbedtls_ecdh_side side )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECDH_VALIDATE_RET( ctx != NULL );
ECDH_VALIDATE_RET( key != NULL );
ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS ||
@@ -473,6 +503,16 @@
#else
switch( ctx->var )
{
+#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+ case MBEDTLS_ECDH_VARIANT_EVEREST:
+ {
+ mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
+ MBEDTLS_EVEREST_ECDH_OURS :
+ MBEDTLS_EVEREST_ECDH_THEIRS;
+ return( mbedtls_everest_get_params( &ctx->ctx.everest_ecdh,
+ key, s) );
+ }
+#endif
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh,
key, side ) );
@@ -491,7 +531,7 @@
void *p_rng,
int restart_enabled )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
#endif
@@ -544,6 +584,11 @@
#else
switch( ctx->var )
{
+#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+ case MBEDTLS_ECDH_VARIANT_EVEREST:
+ return( mbedtls_everest_make_public( &ctx->ctx.everest_ecdh, olen,
+ buf, blen, f_rng, p_rng ) );
+#endif
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen,
ctx->point_format, buf, blen,
@@ -558,7 +603,7 @@
static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
const unsigned char *buf, size_t blen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const unsigned char *p = buf;
if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p,
@@ -585,6 +630,11 @@
#else
switch( ctx->var )
{
+#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+ case MBEDTLS_ECDH_VARIANT_EVEREST:
+ return( mbedtls_everest_read_public( &ctx->ctx.everest_ecdh,
+ buf, blen ) );
+#endif
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh,
buf, blen ) );
@@ -603,7 +653,7 @@
void *p_rng,
int restart_enabled )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
#endif
@@ -637,6 +687,10 @@
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
*olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 );
+
+ if( mbedtls_ecp_get_type( &ctx->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
+ return mbedtls_mpi_write_binary_le( &ctx->z, buf, *olen );
+
return mbedtls_mpi_write_binary( &ctx->z, buf, *olen );
}
@@ -663,6 +717,11 @@
#else
switch( ctx->var )
{
+#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+ case MBEDTLS_ECDH_VARIANT_EVEREST:
+ return( mbedtls_everest_calc_secret( &ctx->ctx.everest_ecdh, olen,
+ buf, blen, f_rng, p_rng ) );
+#endif
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf,
blen, f_rng, p_rng,
diff --git a/lib/libmbedtls/mbedtls/library/ecdsa.c b/lib/libmbedtls/mbedtls/library/ecdsa.c
index 517d187..bf99573 100644
--- a/lib/libmbedtls/mbedtls/library/ecdsa.c
+++ b/lib/libmbedtls/mbedtls/library/ecdsa.c
@@ -51,6 +51,7 @@
#endif
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
/* Parameter validation macros based on platform_util.h */
#define ECDSA_VALIDATE_RET( cond ) \
@@ -229,7 +230,7 @@
static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x,
const unsigned char *buf, size_t blen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n_size = ( grp->nbits + 7 ) / 8;
size_t use_size = blen > n_size ? n_size : blen;
@@ -265,7 +266,7 @@
mbedtls_mpi *pk = &k, *pr = r;
/* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
- if( grp->N.p == NULL )
+ if( ! mbedtls_ecdsa_can_do( grp->id ) || grp->N.p == NULL )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
/* Make sure d is in range 1..n-1 */
@@ -384,6 +385,20 @@
return( ret );
}
+int mbedtls_ecdsa_can_do( mbedtls_ecp_group_id gid )
+{
+ switch( gid )
+ {
+#ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ case MBEDTLS_ECP_DP_CURVE25519: return 0;
+#endif
+#ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
+ case MBEDTLS_ECP_DP_CURVE448: return 0;
+#endif
+ default: return 1;
+ }
+}
+
/*
* Compute ECDSA signature of a hashed message
*/
@@ -416,7 +431,7 @@
void *p_rng_blind,
mbedtls_ecdsa_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_hmac_drbg_context rng_ctx;
mbedtls_hmac_drbg_context *p_rng = &rng_ctx;
unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
@@ -480,7 +495,6 @@
mbedtls_hmac_drbg_init( &rng_ctx_blind );
p_rng_blind_det = &rng_ctx_blind;
-
mbedtls_hmac_drbg_seed_buf( p_rng_blind_det, md_info,
data, 2 * grp_len );
ret = mbedtls_hmac_drbg_update_ret( p_rng_blind_det,
@@ -538,6 +552,8 @@
/*
* Deterministic signature wrappers
*/
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r,
mbedtls_mpi *s, const mbedtls_mpi *d,
const unsigned char *buf, size_t blen,
@@ -552,6 +568,7 @@
return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg,
NULL, NULL, NULL ) );
}
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r,
mbedtls_mpi *s, const mbedtls_mpi *d,
@@ -584,7 +601,7 @@
const mbedtls_mpi *r, const mbedtls_mpi *s,
mbedtls_ecdsa_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi e, s_inv, u1, u2;
mbedtls_ecp_point R;
mbedtls_mpi *pu1 = &u1, *pu2 = &u2;
@@ -594,7 +611,7 @@
mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
/* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
- if( grp->N.p == NULL )
+ if( ! mbedtls_ecdsa_can_do( grp->id ) || grp->N.p == NULL )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
ECDSA_RS_ENTER( ver );
@@ -708,7 +725,7 @@
static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
unsigned char *sig, size_t *slen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char buf[MBEDTLS_ECDSA_MAX_LEN];
unsigned char *p = buf + sizeof( buf );
size_t len = 0;
@@ -737,7 +754,7 @@
void *p_rng,
mbedtls_ecdsa_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi r, s;
ECDSA_VALIDATE_RET( ctx != NULL );
ECDSA_VALIDATE_RET( hash != NULL );
@@ -830,7 +847,7 @@
const unsigned char *sig, size_t slen,
mbedtls_ecdsa_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = (unsigned char *) sig;
const unsigned char *end = sig + slen;
size_t len;
@@ -910,7 +927,7 @@
*/
int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECDSA_VALIDATE_RET( ctx != NULL );
ECDSA_VALIDATE_RET( key != NULL );
diff --git a/lib/libmbedtls/mbedtls/library/ecjpake.c b/lib/libmbedtls/mbedtls/library/ecjpake.c
index 70debff..4aca839 100644
--- a/lib/libmbedtls/mbedtls/library/ecjpake.c
+++ b/lib/libmbedtls/mbedtls/library/ecjpake.c
@@ -34,6 +34,7 @@
#include "mbedtls/ecjpake.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -110,7 +111,7 @@
const unsigned char *secret,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECJPAKE_VALIDATE_RET( ctx != NULL );
ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
@@ -159,7 +160,7 @@
const int pf,
const mbedtls_ecp_point *P )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
/* Need at least 4 for length plus 1 for point */
@@ -199,7 +200,7 @@
const char *id,
mbedtls_mpi *h )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char buf[ECJPAKE_HASH_BUF_LEN];
unsigned char *p = buf;
const unsigned char *end = buf + sizeof( buf );
@@ -249,7 +250,7 @@
const unsigned char **p,
const unsigned char *end )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point V, VV;
mbedtls_mpi r, h;
size_t r_len;
@@ -324,7 +325,7 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point V;
mbedtls_mpi v;
mbedtls_mpi h; /* later recycled to hold r */
@@ -382,7 +383,7 @@
const unsigned char **p,
const unsigned char *end )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( end < *p )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
@@ -422,7 +423,7 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( end < *p )
@@ -457,7 +458,7 @@
const unsigned char *buf,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const unsigned char *p = buf;
const unsigned char *end = buf + len;
@@ -495,7 +496,7 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = buf;
const unsigned char *end = buf + len;
@@ -553,7 +554,7 @@
const mbedtls_ecp_point *B,
const mbedtls_ecp_point *C )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi one;
mbedtls_mpi_init( &one );
@@ -575,7 +576,7 @@
const unsigned char *buf,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const unsigned char *p = buf;
const unsigned char *end = buf + len;
mbedtls_ecp_group grp;
@@ -639,7 +640,7 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi b; /* Blinding value, then s + N * blinding */
mbedtls_mpi_init( &b );
@@ -668,7 +669,7 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point G; /* C: GA, S: GB */
mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
mbedtls_mpi xm; /* C: xc, S: xs */
@@ -750,7 +751,7 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point K;
mbedtls_mpi m_xm2_s, one;
unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
@@ -956,7 +957,7 @@
const unsigned char *xm1, size_t len1,
const unsigned char *xm2, size_t len2 )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
@@ -1004,7 +1005,7 @@
*/
int mbedtls_ecjpake_self_test( int verbose )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecjpake_context cli;
mbedtls_ecjpake_context srv;
unsigned char buf[512], pms[32];
diff --git a/lib/libmbedtls/mbedtls/library/ecp.c b/lib/libmbedtls/mbedtls/library/ecp.c
index c59e8e2..1efc57a 100644
--- a/lib/libmbedtls/mbedtls/library/ecp.c
+++ b/lib/libmbedtls/mbedtls/library/ecp.c
@@ -81,6 +81,7 @@
#include "mbedtls/ecp.h"
#include "mbedtls/threading.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -364,19 +365,9 @@
#endif
/*
- * Curve types: internal for now, might be exposed later
- */
-typedef enum
-{
- ECP_TYPE_NONE = 0,
- ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
- ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
-} ecp_curve_type;
-
-/*
* List of supported curves:
* - internal ID
- * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
+ * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2, RFC 8446 sec. 4.2.7)
* - size in bits
* - readable name
*
@@ -420,6 +411,9 @@
#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
{ MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
#endif
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) && defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+ { MBEDTLS_ECP_DP_CURVE25519, 29, 256, "x25519" },
+#endif
{ MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
};
@@ -522,15 +516,15 @@
/*
* Get the type of a curve
*/
-static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
+mbedtls_ecp_curve_type mbedtls_ecp_get_type( const mbedtls_ecp_group *grp )
{
if( grp->G.X.p == NULL )
- return( ECP_TYPE_NONE );
+ return( MBEDTLS_ECP_TYPE_NONE );
if( grp->G.Y.p == NULL )
- return( ECP_TYPE_MONTGOMERY );
+ return( MBEDTLS_ECP_TYPE_MONTGOMERY );
else
- return( ECP_TYPE_SHORT_WEIERSTRASS );
+ return( MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS );
}
/*
@@ -641,7 +635,7 @@
*/
int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECP_VALIDATE_RET( P != NULL );
ECP_VALIDATE_RET( Q != NULL );
@@ -669,7 +663,7 @@
*/
int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECP_VALIDATE_RET( pt != NULL );
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
@@ -715,7 +709,7 @@
int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
const char *x, const char *y )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECP_VALIDATE_RET( P != NULL );
ECP_VALIDATE_RET( x != NULL );
ECP_VALIDATE_RET( y != NULL );
@@ -729,14 +723,14 @@
}
/*
- * Export a point into unsigned binary data (SEC1 2.3.3)
+ * Export a point into unsigned binary data (SEC1 2.3.3 and RFC7748)
*/
int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp,
const mbedtls_ecp_point *P,
int format, size_t *olen,
unsigned char *buf, size_t buflen )
{
- int ret = 0;
+ int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
size_t plen;
ECP_VALIDATE_RET( grp != NULL );
ECP_VALIDATE_RET( P != NULL );
@@ -745,56 +739,71 @@
ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
format == MBEDTLS_ECP_PF_COMPRESSED );
- /*
- * Common case: P == 0
- */
- if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
- {
- if( buflen < 1 )
- return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
-
- buf[0] = 0x00;
- *olen = 1;
-
- return( 0 );
- }
-
plen = mbedtls_mpi_size( &grp->P );
- if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
+#if defined(ECP_MONTGOMERY)
+ if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
{
- *olen = 2 * plen + 1;
-
+ *olen = plen;
if( buflen < *olen )
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
- buf[0] = 0x04;
- MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary_le( &P->X, buf, plen ) );
}
- else if( format == MBEDTLS_ECP_PF_COMPRESSED )
+#endif
+#if defined(ECP_SHORTWEIERSTRASS)
+ if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
{
- *olen = plen + 1;
+ /*
+ * Common case: P == 0
+ */
+ if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
+ {
+ if( buflen < 1 )
+ return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
- if( buflen < *olen )
- return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
+ buf[0] = 0x00;
+ *olen = 1;
- buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
- MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
+ return( 0 );
+ }
+
+ if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
+ {
+ *olen = 2 * plen + 1;
+
+ if( buflen < *olen )
+ return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
+
+ buf[0] = 0x04;
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
+ }
+ else if( format == MBEDTLS_ECP_PF_COMPRESSED )
+ {
+ *olen = plen + 1;
+
+ if( buflen < *olen )
+ return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
+
+ buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
+ }
}
+#endif
cleanup:
return( ret );
}
/*
- * Import a point from unsigned binary data (SEC1 2.3.4)
+ * Import a point from unsigned binary data (SEC1 2.3.4 and RFC7748)
*/
int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *pt,
const unsigned char *buf, size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
size_t plen;
ECP_VALIDATE_RET( grp != NULL );
ECP_VALIDATE_RET( pt != NULL );
@@ -803,25 +812,47 @@
if( ilen < 1 )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
- if( buf[0] == 0x00 )
- {
- if( ilen == 1 )
- return( mbedtls_ecp_set_zero( pt ) );
- else
- return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
- }
-
plen = mbedtls_mpi_size( &grp->P );
- if( buf[0] != 0x04 )
- return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+#if defined(ECP_MONTGOMERY)
+ if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
+ {
+ if( plen != ilen )
+ return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
- if( ilen != 2 * plen + 1 )
- return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary_le( &pt->X, buf, plen ) );
+ mbedtls_mpi_free( &pt->Y );
- MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
+ if( grp->id == MBEDTLS_ECP_DP_CURVE25519 )
+ /* Set most significant bit to 0 as prescribed in RFC7748 §5 */
+ MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &pt->X, plen * 8 - 1, 0 ) );
+
+ MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
+ }
+#endif
+#if defined(ECP_SHORTWEIERSTRASS)
+ if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
+ {
+ if( buf[0] == 0x00 )
+ {
+ if( ilen == 1 )
+ return( mbedtls_ecp_set_zero( pt ) );
+ else
+ return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+ }
+
+ if( buf[0] != 0x04 )
+ return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+
+ if( ilen != 2 * plen + 1 )
+ return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+
+ MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y,
+ buf + 1 + plen, plen ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
+ }
+#endif
cleanup:
return( ret );
@@ -873,7 +904,7 @@
int format, size_t *olen,
unsigned char *buf, size_t blen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECP_VALIDATE_RET( grp != NULL );
ECP_VALIDATE_RET( pt != NULL );
ECP_VALIDATE_RET( olen != NULL );
@@ -906,7 +937,7 @@
int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp,
const unsigned char **buf, size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_group_id grp_id;
ECP_VALIDATE_RET( grp != NULL );
ECP_VALIDATE_RET( buf != NULL );
@@ -1001,7 +1032,7 @@
*/
static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( grp->modp == NULL )
return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
@@ -1053,6 +1084,18 @@
INC_MUL_COUNT \
} while( 0 )
+static inline int mbedtls_mpi_mul_mod( const mbedtls_ecp_group *grp,
+ mbedtls_mpi *X,
+ const mbedtls_mpi *A,
+ const mbedtls_mpi *B )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( X, A, B ) );
+ MOD_MUL( *X );
+cleanup:
+ return( ret );
+}
+
/*
* Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
* N->s < 0 is a very fast test, which fails only if N is 0
@@ -1061,6 +1104,18 @@
while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 ) \
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) )
+static inline int mbedtls_mpi_sub_mod( const mbedtls_ecp_group *grp,
+ mbedtls_mpi *X,
+ const mbedtls_mpi *A,
+ const mbedtls_mpi *B )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( X, A, B ) );
+ MOD_SUB( *X );
+cleanup:
+ return( ret );
+}
+
/*
* Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int.
* We known P, N and the result are positive, so sub_abs is correct, and
@@ -1070,6 +1125,29 @@
while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 ) \
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) )
+static inline int mbedtls_mpi_add_mod( const mbedtls_ecp_group *grp,
+ mbedtls_mpi *X,
+ const mbedtls_mpi *A,
+ const mbedtls_mpi *B )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, A, B ) );
+ MOD_ADD( *X );
+cleanup:
+ return( ret );
+}
+
+static inline int mbedtls_mpi_shift_l_mod( const mbedtls_ecp_group *grp,
+ mbedtls_mpi *X,
+ size_t count )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( X, count ) );
+ MOD_ADD( *X );
+cleanup:
+ return( ret );
+}
+
#if defined(ECP_SHORTWEIERSTRASS)
/*
* For curves in short Weierstrass form, we do all the internal operations in
@@ -1085,7 +1163,7 @@
*/
static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi Zi, ZZi;
if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
@@ -1102,14 +1180,14 @@
* X = X / Z^2 mod p
*/
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ZZi ) ); MOD_MUL( pt->X );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ZZi, &Zi, &Zi ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->X, &pt->X, &ZZi ) );
/*
* Y = Y / Z^3 mod p
*/
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &Zi ) ); MOD_MUL( pt->Y );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Y, &pt->Y, &ZZi ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Y, &pt->Y, &Zi ) );
/*
* Z = 1
@@ -1137,7 +1215,7 @@
static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *T[], size_t T_size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
mbedtls_mpi *c, u, Zi, ZZi;
@@ -1163,8 +1241,7 @@
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
for( i = 1; i < T_size; i++ )
{
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
- MOD_MUL( c[i] );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &c[i], &c[i-1], &T[i]->Z ) );
}
/*
@@ -1183,17 +1260,17 @@
}
else
{
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &Zi, &u, &c[i-1] ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &u, &u, &T[i]->Z ) );
}
/*
* proceed as in normalize()
*/
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &Zi ) ); MOD_MUL( T[i]->Y );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ZZi, &Zi, &Zi ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T[i]->X, &T[i]->X, &ZZi ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T[i]->Y, &T[i]->Y, &ZZi ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T[i]->Y, &T[i]->Y, &Zi ) );
/*
* Post-precessing: reclaim some memory by shrinking coordinates
@@ -1227,7 +1304,7 @@
mbedtls_ecp_point *Q,
unsigned char inv )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char nonzero;
mbedtls_mpi mQY;
@@ -1261,7 +1338,7 @@
static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_ecp_point *P )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi M, S, T, U;
#if defined(MBEDTLS_SELF_TEST)
@@ -1279,52 +1356,52 @@
if( grp->A.p == NULL )
{
/* M = 3(X + Z^2)(X - Z^2) */
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
- MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &P->Z, &P->Z ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &T, &P->X, &S ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &U, &P->X, &S ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &T, &U ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
}
else
{
/* M = 3.X^2 */
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &P->X, &P->X ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
/* Optimize away for "koblitz" curves with A = 0 */
if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
{
/* M += A.Z^4 */
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
- MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &P->Z, &P->Z ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T, &S, &S ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &T, &grp->A ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &M, &M, &S ) );
}
}
/* S = 4.X.Y^2 */
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T, &P->Y, &P->Y ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &T, 1 ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &P->X, &T ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &S, 1 ) );
/* U = 8.Y^4 */
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &U, &T, &T ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &U, 1 ) );
/* T = M^2 - 2.S */
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T, &M, &M ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T, &T, &S ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T, &T, &S ) );
/* S = M(S - T) - U */
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &S, &S, &T ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &S, &M ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &S, &S, &U ) );
/* U = 2.Y.Z */
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
- MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &U, &P->Y, &P->Z ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &U, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
@@ -1357,7 +1434,7 @@
static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
#if defined(MBEDTLS_SELF_TEST)
@@ -1387,12 +1464,12 @@
mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T1, &P->Z, &P->Z ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T2, &T1, &P->Z ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T1, &T1, &Q->X ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T2, &T2, &Q->Y ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T1, &T1, &P->X ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T2, &T2, &P->Y ) );
/* Special cases (2) and (3) */
if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
@@ -1409,18 +1486,19 @@
}
}
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &Z, &P->Z, &T1 ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T3, &T1, &T1 ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T4, &T3, &T1 ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T3, &T3, &P->X ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &T3 ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &T1, 1 ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &X, &T2, &T2 ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &X, &X, &T1 ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &X, &X, &T4 ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T3, &T3, &X ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T3, &T3, &T2 ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T4, &T4, &P->Y ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &Y, &T3, &T4 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
@@ -1444,7 +1522,7 @@
static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi l, ll;
size_t p_size;
int count = 0;
@@ -1471,15 +1549,15 @@
while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
/* Z = l * Z */
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Z, &pt->Z, &l ) );
/* X = l^2 * X */
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ll ) ); MOD_MUL( pt->X );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ll, &l, &l ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->X, &pt->X, &ll ) );
/* Y = l^3 * Y */
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ll ) ); MOD_MUL( pt->Y );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ll, &ll, &l ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Y, &pt->Y, &ll ) );
cleanup:
mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
@@ -1616,7 +1694,7 @@
unsigned char w, size_t d,
mbedtls_ecp_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char i;
size_t j = 0;
const unsigned char T_size = 1U << ( w - 1 );
@@ -1752,7 +1830,7 @@
const mbedtls_ecp_point T[], unsigned char T_size,
unsigned char i )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char ii, j;
/* Ignore the "sign" bit and scale down */
@@ -1785,7 +1863,7 @@
void *p_rng,
mbedtls_ecp_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point Txi;
size_t i;
@@ -1865,7 +1943,7 @@
unsigned char w,
unsigned char *parity_trick )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi M, mm;
mbedtls_mpi_init( &M );
@@ -1911,7 +1989,7 @@
void *p_rng,
mbedtls_ecp_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char parity_trick;
unsigned char k[COMB_MAX_D + 1];
mbedtls_ecp_point *RR = R;
@@ -1938,6 +2016,20 @@
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 ) );
@@ -1977,8 +2069,10 @@
* Make sure w is within bounds.
* (The last test is useful only for very small curves in the test suite.)
*/
+#if( MBEDTLS_ECP_WINDOW_SIZE < 6 )
if( w > MBEDTLS_ECP_WINDOW_SIZE )
w = MBEDTLS_ECP_WINDOW_SIZE;
+#endif
if( w >= grp->nbits )
w = 2;
@@ -2004,7 +2098,7 @@
void *p_rng,
mbedtls_ecp_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char w, p_eq_g, i;
size_t d;
unsigned char T_size, T_ok;
@@ -2136,7 +2230,7 @@
*/
static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
if( mbedtls_internal_ecp_grp_capable( grp ) )
@@ -2144,7 +2238,7 @@
#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->X, &P->X, &P->Z ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
cleanup:
@@ -2162,7 +2256,7 @@
static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi l;
size_t p_size;
int count = 0;
@@ -2188,8 +2282,8 @@
}
while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->X, &P->X, &l ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->Z, &P->Z, &l ) );
cleanup:
mbedtls_mpi_free( &l );
@@ -2217,7 +2311,7 @@
const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
const mbedtls_mpi *d )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
@@ -2229,24 +2323,24 @@
mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
- MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
- MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &A, &P->X, &P->Z ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &AA, &A, &A ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &B, &P->X, &P->Z ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &BB, &B, &B ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &E, &AA, &BB ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &C, &Q->X, &Q->Z ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &D, &Q->X, &Q->Z ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &DA, &D, &A ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &CB, &C, &B ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
- MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
- MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &E, &R->Z ) ); MOD_MUL( R->Z );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S->X, &S->X, &S->X ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &S->Z, &DA, &CB ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S->Z, &S->Z, &S->Z ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S->Z, d, &S->Z ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &R->X, &AA, &BB ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &R->Z, &grp->A, &E ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &R->Z, &BB, &R->Z ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &R->Z, &E, &R->Z ) );
cleanup:
mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
@@ -2265,7 +2359,7 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
unsigned char b;
mbedtls_ecp_point RP;
@@ -2308,6 +2402,20 @@
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:
@@ -2361,11 +2469,11 @@
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
#if defined(ECP_MONTGOMERY)
- if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
+ if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) );
#endif
#if defined(ECP_SHORTWEIERSTRASS)
- if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
+ if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) );
#endif
@@ -2405,7 +2513,7 @@
*/
static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi YY, RHS;
/* pt coordinates must be normalized for our checks */
@@ -2421,8 +2529,8 @@
* YY = Y^2
* RHS = X (X^2 + A) + B = X^3 + A X + B
*/
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &YY, &pt->Y, &pt->Y ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &RHS, &pt->X, &pt->X ) );
/* Special case for A = -3 */
if( grp->A.p == NULL )
@@ -2431,11 +2539,11 @@
}
else
{
- MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &RHS, &RHS, &grp->A ) );
}
- MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
- MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &RHS, &RHS, &pt->X ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &RHS, &RHS, &grp->B ) );
if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
ret = MBEDTLS_ERR_ECP_INVALID_KEY;
@@ -2458,7 +2566,7 @@
const mbedtls_ecp_point *P,
mbedtls_ecp_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
{
@@ -2490,7 +2598,7 @@
const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
mbedtls_ecp_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point mP;
mbedtls_ecp_point *pmP = &mP;
mbedtls_ecp_point *pR = R;
@@ -2504,7 +2612,7 @@
ECP_VALIDATE_RET( n != NULL );
ECP_VALIDATE_RET( Q != NULL );
- if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
+ if( mbedtls_ecp_get_type( grp ) != MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
mbedtls_ecp_point_init( &mP );
@@ -2624,11 +2732,11 @@
return( MBEDTLS_ERR_ECP_INVALID_KEY );
#if defined(ECP_MONTGOMERY)
- if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
+ if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
return( ecp_check_pubkey_mx( grp, pt ) );
#endif
#if defined(ECP_SHORTWEIERSTRASS)
- if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
+ if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
return( ecp_check_pubkey_sw( grp, pt ) );
#endif
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
@@ -2644,7 +2752,7 @@
ECP_VALIDATE_RET( d != NULL );
#if defined(ECP_MONTGOMERY)
- if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
+ if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
{
/* see RFC 7748 sec. 5 para. 5 */
if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
@@ -2660,7 +2768,7 @@
}
#endif /* ECP_MONTGOMERY */
#if defined(ECP_SHORTWEIERSTRASS)
- if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
+ if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
{
/* see SEC1 3.2 */
if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
@@ -2692,7 +2800,7 @@
n_size = ( grp->nbits + 7 ) / 8;
#if defined(ECP_MONTGOMERY)
- if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
+ if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
{
/* [M225] page 5 */
size_t b;
@@ -2720,7 +2828,7 @@
#endif /* ECP_MONTGOMERY */
#if defined(ECP_SHORTWEIERSTRASS)
- if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
+ if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
{
/* SEC1 3.2.1: Generate d such that 1 <= n < N */
int count = 0;
@@ -2773,7 +2881,7 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECP_VALIDATE_RET( grp != NULL );
ECP_VALIDATE_RET( d != NULL );
ECP_VALIDATE_RET( G != NULL );
@@ -2809,7 +2917,7 @@
int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECP_VALIDATE_RET( key != NULL );
ECP_VALIDATE_RET( f_rng != NULL );
@@ -2819,12 +2927,81 @@
return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
}
+#define ECP_CURVE25519_KEY_SIZE 32
+/*
+ * Read a private key.
+ */
+int mbedtls_ecp_read_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
+ const unsigned char *buf, size_t buflen )
+{
+ int ret = 0;
+
+ ECP_VALIDATE_RET( key != NULL );
+ ECP_VALIDATE_RET( buf != NULL );
+
+ if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
+ return( ret );
+
+ ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+
+#if defined(ECP_MONTGOMERY)
+ if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
+ {
+ /*
+ * If it is Curve25519 curve then mask the key as mandated by RFC7748
+ */
+ if( grp_id == MBEDTLS_ECP_DP_CURVE25519 )
+ {
+ if( buflen != ECP_CURVE25519_KEY_SIZE )
+ return MBEDTLS_ERR_ECP_INVALID_KEY;
+
+ MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary_le( &key->d, buf, buflen ) );
+
+ /* Set the three least significant bits to 0 */
+ MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 0, 0 ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 1, 0 ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 2, 0 ) );
+
+ /* Set the most significant bit to 0 */
+ MBEDTLS_MPI_CHK(
+ mbedtls_mpi_set_bit( &key->d,
+ ECP_CURVE25519_KEY_SIZE * 8 - 1, 0 )
+ );
+
+ /* Set the second most significant bit to 1 */
+ MBEDTLS_MPI_CHK(
+ mbedtls_mpi_set_bit( &key->d,
+ ECP_CURVE25519_KEY_SIZE * 8 - 2, 1 )
+ );
+ }
+ else
+ ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+ }
+
+#endif
+#if defined(ECP_SHORTWEIERSTRASS)
+ if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
+ {
+ MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &key->d, buf, buflen ) );
+
+ MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( &key->grp, &key->d ) );
+ }
+
+#endif
+cleanup:
+
+ if( ret != 0 )
+ mbedtls_mpi_free( &key->d );
+
+ return( ret );
+}
+
/*
* Check a public-private key pair
*/
int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point Q;
mbedtls_ecp_group grp;
ECP_VALIDATE_RET( pub != NULL );
@@ -2870,7 +3047,7 @@
*/
int mbedtls_ecp_self_test( int verbose )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
mbedtls_ecp_group grp;
mbedtls_ecp_point R, P;
diff --git a/lib/libmbedtls/mbedtls/library/ecp_curves.c b/lib/libmbedtls/mbedtls/library/ecp_curves.c
index c0a3494..f78984e 100644
--- a/lib/libmbedtls/mbedtls/library/ecp_curves.c
+++ b/lib/libmbedtls/mbedtls/library/ecp_curves.c
@@ -29,6 +29,7 @@
#include "mbedtls/ecp.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -669,7 +670,7 @@
*/
static int ecp_use_curve25519( mbedtls_ecp_group *grp )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* Actually ( A + 2 ) / 4 */
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "01DB42" ) );
@@ -709,7 +710,7 @@
static int ecp_use_curve448( mbedtls_ecp_group *grp )
{
mbedtls_mpi Ns;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi_init( &Ns );
@@ -836,7 +837,7 @@
#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */
default:
- mbedtls_ecp_group_free( grp );
+ grp->id = MBEDTLS_ECP_DP_NONE;
return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
}
}
@@ -900,7 +901,7 @@
*/
static int ecp_mod_p192( mbedtls_mpi *N )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi_uint c = 0;
mbedtls_mpi_uint *p, *end;
@@ -991,7 +992,7 @@
* (see fix_negative for the motivation of C)
*/
#define INIT( b ) \
- int ret; \
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; \
signed char c = 0, cc; \
uint32_t cur; \
size_t i = 0, bits = (b); \
@@ -1027,7 +1028,7 @@
*/
static inline int fix_negative( mbedtls_mpi *N, signed char c, mbedtls_mpi *C, size_t bits )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* C = - c * 2^(bits + 32) */
#if !defined(MBEDTLS_HAVE_INT64)
@@ -1185,7 +1186,7 @@
*/
static int ecp_mod_p521( mbedtls_mpi *N )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
mbedtls_mpi M;
mbedtls_mpi_uint Mp[P521_WIDTH + 1];
@@ -1234,7 +1235,7 @@
*/
static int ecp_mod_p255( mbedtls_mpi *N )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
mbedtls_mpi M;
mbedtls_mpi_uint Mp[P255_WIDTH + 2];
@@ -1291,7 +1292,7 @@
*/
static int ecp_mod_p448( mbedtls_mpi *N )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
mbedtls_mpi M, Q;
mbedtls_mpi_uint Mp[P448_WIDTH + 1], Qp[P448_WIDTH];
@@ -1353,7 +1354,7 @@
static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs,
size_t adjust, size_t shift, mbedtls_mpi_uint mask )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
mbedtls_mpi M, R;
mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1];
diff --git a/lib/libmbedtls/mbedtls/library/entropy.c b/lib/libmbedtls/mbedtls/library/entropy.c
index c133f02..e40c8ec 100644
--- a/lib/libmbedtls/mbedtls/library/entropy.c
+++ b/lib/libmbedtls/mbedtls/library/entropy.c
@@ -36,6 +36,7 @@
#include "mbedtls/entropy.h"
#include "mbedtls/entropy_poll.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -236,7 +237,7 @@
int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx,
const unsigned char *data, size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_THREADING_C)
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
@@ -258,7 +259,9 @@
*/
static int entropy_gather_internal( mbedtls_entropy_context *ctx )
{
- int ret, i, have_one_strong = 0;
+ int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+ int i;
+ int have_one_strong = 0;
unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER];
size_t olen;
@@ -306,7 +309,7 @@
*/
int mbedtls_entropy_gather( mbedtls_entropy_context *ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_THREADING_C)
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
@@ -325,7 +328,8 @@
int mbedtls_entropy_func( void *data, unsigned char *output, size_t len )
{
- int ret, count = 0, i, done;
+ int ret, count = 0, i, thresholds_reached;
+ size_t strong_size;
mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data;
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
@@ -363,12 +367,17 @@
if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
goto exit;
- done = 1;
+ thresholds_reached = 1;
+ strong_size = 0;
for( i = 0; i < ctx->source_count; i++ )
+ {
if( ctx->source[i].size < ctx->source[i].threshold )
- done = 0;
+ thresholds_reached = 0;
+ if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG )
+ strong_size += ctx->source[i].size;
+ }
}
- while( ! done );
+ while( ! thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE );
memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
diff --git a/lib/libmbedtls/mbedtls/library/entropy_poll.c b/lib/libmbedtls/mbedtls/library/entropy_poll.c
index f4e539e..8148aff 100644
--- a/lib/libmbedtls/mbedtls/library/entropy_poll.c
+++ b/lib/libmbedtls/mbedtls/library/entropy_poll.c
@@ -36,6 +36,7 @@
#include "mbedtls/entropy.h"
#include "mbedtls/entropy_poll.h"
+#include "mbedtls/error.h"
#if defined(MBEDTLS_TIMING_C)
#include "mbedtls/timing.h"
@@ -121,7 +122,7 @@
{
FILE *file;
size_t read_len;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
((void) data);
#if defined(HAVE_GETRANDOM)
diff --git a/lib/libmbedtls/mbedtls/library/error.c b/lib/libmbedtls/mbedtls/library/error.c
index 3f3f6de..b171fd3 100644
--- a/lib/libmbedtls/mbedtls/library/error.c
+++ b/lib/libmbedtls/mbedtls/library/error.c
@@ -25,8 +25,7 @@
#include MBEDTLS_CONFIG_FILE
#endif
-#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
-#include "mbedtls/error.h"
+#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
#include <string.h>
#endif
@@ -109,6 +108,10 @@
#include "mbedtls/entropy.h"
#endif
+#if defined(MBEDTLS_ERROR_C)
+#include "mbedtls/error.h"
+#endif
+
#if defined(MBEDTLS_GCM_C)
#include "mbedtls/gcm.h"
#endif
@@ -523,6 +526,10 @@
mbedtls_snprintf( buf, buflen, "SSL - The asynchronous operation is not completed yet" );
if( use_ret == -(MBEDTLS_ERR_SSL_EARLY_MESSAGE) )
mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that a message arrived early" );
+ if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_CID) )
+ mbedtls_snprintf( buf, buflen, "SSL - An encrypted DTLS-frame with an unexpected CID was received" );
+ if( use_ret == -(MBEDTLS_ERR_SSL_VERSION_MISMATCH) )
+ mbedtls_snprintf( buf, buflen, "SSL - An operation failed due to an unexpected version or configuration" );
if( use_ret == -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) )
mbedtls_snprintf( buf, buflen, "SSL - A cryptographic operation is in progress. Try again later" );
#endif /* MBEDTLS_SSL_TLS_C */
@@ -638,7 +645,7 @@
if( use_ret == -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH) )
mbedtls_snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" );
if( use_ret == -(MBEDTLS_ERR_ASN1_INVALID_DATA) )
- mbedtls_snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" );
+ mbedtls_snprintf( buf, buflen, "ASN1 - Data is invalid" );
if( use_ret == -(MBEDTLS_ERR_ASN1_ALLOC_FAILED) )
mbedtls_snprintf( buf, buflen, "ASN1 - Memory allocation failed" );
if( use_ret == -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) )
@@ -750,6 +757,13 @@
mbedtls_snprintf( buf, buflen, "ENTROPY - Read/write error in file" );
#endif /* MBEDTLS_ENTROPY_C */
+#if defined(MBEDTLS_ERROR_C)
+ if( use_ret == -(MBEDTLS_ERR_ERROR_GENERIC_ERROR) )
+ mbedtls_snprintf( buf, buflen, "ERROR - Generic error" );
+ if( use_ret == -(MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED) )
+ mbedtls_snprintf( buf, buflen, "ERROR - This is a bug in the library" );
+#endif /* MBEDTLS_ERROR_C */
+
#if defined(MBEDTLS_GCM_C)
if( use_ret == -(MBEDTLS_ERR_GCM_AUTH_FAILED) )
mbedtls_snprintf( buf, buflen, "GCM - Authenticated decryption failed" );
diff --git a/lib/libmbedtls/mbedtls/library/gcm.c b/lib/libmbedtls/mbedtls/library/gcm.c
index d1b311d..ddd2d4e 100644
--- a/lib/libmbedtls/mbedtls/library/gcm.c
+++ b/lib/libmbedtls/mbedtls/library/gcm.c
@@ -39,6 +39,7 @@
#include "mbedtls/gcm.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -168,14 +169,15 @@
const unsigned char *key,
unsigned int keybits )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_cipher_info_t *cipher_info;
GCM_VALIDATE_RET( ctx != NULL );
GCM_VALIDATE_RET( key != NULL );
GCM_VALIDATE_RET( keybits == 128 || keybits == 192 || keybits == 256 );
- cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB );
+ cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
+ MBEDTLS_MODE_ECB );
if( cipher_info == NULL )
return( MBEDTLS_ERR_GCM_BAD_INPUT );
@@ -245,7 +247,7 @@
for( i = 15; i >= 0; i-- )
{
lo = x[i] & 0xf;
- hi = x[i] >> 4;
+ hi = ( x[i] >> 4 ) & 0xf;
if( i != 15 )
{
@@ -279,7 +281,7 @@
const unsigned char *add,
size_t add_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char work_buf[16];
size_t i;
const unsigned char *p;
@@ -335,8 +337,8 @@
gcm_mult( ctx, ctx->y, ctx->y );
}
- if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
- &olen ) ) != 0 )
+ if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16,
+ ctx->base_ectr, &olen ) ) != 0 )
{
return( ret );
}
@@ -364,7 +366,7 @@
const unsigned char *input,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char ectr[16];
size_t i;
const unsigned char *p;
@@ -475,7 +477,7 @@
size_t tag_len,
unsigned char *tag )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
GCM_VALIDATE_RET( ctx != NULL );
GCM_VALIDATE_RET( iv != NULL );
@@ -507,7 +509,7 @@
const unsigned char *input,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char check_tag[16];
size_t i;
int diff;
@@ -557,10 +559,10 @@
*/
#define MAX_TESTS 6
-static const int key_index[MAX_TESTS] =
+static const int key_index_test_data[MAX_TESTS] =
{ 0, 0, 1, 1, 1, 1 };
-static const unsigned char key[MAX_TESTS][32] =
+static const unsigned char key_test_data[MAX_TESTS][32] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -572,13 +574,13 @@
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
};
-static const size_t iv_len[MAX_TESTS] =
+static const size_t iv_len_test_data[MAX_TESTS] =
{ 12, 12, 12, 12, 8, 60 };
-static const int iv_index[MAX_TESTS] =
+static const int iv_index_test_data[MAX_TESTS] =
{ 0, 0, 1, 1, 1, 2 };
-static const unsigned char iv[MAX_TESTS][64] =
+static const unsigned char iv_test_data[MAX_TESTS][64] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 },
@@ -594,13 +596,13 @@
0xa6, 0x37, 0xb3, 0x9b },
};
-static const size_t add_len[MAX_TESTS] =
+static const size_t add_len_test_data[MAX_TESTS] =
{ 0, 0, 0, 20, 20, 20 };
-static const int add_index[MAX_TESTS] =
+static const int add_index_test_data[MAX_TESTS] =
{ 0, 0, 0, 1, 1, 1 };
-static const unsigned char additional[MAX_TESTS][64] =
+static const unsigned char additional_test_data[MAX_TESTS][64] =
{
{ 0x00 },
{ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
@@ -608,13 +610,13 @@
0xab, 0xad, 0xda, 0xd2 },
};
-static const size_t pt_len[MAX_TESTS] =
+static const size_t pt_len_test_data[MAX_TESTS] =
{ 0, 16, 64, 60, 60, 60 };
-static const int pt_index[MAX_TESTS] =
+static const int pt_index_test_data[MAX_TESTS] =
{ 0, 0, 1, 1, 1, 1 };
-static const unsigned char pt[MAX_TESTS][64] =
+static const unsigned char pt_test_data[MAX_TESTS][64] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -628,7 +630,7 @@
0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
};
-static const unsigned char ct[MAX_TESTS * 3][64] =
+static const unsigned char ct_test_data[MAX_TESTS * 3][64] =
{
{ 0x00 },
{ 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
@@ -737,7 +739,7 @@
0x44, 0xae, 0x7e, 0x3f },
};
-static const unsigned char tag[MAX_TESTS * 3][16] =
+static const unsigned char tag_test_data[MAX_TESTS * 3][16] =
{
{ 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
@@ -797,7 +799,8 @@
mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
key_len, i, "enc" );
- ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
+ ret = mbedtls_gcm_setkey( &ctx, cipher,
+ key_test_data[key_index_test_data[i]],
key_len );
/*
* AES-192 is an optional feature that may be unavailable when
@@ -815,15 +818,19 @@
}
ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
- pt_len[i],
- iv[iv_index[i]], iv_len[i],
- additional[add_index[i]], add_len[i],
- pt[pt_index[i]], buf, 16, tag_buf );
+ pt_len_test_data[i],
+ iv_test_data[iv_index_test_data[i]],
+ iv_len_test_data[i],
+ additional_test_data[add_index_test_data[i]],
+ add_len_test_data[i],
+ pt_test_data[pt_index_test_data[i]],
+ buf, 16, tag_buf );
if( ret != 0 )
goto exit;
- if ( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
- memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+ if ( memcmp( buf, ct_test_data[j * 6 + i],
+ pt_len_test_data[i] ) != 0 ||
+ memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
{
ret = 1;
goto exit;
@@ -840,22 +847,26 @@
mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
key_len, i, "dec" );
- ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
+ ret = mbedtls_gcm_setkey( &ctx, cipher,
+ key_test_data[key_index_test_data[i]],
key_len );
if( ret != 0 )
goto exit;
ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
- pt_len[i],
- iv[iv_index[i]], iv_len[i],
- additional[add_index[i]], add_len[i],
- ct[j * 6 + i], buf, 16, tag_buf );
+ pt_len_test_data[i],
+ iv_test_data[iv_index_test_data[i]],
+ iv_len_test_data[i],
+ additional_test_data[add_index_test_data[i]],
+ add_len_test_data[i],
+ ct_test_data[j * 6 + i], buf, 16, tag_buf );
if( ret != 0 )
goto exit;
- if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
- memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+ if( memcmp( buf, pt_test_data[pt_index_test_data[i]],
+ pt_len_test_data[i] ) != 0 ||
+ memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
{
ret = 1;
goto exit;
@@ -872,32 +883,40 @@
mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
key_len, i, "enc" );
- ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
+ ret = mbedtls_gcm_setkey( &ctx, cipher,
+ key_test_data[key_index_test_data[i]],
key_len );
if( ret != 0 )
goto exit;
ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
- iv[iv_index[i]], iv_len[i],
- additional[add_index[i]], add_len[i] );
+ iv_test_data[iv_index_test_data[i]],
+ iv_len_test_data[i],
+ additional_test_data[add_index_test_data[i]],
+ add_len_test_data[i] );
if( ret != 0 )
goto exit;
- if( pt_len[i] > 32 )
+ if( pt_len_test_data[i] > 32 )
{
- size_t rest_len = pt_len[i] - 32;
- ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
+ size_t rest_len = pt_len_test_data[i] - 32;
+ ret = mbedtls_gcm_update( &ctx, 32,
+ pt_test_data[pt_index_test_data[i]],
+ buf );
if( ret != 0 )
goto exit;
- ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
- buf + 32 );
+ ret = mbedtls_gcm_update( &ctx, rest_len,
+ pt_test_data[pt_index_test_data[i]] + 32,
+ buf + 32 );
if( ret != 0 )
goto exit;
}
else
{
- ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
+ ret = mbedtls_gcm_update( &ctx, pt_len_test_data[i],
+ pt_test_data[pt_index_test_data[i]],
+ buf );
if( ret != 0 )
goto exit;
}
@@ -906,8 +925,9 @@
if( ret != 0 )
goto exit;
- if( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
- memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+ if( memcmp( buf, ct_test_data[j * 6 + i],
+ pt_len_test_data[i] ) != 0 ||
+ memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
{
ret = 1;
goto exit;
@@ -924,32 +944,38 @@
mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
key_len, i, "dec" );
- ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
+ ret = mbedtls_gcm_setkey( &ctx, cipher,
+ key_test_data[key_index_test_data[i]],
key_len );
if( ret != 0 )
goto exit;
ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
- iv[iv_index[i]], iv_len[i],
- additional[add_index[i]], add_len[i] );
+ iv_test_data[iv_index_test_data[i]],
+ iv_len_test_data[i],
+ additional_test_data[add_index_test_data[i]],
+ add_len_test_data[i] );
if( ret != 0 )
goto exit;
- if( pt_len[i] > 32 )
+ if( pt_len_test_data[i] > 32 )
{
- size_t rest_len = pt_len[i] - 32;
- ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
+ size_t rest_len = pt_len_test_data[i] - 32;
+ ret = mbedtls_gcm_update( &ctx, 32, ct_test_data[j * 6 + i],
+ buf );
if( ret != 0 )
goto exit;
- ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
+ ret = mbedtls_gcm_update( &ctx, rest_len,
+ ct_test_data[j * 6 + i] + 32,
buf + 32 );
if( ret != 0 )
goto exit;
}
else
{
- ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i],
+ ret = mbedtls_gcm_update( &ctx, pt_len_test_data[i],
+ ct_test_data[j * 6 + i],
buf );
if( ret != 0 )
goto exit;
@@ -959,8 +985,9 @@
if( ret != 0 )
goto exit;
- if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
- memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+ if( memcmp( buf, pt_test_data[pt_index_test_data[i]],
+ pt_len_test_data[i] ) != 0 ||
+ memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 )
{
ret = 1;
goto exit;
diff --git a/lib/libmbedtls/mbedtls/library/havege.c b/lib/libmbedtls/mbedtls/library/havege.c
index c5e6126..1140544 100644
--- a/lib/libmbedtls/mbedtls/library/havege.c
+++ b/lib/libmbedtls/mbedtls/library/havege.c
@@ -38,19 +38,9 @@
#include "mbedtls/timing.h"
#include "mbedtls/platform_util.h"
-#include <limits.h>
+#include <stdint.h>
#include <string.h>
-/* If int isn't capable of storing 2^32 distinct values, the code of this
- * module may cause a processor trap or a miscalculation. If int is more
- * than 32 bits, the code may not calculate the intended values. */
-#if INT_MIN + 1 != -0x7fffffff
-#error "The HAVEGE module requires int to be exactly 32 bits, with INT_MIN = -2^31."
-#endif
-#if UINT_MAX != 0xffffffff
-#error "The HAVEGE module requires unsigned to be exactly 32 bits."
-#endif
-
/* ------------------------------------------------------------------------
* On average, one iteration accesses two 8-word blocks in the havege WALK
* table, and generates 16 words in the RES array.
@@ -65,7 +55,7 @@
* ------------------------------------------------------------------------
*/
-#define SWAP(X,Y) { unsigned *T = (X); (X) = (Y); (Y) = T; }
+#define SWAP(X,Y) { uint32_t *T = (X); (X) = (Y); (Y) = T; }
#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
@@ -88,7 +78,7 @@
PTX = (PT1 >> 18) & 7; \
PT1 &= 0x1FFF; \
PT2 &= 0x1FFF; \
- CLK = (unsigned) mbedtls_timing_hardclock(); \
+ CLK = (uint32_t) mbedtls_timing_hardclock(); \
\
i = 0; \
A = &WALK[PT1 ]; RES[i++] ^= *A; \
@@ -111,7 +101,7 @@
\
IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \
*A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \
- *B = IN; CLK = (unsigned) mbedtls_timing_hardclock(); \
+ *B = IN; CLK = (uint32_t) mbedtls_timing_hardclock(); \
*C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \
*D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \
\
@@ -162,20 +152,20 @@
PT1 ^= (PT2 ^ 0x10) & 0x10; \
\
for( n++, i = 0; i < 16; i++ ) \
- POOL[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i];
+ hs->pool[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i];
/*
* Entropy gathering function
*/
static void havege_fill( mbedtls_havege_state *hs )
{
- unsigned i, n = 0;
- unsigned U1, U2, *A, *B, *C, *D;
- unsigned PT1, PT2, *WALK, *POOL, RES[16];
- unsigned PTX, PTY, CLK, PTEST, IN;
+ size_t n = 0;
+ size_t i;
+ uint32_t U1, U2, *A, *B, *C, *D;
+ uint32_t PT1, PT2, *WALK, RES[16];
+ uint32_t PTX, PTY, CLK, PTEST, IN;
- WALK = (unsigned *) hs->WALK;
- POOL = (unsigned *) hs->pool;
+ WALK = hs->WALK;
PT1 = hs->PT1;
PT2 = hs->PT2;
@@ -224,7 +214,7 @@
*/
int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len )
{
- int val;
+ uint32_t val;
size_t use_len;
mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng;
unsigned char *p = buf;
@@ -232,8 +222,8 @@
while( len > 0 )
{
use_len = len;
- if( use_len > sizeof(int) )
- use_len = sizeof(int);
+ if( use_len > sizeof( val ) )
+ use_len = sizeof( val );
if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE )
havege_fill( hs );
diff --git a/lib/libmbedtls/mbedtls/library/hkdf.c b/lib/libmbedtls/mbedtls/library/hkdf.c
index 82d8a42..82df597 100644
--- a/lib/libmbedtls/mbedtls/library/hkdf.c
+++ b/lib/libmbedtls/mbedtls/library/hkdf.c
@@ -29,13 +29,14 @@
#include <string.h>
#include "mbedtls/hkdf.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt,
size_t salt_len, const unsigned char *ikm, size_t ikm_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char prk[MBEDTLS_MD_MAX_SIZE];
ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk );
@@ -114,7 +115,7 @@
n = okm_len / hash_len;
- if( (okm_len % hash_len) != 0 )
+ if( okm_len % hash_len != 0 )
{
n++;
}
@@ -130,11 +131,13 @@
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/lib/libmbedtls/mbedtls/library/hmac_drbg.c b/lib/libmbedtls/mbedtls/library/hmac_drbg.c
index 3fce52d..167cdd5 100644
--- a/lib/libmbedtls/mbedtls/library/hmac_drbg.c
+++ b/lib/libmbedtls/mbedtls/library/hmac_drbg.c
@@ -35,6 +35,7 @@
#include "mbedtls/hmac_drbg.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -74,7 +75,7 @@
unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
unsigned char sep[1];
unsigned char K[MBEDTLS_MD_MAX_SIZE];
- int ret;
+ int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
{
@@ -127,7 +128,7 @@
const mbedtls_md_info_t * md_info,
const unsigned char *data, size_t data_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
return( ret );
@@ -159,7 +160,7 @@
{
unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
size_t seedlen = 0;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
{
size_t total_entropy_len;
@@ -251,7 +252,7 @@
const unsigned char *custom,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t md_size;
if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
@@ -329,7 +330,7 @@
unsigned char *output, size_t out_len,
const unsigned char *additional, size_t add_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
size_t left = out_len;
@@ -398,7 +399,7 @@
*/
int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
#if defined(MBEDTLS_THREADING_C)
@@ -434,7 +435,7 @@
#if defined(MBEDTLS_FS_IO)
int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
FILE *f;
unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
diff --git a/lib/libmbedtls/mbedtls/library/md.c b/lib/libmbedtls/mbedtls/library/md.c
index f0e85f0..869b177 100644
--- a/lib/libmbedtls/mbedtls/library/md.c
+++ b/lib/libmbedtls/mbedtls/library/md.c
@@ -34,6 +34,15 @@
#include "mbedtls/md.h"
#include "mbedtls/md_internal.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
+
+#include "mbedtls/md2.h"
+#include "mbedtls/md4.h"
+#include "mbedtls/md5.h"
+#include "mbedtls/ripemd160.h"
+#include "mbedtls/sha1.h"
+#include "mbedtls/sha256.h"
+#include "mbedtls/sha512.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
@@ -49,6 +58,85 @@
#include <stdio.h>
#endif
+#if defined(MBEDTLS_MD2_C)
+const mbedtls_md_info_t mbedtls_md2_info = {
+ "MD2",
+ MBEDTLS_MD_MD2,
+ 16,
+ 16,
+};
+#endif
+
+#if defined(MBEDTLS_MD4_C)
+const mbedtls_md_info_t mbedtls_md4_info = {
+ "MD4",
+ MBEDTLS_MD_MD4,
+ 16,
+ 64,
+};
+#endif
+
+#if defined(MBEDTLS_MD5_C)
+const mbedtls_md_info_t mbedtls_md5_info = {
+ "MD5",
+ MBEDTLS_MD_MD5,
+ 16,
+ 64,
+};
+#endif
+
+#if defined(MBEDTLS_RIPEMD160_C)
+const mbedtls_md_info_t mbedtls_ripemd160_info = {
+ "RIPEMD160",
+ MBEDTLS_MD_RIPEMD160,
+ 20,
+ 64,
+};
+#endif
+
+#if defined(MBEDTLS_SHA1_C)
+const mbedtls_md_info_t mbedtls_sha1_info = {
+ "SHA1",
+ MBEDTLS_MD_SHA1,
+ 20,
+ 64,
+};
+#endif
+
+#if defined(MBEDTLS_SHA256_C)
+const mbedtls_md_info_t mbedtls_sha224_info = {
+ "SHA224",
+ MBEDTLS_MD_SHA224,
+ 28,
+ 64,
+};
+
+const mbedtls_md_info_t mbedtls_sha256_info = {
+ "SHA256",
+ MBEDTLS_MD_SHA256,
+ 32,
+ 64,
+};
+#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",
+ MBEDTLS_MD_SHA512,
+ 64,
+ 128,
+};
+#endif
+
/*
* Reminder: update profiles in x509_crt.c when adding a new hash!
*/
@@ -56,8 +144,10 @@
#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,
@@ -125,8 +215,10 @@
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
@@ -164,8 +256,10 @@
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
@@ -185,7 +279,54 @@
return;
if( ctx->md_ctx != NULL )
- ctx->md_info->ctx_free_func( ctx->md_ctx );
+ {
+ switch( ctx->md_info->type )
+ {
+#if defined(MBEDTLS_MD2_C)
+ case MBEDTLS_MD_MD2:
+ mbedtls_md2_free( ctx->md_ctx );
+ break;
+#endif
+#if defined(MBEDTLS_MD4_C)
+ case MBEDTLS_MD_MD4:
+ mbedtls_md4_free( ctx->md_ctx );
+ break;
+#endif
+#if defined(MBEDTLS_MD5_C)
+ case MBEDTLS_MD_MD5:
+ mbedtls_md5_free( ctx->md_ctx );
+ break;
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+ case MBEDTLS_MD_RIPEMD160:
+ mbedtls_ripemd160_free( ctx->md_ctx );
+ break;
+#endif
+#if defined(MBEDTLS_SHA1_C)
+ case MBEDTLS_MD_SHA1:
+ mbedtls_sha1_free( ctx->md_ctx );
+ break;
+#endif
+#if defined(MBEDTLS_SHA256_C)
+ case MBEDTLS_MD_SHA224:
+ case MBEDTLS_MD_SHA256:
+ mbedtls_sha256_free( ctx->md_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;
+#endif
+ default:
+ /* Shouldn't happen */
+ break;
+ }
+ mbedtls_free( ctx->md_ctx );
+ }
if( ctx->hmac_ctx != NULL )
{
@@ -207,7 +348,50 @@
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
}
- dst->md_info->clone_func( dst->md_ctx, src->md_ctx );
+ switch( src->md_info->type )
+ {
+#if defined(MBEDTLS_MD2_C)
+ case MBEDTLS_MD_MD2:
+ mbedtls_md2_clone( dst->md_ctx, src->md_ctx );
+ break;
+#endif
+#if defined(MBEDTLS_MD4_C)
+ case MBEDTLS_MD_MD4:
+ mbedtls_md4_clone( dst->md_ctx, src->md_ctx );
+ break;
+#endif
+#if defined(MBEDTLS_MD5_C)
+ case MBEDTLS_MD_MD5:
+ mbedtls_md5_clone( dst->md_ctx, src->md_ctx );
+ break;
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+ case MBEDTLS_MD_RIPEMD160:
+ mbedtls_ripemd160_clone( dst->md_ctx, src->md_ctx );
+ break;
+#endif
+#if defined(MBEDTLS_SHA1_C)
+ case MBEDTLS_MD_SHA1:
+ mbedtls_sha1_clone( dst->md_ctx, src->md_ctx );
+ break;
+#endif
+#if defined(MBEDTLS_SHA256_C)
+ case MBEDTLS_MD_SHA224:
+ case MBEDTLS_MD_SHA256:
+ mbedtls_sha256_clone( dst->md_ctx, src->md_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_clone( dst->md_ctx, src->md_ctx );
+ break;
+#endif
+ default:
+ return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+ }
if( dst->hmac_ctx != NULL && src->hmac_ctx != NULL )
memcpy( dst->hmac_ctx, src->hmac_ctx, 2 * src->md_info->block_size );
@@ -222,20 +406,71 @@
}
#endif
+#define ALLOC( type ) \
+ do { \
+ ctx->md_ctx = mbedtls_calloc( 1, sizeof( mbedtls_##type##_context ) ); \
+ if( ctx->md_ctx == NULL ) \
+ return( MBEDTLS_ERR_MD_ALLOC_FAILED ); \
+ mbedtls_##type##_init( ctx->md_ctx ); \
+ } \
+ while( 0 )
+
int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac )
{
if( md_info == NULL || ctx == NULL )
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
- if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL )
- return( MBEDTLS_ERR_MD_ALLOC_FAILED );
+ switch( md_info->type )
+ {
+#if defined(MBEDTLS_MD2_C)
+ case MBEDTLS_MD_MD2:
+ ALLOC( md2 );
+ break;
+#endif
+#if defined(MBEDTLS_MD4_C)
+ case MBEDTLS_MD_MD4:
+ ALLOC( md4 );
+ break;
+#endif
+#if defined(MBEDTLS_MD5_C)
+ case MBEDTLS_MD_MD5:
+ ALLOC( md5 );
+ break;
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+ case MBEDTLS_MD_RIPEMD160:
+ ALLOC( ripemd160 );
+ break;
+#endif
+#if defined(MBEDTLS_SHA1_C)
+ case MBEDTLS_MD_SHA1:
+ ALLOC( sha1 );
+ break;
+#endif
+#if defined(MBEDTLS_SHA256_C)
+ case MBEDTLS_MD_SHA224:
+ case MBEDTLS_MD_SHA256:
+ ALLOC( sha256 );
+ 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;
+#endif
+ default:
+ return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+ }
if( hmac != 0 )
{
ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size );
if( ctx->hmac_ctx == NULL )
{
- md_info->ctx_free_func( ctx->md_ctx );
+ mbedtls_md_free( ctx );
return( MBEDTLS_ERR_MD_ALLOC_FAILED );
}
}
@@ -244,13 +479,52 @@
return( 0 );
}
+#undef ALLOC
int mbedtls_md_starts( mbedtls_md_context_t *ctx )
{
if( ctx == NULL || ctx->md_info == NULL )
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
- return( ctx->md_info->starts_func( ctx->md_ctx ) );
+ switch( ctx->md_info->type )
+ {
+#if defined(MBEDTLS_MD2_C)
+ case MBEDTLS_MD_MD2:
+ return( mbedtls_md2_starts_ret( ctx->md_ctx ) );
+#endif
+#if defined(MBEDTLS_MD4_C)
+ case MBEDTLS_MD_MD4:
+ return( mbedtls_md4_starts_ret( ctx->md_ctx ) );
+#endif
+#if defined(MBEDTLS_MD5_C)
+ case MBEDTLS_MD_MD5:
+ return( mbedtls_md5_starts_ret( ctx->md_ctx ) );
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+ case MBEDTLS_MD_RIPEMD160:
+ return( mbedtls_ripemd160_starts_ret( ctx->md_ctx ) );
+#endif
+#if defined(MBEDTLS_SHA1_C)
+ case MBEDTLS_MD_SHA1:
+ return( mbedtls_sha1_starts_ret( ctx->md_ctx ) );
+#endif
+#if defined(MBEDTLS_SHA256_C)
+ case MBEDTLS_MD_SHA224:
+ return( mbedtls_sha256_starts_ret( ctx->md_ctx, 1 ) );
+ case MBEDTLS_MD_SHA256:
+ 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
+ default:
+ return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+ }
}
int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen )
@@ -258,7 +532,45 @@
if( ctx == NULL || ctx->md_info == NULL )
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
- return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) );
+ switch( ctx->md_info->type )
+ {
+#if defined(MBEDTLS_MD2_C)
+ case MBEDTLS_MD_MD2:
+ return( mbedtls_md2_update_ret( ctx->md_ctx, input, ilen ) );
+#endif
+#if defined(MBEDTLS_MD4_C)
+ case MBEDTLS_MD_MD4:
+ return( mbedtls_md4_update_ret( ctx->md_ctx, input, ilen ) );
+#endif
+#if defined(MBEDTLS_MD5_C)
+ case MBEDTLS_MD_MD5:
+ return( mbedtls_md5_update_ret( ctx->md_ctx, input, ilen ) );
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+ case MBEDTLS_MD_RIPEMD160:
+ return( mbedtls_ripemd160_update_ret( ctx->md_ctx, input, ilen ) );
+#endif
+#if defined(MBEDTLS_SHA1_C)
+ case MBEDTLS_MD_SHA1:
+ return( mbedtls_sha1_update_ret( ctx->md_ctx, input, ilen ) );
+#endif
+#if defined(MBEDTLS_SHA256_C)
+ case MBEDTLS_MD_SHA224:
+ return( mbedtls_sha256_update_ret( ctx->md_ctx, input, ilen ) );
+ case MBEDTLS_MD_SHA256:
+ 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
+ default:
+ return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+ }
}
int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output )
@@ -266,7 +578,45 @@
if( ctx == NULL || ctx->md_info == NULL )
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
- return( ctx->md_info->finish_func( ctx->md_ctx, output ) );
+ switch( ctx->md_info->type )
+ {
+#if defined(MBEDTLS_MD2_C)
+ case MBEDTLS_MD_MD2:
+ return( mbedtls_md2_finish_ret( ctx->md_ctx, output ) );
+#endif
+#if defined(MBEDTLS_MD4_C)
+ case MBEDTLS_MD_MD4:
+ return( mbedtls_md4_finish_ret( ctx->md_ctx, output ) );
+#endif
+#if defined(MBEDTLS_MD5_C)
+ case MBEDTLS_MD_MD5:
+ return( mbedtls_md5_finish_ret( ctx->md_ctx, output ) );
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+ case MBEDTLS_MD_RIPEMD160:
+ return( mbedtls_ripemd160_finish_ret( ctx->md_ctx, output ) );
+#endif
+#if defined(MBEDTLS_SHA1_C)
+ case MBEDTLS_MD_SHA1:
+ return( mbedtls_sha1_finish_ret( ctx->md_ctx, output ) );
+#endif
+#if defined(MBEDTLS_SHA256_C)
+ case MBEDTLS_MD_SHA224:
+ return( mbedtls_sha256_finish_ret( ctx->md_ctx, output ) );
+ case MBEDTLS_MD_SHA256:
+ 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
+ default:
+ return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+ }
}
int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen,
@@ -275,13 +625,51 @@
if( md_info == NULL )
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
- return( md_info->digest_func( input, ilen, output ) );
+ switch( md_info->type )
+ {
+#if defined(MBEDTLS_MD2_C)
+ case MBEDTLS_MD_MD2:
+ return( mbedtls_md2_ret( input, ilen, output ) );
+#endif
+#if defined(MBEDTLS_MD4_C)
+ case MBEDTLS_MD_MD4:
+ return( mbedtls_md4_ret( input, ilen, output ) );
+#endif
+#if defined(MBEDTLS_MD5_C)
+ case MBEDTLS_MD_MD5:
+ return( mbedtls_md5_ret( input, ilen, output ) );
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+ case MBEDTLS_MD_RIPEMD160:
+ return( mbedtls_ripemd160_ret( input, ilen, output ) );
+#endif
+#if defined(MBEDTLS_SHA1_C)
+ case MBEDTLS_MD_SHA1:
+ return( mbedtls_sha1_ret( input, ilen, output ) );
+#endif
+#if defined(MBEDTLS_SHA256_C)
+ case MBEDTLS_MD_SHA224:
+ return( mbedtls_sha256_ret( input, ilen, output, 1 ) );
+ case MBEDTLS_MD_SHA256:
+ 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
+ default:
+ return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+ }
}
#if defined(MBEDTLS_FS_IO)
int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
FILE *f;
size_t n;
mbedtls_md_context_t ctx;
@@ -298,17 +686,17 @@
if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 )
goto cleanup;
- if( ( ret = md_info->starts_func( ctx.md_ctx ) ) != 0 )
+ if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 )
goto cleanup;
while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
- if( ( ret = md_info->update_func( ctx.md_ctx, buf, n ) ) != 0 )
+ if( ( ret = mbedtls_md_update( &ctx, buf, n ) ) != 0 )
goto cleanup;
if( ferror( f ) != 0 )
ret = MBEDTLS_ERR_MD_FILE_IO_ERROR;
else
- ret = md_info->finish_func( ctx.md_ctx, output );
+ ret = mbedtls_md_finish( &ctx, output );
cleanup:
mbedtls_platform_zeroize( buf, sizeof( buf ) );
@@ -321,7 +709,7 @@
int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char sum[MBEDTLS_MD_MAX_SIZE];
unsigned char *ipad, *opad;
size_t i;
@@ -331,11 +719,11 @@
if( keylen > (size_t) ctx->md_info->block_size )
{
- if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
+ if( ( ret = mbedtls_md_starts( ctx ) ) != 0 )
goto cleanup;
- if( ( ret = ctx->md_info->update_func( ctx->md_ctx, key, keylen ) ) != 0 )
+ if( ( ret = mbedtls_md_update( ctx, key, keylen ) ) != 0 )
goto cleanup;
- if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, sum ) ) != 0 )
+ if( ( ret = mbedtls_md_finish( ctx, sum ) ) != 0 )
goto cleanup;
keylen = ctx->md_info->size;
@@ -354,10 +742,10 @@
opad[i] = (unsigned char)( opad[i] ^ key[i] );
}
- if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
+ if( ( ret = mbedtls_md_starts( ctx ) ) != 0 )
goto cleanup;
- if( ( ret = ctx->md_info->update_func( ctx->md_ctx, ipad,
- ctx->md_info->block_size ) ) != 0 )
+ if( ( ret = mbedtls_md_update( ctx, ipad,
+ ctx->md_info->block_size ) ) != 0 )
goto cleanup;
cleanup:
@@ -371,12 +759,12 @@
if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
- return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) );
+ return( mbedtls_md_update( ctx, input, ilen ) );
}
int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char tmp[MBEDTLS_MD_MAX_SIZE];
unsigned char *opad;
@@ -385,22 +773,22 @@
opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size;
- if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, tmp ) ) != 0 )
+ if( ( ret = mbedtls_md_finish( ctx, tmp ) ) != 0 )
return( ret );
- if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
+ if( ( ret = mbedtls_md_starts( ctx ) ) != 0 )
return( ret );
- if( ( ret = ctx->md_info->update_func( ctx->md_ctx, opad,
- ctx->md_info->block_size ) ) != 0 )
+ if( ( ret = mbedtls_md_update( ctx, opad,
+ ctx->md_info->block_size ) ) != 0 )
return( ret );
- if( ( ret = ctx->md_info->update_func( ctx->md_ctx, tmp,
- ctx->md_info->size ) ) != 0 )
+ if( ( ret = mbedtls_md_update( ctx, tmp,
+ ctx->md_info->size ) ) != 0 )
return( ret );
- return( ctx->md_info->finish_func( ctx->md_ctx, output ) );
+ return( mbedtls_md_finish( ctx, output ) );
}
int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *ipad;
if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
@@ -408,10 +796,9 @@
ipad = (unsigned char *) ctx->hmac_ctx;
- if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
+ if( ( ret = mbedtls_md_starts( ctx ) ) != 0 )
return( ret );
- return( ctx->md_info->update_func( ctx->md_ctx, ipad,
- ctx->md_info->block_size ) );
+ return( mbedtls_md_update( ctx, ipad, ctx->md_info->block_size ) );
}
int mbedtls_md_hmac( const mbedtls_md_info_t *md_info,
@@ -420,7 +807,7 @@
unsigned char *output )
{
mbedtls_md_context_t ctx;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( md_info == NULL )
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
@@ -448,7 +835,45 @@
if( ctx == NULL || ctx->md_info == NULL )
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
- return( ctx->md_info->process_func( ctx->md_ctx, data ) );
+ switch( ctx->md_info->type )
+ {
+#if defined(MBEDTLS_MD2_C)
+ case MBEDTLS_MD_MD2:
+ return( mbedtls_internal_md2_process( ctx->md_ctx ) );
+#endif
+#if defined(MBEDTLS_MD4_C)
+ case MBEDTLS_MD_MD4:
+ return( mbedtls_internal_md4_process( ctx->md_ctx, data ) );
+#endif
+#if defined(MBEDTLS_MD5_C)
+ case MBEDTLS_MD_MD5:
+ return( mbedtls_internal_md5_process( ctx->md_ctx, data ) );
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+ case MBEDTLS_MD_RIPEMD160:
+ return( mbedtls_internal_ripemd160_process( ctx->md_ctx, data ) );
+#endif
+#if defined(MBEDTLS_SHA1_C)
+ case MBEDTLS_MD_SHA1:
+ return( mbedtls_internal_sha1_process( ctx->md_ctx, data ) );
+#endif
+#if defined(MBEDTLS_SHA256_C)
+ case MBEDTLS_MD_SHA224:
+ return( mbedtls_internal_sha256_process( ctx->md_ctx, data ) );
+ case MBEDTLS_MD_SHA256:
+ 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
+ default:
+ return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+ }
}
unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info )
diff --git a/lib/libmbedtls/mbedtls/library/md2.c b/lib/libmbedtls/mbedtls/library/md2.c
index f30086a..32e926c 100644
--- a/lib/libmbedtls/mbedtls/library/md2.c
+++ b/lib/libmbedtls/mbedtls/library/md2.c
@@ -35,6 +35,7 @@
#include "mbedtls/md2.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -170,7 +171,7 @@
const unsigned char *input,
size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill;
while( ilen > 0 )
@@ -212,7 +213,7 @@
int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx,
unsigned char output[16] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
unsigned char x;
@@ -250,7 +251,7 @@
size_t ilen,
unsigned char output[16] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md2_context ctx;
mbedtls_md2_init( &ctx );
diff --git a/lib/libmbedtls/mbedtls/library/md4.c b/lib/libmbedtls/mbedtls/library/md4.c
index 8156d0b..943c953 100644
--- a/lib/libmbedtls/mbedtls/library/md4.c
+++ b/lib/libmbedtls/mbedtls/library/md4.c
@@ -35,6 +35,7 @@
#include "mbedtls/md4.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -253,7 +254,7 @@
const unsigned char *input,
size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill;
uint32_t left;
@@ -323,7 +324,7 @@
int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
unsigned char output[16] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
@@ -371,7 +372,7 @@
size_t ilen,
unsigned char output[16] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md4_context ctx;
mbedtls_md4_init( &ctx );
diff --git a/lib/libmbedtls/mbedtls/library/md5.c b/lib/libmbedtls/mbedtls/library/md5.c
index 61bdcea..da4fa0d 100644
--- a/lib/libmbedtls/mbedtls/library/md5.c
+++ b/lib/libmbedtls/mbedtls/library/md5.c
@@ -34,6 +34,7 @@
#include "mbedtls/md5.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -259,7 +260,7 @@
const unsigned char *input,
size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill;
uint32_t left;
@@ -318,7 +319,7 @@
int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx,
unsigned char output[16] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t used;
uint32_t high, low;
@@ -386,7 +387,7 @@
size_t ilen,
unsigned char output[16] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md5_context ctx;
mbedtls_md5_init( &ctx );
diff --git a/lib/libmbedtls/mbedtls/library/md_wrap.c b/lib/libmbedtls/mbedtls/library/md_wrap.c
deleted file mode 100644
index 8bb9349..0000000
--- a/lib/libmbedtls/mbedtls/library/md_wrap.c
+++ /dev/null
@@ -1,586 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-/**
- * \file md_wrap.c
- *
- * \brief Generic message digest wrapper for mbed TLS
- *
- * \author Adriaan de Jong <dejong@fox-it.com>
- *
- * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * This file is part of mbed TLS (https://tls.mbed.org)
- */
-
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
-
-#if defined(MBEDTLS_MD_C)
-
-#include "mbedtls/md_internal.h"
-
-#if defined(MBEDTLS_MD2_C)
-#include "mbedtls/md2.h"
-#endif
-
-#if defined(MBEDTLS_MD4_C)
-#include "mbedtls/md4.h"
-#endif
-
-#if defined(MBEDTLS_MD5_C)
-#include "mbedtls/md5.h"
-#endif
-
-#if defined(MBEDTLS_RIPEMD160_C)
-#include "mbedtls/ripemd160.h"
-#endif
-
-#if defined(MBEDTLS_SHA1_C)
-#include "mbedtls/sha1.h"
-#endif
-
-#if defined(MBEDTLS_SHA256_C)
-#include "mbedtls/sha256.h"
-#endif
-
-#if defined(MBEDTLS_SHA512_C)
-#include "mbedtls/sha512.h"
-#endif
-
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdlib.h>
-#define mbedtls_calloc calloc
-#define mbedtls_free free
-#endif
-
-#if defined(MBEDTLS_MD2_C)
-
-static int md2_starts_wrap( void *ctx )
-{
- return( mbedtls_md2_starts_ret( (mbedtls_md2_context *) ctx ) );
-}
-
-static int md2_update_wrap( void *ctx, const unsigned char *input,
- size_t ilen )
-{
- return( mbedtls_md2_update_ret( (mbedtls_md2_context *) ctx, input, ilen ) );
-}
-
-static int md2_finish_wrap( void *ctx, unsigned char *output )
-{
- return( mbedtls_md2_finish_ret( (mbedtls_md2_context *) ctx, output ) );
-}
-
-static void *md2_ctx_alloc( void )
-{
- void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md2_context ) );
-
- if( ctx != NULL )
- mbedtls_md2_init( (mbedtls_md2_context *) ctx );
-
- return( ctx );
-}
-
-static void md2_ctx_free( void *ctx )
-{
- mbedtls_md2_free( (mbedtls_md2_context *) ctx );
- mbedtls_free( ctx );
-}
-
-static void md2_clone_wrap( void *dst, const void *src )
-{
- mbedtls_md2_clone( (mbedtls_md2_context *) dst,
- (const mbedtls_md2_context *) src );
-}
-
-static int md2_process_wrap( void *ctx, const unsigned char *data )
-{
- ((void) data);
-
- return( mbedtls_internal_md2_process( (mbedtls_md2_context *) ctx ) );
-}
-
-const mbedtls_md_info_t mbedtls_md2_info = {
- MBEDTLS_MD_MD2,
- "MD2",
- 16,
- 16,
- md2_starts_wrap,
- md2_update_wrap,
- md2_finish_wrap,
- mbedtls_md2_ret,
- md2_ctx_alloc,
- md2_ctx_free,
- md2_clone_wrap,
- md2_process_wrap,
-};
-
-#endif /* MBEDTLS_MD2_C */
-
-#if defined(MBEDTLS_MD4_C)
-
-static int md4_starts_wrap( void *ctx )
-{
- return( mbedtls_md4_starts_ret( (mbedtls_md4_context *) ctx ) );
-}
-
-static int md4_update_wrap( void *ctx, const unsigned char *input,
- size_t ilen )
-{
- return( mbedtls_md4_update_ret( (mbedtls_md4_context *) ctx, input, ilen ) );
-}
-
-static int md4_finish_wrap( void *ctx, unsigned char *output )
-{
- return( mbedtls_md4_finish_ret( (mbedtls_md4_context *) ctx, output ) );
-}
-
-static void *md4_ctx_alloc( void )
-{
- void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md4_context ) );
-
- if( ctx != NULL )
- mbedtls_md4_init( (mbedtls_md4_context *) ctx );
-
- return( ctx );
-}
-
-static void md4_ctx_free( void *ctx )
-{
- mbedtls_md4_free( (mbedtls_md4_context *) ctx );
- mbedtls_free( ctx );
-}
-
-static void md4_clone_wrap( void *dst, const void *src )
-{
- mbedtls_md4_clone( (mbedtls_md4_context *) dst,
- (const mbedtls_md4_context *) src );
-}
-
-static int md4_process_wrap( void *ctx, const unsigned char *data )
-{
- return( mbedtls_internal_md4_process( (mbedtls_md4_context *) ctx, data ) );
-}
-
-const mbedtls_md_info_t mbedtls_md4_info = {
- MBEDTLS_MD_MD4,
- "MD4",
- 16,
- 64,
- md4_starts_wrap,
- md4_update_wrap,
- md4_finish_wrap,
- mbedtls_md4_ret,
- md4_ctx_alloc,
- md4_ctx_free,
- md4_clone_wrap,
- md4_process_wrap,
-};
-
-#endif /* MBEDTLS_MD4_C */
-
-#if defined(MBEDTLS_MD5_C)
-
-static int md5_starts_wrap( void *ctx )
-{
- return( mbedtls_md5_starts_ret( (mbedtls_md5_context *) ctx ) );
-}
-
-static int md5_update_wrap( void *ctx, const unsigned char *input,
- size_t ilen )
-{
- return( mbedtls_md5_update_ret( (mbedtls_md5_context *) ctx, input, ilen ) );
-}
-
-static int md5_finish_wrap( void *ctx, unsigned char *output )
-{
- return( mbedtls_md5_finish_ret( (mbedtls_md5_context *) ctx, output ) );
-}
-
-static void *md5_ctx_alloc( void )
-{
- void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md5_context ) );
-
- if( ctx != NULL )
- mbedtls_md5_init( (mbedtls_md5_context *) ctx );
-
- return( ctx );
-}
-
-static void md5_ctx_free( void *ctx )
-{
- mbedtls_md5_free( (mbedtls_md5_context *) ctx );
- mbedtls_free( ctx );
-}
-
-static void md5_clone_wrap( void *dst, const void *src )
-{
- mbedtls_md5_clone( (mbedtls_md5_context *) dst,
- (const mbedtls_md5_context *) src );
-}
-
-static int md5_process_wrap( void *ctx, const unsigned char *data )
-{
- return( mbedtls_internal_md5_process( (mbedtls_md5_context *) ctx, data ) );
-}
-
-const mbedtls_md_info_t mbedtls_md5_info = {
- MBEDTLS_MD_MD5,
- "MD5",
- 16,
- 64,
- md5_starts_wrap,
- md5_update_wrap,
- md5_finish_wrap,
- mbedtls_md5_ret,
- md5_ctx_alloc,
- md5_ctx_free,
- md5_clone_wrap,
- md5_process_wrap,
-};
-
-#endif /* MBEDTLS_MD5_C */
-
-#if defined(MBEDTLS_RIPEMD160_C)
-
-static int ripemd160_starts_wrap( void *ctx )
-{
- return( mbedtls_ripemd160_starts_ret( (mbedtls_ripemd160_context *) ctx ) );
-}
-
-static int ripemd160_update_wrap( void *ctx, const unsigned char *input,
- size_t ilen )
-{
- return( mbedtls_ripemd160_update_ret( (mbedtls_ripemd160_context *) ctx,
- input, ilen ) );
-}
-
-static int ripemd160_finish_wrap( void *ctx, unsigned char *output )
-{
- return( mbedtls_ripemd160_finish_ret( (mbedtls_ripemd160_context *) ctx,
- output ) );
-}
-
-static void *ripemd160_ctx_alloc( void )
-{
- void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ripemd160_context ) );
-
- if( ctx != NULL )
- mbedtls_ripemd160_init( (mbedtls_ripemd160_context *) ctx );
-
- return( ctx );
-}
-
-static void ripemd160_ctx_free( void *ctx )
-{
- mbedtls_ripemd160_free( (mbedtls_ripemd160_context *) ctx );
- mbedtls_free( ctx );
-}
-
-static void ripemd160_clone_wrap( void *dst, const void *src )
-{
- mbedtls_ripemd160_clone( (mbedtls_ripemd160_context *) dst,
- (const mbedtls_ripemd160_context *) src );
-}
-
-static int ripemd160_process_wrap( void *ctx, const unsigned char *data )
-{
- return( mbedtls_internal_ripemd160_process(
- (mbedtls_ripemd160_context *) ctx, data ) );
-}
-
-const mbedtls_md_info_t mbedtls_ripemd160_info = {
- MBEDTLS_MD_RIPEMD160,
- "RIPEMD160",
- 20,
- 64,
- ripemd160_starts_wrap,
- ripemd160_update_wrap,
- ripemd160_finish_wrap,
- mbedtls_ripemd160_ret,
- ripemd160_ctx_alloc,
- ripemd160_ctx_free,
- ripemd160_clone_wrap,
- ripemd160_process_wrap,
-};
-
-#endif /* MBEDTLS_RIPEMD160_C */
-
-#if defined(MBEDTLS_SHA1_C)
-
-static int sha1_starts_wrap( void *ctx )
-{
- return( mbedtls_sha1_starts_ret( (mbedtls_sha1_context *) ctx ) );
-}
-
-static int sha1_update_wrap( void *ctx, const unsigned char *input,
- size_t ilen )
-{
- return( mbedtls_sha1_update_ret( (mbedtls_sha1_context *) ctx,
- input, ilen ) );
-}
-
-static int sha1_finish_wrap( void *ctx, unsigned char *output )
-{
- return( mbedtls_sha1_finish_ret( (mbedtls_sha1_context *) ctx, output ) );
-}
-
-static void *sha1_ctx_alloc( void )
-{
- void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha1_context ) );
-
- if( ctx != NULL )
- mbedtls_sha1_init( (mbedtls_sha1_context *) ctx );
-
- return( ctx );
-}
-
-static void sha1_clone_wrap( void *dst, const void *src )
-{
- mbedtls_sha1_clone( (mbedtls_sha1_context *) dst,
- (const mbedtls_sha1_context *) src );
-}
-
-static void sha1_ctx_free( void *ctx )
-{
- mbedtls_sha1_free( (mbedtls_sha1_context *) ctx );
- mbedtls_free( ctx );
-}
-
-static int sha1_process_wrap( void *ctx, const unsigned char *data )
-{
- return( mbedtls_internal_sha1_process( (mbedtls_sha1_context *) ctx,
- data ) );
-}
-
-const mbedtls_md_info_t mbedtls_sha1_info = {
- MBEDTLS_MD_SHA1,
- "SHA1",
- 20,
- 64,
- sha1_starts_wrap,
- sha1_update_wrap,
- sha1_finish_wrap,
- mbedtls_sha1_ret,
- sha1_ctx_alloc,
- sha1_ctx_free,
- sha1_clone_wrap,
- sha1_process_wrap,
-};
-
-#endif /* MBEDTLS_SHA1_C */
-
-/*
- * Wrappers for generic message digests
- */
-#if defined(MBEDTLS_SHA256_C)
-
-static int sha224_starts_wrap( void *ctx )
-{
- return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 1 ) );
-}
-
-static int sha224_update_wrap( void *ctx, const unsigned char *input,
- size_t ilen )
-{
- return( mbedtls_sha256_update_ret( (mbedtls_sha256_context *) ctx,
- input, ilen ) );
-}
-
-static int sha224_finish_wrap( void *ctx, unsigned char *output )
-{
- return( mbedtls_sha256_finish_ret( (mbedtls_sha256_context *) ctx,
- output ) );
-}
-
-static int sha224_wrap( const unsigned char *input, size_t ilen,
- unsigned char *output )
-{
- return( mbedtls_sha256_ret( input, ilen, output, 1 ) );
-}
-
-static void *sha224_ctx_alloc( void )
-{
- void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha256_context ) );
-
- if( ctx != NULL )
- mbedtls_sha256_init( (mbedtls_sha256_context *) ctx );
-
- return( ctx );
-}
-
-static void sha224_ctx_free( void *ctx )
-{
- mbedtls_sha256_free( (mbedtls_sha256_context *) ctx );
- mbedtls_free( ctx );
-}
-
-static void sha224_clone_wrap( void *dst, const void *src )
-{
- mbedtls_sha256_clone( (mbedtls_sha256_context *) dst,
- (const mbedtls_sha256_context *) src );
-}
-
-static int sha224_process_wrap( void *ctx, const unsigned char *data )
-{
- return( mbedtls_internal_sha256_process( (mbedtls_sha256_context *) ctx,
- data ) );
-}
-
-const mbedtls_md_info_t mbedtls_sha224_info = {
- MBEDTLS_MD_SHA224,
- "SHA224",
- 28,
- 64,
- sha224_starts_wrap,
- sha224_update_wrap,
- sha224_finish_wrap,
- sha224_wrap,
- sha224_ctx_alloc,
- sha224_ctx_free,
- sha224_clone_wrap,
- sha224_process_wrap,
-};
-
-static int sha256_starts_wrap( void *ctx )
-{
- return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 0 ) );
-}
-
-static int sha256_wrap( const unsigned char *input, size_t ilen,
- unsigned char *output )
-{
- return( mbedtls_sha256_ret( input, ilen, output, 0 ) );
-}
-
-const mbedtls_md_info_t mbedtls_sha256_info = {
- MBEDTLS_MD_SHA256,
- "SHA256",
- 32,
- 64,
- sha256_starts_wrap,
- sha224_update_wrap,
- sha224_finish_wrap,
- sha256_wrap,
- sha224_ctx_alloc,
- sha224_ctx_free,
- sha224_clone_wrap,
- sha224_process_wrap,
-};
-
-#endif /* MBEDTLS_SHA256_C */
-
-#if defined(MBEDTLS_SHA512_C)
-
-static int sha384_starts_wrap( void *ctx )
-{
- return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 1 ) );
-}
-
-static int sha384_update_wrap( void *ctx, const unsigned char *input,
- size_t ilen )
-{
- return( mbedtls_sha512_update_ret( (mbedtls_sha512_context *) ctx,
- input, ilen ) );
-}
-
-static int sha384_finish_wrap( void *ctx, unsigned char *output )
-{
- return( mbedtls_sha512_finish_ret( (mbedtls_sha512_context *) ctx,
- output ) );
-}
-
-static int sha384_wrap( const unsigned char *input, size_t ilen,
- unsigned char *output )
-{
- return( mbedtls_sha512_ret( input, ilen, output, 1 ) );
-}
-
-static void *sha384_ctx_alloc( void )
-{
- void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha512_context ) );
-
- if( ctx != NULL )
- mbedtls_sha512_init( (mbedtls_sha512_context *) ctx );
-
- return( ctx );
-}
-
-static void sha384_ctx_free( void *ctx )
-{
- mbedtls_sha512_free( (mbedtls_sha512_context *) ctx );
- mbedtls_free( ctx );
-}
-
-static void sha384_clone_wrap( void *dst, const void *src )
-{
- mbedtls_sha512_clone( (mbedtls_sha512_context *) dst,
- (const mbedtls_sha512_context *) src );
-}
-
-static int sha384_process_wrap( void *ctx, const unsigned char *data )
-{
- return( mbedtls_internal_sha512_process( (mbedtls_sha512_context *) ctx,
- data ) );
-}
-
-const mbedtls_md_info_t mbedtls_sha384_info = {
- MBEDTLS_MD_SHA384,
- "SHA384",
- 48,
- 128,
- sha384_starts_wrap,
- sha384_update_wrap,
- sha384_finish_wrap,
- sha384_wrap,
- sha384_ctx_alloc,
- sha384_ctx_free,
- sha384_clone_wrap,
- sha384_process_wrap,
-};
-
-static int sha512_starts_wrap( void *ctx )
-{
- return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 0 ) );
-}
-
-static int sha512_wrap( const unsigned char *input, size_t ilen,
- unsigned char *output )
-{
- return( mbedtls_sha512_ret( input, ilen, output, 0 ) );
-}
-
-const mbedtls_md_info_t mbedtls_sha512_info = {
- MBEDTLS_MD_SHA512,
- "SHA512",
- 64,
- 128,
- sha512_starts_wrap,
- sha384_update_wrap,
- sha384_finish_wrap,
- sha512_wrap,
- sha384_ctx_alloc,
- sha384_ctx_free,
- sha384_clone_wrap,
- sha384_process_wrap,
-};
-
-#endif /* MBEDTLS_SHA512_C */
-
-#endif /* MBEDTLS_MD_C */
diff --git a/lib/libmbedtls/mbedtls/library/net_sockets.c b/lib/libmbedtls/mbedtls/library/net_sockets.c
index 4715cfa..bb313c2 100644
--- a/lib/libmbedtls/mbedtls/library/net_sockets.c
+++ b/lib/libmbedtls/mbedtls/library/net_sockets.c
@@ -45,6 +45,7 @@
#endif
#include "mbedtls/net_sockets.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -147,7 +148,7 @@
int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host,
const char *port, int proto )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
struct addrinfo hints, *addr_list, *cur;
if( ( ret = net_prepare() ) != 0 )
@@ -313,7 +314,7 @@
mbedtls_net_context *client_ctx,
void *client_ip, size_t buf_size, size_t *ip_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int type;
struct sockaddr_storage client_addr;
@@ -455,7 +456,7 @@
int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
struct timeval tv;
fd_set read_fds;
@@ -540,7 +541,7 @@
*/
int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int fd = ((mbedtls_net_context *) ctx)->fd;
if( fd < 0 )
@@ -577,7 +578,7 @@
int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf,
size_t len, uint32_t timeout )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
struct timeval tv;
fd_set read_fds;
int fd = ((mbedtls_net_context *) ctx)->fd;
@@ -620,7 +621,7 @@
*/
int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int fd = ((mbedtls_net_context *) ctx)->fd;
if( fd < 0 )
@@ -652,6 +653,19 @@
}
/*
+ * Close the connection
+ */
+void mbedtls_net_close( mbedtls_net_context *ctx )
+{
+ if( ctx->fd == -1 )
+ return;
+
+ close( ctx->fd );
+
+ ctx->fd = -1;
+}
+
+/*
* Gracefully close the connection
*/
void mbedtls_net_free( mbedtls_net_context *ctx )
diff --git a/lib/libmbedtls/mbedtls/library/nist_kw.c b/lib/libmbedtls/mbedtls/library/nist_kw.c
index 4a2c10e..7201346 100644
--- a/lib/libmbedtls/mbedtls/library/nist_kw.c
+++ b/lib/libmbedtls/mbedtls/library/nist_kw.c
@@ -39,6 +39,7 @@
#include "mbedtls/nist_kw.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <stdint.h>
#include <string.h>
@@ -116,7 +117,7 @@
unsigned int keybits,
const int is_wrap )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_cipher_info_t *cipher_info;
cipher_info = mbedtls_cipher_info_from_values( cipher,
diff --git a/lib/libmbedtls/mbedtls/library/oid.c b/lib/libmbedtls/mbedtls/library/oid.c
index b361fad..6272f32 100644
--- a/lib/libmbedtls/mbedtls/library/oid.c
+++ b/lib/libmbedtls/mbedtls/library/oid.c
@@ -31,6 +31,7 @@
#include "mbedtls/oid.h"
#include "mbedtls/rsa.h"
+#include "mbedtls/error.h"
#include <stdio.h>
#include <string.h>
@@ -41,10 +42,6 @@
#define mbedtls_snprintf snprintf
#endif
-#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
-#include "mbedtls/x509.h"
-#endif
-
/*
* Macro to automatically add the size of #define'd OIDs
*/
@@ -155,7 +152,6 @@
return( MBEDTLS_ERR_OID_NOT_FOUND ); \
}
-#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
/*
* For X520 attribute types
*/
@@ -262,24 +258,28 @@
static const oid_x509_ext_t oid_x509_ext[] =
{
{
- { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" },
- MBEDTLS_X509_EXT_BASIC_CONSTRAINTS,
+ { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" },
+ MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS,
},
{
- { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" },
- MBEDTLS_X509_EXT_KEY_USAGE,
+ { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" },
+ MBEDTLS_OID_X509_EXT_KEY_USAGE,
},
{
- { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" },
- MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE,
+ { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" },
+ MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE,
},
{
- { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" },
- MBEDTLS_X509_EXT_SUBJECT_ALT_NAME,
+ { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" },
+ MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME,
},
{
- { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" },
- MBEDTLS_X509_EXT_NS_CERT_TYPE,
+ { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" },
+ MBEDTLS_OID_X509_EXT_NS_CERT_TYPE,
+ },
+ {
+ { ADD_LEN( MBEDTLS_OID_CERTIFICATE_POLICIES ), "id-ce-certificatePolicies", "Certificate Policies" },
+ MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES,
},
{
{ NULL, 0, NULL, NULL },
@@ -292,18 +292,27 @@
static const mbedtls_oid_descriptor_t oid_ext_key_usage[] =
{
- { ADD_LEN( MBEDTLS_OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" },
- { ADD_LEN( MBEDTLS_OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" },
- { ADD_LEN( MBEDTLS_OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" },
- { ADD_LEN( MBEDTLS_OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" },
- { ADD_LEN( MBEDTLS_OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" },
- { ADD_LEN( MBEDTLS_OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" },
+ { ADD_LEN( MBEDTLS_OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" },
+ { ADD_LEN( MBEDTLS_OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" },
+ { ADD_LEN( MBEDTLS_OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" },
+ { ADD_LEN( MBEDTLS_OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" },
+ { ADD_LEN( MBEDTLS_OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" },
+ { ADD_LEN( MBEDTLS_OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" },
+ { ADD_LEN( MBEDTLS_OID_WISUN_FAN ), "id-kp-wisun-fan-device", "Wi-SUN Alliance Field Area Network (FAN)" },
{ NULL, 0, NULL, NULL },
};
FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage)
FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description)
-#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */
+
+static const mbedtls_oid_descriptor_t oid_certificate_policies[] =
+{
+ { ADD_LEN( MBEDTLS_OID_ANY_POLICY ), "anyPolicy", "Any Policy" },
+ { NULL, 0, NULL, NULL },
+};
+
+FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, certificate_policies, oid_certificate_policies)
+FN_OID_GET_ATTR1(mbedtls_oid_get_certificate_policies, mbedtls_oid_descriptor_t, certificate_policies, const char *, description)
#if defined(MBEDTLS_MD_C)
/*
@@ -619,6 +628,12 @@
MBEDTLS_MD_SHA512,
},
#endif /* MBEDTLS_SHA512_C */
+#if defined(MBEDTLS_RIPEMD160_C)
+ {
+ { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_RIPEMD160 ), "id-ripemd160", "RIPEMD-160" },
+ MBEDTLS_MD_RIPEMD160,
+ },
+#endif /* MBEDTLS_RIPEMD160_C */
{
{ NULL, 0, NULL, NULL },
MBEDTLS_MD_NONE,
@@ -718,7 +733,7 @@
int mbedtls_oid_get_numeric_string( char *buf, size_t size,
const mbedtls_asn1_buf *oid )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, n;
unsigned int value;
char *p;
diff --git a/lib/libmbedtls/mbedtls/library/pem.c b/lib/libmbedtls/mbedtls/library/pem.c
index 4a9041f..06cf8f0 100644
--- a/lib/libmbedtls/mbedtls/library/pem.c
+++ b/lib/libmbedtls/mbedtls/library/pem.c
@@ -34,6 +34,7 @@
#include "mbedtls/md5.h"
#include "mbedtls/cipher.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -85,7 +86,7 @@
mbedtls_md5_context md5_ctx;
unsigned char md5sum[16];
size_t use_len;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md5_init( &md5_ctx );
@@ -146,7 +147,7 @@
{
mbedtls_des_context des_ctx;
unsigned char des_key[8];
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_des_init( &des_ctx );
@@ -174,7 +175,7 @@
{
mbedtls_des3_context des3_ctx;
unsigned char des3_key[24];
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_des3_init( &des3_ctx );
@@ -204,7 +205,7 @@
{
mbedtls_aes_context aes_ctx;
unsigned char aes_key[32];
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_aes_init( &aes_ctx );
@@ -439,7 +440,7 @@
const unsigned char *der_data, size_t der_len,
unsigned char *buf, size_t buf_len, size_t *olen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *encode_buf = NULL, *c, *p = buf;
size_t len = 0, use_len, add_len = 0;
diff --git a/lib/libmbedtls/mbedtls/library/pk.c b/lib/libmbedtls/mbedtls/library/pk.c
index ed59017..98ad7b8 100644
--- a/lib/libmbedtls/mbedtls/library/pk.c
+++ b/lib/libmbedtls/mbedtls/library/pk.c
@@ -30,6 +30,7 @@
#include "mbedtls/pk_internal.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h"
@@ -41,6 +42,10 @@
#include "mbedtls/ecdsa.h"
#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "mbedtls/psa_util.h"
+#endif
+
#include <limits.h>
#include <stdint.h>
@@ -147,6 +152,41 @@
return( 0 );
}
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/*
+ * Initialise a PSA-wrapping context
+ */
+int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx, const psa_key_handle_t key )
+{
+ const mbedtls_pk_info_t * const info = &mbedtls_pk_opaque_info;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ psa_key_handle_t *pk_ctx;
+ psa_key_type_t type;
+
+ if( ctx == NULL || ctx->pk_info != NULL )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+ if( PSA_SUCCESS != psa_get_key_attributes( key, &attributes ) )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+ type = psa_get_key_type( &attributes );
+ psa_reset_key_attributes( &attributes );
+
+ /* Current implementation of can_do() relies on this. */
+ if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( type ) )
+ return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ;
+
+ if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
+ return( MBEDTLS_ERR_PK_ALLOC_FAILED );
+
+ ctx->pk_info = info;
+
+ pk_ctx = (psa_key_handle_t *) ctx->pk_ctx;
+ *pk_ctx = key;
+
+ return( 0 );
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
/*
* Initialize an RSA-alt context
@@ -258,7 +298,7 @@
mbedtls_ecp_restart_is_enabled() &&
ctx->pk_info->verify_rs_func != NULL )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
return( ret );
@@ -315,7 +355,7 @@
if( type == MBEDTLS_PK_RSASSA_PSS )
{
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_pk_rsassa_pss_options *pss_opts;
#if SIZE_MAX > UINT_MAX
@@ -381,7 +421,7 @@
mbedtls_ecp_restart_is_enabled() &&
ctx->pk_info->sign_rs_func != NULL )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
return( ret );
@@ -472,12 +512,14 @@
PK_VALIDATE_RET( prv != NULL );
if( pub->pk_info == NULL ||
- prv->pk_info == NULL ||
- prv->pk_info->check_pair_func == NULL )
+ prv->pk_info == NULL )
{
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
}
+ if( prv->pk_info->check_pair_func == NULL )
+ return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
+
if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT )
{
if( pub->pk_info->type != MBEDTLS_PK_RSA )
@@ -543,4 +585,57 @@
return( ctx->pk_info->type );
}
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/*
+ * Load the key to a PSA key slot,
+ * then turn the PK context into a wrapper for that key slot.
+ *
+ * Currently only works for EC private keys.
+ */
+int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk,
+ psa_key_handle_t *handle,
+ psa_algorithm_t hash_alg )
+{
+#if !defined(MBEDTLS_ECP_C)
+ return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
+#else
+ const mbedtls_ecp_keypair *ec;
+ unsigned char d[MBEDTLS_ECP_MAX_BYTES];
+ size_t d_len;
+ 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 */
+ if( mbedtls_pk_get_type( pk ) != MBEDTLS_PK_ECKEY )
+ return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
+
+ ec = mbedtls_pk_ec( *pk );
+ d_len = ( ec->grp.nbits + 7 ) / 8;
+ if( ( ret = mbedtls_mpi_write_binary( &ec->d, d, d_len ) ) != 0 )
+ return( ret );
+
+ curve_id = mbedtls_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) );
+
+ /* import private key into PSA */
+ if( PSA_SUCCESS != psa_import_key( &attributes, d, d_len, handle ) )
+ return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
+
+ /* make PK context wrap the key slot */
+ mbedtls_pk_free( pk );
+ mbedtls_pk_init( pk );
+
+ return( mbedtls_pk_setup_opaque( pk, *handle ) );
+#endif /* MBEDTLS_ECP_C */
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_PK_C */
diff --git a/lib/libmbedtls/mbedtls/library/pk_wrap.c b/lib/libmbedtls/mbedtls/library/pk_wrap.c
index 093bc66..919a7ba 100644
--- a/lib/libmbedtls/mbedtls/library/pk_wrap.c
+++ b/lib/libmbedtls/mbedtls/library/pk_wrap.c
@@ -27,6 +27,7 @@
#if defined(MBEDTLS_PK_C)
#include "mbedtls/pk_internal.h"
+#include "mbedtls/error.h"
/* Even if RSA not activated, for the sake of RSA-alt */
#include "mbedtls/rsa.h"
@@ -41,10 +42,20 @@
#include "mbedtls/ecdsa.h"
#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "mbedtls/asn1write.h"
+#endif
+
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
#include "mbedtls/platform_util.h"
#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
+#include "mbedtls/asn1.h"
+#endif
+
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
@@ -73,7 +84,7 @@
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
size_t rsa_len = mbedtls_rsa_get_len( rsa );
@@ -238,7 +249,7 @@
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecdsa_context ecdsa;
mbedtls_ecdsa_init( &ecdsa );
@@ -256,7 +267,7 @@
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecdsa_context ecdsa;
mbedtls_ecdsa_init( &ecdsa );
@@ -330,7 +341,7 @@
const unsigned char *sig, size_t sig_len,
void *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
eckey_restart_ctx *rs = rs_ctx;
/* Should never happen */
@@ -355,7 +366,7 @@
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
void *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
eckey_restart_ctx *rs = rs_ctx;
/* Should never happen */
@@ -472,11 +483,157 @@
return( type == MBEDTLS_PK_ECDSA );
}
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/*
+ * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of
+ * those integers and convert it to the fixed-length encoding expected by PSA.
+ */
+static int extract_ecdsa_sig_int( unsigned char **from, const unsigned char *end,
+ unsigned char *to, size_t to_len )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t unpadded_len, padding_len;
+
+ if( ( ret = mbedtls_asn1_get_tag( from, end, &unpadded_len,
+ MBEDTLS_ASN1_INTEGER ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ while( unpadded_len > 0 && **from == 0x00 )
+ {
+ ( *from )++;
+ unpadded_len--;
+ }
+
+ if( unpadded_len > to_len || unpadded_len == 0 )
+ return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+ padding_len = to_len - unpadded_len;
+ memset( to, 0x00, padding_len );
+ memcpy( to + padding_len, *from, unpadded_len );
+ ( *from ) += unpadded_len;
+
+ return( 0 );
+}
+
+/*
+ * Convert a signature from an ASN.1 sequence of two integers
+ * to a raw {r,s} buffer. Note: the provided sig buffer must be at least
+ * twice as big as int_size.
+ */
+static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end,
+ unsigned char *sig, size_t int_size )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t tmp_size;
+
+ if( ( ret = mbedtls_asn1_get_tag( p, end, &tmp_size,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+ return( ret );
+
+ /* Extract r */
+ if( ( ret = extract_ecdsa_sig_int( p, end, sig, int_size ) ) != 0 )
+ return( ret );
+ /* Extract s */
+ if( ( ret = extract_ecdsa_sig_int( p, end, sig + int_size, int_size ) ) != 0 )
+ return( ret );
+
+ return( 0 );
+}
+
+static int ecdsa_verify_wrap( void *ctx_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;
+ psa_status_t status;
+ mbedtls_pk_context key;
+ int key_len;
+ /* see ECP_PUB_DER_MAX_BYTES in pkwrite.c */
+ unsigned char buf[30 + 2 * MBEDTLS_ECP_MAX_BYTES];
+ unsigned char *p;
+ mbedtls_pk_info_t pk_info = mbedtls_eckey_info;
+ psa_algorithm_t psa_sig_md, psa_md;
+ 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 );
+
+ /* mbedtls_pk_write_pubkey() expects a full PK context;
+ * re-construct one to make it happy */
+ key.pk_info = &pk_info;
+ key.pk_ctx = ctx;
+ p = buf + sizeof( buf );
+ key_len = mbedtls_pk_write_pubkey( &p, buf, &key );
+ if( key_len <= 0 )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+ psa_md = mbedtls_psa_translate_md( md_alg );
+ if( psa_md == 0 )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+ psa_sig_md = PSA_ALG_ECDSA( psa_md );
+
+ psa_set_key_type( &attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY( curve ) );
+ psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH );
+ psa_set_key_algorithm( &attributes, psa_sig_md );
+
+ status = psa_import_key( &attributes,
+ buf + sizeof( buf ) - key_len, key_len,
+ &key_handle );
+ if( status != PSA_SUCCESS )
+ {
+ ret = mbedtls_psa_err_translate_pk( status );
+ goto cleanup;
+ }
+
+ /* We don't need the exported key anymore and can
+ * reuse its buffer for signature extraction. */
+ if( 2 * signature_part_size > sizeof( buf ) )
+ {
+ ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+ goto cleanup;
+ }
+
+ p = (unsigned char*) sig;
+ if( ( ret = extract_ecdsa_sig( &p, sig + sig_len, buf,
+ signature_part_size ) ) != 0 )
+ {
+ goto cleanup;
+ }
+
+ if( psa_verify_hash( key_handle, psa_sig_md,
+ hash, hash_len,
+ buf, 2 * signature_part_size )
+ != PSA_SUCCESS )
+ {
+ ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
+ goto cleanup;
+ }
+
+ if( p != sig + sig_len )
+ {
+ ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
+ goto cleanup;
+ }
+ ret = 0;
+
+cleanup:
+ psa_destroy_key( key_handle );
+ return( ret );
+}
+#else /* MBEDTLS_USE_PSA_CRYPTO */
static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
((void) md_alg);
ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx,
@@ -487,6 +644,7 @@
return( ret );
}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
@@ -503,7 +661,7 @@
const unsigned char *sig, size_t sig_len,
void *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
((void) md_alg);
ret = mbedtls_ecdsa_read_signature_restartable(
@@ -619,6 +777,8 @@
#endif /* SIZE_MAX > UINT_MAX */
*sig_len = rsa_alt->key_len_func( rsa_alt->key );
+ if( *sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE,
md_alg, (unsigned int) hash_len, hash, sig ) );
@@ -647,7 +807,7 @@
unsigned char sig[MBEDTLS_MPI_MAX_SIZE];
unsigned char hash[32];
size_t sig_len = 0;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) )
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
@@ -716,4 +876,188 @@
#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+
+static void *pk_opaque_alloc_wrap( void )
+{
+ void *ctx = mbedtls_calloc( 1, sizeof( psa_key_handle_t ) );
+
+ /* no _init() function to call, an calloc() already zeroized */
+
+ return( ctx );
+}
+
+static void pk_opaque_free_wrap( void *ctx )
+{
+ mbedtls_platform_zeroize( ctx, sizeof( psa_key_handle_t ) );
+ mbedtls_free( ctx );
+}
+
+static size_t pk_opaque_get_bitlen( const void *ctx )
+{
+ const psa_key_handle_t *key = (const psa_key_handle_t *) ctx;
+ size_t bits;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+ if( PSA_SUCCESS != psa_get_key_attributes( *key, &attributes ) )
+ return( 0 );
+
+ bits = psa_get_key_bits( &attributes );
+ psa_reset_key_attributes( &attributes );
+ return( bits );
+}
+
+static int pk_opaque_can_do( mbedtls_pk_type_t type )
+{
+ /* For now opaque PSA keys can only wrap ECC keypairs,
+ * as checked by setup_psa().
+ * Also, ECKEY_DH does not really make sense with the current API. */
+ return( type == MBEDTLS_PK_ECKEY ||
+ type == MBEDTLS_PK_ECDSA );
+}
+
+/*
+ * Simultaneously convert and move raw MPI from the beginning of a buffer
+ * to an ASN.1 MPI at the end of the buffer.
+ * See also mbedtls_asn1_write_mpi().
+ *
+ * p: pointer to the end of the output buffer
+ * start: start of the output buffer, and also of the mpi to write at the end
+ * n_len: length of the mpi to read from start
+ */
+static int asn1_write_mpibuf( unsigned char **p, unsigned char *start,
+ size_t n_len )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t len = 0;
+
+ if( (size_t)( *p - start ) < n_len )
+ return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
+ len = n_len;
+ *p -= len;
+ memmove( *p, start, len );
+
+ /* ASN.1 DER encoding requires minimal length, so skip leading 0s.
+ * Neither r nor s should be 0, but as a failsafe measure, still detect
+ * that rather than overflowing the buffer in case of a PSA error. */
+ while( len > 0 && **p == 0x00 )
+ {
+ ++(*p);
+ --len;
+ }
+
+ /* this is only reached if the signature was invalid */
+ if( len == 0 )
+ return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
+
+ /* if the msb is 1, ASN.1 requires that we prepend a 0.
+ * Neither r nor s can be 0, so we can assume len > 0 at all times. */
+ if( **p & 0x80 )
+ {
+ if( *p - start < 1 )
+ return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
+ *--(*p) = 0x00;
+ len += 1;
+ }
+
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
+ MBEDTLS_ASN1_INTEGER ) );
+
+ return( (int) len );
+}
+
+/* Transcode signature from PSA format to ASN.1 sequence.
+ * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of
+ * MPIs, and in-place.
+ *
+ * [in/out] sig: the signature pre- and post-transcoding
+ * [in/out] sig_len: signature length pre- and post-transcoding
+ * [int] buf_len: the available size the in/out buffer
+ */
+static int pk_ecdsa_sig_asn1_from_psa( unsigned char *sig, size_t *sig_len,
+ size_t buf_len )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t len = 0;
+ const size_t rs_len = *sig_len / 2;
+ unsigned char *p = sig + buf_len;
+
+ MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig + rs_len, rs_len ) );
+ MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig, rs_len ) );
+
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, sig, len ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, sig,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
+
+ memmove( sig, p, len );
+ *sig_len = len;
+
+ return( 0 );
+}
+
+static int pk_opaque_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
+ const unsigned char *hash, size_t hash_len,
+ unsigned char *sig, size_t *sig_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ const psa_key_handle_t *key = (const psa_key_handle_t *) ctx;
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ psa_algorithm_t alg = PSA_ALG_ECDSA( mbedtls_psa_translate_md( md_alg ) );
+ size_t buf_len;
+ psa_status_t status;
+
+ /* PSA has its own RNG */
+ (void) f_rng;
+ (void) p_rng;
+
+ /* PSA needs an output buffer of known size, but our API doesn't provide
+ * that information. Assume that the buffer is large enough for a
+ * maximal-length signature with that key (otherwise the application is
+ * buggy anyway). */
+ status = psa_get_key_attributes( *key, &attributes );
+ if( status != PSA_SUCCESS )
+ return( mbedtls_psa_err_translate_pk( status ) );
+ buf_len = MBEDTLS_ECDSA_MAX_SIG_LEN( psa_get_key_bits( &attributes ) );
+ psa_reset_key_attributes( &attributes );
+ if( buf_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+ /* make the signature */
+ status = psa_sign_hash( *key, alg, hash, hash_len,
+ sig, buf_len, sig_len );
+ if( status != PSA_SUCCESS )
+ return( mbedtls_psa_err_translate_pk( status ) );
+
+ /* transcode it to ASN.1 sequence */
+ return( pk_ecdsa_sig_asn1_from_psa( sig, sig_len, buf_len ) );
+}
+
+const mbedtls_pk_info_t mbedtls_pk_opaque_info = {
+ MBEDTLS_PK_OPAQUE,
+ "Opaque",
+ pk_opaque_get_bitlen,
+ pk_opaque_can_do,
+ NULL, /* verify - will be done later */
+ pk_opaque_sign_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ NULL, /* restartable verify - not relevant */
+ NULL, /* restartable sign - not relevant */
+#endif
+ NULL, /* decrypt - will be done later */
+ NULL, /* encrypt - will be done later */
+ NULL, /* check_pair - could be done later or left NULL */
+ pk_opaque_alloc_wrap,
+ pk_opaque_free_wrap,
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+ NULL, /* restart alloc - not relevant */
+ NULL, /* restart free - not relevant */
+#endif
+ NULL, /* debug - could be done later, or even left NULL */
+};
+
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
#endif /* MBEDTLS_PK_C */
diff --git a/lib/libmbedtls/mbedtls/library/pkcs12.c b/lib/libmbedtls/mbedtls/library/pkcs12.c
index a637770..9305457 100644
--- a/lib/libmbedtls/mbedtls/library/pkcs12.c
+++ b/lib/libmbedtls/mbedtls/library/pkcs12.c
@@ -37,6 +37,7 @@
#include "mbedtls/asn1.h"
#include "mbedtls/cipher.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -53,7 +54,7 @@
static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params,
mbedtls_asn1_buf *salt, int *iterations )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char **p = ¶ms->p;
const unsigned char *end = params->p + params->len;
@@ -145,7 +146,7 @@
((void) output);
return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
#else
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char key[16];
mbedtls_arc4_context ctx;
((void) mode);
@@ -250,7 +251,7 @@
const unsigned char *salt, size_t saltlen,
mbedtls_md_type_t md_type, int id, int iterations )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned int j;
unsigned char diversifier[128];
diff --git a/lib/libmbedtls/mbedtls/library/pkcs5.c b/lib/libmbedtls/mbedtls/library/pkcs5.c
index d673bbb..24b8778 100644
--- a/lib/libmbedtls/mbedtls/library/pkcs5.c
+++ b/lib/libmbedtls/mbedtls/library/pkcs5.c
@@ -38,6 +38,7 @@
#if defined(MBEDTLS_PKCS5_C)
#include "mbedtls/pkcs5.h"
+#include "mbedtls/error.h"
#if defined(MBEDTLS_ASN1_PARSE_C)
#include "mbedtls/asn1.h"
@@ -59,7 +60,7 @@
mbedtls_asn1_buf *salt, int *iterations,
int *keylen, mbedtls_md_type_t *md_type )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_asn1_buf prf_alg_oid;
unsigned char *p = params->p;
const unsigned char *end = params->p + params->len;
@@ -76,7 +77,8 @@
* }
*
*/
- if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
+ if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len,
+ MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
salt->p = p;
@@ -141,7 +143,8 @@
return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT +
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
- if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 )
+ if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid,
+ &kdf_alg_params ) ) != 0 )
return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
// Only PBKDF2 supported at the moment
@@ -202,7 +205,8 @@
if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 )
goto exit;
- if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 )
+ if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen,
+ (mbedtls_operation_t) mode ) ) != 0 )
goto exit;
if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len,
@@ -217,7 +221,8 @@
}
#endif /* MBEDTLS_ASN1_PARSE_C */
-int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password,
+int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx,
+ const unsigned char *password,
size_t plen, const unsigned char *salt, size_t slen,
unsigned int iteration_count,
uint32_t key_length, unsigned char *output )
@@ -239,13 +244,12 @@
return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA );
#endif
+ if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 )
+ return( ret );
while( key_length )
{
// U1 ends up in work
//
- if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 )
- return( ret );
-
if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 )
return( ret );
@@ -255,21 +259,24 @@
if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 )
return( ret );
+ if( ( ret = mbedtls_md_hmac_reset( ctx ) ) != 0 )
+ return( ret );
+
memcpy( md1, work, md_size );
for( i = 1; i < iteration_count; i++ )
{
// U2 ends up in md1
//
- if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 )
- return( ret );
-
if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 )
return( ret );
if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 )
return( ret );
+ if( ( ret = mbedtls_md_hmac_reset( ctx ) ) != 0 )
+ return( ret );
+
// U1 xor U2
//
for( j = 0; j < md_size; j++ )
@@ -304,10 +311,10 @@
#define MAX_TESTS 6
-static const size_t plen[MAX_TESTS] =
+static const size_t plen_test_data[MAX_TESTS] =
{ 8, 8, 8, 24, 9 };
-static const unsigned char password[MAX_TESTS][32] =
+static const unsigned char password_test_data[MAX_TESTS][32] =
{
"password",
"password",
@@ -316,10 +323,10 @@
"pass\0word",
};
-static const size_t slen[MAX_TESTS] =
+static const size_t slen_test_data[MAX_TESTS] =
{ 4, 4, 4, 36, 5 };
-static const unsigned char salt[MAX_TESTS][40] =
+static const unsigned char salt_test_data[MAX_TESTS][40] =
{
"salt",
"salt",
@@ -328,13 +335,13 @@
"sa\0lt",
};
-static const uint32_t it_cnt[MAX_TESTS] =
+static const uint32_t it_cnt_test_data[MAX_TESTS] =
{ 1, 2, 4096, 4096, 4096 };
-static const uint32_t key_len[MAX_TESTS] =
+static const uint32_t key_len_test_data[MAX_TESTS] =
{ 20, 20, 20, 25, 16 };
-static const unsigned char result_key[MAX_TESTS][32] =
+static const unsigned char result_key_test_data[MAX_TESTS][32] =
{
{ 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
@@ -380,10 +387,12 @@
if( verbose != 0 )
mbedtls_printf( " PBKDF2 (SHA1) #%d: ", i );
- ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i],
- slen[i], it_cnt[i], key_len[i], key );
+ ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password_test_data[i],
+ plen_test_data[i], salt_test_data[i],
+ slen_test_data[i], it_cnt_test_data[i],
+ key_len_test_data[i], key );
if( ret != 0 ||
- memcmp( result_key[i], key, key_len[i] ) != 0 )
+ memcmp( result_key_test_data[i], key, key_len_test_data[i] ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
diff --git a/lib/libmbedtls/mbedtls/library/pkparse.c b/lib/libmbedtls/mbedtls/library/pkparse.c
index 9318462..09219bc 100644
--- a/lib/libmbedtls/mbedtls/library/pkparse.c
+++ b/lib/libmbedtls/mbedtls/library/pkparse.c
@@ -31,6 +31,7 @@
#include "mbedtls/asn1.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -130,7 +131,7 @@
int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx,
const char *path, const char *pwd )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
unsigned char *buf;
@@ -157,7 +158,7 @@
*/
int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
unsigned char *buf;
@@ -188,7 +189,7 @@
static int pk_get_ecparams( unsigned char **p, const unsigned char *end,
mbedtls_asn1_buf *params )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if ( end - *p < 1 )
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
@@ -243,7 +244,7 @@
*/
static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = params->p;
const unsigned char * const end = params->p + params->len;
const unsigned char *end_field, *end_curve;
@@ -433,7 +434,7 @@
static int pk_group_id_from_specified( const mbedtls_asn1_buf *params,
mbedtls_ecp_group_id *grp_id )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_group grp;
mbedtls_ecp_group_init( &grp );
@@ -460,7 +461,7 @@
*/
static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_group_id grp_id;
if( params->tag == MBEDTLS_ASN1_OID )
@@ -500,7 +501,7 @@
static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end,
mbedtls_ecp_keypair *key )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q,
(const unsigned char *) *p, end - *p ) ) == 0 )
@@ -528,7 +529,7 @@
const unsigned char *end,
mbedtls_rsa_context *rsa )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
@@ -583,7 +584,7 @@
const unsigned char *end,
mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_asn1_buf alg_oid;
memset( params, 0, sizeof(mbedtls_asn1_buf) );
@@ -615,7 +616,7 @@
int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
mbedtls_pk_context *pk )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
mbedtls_asn1_buf alg_params;
mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
@@ -867,7 +868,7 @@
const unsigned char *key,
size_t keylen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int version, pubkey_done;
size_t len;
mbedtls_asn1_buf params;
@@ -1220,7 +1221,7 @@
const unsigned char *key, size_t keylen,
const unsigned char *pwd, size_t pwdlen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_pk_info_t *pk_info;
#if defined(MBEDTLS_PEM_PARSE_C)
size_t len;
@@ -1432,7 +1433,7 @@
int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx,
const unsigned char *key, size_t keylen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p;
#if defined(MBEDTLS_RSA_C)
const mbedtls_pk_info_t *pk_info;
diff --git a/lib/libmbedtls/mbedtls/library/pkwrite.c b/lib/libmbedtls/mbedtls/library/pkwrite.c
index eff9e67..854d22e 100644
--- a/lib/libmbedtls/mbedtls/library/pkwrite.c
+++ b/lib/libmbedtls/mbedtls/library/pkwrite.c
@@ -31,6 +31,7 @@
#include "mbedtls/asn1write.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -49,6 +50,10 @@
#include "mbedtls/pem.h"
#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
+#endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
@@ -73,7 +78,7 @@
static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
mbedtls_rsa_context *rsa )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
mbedtls_mpi T;
@@ -112,7 +117,7 @@
static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
mbedtls_ecp_keypair *ec )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];
@@ -140,7 +145,7 @@
static int pk_write_ec_param( unsigned char **p, unsigned char *start,
mbedtls_ecp_keypair *ec )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
const char *oid;
size_t oid_len;
@@ -159,7 +164,7 @@
static int pk_write_ec_private( unsigned char **p, unsigned char *start,
mbedtls_ecp_keypair *ec )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t byte_length = ( ec->grp.pbits + 7 ) / 8;
unsigned char tmp[MBEDTLS_ECP_MAX_BYTES];
@@ -177,7 +182,7 @@
int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
const mbedtls_pk_context *key )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
PK_VALIDATE_RET( p != NULL );
@@ -195,6 +200,29 @@
MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) );
else
#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_OPAQUE )
+ {
+ size_t buffer_size;
+ psa_key_handle_t* key_slot = (psa_key_handle_t*) key->pk_ctx;
+
+ if ( *p < start )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+
+ buffer_size = (size_t)( *p - start );
+ if ( psa_export_public_key( *key_slot, start, buffer_size, &len )
+ != PSA_SUCCESS )
+ {
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
+ }
+ else
+ {
+ *p -= len;
+ memmove( *p, start, len );
+ }
+ }
+ else
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
return( (int) len );
@@ -202,9 +230,10 @@
int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *c;
size_t len = 0, par_len = 0, oid_len;
+ mbedtls_pk_type_t pk_type;
const char *oid;
PK_VALIDATE_RET( key != NULL );
@@ -230,18 +259,52 @@
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) );
- if( ( ret = mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_get_type( key ),
- &oid, &oid_len ) ) != 0 )
- {
- return( ret );
- }
-
+ pk_type = mbedtls_pk_get_type( key );
#if defined(MBEDTLS_ECP_C)
- if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
+ if( pk_type == MBEDTLS_PK_ECKEY )
{
MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) );
}
#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( pk_type == MBEDTLS_PK_OPAQUE )
+ {
+ psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ 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, bits, &oid, &oid_len );
+ if( ret != 0 )
+ return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
+
+ /* Write EC algorithm parameters; that's akin
+ * to pk_write_ec_param() above. */
+ MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_oid( &c, buf,
+ oid, oid_len ) );
+
+ /* The rest of the function works as for legacy EC contexts. */
+ pk_type = MBEDTLS_PK_ECKEY;
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+ if( ( ret = mbedtls_oid_get_oid_by_pk_alg( pk_type, &oid,
+ &oid_len ) ) != 0 )
+ {
+ return( ret );
+ }
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len,
par_len ) );
@@ -255,7 +318,7 @@
int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *c;
size_t len = 0;
@@ -498,7 +561,7 @@
int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char output_buf[PUB_DER_MAX_BYTES];
size_t olen = 0;
@@ -523,7 +586,7 @@
int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char output_buf[PRV_DER_MAX_BYTES];
const char *begin, *end;
size_t olen = 0;
diff --git a/lib/libmbedtls/mbedtls/library/platform.c b/lib/libmbedtls/mbedtls/library/platform.c
index 14415a7..ffd9890 100644
--- a/lib/libmbedtls/mbedtls/library/platform.c
+++ b/lib/libmbedtls/mbedtls/library/platform.c
@@ -29,6 +29,7 @@
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
/* The compile time configuration of memory allocation via the macros
* MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime
@@ -82,28 +83,15 @@
!( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&
defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */
-#if defined(_WIN32)
+#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF)
#include <stdarg.h>
int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
va_list argp;
- /* Avoid calling the invalid parameter handler by checking ourselves */
- if( s == NULL || n == 0 || fmt == NULL )
- return( -1 );
-
va_start( argp, fmt );
-#if defined(_TRUNCATE) && !defined(__MINGW32__)
- ret = _vsnprintf_s( s, n, _TRUNCATE, fmt, argp );
-#else
- ret = _vsnprintf( s, n, fmt, argp );
- if( ret < 0 || (size_t) ret == n )
- {
- s[n-1] = '\0';
- ret = -1;
- }
-#endif
+ ret = mbedtls_vsnprintf( s, n, fmt, argp );
va_end( argp );
return( ret );
@@ -140,6 +128,62 @@
}
#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
+#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF)
+#include <stdarg.h>
+int mbedtls_platform_win32_vsnprintf( char *s, size_t n, const char *fmt, va_list arg )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ /* Avoid calling the invalid parameter handler by checking ourselves */
+ if( s == NULL || n == 0 || fmt == NULL )
+ return( -1 );
+
+#if defined(_TRUNCATE)
+ ret = vsnprintf_s( s, n, _TRUNCATE, fmt, arg );
+#else
+ ret = vsnprintf( s, n, fmt, arg );
+ if( ret < 0 || (size_t) ret == n )
+ {
+ s[n-1] = '\0';
+ ret = -1;
+ }
+#endif
+
+ return( ret );
+}
+#endif
+
+#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT)
+#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static int platform_vsnprintf_uninit( char * s, size_t n,
+ const char * format, va_list arg )
+{
+ ((void) s);
+ ((void) n);
+ ((void) format);
+ ((void) arg);
+ return( -1 );
+}
+
+#define MBEDTLS_PLATFORM_STD_VSNPRINTF platform_vsnprintf_uninit
+#endif /* !MBEDTLS_PLATFORM_STD_VSNPRINTF */
+
+int (*mbedtls_vsnprintf)( char * s, size_t n,
+ const char * format,
+ va_list arg ) = MBEDTLS_PLATFORM_STD_VSNPRINTF;
+
+int mbedtls_platform_set_vsnprintf( int (*vsnprintf_func)( char * s, size_t n,
+ const char * format,
+ va_list arg ) )
+{
+ mbedtls_vsnprintf = vsnprintf_func;
+ return( 0 );
+}
+#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */
+
#if defined(MBEDTLS_PLATFORM_PRINTF_ALT)
#if !defined(MBEDTLS_PLATFORM_STD_PRINTF)
/*
diff --git a/lib/libmbedtls/mbedtls/library/poly1305.c b/lib/libmbedtls/mbedtls/library/poly1305.c
index 24f1511..5ac21cc 100644
--- a/lib/libmbedtls/mbedtls/library/poly1305.c
+++ b/lib/libmbedtls/mbedtls/library/poly1305.c
@@ -30,6 +30,7 @@
#include "mbedtls/poly1305.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -423,7 +424,7 @@
unsigned char mac[16] )
{
mbedtls_poly1305_context ctx;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
POLY1305_VALIDATE_RET( key != NULL );
POLY1305_VALIDATE_RET( mac != NULL );
POLY1305_VALIDATE_RET( ilen == 0 || input != NULL );
@@ -529,7 +530,7 @@
{
unsigned char mac[16];
unsigned i;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
for( i = 0U; i < 2U; i++ )
{
diff --git a/lib/libmbedtls/mbedtls/library/ripemd160.c b/lib/libmbedtls/mbedtls/library/ripemd160.c
index 887ef9f..edd9f45 100644
--- a/lib/libmbedtls/mbedtls/library/ripemd160.c
+++ b/lib/libmbedtls/mbedtls/library/ripemd160.c
@@ -35,6 +35,7 @@
#include "mbedtls/ripemd160.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -322,7 +323,7 @@
const unsigned char *input,
size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill;
uint32_t left;
@@ -390,7 +391,7 @@
int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx,
unsigned char output[20] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
@@ -439,7 +440,7 @@
size_t ilen,
unsigned char output[20] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ripemd160_context ctx;
mbedtls_ripemd160_init( &ctx );
diff --git a/lib/libmbedtls/mbedtls/library/rsa.c b/lib/libmbedtls/mbedtls/library/rsa.c
index 9e8432d..b6bc225 100644
--- a/lib/libmbedtls/mbedtls/library/rsa.c
+++ b/lib/libmbedtls/mbedtls/library/rsa.c
@@ -49,6 +49,7 @@
#include "mbedtls/rsa_internal.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -98,7 +99,7 @@
const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, const mbedtls_mpi *E )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
RSA_VALIDATE_RET( ctx != NULL );
if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) ||
@@ -401,7 +402,7 @@
mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q,
mbedtls_mpi *D, mbedtls_mpi *E )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int is_priv;
RSA_VALIDATE_RET( ctx != NULL );
@@ -445,7 +446,7 @@
int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx,
mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int is_priv;
RSA_VALIDATE_RET( ctx != NULL );
@@ -536,7 +537,7 @@
void *p_rng,
unsigned int nbits, int exponent )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi H, G, L;
int prime_quality = 0;
RSA_VALIDATE_RET( ctx != NULL );
@@ -728,7 +729,7 @@
const unsigned char *input,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t olen;
mbedtls_mpi T;
RSA_VALIDATE_RET( ctx != NULL );
@@ -841,7 +842,7 @@
const unsigned char *input,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t olen;
/* Temporary holding the result */
@@ -1134,7 +1135,7 @@
unsigned char *output )
{
size_t olen;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = output;
unsigned int hlen;
const mbedtls_md_info_t *md_info;
@@ -1144,7 +1145,7 @@
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
mode == MBEDTLS_RSA_PUBLIC );
RSA_VALIDATE_RET( output != NULL );
- RSA_VALIDATE_RET( input != NULL );
+ RSA_VALIDATE_RET( ilen == 0 || input != NULL );
RSA_VALIDATE_RET( label_len == 0 || label != NULL );
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
@@ -1180,7 +1181,8 @@
p += hlen;
p += olen - 2 * hlen - 2 - ilen;
*p++ = 1;
- memcpy( p, input, ilen );
+ if( ilen != 0 )
+ memcpy( p, input, ilen );
mbedtls_md_init( &md_ctx );
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
@@ -1220,14 +1222,14 @@
unsigned char *output )
{
size_t nb_pad, olen;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = output;
RSA_VALIDATE_RET( ctx != NULL );
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
mode == MBEDTLS_RSA_PUBLIC );
RSA_VALIDATE_RET( output != NULL );
- RSA_VALIDATE_RET( input != NULL );
+ RSA_VALIDATE_RET( ilen == 0 || input != NULL );
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@@ -1272,7 +1274,8 @@
}
*p++ = 0;
- memcpy( p, input, ilen );
+ if( ilen != 0 )
+ memcpy( p, input, ilen );
return( ( mode == MBEDTLS_RSA_PUBLIC )
? mbedtls_rsa_public( ctx, output, output )
@@ -1294,7 +1297,7 @@
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
mode == MBEDTLS_RSA_PUBLIC );
RSA_VALIDATE_RET( output != NULL );
- RSA_VALIDATE_RET( input != NULL );
+ RSA_VALIDATE_RET( ilen == 0 || input != NULL );
switch( ctx->padding )
{
@@ -1329,7 +1332,7 @@
unsigned char *output,
size_t output_max_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t ilen, i, pad_len;
unsigned char *p, bad, pad_done;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
@@ -1455,7 +1458,8 @@
}
*olen = ilen - (p - buf);
- memcpy( output, p, *olen );
+ if( *olen != 0 )
+ memcpy( output, p, *olen );
ret = 0;
cleanup:
@@ -1569,7 +1573,7 @@
unsigned char *output,
size_t output_max_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t ilen, i, plaintext_max_size;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
/* The following variables take sensitive values: their value must
@@ -1707,9 +1711,15 @@
plaintext_max_size,
plaintext_max_size - plaintext_size );
- /* Finally copy the decrypted plaintext plus trailing zeros
- * into the output buffer. */
- memcpy( output, buf + ilen - plaintext_max_size, plaintext_max_size );
+ /* Finally copy the decrypted plaintext plus trailing zeros into the output
+ * buffer. If output_max_len is 0, then output may be an invalid pointer
+ * and the result of memcpy() would be undefined; prevent undefined
+ * behavior making sure to depend only on output_max_len (the size of the
+ * user-provided output buffer), which is independent from plaintext
+ * length, validity of padding, success of the decryption, and other
+ * secrets. */
+ if( output_max_len != 0 )
+ memcpy( output, buf + ilen - plaintext_max_size, plaintext_max_size );
/* Report the amount of data we copied to the output buffer. In case
* of errors (bad padding or output too large), the value of *olen
@@ -1779,7 +1789,7 @@
unsigned char *p = sig;
unsigned char salt[MBEDTLS_MD_MAX_SIZE];
size_t slen, min_slen, hlen, offset = 0;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t msb;
const mbedtls_md_info_t *md_info;
mbedtls_md_context_t md_ctx;
@@ -2039,7 +2049,7 @@
const unsigned char *hash,
unsigned char *sig )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *sig_try = NULL, *verif = NULL;
RSA_VALIDATE_RET( ctx != NULL );
@@ -2161,7 +2171,7 @@
int expected_salt_len,
const unsigned char *sig )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t siglen;
unsigned char *p;
unsigned char *hash_start;
@@ -2458,7 +2468,7 @@
*/
int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
RSA_VALIDATE_RET( dst != NULL );
RSA_VALIDATE_RET( src != NULL );
diff --git a/lib/libmbedtls/mbedtls/library/sha1.c b/lib/libmbedtls/mbedtls/library/sha1.c
index f80f617..4aeafaf 100644
--- a/lib/libmbedtls/mbedtls/library/sha1.c
+++ b/lib/libmbedtls/mbedtls/library/sha1.c
@@ -34,6 +34,7 @@
#include "mbedtls/sha1.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -307,7 +308,7 @@
const unsigned char *input,
size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill;
uint32_t left;
@@ -368,7 +369,7 @@
int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx,
unsigned char output[20] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t used;
uint32_t high, low;
@@ -440,7 +441,7 @@
size_t ilen,
unsigned char output[20] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_sha1_context ctx;
SHA1_VALIDATE_RET( ilen == 0 || input != NULL );
diff --git a/lib/libmbedtls/mbedtls/library/sha256.c b/lib/libmbedtls/mbedtls/library/sha256.c
index bcdcb07..d0142a9 100644
--- a/lib/libmbedtls/mbedtls/library/sha256.c
+++ b/lib/libmbedtls/mbedtls/library/sha256.c
@@ -34,6 +34,7 @@
#include "mbedtls/sha256.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include <string.h>
@@ -275,7 +276,7 @@
const unsigned char *input,
size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill;
uint32_t left;
@@ -336,7 +337,7 @@
int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx,
unsigned char output[32] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t used;
uint32_t high, low;
@@ -414,7 +415,7 @@
unsigned char output[32],
int is224 )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_sha256_context ctx;
SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 );
diff --git a/lib/libmbedtls/mbedtls/library/sha512.c b/lib/libmbedtls/mbedtls/library/sha512.c
index 51c9a23..c19a5df 100644
--- a/lib/libmbedtls/mbedtls/library/sha512.c
+++ b/lib/libmbedtls/mbedtls/library/sha512.c
@@ -34,6 +34,7 @@
#include "mbedtls/sha512.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#if defined(_MSC_VER) || defined(__WATCOMC__)
#define UL64(x) x##ui64
@@ -92,6 +93,15 @@
}
#endif /* PUT_UINT64_BE */
+#if defined(MBEDTLS_SHA512_SMALLER)
+static void sha512_put_uint64_be( uint64_t n, unsigned char *b, uint8_t i )
+{
+ PUT_UINT64_BE(n, b, i);
+}
+#else
+#define sha512_put_uint64_be PUT_UINT64_BE
+#endif /* MBEDTLS_SHA512_SMALLER */
+
void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
{
SHA512_VALIDATE( ctx != NULL );
@@ -122,7 +132,11 @@
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;
@@ -141,6 +155,9 @@
}
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);
@@ -150,9 +167,12 @@
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 );
}
@@ -219,7 +239,7 @@
{
int i;
uint64_t temp1, temp2, W[80];
- uint64_t A, B, C, D, E, F, G, H;
+ uint64_t A[8];
SHA512_VALIDATE_RET( ctx != NULL );
SHA512_VALIDATE_RET( (const unsigned char *)data != NULL );
@@ -244,6 +264,28 @@
(d) += temp1; (h) = temp1 + temp2; \
} while( 0 )
+ for( i = 0; i < 8; i++ )
+ A[i] = ctx->state[i];
+
+#if defined(MBEDTLS_SHA512_SMALLER)
+ for( i = 0; i < 80; i++ )
+ {
+ if( i < 16 )
+ {
+ GET_UINT64_BE( W[i], data, i << 3 );
+ }
+ else
+ {
+ W[i] = S1(W[i - 2]) + W[i - 7] +
+ S0(W[i - 15]) + W[i - 16];
+ }
+
+ P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] );
+
+ temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3];
+ A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1;
+ }
+#else /* MBEDTLS_SHA512_SMALLER */
for( i = 0; i < 16; i++ )
{
GET_UINT64_BE( W[i], data, i << 3 );
@@ -255,37 +297,23 @@
S0(W[i - 15]) + W[i - 16];
}
- A = ctx->state[0];
- B = ctx->state[1];
- C = ctx->state[2];
- D = ctx->state[3];
- E = ctx->state[4];
- F = ctx->state[5];
- G = ctx->state[6];
- H = ctx->state[7];
i = 0;
-
do
{
- P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
- P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
- P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
- P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
- P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
- P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
- P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
- P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
+ P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); i++;
+ P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i], K[i] ); i++;
+ P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i], K[i] ); i++;
+ P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i], K[i] ); i++;
+ P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i], K[i] ); i++;
+ P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i], K[i] ); i++;
+ P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i], K[i] ); i++;
+ P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i], K[i] ); i++;
}
while( i < 80 );
+#endif /* MBEDTLS_SHA512_SMALLER */
- ctx->state[0] += A;
- ctx->state[1] += B;
- ctx->state[2] += C;
- ctx->state[3] += D;
- ctx->state[4] += E;
- ctx->state[5] += F;
- ctx->state[6] += G;
- ctx->state[7] += H;
+ for( i = 0; i < 8; i++ )
+ ctx->state[i] += A[i];
return( 0 );
}
@@ -306,7 +334,7 @@
const unsigned char *input,
size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill;
unsigned int left;
@@ -366,7 +394,7 @@
int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx,
unsigned char output[64] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned used;
uint64_t high, low;
@@ -403,8 +431,8 @@
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
- PUT_UINT64_BE( high, ctx->buffer, 112 );
- PUT_UINT64_BE( low, ctx->buffer, 120 );
+ sha512_put_uint64_be( high, ctx->buffer, 112 );
+ sha512_put_uint64_be( low, ctx->buffer, 120 );
if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
@@ -412,17 +440,19 @@
/*
* Output final state
*/
- PUT_UINT64_BE( ctx->state[0], output, 0 );
- PUT_UINT64_BE( ctx->state[1], output, 8 );
- PUT_UINT64_BE( ctx->state[2], output, 16 );
- PUT_UINT64_BE( ctx->state[3], output, 24 );
- PUT_UINT64_BE( ctx->state[4], output, 32 );
- PUT_UINT64_BE( ctx->state[5], output, 40 );
+ sha512_put_uint64_be( ctx->state[0], output, 0 );
+ sha512_put_uint64_be( ctx->state[1], output, 8 );
+ sha512_put_uint64_be( ctx->state[2], output, 16 );
+ sha512_put_uint64_be( ctx->state[3], output, 24 );
+ 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
{
- PUT_UINT64_BE( ctx->state[6], output, 48 );
- PUT_UINT64_BE( ctx->state[7], output, 56 );
+ sha512_put_uint64_be( ctx->state[6], output, 48 );
+ sha512_put_uint64_be( ctx->state[7], output, 56 );
}
return( 0 );
@@ -446,10 +476,14 @@
unsigned char output[64],
int is384 )
{
- int ret;
+ 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 );
@@ -498,8 +532,9 @@
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
*/
@@ -521,6 +556,7 @@
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
@@ -551,6 +587,8 @@
0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
};
+#define ARRAY_LENGTH( a ) ( sizeof( a ) / sizeof( ( a )[0] ) )
+
/*
* Checkup routine
*/
@@ -572,10 +610,14 @@
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 );
@@ -631,6 +673,8 @@
return( ret );
}
+#undef ARRAY_LENGTH
+
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_SHA512_C */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_cache.c b/lib/libmbedtls/mbedtls/library/ssl_cache.c
index 4d8c866..07dcc88 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_cache.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_cache.c
@@ -40,6 +40,7 @@
#endif
#include "mbedtls/ssl_cache.h"
+#include "mbedtls/ssl_internal.h"
#include <string.h>
@@ -92,16 +93,24 @@
entry->session.id_len ) != 0 )
continue;
- memcpy( session->master, entry->session.master, 48 );
+ ret = mbedtls_ssl_session_copy( session, &entry->session );
+ if( ret != 0 )
+ {
+ ret = 1;
+ goto exit;
+ }
- session->verify_result = entry->session.verify_result;
-
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+ defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
/*
* Restore peer certificate (without rest of the original chain)
*/
if( entry->peer_cert.p != NULL )
{
+ /* `session->peer_cert` is NULL after the call to
+ * mbedtls_ssl_session_copy(), because cache entries
+ * have the `peer_cert` field set to NULL. */
+
if( ( session->peer_cert = mbedtls_calloc( 1,
sizeof(mbedtls_x509_crt) ) ) == NULL )
{
@@ -119,7 +128,7 @@
goto exit;
}
}
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
ret = 0;
goto exit;
@@ -239,9 +248,8 @@
#endif
}
- memcpy( &cur->session, session, sizeof( mbedtls_ssl_session ) );
-
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+ defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
/*
* If we're reusing an entry, free its certificate first
*/
@@ -250,26 +258,43 @@
mbedtls_free( cur->peer_cert.p );
memset( &cur->peer_cert, 0, sizeof(mbedtls_x509_buf) );
}
+#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
- /*
- * Store peer certificate
- */
- if( session->peer_cert != NULL )
+ /* Copy the entire session; this temporarily makes a copy of the
+ * X.509 CRT structure even though we only want to store the raw CRT.
+ * This inefficiency will go away as soon as we implement on-demand
+ * parsing of CRTs, in which case there's no need for the `peer_cert`
+ * field anymore in the first place, and we're done after this call. */
+ ret = mbedtls_ssl_session_copy( &cur->session, session );
+ if( ret != 0 )
{
- cur->peer_cert.p = mbedtls_calloc( 1, session->peer_cert->raw.len );
+ ret = 1;
+ goto exit;
+ }
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+ defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ /* If present, free the X.509 structure and only store the raw CRT data. */
+ if( cur->session.peer_cert != NULL )
+ {
+ cur->peer_cert.p =
+ mbedtls_calloc( 1, cur->session.peer_cert->raw.len );
if( cur->peer_cert.p == NULL )
{
ret = 1;
goto exit;
}
- memcpy( cur->peer_cert.p, session->peer_cert->raw.p,
- session->peer_cert->raw.len );
+ memcpy( cur->peer_cert.p,
+ cur->session.peer_cert->raw.p,
+ cur->session.peer_cert->raw.len );
cur->peer_cert.len = session->peer_cert->raw.len;
+ mbedtls_x509_crt_free( cur->session.peer_cert );
+ mbedtls_free( cur->session.peer_cert );
cur->session.peer_cert = NULL;
}
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
ret = 0;
@@ -311,9 +336,10 @@
mbedtls_ssl_session_free( &prv->session );
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+ defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
mbedtls_free( prv->peer_cert.p );
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
mbedtls_free( prv );
}
diff --git a/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c b/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c
index ec34787..967981c 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c
@@ -2353,7 +2353,7 @@
}
#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 @@
return( 0 );
}
}
-#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif /* MBEDTLS_SSL_TLS_C */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_cli.c b/lib/libmbedtls/mbedtls/library/ssl_cli.c
index 15b166c..47b6d0c 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_cli.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_cli.c
@@ -35,9 +35,14 @@
#define mbedtls_free free
#endif
-#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "mbedtls/psa_util.h"
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
#include <string.h>
@@ -51,6 +56,44 @@
#include "mbedtls/platform_util.h"
#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+static int ssl_conf_has_static_psk( mbedtls_ssl_config const *conf )
+{
+ if( conf->psk_identity == NULL ||
+ conf->psk_identity_len == 0 )
+ {
+ return( 0 );
+ }
+
+ if( conf->psk != NULL && conf->psk_len != 0 )
+ return( 1 );
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( conf->psk_opaque != 0 )
+ return( 1 );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+ return( 0 );
+}
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+static int ssl_conf_has_static_raw_psk( mbedtls_ssl_config const *conf )
+{
+ if( conf->psk_identity == NULL ||
+ conf->psk_identity_len == 0 )
+ {
+ return( 0 );
+ }
+
+ if( conf->psk != NULL && conf->psk_len != 0 )
+ return( 1 );
+
+ return( 0 );
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
@@ -165,7 +208,7 @@
* 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 )
@@ -247,7 +290,7 @@
*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)
@@ -360,7 +403,7 @@
unsigned char *buf,
size_t *olen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
size_t kkpp_len;
@@ -433,6 +476,54 @@
}
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+static void ssl_write_cid_ext( mbedtls_ssl_context *ssl,
+ unsigned char *buf,
+ size_t *olen )
+{
+ unsigned char *p = buf;
+ size_t ext_len;
+ const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
+
+ /*
+ * Quoting draft-ietf-tls-dtls-connection-id-05
+ * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05
+ *
+ * struct {
+ * opaque cid<0..2^8-1>;
+ * } ConnectionId;
+ */
+
+ *olen = 0;
+ if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
+ ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED )
+ {
+ return;
+ }
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding CID extension" ) );
+
+ /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX
+ * which is at most 255, so the increment cannot overflow. */
+ if( end < p || (size_t)( end - p ) < (unsigned)( ssl->own_cid_len + 5 ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
+ return;
+ }
+
+ /* Add extension ID + size */
+ *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_CID >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_CID ) & 0xFF );
+ ext_len = (size_t) ssl->own_cid_len + 1;
+ *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( ext_len ) & 0xFF );
+
+ *p++ = (uint8_t) ssl->own_cid_len;
+ memcpy( p, ssl->own_cid, ssl->own_cid_len );
+
+ *olen = ssl->own_cid_len + 5;
+}
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
@@ -676,7 +767,7 @@
*/
static int ssl_generate_random( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = ssl->handshake->randbytes;
#if defined(MBEDTLS_HAVE_TIME)
mbedtls_time_t t;
@@ -754,12 +845,21 @@
return( 1 );
#endif
+ /* Don't suggest PSK-based ciphersuite if no PSK is available. */
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+ if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) &&
+ ssl_conf_has_static_psk( ssl->conf ) == 0 )
+ {
+ return( 1 );
+ }
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+
return( 0 );
}
static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, n, olen, ext_len = 0;
unsigned char *buf;
unsigned char *p, *q;
@@ -1012,7 +1112,7 @@
#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
@@ -1034,6 +1134,11 @@
ext_len += olen;
#endif
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ ssl_write_cid_ext( ssl, p + 2 + ext_len, &olen );
+ ext_len += olen;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen );
ext_len += olen;
@@ -1191,6 +1296,62 @@
}
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl,
+ const unsigned char *buf,
+ size_t len )
+{
+ size_t peer_cid_len;
+
+ if( /* CID extension only makes sense in DTLS */
+ ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
+ /* The server must only send the CID extension if we have offered it. */
+ ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension unexpected" ) );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+ return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
+ if( len == 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+ return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
+ peer_cid_len = *buf++;
+ len--;
+
+ if( peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+ return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
+ if( len != peer_cid_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+ return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+ }
+
+ ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED;
+ ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len;
+ memcpy( ssl->handshake->peer_cid, buf, peer_cid_len );
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use of CID extension negotiated" ) );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "Server CID", buf, peer_cid_len );
+
+ return( 0 );
+}
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
@@ -1310,9 +1471,9 @@
const unsigned char *buf,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- if( ssl->transform_negotiate->ciphersuite_info->key_exchange !=
+ if( ssl->handshake->ciphersuite_info->key_exchange !=
MBEDTLS_KEY_EXCHANGE_ECJPAKE )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) );
@@ -1417,6 +1578,19 @@
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;
@@ -1445,8 +1619,6 @@
}
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,
@@ -1455,6 +1627,7 @@
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 );
@@ -1498,8 +1671,6 @@
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) );
- buf = ssl->in_msg;
-
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
/* No alert on a read error. */
@@ -1507,6 +1678,8 @@
return( ret );
}
+ buf = ssl->in_msg;
+
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
{
#if defined(MBEDTLS_SSL_RENEGOTIATION)
@@ -1675,9 +1848,8 @@
/*
* Initialize update checksum functions
*/
- ssl->transform_negotiate->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i );
-
- if( ssl->transform_negotiate->ciphersuite_info == NULL )
+ ssl->handshake->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i );
+ if( ssl->handshake->ciphersuite_info == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
@@ -1685,7 +1857,7 @@
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
- mbedtls_ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info );
+ mbedtls_ssl_optimize_checksum( ssl, ssl->handshake->ciphersuite_info );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) );
MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 35, n );
@@ -1763,7 +1935,7 @@
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 )
{
@@ -1843,6 +2015,20 @@
break;
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ case MBEDTLS_TLS_EXT_CID:
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "found CID extension" ) );
+
+ if( ( ret = ssl_parse_cid_ext( ssl,
+ ext + 4,
+ ext_size ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ break;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt_then_mac extension" ) );
@@ -2062,6 +2248,68 @@
MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
+ ( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) )
+static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl,
+ unsigned char **p,
+ unsigned char *end )
+{
+ uint16_t tls_id;
+ size_t ecdh_bits = 0;
+ uint8_t ecpoint_len;
+ mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+ /*
+ * Parse ECC group
+ */
+
+ if( end - *p < 4 )
+ return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+
+ /* First byte is curve_type; only named_curve is handled */
+ if( *(*p)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
+ return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+
+ /* Next two bytes are the namedcurve value */
+ tls_id = *(*p)++;
+ tls_id <<= 8;
+ tls_id |= *(*p)++;
+
+ /* Convert EC group to PSA key type. */
+ 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.
+ */
+
+ ecpoint_len = *(*p)++;
+ if( (size_t)( end - *p ) < ecpoint_len )
+ return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+
+ if( mbedtls_psa_tls_ecpoint_to_psa_ec(
+ *p, ecpoint_len,
+ handshake->ecdh_psa_peerkey,
+ sizeof( handshake->ecdh_psa_peerkey ),
+ &handshake->ecdh_psa_peerkey_len ) != 0 )
+ {
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ }
+
+ *p += ecpoint_len;
+ return( 0 );
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO &&
+ ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+ MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */
+
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
@@ -2083,7 +2331,7 @@
(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
@@ -2102,13 +2350,13 @@
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);
/*
@@ -2125,7 +2373,7 @@
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)" ) );
@@ -2142,7 +2390,7 @@
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)
@@ -2153,9 +2401,10 @@
size_t offset, size_t *olen,
size_t pms_offset )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2;
unsigned char *p = ssl->handshake->premaster + pms_offset;
+ mbedtls_pk_context * peer_pk;
if( offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN )
{
@@ -2181,23 +2430,28 @@
ssl->handshake->pmslen = 48;
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ peer_pk = &ssl->handshake->peer_pubkey;
+#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
if( ssl->session_negotiate->peer_cert == NULL )
{
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) );
- return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+ /* Should never happen */
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
+ peer_pk = &ssl->session_negotiate->peer_cert->pk;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
/*
* Now write it out, encrypted
*/
- if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk,
- MBEDTLS_PK_RSA ) )
+ if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_RSA ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) );
return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
}
- if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk,
+ if( ( ret = mbedtls_pk_encrypt( peer_pk,
p, ssl->handshake->pmslen,
ssl->out_msg + offset + len_bytes, olen,
MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes,
@@ -2217,6 +2471,10 @@
}
#endif
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ /* We don't need the peer's public key anymore. Free it. */
+ mbedtls_pk_free( peer_pk );
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
return( 0 );
}
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED ||
@@ -2290,23 +2548,29 @@
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_ecp_keypair *peer_key;
+ mbedtls_pk_context * peer_pk;
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ peer_pk = &ssl->handshake->peer_pubkey;
+#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
if( ssl->session_negotiate->peer_cert == NULL )
{
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) );
- return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+ /* Should never happen */
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
+ peer_pk = &ssl->session_negotiate->peer_cert->pk;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
- if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk,
- MBEDTLS_PK_ECKEY ) )
+ if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_ECKEY ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
}
- peer_key = mbedtls_pk_ec( ssl->session_negotiate->peer_cert->pk );
+ peer_key = mbedtls_pk_ec( *peer_pk );
if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key,
MBEDTLS_ECDH_THEIRS ) ) != 0 )
@@ -2321,6 +2585,13 @@
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
}
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ /* We don't need the peer's public key anymore. Free it,
+ * so that more RAM is available for upcoming expensive
+ * operations like ECDHE. */
+ mbedtls_pk_free( peer_pk );
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
return( ret );
}
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
@@ -2328,9 +2599,9 @@
static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
- ssl->transform_negotiate->ciphersuite_info;
+ ssl->handshake->ciphersuite_info;
unsigned char *p = NULL, *end = NULL;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) );
@@ -2368,7 +2639,7 @@
#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 )
{
@@ -2413,7 +2684,7 @@
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;
@@ -2423,7 +2694,7 @@
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 ||
@@ -2437,7 +2708,7 @@
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)
@@ -2463,6 +2734,24 @@
else
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
+ ( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) )
+ if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
+ ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
+ {
+ if( ssl_parse_server_ecdh_params_psa( ssl, &p, end ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+ return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+ }
+ }
+ else
+#endif /* MBEDTLS_USE_PSA_CRYPTO &&
+ ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+ MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
@@ -2502,7 +2791,7 @@
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;
@@ -2513,6 +2802,8 @@
size_t params_len = p - params;
void *rs_ctx = NULL;
+ mbedtls_pk_context * peer_pk;
+
/*
* Handle the digitally-signed structure
*/
@@ -2615,18 +2906,22 @@
MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ peer_pk = &ssl->handshake->peer_pubkey;
+#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
if( ssl->session_negotiate->peer_cert == NULL )
{
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) );
- mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
- return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+ /* Should never happen */
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
+ peer_pk = &ssl->session_negotiate->peer_cert->pk;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
/*
* Verify signature
*/
- if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) )
+ if( !mbedtls_pk_can_do( peer_pk, pk_alg ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
@@ -2634,29 +2929,35 @@
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
- if( ( ret = mbedtls_pk_verify_restartable(
- &ssl->session_negotiate->peer_cert->pk,
+ 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
return( ret );
}
+
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ /* We don't need the peer's public key anymore. Free it,
+ * so that more RAM is available for upcoming expensive
+ * operations like ECDHE. */
+ 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++;
@@ -2666,11 +2967,11 @@
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 =
- ssl->transform_negotiate->ciphersuite_info;
+ ssl->handshake->ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
@@ -2684,15 +2985,15 @@
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;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *buf;
size_t n = 0;
size_t cert_type_len = 0, dn_len = 0;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
- ssl->transform_negotiate->ciphersuite_info;
+ ssl->handshake->ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) );
@@ -2847,11 +3148,11 @@
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 )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
@@ -2890,10 +3191,12 @@
static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
{
- int ret;
- size_t i, n;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ size_t header_len;
+ size_t content_len;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
- ssl->transform_negotiate->ciphersuite_info;
+ ssl->handshake->ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) );
@@ -2903,16 +3206,16 @@
/*
* DHM key exchange -- send G^X mod P
*/
- n = ssl->handshake->dhm_ctx.len;
+ content_len = ssl->handshake->dhm_ctx.len;
- ssl->out_msg[4] = (unsigned char)( n >> 8 );
- ssl->out_msg[5] = (unsigned char)( n );
- i = 6;
+ ssl->out_msg[4] = (unsigned char)( content_len >> 8 );
+ ssl->out_msg[5] = (unsigned char)( content_len );
+ header_len = 6;
ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx,
- (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
- &ssl->out_msg[i], n,
- ssl->conf->f_rng, ssl->conf->p_rng );
+ (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
+ &ssl->out_msg[header_len], content_len,
+ ssl->conf->f_rng, ssl->conf->p_rng );
if( ret != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret );
@@ -2923,10 +3226,10 @@
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX );
if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx,
- ssl->handshake->premaster,
- MBEDTLS_PREMASTER_SIZE,
- &ssl->handshake->pmslen,
- ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
+ ssl->handshake->premaster,
+ MBEDTLS_PREMASTER_SIZE,
+ &ssl->handshake->pmslen,
+ ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret );
return( ret );
@@ -2936,6 +3239,93 @@
}
else
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
+ ( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) )
+ if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
+ ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
+ {
+ psa_status_t status;
+ psa_key_attributes_t key_attributes;
+
+ mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+ unsigned char own_pubkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
+ size_t own_pubkey_len;
+ unsigned char *own_pubkey_ecpoint;
+ size_t own_pubkey_ecpoint_len;
+
+ header_len = 4;
+
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Perform PSA-based ECDH computation." ) );
+
+ /*
+ * Generate EC private key for ECDHE exchange.
+ */
+
+ /* The master secret is obtained from the shared ECDH secret by
+ * applying the TLS 1.2 PRF with a specific salt and label. While
+ * the PSA Crypto API encourages combining key agreement schemes
+ * such as ECDH with fixed KDFs such as TLS 1.2 PRF, it does not
+ * yet support the provisioning of salt + label to the KDF.
+ * For the time being, we therefore need to split the computation
+ * of the ECDH secret and the application of the TLS 1.2 PRF. */
+ 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, handshake->ecdh_psa_type );
+ psa_set_key_bits( &key_attributes, handshake->ecdh_bits );
+
+ /* Generate ECDH private key. */
+ status = psa_generate_key( &key_attributes,
+ &handshake->ecdh_psa_privkey );
+ if( status != PSA_SUCCESS )
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+
+ /* Export the public part of the ECDH private key from PSA
+ * and convert it to ECPoint format used in ClientKeyExchange. */
+ status = psa_export_public_key( handshake->ecdh_psa_privkey,
+ own_pubkey, sizeof( own_pubkey ),
+ &own_pubkey_len );
+ if( status != PSA_SUCCESS )
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+
+ if( mbedtls_psa_tls_psa_ec_to_ecpoint( own_pubkey,
+ own_pubkey_len,
+ &own_pubkey_ecpoint,
+ &own_pubkey_ecpoint_len ) != 0 )
+ {
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ }
+
+ /* Copy ECPoint structure to outgoing message buffer. */
+ ssl->out_msg[header_len] = (unsigned char) own_pubkey_ecpoint_len;
+ memcpy( ssl->out_msg + header_len + 1,
+ own_pubkey_ecpoint, own_pubkey_ecpoint_len );
+ content_len = own_pubkey_ecpoint_len + 1;
+
+ /* The ECDH secret is the premaster secret used for key derivation. */
+
+ /* Compute ECDH shared secret. */
+ status = psa_raw_key_agreement( PSA_ALG_ECDH,
+ handshake->ecdh_psa_privkey,
+ handshake->ecdh_psa_peerkey,
+ handshake->ecdh_psa_peerkey_len,
+ ssl->handshake->premaster,
+ sizeof( ssl->handshake->premaster ),
+ &ssl->handshake->pmslen );
+ if( status != PSA_SUCCESS )
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+
+ status = psa_destroy_key( handshake->ecdh_psa_privkey );
+ if( status != PSA_SUCCESS )
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ handshake->ecdh_psa_privkey = 0;
+ }
+ else
+#endif /* MBEDTLS_USE_PSA_CRYPTO &&
+ ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+ MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
@@ -2948,9 +3338,9 @@
/*
* ECDH key exchange -- send client public value
*/
- i = 4;
+ 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 )
@@ -2961,13 +3351,13 @@
#endif
ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx,
- &n,
- &ssl->out_msg[i], 1000,
+ &content_len,
+ &ssl->out_msg[header_len], 1000,
ssl->conf->f_rng, ssl->conf->p_rng );
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
@@ -2977,25 +3367,25 @@
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 = n;
+ ssl->handshake->ecrs_n = content_len;
ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret;
}
ecdh_calc_secret:
if( ssl->handshake->ecrs_enabled )
- n = ssl->handshake->ecrs_n;
+ content_len = ssl->handshake->ecrs_n;
#endif
if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
- &ssl->handshake->pmslen,
- ssl->handshake->premaster,
- MBEDTLS_MPI_MAX_SIZE,
- ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
+ &ssl->handshake->pmslen,
+ ssl->handshake->premaster,
+ MBEDTLS_MPI_MAX_SIZE,
+ 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
@@ -3010,45 +3400,56 @@
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 ) )
{
/*
* opaque psk_identity<0..2^16-1>;
*/
- if( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL )
+ if( ssl_conf_has_static_psk( ssl->conf ) == 0 )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for PSK" ) );
- return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
+ /* We don't offer PSK suites if we don't have a PSK,
+ * and we check that the server's choice is among the
+ * ciphersuites we offered, so this should never happen. */
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
- i = 4;
- n = ssl->conf->psk_identity_len;
+ header_len = 4;
+ content_len = ssl->conf->psk_identity_len;
- if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN )
+ if( header_len + 2 + content_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or "
"SSL buffer too short" ) );
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
}
- ssl->out_msg[i++] = (unsigned char)( n >> 8 );
- ssl->out_msg[i++] = (unsigned char)( n );
+ ssl->out_msg[header_len++] = (unsigned char)( content_len >> 8 );
+ ssl->out_msg[header_len++] = (unsigned char)( content_len );
- memcpy( ssl->out_msg + i, ssl->conf->psk_identity, ssl->conf->psk_identity_len );
- i += ssl->conf->psk_identity_len;
+ memcpy( ssl->out_msg + header_len,
+ ssl->conf->psk_identity,
+ ssl->conf->psk_identity_len );
+ header_len += ssl->conf->psk_identity_len;
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK )
{
- n = 0;
+ content_len = 0;
}
else
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
{
- if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 )
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ /* Opaque PSKs are currently only supported for PSK-only suites. */
+ if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
+ return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+ if( ( ret = ssl_write_encrypted_pms( ssl, header_len,
+ &content_len, 2 ) ) != 0 )
return( ret );
}
else
@@ -3056,24 +3457,31 @@
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK )
{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ /* Opaque PSKs are currently only supported for PSK-only suites. */
+ if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
+ return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
/*
* ClientDiffieHellmanPublic public (DHM send G^X mod P)
*/
- n = ssl->handshake->dhm_ctx.len;
+ content_len = ssl->handshake->dhm_ctx.len;
- if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN )
+ if( header_len + 2 + content_len >
+ MBEDTLS_SSL_OUT_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long"
" or SSL buffer too short" ) );
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
}
- ssl->out_msg[i++] = (unsigned char)( n >> 8 );
- ssl->out_msg[i++] = (unsigned char)( n );
+ ssl->out_msg[header_len++] = (unsigned char)( content_len >> 8 );
+ ssl->out_msg[header_len++] = (unsigned char)( content_len );
ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx,
(int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
- &ssl->out_msg[i], n,
+ &ssl->out_msg[header_len], content_len,
ssl->conf->f_rng, ssl->conf->p_rng );
if( ret != 0 )
{
@@ -3086,11 +3494,19 @@
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ /* Opaque PSKs are currently only supported for PSK-only suites. */
+ if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
+ return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
/*
* ClientECDiffieHellmanPublic public;
*/
- ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n,
- &ssl->out_msg[i], MBEDTLS_SSL_OUT_CONTENT_LEN - i,
+ ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx,
+ &content_len,
+ &ssl->out_msg[header_len],
+ MBEDTLS_SSL_OUT_CONTENT_LEN - header_len,
ssl->conf->f_rng, ssl->conf->p_rng );
if( ret != 0 )
{
@@ -3108,6 +3524,17 @@
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
+ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
+ if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK &&
+ ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 &&
+ ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "skip PMS generation for opaque PSK" ) );
+ }
+ else
+#endif /* MBEDTLS_USE_PSA_CRYPTO &&
+ MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
ciphersuite_info->key_exchange ) ) != 0 )
{
@@ -3116,12 +3543,13 @@
}
}
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 )
{
- i = 4;
- if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 0 ) ) != 0 )
+ header_len = 4;
+ if( ( ret = ssl_write_encrypted_pms( ssl, header_len,
+ &content_len, 0 ) ) != 0 )
return( ret );
}
else
@@ -3129,10 +3557,12 @@
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
{
- i = 4;
+ header_len = 4;
ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx,
- ssl->out_msg + i, MBEDTLS_SSL_OUT_CONTENT_LEN - i, &n,
+ ssl->out_msg + header_len,
+ MBEDTLS_SSL_OUT_CONTENT_LEN - header_len,
+ &content_len,
ssl->conf->f_rng, ssl->conf->p_rng );
if( ret != 0 )
{
@@ -3157,7 +3587,7 @@
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
- ssl->out_msglen = i + n;
+ ssl->out_msglen = header_len + content_len;
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE;
@@ -3174,17 +3604,12 @@
return( 0 );
}
-#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
- !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
- !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
- !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
- !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \
- !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_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 =
- ssl->transform_negotiate->ciphersuite_info;
- int ret;
+ ssl->handshake->ciphersuite_info;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
@@ -3194,11 +3619,7 @@
return( ret );
}
- 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_ECDHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
+ if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
ssl->state++;
@@ -3208,22 +3629,22 @@
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
-#else
+#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;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
- ssl->transform_negotiate->ciphersuite_info;
+ ssl->handshake->ciphersuite_info;
size_t n = 0, offset = 0;
unsigned char hash[48];
unsigned char *hash_start = hash;
mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
- unsigned int hashlen;
+ size_t hashlen;
void *rs_ctx = NULL;
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 )
{
@@ -3237,11 +3658,7 @@
return( ret );
}
- 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_ECDHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
+ if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
ssl->state++;
@@ -3264,14 +3681,14 @@
/*
* 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;
sign:
#endif
- ssl->handshake->calc_verify( ssl, hash );
+ ssl->handshake->calc_verify( ssl, hash, &hashlen );
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_1)
@@ -3289,7 +3706,6 @@
* sha_hash
* SHA(handshake_messages);
*/
- hashlen = 36;
md_alg = MBEDTLS_MD_NONE;
/*
@@ -3323,8 +3739,7 @@
* Reason: Otherwise we should have running hashes for SHA512 and SHA224
* in order to satisfy 'weird' needs from the server side.
*/
- if( ssl->transform_negotiate->ciphersuite_info->mac ==
- MBEDTLS_MD_SHA384 )
+ if( ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384 )
{
md_alg = MBEDTLS_MD_SHA384;
ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384;
@@ -3347,7 +3762,7 @@
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
@@ -3358,7 +3773,7 @@
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
@@ -3384,17 +3799,12 @@
return( ret );
}
-#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED &&
- !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED &&
- !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED &&
- !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
- !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED &&
- !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_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 )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t lifetime;
size_t ticket_len;
unsigned char *ticket;
@@ -3463,6 +3873,15 @@
if( ticket_len == 0 )
return( 0 );
+ if( ssl->session != NULL && ssl->session->ticket != NULL )
+ {
+ mbedtls_platform_zeroize( ssl->session->ticket,
+ ssl->session->ticket_len );
+ mbedtls_free( ssl->session->ticket );
+ ssl->session->ticket = NULL;
+ ssl->session->ticket_len = 0;
+ }
+
mbedtls_platform_zeroize( ssl->session_negotiate->ticket,
ssl->session_negotiate->ticket_len );
mbedtls_free( ssl->session_negotiate->ticket );
diff --git a/lib/libmbedtls/mbedtls/library/ssl_cookie.c b/lib/libmbedtls/mbedtls/library/ssl_cookie.c
index 239eb27..0b566d6 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_cookie.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_cookie.c
@@ -40,6 +40,7 @@
#include "mbedtls/ssl_cookie.h"
#include "mbedtls/ssl_internal.h"
+#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include <string.h>
@@ -104,7 +105,7 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char key[COOKIE_MD_OUTLEN];
if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 )
@@ -157,7 +158,7 @@
unsigned char **p, unsigned char *end,
const unsigned char *cli_id, size_t cli_id_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx;
unsigned long t;
diff --git a/lib/libmbedtls/mbedtls/library/ssl_msg.c b/lib/libmbedtls/mbedtls/library/ssl_msg.c
new file mode 100644
index 0000000..976fc7b
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/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 <stdlib.h>
+#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 <string.h>
+
+#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/lib/libmbedtls/mbedtls/library/ssl_srv.c b/lib/libmbedtls/mbedtls/library/ssl_srv.c
index fde24f9..5f184e8 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_srv.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_srv.c
@@ -35,9 +35,10 @@
#define mbedtls_free free
#endif
-#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include <string.h>
@@ -85,7 +86,7 @@
const unsigned char *buf,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t servername_list_size, hostname_len;
const unsigned char *p;
@@ -149,6 +150,48 @@
}
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+static int ssl_conf_has_psk_or_cb( mbedtls_ssl_config const *conf )
+{
+ if( conf->f_psk != NULL )
+ return( 1 );
+
+ if( conf->psk_identity_len == 0 || conf->psk_identity == NULL )
+ return( 0 );
+
+ if( conf->psk != NULL && conf->psk_len != 0 )
+ return( 1 );
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( conf->psk_opaque != 0 )
+ return( 1 );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+ return( 0 );
+}
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl )
+{
+ if( ssl->conf->f_psk != NULL )
+ {
+ /* If we've used a callback to select the PSK,
+ * the static configuration is irrelevant. */
+
+ if( ssl->handshake->psk_opaque != 0 )
+ return( 1 );
+
+ return( 0 );
+ }
+
+ if( ssl->conf->psk_opaque != 0 )
+ return( 1 );
+
+ return( 0 );
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+
static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -186,7 +229,7 @@
}
#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:
@@ -274,7 +317,7 @@
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)
@@ -390,7 +433,7 @@
const unsigned char *buf,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 )
{
@@ -433,6 +476,78 @@
}
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl,
+ const unsigned char *buf,
+ size_t len )
+{
+ size_t peer_cid_len;
+
+ /* CID extension only makes sense in DTLS */
+ if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ /*
+ * Quoting draft-ietf-tls-dtls-connection-id-05
+ * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05
+ *
+ * struct {
+ * opaque cid<0..2^8-1>;
+ * } ConnectionId;
+ */
+
+ if( len < 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ peer_cid_len = *buf++;
+ len--;
+
+ if( len != peer_cid_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ /* Ignore CID if the user has disabled its use. */
+ if( ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED )
+ {
+ /* Leave ssl->handshake->cid_in_use in its default
+ * value of MBEDTLS_SSL_CID_DISABLED. */
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Client sent CID extension, but CID disabled" ) );
+ return( 0 );
+ }
+
+ if( peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED;
+ ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len;
+ memcpy( ssl->handshake->peer_cid, buf, peer_cid_len );
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use of CID extension negotiated" ) );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "Client CID", buf, peer_cid_len );
+
+ return( 0 );
+}
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
@@ -510,7 +625,7 @@
unsigned char *buf,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ssl_session session;
mbedtls_ssl_session_init( &session );
@@ -725,6 +840,7 @@
for( cur = list; cur != NULL; cur = cur->next )
{
+ flags = 0;
MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate",
cur->cert );
@@ -806,7 +922,7 @@
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
@@ -863,13 +979,11 @@
}
#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 ) &&
- ssl->conf->f_psk == NULL &&
- ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL ||
- ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) )
+ ssl_conf_has_psk_or_cb( ssl->conf ) == 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) );
return( 0 );
@@ -877,7 +991,7 @@
#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 )
@@ -893,7 +1007,7 @@
}
#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)
/*
@@ -1155,7 +1269,7 @@
MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) );
ssl->session_negotiate->ciphersuite = ciphersuites[i];
- ssl->transform_negotiate->ciphersuite_info = ciphersuite_info;
+ ssl->handshake->ciphersuite_info = ciphersuite_info;
/*
* SSLv2 Client Hello relevant renegotiation security checks
@@ -1203,10 +1317,10 @@
* 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" ) );
@@ -1240,7 +1354,7 @@
return( ssl_parse_client_hello_v2( ssl ) );
#endif
- MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_hdr_len( ssl ) );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_in_hdr_len( ssl ) );
/*
* SSLv3/TLS Client Hello
@@ -1329,7 +1443,7 @@
}
if( ( ret = mbedtls_ssl_fetch_input( ssl,
- mbedtls_ssl_hdr_len( ssl ) + msg_len ) ) != 0 )
+ mbedtls_ssl_in_hdr_len( ssl ) + msg_len ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
return( ret );
@@ -1338,7 +1452,7 @@
/* Done reading this record, get ready for the next one */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- ssl->next_record_offset = msg_len + mbedtls_ssl_hdr_len( ssl );
+ ssl->next_record_offset = msg_len + mbedtls_ssl_in_hdr_len( ssl );
else
#endif
ssl->in_left = 0;
@@ -1719,7 +1833,7 @@
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" ) );
@@ -1730,7 +1844,7 @@
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)
@@ -1783,6 +1897,16 @@
break;
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ case MBEDTLS_TLS_EXT_CID:
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "found CID extension" ) );
+
+ ret = ssl_parse_cid_ext( ssl, ext + 4, ext_size );
+ if( ret != 0 )
+ return( ret );
+ break;
+#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
+
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) );
@@ -1867,7 +1991,7 @@
#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
@@ -1884,7 +2008,7 @@
}
#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
@@ -1999,7 +2123,7 @@
MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) );
ssl->session_negotiate->ciphersuite = ciphersuites[i];
- ssl->transform_negotiate->ciphersuite_info = ciphersuite_info;
+ ssl->handshake->ciphersuite_info = ciphersuite_info;
ssl->state++;
@@ -2011,7 +2135,7 @@
/* 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 );
@@ -2060,6 +2184,54 @@
}
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+static void ssl_write_cid_ext( mbedtls_ssl_context *ssl,
+ unsigned char *buf,
+ size_t *olen )
+{
+ unsigned char *p = buf;
+ size_t ext_len;
+ const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
+
+ *olen = 0;
+
+ /* Skip writing the extension if we don't want to use it or if
+ * the client hasn't offered it. */
+ if( ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_DISABLED )
+ return;
+
+ /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX
+ * which is at most 255, so the increment cannot overflow. */
+ if( end < p || (size_t)( end - p ) < (unsigned)( ssl->own_cid_len + 5 ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
+ return;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding CID extension" ) );
+
+ /*
+ * Quoting draft-ietf-tls-dtls-connection-id-05
+ * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05
+ *
+ * struct {
+ * opaque cid<0..2^8-1>;
+ * } ConnectionId;
+ */
+
+ *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_CID >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_CID ) & 0xFF );
+ ext_len = (size_t) ssl->own_cid_len + 1;
+ *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( ext_len ) & 0xFF );
+
+ *p++ = (uint8_t) ssl->own_cid_len;
+ memcpy( p, ssl->own_cid, ssl->own_cid_len );
+
+ *olen = ssl->own_cid_len + 5;
+}
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
@@ -2258,7 +2430,7 @@
unsigned char *buf,
size_t *olen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
size_t kkpp_len;
@@ -2266,7 +2438,7 @@
*olen = 0;
/* Skip costly computation if not needed */
- if( ssl->transform_negotiate->ciphersuite_info->key_exchange !=
+ if( ssl->handshake->ciphersuite_info->key_exchange !=
MBEDTLS_KEY_EXCHANGE_ECJPAKE )
return;
@@ -2336,7 +2508,7 @@
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = ssl->out_msg + 4;
unsigned char *cookie_len_byte;
@@ -2410,7 +2582,7 @@
#if defined(MBEDTLS_HAVE_TIME)
mbedtls_time_t t;
#endif
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t olen, ext_len = 0, n;
unsigned char *buf, *p;
@@ -2581,6 +2753,11 @@
ext_len += olen;
#endif
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ ssl_write_cid_ext( ssl, p + 2 + ext_len, &olen );
+ ext_len += olen;
+#endif
+
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen );
ext_len += olen;
@@ -2640,24 +2817,15 @@
return( ret );
}
-#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
- !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
- !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
- !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
- !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \
- !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_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 =
- ssl->transform_negotiate->ciphersuite_info;
+ ssl->handshake->ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
- 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 ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
+ if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) );
ssl->state++;
@@ -2667,12 +2835,12 @@
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
-#else
+#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;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
- ssl->transform_negotiate->ciphersuite_info;
+ ssl->handshake->ciphersuite_info;
size_t dn_size, total_dn_size; /* excluding length bytes */
size_t ct_len, sa_len; /* including length bytes */
unsigned char *buf, *p;
@@ -2691,11 +2859,7 @@
#endif
authmode = ssl->conf->authmode;
- 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 ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
+ if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ||
authmode == MBEDTLS_SSL_VERIFY_NONE )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) );
@@ -2791,6 +2955,11 @@
if( ssl->conf->cert_req_ca_list == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED )
{
+ /* NOTE: If trusted certificates are provisioned
+ * via a CA callback (configured through
+ * `mbedtls_ssl_conf_ca_cb()`, then the
+ * CertificateRequest is currently left empty. */
+
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
if( ssl->handshake->sni_ca_chain != NULL )
crt = ssl->handshake->sni_ca_chain;
@@ -2834,18 +3003,13 @@
return( ret );
}
-#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED &&
- !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED &&
- !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED &&
- !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
- !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED &&
- !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) )
{
@@ -2866,7 +3030,7 @@
#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 )
@@ -2889,7 +3053,7 @@
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
@@ -2899,17 +3063,18 @@
size_t *signature_len )
{
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
- ssl->transform_negotiate->ciphersuite_info;
-#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED)
-#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
+ ssl->handshake->ciphersuite_info;
+
+#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 */
@@ -2925,7 +3090,7 @@
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
ret = mbedtls_ecjpake_write_round_two(
@@ -2962,10 +3127,10 @@
/*
* - 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;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL )
@@ -3001,7 +3166,7 @@
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
@@ -3012,12 +3177,12 @@
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 ) )
{
/*
@@ -3030,7 +3195,7 @@
*/
const mbedtls_ecp_curve_info **curve = NULL;
const mbedtls_ecp_group_id *gid;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
/* Match our preference list against the offered curves */
@@ -3065,7 +3230,7 @@
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
@@ -3074,7 +3239,7 @@
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 */
/*
*
@@ -3082,13 +3247,13 @@
* 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;
size_t hashlen = 0;
unsigned char hash[MBEDTLS_MD_MAX_SIZE];
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/*
* 2.1: Choose hash algorithm:
@@ -3250,7 +3415,7 @@
return( ret );
}
}
-#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */
return( 0 );
}
@@ -3261,28 +3426,28 @@
* machine. */
static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
{
- int ret;
+ 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->transform_negotiate->ciphersuite_info;
-#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */
+ ssl->handshake->ciphersuite_info;
+#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. */
@@ -3290,9 +3455,9 @@
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. */
@@ -3302,7 +3467,7 @@
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. */
@@ -3325,7 +3490,7 @@
/* 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 );
@@ -3338,7 +3503,7 @@
/* 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;
@@ -3358,7 +3523,7 @@
static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) );
@@ -3462,7 +3627,7 @@
size_t *peer_pmslen,
size_t peer_pmssize )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl );
mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk;
size_t len = mbedtls_pk_get_len( public_key );
@@ -3551,7 +3716,7 @@
const unsigned char *end,
size_t pms_offset )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *pms = ssl->handshake->premaster + pms_offset;
unsigned char ver[2];
unsigned char fake_pms[48], peer_pms[48];
@@ -3642,16 +3807,14 @@
#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->f_psk == NULL &&
- ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL ||
- ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) )
+ if( ssl_conf_has_psk_or_cb( ssl->conf ) == 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) );
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
@@ -3669,7 +3832,7 @@
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 );
@@ -3703,15 +3866,15 @@
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 )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
unsigned char *p, *end;
- ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+ ciphersuite_info = ssl->handshake->ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) );
@@ -3831,6 +3994,13 @@
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
}
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ /* For opaque PSKs, we perform the PSK-to-MS derivation atomatically
+ * and skip the intermediate PMS. */
+ if( ssl_use_opaque_psk( ssl ) == 1 )
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "skip PMS generation for opaque PSK" ) );
+ else
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl,
ciphersuite_info->key_exchange ) ) != 0 )
{
@@ -3862,6 +4032,12 @@
return( ret );
}
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ /* Opaque PSKs are currently only supported for PSK-only. */
+ if( ssl_use_opaque_psk( ssl ) == 1 )
+ return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+#endif
+
if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret );
@@ -3891,6 +4067,12 @@
return( ret );
}
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ /* Opaque PSKs are currently only supported for PSK-only. */
+ if( ssl_use_opaque_psk( ssl ) == 1 )
+ return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+#endif
+
if( p != end )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) );
@@ -3922,6 +4104,12 @@
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP );
}
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ /* Opaque PSKs are currently only supported for PSK-only. */
+ if( ssl_use_opaque_psk( ssl ) == 1 )
+ return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+#endif
+
MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
MBEDTLS_DEBUG_ECDH_QP );
@@ -3985,24 +4173,15 @@
return( 0 );
}
-#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
- !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
- !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
- !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
- !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \
- !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_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 =
- ssl->transform_negotiate->ciphersuite_info;
+ ssl->handshake->ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
- 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_ECDHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
+ if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
ssl->state++;
@@ -4012,7 +4191,7 @@
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
-#else
+#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;
@@ -4025,22 +4204,34 @@
#endif
mbedtls_md_type_t md_alg;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
- ssl->transform_negotiate->ciphersuite_info;
+ ssl->handshake->ciphersuite_info;
+ mbedtls_pk_context * peer_pk;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
- 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_ECDHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
- ssl->session_negotiate->peer_cert == NULL )
+ if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
ssl->state++;
return( 0 );
}
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ if( ssl->session_negotiate->peer_cert == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
+ ssl->state++;
+ return( 0 );
+ }
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+ if( ssl->session_negotiate->peer_cert_digest == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
+ ssl->state++;
+ return( 0 );
+ }
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
/* Read the message without adding it to the checksum */
ret = mbedtls_ssl_read_record( ssl, 0 /* no checksum update */ );
if( 0 != ret )
@@ -4061,6 +4252,17 @@
i = mbedtls_ssl_hs_hdr_len( ssl );
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ peer_pk = &ssl->handshake->peer_pubkey;
+#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+ if( ssl->session_negotiate->peer_cert == NULL )
+ {
+ /* Should never happen */
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+ peer_pk = &ssl->session_negotiate->peer_cert->pk;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
/*
* struct {
* SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only
@@ -4075,8 +4277,7 @@
hashlen = 36;
/* For ECDSA, use SHA-1, not MD-5 + SHA-1 */
- if( mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk,
- MBEDTLS_PK_ECDSA ) )
+ if( mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_ECDSA ) )
{
hash_start += 16;
hashlen -= 16;
@@ -4131,7 +4332,7 @@
/*
* Check the certificate's key type matches the signature alg
*/
- if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) )
+ if( !mbedtls_pk_can_do( peer_pk, pk_alg ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
@@ -4162,9 +4363,12 @@
}
/* Calculate hash and verify signature */
- ssl->handshake->calc_verify( ssl, hash );
+ {
+ size_t dummy_hlen;
+ ssl->handshake->calc_verify( ssl, hash, &dummy_hlen );
+ }
- if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk,
+ if( ( ret = mbedtls_pk_verify( peer_pk,
md_alg, hash_start, hashlen,
ssl->in_msg + i, sig_len ) ) != 0 )
{
@@ -4178,17 +4382,12 @@
return( ret );
}
-#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED &&
- !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED &&
- !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED &&
- !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
- !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED &&
- !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_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 )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t tlen;
uint32_t lifetime;
diff --git a/lib/libmbedtls/mbedtls/library/ssl_ticket.c b/lib/libmbedtls/mbedtls/library/ssl_ticket.c
index 0db5479..ddc88db 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_ticket.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_ticket.c
@@ -36,6 +36,7 @@
#endif
#include "mbedtls/ssl_ticket.h"
+#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include <string.h>
@@ -54,13 +55,26 @@
#define MAX_KEY_BYTES 32 /* 256 bits */
+#define TICKET_KEY_NAME_BYTES 4
+#define TICKET_IV_BYTES 12
+#define TICKET_CRYPT_LEN_BYTES 2
+#define TICKET_AUTH_TAG_BYTES 16
+
+#define TICKET_MIN_LEN ( TICKET_KEY_NAME_BYTES + \
+ TICKET_IV_BYTES + \
+ TICKET_CRYPT_LEN_BYTES + \
+ TICKET_AUTH_TAG_BYTES )
+#define TICKET_ADD_DATA_LEN ( TICKET_KEY_NAME_BYTES + \
+ TICKET_IV_BYTES + \
+ TICKET_CRYPT_LEN_BYTES )
+
/*
* Generate/update a key
*/
static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx,
unsigned char index )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char buf[MAX_KEY_BYTES];
mbedtls_ssl_ticket_key *key = ctx->keys + index;
@@ -120,7 +134,7 @@
mbedtls_cipher_type_t cipher,
uint32_t lifetime )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_cipher_info_t *cipher_info;
ctx->f_rng = f_rng;
@@ -141,11 +155,27 @@
if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 ||
- ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 )
- {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ ret = mbedtls_cipher_setup_psa( &ctx->keys[0].ctx,
+ cipher_info, TICKET_AUTH_TAG_BYTES );
+ if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
return( ret );
- }
+ /* We don't yet expect to support all ciphers through PSA,
+ * so allow fallback to ordinary mbedtls_cipher_setup(). */
+ if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+ if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 )
+ return( ret );
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ ret = mbedtls_cipher_setup_psa( &ctx->keys[1].ctx,
+ cipher_info, TICKET_AUTH_TAG_BYTES );
+ if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
+ return( ret );
+ if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+ if( ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 )
+ return( ret );
if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 ||
( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 )
@@ -157,115 +187,6 @@
}
/*
- * Serialize a session in the following format:
- * 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session)
- * n . n+2 peer_cert length = m (0 if no certificate)
- * n+3 . n+2+m peer cert ASN.1
- */
-static int ssl_save_session( const mbedtls_ssl_session *session,
- unsigned char *buf, size_t buf_len,
- size_t *olen )
-{
- unsigned char *p = buf;
- size_t left = buf_len;
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
- size_t cert_len;
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
-
- if( left < sizeof( mbedtls_ssl_session ) )
- return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
-
- memcpy( p, session, sizeof( mbedtls_ssl_session ) );
- p += sizeof( mbedtls_ssl_session );
- left -= sizeof( mbedtls_ssl_session );
-
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
- if( session->peer_cert == NULL )
- cert_len = 0;
- else
- cert_len = session->peer_cert->raw.len;
-
- if( left < 3 + cert_len )
- return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
-
- *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF );
- *p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF );
- *p++ = (unsigned char)( ( cert_len ) & 0xFF );
-
- if( session->peer_cert != NULL )
- memcpy( p, session->peer_cert->raw.p, cert_len );
-
- p += cert_len;
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
-
- *olen = p - buf;
-
- return( 0 );
-}
-
-/*
- * Unserialise session, see ssl_save_session()
- */
-static int ssl_load_session( mbedtls_ssl_session *session,
- const unsigned char *buf, size_t len )
-{
- const unsigned char *p = buf;
- const unsigned char * const end = buf + len;
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
- size_t cert_len;
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
-
- if( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) )
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
- memcpy( session, p, sizeof( mbedtls_ssl_session ) );
- p += sizeof( mbedtls_ssl_session );
-
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
- 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 )
- {
- session->peer_cert = NULL;
- }
- else
- {
- int ret;
-
- 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;
- }
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
-
- if( p != end )
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
- return( 0 );
-}
-
-/*
* Create session ticket, with the following structure:
*
* struct {
@@ -278,6 +199,7 @@
* The key_name, iv, and length of encrypted_state are the additional
* authenticated data.
*/
+
int mbedtls_ssl_ticket_write( void *p_ticket,
const mbedtls_ssl_session *session,
unsigned char *start,
@@ -285,13 +207,13 @@
size_t *tlen,
uint32_t *ticket_lifetime )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ssl_ticket_context *ctx = p_ticket;
mbedtls_ssl_ticket_key *key;
unsigned char *key_name = start;
- unsigned char *iv = start + 4;
- unsigned char *state_len_bytes = iv + 12;
- unsigned char *state = state_len_bytes + 2;
+ unsigned char *iv = start + TICKET_KEY_NAME_BYTES;
+ unsigned char *state_len_bytes = iv + TICKET_IV_BYTES;
+ unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES;
unsigned char *tag;
size_t clear_len, ciph_len;
@@ -302,7 +224,7 @@
/* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag,
* in addition to session itself, that will be checked when writing it. */
- if( end - start < 4 + 12 + 2 + 16 )
+ if( end - start < TICKET_MIN_LEN )
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
#if defined(MBEDTLS_THREADING_C)
@@ -317,14 +239,15 @@
*ticket_lifetime = ctx->ticket_lifetime;
- memcpy( key_name, key->name, 4 );
+ memcpy( key_name, key->name, TICKET_KEY_NAME_BYTES );
- if( ( ret = ctx->f_rng( ctx->p_rng, iv, 12 ) ) != 0 )
+ if( ( ret = ctx->f_rng( ctx->p_rng, iv, TICKET_IV_BYTES ) ) != 0 )
goto cleanup;
/* Dump session state */
- if( ( ret = ssl_save_session( session,
- state, end - state, &clear_len ) ) != 0 ||
+ if( ( ret = mbedtls_ssl_session_save( session,
+ state, end - state,
+ &clear_len ) ) != 0 ||
(unsigned long) clear_len > 65535 )
{
goto cleanup;
@@ -335,8 +258,11 @@
/* Encrypt and authenticate */
tag = state + clear_len;
if( ( ret = mbedtls_cipher_auth_encrypt( &key->ctx,
- iv, 12, key_name, 4 + 12 + 2,
- state, clear_len, state, &ciph_len, tag, 16 ) ) != 0 )
+ iv, TICKET_IV_BYTES,
+ /* Additional data: key name, IV and length */
+ key_name, TICKET_ADD_DATA_LEN,
+ state, clear_len, state, &ciph_len,
+ tag, TICKET_AUTH_TAG_BYTES ) ) != 0 )
{
goto cleanup;
}
@@ -346,7 +272,7 @@
goto cleanup;
}
- *tlen = 4 + 12 + 2 + 16 + ciph_len;
+ *tlen = TICKET_MIN_LEN + ciph_len;
cleanup:
#if defined(MBEDTLS_THREADING_C)
@@ -381,21 +307,20 @@
unsigned char *buf,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ssl_ticket_context *ctx = p_ticket;
mbedtls_ssl_ticket_key *key;
unsigned char *key_name = buf;
- unsigned char *iv = buf + 4;
- unsigned char *enc_len_p = iv + 12;
- unsigned char *ticket = enc_len_p + 2;
+ unsigned char *iv = buf + TICKET_KEY_NAME_BYTES;
+ unsigned char *enc_len_p = iv + TICKET_IV_BYTES;
+ unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES;
unsigned char *tag;
size_t enc_len, clear_len;
if( ctx == NULL || ctx->f_rng == NULL )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- /* See mbedtls_ssl_ticket_write() */
- if( len < 4 + 12 + 2 + 16 )
+ if( len < TICKET_MIN_LEN )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
#if defined(MBEDTLS_THREADING_C)
@@ -409,7 +334,7 @@
enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1];
tag = ticket + enc_len;
- if( len != 4 + 12 + 2 + enc_len + 16 )
+ if( len != TICKET_MIN_LEN + enc_len )
{
ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
goto cleanup;
@@ -425,9 +350,13 @@
}
/* Decrypt and authenticate */
- if( ( ret = mbedtls_cipher_auth_decrypt( &key->ctx, iv, 12,
- key_name, 4 + 12 + 2, ticket, enc_len,
- ticket, &clear_len, tag, 16 ) ) != 0 )
+ if( ( ret = mbedtls_cipher_auth_decrypt( &key->ctx,
+ iv, TICKET_IV_BYTES,
+ /* Additional data: key name, IV and length */
+ key_name, TICKET_ADD_DATA_LEN,
+ ticket, enc_len,
+ ticket, &clear_len,
+ tag, TICKET_AUTH_TAG_BYTES ) ) != 0 )
{
if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED )
ret = MBEDTLS_ERR_SSL_INVALID_MAC;
@@ -441,7 +370,7 @@
}
/* Actually load session */
- if( ( ret = ssl_load_session( session, ticket, clear_len ) ) != 0 )
+ if( ( ret = mbedtls_ssl_session_load( session, ticket, clear_len ) ) != 0 )
goto cleanup;
#if defined(MBEDTLS_HAVE_TIME)
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls.c b/lib/libmbedtls/mbedtls/library/ssl_tls.c
index 9b633b7..e2bdfd5 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_tls.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls.c
@@ -43,202 +43,119 @@
#define mbedtls_free free
#endif
-#include "mbedtls/debug.h"
#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 <string.h>
+#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 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,
- mbedtls_ssl_transform *transform );
-
-#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( 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 );
-static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl );
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+/* Top-level Connection ID API */
-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 )
+int mbedtls_ssl_conf_cid( mbedtls_ssl_config *conf,
+ size_t len,
+ int ignore_other_cid )
{
- size_t mtu = ssl_get_current_mtu( ssl );
+ if( len > MBEDTLS_SSL_CID_IN_LEN_MAX )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- 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 )
+ if( ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_FAIL &&
+ ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_IGNORE )
{
- /* Should never happen... */
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
- return( (int) ( mtu - bytes_written ) );
+ conf->ignore_unexpected_cid = ignore_other_cid;
+ conf->cid_len = len;
+ return( 0 );
}
-static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl )
+int mbedtls_ssl_set_cid( mbedtls_ssl_context *ssl,
+ int enable,
+ unsigned char const *own_cid,
+ size_t own_cid_len )
{
- int ret;
- size_t remaining, expansion;
- size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
+ if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-#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 )
+ ssl->negotiate_cid = enable;
+ if( enable == MBEDTLS_SSL_CID_DISABLED )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Disable use of CID extension." ) );
return( 0 );
+ }
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Enable use of CID extension." ) );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "Own CID", own_cid, own_cid_len );
- 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 )
+ if( own_cid_len != ssl->conf->cid_len )
{
- ssl->handshake->mtu = 508;
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) );
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "CID length %u does not match CID length %u in config",
+ (unsigned) own_cid_len,
+ (unsigned) ssl->conf->cid_len ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
- 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 ) );
+ memcpy( ssl->own_cid, own_cid, own_cid_len );
+ /* Truncation is not an issue here because
+ * MBEDTLS_SSL_CID_IN_LEN_MAX at most 255. */
+ ssl->own_cid_len = (uint8_t) own_cid_len;
return( 0 );
}
-static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_get_peer_cid( mbedtls_ssl_context *ssl,
+ int *enabled,
+ unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ],
+ size_t *peer_cid_len )
{
- ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min;
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs",
- ssl->handshake->retransmit_timeout ) );
+ *enabled = MBEDTLS_SSL_CID_DISABLED;
+
+ if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
+ ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+ {
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+ /* We report MBEDTLS_SSL_CID_DISABLED in case the CID extensions
+ * were used, but client and server requested the empty CID.
+ * This is indistinguishable from not using the CID extension
+ * in the first place. */
+ if( ssl->transform_in->in_cid_len == 0 &&
+ ssl->transform_in->out_cid_len == 0 )
+ {
+ return( 0 );
+ }
+
+ if( peer_cid_len != NULL )
+ {
+ *peer_cid_len = ssl->transform_in->out_cid_len;
+ if( peer_cid != NULL )
+ {
+ memcpy( peer_cid, ssl->transform_in->out_cid,
+ ssl->transform_in->out_cid_len );
+ }
+ }
+
+ *enabled = MBEDTLS_SSL_CID_ENABLED;
+
+ return( 0 );
}
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
#endif /* MBEDTLS_SSL_PROTO_DTLS */
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
@@ -270,16 +187,18 @@
}
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
-#if defined(MBEDTLS_SSL_CLI_C)
-static int ssl_session_copy( mbedtls_ssl_session *dst, const mbedtls_ssl_session *src )
+int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst,
+ const mbedtls_ssl_session *src )
{
mbedtls_ssl_session_free( dst );
memcpy( dst, src, sizeof( mbedtls_ssl_session ) );
#if defined(MBEDTLS_X509_CRT_PARSE_C)
+
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
if( src->peer_cert != NULL )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
dst->peer_cert = mbedtls_calloc( 1, sizeof(mbedtls_x509_crt) );
if( dst->peer_cert == NULL )
@@ -295,6 +214,21 @@
return( ret );
}
}
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+ if( src->peer_cert_digest != NULL )
+ {
+ dst->peer_cert_digest =
+ mbedtls_calloc( 1, src->peer_cert_digest_len );
+ if( dst->peer_cert_digest == NULL )
+ return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+
+ memcpy( dst->peer_cert_digest, src->peer_cert_digest,
+ src->peer_cert_digest_len );
+ dst->peer_cert_digest_type = src->peer_cert_digest_type;
+ dst->peer_cert_digest_len = src->peer_cert_digest_len;
+ }
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
@@ -310,22 +244,29 @@
return( 0 );
}
-#endif /* MBEDTLS_SSL_CLI_C */
-#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
@@ -400,16 +341,22 @@
size_t nb, hs;
size_t i, j, k;
const unsigned char *S1, *S2;
- unsigned char tmp[128];
+ unsigned char *tmp;
+ size_t tmp_len = 0;
unsigned char h_i[20];
const mbedtls_md_info_t *md_info;
mbedtls_md_context_t md_ctx;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_init( &md_ctx );
- if( sizeof( tmp ) < 20 + strlen( label ) + rlen )
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ tmp_len = 20 + strlen( label ) + rlen;
+ tmp = mbedtls_calloc( 1, tmp_len );
+ if( tmp == NULL )
+ {
+ ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ goto exit;
+ }
hs = ( slen + 1 ) / 2;
S1 = secret;
@@ -424,10 +371,15 @@
* First compute P_md5(secret,label+random)[0..dlen]
*/
if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ) ) == NULL )
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ {
+ ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+ goto exit;
+ }
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
- return( ret );
+ {
+ goto exit;
+ }
mbedtls_md_hmac_starts( &md_ctx, S1, hs );
mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb );
@@ -455,10 +407,15 @@
* XOR out with P_sha1(secret,label+random)[0..dlen]
*/
if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL )
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ {
+ ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+ goto exit;
+ }
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
- return( ret );
+ {
+ goto exit;
+ }
mbedtls_md_hmac_starts( &md_ctx, S2, hs );
mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb );
@@ -480,16 +437,148 @@
dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] );
}
+exit:
mbedtls_md_free( &md_ctx );
- mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
+ mbedtls_platform_zeroize( tmp, tmp_len );
mbedtls_platform_zeroize( h_i, sizeof( h_i ) );
- return( 0 );
+ mbedtls_free( tmp );
+ return( ret );
}
#endif /* MBEDTLS_SSL_PROTO_TLS1) || MBEDTLS_SSL_PROTO_TLS1_1 */
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+
+static psa_status_t setup_psa_key_derivation( psa_key_derivation_operation_t* derivation,
+ psa_key_handle_t slot,
+ psa_algorithm_t alg,
+ const unsigned char* seed, size_t seed_length,
+ const unsigned char* label, size_t label_length,
+ size_t capacity )
+{
+ psa_status_t status;
+
+ status = psa_key_derivation_setup( derivation, alg );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ if( PSA_ALG_IS_TLS12_PRF( alg ) || PSA_ALG_IS_TLS12_PSK_TO_MS( alg ) )
+ {
+ status = psa_key_derivation_input_bytes( derivation,
+ PSA_KEY_DERIVATION_INPUT_SEED,
+ seed, seed_length );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ if( slot == 0 )
+ {
+ status = psa_key_derivation_input_bytes(
+ derivation, PSA_KEY_DERIVATION_INPUT_SECRET,
+ NULL, 0 );
+ }
+ else
+ {
+ status = psa_key_derivation_input_key(
+ derivation, PSA_KEY_DERIVATION_INPUT_SECRET,
+ slot );
+ }
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ status = psa_key_derivation_input_bytes( derivation,
+ PSA_KEY_DERIVATION_INPUT_LABEL,
+ label, label_length );
+ if( status != PSA_SUCCESS )
+ return( status );
+ }
+ else
+ {
+ return( PSA_ERROR_NOT_SUPPORTED );
+ }
+
+ status = psa_key_derivation_set_capacity( derivation, capacity );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ return( PSA_SUCCESS );
+}
+
+static int tls_prf_generic( mbedtls_md_type_t md_type,
+ const unsigned char *secret, size_t slen,
+ const char *label,
+ const unsigned char *random, size_t rlen,
+ unsigned char *dstbuf, size_t dlen )
+{
+ psa_status_t status;
+ psa_algorithm_t alg;
+ psa_key_handle_t master_slot = 0;
+ psa_key_derivation_operation_t derivation =
+ PSA_KEY_DERIVATION_OPERATION_INIT;
+
+ if( md_type == MBEDTLS_MD_SHA384 )
+ alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384);
+ else
+ alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256);
+
+ /* Normally a "secret" should be long enough to be impossible to
+ * find by brute force, and in particular should not be empty. But
+ * this PRF is also used to derive an IV, in particular in EAP-TLS,
+ * and for this use case it makes sense to have a 0-length "secret".
+ * Since the key API doesn't allow importing a key of length 0,
+ * keep master_slot=0, which setup_psa_key_derivation() understands
+ * to mean a 0-length "secret" input. */
+ if( slen != 0 )
+ {
+ psa_key_attributes_t key_attributes = psa_key_attributes_init();
+ psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_DERIVE );
+ psa_set_key_algorithm( &key_attributes, alg );
+ psa_set_key_type( &key_attributes, PSA_KEY_TYPE_DERIVE );
+
+ status = psa_import_key( &key_attributes, secret, slen, &master_slot );
+ if( status != PSA_SUCCESS )
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ }
+
+ status = setup_psa_key_derivation( &derivation,
+ master_slot, alg,
+ random, rlen,
+ (unsigned char const *) label,
+ (size_t) strlen( label ),
+ dlen );
+ if( status != PSA_SUCCESS )
+ {
+ psa_key_derivation_abort( &derivation );
+ psa_destroy_key( master_slot );
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ }
+
+ status = psa_key_derivation_output_bytes( &derivation, dstbuf, dlen );
+ if( status != PSA_SUCCESS )
+ {
+ psa_key_derivation_abort( &derivation );
+ psa_destroy_key( master_slot );
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ }
+
+ status = psa_key_derivation_abort( &derivation );
+ if( status != PSA_SUCCESS )
+ {
+ psa_destroy_key( master_slot );
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ }
+
+ if( master_slot != 0 )
+ status = psa_destroy_key( master_slot );
+ if( status != PSA_SUCCESS )
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+
+ return( 0 );
+}
+
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+
static int tls_prf_generic( mbedtls_md_type_t md_type,
const unsigned char *secret, size_t slen,
const char *label,
@@ -498,11 +587,12 @@
{
size_t nb;
size_t i, j, k, md_len;
- unsigned char tmp[128];
+ unsigned char *tmp;
+ size_t tmp_len = 0;
unsigned char h_i[MBEDTLS_MD_MAX_SIZE];
const mbedtls_md_info_t *md_info;
mbedtls_md_context_t md_ctx;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_init( &md_ctx );
@@ -511,8 +601,13 @@
md_len = mbedtls_md_get_size( md_info );
- if( sizeof( tmp ) < md_len + strlen( label ) + rlen )
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ tmp_len = md_len + strlen( label ) + rlen;
+ tmp = mbedtls_calloc( 1, tmp_len );
+ if( tmp == NULL )
+ {
+ ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ goto exit;
+ }
nb = strlen( label );
memcpy( tmp + md_len, label, nb );
@@ -523,7 +618,7 @@
* Compute P_<hash>(secret, label + random)[0..dlen]
*/
if ( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
- return( ret );
+ goto exit;
mbedtls_md_hmac_starts( &md_ctx, secret, slen );
mbedtls_md_hmac_update( &md_ctx, tmp + md_len, nb );
@@ -545,14 +640,17 @@
dstbuf[i + j] = h_i[j];
}
+exit:
mbedtls_md_free( &md_ctx );
- mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
+ mbedtls_platform_zeroize( tmp, tmp_len );
mbedtls_platform_zeroize( h_i, sizeof( h_i ) );
- return( 0 );
-}
+ mbedtls_free( tmp );
+ return( ret );
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_SHA256_C)
static int tls_prf_sha256( const unsigned char *secret, size_t slen,
const char *label,
@@ -584,33 +682,182 @@
#endif
#if defined(MBEDTLS_SSL_PROTO_SSL3)
-static void ssl_calc_verify_ssl( mbedtls_ssl_context *, unsigned char * );
+static void ssl_calc_verify_ssl( const mbedtls_ssl_context *, unsigned char *, size_t * );
static void ssl_calc_finished_ssl( mbedtls_ssl_context *, unsigned char *, int );
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
-static void ssl_calc_verify_tls( mbedtls_ssl_context *, unsigned char * );
+static void ssl_calc_verify_tls( const mbedtls_ssl_context *, unsigned char *, size_t * );
static void ssl_calc_finished_tls( mbedtls_ssl_context *, unsigned char *, int );
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
#if defined(MBEDTLS_SHA256_C)
static void ssl_update_checksum_sha256( mbedtls_ssl_context *, const unsigned char *, size_t );
-static void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *,unsigned char * );
+static void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *,unsigned char *, size_t * );
static void ssl_calc_finished_tls_sha256( mbedtls_ssl_context *,unsigned char *, int );
#endif
#if defined(MBEDTLS_SHA512_C)
static void ssl_update_checksum_sha384( mbedtls_ssl_context *, const unsigned char *, size_t );
-static void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *, unsigned char * );
+static void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *, unsigned char *, size_t * );
static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *, int );
#endif
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
+#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) && \
+ defined(MBEDTLS_USE_PSA_CRYPTO)
+static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl )
+{
+ if( ssl->conf->f_psk != NULL )
+ {
+ /* If we've used a callback to select the PSK,
+ * the static configuration is irrelevant. */
+ if( ssl->handshake->psk_opaque != 0 )
+ return( 1 );
+
+ return( 0 );
+ }
+
+ if( ssl->conf->psk_opaque != 0 )
+ return( 1 );
+
+ return( 0 );
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO &&
+ MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
+
+#if defined(MBEDTLS_SSL_EXPORT_KEYS)
+static mbedtls_tls_prf_types tls_prf_get_type( mbedtls_ssl_tls_prf_cb *tls_prf )
+{
+#if defined(MBEDTLS_SSL_PROTO_SSL3)
+ if( tls_prf == ssl3_prf )
+ {
+ return( MBEDTLS_SSL_TLS_PRF_SSL3 );
+ }
+ else
+#endif
+#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
+ if( tls_prf == tls1_prf )
+ {
+ return( MBEDTLS_SSL_TLS_PRF_TLS1 );
+ }
+ else
+#endif
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#if defined(MBEDTLS_SHA512_C)
+ if( tls_prf == tls_prf_sha384 )
+ {
+ return( MBEDTLS_SSL_TLS_PRF_SHA384 );
+ }
+ else
+#endif
+#if defined(MBEDTLS_SHA256_C)
+ if( tls_prf == tls_prf_sha256 )
+ {
+ return( MBEDTLS_SSL_TLS_PRF_SHA256 );
+ }
+ else
+#endif
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+ return( MBEDTLS_SSL_TLS_PRF_NONE );
+}
+#endif /* MBEDTLS_SSL_EXPORT_KEYS */
+
+int mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf,
+ const unsigned char *secret, size_t slen,
+ const char *label,
+ const unsigned char *random, size_t rlen,
+ unsigned char *dstbuf, size_t dlen )
+{
+ mbedtls_ssl_tls_prf_cb *tls_prf = NULL;
+
+ switch( prf )
+ {
+#if defined(MBEDTLS_SSL_PROTO_SSL3)
+ case MBEDTLS_SSL_TLS_PRF_SSL3:
+ tls_prf = ssl3_prf;
+ break;
+#endif /* MBEDTLS_SSL_PROTO_SSL3 */
+#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
+ case MBEDTLS_SSL_TLS_PRF_TLS1:
+ tls_prf = tls1_prf;
+ break;
+#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#if defined(MBEDTLS_SHA512_C)
+ case MBEDTLS_SSL_TLS_PRF_SHA384:
+ tls_prf = tls_prf_sha384;
+ break;
+#endif /* MBEDTLS_SHA512_C */
+#if defined(MBEDTLS_SHA256_C)
+ case MBEDTLS_SSL_TLS_PRF_SHA256:
+ tls_prf = tls_prf_sha256;
+ break;
+#endif /* MBEDTLS_SHA256_C */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+ default:
+ return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+
+ return( tls_prf( secret, slen, label, random, rlen, dstbuf, dlen ) );
+}
+
+/* Type for the TLS PRF */
+typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *,
+ const unsigned char *, size_t,
+ unsigned char *, size_t);
+
+/*
+ * Populate a transform structure with session keys and all the other
+ * necessary information.
+ *
+ * Parameters:
+ * - [in/out]: transform: structure to populate
+ * [in] must be just initialised with mbedtls_ssl_transform_init()
+ * [out] fully populated, ready for use by mbedtls_ssl_{en,de}crypt_buf()
+ * - [in] ciphersuite
+ * - [in] master
+ * - [in] encrypt_then_mac
+ * - [in] trunc_hmac
+ * - [in] compression
+ * - [in] tls_prf: pointer to PRF to use for key derivation
+ * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random
+ * - [in] minor_ver: SSL/TLS minor version
+ * - [in] endpoint: client or server
+ * - [in] ssl: optionally used for:
+ * - 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
+ */
+static int ssl_populate_transform( mbedtls_ssl_transform *transform,
+ int ciphersuite,
+ const unsigned char master[48],
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+ int encrypt_then_mac,
+#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
+#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
+ int trunc_hmac,
+#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
+#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
+#if defined(MBEDTLS_ZLIB_SUPPORT)
+ int compression,
+#endif
+ ssl_tls_prf_t tls_prf,
+ const unsigned char randbytes[64],
+ int minor_ver,
+ unsigned endpoint,
+#if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
+ const
+#endif
+ mbedtls_ssl_context *ssl )
{
int ret = 0;
- unsigned char tmp[64];
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ int psa_fallthrough;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
unsigned char keyblk[256];
unsigned char *key1;
unsigned char *key2;
@@ -618,173 +865,82 @@
unsigned char *mac_dec;
size_t mac_key_len;
size_t iv_copy_len;
+ unsigned keylen;
+ const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
const mbedtls_cipher_info_t *cipher_info;
const mbedtls_md_info_t *md_info;
- mbedtls_ssl_session *session = ssl->session_negotiate;
- mbedtls_ssl_transform *transform = ssl->transform_negotiate;
- mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+#if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL) && \
+ !defined(MBEDTLS_SSL_EXPORT_KEYS) && \
+ !defined(MBEDTLS_DEBUG_C)
+ ssl = NULL; /* make sure we don't use it except for those cases */
+ (void) ssl;
+#endif
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> derive keys" ) );
+ /*
+ * Some data just needs copying into the structure
+ */
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \
+ defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
+ transform->encrypt_then_mac = encrypt_then_mac;
+#endif
+ transform->minor_ver = minor_ver;
- cipher_info = mbedtls_cipher_info_from_type( transform->ciphersuite_info->cipher );
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+ memcpy( transform->randbytes, randbytes, sizeof( transform->randbytes ) );
+#endif
+
+ /*
+ * Get various info structures
+ */
+ ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite );
+ if( ciphersuite_info == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %d not found",
+ ciphersuite ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+ cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
if( cipher_info == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %d not found",
- transform->ciphersuite_info->cipher ) );
+ ciphersuite_info->cipher ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
- md_info = mbedtls_md_info_from_type( transform->ciphersuite_info->mac );
+ md_info = mbedtls_md_info_from_type( ciphersuite_info->mac );
if( md_info == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %d not found",
- transform->ciphersuite_info->mac ) );
+ ciphersuite_info->mac ) );
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
- /*
- * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions
- */
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ /* Copy own and peer's CID if the use of the CID
+ * extension has been negotiated. */
+ if( ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_ENABLED )
{
- handshake->tls_prf = ssl3_prf;
- handshake->calc_verify = ssl_calc_verify_ssl;
- handshake->calc_finished = ssl_calc_finished_ssl;
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Copy CIDs into SSL transform" ) );
+
+ transform->in_cid_len = ssl->own_cid_len;
+ memcpy( transform->in_cid, ssl->own_cid, ssl->own_cid_len );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "Incoming CID", transform->in_cid,
+ transform->in_cid_len );
+
+ transform->out_cid_len = ssl->handshake->peer_cid_len;
+ memcpy( transform->out_cid, ssl->handshake->peer_cid,
+ ssl->handshake->peer_cid_len );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "Outgoing CID", transform->out_cid,
+ transform->out_cid_len );
}
- else
-#endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
- if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 )
- {
- handshake->tls_prf = tls1_prf;
- handshake->calc_verify = ssl_calc_verify_tls;
- handshake->calc_finished = ssl_calc_finished_tls;
- }
- else
-#endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_SHA512_C)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 &&
- transform->ciphersuite_info->mac == MBEDTLS_MD_SHA384 )
- {
- handshake->tls_prf = tls_prf_sha384;
- handshake->calc_verify = ssl_calc_verify_tls_sha384;
- handshake->calc_finished = ssl_calc_finished_tls_sha384;
- }
- else
-#endif
-#if defined(MBEDTLS_SHA256_C)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
- {
- handshake->tls_prf = tls_prf_sha256;
- handshake->calc_verify = ssl_calc_verify_tls_sha256;
- handshake->calc_finished = ssl_calc_finished_tls_sha256;
- }
- else
-#endif
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
/*
- * SSLv3:
- * master =
- * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) +
- * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) +
- * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) )
- *
- * TLSv1+:
- * master = PRF( premaster, "master secret", randbytes )[0..47]
+ * Compute key block using the PRF
*/
- if( handshake->resume == 0 )
- {
- MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster,
- handshake->pmslen );
-
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
- if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED )
- {
- unsigned char session_hash[48];
- size_t hash_len;
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) );
-
- ssl->handshake->calc_verify( ssl, session_hash );
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
- {
-#if defined(MBEDTLS_SHA512_C)
- if( ssl->transform_negotiate->ciphersuite_info->mac ==
- MBEDTLS_MD_SHA384 )
- {
- hash_len = 48;
- }
- else
-#endif
- hash_len = 32;
- }
- else
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
- hash_len = 36;
-
- MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, hash_len );
-
- ret = handshake->tls_prf( handshake->premaster, handshake->pmslen,
- "extended master secret",
- session_hash, hash_len,
- session->master, 48 );
- if( ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret );
- return( ret );
- }
-
- }
- else
-#endif
- ret = handshake->tls_prf( handshake->premaster, handshake->pmslen,
- "master secret",
- handshake->randbytes, 64,
- session->master, 48 );
- if( ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret );
- return( ret );
- }
-
- mbedtls_platform_zeroize( handshake->premaster,
- sizeof(handshake->premaster) );
- }
- else
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) );
-
- /*
- * Swap the client and server random values.
- */
- memcpy( tmp, handshake->randbytes, 64 );
- memcpy( handshake->randbytes, tmp + 32, 32 );
- memcpy( handshake->randbytes + 32, tmp, 32 );
- mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
-
- /*
- * SSLv3:
- * key block =
- * MD5( master + SHA1( 'A' + master + randbytes ) ) +
- * MD5( master + SHA1( 'BB' + master + randbytes ) ) +
- * MD5( master + SHA1( 'CCC' + master + randbytes ) ) +
- * MD5( master + SHA1( 'DDDD' + master + randbytes ) ) +
- * ...
- *
- * TLSv1:
- * key block = PRF( master, "key expansion", randbytes )
- */
- ret = handshake->tls_prf( session->master, 48, "key expansion",
- handshake->randbytes, 64, keyblk, 256 );
+ ret = tls_prf( master, 48, "key expansion", randbytes, 64, keyblk, 256 );
if( ret != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret );
@@ -792,28 +948,30 @@
}
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s",
- mbedtls_ssl_get_ciphersuite_name( session->ciphersuite ) ) );
- MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", session->master, 48 );
- MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 );
+ mbedtls_ssl_get_ciphersuite_name( ciphersuite ) ) );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", master, 48 );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", randbytes, 64 );
MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 );
- mbedtls_platform_zeroize( handshake->randbytes,
- sizeof( handshake->randbytes ) );
-
/*
* Determine the appropriate key, IV and MAC length.
*/
- transform->keylen = cipher_info->key_bitlen / 8;
+ keylen = cipher_info->key_bitlen / 8;
+#if defined(MBEDTLS_GCM_C) || \
+ defined(MBEDTLS_CCM_C) || \
+ defined(MBEDTLS_CHACHAPOLY_C)
if( cipher_info->mode == MBEDTLS_MODE_GCM ||
cipher_info->mode == MBEDTLS_MODE_CCM ||
cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY )
{
- size_t taglen, explicit_ivlen;
+ size_t explicit_ivlen;
transform->maclen = 0;
mac_key_len = 0;
+ transform->taglen =
+ ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
/* All modes haves 96-bit IVs;
* GCM and CCM has 4 implicit and 8 explicit bytes
@@ -825,23 +983,22 @@
else
transform->fixed_ivlen = 4;
- /* All modes have 128-bit tags, except CCM_8 (ciphersuite flag) */
- taglen = transform->ciphersuite_info->flags &
- MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
-
-
/* Minimum length of encrypted record */
explicit_ivlen = transform->ivlen - transform->fixed_ivlen;
- transform->minlen = explicit_ivlen + taglen;
+ transform->minlen = explicit_ivlen + transform->taglen;
}
else
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
+ if( cipher_info->mode == MBEDTLS_MODE_STREAM ||
+ cipher_info->mode == MBEDTLS_MODE_CBC )
{
/* Initialize HMAC contexts */
if( ( ret = mbedtls_md_setup( &transform->md_ctx_enc, md_info, 1 ) ) != 0 ||
( ret = mbedtls_md_setup( &transform->md_ctx_dec, md_info, 1 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret );
- return( ret );
+ goto end;
}
/* Get MAC length */
@@ -854,7 +1011,7 @@
* (rfc 6066 page 13 or rfc 2104 section 4),
* so we only need to adjust the length here.
*/
- if( session->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED )
+ if( trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED )
{
transform->maclen = MBEDTLS_SSL_TRUNCATED_HMAC_LEN;
@@ -882,7 +1039,7 @@
* 2. IV except for SSL3 and TLS 1.0
*/
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
- if( session->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED )
+ if( encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED )
{
transform->minlen = transform->maclen
+ cipher_info->block_size;
@@ -896,14 +1053,14 @@
}
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ||
- ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_1 )
+ if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ||
+ minor_ver == MBEDTLS_SSL_MINOR_VERSION_1 )
; /* No need to adjust minlen */
else
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_2 ||
- ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
+ if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_2 ||
+ minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{
transform->minlen += transform->ivlen;
}
@@ -911,23 +1068,32 @@
#endif
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+ goto end;
}
}
}
+ else
+#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d",
- transform->keylen, transform->minlen, transform->ivlen,
- transform->maclen ) );
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "keylen: %u, minlen: %u, ivlen: %u, maclen: %u",
+ (unsigned) keylen,
+ (unsigned) transform->minlen,
+ (unsigned) transform->ivlen,
+ (unsigned) transform->maclen ) );
/*
* Finally setup the cipher contexts, IVs and MAC secrets.
*/
#if defined(MBEDTLS_SSL_CLI_C)
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
+ if( endpoint == MBEDTLS_SSL_IS_CLIENT )
{
key1 = keyblk + mac_key_len * 2;
- key2 = keyblk + mac_key_len * 2 + transform->keylen;
+ key2 = keyblk + mac_key_len * 2 + keylen;
mac_enc = keyblk;
mac_dec = keyblk + mac_key_len;
@@ -937,16 +1103,16 @@
*/
iv_copy_len = ( transform->fixed_ivlen ) ?
transform->fixed_ivlen : transform->ivlen;
- memcpy( transform->iv_enc, key2 + transform->keylen, iv_copy_len );
- memcpy( transform->iv_dec, key2 + transform->keylen + iv_copy_len,
+ memcpy( transform->iv_enc, key2 + keylen, iv_copy_len );
+ memcpy( transform->iv_dec, key2 + keylen + iv_copy_len,
iv_copy_len );
}
else
#endif /* MBEDTLS_SSL_CLI_C */
#if defined(MBEDTLS_SSL_SRV_C)
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
+ if( endpoint == MBEDTLS_SSL_IS_SERVER )
{
- key1 = keyblk + mac_key_len * 2 + transform->keylen;
+ key1 = keyblk + mac_key_len * 2 + keylen;
key2 = keyblk + mac_key_len * 2;
mac_enc = keyblk + mac_key_len;
@@ -957,24 +1123,27 @@
*/
iv_copy_len = ( transform->fixed_ivlen ) ?
transform->fixed_ivlen : transform->ivlen;
- memcpy( transform->iv_dec, key1 + transform->keylen, iv_copy_len );
- memcpy( transform->iv_enc, key1 + transform->keylen + iv_copy_len,
+ memcpy( transform->iv_dec, key1 + keylen, iv_copy_len );
+ memcpy( transform->iv_enc, key1 + keylen + iv_copy_len,
iv_copy_len );
}
else
#endif /* MBEDTLS_SSL_SRV_C */
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+ goto end;
}
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
#if defined(MBEDTLS_SSL_PROTO_SSL3)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
+ if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
{
- if( mac_key_len > sizeof transform->mac_enc )
+ if( mac_key_len > sizeof( transform->mac_enc ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+ goto end;
}
memcpy( transform->mac_enc, mac_enc, mac_key_len );
@@ -984,7 +1153,7 @@
#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( minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
{
/* For HMAC-based ciphersuites, initialize the HMAC transforms.
For AEAD-based ciphersuites, there is nothing to do here. */
@@ -998,8 +1167,10 @@
#endif
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+ goto end;
}
+#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
if( mbedtls_ssl_hw_record_init != NULL )
@@ -1008,40 +1179,128 @@
MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_init()" ) );
- if( ( ret = mbedtls_ssl_hw_record_init( ssl, key1, key2, transform->keylen,
+ if( ( ret = mbedtls_ssl_hw_record_init( ssl, key1, key2, keylen,
transform->iv_enc, transform->iv_dec,
iv_copy_len,
mac_enc, mac_dec,
mac_key_len ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_init", ret );
- return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+ goto end;
}
}
+#else
+ ((void) mac_dec);
+ ((void) mac_enc);
#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
#if defined(MBEDTLS_SSL_EXPORT_KEYS)
if( ssl->conf->f_export_keys != NULL )
{
ssl->conf->f_export_keys( ssl->conf->p_export_keys,
- session->master, keyblk,
- mac_key_len, transform->keylen,
+ master, keyblk,
+ mac_key_len, keylen,
iv_copy_len );
}
+
+ if( ssl->conf->f_export_keys_ext != NULL )
+ {
+ ssl->conf->f_export_keys_ext( ssl->conf->p_export_keys,
+ master, keyblk,
+ mac_key_len, keylen,
+ iv_copy_len,
+ randbytes + 32,
+ randbytes,
+ tls_prf_get_type( tls_prf ) );
+ }
#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+
+ /* Only use PSA-based ciphers for TLS-1.2.
+ * That's relevant at least for TLS-1.0, where
+ * we assume that mbedtls_cipher_crypt() updates
+ * the structure field for the IV, which the PSA-based
+ * implementation currently doesn't. */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+ if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
+ {
+ ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_enc,
+ cipher_info, transform->taglen );
+ if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret );
+ goto end;
+ }
+
+ if( ret == 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based encryption cipher context" ) );
+ psa_fallthrough = 0;
+ }
+ else
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record encryption - fall through to default setup." ) );
+ psa_fallthrough = 1;
+ }
+ }
+ else
+ psa_fallthrough = 1;
+#else
+ psa_fallthrough = 1;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+ if( psa_fallthrough == 1 )
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc,
cipher_info ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret );
- return( ret );
+ goto end;
}
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ /* Only use PSA-based ciphers for TLS-1.2.
+ * That's relevant at least for TLS-1.0, where
+ * we assume that mbedtls_cipher_crypt() updates
+ * the structure field for the IV, which the PSA-based
+ * implementation currently doesn't. */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+ if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
+ {
+ ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_dec,
+ cipher_info, transform->taglen );
+ if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret );
+ goto end;
+ }
+
+ if( ret == 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based decryption cipher context" ) );
+ psa_fallthrough = 0;
+ }
+ else
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record decryption - fall through to default setup." ) );
+ psa_fallthrough = 1;
+ }
+ }
+ else
+ psa_fallthrough = 1;
+#else
+ psa_fallthrough = 1;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+ if( psa_fallthrough == 1 )
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec,
cipher_info ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret );
- return( ret );
+ goto end;
}
if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_enc, key1,
@@ -1049,7 +1308,7 @@
MBEDTLS_ENCRYPT ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret );
- return( ret );
+ goto end;
}
if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_dec, key2,
@@ -1057,7 +1316,7 @@
MBEDTLS_DECRYPT ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret );
- return( ret );
+ goto end;
}
#if defined(MBEDTLS_CIPHER_MODE_CBC)
@@ -1067,37 +1326,23 @@
MBEDTLS_PADDING_NONE ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret );
- return( ret );
+ goto end;
}
if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_dec,
MBEDTLS_PADDING_NONE ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret );
- return( ret );
+ goto end;
}
}
#endif /* MBEDTLS_CIPHER_MODE_CBC */
- mbedtls_platform_zeroize( keyblk, sizeof( keyblk ) );
+ /* Initialize Zlib contexts */
#if defined(MBEDTLS_ZLIB_SUPPORT)
- // Initialize compression
- //
- if( session->compression == MBEDTLS_SSL_COMPRESS_DEFLATE )
+ if( compression == MBEDTLS_SSL_COMPRESS_DEFLATE )
{
- if( ssl->compress_buf == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) );
- ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_COMPRESS_BUFFER_LEN );
- if( ssl->compress_buf == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
- MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) );
- return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
- }
- }
-
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) );
memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) );
@@ -1108,18 +1353,318 @@
inflateInit( &transform->ctx_inflate ) != Z_OK )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) );
- return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
+ ret = MBEDTLS_ERR_SSL_COMPRESSION_FAILED;
+ goto end;
}
}
#endif /* MBEDTLS_ZLIB_SUPPORT */
+end:
+ mbedtls_platform_zeroize( keyblk, sizeof( keyblk ) );
+ return( ret );
+}
+
+/*
+ * Set appropriate PRF function and other SSL / TLS 1.0/1.1 / TLS1.2 functions
+ *
+ * Inputs:
+ * - SSL/TLS minor version
+ * - hash associated with the ciphersuite (only used by TLS 1.2)
+ *
+ * Outputs:
+ * - the tls_prf, calc_verify and calc_finished members of handshake structure
+ */
+static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake,
+ int minor_ver,
+ mbedtls_md_type_t hash )
+{
+#if !defined(MBEDTLS_SSL_PROTO_TLS1_2) || !defined(MBEDTLS_SHA512_C)
+ (void) hash;
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_SSL3)
+ if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
+ {
+ handshake->tls_prf = ssl3_prf;
+ handshake->calc_verify = ssl_calc_verify_ssl;
+ handshake->calc_finished = ssl_calc_finished_ssl;
+ }
+ else
+#endif
+#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
+ if( minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 )
+ {
+ handshake->tls_prf = tls1_prf;
+ handshake->calc_verify = ssl_calc_verify_tls;
+ handshake->calc_finished = ssl_calc_finished_tls;
+ }
+ else
+#endif
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#if defined(MBEDTLS_SHA512_C)
+ if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 &&
+ hash == MBEDTLS_MD_SHA384 )
+ {
+ handshake->tls_prf = tls_prf_sha384;
+ handshake->calc_verify = ssl_calc_verify_tls_sha384;
+ handshake->calc_finished = ssl_calc_finished_tls_sha384;
+ }
+ else
+#endif
+#if defined(MBEDTLS_SHA256_C)
+ if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
+ {
+ handshake->tls_prf = tls_prf_sha256;
+ handshake->calc_verify = ssl_calc_verify_tls_sha256;
+ handshake->calc_finished = ssl_calc_finished_tls_sha256;
+ }
+ else
+#endif
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+ {
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Compute master secret if needed
+ *
+ * Parameters:
+ * [in/out] handshake
+ * [in] resume, premaster, extended_ms, calc_verify, tls_prf
+ * (PSA-PSK) ciphersuite_info, psk_opaque
+ * [out] premaster (cleared)
+ * [out] master
+ * [in] ssl: optionally used for debugging, EMS and PSA-PSK
+ * debug: conf->f_dbg, conf->p_dbg
+ * EMS: passed to calc_verify (debug + (SSL3) session_negotiate)
+ * PSA-PSA: minor_ver, conf
+ */
+static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake,
+ unsigned char *master,
+ const mbedtls_ssl_context *ssl )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ /* cf. RFC 5246, Section 8.1:
+ * "The master secret is always exactly 48 bytes in length." */
+ size_t const master_secret_len = 48;
+
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+ unsigned char session_hash[48];
+#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
+
+ /* The label for the KDF used for key expansion.
+ * This is either "master secret" or "extended master secret"
+ * depending on whether the Extended Master Secret extension
+ * is used. */
+ char const *lbl = "master secret";
+
+ /* The salt for the KDF used for key expansion.
+ * - If the Extended Master Secret extension is not used,
+ * this is ClientHello.Random + ServerHello.Random
+ * (see Sect. 8.1 in RFC 5246).
+ * - If the Extended Master Secret extension is used,
+ * this is the transcript of the handshake so far.
+ * (see Sect. 4 in RFC 7627). */
+ unsigned char const *salt = handshake->randbytes;
+ size_t salt_len = 64;
+
+#if !defined(MBEDTLS_DEBUG_C) && \
+ !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \
+ !(defined(MBEDTLS_USE_PSA_CRYPTO) && \
+ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED))
+ ssl = NULL; /* make sure we don't use it except for those cases */
+ (void) ssl;
+#endif
+
+ if( handshake->resume != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) );
+ return( 0 );
+ }
+
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+ if( handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED )
+ {
+ lbl = "extended master secret";
+ salt = session_hash;
+ handshake->calc_verify( ssl, session_hash, &salt_len );
+
+ MBEDTLS_SSL_DEBUG_BUF( 3, "session hash for extended master secret",
+ session_hash, salt_len );
+ }
+#endif /* MBEDTLS_SSL_EXTENDED_MS_ENABLED */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
+ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
+ if( handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK &&
+ ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 &&
+ ssl_use_opaque_psk( ssl ) == 1 )
+ {
+ /* Perform PSK-to-MS expansion in a single step. */
+ psa_status_t status;
+ psa_algorithm_t alg;
+ psa_key_handle_t psk;
+ psa_key_derivation_operation_t derivation =
+ PSA_KEY_DERIVATION_OPERATION_INIT;
+ mbedtls_md_type_t hash_alg = handshake->ciphersuite_info->mac;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "perform PSA-based PSK-to-MS expansion" ) );
+
+ psk = ssl->conf->psk_opaque;
+ if( handshake->psk_opaque != 0 )
+ psk = handshake->psk_opaque;
+
+ if( hash_alg == MBEDTLS_MD_SHA384 )
+ alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384);
+ else
+ alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256);
+
+ status = setup_psa_key_derivation( &derivation, psk, alg,
+ salt, salt_len,
+ (unsigned char const *) lbl,
+ (size_t) strlen( lbl ),
+ master_secret_len );
+ if( status != PSA_SUCCESS )
+ {
+ psa_key_derivation_abort( &derivation );
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ }
+
+ status = psa_key_derivation_output_bytes( &derivation,
+ master,
+ master_secret_len );
+ if( status != PSA_SUCCESS )
+ {
+ psa_key_derivation_abort( &derivation );
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ }
+
+ status = psa_key_derivation_abort( &derivation );
+ if( status != PSA_SUCCESS )
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ }
+ else
+#endif
+ {
+ ret = handshake->tls_prf( handshake->premaster, handshake->pmslen,
+ lbl, salt, salt_len,
+ master,
+ master_secret_len );
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret );
+ return( ret );
+ }
+
+ MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret",
+ handshake->premaster,
+ handshake->pmslen );
+
+ mbedtls_platform_zeroize( handshake->premaster,
+ sizeof(handshake->premaster) );
+ }
+
+ return( 0 );
+}
+
+int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
+ ssl->handshake->ciphersuite_info;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> derive keys" ) );
+
+ /* Set PRF, calc_verify and calc_finished function pointers */
+ ret = ssl_set_handshake_prfs( ssl->handshake,
+ ssl->minor_ver,
+ ciphersuite_info->mac );
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_set_handshake_prfs", ret );
+ return( ret );
+ }
+
+ /* Compute master secret if needed */
+ ret = ssl_compute_master( ssl->handshake,
+ ssl->session_negotiate->master,
+ ssl );
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compute_master", ret );
+ return( ret );
+ }
+
+ /* Swap the client and server random values:
+ * - MS derivation wanted client+server (RFC 5246 8.1)
+ * - key derivation wants server+client (RFC 5246 6.3) */
+ {
+ unsigned char tmp[64];
+ memcpy( tmp, ssl->handshake->randbytes, 64 );
+ memcpy( ssl->handshake->randbytes, tmp + 32, 32 );
+ memcpy( ssl->handshake->randbytes + 32, tmp, 32 );
+ mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
+ }
+
+ /* Populate transform structure */
+ ret = ssl_populate_transform( ssl->transform_negotiate,
+ ssl->session_negotiate->ciphersuite,
+ ssl->session_negotiate->master,
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+ ssl->session_negotiate->encrypt_then_mac,
+#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
+#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
+ ssl->session_negotiate->trunc_hmac,
+#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
+#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
+#if defined(MBEDTLS_ZLIB_SUPPORT)
+ ssl->session_negotiate->compression,
+#endif
+ ssl->handshake->tls_prf,
+ ssl->handshake->randbytes,
+ ssl->minor_ver,
+ ssl->conf->endpoint,
+ ssl );
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_populate_transform", ret );
+ return( ret );
+ }
+
+ /* We no longer need Server/ClientHello.random values */
+ mbedtls_platform_zeroize( ssl->handshake->randbytes,
+ sizeof( ssl->handshake->randbytes ) );
+
+ /* Allocate compression buffer */
+#if defined(MBEDTLS_ZLIB_SUPPORT)
+ if( ssl->session_negotiate->compression == MBEDTLS_SSL_COMPRESS_DEFLATE &&
+ ssl->compress_buf == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) );
+ ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_COMPRESS_BUFFER_LEN );
+ if( ssl->compress_buf == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
+ MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) );
+ return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+ }
+ }
+#endif
+
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive keys" ) );
return( 0 );
}
#if defined(MBEDTLS_SSL_PROTO_SSL3)
-void ssl_calc_verify_ssl( mbedtls_ssl_context *ssl, unsigned char hash[36] )
+void ssl_calc_verify_ssl( const mbedtls_ssl_context *ssl,
+ unsigned char hash[36],
+ size_t *hlen )
{
mbedtls_md5_context md5;
mbedtls_sha1_context sha1;
@@ -1157,7 +1702,9 @@
mbedtls_sha1_update_ret( &sha1, hash + 16, 20 );
mbedtls_sha1_finish_ret( &sha1, hash + 16 );
- MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 );
+ *hlen = 36;
+
+ MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
mbedtls_md5_free( &md5 );
@@ -1168,7 +1715,9 @@
#endif /* MBEDTLS_SSL_PROTO_SSL3 */
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
-void ssl_calc_verify_tls( mbedtls_ssl_context *ssl, unsigned char hash[36] )
+void ssl_calc_verify_tls( const mbedtls_ssl_context *ssl,
+ unsigned char hash[36],
+ size_t *hlen )
{
mbedtls_md5_context md5;
mbedtls_sha1_context sha1;
@@ -1181,10 +1730,12 @@
mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 );
mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 );
- mbedtls_md5_finish_ret( &md5, hash );
+ mbedtls_md5_finish_ret( &md5, hash );
mbedtls_sha1_finish_ret( &sha1, hash + 16 );
- MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 );
+ *hlen = 36;
+
+ MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
mbedtls_md5_free( &md5 );
@@ -1196,8 +1747,34 @@
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
#if defined(MBEDTLS_SHA256_C)
-void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *ssl, unsigned char hash[32] )
+void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *ssl,
+ unsigned char hash[32],
+ size_t *hlen )
{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ size_t hash_size;
+ psa_status_t status;
+ psa_hash_operation_t sha256_psa = psa_hash_operation_init();
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> PSA calc verify sha256" ) );
+ status = psa_hash_clone( &ssl->handshake->fin_sha256_psa, &sha256_psa );
+ if( status != PSA_SUCCESS )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) );
+ return;
+ }
+
+ status = psa_hash_finish( &sha256_psa, hash, 32, &hash_size );
+ if( status != PSA_SUCCESS )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) );
+ return;
+ }
+
+ *hlen = 32;
+ MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated verify result", hash, *hlen );
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= PSA calc verify" ) );
+#else
mbedtls_sha256_context sha256;
mbedtls_sha256_init( &sha256 );
@@ -1207,18 +1784,46 @@
mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 );
mbedtls_sha256_finish_ret( &sha256, hash );
- MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 );
+ *hlen = 32;
+
+ MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
mbedtls_sha256_free( &sha256 );
-
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
return;
}
#endif /* MBEDTLS_SHA256_C */
#if defined(MBEDTLS_SHA512_C)
-void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *ssl, unsigned char hash[48] )
+void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *ssl,
+ unsigned char hash[48],
+ size_t *hlen )
{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ size_t hash_size;
+ psa_status_t status;
+ psa_hash_operation_t sha384_psa = psa_hash_operation_init();
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> PSA calc verify sha384" ) );
+ status = psa_hash_clone( &ssl->handshake->fin_sha384_psa, &sha384_psa );
+ if( status != PSA_SUCCESS )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) );
+ return;
+ }
+
+ status = psa_hash_finish( &sha384_psa, hash, 48, &hash_size );
+ if( status != PSA_SUCCESS )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) );
+ return;
+ }
+
+ *hlen = 48;
+ MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated verify result", hash, *hlen );
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= PSA calc verify" ) );
+#else
mbedtls_sha512_context sha512;
mbedtls_sha512_init( &sha512 );
@@ -1228,17 +1833,19 @@
mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 );
mbedtls_sha512_finish_ret( &sha512, hash );
- MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 );
+ *hlen = 48;
+
+ MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) );
mbedtls_sha512_free( &sha512 );
-
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
return;
}
#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;
@@ -1296,7 +1903,7 @@
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
if( key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
/* Write length only when we know the actual value */
@@ -1318,7 +1925,7 @@
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
if( key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t zlen;
if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen,
@@ -1360,1133 +1967,13 @@
return( 0 );
}
-#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-/*
- * SSLv3.0 MAC functions
- */
-#define SSL_MAC_MAX_BYTES 20 /* MD-5 or SHA-1 */
-static void ssl_mac( mbedtls_md_context_t *md_ctx,
- const unsigned char *secret,
- const unsigned char *buf, size_t len,
- const unsigned char *ctr, int type,
- unsigned char out[SSL_MAC_MAX_BYTES] )
-{
- unsigned char header[11];
- unsigned char padding[48];
- int padlen;
- int md_size = mbedtls_md_get_size( md_ctx->md_info );
- int md_type = mbedtls_md_get_type( md_ctx->md_info );
-
- /* Only MD5 and SHA-1 supported */
- if( md_type == MBEDTLS_MD_MD5 )
- padlen = 48;
- else
- padlen = 40;
-
- memcpy( header, ctr, 8 );
- header[ 8] = (unsigned char) type;
- header[ 9] = (unsigned char)( len >> 8 );
- header[10] = (unsigned char)( len );
-
- memset( padding, 0x36, padlen );
- mbedtls_md_starts( md_ctx );
- mbedtls_md_update( md_ctx, secret, md_size );
- mbedtls_md_update( md_ctx, padding, padlen );
- mbedtls_md_update( md_ctx, header, 11 );
- mbedtls_md_update( md_ctx, buf, len );
- mbedtls_md_finish( md_ctx, out );
-
- memset( padding, 0x5C, padlen );
- mbedtls_md_starts( md_ctx );
- mbedtls_md_update( md_ctx, secret, md_size );
- mbedtls_md_update( md_ctx, padding, padlen );
- mbedtls_md_update( md_ctx, out, md_size );
- mbedtls_md_finish( md_ctx, out );
-}
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-
-#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \
- ( defined(MBEDTLS_CIPHER_MODE_CBC) && \
- ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C)) )
-#define SSL_SOME_MODES_USE_MAC
-#endif
-
-/* The function below is only used in the Lucky 13 counter-measure in
- * ssl_decrypt_buf(). These are the defines that guard the call site. */
-#if defined(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
- */
-static int ssl_encrypt_buf( mbedtls_ssl_context *ssl )
-{
- mbedtls_cipher_mode_t mode;
- int auth_done = 0;
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) );
-
- if( ssl->session_out == NULL || ssl->transform_out == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- mode = mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc );
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload",
- ssl->out_msg, ssl->out_msglen );
-
- /*
- * Add MAC before if needed
- */
-#if defined(SSL_SOME_MODES_USE_MAC)
- if( mode == MBEDTLS_MODE_STREAM ||
- ( mode == MBEDTLS_MODE_CBC
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
- && ssl->session_out->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED
-#endif
- ) )
- {
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
- {
- unsigned char mac[SSL_MAC_MAX_BYTES];
-
- ssl_mac( &ssl->transform_out->md_ctx_enc,
- ssl->transform_out->mac_enc,
- ssl->out_msg, ssl->out_msglen,
- ssl->out_ctr, ssl->out_msgtype,
- mac );
-
- memcpy( ssl->out_msg + ssl->out_msglen, mac, ssl->transform_out->maclen );
- }
- else
-#endif
-#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 )
- {
- unsigned char mac[MBEDTLS_SSL_MAC_ADD];
-
- mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 8 );
- mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_hdr, 3 );
- mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_len, 2 );
- mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc,
- ssl->out_msg, ssl->out_msglen );
- mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, mac );
- mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc );
-
- memcpy( ssl->out_msg + ssl->out_msglen, mac, ssl->transform_out->maclen );
- }
- else
-#endif
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac",
- ssl->out_msg + ssl->out_msglen,
- ssl->transform_out->maclen );
-
- ssl->out_msglen += ssl->transform_out->maclen;
- auth_done++;
- }
-#endif /* AEAD not the only option */
-
- /*
- * Encrypt
- */
-#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
- if( mode == MBEDTLS_MODE_STREAM )
- {
- int ret;
- size_t olen = 0;
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
- "including %d bytes of padding",
- ssl->out_msglen, 0 ) );
-
- if( ( ret = mbedtls_cipher_crypt( &ssl->transform_out->cipher_ctx_enc,
- ssl->transform_out->iv_enc,
- ssl->transform_out->ivlen,
- ssl->out_msg, ssl->out_msglen,
- ssl->out_msg, &olen ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
- return( ret );
- }
-
- if( ssl->out_msglen != 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;
- size_t enc_msglen, olen;
- unsigned char *enc_msg;
- unsigned char add_data[13];
- unsigned char iv[12];
- mbedtls_ssl_transform *transform = ssl->transform_out;
- unsigned char taglen = transform->ciphersuite_info->flags &
- MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
- size_t explicit_ivlen = transform->ivlen - transform->fixed_ivlen;
-
- /*
- * Prepare additional authenticated data
- */
- memcpy( add_data, ssl->out_ctr, 8 );
- add_data[8] = ssl->out_msgtype;
- mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
- ssl->conf->transport, add_data + 9 );
- add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF;
- add_data[12] = ssl->out_msglen & 0xFF;
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 );
-
- /*
- * 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, ssl->out_ctr, 8 );
- memcpy( ssl->out_iv, ssl->out_ctr, 8 );
-
- }
- 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] ^= ssl->out_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 );
- }
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)",
- iv, transform->ivlen );
- MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)",
- ssl->out_iv, explicit_ivlen );
-
- /*
- * Fix message length with added IV
- */
- enc_msg = ssl->out_msg;
- enc_msglen = ssl->out_msglen;
- ssl->out_msglen += explicit_ivlen;
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
- "including 0 bytes of padding",
- ssl->out_msglen ) );
-
- /*
- * Encrypt and authenticate
- */
- if( ( ret = mbedtls_cipher_auth_encrypt( &transform->cipher_ctx_enc,
- iv, transform->ivlen,
- add_data, 13,
- enc_msg, enc_msglen,
- enc_msg, &olen,
- enc_msg + enc_msglen, taglen ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret );
- return( ret );
- }
-
- if( olen != enc_msglen )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- ssl->out_msglen += taglen;
- auth_done++;
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag", enc_msg + enc_msglen, taglen );
- }
- 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;
- unsigned char *enc_msg;
- size_t enc_msglen, padlen, olen = 0, i;
-
- padlen = ssl->transform_out->ivlen - ( ssl->out_msglen + 1 ) %
- ssl->transform_out->ivlen;
- if( padlen == ssl->transform_out->ivlen )
- padlen = 0;
-
- for( i = 0; i <= padlen; i++ )
- ssl->out_msg[ssl->out_msglen + i] = (unsigned char) padlen;
-
- ssl->out_msglen += padlen + 1;
-
- enc_msglen = ssl->out_msglen;
- enc_msg = ssl->out_msg;
-
-#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( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- /*
- * Generate IV
- */
- ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->transform_out->iv_enc,
- ssl->transform_out->ivlen );
- if( ret != 0 )
- return( ret );
-
- memcpy( ssl->out_iv, ssl->transform_out->iv_enc,
- ssl->transform_out->ivlen );
-
- /*
- * Fix pointer positions and message length with added IV
- */
- enc_msg = ssl->out_msg;
- enc_msglen = ssl->out_msglen;
- ssl->out_msglen += ssl->transform_out->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",
- ssl->out_msglen, ssl->transform_out->ivlen,
- padlen + 1 ) );
-
- if( ( ret = mbedtls_cipher_crypt( &ssl->transform_out->cipher_ctx_enc,
- ssl->transform_out->iv_enc,
- ssl->transform_out->ivlen,
- enc_msg, enc_msglen,
- enc_msg, &olen ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
- return( ret );
- }
-
- if( enc_msglen != 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( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- /*
- * Save IV in SSL3 and TLS1
- */
- memcpy( ssl->transform_out->iv_enc,
- ssl->transform_out->cipher_ctx_enc.iv,
- ssl->transform_out->ivlen );
- }
-#endif
-
-#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));
- */
- unsigned char pseudo_hdr[13];
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
-
- memcpy( pseudo_hdr + 0, ssl->out_ctr, 8 );
- memcpy( pseudo_hdr + 8, ssl->out_hdr, 3 );
- pseudo_hdr[11] = (unsigned char)( ( ssl->out_msglen >> 8 ) & 0xFF );
- pseudo_hdr[12] = (unsigned char)( ( ssl->out_msglen ) & 0xFF );
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 );
-
- mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, pseudo_hdr, 13 );
- mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc,
- ssl->out_iv, ssl->out_msglen );
- mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, mac );
- mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc );
-
- memcpy( ssl->out_iv + ssl->out_msglen, mac,
- ssl->transform_out->maclen );
-
- ssl->out_msglen += ssl->transform_out->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 );
-}
-
-static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
-{
- mbedtls_cipher_mode_t mode;
- int auth_done = 0;
-#if defined(SSL_SOME_MODES_USE_MAC)
- size_t padlen = 0, correct = 1;
-#endif
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) );
-
- if( ssl->session_in == NULL || ssl->transform_in == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- mode = mbedtls_cipher_get_cipher_mode( &ssl->transform_in->cipher_ctx_dec );
-
- if( ssl->in_msglen < ssl->transform_in->minlen )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)",
- ssl->in_msglen, ssl->transform_in->minlen ) );
- return( MBEDTLS_ERR_SSL_INVALID_MAC );
- }
-
-#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
- if( mode == MBEDTLS_MODE_STREAM )
- {
- int ret;
- size_t olen = 0;
-
- padlen = 0;
-
- if( ( ret = mbedtls_cipher_crypt( &ssl->transform_in->cipher_ctx_dec,
- ssl->transform_in->iv_dec,
- ssl->transform_in->ivlen,
- ssl->in_msg, ssl->in_msglen,
- ssl->in_msg, &olen ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
- return( ret );
- }
-
- if( ssl->in_msglen != 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;
- size_t dec_msglen, olen;
- unsigned char *dec_msg;
- unsigned char *dec_msg_result;
- unsigned char add_data[13];
- unsigned char iv[12];
- mbedtls_ssl_transform *transform = ssl->transform_in;
- unsigned char taglen = transform->ciphersuite_info->flags &
- MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
- size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen;
-
- /*
- * Compute and update sizes
- */
- if( ssl->in_msglen < explicit_iv_len + taglen )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) "
- "+ taglen (%d)", ssl->in_msglen,
- explicit_iv_len, taglen ) );
- return( MBEDTLS_ERR_SSL_INVALID_MAC );
- }
- dec_msglen = ssl->in_msglen - explicit_iv_len - taglen;
-
- dec_msg = ssl->in_msg;
- dec_msg_result = ssl->in_msg;
- ssl->in_msglen = dec_msglen;
-
- /*
- * Prepare additional authenticated data
- */
- memcpy( add_data, ssl->in_ctr, 8 );
- add_data[8] = ssl->in_msgtype;
- mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
- ssl->conf->transport, add_data + 9 );
- add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF;
- add_data[12] = ssl->in_msglen & 0xFF;
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 );
-
- /*
- * Prepare IV
- */
- if( transform->ivlen == 12 && transform->fixed_ivlen == 4 )
- {
- /* GCM and CCM: fixed || explicit (transmitted) */
- memcpy( iv, transform->iv_dec, transform->fixed_ivlen );
- memcpy( iv + transform->fixed_ivlen, ssl->in_iv, 8 );
-
- }
- else 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] ^= ssl->in_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 );
- }
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen );
- MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen );
-
- /*
- * Decrypt and authenticate
- */
- if( ( ret = mbedtls_cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec,
- iv, transform->ivlen,
- add_data, 13,
- dec_msg, dec_msglen,
- dec_msg_result, &olen,
- dec_msg + dec_msglen, 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++;
-
- if( olen != dec_msglen )
- {
- 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 )
- {
- /*
- * Decrypt and check the padding
- */
- int ret;
- unsigned char *dec_msg;
- unsigned char *dec_msg_result;
- size_t dec_msglen;
- size_t minlen = 0;
- size_t olen = 0;
-
- /*
- * Check immediate ciphertext sanity
- */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
- minlen += ssl->transform_in->ivlen;
-#endif
-
- if( ssl->in_msglen < minlen + ssl->transform_in->ivlen ||
- ssl->in_msglen < minlen + ssl->transform_in->maclen + 1 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) "
- "+ 1 ) ( + expl IV )", ssl->in_msglen,
- ssl->transform_in->ivlen,
- ssl->transform_in->maclen ) );
- return( MBEDTLS_ERR_SSL_INVALID_MAC );
- }
-
- dec_msglen = ssl->in_msglen;
- dec_msg = ssl->in_msg;
- dec_msg_result = ssl->in_msg;
-
- /*
- * Authenticate before decrypt if enabled
- */
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
- if( ssl->session_in->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED )
- {
- unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD];
- unsigned char pseudo_hdr[13];
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
-
- dec_msglen -= ssl->transform_in->maclen;
- ssl->in_msglen -= ssl->transform_in->maclen;
-
- memcpy( pseudo_hdr + 0, ssl->in_ctr, 8 );
- memcpy( pseudo_hdr + 8, ssl->in_hdr, 3 );
- pseudo_hdr[11] = (unsigned char)( ( ssl->in_msglen >> 8 ) & 0xFF );
- pseudo_hdr[12] = (unsigned char)( ( ssl->in_msglen ) & 0xFF );
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 );
-
- mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, pseudo_hdr, 13 );
- mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec,
- ssl->in_iv, ssl->in_msglen );
- mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect );
- mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec );
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_iv + ssl->in_msglen,
- ssl->transform_in->maclen );
- MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect,
- ssl->transform_in->maclen );
-
- if( mbedtls_ssl_safer_memcmp( ssl->in_iv + ssl->in_msglen, mac_expect,
- ssl->transform_in->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
- */
- if( ssl->in_msglen % ssl->transform_in->ivlen != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0",
- ssl->in_msglen, ssl->transform_in->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( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- unsigned char i;
- dec_msglen -= ssl->transform_in->ivlen;
- ssl->in_msglen -= ssl->transform_in->ivlen;
-
- for( i = 0; i < ssl->transform_in->ivlen; i++ )
- ssl->transform_in->iv_dec[i] = ssl->in_iv[i];
- }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
-
- if( ( ret = mbedtls_cipher_crypt( &ssl->transform_in->cipher_ctx_dec,
- ssl->transform_in->iv_dec,
- ssl->transform_in->ivlen,
- dec_msg, dec_msglen,
- dec_msg_result, &olen ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
- return( ret );
- }
-
- if( dec_msglen != 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( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- /*
- * Save IV in SSL3 and TLS1
- */
- memcpy( ssl->transform_in->iv_dec,
- ssl->transform_in->cipher_ctx_dec.iv,
- ssl->transform_in->ivlen );
- }
-#endif
-
- padlen = 1 + ssl->in_msg[ssl->in_msglen - 1];
-
- if( ssl->in_msglen < ssl->transform_in->maclen + padlen &&
- auth_done == 0 )
- {
-#if defined(MBEDTLS_SSL_DEBUG_ALL)
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)",
- ssl->in_msglen, ssl->transform_in->maclen, padlen ) );
-#endif
- padlen = 0;
- correct = 0;
- }
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
- {
- if( padlen > ssl->transform_in->ivlen )
- {
-#if defined(MBEDTLS_SSL_DEBUG_ALL)
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, "
- "should be no more than %d",
- padlen, ssl->transform_in->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( ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 )
- {
- /*
- * TLSv1+: always check the padding up to the first failure
- * and fake check up to 256 bytes of padding
- */
- size_t pad_count = 0, real_count = 1;
- size_t padding_idx = ssl->in_msglen - padlen;
- size_t i;
-
- /*
- * Padding is guaranteed to be incorrect if:
- * 1. padlen > ssl->in_msglen
- *
- * 2. padding_idx > MBEDTLS_SSL_IN_CONTENT_LEN +
- * ssl->transform_in->maclen
- *
- * In both cases we reset padding_idx to a safe value (0) to
- * prevent out-of-buffer reads.
- */
- correct &= ( padlen <= ssl->in_msglen );
- correct &= ( padding_idx <= MBEDTLS_SSL_IN_CONTENT_LEN +
- ssl->transform_in->maclen );
-
- padding_idx *= correct;
-
- for( i = 0; i < 256; i++ )
- {
- real_count &= ( i < padlen );
- pad_count += real_count *
- ( ssl->in_msg[padding_idx + i] == padlen - 1 );
- }
-
- correct &= ( pad_count == padlen ); /* Only 1 on correct padding */
-
-#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 );
- }
-
- ssl->in_msglen -= 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",
- ssl->in_msg, ssl->in_msglen );
-#endif
-
- /*
- * Authenticate if not done yet.
- * Compute the MAC regardless of the padding result (RFC4346, CBCTIME).
- */
-#if defined(SSL_SOME_MODES_USE_MAC)
- if( auth_done == 0 )
- {
- unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD];
-
- ssl->in_msglen -= ssl->transform_in->maclen;
-
- ssl->in_len[0] = (unsigned char)( ssl->in_msglen >> 8 );
- ssl->in_len[1] = (unsigned char)( ssl->in_msglen );
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
- {
- ssl_mac( &ssl->transform_in->md_ctx_dec,
- ssl->transform_in->mac_dec,
- ssl->in_msg, ssl->in_msglen,
- ssl->in_ctr, ssl->in_msgtype,
- 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( ssl->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;
-
- /*
- * 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
- * in_msglen -= 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 = ssl->in_msglen + padlen;
- const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0;
-
- switch( ssl->transform_in->ciphersuite_info->mac )
- {
-#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 = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 -
- ( 13 + ssl->in_msglen + 8 ) / 64;
- break;
-#endif
-#if defined(MBEDTLS_SHA512_C)
- case MBEDTLS_MD_SHA384:
- /* 16 bytes of message size, 128-byte compression blocks */
- extra_run = ( 13 + ssl->in_msglen + padlen + 16 ) / 128 -
- ( 13 + ssl->in_msglen + 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( &ssl->transform_in->md_ctx_dec, ssl->in_ctr, 8 );
- mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_hdr, 3 );
- mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_len, 2 );
- mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg,
- ssl->in_msglen );
- /* 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( ssl->in_msg + ssl->in_msglen, padlen );
- mbedtls_md_hmac_finish( &ssl->transform_in->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( &ssl->transform_in->md_ctx_dec, ssl->in_msg );
-
- mbedtls_md_hmac_reset( &ssl->transform_in->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( ssl->in_msg + min_len,
- max_len - min_len + ssl->transform_in->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, ssl->transform_in->maclen );
- MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_msg + ssl->in_msglen,
- ssl->transform_in->maclen );
-#endif
-
- if( mbedtls_ssl_safer_memcmp( ssl->in_msg + ssl->in_msglen, mac_expect,
- ssl->transform_in->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 /* 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( ssl->in_msglen == 0 )
- {
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3
- && ssl->in_msgtype != 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" ) );
- 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 char 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 );
- }
- }
-
- 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;
- 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;
- unsigned char *msg_post = ssl->in_msg;
- ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf;
- size_t len_pre = ssl->in_msglen;
- unsigned char *msg_pre = ssl->compress_buf;
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) );
-
- if( len_pre == 0 )
- return( 0 );
-
- memcpy( msg_pre, ssl->in_msg, len_pre );
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ",
- ssl->in_msglen ) );
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload",
- ssl->in_msg, ssl->in_msglen );
-
- ssl->transform_in->ctx_inflate.next_in = msg_pre;
- ssl->transform_in->ctx_inflate.avail_in = len_pre;
- ssl->transform_in->ctx_inflate.next_out = msg_post;
- ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_IN_BUFFER_LEN -
- header_bytes;
-
- ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH );
- if( ret != Z_OK )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) );
- return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
- }
-
- ssl->in_msglen = MBEDTLS_SSL_IN_BUFFER_LEN -
- ssl->transform_in->ctx_inflate.avail_out - header_bytes;
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ",
- ssl->in_msglen ) );
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload",
- ssl->in_msg, ssl->in_msglen );
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) );
-
- return( 0 );
-}
-#endif /* MBEDTLS_ZLIB_SUPPORT */
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
static int ssl_write_hello_request( mbedtls_ssl_context *ssl );
#if defined(MBEDTLS_SSL_PROTO_DTLS)
-static int ssl_resend_hello_request( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl )
{
/* If renegotiation is not enforced, retransmit until we would reach max
* timeout if we were using the usual handshake doubling scheme */
@@ -2513,2779 +2000,42 @@
#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 )
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+static void ssl_clear_peer_cert( mbedtls_ssl_session *session )
{
- int ret;
- size_t len;
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) );
-
- if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL )
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ if( session->peer_cert != 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 );
+ mbedtls_x509_crt_free( session->peer_cert );
+ mbedtls_free( session->peer_cert );
+ session->peer_cert = NULL;
}
-
- if( nb_want > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) )
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+ if( session->peer_cert_digest != NULL )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) );
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ /* 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;
}
-
-#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 );
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
}
-
-/*
- * Flush any data not yet written
- */
-int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
-{
- int ret;
- 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_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_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;
- 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;
-
- ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
- 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 )
- {
- if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret );
- return( ret );
- }
-
- len = ssl->out_msglen;
- ssl->out_len[0] = (unsigned char)( len >> 8 );
- ssl->out_len[1] = (unsigned char)( len );
- }
-
- protected_record_size = len + mbedtls_ssl_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 */
-
- 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;
- 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] ) );
-}
-
-/*
- * Return 0 if sequence number is acceptable, -1 otherwise
- */
-int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *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;
-
- if( f_cookie_write == NULL || f_cookie_check == NULL )
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
- /*
- * 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;
- size_t len;
-
- 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 );
-
- return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED );
- }
-
- 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 */
-
-/*
- * 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 *ssl )
-{
- int major_ver, minor_ver;
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) );
-
- ssl->in_msgtype = ssl->in_hdr[0];
- ssl->in_msglen = ( ssl->in_len[0] << 8 ) | ssl->in_len[1];
- mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, ssl->in_hdr + 1 );
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, "
- "version = [%d:%d], msglen = %d",
- ssl->in_msgtype,
- major_ver, minor_ver, ssl->in_msglen ) );
-
- /* Check record type */
- if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE &&
- ssl->in_msgtype != MBEDTLS_SSL_MSG_ALERT &&
- ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&
- ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- /* Silently ignore invalid DTLS records as recommended by RFC 6347
- * Section 4.1.2.7 */
- if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
- mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
-
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- /* Check version */
- 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 );
- }
-
- /* Check length against the size of our buffer */
- if( ssl->in_msglen > MBEDTLS_SSL_IN_BUFFER_LEN
- - (size_t)( ssl->in_msg - ssl->in_buf ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- 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 )
- {
- unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
-
- /* Check epoch (and sequence number) with DTLS */
- if( rec_epoch != ssl->in_epoch )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: "
- "expected %d, received %d",
- ssl->in_epoch, rec_epoch ) );
-
-#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
- /*
- * 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( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
- rec_epoch == 0 &&
- 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 ) );
- }
- else
-#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
- {
- /* Consider buffering the record. */
- if( rec_epoch == (unsigned int) 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)
- /* Replay detection only works for the current epoch */
- if( rec_epoch == ssl->in_epoch &&
- mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) );
- return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
- }
-#endif
-
- /* 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_UNEXPECTED_RECORD );
- }
- }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-
- /* Check length against bounds of the current transform and version */
- if( ssl->transform_in == NULL )
- {
- if( ssl->in_msglen < 1 ||
- ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
- }
- else
- {
- if( ssl->in_msglen < ssl->transform_in->minlen )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
- ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_IN_CONTENT_LEN )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-#endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
- defined(MBEDTLS_SSL_PROTO_TLS1_2)
- /*
- * TLS encrypted messages can have up to 256 bytes of padding
- */
- if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 &&
- ssl->in_msglen > ssl->transform_in->minlen +
- MBEDTLS_SSL_IN_CONTENT_LEN + 256 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-#endif
- }
-
- return( 0 );
-}
-
-/*
- * If applicable, decrypt (and decompress) record content
- */
-static int ssl_prepare_record_content( mbedtls_ssl_context *ssl )
-{
- int ret, done = 0;
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network",
- ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->in_msglen );
-
-#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 )
- {
- if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret );
- return( ret );
- }
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt",
- ssl->in_msg, ssl->in_msglen );
-
- if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
- }
-
-#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
-
- 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_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_ssl_handshake_params * const hs = ssl->handshake;
- size_t const rec_hdr_len = 13;
- size_t const total_buf_sz = rec_hdr_len + ssl->in_msglen;
-
- /* Don't buffer future records outside handshakes. */
- if( hs == NULL )
- return( 0 );
-
- /* Only buffer handshake records (we are only interested
- * in Finished messages). */
- if( ssl->in_msgtype != 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( total_buf_sz > ( 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) total_buf_sz, 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", ssl->in_hdr,
- rec_hdr_len + ssl->in_msglen );
-
- /* 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 = total_buf_sz;
-
- 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, ssl->in_hdr, total_buf_sz );
-
- hs->buffering.total_bytes_buffered += total_buf_sz;
- return( 0 );
-}
-
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-static int ssl_get_next_record( mbedtls_ssl_context *ssl )
-{
- int ret;
-
-#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 */
-
- if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
- return( ret );
- }
-
- if( ( ret = ssl_parse_record_header( ssl ) ) != 0 )
- {
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
- ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT )
- {
- if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
- {
- ret = ssl_buffer_future_record( ssl );
- 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 )
- {
- /* Skip unexpected record (but not whole datagram) */
- ssl->next_record_offset = ssl->in_msglen
- + mbedtls_ssl_hdr_len( ssl );
-
- 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 );
- }
-#endif
- return( ret );
- }
-
- /*
- * Read and optionally decrypt the message contents
- */
- if( ( ret = mbedtls_ssl_fetch_input( ssl,
- mbedtls_ssl_hdr_len( ssl ) + ssl->in_msglen ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
- return( ret );
- }
-
- /* Done reading this record, get ready for the next one */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- ssl->next_record_offset = ssl->in_msglen + mbedtls_ssl_hdr_len( ssl );
- if( ssl->next_record_offset < ssl->in_left )
- {
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) );
- }
- }
- else
-#endif
- ssl->in_left = 0;
-
- if( ( ret = ssl_prepare_record_content( ssl ) ) != 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_RECORD ||
- 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 );
- }
- }
-
- return( 0 );
-}
-
-int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
-{
- int ret;
-
- /*
- * 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 &&
- ssl->handshake != NULL &&
- ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
- {
- ssl_handshake_wrapup_free_hs_transform( ssl );
- }
-#endif
-
- return( 0 );
-}
-
-int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl )
-{
- int ret;
-
- if( ( ret = mbedtls_ssl_send_alert_message( ssl,
- MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ) != 0 )
- {
- return( ret );
- }
-
- return( 0 );
-}
-
-int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
- unsigned char level,
- unsigned char message )
-{
- int ret;
-
- 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 );
-}
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
/*
* Handshake functions
*/
-#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
- !defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_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)
+#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->transform_negotiate->ciphersuite_info;
+ const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+ ssl->handshake->ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) );
- if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
+ if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
ssl->state++;
@@ -5298,14 +2048,12 @@
int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
{
- const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+ const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+ ssl->handshake->ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
- if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
+ if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
ssl->state++;
@@ -5316,7 +2064,7 @@
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
-#else
+#else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
/* Some certificate support -> implement write and parse */
int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl )
@@ -5324,14 +2072,12 @@
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
size_t i, n;
const mbedtls_x509_crt *crt;
- const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
+ const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+ ssl->handshake->ciphersuite_info;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) );
- if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
+ if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
ssl->state++;
@@ -5435,63 +2181,68 @@
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 )
+static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl,
+ mbedtls_x509_crt *chain )
{
- int ret;
+ 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 defined(MBEDTLS_SSL_SRV_C)
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
- /*
- * Check if the client sent an empty certificate
- */
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
- {
- if( ssl->in_msglen == 2 &&
- ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT &&
- ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
- ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) );
-
- /* The client was asked for a certificate but didn't send
- one. The client should know what's going on, so we
- don't send an alert. */
- ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
- return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
- }
- }
-#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->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
- {
- if( ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) &&
- ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
- ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE &&
- memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) );
-
- /* The client was asked for a certificate but didn't send
- one. The client should know what's going on, so we
- don't send an alert. */
- ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
- return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
- }
- }
-#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
- MBEDTLS_SSL_PROTO_TLS1_2 */
-#endif /* MBEDTLS_SSL_SRV_C */
-
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
@@ -5525,43 +2276,32 @@
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
}
- /* In case we tried to reuse a session but it failed */
- if( ssl->session_negotiate->peer_cert != NULL )
- {
- mbedtls_x509_crt_free( ssl->session_negotiate->peer_cert );
- mbedtls_free( ssl->session_negotiate->peer_cert );
- }
-
- if( ( ssl->session_negotiate->peer_cert = mbedtls_calloc( 1,
- sizeof( mbedtls_x509_crt ) ) ) == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
- sizeof( mbedtls_x509_crt ) ) );
- mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
- return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
- }
-
- mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert );
-
+ /* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */
i += 3;
+ /* Iterate through and parse the CRTs in the provided chain. */
while( i < ssl->in_hslen )
{
+ /* Check that there's room for the next CRT's length fields. */
if ( i + 3 > ssl->in_hslen ) {
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 );
+ mbedtls_ssl_send_alert_message( ssl,
+ MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
}
+ /* In theory, the CRT can be up to 2**24 Bytes, but we don't support
+ * anything beyond 2**16 ~ 64K. */
if( ssl->in_msg[i] != 0 )
{
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 );
+ mbedtls_ssl_send_alert_message( ssl,
+ MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
}
+ /* Read length of the next CRT in the chain. */
n = ( (unsigned int) ssl->in_msg[i + 1] << 8 )
| (unsigned int) ssl->in_msg[i + 2];
i += 3;
@@ -5569,161 +2309,207 @@
if( n < 128 || i + n > ssl->in_hslen )
{
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 );
+ mbedtls_ssl_send_alert_message( ssl,
+ MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
}
- ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert,
- ssl->in_msg + i, n );
+ /* Check if we're handling the first CRT in the chain. */
+#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
+ if( crt_cnt++ == 0 &&
+ ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
+ ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
+ {
+ /* During client-side renegotiation, check that the server's
+ * end-CRTs hasn't changed compared to the initial handshake,
+ * mitigating the triple handshake attack. On success, reuse
+ * the original end-CRT instead of parsing it again. */
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Check that peer CRT hasn't changed during renegotiation" ) );
+ if( ssl_check_peer_crt_unchanged( ssl,
+ &ssl->in_msg[i],
+ n ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) );
+ mbedtls_ssl_send_alert_message( ssl,
+ MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
+ }
+
+ /* Now we can safely free the original chain. */
+ ssl_clear_peer_cert( ssl->session );
+ }
+#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
+
+ /* Parse the next certificate in the chain. */
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ ret = mbedtls_x509_crt_parse_der( chain, ssl->in_msg + i, n );
+#else
+ /* If we don't need to store the CRT chain permanently, parse
+ * it in-place from the input buffer instead of making a copy. */
+ ret = mbedtls_x509_crt_parse_der_nocopy( chain, ssl->in_msg + i, n );
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
switch( ret )
{
- case 0: /*ok*/
- case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND:
- /* Ignore certificate with an unknown algorithm: maybe a
- prior certificate was already trusted. */
- break;
+ case 0: /*ok*/
+ case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND:
+ /* Ignore certificate with an unknown algorithm: maybe a
+ prior certificate was already trusted. */
+ break;
- case MBEDTLS_ERR_X509_ALLOC_FAILED:
- alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR;
- goto crt_parse_der_failed;
+ case MBEDTLS_ERR_X509_ALLOC_FAILED:
+ alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR;
+ goto crt_parse_der_failed;
- case MBEDTLS_ERR_X509_UNKNOWN_VERSION:
- alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
- goto crt_parse_der_failed;
+ case MBEDTLS_ERR_X509_UNKNOWN_VERSION:
+ alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+ goto crt_parse_der_failed;
- default:
- alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
- crt_parse_der_failed:
- mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert );
- MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret );
- return( ret );
+ default:
+ alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
+ crt_parse_der_failed:
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert );
+ MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret );
+ return( ret );
}
i += n;
}
- MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert );
-
- /*
- * On client, make sure the server cert doesn't change during renego to
- * avoid "triple handshake" attack: https://secure-resumption.com/
- */
-#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
- ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
- {
- if( ssl->session->peer_cert == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) );
- mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED );
- return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
- }
-
- if( ssl->session->peer_cert->raw.len !=
- ssl->session_negotiate->peer_cert->raw.len ||
- memcmp( ssl->session->peer_cert->raw.p,
- ssl->session_negotiate->peer_cert->raw.p,
- ssl->session->peer_cert->raw.len ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) );
- mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED );
- return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
- }
- }
-#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
-
+ MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", chain );
return( 0 );
}
-int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
+#if defined(MBEDTLS_SSL_SRV_C)
+static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl )
{
- int ret;
- const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
- ssl->transform_negotiate->ciphersuite_info;
-#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
- const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
- ? ssl->handshake->sni_authmode
- : ssl->conf->authmode;
-#else
- const int authmode = ssl->conf->authmode;
-#endif
- void *rs_ctx = NULL;
+ if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
+ return( -1 );
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
-
- if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
+#if defined(MBEDTLS_SSL_PROTO_SSL3)
+ /*
+ * Check if the client sent an empty certificate
+ */
+ if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
{
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
- ssl->state++;
- return( 0 );
- }
-
-#if defined(MBEDTLS_SSL_SRV_C)
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
- ssl->state++;
- return( 0 );
- }
-
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- authmode == MBEDTLS_SSL_VERIFY_NONE )
- {
- ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY;
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
-
- ssl->state++;
- return( 0 );
- }
-#endif
-
-#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
- if( ssl->handshake->ecrs_enabled &&
- ssl->handshake->ecrs_state == ssl_ecrs_crt_verify )
- {
- goto crt_verify;
- }
-#endif
-
- if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
- {
- /* mbedtls_ssl_read_record may have sent an alert already. We
- let it decide whether to alert. */
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
- return( ret );
- }
-
- if( ( ret = ssl_parse_certificate_chain( ssl ) ) != 0 )
- {
-#if defined(MBEDTLS_SSL_SRV_C)
- if( ret == MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE &&
- authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
+ if( ssl->in_msglen == 2 &&
+ ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT &&
+ ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
+ ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT )
{
- ret = 0;
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) );
+ return( 0 );
}
-#endif
- ssl->state++;
- return( ret );
+ return( -1 );
+ }
+#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->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) &&
+ ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+ ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE &&
+ memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) );
+ return( 0 );
}
-#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
- if( ssl->handshake->ecrs_enabled)
- ssl->handshake->ecrs_state = ssl_ecrs_crt_verify;
+ return( -1 );
+#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
+ MBEDTLS_SSL_PROTO_TLS1_2 */
+}
+#endif /* MBEDTLS_SSL_SRV_C */
-crt_verify:
- if( ssl->handshake->ecrs_enabled)
- rs_ctx = &ssl->handshake->ecrs_ctx;
-#endif
+/* Check if a certificate message is expected.
+ * Return either
+ * - SSL_CERTIFICATE_EXPECTED, or
+ * - SSL_CERTIFICATE_SKIP
+ * indicating whether a Certificate message is expected or not.
+ */
+#define SSL_CERTIFICATE_EXPECTED 0
+#define SSL_CERTIFICATE_SKIP 1
+static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl,
+ int authmode )
+{
+ const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+ ssl->handshake->ciphersuite_info;
- if( authmode != MBEDTLS_SSL_VERIFY_NONE )
+ if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) )
+ return( SSL_CERTIFICATE_SKIP );
+
+#if defined(MBEDTLS_SSL_SRV_C)
+ if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
+ {
+ if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
+ return( SSL_CERTIFICATE_SKIP );
+
+ if( authmode == MBEDTLS_SSL_VERIFY_NONE )
+ {
+ ssl->session_negotiate->verify_result =
+ MBEDTLS_X509_BADCERT_SKIP_VERIFY;
+ return( SSL_CERTIFICATE_SKIP );
+ }
+ }
+#else
+ ((void) authmode);
+#endif /* MBEDTLS_SSL_SRV_C */
+
+ return( SSL_CERTIFICATE_EXPECTED );
+}
+
+static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
+ int authmode,
+ mbedtls_x509_crt *chain,
+ void *rs_ctx )
+{
+ int ret = 0;
+ const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+ ssl->handshake->ciphersuite_info;
+ int have_ca_chain = 0;
+
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *);
+ void *p_vrfy;
+
+ if( authmode == MBEDTLS_SSL_VERIFY_NONE )
+ return( 0 );
+
+ if( ssl->f_vrfy != NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use context-specific verification callback" ) );
+ f_vrfy = ssl->f_vrfy;
+ p_vrfy = ssl->p_vrfy;
+ }
+ else
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use configuration-specific verification callback" ) );
+ f_vrfy = ssl->conf->f_vrfy;
+ p_vrfy = ssl->conf->p_vrfy;
+ }
+
+ /*
+ * Main check: verify certificate
+ */
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+ if( ssl->conf->f_ca_cb != NULL )
+ {
+ ((void) rs_ctx);
+ have_ca_chain = 1;
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "use CA callback for X.509 CRT verification" ) );
+ ret = mbedtls_x509_crt_verify_with_ca_cb(
+ chain,
+ ssl->conf->f_ca_cb,
+ ssl->conf->p_ca_cb,
+ ssl->conf->cert_profile,
+ ssl->hostname,
+ &ssl->session_negotiate->verify_result,
+ f_vrfy, p_vrfy );
+ }
+ else
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
{
mbedtls_x509_crt *ca_chain;
mbedtls_x509_crl *ca_crl;
@@ -5741,232 +2527,329 @@
ca_crl = ssl->conf->ca_crl;
}
- /*
- * Main check: verify certificate
- */
+ if( ca_chain != NULL )
+ have_ca_chain = 1;
+
ret = mbedtls_x509_crt_verify_restartable(
- ssl->session_negotiate->peer_cert,
- ca_chain, ca_crl,
- ssl->conf->cert_profile,
- ssl->hostname,
- &ssl->session_negotiate->verify_result,
- ssl->conf->f_vrfy, ssl->conf->p_vrfy, rs_ctx );
+ chain,
+ ca_chain, ca_crl,
+ ssl->conf->cert_profile,
+ ssl->hostname,
+ &ssl->session_negotiate->verify_result,
+ f_vrfy, p_vrfy, rs_ctx );
+ }
- if( ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
- }
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
+ }
-#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
- if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
- return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS );
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+ if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
+ return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS );
#endif
- /*
- * Secondary checks: always done, but change 'ret' only if it was 0
- */
+ /*
+ * Secondary checks: always done, but change 'ret' only if it was 0
+ */
#if defined(MBEDTLS_ECP_C)
+ {
+ const mbedtls_pk_context *pk = &chain->pk;
+
+ /* If certificate uses an EC key, make sure the curve is OK */
+ if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) &&
+ mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 )
{
- const mbedtls_pk_context *pk = &ssl->session_negotiate->peer_cert->pk;
+ ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY;
- /* If certificate uses an EC key, make sure the curve is OK */
- if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) &&
- mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 )
- {
- ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY;
-
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) );
- if( ret == 0 )
- ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
- }
- }
-#endif /* MBEDTLS_ECP_C */
-
- if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert,
- ciphersuite_info,
- ! ssl->conf->endpoint,
- &ssl->session_negotiate->verify_result ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) );
if( ret == 0 )
ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
}
+ }
+#endif /* MBEDTLS_ECP_C */
- /* mbedtls_x509_crt_verify_with_profile is supposed to report a
- * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED,
- * with details encoded in the verification flags. All other kinds
- * of error codes, including those from the user provided f_vrfy
- * functions, are treated as fatal and lead to a failure of
- * ssl_parse_certificate even if verification was optional. */
- if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
- ( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
- ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) )
- {
- ret = 0;
- }
-
- if( ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) );
- ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
- }
-
- if( ret != 0 )
- {
- uint8_t alert;
-
- /* The certificate may have been rejected for several reasons.
- Pick one and send the corresponding alert. Which alert to send
- may be a subject of debate in some cases. */
- if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER )
- alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED;
- else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH )
- alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
- else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE )
- alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
- else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE )
- alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
- else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE )
- alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
- else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK )
- alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
- else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY )
- alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
- else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED )
- alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED;
- else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED )
- alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED;
- else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED )
- alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA;
- else
- alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN;
- mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- alert );
- }
-
-#if defined(MBEDTLS_DEBUG_C)
- if( ssl->session_negotiate->verify_result != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %x",
- ssl->session_negotiate->verify_result ) );
- }
- else
- {
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) );
- }
-#endif /* MBEDTLS_DEBUG_C */
+ if( mbedtls_ssl_check_cert_usage( chain,
+ ciphersuite_info,
+ ! ssl->conf->endpoint,
+ &ssl->session_negotiate->verify_result ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) );
+ if( ret == 0 )
+ ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE;
}
- ssl->state++;
+ /* mbedtls_x509_crt_verify_with_profile is supposed to report a
+ * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED,
+ * with details encoded in the verification flags. All other kinds
+ * of error codes, including those from the user provided f_vrfy
+ * functions, are treated as fatal and lead to a failure of
+ * ssl_parse_certificate even if verification was optional. */
+ if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
+ ( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
+ ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) )
+ {
+ ret = 0;
+ }
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
+ if( have_ca_chain == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) );
+ ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
+ }
+
+ if( ret != 0 )
+ {
+ uint8_t alert;
+
+ /* The certificate may have been rejected for several reasons.
+ Pick one and send the corresponding alert. Which alert to send
+ may be a subject of debate in some cases. */
+ if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER )
+ alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED;
+ else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH )
+ alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
+ else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE )
+ alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+ else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE )
+ alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+ else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE )
+ alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+ else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK )
+ alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+ else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY )
+ alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+ else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED )
+ alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED;
+ else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED )
+ alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED;
+ else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED )
+ alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA;
+ else
+ alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN;
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ alert );
+ }
+
+#if defined(MBEDTLS_DEBUG_C)
+ if( ssl->session_negotiate->verify_result != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %x",
+ ssl->session_negotiate->verify_result ) );
+ }
+ else
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) );
+ }
+#endif /* MBEDTLS_DEBUG_C */
return( ret );
}
-#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
- !MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
- !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
- !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
- !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
- !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
- !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
-int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl )
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl,
+ unsigned char *start, size_t len )
{
- int ret;
-
- 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 )
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ /* Remember digest of the peer's end-CRT. */
+ ssl->session_negotiate->peer_cert_digest =
+ mbedtls_calloc( 1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN );
+ if( ssl->session_negotiate->peer_cert_digest == NULL )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
- return( ret );
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
+ MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN ) );
+ mbedtls_ssl_send_alert_message( ssl,
+ MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
+
+ return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
}
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) );
+ ret = mbedtls_md( mbedtls_md_info_from_type(
+ MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE ),
+ start, len,
+ ssl->session_negotiate->peer_cert_digest );
+
+ ssl->session_negotiate->peer_cert_digest_type =
+ MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE;
+ ssl->session_negotiate->peer_cert_digest_len =
+ MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN;
+
+ return( ret );
+}
+
+static int ssl_remember_peer_pubkey( mbedtls_ssl_context *ssl,
+ unsigned char *start, size_t len )
+{
+ unsigned char *end = start + len;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ /* Make a copy of the peer's raw public key. */
+ mbedtls_pk_init( &ssl->handshake->peer_pubkey );
+ ret = mbedtls_pk_parse_subpubkey( &start, end,
+ &ssl->handshake->peer_pubkey );
+ if( ret != 0 )
+ {
+ /* We should have parsed the public key before. */
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
return( 0 );
}
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = 0;
+ int crt_expected;
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+ const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
+ ? ssl->handshake->sni_authmode
+ : ssl->conf->authmode;
+#else
+ const int authmode = ssl->conf->authmode;
+#endif
+ void *rs_ctx = NULL;
+ mbedtls_x509_crt *chain = NULL;
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
+
+ crt_expected = ssl_parse_certificate_coordinate( ssl, authmode );
+ if( crt_expected == SSL_CERTIFICATE_SKIP )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
+ goto exit;
+ }
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+ if( ssl->handshake->ecrs_enabled &&
+ ssl->handshake->ecrs_state == ssl_ecrs_crt_verify )
+ {
+ chain = ssl->handshake->ecrs_peer_cert;
+ ssl->handshake->ecrs_peer_cert = NULL;
+ goto crt_verify;
+ }
+#endif
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
{
+ /* mbedtls_ssl_read_record may have sent an alert already. We
+ let it decide whether to alert. */
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
- return( ret );
+ goto exit;
}
- if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
+#if defined(MBEDTLS_SSL_SRV_C)
+ if( ssl_srv_check_client_no_crt_notification( ssl ) == 0 )
{
- 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 );
+ ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
+
+ if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
+ ret = 0;
+ else
+ ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE;
+
+ goto exit;
}
+#endif /* MBEDTLS_SSL_SRV_C */
- /* CCS records are only accepted if they have length 1 and content '1',
- * so we don't need to check this here. */
+ /* Clear existing peer CRT structure in case we tried to
+ * reuse a session but it failed, and allocate a new one. */
+ ssl_clear_peer_cert( ssl->session_negotiate );
- /*
- * 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 )
+ chain = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
+ if( chain == NULL )
{
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
- ssl_dtls_replay_reset( ssl );
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
+ sizeof( mbedtls_x509_crt ) ) );
+ mbedtls_ssl_send_alert_message( ssl,
+ MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
+
+ ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ goto exit;
+ }
+ mbedtls_x509_crt_init( chain );
+
+ ret = ssl_parse_certificate_chain( ssl, chain );
+ if( ret != 0 )
+ goto exit;
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+ if( ssl->handshake->ecrs_enabled)
+ ssl->handshake->ecrs_state = ssl_ecrs_crt_verify;
+
+crt_verify:
+ if( ssl->handshake->ecrs_enabled)
+ rs_ctx = &ssl->handshake->ecrs_ctx;
#endif
- /* 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 );
+ ret = ssl_parse_certificate_verify( ssl, authmode,
+ chain, rs_ctx );
+ if( ret != 0 )
+ goto exit;
- ssl_update_in_pointers( ssl, ssl->transform_negotiate );
-
-#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
- if( mbedtls_ssl_hw_record_activate != NULL )
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
{
- 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 );
- }
+ unsigned char *crt_start, *pk_start;
+ size_t crt_len, pk_len;
+
+ /* We parse the CRT chain without copying, so
+ * these pointers point into the input buffer,
+ * and are hence still valid after freeing the
+ * CRT chain. */
+
+ crt_start = chain->raw.p;
+ crt_len = chain->raw.len;
+
+ pk_start = chain->pk_raw.p;
+ pk_len = chain->pk_raw.len;
+
+ /* Free the CRT structures before computing
+ * digest and copying the peer's public key. */
+ mbedtls_x509_crt_free( chain );
+ mbedtls_free( chain );
+ chain = NULL;
+
+ ret = ssl_remember_peer_crt_digest( ssl, crt_start, crt_len );
+ if( ret != 0 )
+ goto exit;
+
+ ret = ssl_remember_peer_pubkey( ssl, pk_start, pk_len );
+ if( ret != 0 )
+ goto exit;
+ }
+#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+ /* Pass ownership to session structure. */
+ ssl->session_negotiate->peer_cert = chain;
+ chain = NULL;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
+
+exit:
+
+ if( ret == 0 )
+ ssl->state++;
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+ if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS )
+ {
+ ssl->handshake->ecrs_peer_cert = chain;
+ chain = NULL;
}
#endif
- ssl->state++;
+ if( chain != NULL )
+ {
+ mbedtls_x509_crt_free( chain );
+ mbedtls_free( chain );
+ }
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) );
-
- return( 0 );
+ return( ret );
}
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl,
const mbedtls_ssl_ciphersuite_t *ciphersuite_info )
@@ -6006,11 +2889,21 @@
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ psa_hash_abort( &ssl->handshake->fin_sha256_psa );
+ psa_hash_setup( &ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256 );
+#else
mbedtls_sha256_starts_ret( &ssl->handshake->fin_sha256, 0 );
#endif
+#endif
#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ psa_hash_abort( &ssl->handshake->fin_sha384_psa );
+ psa_hash_setup( &ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384 );
+#else
mbedtls_sha512_starts_ret( &ssl->handshake->fin_sha512, 1 );
#endif
+#endif
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
}
@@ -6024,11 +2917,19 @@
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ psa_hash_update( &ssl->handshake->fin_sha256_psa, buf, len );
+#else
mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len );
#endif
+#endif
#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ psa_hash_update( &ssl->handshake->fin_sha384_psa, buf, len );
+#else
mbedtls_sha512_update_ret( &ssl->handshake->fin_sha512, buf, len );
#endif
+#endif
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
}
@@ -6047,7 +2948,11 @@
static void ssl_update_checksum_sha256( mbedtls_ssl_context *ssl,
const unsigned char *buf, size_t len )
{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ psa_hash_update( &ssl->handshake->fin_sha256_psa, buf, len );
+#else
mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len );
+#endif
}
#endif
@@ -6055,7 +2960,11 @@
static void ssl_update_checksum_sha384( mbedtls_ssl_context *ssl,
const unsigned char *buf, size_t len )
{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ psa_hash_update( &ssl->handshake->fin_sha384_psa, buf, len );
+#else
mbedtls_sha512_update_ret( &ssl->handshake->fin_sha512, buf, len );
+#endif
}
#endif
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
@@ -6211,13 +3120,44 @@
{
int len = 12;
const char *sender;
- mbedtls_sha256_context sha256;
unsigned char padbuf[32];
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ size_t hash_size;
+ psa_hash_operation_t sha256_psa = PSA_HASH_OPERATION_INIT;
+ psa_status_t status;
+#else
+ mbedtls_sha256_context sha256;
+#endif
mbedtls_ssl_session *session = ssl->session_negotiate;
if( !session )
session = ssl->session;
+ sender = ( from == MBEDTLS_SSL_IS_CLIENT )
+ ? "client finished"
+ : "server finished";
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ sha256_psa = psa_hash_operation_init();
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc PSA finished tls sha256" ) );
+
+ status = psa_hash_clone( &ssl->handshake->fin_sha256_psa, &sha256_psa );
+ if( status != PSA_SUCCESS )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) );
+ return;
+ }
+
+ status = psa_hash_finish( &sha256_psa, padbuf, sizeof( padbuf ), &hash_size );
+ if( status != PSA_SUCCESS )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) );
+ return;
+ }
+ MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated padbuf", padbuf, 32 );
+#else
+
mbedtls_sha256_init( &sha256 );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) );
@@ -6235,19 +3175,15 @@
sha256.state, sizeof( sha256.state ) );
#endif
- sender = ( from == MBEDTLS_SSL_IS_CLIENT )
- ? "client finished"
- : "server finished";
-
mbedtls_sha256_finish_ret( &sha256, padbuf );
+ mbedtls_sha256_free( &sha256 );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
ssl->handshake->tls_prf( session->master, 48, sender,
padbuf, 32, buf, len );
MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
- mbedtls_sha256_free( &sha256 );
-
mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
@@ -6260,13 +3196,43 @@
{
int len = 12;
const char *sender;
- mbedtls_sha512_context sha512;
unsigned char padbuf[48];
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ size_t hash_size;
+ psa_hash_operation_t sha384_psa = PSA_HASH_OPERATION_INIT;
+ psa_status_t status;
+#else
+ mbedtls_sha512_context sha512;
+#endif
mbedtls_ssl_session *session = ssl->session_negotiate;
if( !session )
session = ssl->session;
+ sender = ( from == MBEDTLS_SSL_IS_CLIENT )
+ ? "client finished"
+ : "server finished";
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ sha384_psa = psa_hash_operation_init();
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc PSA finished tls sha384" ) );
+
+ status = psa_hash_clone( &ssl->handshake->fin_sha384_psa, &sha384_psa );
+ if( status != PSA_SUCCESS )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) );
+ return;
+ }
+
+ status = psa_hash_finish( &sha384_psa, padbuf, sizeof( padbuf ), &hash_size );
+ if( status != PSA_SUCCESS )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) );
+ return;
+ }
+ MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated padbuf", padbuf, 48 );
+#else
mbedtls_sha512_init( &sha512 );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) );
@@ -6284,19 +3250,15 @@
sha512.state, sizeof( sha512.state ) );
#endif
- sender = ( from == MBEDTLS_SSL_IS_CLIENT )
- ? "client finished"
- : "server finished";
-
mbedtls_sha512_finish_ret( &sha512, padbuf );
+ mbedtls_sha512_free( &sha512 );
+#endif
ssl->handshake->tls_prf( session->master, 48, sender,
padbuf, 48, buf, len );
MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len );
- mbedtls_sha512_free( &sha512 );
-
mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) );
@@ -6304,7 +3266,7 @@
#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" ) );
@@ -6376,7 +3338,7 @@
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 */
@@ -6384,7 +3346,7 @@
}
else
#endif
- ssl_handshake_wrapup_free_hs_transform( ssl );
+ mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl );
ssl->state++;
@@ -6397,7 +3359,7 @@
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 );
@@ -6517,7 +3479,7 @@
int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned int hash_len;
unsigned char buf[SSL_MAX_HASH_LEN];
@@ -6607,19 +3569,29 @@
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ handshake->fin_sha256_psa = psa_hash_operation_init();
+ psa_hash_setup( &handshake->fin_sha256_psa, PSA_ALG_SHA_256 );
+#else
mbedtls_sha256_init( &handshake->fin_sha256 );
mbedtls_sha256_starts_ret( &handshake->fin_sha256, 0 );
#endif
+#endif
#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ handshake->fin_sha384_psa = psa_hash_operation_init();
+ psa_hash_setup( &handshake->fin_sha384_psa, PSA_ALG_SHA_384 );
+#else
mbedtls_sha512_init( &handshake->fin_sha512 );
mbedtls_sha512_starts_ret( &handshake->fin_sha512, 1 );
#endif
+#endif
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
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
@@ -6637,24 +3609,31 @@
#endif
#endif
-#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
mbedtls_x509_crt_restart_init( &handshake->ecrs_ctx );
#endif
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET;
#endif
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ mbedtls_pk_init( &handshake->peer_pubkey );
+#endif
}
-static void ssl_transform_init( mbedtls_ssl_transform *transform )
+void mbedtls_ssl_transform_init( mbedtls_ssl_transform *transform )
{
memset( transform, 0, sizeof(mbedtls_ssl_transform) );
mbedtls_cipher_init( &transform->cipher_ctx_enc );
mbedtls_cipher_init( &transform->cipher_ctx_dec );
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
mbedtls_md_init( &transform->md_ctx_enc );
mbedtls_md_init( &transform->md_ctx_dec );
+#endif
}
void mbedtls_ssl_session_init( mbedtls_ssl_session *session )
@@ -6690,6 +3669,58 @@
{
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 ||
@@ -6711,7 +3742,7 @@
/* Initialize structures */
mbedtls_ssl_session_init( ssl->session_negotiate );
- ssl_transform_init( ssl->transform_negotiate );
+ mbedtls_ssl_transform_init( ssl->transform_negotiate );
ssl_handshake_params_init( ssl->handshake );
#if defined(MBEDTLS_SSL_PROTO_DTLS)
@@ -6724,7 +3755,7 @@
else
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;
- ssl_set_timer( ssl, 0 );
+ mbedtls_ssl_set_timer( ssl, 0 );
}
#endif
@@ -6760,78 +3791,6 @@
}
#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;
- ssl->out_len = ssl->out_hdr + 11;
- ssl->out_iv = ssl->out_hdr + 13;
- }
- else
-#endif
- {
- ssl->out_ctr = ssl->out_hdr - 8;
- ssl->out_len = ssl->out_hdr + 3;
- 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,
- mbedtls_ssl_transform *transform )
-{
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- ssl->in_ctr = ssl->in_hdr + 3;
- ssl->in_len = ssl->in_hdr + 11;
- ssl->in_iv = ssl->in_hdr + 13;
- }
- else
-#endif
- {
- ssl->in_ctr = ssl->in_hdr - 8;
- ssl->in_len = ssl->in_hdr + 3;
- ssl->in_iv = ssl->in_hdr + 5;
- }
-
- /* Offset in_msg from in_iv to allow space for explicit IV, if used. */
- if( transform != NULL &&
- ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- ssl->in_msg = ssl->in_iv + transform->ivlen - transform->fixed_ivlen;
- }
- else
- ssl->in_msg = ssl->in_iv;
-}
-
/*
* Initialize an SSL context
*/
@@ -6844,31 +3803,12 @@
* 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, NULL /* no transform enabled */ );
-}
-
int mbedtls_ssl_setup( mbedtls_ssl_context *ssl,
const mbedtls_ssl_config *conf )
{
- int ret;
+ 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;
@@ -6879,23 +3819,29 @@
/* 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;
@@ -6908,6 +3854,10 @@
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;
@@ -6933,9 +3883,16 @@
* 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;
+ 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)
@@ -6945,7 +3902,7 @@
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;
@@ -6958,7 +3915,7 @@
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;
@@ -6967,7 +3924,7 @@
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;
@@ -6991,14 +3948,14 @@
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)
@@ -7054,7 +4011,7 @@
*/
int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl )
{
- return( ssl_session_reset_int( ssl, 0 ) );
+ return( mbedtls_ssl_session_reset_int( ssl, 0 ) );
}
/*
@@ -7165,7 +4122,7 @@
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)
@@ -7183,7 +4140,7 @@
#if defined(MBEDTLS_SSL_CLI_C)
int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ssl == NULL ||
session == NULL ||
@@ -7193,7 +4150,8 @@
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
- if( ( ret = ssl_session_copy( ssl->session_negotiate, session ) ) != 0 )
+ if( ( ret = mbedtls_ssl_session_copy( ssl->session_negotiate,
+ session ) ) != 0 )
return( ret );
ssl->handshake->resume = 1;
@@ -7275,7 +4233,29 @@
{
conf->ca_chain = ca_chain;
conf->ca_crl = ca_crl;
+
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+ /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb()
+ * cannot be used together. */
+ conf->f_ca_cb = NULL;
+ conf->p_ca_cb = NULL;
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
}
+
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf,
+ mbedtls_x509_crt_ca_cb_t f_ca_cb,
+ void *p_ca_cb )
+{
+ conf->f_ca_cb = f_ca_cb;
+ conf->p_ca_cb = p_ca_cb;
+
+ /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb()
+ * cannot be used together. */
+ conf->ca_chain = NULL;
+ conf->ca_crl = NULL;
+}
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
@@ -7302,6 +4282,16 @@
}
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+void mbedtls_ssl_set_verify( mbedtls_ssl_context *ssl,
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+ void *p_vrfy )
+{
+ ssl->f_vrfy = f_vrfy;
+ ssl->p_vrfy = p_vrfy;
+}
+#endif
+
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
/*
* Set EC J-PAKE password for current handshake
@@ -7328,24 +4318,24 @@
}
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
-int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf,
- const unsigned char *psk, size_t psk_len,
- const unsigned char *psk_identity, size_t psk_identity_len )
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+
+static void ssl_conf_remove_psk( mbedtls_ssl_config *conf )
{
- if( psk == NULL || psk_identity == NULL )
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
- if( psk_len > MBEDTLS_PSK_MAX_LEN )
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
- /* Identity len will be encoded on two bytes */
- if( ( psk_identity_len >> 16 ) != 0 ||
- psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
+ /* Remove reference to existing PSK, if any. */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( conf->psk_opaque != 0 )
{
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ /* The maintenance of the PSK key slot is the
+ * user's responsibility. */
+ conf->psk_opaque = 0;
}
-
+ /* This and the following branch should never
+ * be taken simultaenously as we maintain the
+ * invariant that raw and opaque PSKs are never
+ * configured simultaneously. As a safeguard,
+ * though, `else` is omitted here. */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( conf->psk != NULL )
{
mbedtls_platform_zeroize( conf->psk, conf->psk_len );
@@ -7354,32 +4344,89 @@
conf->psk = NULL;
conf->psk_len = 0;
}
+
+ /* Remove reference to PSK identity, if any. */
if( conf->psk_identity != NULL )
{
mbedtls_free( conf->psk_identity );
conf->psk_identity = NULL;
conf->psk_identity_len = 0;
}
+}
- if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ||
- ( conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ) ) == NULL )
+/* This function assumes that PSK identity in the SSL config is unset.
+ * It checks that the provided identity is well-formed and attempts
+ * to make a copy of it in the SSL config.
+ * On failure, the PSK identity in the config remains unset. */
+static int ssl_conf_set_psk_identity( mbedtls_ssl_config *conf,
+ unsigned char const *psk_identity,
+ size_t psk_identity_len )
+{
+ /* Identity len will be encoded on two bytes */
+ if( psk_identity == NULL ||
+ ( psk_identity_len >> 16 ) != 0 ||
+ psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
{
- mbedtls_free( conf->psk );
- mbedtls_free( conf->psk_identity );
- conf->psk = NULL;
- conf->psk_identity = NULL;
- return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
- conf->psk_len = psk_len;
- conf->psk_identity_len = psk_identity_len;
+ conf->psk_identity = mbedtls_calloc( 1, psk_identity_len );
+ if( conf->psk_identity == NULL )
+ return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
- memcpy( conf->psk, psk, conf->psk_len );
+ conf->psk_identity_len = psk_identity_len;
memcpy( conf->psk_identity, psk_identity, conf->psk_identity_len );
return( 0 );
}
+int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf,
+ const unsigned char *psk, size_t psk_len,
+ const unsigned char *psk_identity, size_t psk_identity_len )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ /* Remove opaque/raw PSK + PSK Identity */
+ ssl_conf_remove_psk( conf );
+
+ /* Check and set raw PSK */
+ if( psk == NULL )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ if( psk_len == 0 )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ if( psk_len > MBEDTLS_PSK_MAX_LEN )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL )
+ return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+ conf->psk_len = psk_len;
+ memcpy( conf->psk, psk, conf->psk_len );
+
+ /* Check and set PSK Identity */
+ ret = ssl_conf_set_psk_identity( conf, psk_identity, psk_identity_len );
+ if( ret != 0 )
+ ssl_conf_remove_psk( conf );
+
+ return( ret );
+}
+
+static void ssl_remove_psk( mbedtls_ssl_context *ssl )
+{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( ssl->handshake->psk_opaque != 0 )
+ {
+ ssl->handshake->psk_opaque = 0;
+ }
+ else
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+ if( ssl->handshake->psk != NULL )
+ {
+ mbedtls_platform_zeroize( ssl->handshake->psk,
+ ssl->handshake->psk_len );
+ mbedtls_free( ssl->handshake->psk );
+ ssl->handshake->psk_len = 0;
+ }
+}
+
int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl,
const unsigned char *psk, size_t psk_len )
{
@@ -7389,13 +4436,7 @@
if( psk_len > MBEDTLS_PSK_MAX_LEN )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- if( ssl->handshake->psk != NULL )
- {
- mbedtls_platform_zeroize( ssl->handshake->psk,
- ssl->handshake->psk_len );
- mbedtls_free( ssl->handshake->psk );
- ssl->handshake->psk_len = 0;
- }
+ ssl_remove_psk( ssl );
if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL )
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
@@ -7406,6 +4447,42 @@
return( 0 );
}
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf,
+ psa_key_handle_t psk_slot,
+ const unsigned char *psk_identity,
+ size_t psk_identity_len )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ /* Clear opaque/raw PSK + PSK Identity, if present. */
+ ssl_conf_remove_psk( conf );
+
+ /* Check and set opaque PSK */
+ if( psk_slot == 0 )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ conf->psk_opaque = psk_slot;
+
+ /* Check and set PSK Identity */
+ ret = ssl_conf_set_psk_identity( conf, psk_identity,
+ psk_identity_len );
+ if( ret != 0 )
+ ssl_conf_remove_psk( conf );
+
+ return( ret );
+}
+
+int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl,
+ psa_key_handle_t psk_slot )
+{
+ if( psk_slot == 0 || ssl->handshake == NULL )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ ssl_remove_psk( ssl );
+ ssl->handshake->psk_opaque = psk_slot;
+ return( 0 );
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf,
int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *,
size_t),
@@ -7414,14 +4491,14 @@
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)
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_mpi_read_string( &conf->dhm_P, 16, dhm_P ) ) != 0 ||
( ret = mbedtls_mpi_read_string( &conf->dhm_G, 16, dhm_G ) ) != 0 )
@@ -7439,7 +4516,7 @@
const unsigned char *dhm_P, size_t P_len,
const unsigned char *dhm_G, size_t G_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_mpi_read_binary( &conf->dhm_P, dhm_P, P_len ) ) != 0 ||
( ret = mbedtls_mpi_read_binary( &conf->dhm_G, dhm_G, G_len ) ) != 0 )
@@ -7454,7 +4531,7 @@
int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_mpi_copy( &conf->dhm_P, &dhm_ctx->P ) ) != 0 ||
( ret = mbedtls_mpi_copy( &conf->dhm_G, &dhm_ctx->G ) ) != 0 )
@@ -7479,7 +4556,7 @@
}
#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
*/
@@ -7488,7 +4565,7 @@
{
conf->sig_hashes = hashes;
}
-#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#if defined(MBEDTLS_ECP_C)
/*
@@ -7719,6 +4796,14 @@
conf->f_export_keys = f_export_keys;
conf->p_export_keys = p_export_keys;
}
+
+void mbedtls_ssl_conf_export_keys_ext_cb( mbedtls_ssl_config *conf,
+ mbedtls_ssl_export_keys_ext_t *f_export_keys_ext,
+ void *p_export_keys )
+{
+ conf->f_export_keys_ext = f_export_keys_ext;
+ conf->p_export_keys = p_export_keys;
+}
#endif
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
@@ -7761,66 +4846,6 @@
/*
* 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 )
@@ -7878,61 +4903,43 @@
}
}
-int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl )
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+size_t mbedtls_ssl_get_input_max_frag_len( const mbedtls_ssl_context *ssl )
{
- size_t transform_expansion = 0;
- const mbedtls_ssl_transform *transform = ssl->transform_out;
- unsigned block_size;
+ size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN;
+ size_t read_mfl;
- if( transform == NULL )
- return( (int) mbedtls_ssl_hdr_len( ssl ) );
-
-#if defined(MBEDTLS_ZLIB_SUPPORT)
- if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL )
- return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
-#endif
-
- switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) )
+ /* Use the configured MFL for the client if we're past SERVER_HELLO_DONE */
+ if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
+ ssl->state >= MBEDTLS_SSL_SERVER_HELLO_DONE )
{
- case MBEDTLS_MODE_GCM:
- case MBEDTLS_MODE_CCM:
- case MBEDTLS_MODE_CHACHAPOLY:
- case MBEDTLS_MODE_STREAM:
- transform_expansion = transform->minlen;
- break;
-
- case MBEDTLS_MODE_CBC:
-
- block_size = mbedtls_cipher_get_block_size(
- &transform->cipher_ctx_enc );
-
- /* Expansion due to the addition of the MAC. */
- transform_expansion += transform->maclen;
-
- /* Expansion due to the addition of CBC padding;
- * Theoretically up to 256 bytes, but we never use
- * more than the block size of the underlying cipher. */
- transform_expansion += block_size;
-
- /* For TLS 1.1 or higher, an explicit IV is added
- * after the record header. */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
- transform_expansion += block_size;
-#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
-
- break;
-
- default:
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ return ssl_mfl_code_to_length( ssl->conf->mfl_code );
}
- return( (int)( mbedtls_ssl_hdr_len( ssl ) + transform_expansion ) );
+ /* 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;
+ }
+ }
+
+ // During a handshake, use the value being negotiated
+ if( ssl->session_negotiate != NULL )
+ {
+ read_mfl = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code );
+ if( read_mfl < max_len )
+ {
+ max_len = read_mfl;
+ }
+ }
+
+ return( max_len );
}
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl )
+size_t mbedtls_ssl_get_output_max_frag_len( const mbedtls_ssl_context *ssl )
{
size_t max_len;
@@ -7957,10 +4964,17 @@
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 &&
@@ -7989,16 +5003,16 @@
#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;
@@ -8030,12 +5044,17 @@
if( ssl == NULL || ssl->session == NULL )
return( NULL );
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
return( ssl->session->peer_cert );
+#else
+ return( NULL );
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
}
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL_CLI_C)
-int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *dst )
+int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl,
+ mbedtls_ssl_session *dst )
{
if( ssl == NULL ||
dst == NULL ||
@@ -8045,10 +5064,577 @@
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
}
- return( ssl_session_copy( dst, ssl->session ) );
+ return( mbedtls_ssl_session_copy( dst, ssl->session ) );
}
#endif /* MBEDTLS_SSL_CLI_C */
+const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_context *ssl )
+{
+ if( ssl == NULL )
+ return( NULL );
+
+ return( ssl->session );
+}
+
+/*
+ * Define ticket header determining Mbed TLS version
+ * and structure of the ticket.
+ */
+
+/*
+ * Define bitflag determining compile-time settings influencing
+ * structure of serialized SSL sessions.
+ */
+
+#if defined(MBEDTLS_HAVE_TIME)
+#define SSL_SERIALIZED_SESSION_CONFIG_TIME 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_TIME 0
+#endif /* MBEDTLS_HAVE_TIME */
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#define SSL_SERIALIZED_SESSION_CONFIG_CRT 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_CRT 0
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SESSION_TICKETS)
+#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 0
+#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SESSION_TICKETS */
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+#define SSL_SERIALIZED_SESSION_CONFIG_MFL 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_MFL 0
+#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+
+#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
+#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC 0
+#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+#define SSL_SERIALIZED_SESSION_CONFIG_ETM 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_ETM 0
+#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 0
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT 0
+#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT 1
+#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2
+#define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT 3
+#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT 4
+#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 5
+#define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT 6
+
+#define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG \
+ ( (uint16_t) ( \
+ ( SSL_SERIALIZED_SESSION_CONFIG_TIME << SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT ) | \
+ ( SSL_SERIALIZED_SESSION_CONFIG_CRT << SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT ) | \
+ ( SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET << SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT ) | \
+ ( SSL_SERIALIZED_SESSION_CONFIG_MFL << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT ) | \
+ ( SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC << SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT ) | \
+ ( SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT ) | \
+ ( SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT ) ) )
+
+static unsigned char ssl_serialized_session_header[] = {
+ MBEDTLS_VERSION_MAJOR,
+ MBEDTLS_VERSION_MINOR,
+ MBEDTLS_VERSION_PATCH,
+ ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 8 ) & 0xFF,
+ ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 0 ) & 0xFF,
+};
+
+/*
+ * Serialize a session in the following format:
+ * (in the presentation language of TLS, RFC 8446 section 3)
+ *
+ * opaque mbedtls_version[3]; // major, minor, patch
+ * opaque session_format[2]; // version-specific 16-bit field determining
+ * // the format of the remaining
+ * // serialized data.
+ *
+ * Note: When updating the format, remember to keep
+ * these version+format bytes.
+ *
+ * // In this version, `session_format` determines
+ * // the setting of those compile-time
+ * // configuration options which influence
+ * // the structure of mbedtls_ssl_session.
+ * uint64 start_time;
+ * uint8 ciphersuite[2]; // defined by the standard
+ * uint8 compression; // 0 or 1
+ * uint8 session_id_len; // at most 32
+ * opaque session_id[32];
+ * opaque master[48]; // fixed length in the standard
+ * uint32 verify_result;
+ * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
+ * opaque ticket<0..2^24-1>; // length 0 means no ticket
+ * uint32 ticket_lifetime;
+ * uint8 mfl_code; // up to 255 according to standard
+ * uint8 trunc_hmac; // 0 or 1
+ * uint8 encrypt_then_mac; // 0 or 1
+ *
+ * The order is the same as in the definition of the structure, except
+ * verify_result is put before peer_cert so that all mandatory fields come
+ * together in one block.
+ */
+static int ssl_session_save( const mbedtls_ssl_session *session,
+ unsigned char omit_header,
+ unsigned char *buf,
+ size_t buf_len,
+ size_t *olen )
+{
+ unsigned char *p = buf;
+ size_t used = 0;
+#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 )
+ {
+ /*
+ * Add version identifier
+ */
+
+ used += sizeof( ssl_serialized_session_header );
+
+ if( used <= buf_len )
+ {
+ memcpy( p, ssl_serialized_session_header,
+ sizeof( ssl_serialized_session_header ) );
+ p += sizeof( ssl_serialized_session_header );
+ }
+ }
+
+ /*
+ * Time
+ */
+#if defined(MBEDTLS_HAVE_TIME)
+ used += 8;
+
+ if( used <= buf_len )
+ {
+ start = (uint64_t) session->start;
+
+ *p++ = (unsigned char)( ( start >> 56 ) & 0xFF );
+ *p++ = (unsigned char)( ( start >> 48 ) & 0xFF );
+ *p++ = (unsigned char)( ( start >> 40 ) & 0xFF );
+ *p++ = (unsigned char)( ( start >> 32 ) & 0xFF );
+ *p++ = (unsigned char)( ( start >> 24 ) & 0xFF );
+ *p++ = (unsigned char)( ( start >> 16 ) & 0xFF );
+ *p++ = (unsigned char)( ( start >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( start ) & 0xFF );
+ }
+#endif /* MBEDTLS_HAVE_TIME */
+
+ /*
+ * Basic mandatory fields
+ */
+ used += 2 /* ciphersuite */
+ + 1 /* compression */
+ + 1 /* id_len */
+ + sizeof( session->id )
+ + sizeof( session->master )
+ + 4; /* verify_result */
+
+ if( used <= buf_len )
+ {
+ *p++ = (unsigned char)( ( session->ciphersuite >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( session->ciphersuite ) & 0xFF );
+
+ *p++ = (unsigned char)( session->compression & 0xFF );
+
+ *p++ = (unsigned char)( session->id_len & 0xFF );
+ memcpy( p, session->id, 32 );
+ p += 32;
+
+ memcpy( p, session->master, 48 );
+ p += 48;
+
+ *p++ = (unsigned char)( ( session->verify_result >> 24 ) & 0xFF );
+ *p++ = (unsigned char)( ( session->verify_result >> 16 ) & 0xFF );
+ *p++ = (unsigned char)( ( session->verify_result >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( session->verify_result ) & 0xFF );
+ }
+
+ /*
+ * Peer's end-entity certificate
+ */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ if( session->peer_cert == NULL )
+ cert_len = 0;
+ else
+ cert_len = session->peer_cert->raw.len;
+
+ used += 3 + cert_len;
+
+ if( used <= buf_len )
+ {
+ *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF );
+ *p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( cert_len ) & 0xFF );
+
+ if( session->peer_cert != NULL )
+ {
+ memcpy( p, session->peer_cert->raw.p, cert_len );
+ p += cert_len;
+ }
+ }
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+ if( session->peer_cert_digest != NULL )
+ {
+ used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len;
+ if( used <= buf_len )
+ {
+ *p++ = (unsigned char) session->peer_cert_digest_type;
+ *p++ = (unsigned char) session->peer_cert_digest_len;
+ memcpy( p, session->peer_cert_digest,
+ session->peer_cert_digest_len );
+ p += session->peer_cert_digest_len;
+ }
+ }
+ else
+ {
+ used += 2;
+ if( used <= buf_len )
+ {
+ *p++ = (unsigned char) MBEDTLS_MD_NONE;
+ *p++ = 0;
+ }
+ }
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+ /*
+ * Session ticket if any, plus associated data
+ */
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+ used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */
+
+ if( used <= buf_len )
+ {
+ *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 );
+
+ session->ticket = mbedtls_calloc( 1, session->ticket_len );
+ if( session->ticket == NULL )
+ return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+
+ memcpy( session->ticket, p, session->ticket_len );
+ p += session->ticket_len;
+ }
+
+ 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 );
+
+ session->mfl_code = *p++;
+#endif
+
+#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
+ if( 1 > (size_t)( end - p ) )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ session->trunc_hmac = *p++;
+#endif
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+ if( 1 > (size_t)( end - p ) )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ session->encrypt_then_mac = *p++;
+#endif
+
+ /* Done, should have consumed entire buffer */
+ if( p != end )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ return( 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( ret != 0 )
+ mbedtls_ssl_session_free( session );
+
+ return( ret );
+}
+
/*
* Perform a single step of the SSL handshake
*/
@@ -8103,7 +5689,7 @@
*/
static int ssl_write_hello_request( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello request" ) );
@@ -8132,9 +5718,9 @@
* If the handshake doesn't complete due to waiting for I/O, it will continue
* during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively.
*/
-static int ssl_start_renegotiation( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) );
@@ -8206,9 +5792,9 @@
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_start_renegotiation( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation", ret );
return( ret );
}
}
@@ -8224,544 +5810,8 @@
return( ret );
}
-
-/*
- * Check record counters and renegotiate if they're above the limit.
- */
-static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl )
-{
- size_t ep_len = ssl_ep_len( ssl );
- int in_ctr_cmp;
- int out_ctr_cmp;
-
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ||
- ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ||
- ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED )
- {
- return( 0 );
- }
-
- in_ctr_cmp = memcmp( ssl->in_ctr + ep_len,
- ssl->conf->renego_period + ep_len, 8 - ep_len );
- out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len,
- ssl->conf->renego_period + ep_len, 8 - ep_len );
-
- if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 )
- {
- return( 0 );
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) );
- return( mbedtls_ssl_renegotiate( ssl ) );
-}
#endif /* MBEDTLS_SSL_RENEGOTIATION */
-/*
- * Receive application data decrypted from the SSL layer
- */
-int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
-{
- int ret;
- size_t n;
-
- if( ssl == NULL || ssl->conf == NULL )
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) );
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
- return( ret );
-
- if( ssl->handshake != NULL &&
- ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
- {
- if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
- return( ret );
- }
- }
-#endif
-
- /*
- * Check if renegotiation is necessary and/or handshake is
- * in process. If yes, perform/continue, and fall through
- * if an unexpected packet is received while the client
- * is waiting for the ServerHello.
- *
- * (There is no equivalent to the last condition on
- * the server-side as it is not treated as within
- * a handshake while waiting for the ClientHello
- * after a renegotiation request.)
- */
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
- ret = ssl_check_ctr_renegotiate( ssl );
- if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
- ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret );
- return( ret );
- }
-#endif
-
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
- {
- ret = mbedtls_ssl_handshake( ssl );
- if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
- ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret );
- return( ret );
- }
- }
-
- /* Loop as long as no application data record is available */
- while( ssl->in_offt == NULL )
- {
- /* Start timer if not already running */
- if( ssl->f_get_timer != NULL &&
- ssl->f_get_timer( ssl->p_timer ) == -1 )
- {
- ssl_set_timer( ssl, ssl->conf->read_timeout );
- }
-
- if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
- {
- if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
- return( 0 );
-
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
- return( ret );
- }
-
- if( ssl->in_msglen == 0 &&
- ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA )
- {
- /*
- * OpenSSL sends empty messages to randomize the IV
- */
- if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
- {
- if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
- return( 0 );
-
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
- return( ret );
- }
- }
-
- if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) );
-
- /*
- * - For client-side, expect SERVER_HELLO_REQUEST.
- * - For server-side, expect CLIENT_HELLO.
- * - Fail (TLS) or silently drop record (DTLS) in other cases.
- */
-
-#if defined(MBEDTLS_SSL_CLI_C)
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
- ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST ||
- ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) );
-
- /* With DTLS, drop the packet (probably from last handshake) */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- continue;
- }
-#endif
- return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
- }
-#endif /* MBEDTLS_SSL_CLI_C */
-
-#if defined(MBEDTLS_SSL_SRV_C)
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) );
-
- /* With DTLS, drop the packet (probably from last handshake) */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- continue;
- }
-#endif
- return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
- }
-#endif /* MBEDTLS_SSL_SRV_C */
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
- /* Determine whether renegotiation attempt should be accepted */
- if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
- ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
- ssl->conf->allow_legacy_renegotiation ==
- MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) )
- {
- /*
- * Accept renegotiation request
- */
-
- /* DTLS clients need to know renego is server-initiated */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
- ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
- {
- ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;
- }
-#endif
- ret = ssl_start_renegotiation( ssl );
- if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
- ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret );
- return( ret );
- }
- }
- else
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
- {
- /*
- * Refuse renegotiation
- */
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) );
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
- {
- /* SSLv3 does not have a "no_renegotiation" warning, so
- we send a fatal alert and abort the connection. */
- mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
- return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
- }
- else
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
- defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
- {
- if( ( ret = mbedtls_ssl_send_alert_message( ssl,
- MBEDTLS_SSL_ALERT_LEVEL_WARNING,
- MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 )
- {
- return( ret );
- }
- }
- else
-#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 ||
- MBEDTLS_SSL_PROTO_TLS1_2 */
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
- }
-
- /* At this point, we don't know whether the renegotiation has been
- * completed or not. The cases to consider are the following:
- * 1) The renegotiation is complete. In this case, no new record
- * has been read yet.
- * 2) The renegotiation is incomplete because the client received
- * an application data record while awaiting the ServerHello.
- * 3) The renegotiation is incomplete because the client received
- * a non-handshake, non-application data message while awaiting
- * the ServerHello.
- * In each of these case, looping will be the proper action:
- * - For 1), the next iteration will read a new record and check
- * if it's application data.
- * - For 2), the loop condition isn't satisfied as application data
- * is present, hence continue is the same as break
- * - For 3), the loop condition is satisfied and read_record
- * will re-deliver the message that was held back by the client
- * when expecting the ServerHello.
- */
- continue;
- }
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
- else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
- {
- if( ssl->conf->renego_max_records >= 0 )
- {
- if( ++ssl->renego_records_seen > ssl->conf->renego_max_records )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, "
- "but not honored by client" ) );
- return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
- }
- }
- }
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
-
- /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */
- if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) );
- return( MBEDTLS_ERR_SSL_WANT_READ );
- }
-
- if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) );
- return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
- }
-
- ssl->in_offt = ssl->in_msg;
-
- /* We're going to return something now, cancel timer,
- * except if handshake (renegotiation) is in progress */
- if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
- ssl_set_timer( ssl, 0 );
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- /* If we requested renego but received AppData, resend HelloRequest.
- * Do it now, after setting in_offt, to avoid taking this branch
- * again if ssl_write_hello_request() returns WANT_WRITE */
-#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
- {
- if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret );
- return( ret );
- }
- }
-#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
- }
-
- n = ( len < ssl->in_msglen )
- ? len : ssl->in_msglen;
-
- memcpy( buf, ssl->in_offt, n );
- ssl->in_msglen -= n;
-
- if( ssl->in_msglen == 0 )
- {
- /* all bytes consumed */
- ssl->in_offt = NULL;
- ssl->keep_current_message = 0;
- }
- else
- {
- /* more data available */
- ssl->in_offt += n;
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) );
-
- return( (int) n );
-}
-
-/*
- * Send application data to be encrypted by the SSL layer, taking care of max
- * fragment length and buffer size.
- *
- * According to RFC 5246 Section 6.2.1:
- *
- * Zero-length fragments of Application data MAY be sent as they are
- * potentially useful as a traffic analysis countermeasure.
- *
- * Therefore, it is possible that the input message length is 0 and the
- * corresponding return code is 0 on success.
- */
-static int ssl_write_real( mbedtls_ssl_context *ssl,
- const unsigned char *buf, size_t len )
-{
- int ret = mbedtls_ssl_get_max_out_record_payload( ssl );
- const size_t max_len = (size_t) ret;
-
- if( ret < 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret );
- return( ret );
- }
-
- if( len > max_len )
- {
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) "
- "maximum fragment length: %d > %d",
- len, max_len ) );
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- }
- else
-#endif
- len = max_len;
- }
-
- if( ssl->out_left != 0 )
- {
- /*
- * The user has previously tried to send the data and
- * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially
- * written. In this case, we expect the high-level write function
- * (e.g. mbedtls_ssl_write()) to be called with the same parameters
- */
- if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
- return( ret );
- }
- }
- else
- {
- /*
- * The user is trying to send a message the first time, so we need to
- * copy the data into the internal buffers and setup the data structure
- * to keep track of partial writes
- */
- ssl->out_msglen = len;
- ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA;
- memcpy( ssl->out_msg, buf, len );
-
- if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
- return( ret );
- }
- }
-
- return( (int) len );
-}
-
-/*
- * Write application data, doing 1/n-1 splitting if necessary.
- *
- * With non-blocking I/O, ssl_write_real() may return WANT_WRITE,
- * then the caller will call us again with the same arguments, so
- * remember whether we already did the split or not.
- */
-#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
-static int ssl_write_split( mbedtls_ssl_context *ssl,
- const unsigned char *buf, size_t len )
-{
- int ret;
-
- 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_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;
-
- 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 );
-
- mbedtls_md_free( &transform->md_ctx_enc );
- mbedtls_md_free( &transform->md_ctx_dec );
-
- mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) );
-}
-
#if defined(MBEDTLS_X509_CRT_PARSE_C)
static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert )
{
@@ -8776,42 +5826,6 @@
}
#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;
@@ -8834,11 +5848,19 @@
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ psa_hash_abort( &handshake->fin_sha256_psa );
+#else
mbedtls_sha256_free( &handshake->fin_sha256 );
#endif
+#endif
#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ psa_hash_abort( &handshake->fin_sha384_psa );
+#else
mbedtls_sha512_free( &handshake->fin_sha512 );
#endif
+#endif
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
#if defined(MBEDTLS_DHM_C)
@@ -8862,7 +5884,7 @@
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 );
@@ -8889,18 +5911,92 @@
}
#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 )
+ {
+ mbedtls_x509_crt_free( handshake->ecrs_peer_cert );
+ mbedtls_free( handshake->ecrs_peer_cert );
+ }
#endif
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ mbedtls_pk_free( &handshake->peer_pubkey );
+#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
#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) && \
+ defined(MBEDTLS_USE_PSA_CRYPTO)
+ psa_destroy_key( handshake->ecdh_psa_privkey );
+#endif /* MBEDTLS_ECDH_C && MBEDTLS_USE_PSA_CRYPTO */
+
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 )
@@ -8909,11 +6005,7 @@
return;
#if defined(MBEDTLS_X509_CRT_PARSE_C)
- if( session->peer_cert != NULL )
- {
- mbedtls_x509_crt_free( session->peer_cert );
- mbedtls_free( session->peer_cert );
- }
+ ssl_clear_peer_cert( session );
#endif
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
@@ -8923,11 +6015,660 @@
mbedtls_platform_zeroize( session, sizeof( mbedtls_ssl_session ) );
}
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 1u
+#else
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 0u
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 1u
+#else
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 0u
+#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
+
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 1u
+#else
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 0u
+#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
+
+#if defined(MBEDTLS_SSL_ALPN)
+#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 1u
+#else
+#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 0u
+#endif /* MBEDTLS_SSL_ALPN */
+
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT 0
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT 1
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT 2
+#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT 3
+
+#define SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG \
+ ( (uint32_t) ( \
+ ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT ) | \
+ ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT ) | \
+ ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT ) | \
+ ( SSL_SERIALIZED_CONTEXT_CONFIG_ALPN << SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT ) | \
+ 0u ) )
+
+static unsigned char ssl_serialized_context_header[] = {
+ MBEDTLS_VERSION_MAJOR,
+ MBEDTLS_VERSION_MINOR,
+ MBEDTLS_VERSION_PATCH,
+ ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 8 ) & 0xFF,
+ ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 0 ) & 0xFF,
+ ( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG >> 16 ) & 0xFF,
+ ( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG >> 8 ) & 0xFF,
+ ( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG >> 0 ) & 0xFF,
+};
+
+/*
+ * Serialize a full SSL context
+ *
+ * The format of the serialized data is:
+ * (in the presentation language of TLS, RFC 8446 section 3)
+ *
+ * // header
+ * opaque mbedtls_version[3]; // major, minor, patch
+ * opaque context_format[5]; // version-specific field determining
+ * // the format of the remaining
+ * // serialized data.
+ * Note: When updating the format, remember to keep these
+ * version+format bytes. (We may make their size part of the API.)
+ *
+ * // session sub-structure
+ * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save()
+ * // transform sub-structure
+ * uint8 random[64]; // ServerHello.random+ClientHello.random
+ * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value
+ * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use
+ * // fields from ssl_context
+ * uint32 badmac_seen; // DTLS: number of records with failing MAC
+ * uint64 in_window_top; // DTLS: last validated record seq_num
+ * uint64 in_window; // DTLS: bitmask for replay protection
+ * uint8 disable_datagram_packing; // DTLS: only one record per datagram
+ * uint64 cur_out_ctr; // Record layer: outgoing sequence number
+ * uint16 mtu; // DTLS: path mtu (max outgoing fragment size)
+ * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
+ *
+ * Note that many fields of the ssl_context or sub-structures are not
+ * serialized, as they fall in one of the following categories:
+ *
+ * 1. forced value (eg in_left must be 0)
+ * 2. pointer to dynamically-allocated memory (eg session, transform)
+ * 3. value can be re-derived from other data (eg session keys from MS)
+ * 4. value was temporary (eg content of input buffer)
+ * 5. value will be provided by the user again (eg I/O callbacks and context)
+ */
+int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl,
+ unsigned char *buf,
+ size_t buf_len,
+ size_t *olen )
+{
+ unsigned char *p = buf;
+ size_t used = 0;
+ size_t session_len;
+ int ret = 0;
+
+ /*
+ * Enforce usage restrictions, see "return BAD_INPUT_DATA" in
+ * this function's documentation.
+ *
+ * These are due to assumptions/limitations in the implementation. Some of
+ * them are likely to stay (no handshake in progress) some might go away
+ * (only DTLS) but are currently used to simplify the implementation.
+ */
+ /* The initial handshake must be over */
+ if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Initial handshake isn't over" ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+ if( ssl->handshake != NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Handshake isn't completed" ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+ /* Double-check that sub-structures are indeed ready */
+ if( ssl->transform == NULL || ssl->session == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Serialised structures aren't ready" ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+ /* There must be no pending incoming or outgoing data */
+ if( mbedtls_ssl_check_pending( ssl ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "There is pending incoming data" ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+ if( ssl->out_left != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "There is pending outgoing data" ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+ /* Protocol must be DLTS, not TLS */
+ if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only DTLS is supported" ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+ /* Version must be 1.2 */
+ if( ssl->major_ver != MBEDTLS_SSL_MAJOR_VERSION_3 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only version 1.2 supported" ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+ if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only version 1.2 supported" ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+ /* We must be using an AEAD ciphersuite */
+ if( mbedtls_ssl_transform_uses_aead( ssl->transform ) != 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only AEAD ciphersuites supported" ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+ /* Renegotiation must not be enabled */
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+ if( ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Renegotiation must not be enabled" ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+#endif
+
+ /*
+ * Version and format identifier
+ */
+ used += sizeof( ssl_serialized_context_header );
+
+ if( used <= buf_len )
+ {
+ memcpy( p, ssl_serialized_context_header,
+ sizeof( ssl_serialized_context_header ) );
+ p += sizeof( ssl_serialized_context_header );
+ }
+
+ /*
+ * Session (length + data)
+ */
+ ret = ssl_session_save( ssl->session, 1, NULL, 0, &session_len );
+ if( ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL )
+ return( ret );
+
+ used += 4 + session_len;
+ if( used <= buf_len )
+ {
+ *p++ = (unsigned char)( ( session_len >> 24 ) & 0xFF );
+ *p++ = (unsigned char)( ( session_len >> 16 ) & 0xFF );
+ *p++ = (unsigned char)( ( session_len >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( session_len ) & 0xFF );
+
+ ret = ssl_session_save( ssl->session, 1,
+ p, session_len, &session_len );
+ if( ret != 0 )
+ return( ret );
+
+ p += session_len;
+ }
+
+ /*
+ * Transform
+ */
+ used += sizeof( ssl->transform->randbytes );
+ if( used <= buf_len )
+ {
+ memcpy( p, ssl->transform->randbytes,
+ sizeof( ssl->transform->randbytes ) );
+ p += sizeof( ssl->transform->randbytes );
+ }
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ used += 2 + ssl->transform->in_cid_len + ssl->transform->out_cid_len;
+ if( used <= buf_len )
+ {
+ *p++ = ssl->transform->in_cid_len;
+ memcpy( p, ssl->transform->in_cid, ssl->transform->in_cid_len );
+ p += ssl->transform->in_cid_len;
+
+ *p++ = ssl->transform->out_cid_len;
+ memcpy( p, ssl->transform->out_cid, ssl->transform->out_cid_len );
+ p += ssl->transform->out_cid_len;
+ }
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+ /*
+ * Saved fields from top-level ssl_context structure
+ */
+#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
+ used += 4;
+ if( used <= buf_len )
+ {
+ *p++ = (unsigned char)( ( ssl->badmac_seen >> 24 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->badmac_seen >> 16 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->badmac_seen >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->badmac_seen ) & 0xFF );
+ }
+#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
+
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+ used += 16;
+ if( used <= buf_len )
+ {
+ *p++ = (unsigned char)( ( ssl->in_window_top >> 56 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->in_window_top >> 48 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->in_window_top >> 40 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->in_window_top >> 32 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->in_window_top >> 24 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->in_window_top >> 16 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->in_window_top >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->in_window_top ) & 0xFF );
+
+ *p++ = (unsigned char)( ( ssl->in_window >> 56 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->in_window >> 48 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->in_window >> 40 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->in_window >> 32 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->in_window >> 24 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->in_window >> 16 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->in_window >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->in_window ) & 0xFF );
+ }
+#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ used += 1;
+ if( used <= buf_len )
+ {
+ *p++ = ssl->disable_datagram_packing;
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+ used += 8;
+ if( used <= buf_len )
+ {
+ memcpy( p, ssl->cur_out_ctr, 8 );
+ p += 8;
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ used += 2;
+ if( used <= buf_len )
+ {
+ *p++ = (unsigned char)( ( ssl->mtu >> 8 ) & 0xFF );
+ *p++ = (unsigned char)( ( ssl->mtu ) & 0xFF );
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+#if defined(MBEDTLS_SSL_ALPN)
+ {
+ const uint8_t alpn_len = ssl->alpn_chosen
+ ? (uint8_t) strlen( ssl->alpn_chosen )
+ : 0;
+
+ used += 1 + alpn_len;
+ if( used <= buf_len )
+ {
+ *p++ = alpn_len;
+
+ if( ssl->alpn_chosen != NULL )
+ {
+ memcpy( p, ssl->alpn_chosen, alpn_len );
+ p += alpn_len;
+ }
+ }
+ }
+#endif /* MBEDTLS_SSL_ALPN */
+
+ /*
+ * Done
+ */
+ *olen = used;
+
+ if( used > buf_len )
+ return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+
+ MBEDTLS_SSL_DEBUG_BUF( 4, "saved context", buf, used );
+
+ return( mbedtls_ssl_session_reset_int( ssl, 0 ) );
+}
+
+/*
+ * Helper to get TLS 1.2 PRF from ciphersuite
+ * (Duplicates bits of logic from ssl_set_handshake_prfs().)
+ */
+typedef int (*tls_prf_fn)( const unsigned char *secret, size_t slen,
+ const char *label,
+ const unsigned char *random, size_t rlen,
+ unsigned char *dstbuf, size_t dlen );
+static tls_prf_fn ssl_tls12prf_from_cs( int ciphersuite_id )
+{
+#if defined(MBEDTLS_SHA512_C)
+ const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
+ mbedtls_ssl_ciphersuite_from_id( ciphersuite_id );
+
+ if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 )
+ return( tls_prf_sha384 );
+#else
+ (void) ciphersuite_id;
+#endif
+ return( tls_prf_sha256 );
+}
+
+/*
+ * Deserialize context, see mbedtls_ssl_context_save() for format.
+ *
+ * This internal version is wrapped by a public function that cleans up in
+ * case of error.
+ */
+static int ssl_context_load( mbedtls_ssl_context *ssl,
+ const unsigned char *buf,
+ size_t len )
+{
+ const unsigned char *p = buf;
+ const unsigned char * const end = buf + len;
+ size_t session_len;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ /*
+ * The context should have been freshly setup or reset.
+ * Give the user an error in case of obvious misuse.
+ * (Checking session is useful because it won't be NULL if we're
+ * renegotiating, or if the user mistakenly loaded a session first.)
+ */
+ if( ssl->state != MBEDTLS_SSL_HELLO_REQUEST ||
+ ssl->session != NULL )
+ {
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+ /*
+ * We can't check that the config matches the initial one, but we can at
+ * least check it matches the requirements for serializing.
+ */
+ if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
+ ssl->conf->max_major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 ||
+ ssl->conf->min_major_ver > MBEDTLS_SSL_MAJOR_VERSION_3 ||
+ ssl->conf->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ||
+ ssl->conf->min_minor_ver > MBEDTLS_SSL_MINOR_VERSION_3 ||
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+ ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
+#endif
+ 0 )
+ {
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+ MBEDTLS_SSL_DEBUG_BUF( 4, "context to load", buf, len );
+
+ /*
+ * Check version identifier
+ */
+ if( (size_t)( end - p ) < sizeof( ssl_serialized_context_header ) )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ if( memcmp( p, ssl_serialized_context_header,
+ sizeof( ssl_serialized_context_header ) ) != 0 )
+ {
+ return( MBEDTLS_ERR_SSL_VERSION_MISMATCH );
+ }
+ p += sizeof( ssl_serialized_context_header );
+
+ /*
+ * Session
+ */
+ if( (size_t)( end - p ) < 4 )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ session_len = ( (size_t) p[0] << 24 ) |
+ ( (size_t) p[1] << 16 ) |
+ ( (size_t) p[2] << 8 ) |
+ ( (size_t) p[3] );
+ p += 4;
+
+ /* This has been allocated by ssl_handshake_init(), called by
+ * 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;
+ ssl->session_negotiate = NULL;
+
+ if( (size_t)( end - p ) < session_len )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ ret = ssl_session_load( ssl->session, 1, p, session_len );
+ if( ret != 0 )
+ {
+ mbedtls_ssl_session_free( ssl->session );
+ return( ret );
+ }
+
+ p += session_len;
+
+ /*
+ * Transform
+ */
+
+ /* This has been allocated by ssl_handshake_init(), called by
+ * 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;
+ ssl->transform_negotiate = NULL;
+
+ /* Read random bytes and populate structure */
+ if( (size_t)( end - p ) < sizeof( ssl->transform->randbytes ) )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ ret = ssl_populate_transform( ssl->transform,
+ ssl->session->ciphersuite,
+ ssl->session->master,
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+ ssl->session->encrypt_then_mac,
+#endif
+#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
+ ssl->session->trunc_hmac,
+#endif
+#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
+#if defined(MBEDTLS_ZLIB_SUPPORT)
+ ssl->session->compression,
+#endif
+ ssl_tls12prf_from_cs( ssl->session->ciphersuite ),
+ p, /* currently pointing to randbytes */
+ MBEDTLS_SSL_MINOR_VERSION_3, /* (D)TLS 1.2 is forced */
+ ssl->conf->endpoint,
+ ssl );
+ if( ret != 0 )
+ return( ret );
+
+ p += sizeof( ssl->transform->randbytes );
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ /* Read connection IDs and store them */
+ if( (size_t)( end - p ) < 1 )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ ssl->transform->in_cid_len = *p++;
+
+ if( (size_t)( end - p ) < ssl->transform->in_cid_len + 1u )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ memcpy( ssl->transform->in_cid, p, ssl->transform->in_cid_len );
+ p += ssl->transform->in_cid_len;
+
+ ssl->transform->out_cid_len = *p++;
+
+ if( (size_t)( end - p ) < ssl->transform->out_cid_len )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ memcpy( ssl->transform->out_cid, p, ssl->transform->out_cid_len );
+ p += ssl->transform->out_cid_len;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+ /*
+ * Saved fields from top-level ssl_context structure
+ */
+#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
+ if( (size_t)( end - p ) < 4 )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ ssl->badmac_seen = ( (uint32_t) p[0] << 24 ) |
+ ( (uint32_t) p[1] << 16 ) |
+ ( (uint32_t) p[2] << 8 ) |
+ ( (uint32_t) p[3] );
+ p += 4;
+#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
+
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+ if( (size_t)( end - p ) < 16 )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ ssl->in_window_top = ( (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;
+
+ ssl->in_window = ( (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;
+#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( (size_t)( end - p ) < 1 )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ ssl->disable_datagram_packing = *p++;
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+ if( (size_t)( end - p ) < 8 )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ memcpy( ssl->cur_out_ctr, p, 8 );
+ p += 8;
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( (size_t)( end - p ) < 2 )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ ssl->mtu = ( p[0] << 8 ) | p[1];
+ p += 2;
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+#if defined(MBEDTLS_SSL_ALPN)
+ {
+ uint8_t alpn_len;
+ const char **cur;
+
+ if( (size_t)( end - p ) < 1 )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ alpn_len = *p++;
+
+ if( alpn_len != 0 && ssl->conf->alpn_list != NULL )
+ {
+ /* alpn_chosen should point to an item in the configured list */
+ for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ )
+ {
+ if( strlen( *cur ) == alpn_len &&
+ memcmp( p, cur, alpn_len ) == 0 )
+ {
+ ssl->alpn_chosen = *cur;
+ break;
+ }
+ }
+ }
+
+ /* can only happen on conf mismatch */
+ if( alpn_len != 0 && ssl->alpn_chosen == NULL )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ p += alpn_len;
+ }
+#endif /* MBEDTLS_SSL_ALPN */
+
+ /*
+ * Forced fields from top-level ssl_context structure
+ *
+ * Most of them already set to the correct value by mbedtls_ssl_init() and
+ * mbedtls_ssl_reset(), so we only need to set the remaining ones.
+ */
+ ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER;
+
+ ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3;
+ ssl->minor_ver = MBEDTLS_SSL_MINOR_VERSION_3;
+
+ /* Adjust pointers for header fields of outgoing records to
+ * the given transform, accounting for explicit IV and CID. */
+ mbedtls_ssl_update_out_pointers( ssl, ssl->transform );
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ ssl->in_epoch = 1;
+#endif
+
+ /* 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 mbedtls_ssl_handshake_wrapup_free_hs_transform()
+ * inappropriately. */
+ if( ssl->handshake != NULL )
+ {
+ mbedtls_ssl_handshake_free( ssl );
+ mbedtls_free( ssl->handshake );
+ ssl->handshake = NULL;
+ }
+
+ /*
+ * Done - should have consumed entire buffer
+ */
+ if( p != end )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ return( 0 );
+}
+
+/*
+ * Deserialize context: public wrapper for error cleaning
+ */
+int mbedtls_ssl_context_load( mbedtls_ssl_context *context,
+ const unsigned char *buf,
+ size_t len )
+{
+ int ret = ssl_context_load( context, buf, len );
+
+ if( ret != 0 )
+ mbedtls_ssl_free( context );
+
+ return( ret );
+}
+#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
+
/*
* Free an SSL 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;
@@ -8935,14 +6676,16 @@
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)
@@ -9010,7 +6753,7 @@
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,
@@ -9033,7 +6776,7 @@
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,
@@ -9060,7 +6803,7 @@
int endpoint, int transport, int preset )
{
#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#endif
/* Use the functions here so that they are covered in tests,
@@ -9162,7 +6905,7 @@
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
@@ -9201,7 +6944,7 @@
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
@@ -9227,7 +6970,7 @@
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 );
@@ -9302,7 +7045,7 @@
#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,
@@ -9350,7 +7093,7 @@
}
#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
@@ -9436,7 +7179,7 @@
}
#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.
@@ -9455,7 +7198,7 @@
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,
@@ -9548,59 +7291,6 @@
}
#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)
@@ -9731,6 +7421,70 @@
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_2)
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
+ unsigned char *hash, size_t *hashlen,
+ unsigned char *data, size_t data_len,
+ mbedtls_md_type_t md_alg )
+{
+ psa_status_t status;
+ psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT;
+ psa_algorithm_t hash_alg = mbedtls_psa_translate_md( md_alg );
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Perform PSA-based computation of digest of ServerKeyExchange" ) );
+
+ if( ( status = psa_hash_setup( &hash_operation,
+ hash_alg ) ) != PSA_SUCCESS )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_setup", status );
+ goto exit;
+ }
+
+ if( ( status = psa_hash_update( &hash_operation, ssl->handshake->randbytes,
+ 64 ) ) != PSA_SUCCESS )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_update", status );
+ goto exit;
+ }
+
+ if( ( status = psa_hash_update( &hash_operation,
+ data, data_len ) ) != PSA_SUCCESS )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_update", status );
+ goto exit;
+ }
+
+ if( ( status = psa_hash_finish( &hash_operation, hash, MBEDTLS_MD_MAX_SIZE,
+ hashlen ) ) != PSA_SUCCESS )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_finish", status );
+ goto exit;
+ }
+
+exit:
+ if( status != PSA_SUCCESS )
+ {
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
+ switch( status )
+ {
+ case PSA_ERROR_NOT_SUPPORTED:
+ return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
+ case PSA_ERROR_BAD_STATE: /* Intentional fallthrough */
+ case PSA_ERROR_BUFFER_TOO_SMALL:
+ return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+ case PSA_ERROR_INSUFFICIENT_MEMORY:
+ return( MBEDTLS_ERR_MD_ALLOC_FAILED );
+ default:
+ return( MBEDTLS_ERR_MD_HW_ACCEL_FAILED );
+ }
+ }
+ return( 0 );
+}
+
+#else
+
int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
unsigned char *hash, size_t *hashlen,
unsigned char *data, size_t data_len,
@@ -9741,6 +7495,8 @@
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
*hashlen = mbedtls_md_get_size( md_info );
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Perform mbedtls-based computation of digest of ServerKeyExchange" ) );
+
mbedtls_md_init( &ctx );
/*
@@ -9785,6 +7541,8 @@
return( ret );
}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
MBEDTLS_SSL_PROTO_TLS1_2 */
diff --git a/lib/libmbedtls/mbedtls/library/version_features.c b/lib/libmbedtls/mbedtls/library/version_features.c
index 6e1281e..300760c 100644
--- a/lib/libmbedtls/mbedtls/library/version_features.c
+++ b/lib/libmbedtls/mbedtls/library/version_features.c
@@ -31,7 +31,7 @@
#include <string.h>
-static const char *features[] = {
+static const char * const features[] = {
#if defined(MBEDTLS_VERSION_FEATURES)
#if defined(MBEDTLS_HAVE_ASM)
"MBEDTLS_HAVE_ASM",
@@ -72,6 +72,9 @@
#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT)
"MBEDTLS_PLATFORM_SNPRINTF_ALT",
#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
+#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT)
+ "MBEDTLS_PLATFORM_VSNPRINTF_ALT",
+#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */
#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT)
"MBEDTLS_PLATFORM_NV_SEED_ALT",
#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */
@@ -354,6 +357,9 @@
#if defined(MBEDTLS_ECP_RESTARTABLE)
"MBEDTLS_ECP_RESTARTABLE",
#endif /* MBEDTLS_ECP_RESTARTABLE */
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+ "MBEDTLS_ECDH_LEGACY_CONTEXT",
+#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
"MBEDTLS_ECDSA_DETERMINISTIC",
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
@@ -414,6 +420,9 @@
#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 */
@@ -429,6 +438,12 @@
#if defined(MBEDTLS_PKCS1_V21)
"MBEDTLS_PKCS1_V21",
#endif /* MBEDTLS_PKCS1_V21 */
+#if defined(MBEDTLS_PSA_CRYPTO_SPM)
+ "MBEDTLS_PSA_CRYPTO_SPM",
+#endif /* MBEDTLS_PSA_CRYPTO_SPM */
+#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
+ "MBEDTLS_PSA_INJECT_ENTROPY",
+#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
#if defined(MBEDTLS_RSA_NO_CRT)
"MBEDTLS_RSA_NO_CRT",
#endif /* MBEDTLS_RSA_NO_CRT */
@@ -438,12 +453,27 @@
#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 */
+#if defined(MBEDTLS_SSL_RECORD_CHECKING)
+ "MBEDTLS_SSL_RECORD_CHECKING",
+#endif /* MBEDTLS_SSL_RECORD_CHECKING */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ "MBEDTLS_SSL_DTLS_CONNECTION_ID",
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
"MBEDTLS_SSL_ASYNC_PRIVATE",
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+ "MBEDTLS_SSL_CONTEXT_SERIALIZATION",
+#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
#if defined(MBEDTLS_SSL_DEBUG_ALL)
"MBEDTLS_SSL_DEBUG_ALL",
#endif /* MBEDTLS_SSL_DEBUG_ALL */
@@ -456,6 +486,9 @@
#if defined(MBEDTLS_SSL_FALLBACK_SCSV)
"MBEDTLS_SSL_FALLBACK_SCSV",
#endif /* MBEDTLS_SSL_FALLBACK_SCSV */
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ "MBEDTLS_SSL_KEEP_PEER_CERTIFICATE",
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
"MBEDTLS_SSL_HW_RECORD_ACCEL",
#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
@@ -519,12 +552,18 @@
#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 */
#if defined(MBEDTLS_THREADING_PTHREAD)
"MBEDTLS_THREADING_PTHREAD",
#endif /* MBEDTLS_THREADING_PTHREAD */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ "MBEDTLS_USE_PSA_CRYPTO",
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_VERSION_FEATURES)
"MBEDTLS_VERSION_FEATURES",
#endif /* MBEDTLS_VERSION_FEATURES */
@@ -534,6 +573,9 @@
#if defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
"MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION",
#endif /* MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+ "MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK",
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
"MBEDTLS_X509_CHECK_KEY_USAGE",
#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */
@@ -693,6 +735,18 @@
#if defined(MBEDTLS_POLY1305_C)
"MBEDTLS_POLY1305_C",
#endif /* MBEDTLS_POLY1305_C */
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+ "MBEDTLS_PSA_CRYPTO_C",
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+#if defined(MBEDTLS_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 */
+#if defined(MBEDTLS_PSA_ITS_FILE_C)
+ "MBEDTLS_PSA_ITS_FILE_C",
+#endif /* MBEDTLS_PSA_ITS_FILE_C */
#if defined(MBEDTLS_RIPEMD160_C)
"MBEDTLS_RIPEMD160_C",
#endif /* MBEDTLS_RIPEMD160_C */
@@ -765,7 +819,7 @@
int mbedtls_version_check_feature( const char *feature )
{
- const char **idx = features;
+ const char * const *idx = features;
if( *idx == NULL )
return( -2 );
diff --git a/lib/libmbedtls/mbedtls/library/x509.c b/lib/libmbedtls/mbedtls/library/x509.c
index 48a8b07..9e6ba68 100644
--- a/lib/libmbedtls/mbedtls/library/x509.c
+++ b/lib/libmbedtls/mbedtls/library/x509.c
@@ -39,6 +39,7 @@
#include "mbedtls/x509.h"
#include "mbedtls/asn1.h"
+#include "mbedtls/error.h"
#include "mbedtls/oid.h"
#include <stdio.h>
@@ -83,7 +84,7 @@
int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *serial )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( end - *p ) < 1 )
return( MBEDTLS_ERR_X509_INVALID_SERIAL +
@@ -114,7 +115,7 @@
int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *alg )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
@@ -128,7 +129,7 @@
int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *alg, mbedtls_x509_buf *params )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 )
return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
@@ -148,7 +149,7 @@
*/
static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p;
const unsigned char *end;
mbedtls_x509_buf md_oid;
@@ -209,7 +210,7 @@
mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
int *salt_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p;
const unsigned char *end, *end2;
size_t len;
@@ -352,7 +353,7 @@
const unsigned char *end,
mbedtls_x509_name *cur )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
mbedtls_x509_buf *oid;
mbedtls_x509_buf *val;
@@ -433,7 +434,7 @@
int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
mbedtls_x509_name *cur )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t set_len;
const unsigned char *end_set;
@@ -539,7 +540,7 @@
static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen,
mbedtls_x509_time *tm )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/*
* Minimum length is 10 or 12 depending on yearlen
@@ -604,7 +605,7 @@
int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
mbedtls_x509_time *tm )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len, year_len;
unsigned char tag;
@@ -633,7 +634,7 @@
int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
int tag_type;
@@ -662,7 +663,7 @@
mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
void **sig_opts )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( *sig_opts != NULL )
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
@@ -710,7 +711,7 @@
int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *ext, int tag )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
/* Extension structure use EXPLICIT tagging. That is, the actual
@@ -745,7 +746,7 @@
*/
int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, n;
unsigned char c, merge = 0;
const mbedtls_x509_name *name;
@@ -807,7 +808,7 @@
*/
int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, n, nr;
char *p;
@@ -843,7 +844,7 @@
mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
const void *sig_opts )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
char *p = buf;
size_t n = size;
const char *desc = NULL;
@@ -888,7 +889,7 @@
{
char *p = buf;
size_t n = buf_size;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ret = mbedtls_snprintf( p, n, "%s key size", name );
MBEDTLS_X509_SAFE_SNPRINTF;
@@ -1063,7 +1064,7 @@
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/lib/libmbedtls/mbedtls/library/x509_create.c b/lib/libmbedtls/mbedtls/library/x509_create.c
index 55612c4..fd3aad1 100644
--- a/lib/libmbedtls/mbedtls/library/x509_create.c
+++ b/lib/libmbedtls/mbedtls/library/x509_create.c
@@ -29,6 +29,7 @@
#include "mbedtls/x509.h"
#include "mbedtls/asn1write.h"
+#include "mbedtls/error.h"
#include "mbedtls/oid.h"
#include <string.h>
@@ -241,7 +242,7 @@
*/
static int x509_write_name( unsigned char **p, unsigned char *start, mbedtls_asn1_named_data* cur_name)
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
const char *oid = (const char*)cur_name->oid.p;
size_t oid_len = cur_name->oid.len;
@@ -274,7 +275,7 @@
int mbedtls_x509_write_names( unsigned char **p, unsigned char *start,
mbedtls_asn1_named_data *first )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
mbedtls_asn1_named_data *cur = first;
@@ -295,7 +296,7 @@
const char *oid, size_t oid_len,
unsigned char *sig, size_t size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
if( *p < start || (size_t)( *p - start ) < size )
@@ -325,7 +326,7 @@
static int x509_write_extension( unsigned char **p, unsigned char *start,
mbedtls_asn1_named_data *ext )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1,
@@ -363,7 +364,7 @@
int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start,
mbedtls_asn1_named_data *first )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
mbedtls_asn1_named_data *cur_ext = first;
diff --git a/lib/libmbedtls/mbedtls/library/x509_crl.c b/lib/libmbedtls/mbedtls/library/x509_crl.c
index f273251..54b5591 100644
--- a/lib/libmbedtls/mbedtls/library/x509_crl.c
+++ b/lib/libmbedtls/mbedtls/library/x509_crl.c
@@ -38,6 +38,7 @@
#if defined(MBEDTLS_X509_CRL_PARSE_C)
#include "mbedtls/x509_crl.h"
+#include "mbedtls/error.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
@@ -74,7 +75,7 @@
const unsigned char *end,
int *ver )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
{
@@ -101,7 +102,7 @@
const unsigned char *end,
mbedtls_x509_buf *ext )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( *p == end )
return( 0 );
@@ -181,7 +182,7 @@
const unsigned char *end,
mbedtls_x509_buf *ext )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
/* OPTIONAL */
@@ -235,7 +236,7 @@
const unsigned char *end,
mbedtls_x509_crl_entry *entry )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t entry_len;
mbedtls_x509_crl_entry *cur_entry = entry;
@@ -300,7 +301,7 @@
int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain,
const unsigned char *buf, size_t buflen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
unsigned char *p = NULL, *end = NULL;
mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
@@ -539,8 +540,8 @@
int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen )
{
#if defined(MBEDTLS_PEM_PARSE_C)
- int ret;
- size_t use_len;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t use_len = 0;
mbedtls_pem_context pem;
int is_pem = 0;
@@ -603,7 +604,7 @@
*/
int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
unsigned char *buf;
@@ -630,7 +631,7 @@
int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix,
const mbedtls_x509_crl *crl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
char *p;
const mbedtls_x509_crl_entry *entry;
diff --git a/lib/libmbedtls/mbedtls/library/x509_crt.c b/lib/libmbedtls/mbedtls/library/x509_crt.c
index 7d53f25..edad392 100644
--- a/lib/libmbedtls/mbedtls/library/x509_crt.c
+++ b/lib/libmbedtls/mbedtls/library/x509_crt.c
@@ -40,6 +40,7 @@
#if defined(MBEDTLS_X509_CRT_PARSE_C)
#include "mbedtls/x509_crt.h"
+#include "mbedtls/error.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
@@ -49,6 +50,11 @@
#include "mbedtls/pem.h"
#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
+#endif
+
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
@@ -372,6 +378,10 @@
}
ver_chain->len = 0;
+
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+ ver_chain->trust_ca_cb_result = NULL;
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
}
/*
@@ -381,7 +391,7 @@
const unsigned char *end,
int *ver )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
@@ -418,7 +428,7 @@
mbedtls_x509_time *from,
mbedtls_x509_time *to )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
@@ -447,7 +457,7 @@
const unsigned char *end,
mbedtls_x509_buf *uid, int n )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( *p == end )
return( 0 );
@@ -474,7 +484,7 @@
int *ca_istrue,
int *max_pathlen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
/*
@@ -523,7 +533,7 @@
const unsigned char *end,
unsigned char *ns_cert_type)
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_x509_bitstring bs = { 0, 0, NULL };
if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
@@ -542,7 +552,7 @@
const unsigned char *end,
unsigned int *key_usage)
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
mbedtls_x509_bitstring bs = { 0, 0, NULL };
@@ -572,7 +582,7 @@
const unsigned char *end,
mbedtls_x509_sequence *ext_key_usage)
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 )
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
@@ -609,13 +619,14 @@
* nameAssigner [0] DirectoryString OPTIONAL,
* partyName [1] DirectoryString }
*
- * NOTE: we only parse and use dNSName at this point.
+ * NOTE: we list all types, but only use dNSName and otherName
+ * of type HwModuleName, as defined in RFC 4108, at this point.
*/
static int x509_get_subject_alt_name( unsigned char **p,
const unsigned char *end,
mbedtls_x509_sequence *subject_alt_name )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len, tag_len;
mbedtls_asn1_buf *buf;
unsigned char tag;
@@ -632,6 +643,9 @@
while( *p < end )
{
+ mbedtls_x509_subject_alternative_name dummy_san_buf;
+ memset( &dummy_san_buf, 0, sizeof( dummy_san_buf ) );
+
if( ( end - *p ) < 1 )
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
MBEDTLS_ERR_ASN1_OUT_OF_DATA );
@@ -648,11 +662,28 @@
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
}
- /* Skip everything but DNS name */
- if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) )
+ /*
+ * Check that the SAN are structured correct.
+ */
+ ret = mbedtls_x509_parse_subject_alt_name( &(cur->buf), &dummy_san_buf );
+ /*
+ * In case the extension is malformed, return an error,
+ * and clear the allocated sequences.
+ */
+ if( ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
{
- *p += tag_len;
- continue;
+ mbedtls_x509_sequence *seq_cur = subject_alt_name->next;
+ mbedtls_x509_sequence *seq_prv;
+ while( seq_cur != NULL )
+ {
+ seq_prv = seq_cur;
+ seq_cur = seq_cur->next;
+ mbedtls_platform_zeroize( seq_prv,
+ sizeof( mbedtls_x509_sequence ) );
+ mbedtls_free( seq_prv );
+ }
+ subject_alt_name->next = NULL;
+ return( ret );
}
/* Allocate and assign next pointer */
@@ -688,6 +719,168 @@
}
/*
+ * id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 }
+ *
+ * anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 }
+ *
+ * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
+ *
+ * PolicyInformation ::= SEQUENCE {
+ * policyIdentifier CertPolicyId,
+ * policyQualifiers SEQUENCE SIZE (1..MAX) OF
+ * PolicyQualifierInfo OPTIONAL }
+ *
+ * CertPolicyId ::= OBJECT IDENTIFIER
+ *
+ * PolicyQualifierInfo ::= SEQUENCE {
+ * policyQualifierId PolicyQualifierId,
+ * qualifier ANY DEFINED BY policyQualifierId }
+ *
+ * -- policyQualifierIds for Internet policy qualifiers
+ *
+ * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 }
+ * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 }
+ * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 }
+ *
+ * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
+ *
+ * Qualifier ::= CHOICE {
+ * cPSuri CPSuri,
+ * userNotice UserNotice }
+ *
+ * CPSuri ::= IA5String
+ *
+ * UserNotice ::= SEQUENCE {
+ * noticeRef NoticeReference OPTIONAL,
+ * explicitText DisplayText OPTIONAL }
+ *
+ * NoticeReference ::= SEQUENCE {
+ * organization DisplayText,
+ * noticeNumbers SEQUENCE OF INTEGER }
+ *
+ * DisplayText ::= CHOICE {
+ * ia5String IA5String (SIZE (1..200)),
+ * visibleString VisibleString (SIZE (1..200)),
+ * bmpString BMPString (SIZE (1..200)),
+ * utf8String UTF8String (SIZE (1..200)) }
+ *
+ * NOTE: we only parse and use anyPolicy without qualifiers at this point
+ * as defined in RFC 5280.
+ */
+static int x509_get_certificate_policies( unsigned char **p,
+ const unsigned char *end,
+ mbedtls_x509_sequence *certificate_policies )
+{
+ int ret, parse_ret = 0;
+ size_t len;
+ mbedtls_asn1_buf *buf;
+ mbedtls_asn1_sequence *cur = certificate_policies;
+
+ /* Get main sequence tag */
+ ret = mbedtls_asn1_get_tag( p, end, &len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
+ if( ret != 0 )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+ if( *p + len != end )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+ /*
+ * Cannot be an empty sequence.
+ */
+ if( len == 0 )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+ while( *p < end )
+ {
+ mbedtls_x509_buf policy_oid;
+ const unsigned char *policy_end;
+
+ /*
+ * Get the policy sequence
+ */
+ if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+ policy_end = *p + len;
+
+ if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len,
+ MBEDTLS_ASN1_OID ) ) != 0 )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+ policy_oid.tag = MBEDTLS_ASN1_OID;
+ policy_oid.len = len;
+ policy_oid.p = *p;
+
+ /*
+ * Only AnyPolicy is currently supported when enforcing policy.
+ */
+ if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_POLICY, &policy_oid ) != 0 )
+ {
+ /*
+ * Set the parsing return code but continue parsing, in case this
+ * extension is critical and MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+ * is configured.
+ */
+ parse_ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
+ }
+
+ /* Allocate and assign next pointer */
+ if( cur->buf.p != NULL )
+ {
+ if( cur->next != NULL )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS );
+
+ cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
+
+ if( cur->next == NULL )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+ MBEDTLS_ERR_ASN1_ALLOC_FAILED );
+
+ cur = cur->next;
+ }
+
+ buf = &( cur->buf );
+ buf->tag = policy_oid.tag;
+ buf->p = policy_oid.p;
+ buf->len = policy_oid.len;
+
+ *p += len;
+
+ /*
+ * If there is an optional qualifier, then *p < policy_end
+ * Check the Qualifier len to verify it doesn't exceed policy_end.
+ */
+ if( *p < policy_end )
+ {
+ if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+ /*
+ * Skip the optional policy qualifiers.
+ */
+ *p += len;
+ }
+
+ if( *p != policy_end )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+ }
+
+ /* Set final sequence entry's next pointer to NULL */
+ cur->next = NULL;
+
+ if( *p != end )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+ return( parse_ret );
+}
+
+/*
* X.509 v3 extensions
*
*/
@@ -695,7 +888,7 @@
const unsigned char *end,
mbedtls_x509_crt *crt )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
unsigned char *end_ext_data, *end_ext_octet;
@@ -813,8 +1006,39 @@
return( ret );
break;
+ case MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES:
+ /* Parse certificate policies type */
+ if( ( ret = x509_get_certificate_policies( p, end_ext_octet,
+ &crt->certificate_policies ) ) != 0 )
+ {
+#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
+ if( is_critical )
+ return( ret );
+ else
+#endif
+ /*
+ * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, then we
+ * cannot interpret or enforce the policy. However, it is up to
+ * the user to choose how to enforce the policies,
+ * unless the extension is critical.
+ */
+ if( ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
+ return( ret );
+ }
+ break;
+
default:
- return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
+ /*
+ * If this is a non-critical extension, which the oid layer
+ * supports, but there isn't an x509 parser for it,
+ * skip the extension.
+ */
+#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
+ if( is_critical )
+ return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
+ else
+#endif
+ *p = end_ext_octet;
}
}
@@ -828,10 +1052,12 @@
/*
* Parse and fill a single X.509 certificate in DER format
*/
-static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char *buf,
- size_t buflen )
+static int x509_crt_parse_der_core( mbedtls_x509_crt *crt,
+ const unsigned char *buf,
+ size_t buflen,
+ int make_copy )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
unsigned char *p, *end, *crt_end;
mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
@@ -846,7 +1072,7 @@
if( crt == NULL || buf == NULL )
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
- // Use the original buffer until we figure out actual length
+ /* Use the original buffer until we figure out actual length. */
p = (unsigned char*) buf;
len = buflen;
end = p + len;
@@ -864,25 +1090,26 @@
return( MBEDTLS_ERR_X509_INVALID_FORMAT );
}
- if( len > (size_t) ( end - p ) )
- {
- mbedtls_x509_crt_free( crt );
- return( MBEDTLS_ERR_X509_INVALID_FORMAT +
- MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
- }
- crt_end = p + len;
-
- // Create and populate a new buffer for the raw field
- crt->raw.len = crt_end - buf;
- crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len );
- if( p == NULL )
- return( MBEDTLS_ERR_X509_ALLOC_FAILED );
-
- memcpy( p, buf, crt->raw.len );
-
- // Direct pointers to the new buffer
- p += crt->raw.len - len;
end = crt_end = p + len;
+ crt->raw.len = crt_end - buf;
+ if( make_copy != 0 )
+ {
+ /* Create and populate a new buffer for the raw field. */
+ crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len );
+ if( crt->raw.p == NULL )
+ return( MBEDTLS_ERR_X509_ALLOC_FAILED );
+
+ memcpy( crt->raw.p, buf, crt->raw.len );
+ crt->own_buffer = 1;
+
+ p += crt->raw.len - len;
+ end = crt_end = p + len;
+ }
+ else
+ {
+ crt->raw.p = (unsigned char*) buf;
+ crt->own_buffer = 0;
+ }
/*
* TBSCertificate ::= SEQUENCE {
@@ -987,11 +1214,13 @@
/*
* SubjectPublicKeyInfo
*/
+ crt->pk_raw.p = p;
if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 )
{
mbedtls_x509_crt_free( crt );
return( ret );
}
+ crt->pk_raw.len = p - crt->pk_raw.p;
/*
* issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
@@ -1085,10 +1314,12 @@
* Parse one X.509 certificate in DER format from a buffer and add them to a
* chained list
*/
-int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf,
- size_t buflen )
+static int mbedtls_x509_crt_parse_der_internal( mbedtls_x509_crt *chain,
+ const unsigned char *buf,
+ size_t buflen,
+ int make_copy )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_x509_crt *crt = chain, *prev = NULL;
/*
@@ -1118,7 +1349,7 @@
crt = crt->next;
}
- if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 )
+ if( ( ret = x509_crt_parse_der_core( crt, buf, buflen, make_copy ) ) != 0 )
{
if( prev )
prev->next = NULL;
@@ -1132,11 +1363,27 @@
return( 0 );
}
+int mbedtls_x509_crt_parse_der_nocopy( mbedtls_x509_crt *chain,
+ const unsigned char *buf,
+ size_t buflen )
+{
+ return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 0 ) );
+}
+
+int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain,
+ const unsigned char *buf,
+ size_t buflen )
+{
+ return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 1 ) );
+}
+
/*
* Parse one or more PEM certificates from a buffer and add them to the chained
* list
*/
-int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen )
+int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain,
+ const unsigned char *buf,
+ size_t buflen )
{
#if defined(MBEDTLS_PEM_PARSE_C)
int success = 0, first_error = 0, total_failed = 0;
@@ -1169,7 +1416,7 @@
#if defined(MBEDTLS_PEM_PARSE_C)
if( buf_format == MBEDTLS_X509_FORMAT_PEM )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_pem_context pem;
/* 1 rather than 0 since the terminating NULL byte is counted in */
@@ -1253,7 +1500,7 @@
*/
int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
unsigned char *buf;
@@ -1392,32 +1639,201 @@
}
#endif /* MBEDTLS_FS_IO */
-static int x509_info_subject_alt_name( char **buf, size_t *size,
- const mbedtls_x509_sequence *subject_alt_name )
+/*
+ * OtherName ::= SEQUENCE {
+ * type-id OBJECT IDENTIFIER,
+ * value [0] EXPLICIT ANY DEFINED BY type-id }
+ *
+ * HardwareModuleName ::= SEQUENCE {
+ * hwType OBJECT IDENTIFIER,
+ * hwSerialNum OCTET STRING }
+ *
+ * NOTE: we currently only parse and use otherName of type HwModuleName,
+ * as defined in RFC 4108.
+ */
+static int x509_get_other_name( const mbedtls_x509_buf *subject_alt_name,
+ mbedtls_x509_san_other_name *other_name )
{
- size_t i;
+ int ret = 0;
+ size_t len;
+ unsigned char *p = subject_alt_name->p;
+ const unsigned char *end = p + subject_alt_name->len;
+ mbedtls_x509_buf cur_oid;
+
+ if( ( subject_alt_name->tag &
+ ( MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK ) ) !=
+ ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ) )
+ {
+ /*
+ * The given subject alternative name is not of type "othername".
+ */
+ return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+ }
+
+ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
+ MBEDTLS_ASN1_OID ) ) != 0 )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+ cur_oid.tag = MBEDTLS_ASN1_OID;
+ cur_oid.p = p;
+ cur_oid.len = len;
+
+ /*
+ * Only HwModuleName is currently supported.
+ */
+ if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid ) != 0 )
+ {
+ return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
+ }
+
+ if( p + len >= end )
+ {
+ mbedtls_platform_zeroize( other_name, sizeof( *other_name ) );
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+ }
+ p += len;
+ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OID ) ) != 0 )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+ other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID;
+ other_name->value.hardware_module_name.oid.p = p;
+ other_name->value.hardware_module_name.oid.len = len;
+
+ if( p + len >= end )
+ {
+ mbedtls_platform_zeroize( other_name, sizeof( *other_name ) );
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+ }
+ p += len;
+ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
+ MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
+
+ other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
+ other_name->value.hardware_module_name.val.p = p;
+ other_name->value.hardware_module_name.val.len = len;
+ p += len;
+ if( p != end )
+ {
+ mbedtls_platform_zeroize( other_name,
+ sizeof( *other_name ) );
+ return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+ }
+ return( 0 );
+}
+
+static int x509_info_subject_alt_name( char **buf, size_t *size,
+ const mbedtls_x509_sequence
+ *subject_alt_name,
+ const char *prefix )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n = *size;
char *p = *buf;
const mbedtls_x509_sequence *cur = subject_alt_name;
- const char *sep = "";
- size_t sep_len = 0;
+ mbedtls_x509_subject_alternative_name san;
+ int parse_ret;
while( cur != NULL )
{
- if( cur->buf.len + sep_len >= n )
+ memset( &san, 0, sizeof( san ) );
+ parse_ret = mbedtls_x509_parse_subject_alt_name( &cur->buf, &san );
+ if( parse_ret != 0 )
{
- *p = '\0';
- return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+ if( parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE )
+ {
+ ret = mbedtls_snprintf( p, n, "\n%s <unsupported>", prefix );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+ }
+ else
+ {
+ ret = mbedtls_snprintf( p, n, "\n%s <malformed>", prefix );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+ }
+ cur = cur->next;
+ continue;
}
- n -= cur->buf.len + sep_len;
- for( i = 0; i < sep_len; i++ )
- *p++ = sep[i];
- for( i = 0; i < cur->buf.len; i++ )
- *p++ = cur->buf.p[i];
+ switch( san.type )
+ {
+ /*
+ * otherName
+ */
+ case MBEDTLS_X509_SAN_OTHER_NAME:
+ {
+ mbedtls_x509_san_other_name *other_name = &san.san.other_name;
- sep = ", ";
- sep_len = 2;
+ ret = mbedtls_snprintf( p, n, "\n%s otherName :", prefix );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+
+ if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME,
+ &other_name->value.hardware_module_name.oid ) != 0 )
+ {
+ ret = mbedtls_snprintf( p, n, "\n%s hardware module name :", prefix );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+ ret = mbedtls_snprintf( p, n, "\n%s hardware type : ", prefix );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+
+ ret = mbedtls_oid_get_numeric_string( p, n, &other_name->value.hardware_module_name.oid );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+
+ ret = mbedtls_snprintf( p, n, "\n%s hardware serial number : ", prefix );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+
+ if( other_name->value.hardware_module_name.val.len >= n )
+ {
+ *p = '\0';
+ return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+ }
+
+ memcpy( p, other_name->value.hardware_module_name.val.p,
+ other_name->value.hardware_module_name.val.len );
+ p += other_name->value.hardware_module_name.val.len;
+
+ n -= other_name->value.hardware_module_name.val.len;
+
+ }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
+ }
+ break;
+
+ /*
+ * dNSName
+ */
+ case MBEDTLS_X509_SAN_DNS_NAME:
+ {
+ ret = mbedtls_snprintf( p, n, "\n%s dNSName : ", prefix );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+ if( san.san.unstructured_name.len >= n )
+ {
+ *p = '\0';
+ return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+ }
+
+ memcpy( p, san.san.unstructured_name.p, san.san.unstructured_name.len );
+ p += san.san.unstructured_name.len;
+ n -= san.san.unstructured_name.len;
+ }
+ break;
+
+ /*
+ * Type not supported, skip item.
+ */
+ default:
+ ret = mbedtls_snprintf( p, n, "\n%s <unsupported>", prefix );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+ break;
+ }
cur = cur->next;
}
@@ -1430,6 +1846,56 @@
return( 0 );
}
+int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf,
+ mbedtls_x509_subject_alternative_name *san )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ switch( san_buf->tag &
+ ( MBEDTLS_ASN1_TAG_CLASS_MASK |
+ MBEDTLS_ASN1_TAG_VALUE_MASK ) )
+ {
+ /*
+ * otherName
+ */
+ case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ):
+ {
+ mbedtls_x509_san_other_name other_name;
+
+ ret = x509_get_other_name( san_buf, &other_name );
+ if( ret != 0 )
+ return( ret );
+
+ memset( san, 0, sizeof( mbedtls_x509_subject_alternative_name ) );
+ san->type = MBEDTLS_X509_SAN_OTHER_NAME;
+ memcpy( &san->san.other_name,
+ &other_name, sizeof( other_name ) );
+
+ }
+ break;
+
+ /*
+ * dNSName
+ */
+ case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ):
+ {
+ memset( san, 0, sizeof( mbedtls_x509_subject_alternative_name ) );
+ san->type = MBEDTLS_X509_SAN_DNS_NAME;
+
+ memcpy( &san->san.unstructured_name,
+ san_buf, sizeof( *san_buf ) );
+
+ }
+ break;
+
+ /*
+ * Type not supported
+ */
+ default:
+ return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
+ }
+ return( 0 );
+}
+
#define PRINT_ITEM(i) \
{ \
ret = mbedtls_snprintf( p, n, "%s" i, sep ); \
@@ -1444,7 +1910,7 @@
static int x509_info_cert_type( char **buf, size_t *size,
unsigned char ns_cert_type )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n = *size;
char *p = *buf;
const char *sep = "";
@@ -1471,7 +1937,7 @@
static int x509_info_key_usage( char **buf, size_t *size,
unsigned int key_usage )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n = *size;
char *p = *buf;
const char *sep = "";
@@ -1495,7 +1961,7 @@
static int x509_info_ext_key_usage( char **buf, size_t *size,
const mbedtls_x509_sequence *extended_key_usage )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const char *desc;
size_t n = *size;
char *p = *buf;
@@ -1521,6 +1987,35 @@
return( 0 );
}
+static int x509_info_cert_policies( char **buf, size_t *size,
+ const mbedtls_x509_sequence *certificate_policies )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ const char *desc;
+ size_t n = *size;
+ char *p = *buf;
+ const mbedtls_x509_sequence *cur = certificate_policies;
+ const char *sep = "";
+
+ while( cur != NULL )
+ {
+ if( mbedtls_oid_get_certificate_policies( &cur->buf, &desc ) != 0 )
+ desc = "???";
+
+ ret = mbedtls_snprintf( p, n, "%s%s", sep, desc );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+
+ sep = ", ";
+
+ cur = cur->next;
+ }
+
+ *size = n;
+ *buf = p;
+
+ return( 0 );
+}
+
/*
* Return an informational string about the certificate.
*/
@@ -1529,7 +2024,7 @@
int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
const mbedtls_x509_crt *crt )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
char *p;
char key_size_str[BEFORE_COLON];
@@ -1616,11 +2111,12 @@
if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME )
{
- ret = mbedtls_snprintf( p, n, "\n%ssubject alt name : ", prefix );
+ ret = mbedtls_snprintf( p, n, "\n%ssubject alt name :", prefix );
MBEDTLS_X509_SAFE_SNPRINTF;
if( ( ret = x509_info_subject_alt_name( &p, &n,
- &crt->subject_alt_names ) ) != 0 )
+ &crt->subject_alt_names,
+ prefix ) ) != 0 )
return( ret );
}
@@ -1652,6 +2148,16 @@
return( ret );
}
+ if( crt->ext_types & MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES )
+ {
+ ret = mbedtls_snprintf( p, n, "\n%scertificate policies : ", prefix );
+ MBEDTLS_X509_SAFE_SNPRINTF;
+
+ if( ( ret = x509_info_cert_policies( &p, &n,
+ &crt->certificate_policies ) ) != 0 )
+ return( ret );
+ }
+
ret = mbedtls_snprintf( p, n, "\n" );
MBEDTLS_X509_SAFE_SNPRINTF;
@@ -1690,7 +2196,7 @@
int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
uint32_t flags )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const struct x509_crt_verify_string *cur;
char *p = buf;
size_t n = size;
@@ -1891,16 +2397,35 @@
mbedtls_x509_crt *parent,
mbedtls_x509_crt_restart_ctx *rs_ctx )
{
- const mbedtls_md_info_t *md_info;
unsigned char hash[MBEDTLS_MD_MAX_SIZE];
-
+ size_t hash_len;
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+ const mbedtls_md_info_t *md_info;
md_info = mbedtls_md_info_from_type( child->sig_md );
+ hash_len = mbedtls_md_get_size( md_info );
+
+ /* Note: hash errors can happen only after an internal error */
if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 )
+ return( -1 );
+#else
+ psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT;
+ psa_algorithm_t hash_alg = mbedtls_psa_translate_md( child->sig_md );
+
+ if( psa_hash_setup( &hash_operation, hash_alg ) != PSA_SUCCESS )
+ return( -1 );
+
+ if( psa_hash_update( &hash_operation, child->tbs.p, child->tbs.len )
+ != PSA_SUCCESS )
{
- /* Note: this can't happen except after an internal error */
return( -1 );
}
+ if( psa_hash_finish( &hash_operation, hash, sizeof( hash ), &hash_len )
+ != PSA_SUCCESS )
+ {
+ return( -1 );
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
/* Skip expensive computation on obvious mismatch */
if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) )
return( -1 );
@@ -1909,7 +2434,7 @@
if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA )
{
return( mbedtls_pk_verify_restartable( &parent->pk,
- child->sig_md, hash, mbedtls_md_get_size( md_info ),
+ child->sig_md, hash, hash_len,
child->sig.p, child->sig.len, &rs_ctx->pk ) );
}
#else
@@ -1917,7 +2442,7 @@
#endif
return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk,
- child->sig_md, hash, mbedtls_md_get_size( md_info ),
+ child->sig_md, hash, hash_len,
child->sig.p, child->sig.len ) );
}
@@ -2011,9 +2536,9 @@
unsigned self_cnt,
mbedtls_x509_crt_restart_ctx *rs_ctx )
{
- int ret;
+ 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? */
@@ -2134,7 +2659,7 @@
unsigned self_cnt,
mbedtls_x509_crt_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_x509_crt *search_list;
*parent_is_trusted = 1;
@@ -2259,13 +2784,15 @@
mbedtls_x509_crt *crt,
mbedtls_x509_crt *trust_ca,
mbedtls_x509_crl *ca_crl,
+ mbedtls_x509_crt_ca_cb_t f_ca_cb,
+ void *p_ca_cb,
const mbedtls_x509_crt_profile *profile,
mbedtls_x509_crt_verify_chain *ver_chain,
mbedtls_x509_crt_restart_ctx *rs_ctx )
{
/* Don't initialize any of those variables here, so that the compiler can
* catch potential issues with jumping ahead when restarting */
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t *flags;
mbedtls_x509_crt_verify_chain_item *cur;
mbedtls_x509_crt *child;
@@ -2274,6 +2801,7 @@
int child_is_trusted;
int signature_is_good;
unsigned self_cnt;
+ mbedtls_x509_crt *cur_trust_ca = NULL;
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/* resume if we had an operation in progress */
@@ -2333,8 +2861,32 @@
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
find_parent:
#endif
+
+ /* Obtain list of potential trusted signers from CA callback,
+ * or use statically provided list. */
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+ if( f_ca_cb != NULL )
+ {
+ mbedtls_x509_crt_free( ver_chain->trust_ca_cb_result );
+ mbedtls_free( ver_chain->trust_ca_cb_result );
+ ver_chain->trust_ca_cb_result = NULL;
+
+ ret = f_ca_cb( p_ca_cb, child, &ver_chain->trust_ca_cb_result );
+ if( ret != 0 )
+ return( MBEDTLS_ERR_X509_FATAL_ERROR );
+
+ cur_trust_ca = ver_chain->trust_ca_cb_result;
+ }
+ else
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
+ {
+ ((void) f_ca_cb);
+ ((void) p_ca_cb);
+ cur_trust_ca = trust_ca;
+ }
+
/* Look for a parent in trusted CAs or up the chain */
- ret = x509_crt_find_parent( child, trust_ca, &parent,
+ ret = x509_crt_find_parent( child, cur_trust_ca, &parent,
&parent_is_trusted, &signature_is_good,
ver_chain->len - 1, self_cnt, rs_ctx );
@@ -2469,7 +3021,7 @@
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
void *p_vrfy )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned i;
uint32_t cur_flags;
const mbedtls_x509_crt_verify_chain_item *cur;
@@ -2490,36 +3042,6 @@
}
/*
- * Verify the certificate validity (default profile, not restartable)
- */
-int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
- mbedtls_x509_crt *trust_ca,
- mbedtls_x509_crl *ca_crl,
- const char *cn, uint32_t *flags,
- int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
- void *p_vrfy )
-{
- return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
- &mbedtls_x509_crt_profile_default, cn, flags,
- f_vrfy, p_vrfy, NULL ) );
-}
-
-/*
- * Verify the certificate validity (user-chosen profile, not restartable)
- */
-int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
- mbedtls_x509_crt *trust_ca,
- mbedtls_x509_crl *ca_crl,
- const mbedtls_x509_crt_profile *profile,
- const char *cn, uint32_t *flags,
- int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
- void *p_vrfy )
-{
- return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl,
- profile, cn, flags, f_vrfy, p_vrfy, NULL ) );
-}
-
-/*
* Verify the certificate validity, with profile, restartable version
*
* This function:
@@ -2528,17 +3050,26 @@
* as that isn't done as part of chain building/verification currently
* - builds and verifies the chain
* - then calls the callback and merges the flags
+ *
+ * The parameters pairs `trust_ca`, `ca_crl` and `f_ca_cb`, `p_ca_cb`
+ * are mutually exclusive: If `f_ca_cb != NULL`, it will be used by the
+ * verification routine to search for trusted signers, and CRLs will
+ * be disabled. Otherwise, `trust_ca` will be used as the static list
+ * of trusted signers, and `ca_crl` will be use as the static list
+ * of CRLs.
*/
-int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
+static int x509_crt_verify_restartable_ca_cb( mbedtls_x509_crt *crt,
mbedtls_x509_crt *trust_ca,
mbedtls_x509_crl *ca_crl,
+ mbedtls_x509_crt_ca_cb_t f_ca_cb,
+ void *p_ca_cb,
const mbedtls_x509_crt_profile *profile,
const char *cn, uint32_t *flags,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
void *p_vrfy,
mbedtls_x509_crt_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_pk_type_t pk_type;
mbedtls_x509_crt_verify_chain ver_chain;
uint32_t ee_flags;
@@ -2567,7 +3098,8 @@
ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
/* Check the chain */
- ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile,
+ ret = x509_crt_verify_chain( crt, trust_ca, ca_crl,
+ f_ca_cb, p_ca_cb, profile,
&ver_chain, rs_ctx );
if( ret != 0 )
@@ -2580,6 +3112,13 @@
ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy );
exit:
+
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+ mbedtls_x509_crt_free( ver_chain.trust_ca_cb_result );
+ mbedtls_free( ver_chain.trust_ca_cb_result );
+ ver_chain.trust_ca_cb_result = NULL;
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
+
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
mbedtls_x509_crt_restart_free( rs_ctx );
@@ -2603,6 +3142,77 @@
return( 0 );
}
+
+/*
+ * Verify the certificate validity (default profile, not restartable)
+ */
+int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
+ mbedtls_x509_crt *trust_ca,
+ mbedtls_x509_crl *ca_crl,
+ const char *cn, uint32_t *flags,
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+ void *p_vrfy )
+{
+ return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl,
+ NULL, NULL,
+ &mbedtls_x509_crt_profile_default,
+ cn, flags,
+ f_vrfy, p_vrfy, NULL ) );
+}
+
+/*
+ * Verify the certificate validity (user-chosen profile, not restartable)
+ */
+int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
+ mbedtls_x509_crt *trust_ca,
+ mbedtls_x509_crl *ca_crl,
+ const mbedtls_x509_crt_profile *profile,
+ const char *cn, uint32_t *flags,
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+ void *p_vrfy )
+{
+ return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl,
+ NULL, NULL,
+ profile, cn, flags,
+ f_vrfy, p_vrfy, NULL ) );
+}
+
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+/*
+ * Verify the certificate validity (user-chosen profile, CA callback,
+ * not restartable).
+ */
+int mbedtls_x509_crt_verify_with_ca_cb( mbedtls_x509_crt *crt,
+ mbedtls_x509_crt_ca_cb_t f_ca_cb,
+ void *p_ca_cb,
+ const mbedtls_x509_crt_profile *profile,
+ const char *cn, uint32_t *flags,
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+ void *p_vrfy )
+{
+ return( x509_crt_verify_restartable_ca_cb( crt, NULL, NULL,
+ f_ca_cb, p_ca_cb,
+ profile, cn, flags,
+ f_vrfy, p_vrfy, NULL ) );
+}
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
+
+int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
+ mbedtls_x509_crt *trust_ca,
+ mbedtls_x509_crl *ca_crl,
+ const mbedtls_x509_crt_profile *profile,
+ const char *cn, uint32_t *flags,
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+ void *p_vrfy,
+ mbedtls_x509_crt_restart_ctx *rs_ctx )
+{
+ return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl,
+ NULL, NULL,
+ profile, cn, flags,
+ f_vrfy, p_vrfy, rs_ctx ) );
+}
+
+
/*
* Initialize a certificate chain
*/
@@ -2672,7 +3282,17 @@
mbedtls_free( seq_prv );
}
- if( cert_cur->raw.p != NULL )
+ seq_cur = cert_cur->certificate_policies.next;
+ while( seq_cur != NULL )
+ {
+ seq_prv = seq_cur;
+ seq_cur = seq_cur->next;
+ mbedtls_platform_zeroize( seq_prv,
+ sizeof( mbedtls_x509_sequence ) );
+ mbedtls_free( seq_prv );
+ }
+
+ if( cert_cur->raw.p != NULL && cert_cur->own_buffer )
{
mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len );
mbedtls_free( cert_cur->raw.p );
diff --git a/lib/libmbedtls/mbedtls/library/x509_csr.c b/lib/libmbedtls/mbedtls/library/x509_csr.c
index b017ad8..37e47e4 100644
--- a/lib/libmbedtls/mbedtls/library/x509_csr.c
+++ b/lib/libmbedtls/mbedtls/library/x509_csr.c
@@ -38,6 +38,7 @@
#if defined(MBEDTLS_X509_CSR_PARSE_C)
#include "mbedtls/x509_csr.h"
+#include "mbedtls/error.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
@@ -68,7 +69,7 @@
const unsigned char *end,
int *ver )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
{
@@ -90,7 +91,7 @@
int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr,
const unsigned char *buf, size_t buflen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
unsigned char *p, *end;
mbedtls_x509_buf sig_params;
@@ -262,7 +263,7 @@
int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen )
{
#if defined(MBEDTLS_PEM_PARSE_C)
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t use_len;
mbedtls_pem_context pem;
#endif
@@ -312,7 +313,7 @@
*/
int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
unsigned char *buf;
@@ -336,7 +337,7 @@
int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix,
const mbedtls_x509_csr *csr )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
char *p;
char key_size_str[BEFORE_COLON];
diff --git a/lib/libmbedtls/mbedtls/library/x509write_crt.c b/lib/libmbedtls/mbedtls/library/x509write_crt.c
index cb5ed5a..80eb23b 100644
--- a/lib/libmbedtls/mbedtls/library/x509write_crt.c
+++ b/lib/libmbedtls/mbedtls/library/x509write_crt.c
@@ -34,10 +34,11 @@
#if defined(MBEDTLS_X509_CRT_WRITE_C)
#include "mbedtls/x509_crt.h"
-#include "mbedtls/oid.h"
#include "mbedtls/asn1write.h"
-#include "mbedtls/sha1.h"
+#include "mbedtls/error.h"
+#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/sha1.h"
#include <string.h>
@@ -45,16 +46,6 @@
#include "mbedtls/pem.h"
#endif /* MBEDTLS_PEM_WRITE_C */
-/*
- * For the currently used signature algorithms the buffer to store any signature
- * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)
- */
-#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
-#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
-#else
-#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
-#endif
-
void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx )
{
memset( ctx, 0, sizeof( mbedtls_x509write_cert ) );
@@ -74,41 +65,46 @@
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) );
}
-void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version )
+void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx,
+ int version )
{
ctx->version = version;
}
-void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg )
+void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx,
+ mbedtls_md_type_t md_alg )
{
ctx->md_alg = md_alg;
}
-void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key )
+void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx,
+ mbedtls_pk_context *key )
{
ctx->subject_key = key;
}
-void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key )
+void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx,
+ mbedtls_pk_context *key )
{
ctx->issuer_key = key;
}
int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx,
- const char *subject_name )
+ const char *subject_name )
{
return mbedtls_x509_string_to_names( &ctx->subject, subject_name );
}
int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx,
- const char *issuer_name )
+ const char *issuer_name )
{
return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name );
}
-int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial )
+int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx,
+ const mbedtls_mpi *serial )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 )
return( ret );
@@ -116,8 +112,9 @@
return( 0 );
}
-int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before,
- const char *not_after )
+int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx,
+ const char *not_before,
+ const char *not_after )
{
if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ||
strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 )
@@ -137,14 +134,14 @@
int critical,
const unsigned char *val, size_t val_len )
{
- return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
- critical, val, val_len );
+ return( mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
+ critical, val, val_len ) );
}
int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx,
- int is_ca, int max_pathlen )
+ int is_ca, int max_pathlen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char buf[9];
unsigned char *c = buf + sizeof(buf);
size_t len = 0;
@@ -158,30 +155,34 @@
{
if( max_pathlen >= 0 )
{
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf,
+ max_pathlen ) );
}
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) );
}
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf,
+ MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE ) );
- return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
- MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ),
- 0, buf + sizeof(buf) - len, len );
+ return(
+ mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
+ MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ),
+ 0, buf + sizeof(buf) - len, len ) );
}
#if defined(MBEDTLS_SHA1_C)
int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
unsigned char *c = buf + sizeof(buf);
size_t len = 0;
memset( buf, 0, sizeof(buf) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) );
+ MBEDTLS_ASN1_CHK_ADD( len,
+ mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) );
ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len,
buf + sizeof( buf ) - 20 );
@@ -191,22 +192,25 @@
len = 20;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) );
+ MBEDTLS_ASN1_CHK_ADD( len,
+ mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) );
- return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
- MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ),
- 0, buf + sizeof(buf) - len, len );
+ return mbedtls_x509write_crt_set_extension( ctx,
+ MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
+ MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ),
+ 0, buf + sizeof(buf) - len, len );
}
int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
unsigned char *c = buf + sizeof( buf );
size_t len = 0;
memset( buf, 0, sizeof(buf) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) );
+ MBEDTLS_ASN1_CHK_ADD( len,
+ mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) );
ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len,
buf + sizeof( buf ) - 20 );
@@ -216,63 +220,55 @@
len = 20;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) );
+ MBEDTLS_ASN1_CHK_ADD( len,
+ mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
- MBEDTLS_ASN1_SEQUENCE ) );
+ MBEDTLS_ASN1_CHK_ADD( len,
+ mbedtls_asn1_write_tag( &c, buf,
+ MBEDTLS_ASN1_CONSTRUCTED |
+ MBEDTLS_ASN1_SEQUENCE ) );
- return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
- MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ),
- 0, buf + sizeof( buf ) - len, len );
+ return mbedtls_x509write_crt_set_extension(
+ ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
+ MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ),
+ 0, buf + sizeof( buf ) - len, len );
}
#endif /* MBEDTLS_SHA1_C */
-static size_t crt_get_unused_bits_for_named_bitstring( unsigned char bitstring,
- size_t bit_offset )
-{
- size_t unused_bits;
-
- /* Count the unused bits removing trailing 0s */
- for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ )
- if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 )
- break;
-
- return( unused_bits );
-}
-
int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
unsigned int key_usage )
{
- unsigned char buf[4], ku;
+ unsigned char buf[5], ku[2];
unsigned char *c;
- int ret;
- size_t unused_bits;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
MBEDTLS_X509_KU_NON_REPUDIATION |
MBEDTLS_X509_KU_KEY_ENCIPHERMENT |
MBEDTLS_X509_KU_DATA_ENCIPHERMENT |
MBEDTLS_X509_KU_KEY_AGREEMENT |
MBEDTLS_X509_KU_KEY_CERT_SIGN |
- MBEDTLS_X509_KU_CRL_SIGN;
+ MBEDTLS_X509_KU_CRL_SIGN |
+ MBEDTLS_X509_KU_ENCIPHER_ONLY |
+ MBEDTLS_X509_KU_DECIPHER_ONLY;
/* Check that nothing other than the allowed flags is set */
if( ( key_usage & ~allowed_bits ) != 0 )
return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
- c = buf + 4;
- ku = (unsigned char)key_usage;
- unused_bits = crt_get_unused_bits_for_named_bitstring( ku, 1 );
- ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 8 - unused_bits );
+ c = buf + 5;
+ ku[0] = (unsigned char)( key_usage );
+ ku[1] = (unsigned char)( key_usage >> 8 );
+ ret = mbedtls_asn1_write_named_bitstring( &c, buf, ku, 9 );
if( ret < 0 )
return( ret );
- else if( ret < 3 || ret > 4 )
+ else if( ret < 3 || ret > 5 )
return( MBEDTLS_ERR_X509_INVALID_FORMAT );
ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
- MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
- 1, c, (size_t)ret );
+ MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
+ 1, c, (size_t)ret );
if( ret != 0 )
return( ret );
@@ -284,22 +280,17 @@
{
unsigned char buf[4];
unsigned char *c;
- size_t unused_bits;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
c = buf + 4;
- unused_bits = crt_get_unused_bits_for_named_bitstring( ns_cert_type, 0 );
- ret = mbedtls_asn1_write_bitstring( &c,
- buf,
- &ns_cert_type,
- 8 - unused_bits );
+ ret = mbedtls_asn1_write_named_bitstring( &c, buf, &ns_cert_type, 8 );
if( ret < 3 || ret > 4 )
return( ret );
ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
- MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
- 0, c, (size_t)ret );
+ MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
+ 0, c, (size_t)ret );
if( ret != 0 )
return( ret );
@@ -309,7 +300,7 @@
static int x509_write_time( unsigned char **p, unsigned char *start,
const char *t, size_t size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
/*
@@ -321,7 +312,8 @@
(const unsigned char *) t + 2,
size - 2 ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
+ MBEDTLS_ASN1_UTC_TIME ) );
}
else
{
@@ -329,31 +321,32 @@
(const unsigned char *) t,
size ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
+ MBEDTLS_ASN1_GENERALIZED_TIME ) );
}
return( (int) len );
}
-int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
+int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx,
+ unsigned char *buf, size_t size,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const char *sig_oid;
size_t sig_oid_len = 0;
unsigned char *c, *c2;
unsigned char hash[64];
- unsigned char sig[SIGNATURE_MAX_SIZE];
- unsigned char tmp_buf[2048];
+ unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE];
size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
size_t len = 0;
mbedtls_pk_type_t pk_alg;
/*
- * Prepare data to be signed in tmp_buf
+ * Prepare data to be signed at the end of the target buffer
*/
- c = tmp_buf + sizeof( tmp_buf );
+ c = buf + size;
/* Signature algorithm needed in TBS, and later for actual signature */
@@ -379,27 +372,36 @@
/* Only for v3 */
if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 )
{
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
- MBEDTLS_ASN1_SEQUENCE ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC |
- MBEDTLS_ASN1_CONSTRUCTED | 3 ) );
+ MBEDTLS_ASN1_CHK_ADD( len,
+ mbedtls_x509_write_extensions( &c,
+ buf, ctx->extensions ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
+ MBEDTLS_ASN1_CHK_ADD( len,
+ mbedtls_asn1_write_tag( &c, buf,
+ MBEDTLS_ASN1_CONSTRUCTED |
+ MBEDTLS_ASN1_SEQUENCE ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
+ MBEDTLS_ASN1_CHK_ADD( len,
+ mbedtls_asn1_write_tag( &c, buf,
+ MBEDTLS_ASN1_CONTEXT_SPECIFIC |
+ MBEDTLS_ASN1_CONSTRUCTED | 3 ) );
}
/*
* SubjectPublicKeyInfo
*/
- MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->subject_key,
- tmp_buf, c - tmp_buf ) );
+ MBEDTLS_ASN1_CHK_ADD( pub_len,
+ mbedtls_pk_write_pubkey_der( ctx->subject_key,
+ buf, c - buf ) );
c -= pub_len;
len += pub_len;
/*
* Subject ::= Name
*/
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) );
+ MBEDTLS_ASN1_CHK_ADD( len,
+ mbedtls_x509_write_names( &c, buf,
+ ctx->subject ) );
/*
* Validity ::= SEQUENCE {
@@ -408,32 +410,39 @@
*/
sub_len = 0;
- MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
- MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
+ MBEDTLS_ASN1_CHK_ADD( sub_len,
+ x509_write_time( &c, buf, ctx->not_after,
+ MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
- MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
- MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
+ MBEDTLS_ASN1_CHK_ADD( sub_len,
+ x509_write_time( &c, buf, ctx->not_before,
+ MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
len += sub_len;
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
- MBEDTLS_ASN1_SEQUENCE ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, sub_len ) );
+ MBEDTLS_ASN1_CHK_ADD( len,
+ mbedtls_asn1_write_tag( &c, buf,
+ MBEDTLS_ASN1_CONSTRUCTED |
+ MBEDTLS_ASN1_SEQUENCE ) );
/*
* Issuer ::= Name
*/
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->issuer ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf,
+ ctx->issuer ) );
/*
* Signature ::= AlgorithmIdentifier
*/
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, tmp_buf,
- sig_oid, strlen( sig_oid ), 0 ) );
+ MBEDTLS_ASN1_CHK_ADD( len,
+ mbedtls_asn1_write_algorithm_identifier( &c, buf,
+ sig_oid, strlen( sig_oid ), 0 ) );
/*
* Serial ::= INTEGER
*/
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf,
+ &ctx->serial ) );
/*
* Version ::= INTEGER { v1(0), v2(1), v3(2) }
@@ -443,48 +452,67 @@
if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 )
{
sub_len = 0;
- MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) );
+ MBEDTLS_ASN1_CHK_ADD( sub_len,
+ mbedtls_asn1_write_int( &c, buf, ctx->version ) );
len += sub_len;
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC |
- MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
+ MBEDTLS_ASN1_CHK_ADD( len,
+ mbedtls_asn1_write_len( &c, buf, sub_len ) );
+ MBEDTLS_ASN1_CHK_ADD( len,
+ mbedtls_asn1_write_tag( &c, buf,
+ MBEDTLS_ASN1_CONTEXT_SPECIFIC |
+ MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
}
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
- MBEDTLS_ASN1_SEQUENCE ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
+ MBEDTLS_ASN1_CHK_ADD( len,
+ mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
+ MBEDTLS_ASN1_SEQUENCE ) );
/*
* Make signature
*/
+
+ /* Compute hash of CRT. */
if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c,
len, hash ) ) != 0 )
{
return( ret );
}
- if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len,
- f_rng, p_rng ) ) != 0 )
+ if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg,
+ hash, 0, sig, &sig_len,
+ f_rng, p_rng ) ) != 0 )
{
return( ret );
}
- /*
- * Write data to output buffer
- */
+ /* Move CRT to the front of the buffer to have space
+ * for the signature. */
+ memmove( buf, c, len );
+ c = buf + len;
+
+ /* Add signature at the end of the buffer,
+ * making sure that it doesn't underflow
+ * into the CRT buffer. */
c2 = buf + size;
- MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf,
+ MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, c,
sig_oid, sig_oid_len, sig, sig_len ) );
- if( len > (size_t)( c2 - buf ) )
- return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+ /*
+ * Memory layout after this step:
+ *
+ * buf c=buf+len c2 buf+size
+ * [CRT0,...,CRTn, UNUSED, ..., UNUSED, SIG0, ..., SIGm]
+ */
- c2 -= len;
- memcpy( c2, c, len );
+ /* Move raw CRT to just before the signature. */
+ c = c2 - len;
+ memmove( c, buf, len );
len += sig_and_oid_len;
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED |
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf,
+ MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE ) );
return( (int) len );
@@ -494,23 +522,23 @@
#define PEM_END_CRT "-----END CERTIFICATE-----\n"
#if defined(MBEDTLS_PEM_WRITE_C)
-int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, size_t size,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
+int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt,
+ unsigned char *buf, size_t size,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
{
- int ret;
- unsigned char output_buf[4096];
- size_t olen = 0;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t olen;
- if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf),
+ if( ( ret = mbedtls_x509write_crt_der( crt, buf, size,
f_rng, p_rng ) ) < 0 )
{
return( ret );
}
if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT,
- output_buf + sizeof(output_buf) - ret,
- ret, buf, size, &olen ) ) != 0 )
+ buf + size - ret, ret,
+ buf, size, &olen ) ) != 0 )
{
return( ret );
}
diff --git a/lib/libmbedtls/mbedtls/library/x509write_csr.c b/lib/libmbedtls/mbedtls/library/x509write_csr.c
index de61934..781a527 100644
--- a/lib/libmbedtls/mbedtls/library/x509write_csr.c
+++ b/lib/libmbedtls/mbedtls/library/x509write_csr.c
@@ -33,10 +33,16 @@
#if defined(MBEDTLS_X509_CSR_WRITE_C)
#include "mbedtls/x509_csr.h"
-#include "mbedtls/oid.h"
#include "mbedtls/asn1write.h"
+#include "mbedtls/error.h"
+#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
+#endif
+
#include <string.h>
#include <stdlib.h>
@@ -44,16 +50,6 @@
#include "mbedtls/pem.h"
#endif
-/*
- * For the currently used signature algorithms the buffer to store any signature
- * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)
- */
-#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
-#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
-#else
-#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
-#endif
-
void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx )
{
memset( ctx, 0, sizeof( mbedtls_x509write_csr ) );
@@ -91,35 +87,17 @@
0, val, val_len );
}
-static size_t csr_get_unused_bits_for_named_bitstring( unsigned char bitstring,
- size_t bit_offset )
-{
- size_t unused_bits;
-
- /* Count the unused bits removing trailing 0s */
- for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ )
- if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 )
- break;
-
- return( unused_bits );
-}
-
int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage )
{
unsigned char buf[4];
unsigned char *c;
- size_t unused_bits;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
c = buf + 4;
- unused_bits = csr_get_unused_bits_for_named_bitstring( key_usage, 0 );
- ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 8 - unused_bits );
-
- if( ret < 0 )
+ ret = mbedtls_asn1_write_named_bitstring( &c, buf, &key_usage, 8 );
+ if( ret < 3 || ret > 4 )
return( ret );
- else if( ret < 3 || ret > 4 )
- return( MBEDTLS_ERR_X509_INVALID_FORMAT );
ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
@@ -135,20 +113,12 @@
{
unsigned char buf[4];
unsigned char *c;
- size_t unused_bits;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
c = buf + 4;
- unused_bits = csr_get_unused_bits_for_named_bitstring( ns_cert_type, 0 );
- ret = mbedtls_asn1_write_bitstring( &c,
- buf,
- &ns_cert_type,
- 8 - unused_bits );
-
- if( ret < 0 )
- return( ret );
- else if( ret < 3 || ret > 4 )
+ ret = mbedtls_asn1_write_named_bitstring( &c, buf, &ns_cert_type, 8 );
+ if( ret < 3 || ret > 4 )
return( ret );
ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
@@ -164,17 +134,21 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const char *sig_oid;
size_t sig_oid_len = 0;
unsigned char *c, *c2;
unsigned char hash[64];
- unsigned char sig[SIGNATURE_MAX_SIZE];
+ unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE];
unsigned char tmp_buf[2048];
size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
size_t len = 0;
mbedtls_pk_type_t pk_alg;
-
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT;
+ size_t hash_len;
+ psa_algorithm_t hash_alg = mbedtls_psa_translate_md( ctx->md_alg );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
/*
* Prepare data to be signed in tmp_buf
*/
@@ -225,11 +199,25 @@
/*
* Prepare signature
+ * Note: hash errors can happen only after an internal error
*/
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if( psa_hash_setup( &hash_operation, hash_alg ) != PSA_SUCCESS )
+ return( MBEDTLS_ERR_X509_FATAL_ERROR );
+
+ if( psa_hash_update( &hash_operation, c, len ) != PSA_SUCCESS )
+ return( MBEDTLS_ERR_X509_FATAL_ERROR );
+
+ if( psa_hash_finish( &hash_operation, hash, sizeof( hash ), &hash_len )
+ != PSA_SUCCESS )
+ {
+ return( MBEDTLS_ERR_X509_FATAL_ERROR );
+ }
+#else /* MBEDTLS_USE_PSA_CRYPTO */
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 )
{
@@ -278,18 +266,17 @@
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
- unsigned char output_buf[4096];
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t olen = 0;
- if( ( ret = mbedtls_x509write_csr_der( ctx, output_buf, sizeof(output_buf),
+ if( ( ret = mbedtls_x509write_csr_der( ctx, buf, size,
f_rng, p_rng ) ) < 0 )
{
return( ret );
}
if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,
- output_buf + sizeof(output_buf) - ret,
+ buf + size - ret,
ret, buf, size, &olen ) ) != 0 )
{
return( ret );