/* needs helper function to pass several parameters */ int
pgp_create_pkt_reader(PullFilter **pf_p, PullFilter *src, int len, int pkttype, PGP_Context *ctx)
{ int res; struct PktData *pkt = palloc(sizeof(*pkt));
pkt->type = pkttype;
pkt->len = len;
res = pullf_create(pf_p, &pktreader_filter, pkt, src); if (res < 0)
pfree(pkt); return res;
}
len = pgp_get_cipher_block_size(ctx->cipher_algo); /* Make sure we have space for prefix */ if (len > PGP_MAX_BLOCK) 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");
px_memset(tmpbuf, 0, sizeof(tmpbuf)); return PXE_PGP_CORRUPT_DATA;
}
staticint
mdcbuf_refill(struct MDCBufData *st, PullFilter *src)
{
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;
staticint
copy_crlf(MBuf *dst, uint8 *data, int len, int *got_cr)
{
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;
}
px_memset(tmpbuf, 0, sizeof(tmpbuf)); return0;
}
staticint
parse_literal_data(PGP_Context *ctx, MBuf *dst, PullFilter *pkt)
{ 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;
}
px_memset(tmpbuf, 0, 4);
/* *IfcalledfromanSQLfunctionthatreturnstext,pgp_decrypt()rejects *inputsnotself-identifyingastext.
*/ if (ctx->text_mode) if (type != 't' && type != 'u')
{
px_debug("parse_literal_data: data type=%c", type);
ctx->unexpected_binary = true;
}
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;
}
/* process_data_packets and parse_compressed_data call each other */ staticint process_data_packets(PGP_Context *ctx, MBuf *dst,
PullFilter *src, int allow_compr, int need_mdc);
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"); /* report error in pgp_decrypt() */
ctx->unsupported_compr = 1;
/* *Discardthecompresseddata,allowingittofirstaffectany *MDCdigestcomputation.
*/ while (1)
{
res = pullf_read(pkt, 32 * 1024, &discard_buf); if (res <= 0) break;
}
break;
default:
px_debug("parse_compressed_data: unknown compr type");
res = PXE_PGP_CORRUPT_DATA;
}
return res;
}
staticint
process_data_packets(PGP_Context *ctx, MBuf *dst, PullFilter *src, int allow_compr, int need_mdc)
{
uint8 tag; int len,
res; int got_data = 0; int got_mdc = 0;
PullFilter *pkt = NULL;
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;
}
/* *ContextlengthinsideSYMENCRYPTED_DATA_MDCpacketneedsspecial *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;
} elseif (got_data)
{ /* *comprdatamustbealone
*/
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;
}
res = mdc_finish(ctx, pkt, len); 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;
}
int
pgp_decrypt(PGP_Context *ctx, MBuf *msrc, MBuf *mdst)
{ 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,therecouldbeseveralkeys,bothpublic *andsymmetric,allofwhichencryptsamesessionkey. *Decryptshouldtrywitheachone,beforefailing.
*/
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"); elseif (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"); elseif (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;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.