Commit 18cc8bd7 authored by Geoff Simmons's avatar Geoff Simmons

Improvements in padding and unpadding:

- Fix an off-by-one error in ISO7816 unpadding.
- Unpadding errors are not assertion failures, handle the error.
- Check all the requirements of the padding scheme when unpadding.
parent d09c1897
Pipeline #192 skipped
......@@ -464,6 +464,12 @@ The failure conditions of ``.decrypt()`` are similar to those for
* Missing ``iv`` or ``ctr`` parameters for modes of operation that
require them.
* An error in the padding bytes, if padding is specified. For example,
if the number of padding bytes added is longer than the cipher's
block length (for ``PKCS7`` and ``X923`` padding), or if a value
such as 0x80 or 0x00 is not found where the padding scheme requires
it.
* Failure of the libgcrypt library.
If the method fails, a message is logged using the ``VCL_Error`` tag,
......
......@@ -95,30 +95,43 @@ static pad_f * const padf[] = {
[X923] = pad_x923,
};
typedef int unpadlen_f(void *plaintext, int cipherlen, size_t blocklen);
typedef ssize_t unpadlen_f(void *plaintext, int cipherlen, size_t blocklen);
static int __match_proto__(unpadlen_f)
static ssize_t __match_proto__(unpadlen_f)
unpadlen_pkcs7(void *plaintext, int cipherlen, size_t blocklen)
{
assert(((unsigned char *)plaintext)[cipherlen-1] <= blocklen);
assert(((unsigned char *)plaintext)[cipherlen-1] <= cipherlen);
return cipherlen - ((unsigned char *)plaintext)[cipherlen-1];
uint8_t padlen = ((uint8_t *)plaintext)[cipherlen-1];
if (padlen > blocklen || padlen > cipherlen)
return -1;
for (int i = cipherlen - 2; i >= cipherlen - padlen; i--)
if (padlen != ((uint8_t *)plaintext)[i])
return -1;
return cipherlen - padlen;
}
static int __match_proto__(unpadlen_f)
static ssize_t __match_proto__(unpadlen_f)
unpadlen_iso7816(void *plaintext, int cipherlen, size_t blocklen)
{
(void) blocklen;
int i = cipherlen - 1;
while (i > 0 && ((unsigned char *)plaintext)[i] != 0x80)
assert(0 == ((unsigned char *)plaintext)[i--]);
return i - 1;
while (i >= 0 && ((uint8_t *)plaintext)[i] != 0x80)
if (0 != ((uint8_t *)plaintext)[i--])
return -1;
return i;
}
static int __match_proto__(unpadlen_f)
static ssize_t __match_proto__(unpadlen_f)
unpadlen_x923(void *plaintext, int cipherlen, size_t blocklen)
{
return unpadlen_pkcs7(plaintext, cipherlen, blocklen);
uint8_t padlen = ((uint8_t *)plaintext)[cipherlen-1];
if (padlen > blocklen || padlen > cipherlen)
return -1;
for (int i = cipherlen - 2; i >= cipherlen - padlen; i--)
if (0 != ((uint8_t *)plaintext)[i])
return -1;
return cipherlen - padlen;
}
static unpadlen_f * const unpadlenf[] = {
......
This diff is collapsed.
......@@ -526,6 +526,13 @@ vmod_symmetric_decrypt(VRT_CTX, struct vmod_gcrypt_symmetric *symmetric,
(unpadlenf[symmetric->padding])(plaintext->priv,
ciphertext->len,
symmetric->blocklen);
if (plaintext->len < 0) {
VERR(ctx, "in %s.decrypt(): incorrect padding",
symmetric->vcl_name);
WS_Release(ctx->ws, 0);
WS_Reset(ctx->ws, snap);
return NULL;
}
}
WS_Release(ctx->ws, plaintext->len);
plaintext->free = NULL;
......
......@@ -413,6 +413,12 @@ The failure conditions of ``.decrypt()`` are similar to those for
* Missing ``iv`` or ``ctr`` parameters for modes of operation that
require them.
* An error in the padding bytes, if padding is specified. For example,
if the number of padding bytes added is longer than the cipher's
block length (for ``PKCS7`` and ``X923`` padding), or if a value
such as 0x80 or 0x00 is not found where the padding scheme requires
it.
* Failure of the libgcrypt library.
If the method fails, a message is logged using the ``VCL_Error`` tag,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment