LCOV - differential code coverage report
Current view: top level - contrib/pgcrypto - pgp-decrypt.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 80.1 % 558 447 111 447
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 31 31 31
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a