* grub-core/disk/AFSplitter.c: Remove variable length arrays.

* grub-core/disk/cryptodisk.c: Likewise.
	* grub-core/disk/geli.c: Likewise.
	* grub-core/disk/luks.c: Likewise.
This commit is contained in:
Vladimir Serbinenko 2013-11-12 02:48:02 +01:00
parent 15decd26cc
commit c35fcdc0b7
5 changed files with 61 additions and 23 deletions

View file

@ -1,3 +1,10 @@
2013-11-12 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/disk/AFSplitter.c: Remove variable length arrays.
* grub-core/disk/cryptodisk.c: Likewise.
* grub-core/disk/geli.c: Likewise.
* grub-core/disk/luks.c: Likewise.
2013-11-12 Vladimir Serbinenko <phcoder@gmail.com> 2013-11-12 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/tests/legacy_password_test.c: New test. * grub-core/tests/legacy_password_test.c: New test.

View file

@ -37,8 +37,8 @@ diffuse (const gcry_md_spec_t * hash, grub_uint8_t * src,
grub_size_t fullblocks = size / hash->mdlen; grub_size_t fullblocks = size / hash->mdlen;
int padding = size % hash->mdlen; int padding = size % hash->mdlen;
grub_uint8_t final[hash->mdlen]; grub_uint8_t final[GRUB_CRYPTO_MAX_MDLEN];
grub_uint8_t temp[sizeof (IV) + hash->mdlen]; grub_uint8_t temp[sizeof (IV) + GRUB_CRYPTO_MAX_MDLEN];
/* hash block the whole data set with different IVs to produce /* hash block the whole data set with different IVs to produce
* more than just a single data block * more than just a single data block
@ -76,6 +76,9 @@ AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, grub_uint8_t * dst,
if (bufblock == NULL) if (bufblock == NULL)
return GPG_ERR_OUT_OF_MEMORY; return GPG_ERR_OUT_OF_MEMORY;
if (hash->mdlen > GRUB_CRYPTO_MAX_MDLEN)
return GPG_ERR_INV_ARG;
grub_memset (bufblock, 0, blocksize); grub_memset (bufblock, 0, blocksize);
for (i = 0; i < blocknumbers - 1; i++) for (i = 0; i < blocknumbers - 1; i++)
{ {

View file

@ -109,7 +109,9 @@ grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher,
void *iv) void *iv)
{ {
grub_uint8_t *inptr, *outptr, *end; grub_uint8_t *inptr, *outptr, *end;
grub_uint8_t ivt[cipher->cipher->blocksize]; 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) if (!cipher->cipher->decrypt)
return GPG_ERR_NOT_SUPPORTED; return GPG_ERR_NOT_SUPPORTED;
if (size % cipher->cipher->blocksize != 0) if (size % cipher->cipher->blocksize != 0)
@ -132,7 +134,9 @@ grub_crypto_pcbc_encrypt (grub_crypto_cipher_handle_t cipher,
void *iv) void *iv)
{ {
grub_uint8_t *inptr, *outptr, *end; grub_uint8_t *inptr, *outptr, *end;
grub_uint8_t ivt[cipher->cipher->blocksize]; 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) if (!cipher->cipher->decrypt)
return GPG_ERR_NOT_SUPPORTED; return GPG_ERR_NOT_SUPPORTED;
if (size % cipher->cipher->blocksize != 0) if (size % cipher->cipher->blocksize != 0)
@ -218,6 +222,9 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
grub_size_t i; grub_size_t i;
gcry_err_code_t err; gcry_err_code_t err;
if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
return GPG_ERR_INV_ARG;
/* The only mode without IV. */ /* The only mode without IV. */
if (dev->mode == GRUB_CRYPTODISK_MODE_ECB && !dev->rekey) if (dev->mode == GRUB_CRYPTODISK_MODE_ECB && !dev->rekey)
return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len) return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
@ -228,7 +235,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
grub_size_t sz = ((dev->cipher->cipher->blocksize grub_size_t sz = ((dev->cipher->cipher->blocksize
+ sizeof (grub_uint32_t) - 1) + sizeof (grub_uint32_t) - 1)
/ sizeof (grub_uint32_t)); / sizeof (grub_uint32_t));
grub_uint32_t iv[sz]; grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4];
if (dev->rekey) if (dev->rekey)
{ {
@ -242,7 +249,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
} }
} }
grub_memset (iv, 0, sz * sizeof (iv[0])); grub_memset (iv, 0, sizeof (iv));
switch (dev->mode_iv) switch (dev->mode_iv)
{ {
case GRUB_CRYPTODISK_MODE_IV_NULL: case GRUB_CRYPTODISK_MODE_IV_NULL:
@ -250,9 +257,11 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH: case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH:
{ {
grub_uint64_t tmp; grub_uint64_t tmp;
GRUB_PROPERLY_ALIGNED_ARRAY (ctx, dev->iv_hash->contextsize); void *ctx;
grub_memset (ctx, 0, sizeof (ctx)); ctx = grub_zalloc (dev->iv_hash->contextsize);
if (!ctx)
return GPG_ERR_OUT_OF_MEMORY;
tmp = grub_cpu_to_le64 (sector << dev->log_sector_size); tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
dev->iv_hash->init (ctx); dev->iv_hash->init (ctx);
@ -261,6 +270,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
dev->iv_hash->final (ctx); dev->iv_hash->final (ctx);
grub_memcpy (iv, dev->iv_hash->read (ctx), sizeof (iv)); grub_memcpy (iv, dev->iv_hash->read (ctx), sizeof (iv));
grub_free (ctx);
} }
break; break;
case GRUB_CRYPTODISK_MODE_IV_PLAIN64: case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
@ -407,7 +417,9 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t ke
if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_ESSIV) if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_ESSIV)
{ {
grub_size_t essiv_keysize = dev->essiv_hash->mdlen; grub_size_t essiv_keysize = dev->essiv_hash->mdlen;
grub_uint8_t hashed_key[essiv_keysize]; grub_uint8_t hashed_key[GRUB_CRYPTO_MAX_MDLEN];
if (essiv_keysize > GRUB_CRYPTO_MAX_MDLEN)
return GPG_ERR_INV_ARG;
grub_crypto_hash (dev->essiv_hash, hashed_key, key, keysize); grub_crypto_hash (dev->essiv_hash, hashed_key, key, keysize);
err = grub_crypto_cipher_set_key (dev->essiv_cipher, err = grub_crypto_cipher_set_key (dev->essiv_cipher,

View file

@ -146,7 +146,10 @@ geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno)
grub_uint64_t zone; grub_uint64_t zone;
} __attribute__ ((packed)) tohash } __attribute__ ((packed)) tohash
= { {'e', 'k', 'e', 'y'}, grub_cpu_to_le64 (zoneno) }; = { {'e', 'k', 'e', 'y'}, grub_cpu_to_le64 (zoneno) };
GRUB_PROPERLY_ALIGNED_ARRAY (key, dev->hash->mdlen); GRUB_PROPERLY_ALIGNED_ARRAY (key, GRUB_CRYPTO_MAX_MDLEN);
if (dev->hash->mdlen > GRUB_CRYPTO_MAX_MDLEN)
return GPG_ERR_INV_ARG;
grub_dprintf ("geli", "rekeying %" PRIuGRUB_UINT64_T " keysize=%d\n", grub_dprintf ("geli", "rekeying %" PRIuGRUB_UINT64_T " keysize=%d\n",
zoneno, dev->rekey_derived_size); zoneno, dev->rekey_derived_size);
@ -163,11 +166,13 @@ static inline gcry_err_code_t
make_uuid (const struct grub_geli_phdr *header, make_uuid (const struct grub_geli_phdr *header,
char *uuid) char *uuid)
{ {
grub_uint8_t uuidbin[GRUB_MD_SHA256->mdlen]; grub_uint8_t uuidbin[GRUB_CRYPTODISK_MAX_UUID_LENGTH];
gcry_err_code_t err; gcry_err_code_t err;
grub_uint8_t *iptr; grub_uint8_t *iptr;
char *optr; char *optr;
if (2 * GRUB_MD_SHA256->mdlen + 1 > GRUB_CRYPTODISK_MAX_UUID_LENGTH)
return GPG_ERR_TOO_LARGE;
err = grub_crypto_hmac_buffer (GRUB_MD_SHA256, err = grub_crypto_hmac_buffer (GRUB_MD_SHA256,
header->salt, sizeof (header->salt), header->salt, sizeof (header->salt),
"uuid", sizeof ("uuid") - 1, uuidbin); "uuid", sizeof ("uuid") - 1, uuidbin);
@ -175,7 +180,7 @@ make_uuid (const struct grub_geli_phdr *header,
return err; return err;
optr = uuid; optr = uuid;
for (iptr = uuidbin; iptr < &uuidbin[ARRAY_SIZE (uuidbin)]; iptr++) for (iptr = uuidbin; iptr < &uuidbin[GRUB_MD_SHA256->mdlen]; iptr++)
{ {
grub_snprintf (optr, 3, "%02x", *iptr); grub_snprintf (optr, 3, "%02x", *iptr);
optr += 2; optr += 2;
@ -242,10 +247,13 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
const struct gcry_cipher_spec *ciph; const struct gcry_cipher_spec *ciph;
const char *ciphername = NULL; const char *ciphername = NULL;
gcry_err_code_t gcry_err; gcry_err_code_t gcry_err;
char uuid[GRUB_MD_SHA256->mdlen * 2 + 1]; char uuid[GRUB_CRYPTODISK_MAX_UUID_LENGTH];
grub_disk_addr_t sector; grub_disk_addr_t sector;
grub_err_t err; grub_err_t err;
if (2 * GRUB_MD_SHA256->mdlen + 1 > GRUB_CRYPTODISK_MAX_UUID_LENGTH)
return NULL;
sector = grub_disk_get_size (disk); sector = grub_disk_get_size (disk);
if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0) if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
return NULL; return NULL;
@ -379,10 +387,10 @@ static grub_err_t
recover_key (grub_disk_t source, grub_cryptodisk_t dev) recover_key (grub_disk_t source, grub_cryptodisk_t dev)
{ {
grub_size_t keysize; grub_size_t keysize;
grub_uint8_t digest[dev->hash->mdlen]; grub_uint8_t digest[GRUB_CRYPTO_MAX_MDLEN];
grub_uint8_t geomkey[dev->hash->mdlen]; grub_uint8_t geomkey[GRUB_CRYPTO_MAX_MDLEN];
grub_uint8_t verify_key[dev->hash->mdlen]; grub_uint8_t verify_key[GRUB_CRYPTO_MAX_MDLEN];
grub_uint8_t zero[dev->cipher->cipher->blocksize]; grub_uint8_t zero[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
char passphrase[MAX_PASSPHRASE] = ""; char passphrase[MAX_PASSPHRASE] = "";
unsigned i; unsigned i;
gcry_err_code_t gcry_err; gcry_err_code_t gcry_err;
@ -391,6 +399,12 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
grub_disk_addr_t sector; grub_disk_addr_t sector;
grub_err_t err; grub_err_t err;
if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
return grub_error (GRUB_ERR_BUG, "cipher block is too long");
if (dev->hash->mdlen > GRUB_CRYPTO_MAX_MDLEN)
return grub_error (GRUB_ERR_BUG, "mdlen is too long");
sector = grub_disk_get_size (source); sector = grub_disk_get_size (source);
if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0) if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
return grub_error (GRUB_ERR_BUG, "not a geli"); return grub_error (GRUB_ERR_BUG, "not a geli");
@ -452,12 +466,12 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
} }
gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey, gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey,
sizeof (geomkey), "\1", 1, digest); dev->hash->mdlen, "\1", 1, digest);
if (gcry_err) if (gcry_err)
return grub_crypto_gcry_error (gcry_err); return grub_crypto_gcry_error (gcry_err);
gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey, gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey,
sizeof (geomkey), "\0", 1, verify_key); dev->hash->mdlen, "\0", 1, verify_key);
if (gcry_err) if (gcry_err)
return grub_crypto_gcry_error (gcry_err); return grub_crypto_gcry_error (gcry_err);
@ -467,7 +481,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
for (i = 0; i < ARRAY_SIZE (header.keys); i++) for (i = 0; i < ARRAY_SIZE (header.keys); i++)
{ {
struct grub_geli_key candidate_key; struct grub_geli_key candidate_key;
grub_uint8_t key_hmac[dev->hash->mdlen]; grub_uint8_t key_hmac[GRUB_CRYPTO_MAX_MDLEN];
/* Check if keyslot is enabled. */ /* Check if keyslot is enabled. */
if (! (header.keys_used & (1 << i))) if (! (header.keys_used & (1 << i)))
@ -488,7 +502,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
return grub_crypto_gcry_error (gcry_err); return grub_crypto_gcry_error (gcry_err);
gcry_err = grub_crypto_hmac_buffer (dev->hash, verify_key, gcry_err = grub_crypto_hmac_buffer (dev->hash, verify_key,
sizeof (verify_key), dev->hash->mdlen,
&candidate_key, &candidate_key,
(sizeof (candidate_key) (sizeof (candidate_key)
- sizeof (candidate_key.hmac)), - sizeof (candidate_key.hmac)),

View file

@ -316,6 +316,8 @@ luks_recover_key (grub_disk_t source,
grub_puts_ (N_("Attempting to decrypt master key...")); grub_puts_ (N_("Attempting to decrypt master key..."));
keysize = grub_be_to_cpu32 (header.keyBytes); keysize = grub_be_to_cpu32 (header.keyBytes);
if (keysize > GRUB_CRYPTODISK_MAX_KEYLEN)
return grub_error (GRUB_ERR_BAD_FS, "key is too long");
for (i = 0; i < ARRAY_SIZE (header.keyblock); i++) for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
if (grub_be_to_cpu32 (header.keyblock[i].active) == LUKS_KEY_ENABLED if (grub_be_to_cpu32 (header.keyblock[i].active) == LUKS_KEY_ENABLED
@ -344,8 +346,8 @@ luks_recover_key (grub_disk_t source,
for (i = 0; i < ARRAY_SIZE (header.keyblock); i++) for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
{ {
gcry_err_code_t gcry_err; gcry_err_code_t gcry_err;
grub_uint8_t candidate_key[keysize]; grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
grub_uint8_t digest[keysize]; grub_uint8_t digest[GRUB_CRYPTODISK_MAX_KEYLEN];
/* Check if keyslot is enabled. */ /* Check if keyslot is enabled. */
if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED) if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED)