Skip to content

Commit

Permalink
Merge pull request #20676 from LP-HAW/fix-uecc-key-format
Browse files Browse the repository at this point in the history
pkg/micro-ecc/psa_uecc: convert between SEC 1 and micro-ecc public key formats
  • Loading branch information
mguetschow authored May 22, 2024
2 parents fc78e1f + 2ed082a commit c46d75d
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 4 deletions.
13 changes: 11 additions & 2 deletions pkg/micro-ecc/psa_uecc/p192.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,15 @@ psa_status_t psa_generate_ecc_p192r1_key_pair( const psa_key_attributes_t *attr

const struct uECC_Curve_t *curve = uECC_secp192r1();

ret = uECC_make_key(pub_key_buffer, priv_key_buffer, curve);
/**
* Add 0x04 prefix for SEC 1 encoded uncompressed elliptic curve points.
* Micro-ECC represents public keys in SEC 1 uncompressed format without the 0x04 prefix [1].
* PSA Crypto uses a standard SEC 1 uncompressed representation [2].
* [1] https://github.com/kmackay/micro-ecc/blob/master/README.md#point-representation
* [2] https://arm-software.github.io/psa-api/crypto/1.1/api/keys/management.html#key-formats
*/
pub_key_buffer[0] = 0x04;
ret = uECC_make_key(pub_key_buffer+1, priv_key_buffer, curve);
if (!ret) {
return PSA_ERROR_GENERIC_ERROR;
}
Expand Down Expand Up @@ -90,7 +98,8 @@ psa_status_t psa_ecc_p192r1_verify_hash(const psa_key_attributes_t *attributes,
int ret = 0;
const struct uECC_Curve_t *curve = uECC_secp192r1();

ret = uECC_verify(key_buffer, hash, hash_length, signature, curve);
/* Micro-ECC expects uncompressed public key without 0x04 prefix */
ret = uECC_verify(key_buffer+1, hash, hash_length, signature, curve);
if (!ret) {
return PSA_ERROR_GENERIC_ERROR;
}
Expand Down
13 changes: 11 additions & 2 deletions pkg/micro-ecc/psa_uecc/p256.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,15 @@ psa_status_t psa_generate_ecc_p256r1_key_pair( const psa_key_attributes_t *attr

const struct uECC_Curve_t *curve = uECC_secp256r1();

ret = uECC_make_key(pub_key_buffer, priv_key_buffer, curve);
/**
* Add 0x04 prefix for SEC 1 encoded uncompressed elliptic curve points.
* Micro-ECC represents public keys in SEC 1 uncompressed format without the 0x04 prefix [1].
* PSA Crypto uses a standard SEC 1 uncompressed representation [2].
* [1] https://github.com/kmackay/micro-ecc/blob/master/README.md#point-representation
* [2] https://arm-software.github.io/psa-api/crypto/1.1/api/keys/management.html#key-formats
*/
pub_key_buffer[0] = 0x04;
ret = uECC_make_key(pub_key_buffer+1, priv_key_buffer, curve);
if (!ret) {
return PSA_ERROR_GENERIC_ERROR;
}
Expand Down Expand Up @@ -90,7 +98,8 @@ psa_status_t psa_ecc_p256r1_verify_hash(const psa_key_attributes_t *attributes,
int ret = 0;
const struct uECC_Curve_t *curve = uECC_secp256r1();

ret = uECC_verify(key_buffer, hash, hash_length, signature, curve);
/* Micro-ECC expects uncompressed public key without 0x04 prefix */
ret = uECC_verify(key_buffer+1, hash, hash_length, signature, curve);
if (!ret) {
return PSA_ERROR_GENERIC_ERROR;
}
Expand Down
7 changes: 7 additions & 0 deletions tests/sys/psa_crypto_ecdsa/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "ztimer.h"

extern psa_status_t example_ecdsa_p256(void);
extern psa_status_t test_ecdsa_p256_vectors(void);

int main(void)
{
Expand All @@ -31,6 +32,12 @@ int main(void)

psa_crypto_init();

status = test_ecdsa_p256_vectors();
if (status != PSA_SUCCESS) {
failed = true;
printf("ECDSA test vectors failed: %s\n", psa_status_to_humanly_readable(status));
}

ztimer_acquire(ZTIMER_USEC);
ztimer_now_t start = ztimer_now(ZTIMER_USEC);

Expand Down
76 changes: 76 additions & 0 deletions tests/sys/psa_crypto_ecdsa/test_ecdsa_p256_vectors.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright (C) 2024 Lars Pfau <lars.pfau@haw-hamburg.de>
*
* 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 tests
* @{
*
* @file
* @brief Tests PSA ECDSA with test vectors
*
* @author Lars Pfau <lars.pfau@haw-hamburg.de>
*
* @}
*/
#include <stdio.h>
#include <stdint.h>

#include "psa/crypto.h"

/*
* RFC6979 test vector for P-256, SHA256 [1].
*
* [1] https://www.rfc-editor.org/rfc/rfc6979#appendix-A.2.5
*/
static const psa_algorithm_t algo = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
static const psa_key_type_t type = PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1);

static const uint8_t private_key[] = {0xC9, 0xAF, 0xA9, 0xD8, 0x45, 0xBA, 0x75, 0x16, 0x6B, 0x5C,
0x21, 0x57, 0x67, 0xB1, 0xD6, 0x93, 0x4E, 0x50, 0xC3, 0xDB, 0x36, 0xE8, 0x9B, 0x12, 0x7B, 0x8A,
0x62, 0x2B, 0x12, 0x0F, 0x67, 0x21};

static const uint8_t public_key[] = {0x04, 0x60, 0xFE, 0xD4, 0xBA, 0x25, 0x5A, 0x9D, 0x31, 0xC9,
0x61, 0xEB, 0x74, 0xC6, 0x35, 0x6D, 0x68, 0xC0, 0x49, 0xB8, 0x92, 0x3B, 0x61, 0xFA, 0x6C, 0xE6,
0x69, 0x62, 0x2E, 0x60, 0xF2, 0x9F, 0xB6, 0x79, 0x03, 0xFE, 0x10, 0x08, 0xB8, 0xBC, 0x99, 0xA4,
0x1A, 0xE9, 0xE9, 0x56, 0x28, 0xBC, 0x64, 0xF2, 0xF1, 0xB2, 0x0C, 0x2D, 0x7E, 0x9F, 0x51, 0x77,
0xA3, 0xC2, 0x94, 0xD4, 0x46, 0x22, 0x99};

static const uint8_t message[6] = "sample";

static const uint8_t signature[] = {0xEF, 0xD4, 0x8B, 0x2A, 0xAC, 0xB6, 0xA8, 0xFD, 0x11, 0x40,
0xDD, 0x9C, 0xD4, 0x5E, 0x81, 0xD6, 0x9D, 0x2C, 0x87, 0x7B, 0x56, 0xAA, 0xF9, 0x91, 0xC3, 0x4D,
0x0E, 0xA8, 0x4E, 0xAF, 0x37, 0x16, 0xF7, 0xCB, 0x1C, 0x94, 0x2D, 0x65, 0x7C, 0x41, 0xD4, 0x36,
0xC7, 0xA1, 0xB6, 0xE2, 0x9F, 0x65, 0xF3, 0xE9, 0x00, 0xDB, 0xB9, 0xAF, 0xF4, 0x06, 0x4D, 0xC4,
0xAB, 0x2F, 0x84, 0x3A, 0xCD, 0xA8};

/**
* @brief Verify a sample NIST P-256 signature from a message using SHA256
*
* @return psa_status_t
*/
psa_status_t test_ecdsa_p256_vectors(void) {
psa_key_attributes_t key_attr = psa_key_attributes_init();
psa_key_id_t key_id;

psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&key_attr, algo);
psa_set_key_bits(&key_attr, PSA_BYTES_TO_BITS(sizeof(private_key)));
psa_set_key_type(&key_attr, type);

psa_status_t status;
status = psa_import_key(&key_attr, public_key, sizeof(public_key), &key_id);
if (status != PSA_SUCCESS) {
return status;
}

status = psa_verify_message(key_id, algo, message, sizeof(message), signature, sizeof(signature));

Check warning on line 71 in tests/sys/psa_crypto_ecdsa/test_ecdsa_p256_vectors.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters

psa_destroy_key(key_id);

return status;
}

0 comments on commit c46d75d

Please sign in to comment.