/* * Copyright (C) 2022 HAW Hamburg * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level * directory for more details. */ /** * @ingroup examples * @{ * * @brief Example functions for ECDSA with PSA Crypto * * @author Lena Boeckmann * * @} */ #include #include #include "psa/crypto.h" #define ECDSA_MESSAGE_SIZE (127) #define ECC_KEY_SIZE (256) /** * @brief Example function to perform an ECDSA operation with a NIST P256 curve * with the PSA Crypto API. * * @return psa_status_t */ psa_status_t example_ecdsa_p256(void) { psa_key_id_t privkey_id; psa_key_attributes_t privkey_attr = psa_key_attributes_init(); psa_key_id_t pubkey_id; psa_key_attributes_t pubkey_attr = psa_key_attributes_init(); psa_key_usage_t usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH; psa_key_type_t type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1); psa_algorithm_t alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256); psa_key_bits_t bits = ECC_KEY_SIZE; uint8_t bytes = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1), bits); uint8_t public_key[PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1), ECC_KEY_SIZE)] = { 0 }; size_t pubkey_length; uint8_t signature[PSA_SIGN_OUTPUT_SIZE(type, bits, alg)]; size_t sig_length; uint8_t msg[ECDSA_MESSAGE_SIZE] = { 0x0b }; uint8_t hash[PSA_HASH_LENGTH(PSA_ALG_SHA_256)]; size_t hash_length; psa_set_key_algorithm(&privkey_attr, alg); psa_set_key_usage_flags(&privkey_attr, usage); psa_set_key_type(&privkey_attr, type); psa_set_key_bits(&privkey_attr, bits); #ifdef SECURE_ELEMENT psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( PSA_KEY_LIFETIME_VOLATILE, PSA_ATCA_LOCATION_DEV0); psa_set_key_lifetime(&privkey_attr, lifetime); #endif psa_status_t status = PSA_ERROR_DOES_NOT_EXIST; status = psa_generate_key(&privkey_attr, &privkey_id); if (status != PSA_SUCCESS) { return status; } status = psa_export_public_key(privkey_id, public_key, sizeof(public_key), &pubkey_length); if (status != PSA_SUCCESS) { return status; } status = psa_hash_compute(PSA_ALG_SHA_256, msg, sizeof(msg), hash, sizeof(hash), &hash_length); if (status != PSA_SUCCESS) { return status; } #ifdef SECURE_ELEMENT psa_set_key_lifetime(&pubkey_attr, lifetime); #endif psa_set_key_algorithm(&pubkey_attr, alg); psa_set_key_usage_flags(&pubkey_attr, PSA_KEY_USAGE_VERIFY_HASH); psa_set_key_bits(&pubkey_attr, PSA_BYTES_TO_BITS(bytes)); psa_set_key_type(&pubkey_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)); status = psa_import_key(&pubkey_attr, public_key, pubkey_length, &pubkey_id); if (status != PSA_SUCCESS) { return status; } status = psa_sign_hash(privkey_id, alg, hash, sizeof(hash), signature, sizeof(signature), &sig_length); if (status != PSA_SUCCESS) { return status; } return psa_verify_hash(pubkey_id, alg, hash, sizeof(hash), signature, sig_length); } #ifdef MULTIPLE_SE psa_status_t example_ecdsa_p256_sec_se(void) { psa_key_id_t privkey_id; psa_key_attributes_t privkey_attr = psa_key_attributes_init(); psa_key_id_t pubkey_id; psa_key_attributes_t pubkey_attr = psa_key_attributes_init(); psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( PSA_KEY_LIFETIME_VOLATILE, PSA_ATCA_LOCATION_DEV1); psa_key_usage_t usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH; psa_key_type_t type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1); psa_algorithm_t alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256); psa_key_bits_t bits = 256; uint8_t bytes = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1), bits); uint8_t public_key[PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_FAMILY_SECP_R1), 256)] = { 0 }; size_t pubkey_length; uint8_t signature[PSA_SIGN_OUTPUT_SIZE(type, bits, alg)]; size_t sig_length; uint8_t msg[ECDSA_MESSAGE_SIZE] = { 0x0b }; uint8_t hash[PSA_HASH_LENGTH(PSA_ALG_SHA_256)]; size_t hash_length; psa_set_key_lifetime(&privkey_attr, lifetime); psa_set_key_algorithm(&privkey_attr, alg); psa_set_key_usage_flags(&privkey_attr, usage); psa_set_key_type(&privkey_attr, type); psa_set_key_bits(&privkey_attr, bits); psa_status_t status = PSA_ERROR_DOES_NOT_EXIST; status = psa_generate_key(&privkey_attr, &privkey_id); if (status != PSA_SUCCESS) { return status; } status = psa_export_public_key(privkey_id, public_key, sizeof(public_key), &pubkey_length); if (status != PSA_SUCCESS) { return status; } status = psa_hash_compute(PSA_ALG_SHA_256, msg, sizeof(msg), hash, sizeof(hash), &hash_length); if (status != PSA_SUCCESS) { return status; } psa_set_key_lifetime(&pubkey_attr, lifetime); psa_set_key_algorithm(&pubkey_attr, alg); psa_set_key_usage_flags(&pubkey_attr, PSA_KEY_USAGE_VERIFY_HASH); psa_set_key_bits(&pubkey_attr, PSA_BYTES_TO_BITS(bytes)); psa_set_key_type(&pubkey_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)); status = psa_import_key(&pubkey_attr, public_key, pubkey_length, &pubkey_id); if (status != PSA_SUCCESS) { return status; } status = psa_sign_hash(privkey_id, alg, hash, sizeof(hash), signature, sizeof(signature), &sig_length); if (status != PSA_SUCCESS) { return status; } return psa_verify_hash(pubkey_id, alg, hash, sizeof(hash), signature, sig_length); } #endif