crypto: restrict cipher block size to power of 2.

All current ciphers have blocks which are power of 2 and it's
unlikely to change. Other block length would be tricky to handle anyway.
This restriction allows avoiding extra divisions.
This commit is contained in:
Vladimir Serbinenko 2015-02-26 22:04:40 +01:00
parent 7213c1e028
commit 94f701a826
2 changed files with 48 additions and 30 deletions

View file

@ -110,20 +110,23 @@ grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher,
{ {
grub_uint8_t *inptr, *outptr, *end; grub_uint8_t *inptr, *outptr, *end;
grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE]; grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
if (cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE) grub_size_t blocksize;
return GPG_ERR_INV_ARG;
if (!cipher->cipher->decrypt) if (!cipher->cipher->decrypt)
return GPG_ERR_NOT_SUPPORTED; return GPG_ERR_NOT_SUPPORTED;
if (size % cipher->cipher->blocksize != 0) blocksize = cipher->cipher->blocksize;
if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
|| ((size & (blocksize - 1)) != 0))
return GPG_ERR_INV_ARG;
if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
return GPG_ERR_INV_ARG; return GPG_ERR_INV_ARG;
end = (grub_uint8_t *) in + size; end = (grub_uint8_t *) in + size;
for (inptr = in, outptr = out; inptr < end; for (inptr = in, outptr = out; inptr < end;
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) inptr += blocksize, outptr += blocksize)
{ {
grub_memcpy (ivt, inptr, cipher->cipher->blocksize); grub_memcpy (ivt, inptr, blocksize);
cipher->cipher->decrypt (cipher->ctx, outptr, inptr); cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize); grub_crypto_xor (outptr, outptr, iv, blocksize);
grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize); grub_crypto_xor (iv, ivt, outptr, blocksize);
} }
return GPG_ERR_NO_ERROR; return GPG_ERR_NO_ERROR;
} }
@ -135,20 +138,23 @@ grub_crypto_pcbc_encrypt (grub_crypto_cipher_handle_t cipher,
{ {
grub_uint8_t *inptr, *outptr, *end; grub_uint8_t *inptr, *outptr, *end;
grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE]; grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
if (cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE) grub_size_t blocksize;
return GPG_ERR_INV_ARG; if (!cipher->cipher->encrypt)
if (!cipher->cipher->decrypt)
return GPG_ERR_NOT_SUPPORTED; return GPG_ERR_NOT_SUPPORTED;
if (size % cipher->cipher->blocksize != 0) blocksize = cipher->cipher->blocksize;
if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
return GPG_ERR_INV_ARG;
if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
|| ((size & (blocksize - 1)) != 0))
return GPG_ERR_INV_ARG; return GPG_ERR_INV_ARG;
end = (grub_uint8_t *) in + size; end = (grub_uint8_t *) in + size;
for (inptr = in, outptr = out; inptr < end; for (inptr = in, outptr = out; inptr < end;
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) inptr += blocksize, outptr += blocksize)
{ {
grub_memcpy (ivt, inptr, cipher->cipher->blocksize); grub_memcpy (ivt, inptr, blocksize);
grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize); grub_crypto_xor (outptr, outptr, iv, blocksize);
cipher->cipher->encrypt (cipher->ctx, outptr, inptr); cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize); grub_crypto_xor (iv, ivt, outptr, blocksize);
} }
return GPG_ERR_NO_ERROR; return GPG_ERR_NO_ERROR;
} }

View file

@ -205,13 +205,16 @@ grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
{ {
const grub_uint8_t *inptr, *end; const grub_uint8_t *inptr, *end;
grub_uint8_t *outptr; grub_uint8_t *outptr;
grub_size_t blocksize;
if (!cipher->cipher->decrypt) if (!cipher->cipher->decrypt)
return GPG_ERR_NOT_SUPPORTED; return GPG_ERR_NOT_SUPPORTED;
if (size % cipher->cipher->blocksize != 0) blocksize = cipher->cipher->blocksize;
if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
|| ((size & (blocksize - 1)) != 0))
return GPG_ERR_INV_ARG; return GPG_ERR_INV_ARG;
end = (const grub_uint8_t *) in + size; end = (const grub_uint8_t *) in + size;
for (inptr = in, outptr = out; inptr < end; for (inptr = in, outptr = out; inptr < end;
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) inptr += blocksize, outptr += blocksize)
cipher->cipher->decrypt (cipher->ctx, outptr, inptr); cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
return GPG_ERR_NO_ERROR; return GPG_ERR_NO_ERROR;
} }
@ -222,13 +225,16 @@ grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher,
{ {
const grub_uint8_t *inptr, *end; const grub_uint8_t *inptr, *end;
grub_uint8_t *outptr; grub_uint8_t *outptr;
grub_size_t blocksize;
if (!cipher->cipher->encrypt) if (!cipher->cipher->encrypt)
return GPG_ERR_NOT_SUPPORTED; return GPG_ERR_NOT_SUPPORTED;
if (size % cipher->cipher->blocksize != 0) blocksize = cipher->cipher->blocksize;
if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
|| ((size & (blocksize - 1)) != 0))
return GPG_ERR_INV_ARG; return GPG_ERR_INV_ARG;
end = (const grub_uint8_t *) in + size; end = (const grub_uint8_t *) in + size;
for (inptr = in, outptr = out; inptr < end; for (inptr = in, outptr = out; inptr < end;
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) inptr += blocksize, outptr += blocksize)
cipher->cipher->encrypt (cipher->ctx, outptr, inptr); cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
return GPG_ERR_NO_ERROR; return GPG_ERR_NO_ERROR;
} }
@ -241,20 +247,23 @@ grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
grub_uint8_t *outptr; grub_uint8_t *outptr;
const grub_uint8_t *inptr, *end; const grub_uint8_t *inptr, *end;
void *iv; void *iv;
if (!cipher->cipher->decrypt) grub_size_t blocksize;
if (!cipher->cipher->encrypt)
return GPG_ERR_NOT_SUPPORTED; return GPG_ERR_NOT_SUPPORTED;
if (size % cipher->cipher->blocksize != 0) blocksize = cipher->cipher->blocksize;
if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
|| ((size & (blocksize - 1)) != 0))
return GPG_ERR_INV_ARG; return GPG_ERR_INV_ARG;
end = (const grub_uint8_t *) in + size; end = (const grub_uint8_t *) in + size;
iv = iv_in; iv = iv_in;
for (inptr = in, outptr = out; inptr < end; for (inptr = in, outptr = out; inptr < end;
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) inptr += blocksize, outptr += blocksize)
{ {
grub_crypto_xor (outptr, inptr, iv, cipher->cipher->blocksize); grub_crypto_xor (outptr, inptr, iv, blocksize);
cipher->cipher->encrypt (cipher->ctx, outptr, outptr); cipher->cipher->encrypt (cipher->ctx, outptr, outptr);
iv = outptr; iv = outptr;
} }
grub_memcpy (iv_in, iv, cipher->cipher->blocksize); grub_memcpy (iv_in, iv, blocksize);
return GPG_ERR_NO_ERROR; return GPG_ERR_NO_ERROR;
} }
@ -266,20 +275,23 @@ grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
const grub_uint8_t *inptr, *end; const grub_uint8_t *inptr, *end;
grub_uint8_t *outptr; grub_uint8_t *outptr;
grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE]; grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
grub_size_t blocksize;
if (!cipher->cipher->decrypt) if (!cipher->cipher->decrypt)
return GPG_ERR_NOT_SUPPORTED; return GPG_ERR_NOT_SUPPORTED;
if (size % cipher->cipher->blocksize != 0) blocksize = cipher->cipher->blocksize;
if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
|| ((size & (blocksize - 1)) != 0))
return GPG_ERR_INV_ARG; return GPG_ERR_INV_ARG;
if (cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE) if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
return GPG_ERR_INV_ARG; return GPG_ERR_INV_ARG;
end = (const grub_uint8_t *) in + size; end = (const grub_uint8_t *) in + size;
for (inptr = in, outptr = out; inptr < end; for (inptr = in, outptr = out; inptr < end;
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) inptr += blocksize, outptr += blocksize)
{ {
grub_memcpy (ivt, inptr, cipher->cipher->blocksize); grub_memcpy (ivt, inptr, blocksize);
cipher->cipher->decrypt (cipher->ctx, outptr, inptr); cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize); grub_crypto_xor (outptr, outptr, iv, blocksize);
grub_memcpy (iv, ivt, cipher->cipher->blocksize); grub_memcpy (iv, ivt, blocksize);
} }
return GPG_ERR_NO_ERROR; return GPG_ERR_NO_ERROR;
} }