diff --git a/.github/workflows/test-psa-api.yml b/.github/workflows/test-psa-api.yml index e62a595..152a7ff 100644 --- a/.github/workflows/test-psa-api.yml +++ b/.github/workflows/test-psa-api.yml @@ -26,8 +26,8 @@ jobs: - name: Build sibling wolfSSL for wolfPSA tests run: make -C test rebuild-wolfssl-psa - - name: Build PSA API test - run: make -C test psa_api_test + - name: Build PSA API tests + run: make -C test psa_api_test psa_des3_stack_scrub_test psa_ecc_bit_inference_test psa_ecc_curve_id_test psa_random_size_test - name: Run PSA API test env: @@ -35,3 +35,31 @@ jobs: run: | rm -rf test/.store ./test/psa_api_test + + - name: Run ECC bit inference test + env: + LD_LIBRARY_PATH: ${{ github.workspace }}:${{ github.workspace }}/../wolfssl/src/.libs + run: | + rm -rf test/.store + ./test/psa_ecc_bit_inference_test + + - name: Run DES3 stack scrub test + env: + LD_LIBRARY_PATH: ${{ github.workspace }}:${{ github.workspace }}/../wolfssl/src/.libs + run: | + rm -rf test/.store + ./test/psa_des3_stack_scrub_test + + - name: Run ECC curve id test + env: + LD_LIBRARY_PATH: ${{ github.workspace }}:${{ github.workspace }}/../wolfssl/src/.libs + run: | + rm -rf test/.store + ./test/psa_ecc_curve_id_test + + - name: Run random size test + env: + LD_LIBRARY_PATH: ${{ github.workspace }}:${{ github.workspace }}/../wolfssl/src/.libs + run: | + rm -rf test/.store + ./test/psa_random_size_test diff --git a/.gitignore b/.gitignore index d3685c1..08803db 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,12 @@ test-psa-api/psa-arch-tests libwolfpsa.so *.o test/psa_api_test +test/psa_ecc_bit_inference_test +test/psa_ecc_curve_id_test test/psa_tls_server +test/psa_des3_stack_scrub_test +test/psa_random_size_test +test/psa_rsa_pss_interop_test psa_server/tls_client/psa_tls_client psa_tls_client wolfcrypt-benchmark/wolfcrypt-psa-benchmark diff --git a/src/psa_aead.c b/src/psa_aead.c index 9ef5222..de456d3 100644 --- a/src/psa_aead.c +++ b/src/psa_aead.c @@ -33,32 +33,11 @@ #include #include #include - -typedef struct wolfpsa_aead_ctx { - psa_algorithm_t alg; - psa_key_type_t key_type; - size_t key_bits; - int direction; - uint8_t *key; - size_t key_length; - uint8_t nonce[PSA_AEAD_NONCE_MAX_SIZE]; - size_t nonce_length; - uint8_t *aad; - size_t aad_length; - uint8_t *input; - size_t input_length; - size_t ad_expected; - size_t plaintext_expected; - size_t tag_length; - int lengths_set; -} wolfpsa_aead_ctx_t; +#include "psa_aead_internal.h" static wolfpsa_aead_ctx_t* wolfpsa_aead_get_ctx(psa_aead_operation_t *operation) { - if (operation == NULL) { - return NULL; - } - return (wolfpsa_aead_ctx_t *)(uintptr_t)operation->opaque; + return wolfpsa_aead_get_ctx_ptr(operation); } static psa_status_t wolfpsa_aead_append(uint8_t **buf, size_t *len, @@ -124,7 +103,7 @@ static psa_status_t wolfpsa_aead_check_key(psa_key_id_t key, if (PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_GCM) || PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CCM)) { if (attributes->type != PSA_KEY_TYPE_AES) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_INVALID_ARGUMENT; @@ -132,14 +111,14 @@ static psa_status_t wolfpsa_aead_check_key(psa_key_id_t key, } else if (PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CHACHA20_POLY1305)) { if (attributes->type != PSA_KEY_TYPE_CHACHA20) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_INVALID_ARGUMENT; } } else { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_SUPPORTED; @@ -147,7 +126,7 @@ static psa_status_t wolfpsa_aead_check_key(psa_key_id_t key, key_usage = psa_get_key_usage_flags(attributes); if ((key_usage & usage) == 0) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_PERMITTED; @@ -161,14 +140,14 @@ static psa_status_t wolfpsa_aead_check_key(psa_key_id_t key, req_tag_len = wolfpsa_aead_tag_length(alg); if (key_tag_len == 0 || req_tag_len == 0) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_INVALID_ARGUMENT; } if (key_base != req_base) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_PERMITTED; @@ -176,14 +155,14 @@ static psa_status_t wolfpsa_aead_check_key(psa_key_id_t key, if ((key_alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) { if (req_tag_len < key_tag_len) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_PERMITTED; } } else if (req_tag_len != key_tag_len) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_PERMITTED; @@ -224,7 +203,7 @@ static psa_status_t wolfpsa_aead_setup(psa_aead_operation_t *operation, ctx = (wolfpsa_aead_ctx_t *)XMALLOC(sizeof(*ctx), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (ctx == NULL) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INSUFFICIENT_MEMORY; } XMEMSET(ctx, 0, sizeof(*ctx)); @@ -234,14 +213,14 @@ static psa_status_t wolfpsa_aead_setup(psa_aead_operation_t *operation, ctx->key_bits = attributes.bits; ctx->tag_length = wolfpsa_aead_tag_length(alg); if (ctx->tag_length == 0) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); return PSA_ERROR_INVALID_ARGUMENT; } ctx->direction = (usage == PSA_KEY_USAGE_ENCRYPT) ? 1 : 0; if (PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CCM) && wc_AesCcmCheckTagSize((int)ctx->tag_length) != 0) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); return PSA_ERROR_INVALID_ARGUMENT; } @@ -249,14 +228,14 @@ static psa_status_t wolfpsa_aead_setup(psa_aead_operation_t *operation, ctx->key = (uint8_t *)XMALLOC(key_data_length, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (ctx->key == NULL) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); return PSA_ERROR_INSUFFICIENT_MEMORY; } XMEMCPY(ctx->key, key_data, key_data_length); ctx->key_length = key_data_length; - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); operation->opaque = (uintptr_t)ctx; return PSA_SUCCESS; } @@ -398,7 +377,8 @@ psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, return PSA_ERROR_BAD_STATE; } if (ctx->lengths_set && - ctx->aad_length + input_length > ctx->ad_expected) { + (input_length > SIZE_MAX - ctx->aad_length || + ctx->aad_length + input_length > ctx->ad_expected)) { status = PSA_ERROR_INVALID_ARGUMENT; psa_aead_abort(operation); return status; @@ -443,7 +423,8 @@ psa_status_t psa_aead_update(psa_aead_operation_t *operation, return status; } if (ctx->lengths_set && - ctx->input_length + input_length > ctx->plaintext_expected) { + (input_length > SIZE_MAX - ctx->input_length || + ctx->input_length + input_length > ctx->plaintext_expected)) { status = PSA_ERROR_INVALID_ARGUMENT; psa_aead_abort(operation); return status; diff --git a/src/psa_aead_internal.h b/src/psa_aead_internal.h new file mode 100644 index 0000000..1f71f54 --- /dev/null +++ b/src/psa_aead_internal.h @@ -0,0 +1,37 @@ +#ifndef WOLFPSA_PSA_AEAD_INTERNAL_H +#define WOLFPSA_PSA_AEAD_INTERNAL_H + +#include + +#include + +typedef struct wolfpsa_aead_ctx { + psa_algorithm_t alg; + psa_key_type_t key_type; + size_t key_bits; + int direction; + uint8_t *key; + size_t key_length; + uint8_t nonce[PSA_AEAD_NONCE_MAX_SIZE]; + size_t nonce_length; + uint8_t *aad; + size_t aad_length; + uint8_t *input; + size_t input_length; + size_t ad_expected; + size_t plaintext_expected; + size_t tag_length; + int lengths_set; +} wolfpsa_aead_ctx_t; + +static inline wolfpsa_aead_ctx_t* +wolfpsa_aead_get_ctx_ptr(psa_aead_operation_t *operation) +{ + if (operation == NULL) { + return NULL; + } + + return (wolfpsa_aead_ctx_t *)(uintptr_t)operation->opaque; +} + +#endif /* WOLFPSA_PSA_AEAD_INTERNAL_H */ diff --git a/src/psa_asymmetric.c b/src/psa_asymmetric.c index c7d1e39..5d626d8 100644 --- a/src/psa_asymmetric.c +++ b/src/psa_asymmetric.c @@ -655,10 +655,18 @@ int wc_psa_get_ecc_curve_id(psa_key_type_t type, size_t bits) case PSA_ECC_FAMILY_SECP_R1: switch (bits) { case 192: + #ifdef HAVE_ECC192 + return ECC_SECP192R1; + #else return ECC_CURVE_INVALID; + #endif case 224: + #ifdef HAVE_ECC224 + return ECC_SECP224R1; + #else return ECC_CURVE_INVALID; + #endif case 256: return ECC_SECP256R1; @@ -676,10 +684,18 @@ int wc_psa_get_ecc_curve_id(psa_key_type_t type, size_t bits) case PSA_ECC_FAMILY_SECP_K1: switch (bits) { case 192: + #if defined(HAVE_ECC192) && defined(HAVE_ECC_KOBLITZ) + return ECC_SECP192K1; + #else return ECC_CURVE_INVALID; + #endif case 224: + #if defined(HAVE_ECC224) && defined(HAVE_ECC_KOBLITZ) + return ECC_SECP224K1; + #else return ECC_CURVE_INVALID; + #endif case 256: return ECC_SECP256K1; diff --git a/src/psa_asymmetric_api.c b/src/psa_asymmetric_api.c index 649eac9..f22a71a 100644 --- a/src/psa_asymmetric_api.c +++ b/src/psa_asymmetric_api.c @@ -160,7 +160,7 @@ static psa_status_t wolfpsa_asymmetric_check_key(psa_key_id_t key, key_usage = psa_get_key_usage_flags(attributes); if ((key_usage & usage) == 0) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_PERMITTED; @@ -171,14 +171,14 @@ static psa_status_t wolfpsa_asymmetric_check_key(psa_key_id_t key, if (PSA_ALG_IS_KEY_AGREEMENT(alg) && PSA_ALG_IS_KEY_AGREEMENT(key_alg)) { if (PSA_ALG_KEY_AGREEMENT_GET_BASE(key_alg) != PSA_ALG_KEY_AGREEMENT_GET_BASE(alg)) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_PERMITTED; } } else if (key_alg != alg) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_PERMITTED; @@ -215,7 +215,7 @@ psa_status_t psa_asymmetric_encrypt(psa_key_id_t key, if (PSA_KEY_TYPE_IS_RSA(attributes.type)) { if (output == NULL) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INVALID_ARGUMENT; } status = psa_asymmetric_encrypt_rsa(attributes.type, attributes.bits, @@ -229,7 +229,7 @@ psa_status_t psa_asymmetric_encrypt(psa_key_id_t key, PSA_ERROR_NOT_SUPPORTED : PSA_ERROR_INVALID_ARGUMENT; } - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return status; } @@ -260,7 +260,7 @@ psa_status_t psa_asymmetric_decrypt(psa_key_id_t key, if (PSA_KEY_TYPE_IS_RSA(attributes.type)) { if (output == NULL) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INVALID_ARGUMENT; } status = psa_asymmetric_decrypt_rsa(attributes.type, attributes.bits, @@ -274,7 +274,7 @@ psa_status_t psa_asymmetric_decrypt(psa_key_id_t key, PSA_ERROR_NOT_SUPPORTED : PSA_ERROR_INVALID_ARGUMENT; } - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return status; } @@ -348,7 +348,7 @@ psa_status_t psa_sign_hash(psa_key_id_t key, status = PSA_ERROR_NOT_SUPPORTED; } - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return status; } @@ -417,7 +417,7 @@ psa_status_t psa_verify_hash(psa_key_id_t key, status = PSA_ERROR_NOT_SUPPORTED; } - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return status; } @@ -451,7 +451,7 @@ psa_status_t psa_sign_message(psa_key_id_t key, hash_alg = 0; hash_length = input_length; if (hash_length > sizeof(hash)) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INVALID_ARGUMENT; } XMEMCPY(hash, input, hash_length); @@ -459,14 +459,14 @@ psa_status_t psa_sign_message(psa_key_id_t key, else { hash_alg = PSA_ALG_SIGN_GET_HASH(alg); if (hash_alg == 0) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_NOT_SUPPORTED; } status = psa_hash_compute(hash_alg, input, input_length, hash, sizeof(hash), &hash_length); if (status != PSA_SUCCESS) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return status; } } @@ -516,7 +516,7 @@ psa_status_t psa_sign_message(psa_key_id_t key, status = PSA_ERROR_NOT_SUPPORTED; } - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return status; } @@ -549,7 +549,7 @@ psa_status_t psa_verify_message(psa_key_id_t key, hash_alg = 0; hash_length = input_length; if (hash_length > sizeof(hash)) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INVALID_ARGUMENT; } XMEMCPY(hash, input, hash_length); @@ -557,14 +557,14 @@ psa_status_t psa_verify_message(psa_key_id_t key, else { hash_alg = PSA_ALG_SIGN_GET_HASH(alg); if (hash_alg == 0) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_NOT_SUPPORTED; } status = psa_hash_compute(hash_alg, input, input_length, hash, sizeof(hash), &hash_length); if (status != PSA_SUCCESS) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return status; } } @@ -610,7 +610,7 @@ psa_status_t psa_verify_message(psa_key_id_t key, status = PSA_ERROR_NOT_SUPPORTED; } - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return status; } @@ -652,13 +652,13 @@ psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, } if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes.type)) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INVALID_ARGUMENT; } curve_id = wc_psa_get_ecc_curve_id(attributes.type, attributes.bits); if (curve_id == ECC_CURVE_INVALID) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_NOT_SUPPORTED; } @@ -668,17 +668,17 @@ psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, expected_secret_len = PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(attributes.type, attributes.bits); if (expected_secret_len == 0) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_NOT_SUPPORTED; } if (output_size < expected_secret_len) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_BUFFER_TOO_SMALL; } } if (peer_key == NULL && peer_key_length > 0) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INVALID_ARGUMENT; } { @@ -687,20 +687,20 @@ psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, if (peer_key_length != expected_peer_len || peer_key[0] != 0x04) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INVALID_ARGUMENT; } } ret = wc_ecc_init(&priv); if (ret != 0) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return wc_error_to_psa_status(ret); } ret = wc_ecc_init(&pub); if (ret != 0) { wc_ecc_free(&priv); - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return wc_error_to_psa_status(ret); } @@ -715,7 +715,7 @@ psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, if (ret != 0) { wc_ecc_free(&pub); wc_ecc_free(&priv); - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return wc_error_to_psa_status(ret); } @@ -723,7 +723,7 @@ psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, ret = wc_ecc_shared_secret(&priv, &pub, output, &out_len); wc_ecc_free(&pub); wc_ecc_free(&priv); - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); if (ret != 0) { return wc_error_to_psa_status(ret); } @@ -775,6 +775,7 @@ psa_status_t psa_key_agreement(psa_key_id_t private_key, status = psa_raw_key_agreement(alg, private_key, peer_key, peer_key_length, secret, secret_len, &output_len); if (status != PSA_SUCCESS) { + wc_ForceZero(secret, secret_len); XFREE(secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); return status; } @@ -785,22 +786,26 @@ psa_status_t psa_key_agreement(psa_key_id_t private_key, if (out_type != PSA_KEY_TYPE_DERIVE && out_type != PSA_KEY_TYPE_RAW_DATA) { + wc_ForceZero(secret, secret_len); XFREE(secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); return PSA_ERROR_INVALID_ARGUMENT; } status = psa_import_key(attributes, secret, output_len, key); + wc_ForceZero(secret, secret_len); XFREE(secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); return status; } status = psa_key_derivation_setup(&kdf_op, kdf_alg); if (status != PSA_SUCCESS) { + wc_ForceZero(secret, secret_len); XFREE(secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); return status; } status = psa_key_derivation_input_bytes(&kdf_op, PSA_KEY_DERIVATION_INPUT_SECRET, secret, output_len); + wc_ForceZero(secret, secret_len); XFREE(secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (status != PSA_SUCCESS) { psa_key_derivation_abort(&kdf_op); diff --git a/src/psa_cipher.c b/src/psa_cipher.c index 15994b7..534468d 100644 --- a/src/psa_cipher.c +++ b/src/psa_cipher.c @@ -138,7 +138,7 @@ static psa_status_t wolfpsa_cipher_check_key( if (alg == PSA_ALG_STREAM_CIPHER) { if (attributes->type != PSA_KEY_TYPE_CHACHA20) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_SUPPORTED; @@ -146,7 +146,7 @@ static psa_status_t wolfpsa_cipher_check_key( } else if (attributes->type == PSA_KEY_TYPE_DES) { if (alg != PSA_ALG_CBC_NO_PADDING && alg != PSA_ALG_ECB_NO_PADDING) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_SUPPORTED; @@ -154,7 +154,7 @@ static psa_status_t wolfpsa_cipher_check_key( } else { if (attributes->type != PSA_KEY_TYPE_AES) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_SUPPORTED; @@ -163,7 +163,7 @@ static psa_status_t wolfpsa_cipher_check_key( key_usage = psa_get_key_usage_flags(attributes); if ((key_usage & usage) == 0) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_PERMITTED; @@ -171,7 +171,7 @@ static psa_status_t wolfpsa_cipher_check_key( key_alg = psa_get_key_algorithm(attributes); if (key_alg != PSA_ALG_NONE && key_alg != alg) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_PERMITTED; @@ -179,13 +179,13 @@ static psa_status_t wolfpsa_cipher_check_key( if (attributes->type == PSA_KEY_TYPE_CHACHA20) { if (*key_data_length != CHACHA_MAX_KEY_SZ) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_INVALID_ARGUMENT; } if (attributes->bits != 256) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_INVALID_ARGUMENT; @@ -195,14 +195,14 @@ static psa_status_t wolfpsa_cipher_check_key( if (attributes->type == PSA_KEY_TYPE_DES) { if (*key_data_length != 16 && *key_data_length != 24) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_INVALID_ARGUMENT; } if (attributes->bits != (psa_key_bits_t)(*key_data_length * 8U)) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_INVALID_ARGUMENT; @@ -213,7 +213,7 @@ static psa_status_t wolfpsa_cipher_check_key( if (*key_data_length != 16 && *key_data_length != 24 && *key_data_length != 32) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_INVALID_ARGUMENT; @@ -221,7 +221,7 @@ static psa_status_t wolfpsa_cipher_check_key( if (attributes->bits != 128 && attributes->bits != 192 && attributes->bits != 256) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_INVALID_ARGUMENT; @@ -267,7 +267,7 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, ctx = (wolfpsa_cipher_ctx_t *)XMALLOC(sizeof(*ctx), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (ctx == NULL) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INSUFFICIENT_MEMORY; } XMEMSET(ctx, 0, sizeof(*ctx)); @@ -283,7 +283,7 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, #else ctx->is_des3 = 0; if (attributes.type == PSA_KEY_TYPE_DES) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); return PSA_ERROR_NOT_SUPPORTED; } @@ -310,14 +310,16 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, ret = wc_Des3Init(&ctx->des3, NULL, INVALID_DEVID); if (ret != 0) { - wolfpsa_free_key_data(key_data); + wc_ForceZero(des_key, sizeof(des_key)); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); return wc_error_to_psa_status(ret); } ret = wc_Des3_SetKey(&ctx->des3, des_key, ctx->iv, AES_ENCRYPTION); + wc_ForceZero(des_key, sizeof(des_key)); #else - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); return PSA_ERROR_NOT_SUPPORTED; #endif @@ -325,7 +327,7 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, else { ret = wc_AesInit(&ctx->aes, NULL, INVALID_DEVID); if (ret != 0) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); return wc_error_to_psa_status(ret); } @@ -343,7 +345,7 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, ctx->iv, AES_ENCRYPTION); } } - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); if (ret != 0) { #ifndef NO_DES3 if (ctx->is_des3) { @@ -401,7 +403,7 @@ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, ctx = (wolfpsa_cipher_ctx_t *)XMALLOC(sizeof(*ctx), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (ctx == NULL) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INSUFFICIENT_MEMORY; } XMEMSET(ctx, 0, sizeof(*ctx)); @@ -417,7 +419,7 @@ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, #else ctx->is_des3 = 0; if (attributes.type == PSA_KEY_TYPE_DES) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); return PSA_ERROR_NOT_SUPPORTED; } @@ -444,14 +446,16 @@ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, ret = wc_Des3Init(&ctx->des3, NULL, INVALID_DEVID); if (ret != 0) { - wolfpsa_free_key_data(key_data); + wc_ForceZero(des_key, sizeof(des_key)); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); return wc_error_to_psa_status(ret); } ret = wc_Des3_SetKey(&ctx->des3, des_key, ctx->iv, AES_DECRYPTION); + wc_ForceZero(des_key, sizeof(des_key)); #else - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); return PSA_ERROR_NOT_SUPPORTED; #endif @@ -459,7 +463,7 @@ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, else { ret = wc_AesInit(&ctx->aes, NULL, INVALID_DEVID); if (ret != 0) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); return wc_error_to_psa_status(ret); } @@ -477,7 +481,7 @@ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, ctx->iv, AES_DECRYPTION); } } - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); if (ret != 0) { #ifndef NO_DES3 if (ctx->is_des3) { diff --git a/src/psa_key_derivation.c b/src/psa_key_derivation.c index 041543e..9a29425 100644 --- a/src/psa_key_derivation.c +++ b/src/psa_key_derivation.c @@ -584,32 +584,32 @@ psa_status_t psa_key_derivation_input_key(psa_key_derivation_operation_t *operat status = wolfpsa_kdf_validate_step(ctx, step, key_data_length); if (status != PSA_SUCCESS) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return status; } if ((psa_get_key_usage_flags(&attributes) & (PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_VERIFY_DERIVATION)) == 0) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_NOT_PERMITTED; } if (PSA_ALG_IS_PBKDF2(ctx->alg)) { if (step != PSA_KEY_DERIVATION_INPUT_PASSWORD || psa_get_key_type(&attributes) != PSA_KEY_TYPE_PASSWORD) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INVALID_ARGUMENT; } } else if (step == PSA_KEY_DERIVATION_INPUT_SECRET || step == PSA_KEY_DERIVATION_INPUT_OTHER_SECRET) { if (psa_get_key_type(&attributes) != PSA_KEY_TYPE_DERIVE) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INVALID_ARGUMENT; } } else { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INVALID_ARGUMENT; } @@ -618,19 +618,19 @@ psa_status_t psa_key_derivation_input_key(psa_key_derivation_operation_t *operat if (ctx->is_key_agreement) { if (!PSA_ALG_IS_KEY_AGREEMENT(key_alg) || PSA_ALG_KEY_AGREEMENT_GET_KDF(key_alg) != ctx->alg) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_NOT_PERMITTED; } } else if (key_alg != ctx->alg) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_NOT_PERMITTED; } } status = psa_key_derivation_input_bytes(operation, step, key_data, key_data_length); - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return status; } @@ -697,6 +697,7 @@ psa_status_t psa_key_derivation_key_agreement(psa_key_derivation_operation_t *op secret, output_len); } + wc_ForceZero(secret, secret_len); XFREE(secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); return status; } @@ -738,6 +739,7 @@ static psa_status_t wolfpsa_kdf_hkdf(wolfpsa_kdf_ctx_t *ctx, if (PSA_ALG_IS_HKDF(ctx->alg)) { int hash_len = wc_HashGetDigestSize(hash_type); uint8_t prk[WC_MAX_DIGEST_SIZE]; + psa_status_t status; if (hash_len <= 0 || (size_t)hash_len > sizeof(prk)) { return PSA_ERROR_NOT_SUPPORTED; @@ -747,7 +749,9 @@ static psa_status_t wolfpsa_kdf_hkdf(wolfpsa_kdf_ctx_t *ctx, ctx->secret, (word32)ctx->secret_length, prk); if (ret != 0) { - return wc_error_to_psa_status(ret); + status = wc_error_to_psa_status(ret); + wc_ForceZero(prk, sizeof(prk)); + return status; } ret = wc_HKDF_Expand(hash_type, @@ -755,8 +759,11 @@ static psa_status_t wolfpsa_kdf_hkdf(wolfpsa_kdf_ctx_t *ctx, ctx->info, (word32)ctx->info_length, output, (word32)output_length); if (ret != 0) { - return wc_error_to_psa_status(ret); + status = wc_error_to_psa_status(ret); + wc_ForceZero(prk, sizeof(prk)); + return status; } + wc_ForceZero(prk, sizeof(prk)); return PSA_SUCCESS; } @@ -823,6 +830,7 @@ static psa_status_t wolfpsa_kdf_tls12_psk_to_ms(wolfpsa_kdf_ctx_t *ctx, status = PSA_SUCCESS; } + wc_ForceZero(premaster, premaster_len); XFREE(premaster, NULL, DYNAMIC_TYPE_TMP_BUFFER); return status; } @@ -862,29 +870,35 @@ static psa_status_t wolfpsa_kdf_pbkdf2(wolfpsa_kdf_ctx_t *ctx, int ret; Cmac cmac; word32 out_sz = WC_AES_BLOCK_SIZE; + psa_status_t status = PSA_SUCCESS; XMEMSET(zero_key, 0, sizeof(zero_key)); ret = wc_InitCmac(&cmac, zero_key, (word32)sizeof(zero_key), WC_CMAC_AES, NULL); if (ret != 0) { - return wc_error_to_psa_status(ret); + status = wc_error_to_psa_status(ret); + goto cleanup; } ret = wc_CmacUpdate(&cmac, ctx->password, (word32)ctx->password_length); if (ret != 0) { wc_CmacFree(&cmac); - return wc_error_to_psa_status(ret); + status = wc_error_to_psa_status(ret); + goto cleanup; } ret = wc_CmacFinal(&cmac, prf_key, &out_sz); wc_CmacFree(&cmac); if (ret != 0 || out_sz != WC_AES_BLOCK_SIZE) { - return ret == 0 ? PSA_ERROR_NOT_SUPPORTED : wc_error_to_psa_status(ret); + status = ret == 0 ? PSA_ERROR_NOT_SUPPORTED : + wc_error_to_psa_status(ret); + goto cleanup; } block_input_len = ctx->salt_length + 4; block_input = (uint8_t *)XMALLOC(block_input_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (block_input == NULL) { - return PSA_ERROR_INSUFFICIENT_MEMORY; + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto cleanup; } blocks = (output_length + WC_AES_BLOCK_SIZE - 1) / WC_AES_BLOCK_SIZE; @@ -898,8 +912,8 @@ static psa_status_t wolfpsa_kdf_pbkdf2(wolfpsa_kdf_ctx_t *ctx, ret = wc_InitCmac(&cmac, prf_key, (word32)sizeof(prf_key), WC_CMAC_AES, NULL); if (ret != 0) { - XFREE(block_input, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return wc_error_to_psa_status(ret); + status = wc_error_to_psa_status(ret); + goto cleanup; } out_sz = WC_AES_BLOCK_SIZE; ret = wc_CmacUpdate(&cmac, block_input, (word32)block_input_len); @@ -908,8 +922,9 @@ static psa_status_t wolfpsa_kdf_pbkdf2(wolfpsa_kdf_ctx_t *ctx, } wc_CmacFree(&cmac); if (ret != 0 || out_sz != WC_AES_BLOCK_SIZE) { - XFREE(block_input, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return ret == 0 ? PSA_ERROR_NOT_SUPPORTED : wc_error_to_psa_status(ret); + status = ret == 0 ? PSA_ERROR_NOT_SUPPORTED : + wc_error_to_psa_status(ret); + goto cleanup; } XMEMCPY(t_block, u_block, WC_AES_BLOCK_SIZE); @@ -917,8 +932,8 @@ static psa_status_t wolfpsa_kdf_pbkdf2(wolfpsa_kdf_ctx_t *ctx, ret = wc_InitCmac(&cmac, prf_key, (word32)sizeof(prf_key), WC_CMAC_AES, NULL); if (ret != 0) { - XFREE(block_input, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return wc_error_to_psa_status(ret); + status = wc_error_to_psa_status(ret); + goto cleanup; } out_sz = WC_AES_BLOCK_SIZE; ret = wc_CmacUpdate(&cmac, u_block, WC_AES_BLOCK_SIZE); @@ -927,8 +942,9 @@ static psa_status_t wolfpsa_kdf_pbkdf2(wolfpsa_kdf_ctx_t *ctx, } wc_CmacFree(&cmac); if (ret != 0 || out_sz != WC_AES_BLOCK_SIZE) { - XFREE(block_input, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return ret == 0 ? PSA_ERROR_NOT_SUPPORTED : wc_error_to_psa_status(ret); + status = ret == 0 ? PSA_ERROR_NOT_SUPPORTED : + wc_error_to_psa_status(ret); + goto cleanup; } t_block[0] ^= u_block[0]; t_block[1] ^= u_block[1]; @@ -957,8 +973,12 @@ static psa_status_t wolfpsa_kdf_pbkdf2(wolfpsa_kdf_ctx_t *ctx, offset = output_length; } } +cleanup: + wc_ForceZero(t_block, sizeof(t_block)); + wc_ForceZero(u_block, sizeof(u_block)); + wc_ForceZero(prf_key, sizeof(prf_key)); XFREE(block_input, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return PSA_SUCCESS; + return status; #else return PSA_ERROR_NOT_SUPPORTED; #endif @@ -1082,11 +1102,13 @@ psa_status_t psa_key_derivation_output_key(const psa_key_attributes_t *attribute status = psa_key_derivation_output_bytes(operation, buffer, key_len); if (status != PSA_SUCCESS) { + wc_ForceZero(buffer, key_len); XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); return status; } status = psa_import_key(attributes, buffer, key_len, key); + wc_ForceZero(buffer, key_len); XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); return status; } @@ -1161,13 +1183,13 @@ psa_status_t psa_key_derivation_verify_key(psa_key_derivation_operation_t *opera status = wolfpsa_get_key_data(expected, NULL, &expected_data, &expected_length); if (status != PSA_SUCCESS) { - wolfpsa_free_key_data(expected_data); + wolfpsa_forcezero_free_key_data(expected_data, expected_length); return status; } status = psa_key_derivation_verify_bytes(operation, expected_data, expected_length); - wolfpsa_free_key_data(expected_data); + wolfpsa_forcezero_free_key_data(expected_data, expected_length); return status; } diff --git a/src/psa_key_storage.c b/src/psa_key_storage.c index 469037b..3731846 100644 --- a/src/psa_key_storage.c +++ b/src/psa_key_storage.c @@ -38,6 +38,7 @@ #include #include #include +#include #ifdef WOLFPSA_DEBUG_IMPORT #include @@ -112,6 +113,50 @@ static psa_status_t psa_wc_error_to_psa_status(int ret) return status; } +static psa_key_bits_t wolfpsa_ecc_bits_from_length(psa_ecc_family_t family, + size_t length_bytes) +{ + switch (family) { + case PSA_ECC_FAMILY_SECP_R1: + switch (length_bytes) { + case 24: return 192; + case 28: return 224; + case 32: return 256; + case 48: return 384; + case 66: return 521; + default: return 0; + } + + case PSA_ECC_FAMILY_SECP_K1: + switch (length_bytes) { + case 24: return 192; + case 28: return 224; + case 32: return 256; + default: return 0; + } + + case PSA_ECC_FAMILY_BRAINPOOL_P_R1: + switch (length_bytes) { + case 32: return 256; + case 48: return 384; + case 64: return 512; + default: return 0; + } + + case PSA_ECC_FAMILY_MONTGOMERY: + case PSA_ECC_FAMILY_TWISTED_EDWARDS: + switch (length_bytes) { + case 32: return 255; + case 56: return 448; + case 57: return 448; + default: return 0; + } + + default: + return 0; + } +} + static int wolfpsa_usage_flags_valid(psa_key_usage_t usage) { psa_key_usage_t mask = PSA_KEY_USAGE_EXPORT | @@ -195,6 +240,7 @@ static psa_status_t wolfpsa_volatile_remove(psa_key_id_t key_id) g_volatile_keys = cur->next; } if (cur->data != NULL) { + wc_ForceZero(cur->data, cur->data_length); XFREE(cur->data, NULL, DYNAMIC_TYPE_TMP_BUFFER); } XMEMSET(cur, 0, sizeof(*cur)); @@ -290,15 +336,25 @@ static psa_status_t wolfpsa_infer_key_bits(psa_key_attributes_t* attr, } if (PSA_KEY_TYPE_IS_ECC(attr->type)) { + psa_ecc_family_t family = PSA_KEY_TYPE_ECC_GET_FAMILY(attr->type); + psa_key_bits_t inferred_bits; + if (PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(attr->type)) { if (data_length < 2u || ((data_length - 1u) & 1u) != 0u) { return PSA_ERROR_INVALID_ARGUMENT; } - attr->bits = (psa_key_bits_t)(((data_length - 1u) / 2u) * 8u); + inferred_bits = wolfpsa_ecc_bits_from_length(family, + (data_length - 1u) / 2u); } else { - attr->bits = (psa_key_bits_t)(data_length * 8U); + inferred_bits = wolfpsa_ecc_bits_from_length(family, data_length); + } + + if (inferred_bits == 0) { + return PSA_ERROR_INVALID_ARGUMENT; } + + attr->bits = inferred_bits; return PSA_SUCCESS; } @@ -460,6 +516,7 @@ void psa_key_storage_cleanup(void) while (cur != NULL) { wolfpsa_volatile_key_node* next = cur->next; if (cur->data != NULL) { + wc_ForceZero(cur->data, cur->data_length); XFREE(cur->data, NULL, DYNAMIC_TYPE_TMP_BUFFER); } XMEMSET(cur, 0, sizeof(*cur)); @@ -677,9 +734,10 @@ psa_status_t wolfpsa_get_key_data(psa_key_id_t key_id, return PSA_SUCCESS; } -void wolfpsa_free_key_data(uint8_t* key_data) +void wolfpsa_forcezero_free_key_data(uint8_t* key_data, size_t key_data_length) { if (key_data != NULL) { + wc_ForceZero(key_data, key_data_length); XFREE(key_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); } } @@ -870,11 +928,13 @@ psa_status_t psa_generate_key( status = psa_generate_random(key_data, key_data_length); if (status != PSA_SUCCESS) { + wc_ForceZero(key_data, key_data_length); XFREE(key_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); return status; } status = psa_import_key(attributes, key_data, key_data_length, key_id); + wc_ForceZero(key_data, key_data_length); XFREE(key_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); return status; } @@ -895,11 +955,13 @@ psa_status_t psa_generate_key( &priv_len, NULL, 0, NULL); if (status != PSA_SUCCESS) { + wc_ForceZero(key_data, priv_buf_size); XFREE(key_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); return status; } status = psa_import_key(attributes, key_data, priv_len, key_id); + wc_ForceZero(key_data, priv_buf_size); XFREE(key_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); return status; #else @@ -923,6 +985,7 @@ psa_status_t psa_generate_key( pub_buf = (uint8_t *)XMALLOC(pub_buf_size, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (pub_buf == NULL) { + wc_ForceZero(key_data, priv_buf_size); XFREE(key_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); return PSA_ERROR_INSUFFICIENT_MEMORY; } @@ -934,11 +997,13 @@ psa_status_t psa_generate_key( &pub_len); XFREE(pub_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (status != PSA_SUCCESS) { + wc_ForceZero(key_data, priv_buf_size); XFREE(key_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); return status; } status = psa_import_key(attributes, key_data, priv_len, key_id); + wc_ForceZero(key_data, priv_buf_size); XFREE(key_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); return status; #else @@ -1018,16 +1083,16 @@ psa_status_t psa_export_key( if (status == PSA_SUCCESS) { if ((psa_get_key_usage_flags(&vol_attr) & PSA_KEY_USAGE_EXPORT) == 0) { - wolfpsa_free_key_data(vol_data); + wolfpsa_forcezero_free_key_data(vol_data, vol_len); return PSA_ERROR_NOT_PERMITTED; } if (data_size < vol_len) { - wolfpsa_free_key_data(vol_data); + wolfpsa_forcezero_free_key_data(vol_data, vol_len); return PSA_ERROR_BUFFER_TOO_SMALL; } XMEMCPY(data, vol_data, vol_len); *data_length = vol_len; - wolfpsa_free_key_data(vol_data); + wolfpsa_forcezero_free_key_data(vol_data, vol_len); return PSA_SUCCESS; } } @@ -1135,7 +1200,7 @@ psa_status_t psa_export_public_key( if (!PSA_KEY_TYPE_IS_RSA(attributes.type) && !PSA_KEY_TYPE_IS_ECC(attributes.type)) { if (use_volatile) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); } return PSA_ERROR_INVALID_ARGUMENT; } @@ -1173,7 +1238,7 @@ psa_status_t psa_export_public_key( wolfPSA_Store_Close(store); store = NULL; if (ret != (int)key_data_length) { - XFREE(key_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_STORAGE_FAILURE; } } @@ -1325,7 +1390,7 @@ psa_status_t psa_export_public_key( #endif } - XFREE(key_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return status; } @@ -1414,36 +1479,36 @@ psa_status_t psa_copy_key( { psa_key_attributes_t vol_attr = PSA_KEY_ATTRIBUTES_INIT; uint8_t* key_data = NULL; - size_t key_data_length = 0; + key_data_length = 0; status = wolfpsa_volatile_get(source_key, &vol_attr, &key_data, &key_data_length); if (status == PSA_SUCCESS) { - psa_key_attributes_t dst_attr = *attributes; + dst_attr = *attributes; if ((psa_get_key_usage_flags(&vol_attr) & PSA_KEY_USAGE_COPY) == 0) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_NOT_PERMITTED; } if (attributes->type != vol_attr.type) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INVALID_ARGUMENT; } if (attributes->bits != 0 && attributes->bits != vol_attr.bits) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INVALID_ARGUMENT; } if (attributes->policy.alg != psa_get_key_algorithm(&vol_attr)) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INVALID_ARGUMENT; } if (attributes->lifetime != vol_attr.lifetime) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INVALID_ARGUMENT; } @@ -1453,7 +1518,7 @@ psa_status_t psa_copy_key( status = psa_import_key(&dst_attr, key_data, key_data_length, target_key); - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return status; } } @@ -1524,14 +1589,14 @@ psa_status_t psa_copy_key( wolfPSA_Store_Close(store); store = NULL; if (ret != (int)key_data_length) { - XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wolfpsa_forcezero_free_key_data(buffer, key_data_length); return PSA_ERROR_STORAGE_FAILURE; } /* Import the key with new attributes */ status = psa_import_key(&dst_attr, buffer, key_data_length, target_key); - XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wolfpsa_forcezero_free_key_data(buffer, key_data_length); return status; } diff --git a/src/psa_mac.c b/src/psa_mac.c index 3f51ea4..528e42a 100644 --- a/src/psa_mac.c +++ b/src/psa_mac.c @@ -122,7 +122,7 @@ static psa_status_t wolfpsa_mac_check_key(psa_key_id_t key, if (PSA_ALG_IS_HMAC(alg)) { if (attributes->type != PSA_KEY_TYPE_HMAC) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_INVALID_ARGUMENT; @@ -130,14 +130,14 @@ static psa_status_t wolfpsa_mac_check_key(psa_key_id_t key, } else if (PSA_ALG_IS_BLOCK_CIPHER_MAC(alg)) { if (attributes->type != PSA_KEY_TYPE_AES) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_INVALID_ARGUMENT; } } else { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_SUPPORTED; @@ -145,7 +145,7 @@ static psa_status_t wolfpsa_mac_check_key(psa_key_id_t key, key_usage = psa_get_key_usage_flags(attributes); if ((key_usage & usage) == 0) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_PERMITTED; @@ -156,7 +156,7 @@ static psa_status_t wolfpsa_mac_check_key(psa_key_id_t key, req_alg_full = PSA_ALG_FULL_LENGTH_MAC(alg); if (key_alg != PSA_ALG_NONE) { if (key_alg_full != req_alg_full) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_PERMITTED; @@ -171,7 +171,7 @@ static psa_status_t wolfpsa_mac_check_key(psa_key_id_t key, if ((key_alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) { if (req_mac_length < key_min_length) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_PERMITTED; @@ -180,14 +180,14 @@ static psa_status_t wolfpsa_mac_check_key(psa_key_id_t key, else { if ((key_alg & PSA_ALG_MAC_TRUNCATION_MASK) != 0) { if (req_mac_length != key_min_length) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_PERMITTED; } } else if (req_mac_length != key_full_length) { - wolfpsa_free_key_data(*key_data); + wolfpsa_forcezero_free_key_data(*key_data, *key_data_length); *key_data = NULL; *key_data_length = 0; return PSA_ERROR_NOT_PERMITTED; @@ -230,7 +230,7 @@ static psa_status_t wolfpsa_mac_setup(psa_mac_operation_t *operation, ctx = (wolfpsa_mac_ctx_t *)XMALLOC(sizeof(*ctx), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (ctx == NULL) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); return PSA_ERROR_INSUFFICIENT_MEMORY; } XMEMSET(ctx, 0, sizeof(*ctx)); @@ -245,7 +245,7 @@ static psa_status_t wolfpsa_mac_setup(psa_mac_operation_t *operation, if (PSA_ALG_IS_HMAC(alg)) { int hash_type = wolfpsa_hash_type_from_alg(alg); if (hash_type == WC_HASH_TYPE_NONE) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); return PSA_ERROR_NOT_SUPPORTED; } @@ -265,7 +265,7 @@ static psa_status_t wolfpsa_mac_setup(psa_mac_operation_t *operation, if (ctx->mac_length == 0 || ctx->full_length == 0 || ctx->mac_length > ctx->full_length) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); return PSA_ERROR_INVALID_ARGUMENT; } @@ -273,18 +273,18 @@ static psa_status_t wolfpsa_mac_setup(psa_mac_operation_t *operation, if ((alg & PSA_ALG_MAC_TRUNCATION_MASK) != 0) { size_t trunc_len = PSA_MAC_TRUNCATED_LENGTH(alg); if (trunc_len > ctx->full_length) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); return PSA_ERROR_INVALID_ARGUMENT; } if (trunc_len < 4u) { - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); return PSA_ERROR_NOT_SUPPORTED; } } - wolfpsa_free_key_data(key_data); + wolfpsa_forcezero_free_key_data(key_data, key_data_length); if (ret != 0) { XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); diff --git a/src/psa_random.c b/src/psa_random.c index df7b188..1ccc747 100644 --- a/src/psa_random.c +++ b/src/psa_random.c @@ -48,6 +48,9 @@ psa_status_t psa_generate_random(uint8_t *output, size_t output_size) if (output == NULL && output_size > 0) { return PSA_ERROR_INVALID_ARGUMENT; } + if (output_size > UINT32_MAX) { + return PSA_ERROR_INVALID_ARGUMENT; + } wolfpsa_trace("psa_generate_random(%zu)", output_size); diff --git a/test/Makefile b/test/Makefile index 1e85e69..a8105f2 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,6 +1,7 @@ WOLFPSA_PATH ?= .. WOLFSSL_PATH ?= $(WOLFPSA_PATH)/../wolfssl WOLFPSA_ABS := $(abspath $(WOLFPSA_PATH)) +BUILD_DIR ?= build WOLFSSL_CANDIDATE_DIRS := \ $(WOLFSSL_PATH)/build \ @@ -33,6 +34,7 @@ ifneq ($(WOLFSSL_BUILD_DIR),) CPPFLAGS += -I$(WOLFSSL_BUILD_DIR) endif CPPFLAGS += -I$(WOLFPSA_PATH) -I$(WOLFPSA_PATH)/wolfpsa +CPPFLAGS += -I$(WOLFPSA_PATH)/src CPPFLAGS += -I$(WOLFPSA_PATH)/test/psa_server LDFLAGS += -L$(WOLFPSA_PATH) @@ -55,13 +57,19 @@ WOLFSSL_LOCAL_SYMBOLS := $(if $(WOLFSSL_LOCAL_LIB),$(shell \ $(NM) $(WOLFSSL_LOCAL_LIB) 2>/dev/null)) WOLFSSL_HAS_PSA_TLS := $(findstring wolfSSL_CTX_psa_enable,$(WOLFSSL_LOCAL_SYMBOLS)) -BINARIES = psa_api_test psa_rsa_pss_interop_test psa_tls_client wolfcrypt-psa-benchmark +BINARIES = psa_api_test psa_des3_stack_scrub_test psa_ecc_bit_inference_test psa_ecc_curve_id_test psa_random_size_test psa_rsa_pss_interop_test psa_tls_client wolfcrypt-psa-benchmark ifdef WOLFSSL_HAS_PSA_TLS BINARIES += psa_tls_server endif PSA_API_TEST_OBJS = psa_server/psa_api_test.o +PSA_DES3_STACK_SCRUB_TEST_OBJS = psa_server/psa_des3_stack_scrub_test.o +PSA_ECC_BIT_INFERENCE_TEST_OBJS = psa_server/psa_ecc_bit_inference_test.o +PSA_ECC_CURVE_ID_TEST_OBJS = psa_server/psa_ecc_curve_id_test.o +PSA_RANDOM_SIZE_TEST_OBJS = psa_server/psa_random_size_test.o +PSA_ECC_CURVE_ID_TEST_DEPS = $(WOLFPSA_PATH)/$(BUILD_DIR)/obj/psa_asymmetric.o \ + $(WOLFPSA_PATH)/$(BUILD_DIR)/obj/psa_pq.o PSA_RSA_PSS_TEST_OBJS = psa_server/psa_rsa_pss_interop_test.o .PHONY: all clean rebuild-wolfssl-psa require-wolfssl-lib @@ -78,6 +86,18 @@ endif psa_api_test: require-wolfssl-lib $(PSA_API_TEST_OBJS) $(CC) $(CFLAGS) -o $@ $(PSA_API_TEST_OBJS) $(LDFLAGS) $(LDLIBS) $(RPATH_WOLFPSA) $(RPATH_WOLFSSL) +psa_des3_stack_scrub_test: require-wolfssl-lib $(PSA_DES3_STACK_SCRUB_TEST_OBJS) + $(CC) $(CFLAGS) -o $@ $(PSA_DES3_STACK_SCRUB_TEST_OBJS) $(LDFLAGS) $(LDLIBS) $(RPATH_WOLFPSA) $(RPATH_WOLFSSL) + +psa_ecc_bit_inference_test: require-wolfssl-lib $(PSA_ECC_BIT_INFERENCE_TEST_OBJS) + $(CC) $(CFLAGS) -o $@ $(PSA_ECC_BIT_INFERENCE_TEST_OBJS) $(LDFLAGS) $(LDLIBS) $(RPATH_WOLFPSA) $(RPATH_WOLFSSL) + +psa_ecc_curve_id_test: require-wolfssl-lib $(PSA_ECC_CURVE_ID_TEST_OBJS) $(PSA_ECC_CURVE_ID_TEST_DEPS) + $(CC) $(CFLAGS) -o $@ $(PSA_ECC_CURVE_ID_TEST_OBJS) $(PSA_ECC_CURVE_ID_TEST_DEPS) $(LDFLAGS) $(LDLIBS) $(RPATH_WOLFPSA) $(RPATH_WOLFSSL) + +psa_random_size_test: require-wolfssl-lib $(PSA_RANDOM_SIZE_TEST_OBJS) + $(CC) $(CFLAGS) -o $@ $(PSA_RANDOM_SIZE_TEST_OBJS) $(LDFLAGS) $(LDLIBS) $(RPATH_WOLFPSA) $(RPATH_WOLFSSL) + psa_rsa_pss_interop_test: require-wolfssl-lib $(PSA_RSA_PSS_TEST_OBJS) $(CC) $(CFLAGS) -o $@ $(PSA_RSA_PSS_TEST_OBJS) $(LDFLAGS) $(LDLIBS) $(RPATH_WOLFPSA) $(RPATH_WOLFSSL) diff --git a/test/psa_server/psa_api_test.c b/test/psa_server/psa_api_test.c index da19dea..3a60e4d 100644 --- a/test/psa_server/psa_api_test.c +++ b/test/psa_server/psa_api_test.c @@ -15,6 +15,7 @@ #include #include +#include "psa_aead_internal.h" #include #include @@ -302,6 +303,73 @@ static int test_aead_gcm(void) return TEST_OK; } +static int test_aead_multipart_length_overflow_rejected(void) +{ + static const uint8_t key[16] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }; + static const uint8_t nonce[12] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00 + }; + static const uint8_t chunk[2] = { 0xaa, 0x55 }; + uint8_t out[sizeof(chunk)]; + size_t out_len = 0; + psa_key_id_t key_id = 0; + psa_key_attributes_t attrs = psa_key_attributes_init(); + psa_aead_operation_t op = psa_aead_operation_init(); + wolfpsa_aead_ctx_t *ctx; + int ret = TEST_OK; + psa_status_t st; + + psa_set_key_type(&attrs, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attrs, 128); + psa_set_key_usage_flags(&attrs, PSA_KEY_USAGE_ENCRYPT); + psa_set_key_algorithm(&attrs, PSA_ALG_GCM); + + st = psa_import_key(&attrs, key, sizeof(key), &key_id); + if (check_status(st, "psa_import_key(GCM overflow)") != TEST_OK) return TEST_FAIL; + + st = psa_aead_encrypt_setup(&op, key_id, PSA_ALG_GCM); + if (check_status(st, "psa_aead_encrypt_setup") != TEST_OK) goto cleanup; + st = psa_aead_set_lengths(&op, SIZE_MAX, SIZE_MAX); + if (check_status(st, "psa_aead_set_lengths") != TEST_OK) goto cleanup; + st = psa_aead_set_nonce(&op, nonce, sizeof(nonce)); + if (check_status(st, "psa_aead_set_nonce") != TEST_OK) goto cleanup; + + ctx = wolfpsa_aead_get_ctx_ptr(&op); + ctx->aad_length = SIZE_MAX - 1; + st = psa_aead_update_ad(&op, chunk, sizeof(chunk)); + if (check_true(st == PSA_ERROR_INVALID_ARGUMENT, + "psa_aead_update_ad rejects wrapped accumulated length") != TEST_OK) { + ret = TEST_FAIL; + goto cleanup; + } + + st = psa_aead_encrypt_setup(&op, key_id, PSA_ALG_GCM); + if (check_status(st, "psa_aead_encrypt_setup(plaintext)") != TEST_OK) goto cleanup; + st = psa_aead_set_lengths(&op, 0, SIZE_MAX); + if (check_status(st, "psa_aead_set_lengths(plaintext)") != TEST_OK) goto cleanup; + st = psa_aead_set_nonce(&op, nonce, sizeof(nonce)); + if (check_status(st, "psa_aead_set_nonce(plaintext)") != TEST_OK) goto cleanup; + + ctx = wolfpsa_aead_get_ctx_ptr(&op); + ctx->input_length = SIZE_MAX - 1; + st = psa_aead_update(&op, chunk, sizeof(chunk), out, sizeof(out), &out_len); + if (check_true(st == PSA_ERROR_INVALID_ARGUMENT, + "psa_aead_update rejects wrapped accumulated length") != TEST_OK) { + ret = TEST_FAIL; + goto cleanup; + } + +cleanup: + psa_aead_abort(&op); + st = psa_destroy_key(key_id); + if (check_status(st, "psa_destroy_key(GCM overflow)") != TEST_OK) return TEST_FAIL; + return ret; +} + static int test_chacha20_poly1305_rejects_aes_key(void) { static const uint8_t key[32] = { @@ -558,6 +626,12 @@ int main(int argc, char** argv) if (only == NULL || strcmp(only, "aead_gcm") == 0) { if (run_named_test("aead_gcm", test_aead_gcm) == TEST_FAIL) return TEST_FAIL; } + if (only == NULL || strcmp(only, "aead_multipart_length_overflow") == 0) { + if (run_named_test("aead_multipart_length_overflow", + test_aead_multipart_length_overflow_rejected) == TEST_FAIL) { + return TEST_FAIL; + } + } if (only == NULL || strcmp(only, "chacha20_aes_reject") == 0) { if (run_named_test("chacha20_aes_reject", test_chacha20_poly1305_rejects_aes_key) == TEST_FAIL) { diff --git a/test/psa_server/psa_des3_stack_scrub_test.c b/test/psa_server/psa_des3_stack_scrub_test.c new file mode 100644 index 0000000..90d37d3 --- /dev/null +++ b/test/psa_server/psa_des3_stack_scrub_test.c @@ -0,0 +1,53 @@ +#include "psa_api_test_user_settings.h" + +#ifndef WOLFSSL_USER_SETTINGS +#define WOLFSSL_USER_SETTINGS +#endif + +#include + +#include +#include + +#include + +int main(void) +{ + static const uint8_t key[16] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 + }; + psa_key_attributes_t attrs = psa_key_attributes_init(); + psa_cipher_operation_t op = psa_cipher_operation_init(); + psa_key_id_t key_id = PSA_KEY_ID_NULL; + psa_status_t st; + + st = psa_crypto_init(); + if (st != PSA_SUCCESS) { + printf("FAIL psa_crypto_init status=%d\n", (int)st); + return 1; + } + + psa_set_key_type(&attrs, PSA_KEY_TYPE_DES); + psa_set_key_bits(&attrs, 128); + psa_set_key_usage_flags(&attrs, PSA_KEY_USAGE_ENCRYPT); + psa_set_key_algorithm(&attrs, PSA_ALG_CBC_NO_PADDING); + + st = psa_import_key(&attrs, key, sizeof(key), &key_id); + if (st != PSA_SUCCESS) { + printf("FAIL psa_import_key status=%d\n", (int)st); + return 1; + } + + st = psa_cipher_encrypt_setup(&op, key_id, PSA_ALG_CBC_NO_PADDING); + if (st != PSA_SUCCESS) { + printf("FAIL psa_cipher_encrypt_setup status=%d\n", (int)st); + (void)psa_destroy_key(key_id); + return 1; + } + + (void)psa_cipher_abort(&op); + (void)psa_destroy_key(key_id); + puts("PSA DES3 setup test: OK"); + return 0; +} diff --git a/test/psa_server/psa_ecc_bit_inference_test.c b/test/psa_server/psa_ecc_bit_inference_test.c new file mode 100644 index 0000000..488f438 --- /dev/null +++ b/test/psa_server/psa_ecc_bit_inference_test.c @@ -0,0 +1,107 @@ +#include "psa_api_test_user_settings.h" + +#ifndef WOLFSSL_USER_SETTINGS +#define WOLFSSL_USER_SETTINGS +#endif + +#include + +#include +#include + +#include + +static int test_public_key_bits(void) +{ + uint8_t pub[133]; + psa_key_attributes_t attrs = psa_key_attributes_init(); + psa_key_attributes_t got = psa_key_attributes_init(); + psa_key_id_t key_id = PSA_KEY_ID_NULL; + psa_status_t st; + + memset(pub, 0, sizeof(pub)); + pub[0] = 0x04; + + psa_set_key_type(&attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_usage_flags(&attrs, PSA_KEY_USAGE_EXPORT); + + st = psa_import_key(&attrs, pub, sizeof(pub), &key_id); + if (st != PSA_SUCCESS) { + printf("FAIL public import status=%d\n", (int)st); + return 1; + } + + st = psa_get_key_attributes(key_id, &got); + if (st != PSA_SUCCESS) { + printf("FAIL public attrs status=%d\n", (int)st); + (void)psa_destroy_key(key_id); + return 1; + } + + if (psa_get_key_bits(&got) != 521) { + printf("FAIL public bits=%u expected=521\n", + (unsigned)psa_get_key_bits(&got)); + (void)psa_destroy_key(key_id); + return 1; + } + + (void)psa_destroy_key(key_id); + return 0; +} + +static int test_private_key_bits(void) +{ + uint8_t priv[66]; + psa_key_attributes_t attrs = psa_key_attributes_init(); + psa_key_attributes_t got = psa_key_attributes_init(); + psa_key_id_t key_id = PSA_KEY_ID_NULL; + psa_status_t st; + + memset(priv, 0, sizeof(priv)); + priv[sizeof(priv) - 1] = 1; + + psa_set_key_type(&attrs, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_usage_flags(&attrs, PSA_KEY_USAGE_EXPORT); + + st = psa_import_key(&attrs, priv, sizeof(priv), &key_id); + if (st != PSA_SUCCESS) { + printf("FAIL private import status=%d\n", (int)st); + return 1; + } + + st = psa_get_key_attributes(key_id, &got); + if (st != PSA_SUCCESS) { + printf("FAIL private attrs status=%d\n", (int)st); + (void)psa_destroy_key(key_id); + return 1; + } + + if (psa_get_key_bits(&got) != 521) { + printf("FAIL private bits=%u expected=521\n", + (unsigned)psa_get_key_bits(&got)); + (void)psa_destroy_key(key_id); + return 1; + } + + (void)psa_destroy_key(key_id); + return 0; +} + +int main(void) +{ + psa_status_t st = psa_crypto_init(); + if (st != PSA_SUCCESS) { + printf("FAIL psa_crypto_init status=%d\n", (int)st); + return 1; + } + + if (test_public_key_bits() != 0) { + return 1; + } + if (test_private_key_bits() != 0) { + return 1; + } + + printf("PSA ECC bit inference test: OK\n"); + return 0; +} diff --git a/test/psa_server/psa_ecc_curve_id_test.c b/test/psa_server/psa_ecc_curve_id_test.c new file mode 100644 index 0000000..8e6cf60 --- /dev/null +++ b/test/psa_server/psa_ecc_curve_id_test.c @@ -0,0 +1,58 @@ +#include "psa_api_test_user_settings.h" + +#ifndef WOLFSSL_USER_SETTINGS +#define WOLFSSL_USER_SETTINGS +#endif + +#include + +#include + +#include +#include + +extern psa_status_t psa_asymmetric_check_key_size_valid(psa_key_type_t type, + size_t bits); +extern int wc_psa_get_ecc_curve_id(psa_key_type_t type, size_t bits); + +static int check_curve(psa_ecc_family_t family, size_t bits, int expected_curve, + const char* label) +{ + psa_key_type_t type = PSA_KEY_TYPE_ECC_KEY_PAIR(family); + psa_status_t st = psa_asymmetric_check_key_size_valid(type, bits); + int curve_id = wc_psa_get_ecc_curve_id(type, bits); + + if (st != PSA_SUCCESS) { + printf("SKIP %s validation unsupported (status=%d)\n", label, (int)st); + return 0; + } + + if (curve_id != expected_curve) { + printf("FAIL %s curve_id=%d expected=%d\n", + label, curve_id, expected_curve); + return 1; + } + + return 0; +} + +int main(void) +{ + int failed = 0; + + failed |= check_curve(PSA_ECC_FAMILY_SECP_R1, 192, ECC_SECP192R1, + "secp_r1_192"); + failed |= check_curve(PSA_ECC_FAMILY_SECP_R1, 224, ECC_SECP224R1, + "secp_r1_224"); + failed |= check_curve(PSA_ECC_FAMILY_SECP_K1, 192, ECC_SECP192K1, + "secp_k1_192"); + failed |= check_curve(PSA_ECC_FAMILY_SECP_K1, 224, ECC_SECP224K1, + "secp_k1_224"); + + if (failed != 0) { + return 1; + } + + printf("PSA ECC curve id test: OK\n"); + return 0; +} diff --git a/test/psa_server/psa_random_size_test.c b/test/psa_server/psa_random_size_test.c new file mode 100644 index 0000000..f4145fb --- /dev/null +++ b/test/psa_server/psa_random_size_test.c @@ -0,0 +1,53 @@ +#include "psa_api_test_user_settings.h" + +#ifndef WOLFSSL_USER_SETTINGS +#define WOLFSSL_USER_SETTINGS +#endif + +#include + +#include +#include +#include +#include + +#include + +int main(void) +{ + size_t huge; + uint8_t* buf; + psa_status_t st; + + if (SIZE_MAX <= UINT32_MAX) { + printf("SKIP psa_random_size_test requires size_t wider than 32 bits\n"); + return 0; + } + + huge = (size_t)UINT32_MAX + 1u; + + st = psa_crypto_init(); + if (st != PSA_SUCCESS) { + printf("FAIL psa_crypto_init status=%d\n", (int)st); + return 1; + } + + buf = (uint8_t*)mmap(NULL, huge, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (buf == MAP_FAILED) { + printf("SKIP mmap failed for size=%zu\n", huge); + return 0; + } + + st = psa_generate_random(buf, huge); + munmap(buf, huge); + + if (st == PSA_SUCCESS) { + printf("FAIL psa_generate_random unexpectedly succeeded for size=%zu\n", + huge); + return 1; + } + + printf("PSA random size test: OK (status=%d)\n", (int)st); + return 0; +} diff --git a/wolfpsa/psa_key_storage.h b/wolfpsa/psa_key_storage.h index 7a8f697..8f87e8e 100644 --- a/wolfpsa/psa_key_storage.h +++ b/wolfpsa/psa_key_storage.h @@ -98,7 +98,8 @@ WOLFSSL_API psa_status_t wolfpsa_get_key_data(psa_key_id_t key_id, psa_key_attributes_t* attributes, uint8_t** key_data, size_t* key_data_length); -WOLFSSL_API void wolfpsa_free_key_data(uint8_t* key_data); +WOLFSSL_API void wolfpsa_forcezero_free_key_data(uint8_t* key_data, + size_t key_data_length); #ifdef __cplusplus }