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:
parent
7213c1e028
commit
94f701a826
2 changed files with 48 additions and 30 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue