LCOV - code coverage report
Current view: top level - os_stub/cryptlib_mbedtls/pk - dh.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 46.2 % 106 49
Test Date: 2025-06-29 08:09:00 Functions: 66.7 % 6 4

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2024 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              :  * Diffie-Hellman Wrapper Implementation over.
       9              :  *
      10              :  * RFC 7919 - Negotiated Finite Field Diffie-Hellman Ephemeral (FFDHE) Parameters
      11              :  **/
      12              : 
      13              : #include "internal_crypt_lib.h"
      14              : #include <mbedtls/dhm.h>
      15              : #include <mbedtls/bignum.h>
      16              : #include <string.h>
      17              : 
      18              : #if LIBSPDM_FFDHE_SUPPORT
      19              : 
      20              : static const unsigned char m_ffehde2048_p[] =
      21              :     MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN;
      22              : static const unsigned char m_ffehde3072_p[] =
      23              :     MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN;
      24              : static const unsigned char m_ffehde4096_p[] =
      25              :     MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN;
      26              : static const unsigned char m_ffehde2048_g[] =
      27              :     MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN;
      28              : static const unsigned char m_ffehde3072_g[] =
      29              :     MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN;
      30              : static const unsigned char m_ffehde4096_g[] =
      31              :     MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN;
      32              : 
      33              : /**
      34              :  * Allocates and Initializes one Diffie-Hellman context for subsequent use
      35              :  * with the NID.
      36              :  *
      37              :  * @param nid cipher NID
      38              :  *
      39              :  * @return  Pointer to the Diffie-Hellman context that has been initialized.
      40              :  *         If the allocations fails, dh_new() returns NULL.
      41              :  *
      42              :  **/
      43            2 : void *libspdm_dh_new_by_nid(size_t nid)
      44              : {
      45              :     mbedtls_dhm_context *ctx;
      46              :     int ret;
      47              : 
      48            2 :     ctx = allocate_zero_pool(sizeof(mbedtls_dhm_context));
      49            2 :     if (ctx == NULL) {
      50            0 :         return NULL;
      51              :     }
      52              : 
      53            2 :     mbedtls_dhm_init(ctx);
      54              : 
      55            2 :     switch (nid) {
      56            2 :     case LIBSPDM_CRYPTO_NID_FFDHE2048:
      57            2 :         ret = mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(P), m_ffehde2048_p,
      58              :                                       sizeof(m_ffehde2048_p));
      59            2 :         if (ret != 0) {
      60            0 :             goto error;
      61              :         }
      62            2 :         ret = mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(G), m_ffehde2048_g,
      63              :                                       sizeof(m_ffehde2048_g));
      64            2 :         if (ret != 0) {
      65            0 :             goto error;
      66              :         }
      67            2 :         break;
      68            0 :     case LIBSPDM_CRYPTO_NID_FFDHE3072:
      69            0 :         ret = mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(P), m_ffehde3072_p,
      70              :                                       sizeof(m_ffehde3072_p));
      71            0 :         if (ret != 0) {
      72            0 :             goto error;
      73              :         }
      74            0 :         ret = mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(G), m_ffehde3072_g,
      75              :                                       sizeof(m_ffehde3072_g));
      76            0 :         if (ret != 0) {
      77            0 :             goto error;
      78              :         }
      79            0 :         break;
      80            0 :     case LIBSPDM_CRYPTO_NID_FFDHE4096:
      81            0 :         ret = mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(P), m_ffehde4096_p,
      82              :                                       sizeof(m_ffehde4096_p));
      83            0 :         if (ret != 0) {
      84            0 :             goto error;
      85              :         }
      86            0 :         ret = mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(G), m_ffehde4096_g,
      87              :                                       sizeof(m_ffehde4096_g));
      88            0 :         if (ret != 0) {
      89            0 :             goto error;
      90              :         }
      91            0 :         break;
      92            0 :     default:
      93            0 :         goto error;
      94              :     }
      95            2 :     return ctx;
      96            0 : error:
      97            0 :     free_pool(ctx);
      98            0 :     return NULL;
      99              : }
     100              : 
     101              : /**
     102              :  * Release the specified DH context.
     103              :  *
     104              :  * If dh_context is NULL, then return false.
     105              :  *
     106              :  * @param[in]  dh_context  Pointer to the DH context to be released.
     107              :  *
     108              :  **/
     109            2 : void libspdm_dh_free(void *dh_context)
     110              : {
     111            2 :     mbedtls_dhm_free(dh_context);
     112            2 :     free_pool(dh_context);
     113            2 : }
     114              : 
     115              : /**
     116              :  * Generates DH parameter.
     117              :  *
     118              :  * Given generator g, and length of prime number p in bits, this function generates p,
     119              :  * and sets DH context according to value of g and p.
     120              :  *
     121              :  * If dh_context is NULL, then return false.
     122              :  * If prime is NULL, then return false.
     123              :  *
     124              :  * @param[in, out]  dh_context    Pointer to the DH context.
     125              :  * @param[in]       generator    value of generator.
     126              :  * @param[in]       prime_length  length in bits of prime to be generated.
     127              :  * @param[out]      prime        Pointer to the buffer to receive the generated prime number.
     128              :  *
     129              :  * @retval true   DH parameter generation succeeded.
     130              :  * @retval false  value of generator is not supported.
     131              :  * @retval false  PRNG fails to generate random prime number with prime_length.
     132              :  *
     133              :  **/
     134            0 : bool libspdm_dh_generate_parameter(void *dh_context, size_t generator,
     135              :                                    size_t prime_length, uint8_t *prime)
     136              : {
     137            0 :     return false;
     138              : }
     139              : 
     140              : /**
     141              :  * Sets generator and prime parameters for DH.
     142              :  *
     143              :  * Given generator g, and prime number p, this function and sets DH
     144              :  * context accordingly.
     145              :  *
     146              :  * If dh_context is NULL, then return false.
     147              :  * If prime is NULL, then return false.
     148              :  *
     149              :  * @param[in, out]  dh_context    Pointer to the DH context.
     150              :  * @param[in]       generator    value of generator.
     151              :  * @param[in]       prime_length  length in bits of prime to be generated.
     152              :  * @param[in]       prime        Pointer to the prime number.
     153              :  *
     154              :  * @retval true   DH parameter setting succeeded.
     155              :  * @retval false  value of generator is not supported.
     156              :  * @retval false  value of generator is not suitable for the prime.
     157              :  * @retval false  value of prime is not a prime number.
     158              :  * @retval false  value of prime is not a safe prime number.
     159              :  *
     160              :  **/
     161            0 : bool libspdm_dh_set_parameter(void *dh_context, size_t generator,
     162              :                               size_t prime_length, const uint8_t *prime)
     163              : {
     164            0 :     return false;
     165              : }
     166              : 
     167              : /**
     168              :  * Generates DH public key.
     169              :  *
     170              :  * This function generates random secret exponent, and computes the public key, which is
     171              :  * returned via parameter public_key and public_key_size. DH context is updated accordingly.
     172              :  * If the public_key buffer is too small to hold the public key, false is returned and
     173              :  * public_key_size is set to the required buffer size to obtain the public key.
     174              :  *
     175              :  * If dh_context is NULL, then return false.
     176              :  * If public_key_size is NULL, then return false.
     177              :  * If public_key_size is large enough but public_key is NULL, then return false.
     178              :  *
     179              :  * For FFDHE2048, the public_size is 256.
     180              :  * For FFDHE3072, the public_size is 384.
     181              :  * For FFDHE4096, the public_size is 512.
     182              :  *
     183              :  * @param[in, out]  dh_context      Pointer to the DH context.
     184              :  * @param[out]      public_key      Pointer to the buffer to receive generated public key.
     185              :  * @param[in, out]  public_key_size  On input, the size of public_key buffer in bytes.
     186              :  *                                On output, the size of data returned in public_key buffer in bytes.
     187              :  *
     188              :  * @retval true   DH public key generation succeeded.
     189              :  * @retval false  DH public key generation failed.
     190              :  * @retval false  public_key_size is not large enough.
     191              :  *
     192              :  **/
     193            2 : bool libspdm_dh_generate_key(void *dh_context, uint8_t *public_key,
     194              :                              size_t *public_key_size)
     195              : {
     196              :     int ret;
     197              :     mbedtls_dhm_context *ctx;
     198              :     size_t final_pub_key_size;
     199              : 
     200              : 
     201              :     /* Check input parameters.*/
     202              : 
     203            2 :     if (dh_context == NULL || public_key_size == NULL) {
     204            0 :         return false;
     205              :     }
     206              : 
     207            2 :     if (public_key == NULL && *public_key_size != 0) {
     208            0 :         return false;
     209              :     }
     210              : 
     211            2 :     ctx = dh_context;
     212            2 :     switch (mbedtls_mpi_size(&ctx->MBEDTLS_PRIVATE(P))) {
     213            2 :     case 256:
     214            2 :         final_pub_key_size = 256;
     215            2 :         break;
     216            0 :     case 384:
     217            0 :         final_pub_key_size = 384;
     218            0 :         break;
     219            0 :     case 512:
     220            0 :         final_pub_key_size = 512;
     221            0 :         break;
     222            0 :     default:
     223            0 :         return false;
     224              :     }
     225            2 :     if (*public_key_size < final_pub_key_size) {
     226            0 :         *public_key_size = final_pub_key_size;
     227            0 :         return false;
     228              :     }
     229            2 :     *public_key_size = final_pub_key_size;
     230            2 :     libspdm_zero_mem(public_key, *public_key_size);
     231              : 
     232            2 :     ret = mbedtls_dhm_make_public(dh_context, (uint32_t)*public_key_size,
     233            2 :                                   public_key, (uint32_t)*public_key_size,
     234              :                                   libspdm_myrand, NULL);
     235            2 :     if (ret != 0) {
     236            0 :         return false;
     237              :     }
     238              : 
     239            2 :     return true;
     240              : }
     241              : 
     242              : /**
     243              :  * Computes exchanged common key.
     244              :  *
     245              :  * Given peer's public key, this function computes the exchanged common key, based on its own
     246              :  * context including value of prime modulus and random secret exponent.
     247              :  *
     248              :  * If dh_context is NULL, then return false.
     249              :  * If peer_public_key is NULL, then return false.
     250              :  * If key_size is NULL, then return false.
     251              :  * If key is NULL, then return false.
     252              :  * If key_size is not large enough, then return false.
     253              :  *
     254              :  * For FFDHE2048, the peer_public_size is 256.
     255              :  * For FFDHE3072, the peer_public_size is 384.
     256              :  * For FFDHE4096, the peer_public_size is 512.
     257              :  *
     258              :  * @param[in, out]  dh_context          Pointer to the DH context.
     259              :  * @param[in]       peer_public_key      Pointer to the peer's public key.
     260              :  * @param[in]       peer_public_key_size  size of peer's public key in bytes.
     261              :  * @param[out]      key                Pointer to the buffer to receive generated key.
     262              :  * @param[in, out]  key_size            On input, the size of key buffer in bytes.
     263              :  *                                    On output, the size of data returned in key buffer in bytes.
     264              :  *
     265              :  * @retval true   DH exchanged key generation succeeded.
     266              :  * @retval false  DH exchanged key generation failed.
     267              :  * @retval false  key_size is not large enough.
     268              :  *
     269              :  **/
     270            2 : bool libspdm_dh_compute_key(void *dh_context, const uint8_t *peer_public_key,
     271              :                             size_t peer_public_key_size, uint8_t *key,
     272              :                             size_t *key_size)
     273              : {
     274              :     int ret;
     275              :     mbedtls_dhm_context *ctx;
     276              :     size_t return_size;
     277              :     size_t dh_key_size;
     278              : 
     279              :     /* Check input parameters.*/
     280              : 
     281            2 :     if (dh_context == NULL || peer_public_key == NULL || key_size == NULL ||
     282              :         key == NULL) {
     283            0 :         return false;
     284              :     }
     285              : 
     286            2 :     if (peer_public_key_size > INT_MAX) {
     287            0 :         return false;
     288              :     }
     289              : 
     290            2 :     ctx = dh_context;
     291            2 :     switch (mbedtls_mpi_size(&ctx->MBEDTLS_PRIVATE(P))) {
     292            2 :     case 256:
     293            2 :         dh_key_size = 256;
     294            2 :         break;
     295            0 :     case 384:
     296            0 :         dh_key_size = 384;
     297            0 :         break;
     298            0 :     case 512:
     299            0 :         dh_key_size = 512;
     300            0 :         break;
     301            0 :     default:
     302            0 :         return false;
     303              :     }
     304            2 :     if (peer_public_key_size != dh_key_size) {
     305            0 :         return false;
     306              :     }
     307            2 :     if (*key_size < dh_key_size) {
     308            0 :         return false;
     309              :     }
     310            2 :     *key_size = dh_key_size;
     311              : 
     312            2 :     ret = mbedtls_dhm_read_public(dh_context, peer_public_key,
     313              :                                   peer_public_key_size);
     314            2 :     if (ret != 0) {
     315            0 :         return false;
     316              :     }
     317              : 
     318            2 :     return_size = 0;
     319            2 :     ret = mbedtls_dhm_calc_secret(dh_context, key, *key_size, &return_size,
     320              :                                   libspdm_myrand, NULL);
     321            2 :     if (ret != 0) {
     322            0 :         return false;
     323              :     }
     324              : 
     325              :     /*change the key, for example: from 0x123400 to 0x001234*/
     326            2 :     if (return_size < dh_key_size) {
     327            0 :         memmove(key + dh_key_size - return_size, key, return_size);
     328            0 :         libspdm_zero_mem(key, dh_key_size - return_size);
     329              :     }
     330              : 
     331            2 :     return true;
     332              : }
     333              : 
     334              : #endif /* LIBSPDM_FFDHE_SUPPORT */
        

Generated by: LCOV version 2.0-1