quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

p256-m_driver_entrypoints.c (10453B)


      1 /*
      2  *  Driver entry points for p256-m
      3  */
      4 /*
      5  *  Copyright The Mbed TLS Contributors
      6  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
      7  */
      8 
      9 #include "mbedtls/platform.h"
     10 #include "p256-m_driver_entrypoints.h"
     11 #include "p256-m/p256-m.h"
     12 #include "psa/crypto.h"
     13 #include <stddef.h>
     14 #include <string.h>
     15 #include "psa_crypto_driver_wrappers_no_static.h"
     16 
     17 #if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)
     18 
     19 /* INFORMATION ON PSA KEY EXPORT FORMATS:
     20  *
     21  * PSA exports SECP256R1 keys in two formats:
     22  * 1. Keypair format: 32 byte string which is just the private key (public key
     23  *                    can be calculated from the private key)
     24  * 2. Public Key format: A leading byte 0x04 (indicating uncompressed format),
     25  *                       followed by the 64 byte public key. This results in a
     26  *                       total of 65 bytes.
     27  *
     28  * p256-m's internal format for private keys matches PSA. Its format for public
     29  * keys is only 64 bytes: the same as PSA but without the leading byte (0x04).
     30  * Hence, when passing public keys from PSA to p256-m, the leading byte is
     31  * removed.
     32  *
     33  * Shared secret and signature have the same format between PSA and p256-m.
     34  */
     35 #define PSA_PUBKEY_SIZE         65
     36 #define PSA_PUBKEY_HEADER_BYTE  0x04
     37 #define P256_PUBKEY_SIZE        64
     38 #define PRIVKEY_SIZE            32
     39 #define SHARED_SECRET_SIZE      32
     40 #define SIGNATURE_SIZE          64
     41 
     42 #define CURVE_BITS              256
     43 
     44 /* Convert between p256-m and PSA error codes */
     45 static psa_status_t p256_to_psa_error(int ret)
     46 {
     47     switch (ret) {
     48         case P256_SUCCESS:
     49             return PSA_SUCCESS;
     50         case P256_INVALID_PUBKEY:
     51         case P256_INVALID_PRIVKEY:
     52             return PSA_ERROR_INVALID_ARGUMENT;
     53         case P256_INVALID_SIGNATURE:
     54             return PSA_ERROR_INVALID_SIGNATURE;
     55         case P256_RANDOM_FAILED:
     56         default:
     57             return PSA_ERROR_GENERIC_ERROR;
     58     }
     59 }
     60 
     61 psa_status_t p256_transparent_import_key(const psa_key_attributes_t *attributes,
     62                              const uint8_t *data,
     63                              size_t data_length,
     64                              uint8_t *key_buffer,
     65                              size_t key_buffer_size,
     66                              size_t *key_buffer_length,
     67                              size_t *bits)
     68 {
     69     /* Check the key size */
     70     if (*bits != 0 && *bits != CURVE_BITS) {
     71         return PSA_ERROR_NOT_SUPPORTED;
     72     }
     73 
     74     /* Validate the key (and its type and size) */
     75     psa_key_type_t type = psa_get_key_type(attributes);
     76     if (type == PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)) {
     77         if (data_length != PSA_PUBKEY_SIZE) {
     78             return *bits == 0 ? PSA_ERROR_NOT_SUPPORTED : PSA_ERROR_INVALID_ARGUMENT;
     79         }
     80         /* See INFORMATION ON PSA KEY EXPORT FORMATS near top of file */
     81         if (p256_validate_pubkey(data + 1) != P256_SUCCESS) {
     82             return PSA_ERROR_INVALID_ARGUMENT;
     83         }
     84     } else if (type == PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)) {
     85         if (data_length != PRIVKEY_SIZE) {
     86             return *bits == 0 ? PSA_ERROR_NOT_SUPPORTED : PSA_ERROR_INVALID_ARGUMENT;
     87         }
     88         if (p256_validate_privkey(data) != P256_SUCCESS) {
     89             return PSA_ERROR_INVALID_ARGUMENT;
     90         }
     91     } else {
     92         return PSA_ERROR_NOT_SUPPORTED;
     93     }
     94     *bits = CURVE_BITS;
     95 
     96     /* We only support the export format for input, so just copy. */
     97     if (key_buffer_size < data_length) {
     98         return PSA_ERROR_BUFFER_TOO_SMALL;
     99     }
    100     memcpy(key_buffer, data, data_length);
    101     *key_buffer_length = data_length;
    102 
    103     return PSA_SUCCESS;
    104 }
    105 
    106 psa_status_t p256_transparent_export_public_key(const psa_key_attributes_t *attributes,
    107                                     const uint8_t *key_buffer,
    108                                     size_t key_buffer_size,
    109                                     uint8_t *data,
    110                                     size_t data_size,
    111                                     size_t *data_length)
    112 {
    113     /* Is this the right curve? */
    114     size_t bits = psa_get_key_bits(attributes);
    115     psa_key_type_t type = psa_get_key_type(attributes);
    116     if (bits != CURVE_BITS || type != PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)) {
    117         return PSA_ERROR_NOT_SUPPORTED;
    118     }
    119 
    120     /* Validate sizes, as p256-m expects fixed-size buffers */
    121     if (key_buffer_size != PRIVKEY_SIZE) {
    122         return PSA_ERROR_INVALID_ARGUMENT;
    123     }
    124     if (data_size < PSA_PUBKEY_SIZE) {
    125         return PSA_ERROR_BUFFER_TOO_SMALL;
    126     }
    127 
    128     /* See INFORMATION ON PSA KEY EXPORT FORMATS near top of file */
    129     data[0] = PSA_PUBKEY_HEADER_BYTE;
    130     int ret = p256_public_from_private(data + 1, key_buffer);
    131     if (ret == P256_SUCCESS) {
    132         *data_length = PSA_PUBKEY_SIZE;
    133     }
    134 
    135     return p256_to_psa_error(ret);
    136 }
    137 
    138 psa_status_t p256_transparent_generate_key(
    139     const psa_key_attributes_t *attributes,
    140     uint8_t *key_buffer,
    141     size_t key_buffer_size,
    142     size_t *key_buffer_length)
    143 {
    144     /* We don't use this argument, but the specification mandates the signature
    145      * of driver entry-points. (void) used to avoid compiler warning. */
    146     (void) attributes;
    147 
    148     /* Validate sizes, as p256-m expects fixed-size buffers */
    149     if (key_buffer_size != PRIVKEY_SIZE) {
    150         return PSA_ERROR_BUFFER_TOO_SMALL;
    151     }
    152 
    153     /*
    154      *  p256-m's keypair generation function outputs both public and private
    155      *  keys. Allocate a buffer to which the public key will be written. The
    156      *  private key will be written to key_buffer, which is passed to this
    157      *  function as an argument. */
    158     uint8_t public_key_buffer[P256_PUBKEY_SIZE];
    159 
    160     int ret = p256_gen_keypair(key_buffer, public_key_buffer);
    161     if (ret == P256_SUCCESS) {
    162         *key_buffer_length = PRIVKEY_SIZE;
    163     }
    164 
    165     return p256_to_psa_error(ret);
    166 }
    167 
    168 psa_status_t p256_transparent_key_agreement(
    169     const psa_key_attributes_t *attributes,
    170     const uint8_t *key_buffer,
    171     size_t key_buffer_size,
    172     psa_algorithm_t alg,
    173     const uint8_t *peer_key,
    174     size_t peer_key_length,
    175     uint8_t *shared_secret,
    176     size_t shared_secret_size,
    177     size_t *shared_secret_length)
    178 {
    179     /* We don't use these arguments, but the specification mandates the
    180      * sginature of driver entry-points. (void) used to avoid compiler
    181      * warning. */
    182     (void) attributes;
    183     (void) alg;
    184 
    185     /* Validate sizes, as p256-m expects fixed-size buffers */
    186     if (key_buffer_size != PRIVKEY_SIZE || peer_key_length != PSA_PUBKEY_SIZE) {
    187         return PSA_ERROR_INVALID_ARGUMENT;
    188     }
    189     if (shared_secret_size < SHARED_SECRET_SIZE) {
    190         return PSA_ERROR_BUFFER_TOO_SMALL;
    191     }
    192 
    193     /* See INFORMATION ON PSA KEY EXPORT FORMATS near top of file */
    194     const uint8_t *peer_key_p256m = peer_key + 1;
    195     int ret = p256_ecdh_shared_secret(shared_secret, key_buffer, peer_key_p256m);
    196     if (ret == P256_SUCCESS) {
    197         *shared_secret_length = SHARED_SECRET_SIZE;
    198     }
    199 
    200     return p256_to_psa_error(ret);
    201 }
    202 
    203 psa_status_t p256_transparent_sign_hash(
    204     const psa_key_attributes_t *attributes,
    205     const uint8_t *key_buffer,
    206     size_t key_buffer_size,
    207     psa_algorithm_t alg,
    208     const uint8_t *hash,
    209     size_t hash_length,
    210     uint8_t *signature,
    211     size_t signature_size,
    212     size_t *signature_length)
    213 {
    214     /* We don't use these arguments, but the specification mandates the
    215      * sginature of driver entry-points. (void) used to avoid compiler
    216      * warning. */
    217     (void) attributes;
    218     (void) alg;
    219 
    220     /* Validate sizes, as p256-m expects fixed-size buffers */
    221     if (key_buffer_size != PRIVKEY_SIZE) {
    222         return PSA_ERROR_INVALID_ARGUMENT;
    223     }
    224     if (signature_size < SIGNATURE_SIZE) {
    225         return PSA_ERROR_BUFFER_TOO_SMALL;
    226     }
    227 
    228     int ret = p256_ecdsa_sign(signature, key_buffer, hash, hash_length);
    229     if (ret == P256_SUCCESS) {
    230         *signature_length = SIGNATURE_SIZE;
    231     }
    232 
    233     return p256_to_psa_error(ret);
    234 }
    235 
    236 /*  This function expects the key buffer to contain a PSA public key,
    237  *  as exported by psa_export_public_key() */
    238 static psa_status_t p256_verify_hash_with_public_key(
    239     const uint8_t *key_buffer,
    240     size_t key_buffer_size,
    241     const uint8_t *hash,
    242     size_t hash_length,
    243     const uint8_t *signature,
    244     size_t signature_length)
    245 {
    246     /* Validate sizes, as p256-m expects fixed-size buffers */
    247     if (key_buffer_size != PSA_PUBKEY_SIZE || *key_buffer != PSA_PUBKEY_HEADER_BYTE) {
    248         return PSA_ERROR_INVALID_ARGUMENT;
    249     }
    250     if (signature_length != SIGNATURE_SIZE) {
    251         return PSA_ERROR_INVALID_SIGNATURE;
    252     }
    253 
    254     /* See INFORMATION ON PSA KEY EXPORT FORMATS near top of file */
    255     const uint8_t *public_key_p256m = key_buffer + 1;
    256     int ret = p256_ecdsa_verify(signature, public_key_p256m, hash, hash_length);
    257 
    258     return p256_to_psa_error(ret);
    259 }
    260 
    261 psa_status_t p256_transparent_verify_hash(
    262     const psa_key_attributes_t *attributes,
    263     const uint8_t *key_buffer,
    264     size_t key_buffer_size,
    265     psa_algorithm_t alg,
    266     const uint8_t *hash,
    267     size_t hash_length,
    268     const uint8_t *signature,
    269     size_t signature_length)
    270 {
    271     /* We don't use this argument, but the specification mandates the signature
    272      * of driver entry-points. (void) used to avoid compiler warning. */
    273     (void) alg;
    274 
    275     psa_status_t status;
    276     uint8_t public_key_buffer[PSA_PUBKEY_SIZE];
    277     size_t public_key_buffer_size = PSA_PUBKEY_SIZE;
    278 
    279     size_t public_key_length = PSA_PUBKEY_SIZE;
    280     /* As p256-m doesn't require dynamic allocation, we want to avoid it in
    281      * the entrypoint functions as well. psa_driver_wrapper_export_public_key()
    282      * requires size_t*, so we use a pointer to a stack variable. */
    283     size_t *public_key_length_ptr = &public_key_length;
    284 
    285     /* The contents of key_buffer may either be the 32 byte private key
    286      * (keypair format), or 0x04 followed by the 64 byte public key (public
    287      * key format). To ensure the key is in the latter format, the public key
    288      * is exported. */
    289     status = psa_driver_wrapper_export_public_key(
    290         attributes,
    291         key_buffer,
    292         key_buffer_size,
    293         public_key_buffer,
    294         public_key_buffer_size,
    295         public_key_length_ptr);
    296     if (status != PSA_SUCCESS) {
    297         goto exit;
    298     }
    299 
    300     status = p256_verify_hash_with_public_key(
    301         public_key_buffer,
    302         public_key_buffer_size,
    303         hash,
    304         hash_length,
    305         signature,
    306         signature_length);
    307 
    308 exit:
    309     return status;
    310 }
    311 
    312 #endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */