LCOV - code coverage report
Current view: top level - os_stub/mbedtlslib/mbedtls/library - asn1write.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 52.0 % 173 90
Test Date: 2025-06-29 08:09:00 Functions: 52.4 % 21 11

            Line data    Source code
       1              : /*
       2              :  * ASN.1 buffer writing functionality
       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_ASN1_WRITE_C) || defined(MBEDTLS_X509_USE_C) || \
      11              :     defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
      12              : 
      13              : #include "mbedtls/asn1write.h"
      14              : #include "mbedtls/error.h"
      15              : 
      16              : #include <string.h>
      17              : 
      18              : #include "mbedtls/platform.h"
      19              : 
      20              : #if defined(MBEDTLS_ASN1_PARSE_C)
      21              : #include "mbedtls/asn1.h"
      22              : #endif
      23              : 
      24          336 : int mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start, size_t len)
      25              : {
      26              : #if SIZE_MAX > 0xFFFFFFFF
      27          336 :     if (len > 0xFFFFFFFF) {
      28            0 :         return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
      29              :     }
      30              : #endif
      31              : 
      32          336 :     int required = 1;
      33              : 
      34          336 :     if (len >= 0x80) {
      35           84 :         for (size_t l = len; l != 0; l >>= 8) {
      36           48 :             required++;
      37              :         }
      38              :     }
      39              : 
      40          336 :     if (required > (*p - start)) {
      41            0 :         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
      42              :     }
      43              : 
      44              :     do {
      45          348 :         *--(*p) = MBEDTLS_BYTE_0(len);
      46          348 :         len >>= 8;
      47          348 :     } while (len);
      48              : 
      49          336 :     if (required > 1) {
      50           36 :         *--(*p) = (unsigned char) (0x80 + required - 1);
      51              :     }
      52              : 
      53          336 :     return required;
      54              : }
      55              : 
      56          336 : int mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start, unsigned char tag)
      57              : {
      58          336 :     if (*p - start < 1) {
      59            0 :         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
      60              :     }
      61              : 
      62          336 :     *--(*p) = tag;
      63              : 
      64          336 :     return 1;
      65              : }
      66              : #endif /* MBEDTLS_ASN1_WRITE_C || MBEDTLS_X509_USE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */
      67              : 
      68              : #if defined(MBEDTLS_ASN1_WRITE_C)
      69          108 : static int mbedtls_asn1_write_len_and_tag(unsigned char **p,
      70              :                                           const unsigned char *start,
      71              :                                           size_t len,
      72              :                                           unsigned char tag)
      73              : {
      74          108 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
      75              : 
      76          108 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
      77          108 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag));
      78              : 
      79          108 :     return (int) len;
      80              : }
      81              : 
      82          148 : int mbedtls_asn1_write_raw_buffer(unsigned char **p, const unsigned char *start,
      83              :                                   const unsigned char *buf, size_t size)
      84              : {
      85          148 :     size_t len = 0;
      86              : 
      87          148 :     if (*p < start || (size_t) (*p - start) < size) {
      88            0 :         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
      89              :     }
      90              : 
      91          148 :     len = size;
      92          148 :     (*p) -= len;
      93          148 :     memcpy(*p, buf, len);
      94              : 
      95          148 :     return (int) len;
      96              : }
      97              : 
      98              : #if defined(MBEDTLS_BIGNUM_C)
      99           12 : int mbedtls_asn1_write_mpi(unsigned char **p, const unsigned char *start, const mbedtls_mpi *X)
     100              : {
     101           12 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     102           12 :     size_t len = 0;
     103              : 
     104              :     // Write the MPI
     105              :     //
     106           12 :     len = mbedtls_mpi_size(X);
     107              : 
     108              :     /* DER represents 0 with a sign bit (0=nonnegative) and 7 value bits, not
     109              :      * as 0 digits. We need to end up with 020100, not with 0200. */
     110           12 :     if (len == 0) {
     111            0 :         len = 1;
     112              :     }
     113              : 
     114           12 :     if (*p < start || (size_t) (*p - start) < len) {
     115            0 :         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
     116              :     }
     117              : 
     118           12 :     (*p) -= len;
     119           12 :     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(X, *p, len));
     120              : 
     121              :     // DER format assumes 2s complement for numbers, so the leftmost bit
     122              :     // should be 0 for positive numbers and 1 for negative numbers.
     123              :     //
     124           12 :     if (X->s == 1 && **p & 0x80) {
     125            4 :         if (*p - start < 1) {
     126            0 :             return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
     127              :         }
     128              : 
     129            4 :         *--(*p) = 0x00;
     130            4 :         len += 1;
     131              :     }
     132              : 
     133           12 :     ret = mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_INTEGER);
     134              : 
     135           12 : cleanup:
     136           12 :     return ret;
     137              : }
     138              : #endif /* MBEDTLS_BIGNUM_C */
     139              : 
     140            0 : int mbedtls_asn1_write_null(unsigned char **p, const unsigned char *start)
     141              : {
     142              :     // Write NULL
     143              :     //
     144            0 :     return mbedtls_asn1_write_len_and_tag(p, start, 0, MBEDTLS_ASN1_NULL);
     145              : }
     146              : 
     147           54 : int mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start,
     148              :                            const char *oid, size_t oid_len)
     149              : {
     150           54 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     151           54 :     size_t len = 0;
     152              : 
     153           54 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
     154              :                                                             (const unsigned char *) oid, oid_len));
     155           54 :     return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OID);
     156              : }
     157              : 
     158            0 : int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, const unsigned char *start,
     159              :                                             const char *oid, size_t oid_len,
     160              :                                             size_t par_len)
     161              : {
     162            0 :     return mbedtls_asn1_write_algorithm_identifier_ext(p, start, oid, oid_len, par_len, 1);
     163              : }
     164              : 
     165           18 : int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, const unsigned char *start,
     166              :                                                 const char *oid, size_t oid_len,
     167              :                                                 size_t par_len, int has_par)
     168              : {
     169           18 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     170           18 :     size_t len = 0;
     171              : 
     172           18 :     if (has_par) {
     173           12 :         if (par_len == 0) {
     174            0 :             MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_null(p, start));
     175              :         } else {
     176           12 :             len += par_len;
     177              :         }
     178              :     }
     179              : 
     180           18 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
     181              : 
     182           18 :     return mbedtls_asn1_write_len_and_tag(p, start, len,
     183              :                                           MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
     184              : }
     185              : 
     186            0 : int mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start, int boolean)
     187              : {
     188            0 :     size_t len = 0;
     189              : 
     190            0 :     if (*p - start < 1) {
     191            0 :         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
     192              :     }
     193              : 
     194            0 :     *--(*p) = (boolean) ? 255 : 0;
     195            0 :     len++;
     196              : 
     197            0 :     return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BOOLEAN);
     198              : }
     199              : 
     200            6 : static int asn1_write_tagged_int(unsigned char **p, const unsigned char *start, int val, int tag)
     201              : {
     202            6 :     size_t len = 0;
     203              : 
     204              :     do {
     205            6 :         if (*p - start < 1) {
     206            0 :             return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
     207              :         }
     208            6 :         len += 1;
     209            6 :         *--(*p) = val & 0xff;
     210            6 :         val >>= 8;
     211            6 :     } while (val > 0);
     212              : 
     213            6 :     if (**p & 0x80) {
     214            0 :         if (*p - start < 1) {
     215            0 :             return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
     216              :         }
     217            0 :         *--(*p) = 0x00;
     218            0 :         len += 1;
     219              :     }
     220              : 
     221            6 :     return mbedtls_asn1_write_len_and_tag(p, start, len, tag);
     222              : }
     223              : 
     224            6 : int mbedtls_asn1_write_int(unsigned char **p, const unsigned char *start, int val)
     225              : {
     226            6 :     return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_INTEGER);
     227              : }
     228              : 
     229            0 : int mbedtls_asn1_write_enum(unsigned char **p, const unsigned char *start, int val)
     230              : {
     231            0 :     return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_ENUMERATED);
     232              : }
     233              : 
     234           18 : int mbedtls_asn1_write_tagged_string(unsigned char **p, const unsigned char *start, int tag,
     235              :                                      const char *text, size_t text_len)
     236              : {
     237           18 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     238           18 :     size_t len = 0;
     239              : 
     240           18 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
     241              :                                                             (const unsigned char *) text,
     242              :                                                             text_len));
     243              : 
     244           18 :     return mbedtls_asn1_write_len_and_tag(p, start, len, tag);
     245              : }
     246              : 
     247            0 : int mbedtls_asn1_write_utf8_string(unsigned char **p, const unsigned char *start,
     248              :                                    const char *text, size_t text_len)
     249              : {
     250            0 :     return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len);
     251              : }
     252              : 
     253            0 : int mbedtls_asn1_write_printable_string(unsigned char **p, const unsigned char *start,
     254              :                                         const char *text, size_t text_len)
     255              : {
     256            0 :     return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text,
     257              :                                             text_len);
     258              : }
     259              : 
     260            0 : int mbedtls_asn1_write_ia5_string(unsigned char **p, const unsigned char *start,
     261              :                                   const char *text, size_t text_len)
     262              : {
     263            0 :     return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len);
     264              : }
     265              : 
     266            0 : int mbedtls_asn1_write_named_bitstring(unsigned char **p,
     267              :                                        const unsigned char *start,
     268              :                                        const unsigned char *buf,
     269              :                                        size_t bits)
     270              : {
     271              :     size_t unused_bits, byte_len;
     272              :     const unsigned char *cur_byte;
     273              :     unsigned char cur_byte_shifted;
     274              :     unsigned char bit;
     275              : 
     276            0 :     byte_len = (bits + 7) / 8;
     277            0 :     unused_bits = (byte_len * 8) - bits;
     278              : 
     279              :     /*
     280              :      * Named bitstrings require that trailing 0s are excluded in the encoding
     281              :      * of the bitstring. Trailing 0s are considered part of the 'unused' bits
     282              :      * when encoding this value in the first content octet
     283              :      */
     284            0 :     if (bits != 0) {
     285            0 :         cur_byte = buf + byte_len - 1;
     286            0 :         cur_byte_shifted = *cur_byte >> unused_bits;
     287              : 
     288              :         for (;;) {
     289            0 :             bit = cur_byte_shifted & 0x1;
     290            0 :             cur_byte_shifted >>= 1;
     291              : 
     292            0 :             if (bit != 0) {
     293            0 :                 break;
     294              :             }
     295              : 
     296            0 :             bits--;
     297            0 :             if (bits == 0) {
     298            0 :                 break;
     299              :             }
     300              : 
     301            0 :             if (bits % 8 == 0) {
     302            0 :                 cur_byte_shifted = *--cur_byte;
     303              :             }
     304              :         }
     305              :     }
     306              : 
     307            0 :     return mbedtls_asn1_write_bitstring(p, start, buf, bits);
     308              : }
     309              : 
     310            0 : int mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start,
     311              :                                  const unsigned char *buf, size_t bits)
     312              : {
     313            0 :     size_t len = 0;
     314              :     size_t unused_bits, byte_len;
     315              : 
     316            0 :     byte_len = (bits + 7) / 8;
     317            0 :     unused_bits = (byte_len * 8) - bits;
     318              : 
     319            0 :     if (*p < start || (size_t) (*p - start) < byte_len + 1) {
     320            0 :         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
     321              :     }
     322              : 
     323            0 :     len = byte_len + 1;
     324              : 
     325              :     /* Write the bitstring. Ensure the unused bits are zeroed */
     326            0 :     if (byte_len > 0) {
     327            0 :         byte_len--;
     328            0 :         *--(*p) = buf[byte_len] & ~((0x1 << unused_bits) - 1);
     329            0 :         (*p) -= byte_len;
     330            0 :         memcpy(*p, buf, byte_len);
     331              :     }
     332              : 
     333              :     /* Write unused bits */
     334            0 :     *--(*p) = (unsigned char) unused_bits;
     335              : 
     336            0 :     return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BIT_STRING);
     337              : }
     338              : 
     339            0 : int mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *start,
     340              :                                     const unsigned char *buf, size_t size)
     341              : {
     342            0 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     343            0 :     size_t len = 0;
     344              : 
     345            0 :     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, buf, size));
     346              : 
     347            0 :     return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OCTET_STRING);
     348              : }
     349              : 
     350              : 
     351              : #if !defined(MBEDTLS_ASN1_PARSE_C)
     352              : /* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(),
     353              :  * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */
     354              : static mbedtls_asn1_named_data *asn1_find_named_data(
     355              :     mbedtls_asn1_named_data *list,
     356              :     const char *oid, size_t len)
     357              : {
     358              :     while (list != NULL) {
     359              :         if (list->oid.len == len &&
     360              :             memcmp(list->oid.p, oid, len) == 0) {
     361              :             break;
     362              :         }
     363              : 
     364              :         list = list->next;
     365              :     }
     366              : 
     367              :     return list;
     368              : }
     369              : #else
     370              : #define asn1_find_named_data(list, oid, len) \
     371              :     ((mbedtls_asn1_named_data *) mbedtls_asn1_find_named_data(list, oid, len))
     372              : #endif
     373              : 
     374           62 : mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(
     375              :     mbedtls_asn1_named_data **head,
     376              :     const char *oid, size_t oid_len,
     377              :     const unsigned char *val,
     378              :     size_t val_len)
     379              : {
     380              :     mbedtls_asn1_named_data *cur;
     381              : 
     382           62 :     if ((cur = asn1_find_named_data(*head, oid, oid_len)) == NULL) {
     383              :         // Add new entry if not present yet based on OID
     384              :         //
     385           62 :         cur = (mbedtls_asn1_named_data *) mbedtls_calloc(1,
     386              :                                                          sizeof(mbedtls_asn1_named_data));
     387           62 :         if (cur == NULL) {
     388            0 :             return NULL;
     389              :         }
     390              : 
     391           62 :         cur->oid.len = oid_len;
     392           62 :         cur->oid.p = mbedtls_calloc(1, oid_len);
     393           62 :         if (cur->oid.p == NULL) {
     394            0 :             mbedtls_free(cur);
     395            0 :             return NULL;
     396              :         }
     397              : 
     398           62 :         memcpy(cur->oid.p, oid, oid_len);
     399              : 
     400           62 :         cur->val.len = val_len;
     401           62 :         if (val_len != 0) {
     402           62 :             cur->val.p = mbedtls_calloc(1, val_len);
     403           62 :             if (cur->val.p == NULL) {
     404            0 :                 mbedtls_free(cur->oid.p);
     405            0 :                 mbedtls_free(cur);
     406            0 :                 return NULL;
     407              :             }
     408              :         }
     409              : 
     410           62 :         cur->next = *head;
     411           62 :         *head = cur;
     412            0 :     } else if (val_len == 0) {
     413            0 :         mbedtls_free(cur->val.p);
     414            0 :         cur->val.p = NULL;
     415            0 :     } else if (cur->val.len != val_len) {
     416              :         /*
     417              :          * Enlarge existing value buffer if needed
     418              :          * Preserve old data until the allocation succeeded, to leave list in
     419              :          * a consistent state in case allocation fails.
     420              :          */
     421            0 :         void *p = mbedtls_calloc(1, val_len);
     422            0 :         if (p == NULL) {
     423            0 :             return NULL;
     424              :         }
     425              : 
     426            0 :         mbedtls_free(cur->val.p);
     427            0 :         cur->val.p = p;
     428            0 :         cur->val.len = val_len;
     429              :     }
     430              : 
     431           62 :     if (val != NULL && val_len != 0) {
     432           24 :         memcpy(cur->val.p, val, val_len);
     433              :     }
     434              : 
     435           62 :     return cur;
     436              : }
     437              : #endif /* MBEDTLS_ASN1_WRITE_C */
        

Generated by: LCOV version 2.0-1