#include "postgres.h"
#include "px.h"
#include "mbuf.h"
#include "pgp.h"
Go to the source code of this file.
Data Structures | |
struct | PktData |
struct | MDCBufData |
Defines | |
#define | NO_CTX_SIZE 0 |
#define | ALLOW_CTX_SIZE 1 |
#define | NO_COMPR 0 |
#define | ALLOW_COMPR 1 |
#define | NO_MDC 0 |
#define | NEED_MDC 1 |
#define | PKT_NORMAL 1 |
#define | PKT_STREAM 2 |
#define | PKT_CONTEXT 3 |
#define | MAX_CHUNK (16*1024*1024) |
#define | MDCBUF_LEN 8192 |
Functions | |
static int | parse_new_len (PullFilter *src, int *len_p) |
static int | parse_old_len (PullFilter *src, int *len_p, int lentype) |
int | pgp_parse_pkt_hdr (PullFilter *src, uint8 *tag, int *len_p, int allow_ctx) |
static int | pktreader_pull (void *priv, PullFilter *src, int len, uint8 **data_p, uint8 *buf, int buflen) |
static void | pktreader_free (void *priv) |
int | pgp_create_pkt_reader (PullFilter **pf_p, PullFilter *src, int len, int pkttype, PGP_Context *ctx) |
static int | prefix_init (void **priv_p, void *arg, PullFilter *src) |
static int | decrypt_init (void **priv_p, void *arg, PullFilter *src) |
static int | decrypt_read (void *priv, PullFilter *src, int len, uint8 **data_p, uint8 *buf, int buflen) |
static int | mdc_init (void **priv_p, void *arg, PullFilter *src) |
static void | mdc_free (void *priv) |
static int | mdc_finish (PGP_Context *ctx, PullFilter *src, int len, uint8 **data_p) |
static int | mdc_read (void *priv, PullFilter *src, int len, uint8 **data_p, uint8 *buf, int buflen) |
static int | mdcbuf_init (void **priv_p, void *arg, PullFilter *src) |
static int | mdcbuf_finish (struct MDCBufData *st) |
static void | mdcbuf_load_data (struct MDCBufData *st, uint8 *src, int len) |
static void | mdcbuf_load_mdc (struct MDCBufData *st, uint8 *src, int len) |
static int | mdcbuf_refill (struct MDCBufData *st, PullFilter *src) |
static int | mdcbuf_read (void *priv, PullFilter *src, int len, uint8 **data_p, uint8 *buf, int buflen) |
static void | mdcbuf_free (void *priv) |
static int | decrypt_key (PGP_Context *ctx, const uint8 *src, int len) |
static int | parse_symenc_sesskey (PGP_Context *ctx, PullFilter *src) |
static int | copy_crlf (MBuf *dst, uint8 *data, int len, int *got_cr) |
static int | parse_literal_data (PGP_Context *ctx, MBuf *dst, PullFilter *pkt) |
static int | process_data_packets (PGP_Context *ctx, MBuf *dst, PullFilter *src, int allow_compr, int need_mdc) |
static int | parse_compressed_data (PGP_Context *ctx, MBuf *dst, PullFilter *pkt) |
static int | parse_symenc_data (PGP_Context *ctx, PullFilter *pkt, MBuf *dst) |
static int | parse_symenc_mdc_data (PGP_Context *ctx, PullFilter *pkt, MBuf *dst) |
int | pgp_skip_packet (PullFilter *pkt) |
int | pgp_expect_packet_end (PullFilter *pkt) |
int | pgp_decrypt (PGP_Context *ctx, MBuf *msrc, MBuf *mdst) |
Variables | |
static struct PullFilterOps | pktreader_filter |
static struct PullFilterOps | prefix_filter |
struct PullFilterOps | pgp_decrypt_filter |
static struct PullFilterOps | mdc_filter |
static struct PullFilterOps | mdcbuf_filter |
#define ALLOW_COMPR 1 |
Definition at line 41 of file pgp-decrypt.c.
Referenced by parse_symenc_data(), and parse_symenc_mdc_data().
#define ALLOW_CTX_SIZE 1 |
Definition at line 39 of file pgp-decrypt.c.
Referenced by process_data_packets().
#define MAX_CHUNK (16*1024*1024) |
Definition at line 49 of file pgp-decrypt.c.
Referenced by parse_new_len(), and parse_old_len().
#define MDCBUF_LEN 8192 |
Definition at line 449 of file pgp-decrypt.c.
#define NEED_MDC 1 |
Definition at line 43 of file pgp-decrypt.c.
Referenced by parse_symenc_mdc_data().
#define NO_COMPR 0 |
Definition at line 40 of file pgp-decrypt.c.
Referenced by parse_compressed_data().
#define NO_CTX_SIZE 0 |
Definition at line 38 of file pgp-decrypt.c.
Referenced by pgp_decrypt().
#define NO_MDC 0 |
Definition at line 42 of file pgp-decrypt.c.
Referenced by parse_compressed_data(), parse_symenc_data(), and process_data_packets().
#define PKT_CONTEXT 3 |
Definition at line 47 of file pgp-decrypt.c.
Referenced by pgp_parse_pkt_hdr(), pktreader_pull(), and process_data_packets().
#define PKT_NORMAL 1 |
Definition at line 45 of file pgp-decrypt.c.
Referenced by pktreader_pull().
#define PKT_STREAM 2 |
Definition at line 46 of file pgp-decrypt.c.
Definition at line 711 of file pgp-decrypt.c.
References mbuf_append(), and tmpbuf.
Referenced by parse_literal_data().
{ uint8 *data_end = data + len; uint8 tmpbuf[1024]; uint8 *tmp_end = tmpbuf + sizeof(tmpbuf); uint8 *p; int res; p = tmpbuf; if (*got_cr) { if (*data != '\n') *p++ = '\r'; *got_cr = 0; } while (data < data_end) { if (*data == '\r') { if (data + 1 < data_end) { if (*(data + 1) == '\n') data++; } else { *got_cr = 1; break; } } *p++ = *data++; if (p >= tmp_end) { res = mbuf_append(dst, tmpbuf, p - tmpbuf); if (res < 0) return res; p = tmpbuf; } } if (p - tmpbuf > 0) { res = mbuf_append(dst, tmpbuf, p - tmpbuf); if (res < 0) return res; } return 0; }
static int decrypt_init | ( | void ** | priv_p, | |
void * | arg, | |||
PullFilter * | src | |||
) | [static] |
Definition at line 297 of file pgp-decrypt.c.
static int decrypt_key | ( | PGP_Context * | ctx, | |
const uint8 * | src, | |||
int | len | |||
) | [static] |
Definition at line 609 of file pgp-decrypt.c.
References PGP_Context::cipher_algo, PGP_S2K::key, PGP_S2K::key_len, NULL, pgp_cfb_create(), pgp_cfb_decrypt(), pgp_cfb_free(), pgp_get_cipher_key_size(), px_debug(), PGP_Context::s2k, PGP_Context::s2k_cipher_algo, PGP_Context::sess_key, and PGP_Context::sess_key_len.
Referenced by parse_symenc_sesskey().
{ int res; uint8 algo; PGP_CFB *cfb; res = pgp_cfb_create(&cfb, ctx->s2k_cipher_algo, ctx->s2k.key, ctx->s2k.key_len, 0, NULL); if (res < 0) return res; pgp_cfb_decrypt(cfb, src, 1, &algo); src++; len--; pgp_cfb_decrypt(cfb, src, len, ctx->sess_key); pgp_cfb_free(cfb); ctx->sess_key_len = len; ctx->cipher_algo = algo; if (pgp_get_cipher_key_size(algo) != len) { px_debug("sesskey bad len: algo=%d, expected=%d, got=%d", algo, pgp_get_cipher_key_size(algo), len); return PXE_PGP_CORRUPT_DATA; } return 0; }
static int decrypt_read | ( | void * | priv, | |
PullFilter * | src, | |||
int | len, | |||
uint8 ** | data_p, | |||
uint8 * | buf, | |||
int | buflen | |||
) | [static] |
Definition at line 308 of file pgp-decrypt.c.
References pgp_cfb_decrypt(), and pullf_read().
{ PGP_CFB *cfb = priv; uint8 *tmp; int res; res = pullf_read(src, len, &tmp); if (res > 0) { pgp_cfb_decrypt(cfb, tmp, res, buf); *data_p = buf; } return res; }
static int mdc_finish | ( | PGP_Context * | ctx, | |
PullFilter * | src, | |||
int | len, | |||
uint8 ** | data_p | |||
) | [static] |
Definition at line 354 of file pgp-decrypt.c.
References hash(), PGP_Context::in_mdc_pkt, PGP_Context::mdc_checked, PGP_Context::mdc_ctx, memcmp(), pullf_read_max(), px_debug(), px_md_finish, and tmpbuf.
Referenced by mdc_read().
{ int res; uint8 hash[20]; uint8 tmpbuf[22]; if (len + 1 > sizeof(tmpbuf)) return PXE_BUG; /* read data */ res = pullf_read_max(src, len + 1, data_p, tmpbuf); if (res < 0) return res; if (res == 0) { if (ctx->mdc_checked == 0) { px_debug("no mdc"); return PXE_PGP_CORRUPT_DATA; } return 0; } /* safety check */ if (ctx->in_mdc_pkt > 1) { px_debug("mdc_finish: several times here?"); return PXE_PGP_CORRUPT_DATA; } ctx->in_mdc_pkt++; /* is the packet sane? */ if (res != 20) { px_debug("mdc_finish: read failed, res=%d", res); return PXE_PGP_CORRUPT_DATA; } /* * ok, we got the hash, now check */ px_md_finish(ctx->mdc_ctx, hash); res = memcmp(hash, *data_p, 20); memset(hash, 0, 20); memset(tmpbuf, 0, sizeof(tmpbuf)); if (res != 0) { px_debug("mdc_finish: mdc failed"); return PXE_PGP_CORRUPT_DATA; } ctx->mdc_checked = 1; return len; }
static void mdc_free | ( | void * | priv | ) | [static] |
Definition at line 343 of file pgp-decrypt.c.
References PGP_Context::mdc_ctx, px_md_free, and PGP_Context::use_mdcbuf_filter.
{ PGP_Context *ctx = priv; if (ctx->use_mdcbuf_filter) return; px_md_free(ctx->mdc_ctx); ctx->mdc_ctx = NULL; }
static int mdc_init | ( | void ** | priv_p, | |
void * | arg, | |||
PullFilter * | src | |||
) | [static] |
Definition at line 334 of file pgp-decrypt.c.
References PGP_Context::mdc_ctx, PGP_DIGEST_SHA1, and pgp_load_digest().
{ PGP_Context *ctx = arg; *priv_p = ctx; return pgp_load_digest(PGP_DIGEST_SHA1, &ctx->mdc_ctx); }
static int mdc_read | ( | void * | priv, | |
PullFilter * | src, | |||
int | len, | |||
uint8 ** | data_p, | |||
uint8 * | buf, | |||
int | buflen | |||
) | [static] |
Definition at line 410 of file pgp-decrypt.c.
References PGP_Context::in_mdc_pkt, PGP_Context::mdc_ctx, mdc_finish(), pullf_read(), px_debug(), px_md_update, and PGP_Context::use_mdcbuf_filter.
{ int res; PGP_Context *ctx = priv; /* skip this filter? */ if (ctx->use_mdcbuf_filter) return pullf_read(src, len, data_p); if (ctx->in_mdc_pkt) return mdc_finish(ctx, src, len, data_p); res = pullf_read(src, len, data_p); if (res < 0) return res; if (res == 0) { px_debug("mdc_read: unexpected eof"); return PXE_PGP_CORRUPT_DATA; } px_md_update(ctx->mdc_ctx, *data_p, res); return res; }
static int mdcbuf_finish | ( | struct MDCBufData * | st | ) | [static] |
Definition at line 481 of file pgp-decrypt.c.
References MDCBufData::ctx, MDCBufData::eof, hash(), MDCBufData::mdc_buf, PGP_Context::mdc_ctx, memcmp(), px_debug(), px_md_finish, and px_md_update.
Referenced by mdcbuf_refill().
{ uint8 hash[20]; int res; st->eof = 1; if (st->mdc_buf[0] != 0xD3 || st->mdc_buf[1] != 0x14) { px_debug("mdcbuf_finish: bad MDC pkt hdr"); return PXE_PGP_CORRUPT_DATA; } px_md_update(st->ctx->mdc_ctx, st->mdc_buf, 2); px_md_finish(st->ctx->mdc_ctx, hash); res = memcmp(hash, st->mdc_buf + 2, 20); memset(hash, 0, 20); if (res) { px_debug("mdcbuf_finish: MDC does not match"); res = PXE_PGP_CORRUPT_DATA; } return res; }
static void mdcbuf_free | ( | void * | priv | ) | [static] |
Definition at line 590 of file pgp-decrypt.c.
References MDCBufData::ctx, PGP_Context::mdc_ctx, px_free, and px_md_free.
{ struct MDCBufData *st = priv; px_md_free(st->ctx->mdc_ctx); st->ctx->mdc_ctx = NULL; memset(st, 0, sizeof(*st)); px_free(st); }
static int mdcbuf_init | ( | void ** | priv_p, | |
void * | arg, | |||
PullFilter * | src | |||
) | [static] |
Definition at line 463 of file pgp-decrypt.c.
References MDCBufData::buf, MDCBufData::buflen, MDCBufData::ctx, px_alloc, and PGP_Context::use_mdcbuf_filter.
{ PGP_Context *ctx = arg; struct MDCBufData *st; st = px_alloc(sizeof(*st)); memset(st, 0, sizeof(*st)); st->buflen = sizeof(st->buf); st->ctx = ctx; *priv_p = st; /* take over the work of mdc_filter */ ctx->use_mdcbuf_filter = 1; return 0; }
static void mdcbuf_load_data | ( | struct MDCBufData * | st, | |
uint8 * | src, | |||
int | len | |||
) | [static] |
Definition at line 506 of file pgp-decrypt.c.
References MDCBufData::avail, MDCBufData::ctx, PGP_Context::mdc_ctx, MDCBufData::pos, and px_md_update.
Referenced by mdcbuf_refill().
static void mdcbuf_load_mdc | ( | struct MDCBufData * | st, | |
uint8 * | src, | |||
int | len | |||
) | [static] |
Definition at line 516 of file pgp-decrypt.c.
References MDCBufData::mdc_avail, MDCBufData::mdc_buf, and memmove.
Referenced by mdcbuf_refill().
static int mdcbuf_read | ( | void * | priv, | |
PullFilter * | src, | |||
int | len, | |||
uint8 ** | data_p, | |||
uint8 * | buf, | |||
int | buflen | |||
) | [static] |
Definition at line 567 of file pgp-decrypt.c.
References MDCBufData::avail, MDCBufData::eof, mdcbuf_refill(), and MDCBufData::pos.
{ struct MDCBufData *st = priv; int res; if (!st->eof && len > st->avail) { res = mdcbuf_refill(st, src); if (res < 0) return res; } if (len > st->avail) len = st->avail; *data_p = st->pos; st->pos += len; st->avail -= len; return len; }
static int mdcbuf_refill | ( | struct MDCBufData * | st, | |
PullFilter * | src | |||
) | [static] |
Definition at line 523 of file pgp-decrypt.c.
References MDCBufData::avail, MDCBufData::buf, MDCBufData::buflen, MDCBufData::mdc_avail, MDCBufData::mdc_buf, mdcbuf_finish(), mdcbuf_load_data(), mdcbuf_load_mdc(), memmove, MDCBufData::pos, and pullf_read().
Referenced by mdcbuf_read().
{ uint8 *data; int res; int need; /* put avail data in start */ if (st->avail > 0 && st->pos != st->buf) memmove(st->buf, st->pos, st->avail); st->pos = st->buf; /* read new data */ need = st->buflen + 22 - st->avail - st->mdc_avail; res = pullf_read(src, need, &data); if (res < 0) return res; if (res == 0) return mdcbuf_finish(st); /* add to buffer */ if (res >= 22) { mdcbuf_load_data(st, st->mdc_buf, st->mdc_avail); st->mdc_avail = 0; mdcbuf_load_data(st, data, res - 22); mdcbuf_load_mdc(st, data + res - 22, 22); } else { int canmove = st->mdc_avail + res - 22; if (canmove > 0) { mdcbuf_load_data(st, st->mdc_buf, canmove); st->mdc_avail -= canmove; memmove(st->mdc_buf, st->mdc_buf + canmove, st->mdc_avail); } mdcbuf_load_mdc(st, data, res); } return 0; }
static int parse_compressed_data | ( | PGP_Context * | ctx, | |
MBuf * | dst, | |||
PullFilter * | pkt | |||
) | [static] |
Definition at line 831 of file pgp-decrypt.c.
References PGP_Context::compress_algo, GETBYTE, NO_COMPR, NO_MDC, PGP_COMPR_BZIP2, PGP_COMPR_NONE, PGP_COMPR_ZIP, PGP_COMPR_ZLIB, pgp_decompress_filter(), process_data_packets(), pullf_free(), and px_debug().
Referenced by process_data_packets().
{ int res; uint8 type; PullFilter *pf_decompr; GETBYTE(pkt, type); ctx->compress_algo = type; switch (type) { case PGP_COMPR_NONE: res = process_data_packets(ctx, dst, pkt, NO_COMPR, NO_MDC); break; case PGP_COMPR_ZIP: case PGP_COMPR_ZLIB: res = pgp_decompress_filter(&pf_decompr, ctx, pkt); if (res >= 0) { res = process_data_packets(ctx, dst, pf_decompr, NO_COMPR, NO_MDC); pullf_free(pf_decompr); } break; case PGP_COMPR_BZIP2: px_debug("parse_compressed_data: bzip2 unsupported"); res = PXE_PGP_UNSUPPORTED_COMPR; break; default: px_debug("parse_compressed_data: unknown compr type"); res = PXE_PGP_CORRUPT_DATA; } return res; }
static int parse_literal_data | ( | PGP_Context * | ctx, | |
MBuf * | dst, | |||
PullFilter * | pkt | |||
) | [static] |
Definition at line 760 of file pgp-decrypt.c.
References buf, PGP_Context::convert_crlf, copy_crlf(), GETBYTE, mbuf_append(), pullf_read(), pullf_read_max(), px_debug(), PGP_Context::text_mode, tmpbuf, and PGP_Context::unicode_mode.
Referenced by process_data_packets().
{ int type; int name_len; int res; uint8 *buf; uint8 tmpbuf[4]; int got_cr = 0; GETBYTE(pkt, type); GETBYTE(pkt, name_len); /* skip name */ while (name_len > 0) { res = pullf_read(pkt, name_len, &buf); if (res < 0) return res; if (res == 0) break; name_len -= res; } if (name_len > 0) { px_debug("parse_literal_data: unexpected eof"); return PXE_PGP_CORRUPT_DATA; } /* skip date */ res = pullf_read_max(pkt, 4, &buf, tmpbuf); if (res != 4) { px_debug("parse_literal_data: unexpected eof"); return PXE_PGP_CORRUPT_DATA; } memset(tmpbuf, 0, 4); /* check if text */ if (ctx->text_mode) if (type != 't' && type != 'u') { px_debug("parse_literal_data: data type=%c", type); return PXE_PGP_NOT_TEXT; } ctx->unicode_mode = (type == 'u') ? 1 : 0; /* read data */ while (1) { res = pullf_read(pkt, 32 * 1024, &buf); if (res <= 0) break; if (ctx->text_mode && ctx->convert_crlf) res = copy_crlf(dst, buf, res, &got_cr); else res = mbuf_append(dst, buf, res); if (res < 0) break; } if (res >= 0 && got_cr) res = mbuf_append(dst, (const uint8 *) "\r", 1); return res; }
static int parse_new_len | ( | PullFilter * | src, | |
int * | len_p | |||
) | [static] |
Definition at line 52 of file pgp-decrypt.c.
References GETBYTE, MAX_CHUNK, and px_debug().
Referenced by pgp_parse_pkt_hdr(), and pktreader_pull().
{ uint8 b; int len; int pkttype = PKT_NORMAL; GETBYTE(src, b); if (b <= 191) len = b; else if (b >= 192 && b <= 223) { len = ((unsigned) (b) - 192) << 8; GETBYTE(src, b); len += 192 + b; } else if (b == 255) { GETBYTE(src, b); len = b; GETBYTE(src, b); len = (len << 8) | b; GETBYTE(src, b); len = (len << 8) | b; GETBYTE(src, b); len = (len << 8) | b; } else { len = 1 << (b & 0x1F); pkttype = PKT_STREAM; } if (len < 0 || len > MAX_CHUNK) { px_debug("parse_new_len: weird length"); return PXE_PGP_CORRUPT_DATA; } *len_p = len; return pkttype; }
static int parse_old_len | ( | PullFilter * | src, | |
int * | len_p, | |||
int | lentype | |||
) | [static] |
Definition at line 95 of file pgp-decrypt.c.
References GETBYTE, MAX_CHUNK, and px_debug().
Referenced by pgp_parse_pkt_hdr().
{ uint8 b; int len; GETBYTE(src, b); len = b; if (lentype == 1) { GETBYTE(src, b); len = (len << 8) | b; } else if (lentype == 2) { GETBYTE(src, b); len = (len << 8) | b; GETBYTE(src, b); len = (len << 8) | b; GETBYTE(src, b); len = (len << 8) | b; } if (len < 0 || len > MAX_CHUNK) { px_debug("parse_old_len: weird length"); return PXE_PGP_CORRUPT_DATA; } *len_p = len; return PKT_NORMAL; }
static int parse_symenc_data | ( | PGP_Context * | ctx, | |
PullFilter * | pkt, | |||
MBuf * | dst | |||
) | [static] |
Definition at line 978 of file pgp-decrypt.c.
References ALLOW_COMPR, PGP_Context::cipher_algo, NO_MDC, NULL, pgp_cfb_create(), pgp_cfb_free(), process_data_packets(), pullf_create(), pullf_free(), PGP_Context::sess_key, and PGP_Context::sess_key_len.
Referenced by pgp_decrypt().
{ int res; PGP_CFB *cfb = NULL; PullFilter *pf_decrypt = NULL; PullFilter *pf_prefix = NULL; res = pgp_cfb_create(&cfb, ctx->cipher_algo, ctx->sess_key, ctx->sess_key_len, 1, NULL); if (res < 0) goto out; res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt); if (res < 0) goto out; res = pullf_create(&pf_prefix, &prefix_filter, ctx, pf_decrypt); if (res < 0) goto out; res = process_data_packets(ctx, dst, pf_prefix, ALLOW_COMPR, NO_MDC); out: if (pf_prefix) pullf_free(pf_prefix); if (pf_decrypt) pullf_free(pf_decrypt); if (cfb) pgp_cfb_free(cfb); return res; }
static int parse_symenc_mdc_data | ( | PGP_Context * | ctx, | |
PullFilter * | pkt, | |||
MBuf * | dst | |||
) | [static] |
Definition at line 1012 of file pgp-decrypt.c.
References ALLOW_COMPR, PGP_Context::cipher_algo, GETBYTE, NEED_MDC, NULL, pgp_cfb_create(), pgp_cfb_free(), process_data_packets(), pullf_create(), pullf_free(), px_debug(), PGP_Context::sess_key, and PGP_Context::sess_key_len.
Referenced by pgp_decrypt().
{ int res; PGP_CFB *cfb = NULL; PullFilter *pf_decrypt = NULL; PullFilter *pf_prefix = NULL; PullFilter *pf_mdc = NULL; uint8 ver; GETBYTE(pkt, ver); if (ver != 1) { px_debug("parse_symenc_mdc_data: pkt ver != 1"); return PXE_PGP_CORRUPT_DATA; } res = pgp_cfb_create(&cfb, ctx->cipher_algo, ctx->sess_key, ctx->sess_key_len, 0, NULL); if (res < 0) goto out; res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt); if (res < 0) goto out; res = pullf_create(&pf_mdc, &mdc_filter, ctx, pf_decrypt); if (res < 0) goto out; res = pullf_create(&pf_prefix, &prefix_filter, ctx, pf_mdc); if (res < 0) goto out; res = process_data_packets(ctx, dst, pf_prefix, ALLOW_COMPR, NEED_MDC); out: if (pf_prefix) pullf_free(pf_prefix); if (pf_mdc) pullf_free(pf_mdc); if (pf_decrypt) pullf_free(pf_decrypt); if (cfb) pgp_cfb_free(cfb); return res; }
static int parse_symenc_sesskey | ( | PGP_Context * | ctx, | |
PullFilter * | src | |||
) | [static] |
Definition at line 642 of file pgp-decrypt.c.
References PGP_Context::cipher_algo, decrypt_key(), PGP_S2K::digest_algo, GETBYTE, PGP_S2K::key, PGP_S2K::key_len, PGP_S2K::mode, PGP_MAX_KEY, pgp_s2k_process(), pgp_s2k_read(), pullf_read_max(), px_debug(), PGP_Context::s2k, PGP_Context::s2k_cipher_algo, PGP_Context::s2k_digest_algo, PGP_Context::s2k_mode, PGP_Context::sess_key, PGP_Context::sess_key_len, PGP_Context::sym_key, PGP_Context::sym_key_len, tmpbuf, and PGP_Context::use_sess_key.
Referenced by pgp_decrypt().
{ uint8 *p; int res; uint8 tmpbuf[PGP_MAX_KEY + 2]; uint8 ver; GETBYTE(src, ver); GETBYTE(src, ctx->s2k_cipher_algo); if (ver != 4) { px_debug("bad key pkt ver"); return PXE_PGP_CORRUPT_DATA; } /* * read S2K info */ res = pgp_s2k_read(src, &ctx->s2k); if (res < 0) return res; ctx->s2k_mode = ctx->s2k.mode; ctx->s2k_digest_algo = ctx->s2k.digest_algo; /* * generate key from password */ res = pgp_s2k_process(&ctx->s2k, ctx->s2k_cipher_algo, ctx->sym_key, ctx->sym_key_len); if (res < 0) return res; /* * do we have separate session key? */ res = pullf_read_max(src, PGP_MAX_KEY + 2, &p, tmpbuf); if (res < 0) return res; if (res == 0) { /* * no, s2k key is session key */ memcpy(ctx->sess_key, ctx->s2k.key, ctx->s2k.key_len); ctx->sess_key_len = ctx->s2k.key_len; ctx->cipher_algo = ctx->s2k_cipher_algo; res = 0; ctx->use_sess_key = 0; } else { /* * yes, decrypt it */ if (res < 17 || res > PGP_MAX_KEY + 1) { px_debug("expect key, but bad data"); return PXE_PGP_CORRUPT_DATA; } ctx->use_sess_key = 1; res = decrypt_key(ctx, p, res); } memset(tmpbuf, 0, sizeof(tmpbuf)); return res; }
int pgp_create_pkt_reader | ( | PullFilter ** | pf_p, | |
PullFilter * | src, | |||
int | len, | |||
int | pkttype, | |||
PGP_Context * | ctx | |||
) |
Definition at line 223 of file pgp-decrypt.c.
References PktData::len, pullf_create(), px_alloc, px_free, and PktData::type.
Referenced by internal_read_key(), pgp_decrypt(), pgp_get_keyid(), and process_data_packets().
{ int res; struct PktData *pkt = px_alloc(sizeof(*pkt)); pkt->type = pkttype; pkt->len = len; res = pullf_create(pf_p, &pktreader_filter, pkt, src); if (res < 0) px_free(pkt); return res; }
int pgp_decrypt | ( | PGP_Context * | ctx, | |
MBuf * | msrc, | |||
MBuf * | mdst | |||
) |
Definition at line 1096 of file pgp-decrypt.c.
References PGP_Context::corrupt_prefix, PGP_Context::disable_mdc, NO_CTX_SIZE, parse_symenc_data(), parse_symenc_mdc_data(), parse_symenc_sesskey(), pgp_create_pkt_reader(), pgp_parse_pkt_hdr(), pgp_parse_pubenc_sesskey(), PGP_PKT_MARKER, PGP_PKT_PUBENCRYPTED_SESSKEY, PGP_PKT_SYMENCRYPTED_DATA, PGP_PKT_SYMENCRYPTED_DATA_MDC, PGP_PKT_SYMENCRYPTED_SESSKEY, pgp_skip_packet(), pullf_create_mbuf_reader(), pullf_free(), and px_debug().
Referenced by decrypt_internal().
{ int res; PullFilter *src = NULL; PullFilter *pkt = NULL; uint8 tag; int len; int got_key = 0; int got_data = 0; res = pullf_create_mbuf_reader(&src, msrc); while (res >= 0) { res = pgp_parse_pkt_hdr(src, &tag, &len, NO_CTX_SIZE); if (res <= 0) break; res = pgp_create_pkt_reader(&pkt, src, len, res, ctx); if (res < 0) break; res = PXE_PGP_CORRUPT_DATA; switch (tag) { case PGP_PKT_MARKER: res = pgp_skip_packet(pkt); break; case PGP_PKT_PUBENCRYPTED_SESSKEY: /* fixme: skip those */ res = pgp_parse_pubenc_sesskey(ctx, pkt); got_key = 1; break; case PGP_PKT_SYMENCRYPTED_SESSKEY: if (got_key) /* * Theoretically, there could be several keys, both public * and symmetric, all of which encrypt same session key. * Decrypt should try with each one, before failing. */ px_debug("pgp_decrypt: using first of several keys"); else { got_key = 1; res = parse_symenc_sesskey(ctx, pkt); } break; case PGP_PKT_SYMENCRYPTED_DATA: if (!got_key) px_debug("pgp_decrypt: have data but no key"); else if (got_data) px_debug("pgp_decrypt: got second data packet"); else { got_data = 1; ctx->disable_mdc = 1; res = parse_symenc_data(ctx, pkt, mdst); } break; case PGP_PKT_SYMENCRYPTED_DATA_MDC: if (!got_key) px_debug("pgp_decrypt: have data but no key"); else if (got_data) px_debug("pgp_decrypt: several data pkts not supported"); else { got_data = 1; ctx->disable_mdc = 0; res = parse_symenc_mdc_data(ctx, pkt, mdst); } break; default: px_debug("pgp_decrypt: unknown tag: 0x%02x", tag); } pullf_free(pkt); pkt = NULL; } if (pkt) pullf_free(pkt); if (src) pullf_free(src); if (res < 0) return res; if (!got_data || ctx->corrupt_prefix) res = PXE_PGP_CORRUPT_DATA; return res; }
int pgp_expect_packet_end | ( | PullFilter * | pkt | ) |
Definition at line 1078 of file pgp-decrypt.c.
References pullf_read(), and px_debug().
Referenced by pgp_parse_pubenc_sesskey(), and process_secret_key().
{ int res = 1; uint8 *tmp; while (res > 0) { res = pullf_read(pkt, 32 * 1024, &tmp); if (res > 0) { px_debug("pgp_expect_packet_end: got data"); return PXE_PGP_CORRUPT_DATA; } } return res < 0 ? res : 0; }
int pgp_parse_pkt_hdr | ( | PullFilter * | src, | |
uint8 * | tag, | |||
int * | len_p, | |||
int | allow_ctx | |||
) |
Definition at line 129 of file pgp-decrypt.c.
References parse_new_len(), parse_old_len(), PKT_CONTEXT, pullf_read(), and px_debug().
Referenced by internal_read_key(), pgp_decrypt(), pgp_get_keyid(), and process_data_packets().
{ int lentype; int res; uint8 *p; /* EOF is normal here, thus we dont use GETBYTE */ res = pullf_read(src, 1, &p); if (res < 0) return res; if (res == 0) return 0; if ((*p & 0x80) == 0) { px_debug("pgp_parse_pkt_hdr: not pkt hdr"); return PXE_PGP_CORRUPT_DATA; } if (*p & 0x40) { *tag = *p & 0x3f; res = parse_new_len(src, len_p); } else { lentype = *p & 3; *tag = (*p >> 2) & 0x0F; if (lentype == 3) res = allow_ctx ? PKT_CONTEXT : PXE_PGP_CORRUPT_DATA; else res = parse_old_len(src, len_p, lentype); } return res; }
int pgp_skip_packet | ( | PullFilter * | pkt | ) |
Definition at line 1064 of file pgp-decrypt.c.
References pullf_read().
Referenced by internal_read_key(), pgp_decrypt(), pgp_get_keyid(), read_pubenc_keyid(), and read_pubkey_keyid().
{ int res = 1; uint8 *tmp; while (res > 0) res = pullf_read(pkt, 32 * 1024, &tmp); return res < 0 ? res : 0; }
static void pktreader_free | ( | void * | priv | ) | [static] |
Definition at line 209 of file pgp-decrypt.c.
References px_free.
static int pktreader_pull | ( | void * | priv, | |
PullFilter * | src, | |||
int | len, | |||
uint8 ** | data_p, | |||
uint8 * | buf, | |||
int | buflen | |||
) | [static] |
Definition at line 175 of file pgp-decrypt.c.
References PktData::len, parse_new_len(), PKT_CONTEXT, PKT_NORMAL, pullf_read(), and PktData::type.
{ int res; struct PktData *pkt = priv; /* PKT_CONTEXT means: whatever there is */ if (pkt->type == PKT_CONTEXT) return pullf_read(src, len, data_p); if (pkt->len == 0) { /* this was last chunk in stream */ if (pkt->type == PKT_NORMAL) return 0; /* next chunk in stream */ res = parse_new_len(src, &pkt->len); if (res < 0) return res; pkt->type = res; } if (len > pkt->len) len = pkt->len; res = pullf_read(src, len, data_p); if (res > 0) pkt->len -= res; return res; }
static int prefix_init | ( | void ** | priv_p, | |
void * | arg, | |||
PullFilter * | src | |||
) | [static] |
Definition at line 242 of file pgp-decrypt.c.
References buf, PGP_Context::cipher_algo, PGP_Context::corrupt_prefix, PktData::len, pgp_get_cipher_block_size(), PGP_MAX_BLOCK, pullf_read_max(), px_debug(), and tmpbuf.
{ PGP_Context *ctx = arg; int len; int res; uint8 *buf; uint8 tmpbuf[PGP_MAX_BLOCK + 2]; len = pgp_get_cipher_block_size(ctx->cipher_algo); if (len > sizeof(tmpbuf)) return PXE_BUG; res = pullf_read_max(src, len + 2, &buf, tmpbuf); if (res < 0) return res; if (res != len + 2) { px_debug("prefix_init: short read"); memset(tmpbuf, 0, sizeof(tmpbuf)); return PXE_PGP_CORRUPT_DATA; } if (buf[len - 2] != buf[len] || buf[len - 1] != buf[len + 1]) { px_debug("prefix_init: corrupt prefix"); /* * The original purpose of the 2-byte check was to show user a * friendly "wrong key" message. This made following possible: * * "An Attack on CFB Mode Encryption As Used By OpenPGP" by Serge * Mister and Robert Zuccherato * * To avoid being 'oracle', we delay reporting, which basically means * we prefer to run into corrupt packet header. * * We _could_ throw PXE_PGP_CORRUPT_DATA here, but there is * possibility of attack via timing, so we don't. */ ctx->corrupt_prefix = 1; } memset(tmpbuf, 0, sizeof(tmpbuf)); return 0; }
static int process_data_packets | ( | PGP_Context * | ctx, | |
MBuf * | dst, | |||
PullFilter * | src, | |||
int | allow_compr, | |||
int | need_mdc | |||
) | [static] |
Definition at line 871 of file pgp-decrypt.c.
References ALLOW_CTX_SIZE, PGP_Context::in_mdc_pkt, NO_MDC, parse_compressed_data(), parse_literal_data(), pgp_create_pkt_reader(), pgp_parse_pkt_hdr(), PGP_PKT_COMPRESSED_DATA, PGP_PKT_LITERAL_DATA, PGP_PKT_MDC, PKT_CONTEXT, pullf_create(), pullf_free(), pullf_read(), px_debug(), and PGP_Context::use_mdcbuf_filter.
Referenced by parse_compressed_data(), parse_symenc_data(), and parse_symenc_mdc_data().
{ uint8 tag; int len, res; int got_data = 0; int got_mdc = 0; PullFilter *pkt = NULL; uint8 *tmp; while (1) { res = pgp_parse_pkt_hdr(src, &tag, &len, ALLOW_CTX_SIZE); if (res <= 0) break; /* mdc packet should be last */ if (got_mdc) { px_debug("process_data_packets: data after mdc"); res = PXE_PGP_CORRUPT_DATA; break; } /* context length inside SYMENC_MDC needs special handling */ if (need_mdc && res == PKT_CONTEXT) res = pullf_create(&pkt, &mdcbuf_filter, ctx, src); else res = pgp_create_pkt_reader(&pkt, src, len, res, ctx); if (res < 0) break; switch (tag) { case PGP_PKT_LITERAL_DATA: got_data = 1; res = parse_literal_data(ctx, dst, pkt); break; case PGP_PKT_COMPRESSED_DATA: if (allow_compr == 0) { px_debug("process_data_packets: unexpected compression"); res = PXE_PGP_CORRUPT_DATA; } else if (got_data) { /* * compr data must be alone */ px_debug("process_data_packets: only one cmpr pkt allowed"); res = PXE_PGP_CORRUPT_DATA; } else { got_data = 1; res = parse_compressed_data(ctx, dst, pkt); } break; case PGP_PKT_MDC: if (need_mdc == NO_MDC) { px_debug("process_data_packets: unexpected MDC"); res = PXE_PGP_CORRUPT_DATA; break; } /* notify mdc_filter */ ctx->in_mdc_pkt = 1; res = pullf_read(pkt, 8192, &tmp); if (res > 0) got_mdc = 1; break; default: px_debug("process_data_packets: unexpected pkt tag=%d", tag); res = PXE_PGP_CORRUPT_DATA; } pullf_free(pkt); pkt = NULL; if (res < 0) break; } if (pkt) pullf_free(pkt); if (res < 0) return res; if (!got_data) { px_debug("process_data_packets: no data"); res = PXE_PGP_CORRUPT_DATA; } if (need_mdc && !got_mdc && !ctx->use_mdcbuf_filter) { px_debug("process_data_packets: got no mdc"); res = PXE_PGP_CORRUPT_DATA; } return res; }
struct PullFilterOps mdc_filter [static] |
{ mdc_init, mdc_read, mdc_free }
Definition at line 436 of file pgp-decrypt.c.
struct PullFilterOps mdcbuf_filter [static] |
{ mdcbuf_init, mdcbuf_read, mdcbuf_free }
Definition at line 600 of file pgp-decrypt.c.
struct PullFilterOps pgp_decrypt_filter |
{ decrypt_init, decrypt_read, NULL }
Definition at line 324 of file pgp-decrypt.c.
Referenced by process_secret_key().
struct PullFilterOps pktreader_filter [static] |
{ NULL, pktreader_pull, pktreader_free }
Definition at line 217 of file pgp-decrypt.c.
struct PullFilterOps prefix_filter [static] |
{ prefix_init, NULL, NULL }
Definition at line 287 of file pgp-decrypt.c.