diff options
Diffstat (limited to 'contrib/pgcrypto/pgp-decrypt.c')
-rw-r--r-- | contrib/pgcrypto/pgp-decrypt.c | 70 |
1 files changed, 52 insertions, 18 deletions
diff --git a/contrib/pgcrypto/pgp-decrypt.c b/contrib/pgcrypto/pgp-decrypt.c index c0c5773e66c..5c69745156c 100644 --- a/contrib/pgcrypto/pgp-decrypt.c +++ b/contrib/pgcrypto/pgp-decrypt.c @@ -236,6 +236,8 @@ pgp_create_pkt_reader(PullFilter **pf_p, PullFilter *src, int len, /* * Prefix check filter + * https://tools.ietf.org/html/rfc4880#section-5.7 + * https://tools.ietf.org/html/rfc4880#section-5.13 */ static int @@ -264,20 +266,7 @@ prefix_init(void **priv_p, void *arg, PullFilter *src) 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. - */ + /* report error in pgp_decrypt() */ ctx->corrupt_prefix = 1; } px_memset(tmpbuf, 0, sizeof(tmpbuf)); @@ -788,12 +777,15 @@ parse_literal_data(PGP_Context *ctx, MBuf *dst, PullFilter *pkt) } px_memset(tmpbuf, 0, 4); - /* check if text */ + /* + * If called from an SQL function that returns text, pgp_decrypt() rejects + * inputs not self-identifying as 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->unexpected_binary = true; } ctx->unicode_mode = (type == 'u') ? 1 : 0; @@ -827,6 +819,7 @@ parse_compressed_data(PGP_Context *ctx, MBuf *dst, PullFilter *pkt) int res; uint8 type; PullFilter *pf_decompr; + uint8 *discard_buf; GETBYTE(pkt, type); @@ -850,7 +843,20 @@ parse_compressed_data(PGP_Context *ctx, MBuf *dst, PullFilter *pkt) case PGP_COMPR_BZIP2: px_debug("parse_compressed_data: bzip2 unsupported"); - res = PXE_PGP_UNSUPPORTED_COMPR; + /* report error in pgp_decrypt() */ + ctx->unsupported_compr = 1; + + /* + * Discard the compressed data, allowing it to first affect any + * MDC digest computation. + */ + while (1) + { + res = pullf_read(pkt, 32 * 1024, &discard_buf); + if (res <= 0) + break; + } + break; default: @@ -1168,8 +1174,36 @@ pgp_decrypt(PGP_Context *ctx, MBuf *msrc, MBuf *mdst) if (res < 0) return res; + /* + * Report a failure of the prefix_init() "quick check" now, rather than + * upon detection, to hinder timing attacks. pgcrypto is not generally + * secure against timing attacks, but this helps. + */ if (!got_data || ctx->corrupt_prefix) - res = PXE_PGP_CORRUPT_DATA; + return PXE_PGP_CORRUPT_DATA; + + /* + * Code interpreting purportedly-decrypted data prior to this stage shall + * report no error other than PXE_PGP_CORRUPT_DATA. (PXE_BUG is okay so + * long as it remains unreachable.) This ensures that an attacker able to + * choose a ciphertext and receive a corresponding decryption error + * message cannot use that oracle to gather clues about the decryption + * key. See "An Attack on CFB Mode Encryption As Used By OpenPGP" by + * Serge Mister and Robert Zuccherato. + * + * A problematic value in the first octet of a Literal Data or Compressed + * Data packet may indicate a simple user error, such as the need to call + * pgp_sym_decrypt_bytea instead of pgp_sym_decrypt. Occasionally, + * though, it is the first symptom of the encryption key not matching the + * decryption key. When this was the only problem encountered, report a + * specific error to guide the user; otherwise, we will have reported + * PXE_PGP_CORRUPT_DATA before now. A key mismatch makes the other errors + * into red herrings, and this avoids leaking clues to attackers. + */ + if (ctx->unsupported_compr) + return PXE_PGP_UNSUPPORTED_COMPR; + if (ctx->unexpected_binary) + return PXE_PGP_NOT_TEXT; return res; } |