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

            Line data    Source code
       1              : /*
       2              :  * pgp-decrypt.c
       3              :  *        OpenPGP decrypt.
       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-decrypt.c
      30              :  */
      31              : 
      32              : #include "postgres.h"
      33              : 
      34              : #include "mbuf.h"
      35              : #include "pgp.h"
      36              : #include "px.h"
      37              : 
      38              : #define NO_CTX_SIZE             0
      39              : #define ALLOW_CTX_SIZE  1
      40              : #define NO_COMPR                0
      41              : #define ALLOW_COMPR             1
      42              : #define NO_MDC                  0
      43              : #define NEED_MDC                1
      44              : 
      45              : #define PKT_NORMAL 1
      46              : #define PKT_STREAM 2
      47              : #define PKT_CONTEXT 3
      48              : 
      49              : #define MAX_CHUNK (16*1024*1024)
      50              : 
      51              : static int
      52            0 : parse_new_len(PullFilter *src, int *len_p)
      53              : {
      54            0 :         uint8           b;
      55            0 :         int                     len;
      56            0 :         int                     pkttype = PKT_NORMAL;
      57              : 
      58            0 :         GETBYTE(src, b);
      59            0 :         if (b <= 191)
      60            0 :                 len = b;
      61            0 :         else if (b >= 192 && b <= 223)
      62              :         {
      63            0 :                 len = ((unsigned) (b) - 192) << 8;
      64            0 :                 GETBYTE(src, b);
      65            0 :                 len += 192 + b;
      66            0 :         }
      67            0 :         else if (b == 255)
      68              :         {
      69            0 :                 GETBYTE(src, b);
      70            0 :                 len = b;
      71            0 :                 GETBYTE(src, b);
      72            0 :                 len = (len << 8) | b;
      73            0 :                 GETBYTE(src, b);
      74            0 :                 len = (len << 8) | b;
      75            0 :                 GETBYTE(src, b);
      76            0 :                 len = (len << 8) | b;
      77            0 :         }
      78              :         else
      79              :         {
      80            0 :                 len = 1 << (b & 0x1F);
      81            0 :                 pkttype = PKT_STREAM;
      82              :         }
      83              : 
      84            0 :         if (len < 0 || len > MAX_CHUNK)
      85              :         {
      86            0 :                 px_debug("parse_new_len: weird length");
      87            0 :                 return PXE_PGP_CORRUPT_DATA;
      88              :         }
      89              : 
      90            0 :         *len_p = len;
      91            0 :         return pkttype;
      92            0 : }
      93              : 
      94              : static int
      95            0 : parse_old_len(PullFilter *src, int *len_p, int lentype)
      96              : {
      97            0 :         uint8           b;
      98            0 :         int                     len;
      99              : 
     100            0 :         GETBYTE(src, b);
     101            0 :         len = b;
     102              : 
     103            0 :         if (lentype == 1)
     104              :         {
     105            0 :                 GETBYTE(src, b);
     106            0 :                 len = (len << 8) | b;
     107            0 :         }
     108            0 :         else if (lentype == 2)
     109              :         {
     110            0 :                 GETBYTE(src, b);
     111            0 :                 len = (len << 8) | b;
     112            0 :                 GETBYTE(src, b);
     113            0 :                 len = (len << 8) | b;
     114            0 :                 GETBYTE(src, b);
     115            0 :                 len = (len << 8) | b;
     116            0 :         }
     117              : 
     118            0 :         if (len < 0 || len > MAX_CHUNK)
     119              :         {
     120            0 :                 px_debug("parse_old_len: weird length");
     121            0 :                 return PXE_PGP_CORRUPT_DATA;
     122              :         }
     123            0 :         *len_p = len;
     124            0 :         return PKT_NORMAL;
     125            0 : }
     126              : 
     127              : /* returns pkttype or 0 on eof */
     128              : int
     129            0 : pgp_parse_pkt_hdr(PullFilter *src, uint8 *tag, int *len_p, int allow_ctx)
     130              : {
     131            0 :         int                     lentype;
     132            0 :         int                     res;
     133            0 :         uint8      *p;
     134              : 
     135              :         /* EOF is normal here, thus we don't use GETBYTE */
     136            0 :         res = pullf_read(src, 1, &p);
     137            0 :         if (res < 0)
     138            0 :                 return res;
     139            0 :         if (res == 0)
     140            0 :                 return 0;
     141              : 
     142            0 :         if ((*p & 0x80) == 0)
     143              :         {
     144            0 :                 px_debug("pgp_parse_pkt_hdr: not pkt hdr");
     145            0 :                 return PXE_PGP_CORRUPT_DATA;
     146              :         }
     147              : 
     148            0 :         if (*p & 0x40)
     149              :         {
     150            0 :                 *tag = *p & 0x3f;
     151            0 :                 res = parse_new_len(src, len_p);
     152            0 :         }
     153              :         else
     154              :         {
     155            0 :                 lentype = *p & 3;
     156            0 :                 *tag = (*p >> 2) & 0x0F;
     157            0 :                 if (lentype == 3)
     158            0 :                         res = allow_ctx ? PKT_CONTEXT : PXE_PGP_CORRUPT_DATA;
     159              :                 else
     160            0 :                         res = parse_old_len(src, len_p, lentype);
     161              :         }
     162            0 :         return res;
     163            0 : }
     164              : 
     165              : /*
     166              :  * Packet reader
     167              :  */
     168              : struct PktData
     169              : {
     170              :         int                     type;
     171              :         int                     len;
     172              : };
     173              : 
     174              : static int
     175            0 : pktreader_pull(void *priv, PullFilter *src, int len,
     176              :                            uint8 **data_p, uint8 *buf, int buflen)
     177              : {
     178            0 :         int                     res;
     179            0 :         struct PktData *pkt = priv;
     180              : 
     181              :         /* PKT_CONTEXT means: whatever there is */
     182            0 :         if (pkt->type == PKT_CONTEXT)
     183            0 :                 return pullf_read(src, len, data_p);
     184              : 
     185            0 :         while (pkt->len == 0)
     186              :         {
     187              :                 /* this was last chunk in stream */
     188            0 :                 if (pkt->type == PKT_NORMAL)
     189            0 :                         return 0;
     190              : 
     191              :                 /* next chunk in stream */
     192            0 :                 res = parse_new_len(src, &pkt->len);
     193            0 :                 if (res < 0)
     194            0 :                         return res;
     195            0 :                 pkt->type = res;
     196              :         }
     197              : 
     198            0 :         if (len > pkt->len)
     199            0 :                 len = pkt->len;
     200              : 
     201            0 :         res = pullf_read(src, len, data_p);
     202            0 :         if (res > 0)
     203            0 :                 pkt->len -= res;
     204              : 
     205            0 :         return res;
     206            0 : }
     207              : 
     208              : static void
     209            0 : pktreader_free(void *priv)
     210              : {
     211            0 :         struct PktData *pkt = priv;
     212              : 
     213            0 :         px_memset(pkt, 0, sizeof(*pkt));
     214            0 :         pfree(pkt);
     215            0 : }
     216              : 
     217              : static struct PullFilterOps pktreader_filter = {
     218              :         NULL, pktreader_pull, pktreader_free
     219              : };
     220              : 
     221              : /* needs helper function to pass several parameters */
     222              : int
     223            0 : pgp_create_pkt_reader(PullFilter **pf_p, PullFilter *src, int len,
     224              :                                           int pkttype, PGP_Context *ctx)
     225              : {
     226            0 :         int                     res;
     227            0 :         struct PktData *pkt = palloc_object(struct PktData);
     228              : 
     229            0 :         pkt->type = pkttype;
     230            0 :         pkt->len = len;
     231            0 :         res = pullf_create(pf_p, &pktreader_filter, pkt, src);
     232            0 :         if (res < 0)
     233            0 :                 pfree(pkt);
     234            0 :         return res;
     235            0 : }
     236              : 
     237              : /*
     238              :  * Prefix check filter
     239              :  * https://tools.ietf.org/html/rfc4880#section-5.7
     240              :  * https://tools.ietf.org/html/rfc4880#section-5.13
     241              :  */
     242              : 
     243              : static int
     244            0 : prefix_init(void **priv_p, void *arg, PullFilter *src)
     245              : {
     246            0 :         PGP_Context *ctx = arg;
     247            0 :         int                     len;
     248            0 :         int                     res;
     249            0 :         uint8      *buf;
     250            0 :         uint8           tmpbuf[PGP_MAX_BLOCK + 2];
     251              : 
     252            0 :         len = pgp_get_cipher_block_size(ctx->cipher_algo);
     253              :         /* Make sure we have space for prefix */
     254            0 :         if (len > PGP_MAX_BLOCK)
     255            0 :                 return PXE_BUG;
     256              : 
     257            0 :         res = pullf_read_max(src, len + 2, &buf, tmpbuf);
     258            0 :         if (res < 0)
     259            0 :                 return res;
     260            0 :         if (res != len + 2)
     261              :         {
     262            0 :                 px_debug("prefix_init: short read");
     263            0 :                 px_memset(tmpbuf, 0, sizeof(tmpbuf));
     264            0 :                 return PXE_PGP_CORRUPT_DATA;
     265              :         }
     266              : 
     267            0 :         if (buf[len - 2] != buf[len] || buf[len - 1] != buf[len + 1])
     268              :         {
     269            0 :                 px_debug("prefix_init: corrupt prefix");
     270              :                 /* report error in pgp_decrypt() */
     271            0 :                 ctx->corrupt_prefix = 1;
     272            0 :         }
     273            0 :         px_memset(tmpbuf, 0, sizeof(tmpbuf));
     274            0 :         return 0;
     275            0 : }
     276              : 
     277              : static struct PullFilterOps prefix_filter = {
     278              :         prefix_init, NULL, NULL
     279              : };
     280              : 
     281              : 
     282              : /*
     283              :  * Decrypt filter
     284              :  */
     285              : 
     286              : static int
     287            0 : decrypt_init(void **priv_p, void *arg, PullFilter *src)
     288              : {
     289            0 :         PGP_CFB    *cfb = arg;
     290              : 
     291            0 :         *priv_p = cfb;
     292              : 
     293              :         /* we need to write somewhere, so ask for a buffer */
     294            0 :         return 4096;
     295            0 : }
     296              : 
     297              : static int
     298            0 : decrypt_read(void *priv, PullFilter *src, int len,
     299              :                          uint8 **data_p, uint8 *buf, int buflen)
     300              : {
     301            0 :         PGP_CFB    *cfb = priv;
     302            0 :         uint8      *tmp;
     303            0 :         int                     res;
     304              : 
     305            0 :         res = pullf_read(src, len, &tmp);
     306            0 :         if (res > 0)
     307              :         {
     308            0 :                 pgp_cfb_decrypt(cfb, tmp, res, buf);
     309            0 :                 *data_p = buf;
     310            0 :         }
     311            0 :         return res;
     312            0 : }
     313              : 
     314              : struct PullFilterOps pgp_decrypt_filter = {
     315              :         decrypt_init, decrypt_read, NULL
     316              : };
     317              : 
     318              : 
     319              : /*
     320              :  * MDC hasher filter
     321              :  */
     322              : 
     323              : static int
     324            0 : mdc_init(void **priv_p, void *arg, PullFilter *src)
     325              : {
     326            0 :         PGP_Context *ctx = arg;
     327              : 
     328            0 :         *priv_p = ctx;
     329            0 :         return pgp_load_digest(PGP_DIGEST_SHA1, &ctx->mdc_ctx);
     330            0 : }
     331              : 
     332              : static void
     333            0 : mdc_free(void *priv)
     334              : {
     335            0 :         PGP_Context *ctx = priv;
     336              : 
     337            0 :         if (ctx->use_mdcbuf_filter)
     338            0 :                 return;
     339            0 :         px_md_free(ctx->mdc_ctx);
     340            0 :         ctx->mdc_ctx = NULL;
     341            0 : }
     342              : 
     343              : static int
     344            0 : mdc_finish(PGP_Context *ctx, PullFilter *src, int len)
     345              : {
     346            0 :         int                     res;
     347            0 :         uint8           hash[20];
     348            0 :         uint8           tmpbuf[20];
     349            0 :         uint8      *data;
     350              : 
     351              :         /* should not happen */
     352            0 :         if (ctx->use_mdcbuf_filter)
     353            0 :                 return PXE_BUG;
     354              : 
     355              :         /* It's SHA1 */
     356            0 :         if (len != 20)
     357            0 :                 return PXE_PGP_CORRUPT_DATA;
     358              : 
     359              :         /* mdc_read should not call px_md_update */
     360            0 :         ctx->in_mdc_pkt = 1;
     361              : 
     362              :         /* read data */
     363            0 :         res = pullf_read_max(src, len, &data, tmpbuf);
     364            0 :         if (res < 0)
     365            0 :                 return res;
     366            0 :         if (res == 0)
     367              :         {
     368            0 :                 px_debug("no mdc");
     369            0 :                 return PXE_PGP_CORRUPT_DATA;
     370              :         }
     371              : 
     372              :         /* is the packet sane? */
     373            0 :         if (res != 20)
     374              :         {
     375            0 :                 px_debug("mdc_finish: read failed, res=%d", res);
     376            0 :                 return PXE_PGP_CORRUPT_DATA;
     377              :         }
     378              : 
     379              :         /*
     380              :          * ok, we got the hash, now check
     381              :          */
     382            0 :         px_md_finish(ctx->mdc_ctx, hash);
     383            0 :         res = memcmp(hash, data, 20);
     384            0 :         px_memset(hash, 0, 20);
     385            0 :         px_memset(tmpbuf, 0, sizeof(tmpbuf));
     386            0 :         if (res != 0)
     387              :         {
     388            0 :                 px_debug("mdc_finish: mdc failed");
     389            0 :                 return PXE_PGP_CORRUPT_DATA;
     390              :         }
     391            0 :         ctx->mdc_checked = 1;
     392            0 :         return 0;
     393            0 : }
     394              : 
     395              : static int
     396            0 : mdc_read(void *priv, PullFilter *src, int len,
     397              :                  uint8 **data_p, uint8 *buf, int buflen)
     398              : {
     399            0 :         int                     res;
     400            0 :         PGP_Context *ctx = priv;
     401              : 
     402              :         /* skip this filter? */
     403            0 :         if (ctx->use_mdcbuf_filter || ctx->in_mdc_pkt)
     404            0 :                 return pullf_read(src, len, data_p);
     405              : 
     406            0 :         res = pullf_read(src, len, data_p);
     407            0 :         if (res < 0)
     408            0 :                 return res;
     409            0 :         if (res == 0)
     410              :         {
     411            0 :                 px_debug("mdc_read: unexpected eof");
     412            0 :                 return PXE_PGP_CORRUPT_DATA;
     413              :         }
     414            0 :         px_md_update(ctx->mdc_ctx, *data_p, res);
     415              : 
     416            0 :         return res;
     417            0 : }
     418              : 
     419              : static struct PullFilterOps mdc_filter = {
     420              :         mdc_init, mdc_read, mdc_free
     421              : };
     422              : 
     423              : 
     424              : /*
     425              :  * Combined Pkt reader and MDC hasher.
     426              :  *
     427              :  * For the case of SYMENCRYPTED_DATA_MDC packet, where
     428              :  * the data part has 'context length', which means
     429              :  * that data packet ends 22 bytes before end of parent
     430              :  * packet, which is silly.
     431              :  */
     432              : #define MDCBUF_LEN 8192
     433              : struct MDCBufData
     434              : {
     435              :         PGP_Context *ctx;
     436              :         int                     eof;
     437              :         int                     buflen;
     438              :         int                     avail;
     439              :         uint8      *pos;
     440              :         int                     mdc_avail;
     441              :         uint8           mdc_buf[22];
     442              :         uint8           buf[MDCBUF_LEN];
     443              : };
     444              : 
     445              : static int
     446            0 : mdcbuf_init(void **priv_p, void *arg, PullFilter *src)
     447              : {
     448            0 :         PGP_Context *ctx = arg;
     449            0 :         struct MDCBufData *st;
     450              : 
     451            0 :         st = palloc0_object(struct MDCBufData);
     452            0 :         st->buflen = sizeof(st->buf);
     453            0 :         st->ctx = ctx;
     454            0 :         *priv_p = st;
     455              : 
     456              :         /* take over the work of mdc_filter */
     457            0 :         ctx->use_mdcbuf_filter = 1;
     458              : 
     459            0 :         return 0;
     460            0 : }
     461              : 
     462              : static int
     463            0 : mdcbuf_finish(struct MDCBufData *st)
     464              : {
     465            0 :         uint8           hash[20];
     466            0 :         int                     res;
     467              : 
     468            0 :         st->eof = 1;
     469              : 
     470            0 :         if (st->mdc_buf[0] != 0xD3 || st->mdc_buf[1] != 0x14)
     471              :         {
     472            0 :                 px_debug("mdcbuf_finish: bad MDC pkt hdr");
     473            0 :                 return PXE_PGP_CORRUPT_DATA;
     474              :         }
     475            0 :         px_md_update(st->ctx->mdc_ctx, st->mdc_buf, 2);
     476            0 :         px_md_finish(st->ctx->mdc_ctx, hash);
     477            0 :         res = memcmp(hash, st->mdc_buf + 2, 20);
     478            0 :         px_memset(hash, 0, 20);
     479            0 :         if (res)
     480              :         {
     481            0 :                 px_debug("mdcbuf_finish: MDC does not match");
     482            0 :                 res = PXE_PGP_CORRUPT_DATA;
     483            0 :         }
     484            0 :         return res;
     485            0 : }
     486              : 
     487              : static void
     488            0 : mdcbuf_load_data(struct MDCBufData *st, uint8 *src, int len)
     489              : {
     490            0 :         uint8      *dst = st->pos + st->avail;
     491              : 
     492            0 :         memcpy(dst, src, len);
     493            0 :         px_md_update(st->ctx->mdc_ctx, src, len);
     494            0 :         st->avail += len;
     495            0 : }
     496              : 
     497              : static void
     498            0 : mdcbuf_load_mdc(struct MDCBufData *st, uint8 *src, int len)
     499              : {
     500            0 :         memmove(st->mdc_buf + st->mdc_avail, src, len);
     501            0 :         st->mdc_avail += len;
     502            0 : }
     503              : 
     504              : static int
     505            0 : mdcbuf_refill(struct MDCBufData *st, PullFilter *src)
     506              : {
     507            0 :         uint8      *data;
     508            0 :         int                     res;
     509            0 :         int                     need;
     510              : 
     511              :         /* put avail data in start */
     512            0 :         if (st->avail > 0 && st->pos != st->buf)
     513            0 :                 memmove(st->buf, st->pos, st->avail);
     514            0 :         st->pos = st->buf;
     515              : 
     516              :         /* read new data */
     517            0 :         need = st->buflen + 22 - st->avail - st->mdc_avail;
     518            0 :         res = pullf_read(src, need, &data);
     519            0 :         if (res < 0)
     520            0 :                 return res;
     521            0 :         if (res == 0)
     522            0 :                 return mdcbuf_finish(st);
     523              : 
     524              :         /* add to buffer */
     525            0 :         if (res >= 22)
     526              :         {
     527            0 :                 mdcbuf_load_data(st, st->mdc_buf, st->mdc_avail);
     528            0 :                 st->mdc_avail = 0;
     529              : 
     530            0 :                 mdcbuf_load_data(st, data, res - 22);
     531            0 :                 mdcbuf_load_mdc(st, data + res - 22, 22);
     532            0 :         }
     533              :         else
     534              :         {
     535            0 :                 int                     canmove = st->mdc_avail + res - 22;
     536              : 
     537            0 :                 if (canmove > 0)
     538              :                 {
     539            0 :                         mdcbuf_load_data(st, st->mdc_buf, canmove);
     540            0 :                         st->mdc_avail -= canmove;
     541            0 :                         memmove(st->mdc_buf, st->mdc_buf + canmove, st->mdc_avail);
     542            0 :                 }
     543            0 :                 mdcbuf_load_mdc(st, data, res);
     544            0 :         }
     545            0 :         return 0;
     546            0 : }
     547              : 
     548              : static int
     549            0 : mdcbuf_read(void *priv, PullFilter *src, int len,
     550              :                         uint8 **data_p, uint8 *buf, int buflen)
     551              : {
     552            0 :         struct MDCBufData *st = priv;
     553            0 :         int                     res;
     554              : 
     555            0 :         if (!st->eof && len > st->avail)
     556              :         {
     557            0 :                 res = mdcbuf_refill(st, src);
     558            0 :                 if (res < 0)
     559            0 :                         return res;
     560            0 :         }
     561              : 
     562            0 :         if (len > st->avail)
     563            0 :                 len = st->avail;
     564              : 
     565            0 :         *data_p = st->pos;
     566            0 :         st->pos += len;
     567            0 :         st->avail -= len;
     568            0 :         return len;
     569            0 : }
     570              : 
     571              : static void
     572            0 : mdcbuf_free(void *priv)
     573              : {
     574            0 :         struct MDCBufData *st = priv;
     575              : 
     576            0 :         px_md_free(st->ctx->mdc_ctx);
     577            0 :         st->ctx->mdc_ctx = NULL;
     578            0 :         px_memset(st, 0, sizeof(*st));
     579            0 :         pfree(st);
     580            0 : }
     581              : 
     582              : static struct PullFilterOps mdcbuf_filter = {
     583              :         mdcbuf_init, mdcbuf_read, mdcbuf_free
     584              : };
     585              : 
     586              : 
     587              : /*
     588              :  * Decrypt separate session key
     589              :  */
     590              : static int
     591            0 : decrypt_key(PGP_Context *ctx, const uint8 *src, int len)
     592              : {
     593            0 :         int                     res;
     594            0 :         uint8           algo;
     595            0 :         PGP_CFB    *cfb;
     596              : 
     597            0 :         res = pgp_cfb_create(&cfb, ctx->s2k_cipher_algo,
     598            0 :                                                  ctx->s2k.key, ctx->s2k.key_len, 0, NULL);
     599            0 :         if (res < 0)
     600            0 :                 return res;
     601              : 
     602            0 :         pgp_cfb_decrypt(cfb, src, 1, &algo);
     603            0 :         src++;
     604            0 :         len--;
     605              : 
     606            0 :         pgp_cfb_decrypt(cfb, src, len, ctx->sess_key);
     607            0 :         pgp_cfb_free(cfb);
     608            0 :         ctx->sess_key_len = len;
     609            0 :         ctx->cipher_algo = algo;
     610              : 
     611            0 :         if (pgp_get_cipher_key_size(algo) != len)
     612              :         {
     613            0 :                 px_debug("sesskey bad len: algo=%d, expected=%d, got=%d",
     614            0 :                                  algo, pgp_get_cipher_key_size(algo), len);
     615            0 :                 return PXE_PGP_CORRUPT_DATA;
     616              :         }
     617            0 :         return 0;
     618            0 : }
     619              : 
     620              : /*
     621              :  * Handle key packet
     622              :  */
     623              : static int
     624            0 : parse_symenc_sesskey(PGP_Context *ctx, PullFilter *src)
     625              : {
     626            0 :         uint8      *p;
     627            0 :         int                     res;
     628            0 :         uint8           tmpbuf[PGP_MAX_KEY + 2];
     629            0 :         uint8           ver;
     630              : 
     631            0 :         GETBYTE(src, ver);
     632            0 :         GETBYTE(src, ctx->s2k_cipher_algo);
     633            0 :         if (ver != 4)
     634              :         {
     635            0 :                 px_debug("bad key pkt ver");
     636            0 :                 return PXE_PGP_CORRUPT_DATA;
     637              :         }
     638              : 
     639              :         /*
     640              :          * read S2K info
     641              :          */
     642            0 :         res = pgp_s2k_read(src, &ctx->s2k);
     643            0 :         if (res < 0)
     644            0 :                 return res;
     645            0 :         ctx->s2k_mode = ctx->s2k.mode;
     646            0 :         ctx->s2k_count = s2k_decode_count(ctx->s2k.iter);
     647            0 :         ctx->s2k_digest_algo = ctx->s2k.digest_algo;
     648              : 
     649              :         /*
     650              :          * generate key from password
     651              :          */
     652            0 :         res = pgp_s2k_process(&ctx->s2k, ctx->s2k_cipher_algo,
     653            0 :                                                   ctx->sym_key, ctx->sym_key_len);
     654            0 :         if (res < 0)
     655            0 :                 return res;
     656              : 
     657              :         /*
     658              :          * do we have separate session key?
     659              :          */
     660            0 :         res = pullf_read_max(src, PGP_MAX_KEY + 2, &p, tmpbuf);
     661            0 :         if (res < 0)
     662            0 :                 return res;
     663              : 
     664            0 :         if (res == 0)
     665              :         {
     666              :                 /*
     667              :                  * no, s2k key is session key
     668              :                  */
     669            0 :                 memcpy(ctx->sess_key, ctx->s2k.key, ctx->s2k.key_len);
     670            0 :                 ctx->sess_key_len = ctx->s2k.key_len;
     671            0 :                 ctx->cipher_algo = ctx->s2k_cipher_algo;
     672            0 :                 res = 0;
     673            0 :                 ctx->use_sess_key = 0;
     674            0 :         }
     675              :         else
     676              :         {
     677              :                 /*
     678              :                  * yes, decrypt it
     679              :                  */
     680            0 :                 if (res < 17 || res > PGP_MAX_KEY + 1)
     681              :                 {
     682            0 :                         px_debug("expect key, but bad data");
     683            0 :                         return PXE_PGP_CORRUPT_DATA;
     684              :                 }
     685            0 :                 ctx->use_sess_key = 1;
     686            0 :                 res = decrypt_key(ctx, p, res);
     687              :         }
     688              : 
     689            0 :         px_memset(tmpbuf, 0, sizeof(tmpbuf));
     690            0 :         return res;
     691            0 : }
     692              : 
     693              : static int
     694            0 : copy_crlf(MBuf *dst, uint8 *data, int len, int *got_cr)
     695              : {
     696            0 :         uint8      *data_end = data + len;
     697            0 :         uint8           tmpbuf[1024];
     698            0 :         uint8      *tmp_end = tmpbuf + sizeof(tmpbuf);
     699            0 :         uint8      *p;
     700            0 :         int                     res;
     701              : 
     702            0 :         p = tmpbuf;
     703            0 :         if (*got_cr)
     704              :         {
     705            0 :                 if (*data != '\n')
     706            0 :                         *p++ = '\r';
     707            0 :                 *got_cr = 0;
     708            0 :         }
     709            0 :         while (data < data_end)
     710              :         {
     711            0 :                 if (*data == '\r')
     712              :                 {
     713            0 :                         if (data + 1 < data_end)
     714              :                         {
     715            0 :                                 if (*(data + 1) == '\n')
     716            0 :                                         data++;
     717            0 :                         }
     718              :                         else
     719              :                         {
     720            0 :                                 *got_cr = 1;
     721            0 :                                 break;
     722              :                         }
     723            0 :                 }
     724            0 :                 *p++ = *data++;
     725            0 :                 if (p >= tmp_end)
     726              :                 {
     727            0 :                         res = mbuf_append(dst, tmpbuf, p - tmpbuf);
     728            0 :                         if (res < 0)
     729            0 :                                 return res;
     730            0 :                         p = tmpbuf;
     731            0 :                 }
     732              :         }
     733            0 :         if (p - tmpbuf > 0)
     734              :         {
     735            0 :                 res = mbuf_append(dst, tmpbuf, p - tmpbuf);
     736            0 :                 if (res < 0)
     737            0 :                         return res;
     738            0 :         }
     739            0 :         px_memset(tmpbuf, 0, sizeof(tmpbuf));
     740            0 :         return 0;
     741            0 : }
     742              : 
     743              : static int
     744            0 : parse_literal_data(PGP_Context *ctx, MBuf *dst, PullFilter *pkt)
     745              : {
     746            0 :         int                     type;
     747            0 :         int                     name_len;
     748            0 :         int                     res;
     749            0 :         uint8      *buf;
     750            0 :         uint8           tmpbuf[4];
     751            0 :         int                     got_cr = 0;
     752              : 
     753            0 :         GETBYTE(pkt, type);
     754            0 :         GETBYTE(pkt, name_len);
     755              : 
     756              :         /* skip name */
     757            0 :         while (name_len > 0)
     758              :         {
     759            0 :                 res = pullf_read(pkt, name_len, &buf);
     760            0 :                 if (res < 0)
     761            0 :                         return res;
     762            0 :                 if (res == 0)
     763            0 :                         break;
     764            0 :                 name_len -= res;
     765              :         }
     766            0 :         if (name_len > 0)
     767              :         {
     768            0 :                 px_debug("parse_literal_data: unexpected eof");
     769            0 :                 return PXE_PGP_CORRUPT_DATA;
     770              :         }
     771              : 
     772              :         /* skip date */
     773            0 :         res = pullf_read_max(pkt, 4, &buf, tmpbuf);
     774            0 :         if (res != 4)
     775              :         {
     776            0 :                 px_debug("parse_literal_data: unexpected eof");
     777            0 :                 return PXE_PGP_CORRUPT_DATA;
     778              :         }
     779            0 :         px_memset(tmpbuf, 0, 4);
     780              : 
     781              :         /*
     782              :          * If called from an SQL function that returns text, pgp_decrypt() rejects
     783              :          * inputs not self-identifying as text.
     784              :          */
     785            0 :         if (ctx->text_mode)
     786            0 :                 if (type != 't' && type != 'u')
     787              :                 {
     788            0 :                         px_debug("parse_literal_data: data type=%c", type);
     789            0 :                         ctx->unexpected_binary = true;
     790            0 :                 }
     791              : 
     792            0 :         ctx->unicode_mode = (type == 'u') ? 1 : 0;
     793              : 
     794              :         /* read data */
     795            0 :         while (1)
     796              :         {
     797            0 :                 res = pullf_read(pkt, 32 * 1024, &buf);
     798            0 :                 if (res <= 0)
     799            0 :                         break;
     800              : 
     801            0 :                 if (ctx->text_mode && ctx->convert_crlf)
     802            0 :                         res = copy_crlf(dst, buf, res, &got_cr);
     803              :                 else
     804            0 :                         res = mbuf_append(dst, buf, res);
     805            0 :                 if (res < 0)
     806            0 :                         break;
     807              :         }
     808            0 :         if (res >= 0 && got_cr)
     809            0 :                 res = mbuf_append(dst, (const uint8 *) "\r", 1);
     810            0 :         return res;
     811            0 : }
     812              : 
     813              : /* process_data_packets and parse_compressed_data call each other */
     814              : static int      process_data_packets(PGP_Context *ctx, MBuf *dst,
     815              :                                                                  PullFilter *src, int allow_compr, int need_mdc);
     816              : 
     817              : static int
     818            0 : parse_compressed_data(PGP_Context *ctx, MBuf *dst, PullFilter *pkt)
     819              : {
     820            0 :         int                     res;
     821            0 :         uint8           type;
     822            0 :         PullFilter *pf_decompr;
     823            0 :         uint8      *discard_buf;
     824              : 
     825            0 :         GETBYTE(pkt, type);
     826              : 
     827            0 :         ctx->compress_algo = type;
     828            0 :         switch (type)
     829              :         {
     830              :                 case PGP_COMPR_NONE:
     831            0 :                         res = process_data_packets(ctx, dst, pkt, NO_COMPR, NO_MDC);
     832            0 :                         break;
     833              : 
     834              :                 case PGP_COMPR_ZIP:
     835              :                 case PGP_COMPR_ZLIB:
     836            0 :                         res = pgp_decompress_filter(&pf_decompr, ctx, pkt);
     837            0 :                         if (res >= 0)
     838              :                         {
     839            0 :                                 res = process_data_packets(ctx, dst, pf_decompr,
     840              :                                                                                    NO_COMPR, NO_MDC);
     841            0 :                                 pullf_free(pf_decompr);
     842            0 :                         }
     843            0 :                         break;
     844              : 
     845              :                 case PGP_COMPR_BZIP2:
     846            0 :                         px_debug("parse_compressed_data: bzip2 unsupported");
     847              :                         /* report error in pgp_decrypt() */
     848            0 :                         ctx->unsupported_compr = 1;
     849              : 
     850              :                         /*
     851              :                          * Discard the compressed data, allowing it to first affect any
     852              :                          * MDC digest computation.
     853              :                          */
     854            0 :                         while (1)
     855              :                         {
     856            0 :                                 res = pullf_read(pkt, 32 * 1024, &discard_buf);
     857            0 :                                 if (res <= 0)
     858            0 :                                         break;
     859              :                         }
     860              : 
     861            0 :                         break;
     862              : 
     863              :                 default:
     864            0 :                         px_debug("parse_compressed_data: unknown compr type");
     865            0 :                         res = PXE_PGP_CORRUPT_DATA;
     866            0 :         }
     867              : 
     868            0 :         return res;
     869            0 : }
     870              : 
     871              : static int
     872            0 : process_data_packets(PGP_Context *ctx, MBuf *dst, PullFilter *src,
     873              :                                          int allow_compr, int need_mdc)
     874              : {
     875            0 :         uint8           tag;
     876            0 :         int                     len,
     877              :                                 res;
     878            0 :         int                     got_data = 0;
     879            0 :         int                     got_mdc = 0;
     880            0 :         PullFilter *pkt = NULL;
     881              : 
     882            0 :         while (1)
     883              :         {
     884            0 :                 res = pgp_parse_pkt_hdr(src, &tag, &len, ALLOW_CTX_SIZE);
     885            0 :                 if (res <= 0)
     886            0 :                         break;
     887              : 
     888              : 
     889              :                 /* mdc packet should be last */
     890            0 :                 if (got_mdc)
     891              :                 {
     892            0 :                         px_debug("process_data_packets: data after mdc");
     893            0 :                         res = PXE_PGP_CORRUPT_DATA;
     894            0 :                         break;
     895              :                 }
     896              : 
     897              :                 /*
     898              :                  * Context length inside SYMENCRYPTED_DATA_MDC packet needs special
     899              :                  * handling.
     900              :                  */
     901            0 :                 if (need_mdc && res == PKT_CONTEXT)
     902            0 :                         res = pullf_create(&pkt, &mdcbuf_filter, ctx, src);
     903              :                 else
     904            0 :                         res = pgp_create_pkt_reader(&pkt, src, len, res, ctx);
     905            0 :                 if (res < 0)
     906            0 :                         break;
     907              : 
     908            0 :                 switch (tag)
     909              :                 {
     910              :                         case PGP_PKT_LITERAL_DATA:
     911            0 :                                 got_data = 1;
     912            0 :                                 res = parse_literal_data(ctx, dst, pkt);
     913            0 :                                 break;
     914              :                         case PGP_PKT_COMPRESSED_DATA:
     915            0 :                                 if (allow_compr == 0)
     916              :                                 {
     917            0 :                                         px_debug("process_data_packets: unexpected compression");
     918            0 :                                         res = PXE_PGP_CORRUPT_DATA;
     919            0 :                                 }
     920            0 :                                 else if (got_data)
     921              :                                 {
     922              :                                         /*
     923              :                                          * compr data must be alone
     924              :                                          */
     925            0 :                                         px_debug("process_data_packets: only one cmpr pkt allowed");
     926            0 :                                         res = PXE_PGP_CORRUPT_DATA;
     927            0 :                                 }
     928              :                                 else
     929              :                                 {
     930            0 :                                         got_data = 1;
     931            0 :                                         res = parse_compressed_data(ctx, dst, pkt);
     932              :                                 }
     933            0 :                                 break;
     934              :                         case PGP_PKT_MDC:
     935            0 :                                 if (need_mdc == NO_MDC)
     936              :                                 {
     937            0 :                                         px_debug("process_data_packets: unexpected MDC");
     938            0 :                                         res = PXE_PGP_CORRUPT_DATA;
     939            0 :                                         break;
     940              :                                 }
     941              : 
     942            0 :                                 res = mdc_finish(ctx, pkt, len);
     943            0 :                                 if (res >= 0)
     944            0 :                                         got_mdc = 1;
     945            0 :                                 break;
     946              :                         default:
     947            0 :                                 px_debug("process_data_packets: unexpected pkt tag=%d", tag);
     948            0 :                                 res = PXE_PGP_CORRUPT_DATA;
     949            0 :                 }
     950              : 
     951            0 :                 pullf_free(pkt);
     952            0 :                 pkt = NULL;
     953              : 
     954            0 :                 if (res < 0)
     955            0 :                         break;
     956              :         }
     957              : 
     958            0 :         if (pkt)
     959            0 :                 pullf_free(pkt);
     960              : 
     961            0 :         if (res < 0)
     962            0 :                 return res;
     963              : 
     964            0 :         if (!got_data)
     965              :         {
     966            0 :                 px_debug("process_data_packets: no data");
     967            0 :                 res = PXE_PGP_CORRUPT_DATA;
     968            0 :         }
     969            0 :         if (need_mdc && !got_mdc && !ctx->use_mdcbuf_filter)
     970              :         {
     971            0 :                 px_debug("process_data_packets: got no mdc");
     972            0 :                 res = PXE_PGP_CORRUPT_DATA;
     973            0 :         }
     974            0 :         return res;
     975            0 : }
     976              : 
     977              : static int
     978            0 : parse_symenc_data(PGP_Context *ctx, PullFilter *pkt, MBuf *dst)
     979              : {
     980            0 :         int                     res;
     981            0 :         PGP_CFB    *cfb = NULL;
     982            0 :         PullFilter *pf_decrypt = NULL;
     983            0 :         PullFilter *pf_prefix = NULL;
     984              : 
     985            0 :         res = pgp_cfb_create(&cfb, ctx->cipher_algo,
     986            0 :                                                  ctx->sess_key, ctx->sess_key_len, 1, NULL);
     987            0 :         if (res < 0)
     988            0 :                 goto out;
     989              : 
     990            0 :         res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt);
     991            0 :         if (res < 0)
     992            0 :                 goto out;
     993              : 
     994            0 :         res = pullf_create(&pf_prefix, &prefix_filter, ctx, pf_decrypt);
     995            0 :         if (res < 0)
     996            0 :                 goto out;
     997              : 
     998            0 :         res = process_data_packets(ctx, dst, pf_prefix, ALLOW_COMPR, NO_MDC);
     999              : 
    1000              : out:
    1001            0 :         if (pf_prefix)
    1002            0 :                 pullf_free(pf_prefix);
    1003            0 :         if (pf_decrypt)
    1004            0 :                 pullf_free(pf_decrypt);
    1005            0 :         if (cfb)
    1006            0 :                 pgp_cfb_free(cfb);
    1007              : 
    1008            0 :         return res;
    1009            0 : }
    1010              : 
    1011              : static int
    1012            0 : parse_symenc_mdc_data(PGP_Context *ctx, PullFilter *pkt, MBuf *dst)
    1013              : {
    1014            0 :         int                     res;
    1015            0 :         PGP_CFB    *cfb = NULL;
    1016            0 :         PullFilter *pf_decrypt = NULL;
    1017            0 :         PullFilter *pf_prefix = NULL;
    1018            0 :         PullFilter *pf_mdc = NULL;
    1019            0 :         uint8           ver;
    1020              : 
    1021            0 :         GETBYTE(pkt, ver);
    1022            0 :         if (ver != 1)
    1023              :         {
    1024            0 :                 px_debug("parse_symenc_mdc_data: pkt ver != 1");
    1025            0 :                 return PXE_PGP_CORRUPT_DATA;
    1026              :         }
    1027              : 
    1028            0 :         res = pgp_cfb_create(&cfb, ctx->cipher_algo,
    1029            0 :                                                  ctx->sess_key, ctx->sess_key_len, 0, NULL);
    1030            0 :         if (res < 0)
    1031            0 :                 goto out;
    1032              : 
    1033            0 :         res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt);
    1034            0 :         if (res < 0)
    1035            0 :                 goto out;
    1036              : 
    1037            0 :         res = pullf_create(&pf_mdc, &mdc_filter, ctx, pf_decrypt);
    1038            0 :         if (res < 0)
    1039            0 :                 goto out;
    1040              : 
    1041            0 :         res = pullf_create(&pf_prefix, &prefix_filter, ctx, pf_mdc);
    1042            0 :         if (res < 0)
    1043            0 :                 goto out;
    1044              : 
    1045            0 :         res = process_data_packets(ctx, dst, pf_prefix, ALLOW_COMPR, NEED_MDC);
    1046              : 
    1047              : out:
    1048            0 :         if (pf_prefix)
    1049            0 :                 pullf_free(pf_prefix);
    1050            0 :         if (pf_mdc)
    1051            0 :                 pullf_free(pf_mdc);
    1052            0 :         if (pf_decrypt)
    1053            0 :                 pullf_free(pf_decrypt);
    1054            0 :         if (cfb)
    1055            0 :                 pgp_cfb_free(cfb);
    1056              : 
    1057            0 :         return res;
    1058            0 : }
    1059              : 
    1060              : /*
    1061              :  * skip over packet contents
    1062              :  */
    1063              : int
    1064            0 : pgp_skip_packet(PullFilter *pkt)
    1065              : {
    1066            0 :         int                     res = 1;
    1067            0 :         uint8      *tmp;
    1068              : 
    1069            0 :         while (res > 0)
    1070            0 :                 res = pullf_read(pkt, 32 * 1024, &tmp);
    1071            0 :         return res;
    1072            0 : }
    1073              : 
    1074              : /*
    1075              :  * expect to be at packet end, any data is error
    1076              :  */
    1077              : int
    1078            0 : pgp_expect_packet_end(PullFilter *pkt)
    1079              : {
    1080            0 :         int                     res;
    1081            0 :         uint8      *tmp;
    1082              : 
    1083            0 :         res = pullf_read(pkt, 32 * 1024, &tmp);
    1084            0 :         if (res > 0)
    1085              :         {
    1086            0 :                 px_debug("pgp_expect_packet_end: got data");
    1087            0 :                 return PXE_PGP_CORRUPT_DATA;
    1088              :         }
    1089            0 :         return res;
    1090            0 : }
    1091              : 
    1092              : int
    1093            0 : pgp_decrypt(PGP_Context *ctx, MBuf *msrc, MBuf *mdst)
    1094              : {
    1095            0 :         int                     res;
    1096            0 :         PullFilter *src = NULL;
    1097            0 :         PullFilter *pkt = NULL;
    1098            0 :         uint8           tag;
    1099            0 :         int                     len;
    1100            0 :         int                     got_key = 0;
    1101            0 :         int                     got_data = 0;
    1102              : 
    1103            0 :         res = pullf_create_mbuf_reader(&src, msrc);
    1104              : 
    1105            0 :         while (res >= 0)
    1106              :         {
    1107            0 :                 res = pgp_parse_pkt_hdr(src, &tag, &len, NO_CTX_SIZE);
    1108            0 :                 if (res <= 0)
    1109            0 :                         break;
    1110              : 
    1111            0 :                 res = pgp_create_pkt_reader(&pkt, src, len, res, ctx);
    1112            0 :                 if (res < 0)
    1113            0 :                         break;
    1114              : 
    1115            0 :                 res = PXE_PGP_CORRUPT_DATA;
    1116            0 :                 switch (tag)
    1117              :                 {
    1118              :                         case PGP_PKT_MARKER:
    1119            0 :                                 res = pgp_skip_packet(pkt);
    1120            0 :                                 break;
    1121              :                         case PGP_PKT_PUBENCRYPTED_SESSKEY:
    1122              :                                 /* fixme: skip those */
    1123            0 :                                 res = pgp_parse_pubenc_sesskey(ctx, pkt);
    1124            0 :                                 got_key = 1;
    1125            0 :                                 break;
    1126              :                         case PGP_PKT_SYMENCRYPTED_SESSKEY:
    1127            0 :                                 if (got_key)
    1128              : 
    1129              :                                         /*
    1130              :                                          * Theoretically, there could be several keys, both public
    1131              :                                          * and symmetric, all of which encrypt same session key.
    1132              :                                          * Decrypt should try with each one, before failing.
    1133              :                                          */
    1134            0 :                                         px_debug("pgp_decrypt: using first of several keys");
    1135              :                                 else
    1136              :                                 {
    1137            0 :                                         got_key = 1;
    1138            0 :                                         res = parse_symenc_sesskey(ctx, pkt);
    1139              :                                 }
    1140            0 :                                 break;
    1141              :                         case PGP_PKT_SYMENCRYPTED_DATA:
    1142            0 :                                 if (!got_key)
    1143            0 :                                         px_debug("pgp_decrypt: have data but no key");
    1144            0 :                                 else if (got_data)
    1145            0 :                                         px_debug("pgp_decrypt: got second data packet");
    1146              :                                 else
    1147              :                                 {
    1148            0 :                                         got_data = 1;
    1149            0 :                                         ctx->disable_mdc = 1;
    1150            0 :                                         res = parse_symenc_data(ctx, pkt, mdst);
    1151              :                                 }
    1152            0 :                                 break;
    1153              :                         case PGP_PKT_SYMENCRYPTED_DATA_MDC:
    1154            0 :                                 if (!got_key)
    1155            0 :                                         px_debug("pgp_decrypt: have data but no key");
    1156            0 :                                 else if (got_data)
    1157            0 :                                         px_debug("pgp_decrypt: several data pkts not supported");
    1158              :                                 else
    1159              :                                 {
    1160            0 :                                         got_data = 1;
    1161            0 :                                         ctx->disable_mdc = 0;
    1162            0 :                                         res = parse_symenc_mdc_data(ctx, pkt, mdst);
    1163              :                                 }
    1164            0 :                                 break;
    1165              :                         default:
    1166            0 :                                 px_debug("pgp_decrypt: unknown tag: 0x%02x", tag);
    1167            0 :                 }
    1168            0 :                 pullf_free(pkt);
    1169            0 :                 pkt = NULL;
    1170              :         }
    1171              : 
    1172            0 :         if (pkt)
    1173            0 :                 pullf_free(pkt);
    1174              : 
    1175            0 :         if (src)
    1176            0 :                 pullf_free(src);
    1177              : 
    1178            0 :         if (res < 0)
    1179            0 :                 return res;
    1180              : 
    1181              :         /*
    1182              :          * Report a failure of the prefix_init() "quick check" now, rather than
    1183              :          * upon detection, to hinder timing attacks.  pgcrypto is not generally
    1184              :          * secure against timing attacks, but this helps.
    1185              :          */
    1186            0 :         if (!got_data || ctx->corrupt_prefix)
    1187            0 :                 return PXE_PGP_CORRUPT_DATA;
    1188              : 
    1189              :         /*
    1190              :          * Code interpreting purportedly-decrypted data prior to this stage shall
    1191              :          * report no error other than PXE_PGP_CORRUPT_DATA.  (PXE_BUG is okay so
    1192              :          * long as it remains unreachable.)  This ensures that an attacker able to
    1193              :          * choose a ciphertext and receive a corresponding decryption error
    1194              :          * message cannot use that oracle to gather clues about the decryption
    1195              :          * key.  See "An Attack on CFB Mode Encryption As Used By OpenPGP" by
    1196              :          * Serge Mister and Robert Zuccherato.
    1197              :          *
    1198              :          * A problematic value in the first octet of a Literal Data or Compressed
    1199              :          * Data packet may indicate a simple user error, such as the need to call
    1200              :          * pgp_sym_decrypt_bytea instead of pgp_sym_decrypt.  Occasionally,
    1201              :          * though, it is the first symptom of the encryption key not matching the
    1202              :          * decryption key.  When this was the only problem encountered, report a
    1203              :          * specific error to guide the user; otherwise, we will have reported
    1204              :          * PXE_PGP_CORRUPT_DATA before now.  A key mismatch makes the other errors
    1205              :          * into red herrings, and this avoids leaking clues to attackers.
    1206              :          */
    1207            0 :         if (ctx->unsupported_compr)
    1208            0 :                 return PXE_PGP_UNSUPPORTED_COMPR;
    1209            0 :         if (ctx->unexpected_binary)
    1210            0 :                 return PXE_PGP_NOT_TEXT;
    1211              : 
    1212            0 :         return res;
    1213            0 : }
        

Generated by: LCOV version 2.3.2-1