]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
crypto: restrict cipher block size to power of 2.
authorVladimir Serbinenko <phcoder@gmail.com>
Thu, 26 Feb 2015 21:04:40 +0000 (22:04 +0100)
committerVladimir Serbinenko <phcoder@gmail.com>
Thu, 26 Feb 2015 21:04:40 +0000 (22:04 +0100)
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.

grub-core/disk/cryptodisk.c
grub-core/lib/crypto.c

index 376ab83268f907f286448c61551385e22aeb59df..82a3dcb637c34b7a6a61f7643ef6fd10d3ad6bcf 100644 (file)
@@ -110,20 +110,23 @@ grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher,
 {
   grub_uint8_t *inptr, *outptr, *end;
   grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
-  if (cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
-    return GPG_ERR_INV_ARG;
+  grub_size_t blocksize;
   if (!cipher->cipher->decrypt)
     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;
   end = (grub_uint8_t *) in + size;
   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);
-      grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
-      grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize);
+      grub_crypto_xor (outptr, outptr, iv, blocksize);
+      grub_crypto_xor (iv, ivt, outptr, blocksize);
     }
   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 ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
-  if (cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
-    return GPG_ERR_INV_ARG;
-  if (!cipher->cipher->decrypt)
+  grub_size_t blocksize;
+  if (!cipher->cipher->encrypt)
     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;
   end = (grub_uint8_t *) in + size;
   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_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
+      grub_memcpy (ivt, inptr, blocksize);
+      grub_crypto_xor (outptr, outptr, iv, blocksize);
       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;
 }
index 8e8426c4ab42a37b12de0423dd0eb9794d43761c..010e550d162bd45cf68bf9e47e78a5f2ff9af45a 100644 (file)
@@ -205,13 +205,16 @@ grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
 {
   const grub_uint8_t *inptr, *end;
   grub_uint8_t *outptr;
+  grub_size_t blocksize;
   if (!cipher->cipher->decrypt)
     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;
   end = (const grub_uint8_t *) in + size;
   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);
   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;
   grub_uint8_t *outptr;
+  grub_size_t blocksize;
   if (!cipher->cipher->encrypt)
     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;
   end = (const grub_uint8_t *) in + size;
   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);
   return GPG_ERR_NO_ERROR;
 }
@@ -241,20 +247,23 @@ grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
   grub_uint8_t *outptr;
   const grub_uint8_t *inptr, *end;
   void *iv;
-  if (!cipher->cipher->decrypt)
+  grub_size_t blocksize;
+  if (!cipher->cipher->encrypt)
     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;
   end = (const grub_uint8_t *) in + size;
   iv = iv_in;
   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);
       iv = outptr;
     }
-  grub_memcpy (iv_in, iv, cipher->cipher->blocksize);
+  grub_memcpy (iv_in, iv, blocksize);
   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;
   grub_uint8_t *outptr;
   grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
+  grub_size_t blocksize;
   if (!cipher->cipher->decrypt)
     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 (cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
+  if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
     return GPG_ERR_INV_ARG;
   end = (const grub_uint8_t *) in + size;
   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);
-      grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
-      grub_memcpy (iv, ivt, cipher->cipher->blocksize);
+      grub_crypto_xor (outptr, outptr, iv, blocksize);
+      grub_memcpy (iv, ivt, blocksize);
     }
   return GPG_ERR_NO_ERROR;
 }