LCOV - code coverage report
Current view: top level - os_stub/mbedtlslib/mbedtls/library - pem.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 47.2 % 89 42
Test Date: 2025-10-12 08:10:56 Functions: 75.0 % 4 3

            Line data    Source code
       1              : /*
       2              :  *  Privacy Enhanced Mail (PEM) decoding
       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_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
      11              : 
      12              : #include "mbedtls/pem.h"
      13              : #include "mbedtls/base64.h"
      14              : #include "mbedtls/des.h"
      15              : #include "mbedtls/aes.h"
      16              : #include "mbedtls/md.h"
      17              : #include "mbedtls/cipher.h"
      18              : #include "mbedtls/platform_util.h"
      19              : #include "mbedtls/error.h"
      20              : 
      21              : #include <string.h>
      22              : 
      23              : #include "mbedtls/platform.h"
      24              : 
      25              : #if defined(MBEDTLS_USE_PSA_CRYPTO)
      26              : #include "psa/crypto.h"
      27              : #endif
      28              : 
      29              : #if defined(MBEDTLS_MD_CAN_MD5) &&  \
      30              :     defined(MBEDTLS_CIPHER_MODE_CBC) &&                             \
      31              :     (defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C))
      32              : #define PEM_RFC1421
      33              : #endif /* MBEDTLS_MD_CAN_MD5 &&
      34              :           MBEDTLS_CIPHER_MODE_CBC &&
      35              :           ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
      36              : 
      37              : #if defined(MBEDTLS_PEM_PARSE_C)
      38          192 : void mbedtls_pem_init(mbedtls_pem_context *ctx)
      39              : {
      40          192 :     memset(ctx, 0, sizeof(mbedtls_pem_context));
      41          192 : }
      42              : 
      43              : #if defined(PEM_RFC1421)
      44              : /*
      45              :  * Read a 16-byte hex string and convert it to binary
      46              :  */
      47              : static int pem_get_iv(const unsigned char *s, unsigned char *iv,
      48              :                       size_t iv_len)
      49              : {
      50              :     size_t i, j, k;
      51              : 
      52              :     memset(iv, 0, iv_len);
      53              : 
      54              :     for (i = 0; i < iv_len * 2; i++, s++) {
      55              :         if (*s >= '0' && *s <= '9') {
      56              :             j = *s - '0';
      57              :         } else
      58              :         if (*s >= 'A' && *s <= 'F') {
      59              :             j = *s - '7';
      60              :         } else
      61              :         if (*s >= 'a' && *s <= 'f') {
      62              :             j = *s - 'W';
      63              :         } else {
      64              :             return MBEDTLS_ERR_PEM_INVALID_ENC_IV;
      65              :         }
      66              : 
      67              :         k = ((i & 1) != 0) ? j : j << 4;
      68              : 
      69              :         iv[i >> 1] = (unsigned char) (iv[i >> 1] | k);
      70              :     }
      71              : 
      72              :     return 0;
      73              : }
      74              : 
      75              : static int pem_pbkdf1(unsigned char *key, size_t keylen,
      76              :                       unsigned char *iv,
      77              :                       const unsigned char *pwd, size_t pwdlen)
      78              : {
      79              :     mbedtls_md_context_t md5_ctx;
      80              :     const mbedtls_md_info_t *md5_info;
      81              :     unsigned char md5sum[16];
      82              :     size_t use_len;
      83              :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
      84              : 
      85              :     mbedtls_md_init(&md5_ctx);
      86              : 
      87              :     /* Prepare the context. (setup() errors gracefully on NULL info.) */
      88              :     md5_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5);
      89              :     if ((ret = mbedtls_md_setup(&md5_ctx, md5_info, 0)) != 0) {
      90              :         goto exit;
      91              :     }
      92              : 
      93              :     /*
      94              :      * key[ 0..15] = MD5(pwd || IV)
      95              :      */
      96              :     if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) {
      97              :         goto exit;
      98              :     }
      99              :     if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) {
     100              :         goto exit;
     101              :     }
     102              :     if ((ret = mbedtls_md_update(&md5_ctx, iv,  8)) != 0) {
     103              :         goto exit;
     104              :     }
     105              :     if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) {
     106              :         goto exit;
     107              :     }
     108              : 
     109              :     if (keylen <= 16) {
     110              :         memcpy(key, md5sum, keylen);
     111              :         goto exit;
     112              :     }
     113              : 
     114              :     memcpy(key, md5sum, 16);
     115              : 
     116              :     /*
     117              :      * key[16..23] = MD5(key[ 0..15] || pwd || IV])
     118              :      */
     119              :     if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) {
     120              :         goto exit;
     121              :     }
     122              :     if ((ret = mbedtls_md_update(&md5_ctx, md5sum, 16)) != 0) {
     123              :         goto exit;
     124              :     }
     125              :     if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) {
     126              :         goto exit;
     127              :     }
     128              :     if ((ret = mbedtls_md_update(&md5_ctx, iv, 8)) != 0) {
     129              :         goto exit;
     130              :     }
     131              :     if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) {
     132              :         goto exit;
     133              :     }
     134              : 
     135              :     use_len = 16;
     136              :     if (keylen < 32) {
     137              :         use_len = keylen - 16;
     138              :     }
     139              : 
     140              :     memcpy(key + 16, md5sum, use_len);
     141              : 
     142              : exit:
     143              :     mbedtls_md_free(&md5_ctx);
     144              :     mbedtls_platform_zeroize(md5sum, 16);
     145              : 
     146              :     return ret;
     147              : }
     148              : 
     149              : #if defined(MBEDTLS_DES_C)
     150              : /*
     151              :  * Decrypt with DES-CBC, using PBKDF1 for key derivation
     152              :  */
     153              : static int pem_des_decrypt(unsigned char des_iv[8],
     154              :                            unsigned char *buf, size_t buflen,
     155              :                            const unsigned char *pwd, size_t pwdlen)
     156              : {
     157              :     mbedtls_des_context des_ctx;
     158              :     unsigned char des_key[8];
     159              :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     160              : 
     161              :     mbedtls_des_init(&des_ctx);
     162              : 
     163              :     if ((ret = pem_pbkdf1(des_key, 8, des_iv, pwd, pwdlen)) != 0) {
     164              :         goto exit;
     165              :     }
     166              : 
     167              :     if ((ret = mbedtls_des_setkey_dec(&des_ctx, des_key)) != 0) {
     168              :         goto exit;
     169              :     }
     170              :     ret = mbedtls_des_crypt_cbc(&des_ctx, MBEDTLS_DES_DECRYPT, buflen,
     171              :                                 des_iv, buf, buf);
     172              : 
     173              : exit:
     174              :     mbedtls_des_free(&des_ctx);
     175              :     mbedtls_platform_zeroize(des_key, 8);
     176              : 
     177              :     return ret;
     178              : }
     179              : 
     180              : /*
     181              :  * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
     182              :  */
     183              : static int pem_des3_decrypt(unsigned char des3_iv[8],
     184              :                             unsigned char *buf, size_t buflen,
     185              :                             const unsigned char *pwd, size_t pwdlen)
     186              : {
     187              :     mbedtls_des3_context des3_ctx;
     188              :     unsigned char des3_key[24];
     189              :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     190              : 
     191              :     mbedtls_des3_init(&des3_ctx);
     192              : 
     193              :     if ((ret = pem_pbkdf1(des3_key, 24, des3_iv, pwd, pwdlen)) != 0) {
     194              :         goto exit;
     195              :     }
     196              : 
     197              :     if ((ret = mbedtls_des3_set3key_dec(&des3_ctx, des3_key)) != 0) {
     198              :         goto exit;
     199              :     }
     200              :     ret = mbedtls_des3_crypt_cbc(&des3_ctx, MBEDTLS_DES_DECRYPT, buflen,
     201              :                                  des3_iv, buf, buf);
     202              : 
     203              : exit:
     204              :     mbedtls_des3_free(&des3_ctx);
     205              :     mbedtls_platform_zeroize(des3_key, 24);
     206              : 
     207              :     return ret;
     208              : }
     209              : #endif /* MBEDTLS_DES_C */
     210              : 
     211              : #if defined(MBEDTLS_AES_C)
     212              : /*
     213              :  * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
     214              :  */
     215              : static int pem_aes_decrypt(unsigned char aes_iv[16], unsigned int keylen,
     216              :                            unsigned char *buf, size_t buflen,
     217              :                            const unsigned char *pwd, size_t pwdlen)
     218              : {
     219              :     mbedtls_aes_context aes_ctx;
     220              :     unsigned char aes_key[32];
     221              :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     222              : 
     223              :     mbedtls_aes_init(&aes_ctx);
     224              : 
     225              :     if ((ret = pem_pbkdf1(aes_key, keylen, aes_iv, pwd, pwdlen)) != 0) {
     226              :         goto exit;
     227              :     }
     228              : 
     229              :     if ((ret = mbedtls_aes_setkey_dec(&aes_ctx, aes_key, keylen * 8)) != 0) {
     230              :         goto exit;
     231              :     }
     232              :     ret = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, buflen,
     233              :                                 aes_iv, buf, buf);
     234              : 
     235              : exit:
     236              :     mbedtls_aes_free(&aes_ctx);
     237              :     mbedtls_platform_zeroize(aes_key, keylen);
     238              : 
     239              :     return ret;
     240              : }
     241              : #endif /* MBEDTLS_AES_C */
     242              : 
     243              : #if defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C)
     244              : static int pem_check_pkcs_padding(unsigned char *input, size_t input_len, size_t *data_len)
     245              : {
     246              :     /* input_len > 0 is not guaranteed by mbedtls_pem_read_buffer(). */
     247              :     if (input_len < 1) {
     248              :         return MBEDTLS_ERR_PEM_INVALID_DATA;
     249              :     }
     250              :     size_t pad_len = input[input_len - 1];
     251              :     size_t i;
     252              : 
     253              :     if (pad_len > input_len) {
     254              :         return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
     255              :     }
     256              : 
     257              :     *data_len = input_len - pad_len;
     258              : 
     259              :     for (i = *data_len; i < input_len; i++) {
     260              :         if (input[i] != pad_len) {
     261              :             return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
     262              :         }
     263              :     }
     264              : 
     265              :     return 0;
     266              : }
     267              : #endif /* MBEDTLS_DES_C || MBEDTLS_AES_C */
     268              : 
     269              : #endif /* PEM_RFC1421 */
     270              : 
     271          546 : int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer,
     272              :                             const unsigned char *data, const unsigned char *pwd,
     273              :                             size_t pwdlen, size_t *use_len)
     274              : {
     275              :     int ret, enc;
     276              :     size_t len;
     277              :     unsigned char *buf;
     278              :     const unsigned char *s1, *s2, *end;
     279              : #if defined(PEM_RFC1421)
     280              :     unsigned char pem_iv[16];
     281              :     mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE;
     282              : #else
     283              :     ((void) pwd);
     284              :     ((void) pwdlen);
     285              : #endif /* PEM_RFC1421 */
     286              : 
     287          546 :     if (ctx == NULL) {
     288            0 :         return MBEDTLS_ERR_PEM_BAD_INPUT_DATA;
     289              :     }
     290              : 
     291          546 :     s1 = (unsigned char *) strstr((const char *) data, header);
     292              : 
     293          546 :     if (s1 == NULL) {
     294          364 :         return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
     295              :     }
     296              : 
     297          182 :     s2 = (unsigned char *) strstr((const char *) data, footer);
     298              : 
     299          182 :     if (s2 == NULL || s2 <= s1) {
     300            0 :         return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
     301              :     }
     302              : 
     303          182 :     s1 += strlen(header);
     304          182 :     if (*s1 == ' ') {
     305            0 :         s1++;
     306              :     }
     307          182 :     if (*s1 == '\r') {
     308          182 :         s1++;
     309              :     }
     310          182 :     if (*s1 == '\n') {
     311          182 :         s1++;
     312              :     } else {
     313            0 :         return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
     314              :     }
     315              : 
     316          182 :     end = s2;
     317          182 :     end += strlen(footer);
     318          182 :     if (*end == ' ') {
     319            0 :         end++;
     320              :     }
     321          182 :     if (*end == '\r') {
     322          182 :         end++;
     323              :     }
     324          182 :     if (*end == '\n') {
     325          182 :         end++;
     326              :     }
     327          182 :     *use_len = (size_t) (end - data);
     328              : 
     329          182 :     enc = 0;
     330              : 
     331          182 :     if (s2 - s1 >= 22 && memcmp(s1, "Proc-Type: 4,ENCRYPTED", 22) == 0) {
     332              : #if defined(PEM_RFC1421)
     333              :         enc++;
     334              : 
     335              :         s1 += 22;
     336              :         if (*s1 == '\r') {
     337              :             s1++;
     338              :         }
     339              :         if (*s1 == '\n') {
     340              :             s1++;
     341              :         } else {
     342              :             return MBEDTLS_ERR_PEM_INVALID_DATA;
     343              :         }
     344              : 
     345              : 
     346              : #if defined(MBEDTLS_DES_C)
     347              :         if (s2 - s1 >= 23 && memcmp(s1, "DEK-Info: DES-EDE3-CBC,", 23) == 0) {
     348              :             enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC;
     349              : 
     350              :             s1 += 23;
     351              :             if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) {
     352              :                 return MBEDTLS_ERR_PEM_INVALID_ENC_IV;
     353              :             }
     354              : 
     355              :             s1 += 16;
     356              :         } else if (s2 - s1 >= 18 && memcmp(s1, "DEK-Info: DES-CBC,", 18) == 0) {
     357              :             enc_alg = MBEDTLS_CIPHER_DES_CBC;
     358              : 
     359              :             s1 += 18;
     360              :             if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) {
     361              :                 return MBEDTLS_ERR_PEM_INVALID_ENC_IV;
     362              :             }
     363              : 
     364              :             s1 += 16;
     365              :         }
     366              : #endif /* MBEDTLS_DES_C */
     367              : 
     368              : #if defined(MBEDTLS_AES_C)
     369              :         if (s2 - s1 >= 14 && memcmp(s1, "DEK-Info: AES-", 14) == 0) {
     370              :             if (s2 - s1 < 22) {
     371              :                 return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG;
     372              :             } else if (memcmp(s1, "DEK-Info: AES-128-CBC,", 22) == 0) {
     373              :                 enc_alg = MBEDTLS_CIPHER_AES_128_CBC;
     374              :             } else if (memcmp(s1, "DEK-Info: AES-192-CBC,", 22) == 0) {
     375              :                 enc_alg = MBEDTLS_CIPHER_AES_192_CBC;
     376              :             } else if (memcmp(s1, "DEK-Info: AES-256-CBC,", 22) == 0) {
     377              :                 enc_alg = MBEDTLS_CIPHER_AES_256_CBC;
     378              :             } else {
     379              :                 return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG;
     380              :             }
     381              : 
     382              :             s1 += 22;
     383              :             if (s2 - s1 < 32 || pem_get_iv(s1, pem_iv, 16) != 0) {
     384              :                 return MBEDTLS_ERR_PEM_INVALID_ENC_IV;
     385              :             }
     386              : 
     387              :             s1 += 32;
     388              :         }
     389              : #endif /* MBEDTLS_AES_C */
     390              : 
     391              :         if (enc_alg == MBEDTLS_CIPHER_NONE) {
     392              :             return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG;
     393              :         }
     394              : 
     395              :         if (*s1 == '\r') {
     396              :             s1++;
     397              :         }
     398              :         if (*s1 == '\n') {
     399              :             s1++;
     400              :         } else {
     401              :             return MBEDTLS_ERR_PEM_INVALID_DATA;
     402              :         }
     403              : #else
     404            0 :         return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE;
     405              : #endif /* PEM_RFC1421 */
     406              :     }
     407              : 
     408          182 :     if (s1 >= s2) {
     409            0 :         return MBEDTLS_ERR_PEM_INVALID_DATA;
     410              :     }
     411              : 
     412          182 :     ret = mbedtls_base64_decode(NULL, 0, &len, s1, (size_t) (s2 - s1));
     413              : 
     414          182 :     if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) {
     415            0 :         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret);
     416              :     }
     417              : 
     418          182 :     if (len == 0) {
     419            0 :         return MBEDTLS_ERR_PEM_BAD_INPUT_DATA;
     420              :     }
     421              : 
     422          182 :     if ((buf = mbedtls_calloc(1, len)) == NULL) {
     423            0 :         return MBEDTLS_ERR_PEM_ALLOC_FAILED;
     424              :     }
     425              : 
     426          182 :     if ((ret = mbedtls_base64_decode(buf, len, &len, s1, (size_t) (s2 - s1))) != 0) {
     427            0 :         mbedtls_zeroize_and_free(buf, len);
     428            0 :         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret);
     429              :     }
     430              : 
     431          182 :     if (enc != 0) {
     432              : #if defined(PEM_RFC1421)
     433              :         if (pwd == NULL) {
     434              :             mbedtls_zeroize_and_free(buf, len);
     435              :             return MBEDTLS_ERR_PEM_PASSWORD_REQUIRED;
     436              :         }
     437              : 
     438              :         ret = 0;
     439              : 
     440              : #if defined(MBEDTLS_DES_C)
     441              :         if (enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC) {
     442              :             ret = pem_des3_decrypt(pem_iv, buf, len, pwd, pwdlen);
     443              :         } else if (enc_alg == MBEDTLS_CIPHER_DES_CBC) {
     444              :             ret = pem_des_decrypt(pem_iv, buf, len, pwd, pwdlen);
     445              :         }
     446              : #endif /* MBEDTLS_DES_C */
     447              : 
     448              : #if defined(MBEDTLS_AES_C)
     449              :         if (enc_alg == MBEDTLS_CIPHER_AES_128_CBC) {
     450              :             ret = pem_aes_decrypt(pem_iv, 16, buf, len, pwd, pwdlen);
     451              :         } else if (enc_alg == MBEDTLS_CIPHER_AES_192_CBC) {
     452              :             ret = pem_aes_decrypt(pem_iv, 24, buf, len, pwd, pwdlen);
     453              :         } else if (enc_alg == MBEDTLS_CIPHER_AES_256_CBC) {
     454              :             ret = pem_aes_decrypt(pem_iv, 32, buf, len, pwd, pwdlen);
     455              :         }
     456              : #endif /* MBEDTLS_AES_C */
     457              : 
     458              :         if (ret != 0) {
     459              :             mbedtls_zeroize_and_free(buf, len);
     460              :             return ret;
     461              :         }
     462              : 
     463              :         /* Check PKCS padding and update data length based on padding info.
     464              :          * This can be used to detect invalid padding data and password
     465              :          * mismatches. */
     466              :         size_t unpadded_len;
     467              :         ret = pem_check_pkcs_padding(buf, len, &unpadded_len);
     468              :         if (ret != 0) {
     469              :             mbedtls_zeroize_and_free(buf, len);
     470              :             return ret;
     471              :         }
     472              :         len = unpadded_len;
     473              : #else
     474            0 :         mbedtls_zeroize_and_free(buf, len);
     475            0 :         return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE;
     476              : #endif /* PEM_RFC1421 */
     477              :     }
     478              : 
     479          182 :     ctx->buf = buf;
     480          182 :     ctx->buflen = len;
     481              : 
     482          182 :     return 0;
     483              : }
     484              : 
     485          192 : void mbedtls_pem_free(mbedtls_pem_context *ctx)
     486              : {
     487          192 :     if (ctx == NULL) {
     488            0 :         return;
     489              :     }
     490              : 
     491          192 :     if (ctx->buf != NULL) {
     492          182 :         mbedtls_zeroize_and_free(ctx->buf, ctx->buflen);
     493              :     }
     494          192 :     mbedtls_free(ctx->info);
     495              : 
     496          192 :     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pem_context));
     497              : }
     498              : #endif /* MBEDTLS_PEM_PARSE_C */
     499              : 
     500              : #if defined(MBEDTLS_PEM_WRITE_C)
     501            0 : int mbedtls_pem_write_buffer(const char *header, const char *footer,
     502              :                              const unsigned char *der_data, size_t der_len,
     503              :                              unsigned char *buf, size_t buf_len, size_t *olen)
     504              : {
     505            0 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     506            0 :     unsigned char *encode_buf = NULL, *c, *p = buf;
     507            0 :     size_t len = 0, use_len, add_len = 0;
     508              : 
     509            0 :     mbedtls_base64_encode(NULL, 0, &use_len, der_data, der_len);
     510            0 :     add_len = strlen(header) + strlen(footer) + (((use_len > 2) ? (use_len - 2) : 0) / 64) + 1;
     511              : 
     512            0 :     if (use_len + add_len > buf_len) {
     513            0 :         *olen = use_len + add_len;
     514            0 :         return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
     515              :     }
     516              : 
     517            0 :     if (use_len != 0 &&
     518            0 :         ((encode_buf = mbedtls_calloc(1, use_len)) == NULL)) {
     519            0 :         return MBEDTLS_ERR_PEM_ALLOC_FAILED;
     520              :     }
     521              : 
     522            0 :     if ((ret = mbedtls_base64_encode(encode_buf, use_len, &use_len, der_data,
     523              :                                      der_len)) != 0) {
     524            0 :         mbedtls_free(encode_buf);
     525            0 :         return ret;
     526              :     }
     527              : 
     528            0 :     memcpy(p, header, strlen(header));
     529            0 :     p += strlen(header);
     530            0 :     c = encode_buf;
     531              : 
     532            0 :     while (use_len) {
     533            0 :         len = (use_len > 64) ? 64 : use_len;
     534            0 :         memcpy(p, c, len);
     535            0 :         use_len -= len;
     536            0 :         p += len;
     537            0 :         c += len;
     538            0 :         *p++ = '\n';
     539              :     }
     540              : 
     541            0 :     memcpy(p, footer, strlen(footer));
     542            0 :     p += strlen(footer);
     543              : 
     544            0 :     *p++ = '\0';
     545            0 :     *olen = (size_t) (p - buf);
     546              : 
     547              :     /* Clean any remaining data previously written to the buffer */
     548            0 :     memset(buf + *olen, 0, buf_len - *olen);
     549              : 
     550            0 :     mbedtls_free(encode_buf);
     551            0 :     return 0;
     552              : }
     553              : #endif /* MBEDTLS_PEM_WRITE_C */
     554              : #endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */
        

Generated by: LCOV version 2.0-1