/* * Common code library for SSL test programs. * * In addition to the functions in this file, there is shared source code * that cannot be compiled separately in "ssl_test_common_source.c". * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define MBEDTLS_ALLOW_PRIVATE_ACCESS #include "ssl_test_lib.h" #if defined(MBEDTLS_TEST_HOOKS) # include "test/helpers.h" #endif #if !defined(MBEDTLS_SSL_TEST_IMPOSSIBLE) void my_debug(void *ctx, int level, const char *file, int line, const char *str) { const char *p, *basename; /* Extract basename from file */ for (p = basename = file; *p != '\0'; p++) if (*p == '/' || *p == '\\') basename = p + 1; mbedtls_fprintf((FILE *)ctx, "%s:%04d: |%d| %s", basename, line, level, str); fflush((FILE *)ctx); } mbedtls_time_t dummy_constant_time(mbedtls_time_t *time) { (void)time; return 0x5af2a056; } # if !defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG) static int dummy_entropy(void *data, unsigned char *output, size_t len) { size_t i; int ret; (void)data; ret = mbedtls_entropy_func(data, output, len); for (i = 0; i < len; i++) { // replace result with pseudo random output[i] = (unsigned char)rand(); } return ret; } # endif void rng_init(rng_context_t *rng) { # if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG) (void)rng; psa_crypto_init(); # else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */ # if defined(MBEDTLS_CTR_DRBG_C) mbedtls_ctr_drbg_init(&rng->drbg); # elif defined(MBEDTLS_HMAC_DRBG_C) mbedtls_hmac_drbg_init(&rng->drbg); # else # error "No DRBG available" # endif mbedtls_entropy_init(&rng->entropy); # endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */ } int rng_seed(rng_context_t *rng, int reproducible, const char *pers) { # if defined(MBEDTLS_USE_PSA_CRYPTO) if (reproducible) { mbedtls_fprintf( stderr, "MBEDTLS_USE_PSA_CRYPTO does not support reproducible mode.\n"); return -1; } # endif # if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG) /* The PSA crypto RNG does its own seeding. */ (void)rng; (void)pers; if (reproducible) { mbedtls_fprintf(stderr, "The PSA RNG does not support reproducible mode.\n"); return -1; } return 0; # else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */ int (*f_entropy)(void *, unsigned char *, size_t) = (reproducible ? dummy_entropy : mbedtls_entropy_func); if (reproducible) srand(1); # if defined(MBEDTLS_CTR_DRBG_C) int ret = mbedtls_ctr_drbg_seed(&rng->drbg, f_entropy, &rng->entropy, (const unsigned char *)pers, strlen(pers)); # elif defined(MBEDTLS_HMAC_DRBG_C) # if defined(MBEDTLS_SHA256_C) const mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256; # elif defined(MBEDTLS_SHA512_C) const mbedtls_md_type_t md_type = MBEDTLS_MD_SHA512; # else # error "No message digest available for HMAC_DRBG" # endif int ret = mbedtls_hmac_drbg_seed(&rng->drbg, mbedtls_md_info_from_type(md_type), f_entropy, &rng->entropy, (const unsigned char *)pers, strlen(pers)); # else /* !defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_HMAC_DRBG_C) \ */ # error "No DRBG available" # endif /* !defined(MBEDTLS_CTR_DRBG_C) && \ !defined(MBEDTLS_HMAC_DRBG_C) */ if (ret != 0) { mbedtls_printf(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", (unsigned int)-ret); return ret; } # endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */ return 0; } void rng_free(rng_context_t *rng) { # if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG) (void)rng; /* Deinitialize the PSA crypto subsystem. This deactivates all PSA APIs. * This is ok because none of our applications try to do any crypto after * deinitializing the RNG. */ mbedtls_psa_crypto_free(); # else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */ # if defined(MBEDTLS_CTR_DRBG_C) mbedtls_ctr_drbg_free(&rng->drbg); # elif defined(MBEDTLS_HMAC_DRBG_C) mbedtls_hmac_drbg_free(&rng->drbg); # else # error "No DRBG available" # endif mbedtls_entropy_free(&rng->entropy); # endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */ } int rng_get(void *p_rng, unsigned char *output, size_t output_len) { # if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG) (void)p_rng; return ( mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, output, output_len)); # else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */ rng_context_t *rng = p_rng; # if defined(MBEDTLS_CTR_DRBG_C) return mbedtls_ctr_drbg_random(&rng->drbg, output, output_len); # elif defined(MBEDTLS_HMAC_DRBG_C) return mbedtls_hmac_drbg_random(&rng->drbg, output, output_len); # else # error "No DRBG available" # endif # endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */ } # if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) int ca_callback(void *data, mbedtls_x509_crt const *child, mbedtls_x509_crt **candidates) { int ret = 0; mbedtls_x509_crt *ca = (mbedtls_x509_crt *)data; mbedtls_x509_crt *first; /* This is a test-only implementation of the CA callback * which always returns the entire list of trusted certificates. * Production implementations managing a large number of CAs * should use an efficient presentation and lookup for the * set of trusted certificates (such as a hashtable) and only * return those trusted certificates which satisfy basic * parental checks, such as the matching of child `Issuer` * and parent `Subject` field or matching key identifiers. */ ((void)child); first = mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); if (first == NULL) { ret = -1; goto exit; } mbedtls_x509_crt_init(first); if (mbedtls_x509_crt_parse_der(first, ca->raw.p, ca->raw.len) != 0) { ret = -1; goto exit; } while (ca->next != NULL) { ca = ca->next; if (mbedtls_x509_crt_parse_der(first, ca->raw.p, ca->raw.len) != 0) { ret = -1; goto exit; } } exit: if (ret != 0) { mbedtls_x509_crt_free(first); mbedtls_free(first); first = NULL; } *candidates = first; return ret; } # endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ int delayed_recv(void *ctx, unsigned char *buf, size_t len) { static int first_try = 1; int ret; if (first_try) { first_try = 0; return MBEDTLS_ERR_SSL_WANT_READ; } ret = mbedtls_net_recv(ctx, buf, len); if (ret != MBEDTLS_ERR_SSL_WANT_READ) first_try = 1; /* Next call will be a new operation */ return ret; } int delayed_send(void *ctx, const unsigned char *buf, size_t len) { static int first_try = 1; int ret; if (first_try) { first_try = 0; return MBEDTLS_ERR_SSL_WANT_WRITE; } ret = mbedtls_net_send(ctx, buf, len); if (ret != MBEDTLS_ERR_SSL_WANT_WRITE) first_try = 1; /* Next call will be a new operation */ return ret; } # if !defined(MBEDTLS_TIMING_C) int idle(mbedtls_net_context *fd, int idle_reason) # else int idle(mbedtls_net_context *fd, mbedtls_timing_delay_context *timer, int idle_reason) # endif { int ret; int poll_type = 0; if (idle_reason == MBEDTLS_ERR_SSL_WANT_WRITE) poll_type = MBEDTLS_NET_POLL_WRITE; else if (idle_reason == MBEDTLS_ERR_SSL_WANT_READ) poll_type = MBEDTLS_NET_POLL_READ; # if !defined(MBEDTLS_TIMING_C) else return 0; # endif while (1) { /* Check if timer has expired */ # if defined(MBEDTLS_TIMING_C) if (timer != NULL && mbedtls_timing_get_delay(timer) == 2) { break; } # endif /* MBEDTLS_TIMING_C */ /* Check if underlying transport became available */ if (poll_type != 0) { ret = mbedtls_net_poll(fd, poll_type, 0); if (ret < 0) return ret; if (ret == poll_type) break; } } return 0; } # if defined(MBEDTLS_TEST_HOOKS) void test_hooks_init(void) { mbedtls_test_info_reset(); # if defined(MBEDTLS_TEST_MUTEX_USAGE) mbedtls_test_mutex_usage_init(); # endif } int test_hooks_failure_detected(void) { # if defined(MBEDTLS_TEST_MUTEX_USAGE) /* Errors are reported via mbedtls_test_info. */ mbedtls_test_mutex_usage_check(); # endif if (mbedtls_test_info.result != MBEDTLS_TEST_RESULT_SUCCESS) return 1; return 0; } void test_hooks_free(void) { } # endif /* MBEDTLS_TEST_HOOKS */ #endif /* !defined(MBEDTLS_SSL_TEST_IMPOSSIBLE) */