LCOV - code coverage report
Current view: top level - os_stub/mbedtlslib/mbedtls/library - pkwrite.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 29.8 % 168 50
Test Date: 2025-06-29 08:09:00 Functions: 41.7 % 12 5

            Line data    Source code
       1              : /*
       2              :  *  Public Key layer for writing key files and structures
       3              :  *
       4              :  *  Copyright The Mbed TLS Contributors
       5              :  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
       6              :  */
       7              : 
       8              : #include "common.h"
       9              : 
      10              : #if defined(MBEDTLS_PK_WRITE_C)
      11              : 
      12              : #include "mbedtls/pk.h"
      13              : #include "mbedtls/asn1write.h"
      14              : #include "mbedtls/oid.h"
      15              : #include "mbedtls/platform_util.h"
      16              : #include "mbedtls/error.h"
      17              : #include "pk_internal.h"
      18              : 
      19              : #include <string.h>
      20              : 
      21              : #if defined(MBEDTLS_ECP_C)
      22              : #include "mbedtls/bignum.h"
      23              : #include "mbedtls/ecp.h"
      24              : #include "mbedtls/platform_util.h"
      25              : #endif
      26              : #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
      27              : #include "pk_internal.h"
      28              : #endif
      29              : #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_HAVE_ECC_KEYS)
      30              : #include "pkwrite.h"
      31              : #endif
      32              : #if defined(MBEDTLS_PEM_WRITE_C)
      33              : #include "mbedtls/pem.h"
      34              : #endif
      35              : #if defined(MBEDTLS_RSA_C)
      36              : #include "rsa_internal.h"
      37              : #endif
      38              : 
      39              : #if defined(MBEDTLS_USE_PSA_CRYPTO)
      40              : #include "psa/crypto.h"
      41              : #include "psa_util_internal.h"
      42              : #endif
      43              : #include "mbedtls/platform.h"
      44              : 
      45              : /* Helpers for properly sizing buffers aimed at holding public keys or
      46              :  * key-pairs based on build symbols. */
      47              : #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
      48              : #define PK_MAX_EC_PUBLIC_KEY_SIZE       PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
      49              : #define PK_MAX_EC_KEY_PAIR_SIZE         MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH
      50              : #elif defined(MBEDTLS_USE_PSA_CRYPTO)
      51              : #define PK_MAX_EC_PUBLIC_KEY_SIZE       PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
      52              : #define PK_MAX_EC_KEY_PAIR_SIZE         MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH
      53              : #else
      54              : #define PK_MAX_EC_PUBLIC_KEY_SIZE       MBEDTLS_ECP_MAX_PT_LEN
      55              : #define PK_MAX_EC_KEY_PAIR_SIZE         MBEDTLS_ECP_MAX_BYTES
      56              : #endif
      57              : 
      58              : /******************************************************************************
      59              :  * Internal functions for RSA keys.
      60              :  ******************************************************************************/
      61              : #if defined(MBEDTLS_RSA_C)
      62            0 : static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
      63              :                             const mbedtls_pk_context *pk)
      64              : {
      65              : #if defined(MBEDTLS_USE_PSA_CRYPTO)
      66              :     if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
      67              :         uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
      68              :         size_t tmp_len = 0;
      69              : 
      70              :         if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) {
      71              :             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
      72              :         }
      73              :         /* Ensure there's enough space in the provided buffer before copying data into it. */
      74              :         if (tmp_len > (size_t) (*p - buf)) {
      75              :             mbedtls_platform_zeroize(tmp, sizeof(tmp));
      76              :             return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
      77              :         }
      78              :         *p -= tmp_len;
      79              :         memcpy(*p, tmp, tmp_len);
      80              :         mbedtls_platform_zeroize(tmp, sizeof(tmp));
      81              : 
      82              :         return (int) tmp_len;
      83              :     }
      84              : #endif /* MBEDTLS_USE_PSA_CRYPTO */
      85            0 :     return mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), buf, p);
      86              : }
      87              : #endif /* MBEDTLS_RSA_C */
      88              : 
      89              : /******************************************************************************
      90              :  * Internal functions for EC keys.
      91              :  ******************************************************************************/
      92              : #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
      93              : #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
      94              : static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
      95              :                               const mbedtls_pk_context *pk)
      96              : {
      97              :     size_t len = 0;
      98              :     uint8_t buf[PK_MAX_EC_PUBLIC_KEY_SIZE];
      99              : 
     100              :     if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
     101              :         if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
     102              :             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     103              :         }
     104              :     } else {
     105              :         len = pk->pub_raw_len;
     106              :         memcpy(buf, pk->pub_raw, len);
     107              :     }
     108              : 
     109              :     if (*p < start || (size_t) (*p - start) < len) {
     110              :         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
     111              :     }
     112              : 
     113              :     *p -= len;
     114              :     memcpy(*p, buf, len);
     115              : 
     116              :     return (int) len;
     117              : }
     118              : #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
     119           12 : static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
     120              :                               const mbedtls_pk_context *pk)
     121              : {
     122           12 :     size_t len = 0;
     123              :     unsigned char buf[PK_MAX_EC_PUBLIC_KEY_SIZE];
     124           12 :     mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk);
     125           12 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     126              : 
     127              : #if defined(MBEDTLS_USE_PSA_CRYPTO)
     128              :     if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
     129              :         if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
     130              :             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     131              :         }
     132              :         /* Ensure there's enough space in the provided buffer before copying data into it. */
     133              :         if (len > (size_t) (*p - start)) {
     134              :             return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
     135              :         }
     136              :         *p -= len;
     137              :         memcpy(*p, buf, len);
     138              :         return (int) len;
     139              :     } else
     140              : #endif /* MBEDTLS_USE_PSA_CRYPTO */
     141              :     {
     142           12 :         if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q,
     143              :                                                   MBEDTLS_ECP_PF_UNCOMPRESSED,
     144              :                                                   &len, buf, sizeof(buf))) != 0) {
     145            0 :             return ret;
     146              :         }
     147              :     }
     148              : 
     149           12 :     if (*p < start || (size_t) (*p - start) < len) {
     150            0 :         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
     151              :     }
     152              : 
     153           12 :     *p -= len;
     154           12 :     memcpy(*p, buf, len);
     155              : 
     156           12 :     return (int) len;
     157              : }
     158              : #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
     159              : 
     160              : /*
     161              :  * privateKey  OCTET STRING -- always of length ceil(log2(n)/8)
     162              :  */
     163              : #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
     164              : static int pk_write_ec_private(unsigned char **p, unsigned char *start,
     165              :                                const mbedtls_pk_context *pk)
     166              : {
     167              :     size_t byte_length;
     168              :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     169              :     unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE];
     170              :     psa_status_t status;
     171              : 
     172              :     if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
     173              :         status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
     174              :         if (status != PSA_SUCCESS) {
     175              :             ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
     176              :             return ret;
     177              :         }
     178              :     } else {
     179              :         status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
     180              :         if (status != PSA_SUCCESS) {
     181              :             ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
     182              :             goto exit;
     183              :         }
     184              :     }
     185              : 
     186              :     ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
     187              : exit:
     188              :     mbedtls_platform_zeroize(tmp, sizeof(tmp));
     189              :     return ret;
     190              : }
     191              : #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
     192            0 : static int pk_write_ec_private(unsigned char **p, unsigned char *start,
     193              :                                const mbedtls_pk_context *pk)
     194              : {
     195              :     size_t byte_length;
     196            0 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     197              :     unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE];
     198              : 
     199              : #if defined(MBEDTLS_USE_PSA_CRYPTO)
     200              :     psa_status_t status;
     201              :     if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
     202              :         status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
     203              :         if (status != PSA_SUCCESS) {
     204              :             ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
     205              :             return ret;
     206              :         }
     207              :     } else
     208              : #endif /* MBEDTLS_USE_PSA_CRYPTO */
     209              :     {
     210            0 :         mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk);
     211            0 :         byte_length = (ec->grp.pbits + 7) / 8;
     212              : 
     213            0 :         ret = mbedtls_ecp_write_key_ext(ec, &byte_length, tmp, sizeof(tmp));
     214            0 :         if (ret != 0) {
     215            0 :             goto exit;
     216              :         }
     217              :     }
     218            0 :     ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
     219            0 : exit:
     220            0 :     mbedtls_platform_zeroize(tmp, sizeof(tmp));
     221            0 :     return ret;
     222              : }
     223              : #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
     224              : 
     225              : /*
     226              :  * ECParameters ::= CHOICE {
     227              :  *   namedCurve         OBJECT IDENTIFIER
     228              :  * }
     229              :  */
     230           12 : static int pk_write_ec_param(unsigned char **p, unsigned char *start,
     231              :                              mbedtls_ecp_group_id grp_id)
     232              : {
     233           12 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     234           12 :     size_t len = 0;
     235              :     const char *oid;
     236              :     size_t oid_len;
     237              : 
     238           12 :     if ((ret = mbedtls_oid_get_oid_by_ec_grp(grp_id, &oid, &oid_len)) != 0) {
     239            0 :         return ret;
     240              :     }
     241              : 
     242           12 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
     243              : 
     244           12 :     return (int) len;
     245              : }
     246              : 
     247              : #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
     248              : /*
     249              :  * RFC8410 section 7
     250              :  *
     251              :  * OneAsymmetricKey ::= SEQUENCE {
     252              :  *    version Version,
     253              :  *    privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
     254              :  *    privateKey PrivateKey,
     255              :  *    attributes [0] IMPLICIT Attributes OPTIONAL,
     256              :  *    ...,
     257              :  *    [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]],
     258              :  *    ...
     259              :  * }
     260              :  * ...
     261              :  * CurvePrivateKey ::= OCTET STRING
     262              :  */
     263            0 : static int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf,
     264              :                                    const mbedtls_pk_context *pk)
     265              : {
     266            0 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     267            0 :     size_t len = 0;
     268            0 :     size_t oid_len = 0;
     269              :     const char *oid;
     270              :     mbedtls_ecp_group_id grp_id;
     271              : 
     272              :     /* privateKey */
     273            0 :     MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
     274            0 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
     275            0 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_OCTET_STRING));
     276              : 
     277            0 :     grp_id = mbedtls_pk_get_ec_group_id(pk);
     278              :     /* privateKeyAlgorithm */
     279            0 :     if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(grp_id, &oid, &oid_len)) != 0) {
     280            0 :         return ret;
     281              :     }
     282            0 :     MBEDTLS_ASN1_CHK_ADD(len,
     283              :                          mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0));
     284              : 
     285              :     /* version */
     286            0 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0));
     287              : 
     288            0 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
     289            0 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |
     290              :                                                      MBEDTLS_ASN1_SEQUENCE));
     291              : 
     292            0 :     return (int) len;
     293              : }
     294              : #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
     295              : 
     296              : /*
     297              :  * RFC 5915, or SEC1 Appendix C.4
     298              :  *
     299              :  * ECPrivateKey ::= SEQUENCE {
     300              :  *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
     301              :  *      privateKey     OCTET STRING,
     302              :  *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
     303              :  *      publicKey  [1] BIT STRING OPTIONAL
     304              :  *    }
     305              :  */
     306            0 : static int pk_write_ec_der(unsigned char **p, unsigned char *buf,
     307              :                            const mbedtls_pk_context *pk)
     308              : {
     309            0 :     size_t len = 0;
     310              :     int ret;
     311            0 :     size_t pub_len = 0, par_len = 0;
     312              :     mbedtls_ecp_group_id grp_id;
     313              : 
     314              :     /* publicKey */
     315            0 :     MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(p, buf, pk));
     316              : 
     317            0 :     if (*p - buf < 1) {
     318            0 :         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
     319              :     }
     320            0 :     (*p)--;
     321            0 :     **p = 0;
     322            0 :     pub_len += 1;
     323              : 
     324            0 :     MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
     325            0 :     MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_BIT_STRING));
     326              : 
     327            0 :     MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
     328            0 :     MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf,
     329              :                                                          MBEDTLS_ASN1_CONTEXT_SPECIFIC |
     330              :                                                          MBEDTLS_ASN1_CONSTRUCTED | 1));
     331            0 :     len += pub_len;
     332              : 
     333              :     /* parameters */
     334            0 :     grp_id = mbedtls_pk_get_ec_group_id(pk);
     335            0 :     MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(p, buf, grp_id));
     336            0 :     MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(p, buf, par_len));
     337            0 :     MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(p, buf,
     338              :                                                          MBEDTLS_ASN1_CONTEXT_SPECIFIC |
     339              :                                                          MBEDTLS_ASN1_CONSTRUCTED | 0));
     340            0 :     len += par_len;
     341              : 
     342              :     /* privateKey */
     343            0 :     MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
     344              : 
     345              :     /* version */
     346            0 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 1));
     347              : 
     348            0 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
     349            0 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |
     350              :                                                      MBEDTLS_ASN1_SEQUENCE));
     351              : 
     352            0 :     return (int) len;
     353              : }
     354              : #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
     355              : 
     356              : /******************************************************************************
     357              :  * Internal functions for Opaque keys.
     358              :  ******************************************************************************/
     359              : #if defined(MBEDTLS_USE_PSA_CRYPTO)
     360              : static int pk_write_opaque_pubkey(unsigned char **p, unsigned char *start,
     361              :                                   const mbedtls_pk_context *pk)
     362              : {
     363              :     size_t buffer_size;
     364              :     size_t len = 0;
     365              : 
     366              :     if (*p < start) {
     367              :         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     368              :     }
     369              : 
     370              :     buffer_size = (size_t) (*p - start);
     371              :     if (psa_export_public_key(pk->priv_id, start, buffer_size,
     372              :                               &len) != PSA_SUCCESS) {
     373              :         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     374              :     }
     375              : 
     376              :     *p -= len;
     377              :     memmove(*p, start, len);
     378              : 
     379              :     return (int) len;
     380              : }
     381              : #endif /* MBEDTLS_USE_PSA_CRYPTO */
     382              : 
     383              : /******************************************************************************
     384              :  * Generic helpers
     385              :  ******************************************************************************/
     386              : 
     387              : /* Extend the public mbedtls_pk_get_type() by getting key type also in case of
     388              :  * opaque keys. */
     389           24 : static mbedtls_pk_type_t pk_get_type_ext(const mbedtls_pk_context *pk)
     390              : {
     391           24 :     mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk);
     392              : 
     393              : #if defined(MBEDTLS_USE_PSA_CRYPTO)
     394              :     if (pk_type == MBEDTLS_PK_OPAQUE) {
     395              :         psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT;
     396              :         psa_key_type_t opaque_key_type;
     397              : 
     398              :         if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) {
     399              :             return MBEDTLS_PK_NONE;
     400              :         }
     401              :         opaque_key_type = psa_get_key_type(&opaque_attrs);
     402              :         psa_reset_key_attributes(&opaque_attrs);
     403              : 
     404              :         if (PSA_KEY_TYPE_IS_ECC(opaque_key_type)) {
     405              :             return MBEDTLS_PK_ECKEY;
     406              :         } else if (PSA_KEY_TYPE_IS_RSA(opaque_key_type)) {
     407              :             return MBEDTLS_PK_RSA;
     408              :         } else {
     409              :             return MBEDTLS_PK_NONE;
     410              :         }
     411              :     } else
     412              : #endif
     413           24 :     return pk_type;
     414              : }
     415              : 
     416              : /******************************************************************************
     417              :  * Public functions for writing private/public DER keys.
     418              :  ******************************************************************************/
     419           12 : int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
     420              :                             const mbedtls_pk_context *key)
     421              : {
     422           12 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     423           12 :     size_t len = 0;
     424              : 
     425              : #if defined(MBEDTLS_RSA_C)
     426           12 :     if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
     427            0 :         MBEDTLS_ASN1_CHK_ADD(len, mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*key), start, p));
     428              :     } else
     429              : #endif
     430              : #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
     431           12 :     if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
     432           12 :         MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, key));
     433              :     } else
     434              : #endif
     435              : #if defined(MBEDTLS_USE_PSA_CRYPTO)
     436              :     if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {
     437              :         MBEDTLS_ASN1_CHK_ADD(len, pk_write_opaque_pubkey(p, start, key));
     438              :     } else
     439              : #endif /* MBEDTLS_USE_PSA_CRYPTO */
     440            0 :     return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
     441              : 
     442           12 :     return (int) len;
     443              : }
     444              : 
     445           12 : int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
     446              : {
     447           12 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     448              :     unsigned char *c;
     449           12 :     int has_par = 1;
     450           12 :     size_t len = 0, par_len = 0, oid_len = 0;
     451              :     mbedtls_pk_type_t pk_type;
     452           12 :     const char *oid = NULL;
     453              : 
     454           12 :     if (size == 0) {
     455            0 :         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
     456              :     }
     457              : 
     458           12 :     c = buf + size;
     459              : 
     460           12 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key));
     461              : 
     462           12 :     if (c - buf < 1) {
     463            0 :         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
     464              :     }
     465              : 
     466              :     /*
     467              :      *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
     468              :      *       algorithm            AlgorithmIdentifier,
     469              :      *       subjectPublicKey     BIT STRING }
     470              :      */
     471           12 :     *--c = 0;
     472           12 :     len += 1;
     473              : 
     474           12 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
     475           12 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
     476              : 
     477           12 :     pk_type = pk_get_type_ext(key);
     478              : 
     479              : #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
     480           12 :     if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
     481           12 :         mbedtls_ecp_group_id ec_grp_id = mbedtls_pk_get_ec_group_id(key);
     482           12 :         if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
     483            0 :             ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len);
     484            0 :             if (ret != 0) {
     485            0 :                 return ret;
     486              :             }
     487            0 :             has_par = 0;
     488              :         } else {
     489           12 :             MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id));
     490              :         }
     491              :     }
     492              : #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
     493              : 
     494              :     /* At this point oid_len is not null only for EC Montgomery keys. */
     495           12 :     if (oid_len == 0) {
     496           12 :         ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, &oid_len);
     497           12 :         if (ret != 0) {
     498            0 :             return ret;
     499              :         }
     500              :     }
     501              : 
     502           12 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, oid, oid_len,
     503              :                                                                           par_len, has_par));
     504              : 
     505           12 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
     506           12 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
     507              :                                                      MBEDTLS_ASN1_SEQUENCE));
     508              : 
     509           12 :     return (int) len;
     510              : }
     511              : 
     512            0 : int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
     513              : {
     514              :     unsigned char *c;
     515              : 
     516            0 :     if (size == 0) {
     517            0 :         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
     518              :     }
     519              : 
     520            0 :     c = buf + size;
     521              : 
     522              : #if defined(MBEDTLS_RSA_C)
     523            0 :     if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) {
     524            0 :         return pk_write_rsa_der(&c, buf, key);
     525              :     } else
     526              : #endif /* MBEDTLS_RSA_C */
     527              : #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
     528            0 :     if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
     529              : #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
     530            0 :         if (mbedtls_pk_is_rfc8410(key)) {
     531            0 :             return pk_write_ec_rfc8410_der(&c, buf, key);
     532              :         }
     533              : #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
     534            0 :         return pk_write_ec_der(&c, buf, key);
     535              :     } else
     536              : #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
     537            0 :     return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
     538              : }
     539              : 
     540              : /******************************************************************************
     541              :  * Public functions for wrinting private/public PEM keys.
     542              :  ******************************************************************************/
     543              : #if defined(MBEDTLS_PEM_WRITE_C)
     544              : 
     545              : #define PUB_DER_MAX_BYTES                                                   \
     546              :     (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \
     547              :      MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES)
     548              : #define PRV_DER_MAX_BYTES                                                   \
     549              :     (MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \
     550              :      MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES)
     551              : 
     552            0 : int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
     553              : {
     554            0 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     555            0 :     unsigned char *output_buf = NULL;
     556            0 :     output_buf = mbedtls_calloc(1, PUB_DER_MAX_BYTES);
     557            0 :     if (output_buf == NULL) {
     558            0 :         return MBEDTLS_ERR_PK_ALLOC_FAILED;
     559              :     }
     560            0 :     size_t olen = 0;
     561              : 
     562            0 :     if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf,
     563              :                                            PUB_DER_MAX_BYTES)) < 0) {
     564            0 :         goto cleanup;
     565              :     }
     566              : 
     567            0 :     if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY "\n", PEM_END_PUBLIC_KEY "\n",
     568            0 :                                         output_buf + PUB_DER_MAX_BYTES - ret,
     569              :                                         ret, buf, size, &olen)) != 0) {
     570            0 :         goto cleanup;
     571              :     }
     572              : 
     573            0 :     ret = 0;
     574            0 : cleanup:
     575            0 :     mbedtls_free(output_buf);
     576            0 :     return ret;
     577              : }
     578              : 
     579            0 : int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
     580              : {
     581            0 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     582            0 :     unsigned char *output_buf = NULL;
     583            0 :     output_buf = mbedtls_calloc(1, PRV_DER_MAX_BYTES);
     584            0 :     if (output_buf == NULL) {
     585            0 :         return MBEDTLS_ERR_PK_ALLOC_FAILED;
     586              :     }
     587              :     const char *begin, *end;
     588            0 :     size_t olen = 0;
     589              : 
     590            0 :     if ((ret = mbedtls_pk_write_key_der(key, output_buf, PRV_DER_MAX_BYTES)) < 0) {
     591            0 :         goto cleanup;
     592              :     }
     593              : 
     594              : #if defined(MBEDTLS_RSA_C)
     595            0 :     if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) {
     596            0 :         begin = PEM_BEGIN_PRIVATE_KEY_RSA "\n";
     597            0 :         end = PEM_END_PRIVATE_KEY_RSA "\n";
     598              :     } else
     599              : #endif
     600              : #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
     601            0 :     if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
     602            0 :         if (mbedtls_pk_is_rfc8410(key)) {
     603            0 :             begin = PEM_BEGIN_PRIVATE_KEY_PKCS8 "\n";
     604            0 :             end = PEM_END_PRIVATE_KEY_PKCS8 "\n";
     605              :         } else {
     606            0 :             begin = PEM_BEGIN_PRIVATE_KEY_EC "\n";
     607            0 :             end = PEM_END_PRIVATE_KEY_EC "\n";
     608              :         }
     609              :     } else
     610              : #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
     611              :     {
     612            0 :         ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
     613            0 :         goto cleanup;
     614              :     }
     615              : 
     616            0 :     if ((ret = mbedtls_pem_write_buffer(begin, end,
     617            0 :                                         output_buf + PRV_DER_MAX_BYTES - ret,
     618              :                                         ret, buf, size, &olen)) != 0) {
     619            0 :         goto cleanup;
     620              :     }
     621              : 
     622            0 :     ret = 0;
     623            0 : cleanup:
     624            0 :     mbedtls_zeroize_and_free(output_buf, PRV_DER_MAX_BYTES);
     625            0 :     return ret;
     626              : }
     627              : #endif /* MBEDTLS_PEM_WRITE_C */
     628              : 
     629              : #endif /* MBEDTLS_PK_WRITE_C */
        

Generated by: LCOV version 2.0-1