Merge branch 'development' into rfc9146_2

Signed-off-by: Dave Rodgman <dave.rodgman@arm.com>
This commit is contained in:
Dave Rodgman 2022-11-14 17:43:15 +00:00 committed by GitHub
commit d384b64dd2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
346 changed files with 24509 additions and 10001 deletions

2
.gitattributes vendored Normal file
View file

@ -0,0 +1,2 @@
# Classify all '.function' files as C for syntax highlighting purposes
*.function linguist-language=C

View file

@ -1,36 +1,19 @@
Notes:
* Pull requests cannot be accepted until the PR follows the [contributing guidelines](../CONTRIBUTING.md). In particular, each commit must have at least one `Signed-off-by:` line from the committer to certify that the contribution is made under the terms of the [Developer Certificate of Origin](../dco.txt).
* This is just a template, so feel free to use/remove the unnecessary things
## Description
A few sentences describing the overall goals of the pull request's commits.
Please write a few sentences describing the overall goals of the pull request's commits.
## Status
**READY/IN DEVELOPMENT/HOLD**
## Requires Backporting
When there is a bug fix, it should be backported to all maintained and supported branches.
Changes do not have to be backported if:
- This PR is a new feature\enhancement
- This PR contains changes in the API. If this is true, and there is a need for the fix to be backported, the fix should be handled differently in the legacy branch
## Gatekeeper checklist
Yes | NO
Which branch?
## Migrations
If there is any API change, what's the incentive and logic for it.
YES | NO
## Additional comments
Any additional information that could be of interest
## Todos
- [ ] Tests
- [ ] Documentation
- [ ] Changelog updated
- [ ] Backported
- [ ] **changelog** provided, or not required
- [ ] **backport** done, or not required
- [ ] **tests** provided, or not required
## Steps to test or reproduce
Outline the steps to test or reproduce the PR here.
## Notes for the submitter
Please refer to the [contributing guidelines](../CONTRIBUTING.md), especially the
checklist for PR contributors.

View file

@ -73,3 +73,7 @@ reports=no
# Allow unused variables if their name starts with an underscore.
# [unused-argument]
dummy-variables-rgx=_.*
[SIMILARITIES]
# Ignore imports when computing similarities.
ignore-imports=yes

View file

@ -28,12 +28,7 @@
#include "everest/x25519.h"
#include "everest/everest.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)

View file

@ -120,38 +120,33 @@ endif()
# Create a symbolic link from ${base_name} in the binary directory
# to the corresponding path in the source directory.
# Note: Copies the file(s) on Windows.
function(link_to_source base_name)
# Get OS dependent path to use in `execute_process`
if (CMAKE_HOST_WIN32)
#mklink is an internal command of cmd.exe it can only work with \
string(REPLACE "/" "\\" link "${CMAKE_CURRENT_BINARY_DIR}/${base_name}")
string(REPLACE "/" "\\" target "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}")
else()
set(link "${CMAKE_CURRENT_BINARY_DIR}/${base_name}")
set(target "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}")
endif()
set(link "${CMAKE_CURRENT_BINARY_DIR}/${base_name}")
set(target "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}")
# Linking to non-existent file is not desirable. At best you will have a
# dangling link, but when building in tree, this can create a symbolic link
# to itself.
if (EXISTS ${target} AND NOT EXISTS ${link})
if (CMAKE_HOST_UNIX)
set(command ln -s ${target} ${link})
execute_process(COMMAND ln -s ${target} ${link}
RESULT_VARIABLE result
ERROR_VARIABLE output)
if (NOT ${result} EQUAL 0)
message(FATAL_ERROR "Could not create symbolic link for: ${target} --> ${output}")
endif()
else()
if (IS_DIRECTORY ${target})
set(command cmd.exe /c mklink /j ${link} ${target})
file(GLOB_RECURSE files FOLLOW_SYMLINKS LIST_DIRECTORIES false RELATIVE ${target} "${target}/*")
foreach(file IN LISTS files)
configure_file("${target}/${file}" "${link}/${file}" COPYONLY)
endforeach(file)
else()
set(command cmd.exe /c mklink /h ${link} ${target})
configure_file(${target} ${link} COPYONLY)
endif()
endif()
execute_process(COMMAND ${command}
RESULT_VARIABLE result
ERROR_VARIABLE output)
if (NOT ${result} EQUAL 0)
message(FATAL_ERROR "Could not create symbolic link for: ${target} --> ${output}")
endif()
endif()
endfunction(link_to_source)

View file

@ -1,13 +1,20 @@
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:
We gratefully accept bug reports and contributions from the community. All PRs are reviewed by the project team / community, and may need some modifications to
be accepted.
- 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.
Quick Checklist for PR contributors
-----------------------------------
More details on all of these points may be found in the sections below.
- [Sign-off](#license-and-copyright): all commits must be signed off.
- [Tests](#tests): please ensure the PR includes adequate tests.
- [Changelog](#documentation): if needed, please provide a changelog entry.
- [Backports](#long-term-support-branches): provide a backport if needed (it's fine to wait until the main PR is accepted).
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.
- We would ask that contributions conform to [our coding standards](https://mbed-tls.readthedocs.io/en/latest/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.
- The code should be written in a clean and readable style.
- The code should be written in a portable generic way, that will benefit the whole community, and not only your own needs.
- The code should be secure, and will be reviewed from a security point of view as well.
@ -19,15 +26,13 @@ Making a Contribution
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. 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).
Backwards Compatibility
-----------------------
The project aims to minimise the impact on users upgrading to newer versions of the library and it should not be necessary for a user to make any changes to their own code to work with a newer version of the library. Unless the user has made an active decision to use newer features, a newer generation of the library or a change has been necessary due to a security issue or other significant software defect, no modifications to their own code should be necessary. To achieve this, API compatibility is maintained between different versions of Mbed TLS on the main development branch and in LTS (Long Term Support) branches, as described in [BRANCHES.md](BRANCHES.md).
To minimise such disruption to users, where a change to the interface is required, all changes to the ABI or API, even on the main development branch where new features are added, need to be justifiable by either being a significant enhancement, new feature or bug fix which is best resolved by an interface change.
To minimise such disruption to users, where a change to the interface is required, all changes to the ABI or API, even on the main development branch where new features are added, need to be justifiable by either being a significant enhancement, new feature or bug fix which is best resolved by an interface change. If there is an API change, the contribution, if accepted, will be merged only when there will be a major release.
Where changes to an existing interface are necessary, functions in the public interface which need to be changed, are marked as 'deprecated'. This is done with the preprocessor symbols `MBEDTLS_DEPRECATED_WARNING` and `MBEDTLS_DEPRECATED_REMOVED`. Then, a new function with a new name but similar if not identical behaviour to the original function containing the necessary changes should be created alongside the existing deprecated function.
@ -56,9 +61,9 @@ Tests
-----
As mentioned, tests that show the correctness of the feature or bug fix should be added to the pull request, if no such tests exist.
Mbed TLS includes a comprehensive set of test suites in the `tests/` directory that are dynamically generated to produce the actual test source files (e.g. `test_suite_mpi.c`). These files are generated from a `function file` (e.g. `suites/test_suite_mpi.function`) and a `data file` (e.g. `suites/test_suite_mpi.data`). The function file contains the test functions. The data file contains the test cases, specified as parameters that will be passed to the test function.
Mbed TLS includes a comprehensive set of test suites in the `tests/` directory that are dynamically generated to produce the actual test source files (e.g. `test_suite_rsa.c`). These files are generated from a `function file` (e.g. `suites/test_suite_rsa.function`) and a `data file` (e.g. `suites/test_suite_rsa.data`). The function file contains the test functions. The data file contains the test cases, specified as parameters that will be passed to the test function.
[A Knowledge Base article describing how to add additional tests is available on the Mbed TLS website](https://tls.mbed.org/kb/development/test_suites).
[A Knowledge Base article describing how to add additional tests is available on the Mbed TLS website](https://mbed-tls.readthedocs.io/en/latest/kb/development/test_suites/).
A test script `tests/scripts/basic-build-test.sh` is available to show test coverage of the library. New code contributions should provide a similar level of code coverage to that which already exists for the library.
@ -77,5 +82,14 @@ 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.
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. If a [Knowledge Base (KB)](https://mbed-tls.readthedocs.io/en/latest/kb/) article should be added, write this as a comment in the PR description.
1. A [ChangeLog](https://github.com/Mbed-TLS/mbedtls/blob/development/ChangeLog.d/00README.md) entry should be added for this contribution.
License and Copyright
---------------------
All new files should include the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) standard license header where possible. For licensing details, please see the [License section of the README](README.md#License).
The copyright on contributions is retained by the original authors of the code. Where possible for new files, this should be noted in a comment at the top of the file in the form: "Copyright The Mbed TLS Contributors".
When contributing code to us, the committer and all authors are required to make the submission under the terms of the [Developer Certificate of Origin](dco.txt), confirming that the code submitted can (legally) become part of the project, and be subject to the same Apache 2.0 license. This is done by including the standard Git `Signed-off-by:` line in every commit message. If more than one person contributed to the commit, they should also add their own `Signed-off-by:` line.

View file

@ -463,7 +463,7 @@ API changes
provides better randomness. Instead of HAVEGE, declare OS or hardware RNG
interfaces with mbedtls_entropy_add_source() and/or use an entropy seed
file created securely during device provisioning. See
https://tls.mbed.org/kb/how-to/add-entropy-sources-to-entropy-pool for
https://mbed-tls.readthedocs.io/en/latest/kb/how-to/add-entropy-sources-to-entropy-pool/ for
more information.
* Add missing const attributes to API functions.
* Remove helpers for the transition from Mbed TLS 1.3 to Mbed TLS 2.0: the

11
ChangeLog.d/LMS.txt Normal file
View file

@ -0,0 +1,11 @@
Features
* Add the LMS post-quantum-safe stateful-hash asymmetric signature scheme.
Signature verification is production-ready, but generation is for testing
purposes only. This currently only supports one parameter set
(LMS_SHA256_M32_H10), meaning that each private key can be used to sign
1024 messages. As such, it is not intended for use in TLS, but instead for
verification of assets transmitted over an insecure channel, particularly
firmware images.
* Add the LM-OTS post-quantum-safe one-time signature scheme, which is
required for LMS. This can be used independently, but each key can only be
used to sign one message so is impractical for most circumstances.

View file

@ -0,0 +1,6 @@
Features
* cert_write: support for setting extended key usage attributes. A
corresponding new public API call has been added in the library,
mbedtls_x509write_crt_set_ext_key_usage().
* cert_write: support for writing certificate files in either PEM
or DER format.

View file

@ -0,0 +1,20 @@
Features
* Some crypto modules that previously depended on MD or a low-level hash
module, either unconditionally (RSA, PK, PKCS5, PKCS12, EC J-PAKE), or
for some features (PEM for encrypted files), are now able to use PSA
Crypto instead when the legacy API is not available. This means it is
now possible to use all features from those modules in configurations
where the built-in implementations of hashes are excluded and the hashes
are only provided by PSA drivers. In these configurations, you need to
call `psa_crypto_init()` before you call any function from those
modules; this is not required in configurations where the built-in
implementation is still available. Note that some crypto modules and
features still depend on the built-in implementation of hashes:
MBEDTLS_HKDF_C (but the PSA HKDF function do not depend on it),
MBEDTLS_ENTROPY_C, MBEDTLS_HMAC_DRBG_C and MBEDTLS_ECDSA_DETERMINISTIC.
In particular, for now, compiling without built-in hashes requires use
of MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG.
* When MBEDTLS_USE_PSA_CRYPTO is enabled, X.509, TLS 1.2 and TLS 1.3 no
longer depend on MD. This means it is now possible to use them in
configurations where the built-in implementations of hashes are excluded
and the hashes are only provided by PSA drivers.

View file

@ -0,0 +1,5 @@
Bugfix
* Fix ECDSA verification, where it was not always validating the
public key. This bug meant that it was possible to verify a
signature with an invalid public key, in some cases. Reported by
Guido Vranken using Cryptofuzz in #4420.

View file

@ -0,0 +1,5 @@
API changes
* Add an ad-hoc key derivation function handling ECJPAKE to PMS
calculation that can be used to derive the session secret in TLS 1.2,
as described in draft-cragie-tls-ecjpake-01. This can be achieved by
using PSA_ALG_TLS12_ECJPAKE_TO_PMS as the key derivation algorithm.

View file

@ -0,0 +1,3 @@
Bugfix
* Fix compilation errors when trying to build with
PSA drivers for AEAD (GCM, CCM, Chacha20-Poly1305).

View file

@ -0,0 +1,4 @@
Bugfix
* Fix bugs and missing dependencies when
building and testing configurations with
only one encryption type enabled in TLS 1.2.

View file

@ -0,0 +1,3 @@
Bugfix
* Fix a build issue on Windows where the source and build directory could not be on
different drives (#5751).

View file

@ -0,0 +1,4 @@
Bugfix
* Fix TLS 1.3 session resumption fail. Fixes #6488.
* Add configuration check to exclude TLS 1.3 optional authentication of
client.

View file

@ -0,0 +1,4 @@
Bugfix
* Fix memory leak in ssl_parse_certificate_request() caused by
mbedtls_x509_get_name() not freeing allocated objects in case of error.
Change mbedtls_x509_get_name() to clean up allocated objects on error.

View file

@ -0,0 +1,5 @@
Bugfix
* Fix a bug in which mbedtls_x509_crt_info() would produce non-printable
bytes when parsing certificates containing a binary RFC 4108
HardwareModuleName as a Subject Alternative Name extension. Hardware
serial numbers are now rendered in hex format. Fixes #6262.

View file

@ -0,0 +1,3 @@
Bugfix
* Fix possible crash in TLS PRF code, if a failure to allocate memory occurs.
Reported by Michael Madsen in #6516.

View file

@ -0,0 +1,6 @@
Features
* Shared code to free x509 structs like mbedtls_x509_named_data
New deprecations
* Deprecate mbedtls_asn1_free_named_data().
Use mbedtls_asn1_free_named_data_list()
or mbedtls_asn1_free_named_data_list_shallow()

View file

@ -0,0 +1,3 @@
Bugfix
* Provide the missing definition of mbedtls_setbuf() in some configurations
with MBEDTLS_PLATFORM_C disabled. Fixes #6118, #6196.

View file

@ -0,0 +1,6 @@
Features
* Brought in PSA code geneneration JSON driver list.
Added auto generated templating support for key management.
Added Support for transparent and opaque keys (import/export/copy).
Included some general JSON validation for the given entry points.
Addresses version 1.1 of #5137.

View file

@ -0,0 +1,4 @@
Features
* Expose the EC J-PAKE functionality through the Draft PSA PAKE Crypto API.
Only the ECC primitive with secp256r1 curve and SHA-256 hash algorithm
are supported in this implementation.

View file

@ -0,0 +1,5 @@
Bugfix
* Fix build failure with MBEDTLS_RSA_C and MBEDTLS_PSA_CRYPTO_C but not
MBEDTLS_USE_PSA_CRYPTO or MBEDTLS_PK_WRITE_C. Fixes #6408.
* Fix build failure with MBEDTLS_RSA_C and MBEDTLS_PSA_CRYPTO_C but not
MBEDTLS_PK_PARSE_C. Fixes #6409.

View file

@ -0,0 +1,9 @@
Features
* Mbed TLS supports TLS 1.3 key establishment via pre-shared keys,
pre-shared keys provisioned externally or via the ticket mechanism
(session resumption).
The MBEDTLS_SSL_SESSION_TICKETS configuration option controls the support
for the ticket mechanism.
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_xxx_ENABLED configuration options
have been introduced to control the support for the three possible
TLS 1.3 key exchange modes.

View file

@ -0,0 +1,3 @@
Features
* Add support for opaque keys as the private keys associated to certificates
for authentication in TLS 1.3.

View file

@ -17,7 +17,9 @@ We provide some non-standard configurations focused on specific use cases in the
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/).
The main Mbed TLS documentation is available via [ReadTheDocs](https://mbed-tls.readthedocs.io/).
Documentation for the PSA Cryptography API is available [on GitHub](https://arm-software.github.io/psa-api/crypto/).
To generate a local copy of the library documentation in HTML format, tailored to your compile-time configuration:
@ -103,9 +105,9 @@ Setting the variable `SHARED` in your environment will build shared libraries in
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.
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://mbed-tls.readthedocs.io/en/latest/kb/) for articles on your platform or issue.
In case you find that you need to do something else as well, please let us know what, so we can add it to the [Mbed TLS Knowledge Base](https://tls.mbed.org/kb).
In case you find that you need to do something else as well, please let us know what, so we can add it to the [Mbed TLS Knowledge Base](https://mbed-tls.readthedocs.io/en/latest/kb/).
### CMake
@ -240,7 +242,7 @@ For machines with a Unix shell and OpenSSL (and optionally GnuTLS) installed, ad
- `tests/ssl-opt.sh` runs integration tests for various TLS options (renegotiation, resumption, etc.) and tests interoperability of these options with other implementations.
- `tests/compat.sh` tests interoperability of every ciphersuite with other implementations.
- `tests/scripts/test-ref-configs.pl` test builds in various reduced configurations.
- `tests/scripts/key-exchanges.pl` test builds in configurations with a single key exchange enabled
- `tests/scripts/depends.py` test builds in configurations with a single curve, key exchange, hash, cipher, or pkalg on.
- `tests/scripts/all.sh` runs a combination of the above tests, plus some more, with various build options (such as ASan, full `mbedtls_config.h`, etc).
Porting Mbed TLS
@ -248,9 +250,9 @@ Porting Mbed TLS
Mbed TLS can be ported to many different architectures, OS's and platforms. Before starting a port, you may find the following Knowledge Base articles useful:
- [Porting Mbed TLS to a new environment or OS](https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS)
- [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)
- [Porting Mbed TLS to a new environment or OS](https://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS/)
- [What external dependencies does Mbed TLS rely on?](https://mbed-tls.readthedocs.io/en/latest/kb/development/what-external-dependencies-does-mbedtls-rely-on/)
- [How do I configure Mbed TLS](https://mbed-tls.readthedocs.io/en/latest/kb/compiling-and-building/how-do-i-configure-mbedtls/)
Mbed TLS is mostly written in portable C99; however, it has a few platform requirements that go beyond the standard, but are met by most modern architectures:
@ -263,11 +265,11 @@ Mbed TLS is mostly written in portable C99; however, it has a few platform requi
PSA cryptography API
--------------------
### PSA API design
### PSA API
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 [PSA cryptography API](https://arm-software.github.io/psa-api/crypto/) 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:
@ -279,10 +281,6 @@ The design goals of the PSA cryptography API include:
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.

View file

@ -2,10 +2,11 @@
Here are some useful sources of information about using Mbed TLS:
- [ReadTheDocs](https://mbed-tls.readthedocs.io/);
- API documentation, see the [Documentation section of the
README](README.md#License);
README](README.md#documentation);
- the `docs` directory in the source tree;
- the [Mbed TLS knowledge Base](https://tls.mbed.org/kb);
- the [Mbed TLS Knowledge Base](https://mbed-tls.readthedocs.io/en/latest/kb/);
- the [Mbed TLS mailing-list
archives](https://lists.trustedfirmware.org/archives/list/mbed-tls@lists.trustedfirmware.org/).

View file

@ -141,7 +141,7 @@ recommended), or users who used it through the entropy module but had it as the
only source of entropy. If you're in that case, please declare OS or hardware
RNG interfaces with `mbedtls_entropy_add_source()` and/or use an entropy seed
file created securely during device provisioning. See
<https://tls.mbed.org/kb/how-to/add-entropy-sources-to-entropy-pool> for more
<https://mbed-tls.readthedocs.io/en/latest/kb/how-to/add-entropy-sources-to-entropy-pool> for more
information.
### Remove helpers for the transition from Mbed TLS 1.3 to Mbed TLS 2.0

View file

@ -38,7 +38,7 @@ The general principle of an alternative implementation is:
* Create a header file `xxx_alt.h` that defines the context type(s) used by the module. For example, `mbedtls_aes_context` for AES.
* Implement all the functions from the module, i.e. the functions declared in `include/mbedtls/xxx.h`.
See https://tls.mbed.org/kb/development/hw_acc_guidelines for a more detailed guide.
See https://mbed-tls.readthedocs.io/en/latest/kb/development/hw_acc_guidelines for a more detailed guide.
### Constraints on context types

View file

@ -31,13 +31,25 @@ DRIVER_COMPONENT=test_psa_crypto_config_accel_hash_use_psa
# A similar configuration to that of the component, except without drivers,
# for comparison.
reference_config () {
scripts/config.py set MBEDTLS_USE_PSA_CRYPTO
scripts/config.py unset MBEDTLS_PKCS1_V21
scripts/config.py unset MBEDTLS_X509_RSASSA_PSS_SUPPORT
# start with full
scripts/config.py full
# use PSA config and disable driver-less algs as in the component
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_STREAM_CIPHER
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_ECB_NO_PADDING
# disable options as in the component
# (no need to disable whole modules, we'll just skip their test suite)
scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_DETERMINISTIC_ECDSA
}
# Space-separated list of test suites of interest.
SUITES="rsa pkcs1_v15 pk pkparse pkwrite"
# Space-separated list of test suites to ignore:
# if SSS is in that list, test_suite_SSS and test_suite_SSS.* are ignored.
IGNORE="md mdx shax" # accelerated
IGNORE="$IGNORE entropy hmac_drbg random" # disabled (ext. RNG)
IGNORE="$IGNORE psa_crypto_init" # needs internal RNG
IGNORE="$IGNORE hkdf" # disabled in the all.sh component tested
# Compare only "reference vs driver" or also "before vs after"?
BEFORE_AFTER=1 # 0 or 1
# ----- END edit this -----
set -eu
@ -53,26 +65,28 @@ record() {
make check
}
# save current HEAD
HEAD=$(git branch --show-current)
if [ "$BEFORE_AFTER" -eq 1 ]; then
# save current HEAD
HEAD=$(git branch --show-current)
# get the numbers before this PR for default and full
cleanup
git checkout $(git merge-base HEAD development)
record "before-default"
# get the numbers before this PR for default and full
cleanup
git checkout $(git merge-base HEAD development)
record "before-default"
cleanup
scripts/config.py full
record "before-full"
cleanup
scripts/config.py full
record "before-full"
# get the numbers now for default and full
cleanup
git checkout $HEAD
record "after-default"
# get the numbers now for default and full
cleanup
git checkout $HEAD
record "after-default"
cleanup
scripts/config.py full
record "after-full"
cleanup
scripts/config.py full
record "after-full"
fi
# get the numbers now for driver-only and reference
cleanup
@ -81,10 +95,27 @@ record "reference"
cleanup
export MBEDTLS_TEST_OUTCOME_FILE="$PWD/outcome-drivers.csv"
export SKIP_SSL_OPT_COMPAT_SH=1
tests/scripts/all.sh -k test_psa_crypto_config_accel_hash_use_psa
# analysis
populate_suites () {
SUITES=''
make generated_files >/dev/null
data_files=$(cd tests/suites && echo *.data)
for data in $data_files; do
suite=${data#test_suite_}
suite=${suite%.data}
suite_base=${suite%%.*}
case " $IGNORE " in
*" $suite_base "*) :;;
*) SUITES="$SUITES $suite";;
esac
done
make neat
}
compare_suite () {
ref="outcome-$1.csv"
new="outcome-$2.csv"
@ -98,19 +129,35 @@ compare_suite () {
nb_ref=$(wc -l <skipped-ref)
nb_new=$(wc -l <skipped-new)
printf "%12s: total %3d; skipped %3d -> %3d\n" \
printf "%36s: total %4d; skipped %4d -> %4d\n" \
$suite $total $nb_ref $nb_new
diff skipped-ref skipped-new | grep '^> ' || true
if diff skipped-ref skipped-new | grep '^> '; then
ret=1
else
ret=0
fi
rm skipped-ref skipped-new
return $ret
}
compare_builds () {
printf "\n*** Comparing $1 -> $2 ***\n"
failed=''
for suite in $SUITES; do
compare_suite "$1" "$2" "$suite"
if compare_suite "$1" "$2" "$suite"; then :; else
failed="$failed $suite"
fi
done
if [ -z "$failed" ]; then
printf "No coverage gap found.\n"
else
printf "Suites with less coverage:%s\n" "$failed"
fi
}
compare_builds before-default after-default
compare_builds before-full after-full
populate_suites
if [ "$BEFORE_AFTER" -eq 1 ]; then
compare_builds before-default after-default
compare_builds before-full after-full
fi
compare_builds reference drivers

View file

@ -29,11 +29,6 @@ github.
[ffdh]: https://github.com/Mbed-TLS/mbedtls/issues/3261
PSA Crypto has an experimental API for EC J-PAKE, but it's not implemented in
Mbed TLS yet. See the [EC J-PAKE follow-up EPIC][ecjp] on github.
[ecjp]: https://github.com/orgs/Mbed-TLS/projects/1#column-17950140
Arbitrary parameters for FFDH
-----------------------------

View file

@ -345,19 +345,29 @@ available. Data related to a certain hash (OID, sizes, translations) should
only be included in the build if it is possible to use that hash in some way.
In order to cater to these new needs, new families of macros are introduced in
`library/legacy_or_psa.h`, see its documentation for details.
`legacy_or_psa.h`, see its documentation for details.
It should be noted that there are currently:
- too many different ways of computing a hash (low-level, MD, PSA);
- too many different ways to configure the library that influence which of
these ways is available and will be used (`MBEDTLS_USE_PSA_CRYPTO`,
`MBEDTLS_PSA_CRYPTO_CONFIG`, `mbedtls_config.h` + `psa/crypto_config.h`).
`MBEDTLS_PSA_CRYPTO_CONFIG`, `mbedtls_config.h` + `psa/crypto_config.h`).
As a result, we need more families of dependency macros than we'd like to.
This is a temporary situation until we move to a place where everything is
based on PSA Crypto. In the meantime, long and explicit names where chosen for
the new macros in the hope of avoiding confusion.
Note: the new macros supplement but do not replace the existing macros:
- code that always uses PSA Crypto (for example, code specific to TLS 1.3)
should use `PSA_WANT_xxx`;
- code that always uses the legacy API (for example, crypto modules that have
not undergone step 1 yet) should use `MBEDTLS_xxx_C`;
- code that may use one of the two APIs, either based on
`MBEDTLS_USE_PSA_CRYPTO` (X.509, TLS 1.2, shared between TLS 1.2 and 1.3),
or based on availability (crypto modules after step 1), should use one of
the new macros from `legacy_or_psa.h`.
Executing step 3 will mostly consist of using the right dependency macros in
the right places (once the previous steps are done).

View file

@ -6,7 +6,7 @@ This document is incomplete. You can help by expanding it.
## Unit tests
See <https://tls.mbed.org/kb/development/test_suites>
See <https://mbed-tls.readthedocs.io/en/latest/kb/development/test_suites>
### Unit test descriptions

View file

@ -28,9 +28,12 @@ Support description
- Mbed TLS does not support DHE key establishment.
- Mbed TLS does not support pre-shared keys, including any form of
session resumption. This implies that it does not support sending early
data (0-RTT data).
- Mbed TLS supports pre-shared keys for key establishment, pre-shared keys
provisioned externally as well as provisioned via the ticket mechanism.
- Mbed TLS supports session resumption via the ticket mechanism.
- Mbed TLS does not support sending or receiving early data (0-RTT data).
- Supported cipher suites: depends on the library configuration. Potentially
all of them:
@ -54,8 +57,8 @@ Support description
| server_certificate_type | no |
| padding | no |
| key_share | YES |
| pre_shared_key | no |
| psk_key_exchange_modes | no |
| pre_shared_key | YES |
| psk_key_exchange_modes | YES |
| early_data | no |
| cookie | no |
| supported_versions | YES |
@ -118,7 +121,7 @@ Support description
| MBEDTLS_SSL_RENEGOTIATION | n/a |
| MBEDTLS_SSL_MAX_FRAGMENT_LENGTH | no |
| | |
| MBEDTLS_SSL_SESSION_TICKETS | no |
| MBEDTLS_SSL_SESSION_TICKETS | yes |
| MBEDTLS_SSL_SERVER_NAME_INDICATION | yes |
| MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH | no |
| | |
@ -141,10 +144,33 @@ Support description
| MBEDTLS_USE_PSA_CRYPTO | yes |
(1) These options must remain in their default state of enabled.
(2) Key exchange configuration options for TLS 1.3 will likely to be
organized around the notion of key exchange mode along the line
of the MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE/PSK/PSK_EPHEMERAL/EPHEMERAL
runtime configuration macros.
(2) See the TLS 1.3 specific build options section below.
- TLS 1.3 specific build options:
- MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE enables the support for middlebox
compatibility mode as defined in section D.4 of RFC 8446.
- MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED enables the support for
the PSK key exchange mode as defined by RFC 8446. If it is the only key
exchange mode enabled, the TLS 1.3 implementation does not contain any code
related to key exchange protocols, certificates and signatures.
- MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED enables the
support for the ephemeral key exchange mode. If it is the only key exchange
mode enabled, the TLS 1.3 implementation does not contain any code related
to PSK based key exchange. The ephemeral key exchange mode requires at least
one of the key exchange protocol allowed by the TLS 1.3 specification, the
parsing and validation of x509 certificates and at least one signature
algorithm allowed by the TLS 1.3 specification for signature computing and
verification.
- MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED enables the
support for the PSK ephemeral key exchange mode. If it is the only key
exchange mode enabled, the TLS 1.3 implementation does not contain any code
related to certificates and signatures. The PSK ephemeral key exchange
mode requires at least one of the key exchange protocol allowed by the
TLS 1.3 specification.
Prototype upstreaming status
@ -152,8 +178,7 @@ Prototype upstreaming status
The following parts of the TLS 1.3 prototype remain to be upstreamed:
- Pre-shared keys, session resumption and 0-RTT data (both client and server
side).
- Sending (client) and receiving (server) early data (0-RTT data).
- New TLS Message Processing Stack (MPS)
@ -181,7 +206,7 @@ Coding rules checklist for TLS 1.3
The following coding rules are aimed to be a checklist for TLS 1.3 upstreaming
work to reduce review rounds and the number of comments in each round. They
come along (do NOT replace) the project coding rules
(https://tls.mbed.org/kb/development/mbedtls-coding-standards). They have been
(https://mbed-tls.readthedocs.io/en/latest/kb/development/mbedtls-coding-standards). They have been
established and discussed following the review of #4882 that was the
PR upstreaming the first part of TLS 1.3 ClientHello writing code.

View file

@ -36,6 +36,12 @@ A driver therefore consists of:
Mbed TLS calls driver entry points [as specified in the PSA Cryptography Driver Interface specification](psa-driver-interface.html#driver-entry-points) except as otherwise indicated in this section.
## Mbed TLS extensions
The driver description can include Mbed TLS extensions (marked by the namespace "mbedtls"). Mbed TLS extensions are meant to extend/help integrating the driver into the library's infrastructure.
* `"mbedtls/h_condition"` (optional, string) can include complex preprocessor definitions to conditionally include header files for a given driver.
* `"mbedtls/c_condition"` (optional, string) can include complex preprocessor definitions to conditionally enable dispatch capabilities for a driver.
## Building and testing your driver
<!-- TODO -->

View file

@ -13,20 +13,28 @@ During the process of implementation there might be minor variations wrt version
## Prerequisites
Python3 and Jinja2 rev 2.10.1
Python3, Jinja2 rev 2.10.1 and jsonschema rev 3.2.0
## Feature Version
1.0
1.1
### What's critical for a migrating user
The Driver Wrapper auto generation project is designed to use a python templating library ( Jinja2 ) to render templates based on drivers that are defined using a Driver description JSON file(s).
While that is the larger goal, for version 1.0 here's what's changed
While that is the larger goal, for version 1.1 here's what's changed
#### What's changed
(1) psa_crypto_driver_wrappers.c will from this point on be auto generated.
(2) The auto generation is based on the template file at scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja.
(3) So while all driver wrapper templating support is yet to come in, the library user will need to patch into the template file as needed, this could be read as replacing the template file with the current psa_crypto_driver_wrappers.c file maintained by the library user.
(2) The auto generation is based on the template file at **scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja**.
(3) The driver JSONS to be used for generating the psa_crypto_driver_wrappers.c file can be found at **scripts/data_files/driver_jsons/** as their default location, this path includes the schemas against which the driver schemas will be validated (driver_opaque_schema.json, driver_transparent_schema.json) and a driverlist.json which specifies the drivers to be considered and the order in which they want to be called into. The default location for driverlist.json and driver JSONS can be overloaded by passing an argument --json-dir while running the script generate_driver_wrappers.py.
(4) While the complete driver wrapper templating support is yet to come in, if the library user sees a need to patch psa_crypto_driver_wrappers.c file, the user will need to patch into the template file as needed (psa_crypto_driver_wrappers.c.jinja).
#### How to set your driver up
Please refer to psa-driver-interface.md for information on how a driver schema can be written.
One can also refer to the example test drivers/ JSON schemas under **scripts/data_files/driver_jsons/**.
The JSON file 'driverlist.json' is meant to be edited by the user to reflect the drivers one wants to use on a device. The order in which the drivers are passed is also essential if/when there are multiple transparent drivers on a given system to retain the same order in the templating.

View file

@ -24,6 +24,7 @@
#include "mbedtls/private_access.h"
#include "mbedtls/build_info.h"
#include "mbedtls/platform_util.h"
#include <stddef.h>
@ -606,25 +607,41 @@ int mbedtls_asn1_get_alg_null( unsigned char **p,
const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( const mbedtls_asn1_named_data *list,
const char *oid, size_t len );
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
/**
* \brief Free a mbedtls_asn1_named_data entry
*
* \deprecated This function is deprecated and will be removed in a
* future version of the library.
* Please use mbedtls_asn1_free_named_data_list()
* or mbedtls_asn1_free_named_data_list_shallow().
*
* \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 );
void MBEDTLS_DEPRECATED mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry );
#endif /* MBEDTLS_DEPRECATED_REMOVED */
/**
* \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.
* This function calls mbedtls_asn1_free_named_data() and
* mbedtls_free() on each list element and
* sets \c *head to \c NULL.
* This function calls mbedtls_free() on
* `entry->oid.p` and `entry->val.p` and then on `entry`
* for each list entry, and sets \c *head to \c NULL.
*/
void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head );
/**
* \brief Free all shallow entries in a mbedtls_asn1_named_data list,
* but do not free internal pointer targets.
*
* \param name Head of the list of named data entries to free.
* This function calls mbedtls_free() on each list element.
*/
void mbedtls_asn1_free_named_data_list_shallow( mbedtls_asn1_named_data *name );
/** \} name Functions to parse ASN.1 data structures */
/** \} addtogroup asn1_module */

View file

@ -758,11 +758,11 @@ int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A,
*
* \param Q The destination MPI for the quotient.
* This may be \c NULL if the value of the
* quotient is not needed.
* quotient is not needed. This must not alias A or B.
* \param R The destination MPI for the remainder value.
* This may be \c NULL if the value of the
* remainder is not needed.
* \param A The dividend. This must point to an initialized MPi.
* remainder is not needed. This must not alias A or B.
* \param A The dividend. This must point to an initialized MPI.
* \param B The divisor. This must point to an initialized MPI.
*
* \return \c 0 if successful.
@ -779,10 +779,10 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
*
* \param Q The destination MPI for the quotient.
* This may be \c NULL if the value of the
* quotient is not needed.
* quotient is not needed. This must not alias A.
* \param R The destination MPI for the remainder value.
* This may be \c NULL if the value of the
* remainder is not needed.
* remainder is not needed. This must not alias A.
* \param A The dividend. This must point to an initialized MPi.
* \param b The divisor.
*
@ -837,6 +837,7 @@ int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A,
* \brief Perform a sliding-window exponentiation: X = A^E mod N
*
* \param X The destination MPI. This must point to an initialized MPI.
* This must not alias E or N.
* \param A The base of the exponentiation.
* This must point to an initialized MPI.
* \param E The exponent MPI. This must point to an initialized MPI.

View file

@ -74,10 +74,61 @@
#include MBEDTLS_USER_CONFIG_FILE
#endif
#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_USE_PSA_CRYPTO)
/* The PK wrappers need pk_write functions to format RSA key objects
* when they are dispatching to the PSA API. This happens under USE_PSA_CRYPTO,
* and also even without USE_PSA_CRYPTO for mbedtls_pk_sign_ext().
* PSA crypto also needs pk_write to export RSA keys (otherwise the build
* goes through but psa_export_key() and psa_export_public_key() fail on
* RSA keys), and pk_parse to work with RSA keys in almost any way.
*/
#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_RSA_C)
#define MBEDTLS_PK_C
#define MBEDTLS_PK_WRITE_C
#define MBEDTLS_PK_PARSE_C
#endif
/* Under MBEDTLS_USE_PSA_CRYPTO, the pk module needs pk_write functions
* to pass ECC keys to PSA. */
#if defined(MBEDTLS_PK_C) && \
defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECP_C)
#define MBEDTLS_PK_WRITE_C
#endif
#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
#if !defined(MBEDTLS_SSL_PROTO_TLS1_2)
#undef MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
#undef MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
#undef MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
#undef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
#undef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
#undef MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
#undef MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
#undef MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
#undef MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
#undef MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
#undef MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
#endif
#if !defined(MBEDTLS_SSL_PROTO_TLS1_3)
#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
#undef MBEDTLS_SSL_EARLY_DATA
#endif
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) || \
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED
#endif
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) || \
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED
#endif
/* Make sure all configuration symbols are set before including check_config.h,
* even the ones that are calculated programmatically. */
#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) /* PSA_WANT_xxx influences MBEDTLS_xxx */ || \
defined(MBEDTLS_PSA_CRYPTO_C) /* MBEDTLS_xxx influences PSA_WANT_xxx */
#include "mbedtls/config_psa.h"
#endif

View file

@ -320,11 +320,20 @@
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
( !defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \
( !defined(MBEDTLS_ECJPAKE_C) || \
!defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) )
#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites"
#endif
/* Use of EC J-PAKE in TLS requires SHA-256.
* This will be taken from MD if it is present, or from PSA if MD is absent.
* Note: ECJPAKE_C depends on MD_C || PSA_CRYPTO_C. */
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
!( defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA256_C) ) && \
!( !defined(MBEDTLS_MD_C) && defined(PSA_WANT_ALG_SHA_256) )
#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) && \
@ -344,6 +353,16 @@
#error "MBEDTLS_MD_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_LMS_C) && \
! ( defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_256) )
#error "MBEDTLS_LMS_C requires MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256"
#endif
#if defined(MBEDTLS_LMS_PRIVATE) && \
( !defined(MBEDTLS_LMS_C) )
#error "MBEDTLS_LMS_PRIVATE requires MBEDTLS_LMS_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"
@ -514,6 +533,20 @@
#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_VSNPRINTF_ALT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_VSNPRINTF_MACRO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) &&\
( defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) ||\
defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) )
#error "MBEDTLS_PLATFORM_VSNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_VSNPRINTF/MBEDTLS_PLATFORM_VSNPRINTF_ALT cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\
!defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS)
#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites"
@ -750,18 +783,42 @@
#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites"
#endif
/*
* HKDF is mandatory for TLS 1.3.
* Otherwise support for at least one ciphersuite mandates either SHA_256 or
* SHA_384.
*/
/* TLS 1.3 requires separate HKDF parts from PSA */
#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
( ( !defined(MBEDTLS_HKDF_C) ) || \
( !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA384_C) ) || \
( !defined(MBEDTLS_PSA_CRYPTO_C) ) )
!( defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_HKDF_EXTRACT) && defined(PSA_WANT_ALG_HKDF_EXPAND) )
#error "MBEDTLS_SSL_PROTO_TLS1_3 defined, but not all prerequisites"
#endif
/* TLS 1.3 requires at least one ciphersuite, so at least SHA-256 or SHA-384 */
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
/* We always need at least one of the hashes via PSA (for use with HKDF) */
#if !( defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_384) )
#error "MBEDTLS_SSL_PROTO_TLS1_3 defined, but not all prerequisites"
#endif /* !(PSA_WANT_ALG_SHA_256 || PSA_WANT_ALG_SHA_384) */
#if !defined(MBEDTLS_USE_PSA_CRYPTO)
/* When USE_PSA_CRYPTO is not defined, we also need SHA-256 or SHA-384 via the
* legacy interface, including via the MD layer, for the parts of the code
* that are shared with TLS 1.2 (running handshake hash). */
#if !defined(MBEDTLS_MD_C) || \
!( defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA384_C) )
#error "MBEDTLS_SSL_PROTO_TLS1_3 defined, but not all prerequisites"
#endif /* !MBEDTLS_MD_C || !(MBEDTLS_SHA256_C || MBEDTLS_SHA384_C) */
#endif /* !MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
#if !( defined(MBEDTLS_ECDH_C) && defined(MBEDTLS_X509_CRT_PARSE_C) && \
( defined(MBEDTLS_ECDSA_C) || defined(MBEDTLS_PKCS1_V21) ) )
#error "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED defined, but not all prerequisites"
#endif
#endif
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
#if !( defined(MBEDTLS_ECDH_C) )
#error "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED defined, but not all prerequisites"
#endif
#endif
/*
* The current implementation of TLS 1.3 requires MBEDTLS_SSL_KEEP_PEER_CERTIFICATE.
*/
@ -785,6 +842,13 @@
"but no key exchange methods defined with MBEDTLS_KEY_EXCHANGE_xxxx"
#endif
/* Early data requires PSK related mode defined */
#if defined(MBEDTLS_SSL_EARLY_DATA) && \
( !defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) && \
!defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED))
#error "MBEDTLS_SSL_EARLY_DATA defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_PROTO_DTLS) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_2)
#error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites"
@ -860,6 +924,11 @@
#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_TICKET_C) && \
!( defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) )
#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH) && \
MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH >= 256
#error "MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH must be less than 256"
@ -948,7 +1017,9 @@
#error "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) && !( defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) )
#error "MBEDTLS_SSL_CONTEXT_SERIALIZATION defined, but not all prerequisites"
#endif
/* Reject attempts to enable options that have been removed and that could
* cause a build to succeed but with features removed. */

View file

@ -146,6 +146,15 @@ extern "C" {
#define MBEDTLS_MD5_C
#endif
#if defined(PSA_WANT_ALG_JPAKE)
#define MBEDTLS_PSA_BUILTIN_PAKE 1
#define MBEDTLS_PSA_BUILTIN_ALG_JPAKE 1
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_ECP_C
#define MBEDTLS_ECJPAKE_C
#endif /* PSA_WANT_ALG_JPAKE */
#if defined(PSA_WANT_ALG_RIPEMD160) && !defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160)
#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1
#define MBEDTLS_RIPEMD160_C
@ -228,6 +237,12 @@ extern "C" {
#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS */
#endif /* PSA_WANT_ALG_TLS12_PSK_TO_MS */
#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS)
#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS 1
#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS */
#endif /* PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS */
#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR)
#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR 1
@ -636,6 +651,12 @@ extern "C" {
#define PSA_WANT_ALG_MD5 1
#endif
#if defined(MBEDTLS_ECJPAKE_C)
#define MBEDTLS_PSA_BUILTIN_PAKE 1
#define MBEDTLS_PSA_BUILTIN_ALG_JPAKE 1
#define PSA_WANT_ALG_JPAKE 1
#endif
#if defined(MBEDTLS_RIPEMD160_C)
#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1
#define PSA_WANT_ALG_RIPEMD160 1
@ -706,6 +727,11 @@ extern "C" {
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)
#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS 1
#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1
#endif
#if defined(MBEDTLS_CHACHA20_C)
#define PSA_WANT_KEY_TYPE_CHACHA20 1
#define PSA_WANT_ALG_STREAM_CIPHER 1

View file

@ -1,6 +1,7 @@
/**
* Constant-time functions
*
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*

View file

@ -245,10 +245,8 @@ int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r,
* This must be initialized.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the signature
* is invalid.
* \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX
* error code on failure for any other reason.
* error code on failure.
*/
int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
const unsigned char *buf, size_t blen,

View file

@ -258,6 +258,29 @@ int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief Write the shared key material to be passed to a Key
* Derivation Function as described in RFC8236.
*
* \param ctx The ECJPAKE context to use. This must be initialized,
* set up and have performed both round one and two.
* \param buf The buffer to write the derived secret to. This must
* be a writable buffer of length \p len Bytes.
* \param len The length of \p buf in Bytes.
* \param olen The address at which to store the total number of bytes
* written to \p buf. This must not be \c NULL.
* \param f_rng The RNG function to use. This must not be \c NULL.
* \param p_rng The RNG parameter to be passed to \p f_rng. This
* may be \c NULL if \p f_rng doesn't use a context.
*
* \return \c 0 if successful.
* \return A negative error code on failure.
*/
int mbedtls_ecjpake_write_shared_key( mbedtls_ecjpake_context *ctx,
unsigned char *buf, size_t len, size_t *olen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief This clears an ECJPAKE context and frees any
* embedded data structure.

View file

@ -82,6 +82,7 @@
* POLY1305 3 0x0057-0x005B
* CHACHAPOLY 2 0x0054-0x0056
* PLATFORM 2 0x0070-0x0072
* LMS 5 0x0011-0x0019
*
* High-level module nr (3 bits - 0x0...-0x7...)
* Name ID Nr of Errors

View file

@ -1,7 +1,10 @@
/**
* Internal macros to express dependencies for code and tests
* that may use either the legacy API or PSA in various builds.
*
* Macros to express dependencies for code and tests that may use either the
* legacy API or PSA in various builds. This whole header file is currently
* for internal use only and both the header file and the macros it defines
* may change or be removed without notice.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
@ -19,6 +22,18 @@
*/
/*
* Note: applications that are targeting a specific configuration do not need
* to use these macros; instead they should directly use the functions they
* know are available in their configuration.
*
* Note: code that is purely based on PSA Crypto (psa_xxx() functions)
* does not need to use these macros; instead it should use the relevant
* PSA_WANT_xxx macros.
*
* Note: code that is purely based on the legacy crypto APIs (mbedtls_xxx())
* does not need to use these macros; instead it should use the relevant
* MBEDTLS_xxx macros.
*
* These macros are for code that wants to use <crypto feature> and will do so
* using <legacy API> or PSA depending on <condition>, where:
* - <crypto feature> will generally be an algorithm (SHA-256, ECDH) but may
@ -36,15 +51,10 @@
* - TLS 1.2 will compute hashes using either mbedtls_md_xxx() (and
* mbedtls_sha256_xxx()) or psa_aead_xxx() depending on whether
* MBEDTLS_USE_PSA_CRYPTO is defined;
* - RSA PKCS#1 v2.1 will, in the near future*, compute hashes (for padding)
* using either `mbedtls_md()` if it's available, or `psa_hash_compute()`
* otherwise;
* - PEM decoding of PEM-encrypted keys will, in the near future*, compute MD5
* hashes using either `mbedtls_md5_xxx()` if it's available, or
* `psa_hash_xxx()` otherwise.
* *See docs/architecture/psa-migration/strategy.md, section "Supporting
* builds with drivers without the software implementation", strategy for step
* 1 (libmbedcrypto except the RNG subsystem).
* - RSA PKCS#1 v2.1 will compute hashes (for padding) using either
* `mbedtls_md()` if it's available, or `psa_hash_compute()` otherwise;
* - PEM decoding of PEM-encrypted keys will compute MD5 hashes using either
* `mbedtls_md5_xxx()` if it's available, or `psa_hash_xxx()` otherwise.
*
* Note: the macros are essential to express test dependencies. Inside code,
* we could instead just use the equivalent pre-processor condition, but
@ -70,9 +80,9 @@
* MBEDTLS_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA
*
* Note: every time it's possible to use, say SHA-256, via the MD API, then
* it's also possible to used it via the low-level API. So, code that wants to
* it's also possible to use it via the low-level API. So, code that wants to
* use SHA-256 via both APIs only needs to depend on the MD macro. Also, it
* just so happens that all the choosing which API to use based on
* just so happens that all the code choosing which API to use based on
* MBEDTLS_USE_PSA_CRYPTO (X.509, TLS 1.2/shared), always uses the abstraction
* layer (sometimes in addition to the low-level API), so we don't need the
* MBEDTLS_HAS_feature_VIA_LOWLEVEL_OR_PSA_BASED_ON_USE_PSA macros.
@ -89,7 +99,7 @@
#ifndef MBEDTLS_OR_PSA_HELPERS_H
#define MBEDTLS_OR_PSA_HELPERS_H
#include "common.h"
#include "mbedtls/build_info.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include "psa/crypto.h"
#endif /* MBEDTLS_PSA_CRYPTO_C */

451
include/mbedtls/lms.h Normal file
View file

@ -0,0 +1,451 @@
/**
* \file lms.h
*
* \brief This file provides an API for the LMS post-quantum-safe stateful-hash
public-key signature scheme as defined in RFC8554 and NIST.SP.200-208.
* This implementation currently only supports a single parameter set
* MBEDTLS_LMS_SHA256_M32_H10 in order to reduce complexity. This is one
* of the signature schemes recommended by the IETF draft SUIT standard
* for IOT firmware upgrades (RFC9019).
*/
/*
* Copyright The Mbed TLS Contributors
* 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.
*/
#ifndef MBEDTLS_LMS_H
#define MBEDTLS_LMS_H
#include <stdint.h>
#include <stddef.h>
#include "mbedtls/private_access.h"
#include "mbedtls/build_info.h"
#define MBEDTLS_ERR_LMS_BAD_INPUT_DATA -0x0011 /**< Bad data has been input to an LMS function */
#define MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS -0x0013 /**< Specified LMS key has utilised all of its private keys */
#define MBEDTLS_ERR_LMS_VERIFY_FAILED -0x0015 /**< LMS signature verification failed */
#define MBEDTLS_ERR_LMS_ALLOC_FAILED -0x0017 /**< LMS failed to allocate space for a private key */
#define MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL -0x0019 /**< Input/output buffer is too small to contain requited data */
/* Currently only defined for SHA256, 32 is the max hash output size */
#define MBEDTLS_LMOTS_N_HASH_LEN_MAX (32u)
#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX (34u)
#define MBEDTLS_LMOTS_N_HASH_LEN(type) ((type) == MBEDTLS_LMOTS_SHA256_N32_W8 ? 32u : 0)
#define MBEDTLS_LMOTS_I_KEY_ID_LEN (16u)
#define MBEDTLS_LMOTS_Q_LEAF_ID_LEN (4u)
#define MBEDTLS_LMOTS_TYPE_LEN (4u)
#define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) ((type) == MBEDTLS_LMOTS_SHA256_N32_W8 ? 34u : 0)
#define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) (MBEDTLS_LMOTS_N_HASH_LEN(type))
#define MBEDTLS_LMOTS_SIG_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \
MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) + \
(MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) * \
MBEDTLS_LMOTS_N_HASH_LEN(type)))
#define MBEDTLS_LMS_TYPE_LEN (4)
#define MBEDTLS_LMS_H_TREE_HEIGHT(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 10u : 0)
/* The length of a hash output, Currently only imlemented for SHA256.
* Max is 32 bytes.
*/
#define MBEDTLS_LMS_M_NODE_BYTES(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 32 : 0)
#define MBEDTLS_LMS_M_NODE_BYTES_MAX 32
#define MBEDTLS_LMS_SIG_LEN(type, otstype) (MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \
MBEDTLS_LMOTS_SIG_LEN(otstype) + \
MBEDTLS_LMS_TYPE_LEN + \
(MBEDTLS_LMS_H_TREE_HEIGHT(type) * \
MBEDTLS_LMS_M_NODE_BYTES(type)))
#define MBEDTLS_LMS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMS_TYPE_LEN + \
MBEDTLS_LMOTS_TYPE_LEN + \
MBEDTLS_LMOTS_I_KEY_ID_LEN + \
MBEDTLS_LMS_M_NODE_BYTES(type))
#ifdef __cplusplus
extern "C" {
#endif
/** The Identifier of the LMS parameter set, as per
* https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml
* We are only implementing a subset of the types, particularly H10, for the sake of simplicty.
*/
typedef enum {
MBEDTLS_LMS_SHA256_M32_H10 = 0x6,
} mbedtls_lms_algorithm_type_t;
/** The Identifier of the LMOTS parameter set, as per
* https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml.
* We are only implementing a subset of the types, particularly N32_W8, for the sake of simplicty.
*/
typedef enum {
MBEDTLS_LMOTS_SHA256_N32_W8 = 4
} mbedtls_lmots_algorithm_type_t;
/** LMOTS parameters structure.
*
* This contains the metadata associated with an LMOTS key, detailing the
* algorithm type, the key ID, and the leaf identifier should be key be part of
* a LMS key.
*/
typedef struct {
unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key
identifier. */
unsigned char MBEDTLS_PRIVATE(q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN]); /*!< Which
leaf of the LMS key this is.
0 if the key is not part of an LMS key. */
mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LM-OTS key type identifier as
per IANA. Only SHA256_N32_W8 is
currently supported. */
} mbedtls_lmots_parameters_t;
/** LMOTS public context structure.
*
* A LMOTS public key is a hash output, and the applicable parameter set.
*
* The context must be initialized before it is used. A public key must either
* be imported or generated from a private context.
*
* \dot
* digraph lmots_public_t {
* UNINITIALIZED -> INIT [label="init"];
* HAVE_PUBLIC_KEY -> INIT [label="free"];
* INIT -> HAVE_PUBLIC_KEY [label="import_public_key"];
* INIT -> HAVE_PUBLIC_KEY [label="calculate_public_key from private key"];
* HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label="export_public_key"];
* }
* \enddot
*/
typedef struct {
mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params);
unsigned char MBEDTLS_PRIVATE(public_key)[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key.
Boolean values only. */
} mbedtls_lmots_public_t;
#if defined(MBEDTLS_LMS_PRIVATE)
/** LMOTS private context structure.
*
* A LMOTS private key is one hash output for each of digit of the digest +
* checksum, and the applicable parameter set.
*
* The context must be initialized before it is used. A public key must either
* be imported or generated from a private context.
*
* \dot
* digraph lmots_public_t {
* UNINITIALIZED -> INIT [label="init"];
* HAVE_PRIVATE_KEY -> INIT [label="free"];
* INIT -> HAVE_PRIVATE_KEY [label="generate_private_key"];
* HAVE_PRIVATE_KEY -> INIT [label="sign"];
* }
* \enddot
*/
typedef struct {
mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params);
unsigned char MBEDTLS_PRIVATE(private_key)[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];
unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key.
Boolean values only. */
} mbedtls_lmots_private_t;
#endif /* defined(MBEDTLS_LMS_PRIVATE) */
/** LMS parameters structure.
*
* This contains the metadata associated with an LMS key, detailing the
* algorithm type, the type of the underlying OTS algorithm, and the key ID.
*/
typedef struct {
unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key
identifier. */
mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(otstype); /*!< The LM-OTS key type identifier as
per IANA. Only SHA256_N32_W8 is
currently supported. */
mbedtls_lms_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LMS key type identifier as per
IANA. Only SHA256_M32_H10 is currently
supported. */
} mbedtls_lms_parameters_t;
/** LMS public context structure.
*
*A LMS public key is the hash output that is the root of the Merkle tree, and
* the applicable parameter set
*
* The context must be initialized before it is used. A public key must either
* be imported or generated from a private context.
*
* \dot
* digraph lms_public_t {
* UNINITIALIZED -> INIT [label="init"];
* HAVE_PUBLIC_KEY -> INIT [label="free"];
* INIT -> HAVE_PUBLIC_KEY [label="import_public_key"];
* INIT -> HAVE_PUBLIC_KEY [label="calculate_public_key from private key"];
* HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label="export_public_key"];
* }
* \enddot
*/
typedef struct {
mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params);
unsigned char MBEDTLS_PRIVATE(T_1_pub_key)[MBEDTLS_LMS_M_NODE_BYTES_MAX]; /*!< The public key, in
the form of the Merkle tree root node. */
unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key.
Boolean values only. */
} mbedtls_lms_public_t;
#if defined(MBEDTLS_LMS_PRIVATE)
/** LMS private context structure.
*
* A LMS private key is a set of LMOTS private keys, an index to the next usable
* key, and the applicable parameter set.
*
* The context must be initialized before it is used. A public key must either
* be imported or generated from a private context.
*
* \dot
* digraph lms_public_t {
* UNINITIALIZED -> INIT [label="init"];
* HAVE_PRIVATE_KEY -> INIT [label="free"];
* INIT -> HAVE_PRIVATE_KEY [label="generate_private_key"];
* }
* \enddot
*/
typedef struct {
mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params);
uint32_t MBEDTLS_PRIVATE(q_next_usable_key); /*!< The index of the next OTS key that has not
been used. */
mbedtls_lmots_private_t *MBEDTLS_PRIVATE(ots_private_keys); /*!< The private key material. One OTS key
for each leaf node in the Merkle tree. NULL
when have_private_key is 0 and non-NULL otherwise.
is 2^MBEDTLS_LMS_H_TREE_HEIGHT(type) in length. */
mbedtls_lmots_public_t *MBEDTLS_PRIVATE(ots_public_keys); /*!< The OTS key public keys, used to
build the Merkle tree. NULL
when have_private_key is 0 and
non-NULL otherwise.
Is 2^MBEDTLS_LMS_H_TREE_HEIGHT(type)
in length. */
unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key.
Boolean values only. */
} mbedtls_lms_private_t;
#endif /* defined(MBEDTLS_LMS_PRIVATE) */
/**
* \brief This function initializes an LMS public context
*
* \param ctx The uninitialized LMS context that will then be
* initialized.
*/
void mbedtls_lms_public_init( mbedtls_lms_public_t *ctx );
/**
* \brief This function uninitializes an LMS public context
*
* \param ctx The initialized LMS context that will then be
* uninitialized.
*/
void mbedtls_lms_public_free( mbedtls_lms_public_t *ctx );
/**
* \brief This function imports an LMS public key into a
* public LMS context.
*
* \note Before this function is called, the context must
* have been initialized.
*
* \note See IETF RFC8554 for details of the encoding of
* this public key.
*
* \param ctx The initialized LMS context store the key in.
* \param key The buffer from which the key will be read.
* #MBEDTLS_LMS_PUBLIC_KEY_LEN bytes will be read from
* this.
* \param key_size The size of the key being imported.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx,
const unsigned char *key, size_t key_size );
/**
* \brief This function exports an LMS public key from a
* LMS public context that already contains a public
* key.
*
* \note Before this function is called, the context must
* have been initialized and the context must contain
* a public key.
*
* \note See IETF RFC8554 for details of the encoding of
* this public key.
*
* \param ctx The initialized LMS public context that contains
* the public key.
* \param key The buffer into which the key will be output. Must
* be at least #MBEDTLS_LMS_PUBLIC_KEY_LEN in size.
* \param key_size The size of the key buffer.
* \param key_len If not NULL, will be written with the size of the
* key.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lms_export_public_key( const mbedtls_lms_public_t *ctx,
unsigned char *key, size_t key_size,
size_t *key_len );
/**
* \brief This function verifies a LMS signature, using a
* LMS context that contains a public key.
*
* \note Before this function is called, the context must
* have been initialized and must contain a public key
* (either by import or generation).
*
* \param ctx The initialized LMS public context from which the
* public key will be read.
* \param msg The buffer from which the message will be read.
* \param msg_size The size of the message that will be read.
* \param sig The buf from which the signature will be read.
* #MBEDTLS_LMS_SIG_LEN bytes will be read from
* this.
* \param sig_size The size of the signature to be verified.
*
* \return \c 0 on successful verification.
* \return A non-zero error code on failure.
*/
int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx,
const unsigned char *msg, size_t msg_size,
const unsigned char *sig, size_t sig_size );
#if defined(MBEDTLS_LMS_PRIVATE)
/**
* \brief This function initializes an LMS private context
*
* \param ctx The uninitialized LMS private context that will
* then be initialized. */
void mbedtls_lms_private_init( mbedtls_lms_private_t *ctx );
/**
* \brief This function uninitializes an LMS private context
*
* \param ctx The initialized LMS private context that will then
* be uninitialized.
*/
void mbedtls_lms_private_free( mbedtls_lms_private_t *ctx );
/**
* \brief This function generates an LMS private key, and
* stores in into an LMS private context.
*
* \warning This function is **not intended for use in
* production**, due to as-yet unsolved problems with
* handling stateful keys. The API for this function
* may change considerably in future versions.
*
* \note The seed must have at least 256 bits of entropy.
*
* \param ctx The initialized LMOTS context to generate the key
* into.
* \param type The LMS parameter set identifier.
* \param otstype The LMOTS parameter set identifier.
* \param f_rng The RNG function to be used to generate the key ID.
* \param p_rng The RNG context to be passed to f_rng
* \param seed The seed used to deterministically generate the
* key.
* \param seed_size The length of the seed.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx,
mbedtls_lms_algorithm_type_t type,
mbedtls_lmots_algorithm_type_t otstype,
int (*f_rng)(void *, unsigned char *, size_t),
void* p_rng, const unsigned char *seed,
size_t seed_size );
/**
* \brief This function calculates an LMS public key from a
* LMS context that already contains a private key.
*
* \note Before this function is called, the context must
* have been initialized and the context must contain
* a private key.
*
* \param ctx The initialized LMS public context to calculate the key
* from and store it into.
*
* \param priv_ctx The LMS private context to read the private key
* from. This must have been initialized and contain a
* private key.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx,
const mbedtls_lms_private_t *priv_ctx );
/**
* \brief This function creates a LMS signature, using a
* LMS context that contains unused private keys.
*
* \warning This function is **not intended for use in
* production**, due to as-yet unsolved problems with
* handling stateful keys. The API for this function
* may change considerably in future versions.
*
* \note Before this function is called, the context must
* have been initialized and must contain a private
* key.
*
* \note Each of the LMOTS private keys inside a LMS private
* key can only be used once. If they are reused, then
* attackers may be able to forge signatures with that
* key. This is all handled transparently, but it is
* important to not perform copy operations on LMS
* contexts that contain private key material.
*
* \param ctx The initialized LMS private context from which the
* private key will be read.
* \param f_rng The RNG function to be used for signature
* generation.
* \param p_rng The RNG context to be passed to f_rng
* \param msg The buffer from which the message will be read.
* \param msg_size The size of the message that will be read.
* \param sig The buf into which the signature will be stored.
* Must be at least #MBEDTLS_LMS_SIG_LEN in size.
* \param sig_size The size of the buffer the signature will be
* written into.
* \param sig_len If not NULL, will be written with the size of the
* signature.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lms_sign( mbedtls_lms_private_t *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void* p_rng, const unsigned char *msg,
unsigned int msg_size, unsigned char *sig, size_t sig_size,
size_t *sig_len );
#endif /* defined(MBEDTLS_LMS_PRIVATE) */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_LMS_H */

View file

@ -958,7 +958,7 @@
* might still happen. For this reason, this is disabled by default.
*
* Requires: MBEDTLS_ECJPAKE_C
* MBEDTLS_SHA256_C
* SHA-256 (via MD if present, or via PSA, see MBEDTLS_ECJPAKE_C)
* MBEDTLS_ECP_DP_SECP256R1_ENABLED
*
* This enables the following ciphersuites (if other requisites are
@ -1130,7 +1130,7 @@
*
* Enable support for PKCS#1 v1.5 encoding.
*
* Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C
* Requires: MBEDTLS_RSA_C
*
* This enables support for PKCS#1 v1.5 operations.
*/
@ -1390,6 +1390,8 @@
* saved after the handshake to allow for more efficient serialization, so if
* you don't need this feature you'll save RAM by disabling it.
*
* Requires: MBEDTLS_GCM_C or MBEDTLS_CCM_C or MBEDTLS_CHACHAPOLY_C
*
* Comment to disable the context serialization APIs.
*/
#define MBEDTLS_SSL_CONTEXT_SERIALIZATION
@ -1502,13 +1504,14 @@
*
* Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled).
*
* Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C
* (Depends on ciphersuites) when MBEDTLS_USE_PSA_CRYPTO
* is not defined, PSA_WANT_ALG_SHA_1 or PSA_WANT_ALG_SHA_256 or
* PSA_WANT_ALG_SHA_512 when MBEDTLS_USE_PSA_CRYPTO is defined.
* Requires: Without MBEDTLS_USE_PSA_CRYPTO: MBEDTLS_MD_C and
* (MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C)
* With MBEDTLS_USE_PSA_CRYPTO:
* PSA_WANT_ALG_SHA_1 or PSA_WANT_ALG_SHA_256 or
* PSA_WANT_ALG_SHA_512
*
* \warning If building without MBEDTLS_MD_C, you must call psa_crypto_init()
* before doing any TLS operation.
* \warning If building with MBEDTLS_USE_PSA_CRYPTO, you must call
* psa_crypto_init() before doing any TLS operations.
*
* Comment this macro to disable support for TLS 1.2 / DTLS 1.2
*/
@ -1527,11 +1530,11 @@
* Requires: MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
* Requires: MBEDTLS_PSA_CRYPTO_C
*
* Note: even though TLS 1.3 depends on PSA Crypto, if you want it to only use
* PSA for all crypto operations, you need to also enable
* MBEDTLS_USE_PSA_CRYPTO; otherwise X.509 operations, and functions that are
* common with TLS 1.2 (record protection, running handshake hash) will still
* use non-PSA crypto.
* Note: even though TLS 1.3 depends on PSA Crypto, and uses it unconditonally
* for most operations, if you want it to only use PSA for all crypto
* operations, you need to also enable MBEDTLS_USE_PSA_CRYPTO; otherwise X.509
* operations, and functions that are common with TLS 1.2 (record protection,
* running handshake hash) will still use non-PSA crypto.
*
* Uncomment this macro to enable the support for TLS 1.3.
*/
@ -1559,6 +1562,67 @@
*/
//#define MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
/**
* \def MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
*
* Enable TLS 1.3 PSK key exchange mode.
*
* Comment to disable support for the PSK key exchange mode in TLS 1.3. If
* MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not have any
* effect on the build.
*
*/
#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
/**
* \def MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
*
* Enable TLS 1.3 ephemeral key exchange mode.
*
* Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C, MBEDTLS_ECDSA_C or
* MBEDTLS_PKCS1_V21
*
* Comment to disable support for the ephemeral key exchange mode in TLS 1.3.
* If MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not have any
* effect on the build.
*
*/
#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
/**
* \def MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
*
* Enable TLS 1.3 PSK ephemeral key exchange mode.
*
* Requires: MBEDTLS_ECDH_C
*
* Comment to disable support for the PSK ephemeral key exchange mode in
* TLS 1.3. If MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not
* have any effect on the build.
*
*/
#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
/**
* \def MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE
*
* Maximum time difference in milliseconds tolerated between the age of a
* ticket from the server and client point of view.
* From the client point of view, the age of a ticket is the time difference
* between the time when the client proposes to the server to use the ticket
* (time of writing of the Pre-Shared Key Extension including the ticket) and
* the time the client received the ticket from the server.
* From the server point of view, the age of a ticket is the time difference
* between the time when the server receives a proposition from the client
* to use the ticket and the time when the ticket was created by the server.
* The server age is expected to be always greater than the client one and
* MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE defines the
* maximum difference tolerated for the server to accept the ticket.
* This is not used in TLS 1.2.
*
*/
#define MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE 6000
/**
* \def MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH
*
@ -1568,6 +1632,33 @@
*/
#define MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH 32
/**
* \def MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS
*
* Default number of NewSessionTicket messages to be sent by a TLS 1.3 server
* after handshake completion. This is not used in TLS 1.2 and relevant only if
* the MBEDTLS_SSL_SESSION_TICKETS option is enabled.
*
*/
#define MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS 1
/**
* \def MBEDTLS_SSL_EARLY_DATA
*
* Enable support for RFC 8446 TLS 1.3 early data.
*
* Requires: MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED or
* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
*
* Comment this to disable support for early data. If MBEDTLS_SSL_PROTO_TLS1_3
* is not enabled, this option does not have any effect on the build.
*
* This feature is experimental, not completed and thus not ready for
* production.
*
*/
//#define MBEDTLS_SSL_EARLY_DATA
/**
* \def MBEDTLS_SSL_PROTO_DTLS
*
@ -2347,7 +2438,7 @@
* This module is used by the following key exchanges:
* ECJPAKE
*
* Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C
* Requires: MBEDTLS_ECP_C and either MBEDTLS_MD_C or MBEDTLS_PSA_CRYPTO_C
*
* \warning If building without MBEDTLS_MD_C, you must call psa_crypto_init()
* before doing any EC J-PAKE operations.
@ -2438,6 +2529,32 @@
*/
#define MBEDTLS_HMAC_DRBG_C
/**
* \def MBEDTLS_LMS_C
*
* Enable the LMS stateful-hash asymmetric signature algorithm.
*
* Module: library/lms.c
* Caller:
*
* Requires: MBEDTLS_PSA_CRYPTO_C
*
* Uncomment to enable the LMS verification algorithm and public key operations.
*/
#define MBEDTLS_LMS_C
/**
* \def MBEDTLS_LMS_PRIVATE
*
* Enable LMS private-key operations and signing code. Functions enabled by this
* option are experimental, and should not be used in production.
*
* Requires: MBEDTLS_LMS_C
*
* Uncomment to enable the LMS signature algorithm and private key operations.
*/
//#define MBEDTLS_LMS_PRIVATE
/**
* \def MBEDTLS_NIST_KW_C
*
@ -2531,7 +2648,7 @@
*
* \note See also our Knowledge Base article about porting to a new
* environment:
* https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS
* https://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS
*
* Module: library/net_sockets.c
*
@ -2664,7 +2781,10 @@
*
* Module: library/pkcs5.c
*
* Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C
* Requires: MBEDTLS_CIPHER_C and either MBEDTLS_MD_C or MBEDTLS_PSA_CRYPTO_C.
*
* \warning If building without MBEDTLS_MD_C, you must call psa_crypto_init()
* before doing any PKCS5 operation.
*
* This module adds support for the PKCS#5 functions.
*/
@ -3028,7 +3148,8 @@
* Module: library/ssl_ticket.c
* Caller:
*
* Requires: MBEDTLS_CIPHER_C || MBEDTLS_USE_PSA_CRYPTO
* Requires: (MBEDTLS_CIPHER_C || MBEDTLS_USE_PSA_CRYPTO) &&
* (MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C)
*/
#define MBEDTLS_SSL_TICKET_C
@ -3084,7 +3205,7 @@
* contexts are not shared between threads. If you do intend to use contexts
* between threads, you will need to enable this layer to prevent race
* conditions. See also our Knowledge Base article about threading:
* https://tls.mbed.org/kb/development/thread-safety-and-multi-threading
* https://mbed-tls.readthedocs.io/en/latest/kb/development/thread-safety-and-multi-threading
*
* Module: library/threading.c
*
@ -3116,7 +3237,7 @@
*
* \note See also our Knowledge Base article about porting to a new
* environment:
* https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS
* https://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS
*
* Module: library/timing.c
*/
@ -3146,8 +3267,8 @@
* Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_PARSE_C,
* (MBEDTLS_MD_C or MBEDTLS_USE_PSA_CRYPTO)
*
* \warning If building without MBEDTLS_MD_C, you must call psa_crypto_init()
* before doing any X.509 operation.
* \warning If building with MBEDTLS_USE_PSA_CRYPTO, you must call
* psa_crypto_init() before doing any X.509 operation.
*
* This module is required for the X.509 parsing modules.
*/
@ -3207,8 +3328,8 @@
* Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_PARSE_C,
* (MBEDTLS_MD_C or MBEDTLS_USE_PSA_CRYPTO)
*
* \warning If building without MBEDTLS_MD_C, you must call psa_crypto_init()
* before doing any X.509 create operation.
* \warning If building with MBEDTLS_USE_PSA_CRYPTO, you must call
* psa_crypto_init() before doing any X.509 create operation.
*
* This module is the basis for creating X.509 certificates and CSRs.
*/

View file

@ -11,6 +11,13 @@
* implementations of these functions, or implementations specific to
* their platform, which can be statically linked to the library or
* dynamically configured at runtime.
*
* When all compilation options related to platform abstraction are
* disabled, this header just defines `mbedtls_xxx` function names
* as aliases to the standard `xxx` function.
*
* Most modules in the library and example programs are expected to
* include this header.
*/
/*
* Copyright The Mbed TLS Contributors

View file

@ -52,9 +52,7 @@
#include "mbedtls/platform_time.h"
#endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/*
* SSL Error codes
@ -331,6 +329,9 @@
#define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED 1
#define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED 0
#define MBEDTLS_SSL_EARLY_DATA_DISABLED 0
#define MBEDTLS_SSL_EARLY_DATA_ENABLED 1
#define MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED 0
#define MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED 1
@ -338,11 +339,11 @@
#define MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER 0
#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)
#if defined(MBEDTLS_SHA384_C)
#if defined(PSA_WANT_ALG_SHA_384)
#define MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN 48
#elif defined(MBEDTLS_SHA256_C)
#elif defined(PSA_WANT_ALG_SHA_256)
#define MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN 32
#endif /* MBEDTLS_SHA256_C */
#endif
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */
/*
* Default range for DTLS retransmission timer value, in milliseconds.
@ -630,7 +631,8 @@ union mbedtls_ssl_premaster_secret
#define MBEDTLS_PREMASTER_SIZE sizeof( union mbedtls_ssl_premaster_secret )
#define MBEDTLS_TLS1_3_MD_MAX_SIZE MBEDTLS_MD_MAX_SIZE
#define MBEDTLS_TLS1_3_MD_MAX_SIZE PSA_HASH_MAX_SIZE
/* Length in number of bytes of the TLS sequence number */
#define MBEDTLS_SSL_SEQUENCE_NUMBER_LEN 8
@ -1190,6 +1192,10 @@ struct mbedtls_ssl_session
uint8_t MBEDTLS_PRIVATE(resumption_key_len); /*!< resumption_key length */
unsigned char MBEDTLS_PRIVATE(resumption_key)[MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN];
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && defined(MBEDTLS_SSL_CLI_C)
char *MBEDTLS_PRIVATE(hostname); /*!< host name binded with tickets */
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION && MBEDTLS_SSL_CLI_C */
#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_CLI_C)
mbedtls_time_t MBEDTLS_PRIVATE(ticket_received); /*!< time ticket was received */
#endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_CLI_C */
@ -1325,9 +1331,17 @@ struct mbedtls_ssl_config
#if defined(MBEDTLS_SSL_RENEGOTIATION)
uint8_t MBEDTLS_PRIVATE(disable_renegotiation); /*!< disable renegotiation? */
#endif
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
uint8_t MBEDTLS_PRIVATE(session_tickets); /*!< use session tickets? */
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \
defined(MBEDTLS_SSL_CLI_C)
uint8_t MBEDTLS_PRIVATE(session_tickets); /*!< use session tickets? */
#endif
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \
defined(MBEDTLS_SSL_SRV_C) && \
defined(MBEDTLS_SSL_PROTO_TLS1_3)
uint16_t MBEDTLS_PRIVATE(new_session_tickets_count); /*!< number of NewSessionTicket */
#endif
#if defined(MBEDTLS_SSL_SRV_C)
uint8_t MBEDTLS_PRIVATE(cert_req_ca_list); /*!< enable sending CA list in
Certificate Request messages? */
@ -1383,11 +1397,13 @@ struct mbedtls_ssl_config
void *MBEDTLS_PRIVATE(p_vrfy); /*!< context for X.509 verify calllback */
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
#if defined(MBEDTLS_SSL_SRV_C)
/** Callback to retrieve PSK key from identity */
int (*MBEDTLS_PRIVATE(f_psk))(void *, mbedtls_ssl_context *, const unsigned char *, size_t);
void *MBEDTLS_PRIVATE(p_psk); /*!< context for PSK callback */
#endif
#endif
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
/** Callback to create & write a cookie for ClientHello verification */
@ -1432,13 +1448,13 @@ struct mbedtls_ssl_config
void *MBEDTLS_PRIVATE(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_SSL_HANDSHAKE_WITH_CERT_ENABLED)
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
const int *MBEDTLS_PRIVATE(sig_hashes); /*!< allowed signature hashes */
#endif
const uint16_t *MBEDTLS_PRIVATE(sig_algs); /*!< allowed signature algorithms */
#endif
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
const mbedtls_ecp_group_id *MBEDTLS_PRIVATE(curve_list); /*!< allowed curves */
@ -1451,7 +1467,7 @@ struct mbedtls_ssl_config
mbedtls_mpi MBEDTLS_PRIVATE(dhm_G); /*!< generator for DHM */
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
#if defined(MBEDTLS_USE_PSA_CRYPTO)
mbedtls_svc_key_id_t MBEDTLS_PRIVATE(psk_opaque); /*!< PSA key slot holding opaque PSK. This field
@ -1482,7 +1498,13 @@ struct mbedtls_ssl_config
* Its value is non-zero if and only if
* \c psk is not \c NULL or \c psk_opaque
* is not \c 0. */
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
#if defined(MBEDTLS_SSL_EARLY_DATA)
int MBEDTLS_PRIVATE(early_data_enabled); /*!< Early data enablement:
* - MBEDTLS_SSL_EARLY_DATA_DISABLED,
* - MBEDTLS_SSL_EARLY_DATA_ENABLED */
#endif /* MBEDTLS_SSL_EARLY_DATA */
#if defined(MBEDTLS_SSL_ALPN)
const char **MBEDTLS_PRIVATE(alpn_list); /*!< ordered list of protocols */
@ -1893,6 +1915,30 @@ void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport );
*/
void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode );
#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_EARLY_DATA)
/**
* \brief Set the early data mode
* Default: disabled on server and client
*
* \param conf The SSL configuration to use.
* \param early_data_enabled can be:
*
* MBEDTLS_SSL_EARLY_DATA_DISABLED: early data functionality is disabled
* This is the default on client and server.
*
* MBEDTLS_SSL_EARLY_DATA_ENABLED: early data functionality is enabled and
* may be negotiated in the handshake. Application using
* early data functionality needs to be aware of the
* lack of replay protection of the early data application
* payloads.
*
* \warning This interface is experimental and may change without notice.
*
*/
void mbedtls_ssl_tls13_conf_early_data( mbedtls_ssl_config *conf,
int early_data_enabled );
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_EARLY_DATA */
#if defined(MBEDTLS_X509_CRT_PARSE_C)
/**
* \brief Set the verification callback (Optional).
@ -2317,7 +2363,7 @@ int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl,
* here, except if using an event-driven style.
*
* \note See also the "DTLS tutorial" article in our knowledge base.
* https://tls.mbed.org/kb/how-to/dtls-tutorial
* https://mbed-tls.readthedocs.io/en/latest/kb/how-to/dtls-tutorial
*/
void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl,
void *p_timer,
@ -3285,7 +3331,7 @@ int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf,
mbedtls_pk_context *pk_key );
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
/**
* \brief Configure pre-shared keys (PSKs) and their
* identities to be used in PSK-based ciphersuites.
@ -3410,6 +3456,7 @@ int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl,
mbedtls_svc_key_id_t psk );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_SSL_SRV_C)
/**
* \brief Set the PSK callback (server-side only).
*
@ -3452,7 +3499,8 @@ 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_SSL_SRV_C */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)
/**
@ -3585,7 +3633,7 @@ void MBEDTLS_DEPRECATED mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf,
void mbedtls_ssl_conf_groups( mbedtls_ssl_config *conf,
const uint16_t *groups );
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
#if !defined(MBEDTLS_DEPRECATED_REMOVED) && defined(MBEDTLS_SSL_PROTO_TLS1_2)
/**
* \brief Set the allowed hashes for signatures during the handshake.
@ -3631,7 +3679,7 @@ void MBEDTLS_DEPRECATED mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf,
*/
void mbedtls_ssl_conf_sig_algs( mbedtls_ssl_config *conf,
const uint16_t* sig_algs );
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
#if defined(MBEDTLS_X509_CRT_PARSE_C)
/**
@ -4106,7 +4154,8 @@ int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_c
void mbedtls_ssl_conf_preference_order( mbedtls_ssl_config *conf, int order );
#endif /* MBEDTLS_SSL_SRV_C */
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \
defined(MBEDTLS_SSL_CLI_C)
/**
* \brief Enable / Disable session tickets (client only).
* (Default: MBEDTLS_SSL_SESSION_TICKETS_ENABLED.)
@ -4118,7 +4167,34 @@ void mbedtls_ssl_conf_preference_order( mbedtls_ssl_config *conf, int order );
* MBEDTLS_SSL_SESSION_TICKETS_DISABLED)
*/
void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets );
#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
#endif /* MBEDTLS_SSL_SESSION_TICKETS &&
MBEDTLS_SSL_CLI_C */
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \
defined(MBEDTLS_SSL_SRV_C) && \
defined(MBEDTLS_SSL_PROTO_TLS1_3)
/**
* \brief Number of NewSessionTicket messages for the server to send
* after handshake completion.
*
* \note The default value is
* \c MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS.
*
* \note In case of a session resumption, this setting only partially apply.
* At most one ticket is sent in that case to just renew the pool of
* tickets of the client. The rationale is to avoid the number of
* tickets on the server to become rapidly out of control when the
* server has the same configuration for all its connection instances.
*
* \param conf SSL configuration
* \param num_tickets Number of NewSessionTicket.
*
*/
void mbedtls_ssl_conf_new_session_tickets( mbedtls_ssl_config *conf,
uint16_t num_tickets );
#endif /* MBEDTLS_SSL_SESSION_TICKETS &&
MBEDTLS_SSL_SRV_C &&
MBEDTLS_SSL_PROTO_TLS1_3*/
#if defined(MBEDTLS_SSL_RENEGOTIATION)
/**

View file

@ -292,6 +292,11 @@ typedef enum {
#define MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) || \
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
#define MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED
#endif
/* Key exchanges allowing client certificate requests */
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
@ -341,6 +346,11 @@ typedef enum {
#define MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) || \
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
#define MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED
#endif
/* Key exchanges using DHE */
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)

View file

@ -24,6 +24,7 @@
#include "mbedtls/private_access.h"
#include "mbedtls/build_info.h"
#include "mbedtls/legacy_or_psa.h"
#include "mbedtls/x509.h"
#include "mbedtls/x509_crl.h"
@ -515,7 +516,7 @@ int mbedtls_x509_crt_parse_der_with_ext_cb( mbedtls_x509_crt *chain,
* 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
* retained and not be changed for the lifetime 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.
@ -1108,7 +1109,7 @@ int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx,
int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx,
int is_ca, int max_pathlen );
#if defined(MBEDTLS_SHA1_C) || ( defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_1) )
#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA)
/**
* \brief Set the subjectKeyIdentifier extension for a CRT
* Requires that mbedtls_x509write_crt_set_subject_key() has been
@ -1130,7 +1131,7 @@ int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ct
* \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED
*/
int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx );
#endif /* MBEDTLS_SHA1_C || (MBEDTLS_PSA_CRYPTO_C && PSA_WANT_ALG_SHA_1)*/
#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA */
/**
* \brief Set the Key Usage Extension flags
@ -1144,6 +1145,19 @@ int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *
int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
unsigned int key_usage );
/**
* \brief Set the Extended Key Usage Extension
* (e.g. MBEDTLS_OID_SERVER_AUTH)
*
* \param ctx CRT context to use
* \param exts extended key usage extensions to set, a sequence of
* MBEDTLS_ASN1_OID objects
*
* \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED
*/
int mbedtls_x509write_crt_set_ext_key_usage( mbedtls_x509write_cert *ctx,
const mbedtls_asn1_sequence *exts );
/**
* \brief Set the Netscape Cert Type flags
* (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL)

View file

@ -65,6 +65,7 @@
#define PSA_WANT_ALG_ECB_NO_PADDING 1
#define PSA_WANT_ALG_ECDH 1
#define PSA_WANT_ALG_ECDSA 1
#define PSA_WANT_ALG_JPAKE 1
#define PSA_WANT_ALG_GCM 1
#define PSA_WANT_ALG_HKDF 1
#define PSA_WANT_ALG_HKDF_EXTRACT 1
@ -88,6 +89,8 @@
#define PSA_WANT_ALG_STREAM_CIPHER 1
#define PSA_WANT_ALG_TLS12_PRF 1
#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1
#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1
/* PBKDF2-HMAC is not yet supported via the PSA API in Mbed TLS.
* Note: when adding support, also adjust include/mbedtls/config_psa.h */
//#define PSA_WANT_ALG_XTS 1

View file

@ -1760,7 +1760,16 @@ psa_status_t psa_pake_abort( psa_pake_operation_t * operation );
* recognized, or the parameters are incompatible,
* return 0.
*/
#define PSA_PAKE_OUTPUT_SIZE(alg, primitive, output_step) 0
#define PSA_PAKE_OUTPUT_SIZE(alg, primitive, output_step) \
( alg == PSA_ALG_JPAKE && \
primitive == PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, \
PSA_ECC_FAMILY_SECP_R1, 256) ? \
( \
output_step == PSA_PAKE_STEP_KEY_SHARE ? 65 : \
output_step == PSA_PAKE_STEP_ZK_PUBLIC ? 65 : \
32 \
) : \
0 )
/** A sufficient input buffer size for psa_pake_input().
*
@ -1781,7 +1790,16 @@ psa_status_t psa_pake_abort( psa_pake_operation_t * operation );
* the input type or PAKE algorithm is not recognized, or
* the parameters are incompatible, return 0.
*/
#define PSA_PAKE_INPUT_SIZE(alg, primitive, input_step) 0
#define PSA_PAKE_INPUT_SIZE(alg, primitive, input_step) \
( alg == PSA_ALG_JPAKE && \
primitive == PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, \
PSA_ECC_FAMILY_SECP_R1, 256) ? \
( \
input_step == PSA_PAKE_STEP_KEY_SHARE ? 65 : \
input_step == PSA_PAKE_STEP_ZK_PUBLIC ? 65 : \
32 \
) : \
0 )
/** Output buffer size for psa_pake_output() for any of the supported PAKE
* algorithm and primitive suites and output step.
@ -1790,7 +1808,7 @@ psa_status_t psa_pake_abort( psa_pake_operation_t * operation );
*
* See also #PSA_PAKE_OUTPUT_SIZE(\p alg, \p primitive, \p step).
*/
#define PSA_PAKE_OUTPUT_MAX_SIZE 0
#define PSA_PAKE_OUTPUT_MAX_SIZE 65
/** Input buffer size for psa_pake_input() for any of the supported PAKE
* algorithm and primitive suites and input step.
@ -1799,7 +1817,7 @@ psa_status_t psa_pake_abort( psa_pake_operation_t * operation );
*
* See also #PSA_PAKE_INPUT_SIZE(\p alg, \p primitive, \p step).
*/
#define PSA_PAKE_INPUT_MAX_SIZE 0
#define PSA_PAKE_INPUT_MAX_SIZE 65
/** Returns a suitable initializer for a PAKE cipher suite object of type
* psa_pake_cipher_suite_t.
@ -1809,7 +1827,14 @@ psa_status_t psa_pake_abort( psa_pake_operation_t * operation );
/** Returns a suitable initializer for a PAKE operation object of type
* psa_pake_operation_t.
*/
#define PSA_PAKE_OPERATION_INIT {PSA_ALG_NONE, {0}}
#if defined(MBEDTLS_PSA_BUILTIN_PAKE)
#define PSA_PAKE_OPERATION_INIT {PSA_ALG_NONE, 0, 0, 0, 0, \
MBEDTLS_SVC_KEY_ID_INIT, \
PSA_PAKE_ROLE_NONE, {0}, 0, 0, \
{.dummy = 0}}
#else
#define PSA_PAKE_OPERATION_INIT {PSA_ALG_NONE, 0, 0, {0}}
#endif
struct psa_pake_cipher_suite_s
{
@ -1879,14 +1904,36 @@ static inline void psa_pake_cs_set_hash( psa_pake_cipher_suite_t *cipher_suite,
cipher_suite->hash = hash;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
#include <mbedtls/ecjpake.h>
/* Note: the format for mbedtls_ecjpake_read/write function has an extra
* length byte for each step, plus an extra 3 bytes for ECParameters in the
* server's 2nd round. */
#define MBEDTLS_PSA_PAKE_BUFFER_SIZE ( ( 3 + 1 + 65 + 1 + 65 + 1 + 32 ) * 2 )
#endif
struct psa_pake_operation_s
{
psa_algorithm_t alg;
psa_algorithm_t MBEDTLS_PRIVATE(alg);
unsigned int MBEDTLS_PRIVATE(state);
unsigned int MBEDTLS_PRIVATE(sequence);
#if defined(MBEDTLS_PSA_BUILTIN_PAKE)
unsigned int MBEDTLS_PRIVATE(input_step);
unsigned int MBEDTLS_PRIVATE(output_step);
mbedtls_svc_key_id_t MBEDTLS_PRIVATE(password);
psa_pake_role_t MBEDTLS_PRIVATE(role);
uint8_t MBEDTLS_PRIVATE(buffer[MBEDTLS_PSA_PAKE_BUFFER_SIZE]);
size_t MBEDTLS_PRIVATE(buffer_length);
size_t MBEDTLS_PRIVATE(buffer_offset);
#endif
union
{
#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
mbedtls_ecjpake_context ecjpake;
#endif
/* Make the union non-empty even with no supported algorithms. */
uint8_t dummy;
} ctx;
} MBEDTLS_PRIVATE(ctx);
};
static inline struct psa_pake_cipher_suite_s psa_pake_cipher_suite_init( void )

View file

@ -239,6 +239,15 @@
*/
#define PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE 128
/* The expected size of input passed to psa_tls12_ecjpake_to_pms_input,
* which is expected to work with P-256 curve only. */
#define PSA_TLS12_ECJPAKE_TO_PMS_INPUT_SIZE 65
/* The size of a serialized K.X coordinate to be used in
* psa_tls12_ecjpake_to_pms_input. This function only accepts the P-256
* curve. */
#define PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE 32
/** The maximum size of a block cipher. */
#define PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE 16

View file

@ -202,6 +202,12 @@ typedef struct
#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF ||
MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT ||
MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
typedef struct
{
uint8_t MBEDTLS_PRIVATE(data)[PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE];
} psa_tls12_ecjpake_to_pms_t;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
@ -266,6 +272,9 @@ struct psa_key_derivation_s
#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
psa_tls12_prf_key_derivation_t MBEDTLS_PRIVATE(tls12_prf);
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
psa_tls12_ecjpake_to_pms_t MBEDTLS_PRIVATE(tls12_ecjpake_to_pms);
#endif
} MBEDTLS_PRIVATE(ctx);
};

View file

@ -2021,6 +2021,20 @@
#define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg) \
(PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK))
/* The TLS 1.2 ECJPAKE-to-PMS KDF. It takes the shared secret K (an EC point
* in case of EC J-PAKE) and calculates SHA256(K.X) that the rest of TLS 1.2
* will use to derive the session secret, as defined by step 2 of
* https://datatracker.ietf.org/doc/html/draft-cragie-tls-ecjpake-01#section-8.7.
* Uses PSA_ALG_SHA_256.
* This function takes a single input:
* #PSA_KEY_DERIVATION_INPUT_SECRET is the shared secret K from EC J-PAKE.
* The only supported curve is secp256r1 (the 256-bit curve in
* #PSA_ECC_FAMILY_SECP_R1), so the input must be exactly 65 bytes.
* The output has to be read as a single chunk of 32 bytes, defined as
* PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE.
*/
#define PSA_ALG_TLS12_ECJPAKE_TO_PMS ((psa_algorithm_t)0x08000609)
/* This flag indicates whether the key derivation algorithm is suitable for
* use on low-entropy secrets such as password - these algorithms are also
* known as key stretching or password hashing schemes. These are also the

View file

@ -44,6 +44,8 @@ set(src_crypto
hash_info.c
hkdf.c
hmac_drbg.c
lmots.c
lms.c
md.c
md5.c
memory_buffer_alloc.c
@ -70,6 +72,7 @@ set(src_crypto
psa_crypto_ecp.c
psa_crypto_hash.c
psa_crypto_mac.c
psa_crypto_pake.c
psa_crypto_rsa.c
psa_crypto_se.c
psa_crypto_slot_management.c

View file

@ -109,6 +109,8 @@ OBJS_CRYPTO= \
hash_info.o \
hkdf.o \
hmac_drbg.o \
lmots.o \
lms.o \
md.o \
md5.o \
memory_buffer_alloc.o \
@ -135,6 +137,7 @@ OBJS_CRYPTO= \
psa_crypto_ecp.o \
psa_crypto_hash.o \
psa_crypto_mac.o \
psa_crypto_pake.o \
psa_crypto_rsa.o \
psa_crypto_se.o \
psa_crypto_slot_management.o \
@ -196,6 +199,7 @@ all: shared static
endif
static: libmbedcrypto.a libmbedx509.a libmbedtls.a
cd ../tests && echo "This is a seedfile that contains 64 bytes (65 on Windows)......" > seedfile
shared: libmbedcrypto.$(DLEXT) libmbedx509.$(DLEXT) libmbedtls.$(DLEXT)

View file

@ -40,23 +40,10 @@
#include "aesni.h"
#endif
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_AES_ALT)
/* Parameter validation macros based on platform_util.h */
#define AES_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_AES_BAD_INPUT_DATA )
#define AES_VALIDATE( cond ) \
MBEDTLS_INTERNAL_VALIDATE( cond )
#if defined(MBEDTLS_PADLOCK_C) && \
( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) )
static int aes_padlock_ace = -1;
@ -489,8 +476,6 @@ static void aes_gen_tables( void )
void mbedtls_aes_init( mbedtls_aes_context *ctx )
{
AES_VALIDATE( ctx != NULL );
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
}
@ -505,8 +490,6 @@ void mbedtls_aes_free( mbedtls_aes_context *ctx )
#if defined(MBEDTLS_CIPHER_MODE_XTS)
void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx )
{
AES_VALIDATE( ctx != NULL );
mbedtls_aes_init( &ctx->crypt );
mbedtls_aes_init( &ctx->tweak );
}
@ -531,9 +514,6 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int i;
uint32_t *RK;
AES_VALIDATE_RET( ctx != NULL );
AES_VALIDATE_RET( key != NULL );
switch( keybits )
{
case 128: ctx->nr = 10; break;
@ -649,9 +629,6 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
uint32_t *RK;
uint32_t *SK;
AES_VALIDATE_RET( ctx != NULL );
AES_VALIDATE_RET( key != NULL );
mbedtls_aes_init( &cty );
ctx->rk_offset = 0;
@ -743,9 +720,6 @@ int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
AES_VALIDATE_RET( ctx != NULL );
AES_VALIDATE_RET( key != NULL );
ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
&key2, &key2bits );
if( ret != 0 )
@ -768,9 +742,6 @@ int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
AES_VALIDATE_RET( ctx != NULL );
AES_VALIDATE_RET( key != NULL );
ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
&key2, &key2bits );
if( ret != 0 )
@ -970,11 +941,8 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
AES_VALIDATE_RET( ctx != NULL );
AES_VALIDATE_RET( input != NULL );
AES_VALIDATE_RET( output != NULL );
AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
mode == MBEDTLS_AES_DECRYPT );
if( mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT )
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) )
@ -1014,12 +982,8 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char temp[16];
AES_VALIDATE_RET( ctx != NULL );
AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
mode == MBEDTLS_AES_DECRYPT );
AES_VALIDATE_RET( iv != NULL );
AES_VALIDATE_RET( input != NULL );
AES_VALIDATE_RET( output != NULL );
if( mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT )
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
if( length % 16 )
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
@ -1123,12 +1087,8 @@ int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
unsigned char prev_tweak[16];
unsigned char tmp[16];
AES_VALIDATE_RET( ctx != NULL );
AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
mode == MBEDTLS_AES_DECRYPT );
AES_VALIDATE_RET( data_unit != NULL );
AES_VALIDATE_RET( input != NULL );
AES_VALIDATE_RET( output != NULL );
if( mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT )
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
/* Data units must be at least 16 bytes long. */
if( length < 16 )
@ -1232,13 +1192,8 @@ int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
AES_VALIDATE_RET( ctx != NULL );
AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
mode == MBEDTLS_AES_DECRYPT );
AES_VALIDATE_RET( iv_off != NULL );
AES_VALIDATE_RET( iv != NULL );
AES_VALIDATE_RET( input != NULL );
AES_VALIDATE_RET( output != NULL );
if( mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT )
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
n = *iv_off;
@ -1301,12 +1256,8 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
unsigned char c;
unsigned char ov[17];
AES_VALIDATE_RET( ctx != NULL );
AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
mode == MBEDTLS_AES_DECRYPT );
AES_VALIDATE_RET( iv != NULL );
AES_VALIDATE_RET( input != NULL );
AES_VALIDATE_RET( output != NULL );
if( mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT )
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
while( length-- )
{
memcpy( ov, iv, 16 );
@ -1345,12 +1296,6 @@ int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
int ret = 0;
size_t n;
AES_VALIDATE_RET( ctx != NULL );
AES_VALIDATE_RET( iv_off != NULL );
AES_VALIDATE_RET( iv != NULL );
AES_VALIDATE_RET( input != NULL );
AES_VALIDATE_RET( output != NULL );
n = *iv_off;
if( n > 15 )
@ -1392,13 +1337,6 @@ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
AES_VALIDATE_RET( ctx != NULL );
AES_VALIDATE_RET( nc_off != NULL );
AES_VALIDATE_RET( nonce_counter != NULL );
AES_VALIDATE_RET( stream_block != NULL );
AES_VALIDATE_RET( input != NULL );
AES_VALIDATE_RET( output != NULL );
n = *nc_off;
if ( n > 0x0F )
@ -1752,7 +1690,8 @@ int mbedtls_aes_self_test( int verbose )
unsigned char key[32];
unsigned char buf[64];
const unsigned char *aes_tests;
#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)
#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \
defined(MBEDTLS_CIPHER_MODE_OFB)
unsigned char iv[16];
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)

View file

@ -31,14 +31,7 @@
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_ARIA_ALT)
@ -895,15 +888,17 @@ static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext
};
#endif /* MBEDTLS_CIPHER_MODE_CFB */
#define ARIA_SELF_TEST_IF_FAIL \
{ \
if( verbose ) \
mbedtls_printf( "failed\n" ); \
goto exit; \
} else { \
if( verbose ) \
mbedtls_printf( "passed\n" ); \
}
#define ARIA_SELF_TEST_ASSERT( cond ) \
do { \
if( cond ) { \
if( verbose ) \
mbedtls_printf( "failed\n" ); \
goto exit; \
} else { \
if( verbose ) \
mbedtls_printf( "passed\n" ); \
} \
} while( 0 )
/*
* Checkup routine
@ -937,16 +932,18 @@ int mbedtls_aria_self_test( int verbose )
mbedtls_printf( " ARIA-ECB-%d (enc): ", 128 + 64 * i );
mbedtls_aria_setkey_enc( &ctx, aria_test1_ecb_key, 128 + 64 * i );
mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_pt, blk );
if( memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
ARIA_SELF_TEST_ASSERT(
memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE )
!= 0 );
/* test ECB decryption */
if( verbose )
mbedtls_printf( " ARIA-ECB-%d (dec): ", 128 + 64 * i );
mbedtls_aria_setkey_dec( &ctx, aria_test1_ecb_key, 128 + 64 * i );
mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_ct[i], blk );
if( memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
ARIA_SELF_TEST_ASSERT(
memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE )
!= 0 );
}
if( verbose )
mbedtls_printf( "\n" );
@ -965,8 +962,8 @@ int mbedtls_aria_self_test( int verbose )
memset( buf, 0x55, sizeof( buf ) );
mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv,
aria_test2_pt, buf );
if( memcmp( buf, aria_test2_cbc_ct[i], 48 ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_cbc_ct[i], 48 )
!= 0 );
/* Test CBC decryption */
if( verbose )
@ -976,8 +973,7 @@ int mbedtls_aria_self_test( int verbose )
memset( buf, 0xAA, sizeof( buf ) );
mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_DECRYPT, 48, iv,
aria_test2_cbc_ct[i], buf );
if( memcmp( buf, aria_test2_pt, 48 ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_pt, 48 ) != 0 );
}
if( verbose )
mbedtls_printf( "\n" );
@ -996,8 +992,7 @@ int mbedtls_aria_self_test( int verbose )
j = 0;
mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv,
aria_test2_pt, buf );
if( memcmp( buf, aria_test2_cfb_ct[i], 48 ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_cfb_ct[i], 48 ) != 0 );
/* Test CFB decryption */
if( verbose )
@ -1008,8 +1003,7 @@ int mbedtls_aria_self_test( int verbose )
j = 0;
mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_DECRYPT, 48, &j,
iv, aria_test2_cfb_ct[i], buf );
if( memcmp( buf, aria_test2_pt, 48 ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_pt, 48 ) != 0 );
}
if( verbose )
mbedtls_printf( "\n" );
@ -1027,8 +1021,7 @@ int mbedtls_aria_self_test( int verbose )
j = 0;
mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk,
aria_test2_pt, buf );
if( memcmp( buf, aria_test2_ctr_ct[i], 48 ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_ctr_ct[i], 48 ) != 0 );
/* Test CTR decryption */
if( verbose )
@ -1039,8 +1032,7 @@ int mbedtls_aria_self_test( int verbose )
j = 0;
mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk,
aria_test2_ctr_ct[i], buf );
if( memcmp( buf, aria_test2_pt, 48 ) != 0 )
ARIA_SELF_TEST_IF_FAIL;
ARIA_SELF_TEST_ASSERT( memcmp( buf, aria_test2_pt, 48 ) != 0 );
}
if( verbose )
mbedtls_printf( "\n" );

View file

@ -31,13 +31,7 @@
#include "mbedtls/bignum.h"
#endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
/*
* ASN.1 DER decoding routines
@ -320,7 +314,6 @@ 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;
}
@ -438,6 +431,7 @@ int mbedtls_asn1_get_alg_null( unsigned char **p,
return( 0 );
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur )
{
if( cur == NULL )
@ -448,6 +442,7 @@ void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur )
mbedtls_platform_zeroize( cur, sizeof( mbedtls_asn1_named_data ) );
}
#endif /* MBEDTLS_DEPRECATED_REMOVED */
void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head )
{
@ -456,11 +451,21 @@ void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head )
while( ( cur = *head ) != NULL )
{
*head = cur->next;
mbedtls_asn1_free_named_data( cur );
mbedtls_free( cur->oid.p );
mbedtls_free( cur->val.p );
mbedtls_free( cur );
}
}
void mbedtls_asn1_free_named_data_list_shallow( mbedtls_asn1_named_data *name )
{
for( mbedtls_asn1_named_data *next; name != NULL; name = next )
{
next = name->next;
mbedtls_free( name );
}
}
const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( const mbedtls_asn1_named_data *list,
const char *oid, size_t len )
{

View file

@ -26,13 +26,7 @@
#include <string.h>
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
int mbedtls_asn1_write_len( unsigned char **p, const unsigned char *start, size_t len )
{
@ -78,9 +72,11 @@ int mbedtls_asn1_write_len( unsigned char **p, const unsigned char *start, size_
return( 4 );
}
int len_is_valid = 1;
#if SIZE_MAX > 0xFFFFFFFF
if( len <= 0xFFFFFFFF )
len_is_valid = ( len <= 0xFFFFFFFF );
#endif
if( len_is_valid )
{
if( *p - start < 5 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
@ -93,9 +89,7 @@ int mbedtls_asn1_write_len( unsigned char **p, const unsigned char *start, size_
return( 5 );
}
#if SIZE_MAX > 0xFFFFFFFF
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
#endif
}
int mbedtls_asn1_write_tag( unsigned char **p, const unsigned char *start, unsigned char tag )

View file

@ -28,12 +28,7 @@
#if defined(MBEDTLS_SELF_TEST)
#include <string.h>
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */

View file

@ -38,7 +38,6 @@
#if defined(MBEDTLS_BIGNUM_C)
#include "mbedtls/bignum.h"
#include "bignum_internal.h"
#include "bignum_core.h"
#include "bn_mul.h"
#include "mbedtls/platform_util.h"
@ -48,15 +47,7 @@
#include <limits.h>
#include <string.h>
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_printf printf
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#define MPI_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
@ -780,42 +771,9 @@ cleanup:
*/
int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
{
size_t i, v0, v1;
mbedtls_mpi_uint r0 = 0, r1;
MPI_VALIDATE_RET( X != NULL );
v0 = count / biL;
v1 = count & (biL - 1);
if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
return mbedtls_mpi_lset( X, 0 );
/*
* shift by count / limb_size
*/
if( v0 > 0 )
{
for( i = 0; i < X->n - v0; i++ )
X->p[i] = X->p[i + v0];
for( ; i < X->n; i++ )
X->p[i] = 0;
}
/*
* shift by count % limb_size
*/
if( v1 > 0 )
{
for( i = X->n; i > 0; i-- )
{
r1 = X->p[i - 1] << (biL - v1);
X->p[i - 1] >>= v1;
X->p[i - 1] |= r0;
r0 = r1;
}
}
if( X->n != 0 )
mbedtls_mpi_core_shift_r( X->p, X->n, count );
return( 0 );
}
@ -909,8 +867,7 @@ int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, j;
mbedtls_mpi_uint *o, *p, c, tmp;
size_t j;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( A != NULL );
MPI_VALIDATE_RET( B != NULL );
@ -924,7 +881,7 @@ int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
/*
* X should always be positive as a result of unsigned additions.
* X must always be positive as a result of unsigned additions.
*/
X->s = 1;
@ -934,27 +891,25 @@ int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
o = B->p; p = X->p; c = 0;
/* j is the number of non-zero limbs of B. Add those to X. */
/*
* tmp is used because it might happen that p == o
*/
for( i = 0; i < j; i++, o++, p++ )
{
tmp= *o;
*p += c; c = ( *p < c );
*p += tmp; c += ( *p < tmp );
}
mbedtls_mpi_uint *p = X->p;
mbedtls_mpi_uint c = mbedtls_mpi_core_add( p, p, B->p, j );
p += j;
/* Now propagate any carry */
while( c != 0 )
{
if( i >= X->n )
if( j >= X->n )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
p = X->p + i;
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j + 1 ) );
p = X->p + j;
}
*p += c; c = ( *p < c ); i++; p++;
*p += c; c = ( *p < c ); j++; p++;
}
cleanup:
@ -962,40 +917,6 @@ cleanup:
return( ret );
}
/**
* Helper for mbedtls_mpi subtraction.
*
* Calculate l - r where l and r have the same size.
* This function operates modulo (2^ciL)^n and returns the carry
* (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
*
* d may be aliased to l or r.
*
* \param n Number of limbs of \p d, \p l and \p r.
* \param[out] d The result of the subtraction.
* \param[in] l The left operand.
* \param[in] r The right operand.
*
* \return 1 if `l < r`.
* 0 if `l >= r`.
*/
static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
mbedtls_mpi_uint *d,
const mbedtls_mpi_uint *l,
const mbedtls_mpi_uint *r )
{
size_t i;
mbedtls_mpi_uint c = 0, t, z;
for( i = 0; i < n; i++ )
{
z = ( l[i] < c ); t = l[i] - c;
c = ( t < r[i] ) + z; d[i] = t - r[i];
}
return( c );
}
/*
* Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10)
*/
@ -1028,7 +949,7 @@ int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
if( X->n > A->n )
memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
carry = mpi_sub_hlp( n, X->p, A->p, B->p );
carry = mbedtls_mpi_core_sub( X->p, A->p, B->p, n );
if( carry != 0 )
{
/* Propagate the carry to the first nonzero limb of X. */
@ -1157,38 +1078,6 @@ int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint
return( mbedtls_mpi_sub_mpi( X, A, &B ) );
}
mbedtls_mpi_uint mbedtls_mpi_core_mla( mbedtls_mpi_uint *d, size_t d_len,
const mbedtls_mpi_uint *s, size_t s_len,
mbedtls_mpi_uint b )
{
mbedtls_mpi_uint c = 0; /* carry */
size_t excess_len = d_len - s_len;
size_t steps_x8 = s_len / 8;
size_t steps_x1 = s_len & 7;
while( steps_x8-- )
{
MULADDC_X8_INIT
MULADDC_X8_CORE
MULADDC_X8_STOP
}
while( steps_x1-- )
{
MULADDC_X1_INIT
MULADDC_X1_CORE
MULADDC_X1_STOP
}
while( excess_len-- )
{
*d += c; c = ( *d < c ); d++;
}
return( c );
}
/*
* Baseline multiplication: X = A * B (HAC 14.12)
*/
@ -1612,21 +1501,9 @@ int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_
return( 0 );
}
/*
* Fast Montgomery initialization (thanks to Tom St Denis)
*/
static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
{
mbedtls_mpi_uint x, m0 = N->p[0];
unsigned int i;
x = m0;
x += ( ( m0 + 2 ) & 4 ) << 1;
for( i = biL; i >= 8; i /= 2 )
x *= ( 2 - ( m0 * x ) );
*mm = ~x + 1;
*mm = mbedtls_mpi_core_montmul_init( N->p );
}
/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
@ -1640,7 +1517,7 @@ static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
* \param[in] B One of the numbers to multiply.
* It must be nonzero and must not have more limbs than N
* (B->n <= N->n).
* \param[in] N The modulo. N must be odd.
* \param[in] N The modulus. \p N must be odd.
* \param mm The value calculated by `mpi_montg_init(&mm, N)`.
* This is -N^-1 mod 2^ciL.
* \param[in,out] T A bignum for temporary storage.
@ -1648,59 +1525,13 @@ static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
* (T->n >= 2 * N->n + 1).
* Its initial content is unused and
* its final content is indeterminate.
* Note that unlike the usual convention in the library
* for `const mbedtls_mpi*`, the content of T can change.
* It does not get reallocated.
*/
static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
const mbedtls_mpi *T )
static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B,
const mbedtls_mpi *N, mbedtls_mpi_uint mm,
mbedtls_mpi *T )
{
size_t n, m;
mbedtls_mpi_uint *d;
memset( T->p, 0, T->n * ciL );
d = T->p;
n = N->n;
m = ( B->n < n ) ? B->n : n;
for( size_t i = 0; i < n; i++ )
{
mbedtls_mpi_uint u0, u1;
/*
* T = (T + u0*B + u1*N) / 2^biL
*/
u0 = A->p[i];
u1 = ( d[0] + u0 * B->p[0] ) * mm;
(void) mbedtls_mpi_core_mla( d, n + 2,
B->p, m,
u0 );
(void) mbedtls_mpi_core_mla( d, n + 2,
N->p, n,
u1 );
d++;
}
/* At this point, d is either the desired result or the desired result
* plus N. We now potentially subtract N, avoiding leaking whether the
* subtraction is performed through side channels. */
/* Copy the n least significant limbs of d to A, so that
* A = d if d < N (recall that N has n limbs). */
memcpy( A->p, d, n * ciL );
/* If d >= N then we want to set A to d - N. To prevent timing attacks,
* do the calculation without using conditional tests. */
/* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
d[n] += 1;
d[n] -= mpi_sub_hlp( n, d, d, N->p );
/* If d0 < N then d < (2^biL)^n
* so d[n] == 0 and we want to keep A as it is.
* If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
* so d[n] == 1 and we want to set A to the result of the subtraction
* which is d - (2^biL)^n, i.e. the n least significant limbs of d.
* This exactly corresponds to a conditional assignment. */
mbedtls_ct_mpi_uint_cond_assign( n, A->p, d, (unsigned char) d[n] );
mbedtls_mpi_core_montmul( A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p );
}
/*
@ -1709,7 +1540,7 @@ static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi
* See mpi_montmul() regarding constraints and guarantees on the parameters.
*/
static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
mbedtls_mpi_uint mm, const mbedtls_mpi *T )
mbedtls_mpi_uint mm, mbedtls_mpi *T )
{
mbedtls_mpi_uint z = 1;
mbedtls_mpi U;
@ -2100,39 +1931,11 @@ cleanup:
return( ret );
}
/* Fill X with n_bytes random bytes.
* X must already have room for those bytes.
* The ordering of the bytes returned from the RNG is suitable for
* deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
* The size and sign of X are unchanged.
* n_bytes must not be 0.
*/
static int mpi_fill_random_internal(
mbedtls_mpi *X, size_t n_bytes,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const size_t limbs = CHARS_TO_LIMBS( n_bytes );
const size_t overhead = ( limbs * ciL ) - n_bytes;
if( X->n < limbs )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
memset( X->p, 0, overhead );
memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
mbedtls_mpi_core_bigendian_to_host( X->p, limbs );
cleanup:
return( ret );
}
/*
* Fill X with size bytes of random.
*
* Use a temporary bytes representation to make sure the result is the same
* regardless of the platform endianness (useful when f_rng is actually
* deterministic, eg for tests).
* The bytes returned from the RNG are used in a specific order which
* is suitable for deterministic ECDSA (see the specification of
* mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()).
*/
int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
int (*f_rng)(void *, unsigned char *, size_t),
@ -2149,7 +1952,7 @@ int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
if( size == 0 )
return( 0 );
ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
ret = mbedtls_mpi_core_fill_random( X->p, X->n, size, f_rng, p_rng );
cleanup:
return( ret );
@ -2211,7 +2014,9 @@ int mbedtls_mpi_random( mbedtls_mpi *X,
*/
do
{
MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_core_fill_random( X->p, X->n,
n_bytes,
f_rng, p_rng ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
if( --count == 0 )

View file

@ -25,18 +25,13 @@
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include "constant_time_internal.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_printf printf
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#include "bignum_core.h"
#include "bn_mul.h"
#include "constant_time_internal.h"
size_t mbedtls_mpi_core_clz( mbedtls_mpi_uint a )
{
@ -153,12 +148,42 @@ void mbedtls_mpi_core_bigendian_to_host( mbedtls_mpi_uint *A,
mbedtls_mpi_uint tmp;
/* Note that if cur_limb_left == cur_limb_right,
* this code effectively swaps the bytes only once. */
tmp = mpi_bigendian_to_host( *cur_limb_left );
tmp = mpi_bigendian_to_host( *cur_limb_left );
*cur_limb_left = mpi_bigendian_to_host( *cur_limb_right );
*cur_limb_right = tmp;
}
}
void mbedtls_mpi_core_cond_assign( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
size_t limbs,
unsigned char assign )
{
if( X == A )
return;
mbedtls_ct_mpi_uint_cond_assign( limbs, X, A, assign );
}
void mbedtls_mpi_core_cond_swap( mbedtls_mpi_uint *X,
mbedtls_mpi_uint *Y,
size_t limbs,
unsigned char swap )
{
if( X == Y )
return;
/* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask( swap );
for( size_t i = 0; i < limbs; i++ )
{
mbedtls_mpi_uint tmp = X[i];
X[i] = ( X[i] & ~limb_mask ) | ( Y[i] & limb_mask );
Y[i] = ( Y[i] & ~limb_mask ) | ( tmp & limb_mask );
}
}
int mbedtls_mpi_core_read_le( mbedtls_mpi_uint *X,
size_t X_limbs,
const unsigned char *input,
@ -291,4 +316,308 @@ int mbedtls_mpi_core_write_be( const mbedtls_mpi_uint *X,
return( 0 );
}
void mbedtls_mpi_core_shift_r( mbedtls_mpi_uint *X, size_t limbs,
size_t count )
{
size_t i, v0, v1;
mbedtls_mpi_uint r0 = 0, r1;
v0 = count / biL;
v1 = count & (biL - 1);
if( v0 > limbs || ( v0 == limbs && v1 > 0 ) )
{
memset( X, 0, limbs * ciL );
return;
}
/*
* shift by count / limb_size
*/
if( v0 > 0 )
{
for( i = 0; i < limbs - v0; i++ )
X[i] = X[i + v0];
for( ; i < limbs; i++ )
X[i] = 0;
}
/*
* shift by count % limb_size
*/
if( v1 > 0 )
{
for( i = limbs; i > 0; i-- )
{
r1 = X[i - 1] << (biL - v1);
X[i - 1] >>= v1;
X[i - 1] |= r0;
r0 = r1;
}
}
}
mbedtls_mpi_uint mbedtls_mpi_core_add( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
size_t limbs )
{
mbedtls_mpi_uint c = 0;
for( size_t i = 0; i < limbs; i++ )
{
mbedtls_mpi_uint t = c + A[i];
c = ( t < A[i] );
t += B[i];
c += ( t < B[i] );
X[i] = t;
}
return( c );
}
mbedtls_mpi_uint mbedtls_mpi_core_add_if( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
size_t limbs,
unsigned cond )
{
mbedtls_mpi_uint c = 0;
/* all-bits 0 if cond is 0, all-bits 1 if cond is non-0 */
const mbedtls_mpi_uint mask = mbedtls_ct_mpi_uint_mask( cond );
for( size_t i = 0; i < limbs; i++ )
{
mbedtls_mpi_uint add = mask & A[i];
mbedtls_mpi_uint t = c + X[i];
c = ( t < X[i] );
t += add;
c += ( t < add );
X[i] = t;
}
return( c );
}
mbedtls_mpi_uint mbedtls_mpi_core_sub( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
size_t limbs )
{
mbedtls_mpi_uint c = 0;
for( size_t i = 0; i < limbs; i++ )
{
mbedtls_mpi_uint z = ( A[i] < c );
mbedtls_mpi_uint t = A[i] - c;
c = ( t < B[i] ) + z;
X[i] = t - B[i];
}
return( c );
}
mbedtls_mpi_uint mbedtls_mpi_core_mla( mbedtls_mpi_uint *d, size_t d_len,
const mbedtls_mpi_uint *s, size_t s_len,
mbedtls_mpi_uint b )
{
mbedtls_mpi_uint c = 0; /* carry */
/*
* It is a documented precondition of this function that d_len >= s_len.
* If that's not the case, we swap these round: this turns what would be
* a buffer overflow into an incorrect result.
*/
if( d_len < s_len )
s_len = d_len;
size_t excess_len = d_len - s_len;
size_t steps_x8 = s_len / 8;
size_t steps_x1 = s_len & 7;
while( steps_x8-- )
{
MULADDC_X8_INIT
MULADDC_X8_CORE
MULADDC_X8_STOP
}
while( steps_x1-- )
{
MULADDC_X1_INIT
MULADDC_X1_CORE
MULADDC_X1_STOP
}
while( excess_len-- )
{
*d += c;
c = ( *d < c );
d++;
}
return( c );
}
/*
* Fast Montgomery initialization (thanks to Tom St Denis).
*/
mbedtls_mpi_uint mbedtls_mpi_core_montmul_init( const mbedtls_mpi_uint *N )
{
mbedtls_mpi_uint x = N[0];
x += ( ( N[0] + 2 ) & 4 ) << 1;
for( unsigned int i = biL; i >= 8; i /= 2 )
x *= ( 2 - ( N[0] * x ) );
return( ~x + 1 );
}
void mbedtls_mpi_core_montmul( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
size_t B_limbs,
const mbedtls_mpi_uint *N,
size_t AN_limbs,
mbedtls_mpi_uint mm,
mbedtls_mpi_uint *T )
{
memset( T, 0, ( 2 * AN_limbs + 1 ) * ciL );
for( size_t i = 0; i < AN_limbs; i++ )
{
/* T = (T + u0*B + u1*N) / 2^biL */
mbedtls_mpi_uint u0 = A[i];
mbedtls_mpi_uint u1 = ( T[0] + u0 * B[0] ) * mm;
(void) mbedtls_mpi_core_mla( T, AN_limbs + 2, B, B_limbs, u0 );
(void) mbedtls_mpi_core_mla( T, AN_limbs + 2, N, AN_limbs, u1 );
T++;
}
/*
* The result we want is (T >= N) ? T - N : T.
*
* For better constant-time properties in this function, we always do the
* subtraction, with the result in X.
*
* We also look to see if there was any carry in the final additions in the
* loop above.
*/
mbedtls_mpi_uint carry = T[AN_limbs];
mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub( X, T, N, AN_limbs );
/*
* Using R as the Montgomery radix (auxiliary modulus) i.e. 2^(biL*AN_limbs):
*
* T can be in one of 3 ranges:
*
* 1) T < N : (carry, borrow) = (0, 1): we want T
* 2) N <= T < R : (carry, borrow) = (0, 0): we want X
* 3) T >= R : (carry, borrow) = (1, 1): we want X
*
* and (carry, borrow) = (1, 0) can't happen.
*
* So the correct return value is already in X if (carry ^ borrow) = 0,
* but is in (the lower AN_limbs limbs of) T if (carry ^ borrow) = 1.
*/
mbedtls_ct_mpi_uint_cond_assign( AN_limbs, X, T, (unsigned char) ( carry ^ borrow ) );
}
int mbedtls_mpi_core_get_mont_r2_unsafe( mbedtls_mpi *X,
const mbedtls_mpi *N )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( X, N->n * 2 * biL ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( X, X, N ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( X, N->n ) );
cleanup:
return( ret );
}
void mbedtls_mpi_core_ct_uint_table_lookup( mbedtls_mpi_uint *dest,
const mbedtls_mpi_uint *table,
size_t limbs,
size_t count,
size_t index )
{
for( size_t i = 0; i < count; i++, table += limbs )
{
unsigned char assign = mbedtls_ct_size_bool_eq( i, index );
mbedtls_mpi_core_cond_assign( dest, table, limbs, assign );
}
}
/* Fill X with n_bytes random bytes.
* X must already have room for those bytes.
* The ordering of the bytes returned from the RNG is suitable for
* deterministic ECDSA (see RFC 6979 §3.3 and the specification of
* mbedtls_mpi_core_random()).
*/
int mbedtls_mpi_core_fill_random(
mbedtls_mpi_uint *X, size_t X_limbs,
size_t n_bytes,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const size_t limbs = CHARS_TO_LIMBS( n_bytes );
const size_t overhead = ( limbs * ciL ) - n_bytes;
if( X_limbs < limbs )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
memset( X, 0, overhead );
memset( (unsigned char *) X + limbs * ciL, 0, ( X_limbs - limbs ) * ciL );
MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X + overhead, n_bytes ) );
mbedtls_mpi_core_bigendian_to_host( X, limbs );
cleanup:
return( ret );
}
/* BEGIN MERGE SLOT 1 */
/* END MERGE SLOT 1 */
/* BEGIN MERGE SLOT 2 */
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
/* END MERGE SLOT 7 */
/* BEGIN MERGE SLOT 8 */
/* END MERGE SLOT 8 */
/* BEGIN MERGE SLOT 9 */
/* END MERGE SLOT 9 */
/* BEGIN MERGE SLOT 10 */
/* END MERGE SLOT 10 */
#endif /* MBEDTLS_BIGNUM_C */

View file

@ -6,6 +6,61 @@
* modules should use the high-level modular bignum interface (bignum_mod.h)
* or the legacy bignum interface (bignum.h).
*
* This module is about processing non-negative integers with a fixed upper
* bound that's of the form 2^n-1 where n is a multiple of #biL.
* These can be thought of integers written in base 2^#biL with a fixed
* number of digits. Digits in this base are called *limbs*.
* Many operations treat these numbers as the principal representation of
* a number modulo 2^n or a smaller bound.
*
* The functions in this module obey the following conventions unless
* explicitly indicated otherwise:
*
* - **Overflow**: some functions indicate overflow from the range
* [0, 2^n-1] by returning carry parameters, while others operate
* modulo and so cannot overflow. This should be clear from the function
* documentation.
* - **Bignum parameters**: Bignums are passed as pointers to an array of
* limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified:
* - Bignum parameters called \p A, \p B, ... are inputs, and are
* not modified by the function.
* - For operations modulo some number, the modulus is called \p N
* and is input-only.
* - Bignum parameters called \p X, \p Y are outputs or input-output.
* The initial content of output-only parameters is ignored.
* - Some functions use different names that reflect traditional
* naming of operands of certain operations (e.g.
* divisor/dividend/quotient/remainder).
* - \p T is a temporary storage area. The initial content of such
* parameter is ignored and the final content is unspecified.
* - **Bignum sizes**: bignum sizes are always expressed in limbs.
* Most functions work on bignums of a given size and take a single
* \p limbs parameter that applies to all parameters that are limb arrays.
* All bignum sizes must be at least 1 and must be significantly less than
* #SIZE_MAX. The behavior if a size is 0 is undefined. The behavior if the
* total size of all parameters overflows #SIZE_MAX is undefined.
* - **Parameter ordering**: for bignum parameters, outputs come before inputs.
* Temporaries come last.
* - **Aliasing**: in general, output bignums may be aliased to one or more
* inputs. As an exception, parameters that are documented as a modulus value
* may not be aliased to an output. Outputs may not be aliased to one another.
* Temporaries may not be aliased to any other parameter.
* - **Overlap**: apart from aliasing of limb array pointers (where two
* arguments are equal pointers), overlap is not supported and may result
* in undefined behavior.
* - **Error handling**: This is a low-level module. Functions generally do not
* try to protect against invalid arguments such as nonsensical sizes or
* null pointers. Note that some functions that operate on bignums of
* different sizes have constraints about their size, and violating those
* constraints may lead to buffer overflows.
* - **Modular representatives**: functions that operate modulo \p N expect
* all modular inputs to be in the range [0, \p N - 1] and guarantee outputs
* in the range [0, \p N - 1]. If an input is out of range, outputs are
* fully unspecified, though bignum values out of range should not cause
* buffer overflows (beware that this is not extensively tested).
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
@ -31,6 +86,20 @@
#include "mbedtls/bignum.h"
#endif
#define ciL ( sizeof(mbedtls_mpi_uint) ) /** chars in limb */
#define biL ( ciL << 3 ) /** bits in limb */
#define biH ( ciL << 2 ) /** half limb size */
/*
* Convert between bits/chars and number of limbs
* Divide first in order to avoid potential overflows
*/
#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
/* Get a specific byte, without range checks. */
#define GET_BYTE( X, i ) \
( ( (X)[(i) / ciL] >> ( ( (i) % ciL ) * 8 ) ) & 0xff )
/** Count leading zero bits in a given integer.
*
* \param a Integer to count leading zero bits.
@ -60,6 +129,58 @@ size_t mbedtls_mpi_core_bitlen( const mbedtls_mpi_uint *A, size_t A_limbs );
void mbedtls_mpi_core_bigendian_to_host( mbedtls_mpi_uint *A,
size_t A_limbs );
/**
* \brief Perform a safe conditional copy of an MPI which doesn't reveal
* whether assignment was done or not.
*
* \param[out] X The address of the destination MPI.
* This must be initialized. Must have enough limbs to
* store the full value of \p A.
* \param[in] A The address of the source MPI. This must be initialized.
* \param limbs The number of limbs of \p A.
* \param assign The condition deciding whether to perform the
* assignment or not. Must be either 0 or 1:
* * \c 1: Perform the assignment `X = A`.
* * \c 0: Keep the original value of \p X.
*
* \note This function avoids leaking any information about whether
* the assignment was done or not.
*
* \warning If \p assign is neither 0 nor 1, the result of this function
* is indeterminate, and the resulting value in \p X might be
* neither its original value nor the value in \p A.
*/
void mbedtls_mpi_core_cond_assign( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
size_t limbs,
unsigned char assign );
/**
* \brief Perform a safe conditional swap of two MPIs which doesn't reveal
* whether the swap was done or not.
*
* \param[in,out] X The address of the first MPI.
* This must be initialized.
* \param[in,out] Y The address of the second MPI.
* This must be initialized.
* \param limbs The number of limbs of \p X and \p Y.
* \param swap The condition deciding whether to perform
* the swap or not. Must be either 0 or 1:
* * \c 1: Swap the values of \p X and \p Y.
* * \c 0: Keep the original values of \p X and \p Y.
*
* \note This function avoids leaking any information about whether
* the swap was done or not.
*
* \warning If \p swap is neither 0 nor 1, the result of this function
* is indeterminate, and both \p X and \p Y might end up with
* values different to either of the original ones.
*/
void mbedtls_mpi_core_cond_swap( mbedtls_mpi_uint *X,
mbedtls_mpi_uint *Y,
size_t limbs,
unsigned char swap );
/** Import X from unsigned binary data, little-endian.
*
* The MPI needs to have enough limbs to store the full value (including any
@ -141,18 +262,276 @@ int mbedtls_mpi_core_write_be( const mbedtls_mpi_uint *A,
unsigned char *output,
size_t output_length );
#define ciL ( sizeof(mbedtls_mpi_uint) ) /* chars in limb */
#define biL ( ciL << 3 ) /* bits in limb */
#define biH ( ciL << 2 ) /* half limb size */
/*
* Convert between bits/chars and number of limbs
* Divide first in order to avoid potential overflows
/** \brief Shift an MPI right in place by a number of bits.
*
* Shifting by more bits than there are bit positions
* in \p X is valid and results in setting \p X to 0.
*
* This function's execution time depends on the value
* of \p count (and of course \p limbs).
*
* \param[in,out] X The number to shift.
* \param limbs The number of limbs of \p X. This must be at least 1.
* \param count The number of bits to shift by.
*/
#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) )
#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
/* Get a specific byte, without range checks. */
#define GET_BYTE( X, i ) \
( ( (X)[(i) / ciL] >> ( ( (i) % ciL ) * 8 ) ) & 0xff )
void mbedtls_mpi_core_shift_r( mbedtls_mpi_uint *X, size_t limbs,
size_t count );
/**
* \brief Add two fixed-size large unsigned integers, returning the carry.
*
* Calculates `A + B` where `A` and `B` have the same size.
*
* This function operates modulo `2^(biL*limbs)` and returns the carry
* (1 if there was a wraparound, and 0 otherwise).
*
* \p X may be aliased to \p A or \p B.
*
* \param[out] X The result of the addition.
* \param[in] A Little-endian presentation of the left operand.
* \param[in] B Little-endian presentation of the right operand.
* \param limbs Number of limbs of \p X, \p A and \p B.
*
* \return 1 if `A + B >= 2^(biL*limbs)`, 0 otherwise.
*/
mbedtls_mpi_uint mbedtls_mpi_core_add( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
size_t limbs );
/**
* \brief Conditional addition of two fixed-size large unsigned integers,
* returning the carry.
*
* Functionally equivalent to
*
* ```
* if( cond )
* X += A;
* return carry;
* ```
*
* This function operates modulo `2^(biL*limbs)`.
*
* \param[in,out] X The pointer to the (little-endian) array
* representing the bignum to accumulate onto.
* \param[in] A The pointer to the (little-endian) array
* representing the bignum to conditionally add
* to \p X. This may be aliased to \p X but may not
* overlap otherwise.
* \param limbs Number of limbs of \p X and \p A.
* \param cond Condition bit dictating whether addition should
* happen or not. This must be \c 0 or \c 1.
*
* \warning If \p cond is neither 0 nor 1, the result of this function
* is unspecified, and the resulting value in \p X might be
* neither its original value nor \p X + \p A.
*
* \return 1 if `X + cond * A >= 2^(biL*limbs)`, 0 otherwise.
*/
mbedtls_mpi_uint mbedtls_mpi_core_add_if( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
size_t limbs,
unsigned cond );
/**
* \brief Subtract two fixed-size large unsigned integers, returning the borrow.
*
* Calculate `A - B` where \p A and \p B have the same size.
* This function operates modulo `2^(biL*limbs)` and returns the carry
* (1 if there was a wraparound, i.e. if `A < B`, and 0 otherwise).
*
* \p X may be aliased to \p A or \p B, or even both, but may not overlap
* either otherwise.
*
* \param[out] X The result of the subtraction.
* \param[in] A Little-endian presentation of left operand.
* \param[in] B Little-endian presentation of right operand.
* \param limbs Number of limbs of \p X, \p A and \p B.
*
* \return 1 if `A < B`.
* 0 if `A >= B`.
*/
mbedtls_mpi_uint mbedtls_mpi_core_sub( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
size_t limbs );
/**
* \brief Perform a fixed-size multiply accumulate operation: X += b * A
*
* \p X may be aliased to \p A (when \p X_limbs == \p A_limbs), but may not
* otherwise overlap.
*
* This function operates modulo `2^(biL*X_limbs)`.
*
* \param[in,out] X The pointer to the (little-endian) array
* representing the bignum to accumulate onto.
* \param X_limbs The number of limbs of \p X. This must be
* at least \p A_limbs.
* \param[in] A The pointer to the (little-endian) array
* representing the bignum to multiply with.
* This may be aliased to \p X but may not overlap
* otherwise.
* \param A_limbs The number of limbs of \p A.
* \param b X scalar to multiply with.
*
* \return The carry at the end of the operation.
*/
mbedtls_mpi_uint mbedtls_mpi_core_mla( mbedtls_mpi_uint *X, size_t X_limbs,
const mbedtls_mpi_uint *A, size_t A_limbs,
mbedtls_mpi_uint b );
/**
* \brief Calculate initialisation value for fast Montgomery modular
* multiplication
*
* \param[in] N Little-endian presentation of the modulus. This must have
* at least one limb.
*
* \return The initialisation value for fast Montgomery modular multiplication
*/
mbedtls_mpi_uint mbedtls_mpi_core_montmul_init( const mbedtls_mpi_uint *N );
/**
* \brief Montgomery multiplication: X = A * B * R^-1 mod N (HAC 14.36)
*
* \p A and \p B must be in canonical form. That is, < \p N.
*
* \p X may be aliased to \p A or \p N, or even \p B (if \p AN_limbs ==
* \p B_limbs) but may not overlap any parameters otherwise.
*
* \p A and \p B may alias each other, if \p AN_limbs == \p B_limbs. They may
* not alias \p N (since they must be in canonical form, they cannot == \p N).
*
* \param[out] X The destination MPI, as a little-endian array of
* length \p AN_limbs.
* On successful completion, X contains the result of
* the multiplication `A * B * R^-1` mod N where
* `R = 2^(biL*AN_limbs)`.
* \param[in] A Little-endian presentation of first operand.
* Must have the same number of limbs as \p N.
* \param[in] B Little-endian presentation of second operand.
* \param[in] B_limbs The number of limbs in \p B.
* Must be <= \p AN_limbs.
* \param[in] N Little-endian presentation of the modulus.
* This must be odd, and have exactly the same number
* of limbs as \p A.
* It may alias \p X, but must not alias or otherwise
* overlap any of the other parameters.
* \param[in] AN_limbs The number of limbs in \p X, \p A and \p N.
* \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL.
* This can be calculated by `mbedtls_mpi_core_montmul_init()`.
* \param[in,out] T Temporary storage of size at least 2*AN_limbs+1 limbs.
* Its initial content is unused and
* its final content is indeterminate.
* It must not alias or otherwise overlap any of the
* other parameters.
*/
void mbedtls_mpi_core_montmul( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B, size_t B_limbs,
const mbedtls_mpi_uint *N, size_t AN_limbs,
mbedtls_mpi_uint mm, mbedtls_mpi_uint *T );
/**
* \brief Calculate the square of the Montgomery constant. (Needed
* for conversion and operations in Montgomery form.)
*
* \param[out] X A pointer to the result of the calculation of
* the square of the Montgomery constant:
* 2^{2*n*biL} mod N.
* \param[in] N Little-endian presentation of the modulus, which must be odd.
*
* \return 0 if successful.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if there is not enough space
* to store the value of Montgomery constant squared.
* \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p N modulus is zero.
* \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p N modulus is negative.
*/
int mbedtls_mpi_core_get_mont_r2_unsafe( mbedtls_mpi *X,
const mbedtls_mpi *N );
/**
* Copy an MPI from a table without leaking the index.
*
* \param dest The destination buffer. This must point to a writable
* buffer of at least \p limbs limbs.
* \param table The address of the table. This must point to a readable
* array of \p count elements of \p limbs limbs each.
* \param limbs The number of limbs in each table entry.
* \param count The number of entries in \p table.
* \param index The (secret) table index to look up. This must be in the
* range `0 .. count-1`.
*/
void mbedtls_mpi_core_ct_uint_table_lookup( mbedtls_mpi_uint *dest,
const mbedtls_mpi_uint *table,
size_t limbs,
size_t count,
size_t index );
/**
* \brief Fill an integer with a number of random bytes.
*
* \param X The destination MPI.
* \param X_limbs The number of limbs of \p X.
* \param bytes The number of random bytes to generate.
* \param f_rng The RNG function to use. This must not be \c NULL.
* \param p_rng The RNG parameter to be passed to \p f_rng. This may be
* \c NULL if \p f_rng doesn't need a context argument.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p X does not have
* enough room for \p bytes bytes.
* \return A negative error code on RNG failure.
*
* \note The bytes obtained from the RNG are interpreted
* as a big-endian representation of an MPI; this can
* be relevant in applications like deterministic ECDSA.
*/
int mbedtls_mpi_core_fill_random( mbedtls_mpi_uint *X, size_t X_limbs,
size_t bytes,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/* BEGIN MERGE SLOT 1 */
/* END MERGE SLOT 1 */
/* BEGIN MERGE SLOT 2 */
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
/* END MERGE SLOT 7 */
/* BEGIN MERGE SLOT 8 */
/* END MERGE SLOT 8 */
/* BEGIN MERGE SLOT 9 */
/* END MERGE SLOT 9 */
/* BEGIN MERGE SLOT 10 */
/* END MERGE SLOT 10 */
#endif /* MBEDTLS_BIGNUM_CORE_H */

View file

@ -1,50 +0,0 @@
/**
* Internal bignum functions
*
* Copyright The Mbed TLS Contributors
* 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.
*/
#ifndef MBEDTLS_BIGNUM_INTERNAL_H
#define MBEDTLS_BIGNUM_INTERNAL_H
#include "common.h"
#if defined(MBEDTLS_BIGNUM_C)
#include "mbedtls/bignum.h"
#endif
/** Perform a known-size multiply accumulate operation
*
* Add \p b * \p s to \p d.
*
* \param[in,out] d The pointer to the (little-endian) array
* representing the bignum to accumulate onto.
* \param d_len The number of limbs of \p d. This must be
* at least \p s_len.
* \param[in] s The pointer to the (little-endian) array
* representing the bignum to multiply with.
* This may be the same as \p d. Otherwise,
* it must be disjoint from \p d.
* \param s_len The number of limbs of \p s.
* \param b A scalar to multiply with.
*
* \return c The carry at the end of the operation.
*/
mbedtls_mpi_uint mbedtls_mpi_core_mla( mbedtls_mpi_uint *d, size_t d_len ,
const mbedtls_mpi_uint *s, size_t s_len,
mbedtls_mpi_uint b );
#endif /* MBEDTLS_BIGNUM_INTERNAL_H */

View file

@ -27,15 +27,7 @@
#include "mbedtls/error.h"
#include "mbedtls/bignum.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_printf printf
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#include "bignum_core.h"
#include "bignum_mod.h"
@ -85,7 +77,14 @@ void mbedtls_mpi_mod_modulus_free( mbedtls_mpi_mod_modulus *m )
switch( m->int_rep )
{
case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
mbedtls_free( m->rep.mont );
if (m->rep.mont.rr != NULL)
{
mbedtls_platform_zeroize( (mbedtls_mpi_uint *) m->rep.mont.rr,
m->limbs );
mbedtls_free( (mbedtls_mpi_uint *)m->rep.mont.rr );
m->rep.mont.rr = NULL;
}
m->rep.mont.mm = 0;
break;
case MBEDTLS_MPI_MOD_REP_OPT_RED:
mbedtls_free( m->rep.ored );
@ -101,6 +100,41 @@ void mbedtls_mpi_mod_modulus_free( mbedtls_mpi_mod_modulus *m )
m->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
}
static int set_mont_const_square( const mbedtls_mpi_uint **X,
const mbedtls_mpi_uint *A,
size_t limbs )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi N;
mbedtls_mpi RR;
*X = NULL;
mbedtls_mpi_init( &N );
mbedtls_mpi_init( &RR );
if ( A == NULL || limbs == 0 || limbs >= ( MBEDTLS_MPI_MAX_LIMBS / 2 ) - 2 )
goto cleanup;
if ( mbedtls_mpi_grow( &N, limbs ) )
goto cleanup;
memcpy( N.p, A, sizeof(mbedtls_mpi_uint) * limbs );
ret = mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N);
if ( ret == 0 )
{
*X = RR.p;
RR.p = NULL;
}
cleanup:
mbedtls_mpi_free(&N);
mbedtls_mpi_free(&RR);
ret = ( ret != 0 ) ? MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED : 0;
return( ret );
}
int mbedtls_mpi_mod_modulus_setup( mbedtls_mpi_mod_modulus *m,
const mbedtls_mpi_uint *p,
size_t p_limbs,
@ -128,7 +162,8 @@ int mbedtls_mpi_mod_modulus_setup( mbedtls_mpi_mod_modulus *m,
{
case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
m->int_rep = int_rep;
m->rep.mont = NULL;
m->rep.mont.mm = mbedtls_mpi_core_montmul_init( m->p );
ret = set_mont_const_square( &m->rep.mont.rr, m->p, m->limbs );
break;
case MBEDTLS_MPI_MOD_REP_OPT_RED:
m->int_rep = int_rep;
@ -149,4 +184,44 @@ exit:
return( ret );
}
/* BEGIN MERGE SLOT 1 */
/* END MERGE SLOT 1 */
/* BEGIN MERGE SLOT 2 */
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
/* END MERGE SLOT 7 */
/* BEGIN MERGE SLOT 8 */
/* END MERGE SLOT 8 */
/* BEGIN MERGE SLOT 9 */
/* END MERGE SLOT 9 */
/* BEGIN MERGE SLOT 10 */
/* END MERGE SLOT 10 */
#endif /* MBEDTLS_BIGNUM_C */

View file

@ -1,6 +1,10 @@
/**
* Modular bignum functions
*
* This module implements operations on integers modulo some fixed modulus.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
@ -49,7 +53,11 @@ typedef struct
size_t limbs;
} mbedtls_mpi_mod_residue;
typedef void *mbedtls_mpi_mont_struct;
typedef struct {
mbedtls_mpi_uint const *rr; /* The residue for 2^{2*n*biL} mod N */
mbedtls_mpi_uint mm; /* Montgomery const for -N^{-1} mod 2^{ciL} */
} mbedtls_mpi_mont_struct;
typedef void *mbedtls_mpi_opt_red_struct;
typedef struct {
@ -140,4 +148,44 @@ int mbedtls_mpi_mod_modulus_setup( mbedtls_mpi_mod_modulus *m,
*/
void mbedtls_mpi_mod_modulus_free( mbedtls_mpi_mod_modulus *m );
/* BEGIN MERGE SLOT 1 */
/* END MERGE SLOT 1 */
/* BEGIN MERGE SLOT 2 */
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
/* END MERGE SLOT 7 */
/* BEGIN MERGE SLOT 8 */
/* END MERGE SLOT 8 */
/* BEGIN MERGE SLOT 9 */
/* END MERGE SLOT 9 */
/* BEGIN MERGE SLOT 10 */
/* END MERGE SLOT 10 */
#endif /* MBEDTLS_BIGNUM_MOD_H */

View file

@ -26,21 +26,29 @@
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_printf printf
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#include "bignum_core.h"
#include "bignum_mod_raw.h"
#include "bignum_mod.h"
#include "constant_time_internal.h"
void mbedtls_mpi_mod_raw_cond_assign( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_mod_modulus *N,
unsigned char assign )
{
mbedtls_mpi_core_cond_assign( X, A, N->limbs, assign );
}
void mbedtls_mpi_mod_raw_cond_swap( mbedtls_mpi_uint *X,
mbedtls_mpi_uint *Y,
const mbedtls_mpi_mod_modulus *N,
unsigned char swap )
{
mbedtls_mpi_core_cond_swap( X, Y, N->limbs, swap );
}
int mbedtls_mpi_mod_raw_read( mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *m,
const unsigned char *input,
@ -94,4 +102,77 @@ int mbedtls_mpi_mod_raw_write( const mbedtls_mpi_uint *A,
}
}
/* BEGIN MERGE SLOT 1 */
/* END MERGE SLOT 1 */
/* BEGIN MERGE SLOT 2 */
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
int mbedtls_mpi_mod_raw_to_mont_rep( mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *m )
{
mbedtls_mpi_uint *T;
const size_t t_limbs = m->limbs * 2 + 1;
if( ( T = (mbedtls_mpi_uint *) mbedtls_calloc( t_limbs, ciL ) ) == NULL )
return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
mbedtls_mpi_core_montmul( X, X, m->rep.mont.rr, m->limbs, m->p, m->limbs,
m->rep.mont.mm, T );
mbedtls_platform_zeroize( T, t_limbs * ciL );
mbedtls_free( T );
return( 0 );
}
int mbedtls_mpi_mod_raw_from_mont_rep( mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *m )
{
const mbedtls_mpi_uint one = 1;
const size_t t_limbs = m->limbs * 2 + 1;
mbedtls_mpi_uint *T;
if( ( T = (mbedtls_mpi_uint *) mbedtls_calloc( t_limbs, ciL ) ) == NULL )
return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
mbedtls_mpi_core_montmul( X, X, &one, 1, m->p, m->limbs,
m->rep.mont.mm, T );
mbedtls_platform_zeroize( T, t_limbs * ciL );
mbedtls_free( T );
return( 0 );
}
/* END MERGE SLOT 7 */
/* BEGIN MERGE SLOT 8 */
/* END MERGE SLOT 8 */
/* BEGIN MERGE SLOT 9 */
/* END MERGE SLOT 9 */
/* BEGIN MERGE SLOT 10 */
/* END MERGE SLOT 10 */
#endif /* MBEDTLS_BIGNUM_C */

View file

@ -6,6 +6,14 @@
* modules should use the high-level modular bignum interface (bignum_mod.h)
* or the legacy bignum interface (bignum.h).
*
* This is a low-level interface to operations on integers modulo which
* has no protection against passing invalid arguments such as arrays of
* the wrong size. The functions in bignum_mod.h provide a higher-level
* interface that includes protections against accidental misuse, at the
* expense of code size and sometimes more cumbersome memory management.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
@ -33,6 +41,60 @@
#include "bignum_mod.h"
/**
* \brief Perform a safe conditional copy of an MPI which doesn't reveal
* whether the assignment was done or not.
*
* The size to copy is determined by \p N.
*
* \param[out] X The address of the destination MPI.
* This must be initialized. Must have enough limbs to
* store the full value of \p A.
* \param[in] A The address of the source MPI. This must be initialized.
* \param[in] N The address of the modulus related to \p X and \p A.
* \param assign The condition deciding whether to perform the
* assignment or not. Must be either 0 or 1:
* * \c 1: Perform the assignment `X = A`.
* * \c 0: Keep the original value of \p X.
*
* \note This function avoids leaking any information about whether
* the assignment was done or not.
*
* \warning If \p assign is neither 0 nor 1, the result of this function
* is indeterminate, and the resulting value in \p X might be
* neither its original value nor the value in \p A.
*/
void mbedtls_mpi_mod_raw_cond_assign( mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_mod_modulus *N,
unsigned char assign );
/**
* \brief Perform a safe conditional swap of two MPIs which doesn't reveal
* whether the swap was done or not.
*
* The size to swap is determined by \p N.
*
* \param[in,out] X The address of the first MPI. This must be initialized.
* \param[in,out] Y The address of the second MPI. This must be initialized.
* \param[in] N The address of the modulus related to \p X and \p Y.
* \param swap The condition deciding whether to perform
* the swap or not. Must be either 0 or 1:
* * \c 1: Swap the values of \p X and \p Y.
* * \c 0: Keep the original values of \p X and \p Y.
*
* \note This function avoids leaking any information about whether
* the swap was done or not.
*
* \warning If \p swap is neither 0 nor 1, the result of this function
* is indeterminate, and both \p X and \p Y might end up with
* values different to either of the original ones.
*/
void mbedtls_mpi_mod_raw_cond_swap( mbedtls_mpi_uint *X,
mbedtls_mpi_uint *Y,
const mbedtls_mpi_mod_modulus *N,
unsigned char swap );
/** Import X from unsigned binary data.
*
* The MPI needs to have enough limbs to store the full value (including any
@ -76,4 +138,66 @@ int mbedtls_mpi_mod_raw_write( const mbedtls_mpi_uint *A,
unsigned char *output,
size_t output_length );
/* BEGIN MERGE SLOT 1 */
/* END MERGE SLOT 1 */
/* BEGIN MERGE SLOT 2 */
/* END MERGE SLOT 2 */
/* BEGIN MERGE SLOT 3 */
/* END MERGE SLOT 3 */
/* BEGIN MERGE SLOT 4 */
/* END MERGE SLOT 4 */
/* BEGIN MERGE SLOT 5 */
/* END MERGE SLOT 5 */
/* BEGIN MERGE SLOT 6 */
/* END MERGE SLOT 6 */
/* BEGIN MERGE SLOT 7 */
/** Convert an MPI into Montgomery form.
*
* \param X The address of the MPI.
* Must have the same number of limbs as \p m.
* \param m The address of the modulus, which gives the size of
* the base `R` = 2^(biL*m->limbs).
*
* \return \c 0 if successful.
*/
int mbedtls_mpi_mod_raw_to_mont_rep( mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *m );
/** Convert an MPI back from Montgomery representation.
*
* \param X The address of the MPI.
* Must have the same number of limbs as \p m.
* \param m The address of the modulus, which gives the size of
* the base `R`= 2^(biL*m->limbs).
*
* \return \c 0 if successful.
*/
int mbedtls_mpi_mod_raw_from_mont_rep( mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *m );
/* END MERGE SLOT 7 */
/* BEGIN MERGE SLOT 8 */
/* END MERGE SLOT 8 */
/* BEGIN MERGE SLOT 9 */
/* END MERGE SLOT 9 */
/* BEGIN MERGE SLOT 10 */
/* END MERGE SLOT 10 */
#endif /* MBEDTLS_BIGNUM_MOD_RAW_H */

View file

@ -32,23 +32,10 @@
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_CAMELLIA_ALT)
/* Parameter validation macros */
#define CAMELLIA_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA )
#define CAMELLIA_VALIDATE( cond ) \
MBEDTLS_INTERNAL_VALIDATE( cond )
static const unsigned char SIGMA_CHARS[6][8] =
{
{ 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b },
@ -298,7 +285,6 @@ static void camellia_feistel( const uint32_t x[2], const uint32_t k[2],
void mbedtls_camellia_init( mbedtls_camellia_context *ctx )
{
CAMELLIA_VALIDATE( ctx != NULL );
memset( ctx, 0, sizeof( mbedtls_camellia_context ) );
}
@ -325,9 +311,6 @@ int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx,
uint32_t KC[16];
uint32_t TK[20];
CAMELLIA_VALIDATE_RET( ctx != NULL );
CAMELLIA_VALIDATE_RET( key != NULL );
RK = ctx->rk;
memset( t, 0, 64 );
@ -431,8 +414,6 @@ int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx,
mbedtls_camellia_context cty;
uint32_t *RK;
uint32_t *SK;
CAMELLIA_VALIDATE_RET( ctx != NULL );
CAMELLIA_VALIDATE_RET( key != NULL );
mbedtls_camellia_init( &cty );
@ -480,11 +461,8 @@ int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx,
{
int NR;
uint32_t *RK, X[4];
CAMELLIA_VALIDATE_RET( ctx != NULL );
CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT ||
mode == MBEDTLS_CAMELLIA_DECRYPT );
CAMELLIA_VALIDATE_RET( input != NULL );
CAMELLIA_VALIDATE_RET( output != NULL );
if( mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT )
return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA;
( (void) mode );
@ -550,12 +528,8 @@ int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx,
{
int i;
unsigned char temp[16];
CAMELLIA_VALIDATE_RET( ctx != NULL );
CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT ||
mode == MBEDTLS_CAMELLIA_DECRYPT );
CAMELLIA_VALIDATE_RET( iv != NULL );
CAMELLIA_VALIDATE_RET( length == 0 || input != NULL );
CAMELLIA_VALIDATE_RET( length == 0 || output != NULL );
if( mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT )
return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA;
if( length % 16 )
return( MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH );
@ -611,13 +585,8 @@ int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx,
{
int c;
size_t n;
CAMELLIA_VALIDATE_RET( ctx != NULL );
CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT ||
mode == MBEDTLS_CAMELLIA_DECRYPT );
CAMELLIA_VALIDATE_RET( iv != NULL );
CAMELLIA_VALIDATE_RET( iv_off != NULL );
CAMELLIA_VALIDATE_RET( length == 0 || input != NULL );
CAMELLIA_VALIDATE_RET( length == 0 || output != NULL );
if( mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT )
return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA;
n = *iv_off;
if( n >= 16 )
@ -670,12 +639,6 @@ int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx,
{
int c, i;
size_t n;
CAMELLIA_VALIDATE_RET( ctx != NULL );
CAMELLIA_VALIDATE_RET( nonce_counter != NULL );
CAMELLIA_VALIDATE_RET( stream_block != NULL );
CAMELLIA_VALIDATE_RET( nc_off != NULL );
CAMELLIA_VALIDATE_RET( length == 0 || input != NULL );
CAMELLIA_VALIDATE_RET( length == 0 || output != NULL );
n = *nc_off;
if( n >= 16 )

View file

@ -32,14 +32,7 @@
#include <stddef.h>
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_CHACHA20_ALT)
@ -48,12 +41,6 @@
#define inline __inline
#endif
/* Parameter validation macros */
#define CHACHA20_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
#define CHACHA20_VALIDATE( cond ) \
MBEDTLS_INTERNAL_VALIDATE( cond )
#define ROTL32( value, amount ) \
( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) )
@ -172,8 +159,6 @@ static void chacha20_block( const uint32_t initial_state[16],
void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
{
CHACHA20_VALIDATE( ctx != NULL );
mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) );
mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) );
@ -192,9 +177,6 @@ void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx )
int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
const unsigned char key[32] )
{
CHACHA20_VALIDATE_RET( ctx != NULL );
CHACHA20_VALIDATE_RET( key != NULL );
/* ChaCha20 constants - the string "expand 32-byte k" */
ctx->state[0] = 0x61707865;
ctx->state[1] = 0x3320646e;
@ -218,9 +200,6 @@ int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
const unsigned char nonce[12],
uint32_t counter )
{
CHACHA20_VALIDATE_RET( ctx != NULL );
CHACHA20_VALIDATE_RET( nonce != NULL );
/* Counter */
ctx->state[12] = counter;
@ -245,10 +224,6 @@ int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
size_t offset = 0U;
size_t i;
CHACHA20_VALIDATE_RET( ctx != NULL );
CHACHA20_VALIDATE_RET( size == 0 || input != NULL );
CHACHA20_VALIDATE_RET( size == 0 || output != NULL );
/* Use leftover keystream bytes, if available */
while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES )
{
@ -312,11 +287,6 @@ int mbedtls_chacha20_crypt( const unsigned char key[32],
mbedtls_chacha20_context ctx;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
CHACHA20_VALIDATE_RET( key != NULL );
CHACHA20_VALIDATE_RET( nonce != NULL );
CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL );
CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL );
mbedtls_chacha20_init( &ctx );
ret = mbedtls_chacha20_setkey( &ctx, key );

View file

@ -28,23 +28,10 @@
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_CHACHAPOLY_ALT)
/* Parameter validation macros */
#define CHACHAPOLY_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA )
#define CHACHAPOLY_VALIDATE( cond ) \
MBEDTLS_INTERNAL_VALIDATE( cond )
#define CHACHAPOLY_STATE_INIT ( 0 )
#define CHACHAPOLY_STATE_AAD ( 1 )
#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */
@ -91,8 +78,6 @@ static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
{
CHACHAPOLY_VALIDATE( ctx != NULL );
mbedtls_chacha20_init( &ctx->chacha20_ctx );
mbedtls_poly1305_init( &ctx->poly1305_ctx );
ctx->aad_len = 0U;
@ -118,8 +103,6 @@ int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
const unsigned char key[32] )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( key != NULL );
ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
@ -132,8 +115,6 @@ int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char poly1305_key[64];
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( nonce != NULL );
/* Set counter = 0, will be update to 1 when generating Poly1305 key */
ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
@ -170,9 +151,6 @@ int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
const unsigned char *aad,
size_t aad_len )
{
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
if( ctx->state != CHACHAPOLY_STATE_AAD )
return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
@ -187,9 +165,6 @@ int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
unsigned char *output )
{
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 );
if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
@ -237,8 +212,6 @@ int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char len_block[16];
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( mac != NULL );
if( ctx->state == CHACHAPOLY_STATE_INIT )
{
@ -314,13 +287,6 @@ int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx,
unsigned char *output,
unsigned char tag[16] )
{
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( nonce != NULL );
CHACHAPOLY_VALIDATE_RET( tag != NULL );
CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
length, nonce, aad, aad_len,
input, output, tag ) );
@ -339,12 +305,6 @@ int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
unsigned char check_tag[16];
size_t i;
int diff;
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( nonce != NULL );
CHACHAPOLY_VALIDATE_RET( tag != NULL );
CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
if( ( ret = chachapoly_crypt_and_tag( ctx,
MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,

View file

@ -93,4 +93,9 @@
#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites"
#endif
#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) && \
!defined(PSA_WANT_ALG_SHA_256)
#error "PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS defined, but not all prerequisites"
#endif
#endif /* MBEDTLS_CHECK_CRYPTO_CONFIG_H */

View file

@ -63,17 +63,7 @@
#include "mbedtls/nist_kw.h"
#endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#define CIPHER_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA )
#define CIPHER_VALIDATE( cond ) \
MBEDTLS_INTERNAL_VALIDATE( cond )
static int supported_init = 0;
@ -143,7 +133,6 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(
void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx )
{
CIPHER_VALIDATE( ctx != NULL );
memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
}
@ -193,7 +182,6 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx )
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 )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
@ -257,10 +245,8 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx,
int key_bitlen,
const mbedtls_operation_t operation )
{
CIPHER_VALIDATE_RET( ctx != NULL );
CIPHER_VALIDATE_RET( key != NULL );
CIPHER_VALIDATE_RET( operation == MBEDTLS_ENCRYPT ||
operation == MBEDTLS_DECRYPT );
if( operation != MBEDTLS_ENCRYPT && operation != MBEDTLS_DECRYPT )
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
@ -356,8 +342,6 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
{
size_t actual_iv_size;
CIPHER_VALIDATE_RET( ctx != NULL );
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)
@ -453,7 +437,6 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx )
{
CIPHER_VALIDATE_RET( ctx != NULL );
if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
@ -475,8 +458,6 @@ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx )
int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
const unsigned char *ad, size_t ad_len )
{
CIPHER_VALIDATE_RET( ctx != NULL );
CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
@ -529,10 +510,6 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t block_size;
CIPHER_VALIDATE_RET( ctx != NULL );
CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
CIPHER_VALIDATE_RET( output != NULL );
CIPHER_VALIDATE_RET( olen != NULL );
if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
@ -952,9 +929,6 @@ static int get_no_padding( unsigned char *input, size_t input_len,
int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
unsigned char *output, size_t *olen )
{
CIPHER_VALIDATE_RET( ctx != NULL );
CIPHER_VALIDATE_RET( output != NULL );
CIPHER_VALIDATE_RET( olen != NULL );
if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
@ -1054,8 +1028,6 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx,
mbedtls_cipher_padding_t mode )
{
CIPHER_VALIDATE_RET( ctx != NULL );
if( NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
@ -1117,8 +1089,6 @@ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx,
int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
unsigned char *tag, size_t tag_len )
{
CIPHER_VALIDATE_RET( ctx != NULL );
CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
@ -1168,8 +1138,6 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
unsigned char check_tag[16];
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
CIPHER_VALIDATE_RET( ctx != NULL );
CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
if( ctx->cipher_info == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
@ -1261,12 +1229,6 @@ int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t finish_olen;
CIPHER_VALIDATE_RET( ctx != NULL );
CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
CIPHER_VALIDATE_RET( output != NULL );
CIPHER_VALIDATE_RET( olen != NULL );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( ctx->psa_enabled == 1 )
{
@ -1542,13 +1504,6 @@ int mbedtls_cipher_auth_encrypt_ext( mbedtls_cipher_context_t *ctx,
unsigned char *output, size_t output_len,
size_t *olen, size_t tag_len )
{
CIPHER_VALIDATE_RET( ctx != NULL );
CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
CIPHER_VALIDATE_RET( output != NULL );
CIPHER_VALIDATE_RET( olen != NULL );
#if defined(MBEDTLS_NIST_KW_C)
if(
#if defined(MBEDTLS_USE_PSA_CRYPTO)
@ -1598,13 +1553,6 @@ int mbedtls_cipher_auth_decrypt_ext( mbedtls_cipher_context_t *ctx,
unsigned char *output, size_t output_len,
size_t *olen, size_t tag_len )
{
CIPHER_VALIDATE_RET( ctx != NULL );
CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
CIPHER_VALIDATE_RET( output_len == 0 || output != NULL );
CIPHER_VALIDATE_RET( olen != NULL );
#if defined(MBEDTLS_NIST_KW_C)
if(
#if defined(MBEDTLS_USE_PSA_CRYPTO)

View file

@ -68,13 +68,7 @@
#include <string.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_GCM_C)
/* shared by all GCM ciphers */

View file

@ -30,6 +30,7 @@
#if defined(MBEDTLS_BIGNUM_C)
#include "mbedtls/bignum.h"
#include "bignum_core.h"
#endif
#if defined(MBEDTLS_SSL_TLS_C)
@ -81,7 +82,7 @@ unsigned mbedtls_ct_uint_mask( unsigned value )
#endif
}
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
size_t mbedtls_ct_size_mask( size_t value )
{
@ -97,7 +98,7 @@ size_t mbedtls_ct_size_mask( size_t value )
#endif
}
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
#if defined(MBEDTLS_BIGNUM_C)
@ -404,7 +405,7 @@ static void mbedtls_ct_mem_move_to_left( void *start,
#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
void mbedtls_ct_memcpy_if_eq( unsigned char *dest,
const unsigned char *src,
@ -654,7 +655,7 @@ cleanup:
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
#if defined(MBEDTLS_BIGNUM_C)
@ -678,21 +679,19 @@ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X,
unsigned char assign )
{
int ret = 0;
size_t i;
mbedtls_mpi_uint limb_mask;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( Y != NULL );
/* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
limb_mask = mbedtls_ct_mpi_uint_mask( assign );;
mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask( assign );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
X->s = mbedtls_ct_cond_select_sign( assign, Y->s, X->s );
mbedtls_ct_mpi_uint_cond_assign( Y->n, X->p, Y->p, assign );
mbedtls_mpi_core_cond_assign( X->p, Y->p, Y->n, assign );
for( i = Y->n; i < X->n; i++ )
for( size_t i = Y->n; i < X->n; i++ )
X->p[i] &= ~limb_mask;
cleanup:
@ -709,19 +708,14 @@ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X,
mbedtls_mpi *Y,
unsigned char swap )
{
int ret, s;
size_t i;
mbedtls_mpi_uint limb_mask;
mbedtls_mpi_uint tmp;
int ret = 0;
int s;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( Y != NULL );
if( X == Y )
return( 0 );
/* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
limb_mask = mbedtls_ct_mpi_uint_mask( swap );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
@ -729,13 +723,7 @@ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X,
X->s = mbedtls_ct_cond_select_sign( swap, Y->s, X->s );
Y->s = mbedtls_ct_cond_select_sign( swap, s, Y->s );
for( i = 0; i < X->n; i++ )
{
tmp = X->p[i];
X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask );
}
mbedtls_mpi_core_cond_swap( X->p, Y->p, X->n, swap );
cleanup:
return( ret );

View file

@ -46,7 +46,7 @@
*/
unsigned mbedtls_ct_uint_mask( unsigned value );
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
/** Turn a value into a mask:
* - if \p value == 0, return the all-bits 0 mask, aka 0
@ -61,7 +61,7 @@ unsigned mbedtls_ct_uint_mask( unsigned value );
*/
size_t mbedtls_ct_size_mask( size_t value );
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
#if defined(MBEDTLS_BIGNUM_C)
@ -138,6 +138,7 @@ unsigned mbedtls_ct_mpi_uint_lt( const mbedtls_mpi_uint x,
* \param B The right-hand MPI. This must point to an array of limbs
* with the same allocated length as \p A.
* \param limbs The number of limbs in \p A and \p B.
* This must not be 0.
*
* \return The result of the comparison:
* \c 1 if \p A is less than \p B.
@ -213,7 +214,7 @@ signed char mbedtls_ct_base64_dec_value( unsigned char c );
#endif /* MBEDTLS_BASE64_C */
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
/** Conditional memcpy without branches.
*
@ -321,7 +322,7 @@ int mbedtls_ct_hmac( mbedtls_md_context_t *ctx,
unsigned char *output );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)

View file

@ -36,14 +36,7 @@
#include <stdio.h>
#endif
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
/*
* CTR_DRBG context initialization

View file

@ -21,16 +21,7 @@
#if defined(MBEDTLS_DEBUG_C)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#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"

View file

@ -33,14 +33,7 @@
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_DES_ALT)

View file

@ -43,23 +43,10 @@
#include "mbedtls/asn1.h"
#endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#include <stdio.h>
#define mbedtls_printf printf
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#if !defined(MBEDTLS_DHM_ALT)
#define DHM_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA )
#define DHM_VALIDATE( cond ) \
MBEDTLS_INTERNAL_VALIDATE( cond )
/*
* helper to validate the mbedtls_mpi size and import it
*/
@ -120,7 +107,6 @@ cleanup:
void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
{
DHM_VALIDATE( ctx != NULL );
memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
}
@ -173,9 +159,6 @@ int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
const unsigned char *end )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( p != NULL && *p != NULL );
DHM_VALIDATE_RET( end != NULL );
if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
@ -252,10 +235,6 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
int ret;
size_t n1, n2, n3;
unsigned char *p;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( output != NULL );
DHM_VALIDATE_RET( olen != NULL );
DHM_VALIDATE_RET( f_rng != NULL );
ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
if( ret != 0 )
@ -300,9 +279,6 @@ int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
const mbedtls_mpi *G )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( P != NULL );
DHM_VALIDATE_RET( G != NULL );
if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
@ -320,8 +296,6 @@ int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
const unsigned char *input, size_t ilen )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( input != NULL );
if( ilen < 1 || ilen > mbedtls_dhm_get_len( ctx ) )
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
@ -341,9 +315,6 @@ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
void *p_rng )
{
int ret;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( output != NULL );
DHM_VALIDATE_RET( f_rng != NULL );
if( olen < 1 || olen > mbedtls_dhm_get_len( ctx ) )
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
@ -440,9 +411,6 @@ int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi GYb;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( output != NULL );
DHM_VALIDATE_RET( olen != NULL );
if( f_rng == NULL )
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
@ -518,9 +486,6 @@ int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
mbedtls_pem_context pem;
#endif /* MBEDTLS_PEM_PARSE_C */
DHM_VALIDATE_RET( dhm != NULL );
DHM_VALIDATE_RET( dhmin != NULL );
#if defined(MBEDTLS_PEM_PARSE_C)
mbedtls_pem_init( &pem );
@ -667,8 +632,6 @@ int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
unsigned char *buf;
DHM_VALIDATE_RET( dhm != NULL );
DHM_VALIDATE_RET( path != NULL );
if( ( ret = load_file( path, &buf, &n ) ) != 0 )
return( ret );

View file

@ -71,10 +71,12 @@ static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* If multiplication is in progress, we already generated a privkey */
int restarting = 0;
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx == NULL || rs_ctx->rsm == NULL )
restarting = ( rs_ctx != NULL && rs_ctx->rsm != NULL );
#endif
/* If multiplication is in progress, we already generated a privkey */
if( !restarting )
MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,

View file

@ -36,13 +36,7 @@
#include "mbedtls/hmac_drbg.h"
#endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"

View file

@ -236,7 +236,7 @@ static int ecjpake_hash( const mbedtls_md_type_t md_type,
unsigned char *p = buf;
const unsigned char *end = buf + sizeof( buf );
const size_t id_len = strlen( id );
unsigned char hash[MBEDTLS_MD_MAX_SIZE];
unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
/* Write things to temporary buffer */
MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) );
@ -760,22 +760,14 @@ cleanup:
/*
* Derive PMS (7.4.2.7 / 7.4.2.8)
*/
int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
unsigned char *buf, size_t len, size_t *olen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
static int mbedtls_ecjpake_derive_k( mbedtls_ecjpake_context *ctx,
mbedtls_ecp_point *K,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point K;
mbedtls_mpi m_xm2_s, one;
unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
size_t x_bytes;
*olen = mbedtls_hash_info_get_size( ctx->md_type );
if( len < *olen )
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
mbedtls_ecp_point_init( &K );
mbedtls_mpi_init( &m_xm2_s );
mbedtls_mpi_init( &one );
@ -788,12 +780,39 @@ int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
*/
MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s,
&ctx->grp.N, f_rng, p_rng ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K,
MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, K,
&one, &ctx->Xp,
&m_xm2_s, &ctx->Xp2 ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K,
MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, K, &ctx->xm2, K,
f_rng, p_rng ) );
cleanup:
mbedtls_mpi_free( &m_xm2_s );
mbedtls_mpi_free( &one );
return( ret );
}
int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
unsigned char *buf, size_t len, size_t *olen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point K;
unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
size_t x_bytes;
*olen = mbedtls_hash_info_get_size( ctx->md_type );
if( len < *olen )
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
mbedtls_ecp_point_init( &K );
ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
if( ret )
goto cleanup;
/* PMS = SHA-256( K.X ) */
x_bytes = ( ctx->grp.pbits + 7 ) / 8;
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) );
@ -802,8 +821,31 @@ int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
cleanup:
mbedtls_ecp_point_free( &K );
mbedtls_mpi_free( &m_xm2_s );
mbedtls_mpi_free( &one );
return( ret );
}
int mbedtls_ecjpake_write_shared_key( mbedtls_ecjpake_context *ctx,
unsigned char *buf, size_t len, size_t *olen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point K;
mbedtls_ecp_point_init( &K );
ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
if( ret )
goto cleanup;
ret = mbedtls_ecp_point_write_binary( &ctx->grp, &K, ctx->point_format,
olen, buf, len );
if( ret != 0 )
goto cleanup;
cleanup:
mbedtls_ecp_point_free( &K );
return( ret );
}
@ -815,12 +857,7 @@ cleanup:
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif
#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
!defined(MBEDTLS_SHA256_C)
@ -958,6 +995,15 @@ static const unsigned char ecjpake_test_cli_two[] = {
0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
};
static const unsigned char ecjpake_test_shared_key[] = {
0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80,
0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79,
0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1,
0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0,
0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12,
0x17, 0xc3, 0xde, 0x27, 0xb4,
};
static const unsigned char ecjpake_test_pms[] = {
0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
@ -1144,6 +1190,13 @@ int mbedtls_ecjpake_self_test( int verbose )
TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
/* Server derives K as unsigned binary data */
TEST_ASSERT( mbedtls_ecjpake_write_shared_key( &srv,
buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
TEST_ASSERT( len == sizeof( ecjpake_test_shared_key ) );
TEST_ASSERT( memcmp( buf, ecjpake_test_shared_key, len ) == 0 );
memset( buf, 0, len ); /* Avoid interferences with next step */
/* Client derives PMS */
@ -1153,6 +1206,13 @@ int mbedtls_ecjpake_self_test( int verbose )
TEST_ASSERT( len == sizeof( ecjpake_test_pms ) );
TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 );
/* Client derives K as unsigned binary data */
TEST_ASSERT( mbedtls_ecjpake_write_shared_key( &cli,
buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 );
TEST_ASSERT( len == sizeof( ecjpake_test_shared_key ) );
TEST_ASSERT( memcmp( buf, ecjpake_test_shared_key, len ) == 0 );
if( verbose != 0 )
mbedtls_printf( "passed\n" );
#endif /* ! MBEDTLS_ECJPAKE_ALT */

View file

@ -84,15 +84,7 @@
#if !defined(MBEDTLS_ECP_ALT)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#include <stdio.h>
#define mbedtls_printf printf
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#include "ecp_internal_alt.h"
@ -2287,12 +2279,14 @@ cleanup:
mbedtls_free( T );
}
/* don't free R while in progress in case R == P */
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
#endif
/* prevent caller from using invalid value */
if( ret != 0 )
int should_free_R = ( ret != 0 );
#if defined(MBEDTLS_ECP_RESTARTABLE)
/* don't free R while in progress in case R == P */
if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
should_free_R = 0;
#endif
if( should_free_R )
mbedtls_ecp_point_free( R );
ECP_RS_LEAVE( rsm );
@ -2467,7 +2461,7 @@ static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
/* Loop invariant: R = result so far, RP = R + P */
i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
i = grp->nbits + 1; /* one past the (zero-based) required msb for private keys */
while( i-- > 0 )
{
b = mbedtls_mpi_get_bit( m, i );
@ -2537,10 +2531,12 @@ static int ecp_mul_restartable_internal( mbedtls_ecp_group *grp, mbedtls_ecp_poi
MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
#endif /* MBEDTLS_ECP_INTERNAL_ALT */
int restarting = 0;
#if defined(MBEDTLS_ECP_RESTARTABLE)
/* skip argument check when restarting */
if( rs_ctx == NULL || rs_ctx->rsm == NULL )
restarting = ( rs_ctx != NULL && rs_ctx->rsm != NULL );
#endif
/* skip argument check when restarting */
if( !restarting )
{
/* check_privkey is free */
MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK );
@ -2666,14 +2662,17 @@ static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
if( mbedtls_mpi_cmp_int( m, 0 ) == 0 )
{
MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_set_zero( R ) );
}
else if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
{
MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
}
else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
{
MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
MPI_ECP_NEG( &R->Y );
}

View file

@ -26,7 +26,7 @@
#include "mbedtls/error.h"
#include "bn_mul.h"
#include "bignum_internal.h"
#include "bignum_core.h"
#include "ecp_invasive.h"
#include <string.h>
@ -4969,9 +4969,6 @@ static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry )
#define ADD( j ) add32( &cur, A( j ), &c );
#define SUB( j ) sub32( &cur, A( j ), &c );
#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
#define biL (ciL << 3) /* bits in limb */
/*
* Helpers for the main 'loop'
*/

View file

@ -32,18 +32,9 @@
#include <stdio.h>
#endif
#if defined(MBEDTLS_ENTROPY_NV_SEED)
#include "mbedtls/platform.h"
#endif
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */

View file

@ -35,9 +35,7 @@
#if defined(MBEDTLS_TIMING_C)
#include "mbedtls/timing.h"
#endif
#if defined(MBEDTLS_ENTROPY_NV_SEED) || !defined(HAVE_SYSCTL_ARND)
#include "mbedtls/platform.h"
#endif
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)

View file

@ -32,6 +32,7 @@
#if defined(MBEDTLS_GCM_C)
#include "mbedtls/gcm.h"
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
@ -41,29 +42,13 @@
#include "aesni.h"
#endif
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
#include "mbedtls/aes.h"
#include "mbedtls/platform.h"
#if !defined(MBEDTLS_PLATFORM_C)
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#if !defined(MBEDTLS_GCM_ALT)
/* Parameter validation macros */
#define GCM_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_GCM_BAD_INPUT )
#define GCM_VALIDATE( cond ) \
MBEDTLS_INTERNAL_VALIDATE( cond )
/*
* Initialize a context
*/
void mbedtls_gcm_init( mbedtls_gcm_context *ctx )
{
GCM_VALIDATE( ctx != NULL );
memset( ctx, 0, sizeof( mbedtls_gcm_context ) );
}
@ -143,9 +128,8 @@ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
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 );
if( keybits != 128 && keybits != 192 && keybits != 256 )
return MBEDTLS_ERR_GCM_BAD_INPUT;
cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
MBEDTLS_MODE_ECB );
@ -256,9 +240,6 @@ int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
size_t use_len, olen = 0;
uint64_t iv_bits;
GCM_VALIDATE_RET( ctx != NULL );
GCM_VALIDATE_RET( iv != NULL );
/* IV is limited to 2^64 bits, so 2^61 bytes */
/* IV is not allowed to be zero length */
if( iv_len == 0 || (uint64_t) iv_len >> 61 != 0 )
@ -334,8 +315,6 @@ int mbedtls_gcm_update_ad( mbedtls_gcm_context *ctx,
const unsigned char *p;
size_t use_len, i, offset;
GCM_VALIDATE_RET( add_len == 0 || add != NULL );
/* IV is limited to 2^64 bits, so 2^61 bytes */
if( (uint64_t) add_len >> 61 != 0 )
return( MBEDTLS_ERR_GCM_BAD_INPUT );
@ -434,7 +413,6 @@ int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
if( output_size < input_length )
return( MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL );
GCM_VALIDATE_RET( output_length != NULL );
*output_length = input_length;
/* Exit early if input_length==0 so that we don't do any pointer arithmetic
@ -444,10 +422,6 @@ int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
if( input_length == 0 )
return( 0 );
GCM_VALIDATE_RET( ctx != NULL );
GCM_VALIDATE_RET( input != NULL );
GCM_VALIDATE_RET( output != NULL );
if( output > input && (size_t) ( output - input ) < input_length )
return( MBEDTLS_ERR_GCM_BAD_INPUT );
@ -519,9 +493,6 @@ int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
uint64_t orig_len;
uint64_t orig_add_len;
GCM_VALIDATE_RET( ctx != NULL );
GCM_VALIDATE_RET( tag != NULL );
/* We never pass any output in finish(). The output parameter exists only
* for the sake of alternative implementations. */
(void) output;
@ -580,13 +551,6 @@ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t olen;
GCM_VALIDATE_RET( ctx != NULL );
GCM_VALIDATE_RET( iv != NULL );
GCM_VALIDATE_RET( add_len == 0 || add != NULL );
GCM_VALIDATE_RET( length == 0 || input != NULL );
GCM_VALIDATE_RET( length == 0 || output != NULL );
GCM_VALIDATE_RET( tag != NULL );
if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len ) ) != 0 )
return( ret );
@ -619,13 +583,6 @@ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
size_t i;
int diff;
GCM_VALIDATE_RET( ctx != NULL );
GCM_VALIDATE_RET( iv != NULL );
GCM_VALIDATE_RET( add_len == 0 || add != NULL );
GCM_VALIDATE_RET( tag != NULL );
GCM_VALIDATE_RET( length == 0 || input != NULL );
GCM_VALIDATE_RET( length == 0 || output != NULL );
if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length,
iv, iv_len, add, add_len,
input, output, tag_len, check_tag ) ) != 0 )

View file

@ -21,7 +21,7 @@
*/
#include "hash_info.h"
#include "legacy_or_psa.h"
#include "mbedtls/legacy_or_psa.h"
#include "mbedtls/error.h"
typedef struct

View file

@ -35,6 +35,20 @@
#include "mbedtls/md.h"
#include "psa/crypto.h"
/** \def MBEDTLS_HASH_MAX_SIZE
*
* Maximum size of a hash based on configuration.
*/
#if defined(MBEDTLS_MD_C) && ( \
!defined(MBEDTLS_PSA_CRYPTO_C) || \
MBEDTLS_MD_MAX_SIZE >= PSA_HASH_MAX_SIZE )
#define MBEDTLS_HASH_MAX_SIZE MBEDTLS_MD_MAX_SIZE
#elif defined(MBEDTLS_PSA_CRYPTO_C) && ( \
!defined(MBEDTLS_MD_C) || \
PSA_HASH_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE )
#define MBEDTLS_HASH_MAX_SIZE PSA_HASH_MAX_SIZE
#endif
/** Get the output length of the given hash type from its MD type.
*
* \note To get the output length from the PSA alg, use \c PSA_HASH_LENGTH().

View file

@ -37,14 +37,7 @@
#include <stdio.h>
#endif
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_PLATFORM_C */
/*
* HMAC_DRBG context initialization

826
library/lmots.c Normal file
View file

@ -0,0 +1,826 @@
/*
* The LM-OTS one-time public-key signature scheme
*
* Copyright The Mbed TLS Contributors
* 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.
*/
/*
* The following sources were referenced in the design of this implementation
* of the LM-OTS algorithm:
*
* [1] IETF RFC8554
* D. McGrew, M. Curcio, S.Fluhrer
* https://datatracker.ietf.org/doc/html/rfc8554
*
* [2] NIST Special Publication 800-208
* David A. Cooper et. al.
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf
*/
#include "common.h"
#if defined(MBEDTLS_LMS_C)
#include <string.h>
#include "lmots.h"
#include "mbedtls/lms.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include "psa/crypto.h"
#define PUBLIC_KEY_TYPE_OFFSET (0)
#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \
MBEDTLS_LMOTS_TYPE_LEN)
#define PUBLIC_KEY_Q_LEAF_ID_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \
MBEDTLS_LMOTS_I_KEY_ID_LEN)
#define PUBLIC_KEY_KEY_HASH_OFFSET (PUBLIC_KEY_Q_LEAF_ID_OFFSET + \
MBEDTLS_LMOTS_Q_LEAF_ID_LEN)
/* We only support parameter sets that use 8-bit digits, as it does not require
* translation logic between digits and bytes */
#define W_WINTERNITZ_PARAMETER (8u)
#define CHECKSUM_LEN (2)
#define I_DIGIT_IDX_LEN (2)
#define J_HASH_IDX_LEN (1)
#define D_CONST_LEN (2)
#define DIGIT_MAX_VALUE ((1u << W_WINTERNITZ_PARAMETER) - 1u)
#define D_CONST_LEN (2)
static const unsigned char D_PUBLIC_CONSTANT_BYTES[D_CONST_LEN] = {0x80, 0x80};
static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = {0x81, 0x81};
#if defined(MBEDTLS_TEST_HOOKS)
int( *mbedtls_lmots_sign_private_key_invalidated_hook )( unsigned char * ) = NULL;
#endif /* defined(MBEDTLS_TEST_HOOKS) */
void mbedtls_lms_unsigned_int_to_network_bytes( unsigned int val, size_t len,
unsigned char *bytes )
{
size_t idx;
for ( idx = 0; idx < len; idx++ )
{
bytes[idx] = ( val >> ( ( len - 1 - idx ) * 8 ) ) & 0xFF;
}
}
unsigned int mbedtls_lms_network_bytes_to_unsigned_int( size_t len,
const unsigned char *bytes )
{
size_t idx;
unsigned int val = 0;
for ( idx = 0; idx < len; idx++ )
{
val |= ( ( unsigned int )bytes[idx] ) << (8 * ( len - 1 - idx ) );
}
return ( val );
}
/* Calculate the checksum digits that are appended to the end of the LMOTS digit
* string. See NIST SP800-208 section 3.1 or RFC8554 Algorithm 2 for details of
* the checksum algorithm.
*
* params The LMOTS parameter set, I and q values which
* describe the key being used.
*
* digest The digit string to create the digest from. As
* this does not contain a checksum, it is the same
* size as a hash output.
*/
static unsigned short lmots_checksum_calculate( const mbedtls_lmots_parameters_t *params,
const unsigned char* digest )
{
size_t idx;
unsigned sum = 0;
for ( idx = 0; idx < MBEDTLS_LMOTS_N_HASH_LEN(params->type); idx++ )
{
sum += DIGIT_MAX_VALUE - digest[idx];
}
return ( sum );
}
/* Create the string of digest digits (in the base determined by the Winternitz
* parameter with the checksum appended to the end (Q || cksm(Q)). See NIST
* SP800-208 section 3.1 or RFC8554 Algorithm 3 step 5 (also used in Algorithm
* 4b step 3) for details.
*
* params The LMOTS parameter set, I and q values which
* describe the key being used.
*
* msg The message that will be hashed to create the
* digest.
*
* msg_size The size of the message.
*
* C_random_value The random value that will be combined with the
* message digest. This is always the same size as a
* hash output for whichever hash algorithm is
* determined by the parameter set.
*
* output An output containing the digit string (+
* checksum) of length P digits (in the case of
* MBEDTLS_LMOTS_SHA256_N32_W8, this means it is of
* size P bytes).
*/
static int create_digit_array_with_checksum( const mbedtls_lmots_parameters_t *params,
const unsigned char *msg,
size_t msg_len,
const unsigned char *C_random_value,
unsigned char *out )
{
psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t output_hash_len;
unsigned short checksum;
status = psa_hash_setup( &op, PSA_ALG_SHA_256 );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, params->I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, params->q_leaf_identifier,
MBEDTLS_LMOTS_Q_LEAF_ID_LEN );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, D_MESSAGE_CONSTANT_BYTES, D_CONST_LEN );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, C_random_value,
MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(params->type) );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, msg, msg_len );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_finish( &op, out,
MBEDTLS_LMOTS_N_HASH_LEN(params->type),
&output_hash_len );
if( status != PSA_SUCCESS )
goto exit;
checksum = lmots_checksum_calculate( params, out );
mbedtls_lms_unsigned_int_to_network_bytes( checksum, CHECKSUM_LEN,
out + MBEDTLS_LMOTS_N_HASH_LEN(params->type) );
exit:
psa_hash_abort( &op );
return( mbedtls_lms_error_from_psa( status ) );
}
/* Hash each element of the string of digits (+ checksum), producing a hash
* output for each element. This is used in several places (by varying the
* hash_idx_min/max_values) in order to calculate a public key from a private
* key (RFC8554 Algorithm 1 step 4), in order to sign a message (RFC8554
* Algorithm 3 step 5), and to calculate a public key candidate from a
* signature and message (RFC8554 Algorithm 4b step 3).
*
* params The LMOTS parameter set, I and q values which
* describe the key being used.
*
* x_digit_array The array of digits (of size P, 34 in the case of
* MBEDTLS_LMOTS_SHA256_N32_W8).
*
* hash_idx_min_values An array of the starting values of the j iterator
* for each of the members of the digit array. If
* this value in NULL, then all iterators will start
* at 0.
*
* hash_idx_max_values An array of the upper bound values of the j
* iterator for each of the members of the digit
* array. If this value in NULL, then iterator is
* bounded to be less than 2^w - 1 (255 in the case
* of MBEDTLS_LMOTS_SHA256_N32_W8)
*
* output An array containing a hash output for each member
* of the digit string P. In the case of
* MBEDTLS_LMOTS_SHA256_N32_W8, this is of size 32 *
* 34.
*/
static int hash_digit_array( const mbedtls_lmots_parameters_t *params,
const unsigned char *x_digit_array,
const unsigned char *hash_idx_min_values,
const unsigned char *hash_idx_max_values,
unsigned char *output )
{
unsigned int i_digit_idx;
unsigned char i_digit_idx_bytes[I_DIGIT_IDX_LEN];
unsigned int j_hash_idx;
unsigned char j_hash_idx_bytes[J_HASH_IDX_LEN];
unsigned int j_hash_idx_min;
unsigned int j_hash_idx_max;
psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t output_hash_len;
unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
for ( i_digit_idx = 0;
i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type);
i_digit_idx++ )
{
memcpy( tmp_hash,
&x_digit_array[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)],
MBEDTLS_LMOTS_N_HASH_LEN(params->type) );
j_hash_idx_min = hash_idx_min_values != NULL ?
hash_idx_min_values[i_digit_idx] : 0;
j_hash_idx_max = hash_idx_max_values != NULL ?
hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE;
for ( j_hash_idx = j_hash_idx_min;
j_hash_idx < j_hash_idx_max;
j_hash_idx++ )
{
status = psa_hash_setup( &op, PSA_ALG_SHA_256 );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op,
params->I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op,
params->q_leaf_identifier,
MBEDTLS_LMOTS_Q_LEAF_ID_LEN );
if( status != PSA_SUCCESS )
goto exit;
mbedtls_lms_unsigned_int_to_network_bytes( i_digit_idx,
I_DIGIT_IDX_LEN,
i_digit_idx_bytes );
status = psa_hash_update( &op, i_digit_idx_bytes, I_DIGIT_IDX_LEN );
if( status != PSA_SUCCESS )
goto exit;
mbedtls_lms_unsigned_int_to_network_bytes( j_hash_idx,
J_HASH_IDX_LEN,
j_hash_idx_bytes );
status = psa_hash_update( &op, j_hash_idx_bytes, J_HASH_IDX_LEN );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, tmp_hash,
MBEDTLS_LMOTS_N_HASH_LEN(params->type) );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_finish( &op, tmp_hash, sizeof( tmp_hash ),
&output_hash_len );
if( status != PSA_SUCCESS )
goto exit;
psa_hash_abort( &op );
}
memcpy( &output[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)],
tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type) );
}
exit:
psa_hash_abort( &op );
mbedtls_platform_zeroize( tmp_hash, sizeof( tmp_hash ) );
return( mbedtls_lms_error_from_psa( status ) );
}
/* Combine the hashes of the digit array into a public key. This is used in
* in order to calculate a public key from a private key (RFC8554 Algorithm 1
* step 4), and to calculate a public key candidate from a signature and message
* (RFC8554 Algorithm 4b step 3).
*
* params The LMOTS parameter set, I and q values which describe
* the key being used.
* y_hashed_digits The array of hashes, one hash for each digit of the
* symbol array (which is of size P, 34 in the case of
* MBEDTLS_LMOTS_SHA256_N32_W8)
*
* pub_key The output public key (or candidate public key in
* case this is being run as part of signature
* verification), in the form of a hash output.
*/
static int public_key_from_hashed_digit_array( const mbedtls_lmots_parameters_t *params,
const unsigned char *y_hashed_digits,
unsigned char *pub_key )
{
psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t output_hash_len;
status = psa_hash_setup( &op, PSA_ALG_SHA_256 );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op,
params->I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, params->q_leaf_identifier,
MBEDTLS_LMOTS_Q_LEAF_ID_LEN );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, D_PUBLIC_CONSTANT_BYTES, D_CONST_LEN );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, y_hashed_digits,
MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type) *
MBEDTLS_LMOTS_N_HASH_LEN(params->type) );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_finish( &op, pub_key,
MBEDTLS_LMOTS_N_HASH_LEN(params->type),
&output_hash_len );
if( status != PSA_SUCCESS )
exit:
psa_hash_abort( &op );
return( mbedtls_lms_error_from_psa( status ) );
}
int mbedtls_lms_error_from_psa( psa_status_t status )
{
switch( status )
{
case PSA_SUCCESS:
return( 0 );
case PSA_ERROR_HARDWARE_FAILURE:
return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED );
case PSA_ERROR_NOT_SUPPORTED:
return( MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED );
case PSA_ERROR_BUFFER_TOO_SMALL:
return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL );
case PSA_ERROR_INVALID_ARGUMENT:
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
default:
return( MBEDTLS_ERR_ERROR_GENERIC_ERROR );
}
}
void mbedtls_lmots_public_init( mbedtls_lmots_public_t *ctx )
{
memset( ctx, 0, sizeof( *ctx ) ) ;
}
void mbedtls_lmots_public_free( mbedtls_lmots_public_t *ctx )
{
mbedtls_platform_zeroize( ctx, sizeof( *ctx ) ) ;
}
int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx,
const unsigned char *key, size_t key_len )
{
if( key_len < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
ctx->params.type =
mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN,
key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET );
if( key_len != MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type) )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
memcpy( ctx->params.I_key_identifier,
key + PUBLIC_KEY_I_KEY_ID_OFFSET,
MBEDTLS_LMOTS_I_KEY_ID_LEN );
memcpy( ctx->params.q_leaf_identifier,
key + PUBLIC_KEY_Q_LEAF_ID_OFFSET,
MBEDTLS_LMOTS_Q_LEAF_ID_LEN );
memcpy( ctx->public_key,
key + PUBLIC_KEY_KEY_HASH_OFFSET,
MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type) );
ctx->have_public_key = 1;
return( 0 );
}
int mbedtls_lmots_export_public_key( const mbedtls_lmots_public_t *ctx,
unsigned char *key, size_t key_size,
size_t *key_len )
{
if( key_size < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type) )
{
return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL );
}
if( ! ctx->have_public_key )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.type,
MBEDTLS_LMOTS_TYPE_LEN,
key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET );
memcpy( key + PUBLIC_KEY_I_KEY_ID_OFFSET,
ctx->params.I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN );
memcpy( key + PUBLIC_KEY_Q_LEAF_ID_OFFSET,
ctx->params.q_leaf_identifier,
MBEDTLS_LMOTS_Q_LEAF_ID_LEN );
memcpy( key + PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key,
MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type) );
if( key_len != NULL )
{
*key_len = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type);
}
return( 0 );
}
int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters_t *params,
const unsigned char *msg,
size_t msg_size,
const unsigned char *sig,
size_t sig_size,
unsigned char *out,
size_t out_size,
size_t *out_len )
{
unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX];
unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( msg == NULL && msg_size != 0 )
{
return ( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
if( sig_size != MBEDTLS_LMOTS_SIG_LEN(params->type) ||
out_size < MBEDTLS_LMOTS_N_HASH_LEN(params->type) )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
ret = create_digit_array_with_checksum( params, msg, msg_size,
sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET,
tmp_digit_array );
if( ret )
{
return ( ret );
}
ret = hash_digit_array( params,
sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(params->type),
tmp_digit_array, NULL, ( unsigned char * )y_hashed_digits );
if( ret )
{
return ( ret );
}
ret = public_key_from_hashed_digit_array( params,
( unsigned char * )y_hashed_digits,
out );
if( ret )
{
return ( ret );
}
if( out_len != NULL )
{
*out_len = MBEDTLS_LMOTS_N_HASH_LEN(params->type);
}
return( 0 );
}
int mbedtls_lmots_verify( const mbedtls_lmots_public_t *ctx,
const unsigned char *msg, size_t msg_size,
const unsigned char *sig, size_t sig_size )
{
unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( msg == NULL && msg_size != 0 )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
if( !ctx->have_public_key )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
if( ctx->params.type != MBEDTLS_LMOTS_SHA256_N32_W8 )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
if( sig_size < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN )
{
return( MBEDTLS_ERR_LMS_VERIFY_FAILED );
}
if( mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN,
sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET ) != MBEDTLS_LMOTS_SHA256_N32_W8 )
{
return( MBEDTLS_ERR_LMS_VERIFY_FAILED );
}
ret = mbedtls_lmots_calculate_public_key_candidate( &ctx->params,
msg, msg_size, sig, sig_size,
Kc_public_key_candidate,
MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type),
NULL );
if( ret )
{
return( MBEDTLS_ERR_LMS_VERIFY_FAILED );
}
if( memcmp( &Kc_public_key_candidate, ctx->public_key,
sizeof( ctx->public_key ) ) )
{
return( MBEDTLS_ERR_LMS_VERIFY_FAILED );
}
return( 0 );
}
#if defined(MBEDTLS_LMS_PRIVATE)
void mbedtls_lmots_private_init( mbedtls_lmots_private_t *ctx )
{
memset( ctx, 0, sizeof( *ctx ) ) ;
}
void mbedtls_lmots_private_free( mbedtls_lmots_private_t *ctx )
{
mbedtls_platform_zeroize( ctx, sizeof( *ctx ) ) ;
}
int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx,
mbedtls_lmots_algorithm_type_t type,
const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN],
uint32_t q_leaf_identifier,
const unsigned char *seed,
size_t seed_size )
{
psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t output_hash_len;
unsigned int i_digit_idx;
unsigned char i_digit_idx_bytes[2];
unsigned char const_bytes[1];
if( ctx->have_private_key )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
if( type != MBEDTLS_LMOTS_SHA256_N32_W8 )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
ctx->params.type = type;
memcpy( ctx->params.I_key_identifier,
I_key_identifier,
sizeof( ctx->params.I_key_identifier ) );
mbedtls_lms_unsigned_int_to_network_bytes( q_leaf_identifier,
MBEDTLS_LMOTS_Q_LEAF_ID_LEN,
ctx->params.q_leaf_identifier );
mbedtls_lms_unsigned_int_to_network_bytes( 0xFF, sizeof( const_bytes ),
const_bytes );
for ( i_digit_idx = 0;
i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type);
i_digit_idx++ )
{
status = psa_hash_setup( &op, PSA_ALG_SHA_256 );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op,
ctx->params.I_key_identifier,
sizeof( ctx->params.I_key_identifier ) );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op,
ctx->params.q_leaf_identifier,
MBEDTLS_LMOTS_Q_LEAF_ID_LEN );
if( status != PSA_SUCCESS )
goto exit;
mbedtls_lms_unsigned_int_to_network_bytes( i_digit_idx, I_DIGIT_IDX_LEN,
i_digit_idx_bytes );
status = psa_hash_update( &op, i_digit_idx_bytes, I_DIGIT_IDX_LEN );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, const_bytes, sizeof( const_bytes ) );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, seed, seed_size );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_finish( &op,
ctx->private_key[i_digit_idx],
MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type),
&output_hash_len );
if( status != PSA_SUCCESS )
goto exit;
psa_hash_abort( &op );
}
ctx->have_private_key = 1;
exit:
psa_hash_abort( &op );
return ( mbedtls_lms_error_from_psa( status ) );
}
int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx,
const mbedtls_lmots_private_t *priv_ctx )
{
unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* Check that a private key is loaded */
if( !priv_ctx->have_private_key )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
ret = hash_digit_array( &priv_ctx->params,
( unsigned char * )priv_ctx->private_key, NULL,
NULL, ( unsigned char * )y_hashed_digits );
if( ret )
{
goto exit;
}
ret = public_key_from_hashed_digit_array( &priv_ctx->params,
( unsigned char * )y_hashed_digits,
ctx->public_key );
if( ret )
{
goto exit;
}
memcpy( &ctx->params, &priv_ctx->params,
sizeof( ctx->params ) );
ctx->have_public_key = 1;
exit:
mbedtls_platform_zeroize( y_hashed_digits, sizeof( y_hashed_digits ) );
return( ret );
}
int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng, const unsigned char *msg, size_t msg_size,
unsigned char *sig, size_t sig_size, size_t* sig_len )
{
unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX];
/* Create a temporary buffer to prepare the signature in. This allows us to
* finish creating a signature (ensuring the process doesn't fail), and then
* erase the private key **before** writing any data into the sig parameter
* buffer. If data were directly written into the sig buffer, it might leak
* a partial signature on failure, which effectively compromises the private
* key.
*/
unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX];
unsigned char tmp_c_random[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( msg == NULL && msg_size != 0 )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
if( sig_size < MBEDTLS_LMOTS_SIG_LEN(ctx->params.type) )
{
return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL );
}
/* Check that a private key is loaded */
if( !ctx->have_private_key )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
ret = f_rng( p_rng, tmp_c_random,
MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type) );
if( ret )
{
return( ret );
}
ret = create_digit_array_with_checksum( &ctx->params,
msg, msg_size,
tmp_c_random,
tmp_digit_array );
if( ret )
{
goto exit;
}
ret = hash_digit_array( &ctx->params, ( unsigned char * )ctx->private_key,
NULL, tmp_digit_array, ( unsigned char * )tmp_sig );
if( ret )
{
goto exit;
}
mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.type,
MBEDTLS_LMOTS_TYPE_LEN,
sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET );
/* Test hook to check if sig is being written to before we invalidate the
* private key.
*/
#if defined(MBEDTLS_TEST_HOOKS)
if( mbedtls_lmots_sign_private_key_invalidated_hook != NULL )
{
ret = ( *mbedtls_lmots_sign_private_key_invalidated_hook )( sig );
if( ret != 0 )
return( ret );
}
#endif /* defined(MBEDTLS_TEST_HOOKS) */
/* We've got a valid signature now, so it's time to make sure the private
* key can't be reused.
*/
ctx->have_private_key = 0;
mbedtls_platform_zeroize( ctx->private_key,
sizeof( ctx->private_key ) );
memcpy( sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_c_random,
MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(ctx->params.type) );
memcpy( sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(ctx->params.type), tmp_sig,
MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type)
* MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type) );
if( sig_len != NULL )
{
*sig_len = MBEDTLS_LMOTS_SIG_LEN(ctx->params.type);
}
ret = 0;
exit:
mbedtls_platform_zeroize( tmp_digit_array, sizeof( tmp_digit_array ) );
mbedtls_platform_zeroize( tmp_sig, sizeof( tmp_sig ) );
return ( ret );
}
#endif /* defined(MBEDTLS_LMS_PRIVATE) */
#endif /* defined(MBEDTLS_LMS_C) */

322
library/lmots.h Normal file
View file

@ -0,0 +1,322 @@
/**
* \file lmots.h
*
* \brief This file provides an API for the LM-OTS post-quantum-safe one-time
* public-key signature scheme as defined in RFC8554 and NIST.SP.200-208.
* This implementation currently only supports a single parameter set
* MBEDTLS_LMOTS_SHA256_N32_W8 in order to reduce complexity.
*/
/*
* Copyright The Mbed TLS Contributors
* 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.
*/
#ifndef MBEDTLS_LMOTS_H
#define MBEDTLS_LMOTS_H
#include "mbedtls/build_info.h"
#include "psa/crypto.h"
#include "mbedtls/lms.h"
#include <stdint.h>
#include <stddef.h>
#define MBEDTLS_LMOTS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \
MBEDTLS_LMOTS_I_KEY_ID_LEN + \
MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \
MBEDTLS_LMOTS_N_HASH_LEN(type))
#define MBEDTLS_LMOTS_SIG_TYPE_OFFSET (0)
#define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + \
MBEDTLS_LMOTS_TYPE_LEN)
#define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(type) (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + \
MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type))
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MBEDTLS_TEST_HOOKS)
extern int( *mbedtls_lmots_sign_private_key_invalidated_hook )( unsigned char * );
#endif /* defined(MBEDTLS_TEST_HOOKS) */
/**
* \brief This function converts an unsigned int into a
* network-byte-order (big endian) string.
*
* \param val The unsigned integer value
* \param len The length of the string.
* \param bytes The string to output into.
*/
void mbedtls_lms_unsigned_int_to_network_bytes( unsigned int val, size_t len,
unsigned char *bytes );
/**
* \brief This function converts a network-byte-order
* (big endian) string into an unsigned integer.
*
* \param len The length of the string.
* \param bytes The string.
*
* \return The corresponding LMS error code.
*/
unsigned int mbedtls_lms_network_bytes_to_unsigned_int( size_t len,
const unsigned char *bytes );
/**
* \brief This function converts a \ref psa_status_t to a
* low-level LMS error code.
*
* \param status The psa_status_t to convert
*
* \return The corresponding LMS error code.
*/
int mbedtls_lms_error_from_psa( psa_status_t status );
/**
* \brief This function initializes a public LMOTS context
*
* \param ctx The uninitialized LMOTS context that will then be
* initialized.
*/
void mbedtls_lmots_public_init( mbedtls_lmots_public_t *ctx );
/**
* \brief This function uninitializes a public LMOTS context
*
* \param ctx The initialized LMOTS context that will then be
* uninitialized.
*/
void mbedtls_lmots_public_free( mbedtls_lmots_public_t *ctx );
/**
* \brief This function imports an LMOTS public key into a
* LMOTS context.
*
* \note Before this function is called, the context must
* have been initialized.
*
* \note See IETF RFC8554 for details of the encoding of
* this public key.
*
* \param ctx The initialized LMOTS context store the key in.
* \param key The buffer from which the key will be read.
* #MBEDTLS_LMOTS_PUBLIC_KEY_LEN bytes will be read
* from this.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_import_public_key( mbedtls_lmots_public_t *ctx,
const unsigned char *key, size_t key_size );
/**
* \brief This function exports an LMOTS public key from a
* LMOTS context that already contains a public key.
*
* \note Before this function is called, the context must
* have been initialized and the context must contain
* a public key.
*
* \note See IETF RFC8554 for details of the encoding of
* this public key.
*
* \param ctx The initialized LMOTS context that contains the
* publc key.
* \param key The buffer into which the key will be output. Must
* be at least #MBEDTLS_LMOTS_PUBLIC_KEY_LEN in size.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_export_public_key( const mbedtls_lmots_public_t *ctx,
unsigned char *key, size_t key_size,
size_t *key_len );
/**
* \brief This function creates a candidate public key from
* an LMOTS signature. This can then be compared to
* the real public key to determine the validity of
* the signature.
*
* \note This function is exposed publicly to be used in LMS
* signature verification, it is expected that
* mbedtls_lmots_verify will be used for LMOTS
* signature verification.
*
* \param params The LMOTS parameter set, q and I values as an
* mbedtls_lmots_parameters_t struct.
* \param msg The buffer from which the message will be read.
* \param msg_size The size of the message that will be read.
* \param sig The buffer from which the signature will be read.
* #MBEDTLS_LMOTS_SIG_LEN bytes will be read from
* this.
* \param out The buffer where the candidate public key will be
* stored. Must be at least #MBEDTLS_LMOTS_N_HASH_LEN
* bytes in size.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_calculate_public_key_candidate( const mbedtls_lmots_parameters_t *params,
const unsigned char *msg,
size_t msg_size,
const unsigned char *sig,
size_t sig_size,
unsigned char *out,
size_t out_size,
size_t *out_len );
/**
* \brief This function verifies a LMOTS signature, using a
* LMOTS context that contains a public key.
*
* \warning This function is **not intended for use in
* production**, due to as-yet unsolved problems with
* handling stateful keys. The API for this function
* may change considerably in future versions.
*
* \note Before this function is called, the context must
* have been initialized and must contain a public key
* (either by import or calculation from a private
* key).
*
* \param ctx The initialized LMOTS context from which the public
* key will be read.
* \param msg The buffer from which the message will be read.
* \param msg_size The size of the message that will be read.
* \param sig The buf from which the signature will be read.
* #MBEDTLS_LMOTS_SIG_LEN bytes will be read from
* this.
*
* \return \c 0 on successful verification.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_verify( const mbedtls_lmots_public_t *ctx,
const unsigned char *msg,
size_t msg_size, const unsigned char *sig,
size_t sig_size );
#if defined(MBEDTLS_LMS_PRIVATE)
/**
* \brief This function initializes a private LMOTS context
*
* \param ctx The uninitialized LMOTS context that will then be
* initialized.
*/
void mbedtls_lmots_private_init( mbedtls_lmots_private_t *ctx );
/**
* \brief This function uninitializes a private LMOTS context
*
* \param ctx The initialized LMOTS context that will then be
* uninitialized.
*/
void mbedtls_lmots_private_free( mbedtls_lmots_private_t *ctx );
/**
* \brief This function calculates an LMOTS private key, and
* stores in into an LMOTS context.
*
* \warning This function is **not intended for use in
* production**, due to as-yet unsolved problems with
* handling stateful keys. The API for this function
* may change considerably in future versions.
*
* \note The seed must have at least 256 bits of entropy.
*
* \param ctx The initialized LMOTS context to generate the key
* into.
* \param I_key_identifier The key identifier of the key, as a 16-byte string.
* \param q_leaf_identifier The leaf identifier of key. If this LMOTS key is
* not being used as part of an LMS key, this should
* be set to 0.
* \param seed The seed used to deterministically generate the
* key.
* \param seed_size The length of the seed.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_generate_private_key( mbedtls_lmots_private_t *ctx,
mbedtls_lmots_algorithm_type_t type,
const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN],
uint32_t q_leaf_identifier,
const unsigned char *seed,
size_t seed_size );
/**
* \brief This function generates an LMOTS public key from a
* LMOTS context that already contains a private key.
*
* \note Before this function is called, the context must
* have been initialized and the context must contain
* a private key.
*
* \param ctx The initialized LMOTS context to generate the key
* from and store it into.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_calculate_public_key( mbedtls_lmots_public_t *ctx,
const mbedtls_lmots_private_t *priv_ctx );
/**
* \brief This function creates a LMOTS signature, using a
* LMOTS context that contains a private key.
*
* \note Before this function is called, the context must
* have been initialized and must contain a private
* key.
*
* \note LMOTS private keys can only be used once, otherwise
* attackers may be able to create forged signatures.
* If the signing operation is successful, the private
* key in the context will be erased, and no further
* signing will be possible until another private key
* is loaded
*
* \param ctx The initialized LMOTS context from which the
* private key will be read.
* \param f_rng The RNG function to be used for signature
* generation.
* \param p_rng The RNG context to be passed to f_rng
* \param msg The buffer from which the message will be read.
* \param msg_size The size of the message that will be read.
* \param sig The buf into which the signature will be stored.
* Must be at least #MBEDTLS_LMOTS_SIG_LEN in size.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_sign( mbedtls_lmots_private_t *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng, const unsigned char *msg, size_t msg_size,
unsigned char *sig, size_t sig_size, size_t* sig_len );
#endif /* defined(MBEDTLS_LMS_PRIVATE) */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_LMOTS_H */

789
library/lms.c Normal file
View file

@ -0,0 +1,789 @@
/*
* The LMS stateful-hash public-key signature scheme
*
* Copyright The Mbed TLS Contributors
* 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.
*/
/*
* The following sources were referenced in the design of this implementation
* of the LMS algorithm:
*
* [1] IETF RFC8554
* D. McGrew, M. Curcio, S.Fluhrer
* https://datatracker.ietf.org/doc/html/rfc8554
*
* [2] NIST Special Publication 800-208
* David A. Cooper et. al.
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf
*/
#include "common.h"
#if defined(MBEDTLS_LMS_C)
#include <string.h>
#include "lmots.h"
#include "psa/crypto.h"
#include "mbedtls/lms.h"
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/platform.h"
#define SIG_Q_LEAF_ID_OFFSET (0)
#define SIG_OTS_SIG_OFFSET (SIG_Q_LEAF_ID_OFFSET + \
MBEDTLS_LMOTS_Q_LEAF_ID_LEN)
#define SIG_TYPE_OFFSET(otstype) (SIG_OTS_SIG_OFFSET + \
MBEDTLS_LMOTS_SIG_LEN(otstype))
#define SIG_PATH_OFFSET(otstype) (SIG_TYPE_OFFSET(otstype) + \
MBEDTLS_LMS_TYPE_LEN)
#define PUBLIC_KEY_TYPE_OFFSET (0)
#define PUBLIC_KEY_OTSTYPE_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \
MBEDTLS_LMS_TYPE_LEN)
#define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_OTSTYPE_OFFSET + \
MBEDTLS_LMOTS_TYPE_LEN)
#define PUBLIC_KEY_ROOT_NODE_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \
MBEDTLS_LMOTS_I_KEY_ID_LEN)
/* Currently only support H=10 */
#define H_TREE_HEIGHT_MAX 10
#define MERKLE_TREE_NODE_AM_MAX (1u << (H_TREE_HEIGHT_MAX + 1u))
#define MERKLE_TREE_NODE_AM(type) (1u << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u))
#define MERKLE_TREE_LEAF_NODE_AM(type) (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type))
#define MERKLE_TREE_INTERNAL_NODE_AM(type) (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type))
#define D_CONST_LEN (2)
static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = {0x82, 0x82};
static const unsigned char D_INTR_CONSTANT_BYTES[D_CONST_LEN] = {0x83, 0x83};
/* Calculate the value of a leaf node of the Merkle tree (which is a hash of a
* public key and some other parameters like the leaf index). This function
* implements RFC8554 section 5.3, in the case where r >= 2^h.
*
* params The LMS parameter set, the underlying LMOTS
* parameter set, and I value which describe the key
* being used.
*
* pub_key The public key of the private whose index
* corresponds to the index of this leaf node. This
* is a hash output.
*
* r_node_idx The index of this node in the Merkle tree. Note
* that the root node of the Merkle tree is
* 1-indexed.
*
* out The output node value, which is a hash output.
*/
static int create_merkle_leaf_value( const mbedtls_lms_parameters_t *params,
unsigned char *pub_key,
unsigned int r_node_idx,
unsigned char *out )
{
psa_hash_operation_t op;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t output_hash_len;
unsigned char r_node_idx_bytes[4];
op = psa_hash_operation_init( );
status = psa_hash_setup( &op, PSA_ALG_SHA_256 );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, params->I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN );
if( status != PSA_SUCCESS )
goto exit;
mbedtls_lms_unsigned_int_to_network_bytes( r_node_idx, 4, r_node_idx_bytes );
status = psa_hash_update( &op, r_node_idx_bytes, 4 );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, D_LEAF_CONSTANT_BYTES, D_CONST_LEN );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, pub_key,
MBEDTLS_LMOTS_N_HASH_LEN(params->otstype) );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_finish( &op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type),
&output_hash_len );
if( status != PSA_SUCCESS )
goto exit;
exit:
psa_hash_abort( &op );
return ( mbedtls_lms_error_from_psa( status ) );
}
/* Calculate the value of an internal node of the Merkle tree (which is a hash
* of a public key and some other parameters like the node index). This function
* implements RFC8554 section 5.3, in the case where r < 2^h.
*
* params The LMS parameter set, the underlying LMOTS
* parameter set, and I value which describe the key
* being used.
*
* left_node The value of the child of this node which is on
* the left-hand side. As with all nodes on the
* Merkle tree, this is a hash output.
*
* right_node The value of the child of this node which is on
* the right-hand side. As with all nodes on the
* Merkle tree, this is a hash output.
*
* r_node_idx The index of this node in the Merkle tree. Note
* that the root node of the Merkle tree is
* 1-indexed.
*
* out The output node value, which is a hash output.
*/
static int create_merkle_internal_value( const mbedtls_lms_parameters_t *params,
const unsigned char *left_node,
const unsigned char *right_node,
unsigned int r_node_idx,
unsigned char *out )
{
psa_hash_operation_t op;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t output_hash_len;
unsigned char r_node_idx_bytes[4];
op = psa_hash_operation_init( );
status = psa_hash_setup( &op, PSA_ALG_SHA_256 );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, params->I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN );
if( status != PSA_SUCCESS )
goto exit;
mbedtls_lms_unsigned_int_to_network_bytes( r_node_idx, 4, r_node_idx_bytes );
status = psa_hash_update( &op, r_node_idx_bytes, 4 );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, D_INTR_CONSTANT_BYTES, D_CONST_LEN );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, left_node,
MBEDTLS_LMS_M_NODE_BYTES(params->type) );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_update( &op, right_node,
MBEDTLS_LMS_M_NODE_BYTES(params->type) );
if( status != PSA_SUCCESS )
goto exit;
status = psa_hash_finish( &op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type),
&output_hash_len );
if( status != PSA_SUCCESS )
goto exit;
exit:
psa_hash_abort( &op );
return( mbedtls_lms_error_from_psa( status ) );
}
void mbedtls_lms_public_init( mbedtls_lms_public_t *ctx )
{
memset( ctx, 0, sizeof( *ctx ) ) ;
}
void mbedtls_lms_public_free( mbedtls_lms_public_t *ctx )
{
mbedtls_platform_zeroize( ctx, sizeof( *ctx ) );
}
int mbedtls_lms_import_public_key( mbedtls_lms_public_t *ctx,
const unsigned char *key, size_t key_size )
{
mbedtls_lms_algorithm_type_t type;
mbedtls_lmots_algorithm_type_t otstype;
type = mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN,
key + PUBLIC_KEY_TYPE_OFFSET );
if( type != MBEDTLS_LMS_SHA256_M32_H10 )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
ctx->params.type = type;
if( key_size != MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type) )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
otstype = mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN,
key + PUBLIC_KEY_OTSTYPE_OFFSET );
if( otstype != MBEDTLS_LMOTS_SHA256_N32_W8 )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
ctx->params.otstype = otstype;
memcpy( ctx->params.I_key_identifier,
key + PUBLIC_KEY_I_KEY_ID_OFFSET,
MBEDTLS_LMOTS_I_KEY_ID_LEN );
memcpy( ctx->T_1_pub_key, key + PUBLIC_KEY_ROOT_NODE_OFFSET,
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) );
ctx->have_public_key = 1;
return( 0 );
}
int mbedtls_lms_export_public_key( const mbedtls_lms_public_t *ctx,
unsigned char *key,
size_t key_size, size_t *key_len )
{
if( key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type) )
{
return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL );
}
if( ! ctx->have_public_key )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
mbedtls_lms_unsigned_int_to_network_bytes(
ctx->params.type,
MBEDTLS_LMS_TYPE_LEN, key + PUBLIC_KEY_TYPE_OFFSET );
mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.otstype,
MBEDTLS_LMOTS_TYPE_LEN,
key + PUBLIC_KEY_OTSTYPE_OFFSET );
memcpy( key + PUBLIC_KEY_I_KEY_ID_OFFSET,
ctx->params.I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN );
memcpy( key +PUBLIC_KEY_ROOT_NODE_OFFSET,
ctx->T_1_pub_key,
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) );
if( key_len != NULL )
{
*key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type);
}
return( 0 );
}
int mbedtls_lms_verify( const mbedtls_lms_public_t *ctx,
const unsigned char *msg, size_t msg_size,
const unsigned char *sig, size_t sig_size )
{
unsigned int q_leaf_identifier;
unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN_MAX];
unsigned char Tc_candidate_root_node[MBEDTLS_LMS_M_NODE_BYTES_MAX];
unsigned int height;
unsigned int curr_node_id;
unsigned int parent_node_id;
const unsigned char* left_node;
const unsigned char* right_node;
mbedtls_lmots_parameters_t ots_params;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ! ctx->have_public_key )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
if( ctx->params.type
!= MBEDTLS_LMS_SHA256_M32_H10 )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
if( ctx->params.otstype
!= MBEDTLS_LMOTS_SHA256_N32_W8 )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
if( sig_size != MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) )
{
return( MBEDTLS_ERR_LMS_VERIFY_FAILED );
}
if( sig_size < SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_TYPE_LEN )
{
return( MBEDTLS_ERR_LMS_VERIFY_FAILED );
}
if( mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMOTS_TYPE_LEN,
sig + SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET )
!= MBEDTLS_LMOTS_SHA256_N32_W8 )
{
return( MBEDTLS_ERR_LMS_VERIFY_FAILED );
}
if( sig_size < SIG_TYPE_OFFSET(ctx->params.otstype) + MBEDTLS_LMS_TYPE_LEN )
{
return( MBEDTLS_ERR_LMS_VERIFY_FAILED );
}
if( mbedtls_lms_network_bytes_to_unsigned_int( MBEDTLS_LMS_TYPE_LEN,
sig + SIG_TYPE_OFFSET(ctx->params.otstype))
!= MBEDTLS_LMS_SHA256_M32_H10 )
{
return( MBEDTLS_ERR_LMS_VERIFY_FAILED );
}
q_leaf_identifier = mbedtls_lms_network_bytes_to_unsigned_int(
MBEDTLS_LMOTS_Q_LEAF_ID_LEN, sig + SIG_Q_LEAF_ID_OFFSET );
if( q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type) )
{
return( MBEDTLS_ERR_LMS_VERIFY_FAILED );
}
memcpy( ots_params.I_key_identifier,
ctx->params.I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN );
mbedtls_lms_unsigned_int_to_network_bytes( q_leaf_identifier,
MBEDTLS_LMOTS_Q_LEAF_ID_LEN,
ots_params.q_leaf_identifier );
ots_params.type = ctx->params.otstype;
ret = mbedtls_lmots_calculate_public_key_candidate( &ots_params, msg,
msg_size, sig + SIG_OTS_SIG_OFFSET,
MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype), Kc_candidate_ots_pub_key,
sizeof( Kc_candidate_ots_pub_key ), NULL );
if( ret != 0 )
{
return( MBEDTLS_ERR_LMS_VERIFY_FAILED );
}
create_merkle_leaf_value(
&ctx->params,
Kc_candidate_ots_pub_key,
MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier,
Tc_candidate_root_node );
curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) +
q_leaf_identifier;
for( height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type);
height++ )
{
parent_node_id = curr_node_id / 2;
/* Left/right node ordering matters for the hash */
if( curr_node_id & 1 )
{
left_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) +
height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
right_node = Tc_candidate_root_node;
}
else
{
left_node = Tc_candidate_root_node;
right_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) +
height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
}
create_merkle_internal_value( &ctx->params, left_node, right_node,
parent_node_id, Tc_candidate_root_node);
curr_node_id /= 2;
}
if( memcmp( Tc_candidate_root_node, ctx->T_1_pub_key,
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)) )
{
return( MBEDTLS_ERR_LMS_VERIFY_FAILED );
}
return( 0 );
}
#if defined(MBEDTLS_LMS_PRIVATE)
/* Calculate a full Merkle tree based on a private key. This function
* implements RFC8554 section 5.3, and is used to generate a public key (as the
* public key is the root node of the Merkle tree).
*
* ctx The LMS private context, containing a parameter
* set and private key material consisting of both
* public and private OTS.
*
* tree The output tree, which is 2^(H + 1) hash outputs.
* In the case of H=10 we have 2048 tree nodes (of
* which 1024 of them are leaf nodes). Note that
* because the Merkle tree root is 1-indexed, the 0
* index tree node is never used.
*/
static int calculate_merkle_tree( const mbedtls_lms_private_t *ctx,
unsigned char *tree )
{
unsigned int priv_key_idx;
unsigned int r_node_idx;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* First create the leaf nodes, in ascending order */
for( priv_key_idx = 0;
priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type);
priv_key_idx++ )
{
r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + priv_key_idx;
ret = create_merkle_leaf_value( &ctx->params,
ctx->ots_public_keys[priv_key_idx].public_key, r_node_idx,
&tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)] );
if( ret != 0 )
{
return( ret );
}
}
/* Then the internal nodes, in reverse order so that we can guarantee the
* parent has been created */
for( r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) - 1;
r_node_idx > 0;
r_node_idx-- )
{
ret = create_merkle_internal_value( &ctx->params,
&tree[( r_node_idx * 2 ) * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],
&tree[( r_node_idx * 2 + 1 ) * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],
r_node_idx,
&tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)] );
if( ret != 0 )
{
return( ret );
}
}
return( 0 );
}
/* Calculate a path from a leaf node of the Merkle tree to the root of the tree,
* and return the full path. This function implements RFC8554 section 5.4.1, as
* the Merkle path is the main component of an LMS signature.
*
* ctx The LMS private context, containing a parameter
* set and private key material consisting of both
* public and private OTS.
*
* leaf_node_id Which leaf node to calculate the path from.
*
* path The output path, which is H hash outputs.
*/
static int get_merkle_path( mbedtls_lms_private_t *ctx,
unsigned int leaf_node_id,
unsigned char *path )
{
unsigned char tree[MERKLE_TREE_NODE_AM_MAX][MBEDTLS_LMS_M_NODE_BYTES_MAX];
unsigned int curr_node_id = leaf_node_id;
unsigned int adjacent_node_id;
unsigned int height;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ret = calculate_merkle_tree( ctx, ( unsigned char * )tree );
if( ret != 0 )
{
goto exit;
}
for( height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type);
height++ )
{
adjacent_node_id = curr_node_id ^ 1;
memcpy( &path[height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],
&tree[adjacent_node_id],
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) );
curr_node_id >>=1;
}
ret = 0;
exit:
mbedtls_platform_zeroize( tree, sizeof( tree ) );
return( ret );
}
void mbedtls_lms_private_init( mbedtls_lms_private_t *ctx )
{
memset( ctx, 0, sizeof( *ctx ) ) ;
}
void mbedtls_lms_private_free( mbedtls_lms_private_t *ctx )
{
unsigned int idx;
if( ctx->have_private_key )
{
if( ctx->ots_private_keys != NULL )
{
for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++ )
{
mbedtls_lmots_private_free( &ctx->ots_private_keys[idx] );
}
}
if( ctx->ots_public_keys != NULL )
{
for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++ )
{
mbedtls_lmots_public_free( &ctx->ots_public_keys[idx] );
}
}
mbedtls_free( ctx->ots_private_keys );
mbedtls_free( ctx->ots_public_keys );
}
mbedtls_platform_zeroize( ctx, sizeof( *ctx ) );
}
int mbedtls_lms_generate_private_key( mbedtls_lms_private_t *ctx,
mbedtls_lms_algorithm_type_t type,
mbedtls_lmots_algorithm_type_t otstype,
int (*f_rng)(void *, unsigned char *, size_t),
void* p_rng, const unsigned char *seed,
size_t seed_size )
{
unsigned int idx = 0;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( type != MBEDTLS_LMS_SHA256_M32_H10 )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
if( otstype != MBEDTLS_LMOTS_SHA256_N32_W8 )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
if( ctx->have_private_key )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
ctx->params.type = type;
ctx->params.otstype = otstype;
ctx->have_private_key = 1;
ret = f_rng( p_rng,
ctx->params.I_key_identifier,
MBEDTLS_LMOTS_I_KEY_ID_LEN );
if( ret != 0 )
{
goto exit;
}
/* Requires a cast to size_t to avoid an implicit cast warning on certain
* platforms (particularly Windows) */
ctx->ots_private_keys = mbedtls_calloc( ( size_t )MERKLE_TREE_LEAF_NODE_AM(ctx->params.type),
sizeof( *ctx->ots_private_keys ) );
if( ctx->ots_private_keys == NULL )
{
ret = MBEDTLS_ERR_LMS_ALLOC_FAILED;
goto exit;
}
/* Requires a cast to size_t to avoid an implicit cast warning on certain
* platforms (particularly Windows) */
ctx->ots_public_keys = mbedtls_calloc( ( size_t )MERKLE_TREE_LEAF_NODE_AM(ctx->params.type),
sizeof( *ctx->ots_public_keys ) );
if( ctx->ots_public_keys == NULL )
{
ret = MBEDTLS_ERR_LMS_ALLOC_FAILED;
goto exit;
}
for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++ )
{
mbedtls_lmots_private_init( &ctx->ots_private_keys[idx] );
mbedtls_lmots_public_init( &ctx->ots_public_keys[idx] );
}
for( idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++ )
{
ret = mbedtls_lmots_generate_private_key( &ctx->ots_private_keys[idx],
otstype,
ctx->params.I_key_identifier,
idx, seed, seed_size );
if( ret != 0 )
goto exit;
ret = mbedtls_lmots_calculate_public_key( &ctx->ots_public_keys[idx],
&ctx->ots_private_keys[idx] );
if( ret != 0 )
goto exit;
}
ctx->q_next_usable_key = 0;
exit:
if( ret != 0 )
{
mbedtls_lms_private_free(ctx);
}
return( ret );
}
int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx,
const mbedtls_lms_private_t *priv_ctx )
{
unsigned char tree[MERKLE_TREE_NODE_AM_MAX][MBEDTLS_LMS_M_NODE_BYTES_MAX];
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ! priv_ctx->have_private_key )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
if( priv_ctx->params.type
!= MBEDTLS_LMS_SHA256_M32_H10 )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
if( priv_ctx->params.otstype
!= MBEDTLS_LMOTS_SHA256_N32_W8 )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
memcpy( &ctx->params, &priv_ctx->params,
sizeof( mbedtls_lmots_parameters_t ) );
ret = calculate_merkle_tree( priv_ctx, ( unsigned char * )tree );
if( ret != 0 )
{
goto exit;
}
/* Root node is always at position 1, due to 1-based indexing */
memcpy( ctx->T_1_pub_key, &tree[1],
MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) );
ctx->have_public_key = 1;
ret = 0;
exit:
mbedtls_platform_zeroize( tree, sizeof( tree ) );
return( ret );
}
int mbedtls_lms_sign( mbedtls_lms_private_t *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void* p_rng, const unsigned char *msg,
unsigned int msg_size, unsigned char *sig, size_t sig_size,
size_t *sig_len )
{
uint32_t q_leaf_identifier;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ! ctx->have_private_key )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
if( sig_size < MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) )
{
return( MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL );
}
if( ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10 )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
if( ctx->params.otstype
!= MBEDTLS_LMOTS_SHA256_N32_W8 )
{
return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
if( ctx->q_next_usable_key >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type) )
{
return( MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS );
}
q_leaf_identifier = ctx->q_next_usable_key;
/* This new value must _always_ be written back to the disk before the
* signature is returned.
*/
ctx->q_next_usable_key += 1;
if ( MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)
< SIG_OTS_SIG_OFFSET )
{
return ( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
}
ret = mbedtls_lmots_sign( &ctx->ots_private_keys[q_leaf_identifier],
f_rng, p_rng, msg, msg_size,
sig + SIG_OTS_SIG_OFFSET,
MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) - SIG_OTS_SIG_OFFSET,
NULL );
if( ret != 0 )
{
return( ret );
}
mbedtls_lms_unsigned_int_to_network_bytes( ctx->params.type,
MBEDTLS_LMS_TYPE_LEN,
sig + SIG_TYPE_OFFSET(ctx->params.otstype) );
mbedtls_lms_unsigned_int_to_network_bytes( q_leaf_identifier,
MBEDTLS_LMOTS_Q_LEAF_ID_LEN,
sig + SIG_Q_LEAF_ID_OFFSET );
ret = get_merkle_path( ctx,
MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier,
sig + SIG_PATH_OFFSET(ctx->params.otstype) );
if( ret != 0 )
{
return( ret );
}
if( sig_len != NULL )
{
*sig_len = MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype);
}
return( 0 );
}
#endif /* defined(MBEDTLS_LMS_PRIVATE) */
#endif /* defined(MBEDTLS_LMS_C) */

View file

@ -36,13 +36,7 @@
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#include <string.h>

Some files were not shown because too many files have changed in this diff Show more