VYPR
Medium severity5.3NVD Advisory· Published Sep 26, 2019· Updated Jun 5, 2026

CVE-2019-16910

CVE-2019-16910

Description

Arm Mbed TLS and Mbed Crypto use insufficient entropy for blinding in deterministic ECDSA, enabling side-channel private key recovery after repeated signing of the same message.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Arm Mbed TLS and Mbed Crypto use insufficient entropy for blinding in deterministic ECDSA, enabling side-channel private key recovery after repeated signing of the same message.

Vulnerability

Arm Mbed TLS before version 2.19.0 (also fixed in 2.7.12 and 2.16.3) and Arm Mbed Crypto before version 2.0.0 contain a flaw in deterministic ECDSA signature generation. When deterministic ECDSA is enabled, the blinding value used to protect against timing side-channel attacks is generated using the same random number generator (RNG) as the ephemeral key, but with insufficient entropy. This allows an attacker to recover the private key via side-channel analysis if the victim signs the same message many times. The fix introduces a separate RNG (f_rng_blind) for blinding to ensure sufficient entropy [1][2].

Exploitation

An attacker must be able to observe side-channel information (e.g., timing or power consumption) during the signing operation. The victim must sign the same message repeatedly using deterministic ECDSA. No authentication or special privileges are required; the attacker only needs proximity to measure the side-channel leakage. The attacker then analyzes the collected measurements to extract the private key.

Impact

Successful exploitation allows the attacker to recover the ECDSA private key. With the private key, the attacker can forge signatures and impersonate the victim, leading to a complete compromise of authentication and integrity for any system relying on the victim's ECDSA signatures.

Mitigation

Upgrade to Mbed TLS version 2.19.0, 2.16.3, or 2.7.12, or Mbed Crypto version 2.0.0. The fix is implemented in the referenced commits [1][2]. No workaround is available for unpatched versions. The vulnerability is not listed in CISA's Known Exploited Vulnerabilities (KEV) catalog as of the publication date.

AI Insight generated on May 26, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2

Patches

6
4197f0e28e15

ChangeLog: Update for 2.19.0

https://github.com/armmbed/mbedtlsJaeden AmeroSep 6, 2019via osv
1 file changed · +7 17
  • ChangeLog+7 17 modified
    @@ -1,8 +1,11 @@
     mbed TLS ChangeLog (Sorted per branch, date)
     
    -= mbed TLS 2.19.0 branch released xxxx-xx-xx
    += mbed TLS 2.19.0 branch released 2019-09-06
     
     Security
    +   * Fix a missing error detection in ECJPAKE. This could have caused a
    +     predictable shared secret if a hardware accelerator failed and the other
    +     side of the key exchange had a similar bug.
        * When writing a private EC key, use a constant size for the private
          value, as specified in RFC 5915. Previously, the value was written
          as an ASN.1 INTEGER, which caused the size of the key to leak
    @@ -45,10 +48,9 @@ API Changes
          just curves for which both are supported. Call mbedtls_ecdsa_can_do() or
          mbedtls_ecdh_can_do() on each result to check whether each algorithm is
          supported.
    -   * The following function in the ECDSA module has been deprecated and replaced
    -     as shown below. The new function can take an RNG function as an argument
    -     which is necessary for adequate blinding.
    -     mbedtls_ecdsa_sign_det() -> mbedtls_ecdsa_sign_det_ext()
    +   * The new function mbedtls_ecdsa_sign_det_ext() is similar to
    +     mbedtls_ecdsa_sign_det() but allows passing an external RNG for the
    +     purpose of blinding.
     
     New deprecations
        * Deprecate mbedtls_ecdsa_sign_det() in favor of a functions that can take an
    @@ -103,22 +105,10 @@ Changes
        * Add a Dockerfile and helper scripts (all-in-docker.sh, basic-in-docker.sh,
          docker-env.sh) to simplify running test suites on a Linux host. Contributed
          by Peter Kolbus (Garmin).
    -   * Enable building of Mbed TLS as a CMake subproject. Suggested and fixed by
    -     Ashley Duncan in #2609.
        * Add `reproducible` option to `ssl_client2` and `ssl_server2` to enable
          test runs without variability. Contributed by Philippe Antoine (Catena
          cyber) in #2681.
        * Extended .gitignore to ignore Visual Studio artifacts. Fixed by ConfusedSushi.
    -   * Enable building of Mbed TLS as a CMake subproject. Suggested and fixed by
    -     Ashley Duncan in #2609.
    -   * Add `reproducible` option to `ssl_client2` and `ssl_server2` to enable
    -     test runs without variability. Contributed by Philippe Antoine (Catena
    -     cyber) in #2681.
    -   * Enable building of Mbed TLS as a CMake subproject. Suggested and fixed by
    -     Ashley Duncan in #2609.
    -   * Add `reproducible` option to `ssl_client2` and `ssl_server2` to enable
    -     test runs without variability. Contributed by Philippe Antoine (Catena
    -     cyber) in #2681.
        * Adds fuzz targets, especially for continuous fuzzing with OSS-Fuzz.
          Contributed by Philippe Antoine (Catena cyber).
     
    
04a049bda1ce

Merge remote-tracking branch 'origin/pr/2823' into mbedtls-2.16

https://github.com/armmbed/mbedtlsJaeden AmeroSep 6, 2019via osv
6 files changed · +12 12
  • ChangeLog+1 1 modified
    @@ -1,6 +1,6 @@
     mbed TLS ChangeLog (Sorted per branch, date)
     
    -= mbed TLS x.x.x branch released xxxx-xx-xx
    += mbed TLS 2.16.3 branch released 2019-09-06
     
     Security
        * Fix a missing error detection in ECJPAKE. This could have caused a
    
  • doxygen/input/doc_mainpage.h+1 1 modified
    @@ -24,7 +24,7 @@
      */
     
     /**
    - * @mainpage mbed TLS v2.16.2 source code documentation
    + * @mainpage mbed TLS v2.16.3 source code documentation
      *
      * This documentation describes the internal structure of mbed TLS.  It was
      * automatically generated from specially formatted comment blocks in
    
  • doxygen/mbedtls.doxyfile+1 1 modified
    @@ -28,7 +28,7 @@ DOXYFILE_ENCODING      = UTF-8
     # identify the project. Note that if you do not use Doxywizard you need
     # to put quotes around the project name if it contains spaces.
     
    -PROJECT_NAME           = "mbed TLS v2.16.2"
    +PROJECT_NAME           = "mbed TLS v2.16.3"
     
     # The PROJECT_NUMBER tag can be used to enter a project or revision number.
     # This could be handy for archiving the generated documentation or
    
  • include/mbedtls/version.h+4 4 modified
    @@ -40,16 +40,16 @@
      */
     #define MBEDTLS_VERSION_MAJOR  2
     #define MBEDTLS_VERSION_MINOR  16
    -#define MBEDTLS_VERSION_PATCH  2
    +#define MBEDTLS_VERSION_PATCH  3
     
     /**
      * The single version number has the following structure:
      *    MMNNPP00
      *    Major version | Minor version | Patch version
      */
    -#define MBEDTLS_VERSION_NUMBER         0x02100200
    -#define MBEDTLS_VERSION_STRING         "2.16.2"
    -#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.16.2"
    +#define MBEDTLS_VERSION_NUMBER         0x02100300
    +#define MBEDTLS_VERSION_STRING         "2.16.3"
    +#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.16.3"
     
     #if defined(MBEDTLS_VERSION_C)
     
    
  • library/CMakeLists.txt+3 3 modified
    @@ -165,15 +165,15 @@ endif(USE_STATIC_MBEDTLS_LIBRARY)
     
     if(USE_SHARED_MBEDTLS_LIBRARY)
         add_library(mbedcrypto SHARED ${src_crypto})
    -    set_target_properties(mbedcrypto PROPERTIES VERSION 2.16.2 SOVERSION 3)
    +    set_target_properties(mbedcrypto PROPERTIES VERSION 2.16.3 SOVERSION 3)
         target_link_libraries(mbedcrypto ${libs})
     
         add_library(mbedx509 SHARED ${src_x509})
    -    set_target_properties(mbedx509 PROPERTIES VERSION 2.16.2 SOVERSION 0)
    +    set_target_properties(mbedx509 PROPERTIES VERSION 2.16.3 SOVERSION 0)
         target_link_libraries(mbedx509 ${libs} mbedcrypto)
     
         add_library(mbedtls SHARED ${src_tls})
    -    set_target_properties(mbedtls PROPERTIES VERSION 2.16.2 SOVERSION 12)
    +    set_target_properties(mbedtls PROPERTIES VERSION 2.16.3 SOVERSION 12)
         target_link_libraries(mbedtls ${libs} mbedx509)
     
         install(TARGETS mbedtls mbedx509 mbedcrypto
    
  • tests/suites/test_suite_version.data+2 2 modified
    @@ -1,8 +1,8 @@
     Check compiletime library version
    -check_compiletime_version:"2.16.2"
    +check_compiletime_version:"2.16.3"
     
     Check runtime library version
    -check_runtime_version:"2.16.2"
    +check_runtime_version:"2.16.3"
     
     Check for MBEDTLS_VERSION_C
     check_feature:"MBEDTLS_VERSION_C":0
    
14c676235139

Merge remote-tracking branch 'origin/pr/2822' into mbedtls-2.7

https://github.com/armmbed/mbedtlsJaeden AmeroSep 6, 2019via osv
6 files changed · +12 12
  • ChangeLog+1 1 modified
    @@ -1,6 +1,6 @@
     mbed TLS ChangeLog (Sorted per branch, date)
     
    -= mbed TLS x.x.x branch released xxxx-xx-xx
    += mbed TLS 2.7.12 branch released 2019-09-06
     
     Security
        * Fix a missing error detection in ECJPAKE. This could have caused a
    
  • doxygen/input/doc_mainpage.h+1 1 modified
    @@ -24,7 +24,7 @@
      */
     
     /**
    - * @mainpage mbed TLS v2.7.11 source code documentation
    + * @mainpage mbed TLS v2.7.12 source code documentation
      *
      * This documentation describes the internal structure of mbed TLS.  It was
      * automatically generated from specially formatted comment blocks in
    
  • doxygen/mbedtls.doxyfile+1 1 modified
    @@ -28,7 +28,7 @@ DOXYFILE_ENCODING      = UTF-8
     # identify the project. Note that if you do not use Doxywizard you need
     # to put quotes around the project name if it contains spaces.
     
    -PROJECT_NAME           = "mbed TLS v2.7.11"
    +PROJECT_NAME           = "mbed TLS v2.7.12"
     
     # The PROJECT_NUMBER tag can be used to enter a project or revision number.
     # This could be handy for archiving the generated documentation or
    
  • include/mbedtls/version.h+4 4 modified
    @@ -40,16 +40,16 @@
      */
     #define MBEDTLS_VERSION_MAJOR  2
     #define MBEDTLS_VERSION_MINOR  7
    -#define MBEDTLS_VERSION_PATCH  11
    +#define MBEDTLS_VERSION_PATCH  12
     
     /**
      * The single version number has the following structure:
      *    MMNNPP00
      *    Major version | Minor version | Patch version
      */
    -#define MBEDTLS_VERSION_NUMBER         0x02070B00
    -#define MBEDTLS_VERSION_STRING         "2.7.11"
    -#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.7.11"
    +#define MBEDTLS_VERSION_NUMBER         0x02070C00
    +#define MBEDTLS_VERSION_STRING         "2.7.12"
    +#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 2.7.12"
     
     #if defined(MBEDTLS_VERSION_C)
     
    
  • library/CMakeLists.txt+3 3 modified
    @@ -147,15 +147,15 @@ endif(USE_STATIC_MBEDTLS_LIBRARY)
     
     if(USE_SHARED_MBEDTLS_LIBRARY)
         add_library(mbedcrypto SHARED ${src_crypto})
    -    set_target_properties(mbedcrypto PROPERTIES VERSION 2.7.11 SOVERSION 2)
    +    set_target_properties(mbedcrypto PROPERTIES VERSION 2.7.12 SOVERSION 2)
         target_link_libraries(mbedcrypto ${libs})
     
         add_library(mbedx509 SHARED ${src_x509})
    -    set_target_properties(mbedx509 PROPERTIES VERSION 2.7.11 SOVERSION 0)
    +    set_target_properties(mbedx509 PROPERTIES VERSION 2.7.12 SOVERSION 0)
         target_link_libraries(mbedx509 ${libs} mbedcrypto)
     
         add_library(mbedtls SHARED ${src_tls})
    -    set_target_properties(mbedtls PROPERTIES VERSION 2.7.11 SOVERSION 10)
    +    set_target_properties(mbedtls PROPERTIES VERSION 2.7.12 SOVERSION 10)
         target_link_libraries(mbedtls ${libs} mbedx509)
     
         install(TARGETS mbedtls mbedx509 mbedcrypto
    
  • tests/suites/test_suite_version.data+2 2 modified
    @@ -1,8 +1,8 @@
     Check compiletime library version
    -check_compiletime_version:"2.7.11"
    +check_compiletime_version:"2.7.12"
     
     Check runtime library version
    -check_runtime_version:"2.7.11"
    +check_runtime_version:"2.7.12"
     
     Check for MBEDTLS_VERSION_C
     check_feature:"MBEDTLS_VERSION_C":0
    
92348d1c4931

Merge remote-tracking branch 'crypto/development' into development-restricted

https://github.com/armmbed/mbed-cryptoJaeden AmeroSep 6, 2019via osv
7 files changed · +380 120
  • CMakeLists.txt+3 3 modified
    @@ -137,8 +137,8 @@ if(CMAKE_COMPILER_IS_GNU)
         set(CMAKE_C_FLAGS_RELEASE     "-O2")
         set(CMAKE_C_FLAGS_DEBUG       "-O0 -g3")
         set(CMAKE_C_FLAGS_COVERAGE    "-O0 -g3 --coverage")
    -    set(CMAKE_C_FLAGS_ASAN        "-Werror -fsanitize=address -fno-common -O3")
    -    set(CMAKE_C_FLAGS_ASANDBG     "-Werror -fsanitize=address -fno-common -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls ")
    +    set(CMAKE_C_FLAGS_ASAN        "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O3")
    +    set(CMAKE_C_FLAGS_ASANDBG     "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls")
         set(CMAKE_C_FLAGS_CHECK       "-Werror -Os")
         set(CMAKE_C_FLAGS_CHECKFULL   "${CMAKE_C_FLAGS_CHECK} -Wcast-qual")
     endif(CMAKE_COMPILER_IS_GNU)
    @@ -149,7 +149,7 @@ if(CMAKE_COMPILER_IS_CLANG)
         set(CMAKE_C_FLAGS_DEBUG       "-O0 -g3")
         set(CMAKE_C_FLAGS_COVERAGE    "-O0 -g3 --coverage")
         set(CMAKE_C_FLAGS_ASAN        "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O3")
    -    set(CMAKE_C_FLAGS_ASANDBG     "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls ")
    +    set(CMAKE_C_FLAGS_ASANDBG     "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls")
         set(CMAKE_C_FLAGS_MEMSAN      "-Werror -fsanitize=memory -O3")
         set(CMAKE_C_FLAGS_MEMSANDBG   "-Werror -fsanitize=memory -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2")
         set(CMAKE_C_FLAGS_CHECK       "-Werror -Os")
    
  • docs/getting_started.md+99 97 modified
    @@ -18,7 +18,7 @@ The Mbed Crypto library is distributed under the Apache License, version 2.0.
     #### Platform Security Architecture (PSA)
     
     Arm's Platform Security Architecture (PSA) 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. Part of the API provided by PSA is the cryptography interface, which provides access to a set of primitives.
    +security analyses, hardware and firmware architecture specifications, and an open source firmware reference implementation. PSA provides a recipe, based on industry best practice, that enables you to design security into both hardware and firmware consistently. Part of the API provided by PSA is the cryptography interface, which provides access to a set of primitives.
     
     ### Using Mbed Crypto
     
    @@ -37,19 +37,19 @@ security analyses, hardware and firmware architecture specifications, and an ope
     
     ### Getting the Mbed Crypto library
     
    -Mbed Crypto releases are available in the [public Github repository]( https://github.com/ARMmbed/mbed-crypto).
    +Mbed Crypto releases are available in the [public GitHub repository](https://github.com/ARMmbed/mbed-crypto).
     
     ### Building the Mbed Crypto library
     
    -You need the following tools to build the library with the provided makefiles:
    +**Prerequisites to building the library with the provided makefiles:**
     * GNU Make.
     * A C toolchain (compiler, linker, archiver).
     * Python 2 or Python 3 (either works) to generate the test code.
     * Perl to run the tests.
     
     If you have a C compiler such as GCC or Clang, just run `make` in the top-level directory to build the library, a set of unit tests and some sample programs.
     
    -To select a different compiler, set the `CC` variable to name or path of the compiler and linker (default: `cc`) and set `AR` to a compatible archiver (default: `ar`), such as:
    +To select a different compiler, set the `CC` variable to the name or path of the compiler and linker (default: `cc`) and set `AR` to a compatible archiver (default: `ar`); for example:
     ```
     make CC=arm-linux-gnueabi-gcc AR=arm-linux-gnueabi-ar
     ```
    @@ -64,13 +64,13 @@ To use the Mbed Crypto APIs, call `psa_crypto_init()` before calling any other A
     ### Importing a key
     
     To use a key for cryptography operations in Mbed Crypto, you need to first
    -import it. Upon importing, you'll be given a handle to refer to the key for use
    +import it. Importing the key creates a handle that refers to the key for use
     with other function calls.
     
    -Prerequisites for importing keys:
    -* Initialize the library with a successful call to `psa_crypto_init`.
    +**Prerequisites to importing keys:**
    +* Initialize the library with a successful call to `psa_crypto_init()`.
     
    -Importing a key:
    +This example shows how to import a key:
     ```C
         psa_status_t status;
         psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
    @@ -112,23 +112,24 @@ Importing a key:
     
     ### Signing a message using RSA
     
    -Mbed Crypto provides support for encrypting, decrypting, signing and verifying messages using public key signature algorithms (such as RSA or ECDSA).
    +Mbed Crypto supports encrypting, decrypting, signing and verifying messages using public key signature algorithms, such as RSA or ECDSA.
     
    -Prerequisites for performing asymmetric signature operations:
    -* Initialize the library with a successful call to `psa_crypto_init`.
    +**Prerequisites to performing asymmetric signature operations:**
    +* Initialize the library with a successful call to `psa_crypto_init()`.
     * Have a valid key with appropriate attributes set:
         * Usage flag `PSA_KEY_USAGE_SIGN` to allow signing.
         * Usage flag `PSA_KEY_USAGE_VERIFY` to allow signature verification.
    -    * Algorithm set to desired signature algorithm.
    +    * Algorithm set to the desired signature algorithm.
     
    -To sign a given `hash` using RSA:
    -1. Call `psa_asymmetric_sign()` and get the output buffer that contains the
    -   signature:
    +This example shows how to sign a hash that has already been calculated:
     ```C
         psa_status_t status;
         psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
         uint8_t key[] = RSA_KEY;
    -    uint8_t hash[] = "INPUT_FOR_SIGN";
    +    uint8_t hash[32] = {0x50, 0xd8, 0x58, 0xe0, 0x98, 0x5e, 0xcc, 0x7f,
    +                        0x60, 0x41, 0x8a, 0xaf, 0x0c, 0xc5, 0xab, 0x58,
    +                        0x7f, 0x42, 0xc2, 0x57, 0x0a, 0x88, 0x40, 0x95,
    +                        0xa9, 0xe8, 0xcc, 0xac, 0xd0, 0xf6, 0x54, 0x5c};
         uint8_t signature[PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE] = {0};
         size_t signature_length;
         psa_key_handle_t handle;
    @@ -179,21 +180,21 @@ To sign a given `hash` using RSA:
     
     ### Using symmetric ciphers
     
    -Mbed Crypto provides support for encrypting and decrypting messages using various symmetric cipher algorithms (both block and stream ciphers).
    +Mbed Crypto supports encrypting and decrypting messages using various symmetric cipher algorithms (both block and stream ciphers).
     
    -Prerequisites to working with the symmetric cipher API:
    -* Initialize the library with a successful call to `psa_crypto_init`.
    -* Configure the key policy accordingly (`PSA_KEY_USAGE_ENCRYPT` to allow encryption or `PSA_KEY_USAGE_DECRYPT` to allow decryption).
    -* Have a valid key in the key slot.
    +**Prerequisites to working with the symmetric cipher API:**
    +* Initialize the library with a successful call to `psa_crypto_init()`.
    +* Have a handle to a symmetric key. This key's usage flags must include `PSA_KEY_USAGE_ENCRYPT` to allow encryption or `PSA_KEY_USAGE_DECRYPT` to allow decryption.
     
    -Encrypting a message with a symmetric cipher:
    +**To encrypt a message with a symmetric cipher:**
     1. Allocate an operation (`psa_cipher_operation_t`) structure to pass to the cipher functions.
    -1. Call `psa_cipher_encrypt_setup` to initialize the operation structure and  specify the algorithm and the key to be used.
    -1. Call either `psa_cipher_generate_iv` or `psa_cipher_set_iv` to generate or set the initialization vector (IV). We recommended `psa_cipher_generate_iv`, unless you require a specific IV value.
    -1. Call `psa_cipher_update` one or more times, passing either the whole or only a fragment of the message each time.
    -1. Call `psa_cipher_finish` to end the operation and output the encrypted message.
    +1. Initialize the operation structure to zero or to `PSA_CIPHER_OPERATION_INIT`.
    +1. Call `psa_cipher_encrypt_setup()` to specify the algorithm and the key to be used.
    +1. Call either `psa_cipher_generate_iv()` or `psa_cipher_set_iv()` to generate or set the initialization vector (IV). We recommend calling `psa_cipher_generate_iv()`, unless you require a specific IV value.
    +1. Call `psa_cipher_update()` with the message to encrypt. You may call this function multiple times, passing successive fragments of the message on successive calls.
    +1. Call `psa_cipher_finish()` to end the operation and output the encrypted message.
     
    -Encrypting data using an AES key in cipher block chain (CBC) mode with no padding (assuming all prerequisites have been fulfilled):
    +This example shows how to encrypt data using an AES (Advanced Encryption Standard) key in CBC (Cipher Block Chaining) mode with no padding (assuming all prerequisites have been fulfilled):
     ```c
         enum {
             block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES),
    @@ -267,14 +268,15 @@ Encrypting data using an AES key in cipher block chain (CBC) mode with no paddin
         mbedtls_psa_crypto_free();
     ```
     
    -Decrypting a message with a symmetric cipher:
    +**To decrypt a message with a symmetric cipher:**
     1. Allocate an operation (`psa_cipher_operation_t`) structure to pass to the cipher functions.
    -1. Call `psa_cipher_decrypt_setup` to initialize the operation structure and to specify the algorithm and the key to be used.
    -1. Call `psa_cipher_set_iv` with the IV for the decryption.
    -1. Call `psa_cipher_update` one or more times passing either the whole or only a fragment of the message each time.
    -1. Call `psa_cipher_finish` to end the operation and output the decrypted message.
    +1. Initialize the operation structure to zero or to `PSA_CIPHER_OPERATION_INIT`.
    +1. Call `psa_cipher_decrypt_setup()` to specify the algorithm and the key to be used.
    +1. Call `psa_cipher_set_iv()` with the IV for the decryption.
    +1. Call `psa_cipher_update()` with the message to encrypt. You may call this function multiple times, passing successive fragments of the message on successive calls.
    +1. Call `psa_cipher_finish()` to end the operation and output the decrypted message.
     
    -Decrypting encrypted data using an AES key in CBC mode with no padding
    +This example shows how to decrypt encrypted data using an AES key in CBC mode with no padding
     (assuming all prerequisites have been fulfilled):
     ```c
         enum {
    @@ -350,33 +352,36 @@ Decrypting encrypted data using an AES key in CBC mode with no padding
     
     #### Handling cipher operation contexts
     
    -Once you've initialized the operation structure with a successful call to `psa_cipher_encrypt_setup` or `psa_cipher_decrypt_setup`, you can terminate the operation at any time by calling `psa_cipher_abort`.
    +After you've initialized the operation structure with a successful call to `psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()`, you can terminate the operation at any time by calling `psa_cipher_abort()`.
    +
    +The call to `psa_cipher_abort()` frees any resources associated with the operation, except for the operation structure itself.
     
    -The call to `psa_cipher_abort` frees any resources associated with the operation (except for the operation structure itself). An implicit call to `psa_cipher_abort` occurs when any of these conditions occur:
    -* A call to `psa_cipher_generate_iv`, `psa_cipher_set_iv` or `psa_cipher_update` has failed (returning any status other than `PSA_SUCCESS`).
    -* Either a successful or failed call to `psa_cipher_finish`.
    +Mbed Crypto implicitly calls `psa_cipher_abort()` when:
    +* A call to `psa_cipher_generate_iv()`, `psa_cipher_set_iv()` or `psa_cipher_update()` fails (returning any status other than `PSA_SUCCESS`).
    +* A call to `psa_cipher_finish()` succeeds or fails.
     
    -Once `psa_cipher_abort` has been called (either implicitly by the implementation or explicitly by the user), the operation structure is invalidated and may not be reused for the same operation. However, the operation structure may be reused for a different operation by calling either `psa_cipher_encrypt_setup` or `psa_cipher_decrypt_setup` again.
    +After an implicit or explicit call to `psa_cipher_abort()`, the operation structure is invalidated; in other words, you cannot reuse the operation structure for the same operation. You can, however, reuse the operation structure for a different operation by calling either `psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()` again.
     
    -For an operation that has been initialized successfully (by a successful call to `psa_cipher_encrypt_setup` or `psa_cipher_decrypt_setup`) it is imperative that at some time `psa_cipher_abort` is called.
    +You must call `psa_cipher_abort()` at some point for any operation that is initialized successfully (by a successful call to `psa_cipher_encrypt_setup()` or `psa_cipher_decrypt_setup()`).
     
    -Multiple sequential calls to `psa_cipher_abort` on an operation that has already been terminated (either implicitly or explicitly) are safe and have no effect.
    +Making multiple sequential calls to `psa_cipher_abort()` on an operation that is terminated (either implicitly or explicitly) is safe and has no effect.
     
     ### Hashing a message
     
     Mbed Crypto lets you compute and verify hashes using various hashing
     algorithms.
     
    -Prerequisites to working with the hash APIs:
    -* Initialize the library with a successful call to `psa_crypto_init`.
    +**Prerequisites to working with the hash APIs:**
    +* Initialize the library with a successful call to `psa_crypto_init()`.
     
    -To calculate a hash:
    +**To calculate a hash:**
     1. Allocate an operation structure (`psa_hash_operation_t`) to pass to the hash functions.
    -1. Call `psa_hash_setup` to initialize the operation structure and specify the hash algorithm.
    -1. Call `psa_hash_update` one or more times, passing either the whole or only a fragment of the message each time.
    -1. Call `psa_hash_finish` to calculate the hash, or `psa_hash_verify` to compare the computed hash with an expected hash value.
    +1. Initialize the operation structure to zero or to `PSA_HASH_OPERATION_INIT`.
    +1. Call `psa_hash_setup()` to specify the hash algorithm.
    +1. Call `psa_hash_update()` with the message to encrypt. You may call this function multiple times, passing successive fragments of the message on successive calls.
    +1. Call `psa_hash_finish()` to calculate the hash, or `psa_hash_verify()` to compare the computed hash with an expected hash value.
     
    -Calculate the `SHA-256` hash of a message:
    +This example shows how to calculate the SHA-256 hash of a message:
     ```c
         psa_status_t status;
         psa_algorithm_t alg = PSA_ALG_SHA_256;
    @@ -421,7 +426,7 @@ Calculate the `SHA-256` hash of a message:
         mbedtls_psa_crypto_free();
     ```
     
    -Verify the `SHA-256` hash of a message:
    +This example shows how to verify the SHA-256 hash of a message:
     ```c
         psa_status_t status;
         psa_algorithm_t alg = PSA_ALG_SHA_256;
    @@ -473,29 +478,29 @@ The API provides the macro `PSA_HASH_SIZE`, which returns the expected hash leng
     
     #### Handling hash operation contexts
     
    -Once the operation structure has been successfully initialized by a successful call to `psa_hash_setup`, it's possible to terminate the operation at any time by calling `psa_hash_abort`. The call to `psa_hash_abort` frees any resources associated with the operation (except for the operation structure itself).
    +After a successful call to `psa_hash_setup()`, you can terminate the operation at any time by calling `psa_hash_abort()`. The call to `psa_hash_abort()` frees any resources associated with the operation, except for the operation structure itself.
     
    -An implicit call to `psa_hash_abort` occurs when any of these conditions occur:
    -1. A call to `psa_hash_update` has failed (returning any status other than `PSA_SUCCESS`).
    -1. Either a successful or failed call to `psa_hash_finish`.
    -1. Either a successful or failed call to `psa_hash_verify`.
    +Mbed Crypto implicitly calls `psa_hash_abort()` when:
    +1. A call to `psa_hash_update()` fails (returning any status other than `PSA_SUCCESS`).
    +1. A call to `psa_hash_finish()` succeeds or fails.
    +1. A call to `psa_hash_verify()` succeeds or fails.
     
    -Once `psa_hash_abort` has been called (either implicitly by the implementation or explicitly by the user), the operation structure is invalidated and may not be reused for the same operation. However, the operation structure may be reused for a different operation by calling `psa_hash_setup` again.
    +After an implicit or explicit call to `psa_hash_abort()`, the operation structure is invalidated; in other words, you cannot reuse the operation structure for the same operation. You can, however, reuse the operation structure for a different operation by calling `psa_hash_setup()` again.
     
    -For an operation that has been initialized successfully (by a successful call to `psa_hash_setup`) it is imperative that at some time `psa_hash_abort` is called.
    +You must call `psa_hash_abort()` at some point for any operation that is initialized successfully (by a successful call to `psa_hash_setup()`) .
     
    -Multiple sequential calls to `psa_hash_abort` on an operation that has already been terminated (either implicitly or explicitly) is safe and has no effect.
    +Making multiple sequential calls to `psa_hash_abort()` on an operation that has already been terminated (either implicitly or explicitly) is safe and has no effect.
     
     ### Generating a random value
     
    -Mbed Crypto can generate random data. To generate a random key, use
    -`psa_generate_key()` instead of `psa_generate_random()`
    +Mbed Crypto can generate random data.
     
    -Prerequisites to random generation:
    +**Prerequisites to generating random data:**
     * Initialize the library with a successful call to `psa_crypto_init()`.
     
    -Generate a random, ten-byte piece of data:
    -1. Generate random bytes by calling `psa_generate_random()`:
    +<span class="notes">**Note:** To generate a random key, use `psa_generate_key()` instead of `psa_generate_random()`.</span>
    +
    +This example shows how to generate ten bytes of random data by calling `psa_generate_random()`:
     ```C
         psa_status_t status;
         uint8_t random[10] = { 0 };
    @@ -527,35 +532,38 @@ Generate a random, ten-byte piece of data:
     Mbed Crypto provides a key derivation API that lets you derive new keys from
     existing ones. The key derivation API has functions to take inputs, including
     other keys and data, and functions to generate outputs, such as new keys or
    -other data. A key derivation context must first be initialized and set up,
    -provided with a key and optionally other data, and then derived data can be
    -read from it either to a buffer or directly sent to a key slot. Refer to the
    -documentation for the particular algorithm (such as HKDF or the TLS1.2 PRF) for
    -information on which inputs to pass when and when you can obtain which outputs.
    -
    -Prerequisites to working with the key derivation APIs:
    -* Initialize the library with a successful call to `psa_crypto_init`.
    +other data.
    +
    +You must first initialize and set up a key derivation context,
    +provided with a key and, optionally, other data. Then, use the key derivation context to either read derived data to a buffer or send derived data directly to a key slot.
    +
    +See the documentation for the particular algorithm (such as HKDF or the TLS1.2 PRF) for
    +information about which inputs to pass when, and when you can obtain which outputs.
    +
    +**Prerequisites to working with the key derivation APIs:**
    +* Initialize the library with a successful call to `psa_crypto_init()`.
     * Use a key with the appropriate attributes set:
         * Usage flags set for key derivation (`PSA_KEY_USAGE_DERIVE`)
         * Key type set to `PSA_KEY_TYPE_DERIVE`.
         * Algorithm set to a key derivation algorithm
    -      (`PSA_ALG_HKDF(PSA_ALG_SHA_256)`).
    +      (for example, `PSA_ALG_HKDF(PSA_ALG_SHA_256)`).
    +
    +**To derive a new AES-CTR 128-bit encryption key into a given key slot using HKDF
    +with a given key, salt and info:**
     
    -Deriving a new AES-CTR 128-bit encryption key into a given key slot using HKDF
    -with a given key, salt and info:
    -1. Set up the key derivation context using the `psa_key_derivation_setup`
    +1. Set up the key derivation context using the `psa_key_derivation_setup()`
     function, specifying the derivation algorithm `PSA_ALG_HKDF(PSA_ALG_SHA_256)`.
    -1. Provide an optional salt with `psa_key_derivation_input_bytes`.
    -1. Provide info with `psa_key_derivation_input_bytes`.
    -1. Provide secret with `psa_key_derivation_input_key`, referencing a key that
    +1. Provide an optional salt with `psa_key_derivation_input_bytes()`.
    +1. Provide info with `psa_key_derivation_input_bytes()`.
    +1. Provide a secret with `psa_key_derivation_input_key()`, referencing a key that
        can be used for key derivation.
     1. Set the key attributes desired for the new derived key. We'll set
    -   `PSA_KEY_USAGE_ENCRYPT` parameter and the algorithm `PSA_ALG_CTR` for this
    +   the `PSA_KEY_USAGE_ENCRYPT` usage flag and the `PSA_ALG_CTR` algorithm for this
        example.
     1. Derive the key by calling `psa_key_derivation_output_key()`.
     1. Clean up the key derivation context.
     
    -At this point the derived key slot holds a new 128-bit AES-CTR encryption key
    +At this point, the derived key slot holds a new 128-bit AES-CTR encryption key
     derived from the key, salt and info provided:
     ```C
         psa_status_t status;
    @@ -659,14 +667,13 @@ derived from the key, salt and info provided:
     
     ### Authenticating and encrypting or decrypting a message
     
    -Mbed Crypto provides a simple way for authenticate and encrypt with associated data (AEAD) supporting `PSA_ALG_CCM` algorithm.
    +Mbed Crypto provides a simple way to authenticate and encrypt with associated data (AEAD), supporting the `PSA_ALG_CCM` algorithm.
     
    -Prerequisites to working with the AEAD ciphers APIs:
    -* Initialize the library with a successful call to `psa_crypto_init`.
    -* The key attributes for the key used for derivation must have usage flags
    -  `PSA_KEY_USAGE_ENCRYPT` or `PSA_KEY_USAGE_DECRYPT`.
    +**Prerequisites to working with the AEAD cipher APIs:**
    +* Initialize the library with a successful call to `psa_crypto_init()`.
    +* The key attributes for the key used for derivation must have the `PSA_KEY_USAGE_ENCRYPT` or `PSA_KEY_USAGE_DECRYPT` usage flags.
     
    -To authenticate and encrypt a message:
    +This example shows how to authenticate and encrypt a message:
     ```C
         psa_status_t status;
         static const uint8_t key[] = {
    @@ -737,7 +744,7 @@ To authenticate and encrypt a message:
         mbedtls_psa_crypto_free();
     ```
     
    -To authenticate and decrypt a message:
    +This example shows how to authenticate and decrypt a message:
     
     ```C
         psa_status_t status;
    @@ -816,18 +823,15 @@ To authenticate and decrypt a message:
     
     Mbed Crypto provides a simple way to generate a key or key pair.
     
    -Prerequisites to using key generation and export APIs:
    -* Initialize the library with a successful call to `psa_crypto_init`.
    +**Prerequisites to using key generation and export APIs:**
    +* Initialize the library with a successful call to `psa_crypto_init()`.
     
    -Generate an ECDSA key:
    +**To generate an ECDSA key:**
     1. Set the desired key attributes for key generation by calling
        `psa_set_key_algorithm()` with the chosen ECDSA algorithm (such as
    -   `PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)`). We don't set
    -   `PSA_KEY_USAGE_EXPORT` as we only want to export the public key, not the key
    -   pair (or private key).
    +   `PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)`). You only want to export the public key, not the key pair (or private key); therefore, do not set `PSA_KEY_USAGE_EXPORT`.
     1. Generate a key by calling `psa_generate_key()`.
    -1. Export the generated public key by calling `psa_export_public_key()`
    -:
    +1. Export the generated public key by calling `psa_export_public_key()`:
     ```C
         enum {
             key_bits = 256,
    @@ -877,8 +881,6 @@ Generate an ECDSA key:
         mbedtls_psa_crypto_free();
     ```
     
    -### More about the Mbed Crypto library
    -
    -More information on [Mbed Crypto](https://github.com/ARMmbed/mbed-crypto/).
    +### More about the PSA Crypto API
     
    -More information on [PSA Crypto](https://github.com/ARMmbed/mbed-crypto/blob/development/docs/PSA_Crypto_API_Overview.pdf).
    +For more information about the PSA Crypto API, please see the [PSA Cryptography API Specification](https://armmbed.github.io/mbed-crypto/html/index.html).
    
  • include/psa/crypto.h+259 12 modified
    @@ -328,6 +328,12 @@ static size_t psa_get_key_bits(const psa_key_attributes_t *attributes);
      * \retval #PSA_ERROR_INVALID_HANDLE
      * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
    + * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_get_key_attributes(psa_key_handle_t handle,
                                         psa_key_attributes_t *attributes);
    @@ -392,7 +398,12 @@ void psa_reset_key_attributes(psa_key_attributes_t *attributes);
      *         define any way to create such a key, but it may be possible
      *         through implementation-specific means.
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
    + * \retval #PSA_ERROR_CORRUPTION_DETECTED
      * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_open_key(psa_key_id_t id,
                               psa_key_handle_t *handle);
    @@ -419,6 +430,11 @@ psa_status_t psa_open_key(psa_key_id_t id,
      * \retval #PSA_SUCCESS
      * \retval #PSA_ERROR_INVALID_HANDLE
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
    + * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_close_key(psa_key_handle_t handle);
     
    @@ -487,6 +503,8 @@ psa_status_t psa_close_key(psa_key_handle_t handle);
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
      * \retval #PSA_ERROR_BAD_STATE
    + *         \p operation is either not initialized or is in use
    + * \retval #PSA_ERROR_BAD_STATE
      *         The library has not been previously initialized by psa_crypto_init().
      *         It is implementation-dependent whether a failure to initialize
      *         results in this error code.
    @@ -602,7 +620,6 @@ psa_status_t psa_destroy_key(psa_key_handle_t handle);
      *
      * \retval #PSA_SUCCESS
      * \retval #PSA_ERROR_INVALID_HANDLE
    - * \retval #PSA_ERROR_DOES_NOT_EXIST
      * \retval #PSA_ERROR_NOT_PERMITTED
      *         The key does not have the #PSA_KEY_USAGE_EXPORT flag.
      * \retval #PSA_ERROR_NOT_SUPPORTED
    @@ -615,6 +632,8 @@ psa_status_t psa_destroy_key(psa_key_handle_t handle);
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
      * \retval #PSA_ERROR_BAD_STATE
      *         The library has not been previously initialized by psa_crypto_init().
      *         It is implementation-dependent whether a failure to initialize
    @@ -671,7 +690,6 @@ psa_status_t psa_export_key(psa_key_handle_t handle,
      *
      * \retval #PSA_SUCCESS
      * \retval #PSA_ERROR_INVALID_HANDLE
    - * \retval #PSA_ERROR_DOES_NOT_EXIST
      * \retval #PSA_ERROR_INVALID_ARGUMENT
      *         The key is neither a public key nor a key pair.
      * \retval #PSA_ERROR_NOT_SUPPORTED
    @@ -684,6 +702,8 @@ psa_status_t psa_export_key(psa_key_handle_t handle,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
      * \retval #PSA_ERROR_BAD_STATE
      *         The library has not been previously initialized by psa_crypto_init().
      *         It is implementation-dependent whether a failure to initialize
    @@ -771,7 +791,12 @@ psa_status_t psa_export_public_key(psa_key_handle_t handle,
      * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_copy_key(psa_key_handle_t source_handle,
                               const psa_key_attributes_t *attributes,
    @@ -802,10 +827,18 @@ psa_status_t psa_copy_key(psa_key_handle_t source_handle,
      *         Success.
      * \retval #PSA_ERROR_NOT_SUPPORTED
      *         \p alg is not supported or is not a hash algorithm.
    + * \retval #PSA_ERROR_INVALID_ARGUMENT
    + * \retval #PSA_ERROR_BUFFER_TOO_SMALL
    + *         \p hash_size is too small
      * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_hash_compute(psa_algorithm_t alg,
                                   const uint8_t *input,
    @@ -831,10 +864,17 @@ psa_status_t psa_hash_compute(psa_algorithm_t alg,
      *         differs from the expected hash.
      * \retval #PSA_ERROR_NOT_SUPPORTED
      *         \p alg is not supported or is not a hash algorithm.
    + * \retval #PSA_ERROR_INVALID_ARGUMENT
    + *         \p input_length or \p hash_length do not match the hash size for \p alg
      * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_hash_compare(psa_algorithm_t alg,
                                   const uint8_t *input,
    @@ -921,14 +961,22 @@ static psa_hash_operation_t psa_hash_operation_init(void);
      * \retval #PSA_SUCCESS
      *         Success.
      * \retval #PSA_ERROR_NOT_SUPPORTED
    - *         \p alg is not supported or is not a hash algorithm.
    + *         \p alg is not a supported hash algorithm.
    + * \retval #PSA_ERROR_INVALID_ARGUMENT
    + *         \p alg is not a hash algorithm.
      * \retval #PSA_ERROR_BAD_STATE
      *         The operation state is not valid (already set up and not
      *         subsequently completed).
      * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_BAD_STATE
    + *         \p operation is either not initialized or is in use
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_hash_setup(psa_hash_operation_t *operation,
                                 psa_algorithm_t alg);
    @@ -951,6 +999,12 @@ psa_status_t psa_hash_setup(psa_hash_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The operation state is not valid.
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_hash_update(psa_hash_operation_t *operation,
                                  const uint8_t *input,
    @@ -992,6 +1046,12 @@ psa_status_t psa_hash_update(psa_hash_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The operation state is not valid.
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_hash_finish(psa_hash_operation_t *operation,
                                  uint8_t *hash,
    @@ -1028,6 +1088,12 @@ psa_status_t psa_hash_finish(psa_hash_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The operation state is not valid.
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_hash_verify(psa_hash_operation_t *operation,
                                  const uint8_t *hash,
    @@ -1059,6 +1125,12 @@ psa_status_t psa_hash_verify(psa_hash_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The operation state is not valid.
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_hash_abort(psa_hash_operation_t *operation);
     
    @@ -1085,6 +1157,15 @@ psa_status_t psa_hash_abort(psa_hash_operation_t *operation);
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The operation state is either not initialized or has already been setup.
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The operation state is either not initialized or has already been setup.
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation,
                                 psa_hash_operation_t *target_operation);
    @@ -1123,10 +1204,14 @@ psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation,
      *         \p handle is not compatible with \p alg.
      * \retval #PSA_ERROR_NOT_SUPPORTED
      *         \p alg is not supported or is not a MAC algorithm.
    + * \retval #PSA_ERROR_BUFFER_TOO_SMALL
    + *         \p mac_size is too small
      * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + *         The key could not be retrieved from storage.
      * \retval #PSA_ERROR_BAD_STATE
      *         The library has not been previously initialized by psa_crypto_init().
      *         It is implementation-dependent whether a failure to initialize
    @@ -1165,6 +1250,12 @@ psa_status_t psa_mac_compute(psa_key_handle_t handle,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + *         The key could not be retrieved from storage.
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_mac_verify(psa_key_handle_t handle,
                                 psa_algorithm_t alg,
    @@ -1258,7 +1349,6 @@ static psa_mac_operation_t psa_mac_operation_init(void);
      * \retval #PSA_SUCCESS
      *         Success.
      * \retval #PSA_ERROR_INVALID_HANDLE
    - * \retval #PSA_ERROR_DOES_NOT_EXIST
      * \retval #PSA_ERROR_NOT_PERMITTED
      * \retval #PSA_ERROR_INVALID_ARGUMENT
      *         \p handle is not compatible with \p alg.
    @@ -1268,6 +1358,8 @@ static psa_mac_operation_t psa_mac_operation_init(void);
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + *         The key could not be retrieved from storage.
      * \retval #PSA_ERROR_BAD_STATE
      *         The operation state is not valid (already set up and not
      *         subsequently completed).
    @@ -1318,7 +1410,6 @@ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation,
      * \retval #PSA_SUCCESS
      *         Success.
      * \retval #PSA_ERROR_INVALID_HANDLE
    - * \retval #PSA_ERROR_DOES_NOT_EXIST
      * \retval #PSA_ERROR_NOT_PERMITTED
      * \retval #PSA_ERROR_INVALID_ARGUMENT
      *         \c key is not compatible with \c alg.
    @@ -1328,6 +1419,8 @@ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + *         The key could not be retrieved from storage
      * \retval #PSA_ERROR_BAD_STATE
      *         The operation state is not valid (already set up and not
      *         subsequently completed).
    @@ -1360,6 +1453,11 @@ psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_mac_update(psa_mac_operation_t *operation,
                                 const uint8_t *input,
    @@ -1402,6 +1500,11 @@ psa_status_t psa_mac_update(psa_mac_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation,
                                      uint8_t *mac,
    @@ -1438,6 +1541,11 @@ psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation,
                                        const uint8_t *mac,
    @@ -1470,6 +1578,10 @@ psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_mac_abort(psa_mac_operation_t *operation);
     
    @@ -1512,6 +1624,11 @@ psa_status_t psa_mac_abort(psa_mac_operation_t *operation);
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_cipher_encrypt(psa_key_handle_t handle,
                                     psa_algorithm_t alg,
    @@ -1552,7 +1669,12 @@ psa_status_t psa_cipher_encrypt(psa_key_handle_t handle,
      * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_cipher_decrypt(psa_key_handle_t handle,
                                     psa_algorithm_t alg,
    @@ -1648,7 +1770,6 @@ static psa_cipher_operation_t psa_cipher_operation_init(void);
      * \retval #PSA_SUCCESS
      *         Success.
      * \retval #PSA_ERROR_INVALID_HANDLE
    - * \retval #PSA_ERROR_DOES_NOT_EXIST
      * \retval #PSA_ERROR_NOT_PERMITTED
      * \retval #PSA_ERROR_INVALID_ARGUMENT
      *         \p handle is not compatible with \p alg.
    @@ -1658,6 +1779,7 @@ static psa_cipher_operation_t psa_cipher_operation_init(void);
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_BAD_STATE
      *         The operation state is not valid (already set up and not
      *         subsequently completed).
    @@ -1710,7 +1832,6 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,
      * \retval #PSA_SUCCESS
      *         Success.
      * \retval #PSA_ERROR_INVALID_HANDLE
    - * \retval #PSA_ERROR_DOES_NOT_EXIST
      * \retval #PSA_ERROR_NOT_PERMITTED
      * \retval #PSA_ERROR_INVALID_ARGUMENT
      *         \p handle is not compatible with \p alg.
    @@ -1720,6 +1841,7 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_BAD_STATE
      *         The operation state is not valid (already set up and not
      *         subsequently completed).
    @@ -1759,6 +1881,11 @@ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation,
                                         uint8_t *iv,
    @@ -1794,6 +1921,11 @@ psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation,
                                    const uint8_t *iv,
    @@ -1830,6 +1962,11 @@ psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_cipher_update(psa_cipher_operation_t *operation,
                                    const uint8_t *input,
    @@ -1868,6 +2005,11 @@ psa_status_t psa_cipher_update(psa_cipher_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation,
                                    uint8_t *output,
    @@ -1901,6 +2043,10 @@ psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation);
     
    @@ -1941,16 +2087,18 @@ psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation);
      * \retval #PSA_SUCCESS
      *         Success.
      * \retval #PSA_ERROR_INVALID_HANDLE
    - * \retval #PSA_ERROR_DOES_NOT_EXIST
      * \retval #PSA_ERROR_NOT_PERMITTED
      * \retval #PSA_ERROR_INVALID_ARGUMENT
      *         \p handle is not compatible with \p alg.
      * \retval #PSA_ERROR_NOT_SUPPORTED
      *         \p alg is not supported or is not an AEAD algorithm.
      * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
    + * \retval #PSA_ERROR_BUFFER_TOO_SMALL
    + *         \p ciphertext_size is too small
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_BAD_STATE
      *         The library has not been previously initialized by psa_crypto_init().
      *         It is implementation-dependent whether a failure to initialize
    @@ -1997,7 +2145,6 @@ psa_status_t psa_aead_encrypt(psa_key_handle_t handle,
      * \retval #PSA_SUCCESS
      *         Success.
      * \retval #PSA_ERROR_INVALID_HANDLE
    - * \retval #PSA_ERROR_DOES_NOT_EXIST
      * \retval #PSA_ERROR_INVALID_SIGNATURE
      *         The ciphertext is not authentic.
      * \retval #PSA_ERROR_NOT_PERMITTED
    @@ -2006,9 +2153,12 @@ psa_status_t psa_aead_encrypt(psa_key_handle_t handle,
      * \retval #PSA_ERROR_NOT_SUPPORTED
      *         \p alg is not supported or is not an AEAD algorithm.
      * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
    + * \retval #PSA_ERROR_BUFFER_TOO_SMALL
    + *         \p plaintext_size or \p nonce_length is too small
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_BAD_STATE
      *         The library has not been previously initialized by psa_crypto_init().
      *         It is implementation-dependent whether a failure to initialize
    @@ -2127,6 +2277,7 @@ static psa_aead_operation_t psa_aead_operation_init(void);
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_BAD_STATE
      *         The library has not been previously initialized by psa_crypto_init().
      *         It is implementation-dependent whether a failure to initialize
    @@ -2188,6 +2339,7 @@ psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_BAD_STATE
      *         The library has not been previously initialized by psa_crypto_init().
      *         It is implementation-dependent whether a failure to initialize
    @@ -2225,6 +2377,11 @@ psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation,
                                          uint8_t *nonce,
    @@ -2259,6 +2416,11 @@ psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation,
                                     const uint8_t *nonce,
    @@ -2297,6 +2459,10 @@ psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation,
                                       size_t ad_length,
    @@ -2339,6 +2505,11 @@ psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation,
                                     const uint8_t *input,
    @@ -2411,6 +2582,11 @@ psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_aead_update(psa_aead_operation_t *operation,
                                  const uint8_t *input,
    @@ -2480,6 +2656,11 @@ psa_status_t psa_aead_update(psa_aead_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_aead_finish(psa_aead_operation_t *operation,
                                  uint8_t *ciphertext,
    @@ -2538,6 +2719,11 @@ psa_status_t psa_aead_finish(psa_aead_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_aead_verify(psa_aead_operation_t *operation,
                                  uint8_t *plaintext,
    @@ -2573,6 +2759,10 @@ psa_status_t psa_aead_verify(psa_aead_operation_t *operation,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_aead_abort(psa_aead_operation_t *operation);
     
    @@ -2603,6 +2793,8 @@ psa_status_t psa_aead_abort(psa_aead_operation_t *operation);
      *                              that make up the returned signature value.
      *
      * \retval #PSA_SUCCESS
    + * \retval #PSA_ERROR_INVALID_HANDLE
    + * \retval #PSA_ERROR_NOT_PERMITTED
      * \retval #PSA_ERROR_BUFFER_TOO_SMALL
      *         The size of the \p signature buffer is too small. You can
      *         determine a sufficient buffer size by calling
    @@ -2615,6 +2807,7 @@ psa_status_t psa_aead_abort(psa_aead_operation_t *operation);
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
      * \retval #PSA_ERROR_BAD_STATE
      *         The library has not been previously initialized by psa_crypto_init().
    @@ -2650,6 +2843,8 @@ psa_status_t psa_asymmetric_sign(psa_key_handle_t handle,
      *
      * \retval #PSA_SUCCESS
      *         The signature is valid.
    + * \retval #PSA_ERROR_INVALID_HANDLE
    + * \retval #PSA_ERROR_NOT_PERMITTED
      * \retval #PSA_ERROR_INVALID_SIGNATURE
      *         The calculation was perfomed successfully, but the passed
      *         signature is not a valid signature.
    @@ -2659,6 +2854,7 @@ psa_status_t psa_asymmetric_sign(psa_key_handle_t handle,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_BAD_STATE
      *         The library has not been previously initialized by psa_crypto_init().
      *         It is implementation-dependent whether a failure to initialize
    @@ -2700,6 +2896,8 @@ psa_status_t psa_asymmetric_verify(psa_key_handle_t handle,
      *                              that make up the returned output.
      *
      * \retval #PSA_SUCCESS
    + * \retval #PSA_ERROR_INVALID_HANDLE
    + * \retval #PSA_ERROR_NOT_PERMITTED
      * \retval #PSA_ERROR_BUFFER_TOO_SMALL
      *         The size of the \p output buffer is too small. You can
      *         determine a sufficient buffer size by calling
    @@ -2712,6 +2910,7 @@ psa_status_t psa_asymmetric_verify(psa_key_handle_t handle,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
      * \retval #PSA_ERROR_BAD_STATE
      *         The library has not been previously initialized by psa_crypto_init().
    @@ -2756,6 +2955,8 @@ psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle,
      *                              that make up the returned output.
      *
      * \retval #PSA_SUCCESS
    + * \retval #PSA_ERROR_INVALID_HANDLE
    + * \retval #PSA_ERROR_NOT_PERMITTED
      * \retval #PSA_ERROR_BUFFER_TOO_SMALL
      *         The size of the \p output buffer is too small. You can
      *         determine a sufficient buffer size by calling
    @@ -2768,6 +2969,7 @@ psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
      * \retval #PSA_ERROR_INVALID_PADDING
      * \retval #PSA_ERROR_BAD_STATE
    @@ -2881,7 +3083,13 @@ static psa_key_derivation_operation_t psa_key_derivation_operation_init(void);
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_BAD_STATE
    + *         The operation state is either not initialized or has already been setup.
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_key_derivation_setup(
         psa_key_derivation_operation_t *operation,
    @@ -2897,8 +3105,15 @@ psa_status_t psa_key_derivation_setup(
      * \param[out] capacity     On success, the capacity of the operation.
      *
      * \retval #PSA_SUCCESS
    - * \retval #PSA_ERROR_BAD_STATE
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The operation state is not valid.
    + * \retval #PSA_ERROR_HARDWARE_FAILURE
    + * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_key_derivation_get_capacity(
         const psa_key_derivation_operation_t *operation,
    @@ -2920,7 +3135,14 @@ psa_status_t psa_key_derivation_get_capacity(
      *         In this case, the operation object remains valid and its capacity
      *         remains unchanged.
      * \retval #PSA_ERROR_BAD_STATE
    + *         The operation state is not valid.
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
    + * \retval #PSA_ERROR_HARDWARE_FAILURE
    + * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_key_derivation_set_capacity(
         psa_key_derivation_operation_t *operation,
    @@ -2963,6 +3185,7 @@ psa_status_t psa_key_derivation_set_capacity(
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_BAD_STATE
      *         The value of \p step is not valid given the state of \p operation.
      * \retval #PSA_ERROR_BAD_STATE
    @@ -2999,7 +3222,6 @@ psa_status_t psa_key_derivation_input_bytes(
      * \retval #PSA_SUCCESS
      *         Success.
      * \retval #PSA_ERROR_INVALID_HANDLE
    - * \retval #PSA_ERROR_DOES_NOT_EXIST
      * \retval #PSA_ERROR_NOT_PERMITTED
      * \retval #PSA_ERROR_INVALID_ARGUMENT
      *         \c step is not compatible with the operation's algorithm.
    @@ -3009,6 +3231,7 @@ psa_status_t psa_key_derivation_input_bytes(
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_BAD_STATE
      *         The value of \p step is not valid given the state of \p operation.
      * \retval #PSA_ERROR_BAD_STATE
    @@ -3061,7 +3284,6 @@ psa_status_t psa_key_derivation_input_key(
      * \retval #PSA_SUCCESS
      *         Success.
      * \retval #PSA_ERROR_INVALID_HANDLE
    - * \retval #PSA_ERROR_DOES_NOT_EXIST
      * \retval #PSA_ERROR_NOT_PERMITTED
      * \retval #PSA_ERROR_INVALID_ARGUMENT
      *         \c private_key is not compatible with \c alg,
    @@ -3073,6 +3295,11 @@ psa_status_t psa_key_derivation_input_key(
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_key_derivation_key_agreement(
         psa_key_derivation_operation_t *operation,
    @@ -3107,6 +3334,11 @@ psa_status_t psa_key_derivation_key_agreement(
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_key_derivation_output_bytes(
         psa_key_derivation_operation_t *operation,
    @@ -3224,6 +3456,7 @@ psa_status_t psa_key_derivation_output_bytes(
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_BAD_STATE
      *         The library has not been previously initialized by psa_crypto_init().
      *         It is implementation-dependent whether a failure to initialize
    @@ -3255,6 +3488,10 @@ psa_status_t psa_key_derivation_output_key(
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_key_derivation_abort(
         psa_key_derivation_operation_t *operation);
    @@ -3295,12 +3532,19 @@ psa_status_t psa_key_derivation_abort(
      *         \p private_key is not compatible with \p alg,
      *         or \p peer_key is not valid for \p alg or not compatible with
      *         \p private_key.
    + * \retval #PSA_ERROR_BUFFER_TOO_SMALL
    + *         \p output_size is too small
      * \retval #PSA_ERROR_NOT_SUPPORTED
      *         \p alg is not a supported key agreement algorithm.
      * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_STORAGE_FAILURE
    + * \retval #PSA_ERROR_BAD_STATE
    + *         The library has not been previously initialized by psa_crypto_init().
    + *         It is implementation-dependent whether a failure to initialize
    + *         results in this error code.
      */
     psa_status_t psa_raw_key_agreement(psa_algorithm_t alg,
                                        psa_key_handle_t private_key,
    @@ -3331,6 +3575,7 @@ psa_status_t psa_raw_key_agreement(psa_algorithm_t alg,
      * \retval #PSA_SUCCESS
      * \retval #PSA_ERROR_NOT_SUPPORTED
      * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY
    + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    @@ -3373,6 +3618,8 @@ psa_status_t psa_generate_random(uint8_t *output,
      * \retval #PSA_ERROR_COMMUNICATION_FAILURE
      * \retval #PSA_ERROR_HARDWARE_FAILURE
      * \retval #PSA_ERROR_CORRUPTION_DETECTED
    + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
    + * \retval #PSA_ERROR_STORAGE_FAILURE
      * \retval #PSA_ERROR_BAD_STATE
      *         The library has not been previously initialized by psa_crypto_init().
      *         It is implementation-dependent whether a failure to initialize
    
  • library/bignum.c+8 3 modified
    @@ -742,10 +742,15 @@ int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE
     static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
     {
         uint8_t i;
    +    unsigned char *x_ptr;
         mbedtls_mpi_uint tmp = 0;
    -    /* This works regardless of the endianness. */
    -    for( i = 0; i < ciL; i++, x >>= 8 )
    -        tmp |= ( x & 0xFF ) << ( ( ciL - 1 - i ) << 3 );
    +
    +    for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
    +    {
    +        tmp <<= CHAR_BIT;
    +        tmp |= (mbedtls_mpi_uint) *x_ptr;
    +    }
    +
         return( tmp );
     }
     
    
  • library/platform_util.c+4 1 modified
    @@ -72,7 +72,10 @@ static void * (* const volatile memset_func)( void *, int, size_t ) = memset;
     
     void mbedtls_platform_zeroize( void *buf, size_t len )
     {
    -    memset_func( buf, 0, len );
    +    MBEDTLS_INTERNAL_VALIDATE( len == 0 || buf != NULL );
    +
    +    if( len > 0 )
    +        memset_func( buf, 0, len );
     }
     #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */
     
    
  • library/psa_its_file.c+6 3 modified
    @@ -214,9 +214,12 @@ psa_status_t psa_its_set( psa_storage_uid_t uid,
         n = fwrite( &header, 1, sizeof( header ), stream );
         if( n != sizeof( header ) )
             goto exit;
    -    n = fwrite( p_data, 1, data_length, stream );
    -    if( n != data_length )
    -        goto exit;
    +    if( data_length != 0 )
    +    {
    +        n = fwrite( p_data, 1, data_length, stream );
    +        if( n != data_length )
    +            goto exit;
    +    }
         status = PSA_SUCCESS;
     
     exit:
    
  • tests/scripts/all.sh+1 1 modified
    @@ -701,7 +701,7 @@ component_test_no_use_psa_crypto_full_cmake_asan() {
         # full minus MBEDTLS_USE_PSA_CRYPTO: run the same set of tests as basic-build-test.sh
         msg "build: cmake, full config + MBEDTLS_USE_PSA_CRYPTO, ASan"
         scripts/config.pl full
    -    scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
    +    scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
         scripts/config.pl set MBEDTLS_ECP_RESTARTABLE  # not using PSA, so enable restartable ECC
         scripts/config.pl set MBEDTLS_PSA_CRYPTO_C
         scripts/config.pl unset MBEDTLS_USE_PSA_CRYPTO
    
33f66ba6fd23

Merge remote-tracking branch 'upstream-restricted/pr/556' into mbedtls-2.16-restricted

https://github.com/mbed-tls/mbedtlsGilles PeskineAug 14, 2019via osv
5 files changed · +220 15
  • ChangeLog+10 0 modified
    @@ -6,6 +6,16 @@ Security
        * Fix a missing error detection in ECJPAKE. This could have caused a
          predictable shared secret if a hardware accelerator failed and the other
          side of the key exchange had a similar bug.
    +   * The deterministic ECDSA calculation reused the scheme's HMAC-DRBG to
    +     implement blinding. Because of this for the same key and message the same
    +     blinding value was generated. This reduced the effectiveness of the
    +     countermeasure and leaked information about the private key through side
    +     channels. Reported by Jack Lloyd.
    +
    +API Changes
    +   * The new function mbedtls_ecdsa_sign_det_ext() is similar to
    +     mbedtls_ecdsa_sign_det() but allows passing an external RNG for the
    +     purpose of blinding.
     
     Bugfix
        * Fix to allow building test suites with any warning that detects unused
    
  • include/mbedtls/config.h+10 0 modified
    @@ -440,6 +440,16 @@
      *            dependencies on them, and considering stronger message digests
      *            and ciphers instead.
      *
    + * \warning   If both MBEDTLS_ECDSA_SIGN_ALT and MBEDTLS_ECDSA_DETERMINISTIC are
    + *            enabled, then the deterministic ECDH signature functions pass the
    + *            the static HMAC-DRBG as RNG to mbedtls_ecdsa_sign(). Therefore
    + *            alternative implementations should use the RNG only for generating
    + *            the ephemeral key and nothing else. If this is not possible, then
    + *            MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative
    + *            implementation should be provided for mbedtls_ecdsa_sign_det_ext()
    + *            (and for mbedtls_ecdsa_sign_det() too if backward compatibility is
    + *            desirable).
    + *
      */
     //#define MBEDTLS_MD2_PROCESS_ALT
     //#define MBEDTLS_MD4_PROCESS_ALT
    
  • include/mbedtls/ecdsa.h+59 0 modified
    @@ -175,6 +175,19 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
      *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section
      *                  4.1.3, step 5.
      *
    + * \warning         Since the output of the internal RNG is always the same for
    + *                  the same key and message, this limits the efficiency of
    + *                  blinding and leaks information through side channels. For
    + *                  secure behavior use mbedtls_ecdsa_sign_det_ext() instead.
    + *
    + *                  (Optimally the blinding is a random value that is different
    + *                  on every execution. In this case the blinding is still
    + *                  random from the attackers perspective, but is the same on
    + *                  each execution. This means that this blinding does not
    + *                  prevent attackers from recovering secrets by combining
    + *                  several measurement traces, but may prevent some attacks
    + *                  that exploit relationships between secret data.)
    + *
      * \see             ecp.h
      *
      * \param grp       The context for the elliptic curve to use.
    @@ -200,6 +213,52 @@ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r,
                                 mbedtls_mpi *s, const mbedtls_mpi *d,
                                 const unsigned char *buf, size_t blen,
                                 mbedtls_md_type_t md_alg );
    +/**
    + * \brief           This function computes the ECDSA signature of a
    + *                  previously-hashed message, deterministic version.
    + *
    + *                  For more information, see <em>RFC-6979: Deterministic
    + *                  Usage of the Digital Signature Algorithm (DSA) and Elliptic
    + *                  Curve Digital Signature Algorithm (ECDSA)</em>.
    + *
    + * \note            If the bitlength of the message hash is larger than the
    + *                  bitlength of the group order, then the hash is truncated as
    + *                  defined in <em>Standards for Efficient Cryptography Group
    + *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section
    + *                  4.1.3, step 5.
    + *
    + * \see             ecp.h
    + *
    + * \param grp           The context for the elliptic curve to use.
    + *                      This must be initialized and have group parameters
    + *                      set, for example through mbedtls_ecp_group_load().
    + * \param r             The MPI context in which to store the first part
    + *                      the signature. This must be initialized.
    + * \param s             The MPI context in which to store the second part
    + *                      the signature. This must be initialized.
    + * \param d             The private signing key. This must be initialized
    + *                      and setup, for example through mbedtls_ecp_gen_privkey().
    + * \param buf           The hashed content to be signed. This must be a readable
    + *                      buffer of length \p blen Bytes. It may be \c NULL if
    + *                      \p blen is zero.
    + * \param blen          The length of \p buf in Bytes.
    + * \param md_alg        The hash algorithm used to hash the original data.
    + * \param f_rng_blind   The RNG function used for blinding. This must not be
    + *                      \c NULL.
    + * \param p_rng_blind   The RNG context to be passed to \p f_rng. This may be
    + *                      \c NULL if \p f_rng doesn't need a context parameter.
    + *
    + * \return          \c 0 on success.
    + * \return          An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX
    + *                  error code on failure.
    + */
    +int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r,
    +                                mbedtls_mpi *s, const mbedtls_mpi *d,
    +                                const unsigned char *buf, size_t blen,
    +                                mbedtls_md_type_t md_alg,
    +                                int (*f_rng_blind)(void *, unsigned char *,
    +                                                   size_t),
    +                                void *p_rng_blind );
     #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
     
     /**
    
  • library/ecdsa.c+106 15 modified
    @@ -254,6 +254,8 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp,
                     mbedtls_mpi *r, mbedtls_mpi *s,
                     const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
                     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
    +                int (*f_rng_blind)(void *, unsigned char *, size_t),
    +                void *p_rng_blind,
                     mbedtls_ecdsa_restart_ctx *rs_ctx )
     {
         int ret, key_tries, sign_tries;
    @@ -323,7 +325,9 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp,
     mul:
     #endif
                 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G,
    -                                                  f_rng, p_rng, ECDSA_RS_ECP ) );
    +                                                          f_rng_blind,
    +                                                          p_rng_blind,
    +                                                          ECDSA_RS_ECP ) );
                 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) );
             }
             while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 );
    @@ -349,7 +353,8 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp,
              * Generate a random value to blind inv_mod in next step,
              * avoiding a potential timing leak.
              */
    -        MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng, p_rng ) );
    +        MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng_blind,
    +                                                  p_rng_blind ) );
     
             /*
              * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
    @@ -392,8 +397,9 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
         ECDSA_VALIDATE_RET( f_rng != NULL );
         ECDSA_VALIDATE_RET( buf   != NULL || blen == 0 );
     
    +    /* Use the same RNG for both blinding and ephemeral key generation */
         return( ecdsa_sign_restartable( grp, r, s, d, buf, blen,
    -                                    f_rng, p_rng, NULL ) );
    +                                    f_rng, p_rng, f_rng, p_rng, NULL ) );
     }
     #endif /* !MBEDTLS_ECDSA_SIGN_ALT */
     
    @@ -405,6 +411,8 @@ static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp,
                         mbedtls_mpi *r, mbedtls_mpi *s,
                         const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
                         mbedtls_md_type_t md_alg,
    +                    int (*f_rng_blind)(void *, unsigned char *, size_t),
    +                    void *p_rng_blind,
                         mbedtls_ecdsa_restart_ctx *rs_ctx )
     {
         int ret;
    @@ -451,8 +459,70 @@ static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp,
         ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen,
                                   mbedtls_hmac_drbg_random, p_rng );
     #else
    -    ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen,
    -                      mbedtls_hmac_drbg_random, p_rng, rs_ctx );
    +    if( f_rng_blind != NULL )
    +        ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen,
    +                                      mbedtls_hmac_drbg_random, p_rng,
    +                                      f_rng_blind, p_rng_blind, rs_ctx );
    +    else
    +    {
    +        mbedtls_hmac_drbg_context *p_rng_blind_det;
    +
    +#if !defined(MBEDTLS_ECP_RESTARTABLE)
    +        /*
    +         * To avoid reusing rng_ctx and risking incorrect behavior we seed a
    +         * second HMAC-DRBG with the same seed. We also apply a label to avoid
    +         * reusing the bits of the ephemeral key for blinding and eliminate the
    +         * risk that they leak this way.
    +         */
    +        const char* blind_label = "BLINDING CONTEXT";
    +        mbedtls_hmac_drbg_context rng_ctx_blind;
    +
    +        mbedtls_hmac_drbg_init( &rng_ctx_blind );
    +        p_rng_blind_det = &rng_ctx_blind;
    +
    +        mbedtls_hmac_drbg_seed_buf( p_rng_blind_det, md_info,
    +                                    data, 2 * grp_len );
    +        ret = mbedtls_hmac_drbg_update_ret( p_rng_blind_det,
    +                                            (const unsigned char*) blind_label,
    +                                            strlen( blind_label ) );
    +        if( ret != 0 )
    +        {
    +            mbedtls_hmac_drbg_free( &rng_ctx_blind );
    +            goto cleanup;
    +        }
    +#else
    +        /*
    +         * In the case of restartable computations we would either need to store
    +         * the second RNG in the restart context too or set it up at every
    +         * restart. The first option would penalize the correct application of
    +         * the function and the second would defeat the purpose of the
    +         * restartable feature.
    +         *
    +         * Therefore in this case we reuse the original RNG. This comes with the
    +         * price that the resulting signature might not be a valid deterministic
    +         * ECDSA signature with a very low probability (same magnitude as
    +         * successfully guessing the private key). However even then it is still
    +         * a valid ECDSA signature.
    +         */
    +        p_rng_blind_det = p_rng;
    +#endif /* MBEDTLS_ECP_RESTARTABLE */
    +
    +        /*
    +         * Since the output of the RNGs is always the same for the same key and
    +         * message, this limits the efficiency of blinding and leaks information
    +         * through side channels. After mbedtls_ecdsa_sign_det() is removed NULL
    +         * won't be a valid value for f_rng_blind anymore. Therefore it should
    +         * be checked by the caller and this branch and check can be removed.
    +         */
    +        ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen,
    +                                      mbedtls_hmac_drbg_random, p_rng,
    +                                      mbedtls_hmac_drbg_random, p_rng_blind_det,
    +                                      rs_ctx );
    +
    +#if !defined(MBEDTLS_ECP_RESTARTABLE)
    +        mbedtls_hmac_drbg_free( &rng_ctx_blind );
    +#endif
    +    }
     #endif /* MBEDTLS_ECDSA_SIGN_ALT */
     
     cleanup:
    @@ -465,19 +535,40 @@ static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp,
     }
     
     /*
    - * Deterministic signature wrapper
    + * Deterministic signature wrappers
      */
    -int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
    -                    const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
    -                    mbedtls_md_type_t md_alg )
    +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r,
    +                            mbedtls_mpi *s, const mbedtls_mpi *d,
    +                            const unsigned char *buf, size_t blen,
    +                            mbedtls_md_type_t md_alg )
    +{
    +    ECDSA_VALIDATE_RET( grp   != NULL );
    +    ECDSA_VALIDATE_RET( r     != NULL );
    +    ECDSA_VALIDATE_RET( s     != NULL );
    +    ECDSA_VALIDATE_RET( d     != NULL );
    +    ECDSA_VALIDATE_RET( buf   != NULL || blen == 0 );
    +
    +    return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg,
    +                                        NULL, NULL, NULL ) );
    +}
    +
    +int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r,
    +                                mbedtls_mpi *s, const mbedtls_mpi *d,
    +                                const unsigned char *buf, size_t blen,
    +                                mbedtls_md_type_t md_alg,
    +                                int (*f_rng_blind)(void *, unsigned char *,
    +                                                   size_t),
    +                                void *p_rng_blind )
     {
         ECDSA_VALIDATE_RET( grp   != NULL );
         ECDSA_VALIDATE_RET( r     != NULL );
         ECDSA_VALIDATE_RET( s     != NULL );
         ECDSA_VALIDATE_RET( d     != NULL );
         ECDSA_VALIDATE_RET( buf   != NULL || blen == 0 );
    +    ECDSA_VALIDATE_RET( f_rng_blind != NULL );
     
    -    return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, NULL ) );
    +    return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg,
    +                                        f_rng_blind, p_rng_blind, NULL ) );
     }
     #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
     
    @@ -656,20 +747,20 @@ int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
         mbedtls_mpi_init( &s );
     
     #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
    -    (void) f_rng;
    -    (void) p_rng;
    -
         MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d,
    -                             hash, hlen, md_alg, rs_ctx ) );
    +                                                 hash, hlen, md_alg, f_rng,
    +                                                 p_rng, rs_ctx ) );
     #else
         (void) md_alg;
     
     #if defined(MBEDTLS_ECDSA_SIGN_ALT)
         MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
                              hash, hlen, f_rng, p_rng ) );
     #else
    +    /* Use the same RNG for both blinding and ephemeral key generation */
         MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d,
    -                         hash, hlen, f_rng, p_rng, rs_ctx ) );
    +                                             hash, hlen, f_rng, p_rng, f_rng,
    +                                             p_rng, rs_ctx ) );
     #endif /* MBEDTLS_ECDSA_SIGN_ALT */
     #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
     
    
  • tests/suites/test_suite_ecdsa.function+35 0 modified
    @@ -74,6 +74,31 @@ void ecdsa_invalid_param( )
                            mbedtls_ecdsa_sign_det( &grp, &m, &m, &m,
                                                     NULL, sizeof( buf ),
                                                     valid_md ) );
    +    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
    +                       mbedtls_ecdsa_sign_det_ext( NULL, &m, &m, &m,
    +                                                   buf, sizeof( buf ),
    +                                                   valid_md,
    +                                                   rnd_std_rand, NULL ) );
    +    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
    +                       mbedtls_ecdsa_sign_det_ext( &grp, NULL, &m, &m,
    +                                                   buf, sizeof( buf ),
    +                                                   valid_md,
    +                                                   rnd_std_rand, NULL ) );
    +    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
    +                       mbedtls_ecdsa_sign_det_ext( &grp, &m, NULL, &m,
    +                                                   buf, sizeof( buf ),
    +                                                   valid_md,
    +                                                   rnd_std_rand, NULL ) );
    +    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
    +                       mbedtls_ecdsa_sign_det_ext( &grp, &m, &m, NULL,
    +                                                   buf, sizeof( buf ),
    +                                                   valid_md,
    +                                                   rnd_std_rand, NULL ) );
    +    TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
    +                       mbedtls_ecdsa_sign_det_ext( &grp, &m, &m, &m,
    +                                                   NULL, sizeof( buf ),
    +                                                   valid_md,
    +                                                   rnd_std_rand, NULL ) );
     #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
     
         TEST_INVALID_PARAM_RET( MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
    @@ -330,6 +355,16 @@ void ecdsa_det_test_vectors( int id, char * d_str, int md_alg, char * msg,
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &r, &r_check ) == 0 );
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &s, &s_check ) == 0 );
     
    +    mbedtls_mpi_free( &r ); mbedtls_mpi_free( &s );
    +    mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s );
    +
    +    TEST_ASSERT(
    +                mbedtls_ecdsa_sign_det_ext( &grp, &r, &s, &d, hash, hlen,
    +                                            md_alg, rnd_std_rand, NULL )
    +                == 0 );
    +
    +    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &r, &r_check ) == 0 );
    +    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &s, &s_check ) == 0 );
     exit:
         mbedtls_ecp_group_free( &grp );
         mbedtls_mpi_free( &d ); mbedtls_mpi_free( &r ); mbedtls_mpi_free( &s );
    
298a43a77ec0

Merge remote-tracking branch 'upstream-restricted/pr/549' into mbedtls-2.7-restricted

https://github.com/mbed-tls/mbedtlsGilles PeskineAug 14, 2019via osv
7 files changed · +238 34
  • ChangeLog+12 0 modified
    @@ -6,6 +6,18 @@ Security
        * Fix a missing error detection in ECJPAKE. This could have caused a
          predictable shared secret if a hardware accelerator failed and the other
          side of the key exchange had a similar bug.
    +   * The deterministic ECDSA calculation reused the scheme's HMAC-DRBG to
    +     implement blinding. Because of this for the same key and message the same
    +     blinding value was generated. This reduced the effectiveness of the
    +     countermeasure and leaked information about the private key through side
    +     channels. Reported by Jack Lloyd.
    +
    +API Changes
    +   * The new function mbedtls_ecdsa_sign_det_ext() is similar to
    +     mbedtls_ecdsa_sign_det() but allows passing an external RNG for the
    +     purpose of blinding.
    +   * The new function mbedtls_ecp_gen_privkey() allows to generate a private
    +     key without generating the public part of the pair.
     
     Bugfix
        * Fix to allow building test suites with any warning that detects unused
    
  • include/mbedtls/config.h+10 0 modified
    @@ -333,6 +333,16 @@
      *            dependencies on them, and considering stronger message digests
      *            and ciphers instead.
      *
    + * \warning   If both MBEDTLS_ECDSA_SIGN_ALT and MBEDTLS_ECDSA_DETERMINISTIC are
    + *            enabled, then the deterministic ECDH signature functions pass the
    + *            the static HMAC-DRBG as RNG to mbedtls_ecdsa_sign(). Therefore
    + *            alternative implementations should use the RNG only for generating
    + *            the ephemeral key and nothing else. If this is not possible, then
    + *            MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative
    + *            implementation should be provided for mbedtls_ecdsa_sign_det_ext()
    + *            (and for mbedtls_ecdsa_sign_det() too if backward compatibility is
    + *            desirable).
    + *
      */
     //#define MBEDTLS_MD2_PROCESS_ALT
     //#define MBEDTLS_MD4_PROCESS_ALT
    
  • include/mbedtls/ecdsa.h+64 3 modified
    @@ -107,6 +107,20 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
      *                  Usage of the Digital Signature Algorithm (DSA) and Elliptic
      *                  Curve Digital Signature Algorithm (ECDSA)</em>.
      *
    + *
    + * \warning         Since the output of the internal RNG is always the same for
    + *                  the same key and message, this limits the efficiency of
    + *                  blinding and leaks information through side channels. For
    + *                  secure behavior use mbedtls_ecdsa_sign_det_ext() instead.
    + *
    + *                  (Optimally the blinding is a random value that is different
    + *                  on every execution. In this case the blinding is still
    + *                  random from the attackers perspective, but is the same on
    + *                  each execution. This means that this blinding does not
    + *                  prevent attackers from recovering secrets by combining
    + *                  several measurement traces, but may prevent some attacks
    + *                  that exploit relationships between secret data.)
    + *
      * \param grp       The ECP group.
      * \param r         The first output integer.
      * \param s         The second output integer.
    @@ -127,9 +141,56 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
      *
      * \see             ecp.h
      */
    -int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
    -                    const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
    -                    mbedtls_md_type_t md_alg );
    +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r,
    +                            mbedtls_mpi *s, const mbedtls_mpi *d,
    +                            const unsigned char *buf, size_t blen,
    +                            mbedtls_md_type_t md_alg );
    +/**
    + * \brief           This function computes the ECDSA signature of a
    + *                  previously-hashed message, deterministic version.
    + *
    + *                  For more information, see <em>RFC-6979: Deterministic
    + *                  Usage of the Digital Signature Algorithm (DSA) and Elliptic
    + *                  Curve Digital Signature Algorithm (ECDSA)</em>.
    + *
    + * \note            If the bitlength of the message hash is larger than the
    + *                  bitlength of the group order, then the hash is truncated as
    + *                  defined in <em>Standards for Efficient Cryptography Group
    + *                  (SECG): SEC1 Elliptic Curve Cryptography</em>, section
    + *                  4.1.3, step 5.
    + *
    + * \see             ecp.h
    + *
    + * \param grp           The context for the elliptic curve to use.
    + *                      This must be initialized and have group parameters
    + *                      set, for example through mbedtls_ecp_group_load().
    + * \param r             The MPI context in which to store the first part
    + *                      the signature. This must be initialized.
    + * \param s             The MPI context in which to store the second part
    + *                      the signature. This must be initialized.
    + * \param d             The private signing key. This must be initialized
    + *                      and setup, for example through mbedtls_ecp_gen_privkey().
    + * \param buf           The hashed content to be signed. This must be a readable
    + *                      buffer of length \p blen Bytes. It may be \c NULL if
    + *                      \p blen is zero.
    + * \param blen          The length of \p buf in Bytes.
    + * \param md_alg        The hash algorithm used to hash the original data.
    + * \param f_rng_blind   The RNG function used for blinding. This must not be
    + *                      \c NULL.
    + * \param p_rng_blind   The RNG context to be passed to \p f_rng. This may be
    + *                      \c NULL if \p f_rng doesn't need a context parameter.
    + *
    + * \return          \c 0 on success.
    + * \return          An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX
    + *                  error code on failure.
    + */
    +int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r,
    +                                mbedtls_mpi *s, const mbedtls_mpi *d,
    +                                const unsigned char *buf, size_t blen,
    +                                mbedtls_md_type_t md_alg,
    +                                int (*f_rng_blind)(void *, unsigned char *,
    +                                                   size_t),
    +                                void *p_rng_blind );
     #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
     
     /**
    
  • include/mbedtls/ecp.h+16 0 modified
    @@ -601,6 +601,22 @@ int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_po
      */
     int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d );
     
    +/**
    + * \brief           Generate a private key
    + *
    + * \param grp       ECP group
    + * \param d         Destination MPI (secret part)
    + * \param f_rng     RNG function
    + * \param p_rng     RNG parameter
    + *
    + * \return          0 if successful,
    + *                  or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code
    + */
    +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
    +                     mbedtls_mpi *d,
    +                     int (*f_rng)(void *, unsigned char *, size_t),
    +                     void *p_rng );
    +
     /**
      * \brief           Generate a keypair with configurable base point
      *
    
  • library/ecdsa.c+103 20 modified
    @@ -70,9 +70,14 @@ static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x,
      * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
      * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
      */
    -int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
    -                const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
    -                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
    +static int ecdsa_sign_internal( mbedtls_ecp_group *grp, mbedtls_mpi *r,
    +                                mbedtls_mpi *s, const mbedtls_mpi *d,
    +                                const unsigned char *buf, size_t blen,
    +                                int (*f_rng)(void *, unsigned char *, size_t),
    +                                void *p_rng,
    +                                int (*f_rng_blind)(void *, unsigned char *,
    +                                                   size_t),
    +                                void *p_rng_blind )
     {
         int ret, key_tries, sign_tries, blind_tries;
         mbedtls_ecp_point R;
    @@ -99,7 +104,10 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
             key_tries = 0;
             do
             {
    -            MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) );
    +            MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &k, f_rng, p_rng ) );
    +
    +            MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &R, &k, &grp->G,
    +                                              f_rng_blind, p_rng_blind ) );
                 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) );
     
                 if( key_tries++ > 10 )
    @@ -118,15 +126,20 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
             /*
              * Generate a random value to blind inv_mod in next step,
              * avoiding a potential timing leak.
    +         *
    +         * This loop does the same job as mbedtls_ecp_gen_privkey() and it is
    +         * replaced by a call to it in the mainline. This change is not
    +         * necessary to backport the fix separating the blinding and ephemeral
    +         * key generating RNGs, therefore the original code is kept.
              */
             blind_tries = 0;
             do
             {
                 size_t n_size = ( grp->nbits + 7 ) / 8;
    -            MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) );
    +            MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng_blind,
    +                                                      p_rng_blind ) );
                 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) );
     
    -            /* See mbedtls_ecp_gen_keypair() */
                 if( ++blind_tries > 30 )
                     return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
             }
    @@ -158,44 +171,116 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
     
         return( ret );
     }
    +
    +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
    +                        const mbedtls_mpi *d, const unsigned char *buf,
    +                        size_t blen,
    +                        int (*f_rng)(void *, unsigned char *, size_t),
    +                        void *p_rng )
    +{
    +    /* Use the same RNG for both blinding and ephemeral key generation */
    +    return( ecdsa_sign_internal( grp, r, s, d, buf, blen, f_rng, p_rng,
    +                                 f_rng, p_rng ) );
    +}
     #endif /* MBEDTLS_ECDSA_SIGN_ALT */
     
     #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
    -/*
    - * Deterministic signature wrapper
    - */
    -int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
    -                    const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
    -                    mbedtls_md_type_t md_alg )
    +static int ecdsa_sign_det_internal( mbedtls_ecp_group *grp, mbedtls_mpi *r,
    +                                    mbedtls_mpi *s, const mbedtls_mpi *d,
    +                                    const unsigned char *buf, size_t blen,
    +                                    mbedtls_md_type_t md_alg,
    +                                    int (*f_rng_blind)(void *, unsigned char *,
    +                                                       size_t),
    +                                    void *p_rng_blind )
     {
         int ret;
         mbedtls_hmac_drbg_context rng_ctx;
         unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
         size_t grp_len = ( grp->nbits + 7 ) / 8;
         const mbedtls_md_info_t *md_info;
         mbedtls_mpi h;
    +    /* Variables for deterministic blinding fallback */
    +    const char* blind_label = "BLINDING CONTEXT";
    +    mbedtls_hmac_drbg_context rng_ctx_blind;
     
         if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
             return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
     
         mbedtls_mpi_init( &h );
         mbedtls_hmac_drbg_init( &rng_ctx );
    +    mbedtls_hmac_drbg_init( &rng_ctx_blind );
     
         /* Use private key and message hash (reduced) to initialize HMAC_DRBG */
         MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) );
         MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
         MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) );
         mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len );
     
    -    ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen,
    -                      mbedtls_hmac_drbg_random, &rng_ctx );
    +    if( f_rng_blind != NULL )
    +        ret = ecdsa_sign_internal( grp, r, s, d, buf, blen,
    +                                   mbedtls_hmac_drbg_random, &rng_ctx,
    +                                   f_rng_blind, p_rng_blind );
    +    else
    +    {
    +        /*
    +         * To avoid reusing rng_ctx and risking incorrect behavior we seed a
    +         * second HMAC-DRBG with the same seed. We also apply a label to avoid
    +         * reusing the bits of the ephemeral key for blinding and eliminate the
    +         * risk that they leak this way.
    +         */
    +
    +        mbedtls_hmac_drbg_seed_buf( &rng_ctx_blind, md_info,
    +                                    data, 2 * grp_len );
    +        ret = mbedtls_hmac_drbg_update_ret( &rng_ctx_blind,
    +                                            (const unsigned char*) blind_label,
    +                                            strlen( blind_label ) );
    +        if( ret != 0 )
    +            goto cleanup;
    +
    +        /*
    +         * Since the output of the RNGs is always the same for the same key and
    +         * message, this limits the efficiency of blinding and leaks information
    +         * through side channels. After mbedtls_ecdsa_sign_det() is removed NULL
    +         * won't be a valid value for f_rng_blind anymore. Therefore it should
    +         * be checked by the caller and this branch and check can be removed.
    +         */
    +        ret = ecdsa_sign_internal( grp, r, s, d, buf, blen,
    +                                   mbedtls_hmac_drbg_random, &rng_ctx,
    +                                   mbedtls_hmac_drbg_random, &rng_ctx_blind );
    +
    +    }
     
     cleanup:
         mbedtls_hmac_drbg_free( &rng_ctx );
    +    mbedtls_hmac_drbg_free( &rng_ctx_blind );
         mbedtls_mpi_free( &h );
     
         return( ret );
     }
    +
    +/*
    + * Deterministic signature wrappers
    + */
    +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r,
    +                            mbedtls_mpi *s, const mbedtls_mpi *d,
    +                            const unsigned char *buf, size_t blen,
    +                            mbedtls_md_type_t md_alg )
    +{
    +    return( ecdsa_sign_det_internal( grp, r, s, d, buf, blen, md_alg,
    +                                     NULL, NULL ) );
    +}
    +
    +int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r,
    +                                mbedtls_mpi *s, const mbedtls_mpi *d,
    +                                const unsigned char *buf, size_t blen,
    +                                mbedtls_md_type_t md_alg,
    +                                int (*f_rng_blind)(void *, unsigned char *,
    +                                                   size_t),
    +                                void *p_rng_blind )
    +{
    +    return( ecdsa_sign_det_internal( grp, r, s, d, buf, blen, md_alg,
    +                                     f_rng_blind, p_rng_blind ) );
    +}
     #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
     
     #if !defined(MBEDTLS_ECDSA_VERIFY_ALT)
    @@ -326,17 +411,15 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t
         mbedtls_mpi_init( &s );
     
     #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
    -    (void) f_rng;
    -    (void) p_rng;
    -
    -    MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d,
    -                             hash, hlen, md_alg ) );
    +    MBEDTLS_MPI_CHK( ecdsa_sign_det_internal( &ctx->grp, &r, &s, &ctx->d,
    +                                              hash, hlen, md_alg,
    +                                              f_rng, p_rng ) );
     #else
         (void) md_alg;
     
         MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
                              hash, hlen, f_rng, p_rng ) );
    -#endif
    +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
     
         MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) );
     
    
  • library/ecp.c+23 11 modified
    @@ -1918,15 +1918,14 @@ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *
     }
     
     /*
    - * Generate a keypair with configurable base point
    + * Generate a private key
      */
    -int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
    -                     const mbedtls_ecp_point *G,
    -                     mbedtls_mpi *d, mbedtls_ecp_point *Q,
    +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
    +                     mbedtls_mpi *d,
                          int (*f_rng)(void *, unsigned char *, size_t),
                          void *p_rng )
     {
    -    int ret;
    +    int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
         size_t n_size = ( grp->nbits + 7 ) / 8;
     
     #if defined(ECP_MONTGOMERY)
    @@ -1951,8 +1950,8 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
             MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
             MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
         }
    -    else
     #endif /* ECP_MONTGOMERY */
    +
     #if defined(ECP_SHORTWEIERSTRASS)
         if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
         {
    @@ -1986,15 +1985,28 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
             while( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
                    mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 );
         }
    -    else
     #endif /* ECP_SHORTWEIERSTRASS */
    -        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
     
     cleanup:
    -    if( ret != 0 )
    -        return( ret );
    +    return( ret );
    +}
     
    -    return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
    +/*
    + * Generate a keypair with configurable base point
    + */
    +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
    +                     const mbedtls_ecp_point *G,
    +                     mbedtls_mpi *d, mbedtls_ecp_point *Q,
    +                     int (*f_rng)(void *, unsigned char *, size_t),
    +                     void *p_rng )
    +{
    +    int ret;
    +
    +    MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
    +    MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
    +
    +cleanup:
    +    return( ret );
     }
     
     /*
    
  • tests/suites/test_suite_ecdsa.function+10 0 modified
    @@ -129,6 +129,16 @@ void ecdsa_det_test_vectors( int id, char *d_str, int md_alg,
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &r, &r_check ) == 0 );
         TEST_ASSERT( mbedtls_mpi_cmp_mpi( &s, &s_check ) == 0 );
     
    +    mbedtls_mpi_free( &r ); mbedtls_mpi_free( &s );
    +    mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s );
    +
    +    TEST_ASSERT(
    +                mbedtls_ecdsa_sign_det_ext( &grp, &r, &s, &d, hash, hlen,
    +                                            md_alg, rnd_std_rand, NULL )
    +                == 0 );
    +
    +    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &r, &r_check ) == 0 );
    +    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &s, &s_check ) == 0 );
     exit:
         mbedtls_ecp_group_free( &grp );
         mbedtls_mpi_free( &d ); mbedtls_mpi_free( &r ); mbedtls_mpi_free( &s );
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.