Mention battery-backed cache under hardware selection options.
[PostgreSQL.git] / contrib / pgcrypto / pgp-decrypt.c
blobbc414a9518ed84800fb3eb35667af97c32c24340
1 /*
2 * pgp-decrypt.c
3 * OpenPGP decrypt.
5 * Copyright (c) 2005 Marko Kreen
6 * All rights reserved.
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.
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.
29 * $PostgreSQL$
32 #include "postgres.h"
34 #include "px.h"
35 #include "mbuf.h"
36 #include "pgp.h"
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
45 #define PKT_NORMAL 1
46 #define PKT_STREAM 2
47 #define PKT_CONTEXT 3
49 #define MAX_CHUNK (16*1024*1024)
51 static int
52 parse_new_len(PullFilter * src, int *len_p)
54 uint8 b;
55 int len;
56 int pkttype = PKT_NORMAL;
58 GETBYTE(src, b);
59 if (b <= 191)
60 len = b;
61 else if (b >= 192 && b <= 223)
63 len = ((unsigned) (b) - 192) << 8;
64 GETBYTE(src, b);
65 len += 192 + b;
67 else if (b == 255)
69 GETBYTE(src, b);
70 len = b;
71 GETBYTE(src, b);
72 len = (len << 8) | b;
73 GETBYTE(src, b);
74 len = (len << 8) | b;
75 GETBYTE(src, b);
76 len = (len << 8) | b;
78 else
80 len = 1 << (b & 0x1F);
81 pkttype = PKT_STREAM;
84 if (len < 0 || len > MAX_CHUNK)
86 px_debug("parse_new_len: weird length");
87 return PXE_PGP_CORRUPT_DATA;
90 *len_p = len;
91 return pkttype;
94 static int
95 parse_old_len(PullFilter * src, int *len_p, int lentype)
97 uint8 b;
98 int len;
100 GETBYTE(src, b);
101 len = b;
103 if (lentype == 1)
105 GETBYTE(src, b);
106 len = (len << 8) | b;
108 else if (lentype == 2)
110 GETBYTE(src, b);
111 len = (len << 8) | b;
112 GETBYTE(src, b);
113 len = (len << 8) | b;
114 GETBYTE(src, b);
115 len = (len << 8) | b;
118 if (len < 0 || len > MAX_CHUNK)
120 px_debug("parse_old_len: weird length");
121 return PXE_PGP_CORRUPT_DATA;
123 *len_p = len;
124 return PKT_NORMAL;
127 /* returns pkttype or 0 on eof */
129 pgp_parse_pkt_hdr(PullFilter * src, uint8 *tag, int *len_p, int allow_ctx)
131 int lentype;
132 int res;
133 uint8 *p;
135 /* EOF is normal here, thus we dont use GETBYTE */
136 res = pullf_read(src, 1, &p);
137 if (res < 0)
138 return res;
139 if (res == 0)
140 return 0;
142 if ((*p & 0x80) == 0)
144 px_debug("pgp_parse_pkt_hdr: not pkt hdr");
145 return PXE_PGP_CORRUPT_DATA;
148 if (*p & 0x40)
150 *tag = *p & 0x3f;
151 res = parse_new_len(src, len_p);
153 else
155 lentype = *p & 3;
156 *tag = (*p >> 2) & 0x0F;
157 if (lentype == 3)
158 res = allow_ctx ? PKT_CONTEXT : PXE_PGP_CORRUPT_DATA;
159 else
160 res = parse_old_len(src, len_p, lentype);
162 return res;
166 * Packet reader
168 struct PktData
170 int type;
171 int len;
174 static int
175 pktreader_pull(void *priv, PullFilter * src, int len,
176 uint8 **data_p, uint8 *buf, int buflen)
178 int res;
179 struct PktData *pkt = priv;
181 /* PKT_CONTEXT means: whatever there is */
182 if (pkt->type == PKT_CONTEXT)
183 return pullf_read(src, len, data_p);
185 if (pkt->len == 0)
187 /* this was last chunk in stream */
188 if (pkt->type == PKT_NORMAL)
189 return 0;
191 /* next chunk in stream */
192 res = parse_new_len(src, &pkt->len);
193 if (res < 0)
194 return res;
195 pkt->type = res;
198 if (len > pkt->len)
199 len = pkt->len;
201 res = pullf_read(src, len, data_p);
202 if (res > 0)
203 pkt->len -= res;
205 return res;
208 static void
209 pktreader_free(void *priv)
211 struct PktData *pkt = priv;
213 memset(pkt, 0, sizeof(*pkt));
214 px_free(pkt);
217 static struct PullFilterOps pktreader_filter = {
218 NULL, pktreader_pull, pktreader_free
221 /* needs helper function to pass several parameters */
223 pgp_create_pkt_reader(PullFilter ** pf_p, PullFilter * src, int len,
224 int pkttype, PGP_Context * ctx)
226 int res;
227 struct PktData *pkt = px_alloc(sizeof(*pkt));
229 pkt->type = pkttype;
230 pkt->len = len;
231 res = pullf_create(pf_p, &pktreader_filter, pkt, src);
232 if (res < 0)
233 px_free(pkt);
234 return res;
238 * Prefix check filter
241 static int
242 prefix_init(void **priv_p, void *arg, PullFilter * src)
244 PGP_Context *ctx = arg;
245 int len;
246 int res;
247 uint8 *buf;
248 uint8 tmpbuf[PGP_MAX_BLOCK + 2];
250 len = pgp_get_cipher_block_size(ctx->cipher_algo);
251 if (len > sizeof(tmpbuf))
252 return PXE_BUG;
254 res = pullf_read_max(src, len + 2, &buf, tmpbuf);
255 if (res < 0)
256 return res;
257 if (res != len + 2)
259 px_debug("prefix_init: short read");
260 memset(tmpbuf, 0, sizeof(tmpbuf));
261 return PXE_PGP_CORRUPT_DATA;
264 if (buf[len - 2] != buf[len] || buf[len - 1] != buf[len + 1])
266 px_debug("prefix_init: corrupt prefix");
269 * The original purpose of the 2-byte check was to show user a
270 * friendly "wrong key" message. This made following possible:
272 * "An Attack on CFB Mode Encryption As Used By OpenPGP" by Serge
273 * Mister and Robert Zuccherato
275 * To avoid being 'oracle', we delay reporting, which basically means
276 * we prefer to run into corrupt packet header.
278 * We _could_ throw PXE_PGP_CORRUPT_DATA here, but there is
279 * possibility of attack via timing, so we don't.
281 ctx->corrupt_prefix = 1;
283 memset(tmpbuf, 0, sizeof(tmpbuf));
284 return 0;
287 static struct PullFilterOps prefix_filter = {
288 prefix_init, NULL, NULL
293 * Decrypt filter
296 static int
297 decrypt_init(void **priv_p, void *arg, PullFilter * src)
299 PGP_CFB *cfb = arg;
301 *priv_p = cfb;
303 /* we need to write somewhere, so ask for a buffer */
304 return 4096;
307 static int
308 decrypt_read(void *priv, PullFilter * src, int len,
309 uint8 **data_p, uint8 *buf, int buflen)
311 PGP_CFB *cfb = priv;
312 uint8 *tmp;
313 int res;
315 res = pullf_read(src, len, &tmp);
316 if (res > 0)
318 pgp_cfb_decrypt(cfb, tmp, res, buf);
319 *data_p = buf;
321 return res;
324 struct PullFilterOps pgp_decrypt_filter = {
325 decrypt_init, decrypt_read, NULL
330 * MDC hasher filter
333 static int
334 mdc_init(void **priv_p, void *arg, PullFilter * src)
336 PGP_Context *ctx = arg;
338 *priv_p = ctx;
339 return pgp_load_digest(PGP_DIGEST_SHA1, &ctx->mdc_ctx);
342 static void
343 mdc_free(void *priv)
345 PGP_Context *ctx = priv;
347 if (ctx->use_mdcbuf_filter)
348 return;
349 px_md_free(ctx->mdc_ctx);
350 ctx->mdc_ctx = NULL;
353 static int
354 mdc_finish(PGP_Context * ctx, PullFilter * src,
355 int len, uint8 **data_p)
357 int res;
358 uint8 hash[20];
359 uint8 tmpbuf[22];
361 if (len + 1 > sizeof(tmpbuf))
362 return PXE_BUG;
364 /* read data */
365 res = pullf_read_max(src, len + 1, data_p, tmpbuf);
366 if (res < 0)
367 return res;
368 if (res == 0)
370 if (ctx->mdc_checked == 0)
372 px_debug("no mdc");
373 return PXE_PGP_CORRUPT_DATA;
375 return 0;
378 /* safety check */
379 if (ctx->in_mdc_pkt > 1)
381 px_debug("mdc_finish: several times here?");
382 return PXE_PGP_CORRUPT_DATA;
384 ctx->in_mdc_pkt++;
386 /* is the packet sane? */
387 if (res != 20)
389 px_debug("mdc_finish: read failed, res=%d", res);
390 return PXE_PGP_CORRUPT_DATA;
394 * ok, we got the hash, now check
396 px_md_finish(ctx->mdc_ctx, hash);
397 res = memcmp(hash, *data_p, 20);
398 memset(hash, 0, 20);
399 memset(tmpbuf, 0, sizeof(tmpbuf));
400 if (res != 0)
402 px_debug("mdc_finish: mdc failed");
403 return PXE_PGP_CORRUPT_DATA;
405 ctx->mdc_checked = 1;
406 return len;
409 static int
410 mdc_read(void *priv, PullFilter * src, int len,
411 uint8 **data_p, uint8 *buf, int buflen)
413 int res;
414 PGP_Context *ctx = priv;
416 /* skip this filter? */
417 if (ctx->use_mdcbuf_filter)
418 return pullf_read(src, len, data_p);
420 if (ctx->in_mdc_pkt)
421 return mdc_finish(ctx, src, len, data_p);
423 res = pullf_read(src, len, data_p);
424 if (res < 0)
425 return res;
426 if (res == 0)
428 px_debug("mdc_read: unexpected eof");
429 return PXE_PGP_CORRUPT_DATA;
431 px_md_update(ctx->mdc_ctx, *data_p, res);
433 return res;
436 static struct PullFilterOps mdc_filter = {
437 mdc_init, mdc_read, mdc_free
442 * Combined Pkt reader and MDC hasher.
444 * For the case of SYMENCRYPTED_MDC packet, where
445 * the data part has 'context length', which means
446 * that data packet ends 22 bytes before end of parent
447 * packet, which is silly.
449 #define MDCBUF_LEN 8192
450 struct MDCBufData
452 PGP_Context *ctx;
453 int eof;
454 int buflen;
455 int avail;
456 uint8 *pos;
457 int mdc_avail;
458 uint8 mdc_buf[22];
459 uint8 buf[MDCBUF_LEN];
462 static int
463 mdcbuf_init(void **priv_p, void *arg, PullFilter * src)
465 PGP_Context *ctx = arg;
466 struct MDCBufData *st;
468 st = px_alloc(sizeof(*st));
469 memset(st, 0, sizeof(*st));
470 st->buflen = sizeof(st->buf);
471 st->ctx = ctx;
472 *priv_p = st;
474 /* take over the work of mdc_filter */
475 ctx->use_mdcbuf_filter = 1;
477 return 0;
480 static int
481 mdcbuf_finish(struct MDCBufData * st)
483 uint8 hash[20];
484 int res;
486 st->eof = 1;
488 if (st->mdc_buf[0] != 0xD3 || st->mdc_buf[1] != 0x14)
490 px_debug("mdcbuf_finish: bad MDC pkt hdr");
491 return PXE_PGP_CORRUPT_DATA;
493 px_md_update(st->ctx->mdc_ctx, st->mdc_buf, 2);
494 px_md_finish(st->ctx->mdc_ctx, hash);
495 res = memcmp(hash, st->mdc_buf + 2, 20);
496 memset(hash, 0, 20);
497 if (res)
499 px_debug("mdcbuf_finish: MDC does not match");
500 res = PXE_PGP_CORRUPT_DATA;
502 return res;
505 static void
506 mdcbuf_load_data(struct MDCBufData * st, uint8 *src, int len)
508 uint8 *dst = st->pos + st->avail;
510 memcpy(dst, src, len);
511 px_md_update(st->ctx->mdc_ctx, src, len);
512 st->avail += len;
515 static void
516 mdcbuf_load_mdc(struct MDCBufData * st, uint8 *src, int len)
518 memmove(st->mdc_buf + st->mdc_avail, src, len);
519 st->mdc_avail += len;
522 static int
523 mdcbuf_refill(struct MDCBufData * st, PullFilter * src)
525 uint8 *data;
526 int res;
527 int need;
529 /* put avail data in start */
530 if (st->avail > 0 && st->pos != st->buf)
531 memmove(st->buf, st->pos, st->avail);
532 st->pos = st->buf;
534 /* read new data */
535 need = st->buflen + 22 - st->avail - st->mdc_avail;
536 res = pullf_read(src, need, &data);
537 if (res < 0)
538 return res;
539 if (res == 0)
540 return mdcbuf_finish(st);
542 /* add to buffer */
543 if (res >= 22)
545 mdcbuf_load_data(st, st->mdc_buf, st->mdc_avail);
546 st->mdc_avail = 0;
548 mdcbuf_load_data(st, data, res - 22);
549 mdcbuf_load_mdc(st, data + res - 22, 22);
551 else
553 int canmove = st->mdc_avail + res - 22;
555 if (canmove > 0)
557 mdcbuf_load_data(st, st->mdc_buf, canmove);
558 st->mdc_avail -= canmove;
559 memmove(st->mdc_buf, st->mdc_buf + canmove, st->mdc_avail);
561 mdcbuf_load_mdc(st, data, res);
563 return 0;
566 static int
567 mdcbuf_read(void *priv, PullFilter * src, int len,
568 uint8 **data_p, uint8 *buf, int buflen)
570 struct MDCBufData *st = priv;
571 int res;
573 if (!st->eof && len > st->avail)
575 res = mdcbuf_refill(st, src);
576 if (res < 0)
577 return res;
580 if (len > st->avail)
581 len = st->avail;
583 *data_p = st->pos;
584 st->pos += len;
585 st->avail -= len;
586 return len;
589 static void
590 mdcbuf_free(void *priv)
592 struct MDCBufData *st = priv;
594 px_md_free(st->ctx->mdc_ctx);
595 st->ctx->mdc_ctx = NULL;
596 memset(st, 0, sizeof(*st));
597 px_free(st);
600 static struct PullFilterOps mdcbuf_filter = {
601 mdcbuf_init, mdcbuf_read, mdcbuf_free
606 * Decrypt separate session key
608 static int
609 decrypt_key(PGP_Context * ctx, const uint8 *src, int len)
611 int res;
612 uint8 algo;
613 PGP_CFB *cfb;
615 res = pgp_cfb_create(&cfb, ctx->s2k_cipher_algo,
616 ctx->s2k.key, ctx->s2k.key_len, 0, NULL);
617 if (res < 0)
618 return res;
620 pgp_cfb_decrypt(cfb, src, 1, &algo);
621 src++;
622 len--;
624 pgp_cfb_decrypt(cfb, src, len, ctx->sess_key);
625 pgp_cfb_free(cfb);
626 ctx->sess_key_len = len;
627 ctx->cipher_algo = algo;
629 if (pgp_get_cipher_key_size(algo) != len)
631 px_debug("sesskey bad len: algo=%d, expected=%d, got=%d",
632 algo, pgp_get_cipher_key_size(algo), len);
633 return PXE_PGP_CORRUPT_DATA;
635 return 0;
639 * Handle key packet
641 static int
642 parse_symenc_sesskey(PGP_Context * ctx, PullFilter * src)
644 uint8 *p;
645 int res;
646 uint8 tmpbuf[PGP_MAX_KEY + 2];
647 uint8 ver;
649 GETBYTE(src, ver);
650 GETBYTE(src, ctx->s2k_cipher_algo);
651 if (ver != 4)
653 px_debug("bad key pkt ver");
654 return PXE_PGP_CORRUPT_DATA;
658 * read S2K info
660 res = pgp_s2k_read(src, &ctx->s2k);
661 if (res < 0)
662 return res;
663 ctx->s2k_mode = ctx->s2k.mode;
664 ctx->s2k_digest_algo = ctx->s2k.digest_algo;
667 * generate key from password
669 res = pgp_s2k_process(&ctx->s2k, ctx->s2k_cipher_algo,
670 ctx->sym_key, ctx->sym_key_len);
671 if (res < 0)
672 return res;
675 * do we have separate session key?
677 res = pullf_read_max(src, PGP_MAX_KEY + 2, &p, tmpbuf);
678 if (res < 0)
679 return res;
681 if (res == 0)
684 * no, s2k key is session key
686 memcpy(ctx->sess_key, ctx->s2k.key, ctx->s2k.key_len);
687 ctx->sess_key_len = ctx->s2k.key_len;
688 ctx->cipher_algo = ctx->s2k_cipher_algo;
689 res = 0;
690 ctx->use_sess_key = 0;
692 else
695 * yes, decrypt it
697 if (res < 17 || res > PGP_MAX_KEY + 1)
699 px_debug("expect key, but bad data");
700 return PXE_PGP_CORRUPT_DATA;
702 ctx->use_sess_key = 1;
703 res = decrypt_key(ctx, p, res);
706 memset(tmpbuf, 0, sizeof(tmpbuf));
707 return res;
710 static int
711 copy_crlf(MBuf * dst, uint8 *data, int len, int *got_cr)
713 uint8 *data_end = data + len;
714 uint8 tmpbuf[1024];
715 uint8 *tmp_end = tmpbuf + sizeof(tmpbuf);
716 uint8 *p;
717 int res;
719 p = tmpbuf;
720 if (*got_cr)
722 if (*data != '\n')
723 *p++ = '\r';
724 *got_cr = 0;
726 while (data < data_end)
728 if (*data == '\r')
730 if (data + 1 < data_end)
732 if (*(data + 1) == '\n')
733 data++;
735 else
737 *got_cr = 1;
738 break;
741 *p++ = *data++;
742 if (p >= tmp_end)
744 res = mbuf_append(dst, tmpbuf, p - tmpbuf);
745 if (res < 0)
746 return res;
747 p = tmpbuf;
750 if (p - tmpbuf > 0)
752 res = mbuf_append(dst, tmpbuf, p - tmpbuf);
753 if (res < 0)
754 return res;
756 return 0;
759 static int
760 parse_literal_data(PGP_Context * ctx, MBuf * dst, PullFilter * pkt)
762 int type;
763 int name_len;
764 int res;
765 uint8 *buf;
766 uint8 tmpbuf[4];
767 int got_cr = 0;
769 GETBYTE(pkt, type);
770 GETBYTE(pkt, name_len);
772 /* skip name */
773 while (name_len > 0)
775 res = pullf_read(pkt, name_len, &buf);
776 if (res < 0)
777 return res;
778 if (res == 0)
779 break;
780 name_len -= res;
782 if (name_len > 0)
784 px_debug("parse_literal_data: unexpected eof");
785 return PXE_PGP_CORRUPT_DATA;
788 /* skip date */
789 res = pullf_read_max(pkt, 4, &buf, tmpbuf);
790 if (res != 4)
792 px_debug("parse_literal_data: unexpected eof");
793 return PXE_PGP_CORRUPT_DATA;
795 memset(tmpbuf, 0, 4);
797 /* check if text */
798 if (ctx->text_mode)
799 if (type != 't' && type != 'u')
801 px_debug("parse_literal_data: data type=%c", type);
802 return PXE_PGP_NOT_TEXT;
805 ctx->unicode_mode = (type == 'u') ? 1 : 0;
807 /* read data */
808 while (1)
810 res = pullf_read(pkt, 32 * 1024, &buf);
811 if (res <= 0)
812 break;
814 if (ctx->text_mode && ctx->convert_crlf)
815 res = copy_crlf(dst, buf, res, &got_cr);
816 else
817 res = mbuf_append(dst, buf, res);
818 if (res < 0)
819 break;
821 if (res >= 0 && got_cr)
822 res = mbuf_append(dst, (const uint8 *) "\r", 1);
823 return res;
826 /* process_data_packets and parse_compressed_data call each other */
827 static int process_data_packets(PGP_Context * ctx, MBuf * dst,
828 PullFilter * src, int allow_compr, int need_mdc);
830 static int
831 parse_compressed_data(PGP_Context * ctx, MBuf * dst, PullFilter * pkt)
833 int res;
834 uint8 type;
835 PullFilter *pf_decompr;
837 GETBYTE(pkt, type);
839 ctx->compress_algo = type;
840 switch (type)
842 case PGP_COMPR_NONE:
843 res = process_data_packets(ctx, dst, pkt, NO_COMPR, NO_MDC);
844 break;
846 case PGP_COMPR_ZIP:
847 case PGP_COMPR_ZLIB:
848 res = pgp_decompress_filter(&pf_decompr, ctx, pkt);
849 if (res >= 0)
851 res = process_data_packets(ctx, dst, pf_decompr,
852 NO_COMPR, NO_MDC);
853 pullf_free(pf_decompr);
855 break;
857 case PGP_COMPR_BZIP2:
858 px_debug("parse_compressed_data: bzip2 unsupported");
859 res = PXE_PGP_UNSUPPORTED_COMPR;
860 break;
862 default:
863 px_debug("parse_compressed_data: unknown compr type");
864 res = PXE_PGP_CORRUPT_DATA;
867 return res;
870 static int
871 process_data_packets(PGP_Context * ctx, MBuf * dst, PullFilter * src,
872 int allow_compr, int need_mdc)
874 uint8 tag;
875 int len,
876 res;
877 int got_data = 0;
878 int got_mdc = 0;
879 PullFilter *pkt = NULL;
880 uint8 *tmp;
882 while (1)
884 res = pgp_parse_pkt_hdr(src, &tag, &len, ALLOW_CTX_SIZE);
885 if (res <= 0)
886 break;
889 /* mdc packet should be last */
890 if (got_mdc)
892 px_debug("process_data_packets: data after mdc");
893 res = PXE_PGP_CORRUPT_DATA;
894 break;
897 /* context length inside SYMENC_MDC needs special handling */
898 if (need_mdc && res == PKT_CONTEXT)
899 res = pullf_create(&pkt, &mdcbuf_filter, ctx, src);
900 else
901 res = pgp_create_pkt_reader(&pkt, src, len, res, ctx);
902 if (res < 0)
903 break;
905 switch (tag)
907 case PGP_PKT_LITERAL_DATA:
908 got_data = 1;
909 res = parse_literal_data(ctx, dst, pkt);
910 break;
911 case PGP_PKT_COMPRESSED_DATA:
912 if (allow_compr == 0)
914 px_debug("process_data_packets: unexpected compression");
915 res = PXE_PGP_CORRUPT_DATA;
917 else if (got_data)
920 * compr data must be alone
922 px_debug("process_data_packets: only one cmpr pkt allowed");
923 res = PXE_PGP_CORRUPT_DATA;
925 else
927 got_data = 1;
928 res = parse_compressed_data(ctx, dst, pkt);
930 break;
931 case PGP_PKT_MDC:
932 if (need_mdc == NO_MDC)
934 px_debug("process_data_packets: unexpected MDC");
935 res = PXE_PGP_CORRUPT_DATA;
936 break;
939 /* notify mdc_filter */
940 ctx->in_mdc_pkt = 1;
942 res = pullf_read(pkt, 8192, &tmp);
943 if (res > 0)
944 got_mdc = 1;
945 break;
946 default:
947 px_debug("process_data_packets: unexpected pkt tag=%d", tag);
948 res = PXE_PGP_CORRUPT_DATA;
951 pullf_free(pkt);
952 pkt = NULL;
954 if (res < 0)
955 break;
958 if (pkt)
959 pullf_free(pkt);
961 if (res < 0)
962 return res;
964 if (!got_data)
966 px_debug("process_data_packets: no data");
967 res = PXE_PGP_CORRUPT_DATA;
969 if (need_mdc && !got_mdc && !ctx->use_mdcbuf_filter)
971 px_debug("process_data_packets: got no mdc");
972 res = PXE_PGP_CORRUPT_DATA;
974 return res;
977 static int
978 parse_symenc_data(PGP_Context * ctx, PullFilter * pkt, MBuf * dst)
980 int res;
981 PGP_CFB *cfb = NULL;
982 PullFilter *pf_decrypt = NULL;
983 PullFilter *pf_prefix = NULL;
985 res = pgp_cfb_create(&cfb, ctx->cipher_algo,
986 ctx->sess_key, ctx->sess_key_len, 1, NULL);
987 if (res < 0)
988 goto out;
990 res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt);
991 if (res < 0)
992 goto out;
994 res = pullf_create(&pf_prefix, &prefix_filter, ctx, pf_decrypt);
995 if (res < 0)
996 goto out;
998 res = process_data_packets(ctx, dst, pf_prefix, ALLOW_COMPR, NO_MDC);
1000 out:
1001 if (pf_prefix)
1002 pullf_free(pf_prefix);
1003 if (pf_decrypt)
1004 pullf_free(pf_decrypt);
1005 if (cfb)
1006 pgp_cfb_free(cfb);
1008 return res;
1011 static int
1012 parse_symenc_mdc_data(PGP_Context * ctx, PullFilter * pkt, MBuf * dst)
1014 int res;
1015 PGP_CFB *cfb = NULL;
1016 PullFilter *pf_decrypt = NULL;
1017 PullFilter *pf_prefix = NULL;
1018 PullFilter *pf_mdc = NULL;
1019 uint8 ver;
1021 GETBYTE(pkt, ver);
1022 if (ver != 1)
1024 px_debug("parse_symenc_mdc_data: pkt ver != 1");
1025 return PXE_PGP_CORRUPT_DATA;
1028 res = pgp_cfb_create(&cfb, ctx->cipher_algo,
1029 ctx->sess_key, ctx->sess_key_len, 0, NULL);
1030 if (res < 0)
1031 goto out;
1033 res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt);
1034 if (res < 0)
1035 goto out;
1037 res = pullf_create(&pf_mdc, &mdc_filter, ctx, pf_decrypt);
1038 if (res < 0)
1039 goto out;
1041 res = pullf_create(&pf_prefix, &prefix_filter, ctx, pf_mdc);
1042 if (res < 0)
1043 goto out;
1045 res = process_data_packets(ctx, dst, pf_prefix, ALLOW_COMPR, NEED_MDC);
1047 out:
1048 if (pf_prefix)
1049 pullf_free(pf_prefix);
1050 if (pf_mdc)
1051 pullf_free(pf_mdc);
1052 if (pf_decrypt)
1053 pullf_free(pf_decrypt);
1054 if (cfb)
1055 pgp_cfb_free(cfb);
1057 return res;
1061 * skip over packet contents
1064 pgp_skip_packet(PullFilter * pkt)
1066 int res = 1;
1067 uint8 *tmp;
1069 while (res > 0)
1070 res = pullf_read(pkt, 32 * 1024, &tmp);
1071 return res < 0 ? res : 0;
1075 * expect to be at packet end, any data is error
1078 pgp_expect_packet_end(PullFilter * pkt)
1080 int res = 1;
1081 uint8 *tmp;
1083 while (res > 0)
1085 res = pullf_read(pkt, 32 * 1024, &tmp);
1086 if (res > 0)
1088 px_debug("pgp_expect_packet_end: got data");
1089 return PXE_PGP_CORRUPT_DATA;
1092 return res < 0 ? res : 0;
1096 pgp_decrypt(PGP_Context * ctx, MBuf * msrc, MBuf * mdst)
1098 int res;
1099 PullFilter *src = NULL;
1100 PullFilter *pkt = NULL;
1101 uint8 tag;
1102 int len;
1103 int got_key = 0;
1104 int got_data = 0;
1106 res = pullf_create_mbuf_reader(&src, msrc);
1108 while (res >= 0)
1110 res = pgp_parse_pkt_hdr(src, &tag, &len, NO_CTX_SIZE);
1111 if (res <= 0)
1112 break;
1114 res = pgp_create_pkt_reader(&pkt, src, len, res, ctx);
1115 if (res < 0)
1116 break;
1118 res = PXE_PGP_CORRUPT_DATA;
1119 switch (tag)
1121 case PGP_PKT_MARKER:
1122 res = pgp_skip_packet(pkt);
1123 break;
1124 case PGP_PKT_PUBENCRYPTED_SESSKEY:
1125 /* fixme: skip those */
1126 res = pgp_parse_pubenc_sesskey(ctx, pkt);
1127 got_key = 1;
1128 break;
1129 case PGP_PKT_SYMENCRYPTED_SESSKEY:
1130 if (got_key)
1133 * Theoretically, there could be several keys, both public
1134 * and symmetric, all of which encrypt same session key.
1135 * Decrypt should try with each one, before failing.
1137 px_debug("pgp_decrypt: using first of several keys");
1138 else
1140 got_key = 1;
1141 res = parse_symenc_sesskey(ctx, pkt);
1143 break;
1144 case PGP_PKT_SYMENCRYPTED_DATA:
1145 if (!got_key)
1146 px_debug("pgp_decrypt: have data but no key");
1147 else if (got_data)
1148 px_debug("pgp_decrypt: got second data packet");
1149 else
1151 got_data = 1;
1152 ctx->disable_mdc = 1;
1153 res = parse_symenc_data(ctx, pkt, mdst);
1155 break;
1156 case PGP_PKT_SYMENCRYPTED_DATA_MDC:
1157 if (!got_key)
1158 px_debug("pgp_decrypt: have data but no key");
1159 else if (got_data)
1160 px_debug("pgp_decrypt: several data pkts not supported");
1161 else
1163 got_data = 1;
1164 ctx->disable_mdc = 0;
1165 res = parse_symenc_mdc_data(ctx, pkt, mdst);
1167 break;
1168 default:
1169 px_debug("pgp_decrypt: unknown tag: 0x%02x", tag);
1171 pullf_free(pkt);
1172 pkt = NULL;
1175 if (pkt)
1176 pullf_free(pkt);
1178 if (src)
1179 pullf_free(src);
1181 if (res < 0)
1182 return res;
1184 if (!got_data || ctx->corrupt_prefix)
1185 res = PXE_PGP_CORRUPT_DATA;
1187 return res;