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-06-29 08:09:00 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          191 : void mbedtls_pem_init(mbedtls_pem_context *ctx)
      39              : {
      40          191 :     memset(ctx, 0, sizeof(mbedtls_pem_context));
      41          191 : }
      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 guaranteed by mbedtls_pem_read_buffer(). */
     247              :     size_t pad_len = input[input_len - 1];
     248              :     size_t i;
     249              : 
     250              :     if (pad_len > input_len) {
     251              :         return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
     252              :     }
     253              : 
     254              :     *data_len = input_len - pad_len;
     255              : 
     256              :     for (i = *data_len; i < input_len; i++) {
     257              :         if (input[i] != pad_len) {
     258              :             return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
     259              :         }
     260              :     }
     261              : 
     262              :     return 0;
     263              : }
     264              : #endif /* MBEDTLS_DES_C || MBEDTLS_AES_C */
     265              : 
     266              : #endif /* PEM_RFC1421 */
     267              : 
     268          543 : int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer,
     269              :                             const unsigned char *data, const unsigned char *pwd,
     270              :                             size_t pwdlen, size_t *use_len)
     271              : {
     272              :     int ret, enc;
     273              :     size_t len;
     274              :     unsigned char *buf;
     275              :     const unsigned char *s1, *s2, *end;
     276              : #if defined(PEM_RFC1421)
     277              :     unsigned char pem_iv[16];
     278              :     mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE;
     279              : #else
     280              :     ((void) pwd);
     281              :     ((void) pwdlen);
     282              : #endif /* PEM_RFC1421 */
     283              : 
     284          543 :     if (ctx == NULL) {
     285            0 :         return MBEDTLS_ERR_PEM_BAD_INPUT_DATA;
     286              :     }
     287              : 
     288          543 :     s1 = (unsigned char *) strstr((const char *) data, header);
     289              : 
     290          543 :     if (s1 == NULL) {
     291          362 :         return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
     292              :     }
     293              : 
     294          181 :     s2 = (unsigned char *) strstr((const char *) data, footer);
     295              : 
     296          181 :     if (s2 == NULL || s2 <= s1) {
     297            0 :         return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
     298              :     }
     299              : 
     300          181 :     s1 += strlen(header);
     301          181 :     if (*s1 == ' ') {
     302            0 :         s1++;
     303              :     }
     304          181 :     if (*s1 == '\r') {
     305          181 :         s1++;
     306              :     }
     307          181 :     if (*s1 == '\n') {
     308          181 :         s1++;
     309              :     } else {
     310            0 :         return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
     311              :     }
     312              : 
     313          181 :     end = s2;
     314          181 :     end += strlen(footer);
     315          181 :     if (*end == ' ') {
     316            0 :         end++;
     317              :     }
     318          181 :     if (*end == '\r') {
     319          181 :         end++;
     320              :     }
     321          181 :     if (*end == '\n') {
     322          181 :         end++;
     323              :     }
     324          181 :     *use_len = (size_t) (end - data);
     325              : 
     326          181 :     enc = 0;
     327              : 
     328          181 :     if (s2 - s1 >= 22 && memcmp(s1, "Proc-Type: 4,ENCRYPTED", 22) == 0) {
     329              : #if defined(PEM_RFC1421)
     330              :         enc++;
     331              : 
     332              :         s1 += 22;
     333              :         if (*s1 == '\r') {
     334              :             s1++;
     335              :         }
     336              :         if (*s1 == '\n') {
     337              :             s1++;
     338              :         } else {
     339              :             return MBEDTLS_ERR_PEM_INVALID_DATA;
     340              :         }
     341              : 
     342              : 
     343              : #if defined(MBEDTLS_DES_C)
     344              :         if (s2 - s1 >= 23 && memcmp(s1, "DEK-Info: DES-EDE3-CBC,", 23) == 0) {
     345              :             enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC;
     346              : 
     347              :             s1 += 23;
     348              :             if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) {
     349              :                 return MBEDTLS_ERR_PEM_INVALID_ENC_IV;
     350              :             }
     351              : 
     352              :             s1 += 16;
     353              :         } else if (s2 - s1 >= 18 && memcmp(s1, "DEK-Info: DES-CBC,", 18) == 0) {
     354              :             enc_alg = MBEDTLS_CIPHER_DES_CBC;
     355              : 
     356              :             s1 += 18;
     357              :             if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) {
     358              :                 return MBEDTLS_ERR_PEM_INVALID_ENC_IV;
     359              :             }
     360              : 
     361              :             s1 += 16;
     362              :         }
     363              : #endif /* MBEDTLS_DES_C */
     364              : 
     365              : #if defined(MBEDTLS_AES_C)
     366              :         if (s2 - s1 >= 14 && memcmp(s1, "DEK-Info: AES-", 14) == 0) {
     367              :             if (s2 - s1 < 22) {
     368              :                 return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG;
     369              :             } else if (memcmp(s1, "DEK-Info: AES-128-CBC,", 22) == 0) {
     370              :                 enc_alg = MBEDTLS_CIPHER_AES_128_CBC;
     371              :             } else if (memcmp(s1, "DEK-Info: AES-192-CBC,", 22) == 0) {
     372              :                 enc_alg = MBEDTLS_CIPHER_AES_192_CBC;
     373              :             } else if (memcmp(s1, "DEK-Info: AES-256-CBC,", 22) == 0) {
     374              :                 enc_alg = MBEDTLS_CIPHER_AES_256_CBC;
     375              :             } else {
     376              :                 return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG;
     377              :             }
     378              : 
     379              :             s1 += 22;
     380              :             if (s2 - s1 < 32 || pem_get_iv(s1, pem_iv, 16) != 0) {
     381              :                 return MBEDTLS_ERR_PEM_INVALID_ENC_IV;
     382              :             }
     383              : 
     384              :             s1 += 32;
     385              :         }
     386              : #endif /* MBEDTLS_AES_C */
     387              : 
     388              :         if (enc_alg == MBEDTLS_CIPHER_NONE) {
     389              :             return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG;
     390              :         }
     391              : 
     392              :         if (*s1 == '\r') {
     393              :             s1++;
     394              :         }
     395              :         if (*s1 == '\n') {
     396              :             s1++;
     397              :         } else {
     398              :             return MBEDTLS_ERR_PEM_INVALID_DATA;
     399              :         }
     400              : #else
     401            0 :         return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE;
     402              : #endif /* PEM_RFC1421 */
     403              :     }
     404              : 
     405          181 :     if (s1 >= s2) {
     406            0 :         return MBEDTLS_ERR_PEM_INVALID_DATA;
     407              :     }
     408              : 
     409          181 :     ret = mbedtls_base64_decode(NULL, 0, &len, s1, (size_t) (s2 - s1));
     410              : 
     411          181 :     if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) {
     412            0 :         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret);
     413              :     }
     414              : 
     415          181 :     if (len == 0) {
     416            0 :         return MBEDTLS_ERR_PEM_BAD_INPUT_DATA;
     417              :     }
     418              : 
     419          181 :     if ((buf = mbedtls_calloc(1, len)) == NULL) {
     420            0 :         return MBEDTLS_ERR_PEM_ALLOC_FAILED;
     421              :     }
     422              : 
     423          181 :     if ((ret = mbedtls_base64_decode(buf, len, &len, s1, (size_t) (s2 - s1))) != 0) {
     424            0 :         mbedtls_zeroize_and_free(buf, len);
     425            0 :         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret);
     426              :     }
     427              : 
     428          181 :     if (enc != 0) {
     429              : #if defined(PEM_RFC1421)
     430              :         if (pwd == NULL) {
     431              :             mbedtls_zeroize_and_free(buf, len);
     432              :             return MBEDTLS_ERR_PEM_PASSWORD_REQUIRED;
     433              :         }
     434              : 
     435              :         ret = 0;
     436              : 
     437              : #if defined(MBEDTLS_DES_C)
     438              :         if (enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC) {
     439              :             ret = pem_des3_decrypt(pem_iv, buf, len, pwd, pwdlen);
     440              :         } else if (enc_alg == MBEDTLS_CIPHER_DES_CBC) {
     441              :             ret = pem_des_decrypt(pem_iv, buf, len, pwd, pwdlen);
     442              :         }
     443              : #endif /* MBEDTLS_DES_C */
     444              : 
     445              : #if defined(MBEDTLS_AES_C)
     446              :         if (enc_alg == MBEDTLS_CIPHER_AES_128_CBC) {
     447              :             ret = pem_aes_decrypt(pem_iv, 16, buf, len, pwd, pwdlen);
     448              :         } else if (enc_alg == MBEDTLS_CIPHER_AES_192_CBC) {
     449              :             ret = pem_aes_decrypt(pem_iv, 24, buf, len, pwd, pwdlen);
     450              :         } else if (enc_alg == MBEDTLS_CIPHER_AES_256_CBC) {
     451              :             ret = pem_aes_decrypt(pem_iv, 32, buf, len, pwd, pwdlen);
     452              :         }
     453              : #endif /* MBEDTLS_AES_C */
     454              : 
     455              :         if (ret != 0) {
     456              :             mbedtls_zeroize_and_free(buf, len);
     457              :             return ret;
     458              :         }
     459              : 
     460              :         /* Check PKCS padding and update data length based on padding info.
     461              :          * This can be used to detect invalid padding data and password
     462              :          * mismatches. */
     463              :         size_t unpadded_len;
     464              :         ret = pem_check_pkcs_padding(buf, len, &unpadded_len);
     465              :         if (ret != 0) {
     466              :             mbedtls_zeroize_and_free(buf, len);
     467              :             return ret;
     468              :         }
     469              :         len = unpadded_len;
     470              : #else
     471            0 :         mbedtls_zeroize_and_free(buf, len);
     472            0 :         return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE;
     473              : #endif /* PEM_RFC1421 */
     474              :     }
     475              : 
     476          181 :     ctx->buf = buf;
     477          181 :     ctx->buflen = len;
     478              : 
     479          181 :     return 0;
     480              : }
     481              : 
     482          191 : void mbedtls_pem_free(mbedtls_pem_context *ctx)
     483              : {
     484          191 :     if (ctx == NULL) {
     485            0 :         return;
     486              :     }
     487              : 
     488          191 :     if (ctx->buf != NULL) {
     489          181 :         mbedtls_zeroize_and_free(ctx->buf, ctx->buflen);
     490              :     }
     491          191 :     mbedtls_free(ctx->info);
     492              : 
     493          191 :     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pem_context));
     494              : }
     495              : #endif /* MBEDTLS_PEM_PARSE_C */
     496              : 
     497              : #if defined(MBEDTLS_PEM_WRITE_C)
     498            0 : int mbedtls_pem_write_buffer(const char *header, const char *footer,
     499              :                              const unsigned char *der_data, size_t der_len,
     500              :                              unsigned char *buf, size_t buf_len, size_t *olen)
     501              : {
     502            0 :     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     503            0 :     unsigned char *encode_buf = NULL, *c, *p = buf;
     504            0 :     size_t len = 0, use_len, add_len = 0;
     505              : 
     506            0 :     mbedtls_base64_encode(NULL, 0, &use_len, der_data, der_len);
     507            0 :     add_len = strlen(header) + strlen(footer) + (((use_len > 2) ? (use_len - 2) : 0) / 64) + 1;
     508              : 
     509            0 :     if (use_len + add_len > buf_len) {
     510            0 :         *olen = use_len + add_len;
     511            0 :         return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
     512              :     }
     513              : 
     514            0 :     if (use_len != 0 &&
     515            0 :         ((encode_buf = mbedtls_calloc(1, use_len)) == NULL)) {
     516            0 :         return MBEDTLS_ERR_PEM_ALLOC_FAILED;
     517              :     }
     518              : 
     519            0 :     if ((ret = mbedtls_base64_encode(encode_buf, use_len, &use_len, der_data,
     520              :                                      der_len)) != 0) {
     521            0 :         mbedtls_free(encode_buf);
     522            0 :         return ret;
     523              :     }
     524              : 
     525            0 :     memcpy(p, header, strlen(header));
     526            0 :     p += strlen(header);
     527            0 :     c = encode_buf;
     528              : 
     529            0 :     while (use_len) {
     530            0 :         len = (use_len > 64) ? 64 : use_len;
     531            0 :         memcpy(p, c, len);
     532            0 :         use_len -= len;
     533            0 :         p += len;
     534            0 :         c += len;
     535            0 :         *p++ = '\n';
     536              :     }
     537              : 
     538            0 :     memcpy(p, footer, strlen(footer));
     539            0 :     p += strlen(footer);
     540              : 
     541            0 :     *p++ = '\0';
     542            0 :     *olen = (size_t) (p - buf);
     543              : 
     544              :     /* Clean any remaining data previously written to the buffer */
     545            0 :     memset(buf + *olen, 0, buf_len - *olen);
     546              : 
     547            0 :     mbedtls_free(encode_buf);
     548            0 :     return 0;
     549              : }
     550              : #endif /* MBEDTLS_PEM_WRITE_C */
     551              : #endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */
        

Generated by: LCOV version 2.0-1