#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.
1.7.1