luks.c 14.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2003,2007,2010,2011  Free Software Foundation, Inc.
 *
 *  GRUB is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  GRUB is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 */

19
#include <grub/cryptodisk.h>
20 21 22 23 24 25 26
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/dl.h>
#include <grub/err.h>
#include <grub/disk.h>
#include <grub/crypto.h>
27
#include <grub/partition.h>
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
#include <grub/i18n.h>

GRUB_MOD_LICENSE ("GPLv3+");

#define MAX_PASSPHRASE 256

#define LUKS_KEY_ENABLED  0x00AC71F3

/* On disk LUKS header */
struct grub_luks_phdr
{
  grub_uint8_t magic[6];
#define LUKS_MAGIC        "LUKS\xBA\xBE"
  grub_uint16_t version;
  char cipherName[32];
  char cipherMode[32];
  char hashSpec[32];
  grub_uint32_t payloadOffset;
  grub_uint32_t keyBytes;
  grub_uint8_t mkDigest[20];
  grub_uint8_t mkDigestSalt[32];
  grub_uint32_t mkDigestIterations;
50
  char uuid[40];
51 52 53 54 55 56 57 58
  struct
  {
    grub_uint32_t active;
    grub_uint32_t passwordIterations;
    grub_uint8_t passwordSalt[32];
    grub_uint32_t keyMaterialOffset;
    grub_uint32_t stripes;
  } keyblock[8];
59
} GRUB_PACKED;
60 61 62 63 64 65 66

typedef struct grub_luks_phdr *grub_luks_phdr_t;

gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src,
			  grub_uint8_t * dst, grub_size_t blocksize,
			  grub_size_t blocknumbers);

67
static grub_cryptodisk_t
68 69
configure_ciphers (grub_disk_t disk, const char *check_uuid,
		   int check_boot)
70
{
71
  grub_cryptodisk_t newdev;
72
  const char *iptr;
73
  struct grub_luks_phdr header;
74
  char *optr;
75 76 77
  char uuid[sizeof (header.uuid) + 1];
  char ciphername[sizeof (header.cipherName) + 1];
  char ciphermode[sizeof (header.cipherMode) + 1];
78
  char *cipheriv = NULL;
79
  char hashspec[sizeof (header.hashSpec) + 1];
80
  grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL;
81
  grub_crypto_cipher_handle_t essiv_cipher = NULL;
82 83
  const gcry_md_spec_t *hash = NULL, *essiv_hash = NULL;
  const struct gcry_cipher_spec *ciph;
84
  grub_cryptodisk_mode_t mode;
85
  grub_cryptodisk_mode_iv_t mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64;
86
  int benbi_log = 0;
87 88 89 90 91 92 93 94 95 96 97 98 99
  grub_err_t err;

  if (check_boot)
    return NULL;

  /* Read the LUKS header.  */
  err = grub_disk_read (disk, 0, 0, sizeof (header), &header);
  if (err)
    {
      if (err == GRUB_ERR_OUT_OF_RANGE)
	grub_errno = GRUB_ERR_NONE;
      return NULL;
    }
100

101
  /* Look for LUKS magic sequence.  */
102 103
  if (grub_memcmp (header.magic, LUKS_MAGIC, sizeof (header.magic))
      || grub_be_to_cpu16 (header.version) != 1)
104
    return NULL;
105

106
  optr = uuid;
107
  for (iptr = header.uuid; iptr < &header.uuid[ARRAY_SIZE (header.uuid)];
108 109 110 111 112 113 114
       iptr++)
    {
      if (*iptr != '-')
	*optr++ = *iptr;
    }
  *optr = 0;

115
  if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
116
    {
117
      grub_dprintf ("luks", "%s != %s\n", uuid, check_uuid);
118
      return NULL;
119
    }
120

121
  /* Make sure that strings are null terminated.  */
122 123 124 125 126 127
  grub_memcpy (ciphername, header.cipherName, sizeof (header.cipherName));
  ciphername[sizeof (header.cipherName)] = 0;
  grub_memcpy (ciphermode, header.cipherMode, sizeof (header.cipherMode));
  ciphermode[sizeof (header.cipherMode)] = 0;
  grub_memcpy (hashspec, header.hashSpec, sizeof (header.hashSpec));
  hashspec[sizeof (header.hashSpec)] = 0;
128 129

  ciph = grub_crypto_lookup_cipher_by_name (ciphername);
130
  if (!ciph)
131 132 133 134 135
    {
      grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available",
		  ciphername);
      return NULL;
    }
136 137 138 139

  /* Configure the cipher used for the bulk data.  */
  cipher = grub_crypto_cipher_open (ciph);
  if (!cipher)
140
    return NULL;
141

142
  if (grub_be_to_cpu32 (header.keyBytes) > 1024)
143 144
    {
      grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d",
145
		  grub_be_to_cpu32 (header.keyBytes));
146
      grub_crypto_cipher_close (cipher);
147 148
      return NULL;
    }
149 150

  /* Configure the cipher mode.  */
151
  if (grub_strcmp (ciphermode, "ecb") == 0)
152
    {
153 154
      mode = GRUB_CRYPTODISK_MODE_ECB;
      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
155
      cipheriv = NULL;
156
    }
157 158
  else if (grub_strcmp (ciphermode, "plain") == 0)
    {
159 160
      mode = GRUB_CRYPTODISK_MODE_CBC;
      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
161 162 163 164
      cipheriv = NULL;
    }
  else if (grub_memcmp (ciphermode, "cbc-", sizeof ("cbc-") - 1) == 0)
    {
165
      mode = GRUB_CRYPTODISK_MODE_CBC;
166 167
      cipheriv = ciphermode + sizeof ("cbc-") - 1;
    }
168 169
  else if (grub_memcmp (ciphermode, "pcbc-", sizeof ("pcbc-") - 1) == 0)
    {
170
      mode = GRUB_CRYPTODISK_MODE_PCBC;
171 172
      cipheriv = ciphermode + sizeof ("pcbc-") - 1;
    }
173
  else if (grub_memcmp (ciphermode, "xts-", sizeof ("xts-") - 1) == 0)
174
    {
175
      mode = GRUB_CRYPTODISK_MODE_XTS;
176
      cipheriv = ciphermode + sizeof ("xts-") - 1;
177 178 179 180 181 182
      secondary_cipher = grub_crypto_cipher_open (ciph);
      if (!secondary_cipher)
	{
	  grub_crypto_cipher_close (cipher);
	  return NULL;
	}
183
      if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
184 185 186
	{
	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
		      cipher->cipher->blocksize);
187 188
	  grub_crypto_cipher_close (cipher);
	  grub_crypto_cipher_close (secondary_cipher);
189 190
	  return NULL;
	}
191
      if (secondary_cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
192
	{
193
	  grub_crypto_cipher_close (cipher);
194 195
	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
		      secondary_cipher->cipher->blocksize);
196
	  grub_crypto_cipher_close (secondary_cipher);
197 198 199
	  return NULL;
	}
    }
200 201
  else if (grub_memcmp (ciphermode, "lrw-", sizeof ("lrw-") - 1) == 0)
    {
202
      mode = GRUB_CRYPTODISK_MODE_LRW;
203
      cipheriv = ciphermode + sizeof ("lrw-") - 1;
204
      if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
205 206 207
	{
	  grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported LRW block size: %d",
		      cipher->cipher->blocksize);
208
	  grub_crypto_cipher_close (cipher);
209 210 211
	  return NULL;
	}
    }
212 213 214
  else
    {
      grub_crypto_cipher_close (cipher);
215 216 217
      grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown cipher mode: %s",
		  ciphermode);
      return NULL;
218 219
    }

220 221
  if (cipheriv == NULL);
  else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0)
222
      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
223
  else if (grub_memcmp (cipheriv, "plain64", sizeof ("plain64") - 1) == 0)
224
      mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64;
225
  else if (grub_memcmp (cipheriv, "benbi", sizeof ("benbi") - 1) == 0)
226 227 228 229 230
    {
      if (cipher->cipher->blocksize & (cipher->cipher->blocksize - 1)
	  || cipher->cipher->blocksize == 0)
	grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported benbi blocksize: %d",
		    cipher->cipher->blocksize);
231
	/* FIXME should we return an error here? */
232 233 234
      for (benbi_log = 0; 
	   (cipher->cipher->blocksize << benbi_log) < GRUB_DISK_SECTOR_SIZE;
	   benbi_log++);
235
      mode_iv = GRUB_CRYPTODISK_MODE_IV_BENBI;
236
    }
237
  else if (grub_memcmp (cipheriv, "null", sizeof ("null") - 1) == 0)
238
      mode_iv = GRUB_CRYPTODISK_MODE_IV_NULL;
239 240 241 242
  else if (grub_memcmp (cipheriv, "essiv:", sizeof ("essiv:") - 1) == 0)
    {
      char *hash_str = cipheriv + 6;

243
      mode_iv = GRUB_CRYPTODISK_MODE_IV_ESSIV;
244 245 246 247 248 249

      /* Configure the hash and cipher used for ESSIV.  */
      essiv_hash = grub_crypto_lookup_md_by_name (hash_str);
      if (!essiv_hash)
	{
	  grub_crypto_cipher_close (cipher);
250
	  grub_crypto_cipher_close (secondary_cipher);
251 252 253 254 255 256 257 258
	  grub_error (GRUB_ERR_FILE_NOT_FOUND,
		      "Couldn't load %s hash", hash_str);
	  return NULL;
	}
      essiv_cipher = grub_crypto_cipher_open (ciph);
      if (!essiv_cipher)
	{
	  grub_crypto_cipher_close (cipher);
259
	  grub_crypto_cipher_close (secondary_cipher);
260 261 262 263 264 265
	  return NULL;
	}
    }
  else
    {
      grub_crypto_cipher_close (cipher);
266
      grub_crypto_cipher_close (secondary_cipher);
267 268 269 270 271
      grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown IV mode: %s",
		  cipheriv);
      return NULL;
    }

272
  /* Configure the hash used for the AF splitter and HMAC.  */
273
  hash = grub_crypto_lookup_md_by_name (hashspec);
274 275 276
  if (!hash)
    {
      grub_crypto_cipher_close (cipher);
277
      grub_crypto_cipher_close (essiv_cipher);
278
      grub_crypto_cipher_close (secondary_cipher);
279 280 281
      grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash",
		  hashspec);
      return NULL;
282 283
    }

284
  newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
285
  if (!newdev)
286 287 288 289 290 291
    {
      grub_crypto_cipher_close (cipher);
      grub_crypto_cipher_close (essiv_cipher);
      grub_crypto_cipher_close (secondary_cipher);
      return NULL;
    }
292
  newdev->cipher = cipher;
293
  newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
294
  newdev->source_disk = NULL;
295
  newdev->benbi_log = benbi_log;
296
  newdev->mode = mode;
297
  newdev->mode_iv = mode_iv;
298
  newdev->secondary_cipher = secondary_cipher;
299
  newdev->essiv_cipher = essiv_cipher;
300 301
  newdev->essiv_hash = essiv_hash;
  newdev->hash = hash;
302
  newdev->log_sector_size = 9;
303
  newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
304
  grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid));
305
  newdev->modname = "luks";
306
  COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= sizeof (uuid));
307 308
  return newdev;
}
309

310
static grub_err_t
311 312
luks_recover_key (grub_disk_t source,
		  grub_cryptodisk_t dev)
313
{
314 315
  struct grub_luks_phdr header;
  grub_size_t keysize;
316 317
  grub_uint8_t *split_key = NULL;
  char passphrase[MAX_PASSPHRASE] = "";
318
  grub_uint8_t candidate_digest[sizeof (header.mkDigest)];
319 320 321
  unsigned i;
  grub_size_t length;
  grub_err_t err;
322
  grub_size_t max_stripes = 1;
323 324 325 326 327
  char *tmp;

  err = grub_disk_read (source, 0, 0, sizeof (header), &header);
  if (err)
    return err;
328

329
  grub_puts_ (N_("Attempting to decrypt master key..."));
330
  keysize = grub_be_to_cpu32 (header.keyBytes);
331 332
  if (keysize > GRUB_CRYPTODISK_MAX_KEYLEN)
    return grub_error (GRUB_ERR_BAD_FS, "key is too long");
333

334 335 336 337
  for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
    if (grub_be_to_cpu32 (header.keyblock[i].active) == LUKS_KEY_ENABLED
	&& grub_be_to_cpu32 (header.keyblock[i].stripes) > max_stripes)
      max_stripes = grub_be_to_cpu32 (header.keyblock[i].stripes);
338 339

  split_key = grub_malloc (keysize * max_stripes);
340
  if (!split_key)
341
    return grub_errno;
342 343

  /* Get the passphrase from the user.  */
344 345 346
  tmp = NULL;
  if (source->partition)
    tmp = grub_partition_get_name (source->partition);
347
  grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
348 349 350
	       source->partition ? "," : "", tmp ? : "",
	       dev->uuid);
  grub_free (tmp);
351 352 353 354 355 356 357
  if (!grub_password_get (passphrase, MAX_PASSPHRASE))
    {
      grub_free (split_key);
      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
    }

  /* Try to recover master key from each active keyslot.  */
358
  for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
359 360
    {
      gcry_err_code_t gcry_err;
361 362
      grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
      grub_uint8_t digest[GRUB_CRYPTODISK_MAX_KEYLEN];
363 364

      /* Check if keyslot is enabled.  */
365
      if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED)
366 367 368 369 370
	continue;

      grub_dprintf ("luks", "Trying keyslot %d\n", i);

      /* Calculate the PBKDF2 of the user supplied passphrase.  */
371
      gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
372
				     grub_strlen (passphrase),
373 374 375
				     header.keyblock[i].passwordSalt,
				     sizeof (header.keyblock[i].passwordSalt),
				     grub_be_to_cpu32 (header.keyblock[i].
376 377 378 379 380 381 382 383 384 385 386
						       passwordIterations),
				     digest, keysize);

      if (gcry_err)
	{
	  grub_free (split_key);
	  return grub_crypto_gcry_error (gcry_err);
	}

      grub_dprintf ("luks", "PBKDF2 done\n");

387
      gcry_err = grub_cryptodisk_setkey (dev, digest, keysize); 
388 389 390 391 392 393
      if (gcry_err)
	{
	  grub_free (split_key);
	  return grub_crypto_gcry_error (gcry_err);
	}

394
      length = (keysize * grub_be_to_cpu32 (header.keyblock[i].stripes));
395 396 397

      /* Read and decrypt the key material from the disk.  */
      err = grub_disk_read (source,
398
			    grub_be_to_cpu32 (header.keyblock
399 400 401 402 403 404 405 406
					      [i].keyMaterialOffset), 0,
			    length, split_key);
      if (err)
	{
	  grub_free (split_key);
	  return err;
	}

407
      gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
408 409 410 411 412 413 414
      if (gcry_err)
	{
	  grub_free (split_key);
	  return grub_crypto_gcry_error (gcry_err);
	}

      /* Merge the decrypted key material to get the candidate master key.  */
415
      gcry_err = AF_merge (dev->hash, split_key, candidate_key, keysize,
416
			   grub_be_to_cpu32 (header.keyblock[i].stripes));
417 418 419 420 421 422 423 424 425
      if (gcry_err)
	{
	  grub_free (split_key);
	  return grub_crypto_gcry_error (gcry_err);
	}

      grub_dprintf ("luks", "candidate key recovered\n");

      /* Calculate the PBKDF2 of the candidate master key.  */
426
      gcry_err = grub_crypto_pbkdf2 (dev->hash, candidate_key,
427 428 429
				     grub_be_to_cpu32 (header.keyBytes),
				     header.mkDigestSalt,
				     sizeof (header.mkDigestSalt),
430
				     grub_be_to_cpu32
431
				     (header.mkDigestIterations),
432 433 434 435 436 437 438 439 440 441
				     candidate_digest,
				     sizeof (candidate_digest));
      if (gcry_err)
	{
	  grub_free (split_key);
	  return grub_crypto_gcry_error (gcry_err);
	}

      /* Compare the calculated PBKDF2 to the digest stored
         in the header to see if it's correct.  */
442 443
      if (grub_memcmp (candidate_digest, header.mkDigest,
		       sizeof (header.mkDigest)) != 0)
444 445 446 447
	{
	  grub_dprintf ("luks", "bad digest\n");
	  continue;
	}
448

449 450
      /* TRANSLATORS: It's a cryptographic key slot: one element of an array
	 where each element is either empty or holds a key.  */
451
      grub_printf_ (N_("Slot %d opened\n"), i);
452 453

      /* Set the master key.  */
454
      gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize); 
455 456 457 458 459 460 461 462 463 464 465
      if (gcry_err)
	{
	  grub_free (split_key);
	  return grub_crypto_gcry_error (gcry_err);
	}

      grub_free (split_key);

      return GRUB_ERR_NONE;
    }

466
  grub_free (split_key);
467 468 469
  return GRUB_ACCESS_DENIED;
}

470 471 472 473
struct grub_cryptodisk_dev luks_crypto = {
  .scan = configure_ciphers,
  .recover_key = luks_recover_key
};
474 475 476

GRUB_MOD_INIT (luks)
{
477 478
  COMPILE_TIME_ASSERT (sizeof (((struct grub_luks_phdr *) 0)->uuid)
		       < GRUB_CRYPTODISK_MAX_UUID_LENGTH);
479
  grub_cryptodisk_dev_register (&luks_crypto);
480 481 482 483
}

GRUB_MOD_FINI (luks)
{
484
  grub_cryptodisk_dev_unregister (&luks_crypto);
485
}