LCOV - code coverage report
Current view: top level - os_stub/cryptlib_mbedtls/pk - ec.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 44.0 % 411 181
Test Date: 2025-06-29 08:09:00 Functions: 81.8 % 11 9

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2022 DMTF. All rights reserved.
       4              :  *  License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
       5              :  **/
       6              : 
       7              : /** @file
       8              :  * Elliptic Curve Wrapper Implementation.
       9              :  *
      10              :  * RFC 8422 - Elliptic Curve Cryptography (ECC) Cipher Suites
      11              :  * FIPS 186-4 - Digital signature Standard (DSS)
      12              :  **/
      13              : 
      14              : #include "internal_crypt_lib.h"
      15              : #include <mbedtls/ecp.h>
      16              : #include <mbedtls/ecdh.h>
      17              : #include <mbedtls/ecdsa.h>
      18              : #include <mbedtls/bignum.h>
      19              : 
      20              : /**
      21              :  * Allocates and Initializes one Elliptic Curve context for subsequent use
      22              :  * with the NID.
      23              :  *
      24              :  * @param nid cipher NID
      25              :  *
      26              :  * @return  Pointer to the Elliptic Curve context that has been initialized.
      27              :  *         If the allocations fails, libspdm_ec_new_by_nid() returns NULL.
      28              :  *
      29              :  **/
      30          170 : void *libspdm_ec_new_by_nid(size_t nid)
      31              : {
      32              :     mbedtls_ecdh_context *ctx;
      33              :     mbedtls_ecp_group_id grp_id;
      34              :     int ret;
      35              : 
      36          170 :     ctx = allocate_zero_pool(sizeof(mbedtls_ecdh_context));
      37          170 :     if (ctx == NULL) {
      38            0 :         return NULL;
      39              :     }
      40          170 :     switch (nid) {
      41          170 :     case LIBSPDM_CRYPTO_NID_SECP256R1:
      42              :     case LIBSPDM_CRYPTO_NID_ECDSA_NIST_P256:
      43          170 :         grp_id = MBEDTLS_ECP_DP_SECP256R1;
      44          170 :         break;
      45            0 :     case LIBSPDM_CRYPTO_NID_SECP384R1:
      46              :     case LIBSPDM_CRYPTO_NID_ECDSA_NIST_P384:
      47            0 :         grp_id = MBEDTLS_ECP_DP_SECP384R1;
      48            0 :         break;
      49            0 :     case LIBSPDM_CRYPTO_NID_SECP521R1:
      50              :     case LIBSPDM_CRYPTO_NID_ECDSA_NIST_P521:
      51            0 :         grp_id = MBEDTLS_ECP_DP_SECP521R1;
      52            0 :         break;
      53            0 :     default:
      54            0 :         goto error;
      55              :     }
      56              : 
      57          170 :     mbedtls_ecdh_init(ctx);
      58          170 :     ret = mbedtls_ecdh_setup(ctx, grp_id);
      59          170 :     if (ret != 0) {
      60            0 :         goto error;
      61              :     }
      62          170 :     return ctx;
      63            0 : error:
      64            0 :     free_pool(ctx);
      65            0 :     return NULL;
      66              : }
      67              : 
      68              : /**
      69              :  * Release the specified EC context.
      70              :  *
      71              :  * @param[in]  ec_context  Pointer to the EC context to be released.
      72              :  *
      73              :  **/
      74         1026 : void libspdm_ec_free(void *ec_context)
      75              : {
      76         1026 :     mbedtls_ecdh_free(ec_context);
      77         1026 :     free_pool(ec_context);
      78         1026 : }
      79              : 
      80              : /**
      81              :  * Sets the public key component into the established EC context.
      82              :  *
      83              :  * For P-256, the public_size is 64. first 32-byte is X, second 32-byte is Y.
      84              :  * For P-384, the public_size is 96. first 48-byte is X, second 48-byte is Y.
      85              :  * For P-521, the public_size is 132. first 66-byte is X, second 66-byte is Y.
      86              :  *
      87              :  * @param[in, out]  ec_context      Pointer to EC context being set.
      88              :  * @param[in]       public         Pointer to the buffer to receive generated public X,Y.
      89              :  * @param[in]       public_size     The size of public buffer in bytes.
      90              :  *
      91              :  * @retval  true   EC public key component was set successfully.
      92              :  * @retval  false  Invalid EC public key component.
      93              :  *
      94              :  **/
      95            1 : bool libspdm_ec_set_pub_key(void *ec_context, const uint8_t *public_key,
      96              :                             size_t public_key_size)
      97              : {
      98              :     mbedtls_ecdh_context *ctx;
      99              :     int ret;
     100              :     size_t half_size;
     101              : 
     102            1 :     if (ec_context == NULL || public_key == NULL) {
     103            0 :         return false;
     104              :     }
     105              : 
     106            1 :     ctx = ec_context;
     107            1 :     switch (mbedtls_ecdh_get_grp_id(ctx)) {
     108            1 :     case MBEDTLS_ECP_DP_SECP256R1:
     109            1 :         half_size = 32;
     110            1 :         break;
     111            0 :     case MBEDTLS_ECP_DP_SECP384R1:
     112            0 :         half_size = 48;
     113            0 :         break;
     114            0 :     case MBEDTLS_ECP_DP_SECP521R1:
     115            0 :         half_size = 66;
     116            0 :         break;
     117            0 :     default:
     118            0 :         return false;
     119              :     }
     120            1 :     if (public_key_size != half_size * 2) {
     121            0 :         return false;
     122              :     }
     123              : 
     124            1 :     ret = mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X),
     125              :                                   public_key, half_size);
     126            1 :     if (ret != 0) {
     127            0 :         return false;
     128              :     }
     129            1 :     ret = mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y),
     130            1 :                                   public_key + half_size, half_size);
     131            1 :     if (ret != 0) {
     132            0 :         return false;
     133              :     }
     134            1 :     ret = mbedtls_mpi_lset(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1);
     135            1 :     if (ret != 0) {
     136            0 :         return false;
     137              :     }
     138              : 
     139            1 :     return true;
     140              : }
     141              : 
     142              : /**
     143              :  * Sets the private key component into the established EC context.
     144              :  *
     145              :  * For P-256, the private_key_size is 32 byte.
     146              :  * For P-384, the private_key_size is 48 byte.
     147              :  * For P-521, the private_key_size is 66 byte.
     148              :  *
     149              :  * @param[in, out]  ec_context       Pointer to EC context being set.
     150              :  * @param[in]       private_key      Pointer to the private key buffer.
     151              :  * @param[in]       private_key_size The size of private key buffer in bytes.
     152              :  *
     153              :  * @retval  true   EC private key component was set successfully.
     154              :  * @retval  false  Invalid EC private key component.
     155              :  *
     156              :  **/
     157            2 : bool libspdm_ec_set_priv_key(void *ec_context, const uint8_t *private_key,
     158              :                              size_t private_key_size)
     159              : {
     160              :     mbedtls_ecdh_context *ctx;
     161              :     int ret;
     162              :     size_t half_size;
     163              : 
     164            2 :     if (ec_context == NULL || private_key == NULL) {
     165            0 :         return false;
     166              :     }
     167              : 
     168            2 :     ctx = ec_context;
     169            2 :     switch (mbedtls_ecdh_get_grp_id(ctx)) {
     170            2 :     case MBEDTLS_ECP_DP_SECP256R1:
     171            2 :         half_size = 32;
     172            2 :         break;
     173            0 :     case MBEDTLS_ECP_DP_SECP384R1:
     174            0 :         half_size = 48;
     175            0 :         break;
     176            0 :     case MBEDTLS_ECP_DP_SECP521R1:
     177            0 :         half_size = 66;
     178            0 :         break;
     179            0 :     default:
     180            0 :         return false;
     181              :     }
     182            2 :     if (private_key_size != half_size) {
     183            0 :         return false;
     184              :     }
     185              : 
     186            2 :     ret = mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(d), private_key,
     187              :                                   private_key_size);
     188            2 :     if (ret != 0) {
     189            0 :         return false;
     190              :     }
     191              : 
     192            2 :     return true;
     193              : }
     194              : 
     195              : /**
     196              :  * Gets the public key component from the established EC context.
     197              :  *
     198              :  * For P-256, the public_size is 64. first 32-byte is X, second 32-byte is Y.
     199              :  * For P-384, the public_size is 96. first 48-byte is X, second 48-byte is Y.
     200              :  * For P-521, the public_size is 132. first 66-byte is X, second 66-byte is Y.
     201              :  *
     202              :  * @param[in, out]  ec_context      Pointer to EC context being set.
     203              :  * @param[out]      public         Pointer to the buffer to receive generated public X,Y.
     204              :  * @param[in, out]  public_size     On input, the size of public buffer in bytes.
     205              :  *                                On output, the size of data returned in public buffer in bytes.
     206              :  *
     207              :  * @retval  true   EC key component was retrieved successfully.
     208              :  * @retval  false  Invalid EC key component.
     209              :  *
     210              :  **/
     211            0 : bool libspdm_ec_get_pub_key(void *ec_context, uint8_t *public_key,
     212              :                             size_t *public_key_size)
     213              : {
     214              :     mbedtls_ecdh_context *ctx;
     215              :     int ret;
     216              :     size_t half_size;
     217              :     size_t x_size;
     218              :     size_t y_size;
     219              : 
     220            0 :     if (ec_context == NULL || public_key_size == NULL) {
     221            0 :         return false;
     222              :     }
     223              : 
     224            0 :     if (public_key == NULL && *public_key_size != 0) {
     225            0 :         return false;
     226              :     }
     227              : 
     228            0 :     ctx = ec_context;
     229            0 :     switch (mbedtls_ecdh_get_grp_id(ctx)) {
     230            0 :     case MBEDTLS_ECP_DP_SECP256R1:
     231            0 :         half_size = 32;
     232            0 :         break;
     233            0 :     case MBEDTLS_ECP_DP_SECP384R1:
     234            0 :         half_size = 48;
     235            0 :         break;
     236            0 :     case MBEDTLS_ECP_DP_SECP521R1:
     237            0 :         half_size = 66;
     238            0 :         break;
     239            0 :     default:
     240            0 :         return false;
     241              :     }
     242            0 :     if (*public_key_size < half_size * 2) {
     243            0 :         *public_key_size = half_size * 2;
     244            0 :         return false;
     245              :     }
     246            0 :     *public_key_size = half_size * 2;
     247            0 :     libspdm_zero_mem(public_key, *public_key_size);
     248              : 
     249            0 :     x_size = mbedtls_mpi_size(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X));
     250            0 :     y_size = mbedtls_mpi_size(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y));
     251            0 :     LIBSPDM_ASSERT(x_size <= half_size && y_size <= half_size);
     252              : 
     253            0 :     ret = mbedtls_mpi_write_binary(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X),
     254            0 :                                    &public_key[0 + half_size - x_size], x_size);
     255            0 :     if (ret != 0) {
     256            0 :         return false;
     257              :     }
     258            0 :     ret = mbedtls_mpi_write_binary(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y),
     259            0 :                                    &public_key[half_size + half_size - y_size],
     260              :                                    y_size);
     261            0 :     if (ret != 0) {
     262            0 :         return false;
     263              :     }
     264              : 
     265            0 :     return true;
     266              : }
     267              : 
     268              : /**
     269              :  * Validates key components of EC context.
     270              :  * NOTE: This function performs integrity checks on all the EC key material, so
     271              :  *      the EC key structure must contain all the private key data.
     272              :  *
     273              :  * If ec_context is NULL, then return false.
     274              :  *
     275              :  * @param[in]  ec_context  Pointer to EC context to check.
     276              :  *
     277              :  * @retval  true   EC key components are valid.
     278              :  * @retval  false  EC key components are not valid.
     279              :  *
     280              :  **/
     281            0 : bool libspdm_ec_check_key(const void *ec_context)
     282              : {
     283              :     /* TBD*/
     284            0 :     return true;
     285              : }
     286              : 
     287              : /**
     288              :  * Generates EC key and returns EC public key (X, Y).
     289              :  *
     290              :  * This function generates random secret, and computes the public key (X, Y), which is
     291              :  * returned via parameter public, public_size.
     292              :  * X is the first half of public with size being public_size / 2,
     293              :  * Y is the second half of public with size being public_size / 2.
     294              :  * EC context is updated accordingly.
     295              :  * If the public buffer is too small to hold the public X, Y, false is returned and
     296              :  * public_size is set to the required buffer size to obtain the public X, Y.
     297              :  *
     298              :  * For P-256, the public_size is 64. first 32-byte is X, second 32-byte is Y.
     299              :  * For P-384, the public_size is 96. first 48-byte is X, second 48-byte is Y.
     300              :  * For P-521, the public_size is 132. first 66-byte is X, second 66-byte is Y.
     301              :  *
     302              :  * If ec_context is NULL, then return false.
     303              :  * If public_size is NULL, then return false.
     304              :  * If public_size is large enough but public is NULL, then return false.
     305              :  *
     306              :  * @param[in, out]  ec_context      Pointer to the EC context.
     307              :  * @param[out]      public_data     Pointer to the buffer to receive generated public X,Y.
     308              :  * @param[in, out]  public_size     On input, the size of public buffer in bytes.
     309              :  *                                On output, the size of data returned in public buffer in bytes.
     310              :  *
     311              :  * @retval true   EC public X,Y generation succeeded.
     312              :  * @retval false  EC public X,Y generation failed.
     313              :  * @retval false  public_size is not large enough.
     314              :  *
     315              :  **/
     316          168 : bool libspdm_ec_generate_key(void *ec_context, uint8_t *public_data,
     317              :                              size_t *public_size)
     318              : {
     319              :     mbedtls_ecdh_context *ctx;
     320              :     int ret;
     321              :     size_t half_size;
     322              :     size_t x_size;
     323              :     size_t y_size;
     324              : 
     325          168 :     if (ec_context == NULL || public_size == NULL) {
     326            0 :         return false;
     327              :     }
     328              : 
     329          168 :     if (public_data == NULL && *public_size != 0) {
     330            0 :         return false;
     331              :     }
     332              : 
     333          168 :     ctx = ec_context;
     334          168 :     ret = mbedtls_ecdh_gen_public(&ctx->MBEDTLS_PRIVATE(grp),
     335              :                                   &ctx->MBEDTLS_PRIVATE(d),
     336              :                                   &ctx->MBEDTLS_PRIVATE(Q), libspdm_myrand,
     337              :                                   NULL);
     338          168 :     if (ret != 0) {
     339            0 :         return false;
     340              :     }
     341              : 
     342          168 :     switch (mbedtls_ecdh_get_grp_id(ctx)) {
     343          168 :     case MBEDTLS_ECP_DP_SECP256R1:
     344          168 :         half_size = 32;
     345          168 :         break;
     346            0 :     case MBEDTLS_ECP_DP_SECP384R1:
     347            0 :         half_size = 48;
     348            0 :         break;
     349            0 :     case MBEDTLS_ECP_DP_SECP521R1:
     350            0 :         half_size = 66;
     351            0 :         break;
     352            0 :     default:
     353            0 :         return false;
     354              :     }
     355          168 :     if (*public_size < half_size * 2) {
     356            0 :         *public_size = half_size * 2;
     357            0 :         return false;
     358              :     }
     359          168 :     *public_size = half_size * 2;
     360          168 :     libspdm_zero_mem(public_data, *public_size);
     361              : 
     362          168 :     x_size = mbedtls_mpi_size(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X));
     363          168 :     y_size = mbedtls_mpi_size(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y));
     364          168 :     LIBSPDM_ASSERT(x_size <= half_size && y_size <= half_size);
     365              : 
     366          168 :     ret = mbedtls_mpi_write_binary(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X),
     367          168 :                                    &public_data[0 + half_size - x_size], x_size);
     368          168 :     if (ret != 0) {
     369            0 :         return false;
     370              :     }
     371          168 :     ret = mbedtls_mpi_write_binary(&ctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y),
     372          168 :                                    &public_data[half_size + half_size - y_size],
     373              :                                    y_size);
     374          168 :     if (ret != 0) {
     375            0 :         return false;
     376              :     }
     377              : 
     378          168 :     return true;
     379              : }
     380              : 
     381              : /**
     382              :  * Computes exchanged common key.
     383              :  *
     384              :  * Given peer's public key (X, Y), this function computes the exchanged common key,
     385              :  * based on its own context including value of curve parameter and random secret.
     386              :  * X is the first half of peer_public with size being peer_public_size / 2,
     387              :  * Y is the second half of peer_public with size being peer_public_size / 2.
     388              :  *
     389              :  * If ec_context is NULL, then return false.
     390              :  * If peer_public is NULL, then return false.
     391              :  * If peer_public_size is 0, then return false.
     392              :  * If key is NULL, then return false.
     393              :  * If key_size is not large enough, then return false.
     394              :  *
     395              :  * For P-256, the peer_public_size is 64. first 32-byte is X, second 32-byte is Y. The key_size is 32.
     396              :  * For P-384, the peer_public_size is 96. first 48-byte is X, second 48-byte is Y. The key_size is 48.
     397              :  * For P-521, the peer_public_size is 132. first 66-byte is X, second 66-byte is Y. The key_size is 66.
     398              :  *
     399              :  * @param[in, out]  ec_context          Pointer to the EC context.
     400              :  * @param[in]       peer_public         Pointer to the peer's public X,Y.
     401              :  * @param[in]       peer_public_size     size of peer's public X,Y in bytes.
     402              :  * @param[out]      key                Pointer to the buffer to receive generated key.
     403              :  * @param[in, out]  key_size            On input, the size of key buffer in bytes.
     404              :  *                                    On output, the size of data returned in key buffer in bytes.
     405              :  *
     406              :  * @retval true   EC exchanged key generation succeeded.
     407              :  * @retval false  EC exchanged key generation failed.
     408              :  * @retval false  key_size is not large enough.
     409              :  *
     410              :  **/
     411           75 : bool libspdm_ec_compute_key(void *ec_context, const uint8_t *peer_public,
     412              :                             size_t peer_public_size, uint8_t *key,
     413              :                             size_t *key_size)
     414              : {
     415              :     mbedtls_ecdh_context *ctx;
     416              :     size_t half_size;
     417              :     int ret;
     418              : 
     419           75 :     if (ec_context == NULL || peer_public == NULL || key_size == NULL ||
     420              :         key == NULL) {
     421            0 :         return false;
     422              :     }
     423              : 
     424           75 :     if (peer_public_size > INT_MAX) {
     425            0 :         return false;
     426              :     }
     427              : 
     428           75 :     ctx = ec_context;
     429           75 :     switch (mbedtls_ecdh_get_grp_id(ctx)) {
     430           75 :     case MBEDTLS_ECP_DP_SECP256R1:
     431           75 :         half_size = 32;
     432           75 :         break;
     433            0 :     case MBEDTLS_ECP_DP_SECP384R1:
     434            0 :         half_size = 48;
     435            0 :         break;
     436            0 :     case MBEDTLS_ECP_DP_SECP521R1:
     437            0 :         half_size = 66;
     438            0 :         break;
     439            0 :     default:
     440            0 :         return false;
     441              :     }
     442           75 :     if (peer_public_size != half_size * 2) {
     443            0 :         return false;
     444              :     }
     445              : 
     446           75 :     ret = mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(Qp).MBEDTLS_PRIVATE(X),
     447              :                                   peer_public, half_size);
     448           75 :     if (ret != 0) {
     449            0 :         return false;
     450              :     }
     451           75 :     ret = mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(Qp).MBEDTLS_PRIVATE(Y),
     452           75 :                                   peer_public + half_size, half_size);
     453           75 :     if (ret != 0) {
     454            0 :         return false;
     455              :     }
     456           75 :     ret = mbedtls_mpi_lset(&ctx->MBEDTLS_PRIVATE(Qp).MBEDTLS_PRIVATE(Z), 1);
     457           75 :     if (ret != 0) {
     458            0 :         return false;
     459              :     }
     460              : 
     461           75 :     ret = mbedtls_ecdh_compute_shared(&ctx->MBEDTLS_PRIVATE(grp),
     462              :                                       &ctx->MBEDTLS_PRIVATE(z),
     463           75 :                                       &ctx->MBEDTLS_PRIVATE(Qp),
     464           75 :                                       &ctx->MBEDTLS_PRIVATE(d),
     465              :                                       libspdm_myrand, NULL);
     466           75 :     if (ret != 0) {
     467            0 :         return false;
     468              :     }
     469              : 
     470           75 :     if (mbedtls_mpi_size(&ctx->MBEDTLS_PRIVATE(z)) > *key_size) {
     471            0 :         return false;
     472              :     }
     473              : 
     474           75 :     *key_size = ctx->MBEDTLS_PRIVATE(grp).pbits / 8 +
     475           75 :                 ((ctx->MBEDTLS_PRIVATE(grp).pbits % 8) != 0);
     476           75 :     ret = mbedtls_mpi_write_binary(&ctx->MBEDTLS_PRIVATE(z), key, *key_size);
     477           75 :     if (ret != 0) {
     478            0 :         return false;
     479              :     }
     480              : 
     481           75 :     return true;
     482              : }
     483              : 
     484              : /**
     485              :  * Carries out the EC-DSA signature.
     486              :  *
     487              :  * This function carries out the EC-DSA signature.
     488              :  * If the signature buffer is too small to hold the contents of signature, false
     489              :  * is returned and sig_size is set to the required buffer size to obtain the signature.
     490              :  *
     491              :  * If ec_context is NULL, then return false.
     492              :  * If message_hash is NULL, then return false.
     493              :  * If hash_size need match the hash_nid. hash_nid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
     494              :  * If sig_size is large enough but signature is NULL, then return false.
     495              :  *
     496              :  * For P-256, the sig_size is 64. first 32-byte is R, second 32-byte is S.
     497              :  * For P-384, the sig_size is 96. first 48-byte is R, second 48-byte is S.
     498              :  * For P-521, the sig_size is 132. first 66-byte is R, second 66-byte is S.
     499              :  *
     500              :  * @param[in]       ec_context    Pointer to EC context for signature generation.
     501              :  * @param[in]       hash_nid      hash NID
     502              :  * @param[in]       message_hash  Pointer to octet message hash to be signed.
     503              :  * @param[in]       hash_size     size of the message hash in bytes.
     504              :  * @param[out]      signature    Pointer to buffer to receive EC-DSA signature.
     505              :  * @param[in, out]  sig_size      On input, the size of signature buffer in bytes.
     506              :  *                              On output, the size of data returned in signature buffer in bytes.
     507              :  *
     508              :  * @retval  true   signature successfully generated in EC-DSA.
     509              :  * @retval  false  signature generation failed.
     510              :  * @retval  false  sig_size is too small.
     511              :  *
     512              :  **/
     513          140 : bool libspdm_ecdsa_sign(void *ec_context, size_t hash_nid,
     514              :                         const uint8_t *message_hash, size_t hash_size,
     515              :                         uint8_t *signature, size_t *sig_size)
     516              : {
     517              :     int ret;
     518              :     mbedtls_ecdh_context *ctx;
     519              :     mbedtls_mpi bn_r;
     520              :     mbedtls_mpi bn_s;
     521              :     size_t r_size;
     522              :     size_t s_size;
     523              :     size_t half_size;
     524              : 
     525          140 :     if (ec_context == NULL || message_hash == NULL) {
     526            0 :         return false;
     527              :     }
     528              : 
     529          140 :     if (signature == NULL) {
     530            0 :         return false;
     531              :     }
     532              : 
     533          140 :     ctx = ec_context;
     534          140 :     switch (mbedtls_ecdh_get_grp_id(ctx)) {
     535          140 :     case MBEDTLS_ECP_DP_SECP256R1:
     536          140 :         half_size = 32;
     537          140 :         break;
     538            0 :     case MBEDTLS_ECP_DP_SECP384R1:
     539            0 :         half_size = 48;
     540            0 :         break;
     541            0 :     case MBEDTLS_ECP_DP_SECP521R1:
     542            0 :         half_size = 66;
     543            0 :         break;
     544            0 :     default:
     545            0 :         return false;
     546              :     }
     547          140 :     if (*sig_size < (size_t)(half_size * 2)) {
     548            0 :         *sig_size = half_size * 2;
     549            0 :         return false;
     550              :     }
     551          140 :     *sig_size = half_size * 2;
     552          140 :     libspdm_zero_mem(signature, *sig_size);
     553              : 
     554          140 :     switch (hash_nid) {
     555          140 :     case LIBSPDM_CRYPTO_NID_SHA256:
     556          140 :         if (hash_size != LIBSPDM_SHA256_DIGEST_SIZE) {
     557            0 :             return false;
     558              :         }
     559          140 :         break;
     560              : 
     561            0 :     case LIBSPDM_CRYPTO_NID_SHA384:
     562            0 :         if (hash_size != LIBSPDM_SHA384_DIGEST_SIZE) {
     563            0 :             return false;
     564              :         }
     565            0 :         break;
     566              : 
     567            0 :     case LIBSPDM_CRYPTO_NID_SHA512:
     568            0 :         if (hash_size != LIBSPDM_SHA512_DIGEST_SIZE) {
     569            0 :             return false;
     570              :         }
     571            0 :         break;
     572              : 
     573            0 :     case LIBSPDM_CRYPTO_NID_SHA3_256:
     574            0 :         if (hash_size != LIBSPDM_SHA3_256_DIGEST_SIZE) {
     575            0 :             return false;
     576              :         }
     577            0 :         break;
     578              : 
     579            0 :     case LIBSPDM_CRYPTO_NID_SHA3_384:
     580            0 :         if (hash_size != LIBSPDM_SHA3_384_DIGEST_SIZE) {
     581            0 :             return false;
     582              :         }
     583            0 :         break;
     584              : 
     585            0 :     case LIBSPDM_CRYPTO_NID_SHA3_512:
     586            0 :         if (hash_size != LIBSPDM_SHA3_512_DIGEST_SIZE) {
     587            0 :             return false;
     588              :         }
     589            0 :         break;
     590              : 
     591            0 :     default:
     592            0 :         return false;
     593              :     }
     594              : 
     595          140 :     mbedtls_mpi_init(&bn_r);
     596          140 :     mbedtls_mpi_init(&bn_s);
     597              : 
     598          140 :     ret = mbedtls_ecdsa_sign(&ctx->MBEDTLS_PRIVATE(grp), &bn_r, &bn_s,
     599          140 :                              &ctx->MBEDTLS_PRIVATE(d), message_hash,
     600              :                              hash_size, libspdm_myrand, NULL);
     601          140 :     if (ret != 0) {
     602            0 :         return false;
     603              :     }
     604              : 
     605          140 :     r_size = mbedtls_mpi_size(&bn_r);
     606          140 :     s_size = mbedtls_mpi_size(&bn_s);
     607          140 :     LIBSPDM_ASSERT(r_size <= half_size && s_size <= half_size);
     608              : 
     609          140 :     ret = mbedtls_mpi_write_binary(
     610          140 :         &bn_r, &signature[0 + half_size - r_size], r_size);
     611          140 :     if (ret != 0) {
     612            0 :         mbedtls_mpi_free(&bn_r);
     613            0 :         mbedtls_mpi_free(&bn_s);
     614            0 :         return false;
     615              :     }
     616          140 :     ret = mbedtls_mpi_write_binary(
     617          140 :         &bn_s, &signature[half_size + half_size - s_size], s_size);
     618          140 :     if (ret != 0) {
     619            0 :         mbedtls_mpi_free(&bn_r);
     620            0 :         mbedtls_mpi_free(&bn_s);
     621            0 :         return false;
     622              :     }
     623              : 
     624          140 :     mbedtls_mpi_free(&bn_r);
     625          140 :     mbedtls_mpi_free(&bn_s);
     626              : 
     627          140 :     return true;
     628              : }
     629              : 
     630              : /**
     631              :  * Verifies the EC-DSA signature.
     632              :  *
     633              :  * If ec_context is NULL, then return false.
     634              :  * If message_hash is NULL, then return false.
     635              :  * If signature is NULL, then return false.
     636              :  * If hash_size need match the hash_nid. hash_nid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
     637              :  *
     638              :  * For P-256, the sig_size is 64. first 32-byte is R, second 32-byte is S.
     639              :  * For P-384, the sig_size is 96. first 48-byte is R, second 48-byte is S.
     640              :  * For P-521, the sig_size is 132. first 66-byte is R, second 66-byte is S.
     641              :  *
     642              :  * @param[in]  ec_context    Pointer to EC context for signature verification.
     643              :  * @param[in]  hash_nid      hash NID
     644              :  * @param[in]  message_hash  Pointer to octet message hash to be checked.
     645              :  * @param[in]  hash_size     size of the message hash in bytes.
     646              :  * @param[in]  signature    Pointer to EC-DSA signature to be verified.
     647              :  * @param[in]  sig_size      size of signature in bytes.
     648              :  *
     649              :  * @retval  true   Valid signature encoded in EC-DSA.
     650              :  * @retval  false  Invalid signature or invalid EC context.
     651              :  *
     652              :  **/
     653           83 : bool libspdm_ecdsa_verify(void *ec_context, size_t hash_nid,
     654              :                           const uint8_t *message_hash, size_t hash_size,
     655              :                           const uint8_t *signature, size_t sig_size)
     656              : {
     657              :     int ret;
     658              :     mbedtls_ecdh_context *ctx;
     659              :     mbedtls_mpi bn_r;
     660              :     mbedtls_mpi bn_s;
     661              :     size_t half_size;
     662              : 
     663           83 :     if (ec_context == NULL || message_hash == NULL || signature == NULL) {
     664            0 :         return false;
     665              :     }
     666              : 
     667           83 :     if (sig_size > INT_MAX || sig_size == 0) {
     668            0 :         return false;
     669              :     }
     670              : 
     671           83 :     ctx = ec_context;
     672           83 :     switch (mbedtls_ecdh_get_grp_id(ctx)) {
     673           83 :     case MBEDTLS_ECP_DP_SECP256R1:
     674           83 :         half_size = 32;
     675           83 :         break;
     676            0 :     case MBEDTLS_ECP_DP_SECP384R1:
     677            0 :         half_size = 48;
     678            0 :         break;
     679            0 :     case MBEDTLS_ECP_DP_SECP521R1:
     680            0 :         half_size = 66;
     681            0 :         break;
     682            0 :     default:
     683            0 :         return false;
     684              :     }
     685           83 :     if (sig_size != (size_t)(half_size * 2)) {
     686            0 :         return false;
     687              :     }
     688              : 
     689           83 :     switch (hash_nid) {
     690           83 :     case LIBSPDM_CRYPTO_NID_SHA256:
     691           83 :         if (hash_size != LIBSPDM_SHA256_DIGEST_SIZE) {
     692            0 :             return false;
     693              :         }
     694           83 :         break;
     695              : 
     696            0 :     case LIBSPDM_CRYPTO_NID_SHA384:
     697            0 :         if (hash_size != LIBSPDM_SHA384_DIGEST_SIZE) {
     698            0 :             return false;
     699              :         }
     700            0 :         break;
     701              : 
     702            0 :     case LIBSPDM_CRYPTO_NID_SHA512:
     703            0 :         if (hash_size != LIBSPDM_SHA512_DIGEST_SIZE) {
     704            0 :             return false;
     705              :         }
     706            0 :         break;
     707              : 
     708            0 :     case LIBSPDM_CRYPTO_NID_SHA3_256:
     709            0 :         if (hash_size != LIBSPDM_SHA3_256_DIGEST_SIZE) {
     710            0 :             return false;
     711              :         }
     712            0 :         break;
     713              : 
     714            0 :     case LIBSPDM_CRYPTO_NID_SHA3_384:
     715            0 :         if (hash_size != LIBSPDM_SHA3_384_DIGEST_SIZE) {
     716            0 :             return false;
     717              :         }
     718            0 :         break;
     719              : 
     720            0 :     case LIBSPDM_CRYPTO_NID_SHA3_512:
     721            0 :         if (hash_size != LIBSPDM_SHA3_512_DIGEST_SIZE) {
     722            0 :             return false;
     723              :         }
     724            0 :         break;
     725              : 
     726            0 :     default:
     727            0 :         return false;
     728              :     }
     729              : 
     730           83 :     mbedtls_mpi_init(&bn_r);
     731           83 :     mbedtls_mpi_init(&bn_s);
     732              : 
     733           83 :     ret = mbedtls_mpi_read_binary(&bn_r, signature, half_size);
     734           83 :     if (ret != 0) {
     735            0 :         mbedtls_mpi_free(&bn_r);
     736            0 :         mbedtls_mpi_free(&bn_s);
     737            0 :         return false;
     738              :     }
     739           83 :     ret = mbedtls_mpi_read_binary(&bn_s, signature + half_size, half_size);
     740           83 :     if (ret != 0) {
     741            0 :         mbedtls_mpi_free(&bn_r);
     742            0 :         mbedtls_mpi_free(&bn_s);
     743            0 :         return false;
     744              :     }
     745              : 
     746           83 :     ret = mbedtls_ecdsa_verify(&ctx->MBEDTLS_PRIVATE(grp), message_hash,
     747           83 :                                hash_size, &ctx->MBEDTLS_PRIVATE(Q),
     748              :                                &bn_r, &bn_s);
     749           83 :     mbedtls_mpi_free(&bn_r);
     750           83 :     mbedtls_mpi_free(&bn_s);
     751              : 
     752           83 :     if (ret != 0) {
     753           17 :         return false;
     754              :     }
     755              : 
     756           66 :     return true;
     757              : }
     758              : 
     759              : #if LIBSPDM_FIPS_MODE
     760              : /**
     761              :  * Carries out the EC-DSA signature with caller input random function. This API can be used for FIPS test.
     762              :  *
     763              :  * @param[in]       ec_context    Pointer to EC context for signature generation.
     764              :  * @param[in]       hash_nid      hash NID
     765              :  * @param[in]       message_hash  Pointer to octet message hash to be signed.
     766              :  * @param[in]       hash_size     Size of the message hash in bytes.
     767              :  * @param[out]      signature     Pointer to buffer to receive EC-DSA signature.
     768              :  * @param[in, out]  sig_size      On input, the size of signature buffer in bytes.
     769              :  *                                On output, the size of data returned in signature buffer in bytes.
     770              :  * @param[in]       random_func   random number function
     771              :  *
     772              :  * @retval  true   signature successfully generated in EC-DSA.
     773              :  * @retval  false  signature generation failed.
     774              :  * @retval  false  sig_size is too small.
     775              :  **/
     776            1 : bool libspdm_ecdsa_sign_ex(void *ec_context, size_t hash_nid,
     777              :                            const uint8_t *message_hash, size_t hash_size,
     778              :                            uint8_t *signature, size_t *sig_size,
     779              :                            int (*random_func)(void *, unsigned char *, size_t))
     780              : {
     781              :     int ret;
     782              :     mbedtls_ecdh_context *ctx;
     783              :     mbedtls_mpi bn_r;
     784              :     mbedtls_mpi bn_s;
     785              :     size_t r_size;
     786              :     size_t s_size;
     787              :     size_t half_size;
     788              : 
     789            1 :     if (ec_context == NULL || message_hash == NULL) {
     790            0 :         return false;
     791              :     }
     792              : 
     793            1 :     if (signature == NULL) {
     794            0 :         return false;
     795              :     }
     796              : 
     797            1 :     ctx = ec_context;
     798            1 :     switch (mbedtls_ecdh_get_grp_id(ctx)) {
     799            1 :     case MBEDTLS_ECP_DP_SECP256R1:
     800            1 :         half_size = 32;
     801            1 :         break;
     802            0 :     case MBEDTLS_ECP_DP_SECP384R1:
     803            0 :         half_size = 48;
     804            0 :         break;
     805            0 :     case MBEDTLS_ECP_DP_SECP521R1:
     806            0 :         half_size = 66;
     807            0 :         break;
     808            0 :     default:
     809            0 :         return false;
     810              :     }
     811            1 :     if (*sig_size < (size_t)(half_size * 2)) {
     812            0 :         *sig_size = half_size * 2;
     813            0 :         return false;
     814              :     }
     815            1 :     *sig_size = half_size * 2;
     816            1 :     libspdm_zero_mem(signature, *sig_size);
     817              : 
     818            1 :     switch (hash_nid) {
     819            1 :     case LIBSPDM_CRYPTO_NID_SHA256:
     820            1 :         if (hash_size != LIBSPDM_SHA256_DIGEST_SIZE) {
     821            0 :             return false;
     822              :         }
     823            1 :         break;
     824              : 
     825            0 :     case LIBSPDM_CRYPTO_NID_SHA384:
     826            0 :         if (hash_size != LIBSPDM_SHA384_DIGEST_SIZE) {
     827            0 :             return false;
     828              :         }
     829            0 :         break;
     830              : 
     831            0 :     case LIBSPDM_CRYPTO_NID_SHA512:
     832            0 :         if (hash_size != LIBSPDM_SHA512_DIGEST_SIZE) {
     833            0 :             return false;
     834              :         }
     835            0 :         break;
     836              : 
     837            0 :     case LIBSPDM_CRYPTO_NID_SHA3_256:
     838            0 :         if (hash_size != LIBSPDM_SHA3_256_DIGEST_SIZE) {
     839            0 :             return false;
     840              :         }
     841            0 :         break;
     842              : 
     843            0 :     case LIBSPDM_CRYPTO_NID_SHA3_384:
     844            0 :         if (hash_size != LIBSPDM_SHA3_384_DIGEST_SIZE) {
     845            0 :             return false;
     846              :         }
     847            0 :         break;
     848              : 
     849            0 :     case LIBSPDM_CRYPTO_NID_SHA3_512:
     850            0 :         if (hash_size != LIBSPDM_SHA3_512_DIGEST_SIZE) {
     851            0 :             return false;
     852              :         }
     853            0 :         break;
     854              : 
     855            0 :     default:
     856            0 :         return false;
     857              :     }
     858              : 
     859            1 :     mbedtls_mpi_init(&bn_r);
     860            1 :     mbedtls_mpi_init(&bn_s);
     861              : 
     862              :     /*retrieve random number*/
     863            1 :     ret = mbedtls_ecdsa_sign(&ctx->MBEDTLS_PRIVATE(grp), &bn_r, &bn_s,
     864            1 :                              &ctx->MBEDTLS_PRIVATE(d), message_hash,
     865              :                              hash_size, random_func, NULL);
     866            1 :     if (ret != 0) {
     867            0 :         return false;
     868              :     }
     869              : 
     870            1 :     r_size = mbedtls_mpi_size(&bn_r);
     871            1 :     s_size = mbedtls_mpi_size(&bn_s);
     872            1 :     LIBSPDM_ASSERT(r_size <= half_size && s_size <= half_size);
     873              : 
     874            1 :     ret = mbedtls_mpi_write_binary(
     875            1 :         &bn_r, &signature[0 + half_size - r_size], r_size);
     876            1 :     if (ret != 0) {
     877            0 :         mbedtls_mpi_free(&bn_r);
     878            0 :         mbedtls_mpi_free(&bn_s);
     879            0 :         return false;
     880              :     }
     881            1 :     ret = mbedtls_mpi_write_binary(
     882            1 :         &bn_s, &signature[half_size + half_size - s_size], s_size);
     883            1 :     if (ret != 0) {
     884            0 :         mbedtls_mpi_free(&bn_r);
     885            0 :         mbedtls_mpi_free(&bn_s);
     886            0 :         return false;
     887              :     }
     888              : 
     889            1 :     mbedtls_mpi_free(&bn_r);
     890            1 :     mbedtls_mpi_free(&bn_s);
     891              : 
     892            1 :     return true;
     893              : }
     894              : #endif/*LIBSPDM_FIPS_MODE*/
        

Generated by: LCOV version 2.0-1