初始提交:terminalX 可运行态(M0/M1/M1.5 已真机验证)

- M0: libghostty SSH 终端(渲染/输入/连接)+ 白屏修复(OutputGate) + 会话状态机/自动重连
- M1: tsnet 用户态组网 + SSH-over-tsnet(fd 桥),shell 级真机验证;R5(Go+gvisor+C+++Swift 同进程) retire
- M1.5: tmux -CC 原生 tab(MVP)
- 结构: packages/(TXCore·TXTransport), apps/TerminalX, vendor/(libghostty-spm/libssh2/mbedtls/tsnet-bridge), artifacts/
- 文档: CLAUDE.md + docs/HANDOFF.md(新会话入口)
- 环境: 认证代理→依赖 vendor 本地化;Go 在 ~/.local/go;仅模拟器/未签名
- 待续: M2 mosh, tmux 多 pane, M4 安全(host key/SE)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
kid
2026-07-24 10:20:46 +08:00
commit aa92d0e676
2761 changed files with 803505 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
# Generated file created by TF-PSA-Crypto and mbedtls
/include/test/test_keys.h

View File

@@ -0,0 +1 @@
mbedtls.run_framework_pr_job()

View File

@@ -0,0 +1,7 @@
/* The goal of the include/alt-extra directory is to test what happens
* if certain files come _after_ the normal include directory.
* Make sure that if the alt-extra directory comes before the normal
* directory (so we wouldn't be achieving our test objective), the build
* will fail.
*/
#error "The normal include directory must come first in the include path"

View File

@@ -0,0 +1,6 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#error "time.h included in a configuration without MBEDTLS_HAVE_TIME"

View File

@@ -0,0 +1,131 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*
*/
/**
* \file crypto_spe.h
*
* \brief When Mbed TLS is built with the MBEDTLS_PSA_CRYPTO_SPM option
* enabled, this header is included by all .c files in Mbed TLS that
* use PSA Crypto function names. This avoids duplication of symbols
* between TF-M and Mbed TLS.
*
* \note This file should be included before including any PSA Crypto headers
* from Mbed TLS.
*/
#ifndef CRYPTO_SPE_H
#define CRYPTO_SPE_H
#define PSA_FUNCTION_NAME(x) mbedcrypto__ ## x
#define psa_crypto_init \
PSA_FUNCTION_NAME(psa_crypto_init)
#define psa_key_derivation_get_capacity \
PSA_FUNCTION_NAME(psa_key_derivation_get_capacity)
#define psa_key_derivation_set_capacity \
PSA_FUNCTION_NAME(psa_key_derivation_set_capacity)
#define psa_key_derivation_input_bytes \
PSA_FUNCTION_NAME(psa_key_derivation_input_bytes)
#define psa_key_derivation_output_bytes \
PSA_FUNCTION_NAME(psa_key_derivation_output_bytes)
#define psa_key_derivation_input_key \
PSA_FUNCTION_NAME(psa_key_derivation_input_key)
#define psa_key_derivation_output_key \
PSA_FUNCTION_NAME(psa_key_derivation_output_key)
#define psa_key_derivation_setup \
PSA_FUNCTION_NAME(psa_key_derivation_setup)
#define psa_key_derivation_abort \
PSA_FUNCTION_NAME(psa_key_derivation_abort)
#define psa_key_derivation_key_agreement \
PSA_FUNCTION_NAME(psa_key_derivation_key_agreement)
#define psa_raw_key_agreement \
PSA_FUNCTION_NAME(psa_raw_key_agreement)
#define psa_generate_random \
PSA_FUNCTION_NAME(psa_generate_random)
#define psa_aead_encrypt \
PSA_FUNCTION_NAME(psa_aead_encrypt)
#define psa_aead_decrypt \
PSA_FUNCTION_NAME(psa_aead_decrypt)
#define psa_open_key \
PSA_FUNCTION_NAME(psa_open_key)
#define psa_close_key \
PSA_FUNCTION_NAME(psa_close_key)
#define psa_import_key \
PSA_FUNCTION_NAME(psa_import_key)
#define psa_destroy_key \
PSA_FUNCTION_NAME(psa_destroy_key)
#define psa_get_key_attributes \
PSA_FUNCTION_NAME(psa_get_key_attributes)
#define psa_reset_key_attributes \
PSA_FUNCTION_NAME(psa_reset_key_attributes)
#define psa_export_key \
PSA_FUNCTION_NAME(psa_export_key)
#define psa_export_public_key \
PSA_FUNCTION_NAME(psa_export_public_key)
#define psa_purge_key \
PSA_FUNCTION_NAME(psa_purge_key)
#define psa_copy_key \
PSA_FUNCTION_NAME(psa_copy_key)
#define psa_cipher_operation_init \
PSA_FUNCTION_NAME(psa_cipher_operation_init)
#define psa_cipher_generate_iv \
PSA_FUNCTION_NAME(psa_cipher_generate_iv)
#define psa_cipher_set_iv \
PSA_FUNCTION_NAME(psa_cipher_set_iv)
#define psa_cipher_encrypt_setup \
PSA_FUNCTION_NAME(psa_cipher_encrypt_setup)
#define psa_cipher_decrypt_setup \
PSA_FUNCTION_NAME(psa_cipher_decrypt_setup)
#define psa_cipher_update \
PSA_FUNCTION_NAME(psa_cipher_update)
#define psa_cipher_finish \
PSA_FUNCTION_NAME(psa_cipher_finish)
#define psa_cipher_abort \
PSA_FUNCTION_NAME(psa_cipher_abort)
#define psa_hash_operation_init \
PSA_FUNCTION_NAME(psa_hash_operation_init)
#define psa_hash_setup \
PSA_FUNCTION_NAME(psa_hash_setup)
#define psa_hash_update \
PSA_FUNCTION_NAME(psa_hash_update)
#define psa_hash_finish \
PSA_FUNCTION_NAME(psa_hash_finish)
#define psa_hash_verify \
PSA_FUNCTION_NAME(psa_hash_verify)
#define psa_hash_abort \
PSA_FUNCTION_NAME(psa_hash_abort)
#define psa_hash_clone \
PSA_FUNCTION_NAME(psa_hash_clone)
#define psa_hash_compute \
PSA_FUNCTION_NAME(psa_hash_compute)
#define psa_hash_compare \
PSA_FUNCTION_NAME(psa_hash_compare)
#define psa_mac_operation_init \
PSA_FUNCTION_NAME(psa_mac_operation_init)
#define psa_mac_sign_setup \
PSA_FUNCTION_NAME(psa_mac_sign_setup)
#define psa_mac_verify_setup \
PSA_FUNCTION_NAME(psa_mac_verify_setup)
#define psa_mac_update \
PSA_FUNCTION_NAME(psa_mac_update)
#define psa_mac_sign_finish \
PSA_FUNCTION_NAME(psa_mac_sign_finish)
#define psa_mac_verify_finish \
PSA_FUNCTION_NAME(psa_mac_verify_finish)
#define psa_mac_abort \
PSA_FUNCTION_NAME(psa_mac_abort)
#define psa_sign_hash \
PSA_FUNCTION_NAME(psa_sign_hash)
#define psa_verify_hash \
PSA_FUNCTION_NAME(psa_verify_hash)
#define psa_asymmetric_encrypt \
PSA_FUNCTION_NAME(psa_asymmetric_encrypt)
#define psa_asymmetric_decrypt \
PSA_FUNCTION_NAME(psa_asymmetric_decrypt)
#define psa_generate_key \
PSA_FUNCTION_NAME(psa_generate_key)
#endif /* CRYPTO_SPE_H */

View File

@@ -0,0 +1,26 @@
/**
* \file arguments.h
*
* \brief Manipulation of test arguments.
*
* Much of the code is in host_test.function, to be migrated here later.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef TEST_ARGUMENTS_H
#define TEST_ARGUMENTS_H
#include "build_info.h"
#include <stdint.h>
#include <stdlib.h>
typedef union {
size_t len;
intmax_t sint;
} mbedtls_test_argument_t;
#endif /* TEST_ARGUMENTS_H */

View File

@@ -0,0 +1,39 @@
/** Helper functions for tests that manipulate ASN.1 data.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef ASN1_HELPERS_H
#define ASN1_HELPERS_H
#include "build_info.h"
#include "test/helpers.h"
/** Skip past an INTEGER in an ASN.1 buffer.
*
* Mark the current test case as failed in any of the following conditions:
* - The buffer does not start with an ASN.1 INTEGER.
* - The integer's size or parity does not match the constraints expressed
* through \p min_bits, \p max_bits and \p must_be_odd.
*
* \param p Upon entry, `*p` points to the first byte of the
* buffer to parse.
* On successful return, `*p` points to the first byte
* after the parsed INTEGER.
* On failure, `*p` is unspecified.
* \param end The end of the ASN.1 buffer.
* \param min_bits Fail the test case if the integer does not have at
* least this many significant bits.
* \param max_bits Fail the test case if the integer has more than
* this many significant bits.
* \param must_be_odd Fail the test case if the integer is even.
*
* \return \c 0 if the test failed, otherwise 1.
*/
int mbedtls_test_asn1_skip_integer(unsigned char **p, const unsigned char *end,
size_t min_bits, size_t max_bits,
int must_be_odd);
#endif /* ASN1_HELPERS_H */

View File

@@ -0,0 +1,96 @@
/** Support for path tracking in optionally safe bignum functions
*
* The functions are called when an optionally safe path is taken and logs it with a single
* variable. This variable is at any time in one of three states:
* - MBEDTLS_MPI_IS_TEST: No optionally safe path has been taken since the last reset
* - MBEDTLS_MPI_IS_SECRET: Only safe paths were teken since the last reset
* - MBEDTLS_MPI_IS_PUBLIC: At least one unsafe path has been taken since the last reset
*
* Use a simple global variable to track execution path. Making it work with multithreading
* isn't worth the effort as multithreaded tests add little to no value here.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef BIGNUM_CODEPATH_CHECK_H
#define BIGNUM_CODEPATH_CHECK_H
#include "build_info.h"
#include "bignum_core.h"
#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
extern int mbedtls_codepath_check;
/**
* \brief Setup the codepath test hooks used by optionally safe bignum functions to signal
* the path taken.
*/
void mbedtls_codepath_test_hooks_setup(void);
/**
* \brief Teardown the codepath test hooks used by optionally safe bignum functions to
* signal the path taken.
*/
void mbedtls_codepath_test_hooks_teardown(void);
/**
* \brief Reset the state of the codepath to the initial state.
*/
static inline void mbedtls_codepath_reset(void)
{
mbedtls_codepath_check = MBEDTLS_MPI_IS_TEST;
}
/** Check the codepath taken and fail if it doesn't match.
*
* When a function returns with an error, it can do so before reaching any interesting codepath. The
* same can happen if a parameter to the function is zero. In these cases we need to allow
* the codepath tracking variable to still have its initial "not set" value.
*
* This macro expands to an instruction, not an expression.
* It may jump to the \c exit label.
*
* \param path The expected codepath.
* This expression may be evaluated multiple times.
* \param ret The expected return value.
* \param E The MPI parameter that can cause shortcuts.
*/
#define ASSERT_BIGNUM_CODEPATH(path, ret, E) \
do { \
if ((ret) != 0 || (E).n == 0) { \
TEST_ASSERT(mbedtls_codepath_check == (path) || \
mbedtls_codepath_check == MBEDTLS_MPI_IS_TEST); \
} else { \
TEST_EQUAL(mbedtls_codepath_check, (path)); \
} \
} while (0)
/** Check the codepath taken and fail if it doesn't match.
*
* When a function returns with an error, it can do so before reaching any interesting codepath. In
* this case we need to allow the codepath tracking variable to still have its
* initial "not set" value.
*
* This macro expands to an instruction, not an expression.
* It may jump to the \c exit label.
*
* \param path The expected codepath.
* This expression may be evaluated multiple times.
* \param ret The expected return value.
*/
#define ASSERT_RSA_CODEPATH(path, ret) \
do { \
if ((ret) != 0) { \
TEST_ASSERT(mbedtls_codepath_check == (path) || \
mbedtls_codepath_check == MBEDTLS_MPI_IS_TEST); \
} else { \
TEST_EQUAL(mbedtls_codepath_check, (path)); \
} \
} while (0)
#endif /* MBEDTLS_TEST_HOOKS && !MBEDTLS_THREADING_C */
#endif /* BIGNUM_CODEPATH_CHECK_H */

View File

@@ -0,0 +1,102 @@
/**
* \file bignum_helpers.h
*
* \brief This file contains the prototypes of helper functions for
* bignum-related testing.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef TEST_BIGNUM_HELPERS_H
#define TEST_BIGNUM_HELPERS_H
#include "build_info.h"
#if defined(MBEDTLS_BIGNUM_C)
#if !defined(MBEDTLS_VERSION_MAJOR) || MBEDTLS_VERSION_MAJOR >= 4
#include <mbedtls/private/bignum.h>
#else
#include <mbedtls/bignum.h>
#endif
#include <bignum_mod.h>
/** Allocate and populate a core MPI from a test case argument.
*
* This function allocates exactly as many limbs as necessary to fit
* the length of the input. In other words, it preserves leading zeros.
*
* The limb array is allocated with mbedtls_calloc() and must later be
* freed with mbedtls_free().
*
* \param[in,out] pX The address where a pointer to the allocated limb
* array will be stored.
* \c *pX must be null on entry.
* On exit, \c *pX is null on error or if the number
* of limbs is 0.
* \param[out] plimbs The address where the number of limbs will be stored.
* \param[in] input The test argument to read.
* It is interpreted as a hexadecimal representation
* of a non-negative integer.
*
* \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
*/
int mbedtls_test_read_mpi_core(mbedtls_mpi_uint **pX, size_t *plimbs,
const char *input);
/** Read a modulus from a hexadecimal string.
*
* This function allocates exactly as many limbs as necessary to fit
* the length of the input. In other words, it preserves leading zeros.
*
* The limb array is allocated with mbedtls_calloc() and must later be
* freed with mbedtls_free(). You can do that by calling
* mbedtls_test_mpi_mod_modulus_free_with_limbs().
*
* \param[in,out] N A modulus structure. It must be initialized, but
* not set up.
* \param[in] s The null-terminated hexadecimal string to read from.
* \param int_rep The desired representation of residues.
*
* \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
*/
int mbedtls_test_read_mpi_modulus(mbedtls_mpi_mod_modulus *N,
const char *s,
mbedtls_mpi_mod_rep_selector int_rep);
/** Free a modulus and its limbs.
*
* \param[in] N A modulus structure such that there is no other
* reference to `N->p`.
*/
void mbedtls_test_mpi_mod_modulus_free_with_limbs(mbedtls_mpi_mod_modulus *N);
/** Read an MPI from a hexadecimal string.
*
* Like mbedtls_mpi_read_string(), but with tighter guarantees around
* edge cases.
*
* - This function guarantees that if \p s begins with '-' then the sign
* bit of the result will be negative, even if the value is 0.
* When this function encounters such a "negative 0", it calls
* mbedtls_test_increment_case_uses_negative_0().
* - The size of the result is exactly the minimum number of limbs needed to fit
* the digits in the input. In particular, this function constructs a bignum
* with 0 limbs for an empty string, and a bignum with leading 0 limbs if the
* string has sufficiently many leading 0 digits. This is important so that
* the "0 (null)" and "0 (1 limb)" and "leading zeros" test cases do what they
* claim.
*
* \param[out] X The MPI object to populate. It must be initialized.
* \param[in] s The null-terminated hexadecimal string to read from.
*
* \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
*/
int mbedtls_test_read_mpi(mbedtls_mpi *X, const char *s);
#endif /* MBEDTLS_BIGNUM_C */
#endif /* TEST_BIGNUM_HELPERS_H */

View File

@@ -0,0 +1,24 @@
/**
* \file test/build_info.h
*
* \brief Common things for all Mbed TLS and TF-PSA-Crypto test headers.
*
* Include this header first in all headers in `include/test/`.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef TEST_BUILD_INFO_H
#define TEST_BUILD_INFO_H
#include <mbedtls/build_info.h>
/* Most fields of publicly available structs are private and are wrapped with
* MBEDTLS_PRIVATE macro. This define allows tests to access the private fields
* directly (without using the MBEDTLS_PRIVATE wrapper). */
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
#endif /* TEST_BUILD_INFO_H */

View File

@@ -0,0 +1,71 @@
/**
* \file constant_flow.h
*
* \brief This file contains tools to ensure tested code has constant flow.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef TEST_CONSTANT_FLOW_H
#define TEST_CONSTANT_FLOW_H
#include "build_info.h"
/*
* This file defines the two macros
*
* #define TEST_CF_SECRET(ptr, size)
* #define TEST_CF_PUBLIC(ptr, size)
*
* that can be used in tests to mark a memory area as secret (no branch or
* memory access should depend on it) or public (default, only needs to be
* marked explicitly when it was derived from secret data).
*
* Arguments:
* - ptr: a pointer to the memory area to be marked
* - size: the size in bytes of the memory area
*
* Implementation:
* The basic idea is that of ctgrind <https://github.com/agl/ctgrind>: we can
* re-use tools that were designed for checking use of uninitialized memory.
* This file contains two implementations: one based on MemorySanitizer, the
* other on valgrind's memcheck. If none of them is enabled, dummy macros that
* do nothing are defined for convenience.
*
* \note #TEST_CF_SECRET must be called directly from within a .function file,
* not indirectly via a macro defined under tests/include or a function
* under tests/src. This is because we only run Valgrind for constant
* flow on test suites that have greppable annotations inside them (see
* `skip_suites_without_constant_flow` in `tests/scripts/all.sh`).
*/
#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN)
#include <sanitizer/msan_interface.h>
/* Use macros to avoid messing up with origin tracking */
#define TEST_CF_SECRET __msan_allocated_memory
// void __msan_allocated_memory(const volatile void* data, size_t size);
#define TEST_CF_PUBLIC __msan_unpoison
// void __msan_unpoison(const volatile void *a, size_t size);
#elif defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND)
#include <valgrind/memcheck.h>
#define TEST_CF_SECRET VALGRIND_MAKE_MEM_UNDEFINED
// VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr, _qzz_len)
#define TEST_CF_PUBLIC VALGRIND_MAKE_MEM_DEFINED
// VALGRIND_MAKE_MEM_DEFINED(_qzz_addr, _qzz_len)
#else /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN ||
MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND */
#define TEST_CF_SECRET(ptr, size)
#define TEST_CF_PUBLIC(ptr, size)
#endif /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN ||
MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND */
#endif /* TEST_CONSTANT_FLOW_H */

View File

@@ -0,0 +1,123 @@
/*
* Test driver for AEAD driver entry points.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_TEST_DRIVERS_AEAD_H
#define PSA_CRYPTO_TEST_DRIVERS_AEAD_H
#include "mbedtls/build_info.h"
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "test_driver_common.h"
#include <psa/crypto_driver_common.h>
typedef struct {
/* If not PSA_SUCCESS, return this error code instead of processing the
* function call. */
psa_status_t forced_status;
/* Count the amount of times AEAD driver functions are called. */
unsigned long hits_encrypt;
unsigned long hits_decrypt;
unsigned long hits_encrypt_setup;
unsigned long hits_decrypt_setup;
unsigned long hits_set_nonce;
unsigned long hits_set_lengths;
unsigned long hits_update_ad;
unsigned long hits_update;
unsigned long hits_finish;
unsigned long hits_verify;
unsigned long hits_abort;
/* Status returned by the last AEAD driver function call. */
psa_status_t driver_status;
} mbedtls_test_driver_aead_hooks_t;
#define MBEDTLS_TEST_DRIVER_AEAD_INIT { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
static inline mbedtls_test_driver_aead_hooks_t
mbedtls_test_driver_aead_hooks_init(void)
{
const mbedtls_test_driver_aead_hooks_t v = MBEDTLS_TEST_DRIVER_AEAD_INIT;
return v;
}
extern mbedtls_test_driver_aead_hooks_t mbedtls_test_driver_aead_hooks;
psa_status_t mbedtls_test_transparent_aead_encrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *nonce, size_t nonce_length,
const uint8_t *additional_data, size_t additional_data_length,
const uint8_t *plaintext, size_t plaintext_length,
uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length);
psa_status_t mbedtls_test_transparent_aead_decrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *nonce, size_t nonce_length,
const uint8_t *additional_data, size_t additional_data_length,
const uint8_t *ciphertext, size_t ciphertext_length,
uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length);
psa_status_t mbedtls_test_transparent_aead_encrypt_setup(
mbedtls_transparent_test_driver_aead_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg);
psa_status_t mbedtls_test_transparent_aead_decrypt_setup(
mbedtls_transparent_test_driver_aead_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg);
psa_status_t mbedtls_test_transparent_aead_set_nonce(
mbedtls_transparent_test_driver_aead_operation_t *operation,
const uint8_t *nonce,
size_t nonce_length);
psa_status_t mbedtls_test_transparent_aead_set_lengths(
mbedtls_transparent_test_driver_aead_operation_t *operation,
size_t ad_length,
size_t plaintext_length);
psa_status_t mbedtls_test_transparent_aead_update_ad(
mbedtls_transparent_test_driver_aead_operation_t *operation,
const uint8_t *input,
size_t input_length);
psa_status_t mbedtls_test_transparent_aead_update(
mbedtls_transparent_test_driver_aead_operation_t *operation,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length);
psa_status_t mbedtls_test_transparent_aead_finish(
mbedtls_transparent_test_driver_aead_operation_t *operation,
uint8_t *ciphertext,
size_t ciphertext_size,
size_t *ciphertext_length,
uint8_t *tag,
size_t tag_size,
size_t *tag_length);
psa_status_t mbedtls_test_transparent_aead_verify(
mbedtls_transparent_test_driver_aead_operation_t *operation,
uint8_t *plaintext,
size_t plaintext_size,
size_t *plaintext_length,
const uint8_t *tag,
size_t tag_length);
psa_status_t mbedtls_test_transparent_aead_abort(
mbedtls_transparent_test_driver_aead_operation_t *operation);
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_TEST_DRIVERS_AEAD_H */

View File

@@ -0,0 +1,69 @@
/*
* Test driver for asymmetric encryption.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_TEST_DRIVERS_ASYMMETRIC_ENCRYPTION_H
#define PSA_CRYPTO_TEST_DRIVERS_ASYMMETRIC_ENCRYPTION_H
#include "mbedtls/build_info.h"
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "test_driver_common.h"
#include <psa/crypto_driver_common.h>
#include <psa/crypto.h>
typedef struct {
/* If non-null, on success, copy this to the output. */
void *forced_output;
size_t forced_output_length;
/* If not PSA_SUCCESS, return this error code instead of processing the
* function call. */
psa_status_t forced_status;
/* Count the amount of times one of the asymmetric_encryption driver
functions is called. */
unsigned long hits;
} mbedtls_test_driver_asymmetric_encryption_hooks_t;
#define MBEDTLS_TEST_DRIVER_ASYMMETRIC_ENCRYPTION_INIT { NULL, 0, PSA_SUCCESS, 0 }
static inline mbedtls_test_driver_asymmetric_encryption_hooks_t
mbedtls_test_driver_asymmetric_encryption_hooks_init(void)
{
const mbedtls_test_driver_asymmetric_encryption_hooks_t v =
MBEDTLS_TEST_DRIVER_ASYMMETRIC_ENCRYPTION_INIT;
return v;
}
extern mbedtls_test_driver_asymmetric_encryption_hooks_t
mbedtls_test_driver_asymmetric_encryption_hooks;
psa_status_t mbedtls_test_transparent_asymmetric_encrypt(
const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input,
size_t input_length, const uint8_t *salt, size_t salt_length,
uint8_t *output, size_t output_size, size_t *output_length);
psa_status_t mbedtls_test_opaque_asymmetric_encrypt(
const psa_key_attributes_t *attributes, const uint8_t *key,
size_t key_length, psa_algorithm_t alg, const uint8_t *input,
size_t input_length, const uint8_t *salt, size_t salt_length,
uint8_t *output, size_t output_size, size_t *output_length);
psa_status_t mbedtls_test_transparent_asymmetric_decrypt(
const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input,
size_t input_length, const uint8_t *salt, size_t salt_length,
uint8_t *output, size_t output_size, size_t *output_length);
psa_status_t mbedtls_test_opaque_asymmetric_decrypt(
const psa_key_attributes_t *attributes, const uint8_t *key,
size_t key_length, psa_algorithm_t alg, const uint8_t *input,
size_t input_length, const uint8_t *salt, size_t salt_length,
uint8_t *output, size_t output_size, size_t *output_length);
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_TEST_DRIVERS_ASYMMETRIC_ENCRYPTION_H */

View File

@@ -0,0 +1,142 @@
/*
* Test driver for cipher functions
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_TEST_DRIVERS_CIPHER_H
#define PSA_CRYPTO_TEST_DRIVERS_CIPHER_H
#include "mbedtls/build_info.h"
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "test_driver_common.h"
#include <psa/crypto_driver_common.h>
#include <psa/crypto.h>
#if !defined(MBEDTLS_VERSION_MAJOR) || MBEDTLS_VERSION_MAJOR >= 4
#include "mbedtls/private/cipher.h"
#else
#include "mbedtls/cipher.h"
#endif
typedef struct {
/* If non-null, on success, copy this to the output. */
void *forced_output;
size_t forced_output_length;
/* If not PSA_SUCCESS, return this error code instead of processing the
* function call. */
psa_status_t forced_status;
psa_status_t forced_status_encrypt;
psa_status_t forced_status_set_iv;
/* Count the amount of times one of the cipher driver functions is called. */
unsigned long hits;
unsigned long hits_encrypt;
unsigned long hits_set_iv;
} mbedtls_test_driver_cipher_hooks_t;
#define MBEDTLS_TEST_DRIVER_CIPHER_INIT { NULL, 0, \
PSA_SUCCESS, PSA_SUCCESS, PSA_SUCCESS, \
0, 0, 0 }
static inline mbedtls_test_driver_cipher_hooks_t
mbedtls_test_driver_cipher_hooks_init(void)
{
const mbedtls_test_driver_cipher_hooks_t v = MBEDTLS_TEST_DRIVER_CIPHER_INIT;
return v;
}
extern mbedtls_test_driver_cipher_hooks_t mbedtls_test_driver_cipher_hooks;
psa_status_t mbedtls_test_transparent_cipher_encrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg,
const uint8_t *iv, size_t iv_length,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size, size_t *output_length);
psa_status_t mbedtls_test_transparent_cipher_decrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size, size_t *output_length);
psa_status_t mbedtls_test_transparent_cipher_encrypt_setup(
mbedtls_transparent_test_driver_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg);
psa_status_t mbedtls_test_transparent_cipher_decrypt_setup(
mbedtls_transparent_test_driver_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg);
psa_status_t mbedtls_test_transparent_cipher_abort(
mbedtls_transparent_test_driver_cipher_operation_t *operation);
psa_status_t mbedtls_test_transparent_cipher_set_iv(
mbedtls_transparent_test_driver_cipher_operation_t *operation,
const uint8_t *iv, size_t iv_length);
psa_status_t mbedtls_test_transparent_cipher_update(
mbedtls_transparent_test_driver_cipher_operation_t *operation,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size, size_t *output_length);
psa_status_t mbedtls_test_transparent_cipher_finish(
mbedtls_transparent_test_driver_cipher_operation_t *operation,
uint8_t *output, size_t output_size, size_t *output_length);
/*
* opaque versions
*/
psa_status_t mbedtls_test_opaque_cipher_encrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg,
const uint8_t *iv, size_t iv_length,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size, size_t *output_length);
psa_status_t mbedtls_test_opaque_cipher_decrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size, size_t *output_length);
psa_status_t mbedtls_test_opaque_cipher_encrypt_setup(
mbedtls_opaque_test_driver_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg);
psa_status_t mbedtls_test_opaque_cipher_decrypt_setup(
mbedtls_opaque_test_driver_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg);
psa_status_t mbedtls_test_opaque_cipher_abort(
mbedtls_opaque_test_driver_cipher_operation_t *operation);
psa_status_t mbedtls_test_opaque_cipher_set_iv(
mbedtls_opaque_test_driver_cipher_operation_t *operation,
const uint8_t *iv, size_t iv_length);
psa_status_t mbedtls_test_opaque_cipher_update(
mbedtls_opaque_test_driver_cipher_operation_t *operation,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size, size_t *output_length);
psa_status_t mbedtls_test_opaque_cipher_finish(
mbedtls_opaque_test_driver_cipher_operation_t *operation,
uint8_t *output, size_t output_size, size_t *output_length);
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_TEST_DRIVERS_CIPHER_H */

View File

@@ -0,0 +1,66 @@
/*
* Test driver for hash driver entry points.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_TEST_DRIVERS_HASH_H
#define PSA_CRYPTO_TEST_DRIVERS_HASH_H
#include "mbedtls/build_info.h"
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "test_driver_common.h"
#include <psa/crypto_driver_common.h>
typedef struct {
/* If not PSA_SUCCESS, return this error code instead of processing the
* function call. */
psa_status_t forced_status;
/* Count the amount of times hash driver entry points are called. */
unsigned long hits;
/* Status returned by the last hash driver entry point call. */
psa_status_t driver_status;
} mbedtls_test_driver_hash_hooks_t;
#define MBEDTLS_TEST_DRIVER_HASH_INIT { 0, 0, 0 }
static inline mbedtls_test_driver_hash_hooks_t
mbedtls_test_driver_hash_hooks_init(void)
{
const mbedtls_test_driver_hash_hooks_t v = MBEDTLS_TEST_DRIVER_HASH_INIT;
return v;
}
extern mbedtls_test_driver_hash_hooks_t mbedtls_test_driver_hash_hooks;
psa_status_t mbedtls_test_transparent_hash_compute(
psa_algorithm_t alg,
const uint8_t *input, size_t input_length,
uint8_t *hash, size_t hash_size, size_t *hash_length);
psa_status_t mbedtls_test_transparent_hash_setup(
mbedtls_transparent_test_driver_hash_operation_t *operation,
psa_algorithm_t alg);
psa_status_t mbedtls_test_transparent_hash_clone(
const mbedtls_transparent_test_driver_hash_operation_t *source_operation,
mbedtls_transparent_test_driver_hash_operation_t *target_operation);
psa_status_t mbedtls_test_transparent_hash_update(
mbedtls_transparent_test_driver_hash_operation_t *operation,
const uint8_t *input,
size_t input_length);
psa_status_t mbedtls_test_transparent_hash_finish(
mbedtls_transparent_test_driver_hash_operation_t *operation,
uint8_t *hash,
size_t hash_size,
size_t *hash_length);
psa_status_t mbedtls_test_transparent_hash_abort(
mbedtls_transparent_test_driver_hash_operation_t *operation);
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_TEST_DRIVERS_HASH_H */

View File

@@ -0,0 +1,64 @@
/*
* Test driver for key agreement functions.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_TEST_DRIVERS_KEY_AGREEMENT_H
#define PSA_CRYPTO_TEST_DRIVERS_KEY_AGREEMENT_H
#include "mbedtls/build_info.h"
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "test_driver_common.h"
#include <psa/crypto_driver_common.h>
typedef struct {
/* If non-null, on success, copy this to the output. */
void *forced_output;
size_t forced_output_length;
/* If not PSA_SUCCESS, return this error code instead of processing the
* function call. */
psa_status_t forced_status;
/* Count the amount of times one of the signature driver functions is called. */
unsigned long hits;
} mbedtls_test_driver_key_agreement_hooks_t;
#define MBEDTLS_TEST_DRIVER_KEY_AGREEMENT_INIT { NULL, 0, PSA_SUCCESS, 0 }
static inline mbedtls_test_driver_key_agreement_hooks_t
mbedtls_test_driver_key_agreement_hooks_init(void)
{
const mbedtls_test_driver_key_agreement_hooks_t
v = MBEDTLS_TEST_DRIVER_KEY_AGREEMENT_INIT;
return v;
}
extern mbedtls_test_driver_key_agreement_hooks_t
mbedtls_test_driver_key_agreement_hooks;
psa_status_t mbedtls_test_transparent_key_agreement(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *peer_key,
size_t peer_key_length,
uint8_t *shared_secret,
size_t shared_secret_size,
size_t *shared_secret_length);
psa_status_t mbedtls_test_opaque_key_agreement(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *peer_key,
size_t peer_key_length,
uint8_t *shared_secret,
size_t shared_secret_size,
size_t *shared_secret_length);
#endif /*PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_TEST_DRIVERS_KEY_AGREEMENT_H */

View File

@@ -0,0 +1,133 @@
/*
* Test driver for generating and verifying keys.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_TEST_DRIVERS_KEY_MANAGEMENT_H
#define PSA_CRYPTO_TEST_DRIVERS_KEY_MANAGEMENT_H
#include "mbedtls/build_info.h"
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "test_driver_common.h"
#include <psa/crypto_driver_common.h>
#define PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT 0
#define PSA_CRYPTO_TEST_DRIVER_BUILTIN_ECDSA_KEY_SLOT 1
typedef struct {
/* If non-null, on success, copy this to the output. */
void *forced_output;
size_t forced_output_length;
/* If not PSA_SUCCESS, return this error code instead of processing the
* function call. */
psa_status_t forced_status;
/* Count the amount of times one of the key management driver functions
* is called. */
unsigned long hits;
/* Subset of hits which only counts public key export operations */
unsigned long hits_export_public_key;
/* Subset of hits which only counts key generation operations */
unsigned long hits_generate_key;
/* Location of the last key management driver called to import a key. */
psa_key_location_t location;
} mbedtls_test_driver_key_management_hooks_t;
/* The location is initialized to the invalid value 0x800000. Invalid in the
* sense that no PSA specification will assign a meaning to this location
* (stated first in version 1.0.1 of the specification) and that it is not
* used as a location of an opaque test drivers. */
#define MBEDTLS_TEST_DRIVER_KEY_MANAGEMENT_INIT { NULL, 0, PSA_SUCCESS, 0, 0, 0, 0x800000 }
static inline mbedtls_test_driver_key_management_hooks_t
mbedtls_test_driver_key_management_hooks_init(void)
{
const mbedtls_test_driver_key_management_hooks_t
v = MBEDTLS_TEST_DRIVER_KEY_MANAGEMENT_INIT;
return v;
}
/*
* In order to convert the plain text keys to Opaque, the size of the key is
* padded up by PSA_CRYPTO_TEST_DRIVER_OPAQUE_PAD_PREFIX_SIZE in addition to
* xor mangling the key. The pad prefix needs to be accounted for while
* sizing for the key.
*/
#define PSA_CRYPTO_TEST_DRIVER_OPAQUE_PAD_PREFIX 0xBEEFED00U
#define PSA_CRYPTO_TEST_DRIVER_OPAQUE_PAD_PREFIX_SIZE sizeof( \
PSA_CRYPTO_TEST_DRIVER_OPAQUE_PAD_PREFIX)
size_t mbedtls_test_opaque_size_function(
const psa_key_type_t key_type,
const size_t key_bits);
extern mbedtls_test_driver_key_management_hooks_t
mbedtls_test_driver_key_management_hooks;
psa_status_t mbedtls_test_transparent_init(void);
void mbedtls_test_transparent_free(void);
psa_status_t mbedtls_test_opaque_init(void);
void mbedtls_test_opaque_free(void);
psa_status_t mbedtls_test_opaque_unwrap_key(
const uint8_t *wrapped_key, size_t wrapped_key_length, uint8_t *key_buffer,
size_t key_buffer_size, size_t *key_buffer_length);
psa_status_t mbedtls_test_transparent_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key, size_t key_size, size_t *key_length);
psa_status_t mbedtls_test_opaque_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key, size_t key_size, size_t *key_length);
psa_status_t mbedtls_test_opaque_export_key(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
uint8_t *data, size_t data_size, size_t *data_length);
psa_status_t mbedtls_test_transparent_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
uint8_t *data, size_t data_size, size_t *data_length);
psa_status_t mbedtls_test_opaque_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
uint8_t *data, size_t data_size, size_t *data_length);
psa_status_t mbedtls_test_transparent_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data,
size_t data_length,
uint8_t *key_buffer,
size_t key_buffer_size,
size_t *key_buffer_length,
size_t *bits);
psa_status_t mbedtls_test_opaque_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data,
size_t data_length,
uint8_t *key_buffer,
size_t key_buffer_size,
size_t *key_buffer_length,
size_t *bits);
psa_status_t mbedtls_test_opaque_get_builtin_key(
psa_drv_slot_number_t slot_number,
psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);
psa_status_t mbedtls_test_opaque_copy_key(
psa_key_attributes_t *attributes,
const uint8_t *source_key,
size_t source_key_length,
uint8_t *target_key_buffer,
size_t target_key_buffer_size,
size_t *target_key_buffer_length);
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_TEST_DRIVERS_KEY_MANAGEMENT_H */

View File

@@ -0,0 +1,127 @@
/*
* Test driver for MAC driver entry points.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_TEST_DRIVERS_MAC_H
#define PSA_CRYPTO_TEST_DRIVERS_MAC_H
#include "mbedtls/build_info.h"
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "test_driver_common.h"
#include <psa/crypto_driver_common.h>
typedef struct {
/* If not PSA_SUCCESS, return this error code instead of processing the
* function call. */
psa_status_t forced_status;
/* Count the amount of times MAC driver functions are called. */
unsigned long hits;
/* Status returned by the last MAC driver function call. */
psa_status_t driver_status;
} mbedtls_test_driver_mac_hooks_t;
#define MBEDTLS_TEST_DRIVER_MAC_INIT { 0, 0, 0 }
static inline mbedtls_test_driver_mac_hooks_t
mbedtls_test_driver_mac_hooks_init(void)
{
const mbedtls_test_driver_mac_hooks_t v = MBEDTLS_TEST_DRIVER_MAC_INIT;
return v;
}
extern mbedtls_test_driver_mac_hooks_t mbedtls_test_driver_mac_hooks;
psa_status_t mbedtls_test_transparent_mac_compute(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *mac,
size_t mac_size,
size_t *mac_length);
psa_status_t mbedtls_test_transparent_mac_sign_setup(
mbedtls_transparent_test_driver_mac_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg);
psa_status_t mbedtls_test_transparent_mac_verify_setup(
mbedtls_transparent_test_driver_mac_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg);
psa_status_t mbedtls_test_transparent_mac_update(
mbedtls_transparent_test_driver_mac_operation_t *operation,
const uint8_t *input,
size_t input_length);
psa_status_t mbedtls_test_transparent_mac_sign_finish(
mbedtls_transparent_test_driver_mac_operation_t *operation,
uint8_t *mac,
size_t mac_size,
size_t *mac_length);
psa_status_t mbedtls_test_transparent_mac_verify_finish(
mbedtls_transparent_test_driver_mac_operation_t *operation,
const uint8_t *mac,
size_t mac_length);
psa_status_t mbedtls_test_transparent_mac_abort(
mbedtls_transparent_test_driver_mac_operation_t *operation);
psa_status_t mbedtls_test_opaque_mac_compute(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *mac,
size_t mac_size,
size_t *mac_length);
psa_status_t mbedtls_test_opaque_mac_sign_setup(
mbedtls_opaque_test_driver_mac_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg);
psa_status_t mbedtls_test_opaque_mac_verify_setup(
mbedtls_opaque_test_driver_mac_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg);
psa_status_t mbedtls_test_opaque_mac_update(
mbedtls_opaque_test_driver_mac_operation_t *operation,
const uint8_t *input,
size_t input_length);
psa_status_t mbedtls_test_opaque_mac_sign_finish(
mbedtls_opaque_test_driver_mac_operation_t *operation,
uint8_t *mac,
size_t mac_size,
size_t *mac_length);
psa_status_t mbedtls_test_opaque_mac_verify_finish(
mbedtls_opaque_test_driver_mac_operation_t *operation,
const uint8_t *mac,
size_t mac_length);
psa_status_t mbedtls_test_opaque_mac_abort(
mbedtls_opaque_test_driver_mac_operation_t *operation);
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_TEST_DRIVERS_MAC_H */

View File

@@ -0,0 +1,77 @@
/*
* Test driver for PAKE driver entry points.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_TEST_DRIVERS_PAKE_H
#define PSA_CRYPTO_TEST_DRIVERS_PAKE_H
#include "mbedtls/build_info.h"
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "test_driver_common.h"
#include <psa/crypto_driver_common.h>
typedef struct {
/* If not PSA_SUCCESS, return this error code instead of processing the
* function call. */
psa_status_t forced_status;
/* PAKE driver setup is executed on the first call to
pake_output/pake_input (added to distinguish forced statuses). */
psa_status_t forced_setup_status;
/* Count the amount of times PAKE driver functions are called. */
struct {
unsigned long total;
unsigned long setup;
unsigned long input;
unsigned long output;
unsigned long implicit_key;
unsigned long abort;
} hits;
/* Status returned by the last PAKE driver function call. */
psa_status_t driver_status;
/* Output returned by pake_output */
void *forced_output;
size_t forced_output_length;
} mbedtls_test_driver_pake_hooks_t;
#define MBEDTLS_TEST_DRIVER_PAKE_INIT { PSA_SUCCESS, PSA_SUCCESS, { 0, 0, 0, 0, 0, 0 }, PSA_SUCCESS, \
NULL, 0 }
static inline mbedtls_test_driver_pake_hooks_t
mbedtls_test_driver_pake_hooks_init(void)
{
const mbedtls_test_driver_pake_hooks_t v = MBEDTLS_TEST_DRIVER_PAKE_INIT;
return v;
}
extern mbedtls_test_driver_pake_hooks_t mbedtls_test_driver_pake_hooks;
psa_status_t mbedtls_test_transparent_pake_setup(
mbedtls_transparent_test_driver_pake_operation_t *operation,
const psa_crypto_driver_pake_inputs_t *inputs);
psa_status_t mbedtls_test_transparent_pake_output(
mbedtls_transparent_test_driver_pake_operation_t *operation,
psa_crypto_driver_pake_step_t step,
uint8_t *output,
size_t output_size,
size_t *output_length);
psa_status_t mbedtls_test_transparent_pake_input(
mbedtls_transparent_test_driver_pake_operation_t *operation,
psa_crypto_driver_pake_step_t step,
const uint8_t *input,
size_t input_length);
psa_status_t mbedtls_test_transparent_pake_get_implicit_key(
mbedtls_transparent_test_driver_pake_operation_t *operation,
uint8_t *output, size_t output_size, size_t *output_length);
psa_status_t mbedtls_test_transparent_pake_abort(
mbedtls_transparent_test_driver_pake_operation_t *operation);
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_TEST_DRIVERS_PAKE_H */

View File

@@ -0,0 +1,114 @@
/*
* Test driver for signature functions.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_TEST_DRIVERS_SIGNATURE_H
#define PSA_CRYPTO_TEST_DRIVERS_SIGNATURE_H
#include "mbedtls/build_info.h"
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "test_driver_common.h"
#include <psa/crypto_driver_common.h>
typedef struct {
/* If non-null, on success, copy this to the output. */
void *forced_output;
size_t forced_output_length;
/* If not PSA_SUCCESS, return this error code instead of processing the
* function call. */
psa_status_t forced_status;
/* Count the amount of times one of the signature driver functions is called. */
unsigned long hits;
} mbedtls_test_driver_signature_hooks_t;
#define MBEDTLS_TEST_DRIVER_SIGNATURE_INIT { NULL, 0, PSA_SUCCESS, 0 }
static inline mbedtls_test_driver_signature_hooks_t
mbedtls_test_driver_signature_hooks_init(void)
{
const mbedtls_test_driver_signature_hooks_t
v = MBEDTLS_TEST_DRIVER_SIGNATURE_INIT;
return v;
}
extern mbedtls_test_driver_signature_hooks_t
mbedtls_test_driver_signature_sign_hooks;
extern mbedtls_test_driver_signature_hooks_t
mbedtls_test_driver_signature_verify_hooks;
psa_status_t mbedtls_test_transparent_signature_sign_message(
const psa_key_attributes_t *attributes,
const uint8_t *key,
size_t key_length,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *signature,
size_t signature_size,
size_t *signature_length);
psa_status_t mbedtls_test_opaque_signature_sign_message(
const psa_key_attributes_t *attributes,
const uint8_t *key,
size_t key_length,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *signature,
size_t signature_size,
size_t *signature_length);
psa_status_t mbedtls_test_transparent_signature_verify_message(
const psa_key_attributes_t *attributes,
const uint8_t *key,
size_t key_length,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
const uint8_t *signature,
size_t signature_length);
psa_status_t mbedtls_test_opaque_signature_verify_message(
const psa_key_attributes_t *attributes,
const uint8_t *key,
size_t key_length,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
const uint8_t *signature,
size_t signature_length);
psa_status_t mbedtls_test_transparent_signature_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg,
const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length);
psa_status_t mbedtls_test_opaque_signature_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg,
const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length);
psa_status_t mbedtls_test_transparent_signature_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg,
const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length);
psa_status_t mbedtls_test_opaque_signature_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg,
const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length);
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_TEST_DRIVERS_SIGNATURE_H */

View File

@@ -0,0 +1,33 @@
/*
* Umbrella include for all of the test driver functionality
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_TEST_DRIVER_H
#define PSA_CRYPTO_TEST_DRIVER_H
#if defined(PSA_CRYPTO_DRIVER_TEST)
#ifndef PSA_CRYPTO_DRIVER_PRESENT
#define PSA_CRYPTO_DRIVER_PRESENT
#endif
#ifndef PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT
#define PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT
#endif
#define PSA_CRYPTO_TEST_DRIVER_LOCATION 0x7fffff
#include "test/drivers/aead.h"
#include "test/drivers/cipher.h"
#include "test/drivers/hash.h"
#include "test/drivers/mac.h"
#include "test/drivers/key_management.h"
#include "test/drivers/signature.h"
#include "test/drivers/asymmetric_encryption.h"
#include "test/drivers/key_agreement.h"
#include "test/drivers/pake.h"
#include "test/drivers/xof.h"
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_TEST_DRIVER_H */

View File

@@ -0,0 +1,90 @@
/* Common definitions used by test drivers. */
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_TEST_DRIVERS_TEST_DRIVER_COMMON_H
#define PSA_CRYPTO_TEST_DRIVERS_TEST_DRIVER_COMMON_H
#include "mbedtls/build_info.h"
/* Use the same formatting for error code definitions as the standard
* error values, which must have a specific sequence of tokens for
* interoperability between implementations of different parts of PSA.
* This means no space between the cast and the - operator.
* This contradicts our code style, so we temporarily disable style checking.
*
* *INDENT-OFF*
*/
/** Error code that test drivers return when they detect that an input
* parameter was not initialized properly. This normally indicates a
* bug in the core.
*/
#define PSA_ERROR_TEST_DETECTED_BAD_INITIALIZATION ((psa_status_t)-0x0201)
/* *INDENT-ON* */
/*
* In the libtestdriver1 library used in Mbed TLS 3.6 and 4.0 for driver
* dispatch testing, the PSA core code is cloned and all identifiers starting
* with MBEDTLS_, PSA_, mbedtls_, or psa_ are prefixed with `libtestdriver1_`.
* As a result, libtestdriver1 drivers use, for example,
* `libtestdriver1_psa_key_attributes_t` instead of `psa_key_attributes_t`.
*
* With the generated test drivers introduced in TF-PSA-Crypto between 1.0
* and 1.1, only the modules under `drivers/builtin` are cloned, not the PSA
* core. The generated test drivers therefore do not use prefixed PSA core
* identifiers. For example, they use the `psa_key_attributes_t` type, just
* like the built-in drivers.
*
* To make driver dispatch work in both cases, we define certain
* `libtestdriver1_xyz` identifiers as aliases of the corresponding `xyz`
* identifiers in the latter case.
*/
#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1)
typedef psa_key_attributes_t libtestdriver1_psa_key_attributes_t;
typedef psa_crypto_driver_pake_inputs_t libtestdriver1_psa_crypto_driver_pake_inputs_t;
typedef psa_crypto_driver_pake_step_t libtestdriver1_psa_crypto_driver_pake_step_t;
#endif
/*
* The LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(basename) macro expands to
* the path of the internal header `basename` of a libtestdriver1 test driver.
*
* The internal headers the macro is dedicated to are the `psa_crypto_xyz.h`
* headers located in `library` in 3.6, in `tf-psa-crypto/drivers/builtin/src`
* in 4.x and in`drivers/builtin/src` in TF-PSA-Crypto.
*
* - In Mbed TLS 3.6 and 4.x, when the libtestdriver1 library is built, its code
* is located in the `libtestdriver1` directory at the root of the project.
* The header path is relative to the repository root and therefore of the
* form:
* - Mbed TLS 3.6: `libtestdriver1/library/xyz`
* - Mbed TLS 4.x: `libtestdriver1/tf-psa-crypto/drivers/builtin/src/xyz`
*
* - In TF-PSA-Crypto, the libtestdriver1 library code is located in
* `drivers/libtestdriver1`. The header path is relative to
* `drivers/libtestdriver1/include` and has the form:
* `../src/libtestdriver1-xyz`
*
* Uncrustify is not happy with the macros, temporarily disable it.
*
* *INDENT-OFF*
*/
#if defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1)
#define LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(basename) \
<../src/libtestdriver1-basename>
#else
#if MBEDTLS_VERSION_MAJOR < 4
#define LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(basename) \
<libtestdriver1/library/basename>
#else
#define LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(basename) \
<libtestdriver1/tf-psa-crypto/drivers/builtin/src/basename>
#endif
#endif
/* *INDENT-ON* */
#endif /* test_driver_common.h */

View File

@@ -0,0 +1,63 @@
/*
* Test driver for xof driver entry points.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_TEST_DRIVERS_XOF_H
#define PSA_CRYPTO_TEST_DRIVERS_XOF_H
#include "mbedtls/build_info.h"
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "test_driver_common.h"
#include <psa/crypto_driver_common.h>
/* The type mbedtls_transparent_test_driver_xof_operation_t is only
* defined since XOF support was added in TF-PSA-Crypto 1.1.0. */
#if defined(PSA_ALG_CATEGORY_XOF)
typedef struct {
/* If not PSA_SUCCESS, return this error code instead of processing the
* function call. */
psa_status_t forced_status;
/* Count the amount of times xof driver entry points are called. */
unsigned long hits;
/* Status returned by the last xof driver entry point call. */
psa_status_t driver_status;
} mbedtls_test_driver_xof_hooks_t;
#define MBEDTLS_TEST_DRIVER_XOF_INIT { 0, 0, 0 }
static inline mbedtls_test_driver_xof_hooks_t
mbedtls_test_driver_xof_hooks_init(void)
{
const mbedtls_test_driver_xof_hooks_t v = MBEDTLS_TEST_DRIVER_XOF_INIT;
return v;
}
extern mbedtls_test_driver_xof_hooks_t mbedtls_test_driver_xof_hooks;
psa_status_t mbedtls_test_transparent_xof_setup(
mbedtls_transparent_test_driver_xof_operation_t *operation,
psa_algorithm_t alg);
psa_status_t mbedtls_test_transparent_xof_set_context(
mbedtls_transparent_test_driver_xof_operation_t *operation,
const uint8_t *context, size_t context_length);
psa_status_t mbedtls_test_transparent_xof_update(
mbedtls_transparent_test_driver_xof_operation_t *operation,
const uint8_t *input, size_t input_length);
psa_status_t mbedtls_test_transparent_xof_output(
mbedtls_transparent_test_driver_xof_operation_t *operation,
uint8_t *output, size_t output_length);
psa_status_t mbedtls_test_transparent_xof_abort(
mbedtls_transparent_test_driver_xof_operation_t *operation);
#endif /* PSA_ALG_CATEGORY_XOF */
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_TEST_DRIVERS_XOF_H */

View File

@@ -0,0 +1,78 @@
/*
* Insecure but standalone implementation of mbedtls_psa_external_get_random().
* Only for use in tests!
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef FAKE_EXTERNAL_RNG_FOR_TEST_H
#define FAKE_EXTERNAL_RNG_FOR_TEST_H
#include "build_info.h"
#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
/** Enable the insecure implementation of mbedtls_psa_external_get_random().
*
* The insecure implementation of mbedtls_psa_external_get_random() is
* disabled by default.
*
* When MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG is enabled and the test
* helpers are linked into a program, you must enable this before running any
* code that uses the PSA subsystem to generate random data (including internal
* random generation for purposes such as blinding when the random generation
* is routed through PSA).
*
* You can enable and disable it at any time, regardless of the state
* of the PSA subsystem. You may disable it temporarily to simulate a
* depleted entropy source.
*/
void mbedtls_test_enable_insecure_external_rng(void);
/** Disable the insecure implementation of mbedtls_psa_external_get_random().
*
* See mbedtls_test_enable_insecure_external_rng().
*/
void mbedtls_test_disable_insecure_external_rng(void);
#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
#if defined(MBEDTLS_PSA_DRIVER_GET_ENTROPY)
#include <mbedtls/platform.h>
/* In the following there are some helper functions which allow tests to
* modify the behavior of the mbedtls_platform_get_entropy() implementation
* provided for test purposes.
* The following features can be controlled:
* - force a return value;
* - force the amount of bytes returned on each call;
* - force amount of entroy returned on each call;
* - get the number of times the callback has been called.
*/
/* Disable all forced values */
void mbedtls_test_platform_get_entropy_reset(void);
/* Force a failure on mbedtls_platform_get_entropy() as follows
* - val = 1 --> returns MBEDTLS_ERR_ENTROPY_SOURCE_FAILED.
* - val = 0 --> works normally (other forced values apply if set).
*/
void mbedtls_test_platform_get_entropy_set_force_failure(int val);
/* If `val < SIZE_MAX` then forcedly limit the amount of data returned from
* mbedtls_platform_get_entropy() to the provided `val` value.
*/
void mbedtls_test_platform_get_entropy_set_output_len(size_t val);
/* If `val < SIZE_MAX` then forcedly limit the amount of returned entropy from
* mbedtls_platform_get_entropy() to the provided `val` value.
*/
void mbedtls_test_platform_get_entropy_set_entropy_content(size_t val);
/* Return the number of times mbedtls_platform_get_entropy() was called. */
size_t mbedtls_test_platform_get_entropy_get_call_count(void);
#endif /* MBEDTLS_PSA_DRIVER_GET_ENTROPY */
#endif /* FAKE_EXTERNAL_RNG_FOR_TEST_H */

View File

@@ -0,0 +1,61 @@
/** Helper functions for testing with subprocesses.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef TEST_FORK_HELPERS_H
#define TEST_FORK_HELPERS_H
#include "test/helpers.h"
/** Type of a function to run in a child process.
*
* The function can mark the test case as failed by calling
* mbedtls_test_fail(). This information will be reported to the parent.
*
* \param param Parameter passed to the callback.
* \param[out] output Buffer for data to pass to the parent.
* This data is ignored if the test case is marked
* as failed.
* \param output_size Size of \p output in bytes.
* \param[out] output_length Number of bytes written to \p output, to be
* passed to the parent. The default is \c 0.
*/
typedef void mbedtls_test_fork_child_callback_t(
void *param,
unsigned char *output, size_t output_size, size_t *output_length);
/* Fork a child process and wait for it to collect some data.
*
* This is similar to backquotes or `$(...)` in a shell.
*
* This function blocks until the child exits.
*
* If the child marks the test as failed or skipped, the child's test
* information (test result and failure location) is propagated to the
* parent.
*
* \note Memory leak detection is disabled in the child.
*
* \param child_callback Callback function to run in the child.
* \param param Parameter to pass to the callback function.
* \param[out] child_output On success, data retrieved from the child.
* Note that the data is only available if the
* child did not mark the test case as failed
* or skipped.
* \param child_output_size Size of \p child_output in bytes.
* \param[out] child_output_length On success, the number of bytes collected
* from the child in \c child_output.
*
* \return \c 0 on success.
* A nonzero value if the test case is marked as failed or skipped.
*/
int mbedtls_test_fork_run_child(
mbedtls_test_fork_child_callback_t *child_callback,
void *param,
unsigned char *child_output, size_t child_output_size,
size_t *child_output_length);
#endif /* TEST_FORK_HELPERS_H */

View File

@@ -0,0 +1,461 @@
/**
* \file helpers.h
*
* \brief This file contains the prototypes of helper functions for the
* purpose of testing.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef TEST_HELPERS_H
#define TEST_HELPERS_H
#include "build_info.h"
#if defined(__SANITIZE_ADDRESS__) /* gcc -fsanitize=address */
# define MBEDTLS_TEST_HAVE_ASAN
#endif
#if defined(__SANITIZE_THREAD__) /* gcc -fsanitize-thread */
# define MBEDTLS_TEST_HAVE_TSAN
#endif
#if defined(__has_feature)
# if __has_feature(address_sanitizer) /* clang -fsanitize=address */
# define MBEDTLS_TEST_HAVE_ASAN
# endif
# if __has_feature(memory_sanitizer) /* clang -fsanitize=memory */
# define MBEDTLS_TEST_HAVE_MSAN
# endif
# if __has_feature(thread_sanitizer) /* clang -fsanitize=thread */
# define MBEDTLS_TEST_HAVE_TSAN
# endif
#endif
#include "test/threading_helpers.h"
#if defined(MBEDTLS_TEST_MUTEX_USAGE)
#include "mbedtls/threading.h"
#endif
#include "mbedtls/platform.h"
#include <stddef.h>
#include <stdint.h>
#if defined(MBEDTLS_BIGNUM_C)
#if !defined(MBEDTLS_VERSION_MAJOR) || MBEDTLS_VERSION_MAJOR >= 4
#include "mbedtls/private/bignum.h"
#else
#include "mbedtls/bignum.h"
#endif
#endif
/** The type of test case arguments that contain binary data. */
typedef struct data_tag {
uint8_t *x;
uint32_t len;
} data_t;
typedef enum {
MBEDTLS_TEST_RESULT_SUCCESS = 0,
MBEDTLS_TEST_RESULT_FAILED,
MBEDTLS_TEST_RESULT_SKIPPED
} mbedtls_test_result_t;
#define MBEDTLS_TEST_LINE_LENGTH 76
typedef struct {
mbedtls_test_result_t result;
const char *test;
const char *filename;
int line_no;
unsigned long step;
char line1[MBEDTLS_TEST_LINE_LENGTH];
char line2[MBEDTLS_TEST_LINE_LENGTH];
#if defined(MBEDTLS_TEST_MUTEX_USAGE)
const char *mutex_usage_error;
#endif
#if defined(MBEDTLS_BIGNUM_C)
unsigned case_uses_negative_0;
#endif
}
mbedtls_test_info_t;
/**
* \brief Get the current test result status
*
* \return The current test result status
*/
mbedtls_test_result_t mbedtls_test_get_result(void);
/**
* \brief Get the current test name/description
*
* \return The current test name/description
*/
const char *mbedtls_test_get_test(void);
/**
* \brief Get the current test filename
*
* \return The current test filename
*/
const char *mbedtls_get_test_filename(void);
/**
* \brief Get the current test file line number (for failure / skip)
*
* \return The current test file line number (for failure / skip)
*/
int mbedtls_test_get_line_no(void);
/**
* \brief Increment the current test step.
*
* \note It is not recommended for multiple threads to call this
* function concurrently - whilst it is entirely thread safe,
* the order of calls to this function can obviously not be
* ensured, so unexpected results may occur.
*/
void mbedtls_test_increment_step(void);
/**
* \brief Get the current test step
*
* \return The current test step
*/
unsigned long mbedtls_test_get_step(void);
/**
* \brief Get the current test line buffer 1
*
* \param line Buffer of minimum size \c MBEDTLS_TEST_LINE_LENGTH,
* which will have line buffer 1 copied to it.
*/
void mbedtls_test_get_line1(char *line);
/**
* \brief Get the current test line buffer 2
*
* \param line Buffer of minimum size \c MBEDTLS_TEST_LINE_LENGTH,
* which will have line buffer 1 copied to it.
*/
void mbedtls_test_get_line2(char *line);
/**
* \brief Get a copy of the test result information.
*
* \param[out] out On output, contains a copy of the current test info.
*/
void mbedtls_test_info_save(mbedtls_test_info_t *out);
/**
* \brief Overwrite the test result information.
* This is intended for some unusual scenarios.
* You probably shouldn't use this in a test function.
*
* \param[in] replacement
* The test info to use instead of the current one.
* The function copies the data, so the pointer does
* not need to be valid after this function returns.
*/
void mbedtls_test_info_overwrite(const mbedtls_test_info_t *replacement);
#if defined(MBEDTLS_TEST_MUTEX_USAGE)
/**
* \brief Get the current mutex usage error message
*
* \return The current mutex error message (may be NULL if no error)
*/
const char *mbedtls_test_get_mutex_usage_error(void);
/**
* \brief Set the current mutex usage error message
*
* \note This will only set the mutex error message if one has not
* already been set, or if we are clearing the message (msg is
* NULL)
*
* \param msg Error message to set (can be NULL to clear)
*/
void mbedtls_test_set_mutex_usage_error(const char *msg);
#endif
/**
* \brief Check whether the given buffer is all-bits-zero.
*
* \param[in] buf Pointer to the buffer to check.
* \param size Buffer size in bytes.
*
* \retval 0 The given buffer has a nonzero byte.
* \retval 1 The given buffer is all-bits-zero (this includes the case
* of an empty buffer).
*/
int mbedtls_test_buffer_is_all_zero(const uint8_t *buf, size_t size);
/** Check whether the object at the given address is all-bits-zero.
*
* \param[in] ptr A pointer to the object to check.
* This macro parameter may be evaluated more than once.
*
* \retval 0 The given object has a nonzero byte.
* \retval 1 The given object is all-bits-zero (this includes the case
* of an empty buffer).
*/
#define MBEDTLS_TEST_OBJECT_IS_ALL_ZERO(ptr) \
(mbedtls_test_buffer_is_all_zero((const uint8_t *) (ptr), sizeof(*(ptr))))
#if defined(MBEDTLS_BIGNUM_C)
/**
* \brief Get whether the current test is a bignum test that uses
* negative zero.
*
* \return non zero if the current test uses bignum negative zero.
*/
unsigned mbedtls_test_get_case_uses_negative_0(void);
/**
* \brief Indicate that the current test uses bignum negative zero.
*
* \note This function is called if the current test case had an
* input parsed with mbedtls_test_read_mpi() that is a negative
* 0 (`"-"`, `"-0"`, `"-00"`, etc., constructing a result with
* the sign bit set to -1 and the value being all-limbs-0,
* which is not a valid representation in #mbedtls_mpi but is
* tested for robustness). *
*/
void mbedtls_test_increment_case_uses_negative_0(void);
#endif
int mbedtls_test_platform_setup(void);
void mbedtls_test_platform_teardown(void);
/**
* \brief Record the current test case as a failure.
*
* This function can be called directly however it is usually
* called via macros such as TEST_ASSERT, TEST_EQUAL,
* PSA_ASSERT, etc...
*
* \note If the test case was already marked as failed, calling
* `mbedtls_test_fail( )` again will not overwrite any
* previous information about the failure.
*
* \param test Description of the failure or assertion that failed. This
* MUST be a string literal.
* \param line_no Line number where the failure originated.
* \param filename Filename where the failure originated.
*/
void mbedtls_test_fail(const char *test, int line_no, const char *filename);
/**
* \brief Record the current test case as a failure
* and show the value of errno.
*
* This function is usually called via #TEST_ASSERT_ERRNO.
*
* \param test Description of the failure or assertion that failed. This
* MUST be a string literal.
* \param line_no Line number where the failure originated.
* \param filename Filename where the failure originated.
*/
void mbedtls_test_fail_errno(const char *test, int line_no, const char *filename);
/**
* \brief Record the current test case as skipped.
*
* This function can be called directly however it is usually
* called via the TEST_ASSUME macro.
*
* \param test Description of the assumption that caused the test case to
* be skipped. This MUST be a string literal.
* \param line_no Line number where the test case was skipped.
* \param filename Filename where the test case was skipped.
*/
void mbedtls_test_skip(const char *test, int line_no, const char *filename);
/**
* \brief Set the test step number for failure reports.
*
* Call this function to display "step NNN" in addition to the
* line number and file name if a test fails. Typically the
* "step number" is the index of a for loop but it can be
* whatever you want.
*
* \note It is not recommended for multiple threads to call this
* function concurrently - whilst it is entirely thread safe,
* the order of calls to this function can obviously not be
* ensured, so unexpected results may occur.
*
* \param step The step number to report.
*/
void mbedtls_test_set_step(unsigned long step);
/**
* \brief Reset mbedtls_test_info to a ready/starting state.
*/
void mbedtls_test_info_reset(void);
#ifdef MBEDTLS_TEST_MUTEX_USAGE
/**
* \brief Get the test info data mutex.
*
* \note This is designed only to be used by threading_helpers to
* avoid a deadlock, not for general access to this mutex.
*
* \return The test info data mutex.
*/
mbedtls_threading_mutex_t *mbedtls_test_get_info_mutex(void);
#endif /* MBEDTLS_TEST_MUTEX_USAGE */
/**
* \brief Record the current test case as a failure if two integers
* have a different value.
*
* This function is usually called via the macro
* #TEST_EQUAL.
*
* \param test Description of the failure or assertion that failed. This
* MUST be a string literal. This normally has the form
* "EXPR1 == EXPR2" where EXPR1 has the value \p value1
* and EXPR2 has the value \p value2.
* \param line_no Line number where the failure originated.
* \param filename Filename where the failure originated.
* \param value1 The first value to compare.
* \param value2 The second value to compare.
*
* \return \c 1 if the values are equal, otherwise \c 0.
*/
int mbedtls_test_equal(const char *test, int line_no, const char *filename,
unsigned long long value1, unsigned long long value2);
/**
* \brief Record the current test case as a failure based
* on comparing two unsigned integers.
*
* This function is usually called via the macro
* #TEST_LE_U.
*
* \param test Description of the failure or assertion that failed. This
* MUST be a string literal. This normally has the form
* "EXPR1 <= EXPR2" where EXPR1 has the value \p value1
* and EXPR2 has the value \p value2.
* \param line_no Line number where the failure originated.
* \param filename Filename where the failure originated.
* \param value1 The first value to compare.
* \param value2 The second value to compare.
*
* \return \c 1 if \p value1 <= \p value2, otherwise \c 0.
*/
int mbedtls_test_le_u(const char *test, int line_no, const char *filename,
unsigned long long value1, unsigned long long value2);
/**
* \brief Record the current test case as a failure based
* on comparing two signed integers.
*
* This function is usually called via the macro
* #TEST_LE_S.
*
* \param test Description of the failure or assertion that failed. This
* MUST be a string literal. This normally has the form
* "EXPR1 <= EXPR2" where EXPR1 has the value \p value1
* and EXPR2 has the value \p value2.
* \param line_no Line number where the failure originated.
* \param filename Filename where the failure originated.
* \param value1 The first value to compare.
* \param value2 The second value to compare.
*
* \return \c 1 if \p value1 <= \p value2, otherwise \c 0.
*/
int mbedtls_test_le_s(const char *test, int line_no, const char *filename,
long long value1, long long value2);
/**
* \brief This function decodes the hexadecimal representation of
* data.
*
* \note The output buffer can be the same as the input buffer. For
* any other overlapping of the input and output buffers, the
* behavior is undefined.
*
* \param obuf Output buffer.
* \param obufmax Size in number of bytes of \p obuf.
* \param ibuf Input buffer.
* \param len The number of unsigned char written in \p obuf. This must
* not be \c NULL.
*
* \return \c 0 on success.
* \return \c -1 if the output buffer is too small or the input string
* is not a valid hexadecimal representation.
*/
int mbedtls_test_unhexify(unsigned char *obuf, size_t obufmax,
const char *ibuf, size_t *len);
void mbedtls_test_hexify(unsigned char *obuf,
const unsigned char *ibuf,
int len);
/**
* \brief Convert hexadecimal digit to an integer.
*
* \param c The digit to convert (`'0'` to `'9'`, `'A'` to `'F'` or
* `'a'` to `'f'`).
* \param[out] uc On success, the value of the digit (0 to 15).
*
* \return 0 on success, -1 if \p c is not a hexadecimal digit.
*/
int mbedtls_test_ascii2uc(const char c, unsigned char *uc);
/**
* Allocate and zeroize a buffer.
*
* If the size if zero, a pointer to a zeroized 1-byte buffer is returned.
*
* For convenience, dies if allocation fails.
*/
unsigned char *mbedtls_test_zero_alloc(size_t len);
/**
* Allocate and fill a buffer from hex data.
*
* The buffer is sized exactly as needed. This allows to detect buffer
* overruns (including overreads) when running the test suite under valgrind.
*
* If the size if zero, a pointer to a zeroized 1-byte buffer is returned.
*
* For convenience, dies if allocation fails.
*/
unsigned char *mbedtls_test_unhexify_alloc(const char *ibuf, size_t *olen);
int mbedtls_test_hexcmp(uint8_t *a, uint8_t *b,
uint32_t a_len, uint32_t b_len);
#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
#include "test/fake_external_rng_for_test.h"
#endif
#if defined(MBEDTLS_TEST_HOOKS)
/**
* \brief Check that only a pure high-level error code is being combined with
* a pure low-level error code as otherwise the resultant error code
* would be corrupted.
*
* \note Both high-level and low-level error codes cannot be greater than
* zero however can be zero. If one error code is zero then the
* other error code is returned even if both codes are zero.
*
* \note If the check fails, fail the test currently being run.
*/
void mbedtls_test_err_add_check(int high, int low,
const char *file, int line);
#endif
#endif /* TEST_HELPERS_H */

View File

@@ -0,0 +1,270 @@
/**
* \file macros.h
*
* \brief This file contains generic macros for the purpose of testing.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef TEST_MACROS_H
#define TEST_MACROS_H
#include "build_info.h"
#include <stdlib.h>
#include "mbedtls/platform.h"
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
#include "mbedtls/memory_buffer_alloc.h"
#endif
#if defined(TF_PSA_CRYPTO_VERSION_NUMBER)
#include "tf_psa_crypto_common.h"
#else
#include "common.h"
#endif
/**
* \brief This macro tests the expression passed to it as a test step or
* individual test in a test case.
*
* It allows a library function to return a value and return an error
* code that can be tested.
*
* Failing the test means:
* - Mark this test case as failed.
* - Print a message identifying the failure.
* - Jump to the \c exit label.
*
* This macro expands to an instruction, not an expression.
* It may jump to the \c exit label.
*
* \param TEST The test expression to be tested.
*/
#define TEST_ASSERT(TEST) \
do { \
if (!(TEST)) \
{ \
mbedtls_test_fail( #TEST, __LINE__, __FILE__); \
goto exit; \
} \
} while (0)
/** \brief Evaluate an integer expression. If the value is 0 (i.e. false),
* mark the test case as failed and display errno.
*
* This is intended for functions that follow the Unix API convention of
* returning a particular value (often -1) and setting errno on failure,
* e.g. `TEST_ASSERT_ERRNO(open(...) != -1)`.
*/
#define TEST_ASSERT_ERRNO(expr) \
do { \
if (!(expr)) { \
mbedtls_test_fail_errno(#expr, __LINE__, __FILE__); \
goto exit; \
} \
} while (0)
/** This macro asserts fails the test with given output message.
*
* \param MESSAGE The message to be outputed on assertion
*/
#define TEST_FAIL(MESSAGE) \
do { \
mbedtls_test_fail(MESSAGE, __LINE__, __FILE__); \
goto exit; \
} while (0)
/** Evaluate two integer expressions and fail the test case if they have
* different values.
*
* The two expressions should have the same signedness, otherwise the
* comparison is not meaningful if the signed value is negative.
*
* \param expr1 An integral-typed expression to evaluate.
* \param expr2 Another integral-typed expression to evaluate.
*/
#define TEST_EQUAL(expr1, expr2) \
do { \
if (!mbedtls_test_equal( #expr1 " == " #expr2, __LINE__, __FILE__, \
(unsigned long long) (expr1), (unsigned long long) (expr2))) \
goto exit; \
} while (0)
/** Evaluate two unsigned integer expressions and fail the test case
* if they are not in increasing order (left <= right).
*
* \param expr1 An integral-typed expression to evaluate.
* \param expr2 Another integral-typed expression to evaluate.
*/
#define TEST_LE_U(expr1, expr2) \
do { \
if (!mbedtls_test_le_u( #expr1 " <= " #expr2, __LINE__, __FILE__, \
expr1, expr2)) \
goto exit; \
} while (0)
/** Evaluate two signed integer expressions and fail the test case
* if they are not in increasing order (left <= right).
*
* \param expr1 An integral-typed expression to evaluate.
* \param expr2 Another integral-typed expression to evaluate.
*/
#define TEST_LE_S(expr1, expr2) \
do { \
if (!mbedtls_test_le_s( #expr1 " <= " #expr2, __LINE__, __FILE__, \
expr1, expr2)) \
goto exit; \
} while (0)
/** Allocate memory dynamically and fail the test case if this fails.
* The allocated memory will be filled with zeros.
*
* You must set \p pointer to \c NULL before calling this macro and
* put `mbedtls_free(pointer)` in the test's cleanup code.
*
* If \p item_count is zero, the resulting \p pointer will be \c NULL.
* This is usually what we want in tests since API functions are
* supposed to accept null pointers when a buffer size is zero.
*
* This macro expands to an instruction, not an expression.
* It may jump to the \c exit label.
*
* \param pointer An lvalue where the address of the allocated buffer
* will be stored.
* This expression may be evaluated multiple times.
* \param item_count Number of elements to allocate.
* This expression may be evaluated multiple times.
*
*/
#define TEST_CALLOC(pointer, item_count) \
do { \
TEST_ASSERT((pointer) == NULL); \
if ((item_count) != 0) { \
(pointer) = mbedtls_calloc((item_count), \
sizeof(*(pointer))); \
TEST_ASSERT((pointer) != NULL); \
} \
} while (0)
/** Allocate memory dynamically and fail the test case if this fails.
* The allocated memory will be filled with zeros.
*
* You must set \p pointer to \c NULL before calling this macro and
* put `mbedtls_free(pointer)` in the test's cleanup code.
*
* If \p item_count is zero, the resulting \p pointer will not be \c NULL.
*
* This macro expands to an instruction, not an expression.
* It may jump to the \c exit label.
*
* \param pointer An lvalue where the address of the allocated buffer
* will be stored.
* This expression may be evaluated multiple times.
* \param item_count Number of elements to allocate.
* This expression may be evaluated multiple times.
*
* Note: if passing size 0, mbedtls_calloc may return NULL. In this case,
* we reattempt to allocate with the smallest possible buffer to assure a
* non-NULL pointer.
*/
#define TEST_CALLOC_NONNULL(pointer, item_count) \
do { \
TEST_ASSERT((pointer) == NULL); \
(pointer) = mbedtls_calloc((item_count), \
sizeof(*(pointer))); \
if (((pointer) == NULL) && ((item_count) == 0)) { \
(pointer) = mbedtls_calloc(1, 1); \
} \
TEST_ASSERT((pointer) != NULL); \
} while (0)
/* For backwards compatibility */
#define ASSERT_ALLOC(pointer, item_count) TEST_CALLOC(pointer, item_count)
/** Allocate memory dynamically. If the allocation fails, skip the test case.
*
* This macro behaves like #TEST_CALLOC, except that if the allocation
* fails, it marks the test as skipped rather than failed.
*/
#define TEST_CALLOC_OR_SKIP(pointer, item_count) \
do { \
TEST_ASSERT((pointer) == NULL); \
if ((item_count) != 0) { \
(pointer) = mbedtls_calloc((item_count), \
sizeof(*(pointer))); \
TEST_ASSUME((pointer) != NULL); \
} \
} while (0)
/* For backwards compatibility */
#define ASSERT_ALLOC_WEAK(pointer, item_count) TEST_CALLOC_OR_SKIP(pointer, item_count)
/** Compare two buffers and fail the test case if they differ.
*
* This macro expands to an instruction, not an expression.
* It may jump to the \c exit label.
*
* \param p1 Pointer to the start of the first buffer.
* \param size1 Size of the first buffer in bytes.
* This expression may be evaluated multiple times.
* \param p2 Pointer to the start of the second buffer.
* \param size2 Size of the second buffer in bytes.
* This expression may be evaluated multiple times.
*/
#define TEST_MEMORY_COMPARE(p1, size1, p2, size2) \
do { \
TEST_EQUAL((size1), (size2)); \
if ((size1) != 0) { \
TEST_ASSERT(memcmp((p1), (p2), (size1)) == 0); \
} \
} while (0)
/* For backwards compatibility */
#define ASSERT_COMPARE(p1, size1, p2, size2) TEST_MEMORY_COMPARE(p1, size1, p2, size2)
/**
* \brief This macro tests the expression passed to it and skips the
* running test if it doesn't evaluate to 'true'.
*
* \param TEST The test expression to be tested.
*/
#define TEST_ASSUME(TEST) \
do { \
if (!(TEST)) \
{ \
mbedtls_test_skip( #TEST, __LINE__, __FILE__); \
goto exit; \
} \
} while (0)
#define TEST_HELPER_ASSERT(a) if (!(a)) \
{ \
mbedtls_fprintf(stderr, "Assertion Failed at %s:%d - %s\n", \
__FILE__, __LINE__, #a); \
mbedtls_exit(1); \
}
/** Return the smaller of two values.
*
* \param x An integer-valued expression without side effects.
* \param y An integer-valued expression without side effects.
*
* \return The smaller of \p x and \p y.
*/
#define MIN(x, y) ((x) < (y) ? (x) : (y))
/** Return the larger of two values.
*
* \param x An integer-valued expression without side effects.
* \param y An integer-valued expression without side effects.
*
* \return The larger of \p x and \p y.
*/
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#endif /* TEST_MACROS_H */

View File

@@ -0,0 +1,109 @@
/**
* \file memory.h
*
* \brief Helper macros and functions related to testing memory management.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef TEST_MEMORY_H
#define TEST_MEMORY_H
#include "build_info.h"
#include "mbedtls/platform.h"
#include "test/helpers.h"
/** \def MBEDTLS_TEST_MEMORY_CAN_POISON
*
* This macro is defined if the tests are compiled with a method to mark
* memory as poisoned, which can be used to enforce some memory access
* policies.
*
* Support for the C11 thread_local keyword is also required.
*
* Currently, only Asan (Address Sanitizer) is supported.
*/
#if defined(MBEDTLS_TEST_HAVE_ASAN) && \
(__STDC_VERSION__ >= 201112L) && \
!defined(PSA_CRYPTO_DRIVER_TEST)
# define MBEDTLS_TEST_MEMORY_CAN_POISON
#endif
/** \def MBEDTLS_TEST_MEMORY_POISON(buf, size)
*
* Poison a memory area so that any attempt to read or write from it will
* cause a runtime failure.
*
* Depending on the implementation, this may poison a few bytes beyond the
* indicated region, but will never poison a separate object on the heap
* or a separate object with more than the alignment of a long long.
*
* The behavior is undefined if any part of the memory area is invalid.
*
* This is a no-op in builds without a poisoning method.
* See #MBEDTLS_TEST_MEMORY_CAN_POISON.
*
* \param buf Pointer to the beginning of the memory area to poison.
* \param size Size of the memory area in bytes.
*/
/** \def MBEDTLS_TEST_MEMORY_UNPOISON(buf, size)
*
* Undo the effect of #MBEDTLS_TEST_MEMORY_POISON.
*
* The behavior is undefined if any part of the memory area is invalid,
* or if the memory area contains a mixture of poisoned and unpoisoned parts.
*
* This is a no-op in builds without a poisoning method.
* See #MBEDTLS_TEST_MEMORY_CAN_POISON.
*
* \param buf Pointer to the beginning of the memory area to unpoison.
* \param size Size of the memory area in bytes.
*/
#if defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
/** Thread-local variable used to enable memory poisoning. This is set and
* unset in the test wrappers so that calls to PSA functions from the library
* do not poison memory.
*/
extern _Thread_local unsigned int mbedtls_test_memory_poisoning_count;
/** Poison a memory area so that any attempt to read or write from it will
* cause a runtime failure.
*
* The behavior is undefined if any part of the memory area is invalid.
*/
void mbedtls_test_memory_poison(const unsigned char *ptr, size_t size);
#define MBEDTLS_TEST_MEMORY_POISON(ptr, size) \
do { \
mbedtls_test_memory_poisoning_count++; \
mbedtls_test_memory_poison(ptr, size); \
} while (0)
/** Undo the effect of mbedtls_test_memory_poison().
*
* This is a no-op if the given area is entirely valid, unpoisoned memory.
*
* The behavior is undefined if any part of the memory area is invalid,
* or if the memory area contains a mixture of poisoned and unpoisoned parts.
*/
void mbedtls_test_memory_unpoison(const unsigned char *ptr, size_t size);
#define MBEDTLS_TEST_MEMORY_UNPOISON(ptr, size) \
do { \
mbedtls_test_memory_unpoison(ptr, size); \
if (mbedtls_test_memory_poisoning_count != 0) { \
mbedtls_test_memory_poisoning_count--; \
} \
} while (0)
#else /* MBEDTLS_TEST_MEMORY_CAN_POISON */
#define MBEDTLS_TEST_MEMORY_POISON(ptr, size) ((void) (ptr), (void) (size))
#define MBEDTLS_TEST_MEMORY_UNPOISON(ptr, size) ((void) (ptr), (void) (size))
#endif /* MBEDTLS_TEST_MEMORY_CAN_POISON */
#endif /* TEST_MEMORY_H */

View File

@@ -0,0 +1,96 @@
/*
* Helper functions for PK.
* This is only for TF-PSA-Crypto 1.0 and above.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PK_HELPERS_H
#define PK_HELPERS_H
#include "build_info.h"
#if defined(MBEDTLS_PK_C)
#include <psa/crypto.h>
#include <mbedtls/pk.h>
/* 'pk_context_populate_method_t' is only used in 'mbedtls_pk_helpers_populate_context'
* which takes a PSA key ID to populate the PK context. The idea is to use that
* function after calling 'mbedtls_pk_helpers_make_psa_key_from_predefined' to
* retrieve a PSA key ID. Adding support for parsing doesn't fit well with the
* current prototype of 'mbedtls_pk_helpers_populate_context'.
* What is needed to add parsing in the list below is a new function which acts
* as a combination between 'mbedtls_pk_helpers_make_psa_key_from_predefined' and
* 'mbedtls_pk_helpers_populate_context', i.e. it takes a key type, key bits and
* population method as input and it returns a PK context.
*/
typedef enum {
TEST_PK_WRAP_PSA,
TEST_PK_COPY_FROM_PSA,
TEST_PK_COPY_PUBLIC_FROM_PSA,
} pk_context_populate_method_t;
/**
* Get predefined key pair/public key data for the requested key.
*
* If the specified key type or bit length does not exist in the list of known
* predefined keys, an assertion failure will be generated.
*
* The output format is compatible with PSA API, so they key can be imported
* with psa_import_key().
*
* \param key_type PSA key type for the key being requested.
* \param key_bits Bit length for the PSA key being requested.
* \param output Pointer which on exit will point to the key material that has
* been requested by "key_type" and "key_bits".
* \param output_len Length of the key material being pointed to from "output".
*
* \return 0 on success; MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the required
* key is not the in list of known ones.
*/
int mbedtls_pk_helpers_get_predefined_key_data(psa_key_type_t key_type, psa_key_bits_t key_bits,
const uint8_t **output, size_t *output_len);
/**
* Create a PSA key using prefined key data.
*
* Predefined key data is used to create the key and the choice of predefined
* key material is based on the combination of "key_type" and "key_bits".
*
* \param key_type Type of key to be created. For the time being only RSA and
* EC key types are supported.
* \param key_bits Length of the key (in bits).
* \param alg Algorithm to be associated with the key.
* \param alg2 Enrollment alogrithm to be associated with the key.
* \param usage_flags Usage flags to be associated with the key.
*
* \return On success the key ID of the created PSA key.
* On failure 0 is returned and the test is marked as failed.
*/
mbedtls_svc_key_id_t mbedtls_pk_helpers_make_psa_key_from_predefined(psa_key_type_t key_type,
psa_key_bits_t key_bits,
psa_algorithm_t alg,
psa_algorithm_t alg2,
psa_key_usage_t usage_flags);
/**
* Populate the given PK context using "key_id" and the desired "method".
*
* \param pk The PK context to be populated; it must have been initialized.
* \param key_id The PSA key ID to be used to populate the PK context.
* \param method The desired method for populating the PK context. See
* "pk_context_populate_method_t" for available options.
*
* \return 0 on success.
* In case of failure -1 is returned and the test case is marked
* as failed.
*/
int mbedtls_pk_helpers_populate_context(mbedtls_pk_context *pk, mbedtls_svc_key_id_t key_id,
pk_context_populate_method_t method);
#endif /* MBEDTLS_PK_C */
#endif /* PK_HELPERS_H */

View File

@@ -0,0 +1,568 @@
/*
* Helper functions for tests that use the PSA Crypto API.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_HELPERS_H
#define PSA_CRYPTO_HELPERS_H
#include "build_info.h"
#include "test/helpers.h"
#if (MBEDTLS_VERSION_MAJOR < 4 && defined(MBEDTLS_PSA_CRYPTO_C)) || \
(MBEDTLS_VERSION_MAJOR >= 4 && defined(MBEDTLS_PSA_CRYPTO_CLIENT))
#include "test/psa_helpers.h"
#endif
#include <psa/crypto.h>
#if !defined(MBEDTLS_VERSION_MAJOR) || MBEDTLS_VERSION_MAJOR >= 4
#include <mbedtls/private/ctr_drbg.h>
#else
#include <mbedtls/ctr_drbg.h>
#endif
#if defined(MBEDTLS_PSA_CRYPTO_C)
/** Initialize the PSA Crypto subsystem. */
#define PSA_INIT() PSA_ASSERT(psa_crypto_init())
/** Shut down the PSA Crypto subsystem and destroy persistent keys.
* Expect a clean shutdown, with no slots in use.
*
* If some key slots are still in use, record the test case as failed,
* but continue executing. This macro is suitable (and primarily intended)
* for use in the cleanup section of test functions.
*
* \note Persistent keys must be recorded with #TEST_USES_KEY_ID before
* creating them.
*/
#define PSA_DONE() \
do \
{ \
mbedtls_test_fail_if_psa_leaking(__LINE__, __FILE__); \
mbedtls_test_psa_purge_key_storage(); \
mbedtls_psa_crypto_free(); \
} \
while (0)
#elif MBEDTLS_VERSION_MAJOR >= 4 && defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#define PSA_INIT() PSA_ASSERT(psa_crypto_init())
#define PSA_DONE() mbedtls_psa_crypto_free();
#else /* MBEDTLS_PSA_CRYPTO_CLIENT && !MBEDTLS_PSA_CRYPTO_C */
#define PSA_INIT() ((void) 0)
#define PSA_DONE() ((void) 0)
#endif /* MBEDTLS_PSA_CRYPTO_C */
#if (MBEDTLS_VERSION_MAJOR < 4 && defined(MBEDTLS_PSA_CRYPTO_C)) || \
(MBEDTLS_VERSION_MAJOR >= 4 && defined(MBEDTLS_PSA_CRYPTO_CLIENT))
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
/* Internal function for #TEST_USES_KEY_ID. Return 1 on success, 0 on failure. */
int mbedtls_test_uses_key_id(mbedtls_svc_key_id_t key_id);
/** Destroy persistent keys recorded with #TEST_USES_KEY_ID.
*/
void mbedtls_test_psa_purge_key_storage(void);
/** Purge the in-memory cache of persistent keys recorded with
* #TEST_USES_KEY_ID.
*
* Call this function before calling PSA_DONE() if it's ok for
* persistent keys to still exist at this point.
*/
void mbedtls_test_psa_purge_key_cache(void);
/** \def TEST_USES_KEY_ID
*
* Call this macro in a test function before potentially creating a
* persistent key. Test functions that use this mechanism must call
* mbedtls_test_psa_purge_key_storage() in their cleanup code.
*
* This macro records a persistent key identifier as potentially used in the
* current test case. Recorded key identifiers will be cleaned up at the end
* of the test case, even on failure.
*
* This macro has no effect on volatile keys. Therefore, it is safe to call
* this macro in a test function that creates either volatile or persistent
* keys depending on the test data.
*
* This macro currently has no effect on special identifiers
* used to store implementation-specific files.
*
* Calling this macro multiple times on the same key identifier in the same
* test case has no effect.
*
* This macro can fail the test case if there isn't enough memory to
* record the key id.
*
* \param key_id The PSA key identifier to record.
*/
#define TEST_USES_KEY_ID(key_id) \
TEST_ASSERT(mbedtls_test_uses_key_id(key_id))
#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
#define TEST_USES_KEY_ID(key_id) ((void) (key_id))
#define mbedtls_test_psa_purge_key_storage() ((void) 0)
#define mbedtls_test_psa_purge_key_cache() ((void) 0)
#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
/** Check for things that have not been cleaned up properly in the
* PSA subsystem.
*
* \return NULL if nothing has leaked.
* \return A string literal explaining what has not been cleaned up
* if applicable.
*/
const char *mbedtls_test_helper_is_psa_leaking(void);
/** Check that no PSA Crypto key slots are in use.
*
* If any slots are in use, mark the current test as failed and jump to
* the exit label. This is equivalent to
* `TEST_ASSERT( ! mbedtls_test_helper_is_psa_leaking( ) )`
* but with a more informative message.
*/
#define ASSERT_PSA_PRISTINE() \
do \
{ \
if (mbedtls_test_fail_if_psa_leaking(__LINE__, __FILE__)) \
goto exit; \
} \
while (0)
/** Shut down the PSA Crypto subsystem, allowing persistent keys to survive.
* Expect a clean shutdown, with no slots in use.
*
* If some key slots are still in use, record the test case as failed and
* jump to the `exit` label.
*/
#define PSA_SESSION_DONE() \
do \
{ \
mbedtls_test_psa_purge_key_cache(); \
ASSERT_PSA_PRISTINE(); \
mbedtls_psa_crypto_free(); \
} \
while (0)
/** Initializer that doesn't set the embedded union to zero.
*
* Use this to validate that our code correctly handles platforms where
* `{0}` does not initialize a union to all-bits-zero, only the first member.
* Such behavior is uncommon, but compliant (see discussion in
* https://github.com/Mbed-TLS/mbedtls/issues/9814).
* You can portably simulate that behavior by using the `xxx_init_short()`
* initializer function instead of `{0}` or an official initializer
* `xxx_init()` or `XXX_INIT`.
*/
psa_hash_operation_t psa_hash_operation_init_short(void);
psa_mac_operation_t psa_mac_operation_init_short(void);
psa_cipher_operation_t psa_cipher_operation_init_short(void);
psa_aead_operation_t psa_aead_operation_init_short(void);
psa_key_derivation_operation_t psa_key_derivation_operation_init_short(void);
psa_pake_operation_t psa_pake_operation_init_short(void);
psa_sign_hash_interruptible_operation_t psa_sign_hash_interruptible_operation_init_short(void);
psa_verify_hash_interruptible_operation_t psa_verify_hash_interruptible_operation_init_short(void);
#if defined(PSA_KEY_AGREEMENT_IOP_INIT)
psa_key_agreement_iop_t psa_key_agreement_iop_init_short(void);
#endif
#if defined(PSA_GENERATE_KEY_IOP_INIT)
psa_generate_key_iop_t psa_generate_key_iop_init_short(void);
#endif
#if defined(PSA_EXPORT_PUBLIC_KEY_IOP_INIT)
psa_export_public_key_iop_t psa_export_public_key_iop_init_short(void);
#endif
#if defined(RECORD_PSA_STATUS_COVERAGE_LOG)
psa_status_t mbedtls_test_record_status(psa_status_t status,
const char *func,
const char *file, int line,
const char *expr);
/** Return value logging wrapper macro.
*
* Evaluate \p expr. Write a line recording its value to the log file
* #STATUS_LOG_FILE_NAME and return the value. The line is a colon-separated
* list of fields:
* ```
* value of expr:string:__FILE__:__LINE__:expr
* ```
*
* The test code does not call this macro explicitly because that would
* be very invasive. Instead, we instrument the source code by defining
* a bunch of wrapper macros like
* ```
* #define psa_crypto_init() RECORD_STATUS("psa_crypto_init", psa_crypto_init())
* ```
* These macro definitions must be present in `instrument_record_status.h`
* when building the test suites.
*
* \param string A string, normally a function name.
* \param expr An expression to evaluate, normally a call of the function
* whose name is in \p string. This expression must return
* a value of type #psa_status_t.
* \return The value of \p expr.
*/
#define RECORD_STATUS(string, expr) \
mbedtls_test_record_status((expr), string, __FILE__, __LINE__, #expr)
#include "instrument_record_status.h"
#endif /* defined(RECORD_PSA_STATUS_COVERAGE_LOG) */
/** Return extended key usage policies.
*
* Do a key policy permission extension on key usage policies always involves
* permissions of other usage policies
* (like PSA_KEY_USAGE_SIGN_HASH involves PSA_KEY_USAGE_SIGN_MESSAGE).
*/
psa_key_usage_t mbedtls_test_update_key_usage_flags(psa_key_usage_t usage_flags);
/** Check that no PSA Crypto key slots are in use.
*
* If any slots are in use, mark the current test as failed.
*
* \return 0 if the key store is empty, 1 otherwise.
*/
int mbedtls_test_fail_if_psa_leaking(int line_no, const char *filename);
#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
/* The #MBEDTLS_PSA_INJECT_ENTROPY feature requires two extra platform
* functions, which must be configured as #MBEDTLS_PLATFORM_NV_SEED_READ_MACRO
* and #MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO. The job of these functions
* is to read and write from the entropy seed file, which is located
* in the PSA ITS file whose uid is #PSA_CRYPTO_ITS_RANDOM_SEED_UID.
* (These could have been provided as library functions, but for historical
* reasons, they weren't, and so each integrator has to provide a copy
* of these functions.)
*
* Provide implementations of these functions for testing. */
int mbedtls_test_inject_entropy_seed_read(unsigned char *buf, size_t len);
int mbedtls_test_inject_entropy_seed_write(unsigned char *buf, size_t len);
/** Make sure that the injected entropy is present.
*
* When MBEDTLS_PSA_INJECT_ENTROPY is enabled, psa_crypto_init()
* will fail if the PSA entropy seed is not present.
* This function must be called at least once in a test suite or other
* program before any call to psa_crypto_init().
* It does not need to be called in each test case.
*
* The test framework calls this function before running any test case.
*
* The few tests that might remove the entropy file must call this function
* in their cleanup.
*/
int mbedtls_test_inject_entropy_restore(void);
#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
/** Parse binary string and convert it to a long integer
*/
uint64_t mbedtls_test_parse_binary_string(data_t *bin_string);
/** Skip a test case if the given key is a 192 bits AES key and the AES
* implementation is at least partially provided by an accelerator or
* alternative implementation.
*
* Call this macro in a test case when a cryptographic operation that may
* involve an AES operation returns a #PSA_ERROR_NOT_SUPPORTED error code.
* The macro call will skip and not fail the test case in case the operation
* involves a 192 bits AES key and the AES implementation is at least
* partially provided by an accelerator or alternative implementation.
*
* Hardware AES implementations not supporting 192 bits keys commonly exist.
* Consequently, PSA test cases aim at not failing when an AES operation with
* a 192 bits key performed by an alternative AES implementation returns
* with the #PSA_ERROR_NOT_SUPPORTED error code. The purpose of this macro
* is to facilitate this and make the test case code more readable.
*
* \param key_type Key type
* \param key_bits Key length in number of bits.
*/
#if defined(MBEDTLS_AES_ALT) || \
defined(MBEDTLS_AES_SETKEY_ENC_ALT) || \
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES)
#define MBEDTLS_TEST_HAVE_ACCEL_AES 1
#else
#define MBEDTLS_TEST_HAVE_ACCEL_AES 0
#endif
#define MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192(key_type, key_bits) \
do \
{ \
if ((MBEDTLS_TEST_HAVE_ACCEL_AES) && \
((key_type) == PSA_KEY_TYPE_AES) && \
(key_bits == 192)) \
{ \
mbedtls_test_skip("AES-192 not supported", __LINE__, __FILE__); \
goto exit; \
} \
} \
while (0)
/** Skip a test case if a GCM operation with a nonce length different from
* 12 bytes fails and was performed by an accelerator or alternative
* implementation.
*
* Call this macro in a test case when an AEAD cryptography operation that
* may involve the GCM mode returns with a #PSA_ERROR_NOT_SUPPORTED error
* code. The macro call will skip and not fail the test case in case the
* operation involves the GCM mode, a nonce with a length different from
* 12 bytes and the GCM mode implementation is an alternative one.
*
* Hardware GCM implementations not supporting nonce lengths different from
* 12 bytes commonly exist, as supporting a non-12-byte nonce requires
* additional computations involving the GHASH function.
* Consequently, PSA test cases aim at not failing when an AEAD operation in
* GCM mode with a nonce length different from 12 bytes is performed by an
* alternative GCM implementation and returns with a #PSA_ERROR_NOT_SUPPORTED
* error code. The purpose of this macro is to facilitate this check and make
* the test case code more readable.
*
* \param alg The AEAD algorithm.
* \param nonce_length The nonce length in number of bytes.
*/
#if defined(MBEDTLS_GCM_ALT) || \
defined(MBEDTLS_PSA_ACCEL_ALG_GCM)
#define MBEDTLS_TEST_HAVE_ACCEL_GCM 1
#else
#define MBEDTLS_TEST_HAVE_ACCEL_GCM 0
#endif
#define MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE(alg, \
nonce_length) \
do \
{ \
if ((MBEDTLS_TEST_HAVE_ACCEL_GCM) && \
(PSA_ALG_AEAD_WITH_SHORTENED_TAG((alg), 0) == \
PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0)) && \
((nonce_length) != 12)) \
{ \
mbedtls_test_skip("GCM with non-12-byte IV is not supported", __LINE__, __FILE__); \
goto exit; \
} \
} \
while (0)
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT || MBEDTLS_PSA_CRYPTO_C */
#if MBEDTLS_VERSION_MAJOR >= 4
/* Legacy PSA_INIT() / PSA_DONE() variants from 3.6 */
#define USE_PSA_INIT() PSA_INIT()
#define USE_PSA_DONE() PSA_DONE()
#define MD_PSA_INIT() PSA_INIT()
#define MD_PSA_DONE() PSA_DONE()
#define BLOCK_CIPHER_PSA_INIT() PSA_INIT()
#define BLOCK_CIPHER_PSA_DONE() PSA_DONE()
#define MD_OR_USE_PSA_INIT() PSA_INIT()
#define MD_OR_USE_PSA_DONE() PSA_DONE()
#define AES_PSA_INIT() PSA_INIT()
#define AES_PSA_DONE() PSA_DONE()
#else /* MBEDTLS_VERSION_MAJOR < 4 */
/** \def USE_PSA_INIT
*
* Call this macro to initialize the PSA subsystem if #MBEDTLS_USE_PSA_CRYPTO
* or #MBEDTLS_SSL_PROTO_TLS1_3 (In contrast to TLS 1.2 implementation, the
* TLS 1.3 one uses PSA independently of the definition of
* #MBEDTLS_USE_PSA_CRYPTO) is enabled and do nothing otherwise.
*
* If the initialization fails, mark the test case as failed and jump to the
* \p exit label.
*/
/** \def USE_PSA_DONE
*
* Call this macro at the end of a test case if you called #USE_PSA_INIT.
*
* This is like #PSA_DONE except it does nothing under the same conditions as
* #USE_PSA_INIT.
*/
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#define USE_PSA_INIT() PSA_INIT()
#define USE_PSA_DONE() PSA_DONE()
#elif defined(MBEDTLS_SSL_PROTO_TLS1_3)
/* TLS 1.3 must work without having called psa_crypto_init(), for backward
* compatibility with Mbed TLS <= 3.5 when connecting with a peer that
* supports both TLS 1.2 and TLS 1.3. See mbedtls_ssl_tls13_crypto_init()
* and https://github.com/Mbed-TLS/mbedtls/issues/9072 . */
#define USE_PSA_INIT() ((void) 0)
/* TLS 1.3 may have initialized the PSA subsystem. Shut it down cleanly,
* otherwise Asan and Valgrind would notice a resource leak. */
#define USE_PSA_DONE() PSA_DONE()
#else /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */
/* Define empty macros so that we can use them in the preamble and teardown
* of every test function that uses PSA conditionally based on
* MBEDTLS_USE_PSA_CRYPTO. */
#define USE_PSA_INIT() ((void) 0)
#define USE_PSA_DONE() ((void) 0)
#endif /* !MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_SSL_PROTO_TLS1_3 */
/** \def MD_PSA_INIT
*
* Call this macro to initialize the PSA subsystem if MD uses a driver,
* and do nothing otherwise.
*
* If the initialization fails, mark the test case as failed and jump to the
* \p exit label.
*/
/** \def MD_PSA_DONE
*
* Call this macro at the end of a test case if you called #MD_PSA_INIT.
*
* This is like #PSA_DONE except it does nothing under the same conditions as
* #MD_PSA_INIT.
*/
#if defined(MBEDTLS_MD_SOME_PSA)
#define MD_PSA_INIT() PSA_INIT()
#define MD_PSA_DONE() PSA_DONE()
#else /* MBEDTLS_MD_SOME_PSA */
#define MD_PSA_INIT() ((void) 0)
#define MD_PSA_DONE() ((void) 0)
#endif /* MBEDTLS_MD_SOME_PSA */
/** \def BLOCK_CIPHER_PSA_INIT
*
* Call this macro to initialize the PSA subsystem if BLOCK_CIPHER uses a driver,
* and do nothing otherwise.
*
* If the initialization fails, mark the test case as failed and jump to the
* \p exit label.
*/
/** \def BLOCK_CIPHER_PSA_DONE
*
* Call this macro at the end of a test case if you called #BLOCK_CIPHER_PSA_INIT.
*
* This is like #PSA_DONE except it does nothing under the same conditions as
* #BLOCK_CIPHER_PSA_INIT.
*/
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
#define BLOCK_CIPHER_PSA_INIT() PSA_INIT()
#define BLOCK_CIPHER_PSA_DONE() PSA_DONE()
#else /* MBEDTLS_MD_SOME_PSA */
#define BLOCK_CIPHER_PSA_INIT() ((void) 0)
#define BLOCK_CIPHER_PSA_DONE() ((void) 0)
#endif /* MBEDTLS_MD_SOME_PSA */
/** \def MD_OR_USE_PSA_INIT
*
* Call this macro to initialize the PSA subsystem if MD uses a driver,
* or if #MBEDTLS_USE_PSA_CRYPTO or #MBEDTLS_SSL_PROTO_TLS1_3 is enabled,
* and do nothing otherwise.
*
* If the initialization fails, mark the test case as failed and jump to the
* \p exit label.
*/
/** \def MD_OR_USE_PSA_DONE
*
* Call this macro at the end of a test case if you called #MD_OR_USE_PSA_INIT.
*
* This is like #PSA_DONE except it does nothing under the same conditions as
* #MD_OR_USE_PSA_INIT.
*/
#if defined(MBEDTLS_MD_SOME_PSA)
#define MD_OR_USE_PSA_INIT() PSA_INIT()
#define MD_OR_USE_PSA_DONE() PSA_DONE()
#else
#define MD_OR_USE_PSA_INIT() USE_PSA_INIT()
#define MD_OR_USE_PSA_DONE() USE_PSA_DONE()
#endif
/** \def AES_PSA_INIT
*
* Call this macro to initialize the PSA subsystem if AES_C is not defined,
* so that CTR_DRBG uses PSA implementation to get AES-ECB.
*
* If the initialization fails, mark the test case as failed and jump to the
* \p exit label.
*/
/** \def AES_PSA_DONE
*
* Call this macro at the end of a test case if you called #AES_PSA_INIT.
*
* This is like #PSA_DONE except it does nothing under the same conditions as
* #AES_PSA_INIT.
*/
#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
#define AES_PSA_INIT() PSA_INIT()
#define AES_PSA_DONE() PSA_DONE()
#else /* MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO */
#define AES_PSA_INIT() ((void) 0)
#define AES_PSA_DONE() ((void) 0)
#endif /* MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO */
#endif /* MBEDTLS_VERSION_MAJOR >= 4 */
#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) && \
defined(MBEDTLS_CTR_DRBG_C) && \
defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
/* When AES_C is not defined and PSA does not have an external RNG,
* then CTR_DRBG uses PSA to perform AES-ECB. In this scenario 1 key
* slot is used internally from PSA to hold the AES key and it should
* not be taken into account when evaluating remaining open slots. */
#define MBEDTLS_TEST_PSA_INTERNAL_KEYS_FOR_DRBG 1
#else
#define MBEDTLS_TEST_PSA_INTERNAL_KEYS_FOR_DRBG 0
#endif
/** The number of volatile keys that PSA crypto uses internally.
*
* We expect that many volatile keys to be in use after a successful
* psa_crypto_init().
*/
#define MBEDTLS_TEST_PSA_INTERNAL_KEYS \
MBEDTLS_TEST_PSA_INTERNAL_KEYS_FOR_DRBG
/* A couple of helper macros to verify if MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE is
* large enough to contain an RSA key pair of the given size. This is meant to be
* used in test cases where MBEDTLS_PSA_STATIC_KEY_SLOTS is enabled. */
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#if (MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE >= PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(4096))
#define MBEDTLS_TEST_STATIC_KEY_SLOTS_SUPPORT_RSA_4096
#endif
#if (MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE >= PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(2048))
#define MBEDTLS_TEST_STATIC_KEY_SLOTS_SUPPORT_RSA_2048
#endif
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
/* Helper macro to get the size of the each key slot buffer. */
#if defined(MBEDTLS_PSA_STATIC_KEY_SLOTS)
#define MBEDTLS_PSA_KEY_BUFFER_MAX_SIZE MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE
#else
#define MBEDTLS_PSA_KEY_BUFFER_MAX_SIZE SIZE_MAX
#endif
/* Helper macro for the PK module to check whether MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE
* is large enough to contain 4096-bit RSA key pairs. Of course this check is only
* necessary if PK relies on PSA (i.e. MBEDTLS_USE_PSA_CRYPTO) to store and manage
* the key. */
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#if !defined(MBEDTLS_PSA_STATIC_KEY_SLOTS) || \
defined(MBEDTLS_TEST_STATIC_KEY_SLOTS_SUPPORT_RSA_4096)
#define MBEDTLS_TEST_PK_ALLOW_RSA_KEY_PAIR_4096
#endif
#else /* MBEDTLS_USE_PSA_CRYPTO */
#define MBEDTLS_TEST_PK_ALLOW_RSA_KEY_PAIR_4096
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* PSA_CRYPTO_HELPERS_H */

View File

@@ -0,0 +1,301 @@
/** Code to exercise a PSA key object, i.e. validate that it seems well-formed
* and can do what it is supposed to do.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_EXERCISE_KEY_H
#define PSA_EXERCISE_KEY_H
#include "build_info.h"
#include "test/helpers.h"
#include "test/psa_crypto_helpers.h"
#include <psa/crypto.h>
#if defined(MBEDTLS_PK_C)
#include <mbedtls/pk.h>
#if defined(MBEDTLS_PK_HAVE_PRIVATE_HEADER)
#include <mbedtls/private/pk_private.h>
#endif /* MBEDTLS_PK_HAVE_PRIVATE_HEADER */
#endif /* MBEDTLS_PK_C */
/** \def KNOWN_SUPPORTED_HASH_ALG
*
* A hash algorithm that is known to be supported.
*
* This is used in some smoke tests.
*/
#if defined(PSA_WANT_ALG_SHA_256)
#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_256
#elif defined(PSA_WANT_ALG_SHA_384)
#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_384
#elif defined(PSA_WANT_ALG_SHA_512)
#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_512
#elif defined(PSA_WANT_ALG_SHA3_256)
#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA3_256
#elif defined(PSA_WANT_ALG_SHA_1)
#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_1
#elif defined(PSA_WANT_ALG_MD5)
#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_MD5
/* PSA_WANT_ALG_RIPEMD160 omitted. This is necessary for the sake of
* exercise_signature_key() because Mbed TLS doesn't support RIPEMD160
* in RSA PKCS#1v1.5 signatures. A RIPEMD160-only configuration would be
* implausible anyway. */
#else
#undef KNOWN_SUPPORTED_HASH_ALG
#endif
/** \def KNOWN_SUPPORTED_BLOCK_CIPHER
*
* A block cipher that is known to be supported.
*
* For simplicity's sake, stick to block ciphers with 16-byte blocks.
*/
#if defined(PSA_WANT_KEY_TYPE_AES)
#define KNOWN_SUPPORTED_BLOCK_CIPHER PSA_KEY_TYPE_AES
#elif defined(PSA_WANT_KEY_TYPE_ARIA)
#define KNOWN_SUPPORTED_BLOCK_CIPHER PSA_KEY_TYPE_ARIA
#elif defined(PSA_WANT_KEY_TYPE_CAMELLIA)
#define KNOWN_SUPPORTED_BLOCK_CIPHER PSA_KEY_TYPE_CAMELLIA
#else
#undef KNOWN_SUPPORTED_BLOCK_CIPHER
#endif
/** \def KNOWN_SUPPORTED_MAC_ALG
*
* A MAC mode that is known to be supported.
*
* It must either be HMAC with #KNOWN_SUPPORTED_HASH_ALG or
* a block cipher-based MAC with #KNOWN_SUPPORTED_BLOCK_CIPHER.
*
* This is used in some smoke tests.
*/
#if defined(KNOWN_SUPPORTED_HASH_ALG) && defined(PSA_WANT_ALG_HMAC)
#define KNOWN_SUPPORTED_MAC_ALG (PSA_ALG_HMAC(KNOWN_SUPPORTED_HASH_ALG))
#define KNOWN_SUPPORTED_MAC_KEY_TYPE PSA_KEY_TYPE_HMAC
#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(MBEDTLS_CMAC_C)
#define KNOWN_SUPPORTED_MAC_ALG PSA_ALG_CMAC
#define KNOWN_SUPPORTED_MAC_KEY_TYPE KNOWN_SUPPORTED_BLOCK_CIPHER
#else
#undef KNOWN_SUPPORTED_MAC_ALG
#undef KNOWN_SUPPORTED_MAC_KEY_TYPE
#endif
/** \def KNOWN_SUPPORTED_BLOCK_CIPHER_ALG
*
* A cipher algorithm and key type that are known to be supported.
*
* This is used in some smoke tests.
*/
#if defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(PSA_WANT_ALG_CTR)
#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_CTR
#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(PSA_WANT_ALG_CBC_NO_PADDING)
#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_CBC_NO_PADDING
#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(PSA_WANT_ALG_CFB)
#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_CFB
#elif defined(KNOWN_SUPPORTED_BLOCK_CIPHER) && defined(PSA_WANT_ALG_OFB)
#define KNOWN_SUPPORTED_BLOCK_CIPHER_ALG PSA_ALG_OFB
#else
#undef KNOWN_SUPPORTED_BLOCK_CIPHER_ALG
#endif
#if defined(KNOWN_SUPPORTED_BLOCK_CIPHER_ALG)
#define KNOWN_SUPPORTED_CIPHER_ALG KNOWN_SUPPORTED_BLOCK_CIPHER_ALG
#define KNOWN_SUPPORTED_CIPHER_KEY_TYPE KNOWN_SUPPORTED_BLOCK_CIPHER
#else
#undef KNOWN_SUPPORTED_CIPHER_ALG
#undef KNOWN_SUPPORTED_CIPHER_KEY_TYPE
#endif
/** Convenience function to set up a key derivation.
*
* In case of failure, mark the current test case as failed.
*
* The inputs \p input1 and \p input2 are, in order:
* - HKDF: salt, info.
* - TKS 1.2 PRF, TLS 1.2 PSK-to-MS: seed, label.
* - PBKDF2: input cost, salt.
*
* \param operation The operation object to use.
* It must be in the initialized state.
* \param key The key to use.
* \param alg The algorithm to use.
* \param input1 The first input to pass.
* \param input1_length The length of \p input1 in bytes.
* \param input2 The first input to pass.
* \param input2_length The length of \p input2 in bytes.
* \param capacity The capacity to set.
* \param key_destroyable If set to 1, a failure due to the key not existing
* or the key being destroyed mid-operation will only
* be reported if the error code is unexpected.
*
* \return \c 1 on success, \c 0 on failure.
*/
int mbedtls_test_psa_setup_key_derivation_wrap(
psa_key_derivation_operation_t *operation,
mbedtls_svc_key_id_t key,
psa_algorithm_t alg,
const unsigned char *input1, size_t input1_length,
const unsigned char *input2, size_t input2_length,
size_t capacity, int key_destroyable);
/** Perform a key agreement using the given key pair against its public key
* (not combined with a key derivation).
*
* The result is discarded. Thus this function can be used for smoke-testing
* a key, and to validate input validation, but not to validate results.
*
* Depending on the library version, there can be multiple interfaces for key
* agreement. This test function performs the ones that are available amongst:
* - psa_raw_key_agreement()
* - psa_key_agreement()
* - psa_key_agreement_iop_setup() and psa_key_agreement_iop_complete()
*
* Mark the current test case as failed in the following cases:
* - Operational errors such as failure to allocate memory for an intermediate
* buffer.
* - Results are not consistent between the methods that are performed:
* different statuses, or inconsistent metadata, or different shared secret.
*
* \param alg A key agreement algorithm compatible with \p key.
* \param key A key that allows key agreement with \p alg.
* \param key_destroyable If set to 1, a failure due to the key not existing
* or the key being destroyed mid-operation will only
* be reported if the error code is unexpected.
*
* \return The status from psa_raw_key_agreement().
*/
psa_status_t mbedtls_test_psa_raw_key_agreement_with_self(
psa_algorithm_t alg,
mbedtls_svc_key_id_t key, int key_destroyable);
/** Perform a key agreement using the given key pair against its public key
* using psa_key_derivation_raw_key().
*
* The result is discarded. The purpose of this function is to smoke-test a key.
*
* In case of failure, mark the current test case as failed.
*
* \param operation An operation that has been set up for a key
* agreement algorithm that is compatible with
* \p key.
* \param key A key pair object that is suitable for a key
* agreement with \p operation.
* \param key_destroyable If set to 1, a failure due to the key not existing
* or the key being destroyed mid-operation will only
* be reported if the error code is unexpected.
*
* \return \c 1 on success, \c 0 on failure.
*/
psa_status_t mbedtls_test_psa_key_agreement_with_self(
psa_key_derivation_operation_t *operation,
mbedtls_svc_key_id_t key, int key_destroyable);
/** Perform sanity checks on the given key representation.
*
* If any of the checks fail, mark the current test case as failed.
*
* The checks depend on the key type.
* - All types: check the export size against maximum-size macros.
* - DES: parity bits.
* - RSA: check the ASN.1 structure and the size and parity of the integers.
* - ECC private or public key: exact representation length.
* - Montgomery public key: first byte.
*
* \param type The key type.
* \param bits The key size in bits.
* \param exported A buffer containing the key representation.
* \param exported_length The length of \p exported in bytes.
*
* \return \c 1 if all checks passed, \c 0 on failure.
*/
int mbedtls_test_psa_exported_key_sanity_check(
psa_key_type_t type, size_t bits,
const uint8_t *exported, size_t exported_length);
/** Do smoke tests on a key.
*
* Perform one of each operation indicated by \p alg (decrypt/encrypt,
* sign/verify, or derivation) that is permitted according to \p usage.
* \p usage and \p alg should correspond to the expected policy on the
* key.
*
* Export the key if permitted by \p usage, and check that the output
* looks sensible. If \p usage forbids export, check that
* \p psa_export_key correctly rejects the attempt. If the key is
* asymmetric, also check \p psa_export_public_key.
*
* If the key fails the tests, this function calls the test framework's
* `mbedtls_test_fail` function and returns false. Otherwise this function
* returns true. Therefore it should be used as follows:
* ```
* if( ! exercise_key( ... ) ) goto exit;
* ```
* To use this function for multi-threaded tests where the key
* may be destroyed at any point: call this function with key_destroyable set
* to 1, while another thread calls psa_destroy_key on the same key;
* this will test whether destroying the key in use leads to any corruption.
*
* There cannot be a set of concurrent calls:
* `mbedtls_test_psa_exercise_key(ki,...)` such that each ki is a unique
* persistent key not loaded into any key slot, and i is greater than the
* number of free key slots.
* This is because such scenarios can lead to unsupported
* `PSA_ERROR_INSUFFICIENT_MEMORY` return codes.
*
*
* \param key The key to exercise. It should be capable of performing
* \p alg.
* \param usage The usage flags to assume.
* \param alg The algorithm to exercise.
* \param key_destroyable If set to 1, a failure due to the key not existing
* or the key being destroyed mid-operation will only
* be reported if the error code is unexpected.
*
* \retval 0 The key failed the smoke tests.
* \retval 1 The key passed the smoke tests.
*/
int mbedtls_test_psa_exercise_key(mbedtls_svc_key_id_t key,
psa_key_usage_t usage,
psa_algorithm_t alg,
int key_destroyable);
psa_key_usage_t mbedtls_test_psa_usage_to_exercise(psa_key_type_t type,
psa_algorithm_t alg);
/** Whether the specified algorithm can be exercised.
*
* \note This function is solely based on the algorithm and does not
* consider potential issues with the compatibility of a key.
* The idea is that you already have a key, so you know that the
* key type is supported, and you want to exercise the key but
* only if the algorithm given in its policy is enabled in the
* compile-time configuration.
*
* \note This function currently only supports signature algorithms
* (including wildcards).
* TODO: a more general mechanism, which should be automatically
* generated and possibly available as a library function?
*/
int mbedtls_test_can_exercise_psa_algorithm(psa_algorithm_t alg);
#if defined(MBEDTLS_PK_C)
/** PK-PSA key consistency test.
*
* This function tests that the pk context and the PSA key are
* consistent. At a minimum:
*
* - The two objects must contain keys of the same type,
* or a key pair and a public key of the matching type.
* - The two objects must have the same public key.
*
* \retval 0 The key failed the consistency tests.
* \retval 1 The key passed the consistency tests.
*/
int mbedtls_test_key_consistency_psa_pk(mbedtls_svc_key_id_t psa_key,
const mbedtls_pk_context *pk);
#endif /* MBEDTLS_PK_C */
#endif /* PSA_EXERCISE_KEY_H */

View File

@@ -0,0 +1,26 @@
/*
* Helper functions for tests that use any PSA API.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_HELPERS_H
#define PSA_HELPERS_H
#include "build_info.h"
#if defined(MBEDTLS_PSA_CRYPTO_SPM)
#include "spm/psa_defs.h"
#endif
/** Evaluate an expression and fail the test case if it returns an error.
*
* \param expr The expression to evaluate. This is typically a call
* to a \c psa_xxx function that returns a value of type
* #psa_status_t.
*/
#define PSA_ASSERT(expr) TEST_EQUAL((expr), PSA_SUCCESS)
#endif /* PSA_HELPERS_H */

View File

@@ -0,0 +1,42 @@
/** Support for memory poisoning wrappers for PSA functions.
*
* The wrappers poison the input and output buffers of each function
* before calling it, to ensure that it does not access the buffers
* except by calling the approved buffer-copying functions.
*
* This header declares support functions. The wrappers themselves are
* decalred in the automatically generated file `test/psa_test_wrappers.h`.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_MEMORY_POISONING_WRAPPERS_H
#define PSA_MEMORY_POISONING_WRAPPERS_H
#include "build_info.h"
#include "psa/crypto.h"
#include "test/memory.h"
#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
/**
* \brief Setup the memory poisoning test hooks used by
* psa_crypto_copy_input() and psa_crypto_copy_output() for
* memory poisoning.
*/
void mbedtls_poison_test_hooks_setup(void);
/**
* \brief Teardown the memory poisoning test hooks used by
* psa_crypto_copy_input() and psa_crypto_copy_output() for
* memory poisoning.
*/
void mbedtls_poison_test_hooks_teardown(void);
#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_TEST_MEMORY_CAN_POISON */
#endif /* PSA_MEMORY_POISONING_WRAPPERS_H */

View File

@@ -0,0 +1,91 @@
/**
* \file random.h
*
* \brief This file contains the prototypes of helper functions to generate
* random numbers for the purpose of testing.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef TEST_RANDOM_H
#define TEST_RANDOM_H
#include "build_info.h"
#include <stddef.h>
#include <stdint.h>
typedef struct {
unsigned char *buf; /* Pointer to a buffer of length bytes. */
size_t length;
/* If fallback_f_rng is NULL, fail after delivering length bytes. */
int (*fallback_f_rng)(void *, unsigned char *, size_t);
void *fallback_p_rng;
} mbedtls_test_rnd_buf_info;
/**
* Info structure for the pseudo random function
*
* Key should be set at the start to a test-unique value.
* Do not forget endianness!
* State( v0, v1 ) should be set to zero.
*/
typedef struct {
uint32_t key[16];
uint32_t v0, v1;
} mbedtls_test_rnd_pseudo_info;
/**
* This function just returns data from rand().
* Although predictable and often similar on multiple
* runs, this does not result in identical random on
* each run. So do not use this if the results of a
* test depend on the random data that is generated.
*
* rng_state shall be NULL.
*/
int mbedtls_test_rnd_std_rand(void *rng_state,
unsigned char *output,
size_t len);
/**
* This function only returns zeros.
*
* \p rng_state shall be \c NULL.
*/
int mbedtls_test_rnd_zero_rand(void *rng_state,
unsigned char *output,
size_t len);
/**
* This function returns random data based on a buffer it receives.
*
* \p rng_state shall be a pointer to a #mbedtls_test_rnd_buf_info structure.
*
* The number of bytes released from the buffer on each call to
* the random function is specified by \p len.
*
* After the buffer is empty, this function will call the fallback RNG in the
* #mbedtls_test_rnd_buf_info structure if there is one, and
* will return #MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise.
*/
int mbedtls_test_rnd_buffer_rand(void *rng_state,
unsigned char *output,
size_t len);
/**
* This function returns random based on a pseudo random function.
* This means the results should be identical on all systems.
* Pseudo random is based on the XTEA encryption algorithm to
* generate pseudorandom.
*
* \p rng_state shall be a pointer to a #mbedtls_test_rnd_pseudo_info structure.
*/
int mbedtls_test_rnd_pseudo_rand(void *rng_state,
unsigned char *output,
size_t len);
#endif /* TEST_RANDOM_H */

View File

@@ -0,0 +1,119 @@
/**
* \file threading_helpers.h
*
* \brief This file contains the prototypes of helper functions for the purpose
* of testing threading.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef THREADING_HELPERS_H
#define THREADING_HELPERS_H
#include "build_info.h"
#if defined MBEDTLS_THREADING_C
#include <mbedtls/threading.h>
/* Error in thread management */
#define MBEDTLS_ERR_THREADING_THREAD_ERROR -0x001F
/* Error in mutex usage (used in Mbed TLS up to 3.6, no longer used
* outside the test framework since TF-PSA-Crypto 1.0).
*
* In Mbed TLS 3.5, this is a redefinition of the macro to the same
* value (down to the exact sequence of tokens and presence/absence of
* whitespace between tokens), which is valid C.
*/
#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C
#if defined(MBEDTLS_THREADING_PTHREAD)
#include <pthread.h>
#endif /* MBEDTLS_THREADING_PTHREAD */
#if defined(MBEDTLS_THREADING_ALT)
/* You should define the mbedtls_test_thread_t type in your header */
#include "threading_alt.h"
/**
* \brief Set your alternate threading implementation
* function pointers for test threads. If used, this
* function must be called once in the main thread
* before any other MbedTLS function is called.
*
* \note These functions are part of the testing API only and
* thus not considered part of the public API of
* MbedTLS and thus may change without notice.
*
* \param thread_create The thread create function implementation.
* \param thread_join The thread join function implementation.
*/
void mbedtls_test_thread_set_alt(int (*thread_create)(mbedtls_test_thread_t *thread,
void *(*thread_func)(
void *),
void *thread_data),
int (*thread_join)(mbedtls_test_thread_t *thread));
#else /* MBEDTLS_THREADING_ALT*/
typedef struct mbedtls_test_thread_t {
#if defined(MBEDTLS_THREADING_PTHREAD)
pthread_t MBEDTLS_PRIVATE(thread);
#else /* MBEDTLS_THREADING_PTHREAD */
/* Make sure this struct is always non-empty */
unsigned dummy;
#endif
} mbedtls_test_thread_t;
#endif /* MBEDTLS_THREADING_ALT*/
/**
* \brief The function pointers for thread create and thread
* join.
*
* \note These functions are part of the testing API only
* and thus not considered part of the public API of
* MbedTLS and thus may change without notice.
*
* \note All these functions are expected to work or
* the result will be undefined.
*/
extern int (*mbedtls_test_thread_create)(mbedtls_test_thread_t *thread,
void *(*thread_func)(void *), void *thread_data);
extern int (*mbedtls_test_thread_join)(mbedtls_test_thread_t *thread);
#if defined(MBEDTLS_THREADING_PTHREAD) && defined(MBEDTLS_TEST_HOOKS)
#define MBEDTLS_TEST_MUTEX_USAGE
#endif
#if defined(MBEDTLS_TEST_MUTEX_USAGE)
/**
* Activate the mutex usage verification framework. See threading_helpers.c for
* information.
*/
void mbedtls_test_mutex_usage_init(void);
/**
* Deactivate the mutex usage verification framework. See threading_helpers.c
* for information.
*/
void mbedtls_test_mutex_usage_end(void);
/**
* Call this function after executing a test case to check for mutex usage
* errors.
*/
void mbedtls_test_mutex_usage_check(void);
#endif /* MBEDTLS_TEST_MUTEX_USAGE */
#endif /* MBEDTLS_THREADING_C */
#endif /* THREADING_HELPERS_H */

View File

@@ -0,0 +1,52 @@
#!/bin/sh
# Run the shared library dynamic loading demo program.
# This is only expected to work when Mbed TLS is built as a shared library.
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
SCRIPT_DIR=$(dirname "$0")
. "${SCRIPT_DIR}/../../scripts/demo_common.sh"
msg "Test the dynamic loading of libmbed*"
# Once demo_common.sh is sourced we'll have $root_dir pointing to the root
# path of Mbed TLS or TF-PSA-Crypto.
if is_mbedtls_root $root_dir; then
msg "Running in Mbed TLS repo"
program="$root_dir/programs/test/dlopen"
library_dir="$root_dir/library"
else
msg "Running in TF-PSA-Crypto repo"
program="$root_dir/programs/test/tfpsacrypto_dlopen"
library_dir="$root_dir/core"
fi
# Skip this test if we don't have a shared library build. Detect this
# through the absence of the demo program.
if [ ! -e "$program" ]; then
msg "Error: demo program $program not found."
# Exit with a success status so that this counts as a pass for run_demos.py.
exit
fi
# ELF-based Unix-like (Linux, *BSD, Solaris, ...)
if [ -n "${LD_LIBRARY_PATH-}" ]; then
LD_LIBRARY_PATH="$library_dir:$LD_LIBRARY_PATH"
else
LD_LIBRARY_PATH="$library_dir"
fi
export LD_LIBRARY_PATH
# OSX/macOS
if [ -n "${DYLD_LIBRARY_PATH-}" ]; then
DYLD_LIBRARY_PATH="$library_dir:$DYLD_LIBRARY_PATH"
else
DYLD_LIBRARY_PATH="$library_dir"
fi
export DYLD_LIBRARY_PATH
msg "Running dynamic loading test program: $program"
msg "Loading libraries from: $library_dir"
"$program"

View File

@@ -0,0 +1,499 @@
/** \file metatest.c
*
* \brief Test features of the test framework.
*
* When you run this program, it runs a single "meta-test". A meta-test
* performs an operation which should be caught as a failure by our
* test framework. The meta-test passes if this program calls `exit` with
* a nonzero status, or aborts, or is terminated by a signal, or if the
* framework running the program considers the run an error (this happens
* with Valgrind for a memory leak). The non-success of the meta-test
* program means that the test failure has been caught correctly.
*
* Some failures are purely functional: the logic of the code causes the
* test result to be set to FAIL. Other failures come from extra
* instrumentation which is not present in a normal build; for example,
* Asan or Valgrind to detect memory leaks. This is reflected by the
* "platform" associated with each meta-test.
*
* Use the companion script `framework/scripts/run-metatests.sh` to run all
* the meta-tests for a given platform and validate that they trigger a
* detected failure as expected.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/* On Mingw-w64, force the use of a C99-compliant printf() and friends.
* This is necessary on older versions of Mingw and/or Windows runtimes
* where snprintf does not always zero-terminate the buffer, and does
* not support formats such as "%zu" for size_t and "%lld" for long long.
*/
#if !defined(__USE_MINGW_ANSI_STDIO)
#define __USE_MINGW_ANSI_STDIO 1
#endif
#include <mbedtls/debug.h>
#include <mbedtls/platform.h>
#include <mbedtls/platform_util.h>
#include "test/helpers.h"
#include "test/threading_helpers.h"
#include "test/macros.h"
#include "test/memory.h"
#include <stdio.h>
#include <string.h>
#if defined(MBEDTLS_THREADING_C)
#include "threading_internal.h"
#endif
/* This is an external variable, so the compiler doesn't know that we're never
* changing its value.
*/
volatile int false_but_the_compiler_does_not_know = 0;
/* Hide calls to calloc/free from static checkers such as
* `gcc-12 -Wuse-after-free`, to avoid compile-time complaints about
* code where we do mean to cause a runtime error. */
void * (* volatile calloc_but_the_compiler_does_not_know)(size_t, size_t) = mbedtls_calloc;
void(*volatile free_but_the_compiler_does_not_know)(void *) = mbedtls_free;
/* Set n bytes at the address p to all-bits-zero, in such a way that
* the compiler should not know that p is all-bits-zero. */
static void set_to_zero_but_the_compiler_does_not_know(volatile void *p, size_t n)
{
memset((void *) p, false_but_the_compiler_does_not_know, n);
}
/* Simulate an access to the given object, to avoid compiler optimizations
* in code that prepares or consumes the object. */
static void do_nothing_with_object(void *p)
{
(void) p;
}
void(*volatile do_nothing_with_object_but_the_compiler_does_not_know)(void *) =
do_nothing_with_object;
/****************************************************************/
/* Test framework features */
/****************************************************************/
static void meta_test_fail(const char *name)
{
(void) name;
mbedtls_test_fail("Forced test failure", __LINE__, __FILE__);
}
static void meta_test_not_equal(const char *name)
{
int left = 20;
int right = 10;
(void) name;
TEST_EQUAL(left, right);
exit:
;
}
static void meta_test_not_le_s(const char *name)
{
int left = 20;
int right = 10;
(void) name;
TEST_LE_S(left, right);
exit:
;
}
static void meta_test_not_le_u(const char *name)
{
size_t left = 20;
size_t right = 10;
(void) name;
TEST_LE_U(left, right);
exit:
;
}
/****************************************************************/
/* Platform features */
/****************************************************************/
static void null_pointer_dereference(const char *name)
{
(void) name;
volatile char *volatile p;
set_to_zero_but_the_compiler_does_not_know(&p, sizeof(p));
/* Undefined behavior (read from null data pointer) */
mbedtls_printf("%p -> %u\n", (void *) p, (unsigned) *p);
}
static void null_pointer_call(const char *name)
{
(void) name;
unsigned(*volatile p)(void);
set_to_zero_but_the_compiler_does_not_know(&p, sizeof(p));
/* Undefined behavior (execute null function pointer) */
/* The pointer representation may be truncated, but we don't care:
* the only point of printing it is to have some use of the pointer
* to dissuade the compiler from optimizing it away. */
mbedtls_printf("%lx() -> %u\n", (unsigned long) (uintptr_t) p, p());
}
/****************************************************************/
/* Memory */
/****************************************************************/
static void read_after_free(const char *name)
{
(void) name;
volatile char *p = calloc_but_the_compiler_does_not_know(1, 1);
*p = 'a';
free_but_the_compiler_does_not_know((void *) p);
/* Undefined behavior (read after free) */
mbedtls_printf("%u\n", (unsigned) *p);
}
static void double_free(const char *name)
{
(void) name;
volatile char *p = calloc_but_the_compiler_does_not_know(1, 1);
*p = 'a';
free_but_the_compiler_does_not_know((void *) p);
/* Undefined behavior (double free) */
free_but_the_compiler_does_not_know((void *) p);
}
static void read_uninitialized_stack(const char *name)
{
(void) name;
char buf[1];
if (false_but_the_compiler_does_not_know) {
buf[0] = '!';
}
char *volatile p = buf;
if (*p != 0) {
/* Unspecified result (read from uninitialized memory) */
mbedtls_printf("%u\n", (unsigned) *p);
}
}
static void memory_leak(const char *name)
{
(void) name;
volatile char *p = calloc_but_the_compiler_does_not_know(1, 1);
mbedtls_printf("%u\n", (unsigned) *p);
/* Leak of a heap object */
}
/* name = "test_memory_poison_%(start)_%(offset)_%(count)_%(direction)"
* Poison a region starting at start from an 8-byte aligned origin,
* encompassing count bytes. Access the region at offset from the start.
* %(start), %(offset) and %(count) are decimal integers.
* %(direction) is either the character 'r' for read or 'w' for write.
*/
static void test_memory_poison(const char *name)
{
size_t start = 0, offset = 0, count = 0;
char direction = 'r';
if (sscanf(name,
"%*[^0-9]%zu%*[^0-9]%zu%*[^0-9]%zu_%c",
&start, &offset, &count, &direction) != 4) {
mbedtls_fprintf(stderr, "%s: Bad name format: %s\n", __func__, name);
return;
}
union {
long long ll;
unsigned char buf[32];
} aligned;
memset(aligned.buf, 'a', sizeof(aligned.buf));
if (start > sizeof(aligned.buf)) {
mbedtls_fprintf(stderr,
"%s: start=%zu > size=%zu",
__func__, start, sizeof(aligned.buf));
return;
}
if (start + count > sizeof(aligned.buf)) {
mbedtls_fprintf(stderr,
"%s: start+count=%zu > size=%zu",
__func__, start + count, sizeof(aligned.buf));
return;
}
if (offset >= count) {
mbedtls_fprintf(stderr,
"%s: offset=%zu >= count=%zu",
__func__, offset, count);
return;
}
MBEDTLS_TEST_MEMORY_POISON(aligned.buf + start, count);
if (direction == 'w') {
aligned.buf[start + offset] = 'b';
do_nothing_with_object_but_the_compiler_does_not_know(aligned.buf);
} else {
do_nothing_with_object_but_the_compiler_does_not_know(aligned.buf);
mbedtls_printf("%u\n", (unsigned) aligned.buf[start + offset]);
}
}
/****************************************************************/
/* Threading */
/****************************************************************/
static void mutex_lock_not_initialized(const char *name)
{
(void) name;
#if defined(MBEDTLS_THREADING_C)
mbedtls_threading_mutex_t mutex;
memset(&mutex, 0, sizeof(mutex));
/* This mutex usage error is detected by our test framework's mutex usage
* verification framework. See framework/tests/src/threading_helpers.c. Other
* threading implementations (e.g. pthread without our instrumentation)
* might consider this normal usage. */
TEST_ASSERT(mbedtls_mutex_lock(&mutex) == 0);
exit:
;
#endif
}
static void mutex_unlock_not_initialized(const char *name)
{
(void) name;
#if defined(MBEDTLS_THREADING_C)
mbedtls_threading_mutex_t mutex;
memset(&mutex, 0, sizeof(mutex));
/* This mutex usage error is detected by our test framework's mutex usage
* verification framework. See framework/tests/src/threading_helpers.c. Other
* threading implementations (e.g. pthread without our instrumentation)
* might consider this normal usage. */
TEST_ASSERT(mbedtls_mutex_unlock(&mutex) == 0);
exit:
;
#endif
}
/* Since TF-PSA-Crypto 1.0, mbedtls_mutex_free() on an all-bits-zero
* mutex is defined to be a no-op. In earlier library versions,
* it had undefined behavior. */
#if MBEDTLS_THREADING_INTERNAL_VERSION <= 0x04000000
static void mutex_free_not_initialized(const char *name)
{
(void) name;
#if defined(MBEDTLS_THREADING_C)
mbedtls_threading_mutex_t mutex;
memset(&mutex, 0, sizeof(mutex));
/* This mutex usage error is detected by our test framework's mutex usage
* verification framework. See framework/tests/src/threading_helpers.c. Other
* threading implementations (e.g. pthread without our instrumentation)
* might consider this normal usage. */
mbedtls_mutex_free(&mutex);
#endif
}
#endif
static void mutex_double_init(const char *name)
{
(void) name;
#if defined(MBEDTLS_THREADING_C)
mbedtls_threading_mutex_t mutex;
mbedtls_mutex_init(&mutex);
/* This mutex usage error is detected by our test framework's mutex usage
* verification framework. See framework/tests/src/threading_helpers.c. Other
* threading implementations (e.g. pthread without our instrumentation)
* might consider this normal usage. */
mbedtls_mutex_init(&mutex);
mbedtls_mutex_free(&mutex);
#endif
}
/* Since TF-PSA-Crypto 1.0, mbedtls_mutex_free() on an all-bits-zero
* mutex is defined to be a no-op. In earlier library versions,
* it had undefined behavior. */
#if MBEDTLS_THREADING_INTERNAL_VERSION <= 0x04000000
static void mutex_double_free(const char *name)
{
(void) name;
#if defined(MBEDTLS_THREADING_C)
mbedtls_threading_mutex_t mutex;
mbedtls_mutex_init(&mutex);
mbedtls_mutex_free(&mutex);
/* This mutex usage error is detected by our test framework's mutex usage
* verification framework. See framework/tests/src/threading_helpers.c. Other
* threading implementations (e.g. pthread without our instrumentation)
* might consider this normal usage. */
mbedtls_mutex_free(&mutex);
#endif
}
#endif
static void mutex_leak(const char *name)
{
(void) name;
#if defined(MBEDTLS_THREADING_C)
mbedtls_threading_mutex_t mutex;
mbedtls_mutex_init(&mutex);
#endif
/* This mutex usage error is detected by our test framework's mutex usage
* verification framework. See framework/tests/src/threading_helpers.c. Other
* threading implementations (e.g. pthread without our instrumentation)
* might consider this normal usage. */
}
/****************************************************************/
/* Command line entry point */
/****************************************************************/
typedef struct {
/** Command line argument that will trigger that metatest.
*
* Conventionally matches "[a-z0-9_]+". */
const char *name;
/** Platform under which that metatest is valid.
*
* - "any": should work anywhere.
* - "asan": triggers ASan (Address Sanitizer).
* - "msan": triggers MSan (Memory Sanitizer).
* - "pthread": requires MBEDTLS_THREADING_PTHREAD and MBEDTLS_TEST_HOOKS,
* which enables MBEDTLS_TEST_MUTEX_USAGE internally in the test
* framework (see framework/tests/src/threading_helpers.c).
*/
const char *platform;
/** Function that performs the metatest.
*
* The function receives the name as an argument. This allows using the
* same function to perform multiple variants of a test based on the name.
*
* When executed on a conforming platform, the function is expected to
* either cause a test failure (mbedtls_test_fail()), or cause the
* program to abort in some way (e.g. by causing a segfault or by
* triggering a sanitizer).
*
* When executed on a non-conforming platform, the function may return
* normally or may have unpredictable behavior.
*/
void (*entry_point)(const char *name);
} metatest_t;
/* The list of available meta-tests. Remember to register new functions here!
*
* Note that we always compile all the functions, so that `metatest --list`
* will always list all the available meta-tests.
*
* See the documentation of metatest_t::platform for the meaning of
* platform values.
*/
metatest_t metatests[] = {
{ "test_fail", "any", meta_test_fail },
{ "test_not_equal", "any", meta_test_not_equal },
{ "test_not_le_s", "any", meta_test_not_le_s },
{ "test_not_le_u", "any", meta_test_not_le_u },
{ "null_dereference", "any", null_pointer_dereference },
{ "null_call", "any", null_pointer_call },
{ "read_after_free", "asan", read_after_free },
{ "double_free", "asan", double_free },
{ "read_uninitialized_stack", "msan", read_uninitialized_stack },
{ "memory_leak", "asan", memory_leak },
{ "test_memory_poison_0_0_8_r", "poison", test_memory_poison },
{ "test_memory_poison_0_0_8_w", "poison", test_memory_poison },
{ "test_memory_poison_0_7_8_r", "poison", test_memory_poison },
{ "test_memory_poison_0_7_8_w", "poison", test_memory_poison },
{ "test_memory_poison_0_0_1_r", "poison", test_memory_poison },
{ "test_memory_poison_0_0_1_w", "poison", test_memory_poison },
{ "test_memory_poison_0_1_2_r", "poison", test_memory_poison },
{ "test_memory_poison_0_1_2_w", "poison", test_memory_poison },
{ "test_memory_poison_7_0_8_r", "poison", test_memory_poison },
{ "test_memory_poison_7_0_8_w", "poison", test_memory_poison },
{ "test_memory_poison_7_7_8_r", "poison", test_memory_poison },
{ "test_memory_poison_7_7_8_w", "poison", test_memory_poison },
{ "test_memory_poison_7_0_1_r", "poison", test_memory_poison },
{ "test_memory_poison_7_0_1_w", "poison", test_memory_poison },
{ "test_memory_poison_7_1_2_r", "poison", test_memory_poison },
{ "test_memory_poison_7_1_2_w", "poison", test_memory_poison },
{ "mutex_lock_not_initialized", "pthread", mutex_lock_not_initialized },
{ "mutex_unlock_not_initialized", "pthread", mutex_unlock_not_initialized },
#if MBEDTLS_THREADING_INTERNAL_VERSION <= 0x04000000
{ "mutex_free_not_initialized", "pthread", mutex_free_not_initialized },
#endif
{ "mutex_double_init", "pthread", mutex_double_init },
#if MBEDTLS_THREADING_INTERNAL_VERSION <= 0x04000000
{ "mutex_double_free", "pthread", mutex_double_free },
#endif
{ "mutex_leak", "pthread", mutex_leak },
{ NULL, NULL, NULL }
};
static void help(FILE *out, const char *argv0)
{
mbedtls_fprintf(out, "Usage: %s list|TEST\n", argv0);
mbedtls_fprintf(out, "Run a meta-test that should cause a test failure.\n");
mbedtls_fprintf(out, "With 'list', list the available tests and their platform requirement.\n");
}
int main(int argc, char *argv[])
{
const char *argv0 = argc > 0 ? argv[0] : "metatest";
if (argc != 2) {
help(stderr, argv0);
mbedtls_exit(MBEDTLS_EXIT_FAILURE);
}
/* Support "-help", "--help", "--list", etc. */
const char *command = argv[1];
while (*command == '-') {
++command;
}
if (strcmp(argv[1], "help") == 0) {
help(stdout, argv0);
mbedtls_exit(MBEDTLS_EXIT_SUCCESS);
}
if (strcmp(argv[1], "list") == 0) {
for (const metatest_t *p = metatests; p->name != NULL; p++) {
mbedtls_printf("%s %s\n", p->name, p->platform);
}
mbedtls_exit(MBEDTLS_EXIT_SUCCESS);
}
#if defined(MBEDTLS_TEST_MUTEX_USAGE)
mbedtls_test_mutex_usage_init();
#endif
for (const metatest_t *p = metatests; p->name != NULL; p++) {
if (strcmp(argv[1], p->name) == 0) {
mbedtls_printf("Running metatest %s...\n", argv[1]);
p->entry_point(argv[1]);
#if defined(MBEDTLS_TEST_MUTEX_USAGE)
mbedtls_test_mutex_usage_check();
#endif
int result = (int) mbedtls_test_get_result();
mbedtls_printf("Running metatest %s... done, result=%d\n",
argv[1], result);
mbedtls_exit(result == MBEDTLS_TEST_RESULT_SUCCESS ?
MBEDTLS_EXIT_SUCCESS :
MBEDTLS_EXIT_FAILURE);
}
}
mbedtls_fprintf(stderr, "%s: FATAL: No such metatest: %s\n",
argv0, command);
mbedtls_exit(MBEDTLS_EXIT_FAILURE);
}

View File

@@ -0,0 +1,66 @@
/*
* Query the Mbed TLS compile time configuration
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "mbedtls/build_info.h"
#include "mbedtls/platform.h"
#define USAGE \
"usage: %s [ -all | -any | -l ] <MBEDTLS_CONFIG> ...\n\n" \
"This program takes command line arguments which correspond to\n" \
"the string representation of Mbed TLS compile time configurations.\n\n" \
"If \"--all\" and \"--any\" are not used, then, if all given arguments\n" \
"are defined in the Mbed TLS build, 0 is returned; otherwise 1 is\n" \
"returned. Macro expansions of configurations will be printed (if any).\n" \
"-l\tPrint all available configuration.\n" \
"-all\tReturn 0 if all configurations are defined. Otherwise, return 1\n" \
"-any\tReturn 0 if any configuration is defined. Otherwise, return 1\n" \
"-h\tPrint this usage\n"
#include <string.h>
#include "query_config.h"
int main(int argc, char *argv[])
{
int i;
if (argc < 2 || strcmp(argv[1], "-h") == 0) {
mbedtls_printf(USAGE, argv[0]);
return MBEDTLS_EXIT_FAILURE;
}
if (strcmp(argv[1], "-l") == 0) {
list_config();
return 0;
}
if (strcmp(argv[1], "-all") == 0) {
for (i = 2; i < argc; i++) {
if (query_config(argv[i]) != 0) {
return 1;
}
}
return 0;
}
if (strcmp(argv[1], "-any") == 0) {
for (i = 2; i < argc; i++) {
if (query_config(argv[i]) == 0) {
return 0;
}
}
return 1;
}
for (i = 1; i < argc; i++) {
if (query_config(argv[i]) != 0) {
return 1;
}
}
return 0;
}

View File

@@ -0,0 +1,34 @@
/*
* Query Mbed TLS compile time configurations from mbedtls_config.h
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_PROGRAMS_TEST_QUERY_CONFIG_H
#define MBEDTLS_PROGRAMS_TEST_QUERY_CONFIG_H
#include "mbedtls/build_info.h"
/** Check whether a given configuration symbol is enabled.
*
* \param config The symbol to query (e.g. "MBEDTLS_RSA_C").
* \return \c 0 if the symbol was defined at compile time
* (in MBEDTLS_CONFIG_FILE or mbedtls_config.h),
* \c 1 otherwise.
*
* \note This function is defined in `programs/test/query_config.c`
* which is automatically generated by
* `scripts/generate_query_config.pl`.
*/
int query_config(const char *config);
/** List all enabled configuration symbols
*
* \note This function is defined in `programs/test/query_config.c`
* which is automatically generated by
* `scripts/generate_query_config.pl`.
*/
void list_config(void);
#endif /* MBEDTLS_PROGRAMS_TEST_QUERY_CONFIG_H */

View File

@@ -0,0 +1,29 @@
/* Ad hoc report on included headers. */
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <psa/crypto.h>
#include <mbedtls/platform.h>
int main(void)
{
/* Which PSA platform header? */
#if defined(PSA_CRYPTO_PLATFORM_H)
mbedtls_printf("PSA_CRYPTO_PLATFORM_H\n");
#endif
#if defined(PSA_CRYPTO_PLATFORM_ALT_H)
mbedtls_printf("PSA_CRYPTO_PLATFORM_ALT_H\n");
#endif
/* Which PSA struct header? */
#if defined(PSA_CRYPTO_STRUCT_H)
mbedtls_printf("PSA_CRYPTO_STRUCT_H\n");
#endif
#if defined(PSA_CRYPTO_STRUCT_ALT_H)
mbedtls_printf("PSA_CRYPTO_STRUCT_ALT_H\n");
#endif
}

View File

@@ -0,0 +1,71 @@
# test_zeroize.gdb
#
# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
#
# Purpose
#
# Run a test using the debugger to check that the mbedtls_platform_zeroize()
# function in platform_util.h is not being optimized out by the compiler. To do
# so, the script loads the test program at programs/test/zeroize and sets a
# breakpoint at the last return statement in main(). When the breakpoint is
# hit, the debugger manually checks the contents to be zeroized and checks that
# it is actually cleared.
#
# The mbedtls_platform_zeroize() test is debugger driven because there does not
# seem to be a mechanism to reliably check whether the zeroize calls are being
# eliminated by compiler optimizations from within the compiled program. The
# problem is that a compiler would typically remove what it considers to be
# "unnecessary" assignments as part of redundant code elimination. To identify
# such code, the compilar will create some form dependency graph between
# reads and writes to variables (among other situations). It will then use this
# data structure to remove redundant code that does not have an impact on the
# program's observable behavior. In the case of mbedtls_platform_zeroize(), an
# intelligent compiler could determine that this function clears a block of
# memory that is not accessed later in the program, so removing the call to
# mbedtls_platform_zeroize() does not have an observable behavior. However,
# inserting a test after a call to mbedtls_platform_zeroize() to check whether
# the block of memory was correctly zeroed would force the compiler to not
# eliminate the mbedtls_platform_zeroize() call. If this does not occur, then
# the compiler potentially has a bug.
#
# Note: This test requires that the test program is compiled with -g3.
set confirm off
# TF-PSA-Crypto uses a different name for the executable and also a build out
# of tree.
if $_isvoid($is_tf_psa_crypto)
file ./programs/test/zeroize
else
file ./programs/test/tf_psa_crypto_zeroize
end
set args ./framework/tests/programs/zeroize.c
search GDB_BREAK_HERE
break $_
run
set $i = 0
set $len = sizeof(buf)
set $buf = buf
while $i < $len
if $buf[$i++] != 0
echo The buffer at was not zeroized\n
quit 1
end
end
echo The buffer was correctly zeroized\n
continue
if $_exitcode != 0
echo The program did not terminate correctly\n
quit 1
end
quit 0

View File

@@ -0,0 +1,72 @@
/*
* Zeroize application for debugger-driven testing
*
* This is a simple test application used for debugger-driven testing to check
* whether calls to mbedtls_platform_zeroize() are being eliminated by compiler
* optimizations. This application is used by the GDB script at
* tests/programs/test_zeroize.gdb: the script sets a breakpoint at the last
* return statement in the main() function of this program. The debugger
* facilities are then used to manually inspect the memory and verify that the
* call to mbedtls_platform_zeroize() was not eliminated.
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "mbedtls/build_info.h"
#include <stdio.h>
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
#define BUFFER_LEN 1024
static void usage(void)
{
mbedtls_printf("Zeroize is a simple program to assist with testing\n");
mbedtls_printf("the mbedtls_platform_zeroize() function by using the\n");
mbedtls_printf("debugger. This program takes a file as input and\n");
mbedtls_printf("prints the first %d characters. Usage:\n\n", BUFFER_LEN);
mbedtls_printf(" zeroize <FILE>\n");
}
int main(int argc, char **argv)
{
int exit_code = MBEDTLS_EXIT_FAILURE;
FILE *fp;
char buf[BUFFER_LEN];
char *p = buf;
char *end = p + BUFFER_LEN;
int c;
if (argc != 2) {
mbedtls_printf("This program takes exactly 1 argument\n");
usage();
mbedtls_exit(exit_code);
}
fp = fopen(argv[1], "r");
if (fp == NULL) {
mbedtls_printf("Could not open file '%s'\n", argv[1]);
mbedtls_exit(exit_code);
}
while ((c = fgetc(fp)) != EOF && p < end - 1) {
*p++ = (char) c;
}
*p = '\0';
if (p - buf != 0) {
mbedtls_printf("%s\n", buf);
exit_code = MBEDTLS_EXIT_SUCCESS;
} else {
mbedtls_printf("The file is empty!\n");
}
fclose(fp);
mbedtls_platform_zeroize(buf, sizeof(buf));
mbedtls_exit(exit_code); // GDB_BREAK_HERE -- don't remove this comment!
}

View File

@@ -0,0 +1,65 @@
/** \file asn1_helpers.c
*
* \brief Helper functions for tests that manipulate ASN.1 data.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "test_common.h"
#include <test/helpers.h>
#include <test/macros.h>
#if defined(MBEDTLS_ASN1_PARSE_C)
#include <mbedtls/asn1.h>
#include <test/asn1_helpers.h>
int mbedtls_test_asn1_skip_integer(unsigned char **p, const unsigned char *end,
size_t min_bits, size_t max_bits,
int must_be_odd)
{
size_t len;
size_t actual_bits;
unsigned char msb;
TEST_EQUAL(mbedtls_asn1_get_tag(p, end, &len,
MBEDTLS_ASN1_INTEGER),
0);
/* Check if the retrieved length doesn't extend the actual buffer's size.
* It is assumed here, that end >= p, which validates casting to size_t. */
TEST_ASSERT(len <= (size_t) (end - *p));
/* Tolerate a slight departure from DER encoding:
* - 0 may be represented by an empty string or a 1-byte string.
* - The sign bit may be used as a value bit. */
if ((len == 1 && (*p)[0] == 0) ||
(len > 1 && (*p)[0] == 0 && ((*p)[1] & 0x80) != 0)) {
++(*p);
--len;
}
if (min_bits == 0 && len == 0) {
return 1;
}
msb = (*p)[0];
TEST_ASSERT(msb != 0);
actual_bits = 8 * (len - 1);
while (msb != 0) {
msb >>= 1;
++actual_bits;
}
TEST_ASSERT(actual_bits >= min_bits);
TEST_ASSERT(actual_bits <= max_bits);
if (must_be_odd) {
TEST_ASSERT(((*p)[len-1] & 1) != 0);
}
*p += len;
return 1;
exit:
return 0;
}
#endif /* MBEDTLS_ASN1_PARSE_C */

View File

@@ -0,0 +1,39 @@
/** Support for path tracking in optionally safe bignum functions
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "test_common.h"
#include "test/bignum_codepath_check.h"
#include "bignum_core_invasive.h"
#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
int mbedtls_codepath_check = MBEDTLS_MPI_IS_TEST;
static void mbedtls_codepath_take_safe(void)
{
if (mbedtls_codepath_check == MBEDTLS_MPI_IS_TEST) {
mbedtls_codepath_check = MBEDTLS_MPI_IS_SECRET;
}
}
static void mbedtls_codepath_take_unsafe(void)
{
mbedtls_codepath_check = MBEDTLS_MPI_IS_PUBLIC;
}
void mbedtls_codepath_test_hooks_setup(void)
{
mbedtls_safe_codepath_hook = mbedtls_codepath_take_safe;
mbedtls_unsafe_codepath_hook = mbedtls_codepath_take_unsafe;
}
void mbedtls_codepath_test_hooks_teardown(void)
{
mbedtls_safe_codepath_hook = NULL;
mbedtls_unsafe_codepath_hook = NULL;
}
#endif /* MBEDTLS_TEST_HOOKS && !MBEDTLS_THREADING_C */

View File

@@ -0,0 +1,152 @@
/**
* \file bignum_helpers.c
*
* \brief This file contains the prototypes of helper functions for
* bignum-related testing.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "test_common.h"
#include <test/bignum_helpers.h>
#if defined(MBEDTLS_BIGNUM_C)
#include <stdlib.h>
#include <string.h>
#if !defined(MBEDTLS_VERSION_MAJOR) || MBEDTLS_VERSION_MAJOR >= 4
#include <mbedtls/private/bignum.h>
#else
#include <mbedtls/bignum.h>
#endif
#include <bignum_core.h>
#include <bignum_mod.h>
#include <bignum_mod_raw.h>
#include <test/helpers.h>
#include <test/macros.h>
int mbedtls_test_read_mpi_core(mbedtls_mpi_uint **pX, size_t *plimbs,
const char *input)
{
/* Sanity check */
if (*pX != NULL) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
size_t hex_len = strlen(input);
size_t byte_len = (hex_len + 1) / 2;
*plimbs = CHARS_TO_LIMBS(byte_len);
/* A core bignum is not allowed to be empty. Forbid it as test data,
* this way static analyzers have a chance of knowing we don't expect
* the bignum functions to support empty inputs. */
if (*plimbs == 0) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
*pX = mbedtls_calloc(*plimbs, sizeof(**pX));
if (*pX == NULL) {
return MBEDTLS_ERR_MPI_ALLOC_FAILED;
}
unsigned char *byte_start = (unsigned char *) *pX;
if (byte_len % sizeof(mbedtls_mpi_uint) != 0) {
byte_start += sizeof(mbedtls_mpi_uint) - byte_len % sizeof(mbedtls_mpi_uint);
}
if ((hex_len & 1) != 0) {
/* mbedtls_test_unhexify wants an even number of hex digits */
TEST_ASSERT(mbedtls_test_ascii2uc(*input, byte_start) == 0);
++byte_start;
++input;
--byte_len;
}
TEST_ASSERT(mbedtls_test_unhexify(byte_start,
byte_len,
input,
&byte_len) == 0);
mbedtls_mpi_core_bigendian_to_host(*pX, *plimbs);
return 0;
exit:
mbedtls_free(*pX);
*pX = NULL;
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
#if defined(MBEDTLS_ECP_WITH_MPI_UINT)
int mbedtls_test_read_mpi_modulus(mbedtls_mpi_mod_modulus *N,
const char *s,
mbedtls_mpi_mod_rep_selector int_rep)
{
mbedtls_mpi_uint *p = NULL;
size_t limbs = 0;
if (N->limbs != 0) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
int ret = mbedtls_test_read_mpi_core(&p, &limbs, s);
if (ret != 0) {
return ret;
}
switch (int_rep) {
case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
ret = mbedtls_mpi_mod_modulus_setup(N, p, limbs);
break;
case MBEDTLS_MPI_MOD_REP_OPT_RED:
ret = mbedtls_mpi_mod_optred_modulus_setup(N, p, limbs, NULL);
break;
default:
ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
break;
}
if (ret != 0) {
mbedtls_free(p);
}
return ret;
}
void mbedtls_test_mpi_mod_modulus_free_with_limbs(mbedtls_mpi_mod_modulus *N)
{
mbedtls_free((mbedtls_mpi_uint *) N->p);
mbedtls_mpi_mod_modulus_free(N);
}
#endif /* MBEDTLS_ECP_WITH_MPI_UINT */
int mbedtls_test_read_mpi(mbedtls_mpi *X, const char *s)
{
int negative = 0;
/* Always set the sign bit to -1 if the input has a minus sign, even for 0.
* This creates an invalid representation, which mbedtls_mpi_read_string()
* avoids but we want to be able to create that in test data. */
if (s[0] == '-') {
++s;
negative = 1;
}
/* mbedtls_mpi_read_string() currently retains leading zeros.
* It always allocates at least one limb for the value 0. */
if (s[0] == 0) {
mbedtls_mpi_free(X);
return 0;
}
int ret = mbedtls_mpi_read_string(X, 16, s);
if (ret != 0) {
return ret;
}
if (negative) {
if (mbedtls_mpi_cmp_int(X, 0) == 0) {
mbedtls_test_increment_case_uses_negative_0();
}
X->s = -1;
}
return 0;
}
#endif /* MBEDTLS_BIGNUM_C */

View File

@@ -0,0 +1,199 @@
/*
* Test driver for hash entry points.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <test/helpers.h>
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "psa_crypto_hash.h"
#include "test/drivers/hash.h"
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_hash.h)
#endif
mbedtls_test_driver_hash_hooks_t
mbedtls_test_driver_hash_hooks = MBEDTLS_TEST_DRIVER_HASH_INIT;
psa_status_t mbedtls_test_transparent_hash_compute(
psa_algorithm_t alg,
const uint8_t *input, size_t input_length,
uint8_t *hash, size_t hash_size, size_t *hash_length)
{
mbedtls_test_driver_hash_hooks.hits++;
if (mbedtls_test_driver_hash_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_hash_hooks.driver_status =
mbedtls_test_driver_hash_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
mbedtls_test_driver_hash_hooks.driver_status =
libtestdriver1_mbedtls_psa_hash_compute(
alg, input, input_length,
hash, hash_size, hash_length);
#elif defined(MBEDTLS_PSA_BUILTIN_HASH)
mbedtls_test_driver_hash_hooks.driver_status =
mbedtls_psa_hash_compute(
alg, input, input_length,
hash, hash_size, hash_length);
#else
(void) alg;
(void) input;
(void) input_length;
(void) hash;
(void) hash_size;
(void) hash_length;
mbedtls_test_driver_hash_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_hash_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_hash_setup(
mbedtls_transparent_test_driver_hash_operation_t *operation,
psa_algorithm_t alg)
{
mbedtls_test_driver_hash_hooks.hits++;
if (mbedtls_test_driver_hash_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_hash_hooks.driver_status =
mbedtls_test_driver_hash_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
mbedtls_test_driver_hash_hooks.driver_status =
libtestdriver1_mbedtls_psa_hash_setup(operation, alg);
#elif defined(MBEDTLS_PSA_BUILTIN_HASH)
mbedtls_test_driver_hash_hooks.driver_status =
mbedtls_psa_hash_setup(operation, alg);
#else
(void) operation;
(void) alg;
mbedtls_test_driver_hash_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_hash_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_hash_clone(
const mbedtls_transparent_test_driver_hash_operation_t *source_operation,
mbedtls_transparent_test_driver_hash_operation_t *target_operation)
{
mbedtls_test_driver_hash_hooks.hits++;
if (mbedtls_test_driver_hash_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_hash_hooks.driver_status =
mbedtls_test_driver_hash_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
mbedtls_test_driver_hash_hooks.driver_status =
libtestdriver1_mbedtls_psa_hash_clone(source_operation,
target_operation);
#elif defined(MBEDTLS_PSA_BUILTIN_HASH)
mbedtls_test_driver_hash_hooks.driver_status =
mbedtls_psa_hash_clone(source_operation, target_operation);
#else
(void) source_operation;
(void) target_operation;
mbedtls_test_driver_hash_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_hash_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_hash_update(
mbedtls_transparent_test_driver_hash_operation_t *operation,
const uint8_t *input,
size_t input_length)
{
mbedtls_test_driver_hash_hooks.hits++;
if (mbedtls_test_driver_hash_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_hash_hooks.driver_status =
mbedtls_test_driver_hash_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
mbedtls_test_driver_hash_hooks.driver_status =
libtestdriver1_mbedtls_psa_hash_update(
operation, input, input_length);
#elif defined(MBEDTLS_PSA_BUILTIN_HASH)
mbedtls_test_driver_hash_hooks.driver_status =
mbedtls_psa_hash_update(operation, input, input_length);
#else
(void) operation;
(void) input;
(void) input_length;
mbedtls_test_driver_hash_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_hash_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_hash_finish(
mbedtls_transparent_test_driver_hash_operation_t *operation,
uint8_t *hash,
size_t hash_size,
size_t *hash_length)
{
mbedtls_test_driver_hash_hooks.hits++;
if (mbedtls_test_driver_hash_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_hash_hooks.driver_status =
mbedtls_test_driver_hash_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
mbedtls_test_driver_hash_hooks.driver_status =
libtestdriver1_mbedtls_psa_hash_finish(
operation, hash, hash_size, hash_length);
#elif defined(MBEDTLS_PSA_BUILTIN_HASH)
mbedtls_test_driver_hash_hooks.driver_status =
mbedtls_psa_hash_finish(operation, hash, hash_size, hash_length);
#else
(void) operation;
(void) hash;
(void) hash_size;
(void) hash_length;
mbedtls_test_driver_hash_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_hash_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_hash_abort(
mbedtls_transparent_test_driver_hash_operation_t *operation)
{
mbedtls_test_driver_hash_hooks.hits++;
if (mbedtls_test_driver_hash_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_hash_hooks.driver_status =
mbedtls_test_driver_hash_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
mbedtls_test_driver_hash_hooks.driver_status =
libtestdriver1_mbedtls_psa_hash_abort(operation);
#elif defined(MBEDTLS_PSA_BUILTIN_HASH)
mbedtls_test_driver_hash_hooks.driver_status =
mbedtls_psa_hash_abort(operation);
#else
(void) operation;
mbedtls_test_driver_hash_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_hash_hooks.driver_status;
}
#endif /* PSA_CRYPTO_DRIVER_TEST */

View File

@@ -0,0 +1,82 @@
/** \file platform_builtin_keys.c
*
* \brief Test driver implementation of the builtin key support
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <test/helpers.h>
#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
#include <psa/crypto.h>
#include <psa/crypto_extra.h>
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include <test/drivers/test_driver.h>
#endif
typedef struct {
psa_key_id_t builtin_key_id;
psa_key_lifetime_t lifetime;
psa_drv_slot_number_t slot_number;
} mbedtls_psa_builtin_key_description_t;
static const mbedtls_psa_builtin_key_description_t builtin_keys[] = {
#if defined(PSA_CRYPTO_DRIVER_TEST)
/* For testing, assign the AES builtin key slot to the boundary values.
* ECDSA can be exercised on key ID MBEDTLS_PSA_KEY_ID_BUILTIN_MIN + 1. */
{ MBEDTLS_PSA_KEY_ID_BUILTIN_MIN - 1,
PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
PSA_KEY_PERSISTENCE_READ_ONLY, PSA_CRYPTO_TEST_DRIVER_LOCATION),
PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT },
{ MBEDTLS_PSA_KEY_ID_BUILTIN_MIN,
PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
PSA_KEY_PERSISTENCE_READ_ONLY, PSA_CRYPTO_TEST_DRIVER_LOCATION),
PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT },
{ MBEDTLS_PSA_KEY_ID_BUILTIN_MIN + 1,
PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
PSA_KEY_PERSISTENCE_READ_ONLY, PSA_CRYPTO_TEST_DRIVER_LOCATION),
PSA_CRYPTO_TEST_DRIVER_BUILTIN_ECDSA_KEY_SLOT },
{ MBEDTLS_PSA_KEY_ID_BUILTIN_MAX - 1,
PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
PSA_KEY_PERSISTENCE_READ_ONLY, PSA_CRYPTO_TEST_DRIVER_LOCATION),
PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT },
{ MBEDTLS_PSA_KEY_ID_BUILTIN_MAX,
PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
PSA_KEY_PERSISTENCE_READ_ONLY, PSA_CRYPTO_TEST_DRIVER_LOCATION),
PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT },
{ MBEDTLS_PSA_KEY_ID_BUILTIN_MAX + 1,
PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
PSA_KEY_PERSISTENCE_READ_ONLY, PSA_CRYPTO_TEST_DRIVER_LOCATION),
PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT },
#else
{ 0, 0, 0 }
#endif
};
psa_status_t mbedtls_psa_platform_get_builtin_key(
mbedtls_svc_key_id_t key_id,
psa_key_lifetime_t *lifetime,
psa_drv_slot_number_t *slot_number)
{
psa_key_id_t app_key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key_id);
const mbedtls_psa_builtin_key_description_t *builtin_key;
for (size_t i = 0;
i < (sizeof(builtin_keys) / sizeof(builtin_keys[0])); i++) {
builtin_key = &builtin_keys[i];
if (builtin_key->builtin_key_id == app_key_id) {
*lifetime = builtin_key->lifetime;
*slot_number = builtin_key->slot_number;
return PSA_SUCCESS;
}
}
return PSA_ERROR_DOES_NOT_EXIST;
}
#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */

View File

@@ -0,0 +1,468 @@
/*
* Test driver for AEAD entry points.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <test/helpers.h>
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "psa_crypto_aead.h"
#include "psa_crypto_core.h"
#include "test/drivers/aead.h"
#include "mbedtls/constant_time.h"
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_aead.h)
#endif
mbedtls_test_driver_aead_hooks_t
mbedtls_test_driver_aead_hooks = MBEDTLS_TEST_DRIVER_AEAD_INIT;
psa_status_t mbedtls_test_transparent_aead_encrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *nonce, size_t nonce_length,
const uint8_t *additional_data, size_t additional_data_length,
const uint8_t *plaintext, size_t plaintext_length,
uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length)
{
mbedtls_test_driver_aead_hooks.hits_encrypt++;
if (mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_test_driver_aead_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
libtestdriver1_mbedtls_psa_aead_encrypt(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size,
alg,
nonce, nonce_length,
additional_data, additional_data_length,
plaintext, plaintext_length,
ciphertext, ciphertext_size, ciphertext_length);
#elif defined(MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_psa_aead_encrypt(
attributes, key_buffer, key_buffer_size,
alg,
nonce, nonce_length,
additional_data, additional_data_length,
plaintext, plaintext_length,
ciphertext, ciphertext_size, ciphertext_length);
#else
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
(void) alg;
(void) nonce;
(void) nonce_length;
(void) additional_data;
(void) additional_data_length;
(void) plaintext;
(void) plaintext_length;
(void) ciphertext;
(void) ciphertext_size;
(void) ciphertext_length;
mbedtls_test_driver_aead_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_aead_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_aead_decrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *nonce, size_t nonce_length,
const uint8_t *additional_data, size_t additional_data_length,
const uint8_t *ciphertext, size_t ciphertext_length,
uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length)
{
mbedtls_test_driver_aead_hooks.hits_decrypt++;
if (mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_test_driver_aead_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
libtestdriver1_mbedtls_psa_aead_decrypt(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size,
alg,
nonce, nonce_length,
additional_data, additional_data_length,
ciphertext, ciphertext_length,
plaintext, plaintext_size, plaintext_length);
#elif defined(MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_psa_aead_decrypt(
attributes, key_buffer, key_buffer_size,
alg,
nonce, nonce_length,
additional_data, additional_data_length,
ciphertext, ciphertext_length,
plaintext, plaintext_size, plaintext_length);
#else
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
(void) alg;
(void) nonce;
(void) nonce_length;
(void) additional_data;
(void) additional_data_length;
(void) ciphertext;
(void) ciphertext_length;
(void) plaintext;
(void) plaintext_size;
(void) plaintext_length;
mbedtls_test_driver_aead_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_aead_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_aead_encrypt_setup(
mbedtls_transparent_test_driver_aead_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg)
{
mbedtls_test_driver_aead_hooks.hits_encrypt_setup++;
if (mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_test_driver_aead_hooks.forced_status;
} else if (!MBEDTLS_TEST_OBJECT_IS_ALL_ZERO(operation)) {
mbedtls_test_driver_aead_hooks.driver_status =
PSA_ERROR_TEST_DETECTED_BAD_INITIALIZATION;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
libtestdriver1_mbedtls_psa_aead_encrypt_setup(operation,
(const libtestdriver1_psa_key_attributes_t
*) attributes,
key_buffer,
key_buffer_size, alg);
#elif defined(MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_psa_aead_encrypt_setup(operation, attributes, key_buffer,
key_buffer_size, alg);
#else
(void) operation;
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
(void) alg;
mbedtls_test_driver_aead_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_aead_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_aead_decrypt_setup(
mbedtls_transparent_test_driver_aead_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg)
{
mbedtls_test_driver_aead_hooks.hits_decrypt_setup++;
if (mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_test_driver_aead_hooks.forced_status;
} else if (!MBEDTLS_TEST_OBJECT_IS_ALL_ZERO(operation)) {
mbedtls_test_driver_aead_hooks.driver_status =
PSA_ERROR_TEST_DETECTED_BAD_INITIALIZATION;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
libtestdriver1_mbedtls_psa_aead_decrypt_setup(operation,
(const libtestdriver1_psa_key_attributes_t
*) attributes,
key_buffer, key_buffer_size, alg);
#elif defined(MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_psa_aead_decrypt_setup(operation, attributes, key_buffer,
key_buffer_size, alg);
#else
(void) operation;
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
(void) alg;
mbedtls_test_driver_aead_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_aead_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_aead_set_nonce(
mbedtls_transparent_test_driver_aead_operation_t *operation,
const uint8_t *nonce,
size_t nonce_length)
{
mbedtls_test_driver_aead_hooks.hits_set_nonce++;
if (mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_test_driver_aead_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
libtestdriver1_mbedtls_psa_aead_set_nonce(operation, nonce, nonce_length);
#elif defined(MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_psa_aead_set_nonce(operation, nonce, nonce_length);
#else
(void) operation;
(void) nonce;
(void) nonce_length;
mbedtls_test_driver_aead_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_aead_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_aead_set_lengths(
mbedtls_transparent_test_driver_aead_operation_t *operation,
size_t ad_length,
size_t plaintext_length)
{
mbedtls_test_driver_aead_hooks.hits_set_lengths++;
if (mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_test_driver_aead_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
libtestdriver1_mbedtls_psa_aead_set_lengths(operation, ad_length,
plaintext_length);
#elif defined(MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_psa_aead_set_lengths(operation, ad_length,
plaintext_length);
#else
(void) operation;
(void) ad_length;
(void) plaintext_length;
mbedtls_test_driver_aead_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_aead_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_aead_update_ad(
mbedtls_transparent_test_driver_aead_operation_t *operation,
const uint8_t *input,
size_t input_length)
{
mbedtls_test_driver_aead_hooks.hits_update_ad++;
if (mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_test_driver_aead_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
libtestdriver1_mbedtls_psa_aead_update_ad(operation, input, input_length);
#elif defined(MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_psa_aead_update_ad(operation, input, input_length);
#else
(void) operation;
(void) input;
(void) input_length;
mbedtls_test_driver_aead_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_aead_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_aead_update(
mbedtls_transparent_test_driver_aead_operation_t *operation,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
mbedtls_test_driver_aead_hooks.hits_update++;
if (mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_test_driver_aead_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
libtestdriver1_mbedtls_psa_aead_update(operation, input,
input_length, output,
output_size, output_length);
#elif defined(MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_psa_aead_update(operation, input, input_length, output,
output_size, output_length);
#else
(void) operation;
(void) input;
(void) input_length;
(void) output;
(void) output_size;
(void) output_length;
mbedtls_test_driver_aead_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_aead_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_aead_finish(
mbedtls_transparent_test_driver_aead_operation_t *operation,
uint8_t *ciphertext,
size_t ciphertext_size,
size_t *ciphertext_length,
uint8_t *tag,
size_t tag_size,
size_t *tag_length)
{
mbedtls_test_driver_aead_hooks.hits_finish++;
if (mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_test_driver_aead_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
libtestdriver1_mbedtls_psa_aead_finish(operation, ciphertext,
ciphertext_size, ciphertext_length,
tag, tag_size, tag_length);
#elif defined(MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_psa_aead_finish(operation, ciphertext, ciphertext_size,
ciphertext_length, tag, tag_size,
tag_length);
#else
(void) operation;
(void) ciphertext;
(void) ciphertext_size;
(void) ciphertext_length;
(void) tag;
(void) tag_size;
(void) tag_length;
mbedtls_test_driver_aead_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_aead_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_aead_verify(
mbedtls_transparent_test_driver_aead_operation_t *operation,
uint8_t *plaintext,
size_t plaintext_size,
size_t *plaintext_length,
const uint8_t *tag,
size_t tag_length)
{
mbedtls_test_driver_aead_hooks.hits_verify++;
if (mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_test_driver_aead_hooks.forced_status;
} else {
uint8_t check_tag[PSA_AEAD_TAG_MAX_SIZE];
size_t check_tag_length = 0;
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
libtestdriver1_mbedtls_psa_aead_finish(operation,
plaintext,
plaintext_size,
plaintext_length,
check_tag,
sizeof(check_tag),
&check_tag_length);
#elif defined(MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_psa_aead_finish(operation,
plaintext,
plaintext_size,
plaintext_length,
check_tag,
sizeof(check_tag),
&check_tag_length);
#else
(void) operation;
(void) plaintext;
(void) plaintext_size;
(void) plaintext_length;
mbedtls_test_driver_aead_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
if (mbedtls_test_driver_aead_hooks.driver_status == PSA_SUCCESS) {
if (tag_length != check_tag_length ||
mbedtls_ct_memcmp(tag, check_tag, tag_length)
!= 0) {
mbedtls_test_driver_aead_hooks.driver_status =
PSA_ERROR_INVALID_SIGNATURE;
}
}
mbedtls_platform_zeroize(check_tag, sizeof(check_tag));
}
return mbedtls_test_driver_aead_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_aead_abort(
mbedtls_transparent_test_driver_aead_operation_t *operation)
{
mbedtls_test_driver_aead_hooks.hits_abort++;
if (mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_test_driver_aead_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
libtestdriver1_mbedtls_psa_aead_abort(operation);
#elif defined(MBEDTLS_PSA_BUILTIN_AEAD)
mbedtls_test_driver_aead_hooks.driver_status =
mbedtls_psa_aead_abort(operation);
#else
(void) operation;
mbedtls_test_driver_aead_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_aead_hooks.driver_status;
}
#endif /* PSA_CRYPTO_DRIVER_TEST */

View File

@@ -0,0 +1,187 @@
/*
* Test driver for asymmetric encryption.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <test/helpers.h>
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "psa/crypto.h"
#if !defined(MBEDTLS_VERSION_MAJOR) || MBEDTLS_VERSION_MAJOR >= 4
#include "mbedtls/private/rsa.h"
#else
#include "mbedtls/rsa.h"
#endif
#include "psa_crypto_rsa.h"
#include "string.h"
#include "test/drivers/asymmetric_encryption.h"
#include "test/drivers/key_management.h"
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_rsa.h)
#endif
#define PSA_RSA_KEY_PAIR_MAX_SIZE \
PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)
mbedtls_test_driver_asymmetric_encryption_hooks_t mbedtls_test_driver_asymmetric_encryption_hooks =
MBEDTLS_TEST_DRIVER_ASYMMETRIC_ENCRYPTION_INIT;
psa_status_t mbedtls_test_transparent_asymmetric_encrypt(
const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input,
size_t input_length, const uint8_t *salt, size_t salt_length,
uint8_t *output, size_t output_size, size_t *output_length)
{
mbedtls_test_driver_asymmetric_encryption_hooks.hits++;
if (mbedtls_test_driver_asymmetric_encryption_hooks.forced_output != NULL) {
if (output_size < mbedtls_test_driver_asymmetric_encryption_hooks.forced_output_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(output,
mbedtls_test_driver_asymmetric_encryption_hooks.forced_output,
mbedtls_test_driver_asymmetric_encryption_hooks.forced_output_length);
*output_length = mbedtls_test_driver_asymmetric_encryption_hooks.forced_output_length;
return mbedtls_test_driver_asymmetric_encryption_hooks.forced_status;
}
if (mbedtls_test_driver_asymmetric_encryption_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_asymmetric_encryption_hooks.forced_status;
}
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
return libtestdriver1_mbedtls_psa_asymmetric_encrypt(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size,
alg, input, input_length, salt, salt_length,
output, output_size, output_length);
#else
return mbedtls_psa_asymmetric_encrypt(
attributes, key_buffer, key_buffer_size,
alg, input, input_length, salt, salt_length,
output, output_size, output_length);
#endif
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_transparent_asymmetric_decrypt(
const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input,
size_t input_length, const uint8_t *salt, size_t salt_length,
uint8_t *output, size_t output_size, size_t *output_length)
{
mbedtls_test_driver_asymmetric_encryption_hooks.hits++;
if (mbedtls_test_driver_asymmetric_encryption_hooks.forced_output != NULL) {
if (output_size < mbedtls_test_driver_asymmetric_encryption_hooks.forced_output_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(output,
mbedtls_test_driver_asymmetric_encryption_hooks.forced_output,
mbedtls_test_driver_asymmetric_encryption_hooks.forced_output_length);
*output_length = mbedtls_test_driver_asymmetric_encryption_hooks.forced_output_length;
return mbedtls_test_driver_asymmetric_encryption_hooks.forced_status;
}
if (mbedtls_test_driver_asymmetric_encryption_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_asymmetric_encryption_hooks.forced_status;
}
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
return libtestdriver1_mbedtls_psa_asymmetric_decrypt(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size,
alg, input, input_length, salt, salt_length,
output, output_size, output_length);
#else
return mbedtls_psa_asymmetric_decrypt(
attributes, key_buffer, key_buffer_size,
alg, input, input_length, salt, salt_length,
output, output_size, output_length);
#endif
return PSA_ERROR_NOT_SUPPORTED;
}
/*
* opaque versions
*/
psa_status_t mbedtls_test_opaque_asymmetric_encrypt(
const psa_key_attributes_t *attributes, const uint8_t *key,
size_t key_length, psa_algorithm_t alg, const uint8_t *input,
size_t input_length, const uint8_t *salt, size_t salt_length,
uint8_t *output, size_t output_size, size_t *output_length)
{
unsigned char unwrapped_key[PSA_RSA_KEY_PAIR_MAX_SIZE];
size_t unwrapped_key_length;
psa_status_t status;
status = mbedtls_test_opaque_unwrap_key(key, key_length,
unwrapped_key, sizeof(unwrapped_key),
&unwrapped_key_length);
if (status != PSA_SUCCESS) {
return status;
}
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
(defined(MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP) || defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT))
return libtestdriver1_mbedtls_psa_asymmetric_encrypt(
(const libtestdriver1_psa_key_attributes_t *) attributes,
unwrapped_key, unwrapped_key_length,
alg, input, input_length, salt, salt_length,
output, output_size, output_length);
#else
return mbedtls_psa_asymmetric_encrypt(
attributes, unwrapped_key, unwrapped_key_length,
alg, input, input_length, salt, salt_length,
output, output_size, output_length);
#endif
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_opaque_asymmetric_decrypt(
const psa_key_attributes_t *attributes, const uint8_t *key,
size_t key_length, psa_algorithm_t alg, const uint8_t *input,
size_t input_length, const uint8_t *salt, size_t salt_length,
uint8_t *output, size_t output_size, size_t *output_length)
{
unsigned char unwrapped_key[PSA_RSA_KEY_PAIR_MAX_SIZE];
size_t unwrapped_key_length;
psa_status_t status;
status = mbedtls_test_opaque_unwrap_key(key, key_length,
unwrapped_key, sizeof(unwrapped_key),
&unwrapped_key_length);
if (status != PSA_SUCCESS) {
return status;
}
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
(defined(MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP) || defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT))
return libtestdriver1_mbedtls_psa_asymmetric_decrypt(
(const libtestdriver1_psa_key_attributes_t *) attributes,
unwrapped_key, unwrapped_key_length,
alg, input, input_length, salt, salt_length,
output, output_size, output_length);
#else
return mbedtls_psa_asymmetric_decrypt(
attributes, unwrapped_key, unwrapped_key_length,
alg, input, input_length, salt, salt_length,
output, output_size, output_length);
#endif
return PSA_ERROR_NOT_SUPPORTED;
}
#endif /* PSA_CRYPTO_DRIVER_TEST */

View File

@@ -0,0 +1,439 @@
/*
* Test driver for cipher functions.
* Currently only supports multi-part operations using AES-CTR.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <test/helpers.h>
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "psa/crypto.h"
#include "psa_crypto_cipher.h"
#include "psa_crypto_core.h"
#if !defined(MBEDTLS_VERSION_MAJOR) || MBEDTLS_VERSION_MAJOR >= 4
#include "mbedtls/private/cipher.h"
#else
#include "mbedtls/cipher.h"
#endif
#include "test/drivers/cipher.h"
#include "test/random.h"
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_cipher.h)
#endif
#include <string.h>
mbedtls_test_driver_cipher_hooks_t mbedtls_test_driver_cipher_hooks =
MBEDTLS_TEST_DRIVER_CIPHER_INIT;
psa_status_t mbedtls_test_transparent_cipher_encrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *iv,
size_t iv_length,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
mbedtls_test_driver_cipher_hooks.hits++;
mbedtls_test_driver_cipher_hooks.hits_encrypt++;
if (mbedtls_test_driver_cipher_hooks.forced_output != NULL) {
if (output_size < mbedtls_test_driver_cipher_hooks.forced_output_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(output,
mbedtls_test_driver_cipher_hooks.forced_output,
mbedtls_test_driver_cipher_hooks.forced_output_length);
*output_length = mbedtls_test_driver_cipher_hooks.forced_output_length;
return mbedtls_test_driver_cipher_hooks.forced_status;
}
if (mbedtls_test_driver_cipher_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_cipher_hooks.forced_status;
}
if (mbedtls_test_driver_cipher_hooks.forced_status_encrypt != PSA_SUCCESS) {
return mbedtls_test_driver_cipher_hooks.forced_status_encrypt;
}
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
return libtestdriver1_mbedtls_psa_cipher_encrypt(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size,
alg, iv, iv_length, input, input_length,
output, output_size, output_length);
#elif defined(MBEDTLS_PSA_BUILTIN_CIPHER)
return mbedtls_psa_cipher_encrypt(
attributes, key_buffer, key_buffer_size,
alg, iv, iv_length, input, input_length,
output, output_size, output_length);
#endif
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_transparent_cipher_decrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
mbedtls_test_driver_cipher_hooks.hits++;
if (mbedtls_test_driver_cipher_hooks.forced_output != NULL) {
if (output_size < mbedtls_test_driver_cipher_hooks.forced_output_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(output,
mbedtls_test_driver_cipher_hooks.forced_output,
mbedtls_test_driver_cipher_hooks.forced_output_length);
*output_length = mbedtls_test_driver_cipher_hooks.forced_output_length;
return mbedtls_test_driver_cipher_hooks.forced_status;
}
if (mbedtls_test_driver_cipher_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_cipher_hooks.forced_status;
}
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
return libtestdriver1_mbedtls_psa_cipher_decrypt(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size,
alg, input, input_length,
output, output_size, output_length);
#elif defined(MBEDTLS_PSA_BUILTIN_CIPHER)
return mbedtls_psa_cipher_decrypt(
attributes, key_buffer, key_buffer_size,
alg, input, input_length,
output, output_size, output_length);
#endif
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_transparent_cipher_encrypt_setup(
mbedtls_transparent_test_driver_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg)
{
mbedtls_test_driver_cipher_hooks.hits++;
if (mbedtls_test_driver_cipher_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_cipher_hooks.forced_status;
}
if (!MBEDTLS_TEST_OBJECT_IS_ALL_ZERO(operation)) {
return PSA_ERROR_TEST_DETECTED_BAD_INITIALIZATION;
}
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
return libtestdriver1_mbedtls_psa_cipher_encrypt_setup(
operation,
(const libtestdriver1_psa_key_attributes_t *) attributes,
key, key_length, alg);
#elif defined(MBEDTLS_PSA_BUILTIN_CIPHER)
return mbedtls_psa_cipher_encrypt_setup(
operation, attributes, key, key_length, alg);
#endif
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_transparent_cipher_decrypt_setup(
mbedtls_transparent_test_driver_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg)
{
mbedtls_test_driver_cipher_hooks.hits++;
if (mbedtls_test_driver_cipher_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_cipher_hooks.forced_status;
}
if (!MBEDTLS_TEST_OBJECT_IS_ALL_ZERO(operation)) {
return PSA_ERROR_TEST_DETECTED_BAD_INITIALIZATION;
}
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
return libtestdriver1_mbedtls_psa_cipher_decrypt_setup(
operation,
(const libtestdriver1_psa_key_attributes_t *) attributes,
key, key_length, alg);
#elif defined(MBEDTLS_PSA_BUILTIN_CIPHER)
return mbedtls_psa_cipher_decrypt_setup(
operation, attributes, key, key_length, alg);
#endif
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_transparent_cipher_abort(
mbedtls_transparent_test_driver_cipher_operation_t *operation)
{
mbedtls_test_driver_cipher_hooks.hits++;
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
libtestdriver1_mbedtls_psa_cipher_abort(operation);
#elif defined(MBEDTLS_PSA_BUILTIN_CIPHER)
mbedtls_psa_cipher_abort(operation);
#endif
/* Wiping the entire struct here, instead of member-by-member. This is
* useful for the test suite, since it gives a chance of catching memory
* corruption errors should the core not have allocated (enough) memory for
* our context struct. */
memset(operation, 0, sizeof(*operation));
return mbedtls_test_driver_cipher_hooks.forced_status;
}
psa_status_t mbedtls_test_transparent_cipher_set_iv(
mbedtls_transparent_test_driver_cipher_operation_t *operation,
const uint8_t *iv,
size_t iv_length)
{
mbedtls_test_driver_cipher_hooks.hits++;
mbedtls_test_driver_cipher_hooks.hits_set_iv++;
if (mbedtls_test_driver_cipher_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_cipher_hooks.forced_status;
}
if (mbedtls_test_driver_cipher_hooks.forced_status_set_iv != PSA_SUCCESS) {
return mbedtls_test_driver_cipher_hooks.forced_status_set_iv;
}
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
return libtestdriver1_mbedtls_psa_cipher_set_iv(
operation, iv, iv_length);
#elif defined(MBEDTLS_PSA_BUILTIN_CIPHER)
return mbedtls_psa_cipher_set_iv(operation, iv, iv_length);
#endif
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_transparent_cipher_update(
mbedtls_transparent_test_driver_cipher_operation_t *operation,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
mbedtls_test_driver_cipher_hooks.hits++;
if (mbedtls_test_driver_cipher_hooks.forced_output != NULL) {
if (output_size < mbedtls_test_driver_cipher_hooks.forced_output_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(output,
mbedtls_test_driver_cipher_hooks.forced_output,
mbedtls_test_driver_cipher_hooks.forced_output_length);
*output_length = mbedtls_test_driver_cipher_hooks.forced_output_length;
return mbedtls_test_driver_cipher_hooks.forced_status;
}
if (mbedtls_test_driver_cipher_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_cipher_hooks.forced_status;
}
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
return libtestdriver1_mbedtls_psa_cipher_update(
operation, input, input_length,
output, output_size, output_length);
#elif defined(MBEDTLS_PSA_BUILTIN_CIPHER)
return mbedtls_psa_cipher_update(
operation, input, input_length,
output, output_size, output_length);
#endif
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_transparent_cipher_finish(
mbedtls_transparent_test_driver_cipher_operation_t *operation,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
mbedtls_test_driver_cipher_hooks.hits++;
if (mbedtls_test_driver_cipher_hooks.forced_output != NULL) {
if (output_size < mbedtls_test_driver_cipher_hooks.forced_output_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(output,
mbedtls_test_driver_cipher_hooks.forced_output,
mbedtls_test_driver_cipher_hooks.forced_output_length);
*output_length = mbedtls_test_driver_cipher_hooks.forced_output_length;
return mbedtls_test_driver_cipher_hooks.forced_status;
}
if (mbedtls_test_driver_cipher_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_cipher_hooks.forced_status;
}
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER)
return libtestdriver1_mbedtls_psa_cipher_finish(
operation, output, output_size, output_length);
#elif defined(MBEDTLS_PSA_BUILTIN_CIPHER)
return mbedtls_psa_cipher_finish(
operation, output, output_size, output_length);
#endif
return PSA_ERROR_NOT_SUPPORTED;
}
/*
* opaque versions, to do
*/
psa_status_t mbedtls_test_opaque_cipher_encrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg,
const uint8_t *iv, size_t iv_length,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size, size_t *output_length)
{
(void) attributes;
(void) key;
(void) key_length;
(void) alg;
(void) iv;
(void) iv_length;
(void) input;
(void) input_length;
(void) output;
(void) output_size;
(void) output_length;
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_opaque_cipher_decrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size, size_t *output_length)
{
(void) attributes;
(void) key;
(void) key_length;
(void) alg;
(void) input;
(void) input_length;
(void) output;
(void) output_size;
(void) output_length;
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_opaque_cipher_encrypt_setup(
mbedtls_opaque_test_driver_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg)
{
(void) operation;
(void) attributes;
(void) key;
(void) key_length;
(void) alg;
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_opaque_cipher_decrypt_setup(
mbedtls_opaque_test_driver_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg)
{
(void) operation;
(void) attributes;
(void) key;
(void) key_length;
(void) alg;
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_opaque_cipher_abort(
mbedtls_opaque_test_driver_cipher_operation_t *operation)
{
(void) operation;
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_opaque_cipher_set_iv(
mbedtls_opaque_test_driver_cipher_operation_t *operation,
const uint8_t *iv,
size_t iv_length)
{
(void) operation;
(void) iv;
(void) iv_length;
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_opaque_cipher_update(
mbedtls_opaque_test_driver_cipher_operation_t *operation,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
(void) operation;
(void) input;
(void) input_length;
(void) output;
(void) output_size;
(void) output_length;
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_opaque_cipher_finish(
mbedtls_opaque_test_driver_cipher_operation_t *operation,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
(void) operation;
(void) output;
(void) output_size;
(void) output_length;
return PSA_ERROR_NOT_SUPPORTED;
}
#endif /* PSA_CRYPTO_DRIVER_TEST */

View File

@@ -0,0 +1,153 @@
/*
* Test driver for key agreement functions.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <test/helpers.h>
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "psa/crypto.h"
#include "psa_crypto_core.h"
#include "psa_crypto_ecp.h"
#include "psa_crypto_ffdh.h"
#include "test/drivers/key_agreement.h"
#include "test/drivers/test_driver.h"
#include <string.h>
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_ecp.h)
#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_ffdh.h)
#if !defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1)
#if MBEDTLS_VERSION_MAJOR < 4
#include "libtestdriver1/include/psa/crypto.h"
#else
#include "libtestdriver1/tf-psa-crypto/include/psa/crypto.h"
#endif
#endif
#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 */
mbedtls_test_driver_key_agreement_hooks_t
mbedtls_test_driver_key_agreement_hooks = MBEDTLS_TEST_DRIVER_KEY_AGREEMENT_INIT;
psa_status_t mbedtls_test_transparent_key_agreement(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *peer_key,
size_t peer_key_length,
uint8_t *shared_secret,
size_t shared_secret_size,
size_t *shared_secret_length)
{
mbedtls_test_driver_key_agreement_hooks.hits++;
if (mbedtls_test_driver_key_agreement_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_key_agreement_hooks.forced_status;
}
if (mbedtls_test_driver_key_agreement_hooks.forced_output != NULL) {
if (mbedtls_test_driver_key_agreement_hooks.forced_output_length > shared_secret_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(shared_secret, mbedtls_test_driver_key_agreement_hooks.forced_output,
mbedtls_test_driver_key_agreement_hooks.forced_output_length);
*shared_secret_length = mbedtls_test_driver_key_agreement_hooks.forced_output_length;
return PSA_SUCCESS;
}
if (PSA_ALG_IS_ECDH(alg)) {
#if (defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_ECDH))
return libtestdriver1_mbedtls_psa_key_agreement_ecdh(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size,
alg, peer_key, peer_key_length,
shared_secret, shared_secret_size,
shared_secret_length);
#elif defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
return mbedtls_psa_key_agreement_ecdh(
attributes,
key_buffer, key_buffer_size,
alg, peer_key, peer_key_length,
shared_secret, shared_secret_size,
shared_secret_length);
#else
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
(void) peer_key;
(void) peer_key_length;
(void) shared_secret;
(void) shared_secret_size;
(void) shared_secret_length;
return PSA_ERROR_NOT_SUPPORTED;
#endif
}
if (PSA_ALG_IS_FFDH(alg)) {
#if (defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_FFDH))
return libtestdriver1_mbedtls_psa_ffdh_key_agreement(
(const libtestdriver1_psa_key_attributes_t *) attributes,
peer_key, peer_key_length,
key_buffer, key_buffer_size,
shared_secret, shared_secret_size,
shared_secret_length);
#elif defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH)
return mbedtls_psa_ffdh_key_agreement(
attributes,
peer_key,
peer_key_length,
key_buffer,
key_buffer_size,
shared_secret,
shared_secret_size,
shared_secret_length);
#else
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
(void) peer_key;
(void) peer_key_length;
(void) shared_secret;
(void) shared_secret_size;
(void) shared_secret_length;
return PSA_ERROR_NOT_SUPPORTED;
#endif
} else {
return PSA_ERROR_INVALID_ARGUMENT;
}
}
psa_status_t mbedtls_test_opaque_key_agreement(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *peer_key,
size_t peer_key_length,
uint8_t *shared_secret,
size_t shared_secret_size,
size_t *shared_secret_length)
{
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
(void) alg;
(void) peer_key;
(void) peer_key_length;
(void) shared_secret;
(void) shared_secret_size;
(void) shared_secret_length;
return PSA_ERROR_NOT_SUPPORTED;
}
#endif /* PSA_CRYPTO_DRIVER_TEST */

View File

@@ -0,0 +1,794 @@
/*
* Test driver for generating and verifying keys.
* Currently only supports generating and verifying ECC keys.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <test/helpers.h>
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "psa/crypto.h"
#include "psa_crypto_core.h"
#include "psa_crypto_ecp.h"
#include "psa_crypto_rsa.h"
#include "psa_crypto_ffdh.h"
#if !defined(MBEDTLS_VERSION_MAJOR) || MBEDTLS_VERSION_MAJOR >= 4
#include "mbedtls/private/ecp.h"
#else
#include "mbedtls/ecp.h"
#endif
#include "test/drivers/key_management.h"
#include "test/drivers/test_driver.h"
#include "test/random.h"
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_ecp.h)
#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_rsa.h)
#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_ffdh.h)
#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 */
#include <string.h>
mbedtls_test_driver_key_management_hooks_t
mbedtls_test_driver_key_management_hooks = MBEDTLS_TEST_DRIVER_KEY_MANAGEMENT_INIT;
const uint8_t mbedtls_test_driver_aes_key[16] =
{ 0x36, 0x77, 0x39, 0x7A, 0x24, 0x43, 0x26, 0x46,
0x29, 0x4A, 0x40, 0x4E, 0x63, 0x52, 0x66, 0x55 };
const uint8_t mbedtls_test_driver_ecdsa_key[32] =
{ 0xdc, 0x7d, 0x9d, 0x26, 0xd6, 0x7a, 0x4f, 0x63,
0x2c, 0x34, 0xc2, 0xdc, 0x0b, 0x69, 0x86, 0x18,
0x38, 0x82, 0xc2, 0x06, 0xdf, 0x04, 0xcd, 0xb7,
0xd6, 0x9a, 0xab, 0xe2, 0x8b, 0xe4, 0xf8, 0x1a };
const uint8_t mbedtls_test_driver_ecdsa_pubkey[65] =
{ 0x04,
0x85, 0xf6, 0x4d, 0x89, 0xf0, 0x0b, 0xe6, 0x6c,
0x88, 0xdd, 0x93, 0x7e, 0xfd, 0x6d, 0x7c, 0x44,
0x56, 0x48, 0xdc, 0xb7, 0x01, 0x15, 0x0b, 0x8a,
0x95, 0x09, 0x29, 0x58, 0x50, 0xf4, 0x1c, 0x19,
0x31, 0xe5, 0x71, 0xfb, 0x8f, 0x8c, 0x78, 0x31,
0x7a, 0x20, 0xb3, 0x80, 0xe8, 0x66, 0x58, 0x4b,
0xbc, 0x25, 0x16, 0xc3, 0xd2, 0x70, 0x2d, 0x79,
0x2f, 0x13, 0x1a, 0x92, 0x20, 0x95, 0xfd, 0x6c };
psa_status_t mbedtls_test_transparent_init(void)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
#if !defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) && \
defined(MBEDTLS_TEST_LIBTESTDRIVER1)
status = libtestdriver1_psa_crypto_init();
if (status != PSA_SUCCESS) {
return status;
}
#endif
(void) status;
return PSA_SUCCESS;
}
void mbedtls_test_transparent_free(void)
{
#if !defined(TF_PSA_CRYPTO_TEST_LIBTESTDRIVER1) && \
defined(MBEDTLS_TEST_LIBTESTDRIVER1)
libtestdriver1_mbedtls_psa_crypto_free();
#endif
return;
}
psa_status_t mbedtls_test_opaque_init(void)
{
return PSA_SUCCESS;
}
void mbedtls_test_opaque_free(void)
{
return;
}
/*
* This macro returns the base size for the key context when SE does not
* support storage. It is the size of the metadata that gets added to the
* wrapped key. In its test functionality the metadata is just some padded
* prefixing to the key.
*/
#define TEST_DRIVER_KEY_CONTEXT_BASE_SIZE \
PSA_CRYPTO_TEST_DRIVER_OPAQUE_PAD_PREFIX_SIZE
size_t mbedtls_test_opaque_size_function(
const psa_key_type_t key_type,
const size_t key_bits)
{
size_t key_buffer_size = 0;
key_buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits);
if (key_buffer_size == 0) {
return 0;
}
/* Include spacing for base size overhead over the key size
* */
key_buffer_size += TEST_DRIVER_KEY_CONTEXT_BASE_SIZE;
return key_buffer_size;
}
static size_t mbedtls_test_opaque_get_base_size()
{
return TEST_DRIVER_KEY_CONTEXT_BASE_SIZE;
}
/*
* The wrap function mbedtls_test_opaque_wrap_key pads and wraps the
* clear key. It expects the clear and wrap buffers to be passed in.
* key_length is the size of the clear key to be wrapped.
* wrapped_key_buffer_size is the size of the output buffer wrap_key.
* The argument wrapped_key_buffer_length is filled with the wrapped
* key_size on success.
* */
static psa_status_t mbedtls_test_opaque_wrap_key(
const uint8_t *key,
size_t key_length,
uint8_t *wrapped_key_buffer,
size_t wrapped_key_buffer_size,
size_t *wrapped_key_buffer_length)
{
size_t opaque_key_base_size = mbedtls_test_opaque_get_base_size();
uint64_t prefix = PSA_CRYPTO_TEST_DRIVER_OPAQUE_PAD_PREFIX;
if (key_length + opaque_key_base_size > wrapped_key_buffer_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
/* Write in the opaque pad prefix */
memcpy(wrapped_key_buffer, &prefix, opaque_key_base_size);
wrapped_key_buffer += opaque_key_base_size;
*wrapped_key_buffer_length = key_length + opaque_key_base_size;
while (key_length--) {
wrapped_key_buffer[key_length] = key[key_length] ^ 0xFF;
}
return PSA_SUCCESS;
}
/*
* The unwrap function mbedtls_test_opaque_unwrap_key removes a pad prefix
* and unwraps the wrapped key. It expects the clear and wrap buffers to be
* passed in.
* wrapped_key_length is the size of the wrapped key,
* key_buffer_size is the size of the output buffer clear_key.
* The argument key_buffer_length is filled with the unwrapped(clear)
* key_size on success.
* */
psa_status_t mbedtls_test_opaque_unwrap_key(
const uint8_t *wrapped_key,
size_t wrapped_key_length,
uint8_t *key_buffer,
size_t key_buffer_size,
size_t *key_buffer_length)
{
/* Remove the pad prefix from the wrapped key */
size_t opaque_key_base_size = mbedtls_test_opaque_get_base_size();
size_t clear_key_size;
/* Check for underflow */
if (wrapped_key_length < opaque_key_base_size) {
return PSA_ERROR_DATA_CORRUPT;
}
clear_key_size = wrapped_key_length - opaque_key_base_size;
wrapped_key += opaque_key_base_size;
if (clear_key_size > key_buffer_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
*key_buffer_length = clear_key_size;
while (clear_key_size--) {
key_buffer[clear_key_size] = wrapped_key[clear_key_size] ^ 0xFF;
}
return PSA_SUCCESS;
}
psa_status_t mbedtls_test_transparent_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key, size_t key_size, size_t *key_length)
{
++mbedtls_test_driver_key_management_hooks.hits;
++mbedtls_test_driver_key_management_hooks.hits_generate_key;
if (mbedtls_test_driver_key_management_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_key_management_hooks.forced_status;
}
if (mbedtls_test_driver_key_management_hooks.forced_output != NULL) {
if (mbedtls_test_driver_key_management_hooks.forced_output_length >
key_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(key, mbedtls_test_driver_key_management_hooks.forced_output,
mbedtls_test_driver_key_management_hooks.forced_output_length);
*key_length = mbedtls_test_driver_key_management_hooks.forced_output_length;
return PSA_SUCCESS;
}
if (PSA_KEY_TYPE_IS_ECC(psa_get_key_type(attributes))
&& PSA_KEY_TYPE_IS_KEY_PAIR(psa_get_key_type(attributes))) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
return libtestdriver1_mbedtls_psa_ecp_generate_key(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key, key_size, key_length);
#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
return mbedtls_psa_ecp_generate_key(
attributes, key, key_size, key_length);
#endif
} else if (psa_get_key_type(attributes) == PSA_KEY_TYPE_RSA_KEY_PAIR) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
return libtestdriver1_mbedtls_psa_rsa_generate_key(
(const libtestdriver1_psa_key_attributes_t *) attributes,
NULL, 0, /* We don't support custom e in the test driver yet */
key, key_size, key_length);
#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
return mbedtls_psa_rsa_generate_key(
attributes,
NULL, 0, /* We don't support custom e in the test driver yet */
key, key_size, key_length);
#endif
} else if (PSA_KEY_TYPE_IS_DH(psa_get_key_type(attributes))
&& PSA_KEY_TYPE_IS_KEY_PAIR(psa_get_key_type(attributes))) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE)
return libtestdriver1_mbedtls_psa_ffdh_generate_key(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key, key_size, key_length);
#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR)
return mbedtls_psa_ffdh_generate_key(
attributes, key, key_size, key_length);
#endif
}
(void) attributes;
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_opaque_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key, size_t key_size, size_t *key_length)
{
(void) attributes;
(void) key;
(void) key_size;
(void) key_length;
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_transparent_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data,
size_t data_length,
uint8_t *key_buffer,
size_t key_buffer_size,
size_t *key_buffer_length,
size_t *bits)
{
psa_key_type_t type = psa_get_key_type(attributes);
++mbedtls_test_driver_key_management_hooks.hits;
mbedtls_test_driver_key_management_hooks.location = PSA_KEY_LOCATION_LOCAL_STORAGE;
if (mbedtls_test_driver_key_management_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_key_management_hooks.forced_status;
}
if (PSA_KEY_TYPE_IS_ECC(type)) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
(defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY))
return libtestdriver1_mbedtls_psa_ecp_import_key(
(const libtestdriver1_psa_key_attributes_t *) attributes,
data, data_length,
key_buffer, key_buffer_size,
key_buffer_length, bits);
#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
return mbedtls_psa_ecp_import_key(
attributes,
data, data_length,
key_buffer, key_buffer_size,
key_buffer_length, bits);
#endif
} else if (PSA_KEY_TYPE_IS_RSA(type)) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
(defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY))
return libtestdriver1_mbedtls_psa_rsa_import_key(
(const libtestdriver1_psa_key_attributes_t *) attributes,
data, data_length,
key_buffer, key_buffer_size,
key_buffer_length, bits);
#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
return mbedtls_psa_rsa_import_key(
attributes,
data, data_length,
key_buffer, key_buffer_size,
key_buffer_length, bits);
#endif
} else if (PSA_KEY_TYPE_IS_DH(type)) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
(defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR) || \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY))
return libtestdriver1_mbedtls_psa_ffdh_import_key(
(const libtestdriver1_psa_key_attributes_t *) attributes,
data, data_length,
key_buffer, key_buffer_size,
key_buffer_length, bits);
#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
return mbedtls_psa_ffdh_import_key(
attributes,
data, data_length,
key_buffer, key_buffer_size,
key_buffer_length, bits);
#endif
}
(void) data;
(void) data_length;
(void) key_buffer;
(void) key_buffer_size;
(void) key_buffer_length;
(void) bits;
(void) type;
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_opaque_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data,
size_t data_length,
uint8_t *key_buffer,
size_t key_buffer_size,
size_t *key_buffer_length,
size_t *bits)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_type_t type = psa_get_key_type(attributes);
/* This buffer will be used as an intermediate placeholder for
* the clear key till we wrap it */
uint8_t *key_buffer_temp;
++mbedtls_test_driver_key_management_hooks.hits;
mbedtls_test_driver_key_management_hooks.location = PSA_CRYPTO_TEST_DRIVER_LOCATION;
if (mbedtls_test_driver_key_management_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_key_management_hooks.forced_status;
}
key_buffer_temp = mbedtls_calloc(1, key_buffer_size);
if (key_buffer_temp == NULL) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
if (PSA_KEY_TYPE_IS_UNSTRUCTURED(type)) {
*bits = PSA_BYTES_TO_BITS(data_length);
status = psa_validate_unstructured_key_bit_size(type,
*bits);
if (status != PSA_SUCCESS) {
goto exit;
}
if (data_length > key_buffer_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
/* Copy the key material accounting for opaque key padding. */
memcpy(key_buffer_temp, data, data_length);
*key_buffer_length = data_length;
} else if (PSA_KEY_TYPE_IS_ECC(type)) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
(defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY))
status = libtestdriver1_mbedtls_psa_ecp_import_key(
(const libtestdriver1_psa_key_attributes_t *) attributes,
data, data_length,
key_buffer_temp, key_buffer_size,
key_buffer_length, bits);
#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
status = mbedtls_psa_ecp_import_key(
attributes,
data, data_length,
key_buffer_temp, key_buffer_size,
key_buffer_length, bits);
#else
status = PSA_ERROR_NOT_SUPPORTED;
#endif
if (status != PSA_SUCCESS) {
goto exit;
}
} else if (PSA_KEY_TYPE_IS_RSA(type)) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
(defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) || \
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY))
status = libtestdriver1_mbedtls_psa_rsa_import_key(
(const libtestdriver1_psa_key_attributes_t *) attributes,
data, data_length,
key_buffer_temp, key_buffer_size,
key_buffer_length, bits);
#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
status = mbedtls_psa_rsa_import_key(
attributes,
data, data_length,
key_buffer_temp, key_buffer_size,
key_buffer_length, bits);
#else
status = PSA_ERROR_NOT_SUPPORTED;
#endif
if (status != PSA_SUCCESS) {
goto exit;
}
} else {
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
status = mbedtls_test_opaque_wrap_key(key_buffer_temp, *key_buffer_length,
key_buffer, key_buffer_size, key_buffer_length);
exit:
mbedtls_free(key_buffer_temp);
return status;
}
psa_status_t mbedtls_test_opaque_export_key(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
uint8_t *data, size_t data_size, size_t *data_length)
{
if (key_length == sizeof(psa_drv_slot_number_t)) {
/* Assume this is a builtin key based on the key material length. */
psa_drv_slot_number_t slot_number = *((psa_drv_slot_number_t *) key);
switch (slot_number) {
case PSA_CRYPTO_TEST_DRIVER_BUILTIN_ECDSA_KEY_SLOT:
/* This is the ECDSA slot. Verify the key's attributes before
* returning the private key. */
if (psa_get_key_type(attributes) !=
PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
if (psa_get_key_bits(attributes) != 256) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
if (psa_get_key_algorithm(attributes) !=
PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
if ((psa_get_key_usage_flags(attributes) &
PSA_KEY_USAGE_EXPORT) == 0) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
if (data_size < sizeof(mbedtls_test_driver_ecdsa_key)) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(data, mbedtls_test_driver_ecdsa_key,
sizeof(mbedtls_test_driver_ecdsa_key));
*data_length = sizeof(mbedtls_test_driver_ecdsa_key);
return PSA_SUCCESS;
case PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT:
/* This is the AES slot. Verify the key's attributes before
* returning the key. */
if (psa_get_key_type(attributes) != PSA_KEY_TYPE_AES) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
if (psa_get_key_bits(attributes) != 128) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
if (psa_get_key_algorithm(attributes) != PSA_ALG_CTR) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
if ((psa_get_key_usage_flags(attributes) &
PSA_KEY_USAGE_EXPORT) == 0) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
if (data_size < sizeof(mbedtls_test_driver_aes_key)) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(data, mbedtls_test_driver_aes_key,
sizeof(mbedtls_test_driver_aes_key));
*data_length = sizeof(mbedtls_test_driver_aes_key);
return PSA_SUCCESS;
default:
return PSA_ERROR_DOES_NOT_EXIST;
}
} else {
/* This buffer will be used as an intermediate placeholder for
* the opaque key till we unwrap the key into key_buffer */
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_type_t type = psa_get_key_type(attributes);
if (PSA_KEY_TYPE_IS_UNSTRUCTURED(type) ||
PSA_KEY_TYPE_IS_RSA(type) ||
PSA_KEY_TYPE_IS_ECC(type)) {
status = mbedtls_test_opaque_unwrap_key(key, key_length,
data, data_size, data_length);
return status;
}
}
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_transparent_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length)
{
++mbedtls_test_driver_key_management_hooks.hits;
++mbedtls_test_driver_key_management_hooks.hits_export_public_key;
if (mbedtls_test_driver_key_management_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_key_management_hooks.forced_status;
}
if (mbedtls_test_driver_key_management_hooks.forced_output != NULL) {
if (mbedtls_test_driver_key_management_hooks.forced_output_length >
data_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(data, mbedtls_test_driver_key_management_hooks.forced_output,
mbedtls_test_driver_key_management_hooks.forced_output_length);
*data_length = mbedtls_test_driver_key_management_hooks.forced_output_length;
return PSA_SUCCESS;
}
psa_key_type_t key_type = psa_get_key_type(attributes);
if (PSA_KEY_TYPE_IS_ECC(key_type)) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
(defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY))
return libtestdriver1_mbedtls_psa_ecp_export_public_key(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size,
data, data_size, data_length);
#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
return mbedtls_psa_ecp_export_public_key(
attributes,
key_buffer, key_buffer_size,
data, data_size, data_length);
#endif
} else if (PSA_KEY_TYPE_IS_RSA(key_type)) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
(defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY))
return libtestdriver1_mbedtls_psa_rsa_export_public_key(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size,
data, data_size, data_length);
#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
return mbedtls_psa_rsa_export_public_key(
attributes,
key_buffer, key_buffer_size,
data, data_size, data_length);
#endif
} else if (PSA_KEY_TYPE_IS_DH(key_type)) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
(defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR) || \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY))
return libtestdriver1_mbedtls_psa_ffdh_export_public_key(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size,
data, data_size, data_length);
#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY)
return mbedtls_psa_ffdh_export_public_key(
attributes,
key_buffer, key_buffer_size,
data, data_size, data_length);
#endif
}
(void) key_buffer;
(void) key_buffer_size;
(void) key_type;
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_opaque_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
uint8_t *data, size_t data_size, size_t *data_length)
{
if (key_length != sizeof(psa_drv_slot_number_t)) {
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_type_t key_type = psa_get_key_type(attributes);
uint8_t *key_buffer_temp;
key_buffer_temp = mbedtls_calloc(1, key_length);
if (key_buffer_temp == NULL) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
if (PSA_KEY_TYPE_IS_ECC(key_type)) {
status = mbedtls_test_opaque_unwrap_key(key, key_length,
key_buffer_temp, key_length, data_length);
if (status == PSA_SUCCESS) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
(defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY))
status = libtestdriver1_mbedtls_psa_ecp_export_public_key(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer_temp, *data_length,
data, data_size, data_length);
#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
status = mbedtls_psa_ecp_export_public_key(
attributes,
key_buffer_temp, *data_length,
data, data_size, data_length);
#else
status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
} else if (PSA_KEY_TYPE_IS_RSA(key_type)) {
status = mbedtls_test_opaque_unwrap_key(key, key_length,
key_buffer_temp, key_length, data_length);
if (status == PSA_SUCCESS) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
(defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) || \
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY))
status = libtestdriver1_mbedtls_psa_rsa_export_public_key(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer_temp, *data_length,
data, data_size, data_length);
#elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
status = mbedtls_psa_rsa_export_public_key(
attributes,
key_buffer_temp, *data_length,
data, data_size, data_length);
#else
status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
} else {
status = PSA_ERROR_NOT_SUPPORTED;
(void) key;
(void) key_type;
}
mbedtls_free(key_buffer_temp);
return status;
}
/* Assume this is a builtin key based on the key material length. */
psa_drv_slot_number_t slot_number = *((psa_drv_slot_number_t *) key);
switch (slot_number) {
case PSA_CRYPTO_TEST_DRIVER_BUILTIN_ECDSA_KEY_SLOT:
/* This is the ECDSA slot. Verify the key's attributes before
* returning the public key. */
if (psa_get_key_type(attributes) !=
PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
if (psa_get_key_bits(attributes) != 256) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
if (psa_get_key_algorithm(attributes) !=
PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
if (data_size < sizeof(mbedtls_test_driver_ecdsa_pubkey)) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(data, mbedtls_test_driver_ecdsa_pubkey,
sizeof(mbedtls_test_driver_ecdsa_pubkey));
*data_length = sizeof(mbedtls_test_driver_ecdsa_pubkey);
return PSA_SUCCESS;
default:
return PSA_ERROR_DOES_NOT_EXIST;
}
}
/* The opaque test driver exposes two built-in keys when builtin key support is
* compiled in.
* The key in slot #PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT is an AES-128
* key which allows CTR mode.
* The key in slot #PSA_CRYPTO_TEST_DRIVER_BUILTIN_ECDSA_KEY_SLOT is a secp256r1
* private key which allows ECDSA sign & verify.
* The key buffer format for these is the raw format of psa_drv_slot_number_t
* (i.e. for an actual driver this would mean 'builtin_key_size' =
* sizeof(psa_drv_slot_number_t)).
*/
psa_status_t mbedtls_test_opaque_get_builtin_key(
psa_drv_slot_number_t slot_number,
psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
{
switch (slot_number) {
case PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT:
psa_set_key_type(attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(attributes, 128);
psa_set_key_usage_flags(
attributes,
PSA_KEY_USAGE_ENCRYPT |
PSA_KEY_USAGE_DECRYPT |
PSA_KEY_USAGE_EXPORT);
psa_set_key_algorithm(attributes, PSA_ALG_CTR);
if (key_buffer_size < sizeof(psa_drv_slot_number_t)) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
*((psa_drv_slot_number_t *) key_buffer) =
PSA_CRYPTO_TEST_DRIVER_BUILTIN_AES_KEY_SLOT;
*key_buffer_length = sizeof(psa_drv_slot_number_t);
return PSA_SUCCESS;
case PSA_CRYPTO_TEST_DRIVER_BUILTIN_ECDSA_KEY_SLOT:
psa_set_key_type(
attributes,
PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(attributes, 256);
psa_set_key_usage_flags(
attributes,
PSA_KEY_USAGE_SIGN_HASH |
PSA_KEY_USAGE_VERIFY_HASH |
PSA_KEY_USAGE_EXPORT);
psa_set_key_algorithm(
attributes, PSA_ALG_ECDSA(PSA_ALG_ANY_HASH));
if (key_buffer_size < sizeof(psa_drv_slot_number_t)) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
*((psa_drv_slot_number_t *) key_buffer) =
PSA_CRYPTO_TEST_DRIVER_BUILTIN_ECDSA_KEY_SLOT;
*key_buffer_length = sizeof(psa_drv_slot_number_t);
return PSA_SUCCESS;
default:
return PSA_ERROR_DOES_NOT_EXIST;
}
}
psa_status_t mbedtls_test_opaque_copy_key(
psa_key_attributes_t *attributes,
const uint8_t *source_key, size_t source_key_length,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
{
/* This is a case where the opaque test driver emulates an SE without storage.
* With that all key context is stored in the wrapped buffer.
* So no additional house keeping is necessary to reference count the
* copied keys. This could change when the opaque test driver is extended
* to support SE with storage, or to emulate an SE without storage but
* still holding some slot references */
if (source_key_length > key_buffer_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(key_buffer, source_key, source_key_length);
*key_buffer_length = source_key_length;
(void) attributes;
return PSA_SUCCESS;
}
#endif /* PSA_CRYPTO_DRIVER_TEST */

View File

@@ -0,0 +1,434 @@
/*
* Test driver for MAC entry points.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <test/helpers.h>
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "psa_crypto_mac.h"
#include "test/drivers/mac.h"
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_mac.h)
#endif
mbedtls_test_driver_mac_hooks_t mbedtls_test_driver_mac_hooks =
MBEDTLS_TEST_DRIVER_MAC_INIT;
psa_status_t mbedtls_test_transparent_mac_compute(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *mac,
size_t mac_size,
size_t *mac_length)
{
mbedtls_test_driver_mac_hooks.hits++;
if (mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_test_driver_mac_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC)
mbedtls_test_driver_mac_hooks.driver_status =
libtestdriver1_mbedtls_psa_mac_compute(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size, alg,
input, input_length,
mac, mac_size, mac_length);
#elif defined(MBEDTLS_PSA_BUILTIN_MAC)
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_psa_mac_compute(
attributes, key_buffer, key_buffer_size, alg,
input, input_length,
mac, mac_size, mac_length);
#else
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
(void) alg;
(void) input;
(void) input_length;
(void) mac;
(void) mac_size;
(void) mac_length;
mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_mac_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_mac_sign_setup(
mbedtls_transparent_test_driver_mac_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg)
{
mbedtls_test_driver_mac_hooks.hits++;
if (mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_test_driver_mac_hooks.forced_status;
} else if (!MBEDTLS_TEST_OBJECT_IS_ALL_ZERO(operation)) {
mbedtls_test_driver_mac_hooks.driver_status =
PSA_ERROR_TEST_DETECTED_BAD_INITIALIZATION;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC)
mbedtls_test_driver_mac_hooks.driver_status =
libtestdriver1_mbedtls_psa_mac_sign_setup(
operation,
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size, alg);
#elif defined(MBEDTLS_PSA_BUILTIN_MAC)
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_psa_mac_sign_setup(
operation, attributes, key_buffer, key_buffer_size, alg);
#else
(void) operation;
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
(void) alg;
mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_mac_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_mac_verify_setup(
mbedtls_transparent_test_driver_mac_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg)
{
mbedtls_test_driver_mac_hooks.hits++;
if (mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_test_driver_mac_hooks.forced_status;
} else if (!MBEDTLS_TEST_OBJECT_IS_ALL_ZERO(operation)) {
mbedtls_test_driver_mac_hooks.driver_status =
PSA_ERROR_TEST_DETECTED_BAD_INITIALIZATION;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC)
mbedtls_test_driver_mac_hooks.driver_status =
libtestdriver1_mbedtls_psa_mac_verify_setup(
operation,
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size, alg);
#elif defined(MBEDTLS_PSA_BUILTIN_MAC)
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_psa_mac_verify_setup(
operation, attributes, key_buffer, key_buffer_size, alg);
#else
(void) operation;
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
(void) alg;
mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_mac_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_mac_update(
mbedtls_transparent_test_driver_mac_operation_t *operation,
const uint8_t *input,
size_t input_length)
{
mbedtls_test_driver_mac_hooks.hits++;
if (mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_test_driver_mac_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC)
mbedtls_test_driver_mac_hooks.driver_status =
libtestdriver1_mbedtls_psa_mac_update(
operation, input, input_length);
#elif defined(MBEDTLS_PSA_BUILTIN_MAC)
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_psa_mac_update(
operation, input, input_length);
#else
(void) operation;
(void) input;
(void) input_length;
mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_mac_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_mac_sign_finish(
mbedtls_transparent_test_driver_mac_operation_t *operation,
uint8_t *mac,
size_t mac_size,
size_t *mac_length)
{
mbedtls_test_driver_mac_hooks.hits++;
if (mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_test_driver_mac_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC)
mbedtls_test_driver_mac_hooks.driver_status =
libtestdriver1_mbedtls_psa_mac_sign_finish(
operation, mac, mac_size, mac_length);
#elif defined(MBEDTLS_PSA_BUILTIN_MAC)
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_psa_mac_sign_finish(
operation, mac, mac_size, mac_length);
#else
(void) operation;
(void) mac;
(void) mac_size;
(void) mac_length;
mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_mac_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_mac_verify_finish(
mbedtls_transparent_test_driver_mac_operation_t *operation,
const uint8_t *mac,
size_t mac_length)
{
mbedtls_test_driver_mac_hooks.hits++;
if (mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_test_driver_mac_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC)
mbedtls_test_driver_mac_hooks.driver_status =
libtestdriver1_mbedtls_psa_mac_verify_finish(
operation, mac, mac_length);
#elif defined(MBEDTLS_PSA_BUILTIN_MAC)
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_psa_mac_verify_finish(
operation, mac, mac_length);
#else
(void) operation;
(void) mac;
(void) mac_length;
mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_mac_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_mac_abort(
mbedtls_transparent_test_driver_mac_operation_t *operation)
{
mbedtls_test_driver_mac_hooks.hits++;
if (mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_test_driver_mac_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC)
mbedtls_test_driver_mac_hooks.driver_status =
libtestdriver1_mbedtls_psa_mac_abort(operation);
#elif defined(MBEDTLS_PSA_BUILTIN_MAC)
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_psa_mac_abort(operation);
#else
(void) operation;
mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_mac_hooks.driver_status;
}
psa_status_t mbedtls_test_opaque_mac_compute(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *mac,
size_t mac_size,
size_t *mac_length)
{
mbedtls_test_driver_mac_hooks.hits++;
if (mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_test_driver_mac_hooks.forced_status;
} else {
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
(void) alg;
(void) input;
(void) input_length;
(void) mac;
(void) mac_size;
(void) mac_length;
mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
}
return mbedtls_test_driver_mac_hooks.driver_status;
}
psa_status_t mbedtls_test_opaque_mac_sign_setup(
mbedtls_opaque_test_driver_mac_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg)
{
mbedtls_test_driver_mac_hooks.hits++;
if (mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_test_driver_mac_hooks.forced_status;
} else if (!MBEDTLS_TEST_OBJECT_IS_ALL_ZERO(operation)) {
mbedtls_test_driver_mac_hooks.driver_status =
PSA_ERROR_TEST_DETECTED_BAD_INITIALIZATION;
} else {
(void) operation;
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
(void) alg;
mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
}
return mbedtls_test_driver_mac_hooks.driver_status;
}
psa_status_t mbedtls_test_opaque_mac_verify_setup(
mbedtls_opaque_test_driver_mac_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg)
{
mbedtls_test_driver_mac_hooks.hits++;
if (mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_test_driver_mac_hooks.forced_status;
} else if (!MBEDTLS_TEST_OBJECT_IS_ALL_ZERO(operation)) {
mbedtls_test_driver_mac_hooks.driver_status =
PSA_ERROR_TEST_DETECTED_BAD_INITIALIZATION;
} else {
(void) operation;
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
(void) alg;
mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
}
return mbedtls_test_driver_mac_hooks.driver_status;
}
psa_status_t mbedtls_test_opaque_mac_update(
mbedtls_opaque_test_driver_mac_operation_t *operation,
const uint8_t *input,
size_t input_length)
{
mbedtls_test_driver_mac_hooks.hits++;
if (mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_test_driver_mac_hooks.forced_status;
} else {
(void) operation;
(void) input;
(void) input_length;
mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
}
return mbedtls_test_driver_mac_hooks.driver_status;
}
psa_status_t mbedtls_test_opaque_mac_sign_finish(
mbedtls_opaque_test_driver_mac_operation_t *operation,
uint8_t *mac,
size_t mac_size,
size_t *mac_length)
{
mbedtls_test_driver_mac_hooks.hits++;
if (mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_test_driver_mac_hooks.forced_status;
} else {
(void) operation;
(void) mac;
(void) mac_size;
(void) mac_length;
mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
}
return mbedtls_test_driver_mac_hooks.driver_status;
}
psa_status_t mbedtls_test_opaque_mac_verify_finish(
mbedtls_opaque_test_driver_mac_operation_t *operation,
const uint8_t *mac,
size_t mac_length)
{
mbedtls_test_driver_mac_hooks.hits++;
if (mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_test_driver_mac_hooks.forced_status;
} else {
(void) operation;
(void) mac;
(void) mac_length;
mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
}
return mbedtls_test_driver_mac_hooks.driver_status;
}
psa_status_t mbedtls_test_opaque_mac_abort(
mbedtls_opaque_test_driver_mac_operation_t *operation)
{
mbedtls_test_driver_mac_hooks.hits++;
if (mbedtls_test_driver_mac_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_mac_hooks.driver_status =
mbedtls_test_driver_mac_hooks.forced_status;
} else {
(void) operation;
mbedtls_test_driver_mac_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
}
return mbedtls_test_driver_mac_hooks.driver_status;
}
#endif /* PSA_CRYPTO_DRIVER_TEST */

View File

@@ -0,0 +1,205 @@
/*
* Test driver for PAKE entry points.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <test/helpers.h>
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "psa_crypto_pake.h"
#include "test/drivers/pake.h"
#include "string.h"
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_pake.h)
#endif
mbedtls_test_driver_pake_hooks_t mbedtls_test_driver_pake_hooks =
MBEDTLS_TEST_DRIVER_PAKE_INIT;
psa_status_t mbedtls_test_transparent_pake_setup(
mbedtls_transparent_test_driver_pake_operation_t *operation,
const psa_crypto_driver_pake_inputs_t *inputs)
{
mbedtls_test_driver_pake_hooks.hits.total++;
mbedtls_test_driver_pake_hooks.hits.setup++;
if (mbedtls_test_driver_pake_hooks.forced_setup_status != PSA_SUCCESS) {
mbedtls_test_driver_pake_hooks.driver_status =
mbedtls_test_driver_pake_hooks.forced_setup_status;
} else if (!MBEDTLS_TEST_OBJECT_IS_ALL_ZERO(operation)) {
mbedtls_test_driver_pake_hooks.driver_status =
PSA_ERROR_TEST_DETECTED_BAD_INITIALIZATION;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_PAKE)
mbedtls_test_driver_pake_hooks.driver_status =
libtestdriver1_mbedtls_psa_pake_setup(
operation, (const libtestdriver1_psa_crypto_driver_pake_inputs_t *) inputs);
#elif defined(MBEDTLS_PSA_BUILTIN_PAKE)
mbedtls_test_driver_pake_hooks.driver_status =
mbedtls_psa_pake_setup(
operation, inputs);
#else
(void) operation;
(void) inputs;
mbedtls_test_driver_pake_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_pake_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_pake_output(
mbedtls_transparent_test_driver_pake_operation_t *operation,
psa_crypto_driver_pake_step_t step,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
mbedtls_test_driver_pake_hooks.hits.total++;
mbedtls_test_driver_pake_hooks.hits.output++;
if (mbedtls_test_driver_pake_hooks.forced_output != NULL) {
if (output_size < mbedtls_test_driver_pake_hooks.forced_output_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(output,
mbedtls_test_driver_pake_hooks.forced_output,
mbedtls_test_driver_pake_hooks.forced_output_length);
*output_length = mbedtls_test_driver_pake_hooks.forced_output_length;
return mbedtls_test_driver_pake_hooks.forced_status;
}
if (mbedtls_test_driver_pake_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_pake_hooks.driver_status =
mbedtls_test_driver_pake_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_PAKE)
mbedtls_test_driver_pake_hooks.driver_status =
libtestdriver1_mbedtls_psa_pake_output(
operation, (libtestdriver1_psa_crypto_driver_pake_step_t) step,
output, output_size, output_length);
#elif defined(MBEDTLS_PSA_BUILTIN_PAKE)
mbedtls_test_driver_pake_hooks.driver_status =
mbedtls_psa_pake_output(
operation, step, output, output_size, output_length);
#else
(void) operation;
(void) step;
(void) output;
(void) output_size;
(void) output_length;
mbedtls_test_driver_pake_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_pake_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_pake_input(
mbedtls_transparent_test_driver_pake_operation_t *operation,
psa_crypto_driver_pake_step_t step,
const uint8_t *input,
size_t input_length)
{
mbedtls_test_driver_pake_hooks.hits.total++;
mbedtls_test_driver_pake_hooks.hits.input++;
if (mbedtls_test_driver_pake_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_pake_hooks.driver_status =
mbedtls_test_driver_pake_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_PAKE)
mbedtls_test_driver_pake_hooks.driver_status =
libtestdriver1_mbedtls_psa_pake_input(
operation, (libtestdriver1_psa_crypto_driver_pake_step_t) step,
input, input_length);
#elif defined(MBEDTLS_PSA_BUILTIN_PAKE)
mbedtls_test_driver_pake_hooks.driver_status =
mbedtls_psa_pake_input(
operation, step, input, input_length);
#else
(void) operation;
(void) step;
(void) input;
(void) input_length;
mbedtls_test_driver_pake_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_pake_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_pake_get_implicit_key(
mbedtls_transparent_test_driver_pake_operation_t *operation,
uint8_t *output, size_t output_size, size_t *output_length)
{
mbedtls_test_driver_pake_hooks.hits.total++;
mbedtls_test_driver_pake_hooks.hits.implicit_key++;
if (mbedtls_test_driver_pake_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_pake_hooks.driver_status =
mbedtls_test_driver_pake_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_PAKE)
mbedtls_test_driver_pake_hooks.driver_status =
libtestdriver1_mbedtls_psa_pake_get_implicit_key(
operation, output, output_size, output_length);
#elif defined(MBEDTLS_PSA_BUILTIN_PAKE)
mbedtls_test_driver_pake_hooks.driver_status =
mbedtls_psa_pake_get_implicit_key(
operation, output, output_size, output_length);
#else
(void) operation;
(void) output;
(void) output_size;
(void) output_length;
mbedtls_test_driver_pake_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_pake_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_pake_abort(
mbedtls_transparent_test_driver_pake_operation_t *operation)
{
mbedtls_test_driver_pake_hooks.hits.total++;
mbedtls_test_driver_pake_hooks.hits.abort++;
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_PAKE)
mbedtls_test_driver_pake_hooks.driver_status =
libtestdriver1_mbedtls_psa_pake_abort(
operation);
#elif defined(MBEDTLS_PSA_BUILTIN_PAKE)
mbedtls_test_driver_pake_hooks.driver_status =
mbedtls_psa_pake_abort(
operation);
#else
(void) operation;
mbedtls_test_driver_pake_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
if (mbedtls_test_driver_pake_hooks.forced_status != PSA_SUCCESS &&
mbedtls_test_driver_pake_hooks.driver_status == PSA_SUCCESS) {
mbedtls_test_driver_pake_hooks.driver_status =
mbedtls_test_driver_pake_hooks.forced_status;
}
return mbedtls_test_driver_pake_hooks.driver_status;
}
#endif /* PSA_CRYPTO_DRIVER_TEST */

View File

@@ -0,0 +1,464 @@
/*
* Test driver for signature functions.
* Currently supports signing and verifying precalculated hashes, using
* only deterministic ECDSA on curves secp256r1, secp384r1 and secp521r1.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <test/helpers.h>
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "psa/crypto.h"
#include "psa_crypto_core.h"
#include "psa_crypto_ecp.h"
#include "psa_crypto_hash.h"
#include "psa_crypto_rsa.h"
#if !defined(MBEDTLS_VERSION_MAJOR) || MBEDTLS_VERSION_MAJOR >= 4
#include "mbedtls/private/ecp.h"
#else
#include "mbedtls/ecp.h"
#endif
#include "test/drivers/hash.h"
#include "test/drivers/signature.h"
#if !defined(MBEDTLS_VERSION_MAJOR) || MBEDTLS_VERSION_MAJOR >= 4
#include "mbedtls/private/ecdsa.h"
#else
#include "mbedtls/ecdsa.h"
#endif
#include "test/random.h"
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_ecp.h)
#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_hash.h)
#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_rsa.h)
#endif
/* This file is part of the framework and needs to be compatible with all
* maintained branches of Mbed TLS and TF-PSA-Crypto.
*
* - Until shortly before TF-PSA-Crypto 1.1.0, ML-DSA does not exist at all.
* - In TF-PSA-Crypto 1.1.0, TF_PSA_CRYPTO_PQCP_MLDSA_ENABLED exists, but
* there is no driver dispatch for it yet, so this driver doesn't need to
* worry about ML-DSA.
* - Shortly after TF-PSA-Crypto 1.1.0, in
* https://github.com/Mbed-TLS/TF-PSA-Crypto/pull/700, we introduced
* driver dispatch for ML-DSA, but the macro PSA_ALG_IS_ML_DSA is not
* in the API yet, only in a private header. Including this private header
* is a pain due to how our various build scripts set up include paths, so
* we don't do it. Instead, define PSA_ALG_IS_ML_DSA manually: it's the
* only thing we need.
* - Later we will add ML-DSA to the API, including the definition of
* PSA_ALG_IS_ML_DSA. After that we may also add driver dispatch testing
* for ML-DSA.
*/
#if !defined(PSA_ALG_IS_ML_DSA)
/* Pure ML-DSA (hedged or deterministic) */
#define PSA_ALG_IS_ML_DSA(alg) \
((alg) == 0x06004400u || (alg) == 0x06004500u)
#endif
#include <string.h>
mbedtls_test_driver_signature_hooks_t
mbedtls_test_driver_signature_sign_hooks = MBEDTLS_TEST_DRIVER_SIGNATURE_INIT;
mbedtls_test_driver_signature_hooks_t
mbedtls_test_driver_signature_verify_hooks = MBEDTLS_TEST_DRIVER_SIGNATURE_INIT;
static psa_status_t sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *hash,
size_t hash_length,
uint8_t *signature,
size_t signature_size,
size_t *signature_length)
{
if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||
PSA_ALG_IS_RSA_PSS(alg)) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
(defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS))
return libtestdriver1_mbedtls_psa_rsa_sign_hash(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_size, signature_length);
#elif defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
return mbedtls_psa_rsa_sign_hash(
attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_size, signature_length);
#endif
} else {
return PSA_ERROR_INVALID_ARGUMENT;
}
} else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) {
if (PSA_ALG_IS_ECDSA(alg)) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
(defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA))
return libtestdriver1_mbedtls_psa_ecdsa_sign_hash(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_size, signature_length);
#elif defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
return mbedtls_psa_ecdsa_sign_hash(
attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_size, signature_length);
#endif
} else {
return PSA_ERROR_INVALID_ARGUMENT;
}
}
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
(void) alg;
(void) hash;
(void) hash_length;
(void) signature;
(void) signature_size;
(void) signature_length;
return PSA_ERROR_NOT_SUPPORTED;
}
static psa_status_t verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *hash,
size_t hash_length,
const uint8_t *signature,
size_t signature_length)
{
if (PSA_KEY_TYPE_IS_RSA(attributes->type)) {
if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||
PSA_ALG_IS_RSA_PSS(alg)) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
(defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS))
return libtestdriver1_mbedtls_psa_rsa_verify_hash(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_length);
#elif defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
return mbedtls_psa_rsa_verify_hash(
attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_length);
#endif
} else {
return PSA_ERROR_INVALID_ARGUMENT;
}
} else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) {
if (PSA_ALG_IS_ECDSA(alg)) {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
(defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA))
return libtestdriver1_mbedtls_psa_ecdsa_verify_hash(
(const libtestdriver1_psa_key_attributes_t *) attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_length);
#elif defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
return mbedtls_psa_ecdsa_verify_hash(
attributes,
key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_length);
#endif
} else {
return PSA_ERROR_INVALID_ARGUMENT;
}
}
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
(void) alg;
(void) hash;
(void) hash_length;
(void) signature;
(void) signature_length;
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_transparent_signature_sign_message(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *signature,
size_t signature_size,
size_t *signature_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t hash_length;
uint8_t hash[PSA_HASH_MAX_SIZE];
++mbedtls_test_driver_signature_sign_hooks.hits;
if (mbedtls_test_driver_signature_sign_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_signature_sign_hooks.forced_status;
}
if (mbedtls_test_driver_signature_sign_hooks.forced_output != NULL) {
if (mbedtls_test_driver_signature_sign_hooks.forced_output_length > signature_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(signature, mbedtls_test_driver_signature_sign_hooks.forced_output,
mbedtls_test_driver_signature_sign_hooks.forced_output_length);
*signature_length = mbedtls_test_driver_signature_sign_hooks.forced_output_length;
return PSA_SUCCESS;
}
#if defined(TF_PSA_CRYPTO_PQCP_MLDSA_ENABLED)
/* Pure ML-DSA is not a sign-the-hash algorithm. At the moment, this
* function only knows how to deal with sign-the-hash algorithms.
* So give up and let the next driver in the chain handle the algorithm.
* For pure ML-DSA, this will be the pqcp driver, which does not have
* a libtestdriver1 variant, meaning that we can't test "driver-only"
* builds for pure ML-DSA, but we can have ML-DSA enabled in builds that
* dispatch through the test driver.
*/
if (PSA_ALG_IS_ML_DSA(alg)) {
return PSA_ERROR_NOT_SUPPORTED;
}
#endif
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
status = libtestdriver1_mbedtls_psa_hash_compute(
PSA_ALG_SIGN_GET_HASH(alg), input, input_length,
hash, sizeof(hash), &hash_length);
#elif defined(MBEDTLS_PSA_BUILTIN_HASH)
status = mbedtls_psa_hash_compute(
PSA_ALG_SIGN_GET_HASH(alg), input, input_length,
hash, sizeof(hash), &hash_length);
#else
(void) input;
(void) input_length;
status = PSA_ERROR_NOT_SUPPORTED;
#endif
if (status != PSA_SUCCESS) {
return status;
}
return sign_hash(attributes, key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_size, signature_length);
}
psa_status_t mbedtls_test_opaque_signature_sign_message(
const psa_key_attributes_t *attributes,
const uint8_t *key,
size_t key_length,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *signature,
size_t signature_size,
size_t *signature_length)
{
(void) attributes;
(void) key;
(void) key_length;
(void) alg;
(void) input;
(void) input_length;
(void) signature;
(void) signature_size;
(void) signature_length;
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_transparent_signature_verify_message(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
const uint8_t *signature,
size_t signature_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t hash_length;
uint8_t hash[PSA_HASH_MAX_SIZE];
++mbedtls_test_driver_signature_verify_hooks.hits;
if (mbedtls_test_driver_signature_verify_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_signature_verify_hooks.forced_status;
}
#if defined(TF_PSA_CRYPTO_PQCP_MLDSA_ENABLED)
/* Pure ML-DSA is not a sign-the-hash algorithm. At the moment, this
* function only knows how to deal with sign-the-hash algorithms.
* So give up and let the next driver in the chain handle the algorithm.
* For pure ML-DSA, this will be the pqcp driver, which does not have
* a libtestdriver1 variant, meaning that we can't test "driver-only"
* builds for pure ML-DSA, but we can have ML-DSA enabled in builds that
* dispatch through the test driver.
*/
if (PSA_ALG_IS_ML_DSA(alg)) {
return PSA_ERROR_NOT_SUPPORTED;
}
#endif
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH)
status = libtestdriver1_mbedtls_psa_hash_compute(
PSA_ALG_SIGN_GET_HASH(alg), input, input_length,
hash, sizeof(hash), &hash_length);
#elif defined(MBEDTLS_PSA_BUILTIN_HASH)
status = mbedtls_psa_hash_compute(
PSA_ALG_SIGN_GET_HASH(alg), input, input_length,
hash, sizeof(hash), &hash_length);
#else
(void) input;
(void) input_length;
status = PSA_ERROR_NOT_SUPPORTED;
#endif
if (status != PSA_SUCCESS) {
return status;
}
return verify_hash(attributes, key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_length);
}
psa_status_t mbedtls_test_opaque_signature_verify_message(
const psa_key_attributes_t *attributes,
const uint8_t *key,
size_t key_length,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
const uint8_t *signature,
size_t signature_length)
{
(void) attributes;
(void) key;
(void) key_length;
(void) alg;
(void) input;
(void) input_length;
(void) signature;
(void) signature_length;
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_transparent_signature_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length)
{
++mbedtls_test_driver_signature_sign_hooks.hits;
if (mbedtls_test_driver_signature_sign_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_signature_sign_hooks.forced_status;
}
if (mbedtls_test_driver_signature_sign_hooks.forced_output != NULL) {
if (mbedtls_test_driver_signature_sign_hooks.forced_output_length > signature_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(signature, mbedtls_test_driver_signature_sign_hooks.forced_output,
mbedtls_test_driver_signature_sign_hooks.forced_output_length);
*signature_length = mbedtls_test_driver_signature_sign_hooks.forced_output_length;
return PSA_SUCCESS;
}
return sign_hash(attributes, key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_size, signature_length);
}
psa_status_t mbedtls_test_opaque_signature_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg,
const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length)
{
(void) attributes;
(void) key;
(void) key_length;
(void) alg;
(void) hash;
(void) hash_length;
(void) signature;
(void) signature_size;
(void) signature_length;
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_test_transparent_signature_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length)
{
++mbedtls_test_driver_signature_verify_hooks.hits;
if (mbedtls_test_driver_signature_verify_hooks.forced_status != PSA_SUCCESS) {
return mbedtls_test_driver_signature_verify_hooks.forced_status;
}
return verify_hash(attributes, key_buffer, key_buffer_size,
alg, hash, hash_length,
signature, signature_length);
}
psa_status_t mbedtls_test_opaque_signature_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg,
const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length)
{
(void) attributes;
(void) key;
(void) key_length;
(void) alg;
(void) hash;
(void) hash_length;
(void) signature;
(void) signature_length;
return PSA_ERROR_NOT_SUPPORTED;
}
#endif /* PSA_CRYPTO_DRIVER_TEST */

View File

@@ -0,0 +1,163 @@
/*
* Test driver for xof entry points.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <test/helpers.h>
#if defined(PSA_ALG_CATEGORY_XOF) && defined(PSA_CRYPTO_DRIVER_TEST)
#include "psa_crypto_xof.h"
#include "test/drivers/xof.h"
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
#include LIBTESTDRIVER1_PSA_DRIVER_INTERNAL_HEADER(psa_crypto_xof.h)
#endif
mbedtls_test_driver_xof_hooks_t
mbedtls_test_driver_xof_hooks = MBEDTLS_TEST_DRIVER_XOF_INIT;
psa_status_t mbedtls_test_transparent_xof_setup(
mbedtls_transparent_test_driver_xof_operation_t *operation,
psa_algorithm_t alg)
{
mbedtls_test_driver_xof_hooks.hits++;
if (mbedtls_test_driver_xof_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_xof_hooks.driver_status =
mbedtls_test_driver_xof_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_XOF)
mbedtls_test_driver_xof_hooks.driver_status =
libtestdriver1_mbedtls_psa_xof_setup(operation, alg);
#elif defined(MBEDTLS_PSA_BUILTIN_XOF)
mbedtls_test_driver_xof_hooks.driver_status =
mbedtls_psa_xof_setup(operation, alg);
#else
(void) operation;
(void) alg;
mbedtls_test_driver_xof_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_xof_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_xof_set_context(
mbedtls_transparent_test_driver_xof_operation_t *operation,
const uint8_t *context, size_t context_length)
{
mbedtls_test_driver_xof_hooks.hits++;
if (mbedtls_test_driver_xof_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_xof_hooks.driver_status =
mbedtls_test_driver_xof_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_XOF)
mbedtls_test_driver_xof_hooks.driver_status =
libtestdriver1_mbedtls_psa_xof_set_context(
operation, context, context_length);
#elif defined(MBEDTLS_PSA_BUILTIN_XOF)
mbedtls_test_driver_xof_hooks.driver_status =
mbedtls_psa_xof_set_context(operation, context, context_length);
#else
(void) operation;
(void) context;
(void) context_length;
mbedtls_test_driver_xof_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_xof_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_xof_update(
mbedtls_transparent_test_driver_xof_operation_t *operation,
const uint8_t *input,
size_t input_length)
{
mbedtls_test_driver_xof_hooks.hits++;
if (mbedtls_test_driver_xof_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_xof_hooks.driver_status =
mbedtls_test_driver_xof_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_XOF)
mbedtls_test_driver_xof_hooks.driver_status =
libtestdriver1_mbedtls_psa_xof_update(
operation, input, input_length);
#elif defined(MBEDTLS_PSA_BUILTIN_XOF)
mbedtls_test_driver_xof_hooks.driver_status =
mbedtls_psa_xof_update(operation, input, input_length);
#else
(void) operation;
(void) input;
(void) input_length;
mbedtls_test_driver_xof_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_xof_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_xof_output(
mbedtls_transparent_test_driver_xof_operation_t *operation,
uint8_t *output, size_t output_length)
{
mbedtls_test_driver_xof_hooks.hits++;
if (mbedtls_test_driver_xof_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_xof_hooks.driver_status =
mbedtls_test_driver_xof_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_XOF)
mbedtls_test_driver_xof_hooks.driver_status =
libtestdriver1_mbedtls_psa_xof_output(
operation, output, output_length);
#elif defined(MBEDTLS_PSA_BUILTIN_XOF)
mbedtls_test_driver_xof_hooks.driver_status =
mbedtls_psa_xof_output(operation, output, output_length);
#else
(void) operation;
(void) output;
(void) output_length;
mbedtls_test_driver_xof_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_xof_hooks.driver_status;
}
psa_status_t mbedtls_test_transparent_xof_abort(
mbedtls_transparent_test_driver_xof_operation_t *operation)
{
mbedtls_test_driver_xof_hooks.hits++;
if (mbedtls_test_driver_xof_hooks.forced_status != PSA_SUCCESS) {
mbedtls_test_driver_xof_hooks.driver_status =
mbedtls_test_driver_xof_hooks.forced_status;
} else {
#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_XOF)
mbedtls_test_driver_xof_hooks.driver_status =
libtestdriver1_mbedtls_psa_xof_abort(operation);
#elif defined(MBEDTLS_PSA_BUILTIN_XOF)
mbedtls_test_driver_xof_hooks.driver_status =
mbedtls_psa_xof_abort(operation);
#else
(void) operation;
mbedtls_test_driver_xof_hooks.driver_status = PSA_ERROR_NOT_SUPPORTED;
#endif
}
return mbedtls_test_driver_xof_hooks.driver_status;
}
#endif /* PSA_CRYPTO_DRIVER_TEST && defined(PSA_ALG_CATEGORY_XOF) */

View File

@@ -0,0 +1,150 @@
/** \file fake_external_rng_for_test.c
*
* Helper functions to test external functions:
* - mbedtls_psa_external_get_random()
* - mbedtls_platform_get_entropy()
*
* These functions are provided only for test purposes and they should not be
* used for production.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "test_common.h"
#include <test/fake_external_rng_for_test.h>
#if defined(MBEDTLS_PSA_DRIVER_GET_ENTROPY)
#include <psa/crypto_driver_random.h>
#endif
#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
#include <test/random.h>
#include <psa/crypto.h>
static int test_insecure_external_rng_enabled = 0;
void mbedtls_test_enable_insecure_external_rng(void)
{
test_insecure_external_rng_enabled = 1;
}
void mbedtls_test_disable_insecure_external_rng(void)
{
test_insecure_external_rng_enabled = 0;
}
psa_status_t mbedtls_psa_external_get_random(
mbedtls_psa_external_random_context_t *context,
uint8_t *output, size_t output_size, size_t *output_length)
{
(void) context;
if (!test_insecure_external_rng_enabled) {
return PSA_ERROR_INSUFFICIENT_ENTROPY;
}
/* This implementation is for test purposes only!
* Use the libc non-cryptographic random generator. */
mbedtls_test_rnd_std_rand(NULL, output, output_size);
*output_length = output_size;
return PSA_SUCCESS;
}
#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
#if defined(MBEDTLS_PSA_DRIVER_GET_ENTROPY)
#include <test/random.h>
#if !defined(MBEDTLS_VERSION_MAJOR) || MBEDTLS_VERSION_MAJOR >= 4
#include <mbedtls/private/entropy.h>
#else
#include <mbedtls/entropy.h>
#endif
static int platform_get_entropy_force_failure;
static size_t platform_get_entropy_forced_entropy_content = SIZE_MAX;
static size_t platform_get_entropy_forced_output_len = SIZE_MAX;
static size_t platform_get_entropy_call_count;
void mbedtls_test_platform_get_entropy_reset(void)
{
platform_get_entropy_call_count = 0;
platform_get_entropy_force_failure = 0;
platform_get_entropy_forced_entropy_content = SIZE_MAX;
platform_get_entropy_forced_output_len = SIZE_MAX;
}
void mbedtls_test_platform_get_entropy_set_force_failure(int val)
{
platform_get_entropy_force_failure = (val != 0);
}
void mbedtls_test_platform_get_entropy_set_output_len(size_t val)
{
platform_get_entropy_forced_output_len = val;
}
void mbedtls_test_platform_get_entropy_set_entropy_content(size_t val)
{
platform_get_entropy_forced_entropy_content = val;
}
size_t mbedtls_test_platform_get_entropy_get_call_count(void)
{
return platform_get_entropy_call_count;
}
static int fake_get_entropy(unsigned char *output, size_t output_size,
size_t *estimate_bits)
{
platform_get_entropy_call_count++;
/* Return a failure if we were requested to. */
if (platform_get_entropy_force_failure != 0) {
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
/* Return less data than requested if we were requested to. */
if (platform_get_entropy_forced_output_len < SIZE_MAX) {
/* Prevent buffer overrun */
if (platform_get_entropy_forced_output_len > output_size) {
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
output_size = platform_get_entropy_forced_output_len;
}
mbedtls_test_rnd_std_rand(NULL, output, output_size);
if (estimate_bits != NULL) {
if (platform_get_entropy_forced_entropy_content < SIZE_MAX) {
*estimate_bits = platform_get_entropy_forced_entropy_content;
} else {
*estimate_bits = output_size * 8;
}
}
return 0;
}
#endif /* MBEDTLS_PSA_DRIVER_GET_ENTROPY */
#if defined(MBEDTLS_PSA_DRIVER_GET_ENTROPY)
int mbedtls_platform_get_entropy(psa_driver_get_entropy_flags_t flags,
size_t *estimate_bits,
unsigned char *output, size_t output_size)
{
/* We don't implement any flags yet. */
if (flags != 0) {
return PSA_ERROR_NOT_SUPPORTED;
}
int ret = fake_get_entropy(output, output_size, estimate_bits);
return ret;
}
#endif /* MBEDTLS_PSA_DRIVER_GET_ENTROPY */

View File

@@ -0,0 +1,244 @@
/** \file fork_helpers.c
*
* \brief Helper functions for testing with subprocesses.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "test_common.h"
#include <test/helpers.h>
#include <test/macros.h>
#if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE)
#include <test/fork_helpers.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
/** Child exit code for mbedtls_test_fork_run_child().
*/
typedef enum {
/** Reporting of the child output or the child test result through
* the pipe succeeded.
*
* The content sent on the pipe has the following format:
* - [1 byte] #mbedtls_test_result_t \c test_result
* - Case \c test_result:
* - If \c test_result == #MBEDTLS_TEST_RESULT_SUCCESS:
* the output from the child body function.
* - Otherwise:
* the child failure (or skip) information, a direct write of
* a #mbedtls_test_result_t structure.
*/
CHILD_EXIT_CODE_OK = 0,
/** Something went wrong, e.g. a write error on the pipe. */
CHILD_EXIT_CODE_REPORTING_FAILED = 122,
} child_exit_code_t;
static int env_contains_substring(const char *name, const char *substring)
{
const char *value = getenv(name);
if (value == NULL) {
return 0;
} else {
return strstr(value, substring) != NULL;
}
}
static int probably_running_under_valgrind(void)
{
if (env_contains_substring("LD_PRELOAD", "/vgpreload_")) {
return 1;
}
if (env_contains_substring("DYLD_INSERT_LIBRARIES", "/vgpreload_")) {
return 1;
}
return 0;
}
#if defined(__GNUC__)
__attribute__((__noreturn__))
#endif
static void run_child(
int write_fd,
mbedtls_test_fork_child_callback_t *child_callback,
void *param,
unsigned char *buf, size_t size)
{
/* If something goes wrong while trying to report what happened
* in the child, exit with a nonzero status. */
int child_exit_code = CHILD_EXIT_CODE_REPORTING_FAILED;
/* We'll use stdio to write to the pipe, so we don't have to
* manage EINTR and such. */
FILE *file = fdopen(write_fd, "a");
size_t length = 0;
if (file == NULL) {
/* There's no way we can report anything other than the exit code.
* So we might as well quit without even running the child callback. */
goto write_done;
}
child_callback(param, buf, size, &length);
TEST_LE_U(length, size);
/* Label called `exit`: this is where TEST_ASSERT() and friends jump to. */
exit:
; // label followed by a declaration is not portable C
char result_char = mbedtls_test_get_result();
if (fputc(result_char, file) == EOF) {
goto write_done;
}
if (result_char == MBEDTLS_TEST_RESULT_SUCCESS) {
if (fwrite(buf, length, 1, file) != 1) {
goto write_done;
}
} else {
mbedtls_test_info_t test_info;
mbedtls_test_info_save(&test_info);
if (fwrite(&test_info, sizeof(test_info), 1, file) != 1) {
goto write_done;
}
}
if (fflush(file) != 0) {
goto write_done;
}
child_exit_code = CHILD_EXIT_CODE_OK;
/* Label for `_exit()` call: this is where we jump to if the failure
* reporting fails. */
write_done:
/* We must call _exit(), not exit(), because the child must not run the
* things that normally run at exit.
*
* - Do not flush any stdio buffers! Any unflushed buffers are inherited
* from our parent, and if we flushed them, we'd get duplicate output
* since the parent would also write the same buffer content.
* - Do not run atexit hooks, e.g. leak detection code from sanitizers
* such as ASan. The child leaks any number of resources which are
* inherited from the parent but not used in the child. It's the
* parent's job to check for resource leaks.
* (We deliberately do not clean up in the child. One reason is that
* we try to minimize what happens in the child, because it's difficult
* to debug. Another reason is that we must not cause external effects
* such as destroying a PSA persistent key.)
*/
if (probably_running_under_valgrind()) {
/* Valgrind overloads _exit(), and this makes it do weird things,
* including an lseek() call to rewind the pointer on the file
* description for the `.datax` file, causing the same test cases
* to run again (or parse errors, depending on the exact amount
* of rewinding).
*
* Valgrind doesn't overload execve() and friends. So instead of
* _exit(), execute a shell command that returns the same status.
*/
char cmd[20];
snprintf(cmd, sizeof(cmd), "exit %d", child_exit_code);
execlp("sh", "sh", "-c", cmd, NULL);
}
_exit(child_exit_code);
}
int mbedtls_test_fork_run_child(
mbedtls_test_fork_child_callback_t *child_callback,
void *param,
unsigned char *child_output, size_t child_output_size,
size_t *child_output_length)
{
*child_output_length = 0;
int ret = -1;
pid_t pid = -1;
int pipe_fd[2] = { -1, -1 };
/* Set up a pipe. The child will write to pipe_fd[1], and the
* parent will read from pipe_fd[0]. */
TEST_ASSERT_ERRNO(pipe(pipe_fd) != -1);
pid = fork();
TEST_ASSERT_ERRNO(pid != -1);
if (pid == 0) {
/* The child code */
close(pipe_fd[0]);
run_child(pipe_fd[1], child_callback, param,
child_output, child_output_size);
/* Unreachable */
}
/* Beyond this point, we're in the parent (original) process. */
close(pipe_fd[1]);
pipe_fd[1] = -1;
unsigned char result_char;
struct {
mbedtls_test_info_t child_test_info;
unsigned char excess;
} reading_on_failure;
/* Normally, the child should give us a 1-byte result, then either
* the child body's output or a test info. */
ssize_t n = read(pipe_fd[0], &result_char, 1);
TEST_EQUAL(n, 1);
/* Tentatively read what we were promised. Don't commit to anything
* until we have the child's exit status. */
size_t bytes_read = 0;
if (result_char == MBEDTLS_TEST_RESULT_SUCCESS) {
do {
n = read(pipe_fd[0],
child_output + bytes_read,
child_output_size - bytes_read);
if (n > 0) {
bytes_read += n;
}
} while (n > 0 && bytes_read < child_output_size);
TEST_ASSERT_ERRNO(n != -1);
} else {
do {
n = read(pipe_fd[0],
(unsigned char *) &reading_on_failure + bytes_read,
sizeof(reading_on_failure) - bytes_read);
if (n > 0) {
bytes_read += n;
}
} while (n > 0 && bytes_read < sizeof(reading_on_failure));
TEST_ASSERT_ERRNO(n != -1);
/* Check that the child wrote the amount of data that what we expect. */
TEST_EQUAL(bytes_read, sizeof(reading_on_failure.child_test_info));
}
/* Close the pipe. If we left it open, there could be a deadlock if the
* child tried to write more than it should, while the parent is just
* waiting for the child to exit. */
close(pipe_fd[0]);
pipe_fd[0] = -1;
int wstatus;
TEST_ASSERT_ERRNO(waitpid(pid, &wstatus, 0) == pid);
if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == CHILD_EXIT_CODE_OK) {
if (result_char == MBEDTLS_TEST_RESULT_SUCCESS) {
*child_output_length = bytes_read;
ret = 0;
} else {
mbedtls_test_info_overwrite(&reading_on_failure.child_test_info);
}
} else {
/* Weird status, just report it. */
TEST_EQUAL(wstatus, 0);
}
exit:
close(pipe_fd[0]);
close(pipe_fd[1]);
return ret;
}
#endif /* MBEDTLS_PLATFORM_IS_UNIXLIKE */

View File

@@ -0,0 +1,783 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "test_common.h"
#include <test/constant_flow.h>
#include <test/helpers.h>
#include <test/macros.h>
#include <errno.h>
#include <string.h>
#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
#include <psa/crypto.h>
#include <test/psa_crypto_helpers.h>
#endif
#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C)
#include <test/psa_memory_poisoning_wrappers.h>
#endif
#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
#include <test/bignum_codepath_check.h>
#endif
#if defined(MBEDTLS_THREADING_C)
#include "mbedtls/threading.h"
#endif
/*----------------------------------------------------------------------------*/
/* Static global variables */
#if defined(MBEDTLS_PLATFORM_C)
static mbedtls_platform_context platform_ctx;
#endif
static mbedtls_test_info_t mbedtls_test_info;
#ifdef MBEDTLS_THREADING_C
mbedtls_threading_mutex_t mbedtls_test_info_mutex;
#endif /* MBEDTLS_THREADING_C */
/*----------------------------------------------------------------------------*/
/* Mbedtls Test Info accessors
*
* NOTE - there are two types of accessors here: public accessors and internal
* accessors. The public accessors have prototypes in helpers.h and lock
* mbedtls_test_info_mutex (if mutexes are enabled). The _internal accessors,
* which are expected to be used from this module *only*, do not lock the mutex.
* These are designed to be called from within public functions which already
* hold the mutex. The main reason for this difference is the need to set
* multiple test data values atomically (without releasing the mutex) to prevent
* race conditions. */
mbedtls_test_result_t mbedtls_test_get_result(void)
{
mbedtls_test_result_t result;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
result = mbedtls_test_info.result;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
return result;
}
static void mbedtls_test_set_result_internal(mbedtls_test_result_t result, const char *test,
int line_no, const char *filename)
{
/* Internal function only - mbedtls_test_info_mutex should be held prior
* to calling this function. */
mbedtls_test_info.result = result;
mbedtls_test_info.test = test;
mbedtls_test_info.line_no = line_no;
mbedtls_test_info.filename = filename;
}
const char *mbedtls_test_get_test(void)
{
const char *test;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
test = mbedtls_test_info.test;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
return test;
}
const char *mbedtls_get_test_filename(void)
{
const char *filename;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
/* It should be ok just to pass back the pointer here, as it is going to
* be a pointer into non changing data. */
filename = mbedtls_test_info.filename;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
return filename;
}
int mbedtls_test_get_line_no(void)
{
int line_no;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
line_no = mbedtls_test_info.line_no;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
return line_no;
}
void mbedtls_test_increment_step(void)
{
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
++mbedtls_test_info.step;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
}
unsigned long mbedtls_test_get_step(void)
{
unsigned long step;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
step = mbedtls_test_info.step;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
return step;
}
static void mbedtls_test_reset_step_internal(void)
{
/* Internal function only - mbedtls_test_info_mutex should be held prior
* to calling this function. */
mbedtls_test_info.step = (unsigned long) (-1);
}
void mbedtls_test_set_step(unsigned long step)
{
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
mbedtls_test_info.step = step;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
}
void mbedtls_test_get_line1(char *line)
{
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
memcpy(line, mbedtls_test_info.line1, MBEDTLS_TEST_LINE_LENGTH);
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
}
static void mbedtls_test_set_line1_internal(const char *line)
{
/* Internal function only - mbedtls_test_info_mutex should be held prior
* to calling this function. */
if (line == NULL) {
memset(mbedtls_test_info.line1, 0, MBEDTLS_TEST_LINE_LENGTH);
} else {
memcpy(mbedtls_test_info.line1, line, MBEDTLS_TEST_LINE_LENGTH);
}
}
void mbedtls_test_get_line2(char *line)
{
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
memcpy(line, mbedtls_test_info.line2, MBEDTLS_TEST_LINE_LENGTH);
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
}
static void mbedtls_test_set_line2_internal(const char *line)
{
/* Internal function only - mbedtls_test_info_mutex should be held prior
* to calling this function. */
if (line == NULL) {
memset(mbedtls_test_info.line2, 0, MBEDTLS_TEST_LINE_LENGTH);
} else {
memcpy(mbedtls_test_info.line2, line, MBEDTLS_TEST_LINE_LENGTH);
}
}
#if defined(MBEDTLS_TEST_MUTEX_USAGE)
const char *mbedtls_test_get_mutex_usage_error(void)
{
const char *usage_error;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
usage_error = mbedtls_test_info.mutex_usage_error;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
return usage_error;
}
void mbedtls_test_set_mutex_usage_error(const char *msg)
{
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
if (mbedtls_test_info.mutex_usage_error == NULL || msg == NULL) {
mbedtls_test_info.mutex_usage_error = msg;
}
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
}
#endif // #if defined(MBEDTLS_TEST_MUTEX_USAGE)
int mbedtls_test_buffer_is_all_zero(const uint8_t *buf, size_t size)
{
for (size_t i = 0; i < size; i++) {
if (buf[i] != 0) {
return 0;
}
}
return 1;
}
#if defined(MBEDTLS_BIGNUM_C)
unsigned mbedtls_test_get_case_uses_negative_0(void)
{
unsigned test_case_uses_negative_0 = 0;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
test_case_uses_negative_0 = mbedtls_test_info.case_uses_negative_0;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
return test_case_uses_negative_0;
}
static void mbedtls_test_set_case_uses_negative_0_internal(unsigned uses)
{
/* Internal function only - mbedtls_test_info_mutex should be held prior
* to calling this function. */
mbedtls_test_info.case_uses_negative_0 = uses;
}
void mbedtls_test_increment_case_uses_negative_0(void)
{
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
++mbedtls_test_info.case_uses_negative_0;
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
}
#endif /* MBEDTLS_BIGNUM_C */
#ifdef MBEDTLS_TEST_MUTEX_USAGE
mbedtls_threading_mutex_t *mbedtls_test_get_info_mutex(void)
{
return &mbedtls_test_info_mutex;
}
#endif /* MBEDTLS_TEST_MUTEX_USAGE */
/*----------------------------------------------------------------------------*/
/* Helper Functions */
int mbedtls_test_platform_setup(void)
{
int ret = 0;
#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C) \
&& !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) \
&& defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
mbedtls_poison_test_hooks_setup();
#endif
#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
/* Make sure that injected entropy is present. Otherwise
* psa_crypto_init() will fail. This is not necessary for test suites
* that don't use PSA, but it's harmless (except for leaving a file
* behind). */
ret = mbedtls_test_inject_entropy_restore();
if (ret != 0) {
return ret;
}
#endif
#if defined(MBEDTLS_PLATFORM_C)
ret = mbedtls_platform_setup(&platform_ctx);
#endif /* MBEDTLS_PLATFORM_C */
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_init(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
mbedtls_codepath_test_hooks_setup();
#endif /* MBEDTLS_TEST_HOOKS && !MBEDTLS_THREADING_C */
return ret;
}
void mbedtls_test_platform_teardown(void)
{
#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C) \
&& !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) \
&& defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
mbedtls_poison_test_hooks_teardown();
#endif
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_free(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
#if defined(MBEDTLS_PLATFORM_C)
mbedtls_platform_teardown(&platform_ctx);
#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
mbedtls_codepath_test_hooks_teardown();
#endif /* MBEDTLS_TEST_HOOKS && !MBEDTLS_THREADING_C */
}
int mbedtls_test_ascii2uc(const char c, unsigned char *uc)
{
if ((c >= '0') && (c <= '9')) {
*uc = c - '0';
} else if ((c >= 'a') && (c <= 'f')) {
*uc = c - 'a' + 10;
} else if ((c >= 'A') && (c <= 'F')) {
*uc = c - 'A' + 10;
} else {
return -1;
}
return 0;
}
static void mbedtls_test_fail_internal(const char *test, int line_no, const char *filename)
{
/* Internal function only - mbedtls_test_info_mutex should be held prior
* to calling this function. */
/* Don't use accessor, we already hold mutex. */
if (mbedtls_test_info.result != MBEDTLS_TEST_RESULT_FAILED) {
/* If we have already recorded the test as having failed then don't
* overwrite any previous information about the failure. */
mbedtls_test_set_result_internal(MBEDTLS_TEST_RESULT_FAILED, test, line_no, filename);
}
}
void mbedtls_test_fail(const char *test, int line_no, const char *filename)
{
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
mbedtls_test_fail_internal(test, line_no, filename);
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
}
void mbedtls_test_skip(const char *test, int line_no, const char *filename)
{
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
mbedtls_test_set_result_internal(MBEDTLS_TEST_RESULT_SKIPPED, test, line_no, filename);
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
}
void mbedtls_test_info_reset(void)
{
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
mbedtls_test_set_result_internal(MBEDTLS_TEST_RESULT_SUCCESS, 0, 0, 0);
mbedtls_test_reset_step_internal();
mbedtls_test_set_line1_internal(NULL);
mbedtls_test_set_line2_internal(NULL);
#if defined(MBEDTLS_BIGNUM_C)
mbedtls_test_set_case_uses_negative_0_internal(0);
#endif
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
}
void mbedtls_test_info_save(mbedtls_test_info_t *out)
{
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
memcpy(out, &mbedtls_test_info, sizeof(mbedtls_test_info));
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
}
void mbedtls_test_info_overwrite(const mbedtls_test_info_t *replacement)
{
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
memcpy(&mbedtls_test_info, replacement, sizeof(mbedtls_test_info));
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
}
int mbedtls_test_equal(const char *test, int line_no, const char *filename,
unsigned long long value1, unsigned long long value2)
{
TEST_CF_PUBLIC(&value1, sizeof(value1));
TEST_CF_PUBLIC(&value2, sizeof(value2));
if (value1 == value2) {
return 1;
}
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
/* Don't use accessor, as we already hold mutex. */
if (mbedtls_test_info.result != MBEDTLS_TEST_RESULT_FAILED) {
/* If we've already recorded the test as having failed then don't
* overwrite any previous information about the failure. */
char buf[MBEDTLS_TEST_LINE_LENGTH];
mbedtls_test_fail_internal(test, line_no, filename);
(void) mbedtls_snprintf(buf, sizeof(buf),
"lhs = 0x%016llx = %lld",
value1, (long long) value1);
mbedtls_test_set_line1_internal(buf);
(void) mbedtls_snprintf(buf, sizeof(buf),
"rhs = 0x%016llx = %lld",
value2, (long long) value2);
mbedtls_test_set_line2_internal(buf);
}
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
return 0;
}
int mbedtls_test_le_u(const char *test, int line_no, const char *filename,
unsigned long long value1, unsigned long long value2)
{
TEST_CF_PUBLIC(&value1, sizeof(value1));
TEST_CF_PUBLIC(&value2, sizeof(value2));
if (value1 <= value2) {
return 1;
}
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
/* Don't use accessor, we already hold mutex. */
if (mbedtls_test_info.result != MBEDTLS_TEST_RESULT_FAILED) {
/* If we've already recorded the test as having failed then don't
* overwrite any previous information about the failure. */
char buf[MBEDTLS_TEST_LINE_LENGTH];
mbedtls_test_fail_internal(test, line_no, filename);
(void) mbedtls_snprintf(buf, sizeof(buf),
"lhs = 0x%016llx = %llu",
value1, value1);
mbedtls_test_set_line1_internal(buf);
(void) mbedtls_snprintf(buf, sizeof(buf),
"rhs = 0x%016llx = %llu",
value2, value2);
mbedtls_test_set_line2_internal(buf);
}
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
return 0;
}
int mbedtls_test_le_s(const char *test, int line_no, const char *filename,
long long value1, long long value2)
{
TEST_CF_PUBLIC(&value1, sizeof(value1));
TEST_CF_PUBLIC(&value2, sizeof(value2));
if (value1 <= value2) {
return 1;
}
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
/* Don't use accessor, we already hold mutex. */
if (mbedtls_test_info.result != MBEDTLS_TEST_RESULT_FAILED) {
/* If we've already recorded the test as having failed then don't
* overwrite any previous information about the failure. */
char buf[MBEDTLS_TEST_LINE_LENGTH];
mbedtls_test_fail_internal(test, line_no, filename);
(void) mbedtls_snprintf(buf, sizeof(buf),
"lhs = 0x%016llx = %lld",
(unsigned long long) value1, value1);
mbedtls_test_set_line1_internal(buf);
(void) mbedtls_snprintf(buf, sizeof(buf),
"rhs = 0x%016llx = %lld",
(unsigned long long) value2, value2);
mbedtls_test_set_line2_internal(buf);
}
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
return 0;
}
void mbedtls_test_fail_errno(const char *test,
int line_no, const char *filename)
{
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_lock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
/* Don't use accessor, we already hold mutex. */
if (mbedtls_test_info.result != MBEDTLS_TEST_RESULT_FAILED) {
/* If we've already recorded the test as having failed then don't
* overwrite any previous information about the failure. */
char buf[MBEDTLS_TEST_LINE_LENGTH];
mbedtls_test_fail_internal(test, line_no, filename);
(void) mbedtls_snprintf(buf, sizeof(buf),
"errno = %d (%s)",
errno, strerror(errno));
mbedtls_test_set_line1_internal(buf);
}
#ifdef MBEDTLS_THREADING_C
mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
#endif /* MBEDTLS_THREADING_C */
}
int mbedtls_test_unhexify(unsigned char *obuf,
size_t obufmax,
const char *ibuf,
size_t *len)
{
unsigned char uc, uc2;
*len = strlen(ibuf);
/* Must be even number of bytes. */
if ((*len) & 1) {
return -1;
}
*len /= 2;
if ((*len) > obufmax) {
return -1;
}
while (*ibuf != 0) {
if (mbedtls_test_ascii2uc(*(ibuf++), &uc) != 0) {
return -1;
}
if (mbedtls_test_ascii2uc(*(ibuf++), &uc2) != 0) {
return -1;
}
*(obuf++) = (uc << 4) | uc2;
}
return 0;
}
void mbedtls_test_hexify(unsigned char *obuf,
const unsigned char *ibuf,
int len)
{
unsigned char l, h;
while (len != 0) {
h = *ibuf / 16;
l = *ibuf % 16;
if (h < 10) {
*obuf++ = '0' + h;
} else {
*obuf++ = 'a' + h - 10;
}
if (l < 10) {
*obuf++ = '0' + l;
} else {
*obuf++ = 'a' + l - 10;
}
++ibuf;
len--;
}
}
unsigned char *mbedtls_test_zero_alloc(size_t len)
{
void *p;
size_t actual_len = (len != 0) ? len : 1;
p = mbedtls_calloc(1, actual_len);
TEST_HELPER_ASSERT(p != NULL);
memset(p, 0x00, actual_len);
return p;
}
unsigned char *mbedtls_test_unhexify_alloc(const char *ibuf, size_t *olen)
{
unsigned char *obuf;
size_t len;
*olen = strlen(ibuf) / 2;
if (*olen == 0) {
return mbedtls_test_zero_alloc(*olen);
}
obuf = mbedtls_calloc(1, *olen);
TEST_HELPER_ASSERT(obuf != NULL);
TEST_HELPER_ASSERT(mbedtls_test_unhexify(obuf, *olen, ibuf, &len) == 0);
return obuf;
}
int mbedtls_test_hexcmp(uint8_t *a, uint8_t *b,
uint32_t a_len, uint32_t b_len)
{
int ret = 0;
uint32_t i = 0;
if (a_len != b_len) {
return -1;
}
for (i = 0; i < a_len; i++) {
if (a[i] != b[i]) {
ret = -1;
break;
}
}
return ret;
}
#if defined(MBEDTLS_TEST_HOOKS)
void mbedtls_test_err_add_check(int high, int low,
const char *file, int line)
{
/* Error codes are always negative (a value of zero is a success) however
* their positive opposites can be easier to understand. The following
* examples given in comments have been made positive for ease of
* understanding. The structure of an error code is such:
*
* shhhhhhhhlllllll
*
* s = sign bit.
* h = high level error code (includes high level module ID (bits 12..14)
* and module-dependent error code (bits 7..11)).
* l = low level error code.
*/
if (high > -0x1000 && high != 0) {
/* high < 0001000000000000
* No high level module ID bits are set.
*/
mbedtls_test_fail("'high' is not a high-level error code",
line, file);
} else if (high < -0x7F80) {
/* high > 0111111110000000
* Error code is greater than the largest allowed high level module ID.
*/
mbedtls_test_fail("'high' error code is greater than 15 bits",
line, file);
} else if ((high & 0x7F) != 0) {
/* high & 0000000001111111
* Error code contains low level error code bits.
*/
mbedtls_test_fail("'high' contains a low-level error code",
line, file);
} else if (low < -0x007F) {
/* low > 0000000001111111
* Error code contains high or module level error code bits.
*/
mbedtls_test_fail("'low' error code is greater than 7 bits",
line, file);
} else if (low > 0) {
mbedtls_test_fail("'low' error code is greater than zero",
line, file);
}
}
void (*mbedtls_test_hook_error_add)(int, int, const char *, int);
#endif /* MBEDTLS_TEST_HOOKS */

View File

@@ -0,0 +1,137 @@
/*
* Helper functions for PK.
* This is only for TF-PSA-Crypto 1.0 and above.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "test_common.h"
#include <test/macros.h>
#include <test/helpers.h>
#include <test/pk_helpers.h>
#include <test/psa_helpers.h>
#include <test/test_keys.h>
#include <mbedtls/pk.h>
#include "psa_util_internal.h"
/* Functions like mbedtls_pk_wrap_psa() are only available in tf-psa-crypto and
* not in 3.6 LTS branch, so we need a guard for this. */
#if TF_PSA_CRYPTO_VERSION_MAJOR >= 1
#if defined(MBEDTLS_PK_C)
typedef struct {
psa_key_type_t key_type;
psa_key_bits_t key_bits;
const uint8_t *key;
size_t key_len;
} mbedtls_pk_helpers_predefined_key_t;
#define EC_KEY(family_type, bits, array_base_name) \
{ PSA_KEY_TYPE_ECC_KEY_PAIR(family_type), bits, \
array_base_name ## _priv, sizeof(array_base_name ## _priv) }, \
{ PSA_KEY_TYPE_ECC_PUBLIC_KEY(family_type), bits, \
array_base_name ## _pub, sizeof(array_base_name ## _pub) }
#define RSA_KEY(bits, array_base_name) \
{ PSA_KEY_TYPE_RSA_KEY_PAIR, bits, \
array_base_name ## _priv, sizeof(array_base_name ## _priv) }, \
{ PSA_KEY_TYPE_RSA_PUBLIC_KEY, bits, \
array_base_name ## _pub, sizeof(array_base_name ## _pub) }
static mbedtls_pk_helpers_predefined_key_t predefined_keys_psa[] = {
EC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1, 256, test_ec_bp256r1),
EC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1, 384, test_ec_bp384r1),
EC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1, 512, test_ec_bp512r1),
EC_KEY(PSA_ECC_FAMILY_MONTGOMERY, 255, test_ec_curve25519),
EC_KEY(PSA_ECC_FAMILY_MONTGOMERY, 448, test_ec_curve448),
EC_KEY(PSA_ECC_FAMILY_SECP_K1, 256, test_ec_secp256k1),
EC_KEY(PSA_ECC_FAMILY_SECP_R1, 256, test_ec_secp256r1),
EC_KEY(PSA_ECC_FAMILY_SECP_R1, 384, test_ec_secp384r1),
EC_KEY(PSA_ECC_FAMILY_SECP_R1, 521, test_ec_secp521r1),
RSA_KEY(1024, test_rsa_1024),
RSA_KEY(1026, test_rsa_1026),
RSA_KEY(1028, test_rsa_1028),
RSA_KEY(1030, test_rsa_1030),
RSA_KEY(1536, test_rsa_1536),
RSA_KEY(2048, test_rsa_2048),
RSA_KEY(4096, test_rsa_4096),
};
int mbedtls_pk_helpers_get_predefined_key_data(psa_key_type_t key_type, psa_key_bits_t key_bits,
const uint8_t **output, size_t *output_len)
{
for (size_t i = 0; i < ARRAY_LENGTH(predefined_keys_psa); i++) {
if ((key_type == predefined_keys_psa[i].key_type) &&
(key_bits == predefined_keys_psa[i].key_bits)) {
*output = predefined_keys_psa[i].key;
*output_len = predefined_keys_psa[i].key_len;
return 0;
}
}
*output = NULL;
*output_len = 0;
TEST_FAIL("Predefined key not available");
exit:
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
}
mbedtls_svc_key_id_t mbedtls_pk_helpers_make_psa_key_from_predefined(psa_key_type_t key_type,
psa_key_bits_t key_bits,
psa_algorithm_t alg,
psa_algorithm_t alg2,
psa_key_usage_t usage_flags)
{
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
const uint8_t *key = NULL;
size_t key_len = 0;
mbedtls_pk_helpers_get_predefined_key_data(key_type, key_bits, &key, &key_len);
psa_set_key_type(&attr, key_type);
psa_set_key_usage_flags(&attr, usage_flags);
psa_set_key_algorithm(&attr, alg);
psa_set_key_enrollment_algorithm(&attr, alg2);
PSA_ASSERT(psa_import_key(&attr, key, key_len, &key_id));
exit:
return key_id;
}
int mbedtls_pk_helpers_populate_context(mbedtls_pk_context *pk, mbedtls_svc_key_id_t key_id,
pk_context_populate_method_t method)
{
int ret = -1;
switch (method) {
case TEST_PK_WRAP_PSA:
TEST_EQUAL(mbedtls_pk_wrap_psa(pk, key_id), 0);
break;
case TEST_PK_COPY_FROM_PSA:
TEST_EQUAL(mbedtls_pk_copy_from_psa(key_id, pk), 0);
break;
case TEST_PK_COPY_PUBLIC_FROM_PSA:
TEST_EQUAL(mbedtls_pk_copy_public_from_psa(key_id, pk), 0);
break;
default:
TEST_FAIL("Unknown population method");
}
ret = 0;
exit:
return ret;
}
#endif /* MBEDTLS_PK_C */
#endif /* !TF_PSA_CRYPTO_VERSION_MAJOR */

View File

@@ -0,0 +1,305 @@
/** \file psa_crypto_helpers.c
*
* \brief Helper functions to test PSA crypto functionality.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "test_common.h"
#include <test/helpers.h>
#include <test/macros.h>
#include <psa_crypto_slot_management.h>
#include <test/psa_crypto_helpers.h>
#if defined(MBEDTLS_CTR_DRBG_C)
#if !defined(MBEDTLS_VERSION_MAJOR) || MBEDTLS_VERSION_MAJOR >= 4
#include <mbedtls/private/ctr_drbg.h>
#else
#include <mbedtls/ctr_drbg.h>
#endif
#endif
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include <psa/crypto.h>
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
#include <psa_crypto_storage.h>
static mbedtls_svc_key_id_t key_ids_used_in_test[9];
static size_t num_key_ids_used;
int mbedtls_test_uses_key_id(mbedtls_svc_key_id_t key_id)
{
size_t i;
if (MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key_id) >
PSA_MAX_PERSISTENT_KEY_IDENTIFIER) {
/* Don't touch key id values that designate non-key files. */
return 1;
}
for (i = 0; i < num_key_ids_used; i++) {
if (mbedtls_svc_key_id_equal(key_id, key_ids_used_in_test[i])) {
return 1;
}
}
if (num_key_ids_used == ARRAY_LENGTH(key_ids_used_in_test)) {
return 0;
}
key_ids_used_in_test[num_key_ids_used] = key_id;
++num_key_ids_used;
return 1;
}
void mbedtls_test_psa_purge_key_storage(void)
{
size_t i;
for (i = 0; i < num_key_ids_used; i++) {
psa_destroy_persistent_key(key_ids_used_in_test[i]);
}
num_key_ids_used = 0;
}
void mbedtls_test_psa_purge_key_cache(void)
{
size_t i;
for (i = 0; i < num_key_ids_used; i++) {
psa_purge_key(key_ids_used_in_test[i]);
}
}
#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
const char *mbedtls_test_helper_is_psa_leaking(void)
{
mbedtls_psa_stats_t stats;
mbedtls_psa_get_stats(&stats);
/* Some volatile slots may be used for internal purposes. Generally
* we'll have exactly MBEDTLS_TEST_PSA_INTERNAL_KEYS at this point,
* but in some cases we might have less, e.g. if a code path calls
* PSA_DONE more than once, or if there has only been a partial or
* failed initialization. */
if (stats.volatile_slots > MBEDTLS_TEST_PSA_INTERNAL_KEYS) {
return "A volatile slot has not been closed properly.";
}
if (stats.persistent_slots != 0) {
return "A persistent slot has not been closed properly.";
}
if (stats.external_slots != 0) {
return "An external slot has not been closed properly.";
}
if (stats.half_filled_slots != 0) {
return "A half-filled slot has not been cleared properly.";
}
if (stats.locked_slots != 0) {
return "Some slots are still marked as locked.";
}
return NULL;
}
psa_hash_operation_t psa_hash_operation_init_short(void)
{
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
memset(&operation.ctx, '!', sizeof(operation.ctx));
return operation;
}
psa_mac_operation_t psa_mac_operation_init_short(void)
{
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
memset(&operation.ctx, '!', sizeof(operation.ctx));
return operation;
}
psa_cipher_operation_t psa_cipher_operation_init_short(void)
{
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
memset(&operation.ctx, '!', sizeof(operation.ctx));
return operation;
}
psa_aead_operation_t psa_aead_operation_init_short(void)
{
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
memset(&operation.ctx, '!', sizeof(operation.ctx));
return operation;
}
psa_key_derivation_operation_t psa_key_derivation_operation_init_short(void)
{
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
memset(&operation.ctx, '!', sizeof(operation.ctx));
return operation;
}
psa_pake_operation_t psa_pake_operation_init_short(void)
{
psa_pake_operation_t operation = PSA_PAKE_OPERATION_INIT;
memset(&operation.computation_stage, '!', sizeof(operation.computation_stage));
memset(&operation.data, '!', sizeof(operation.data));
return operation;
}
psa_sign_hash_interruptible_operation_t psa_sign_hash_interruptible_operation_init_short(void)
{
psa_sign_hash_interruptible_operation_t operation =
PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT;
memset(&operation.ctx, '!', sizeof(operation.ctx));
return operation;
}
psa_verify_hash_interruptible_operation_t psa_verify_hash_interruptible_operation_init_short(void)
{
psa_verify_hash_interruptible_operation_t operation =
PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT;
memset(&operation.ctx, '!', sizeof(operation.ctx));
return operation;
}
#if defined(PSA_KEY_AGREEMENT_IOP_INIT)
psa_key_agreement_iop_t psa_key_agreement_iop_init_short(void)
{
psa_key_agreement_iop_t operation = PSA_KEY_AGREEMENT_IOP_INIT;
/* No driver support, and thus no union, yet, at the time of writing */
return operation;
}
#endif
#if defined(PSA_GENERATE_KEY_IOP_INIT)
psa_generate_key_iop_t psa_generate_key_iop_init_short(void)
{
psa_generate_key_iop_t operation = PSA_GENERATE_KEY_IOP_INIT;
/* No driver support, and thus no union, yet, at the time of writing */
return operation;
}
#endif
#if defined(PSA_EXPORT_PUBLIC_KEY_IOP_INIT)
psa_export_public_key_iop_t psa_export_public_key_iop_init_short(void)
{
psa_export_public_key_iop_t operation = PSA_EXPORT_PUBLIC_KEY_IOP_INIT;
/* No driver support, and thus no union, yet, at the time of writing */
return operation;
}
#endif
#if defined(RECORD_PSA_STATUS_COVERAGE_LOG)
/** Name of the file where return statuses are logged by #RECORD_STATUS. */
#define STATUS_LOG_FILE_NAME "statuses.log"
psa_status_t mbedtls_test_record_status(psa_status_t status,
const char *func,
const char *file, int line,
const char *expr)
{
/* We open the log file on first use.
* We never close the log file, so the record_status feature is not
* compatible with resource leak detectors such as Asan.
*/
static FILE *log;
if (log == NULL) {
log = fopen(STATUS_LOG_FILE_NAME, "a");
}
fprintf(log, "%d:%s:%s:%d:%s\n", (int) status, func, file, line, expr);
return status;
}
#endif /* defined(RECORD_PSA_STATUS_COVERAGE_LOG) */
psa_key_usage_t mbedtls_test_update_key_usage_flags(psa_key_usage_t usage_flags)
{
psa_key_usage_t updated_usage = usage_flags;
if (usage_flags & PSA_KEY_USAGE_SIGN_HASH) {
updated_usage |= PSA_KEY_USAGE_SIGN_MESSAGE;
}
if (usage_flags & PSA_KEY_USAGE_VERIFY_HASH) {
updated_usage |= PSA_KEY_USAGE_VERIFY_MESSAGE;
}
return updated_usage;
}
int mbedtls_test_fail_if_psa_leaking(int line_no, const char *filename)
{
const char *msg = mbedtls_test_helper_is_psa_leaking();
if (msg == NULL) {
return 0;
} else {
mbedtls_test_fail(msg, line_no, filename);
return 1;
}
}
uint64_t mbedtls_test_parse_binary_string(data_t *bin_string)
{
uint64_t result = 0;
TEST_LE_U(bin_string->len, 8);
for (size_t i = 0; i < bin_string->len; i++) {
result = result << 8 | bin_string->x[i];
}
exit:
return result; /* returns 0 if len > 8 */
}
#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
#if !defined(MBEDTLS_VERSION_MAJOR) || MBEDTLS_VERSION_MAJOR >= 4
#include <mbedtls/private/entropy.h>
#else
#include <mbedtls/entropy.h>
#endif
#include <psa_crypto_its.h>
int mbedtls_test_inject_entropy_seed_read(unsigned char *buf, size_t len)
{
size_t actual_len = 0;
psa_status_t status = psa_its_get(PSA_CRYPTO_ITS_RANDOM_SEED_UID,
0, len, buf, &actual_len);
if (status != 0) {
return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
}
if (actual_len != len) {
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
return 0;
}
int mbedtls_test_inject_entropy_seed_write(unsigned char *buf, size_t len)
{
psa_status_t status = psa_its_set(PSA_CRYPTO_ITS_RANDOM_SEED_UID,
len, buf, 0);
if (status != 0) {
return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
}
return 0;
}
int mbedtls_test_inject_entropy_restore(void)
{
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
for (size_t i = 0; i < sizeof(buf); i++) {
buf[i] = (unsigned char) i;
}
psa_status_t status = mbedtls_psa_inject_entropy(buf, sizeof(buf));
/* It's ok if the file was just created, or if it already exists. */
if (status != PSA_SUCCESS && status != PSA_ERROR_NOT_PERMITTED) {
return status;
}
return PSA_SUCCESS;
}
#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
#endif /* MBEDTLS_PSA_CRYPTO_C */

View File

@@ -0,0 +1,134 @@
/** \file psa_crypto_stubs.c
*
* \brief Stub functions when MBEDTLS_PSA_CRYPTO_CLIENT is enabled but
* MBEDTLS_PSA_CRYPTO_C is disabled.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "test_common.h"
#include <psa/crypto.h>
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
psa_status_t psa_generate_random(uint8_t *output,
size_t output_size)
{
(void) output;
(void) output_size;
return PSA_ERROR_COMMUNICATION_FAILURE;
}
psa_status_t psa_export_key(mbedtls_svc_key_id_t key,
uint8_t *data,
size_t data_size,
size_t *data_length)
{
(void) key;
(void) data;
(void) data_size;
(void) data_length;
return PSA_ERROR_COMMUNICATION_FAILURE;
}
psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key,
uint8_t *data,
size_t data_size,
size_t *data_length)
{
(void) key;
(void) data;
(void) data_size;
(void) data_length;
return PSA_ERROR_COMMUNICATION_FAILURE;
}
psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key,
psa_key_attributes_t *attributes)
{
(void) key;
(void) attributes;
return PSA_ERROR_COMMUNICATION_FAILURE;
}
psa_status_t psa_hash_abort(psa_hash_operation_t *operation)
{
(void) operation;
return PSA_ERROR_COMMUNICATION_FAILURE;
}
psa_status_t psa_import_key(const psa_key_attributes_t *attributes,
const uint8_t *data,
size_t data_length,
mbedtls_svc_key_id_t *key)
{
(void) attributes;
(void) data;
(void) data_length;
(void) key;
return PSA_ERROR_COMMUNICATION_FAILURE;
}
int psa_can_do_hash(psa_algorithm_t hash_alg)
{
(void) hash_alg;
return 0;
}
psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation,
psa_hash_operation_t *target_operation)
{
(void) source_operation;
(void) target_operation;
return PSA_ERROR_COMMUNICATION_FAILURE;
}
psa_status_t psa_hash_setup(psa_hash_operation_t *operation,
psa_algorithm_t alg)
{
(void) operation;
(void) alg;
return PSA_ERROR_COMMUNICATION_FAILURE;
}
psa_status_t psa_hash_update(psa_hash_operation_t *operation,
const uint8_t *input_external,
size_t input_length)
{
(void) operation;
(void) input_external;
(void) input_length;
return PSA_ERROR_COMMUNICATION_FAILURE;
}
psa_status_t psa_hash_finish(psa_hash_operation_t *operation,
uint8_t *hash_external,
size_t hash_size,
size_t *hash_length)
{
(void) operation;
(void) hash_external;
(void) hash_size;
(void) hash_length;
return PSA_ERROR_COMMUNICATION_FAILURE;
}
psa_status_t psa_hash_compute(psa_algorithm_t alg,
const uint8_t *input_external, size_t input_length,
uint8_t *hash_external, size_t hash_size,
size_t *hash_length)
{
(void) alg;
(void) input_external;
(void) input_length;
(void) hash_external;
(void) hash_size;
(void) hash_length;
return PSA_ERROR_COMMUNICATION_FAILURE;
}
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT && !MBEDTLS_PSA_CRYPTO_C */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
/** Helper functions for memory poisoning in tests.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "test_common.h"
#include <test/memory.h>
#include <test/psa_memory_poisoning_wrappers.h>
#include "psa_crypto_invasive.h"
#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C) \
&& defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
void mbedtls_poison_test_hooks_setup(void)
{
psa_input_pre_copy_hook = mbedtls_test_memory_unpoison;
psa_input_post_copy_hook = mbedtls_test_memory_poison;
psa_output_pre_copy_hook = mbedtls_test_memory_unpoison;
psa_output_post_copy_hook = mbedtls_test_memory_poison;
}
void mbedtls_poison_test_hooks_teardown(void)
{
psa_input_pre_copy_hook = NULL;
psa_input_post_copy_hook = NULL;
psa_output_pre_copy_hook = NULL;
psa_output_post_copy_hook = NULL;
}
#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_PSA_CRYPTO_C &&
MBEDTLS_TEST_MEMORY_CAN_POISON */

View File

@@ -0,0 +1,141 @@
/**
* \file random.c
*
* \brief This file contains the helper functions to generate random numbers
* for the purpose of testing.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* for arc4random_buf() from <stdlib.h>
*/
#if defined(__NetBSD__)
#define _NETBSD_SOURCE 1
#elif defined(__OpenBSD__)
#define _BSD_SOURCE 1
#endif
#include "test_common.h"
#include <test/macros.h>
#include <test/random.h>
#include <string.h>
#if !defined(MBEDTLS_VERSION_MAJOR) || MBEDTLS_VERSION_MAJOR >= 4
#include <mbedtls/private/entropy.h>
#else
#include <mbedtls/entropy.h>
#endif
#include <alignment.h>
int mbedtls_test_rnd_std_rand(void *rng_state,
unsigned char *output,
size_t len)
{
#if !defined(__OpenBSD__) && !defined(__NetBSD__)
size_t i;
if (rng_state != NULL) {
rng_state = NULL;
}
for (i = 0; i < len; ++i) {
output[i] = rand();
}
#else
if (rng_state != NULL) {
rng_state = NULL;
}
arc4random_buf(output, len);
#endif /* !OpenBSD && !NetBSD */
return 0;
}
int mbedtls_test_rnd_zero_rand(void *rng_state,
unsigned char *output,
size_t len)
{
if (rng_state != NULL) {
rng_state = NULL;
}
memset(output, 0, len);
return 0;
}
int mbedtls_test_rnd_buffer_rand(void *rng_state,
unsigned char *output,
size_t len)
{
mbedtls_test_rnd_buf_info *info = (mbedtls_test_rnd_buf_info *) rng_state;
size_t use_len;
if (rng_state == NULL) {
return mbedtls_test_rnd_std_rand(NULL, output, len);
}
use_len = len;
if (len > info->length) {
use_len = info->length;
}
if (use_len) {
memcpy(output, info->buf, use_len);
info->buf += use_len;
info->length -= use_len;
}
if (len - use_len > 0) {
if (info->fallback_f_rng != NULL) {
return info->fallback_f_rng(info->fallback_p_rng,
output + use_len,
len - use_len);
} else {
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
}
return 0;
}
int mbedtls_test_rnd_pseudo_rand(void *rng_state,
unsigned char *output,
size_t len)
{
mbedtls_test_rnd_pseudo_info *info =
(mbedtls_test_rnd_pseudo_info *) rng_state;
uint32_t i, *k, sum, delta = 0x9E3779B9;
unsigned char result[4], *out = output;
if (rng_state == NULL) {
return mbedtls_test_rnd_std_rand(NULL, output, len);
}
k = info->key;
while (len > 0) {
size_t use_len = (len > 4) ? 4 : len;
sum = 0;
for (i = 0; i < 32; i++) {
info->v0 += (((info->v1 << 4) ^ (info->v1 >> 5))
+ info->v1) ^ (sum + k[sum & 3]);
sum += delta;
info->v1 += (((info->v0 << 4) ^ (info->v0 >> 5))
+ info->v0) ^ (sum + k[(sum>>11) & 3]);
}
MBEDTLS_PUT_UINT32_BE(info->v0, result, 0);
memcpy(out, result, use_len);
len -= use_len;
out += 4;
}
return 0;
}

View File

@@ -0,0 +1,55 @@
/**
* \file test_common.h
*
* \brief Common things for all Mbed TLS and TF-PSA-Crypto test code.
*
* Include this header first in all test C files.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef TEST_TEST_COMMON_H
#define TEST_TEST_COMMON_H
#if !defined(_POSIX_C_SOURCE)
/* For standards-compliant access to
* clock_gettime(), gmtime_r(), ...
*/
#define _POSIX_C_SOURCE 200112L
#endif
/* With GNU libc, define all the things, even when compiling with -pedantic. */
#if !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif
/* On Mingw-w64, force the use of a C99-compliant printf() and friends.
* This is necessary on older versions of Mingw and/or Windows runtimes
* where snprintf does not always zero-terminate the buffer, and does
* not support formats such as "%zu" for size_t and "%lld" for long long.
*/
#if !defined(__USE_MINGW_ANSI_STDIO)
#define __USE_MINGW_ANSI_STDIO 1
#endif
#if defined(__IAR_SYSTEMS_ICC__)
/* With IAR, enable support for ::FILE functions in stdio.h.
*/
#define _DLIB_FILE_DESCRIPTOR 1
#endif
/* Make sure we have the library configuration, and anything else that
* is deemed necessary in test headers. */
#include <test/build_info.h>
/* Give test code access to internal macros of the library. */
#if defined(TF_PSA_CRYPTO_VERSION_NUMBER)
#include "tf_psa_crypto_common.h"
#else
#include "common.h"
#endif
#endif /* TEST_TEST_COMMON_H */

View File

@@ -0,0 +1,61 @@
/**
* \file memory.c
*
* \brief Helper functions related to testing memory management.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "test_common.h"
#include <test/helpers.h>
#include <test/macros.h>
#include <test/memory.h>
#if defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
#include <sanitizer/asan_interface.h>
#include <stdint.h>
#endif
#if defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
_Thread_local unsigned int mbedtls_test_memory_poisoning_count = 0;
static void align_for_asan(const unsigned char **p_ptr, size_t *p_size)
{
uintptr_t start = (uintptr_t) *p_ptr;
uintptr_t end = start + (uintptr_t) *p_size;
/* ASan can only poison regions with 8-byte alignment, and only poisons a
* region if it's fully within the requested range. We want to poison the
* whole requested region and don't mind a few extra bytes. Therefore,
* align start down to an 8-byte boundary, and end up to an 8-byte
* boundary. */
start = start & ~(uintptr_t) 7;
end = (end + 7) & ~(uintptr_t) 7;
*p_ptr = (const unsigned char *) start;
*p_size = end - start;
}
void mbedtls_test_memory_poison(const unsigned char *ptr, size_t size)
{
if (mbedtls_test_memory_poisoning_count == 0) {
return;
}
if (size == 0) {
return;
}
align_for_asan(&ptr, &size);
__asan_poison_memory_region(ptr, size);
}
void mbedtls_test_memory_unpoison(const unsigned char *ptr, size_t size)
{
if (size == 0) {
return;
}
align_for_asan(&ptr, &size);
__asan_unpoison_memory_region(ptr, size);
}
#endif /* Memory poisoning */

View File

@@ -0,0 +1,409 @@
/** Mutex usage verification framework. */
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "test_common.h"
#include <test/helpers.h>
#include <test/threading_helpers.h>
#include <test/macros.h>
#include "threading_internal.h"
#if defined(MBEDTLS_THREADING_C)
#if defined(MBEDTLS_THREADING_PTHREAD)
static int threading_thread_create_pthread(mbedtls_test_thread_t *thread, void *(*thread_func)(
void *), void *thread_data)
{
if (thread == NULL || thread_func == NULL) {
return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA;
}
if (pthread_create(&thread->thread, NULL, thread_func, thread_data)) {
return MBEDTLS_ERR_THREADING_THREAD_ERROR;
}
return 0;
}
static int threading_thread_join_pthread(mbedtls_test_thread_t *thread)
{
if (thread == NULL) {
return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA;
}
if (pthread_join(thread->thread, NULL) != 0) {
return MBEDTLS_ERR_THREADING_THREAD_ERROR;
}
return 0;
}
int (*mbedtls_test_thread_create)(mbedtls_test_thread_t *thread, void *(*thread_func)(void *),
void *thread_data) = threading_thread_create_pthread;
int (*mbedtls_test_thread_join)(mbedtls_test_thread_t *thread) = threading_thread_join_pthread;
#endif /* MBEDTLS_THREADING_PTHREAD */
#if defined(MBEDTLS_THREADING_ALT)
static int threading_thread_create_fail(mbedtls_test_thread_t *thread,
void *(*thread_func)(void *),
void *thread_data)
{
(void) thread;
(void) thread_func;
(void) thread_data;
return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA;
}
static int threading_thread_join_fail(mbedtls_test_thread_t *thread)
{
(void) thread;
return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA;
}
int (*mbedtls_test_thread_create)(mbedtls_test_thread_t *thread, void *(*thread_func)(void *),
void *thread_data) = threading_thread_create_fail;
int (*mbedtls_test_thread_join)(mbedtls_test_thread_t *thread) = threading_thread_join_fail;
#endif /* MBEDTLS_THREADING_ALT */
#if defined(MBEDTLS_TEST_MUTEX_USAGE)
#include "mbedtls/threading.h"
/** Mutex usage verification framework.
*
* The mutex usage verification code below aims to detect bad usage of
* Mbed TLS's mutex abstraction layer at runtime. Note that this is solely
* about the use of the mutex itself, not about checking whether the mutex
* correctly protects whatever it is supposed to protect.
*
* The normal usage of a mutex is:
* ```
* digraph mutex_states {
* "UNINITIALIZED"; // the initial state
* "IDLE";
* "FREED";
* "LOCKED";
* "UNINITIALIZED" -> "IDLE" [label="init"];
* "FREED" -> "IDLE" [label="init"];
* "IDLE" -> "LOCKED" [label="lock"];
* "LOCKED" -> "IDLE" [label="unlock"];
* "IDLE" -> "FREED" [label="free"];
* }
* ```
*
* All bad transitions that can be unambiguously detected are reported.
* An attempt to use an uninitialized mutex cannot be detected in general
* since the memory content may happen to denote a valid state. For the same
* reason, a double init cannot be detected.
* All-bits-zero is the state of a freed mutex, which is distinct from an
* initialized mutex, so attempting to use zero-initialized memory as a mutex
* without calling the init function is detected.
*
* The framework attempts to detect missing calls to init and free by counting
* calls to init and free. If there are more calls to init than free, this
* means that a mutex is not being freed somewhere, which is a memory leak
* on platforms where a mutex consumes resources other than the
* mbedtls_threading_mutex_t object itself. If there are more calls to free
* than init, this indicates a missing init, which is likely to be detected
* by an attempt to lock the mutex as well. A limitation of this framework is
* that it cannot detect scenarios where there is exactly the same number of
* calls to init and free but the calls don't match. A bug like this is
* unlikely to happen uniformly throughout the whole test suite though.
*
* If an error is detected, this framework will report what happened and the
* test case will be marked as failed. Unfortunately, the error report cannot
* indicate the exact location of the problematic call. To locate the error,
* use a debugger and set a breakpoint on mbedtls_test_mutex_usage_error().
*/
enum value_of_mutex_state_field {
/* Potential values for the state field of mbedtls_threading_mutex_t.
* Note that MUTEX_FREED must be 0 and MUTEX_IDLE must be 1 for
* compatibility with threading_mutex_init_pthread() and
* threading_mutex_free_pthread(). MUTEX_LOCKED could be any nonzero
* value. */
MUTEX_FREED = 0, //! < Set by mbedtls_test_wrap_mutex_free
MUTEX_IDLE = 1, //! < Set by mbedtls_test_wrap_mutex_init and by mbedtls_test_wrap_mutex_unlock
MUTEX_LOCKED = 2, //! < Set by mbedtls_test_wrap_mutex_lock
};
#if MBEDTLS_THREADING_INTERNAL_VERSION < 0x04000000
/* Historically, the mutex functions in the API were function pointers.
* Since TF-PSA-Crypto 1.0.0 (paired with Mbed TLS 4.0.0), the API
* functions have the historical names but the pointers have different
* names. When building against Mbed TLS 3.6.x, define the pointer name
* as aliases. */
#define mbedtls_mutex_init_ptr mbedtls_mutex_init
#define mbedtls_mutex_free_ptr mbedtls_mutex_free
#define mbedtls_mutex_lock_ptr mbedtls_mutex_lock
#define mbedtls_mutex_unlock_ptr mbedtls_mutex_unlock
typedef mbedtls_threading_mutex_t mbedtls_platform_mutex_t;
#define mutex_container(platform_mutex) (platform_mutex)
#else /* MBEDTLS_THREADING_INTERNAL_VERSION >= 0x04000000 */
/* Historically, the mutex platform functions received a pointer to the
* mbedtls_threading_mutex_t object, and the pthread implementation of
* that type had a state field. Now the platform functions receive a pointer
* to the mbedtls_platform_mutex_t object which is a field of the
* mbedtls_threading_mutex_t object. Get a pointer to the containing
* object which holds the state field.
*
* This weird arrangement was done to minimize changes when switching the
* mutex usage framework to the separated platform/API types. In the future
* we should clean up how the usage framework fits into the library.
*/
static mbedtls_threading_mutex_t *mutex_container(
mbedtls_platform_mutex_t *platform_mutex)
{
unsigned char *field_address = (unsigned char *) platform_mutex;
size_t offset = offsetof(mbedtls_threading_mutex_t, mutex);
return (mbedtls_threading_mutex_t *) (field_address - offset);
}
#endif /* MBEDTLS_THREADING_INTERNAL_VERSION */
#if MBEDTLS_THREADING_INTERNAL_VERSION >= 0x04000001
typedef int mutex_init_return_t;
#else
typedef void mutex_init_return_t;
#endif
typedef struct {
mutex_init_return_t (*init)(mbedtls_platform_mutex_t *);
void (*free)(mbedtls_platform_mutex_t *);
int (*lock)(mbedtls_platform_mutex_t *);
int (*unlock)(mbedtls_platform_mutex_t *);
} mutex_functions_t;
static mutex_functions_t mutex_functions;
/**
* The mutex used to guard live_mutexes below and access to the status variable
* in every mbedtls_threading_mutex_t.
* Note that we are not reporting any errors when locking and unlocking this
* mutex. This is for a couple of reasons:
*
* 1. We have no real way of reporting any errors with this mutex - we cannot
* report it back to the caller, as the failure was not that of the mutex
* passed in. We could fail the test, but again this would indicate a problem
* with the test code that did not exist.
*
* 2. Any failure to lock is unlikely to be intermittent, and will thus not
* give false test results - the overall result would be to turn off the
* testing. This is not a situation that is likely to happen with normal
* testing and we still have TSan to fall back on should this happen.
*/
mbedtls_platform_mutex_t mbedtls_test_mutex_mutex;
/**
* The total number of calls to mbedtls_mutex_init(), minus the total number
* of calls to mbedtls_mutex_free().
*
* Do not read or write without holding mbedtls_test_mutex_mutex (above). Reset
* to 0 after each test case.
*/
static int live_mutexes;
static void mbedtls_test_mutex_usage_error(mbedtls_platform_mutex_t *mutex,
const char *msg)
{
(void) mutex;
mbedtls_test_set_mutex_usage_error(msg);
mbedtls_fprintf(stdout, "[mutex: %s] ", msg);
/* Don't mark the test as failed yet. This way, if the test fails later
* for a functional reason, the test framework will report the message
* and location for this functional reason. If the test passes,
* mbedtls_test_mutex_usage_check() will mark it as failed. */
}
static int mbedtls_test_mutex_can_test(mbedtls_platform_mutex_t *mutex)
{
/* If we attempt to run tests on this mutex then we are going to run into a
* couple of problems:
* 1. If any test on this mutex fails, we are going to deadlock when
* reporting that failure, as we already hold the mutex at that point.
* 2. Given the 'global' position of the initialization and free of this
* mutex, it will be shown as leaked on the first test run. */
if (mutex_container(mutex) == mbedtls_test_get_info_mutex()) {
return 0;
}
return 1;
}
static mutex_init_return_t mbedtls_test_wrap_mutex_init(mbedtls_platform_mutex_t *mutex)
{
#if MBEDTLS_THREADING_INTERNAL_VERSION >= 0x04000001
int ret = mutex_functions.init(mutex);
if (ret != 0) {
return ret;
}
#else
mutex_functions.init(mutex);
#endif
if (mbedtls_test_mutex_can_test(mutex)) {
if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) {
mutex_container(mutex)->state = MUTEX_IDLE;
++live_mutexes;
mutex_functions.unlock(&mbedtls_test_mutex_mutex);
}
}
#if MBEDTLS_THREADING_INTERNAL_VERSION >= 0x04000001
return 0;
#endif
}
static void mbedtls_test_wrap_mutex_free(mbedtls_platform_mutex_t *mutex)
{
if (mbedtls_test_mutex_can_test(mutex)) {
if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) {
switch (mutex_container(mutex)->state) {
case MUTEX_FREED:
mbedtls_test_mutex_usage_error(mutex, "free without init or double free");
break;
case MUTEX_IDLE:
mutex_container(mutex)->state = MUTEX_FREED;
--live_mutexes;
break;
case MUTEX_LOCKED:
mbedtls_test_mutex_usage_error(mutex, "free without unlock");
break;
default:
mbedtls_test_mutex_usage_error(mutex, "corrupted state");
break;
}
mutex_functions.unlock(&mbedtls_test_mutex_mutex);
}
}
mutex_functions.free(mutex);
}
static int mbedtls_test_wrap_mutex_lock(mbedtls_platform_mutex_t *mutex)
{
/* Lock the passed in mutex first, so that the only way to change the state
* is to hold the passed in and internal mutex - otherwise we create a race
* condition. */
int ret = mutex_functions.lock(mutex);
if (mbedtls_test_mutex_can_test(mutex)) {
if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) {
switch (mutex_container(mutex)->state) {
case MUTEX_FREED:
mbedtls_test_mutex_usage_error(mutex, "lock without init");
break;
case MUTEX_IDLE:
if (ret == 0) {
mutex_container(mutex)->state = MUTEX_LOCKED;
}
break;
case MUTEX_LOCKED:
mbedtls_test_mutex_usage_error(mutex, "double lock");
break;
default:
mbedtls_test_mutex_usage_error(mutex, "corrupted state");
break;
}
mutex_functions.unlock(&mbedtls_test_mutex_mutex);
}
}
return ret;
}
static int mbedtls_test_wrap_mutex_unlock(mbedtls_platform_mutex_t *mutex)
{
/* Lock the internal mutex first and change state, so that the only way to
* change the state is to hold the passed in and internal mutex - otherwise
* we create a race condition. */
if (mbedtls_test_mutex_can_test(mutex)) {
if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) {
switch (mutex_container(mutex)->state) {
case MUTEX_FREED:
mbedtls_test_mutex_usage_error(mutex, "unlock without init");
break;
case MUTEX_IDLE:
mbedtls_test_mutex_usage_error(mutex, "unlock without lock");
break;
case MUTEX_LOCKED:
mutex_container(mutex)->state = MUTEX_IDLE;
break;
default:
mbedtls_test_mutex_usage_error(mutex, "corrupted state");
break;
}
mutex_functions.unlock(&mbedtls_test_mutex_mutex);
}
}
return mutex_functions.unlock(mutex);
}
void mbedtls_test_mutex_usage_init(void)
{
mutex_functions.init = *mbedtls_mutex_init_ptr;
mutex_functions.free = *mbedtls_mutex_free_ptr;
mutex_functions.lock = *mbedtls_mutex_lock_ptr;
mutex_functions.unlock = *mbedtls_mutex_unlock_ptr;
mbedtls_mutex_init_ptr = &mbedtls_test_wrap_mutex_init;
mbedtls_mutex_free_ptr = &mbedtls_test_wrap_mutex_free;
mbedtls_mutex_lock_ptr = &mbedtls_test_wrap_mutex_lock;
mbedtls_mutex_unlock_ptr = &mbedtls_test_wrap_mutex_unlock;
mutex_functions.init(&mbedtls_test_mutex_mutex);
}
void mbedtls_test_mutex_usage_check(void)
{
if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) {
if (live_mutexes != 0) {
/* A positive number (more init than free) means that a mutex resource
* is leaking (on platforms where a mutex consumes more than the
* mbedtls_threading_mutex_t object itself). The (hopefully) rare
* case of a negative number means a missing init somewhere. */
mbedtls_fprintf(stdout, "[mutex: %d leaked] ", live_mutexes);
live_mutexes = 0;
mbedtls_test_set_mutex_usage_error("missing free");
}
if (mbedtls_test_get_mutex_usage_error() != NULL &&
mbedtls_test_get_result() != MBEDTLS_TEST_RESULT_FAILED) {
/* Functionally, the test passed. But there was a mutex usage error,
* so mark the test as failed after all. */
mbedtls_test_fail("Mutex usage error", __LINE__, __FILE__);
}
mbedtls_test_set_mutex_usage_error(NULL);
mutex_functions.unlock(&mbedtls_test_mutex_mutex);
}
}
void mbedtls_test_mutex_usage_end(void)
{
mbedtls_mutex_init_ptr = mutex_functions.init;
mbedtls_mutex_free_ptr = mutex_functions.free;
mbedtls_mutex_lock_ptr = mutex_functions.lock;
mbedtls_mutex_unlock_ptr = mutex_functions.unlock;
mutex_functions.free(&mbedtls_test_mutex_mutex);
}
#endif /* MBEDTLS_TEST_MUTEX_USAGE */
#endif /* MBEDTLS_THREADING_C */