mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
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. The padding algorithm is still the same. The OpenSSL padding implementation is stricter than the previous internal one: Bad padding during decryption is now an error, and encryption without padding now requires the input size to be a multiple of the block size, otherwise it is also an error. Previously, these cases silently proceeded, in spite of the documentation saying otherwise. Add some test cases about this, too. (The test cases are in rijndael.sql, but they apply to all encryption algorithms.) Reviewed-by: Jacob Champion <pchampion@vmware.com> Reviewed-by: Nathan Bossart <nathandbossart@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/ba94c26b-0c58-c97e-7a44-f44e08b4cca2%40enterprisedb.com
This commit is contained in:
@ -44,7 +44,6 @@ static const struct error_desc px_err_list[] = {
|
||||
{PXE_ERR_GENERIC, "Some PX error (not specified)"},
|
||||
{PXE_NO_HASH, "No such hash algorithm"},
|
||||
{PXE_NO_CIPHER, "No such cipher algorithm"},
|
||||
{PXE_NOTBLOCKSIZE, "Data not a multiple of block size"},
|
||||
{PXE_BAD_OPTION, "Unknown option"},
|
||||
{PXE_BAD_FORMAT, "Badly formatted type"},
|
||||
{PXE_KEY_TOO_BIG, "Key was too big"},
|
||||
@ -221,129 +220,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
|
||||
|
Reference in New Issue
Block a user