1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

pgcrypto: Add option to revert to prior decryption behavior

The previous commit raises an ERROR during PGP operations if OpenSSL
does not support the cipher in use. However, any existing messages
created with faulty encryption will no longer be accessible via
pgp_[sym|pub]_decrypt().

To help users out of this situation, add a new ignore-cipher-failure
option which reverts to the broken behavior during decryption only. A
faulty encryption wrapper, created by an OpenSSL configuration that does
not support the cipher, can then be stripped back off by that same
OpenSSL in order to safely reencrypt it. (Note that when OpenSSL does
support the cipher, corrupted messages will not be decrypted regardless
of the ignore-cipher-failure setting; this is unchanged.)

The new tests add a corrupted Blowfish message for both public- and
symmetric-key decryption, resulting in the following test matrix:

- Blowfish supported, default behavior:      fails to decrypt
- Blowfish supported, ignore-cipher-failure: fails to decrypt
- Blowfish unsupported, default behavior:    fails to load cipher
- Blowfish unsupported, ignore-cipher-failure: strips faulty encryption

The previous commit's change to the pubkey tests is expanded similarly:
correctly encrypted messages cannot be decrypted by an OpenSSL that does
not support the cipher, regardless of the option's setting, though the
failure mode will change.

Suggested-by: Noah Misch <noah@leadboat.com>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Noah Misch <noah@leadboat.com>
Security: CVE-2026-14663
Backpatch-through: 14
This commit is contained in:
Jacob Champion
2026-08-10 06:37:50 -07:00
committed by Noah Misch
parent d0ecee6de9
commit 49e7954148
15 changed files with 254 additions and 13 deletions

View File

@@ -439,3 +439,29 @@ UCAAw2JRIISttRHMfDpDuZJpvYo=
'), 'key', 'debug=1');
NOTICE: dbg: parse_compressed_data: bzip2 unsupported
ERROR: Unsupported compression algorithm
-- Check ignore-cipher-failure. This message isn't actually encrypted; it was
-- created with cipher-algo=bf using an OpenSSL that didn't actually support
-- Blowfish. After the fix for CVE-2026-14663, we no longer create these broken
-- ciphertexts, but we allow users to return to the previous behavior during
-- decryption so that the bad wrapper can be stripped.
--
-- Note that if Blowfish is supported by the linked OpenSSL, both decryptions
-- will fail.
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
ww0EBAMC8wIKbtvzJtxi0jABUleCwFJWGCkYKcsNdABqdtXaU2VjcmV0LtMUlnPH3A2QBmZrcucm
1GPb/s2Bkdg=
=6aqD
-----END PGP MESSAGE-----
'), 'wrong key');
ERROR: Wrong key or corrupt data
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
ww0EBAMC8wIKbtvzJtxi0jABUleCwFJWGCkYKcsNdABqdtXaU2VjcmV0LtMUlnPH3A2QBmZrcucm
1GPb/s2Bkdg=
=6aqD
-----END PGP MESSAGE-----
'), 'wrong key', 'ignore-cipher-failure=1');
ERROR: Wrong key or corrupt data

View File

@@ -435,3 +435,33 @@ UCAAw2JRIISttRHMfDpDuZJpvYo=
'), 'key', 'debug=1');
NOTICE: dbg: parse_compressed_data: bzip2 unsupported
ERROR: Unsupported compression algorithm
-- Check ignore-cipher-failure. This message isn't actually encrypted; it was
-- created with cipher-algo=bf using an OpenSSL that didn't actually support
-- Blowfish. After the fix for CVE-2026-14663, we no longer create these broken
-- ciphertexts, but we allow users to return to the previous behavior during
-- decryption so that the bad wrapper can be stripped.
--
-- Note that if Blowfish is supported by the linked OpenSSL, both decryptions
-- will fail.
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
ww0EBAMC8wIKbtvzJtxi0jABUleCwFJWGCkYKcsNdABqdtXaU2VjcmV0LtMUlnPH3A2QBmZrcucm
1GPb/s2Bkdg=
=6aqD
-----END PGP MESSAGE-----
'), 'wrong key');
ERROR: encrypt error: Cipher cannot be initialized
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
ww0EBAMC8wIKbtvzJtxi0jABUleCwFJWGCkYKcsNdABqdtXaU2VjcmV0LtMUlnPH3A2QBmZrcucm
1GPb/s2Bkdg=
=6aqD
-----END PGP MESSAGE-----
'), 'wrong key', 'ignore-cipher-failure=1');
pgp_sym_decrypt
-----------------
Secret.
(1 row)

View File

@@ -75,5 +75,6 @@ from encdata order by id;
B68504FD128E1FF9
FD0206C409B74875
FD0206C409B74875
(5 rows)
D936CF64BB73F466
(6 rows)

View File

@@ -585,6 +585,20 @@ blH2nKZC9d6fi4YzSYMepZpMOFR65M80MCMiDUGnZBB8sEADu2/iVtqDUeG8mAA=
=PHJ1
-----END PGP MESSAGE-----
');
-- CVE-2026-14663. This message was created with cipher-algo=bf using an OpenSSL
-- that didn't actually support Blowfish.
insert into encdata (id, data) values (6, '
-----BEGIN PGP MESSAGE-----
wcBOA9k2z2S7c/RmEAP8DYbU6AeEo6riMMdnf2G62BM9gC0Z32ODydewy3Ki8AnSzpwBDAHuDMcr
P6RJDWvBOVOwgxHEwR7ZHMoFRDJEXdo6rQ9dQpDtbasMLyi6Lm1q+PbEefVd9WkU7fvFAFQx8k3t
lxrlWg/byoNplc7/hFxIFO8bN+FIlLgilAdApNcD/3Mg2/nd7pczovsYoryf9ib04kQ+SVWs3iNE
StoyEXT+oaT8u1vAxiY7fzPpQX1pnlHBUXn+v1J6LQL5Bwi5CTqOyDSyaFfgU0gQwTReFjS6L4Fs
Cv+2cFwbJBGIzr1aI4DLbzSelkmVm4hbOVeET4DJVlUVhhIyy6ZfoXiTEG6s0jMB2JdRGIl0EUQR
RMsQdABqdt5jU2VjcmV0IG1zZ9MUIIP4SPiU2pM/nF/A1hrltMhn/ZI=
=Mkdj
-----END PGP MESSAGE-----
');
-- successful decrypt
select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
from keytbl, encdata where keytbl.id=1 and encdata.id=1;
@@ -600,6 +614,13 @@ from keytbl, encdata where keytbl.id=2 and encdata.id=2;
Secret msg
(1 row)
select pgp_pub_decrypt(dearmor(data), dearmor(seckey), '', 'ignore-cipher-failure=1')
from keytbl, encdata where keytbl.id=2 and encdata.id=2;
pgp_pub_decrypt
-----------------
Secret msg
(1 row)
select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
from keytbl, encdata where keytbl.id=3 and encdata.id=3;
pgp_pub_decrypt
@@ -654,3 +675,12 @@ from keytbl, encdata where keytbl.id=5 and encdata.id=1;
select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
from keytbl, encdata where keytbl.id=6 and encdata.id=5;
ERROR: Wrong key or corrupt data
-- Check that ignore-cipher-failure can strip faulty encryption if OpenSSL
-- doesn't support the cipher. (The decryption will correctly fail both times if
-- OpenSSL does support it.)
select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
from keytbl, encdata where keytbl.id=1 and encdata.id=6;
ERROR: Wrong key or corrupt data
select pgp_pub_decrypt(dearmor(data), dearmor(seckey), '', 'ignore-cipher-failure=1')
from keytbl, encdata where keytbl.id=1 and encdata.id=6;
ERROR: Wrong key or corrupt data

View File

@@ -585,6 +585,20 @@ blH2nKZC9d6fi4YzSYMepZpMOFR65M80MCMiDUGnZBB8sEADu2/iVtqDUeG8mAA=
=PHJ1
-----END PGP MESSAGE-----
');
-- CVE-2026-14663. This message was created with cipher-algo=bf using an OpenSSL
-- that didn't actually support Blowfish.
insert into encdata (id, data) values (6, '
-----BEGIN PGP MESSAGE-----
wcBOA9k2z2S7c/RmEAP8DYbU6AeEo6riMMdnf2G62BM9gC0Z32ODydewy3Ki8AnSzpwBDAHuDMcr
P6RJDWvBOVOwgxHEwR7ZHMoFRDJEXdo6rQ9dQpDtbasMLyi6Lm1q+PbEefVd9WkU7fvFAFQx8k3t
lxrlWg/byoNplc7/hFxIFO8bN+FIlLgilAdApNcD/3Mg2/nd7pczovsYoryf9ib04kQ+SVWs3iNE
StoyEXT+oaT8u1vAxiY7fzPpQX1pnlHBUXn+v1J6LQL5Bwi5CTqOyDSyaFfgU0gQwTReFjS6L4Fs
Cv+2cFwbJBGIzr1aI4DLbzSelkmVm4hbOVeET4DJVlUVhhIyy6ZfoXiTEG6s0jMB2JdRGIl0EUQR
RMsQdABqdt5jU2VjcmV0IG1zZ9MUIIP4SPiU2pM/nF/A1hrltMhn/ZI=
=Mkdj
-----END PGP MESSAGE-----
');
-- successful decrypt
select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
from keytbl, encdata where keytbl.id=1 and encdata.id=1;
@@ -596,6 +610,9 @@ from keytbl, encdata where keytbl.id=1 and encdata.id=1;
select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
from keytbl, encdata where keytbl.id=2 and encdata.id=2;
ERROR: encrypt error: Cipher cannot be initialized
select pgp_pub_decrypt(dearmor(data), dearmor(seckey), '', 'ignore-cipher-failure=1')
from keytbl, encdata where keytbl.id=2 and encdata.id=2;
ERROR: Wrong key or corrupt data
select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
from keytbl, encdata where keytbl.id=3 and encdata.id=3;
pgp_pub_decrypt
@@ -650,3 +667,16 @@ from keytbl, encdata where keytbl.id=5 and encdata.id=1;
select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
from keytbl, encdata where keytbl.id=6 and encdata.id=5;
ERROR: Wrong key or corrupt data
-- Check that ignore-cipher-failure can strip faulty encryption if OpenSSL
-- doesn't support the cipher. (The decryption will correctly fail both times if
-- OpenSSL does support it.)
select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
from keytbl, encdata where keytbl.id=1 and encdata.id=6;
ERROR: encrypt error: Cipher cannot be initialized
select pgp_pub_decrypt(dearmor(data), dearmor(seckey), '', 'ignore-cipher-failure=1')
from keytbl, encdata where keytbl.id=1 and encdata.id=6;
pgp_pub_decrypt
-----------------
Secret msg
(1 row)

View File

@@ -43,6 +43,7 @@ struct PGP_CFB
int pos;
int block_no;
int resync;
int ignore_decrypt_cipher_failure; /* for CVE-2026-14663 recovery */
uint8 fr[PGP_MAX_BLOCK];
uint8 fre[PGP_MAX_BLOCK];
uint8 encbuf[PGP_MAX_BLOCK];
@@ -50,7 +51,7 @@ struct PGP_CFB
int
pgp_cfb_create(PGP_CFB **ctx_p, int algo, const uint8 *key, int key_len,
int resync, uint8 *iv)
int resync, uint8 *iv, int ignore_decrypt_cipher_failure)
{
int res;
PX_Cipher *ciph;
@@ -71,6 +72,7 @@ pgp_cfb_create(PGP_CFB **ctx_p, int algo, const uint8 *key, int key_len,
ctx->ciph = ciph;
ctx->block_size = px_cipher_block_size(ciph);
ctx->resync = resync;
ctx->ignore_decrypt_cipher_failure = ignore_decrypt_cipher_failure;
if (iv)
memcpy(ctx->fr, iv, ctx->block_size);
@@ -195,7 +197,7 @@ mix_decrypt_resync(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
*/
static int
cfb_process(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst,
mix_data_t mix_data)
mix_data_t mix_data, int ignore_cipher_failure)
{
int n;
int res;
@@ -224,7 +226,14 @@ cfb_process(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst,
int err;
err = px_cipher_encrypt(ctx->ciph, 0, ctx->fr, ctx->block_size, ctx->fre, &rlen);
if (err)
/*
* XXX Ignoring cipher failures is dangerous, but we allow it during
* decryption to return to the behavior prior to the fix for
* CVE-2026-14663. This lets users recover data from a badly-encrypted
* message.
*/
if (err && !ignore_cipher_failure)
ereport(ERROR,
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
errmsg("encrypt error: %s", px_strerror(err))));
@@ -259,7 +268,8 @@ pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
{
mix_data_t mix = ctx->resync ? mix_encrypt_resync : mix_encrypt_normal;
return cfb_process(ctx, data, len, dst, mix);
return cfb_process(ctx, data, len, dst, mix,
0 /* never ignore cipher failures for encrypt */ );
}
int
@@ -267,5 +277,6 @@ pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst)
{
mix_data_t mix = ctx->resync ? mix_decrypt_resync : mix_decrypt_normal;
return cfb_process(ctx, data, len, dst, mix);
return cfb_process(ctx, data, len, dst, mix,
ctx->ignore_decrypt_cipher_failure);
}

View File

@@ -595,7 +595,8 @@ decrypt_key(PGP_Context *ctx, const uint8 *src, int len)
PGP_CFB *cfb;
res = pgp_cfb_create(&cfb, ctx->s2k_cipher_algo,
ctx->s2k.key, ctx->s2k.key_len, 0, NULL);
ctx->s2k.key, ctx->s2k.key_len, 0, NULL,
ctx->ignore_cipher_failure);
if (res < 0)
return res;
@@ -983,7 +984,8 @@ parse_symenc_data(PGP_Context *ctx, PullFilter *pkt, MBuf *dst)
PullFilter *pf_prefix = NULL;
res = pgp_cfb_create(&cfb, ctx->cipher_algo,
ctx->sess_key, ctx->sess_key_len, 1, NULL);
ctx->sess_key, ctx->sess_key_len, 1, NULL,
ctx->ignore_cipher_failure);
if (res < 0)
goto out;
@@ -1026,7 +1028,8 @@ parse_symenc_mdc_data(PGP_Context *ctx, PullFilter *pkt, MBuf *dst)
}
res = pgp_cfb_create(&cfb, ctx->cipher_algo,
ctx->sess_key, ctx->sess_key_len, 0, NULL);
ctx->sess_key, ctx->sess_key_len, 0, NULL,
ctx->ignore_cipher_failure);
if (res < 0)
goto out;

View File

@@ -174,7 +174,8 @@ encrypt_init(PushFilter *next, void *init_arg, void **priv_p)
return res;
}
res = pgp_cfb_create(&ciph, ctx->cipher_algo,
ctx->sess_key, ctx->sess_key_len, resync, NULL);
ctx->sess_key, ctx->sess_key_len, resync, NULL,
0 /* never ignore cipher failures for encrypt */ );
if (res < 0)
return res;
@@ -505,7 +506,8 @@ symencrypt_sesskey(PGP_Context *ctx, uint8 *dst)
uint8 algo = ctx->cipher_algo;
res = pgp_cfb_create(&cfb, ctx->s2k_cipher_algo,
ctx->s2k.key, ctx->s2k.key_len, 0, NULL);
ctx->s2k.key, ctx->s2k.key_len, 0, NULL,
0 /* never ignore cipher failures for encrypt */ );
if (res < 0)
return res;

View File

@@ -192,6 +192,8 @@ set_arg(PGP_Context *ctx, char *key, char *val,
res = pgp_set_convert_crlf(ctx, atoi(val));
else if (strcmp(key, "unicode-mode") == 0)
res = pgp_set_unicode_mode(ctx, atoi(val));
else if (strcmp(key, "ignore-cipher-failure") == 0)
res = pgp_set_ignore_cipher_failure(ctx, atoi(val));
/*
* The remaining options are for debugging/testing and are therefore not

View File

@@ -382,8 +382,15 @@ process_secret_key(PullFilter *pkt, PGP_PubKey **pk_p,
/*
* create decrypt filter
*
* ignore-cipher-failure doesn't apply here; pgcrypto didn't encrypt
* the secret key to begin with, and any stored encrypted data was
* generated using the public key, so users don't have a reason to
* want to incorrectly decrypt this. We'll ignore failures during
* decryption with the session key, instead.
*/
res = pgp_cfb_create(&cfb, cipher_algo, s2k.key, s2k.key_len, 0, iv);
res = pgp_cfb_create(&cfb, cipher_algo, s2k.key, s2k.key_len, 0, iv,
0 /* don't ignore cipher failures */ );
if (res < 0)
return res;
res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt);

View File

@@ -49,6 +49,7 @@ static int def_use_sess_key = 0;
static int def_text_mode = 0;
static int def_unicode_mode = 0;
static int def_convert_crlf = 0;
static int def_ignore_cipher_failure = 0;
struct digest_info
{
@@ -204,6 +205,7 @@ pgp_init(PGP_Context **ctx_p)
ctx->unicode_mode = def_unicode_mode;
ctx->convert_crlf = def_convert_crlf;
ctx->text_mode = def_text_mode;
ctx->ignore_cipher_failure = def_ignore_cipher_failure;
*ctx_p = ctx;
return 0;
@@ -349,6 +351,13 @@ pgp_set_unicode_mode(PGP_Context *ctx, int mode)
return 0;
}
int
pgp_set_ignore_cipher_failure(PGP_Context *ctx, int ignore)
{
ctx->ignore_cipher_failure = ignore ? 1 : 0;
return 0;
}
int
pgp_set_symkey(PGP_Context *ctx, const uint8 *key, int len)
{

View File

@@ -150,6 +150,9 @@ struct PGP_Context
int convert_crlf;
int unicode_mode;
/* DANGEROUS recovery aid for CVE-2026-14663. Applies only to decryption. */
int ignore_cipher_failure;
/*
* internal variables
*/
@@ -258,6 +261,7 @@ int pgp_set_compress_level(PGP_Context *ctx, int level);
int pgp_set_text_mode(PGP_Context *ctx, int mode);
int pgp_set_unicode_mode(PGP_Context *ctx, int mode);
int pgp_get_unicode_mode(PGP_Context *ctx);
int pgp_set_ignore_cipher_failure(PGP_Context *ctx, int ignore);
int pgp_set_symkey(PGP_Context *ctx, const uint8 *key, int len);
int pgp_set_pubkey(PGP_Context *ctx, MBuf *keypkt,
@@ -278,7 +282,8 @@ int pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int key_len);
typedef struct PGP_CFB PGP_CFB;
int pgp_cfb_create(PGP_CFB **ctx_p, int algo,
const uint8 *key, int key_len, int resync, uint8 *iv);
const uint8 *key, int key_len, int resync, uint8 *iv,
int ignore_decrypt_cipher_failure);
void pgp_cfb_free(PGP_CFB *ctx);
int pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst);
int pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst);

View File

@@ -328,3 +328,29 @@ UCAAw2JRIISttRHMfDpDuZJpvYo=
=AZ9M
-----END PGP MESSAGE-----
'), 'key', 'debug=1');
-- Check ignore-cipher-failure. This message isn't actually encrypted; it was
-- created with cipher-algo=bf using an OpenSSL that didn't actually support
-- Blowfish. After the fix for CVE-2026-14663, we no longer create these broken
-- ciphertexts, but we allow users to return to the previous behavior during
-- decryption so that the bad wrapper can be stripped.
--
-- Note that if Blowfish is supported by the linked OpenSSL, both decryptions
-- will fail.
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
ww0EBAMC8wIKbtvzJtxi0jABUleCwFJWGCkYKcsNdABqdtXaU2VjcmV0LtMUlnPH3A2QBmZrcucm
1GPb/s2Bkdg=
=6aqD
-----END PGP MESSAGE-----
'), 'wrong key');
select pgp_sym_decrypt(dearmor('
-----BEGIN PGP MESSAGE-----
ww0EBAMC8wIKbtvzJtxi0jABUleCwFJWGCkYKcsNdABqdtXaU2VjcmV0LtMUlnPH3A2QBmZrcucm
1GPb/s2Bkdg=
=6aqD
-----END PGP MESSAGE-----
'), 'wrong key', 'ignore-cipher-failure=1');

View File

@@ -601,6 +601,21 @@ blH2nKZC9d6fi4YzSYMepZpMOFR65M80MCMiDUGnZBB8sEADu2/iVtqDUeG8mAA=
-----END PGP MESSAGE-----
');
-- CVE-2026-14663. This message was created with cipher-algo=bf using an OpenSSL
-- that didn't actually support Blowfish.
insert into encdata (id, data) values (6, '
-----BEGIN PGP MESSAGE-----
wcBOA9k2z2S7c/RmEAP8DYbU6AeEo6riMMdnf2G62BM9gC0Z32ODydewy3Ki8AnSzpwBDAHuDMcr
P6RJDWvBOVOwgxHEwR7ZHMoFRDJEXdo6rQ9dQpDtbasMLyi6Lm1q+PbEefVd9WkU7fvFAFQx8k3t
lxrlWg/byoNplc7/hFxIFO8bN+FIlLgilAdApNcD/3Mg2/nd7pczovsYoryf9ib04kQ+SVWs3iNE
StoyEXT+oaT8u1vAxiY7fzPpQX1pnlHBUXn+v1J6LQL5Bwi5CTqOyDSyaFfgU0gQwTReFjS6L4Fs
Cv+2cFwbJBGIzr1aI4DLbzSelkmVm4hbOVeET4DJVlUVhhIyy6ZfoXiTEG6s0jMB2JdRGIl0EUQR
RMsQdABqdt5jU2VjcmV0IG1zZ9MUIIP4SPiU2pM/nF/A1hrltMhn/ZI=
=Mkdj
-----END PGP MESSAGE-----
');
-- successful decrypt
select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
from keytbl, encdata where keytbl.id=1 and encdata.id=1;
@@ -608,6 +623,9 @@ from keytbl, encdata where keytbl.id=1 and encdata.id=1;
select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
from keytbl, encdata where keytbl.id=2 and encdata.id=2;
select pgp_pub_decrypt(dearmor(data), dearmor(seckey), '', 'ignore-cipher-failure=1')
from keytbl, encdata where keytbl.id=2 and encdata.id=2;
select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
from keytbl, encdata where keytbl.id=3 and encdata.id=3;
@@ -645,3 +663,12 @@ from keytbl, encdata where keytbl.id=5 and encdata.id=1;
-- test for a short read from prefix_init
select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
from keytbl, encdata where keytbl.id=6 and encdata.id=5;
-- Check that ignore-cipher-failure can strip faulty encryption if OpenSSL
-- doesn't support the cipher. (The decryption will correctly fail both times if
-- OpenSSL does support it.)
select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
from keytbl, encdata where keytbl.id=1 and encdata.id=6;
select pgp_pub_decrypt(dearmor(data), dearmor(seckey), '', 'ignore-cipher-failure=1')
from keytbl, encdata where keytbl.id=1 and encdata.id=6;

View File

@@ -966,6 +966,38 @@ Applies to: pgp_sym_encrypt
Values: 0, 1
Default: 0
Applies to: pgp_sym_encrypt, pgp_pub_encrypt
</literallayout>
</sect4>
<sect4 id="pgcrypto-pgp-enc-funcs-opts-ignore-cipher-failure">
<title>ignore-cipher-failure</title>
<para>
Dangerous! Instructs pgcrypto to use an incorrect decryption algorithm
matching the historical behavior prior to the fix for CVE-2026-14663, by
completely ignoring failures from the OpenSSL cipher in use. This is
intended only for users who need to recover incorrectly-encrypted messages
created when the <literal>cipher-algo</literal> was unavailable under the
OpenSSL configuration in use. Such faulty messages do not require the
correct decryption key when <literal>ignore-cipher-failure</literal> is
enabled, so there is no guarantee that the decrypted plaintext actually
originated from a holder of the key.
</para>
<para>
Contrast the case of a message which was correctly encrypted, but the cipher
that produced it is unavailable under the current <productname>OpenSSL</productname>
configuration. Recovering such plaintext via <filename>pgcrypto</filename>
requires making the actual cipher available to OpenSSL by, for example,
enabling the appropriate provider. <literal>ignore-cipher-failure</literal>
is not necessary or helpful for that scenario. If <quote>decryption</quote>
of a correctly encrypted message with this option happens to pass PGP
integrity checks, that result is coincidental and does not make the
recovered plaintext trustworthy.
</para>
<literallayout>
Values: 0, 1
Default: 0
Applies to: pgp_sym_decrypt, pgp_pub_decrypt
</literallayout>
</sect4>
</sect3>