From 86e65690105e3a4a7e38276f48bd97c0e095beec Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Mon, 14 Feb 2022 10:32:48 +0100 Subject: [PATCH v2] pgcrypto: Remove internal padding implementation Use the padding provided by OpenSSL instead of doing it ourselves. The internal implementation was once applicable to the non-OpenSSL code paths, but those have since been removed. Discussion: https://www.postgresql.org/message-id/b1a62889-bb45-e5e0-d138-7a370a0a334f@enterprisedb.com --- contrib/pgcrypto/openssl.c | 22 ++++--- contrib/pgcrypto/pgp-cfb.c | 4 +- contrib/pgcrypto/px.c | 119 +------------------------------------ contrib/pgcrypto/px.h | 12 ++-- 4 files changed, 25 insertions(+), 132 deletions(-) diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c index e236b0d79c..68fd61b716 100644 --- a/contrib/pgcrypto/openssl.c +++ b/contrib/pgcrypto/openssl.c @@ -369,17 +369,17 @@ gen_ossl_free(PX_Cipher *c) } static int -gen_ossl_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, - uint8 *res) +gen_ossl_decrypt(PX_Cipher *c, int padding, const uint8 *data, unsigned dlen, + uint8 *res, unsigned *rlen) { OSSLCipher *od = c->ptr; - int outlen; + int outlen, outlen2; if (!od->init) { if (!EVP_DecryptInit_ex(od->evp_ctx, od->evp_ciph, NULL, NULL, NULL)) return PXE_CIPHER_INIT; - if (!EVP_CIPHER_CTX_set_padding(od->evp_ctx, 0)) + if (!EVP_CIPHER_CTX_set_padding(od->evp_ctx, padding)) return PXE_CIPHER_INIT; if (!EVP_CIPHER_CTX_set_key_length(od->evp_ctx, od->klen)) return PXE_CIPHER_INIT; @@ -390,22 +390,25 @@ gen_ossl_decrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, if (!EVP_DecryptUpdate(od->evp_ctx, res, &outlen, data, dlen)) return PXE_DECRYPT_FAILED; + if (!EVP_DecryptFinal_ex(od->evp_ctx, res + outlen, &outlen2)) + return PXE_DECRYPT_FAILED; + *rlen = outlen + outlen2; return 0; } static int -gen_ossl_encrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, - uint8 *res) +gen_ossl_encrypt(PX_Cipher *c, int padding, const uint8 *data, unsigned dlen, + uint8 *res, unsigned *rlen) { OSSLCipher *od = c->ptr; - int outlen; + int outlen, outlen2; if (!od->init) { if (!EVP_EncryptInit_ex(od->evp_ctx, od->evp_ciph, NULL, NULL, NULL)) return PXE_CIPHER_INIT; - if (!EVP_CIPHER_CTX_set_padding(od->evp_ctx, 0)) + if (!EVP_CIPHER_CTX_set_padding(od->evp_ctx, padding)) return PXE_CIPHER_INIT; if (!EVP_CIPHER_CTX_set_key_length(od->evp_ctx, od->klen)) return PXE_CIPHER_INIT; @@ -416,6 +419,9 @@ gen_ossl_encrypt(PX_Cipher *c, const uint8 *data, unsigned dlen, if (!EVP_EncryptUpdate(od->evp_ctx, res, &outlen, data, dlen)) return PXE_ENCRYPT_FAILED; + if (!EVP_EncryptFinal_ex(od->evp_ctx, res + outlen, &outlen2)) + return PXE_ENCRYPT_FAILED; + *rlen = outlen + outlen2; return 0; } diff --git a/contrib/pgcrypto/pgp-cfb.c b/contrib/pgcrypto/pgp-cfb.c index dafa562daa..de41e825b0 100644 --- a/contrib/pgcrypto/pgp-cfb.c +++ b/contrib/pgcrypto/pgp-cfb.c @@ -220,7 +220,9 @@ cfb_process(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst, while (len > 0) { - px_cipher_encrypt(ctx->ciph, ctx->fr, ctx->block_size, ctx->fre); + unsigned rlen; + + px_cipher_encrypt(ctx->ciph, 0, ctx->fr, ctx->block_size, ctx->fre, &rlen); if (ctx->block_no < 5) ctx->block_no++; diff --git a/contrib/pgcrypto/px.c b/contrib/pgcrypto/px.c index 4205e9c3ef..5ccab44122 100644 --- a/contrib/pgcrypto/px.c +++ b/contrib/pgcrypto/px.c @@ -223,129 +223,14 @@ static int combo_encrypt(PX_Combo *cx, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen) { - int err = 0; - uint8 *bbuf; - unsigned bs, - bpos, - i, - pad; - - PX_Cipher *c = cx->cipher; - - bbuf = NULL; - bs = px_cipher_block_size(c); - - /* encrypt */ - if (bs > 1) - { - bbuf = palloc(bs * 4); - bpos = dlen % bs; - *rlen = dlen - bpos; - memcpy(bbuf, data + *rlen, bpos); - - /* encrypt full-block data */ - if (*rlen) - { - err = px_cipher_encrypt(c, data, *rlen, res); - if (err) - goto out; - } - - /* bbuf has now bpos bytes of stuff */ - if (cx->padding) - { - pad = bs - (bpos % bs); - for (i = 0; i < pad; i++) - bbuf[bpos++] = pad; - } - else if (bpos % bs) - { - /* ERROR? */ - pad = bs - (bpos % bs); - for (i = 0; i < pad; i++) - bbuf[bpos++] = 0; - } - - /* encrypt the rest - pad */ - if (bpos) - { - err = px_cipher_encrypt(c, bbuf, bpos, res + *rlen); - *rlen += bpos; - } - } - else - { - /* stream cipher/mode - no pad needed */ - err = px_cipher_encrypt(c, data, dlen, res); - if (err) - goto out; - *rlen = dlen; - } -out: - if (bbuf) - pfree(bbuf); - - return err; + return px_cipher_encrypt(cx->cipher, cx->padding, data, dlen, res, rlen); } static int combo_decrypt(PX_Combo *cx, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen) { - int err = 0; - unsigned bs, - i, - pad; - unsigned pad_ok; - - PX_Cipher *c = cx->cipher; - - /* decide whether zero-length input is allowed */ - if (dlen == 0) - { - /* with padding, empty ciphertext is not allowed */ - if (cx->padding) - return PXE_DECRYPT_FAILED; - - /* without padding, report empty result */ - *rlen = 0; - return 0; - } - - bs = px_cipher_block_size(c); - if (bs > 1 && (dlen % bs) != 0) - goto block_error; - - /* decrypt */ - *rlen = dlen; - err = px_cipher_decrypt(c, data, dlen, res); - if (err) - return err; - - /* unpad */ - if (bs > 1 && cx->padding) - { - pad = res[*rlen - 1]; - pad_ok = 0; - if (pad > 0 && pad <= bs && pad <= *rlen) - { - pad_ok = 1; - for (i = *rlen - pad; i < *rlen; i++) - if (res[i] != pad) - { - pad_ok = 0; - break; - } - } - - if (pad_ok) - *rlen -= pad; - } - - return 0; - -block_error: - return PXE_NOTBLOCKSIZE; + return px_cipher_decrypt(cx->cipher, cx->padding, data, dlen, res, rlen); } static void diff --git a/contrib/pgcrypto/px.h b/contrib/pgcrypto/px.h index 17d6f22498..9348d6c997 100644 --- a/contrib/pgcrypto/px.h +++ b/contrib/pgcrypto/px.h @@ -143,8 +143,8 @@ struct px_cipher unsigned (*iv_size) (PX_Cipher *c); int (*init) (PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv); - int (*encrypt) (PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res); - int (*decrypt) (PX_Cipher *c, const uint8 *data, unsigned dlen, uint8 *res); + int (*encrypt) (PX_Cipher *c, int padding, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen); + int (*decrypt) (PX_Cipher *c, int padding, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen); void (*free) (PX_Cipher *c); /* private */ void *ptr; @@ -207,10 +207,10 @@ void px_debug(const char *fmt,...) pg_attribute_printf(1, 2); #define px_cipher_block_size(c) (c)->block_size(c) #define px_cipher_iv_size(c) (c)->iv_size(c) #define px_cipher_init(c, k, klen, iv) (c)->init(c, k, klen, iv) -#define px_cipher_encrypt(c, data, dlen, res) \ - (c)->encrypt(c, data, dlen, res) -#define px_cipher_decrypt(c, data, dlen, res) \ - (c)->decrypt(c, data, dlen, res) +#define px_cipher_encrypt(c, padding, data, dlen, res, rlen) \ + (c)->encrypt(c, padding, data, dlen, res, rlen) +#define px_cipher_decrypt(c, padding, data, dlen, res, rlen) \ + (c)->decrypt(c, padding, data, dlen, res, rlen) #define px_cipher_free(c) (c)->free(c) -- 2.35.1