LCOV - code coverage report
Current view: top level - contrib/pgcrypto - pgp-encrypt.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 371 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 25 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*
       2              :  * pgp-encrypt.c
       3              :  *        OpenPGP encrypt.
       4              :  *
       5              :  * Copyright (c) 2005 Marko Kreen
       6              :  * All rights reserved.
       7              :  *
       8              :  * Redistribution and use in source and binary forms, with or without
       9              :  * modification, are permitted provided that the following conditions
      10              :  * are met:
      11              :  * 1. Redistributions of source code must retain the above copyright
      12              :  *        notice, this list of conditions and the following disclaimer.
      13              :  * 2. Redistributions in binary form must reproduce the above copyright
      14              :  *        notice, this list of conditions and the following disclaimer in the
      15              :  *        documentation and/or other materials provided with the distribution.
      16              :  *
      17              :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
      18              :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      19              :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      20              :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      21              :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      22              :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      23              :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      24              :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      25              :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      26              :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      27              :  * SUCH DAMAGE.
      28              :  *
      29              :  * contrib/pgcrypto/pgp-encrypt.c
      30              :  */
      31              : 
      32              : #include "postgres.h"
      33              : 
      34              : #include <time.h>
      35              : 
      36              : #include "mbuf.h"
      37              : #include "pgp.h"
      38              : #include "px.h"
      39              : 
      40              : #define MDC_DIGEST_LEN 20
      41              : #define STREAM_ID 0xE0
      42              : #define STREAM_BLOCK_SHIFT      14
      43              : 
      44              : static uint8 *
      45            0 : render_newlen(uint8 *h, int len)
      46              : {
      47            0 :         if (len <= 191)
      48              :         {
      49            0 :                 *h++ = len & 255;
      50            0 :         }
      51            0 :         else if (len > 191 && len <= 8383)
      52              :         {
      53            0 :                 *h++ = ((len - 192) >> 8) + 192;
      54            0 :                 *h++ = (len - 192) & 255;
      55            0 :         }
      56              :         else
      57              :         {
      58            0 :                 *h++ = 255;
      59            0 :                 *h++ = (len >> 24) & 255;
      60            0 :                 *h++ = (len >> 16) & 255;
      61            0 :                 *h++ = (len >> 8) & 255;
      62            0 :                 *h++ = len & 255;
      63              :         }
      64            0 :         return h;
      65              : }
      66              : 
      67              : static int
      68            0 : write_tag_only(PushFilter *dst, int tag)
      69              : {
      70            0 :         uint8           hdr = 0xC0 | tag;
      71              : 
      72            0 :         return pushf_write(dst, &hdr, 1);
      73            0 : }
      74              : 
      75              : static int
      76            0 : write_normal_header(PushFilter *dst, int tag, int len)
      77              : {
      78            0 :         uint8           hdr[8];
      79            0 :         uint8      *h = hdr;
      80              : 
      81            0 :         *h++ = 0xC0 | tag;
      82            0 :         h = render_newlen(h, len);
      83            0 :         return pushf_write(dst, hdr, h - hdr);
      84            0 : }
      85              : 
      86              : 
      87              : /*
      88              :  * MAC writer
      89              :  */
      90              : 
      91              : static int
      92            0 : mdc_init(PushFilter *dst, void *init_arg, void **priv_p)
      93              : {
      94            0 :         int                     res;
      95            0 :         PX_MD      *md;
      96              : 
      97            0 :         res = pgp_load_digest(PGP_DIGEST_SHA1, &md);
      98            0 :         if (res < 0)
      99            0 :                 return res;
     100              : 
     101            0 :         *priv_p = md;
     102            0 :         return 0;
     103            0 : }
     104              : 
     105              : static int
     106            0 : mdc_write(PushFilter *dst, void *priv, const uint8 *data, int len)
     107              : {
     108            0 :         PX_MD      *md = priv;
     109              : 
     110            0 :         px_md_update(md, data, len);
     111            0 :         return pushf_write(dst, data, len);
     112            0 : }
     113              : 
     114              : static int
     115            0 : mdc_flush(PushFilter *dst, void *priv)
     116              : {
     117            0 :         int                     res;
     118            0 :         uint8           pkt[2 + MDC_DIGEST_LEN];
     119            0 :         PX_MD      *md = priv;
     120              : 
     121              :         /*
     122              :          * create mdc pkt
     123              :          */
     124            0 :         pkt[0] = 0xD3;
     125            0 :         pkt[1] = 0x14;                          /* MDC_DIGEST_LEN */
     126            0 :         px_md_update(md, pkt, 2);
     127            0 :         px_md_finish(md, pkt + 2);
     128              : 
     129            0 :         res = pushf_write(dst, pkt, 2 + MDC_DIGEST_LEN);
     130            0 :         px_memset(pkt, 0, 2 + MDC_DIGEST_LEN);
     131            0 :         return res;
     132            0 : }
     133              : 
     134              : static void
     135            0 : mdc_free(void *priv)
     136              : {
     137            0 :         PX_MD      *md = priv;
     138              : 
     139            0 :         px_md_free(md);
     140            0 : }
     141              : 
     142              : static const PushFilterOps mdc_filter = {
     143              :         mdc_init, mdc_write, mdc_flush, mdc_free
     144              : };
     145              : 
     146              : 
     147              : /*
     148              :  * Encrypted pkt writer
     149              :  */
     150              : #define ENCBUF 8192
     151              : struct EncStat
     152              : {
     153              :         PGP_CFB    *ciph;
     154              :         uint8           buf[ENCBUF];
     155              : };
     156              : 
     157              : static int
     158            0 : encrypt_init(PushFilter *next, void *init_arg, void **priv_p)
     159              : {
     160            0 :         struct EncStat *st;
     161            0 :         PGP_Context *ctx = init_arg;
     162            0 :         PGP_CFB    *ciph;
     163            0 :         int                     resync = 1;
     164            0 :         int                     res;
     165              : 
     166              :         /* should we use newer packet format? */
     167            0 :         if (ctx->disable_mdc == 0)
     168              :         {
     169            0 :                 uint8           ver = 1;
     170              : 
     171            0 :                 resync = 0;
     172            0 :                 res = pushf_write(next, &ver, 1);
     173            0 :                 if (res < 0)
     174            0 :                         return res;
     175            0 :         }
     176            0 :         res = pgp_cfb_create(&ciph, ctx->cipher_algo,
     177            0 :                                                  ctx->sess_key, ctx->sess_key_len, resync, NULL);
     178            0 :         if (res < 0)
     179            0 :                 return res;
     180              : 
     181            0 :         st = palloc0_object(struct EncStat);
     182            0 :         st->ciph = ciph;
     183              : 
     184            0 :         *priv_p = st;
     185            0 :         return ENCBUF;
     186            0 : }
     187              : 
     188              : static int
     189            0 : encrypt_process(PushFilter *next, void *priv, const uint8 *data, int len)
     190              : {
     191            0 :         int                     res;
     192            0 :         struct EncStat *st = priv;
     193            0 :         int                     avail = len;
     194              : 
     195            0 :         while (avail > 0)
     196              :         {
     197            0 :                 int                     tmplen = avail > ENCBUF ? ENCBUF : avail;
     198              : 
     199            0 :                 res = pgp_cfb_encrypt(st->ciph, data, tmplen, st->buf);
     200            0 :                 if (res < 0)
     201            0 :                         return res;
     202              : 
     203            0 :                 res = pushf_write(next, st->buf, tmplen);
     204            0 :                 if (res < 0)
     205            0 :                         return res;
     206              : 
     207            0 :                 data += tmplen;
     208            0 :                 avail -= tmplen;
     209            0 :         }
     210            0 :         return 0;
     211            0 : }
     212              : 
     213              : static void
     214            0 : encrypt_free(void *priv)
     215              : {
     216            0 :         struct EncStat *st = priv;
     217              : 
     218            0 :         if (st->ciph)
     219            0 :                 pgp_cfb_free(st->ciph);
     220            0 :         px_memset(st, 0, sizeof(*st));
     221            0 :         pfree(st);
     222            0 : }
     223              : 
     224              : static const PushFilterOps encrypt_filter = {
     225              :         encrypt_init, encrypt_process, NULL, encrypt_free
     226              : };
     227              : 
     228              : /*
     229              :  * Write Streamable pkts
     230              :  */
     231              : 
     232              : struct PktStreamStat
     233              : {
     234              :         int                     final_done;
     235              :         int                     pkt_block;
     236              : };
     237              : 
     238              : static int
     239            0 : pkt_stream_init(PushFilter *next, void *init_arg, void **priv_p)
     240              : {
     241            0 :         struct PktStreamStat *st;
     242              : 
     243            0 :         st = palloc_object(struct PktStreamStat);
     244            0 :         st->final_done = 0;
     245            0 :         st->pkt_block = 1 << STREAM_BLOCK_SHIFT;
     246            0 :         *priv_p = st;
     247              : 
     248            0 :         return st->pkt_block;
     249            0 : }
     250              : 
     251              : static int
     252            0 : pkt_stream_process(PushFilter *next, void *priv, const uint8 *data, int len)
     253              : {
     254            0 :         int                     res;
     255            0 :         uint8           hdr[8];
     256            0 :         uint8      *h = hdr;
     257            0 :         struct PktStreamStat *st = priv;
     258              : 
     259            0 :         if (st->final_done)
     260            0 :                 return PXE_BUG;
     261              : 
     262            0 :         if (len == st->pkt_block)
     263            0 :                 *h++ = STREAM_ID | STREAM_BLOCK_SHIFT;
     264              :         else
     265              :         {
     266            0 :                 h = render_newlen(h, len);
     267            0 :                 st->final_done = 1;
     268              :         }
     269              : 
     270            0 :         res = pushf_write(next, hdr, h - hdr);
     271            0 :         if (res < 0)
     272            0 :                 return res;
     273              : 
     274            0 :         return pushf_write(next, data, len);
     275            0 : }
     276              : 
     277              : static int
     278            0 : pkt_stream_flush(PushFilter *next, void *priv)
     279              : {
     280            0 :         int                     res;
     281            0 :         uint8           hdr[8];
     282            0 :         uint8      *h = hdr;
     283            0 :         struct PktStreamStat *st = priv;
     284              : 
     285              :         /* stream MUST end with normal packet. */
     286            0 :         if (!st->final_done)
     287              :         {
     288            0 :                 h = render_newlen(h, 0);
     289            0 :                 res = pushf_write(next, hdr, h - hdr);
     290            0 :                 if (res < 0)
     291            0 :                         return res;
     292            0 :                 st->final_done = 1;
     293            0 :         }
     294            0 :         return 0;
     295            0 : }
     296              : 
     297              : static void
     298            0 : pkt_stream_free(void *priv)
     299              : {
     300            0 :         struct PktStreamStat *st = priv;
     301              : 
     302            0 :         px_memset(st, 0, sizeof(*st));
     303            0 :         pfree(st);
     304            0 : }
     305              : 
     306              : static const PushFilterOps pkt_stream_filter = {
     307              :         pkt_stream_init, pkt_stream_process, pkt_stream_flush, pkt_stream_free
     308              : };
     309              : 
     310              : int
     311            0 : pgp_create_pkt_writer(PushFilter *dst, int tag, PushFilter **res_p)
     312              : {
     313            0 :         int                     res;
     314              : 
     315            0 :         res = write_tag_only(dst, tag);
     316            0 :         if (res < 0)
     317            0 :                 return res;
     318              : 
     319            0 :         return pushf_create(res_p, &pkt_stream_filter, NULL, dst);
     320            0 : }
     321              : 
     322              : /*
     323              :  * Text conversion filter
     324              :  */
     325              : 
     326              : static int
     327            0 : crlf_process(PushFilter *dst, void *priv, const uint8 *data, int len)
     328              : {
     329            0 :         const uint8 *data_end = data + len;
     330            0 :         const uint8 *p2,
     331            0 :                            *p1 = data;
     332            0 :         int                     line_len;
     333              :         static const uint8 crlf[] = {'\r', '\n'};
     334            0 :         int                     res = 0;
     335              : 
     336            0 :         while (p1 < data_end)
     337              :         {
     338            0 :                 p2 = memchr(p1, '\n', data_end - p1);
     339            0 :                 if (p2 == NULL)
     340            0 :                         p2 = data_end;
     341              : 
     342            0 :                 line_len = p2 - p1;
     343              : 
     344              :                 /* write data */
     345            0 :                 res = 0;
     346            0 :                 if (line_len > 0)
     347              :                 {
     348            0 :                         res = pushf_write(dst, p1, line_len);
     349            0 :                         if (res < 0)
     350            0 :                                 break;
     351            0 :                         p1 += line_len;
     352            0 :                 }
     353              : 
     354              :                 /* write crlf */
     355            0 :                 while (p1 < data_end && *p1 == '\n')
     356              :                 {
     357            0 :                         res = pushf_write(dst, crlf, 2);
     358            0 :                         if (res < 0)
     359            0 :                                 break;
     360            0 :                         p1++;
     361              :                 }
     362              :         }
     363            0 :         return res;
     364            0 : }
     365              : 
     366              : static const PushFilterOps crlf_filter = {
     367              :         NULL, crlf_process, NULL, NULL
     368              : };
     369              : 
     370              : /*
     371              :  * Initialize literal data packet
     372              :  */
     373              : static int
     374            0 : init_litdata_packet(PushFilter **pf_res, PGP_Context *ctx, PushFilter *dst)
     375              : {
     376            0 :         int                     res;
     377            0 :         int                     hdrlen;
     378            0 :         uint8           hdr[6];
     379            0 :         uint32          t;
     380            0 :         PushFilter *pkt;
     381            0 :         int                     type;
     382              : 
     383              :         /*
     384              :          * Create header
     385              :          */
     386              : 
     387            0 :         if (ctx->text_mode)
     388            0 :                 type = ctx->unicode_mode ? 'u' : 't';
     389              :         else
     390            0 :                 type = 'b';
     391              : 
     392              :         /*
     393              :          * Store the creation time into packet. The goal is to have as few known
     394              :          * bytes as possible.
     395              :          */
     396            0 :         t = (uint32) time(NULL);
     397              : 
     398            0 :         hdr[0] = type;
     399            0 :         hdr[1] = 0;
     400            0 :         hdr[2] = (t >> 24) & 255;
     401            0 :         hdr[3] = (t >> 16) & 255;
     402            0 :         hdr[4] = (t >> 8) & 255;
     403            0 :         hdr[5] = t & 255;
     404            0 :         hdrlen = 6;
     405              : 
     406            0 :         res = write_tag_only(dst, PGP_PKT_LITERAL_DATA);
     407            0 :         if (res < 0)
     408            0 :                 return res;
     409              : 
     410            0 :         res = pushf_create(&pkt, &pkt_stream_filter, ctx, dst);
     411            0 :         if (res < 0)
     412            0 :                 return res;
     413              : 
     414            0 :         res = pushf_write(pkt, hdr, hdrlen);
     415            0 :         if (res < 0)
     416              :         {
     417            0 :                 pushf_free(pkt);
     418            0 :                 return res;
     419              :         }
     420              : 
     421            0 :         *pf_res = pkt;
     422            0 :         return 0;
     423            0 : }
     424              : 
     425              : /*
     426              :  * Initialize compression filter
     427              :  */
     428              : static int
     429            0 : init_compress(PushFilter **pf_res, PGP_Context *ctx, PushFilter *dst)
     430              : {
     431            0 :         int                     res;
     432            0 :         uint8           type = ctx->compress_algo;
     433            0 :         PushFilter *pkt;
     434              : 
     435            0 :         res = write_tag_only(dst, PGP_PKT_COMPRESSED_DATA);
     436            0 :         if (res < 0)
     437            0 :                 return res;
     438              : 
     439            0 :         res = pushf_create(&pkt, &pkt_stream_filter, ctx, dst);
     440            0 :         if (res < 0)
     441            0 :                 return res;
     442              : 
     443            0 :         res = pushf_write(pkt, &type, 1);
     444            0 :         if (res >= 0)
     445            0 :                 res = pgp_compress_filter(pf_res, ctx, pkt);
     446              : 
     447            0 :         if (res < 0)
     448            0 :                 pushf_free(pkt);
     449              : 
     450            0 :         return res;
     451            0 : }
     452              : 
     453              : /*
     454              :  * Initialize encdata packet
     455              :  */
     456              : static int
     457            0 : init_encdata_packet(PushFilter **pf_res, PGP_Context *ctx, PushFilter *dst)
     458              : {
     459            0 :         int                     res;
     460            0 :         int                     tag;
     461              : 
     462            0 :         if (ctx->disable_mdc)
     463            0 :                 tag = PGP_PKT_SYMENCRYPTED_DATA;
     464              :         else
     465            0 :                 tag = PGP_PKT_SYMENCRYPTED_DATA_MDC;
     466              : 
     467            0 :         res = write_tag_only(dst, tag);
     468            0 :         if (res < 0)
     469            0 :                 return res;
     470              : 
     471            0 :         return pushf_create(pf_res, &pkt_stream_filter, ctx, dst);
     472            0 : }
     473              : 
     474              : /*
     475              :  * write prefix
     476              :  */
     477              : static int
     478            0 : write_prefix(PGP_Context *ctx, PushFilter *dst)
     479              : {
     480            0 :         uint8           prefix[PGP_MAX_BLOCK + 2];
     481            0 :         int                     res,
     482              :                                 bs;
     483              : 
     484            0 :         bs = pgp_get_cipher_block_size(ctx->cipher_algo);
     485            0 :         if (!pg_strong_random(prefix, bs))
     486            0 :                 return PXE_NO_RANDOM;
     487              : 
     488            0 :         prefix[bs + 0] = prefix[bs - 2];
     489            0 :         prefix[bs + 1] = prefix[bs - 1];
     490              : 
     491            0 :         res = pushf_write(dst, prefix, bs + 2);
     492            0 :         px_memset(prefix, 0, bs + 2);
     493            0 :         return res < 0 ? res : 0;
     494            0 : }
     495              : 
     496              : /*
     497              :  * write symmetrically encrypted session key packet
     498              :  */
     499              : 
     500              : static int
     501            0 : symencrypt_sesskey(PGP_Context *ctx, uint8 *dst)
     502              : {
     503            0 :         int                     res;
     504            0 :         PGP_CFB    *cfb;
     505            0 :         uint8           algo = ctx->cipher_algo;
     506              : 
     507            0 :         res = pgp_cfb_create(&cfb, ctx->s2k_cipher_algo,
     508            0 :                                                  ctx->s2k.key, ctx->s2k.key_len, 0, NULL);
     509            0 :         if (res < 0)
     510            0 :                 return res;
     511              : 
     512            0 :         pgp_cfb_encrypt(cfb, &algo, 1, dst);
     513            0 :         pgp_cfb_encrypt(cfb, ctx->sess_key, ctx->sess_key_len, dst + 1);
     514              : 
     515            0 :         pgp_cfb_free(cfb);
     516            0 :         return ctx->sess_key_len + 1;
     517            0 : }
     518              : 
     519              : /* 5.3: Symmetric-Key Encrypted Session-Key */
     520              : static int
     521            0 : write_symenc_sesskey(PGP_Context *ctx, PushFilter *dst)
     522              : {
     523            0 :         uint8           pkt[256];
     524            0 :         int                     pktlen;
     525            0 :         int                     res;
     526            0 :         uint8      *p = pkt;
     527              : 
     528            0 :         *p++ = 4;                                       /* 5.3 - version number  */
     529            0 :         *p++ = ctx->s2k_cipher_algo;
     530              : 
     531            0 :         *p++ = ctx->s2k.mode;
     532            0 :         *p++ = ctx->s2k.digest_algo;
     533            0 :         if (ctx->s2k.mode > 0)
     534              :         {
     535            0 :                 memcpy(p, ctx->s2k.salt, 8);
     536            0 :                 p += 8;
     537            0 :         }
     538            0 :         if (ctx->s2k.mode == 3)
     539            0 :                 *p++ = ctx->s2k.iter;
     540              : 
     541            0 :         if (ctx->use_sess_key)
     542              :         {
     543            0 :                 res = symencrypt_sesskey(ctx, p);
     544            0 :                 if (res < 0)
     545            0 :                         return res;
     546            0 :                 p += res;
     547            0 :         }
     548              : 
     549            0 :         pktlen = p - pkt;
     550            0 :         res = write_normal_header(dst, PGP_PKT_SYMENCRYPTED_SESSKEY, pktlen);
     551            0 :         if (res >= 0)
     552            0 :                 res = pushf_write(dst, pkt, pktlen);
     553              : 
     554            0 :         px_memset(pkt, 0, pktlen);
     555            0 :         return res;
     556            0 : }
     557              : 
     558              : /*
     559              :  * key setup
     560              :  */
     561              : static int
     562            0 : init_s2k_key(PGP_Context *ctx)
     563              : {
     564            0 :         int                     res;
     565              : 
     566            0 :         if (ctx->s2k_cipher_algo < 0)
     567            0 :                 ctx->s2k_cipher_algo = ctx->cipher_algo;
     568              : 
     569            0 :         res = pgp_s2k_fill(&ctx->s2k, ctx->s2k_mode, ctx->s2k_digest_algo, ctx->s2k_count);
     570            0 :         if (res < 0)
     571            0 :                 return res;
     572              : 
     573            0 :         return pgp_s2k_process(&ctx->s2k, ctx->s2k_cipher_algo,
     574            0 :                                                    ctx->sym_key, ctx->sym_key_len);
     575            0 : }
     576              : 
     577              : static int
     578            0 : init_sess_key(PGP_Context *ctx)
     579              : {
     580            0 :         if (ctx->use_sess_key || ctx->pub_key)
     581              :         {
     582            0 :                 ctx->sess_key_len = pgp_get_cipher_key_size(ctx->cipher_algo);
     583            0 :                 if (!pg_strong_random(ctx->sess_key, ctx->sess_key_len))
     584            0 :                         return PXE_NO_RANDOM;
     585            0 :         }
     586              :         else
     587              :         {
     588            0 :                 ctx->sess_key_len = ctx->s2k.key_len;
     589            0 :                 memcpy(ctx->sess_key, ctx->s2k.key, ctx->s2k.key_len);
     590              :         }
     591              : 
     592            0 :         return 0;
     593            0 : }
     594              : 
     595              : /*
     596              :  * combine
     597              :  */
     598              : int
     599            0 : pgp_encrypt(PGP_Context *ctx, MBuf *src, MBuf *dst)
     600              : {
     601            0 :         int                     res;
     602            0 :         int                     len;
     603            0 :         uint8      *buf;
     604            0 :         PushFilter *pf,
     605              :                            *pf_tmp;
     606              : 
     607              :         /*
     608              :          * do we have any key
     609              :          */
     610            0 :         if (!ctx->sym_key && !ctx->pub_key)
     611            0 :                 return PXE_ARGUMENT_ERROR;
     612              : 
     613              :         /* MBuf writer */
     614            0 :         res = pushf_create_mbuf_writer(&pf, dst);
     615            0 :         if (res < 0)
     616            0 :                 goto out;
     617              : 
     618              :         /*
     619              :          * initialize sym_key
     620              :          */
     621            0 :         if (ctx->sym_key)
     622              :         {
     623            0 :                 res = init_s2k_key(ctx);
     624            0 :                 if (res < 0)
     625            0 :                         goto out;
     626            0 :         }
     627              : 
     628            0 :         res = init_sess_key(ctx);
     629            0 :         if (res < 0)
     630            0 :                 goto out;
     631              : 
     632              :         /*
     633              :          * write keypkt
     634              :          */
     635            0 :         if (ctx->pub_key)
     636            0 :                 res = pgp_write_pubenc_sesskey(ctx, pf);
     637              :         else
     638            0 :                 res = write_symenc_sesskey(ctx, pf);
     639            0 :         if (res < 0)
     640            0 :                 goto out;
     641              : 
     642              :         /* encrypted data pkt */
     643            0 :         res = init_encdata_packet(&pf_tmp, ctx, pf);
     644            0 :         if (res < 0)
     645            0 :                 goto out;
     646            0 :         pf = pf_tmp;
     647              : 
     648              :         /* encrypter */
     649            0 :         res = pushf_create(&pf_tmp, &encrypt_filter, ctx, pf);
     650            0 :         if (res < 0)
     651            0 :                 goto out;
     652            0 :         pf = pf_tmp;
     653              : 
     654              :         /* hasher */
     655            0 :         if (ctx->disable_mdc == 0)
     656              :         {
     657            0 :                 res = pushf_create(&pf_tmp, &mdc_filter, ctx, pf);
     658            0 :                 if (res < 0)
     659            0 :                         goto out;
     660            0 :                 pf = pf_tmp;
     661            0 :         }
     662              : 
     663              :         /* prefix */
     664            0 :         res = write_prefix(ctx, pf);
     665            0 :         if (res < 0)
     666            0 :                 goto out;
     667              : 
     668              :         /* compressor */
     669            0 :         if (ctx->compress_algo > 0 && ctx->compress_level > 0)
     670              :         {
     671            0 :                 res = init_compress(&pf_tmp, ctx, pf);
     672            0 :                 if (res < 0)
     673            0 :                         goto out;
     674            0 :                 pf = pf_tmp;
     675            0 :         }
     676              : 
     677              :         /* data streamer */
     678            0 :         res = init_litdata_packet(&pf_tmp, ctx, pf);
     679            0 :         if (res < 0)
     680            0 :                 goto out;
     681            0 :         pf = pf_tmp;
     682              : 
     683              : 
     684              :         /* text conversion? */
     685            0 :         if (ctx->text_mode && ctx->convert_crlf)
     686              :         {
     687            0 :                 res = pushf_create(&pf_tmp, &crlf_filter, ctx, pf);
     688            0 :                 if (res < 0)
     689            0 :                         goto out;
     690            0 :                 pf = pf_tmp;
     691            0 :         }
     692              : 
     693              :         /*
     694              :          * chain complete
     695              :          */
     696              : 
     697            0 :         len = mbuf_grab(src, mbuf_avail(src), &buf);
     698            0 :         res = pushf_write(pf, buf, len);
     699            0 :         if (res >= 0)
     700            0 :                 res = pushf_flush(pf);
     701              : out:
     702            0 :         pushf_free_all(pf);
     703            0 :         return res;
     704            0 : }
        

Generated by: LCOV version 2.3.2-1