00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "postgres.h"
00033
00034 #include "px.h"
00035 #include "mbuf.h"
00036 #include "pgp.h"
00037
00038 #define NO_CTX_SIZE 0
00039 #define ALLOW_CTX_SIZE 1
00040 #define NO_COMPR 0
00041 #define ALLOW_COMPR 1
00042 #define NO_MDC 0
00043 #define NEED_MDC 1
00044
00045 #define PKT_NORMAL 1
00046 #define PKT_STREAM 2
00047 #define PKT_CONTEXT 3
00048
00049 #define MAX_CHUNK (16*1024*1024)
00050
00051 static int
00052 parse_new_len(PullFilter *src, int *len_p)
00053 {
00054 uint8 b;
00055 int len;
00056 int pkttype = PKT_NORMAL;
00057
00058 GETBYTE(src, b);
00059 if (b <= 191)
00060 len = b;
00061 else if (b >= 192 && b <= 223)
00062 {
00063 len = ((unsigned) (b) - 192) << 8;
00064 GETBYTE(src, b);
00065 len += 192 + b;
00066 }
00067 else if (b == 255)
00068 {
00069 GETBYTE(src, b);
00070 len = b;
00071 GETBYTE(src, b);
00072 len = (len << 8) | b;
00073 GETBYTE(src, b);
00074 len = (len << 8) | b;
00075 GETBYTE(src, b);
00076 len = (len << 8) | b;
00077 }
00078 else
00079 {
00080 len = 1 << (b & 0x1F);
00081 pkttype = PKT_STREAM;
00082 }
00083
00084 if (len < 0 || len > MAX_CHUNK)
00085 {
00086 px_debug("parse_new_len: weird length");
00087 return PXE_PGP_CORRUPT_DATA;
00088 }
00089
00090 *len_p = len;
00091 return pkttype;
00092 }
00093
00094 static int
00095 parse_old_len(PullFilter *src, int *len_p, int lentype)
00096 {
00097 uint8 b;
00098 int len;
00099
00100 GETBYTE(src, b);
00101 len = b;
00102
00103 if (lentype == 1)
00104 {
00105 GETBYTE(src, b);
00106 len = (len << 8) | b;
00107 }
00108 else if (lentype == 2)
00109 {
00110 GETBYTE(src, b);
00111 len = (len << 8) | b;
00112 GETBYTE(src, b);
00113 len = (len << 8) | b;
00114 GETBYTE(src, b);
00115 len = (len << 8) | b;
00116 }
00117
00118 if (len < 0 || len > MAX_CHUNK)
00119 {
00120 px_debug("parse_old_len: weird length");
00121 return PXE_PGP_CORRUPT_DATA;
00122 }
00123 *len_p = len;
00124 return PKT_NORMAL;
00125 }
00126
00127
00128 int
00129 pgp_parse_pkt_hdr(PullFilter *src, uint8 *tag, int *len_p, int allow_ctx)
00130 {
00131 int lentype;
00132 int res;
00133 uint8 *p;
00134
00135
00136 res = pullf_read(src, 1, &p);
00137 if (res < 0)
00138 return res;
00139 if (res == 0)
00140 return 0;
00141
00142 if ((*p & 0x80) == 0)
00143 {
00144 px_debug("pgp_parse_pkt_hdr: not pkt hdr");
00145 return PXE_PGP_CORRUPT_DATA;
00146 }
00147
00148 if (*p & 0x40)
00149 {
00150 *tag = *p & 0x3f;
00151 res = parse_new_len(src, len_p);
00152 }
00153 else
00154 {
00155 lentype = *p & 3;
00156 *tag = (*p >> 2) & 0x0F;
00157 if (lentype == 3)
00158 res = allow_ctx ? PKT_CONTEXT : PXE_PGP_CORRUPT_DATA;
00159 else
00160 res = parse_old_len(src, len_p, lentype);
00161 }
00162 return res;
00163 }
00164
00165
00166
00167
00168 struct PktData
00169 {
00170 int type;
00171 int len;
00172 };
00173
00174 static int
00175 pktreader_pull(void *priv, PullFilter *src, int len,
00176 uint8 **data_p, uint8 *buf, int buflen)
00177 {
00178 int res;
00179 struct PktData *pkt = priv;
00180
00181
00182 if (pkt->type == PKT_CONTEXT)
00183 return pullf_read(src, len, data_p);
00184
00185 if (pkt->len == 0)
00186 {
00187
00188 if (pkt->type == PKT_NORMAL)
00189 return 0;
00190
00191
00192 res = parse_new_len(src, &pkt->len);
00193 if (res < 0)
00194 return res;
00195 pkt->type = res;
00196 }
00197
00198 if (len > pkt->len)
00199 len = pkt->len;
00200
00201 res = pullf_read(src, len, data_p);
00202 if (res > 0)
00203 pkt->len -= res;
00204
00205 return res;
00206 }
00207
00208 static void
00209 pktreader_free(void *priv)
00210 {
00211 struct PktData *pkt = priv;
00212
00213 memset(pkt, 0, sizeof(*pkt));
00214 px_free(pkt);
00215 }
00216
00217 static struct PullFilterOps pktreader_filter = {
00218 NULL, pktreader_pull, pktreader_free
00219 };
00220
00221
00222 int
00223 pgp_create_pkt_reader(PullFilter **pf_p, PullFilter *src, int len,
00224 int pkttype, PGP_Context *ctx)
00225 {
00226 int res;
00227 struct PktData *pkt = px_alloc(sizeof(*pkt));
00228
00229 pkt->type = pkttype;
00230 pkt->len = len;
00231 res = pullf_create(pf_p, &pktreader_filter, pkt, src);
00232 if (res < 0)
00233 px_free(pkt);
00234 return res;
00235 }
00236
00237
00238
00239
00240
00241 static int
00242 prefix_init(void **priv_p, void *arg, PullFilter *src)
00243 {
00244 PGP_Context *ctx = arg;
00245 int len;
00246 int res;
00247 uint8 *buf;
00248 uint8 tmpbuf[PGP_MAX_BLOCK + 2];
00249
00250 len = pgp_get_cipher_block_size(ctx->cipher_algo);
00251 if (len > sizeof(tmpbuf))
00252 return PXE_BUG;
00253
00254 res = pullf_read_max(src, len + 2, &buf, tmpbuf);
00255 if (res < 0)
00256 return res;
00257 if (res != len + 2)
00258 {
00259 px_debug("prefix_init: short read");
00260 memset(tmpbuf, 0, sizeof(tmpbuf));
00261 return PXE_PGP_CORRUPT_DATA;
00262 }
00263
00264 if (buf[len - 2] != buf[len] || buf[len - 1] != buf[len + 1])
00265 {
00266 px_debug("prefix_init: corrupt prefix");
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 ctx->corrupt_prefix = 1;
00282 }
00283 memset(tmpbuf, 0, sizeof(tmpbuf));
00284 return 0;
00285 }
00286
00287 static struct PullFilterOps prefix_filter = {
00288 prefix_init, NULL, NULL
00289 };
00290
00291
00292
00293
00294
00295
00296 static int
00297 decrypt_init(void **priv_p, void *arg, PullFilter *src)
00298 {
00299 PGP_CFB *cfb = arg;
00300
00301 *priv_p = cfb;
00302
00303
00304 return 4096;
00305 }
00306
00307 static int
00308 decrypt_read(void *priv, PullFilter *src, int len,
00309 uint8 **data_p, uint8 *buf, int buflen)
00310 {
00311 PGP_CFB *cfb = priv;
00312 uint8 *tmp;
00313 int res;
00314
00315 res = pullf_read(src, len, &tmp);
00316 if (res > 0)
00317 {
00318 pgp_cfb_decrypt(cfb, tmp, res, buf);
00319 *data_p = buf;
00320 }
00321 return res;
00322 }
00323
00324 struct PullFilterOps pgp_decrypt_filter = {
00325 decrypt_init, decrypt_read, NULL
00326 };
00327
00328
00329
00330
00331
00332
00333 static int
00334 mdc_init(void **priv_p, void *arg, PullFilter *src)
00335 {
00336 PGP_Context *ctx = arg;
00337
00338 *priv_p = ctx;
00339 return pgp_load_digest(PGP_DIGEST_SHA1, &ctx->mdc_ctx);
00340 }
00341
00342 static void
00343 mdc_free(void *priv)
00344 {
00345 PGP_Context *ctx = priv;
00346
00347 if (ctx->use_mdcbuf_filter)
00348 return;
00349 px_md_free(ctx->mdc_ctx);
00350 ctx->mdc_ctx = NULL;
00351 }
00352
00353 static int
00354 mdc_finish(PGP_Context *ctx, PullFilter *src,
00355 int len, uint8 **data_p)
00356 {
00357 int res;
00358 uint8 hash[20];
00359 uint8 tmpbuf[22];
00360
00361 if (len + 1 > sizeof(tmpbuf))
00362 return PXE_BUG;
00363
00364
00365 res = pullf_read_max(src, len + 1, data_p, tmpbuf);
00366 if (res < 0)
00367 return res;
00368 if (res == 0)
00369 {
00370 if (ctx->mdc_checked == 0)
00371 {
00372 px_debug("no mdc");
00373 return PXE_PGP_CORRUPT_DATA;
00374 }
00375 return 0;
00376 }
00377
00378
00379 if (ctx->in_mdc_pkt > 1)
00380 {
00381 px_debug("mdc_finish: several times here?");
00382 return PXE_PGP_CORRUPT_DATA;
00383 }
00384 ctx->in_mdc_pkt++;
00385
00386
00387 if (res != 20)
00388 {
00389 px_debug("mdc_finish: read failed, res=%d", res);
00390 return PXE_PGP_CORRUPT_DATA;
00391 }
00392
00393
00394
00395
00396 px_md_finish(ctx->mdc_ctx, hash);
00397 res = memcmp(hash, *data_p, 20);
00398 memset(hash, 0, 20);
00399 memset(tmpbuf, 0, sizeof(tmpbuf));
00400 if (res != 0)
00401 {
00402 px_debug("mdc_finish: mdc failed");
00403 return PXE_PGP_CORRUPT_DATA;
00404 }
00405 ctx->mdc_checked = 1;
00406 return len;
00407 }
00408
00409 static int
00410 mdc_read(void *priv, PullFilter *src, int len,
00411 uint8 **data_p, uint8 *buf, int buflen)
00412 {
00413 int res;
00414 PGP_Context *ctx = priv;
00415
00416
00417 if (ctx->use_mdcbuf_filter)
00418 return pullf_read(src, len, data_p);
00419
00420 if (ctx->in_mdc_pkt)
00421 return mdc_finish(ctx, src, len, data_p);
00422
00423 res = pullf_read(src, len, data_p);
00424 if (res < 0)
00425 return res;
00426 if (res == 0)
00427 {
00428 px_debug("mdc_read: unexpected eof");
00429 return PXE_PGP_CORRUPT_DATA;
00430 }
00431 px_md_update(ctx->mdc_ctx, *data_p, res);
00432
00433 return res;
00434 }
00435
00436 static struct PullFilterOps mdc_filter = {
00437 mdc_init, mdc_read, mdc_free
00438 };
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 #define MDCBUF_LEN 8192
00450 struct MDCBufData
00451 {
00452 PGP_Context *ctx;
00453 int eof;
00454 int buflen;
00455 int avail;
00456 uint8 *pos;
00457 int mdc_avail;
00458 uint8 mdc_buf[22];
00459 uint8 buf[MDCBUF_LEN];
00460 };
00461
00462 static int
00463 mdcbuf_init(void **priv_p, void *arg, PullFilter *src)
00464 {
00465 PGP_Context *ctx = arg;
00466 struct MDCBufData *st;
00467
00468 st = px_alloc(sizeof(*st));
00469 memset(st, 0, sizeof(*st));
00470 st->buflen = sizeof(st->buf);
00471 st->ctx = ctx;
00472 *priv_p = st;
00473
00474
00475 ctx->use_mdcbuf_filter = 1;
00476
00477 return 0;
00478 }
00479
00480 static int
00481 mdcbuf_finish(struct MDCBufData * st)
00482 {
00483 uint8 hash[20];
00484 int res;
00485
00486 st->eof = 1;
00487
00488 if (st->mdc_buf[0] != 0xD3 || st->mdc_buf[1] != 0x14)
00489 {
00490 px_debug("mdcbuf_finish: bad MDC pkt hdr");
00491 return PXE_PGP_CORRUPT_DATA;
00492 }
00493 px_md_update(st->ctx->mdc_ctx, st->mdc_buf, 2);
00494 px_md_finish(st->ctx->mdc_ctx, hash);
00495 res = memcmp(hash, st->mdc_buf + 2, 20);
00496 memset(hash, 0, 20);
00497 if (res)
00498 {
00499 px_debug("mdcbuf_finish: MDC does not match");
00500 res = PXE_PGP_CORRUPT_DATA;
00501 }
00502 return res;
00503 }
00504
00505 static void
00506 mdcbuf_load_data(struct MDCBufData * st, uint8 *src, int len)
00507 {
00508 uint8 *dst = st->pos + st->avail;
00509
00510 memcpy(dst, src, len);
00511 px_md_update(st->ctx->mdc_ctx, src, len);
00512 st->avail += len;
00513 }
00514
00515 static void
00516 mdcbuf_load_mdc(struct MDCBufData * st, uint8 *src, int len)
00517 {
00518 memmove(st->mdc_buf + st->mdc_avail, src, len);
00519 st->mdc_avail += len;
00520 }
00521
00522 static int
00523 mdcbuf_refill(struct MDCBufData * st, PullFilter *src)
00524 {
00525 uint8 *data;
00526 int res;
00527 int need;
00528
00529
00530 if (st->avail > 0 && st->pos != st->buf)
00531 memmove(st->buf, st->pos, st->avail);
00532 st->pos = st->buf;
00533
00534
00535 need = st->buflen + 22 - st->avail - st->mdc_avail;
00536 res = pullf_read(src, need, &data);
00537 if (res < 0)
00538 return res;
00539 if (res == 0)
00540 return mdcbuf_finish(st);
00541
00542
00543 if (res >= 22)
00544 {
00545 mdcbuf_load_data(st, st->mdc_buf, st->mdc_avail);
00546 st->mdc_avail = 0;
00547
00548 mdcbuf_load_data(st, data, res - 22);
00549 mdcbuf_load_mdc(st, data + res - 22, 22);
00550 }
00551 else
00552 {
00553 int canmove = st->mdc_avail + res - 22;
00554
00555 if (canmove > 0)
00556 {
00557 mdcbuf_load_data(st, st->mdc_buf, canmove);
00558 st->mdc_avail -= canmove;
00559 memmove(st->mdc_buf, st->mdc_buf + canmove, st->mdc_avail);
00560 }
00561 mdcbuf_load_mdc(st, data, res);
00562 }
00563 return 0;
00564 }
00565
00566 static int
00567 mdcbuf_read(void *priv, PullFilter *src, int len,
00568 uint8 **data_p, uint8 *buf, int buflen)
00569 {
00570 struct MDCBufData *st = priv;
00571 int res;
00572
00573 if (!st->eof && len > st->avail)
00574 {
00575 res = mdcbuf_refill(st, src);
00576 if (res < 0)
00577 return res;
00578 }
00579
00580 if (len > st->avail)
00581 len = st->avail;
00582
00583 *data_p = st->pos;
00584 st->pos += len;
00585 st->avail -= len;
00586 return len;
00587 }
00588
00589 static void
00590 mdcbuf_free(void *priv)
00591 {
00592 struct MDCBufData *st = priv;
00593
00594 px_md_free(st->ctx->mdc_ctx);
00595 st->ctx->mdc_ctx = NULL;
00596 memset(st, 0, sizeof(*st));
00597 px_free(st);
00598 }
00599
00600 static struct PullFilterOps mdcbuf_filter = {
00601 mdcbuf_init, mdcbuf_read, mdcbuf_free
00602 };
00603
00604
00605
00606
00607
00608 static int
00609 decrypt_key(PGP_Context *ctx, const uint8 *src, int len)
00610 {
00611 int res;
00612 uint8 algo;
00613 PGP_CFB *cfb;
00614
00615 res = pgp_cfb_create(&cfb, ctx->s2k_cipher_algo,
00616 ctx->s2k.key, ctx->s2k.key_len, 0, NULL);
00617 if (res < 0)
00618 return res;
00619
00620 pgp_cfb_decrypt(cfb, src, 1, &algo);
00621 src++;
00622 len--;
00623
00624 pgp_cfb_decrypt(cfb, src, len, ctx->sess_key);
00625 pgp_cfb_free(cfb);
00626 ctx->sess_key_len = len;
00627 ctx->cipher_algo = algo;
00628
00629 if (pgp_get_cipher_key_size(algo) != len)
00630 {
00631 px_debug("sesskey bad len: algo=%d, expected=%d, got=%d",
00632 algo, pgp_get_cipher_key_size(algo), len);
00633 return PXE_PGP_CORRUPT_DATA;
00634 }
00635 return 0;
00636 }
00637
00638
00639
00640
00641 static int
00642 parse_symenc_sesskey(PGP_Context *ctx, PullFilter *src)
00643 {
00644 uint8 *p;
00645 int res;
00646 uint8 tmpbuf[PGP_MAX_KEY + 2];
00647 uint8 ver;
00648
00649 GETBYTE(src, ver);
00650 GETBYTE(src, ctx->s2k_cipher_algo);
00651 if (ver != 4)
00652 {
00653 px_debug("bad key pkt ver");
00654 return PXE_PGP_CORRUPT_DATA;
00655 }
00656
00657
00658
00659
00660 res = pgp_s2k_read(src, &ctx->s2k);
00661 if (res < 0)
00662 return res;
00663 ctx->s2k_mode = ctx->s2k.mode;
00664 ctx->s2k_digest_algo = ctx->s2k.digest_algo;
00665
00666
00667
00668
00669 res = pgp_s2k_process(&ctx->s2k, ctx->s2k_cipher_algo,
00670 ctx->sym_key, ctx->sym_key_len);
00671 if (res < 0)
00672 return res;
00673
00674
00675
00676
00677 res = pullf_read_max(src, PGP_MAX_KEY + 2, &p, tmpbuf);
00678 if (res < 0)
00679 return res;
00680
00681 if (res == 0)
00682 {
00683
00684
00685
00686 memcpy(ctx->sess_key, ctx->s2k.key, ctx->s2k.key_len);
00687 ctx->sess_key_len = ctx->s2k.key_len;
00688 ctx->cipher_algo = ctx->s2k_cipher_algo;
00689 res = 0;
00690 ctx->use_sess_key = 0;
00691 }
00692 else
00693 {
00694
00695
00696
00697 if (res < 17 || res > PGP_MAX_KEY + 1)
00698 {
00699 px_debug("expect key, but bad data");
00700 return PXE_PGP_CORRUPT_DATA;
00701 }
00702 ctx->use_sess_key = 1;
00703 res = decrypt_key(ctx, p, res);
00704 }
00705
00706 memset(tmpbuf, 0, sizeof(tmpbuf));
00707 return res;
00708 }
00709
00710 static int
00711 copy_crlf(MBuf *dst, uint8 *data, int len, int *got_cr)
00712 {
00713 uint8 *data_end = data + len;
00714 uint8 tmpbuf[1024];
00715 uint8 *tmp_end = tmpbuf + sizeof(tmpbuf);
00716 uint8 *p;
00717 int res;
00718
00719 p = tmpbuf;
00720 if (*got_cr)
00721 {
00722 if (*data != '\n')
00723 *p++ = '\r';
00724 *got_cr = 0;
00725 }
00726 while (data < data_end)
00727 {
00728 if (*data == '\r')
00729 {
00730 if (data + 1 < data_end)
00731 {
00732 if (*(data + 1) == '\n')
00733 data++;
00734 }
00735 else
00736 {
00737 *got_cr = 1;
00738 break;
00739 }
00740 }
00741 *p++ = *data++;
00742 if (p >= tmp_end)
00743 {
00744 res = mbuf_append(dst, tmpbuf, p - tmpbuf);
00745 if (res < 0)
00746 return res;
00747 p = tmpbuf;
00748 }
00749 }
00750 if (p - tmpbuf > 0)
00751 {
00752 res = mbuf_append(dst, tmpbuf, p - tmpbuf);
00753 if (res < 0)
00754 return res;
00755 }
00756 return 0;
00757 }
00758
00759 static int
00760 parse_literal_data(PGP_Context *ctx, MBuf *dst, PullFilter *pkt)
00761 {
00762 int type;
00763 int name_len;
00764 int res;
00765 uint8 *buf;
00766 uint8 tmpbuf[4];
00767 int got_cr = 0;
00768
00769 GETBYTE(pkt, type);
00770 GETBYTE(pkt, name_len);
00771
00772
00773 while (name_len > 0)
00774 {
00775 res = pullf_read(pkt, name_len, &buf);
00776 if (res < 0)
00777 return res;
00778 if (res == 0)
00779 break;
00780 name_len -= res;
00781 }
00782 if (name_len > 0)
00783 {
00784 px_debug("parse_literal_data: unexpected eof");
00785 return PXE_PGP_CORRUPT_DATA;
00786 }
00787
00788
00789 res = pullf_read_max(pkt, 4, &buf, tmpbuf);
00790 if (res != 4)
00791 {
00792 px_debug("parse_literal_data: unexpected eof");
00793 return PXE_PGP_CORRUPT_DATA;
00794 }
00795 memset(tmpbuf, 0, 4);
00796
00797
00798 if (ctx->text_mode)
00799 if (type != 't' && type != 'u')
00800 {
00801 px_debug("parse_literal_data: data type=%c", type);
00802 return PXE_PGP_NOT_TEXT;
00803 }
00804
00805 ctx->unicode_mode = (type == 'u') ? 1 : 0;
00806
00807
00808 while (1)
00809 {
00810 res = pullf_read(pkt, 32 * 1024, &buf);
00811 if (res <= 0)
00812 break;
00813
00814 if (ctx->text_mode && ctx->convert_crlf)
00815 res = copy_crlf(dst, buf, res, &got_cr);
00816 else
00817 res = mbuf_append(dst, buf, res);
00818 if (res < 0)
00819 break;
00820 }
00821 if (res >= 0 && got_cr)
00822 res = mbuf_append(dst, (const uint8 *) "\r", 1);
00823 return res;
00824 }
00825
00826
00827 static int process_data_packets(PGP_Context *ctx, MBuf *dst,
00828 PullFilter *src, int allow_compr, int need_mdc);
00829
00830 static int
00831 parse_compressed_data(PGP_Context *ctx, MBuf *dst, PullFilter *pkt)
00832 {
00833 int res;
00834 uint8 type;
00835 PullFilter *pf_decompr;
00836
00837 GETBYTE(pkt, type);
00838
00839 ctx->compress_algo = type;
00840 switch (type)
00841 {
00842 case PGP_COMPR_NONE:
00843 res = process_data_packets(ctx, dst, pkt, NO_COMPR, NO_MDC);
00844 break;
00845
00846 case PGP_COMPR_ZIP:
00847 case PGP_COMPR_ZLIB:
00848 res = pgp_decompress_filter(&pf_decompr, ctx, pkt);
00849 if (res >= 0)
00850 {
00851 res = process_data_packets(ctx, dst, pf_decompr,
00852 NO_COMPR, NO_MDC);
00853 pullf_free(pf_decompr);
00854 }
00855 break;
00856
00857 case PGP_COMPR_BZIP2:
00858 px_debug("parse_compressed_data: bzip2 unsupported");
00859 res = PXE_PGP_UNSUPPORTED_COMPR;
00860 break;
00861
00862 default:
00863 px_debug("parse_compressed_data: unknown compr type");
00864 res = PXE_PGP_CORRUPT_DATA;
00865 }
00866
00867 return res;
00868 }
00869
00870 static int
00871 process_data_packets(PGP_Context *ctx, MBuf *dst, PullFilter *src,
00872 int allow_compr, int need_mdc)
00873 {
00874 uint8 tag;
00875 int len,
00876 res;
00877 int got_data = 0;
00878 int got_mdc = 0;
00879 PullFilter *pkt = NULL;
00880 uint8 *tmp;
00881
00882 while (1)
00883 {
00884 res = pgp_parse_pkt_hdr(src, &tag, &len, ALLOW_CTX_SIZE);
00885 if (res <= 0)
00886 break;
00887
00888
00889
00890 if (got_mdc)
00891 {
00892 px_debug("process_data_packets: data after mdc");
00893 res = PXE_PGP_CORRUPT_DATA;
00894 break;
00895 }
00896
00897
00898 if (need_mdc && res == PKT_CONTEXT)
00899 res = pullf_create(&pkt, &mdcbuf_filter, ctx, src);
00900 else
00901 res = pgp_create_pkt_reader(&pkt, src, len, res, ctx);
00902 if (res < 0)
00903 break;
00904
00905 switch (tag)
00906 {
00907 case PGP_PKT_LITERAL_DATA:
00908 got_data = 1;
00909 res = parse_literal_data(ctx, dst, pkt);
00910 break;
00911 case PGP_PKT_COMPRESSED_DATA:
00912 if (allow_compr == 0)
00913 {
00914 px_debug("process_data_packets: unexpected compression");
00915 res = PXE_PGP_CORRUPT_DATA;
00916 }
00917 else if (got_data)
00918 {
00919
00920
00921
00922 px_debug("process_data_packets: only one cmpr pkt allowed");
00923 res = PXE_PGP_CORRUPT_DATA;
00924 }
00925 else
00926 {
00927 got_data = 1;
00928 res = parse_compressed_data(ctx, dst, pkt);
00929 }
00930 break;
00931 case PGP_PKT_MDC:
00932 if (need_mdc == NO_MDC)
00933 {
00934 px_debug("process_data_packets: unexpected MDC");
00935 res = PXE_PGP_CORRUPT_DATA;
00936 break;
00937 }
00938
00939
00940 ctx->in_mdc_pkt = 1;
00941
00942 res = pullf_read(pkt, 8192, &tmp);
00943 if (res > 0)
00944 got_mdc = 1;
00945 break;
00946 default:
00947 px_debug("process_data_packets: unexpected pkt tag=%d", tag);
00948 res = PXE_PGP_CORRUPT_DATA;
00949 }
00950
00951 pullf_free(pkt);
00952 pkt = NULL;
00953
00954 if (res < 0)
00955 break;
00956 }
00957
00958 if (pkt)
00959 pullf_free(pkt);
00960
00961 if (res < 0)
00962 return res;
00963
00964 if (!got_data)
00965 {
00966 px_debug("process_data_packets: no data");
00967 res = PXE_PGP_CORRUPT_DATA;
00968 }
00969 if (need_mdc && !got_mdc && !ctx->use_mdcbuf_filter)
00970 {
00971 px_debug("process_data_packets: got no mdc");
00972 res = PXE_PGP_CORRUPT_DATA;
00973 }
00974 return res;
00975 }
00976
00977 static int
00978 parse_symenc_data(PGP_Context *ctx, PullFilter *pkt, MBuf *dst)
00979 {
00980 int res;
00981 PGP_CFB *cfb = NULL;
00982 PullFilter *pf_decrypt = NULL;
00983 PullFilter *pf_prefix = NULL;
00984
00985 res = pgp_cfb_create(&cfb, ctx->cipher_algo,
00986 ctx->sess_key, ctx->sess_key_len, 1, NULL);
00987 if (res < 0)
00988 goto out;
00989
00990 res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt);
00991 if (res < 0)
00992 goto out;
00993
00994 res = pullf_create(&pf_prefix, &prefix_filter, ctx, pf_decrypt);
00995 if (res < 0)
00996 goto out;
00997
00998 res = process_data_packets(ctx, dst, pf_prefix, ALLOW_COMPR, NO_MDC);
00999
01000 out:
01001 if (pf_prefix)
01002 pullf_free(pf_prefix);
01003 if (pf_decrypt)
01004 pullf_free(pf_decrypt);
01005 if (cfb)
01006 pgp_cfb_free(cfb);
01007
01008 return res;
01009 }
01010
01011 static int
01012 parse_symenc_mdc_data(PGP_Context *ctx, PullFilter *pkt, MBuf *dst)
01013 {
01014 int res;
01015 PGP_CFB *cfb = NULL;
01016 PullFilter *pf_decrypt = NULL;
01017 PullFilter *pf_prefix = NULL;
01018 PullFilter *pf_mdc = NULL;
01019 uint8 ver;
01020
01021 GETBYTE(pkt, ver);
01022 if (ver != 1)
01023 {
01024 px_debug("parse_symenc_mdc_data: pkt ver != 1");
01025 return PXE_PGP_CORRUPT_DATA;
01026 }
01027
01028 res = pgp_cfb_create(&cfb, ctx->cipher_algo,
01029 ctx->sess_key, ctx->sess_key_len, 0, NULL);
01030 if (res < 0)
01031 goto out;
01032
01033 res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt);
01034 if (res < 0)
01035 goto out;
01036
01037 res = pullf_create(&pf_mdc, &mdc_filter, ctx, pf_decrypt);
01038 if (res < 0)
01039 goto out;
01040
01041 res = pullf_create(&pf_prefix, &prefix_filter, ctx, pf_mdc);
01042 if (res < 0)
01043 goto out;
01044
01045 res = process_data_packets(ctx, dst, pf_prefix, ALLOW_COMPR, NEED_MDC);
01046
01047 out:
01048 if (pf_prefix)
01049 pullf_free(pf_prefix);
01050 if (pf_mdc)
01051 pullf_free(pf_mdc);
01052 if (pf_decrypt)
01053 pullf_free(pf_decrypt);
01054 if (cfb)
01055 pgp_cfb_free(cfb);
01056
01057 return res;
01058 }
01059
01060
01061
01062
01063 int
01064 pgp_skip_packet(PullFilter *pkt)
01065 {
01066 int res = 1;
01067 uint8 *tmp;
01068
01069 while (res > 0)
01070 res = pullf_read(pkt, 32 * 1024, &tmp);
01071 return res < 0 ? res : 0;
01072 }
01073
01074
01075
01076
01077 int
01078 pgp_expect_packet_end(PullFilter *pkt)
01079 {
01080 int res = 1;
01081 uint8 *tmp;
01082
01083 while (res > 0)
01084 {
01085 res = pullf_read(pkt, 32 * 1024, &tmp);
01086 if (res > 0)
01087 {
01088 px_debug("pgp_expect_packet_end: got data");
01089 return PXE_PGP_CORRUPT_DATA;
01090 }
01091 }
01092 return res < 0 ? res : 0;
01093 }
01094
01095 int
01096 pgp_decrypt(PGP_Context *ctx, MBuf *msrc, MBuf *mdst)
01097 {
01098 int res;
01099 PullFilter *src = NULL;
01100 PullFilter *pkt = NULL;
01101 uint8 tag;
01102 int len;
01103 int got_key = 0;
01104 int got_data = 0;
01105
01106 res = pullf_create_mbuf_reader(&src, msrc);
01107
01108 while (res >= 0)
01109 {
01110 res = pgp_parse_pkt_hdr(src, &tag, &len, NO_CTX_SIZE);
01111 if (res <= 0)
01112 break;
01113
01114 res = pgp_create_pkt_reader(&pkt, src, len, res, ctx);
01115 if (res < 0)
01116 break;
01117
01118 res = PXE_PGP_CORRUPT_DATA;
01119 switch (tag)
01120 {
01121 case PGP_PKT_MARKER:
01122 res = pgp_skip_packet(pkt);
01123 break;
01124 case PGP_PKT_PUBENCRYPTED_SESSKEY:
01125
01126 res = pgp_parse_pubenc_sesskey(ctx, pkt);
01127 got_key = 1;
01128 break;
01129 case PGP_PKT_SYMENCRYPTED_SESSKEY:
01130 if (got_key)
01131
01132
01133
01134
01135
01136
01137 px_debug("pgp_decrypt: using first of several keys");
01138 else
01139 {
01140 got_key = 1;
01141 res = parse_symenc_sesskey(ctx, pkt);
01142 }
01143 break;
01144 case PGP_PKT_SYMENCRYPTED_DATA:
01145 if (!got_key)
01146 px_debug("pgp_decrypt: have data but no key");
01147 else if (got_data)
01148 px_debug("pgp_decrypt: got second data packet");
01149 else
01150 {
01151 got_data = 1;
01152 ctx->disable_mdc = 1;
01153 res = parse_symenc_data(ctx, pkt, mdst);
01154 }
01155 break;
01156 case PGP_PKT_SYMENCRYPTED_DATA_MDC:
01157 if (!got_key)
01158 px_debug("pgp_decrypt: have data but no key");
01159 else if (got_data)
01160 px_debug("pgp_decrypt: several data pkts not supported");
01161 else
01162 {
01163 got_data = 1;
01164 ctx->disable_mdc = 0;
01165 res = parse_symenc_mdc_data(ctx, pkt, mdst);
01166 }
01167 break;
01168 default:
01169 px_debug("pgp_decrypt: unknown tag: 0x%02x", tag);
01170 }
01171 pullf_free(pkt);
01172 pkt = NULL;
01173 }
01174
01175 if (pkt)
01176 pullf_free(pkt);
01177
01178 if (src)
01179 pullf_free(src);
01180
01181 if (res < 0)
01182 return res;
01183
01184 if (!got_data || ctx->corrupt_prefix)
01185 res = PXE_PGP_CORRUPT_DATA;
01186
01187 return res;
01188 }