2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2003,2007,2010,2011,2019 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <grub/cryptodisk.h>
21 #include <grub/misc.h>
23 #include <grub/extcmd.h>
24 #include <grub/i18n.h>
26 #include <grub/file.h>
27 #include <grub/procfs.h>
28 #include <grub/partition.h>
31 #include <grub/emu/hostdisk.h>
34 GRUB_MOD_LICENSE ("GPLv3+");
36 grub_cryptodisk_dev_t grub_cryptodisk_list
;
38 static const struct grub_arg_option options
[] =
40 {"uuid", 'u', 0, N_("Mount by UUID."), 0, 0},
41 /* TRANSLATORS: It's still restricted to cryptodisks only. */
42 {"all", 'a', 0, N_("Mount all."), 0, 0},
43 {"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0},
47 /* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is: */
48 #define GF_POLYNOM 0x87
49 static inline int GF_PER_SECTOR (const struct grub_cryptodisk
*dev
)
51 return 1U << (dev
->log_sector_size
- GRUB_CRYPTODISK_GF_LOG_BYTES
);
54 static grub_cryptodisk_t cryptodisk_list
= NULL
;
55 static grub_uint8_t last_cryptodisk_id
= 0;
58 gf_mul_x (grub_uint8_t
*g
)
60 int over
= 0, over2
= 0;
63 for (j
= 0; j
< GRUB_CRYPTODISK_GF_BYTES
; j
++)
65 over2
= !!(g
[j
] & 0x80);
76 gf_mul_x_be (grub_uint8_t
*g
)
78 int over
= 0, over2
= 0;
81 for (j
= (int) GRUB_CRYPTODISK_GF_BYTES
- 1; j
>= 0; j
--)
83 over2
= !!(g
[j
] & 0x80);
89 g
[GRUB_CRYPTODISK_GF_BYTES
- 1] ^= GF_POLYNOM
;
93 gf_mul_be (grub_uint8_t
*o
, const grub_uint8_t
*a
, const grub_uint8_t
*b
)
96 grub_uint8_t t
[GRUB_CRYPTODISK_GF_BYTES
];
97 grub_memset (o
, 0, GRUB_CRYPTODISK_GF_BYTES
);
98 grub_memcpy (t
, b
, GRUB_CRYPTODISK_GF_BYTES
);
99 for (i
= 0; i
< GRUB_CRYPTODISK_GF_SIZE
; i
++)
101 if (((a
[GRUB_CRYPTODISK_GF_BYTES
- i
/ GRUB_CHAR_BIT
- 1] >> (i
% GRUB_CHAR_BIT
))) & 1)
102 grub_crypto_xor (o
, o
, t
, GRUB_CRYPTODISK_GF_BYTES
);
107 static gcry_err_code_t
108 grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher
,
109 void *out
, void *in
, grub_size_t size
,
112 grub_uint8_t
*inptr
, *outptr
, *end
;
113 grub_uint8_t ivt
[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE
];
114 grub_size_t blocksize
;
115 if (!cipher
->cipher
->decrypt
)
116 return GPG_ERR_NOT_SUPPORTED
;
117 blocksize
= cipher
->cipher
->blocksize
;
118 if (blocksize
== 0 || (((blocksize
- 1) & blocksize
) != 0)
119 || ((size
& (blocksize
- 1)) != 0))
120 return GPG_ERR_INV_ARG
;
121 if (blocksize
> GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE
)
122 return GPG_ERR_INV_ARG
;
123 end
= (grub_uint8_t
*) in
+ size
;
124 for (inptr
= in
, outptr
= out
; inptr
< end
;
125 inptr
+= blocksize
, outptr
+= blocksize
)
127 grub_memcpy (ivt
, inptr
, blocksize
);
128 cipher
->cipher
->decrypt (cipher
->ctx
, outptr
, inptr
);
129 grub_crypto_xor (outptr
, outptr
, iv
, blocksize
);
130 grub_crypto_xor (iv
, ivt
, outptr
, blocksize
);
132 return GPG_ERR_NO_ERROR
;
135 static gcry_err_code_t
136 grub_crypto_pcbc_encrypt (grub_crypto_cipher_handle_t cipher
,
137 void *out
, void *in
, grub_size_t size
,
140 grub_uint8_t
*inptr
, *outptr
, *end
;
141 grub_uint8_t ivt
[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE
];
142 grub_size_t blocksize
;
143 if (!cipher
->cipher
->encrypt
)
144 return GPG_ERR_NOT_SUPPORTED
;
145 blocksize
= cipher
->cipher
->blocksize
;
146 if (blocksize
> GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE
)
147 return GPG_ERR_INV_ARG
;
148 if (blocksize
== 0 || (((blocksize
- 1) & blocksize
) != 0)
149 || ((size
& (blocksize
- 1)) != 0))
150 return GPG_ERR_INV_ARG
;
151 end
= (grub_uint8_t
*) in
+ size
;
152 for (inptr
= in
, outptr
= out
; inptr
< end
;
153 inptr
+= blocksize
, outptr
+= blocksize
)
155 grub_memcpy (ivt
, inptr
, blocksize
);
156 grub_crypto_xor (outptr
, outptr
, iv
, blocksize
);
157 cipher
->cipher
->encrypt (cipher
->ctx
, outptr
, inptr
);
158 grub_crypto_xor (iv
, ivt
, outptr
, blocksize
);
160 return GPG_ERR_NO_ERROR
;
165 grub_uint8_t low
[GRUB_CRYPTODISK_GF_BYTES
];
166 grub_uint8_t high
[GRUB_CRYPTODISK_GF_BYTES
];
167 grub_uint8_t low_byte
, low_byte_c
;
171 generate_lrw_sector (struct lrw_sector
*sec
,
172 const struct grub_cryptodisk
*dev
,
173 const grub_uint8_t
*iv
)
175 grub_uint8_t idx
[GRUB_CRYPTODISK_GF_BYTES
];
178 grub_memcpy (idx
, iv
, GRUB_CRYPTODISK_GF_BYTES
);
179 sec
->low_byte
= (idx
[GRUB_CRYPTODISK_GF_BYTES
- 1]
180 & (GF_PER_SECTOR (dev
) - 1));
181 sec
->low_byte_c
= (((GF_PER_SECTOR (dev
) - 1) & ~sec
->low_byte
) + 1);
182 idx
[GRUB_CRYPTODISK_GF_BYTES
- 1] &= ~(GF_PER_SECTOR (dev
) - 1);
183 gf_mul_be (sec
->low
, dev
->lrw_key
, idx
);
187 c
= idx
[GRUB_CRYPTODISK_GF_BYTES
- 1] + GF_PER_SECTOR (dev
);
190 for (j
= GRUB_CRYPTODISK_GF_BYTES
- 2; j
>= 0; j
--)
197 idx
[GRUB_CRYPTODISK_GF_BYTES
- 1] = c
;
198 gf_mul_be (sec
->high
, dev
->lrw_key
, idx
);
201 static void __attribute__ ((unused
))
202 lrw_xor (const struct lrw_sector
*sec
,
203 const struct grub_cryptodisk
*dev
,
208 for (i
= 0; i
< sec
->low_byte_c
* GRUB_CRYPTODISK_GF_BYTES
;
209 i
+= GRUB_CRYPTODISK_GF_BYTES
)
210 grub_crypto_xor (b
+ i
, b
+ i
, sec
->low
, GRUB_CRYPTODISK_GF_BYTES
);
211 grub_crypto_xor (b
, b
, dev
->lrw_precalc
+ GRUB_CRYPTODISK_GF_BYTES
* sec
->low_byte
,
212 sec
->low_byte_c
* GRUB_CRYPTODISK_GF_BYTES
);
216 for (i
= sec
->low_byte_c
* GRUB_CRYPTODISK_GF_BYTES
;
217 i
< (1U << dev
->log_sector_size
); i
+= GRUB_CRYPTODISK_GF_BYTES
)
218 grub_crypto_xor (b
+ i
, b
+ i
, sec
->high
, GRUB_CRYPTODISK_GF_BYTES
);
219 grub_crypto_xor (b
+ sec
->low_byte_c
* GRUB_CRYPTODISK_GF_BYTES
,
220 b
+ sec
->low_byte_c
* GRUB_CRYPTODISK_GF_BYTES
,
221 dev
->lrw_precalc
, sec
->low_byte
* GRUB_CRYPTODISK_GF_BYTES
);
224 static gcry_err_code_t
225 grub_cryptodisk_endecrypt (struct grub_cryptodisk
*dev
,
226 grub_uint8_t
* data
, grub_size_t len
,
227 grub_disk_addr_t sector
, int do_encrypt
)
232 if (dev
->cipher
->cipher
->blocksize
> GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE
)
233 return GPG_ERR_INV_ARG
;
235 /* The only mode without IV. */
236 if (dev
->mode
== GRUB_CRYPTODISK_MODE_ECB
&& !dev
->rekey
)
237 return (do_encrypt
? grub_crypto_ecb_encrypt (dev
->cipher
, data
, data
, len
)
238 : grub_crypto_ecb_decrypt (dev
->cipher
, data
, data
, len
));
240 for (i
= 0; i
< len
; i
+= (1U << dev
->log_sector_size
))
242 grub_size_t sz
= ((dev
->cipher
->cipher
->blocksize
243 + sizeof (grub_uint32_t
) - 1)
244 / sizeof (grub_uint32_t
));
245 grub_uint32_t iv
[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE
+ 3) / 4];
249 grub_uint64_t zone
= sector
>> dev
->rekey_shift
;
250 if (zone
!= dev
->last_rekey
)
252 err
= dev
->rekey (dev
, zone
);
255 dev
->last_rekey
= zone
;
259 grub_memset (iv
, 0, sizeof (iv
));
260 switch (dev
->mode_iv
)
262 case GRUB_CRYPTODISK_MODE_IV_NULL
:
264 case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH
:
269 ctx
= grub_zalloc (dev
->iv_hash
->contextsize
);
271 return GPG_ERR_OUT_OF_MEMORY
;
273 tmp
= grub_cpu_to_le64 (sector
<< dev
->log_sector_size
);
274 dev
->iv_hash
->init (ctx
);
275 dev
->iv_hash
->write (ctx
, dev
->iv_prefix
, dev
->iv_prefix_len
);
276 dev
->iv_hash
->write (ctx
, &tmp
, sizeof (tmp
));
277 dev
->iv_hash
->final (ctx
);
279 grub_memcpy (iv
, dev
->iv_hash
->read (ctx
), sizeof (iv
));
283 case GRUB_CRYPTODISK_MODE_IV_PLAIN64
:
284 iv
[1] = grub_cpu_to_le32 (sector
>> 32);
286 case GRUB_CRYPTODISK_MODE_IV_PLAIN
:
287 iv
[0] = grub_cpu_to_le32 (sector
& 0xFFFFFFFF);
289 case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64
:
290 iv
[1] = grub_cpu_to_le32 (sector
>> (32 - dev
->log_sector_size
));
291 iv
[0] = grub_cpu_to_le32 ((sector
<< dev
->log_sector_size
)
294 case GRUB_CRYPTODISK_MODE_IV_BENBI
:
296 grub_uint64_t num
= (sector
<< dev
->benbi_log
) + 1;
297 iv
[sz
- 2] = grub_cpu_to_be32 (num
>> 32);
298 iv
[sz
- 1] = grub_cpu_to_be32 (num
& 0xFFFFFFFF);
301 case GRUB_CRYPTODISK_MODE_IV_ESSIV
:
302 iv
[0] = grub_cpu_to_le32 (sector
& 0xFFFFFFFF);
303 err
= grub_crypto_ecb_encrypt (dev
->essiv_cipher
, iv
, iv
,
304 dev
->cipher
->cipher
->blocksize
);
311 case GRUB_CRYPTODISK_MODE_CBC
:
313 err
= grub_crypto_cbc_encrypt (dev
->cipher
, data
+ i
, data
+ i
,
314 (1U << dev
->log_sector_size
), iv
);
316 err
= grub_crypto_cbc_decrypt (dev
->cipher
, data
+ i
, data
+ i
,
317 (1U << dev
->log_sector_size
), iv
);
322 case GRUB_CRYPTODISK_MODE_PCBC
:
324 err
= grub_crypto_pcbc_encrypt (dev
->cipher
, data
+ i
, data
+ i
,
325 (1U << dev
->log_sector_size
), iv
);
327 err
= grub_crypto_pcbc_decrypt (dev
->cipher
, data
+ i
, data
+ i
,
328 (1U << dev
->log_sector_size
), iv
);
332 case GRUB_CRYPTODISK_MODE_XTS
:
335 err
= grub_crypto_ecb_encrypt (dev
->secondary_cipher
, iv
, iv
,
336 dev
->cipher
->cipher
->blocksize
);
340 for (j
= 0; j
< (1U << dev
->log_sector_size
);
341 j
+= dev
->cipher
->cipher
->blocksize
)
343 grub_crypto_xor (data
+ i
+ j
, data
+ i
+ j
, iv
,
344 dev
->cipher
->cipher
->blocksize
);
346 err
= grub_crypto_ecb_encrypt (dev
->cipher
, data
+ i
+ j
,
348 dev
->cipher
->cipher
->blocksize
);
350 err
= grub_crypto_ecb_decrypt (dev
->cipher
, data
+ i
+ j
,
352 dev
->cipher
->cipher
->blocksize
);
355 grub_crypto_xor (data
+ i
+ j
, data
+ i
+ j
, iv
,
356 dev
->cipher
->cipher
->blocksize
);
357 gf_mul_x ((grub_uint8_t
*) iv
);
361 case GRUB_CRYPTODISK_MODE_LRW
:
363 struct lrw_sector sec
;
365 generate_lrw_sector (&sec
, dev
, (grub_uint8_t
*) iv
);
366 lrw_xor (&sec
, dev
, data
+ i
);
369 err
= grub_crypto_ecb_encrypt (dev
->cipher
, data
+ i
,
371 (1U << dev
->log_sector_size
));
373 err
= grub_crypto_ecb_decrypt (dev
->cipher
, data
+ i
,
375 (1U << dev
->log_sector_size
));
378 lrw_xor (&sec
, dev
, data
+ i
);
381 case GRUB_CRYPTODISK_MODE_ECB
:
383 err
= grub_crypto_ecb_encrypt (dev
->cipher
, data
+ i
, data
+ i
,
384 (1U << dev
->log_sector_size
));
386 err
= grub_crypto_ecb_decrypt (dev
->cipher
, data
+ i
, data
+ i
,
387 (1U << dev
->log_sector_size
));
392 return GPG_ERR_NOT_IMPLEMENTED
;
396 return GPG_ERR_NO_ERROR
;
400 grub_cryptodisk_decrypt (struct grub_cryptodisk
*dev
,
401 grub_uint8_t
* data
, grub_size_t len
,
402 grub_disk_addr_t sector
)
404 return grub_cryptodisk_endecrypt (dev
, data
, len
, sector
, 0);
408 grub_cryptodisk_setcipher (grub_cryptodisk_t crypt
, const char *ciphername
, const char *ciphermode
)
410 const char *cipheriv
= NULL
;
411 grub_crypto_cipher_handle_t cipher
= NULL
, secondary_cipher
= NULL
;
412 grub_crypto_cipher_handle_t essiv_cipher
= NULL
;
413 const gcry_md_spec_t
*essiv_hash
= NULL
;
414 const struct gcry_cipher_spec
*ciph
;
415 grub_cryptodisk_mode_t mode
;
416 grub_cryptodisk_mode_iv_t mode_iv
= GRUB_CRYPTODISK_MODE_IV_PLAIN64
;
418 grub_err_t ret
= GRUB_ERR_NONE
;
420 ciph
= grub_crypto_lookup_cipher_by_name (ciphername
);
423 ret
= grub_error (GRUB_ERR_FILE_NOT_FOUND
, "Cipher %s isn't available",
428 /* Configure the cipher used for the bulk data. */
429 cipher
= grub_crypto_cipher_open (ciph
);
432 ret
= grub_error (GRUB_ERR_FILE_NOT_FOUND
, "Cipher %s could not be initialized",
437 /* Configure the cipher mode. */
438 if (grub_strcmp (ciphermode
, "ecb") == 0)
440 mode
= GRUB_CRYPTODISK_MODE_ECB
;
441 mode_iv
= GRUB_CRYPTODISK_MODE_IV_PLAIN
;
444 else if (grub_strcmp (ciphermode
, "plain") == 0)
446 mode
= GRUB_CRYPTODISK_MODE_CBC
;
447 mode_iv
= GRUB_CRYPTODISK_MODE_IV_PLAIN
;
450 else if (grub_memcmp (ciphermode
, "cbc-", sizeof ("cbc-") - 1) == 0)
452 mode
= GRUB_CRYPTODISK_MODE_CBC
;
453 cipheriv
= ciphermode
+ sizeof ("cbc-") - 1;
455 else if (grub_memcmp (ciphermode
, "pcbc-", sizeof ("pcbc-") - 1) == 0)
457 mode
= GRUB_CRYPTODISK_MODE_PCBC
;
458 cipheriv
= ciphermode
+ sizeof ("pcbc-") - 1;
460 else if (grub_memcmp (ciphermode
, "xts-", sizeof ("xts-") - 1) == 0)
462 mode
= GRUB_CRYPTODISK_MODE_XTS
;
463 cipheriv
= ciphermode
+ sizeof ("xts-") - 1;
464 secondary_cipher
= grub_crypto_cipher_open (ciph
);
465 if (!secondary_cipher
)
467 ret
= grub_error (GRUB_ERR_FILE_NOT_FOUND
,
468 "Secondary cipher %s isn't available", ciphername
);
471 if (cipher
->cipher
->blocksize
!= GRUB_CRYPTODISK_GF_BYTES
)
473 ret
= grub_error (GRUB_ERR_BAD_ARGUMENT
, "Unsupported XTS block size: %d",
474 cipher
->cipher
->blocksize
);
477 if (secondary_cipher
->cipher
->blocksize
!= GRUB_CRYPTODISK_GF_BYTES
)
479 ret
= grub_error (GRUB_ERR_BAD_ARGUMENT
, "Unsupported XTS block size: %d",
480 secondary_cipher
->cipher
->blocksize
);
484 else if (grub_memcmp (ciphermode
, "lrw-", sizeof ("lrw-") - 1) == 0)
486 mode
= GRUB_CRYPTODISK_MODE_LRW
;
487 cipheriv
= ciphermode
+ sizeof ("lrw-") - 1;
488 if (cipher
->cipher
->blocksize
!= GRUB_CRYPTODISK_GF_BYTES
)
490 ret
= grub_error (GRUB_ERR_BAD_ARGUMENT
, "Unsupported LRW block size: %d",
491 cipher
->cipher
->blocksize
);
497 ret
= grub_error (GRUB_ERR_BAD_ARGUMENT
, "Unknown cipher mode: %s",
502 if (cipheriv
== NULL
)
504 else if (grub_memcmp (cipheriv
, "plain64", sizeof ("plain64") - 1) == 0)
505 mode_iv
= GRUB_CRYPTODISK_MODE_IV_PLAIN64
;
506 else if (grub_memcmp (cipheriv
, "plain", sizeof ("plain") - 1) == 0)
507 mode_iv
= GRUB_CRYPTODISK_MODE_IV_PLAIN
;
508 else if (grub_memcmp (cipheriv
, "benbi", sizeof ("benbi") - 1) == 0)
510 if (cipher
->cipher
->blocksize
& (cipher
->cipher
->blocksize
- 1)
511 || cipher
->cipher
->blocksize
== 0)
512 grub_error (GRUB_ERR_BAD_ARGUMENT
, "Unsupported benbi blocksize: %d",
513 cipher
->cipher
->blocksize
);
514 /* FIXME should we return an error here? */
516 (cipher
->cipher
->blocksize
<< benbi_log
) < GRUB_DISK_SECTOR_SIZE
;
518 mode_iv
= GRUB_CRYPTODISK_MODE_IV_BENBI
;
520 else if (grub_memcmp (cipheriv
, "null", sizeof ("null") - 1) == 0)
521 mode_iv
= GRUB_CRYPTODISK_MODE_IV_NULL
;
522 else if (grub_memcmp (cipheriv
, "essiv:", sizeof ("essiv:") - 1) == 0)
524 const char *hash_str
= cipheriv
+ 6;
526 mode_iv
= GRUB_CRYPTODISK_MODE_IV_ESSIV
;
528 /* Configure the hash and cipher used for ESSIV. */
529 essiv_hash
= grub_crypto_lookup_md_by_name (hash_str
);
532 ret
= grub_error (GRUB_ERR_FILE_NOT_FOUND
,
533 "Couldn't load %s hash", hash_str
);
536 essiv_cipher
= grub_crypto_cipher_open (ciph
);
539 ret
= grub_error (GRUB_ERR_FILE_NOT_FOUND
,
540 "Couldn't load %s cipher", ciphername
);
546 ret
= grub_error (GRUB_ERR_BAD_ARGUMENT
, "Unknown IV mode: %s",
551 crypt
->cipher
= cipher
;
552 crypt
->benbi_log
= benbi_log
;
554 crypt
->mode_iv
= mode_iv
;
555 crypt
->secondary_cipher
= secondary_cipher
;
556 crypt
->essiv_cipher
= essiv_cipher
;
557 crypt
->essiv_hash
= essiv_hash
;
562 grub_crypto_cipher_close (cipher
);
563 grub_crypto_cipher_close (secondary_cipher
);
569 grub_cryptodisk_setkey (grub_cryptodisk_t dev
, grub_uint8_t
*key
, grub_size_t keysize
)
574 real_keysize
= keysize
;
575 if (dev
->mode
== GRUB_CRYPTODISK_MODE_XTS
)
577 if (dev
->mode
== GRUB_CRYPTODISK_MODE_LRW
)
578 real_keysize
-= dev
->cipher
->cipher
->blocksize
;
580 /* Set the PBKDF2 output as the cipher key. */
581 err
= grub_crypto_cipher_set_key (dev
->cipher
, key
, real_keysize
);
584 grub_memcpy (dev
->key
, key
, keysize
);
585 dev
->keysize
= keysize
;
587 /* Configure ESSIV if necessary. */
588 if (dev
->mode_iv
== GRUB_CRYPTODISK_MODE_IV_ESSIV
)
590 grub_size_t essiv_keysize
= dev
->essiv_hash
->mdlen
;
591 grub_uint8_t hashed_key
[GRUB_CRYPTO_MAX_MDLEN
];
592 if (essiv_keysize
> GRUB_CRYPTO_MAX_MDLEN
)
593 return GPG_ERR_INV_ARG
;
595 grub_crypto_hash (dev
->essiv_hash
, hashed_key
, key
, keysize
);
596 err
= grub_crypto_cipher_set_key (dev
->essiv_cipher
,
597 hashed_key
, essiv_keysize
);
601 if (dev
->mode
== GRUB_CRYPTODISK_MODE_XTS
)
603 err
= grub_crypto_cipher_set_key (dev
->secondary_cipher
,
610 if (dev
->mode
== GRUB_CRYPTODISK_MODE_LRW
)
613 grub_uint8_t idx
[GRUB_CRYPTODISK_GF_BYTES
];
615 grub_free (dev
->lrw_precalc
);
616 grub_memcpy (dev
->lrw_key
, key
+ real_keysize
,
617 dev
->cipher
->cipher
->blocksize
);
618 dev
->lrw_precalc
= grub_malloc ((1U << dev
->log_sector_size
));
619 if (!dev
->lrw_precalc
)
620 return GPG_ERR_OUT_OF_MEMORY
;
621 grub_memset (idx
, 0, GRUB_CRYPTODISK_GF_BYTES
);
622 for (i
= 0; i
< (1U << dev
->log_sector_size
);
623 i
+= GRUB_CRYPTODISK_GF_BYTES
)
625 idx
[GRUB_CRYPTODISK_GF_BYTES
- 1] = i
/ GRUB_CRYPTODISK_GF_BYTES
;
626 gf_mul_be (dev
->lrw_precalc
+ i
, idx
, dev
->lrw_key
);
629 return GPG_ERR_NO_ERROR
;
633 grub_cryptodisk_iterate (grub_disk_dev_iterate_hook_t hook
, void *hook_data
,
634 grub_disk_pull_t pull
)
638 if (pull
!= GRUB_DISK_PULL_NONE
)
641 for (i
= cryptodisk_list
; i
!= NULL
; i
= i
->next
)
644 grub_snprintf (buf
, sizeof (buf
), "crypto%lu", i
->id
);
645 if (hook (buf
, hook_data
))
649 return GRUB_ERR_NONE
;
653 grub_cryptodisk_open (const char *name
, grub_disk_t disk
)
655 grub_cryptodisk_t dev
;
657 if (grub_memcmp (name
, "crypto", sizeof ("crypto") - 1) != 0)
658 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "No such device");
660 if (grub_memcmp (name
, "cryptouuid/", sizeof ("cryptouuid/") - 1) == 0)
662 for (dev
= cryptodisk_list
; dev
!= NULL
; dev
= dev
->next
)
663 if (grub_strcasecmp (name
+ sizeof ("cryptouuid/") - 1, dev
->uuid
) == 0)
668 unsigned long id
= grub_strtoul (name
+ sizeof ("crypto") - 1, 0, 0);
670 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "No such device");
671 /* Search for requested device in the list of CRYPTODISK devices. */
672 for (dev
= cryptodisk_list
; dev
!= NULL
; dev
= dev
->next
)
677 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "No such device");
679 disk
->log_sector_size
= dev
->log_sector_size
;
684 if (!GRUB_UTIL_FD_IS_VALID (dev
->cheat_fd
))
685 dev
->cheat_fd
= grub_util_fd_open (dev
->cheat
, GRUB_UTIL_FD_O_RDONLY
);
686 if (!GRUB_UTIL_FD_IS_VALID (dev
->cheat_fd
))
687 return grub_error (GRUB_ERR_IO
, N_("cannot open `%s': %s"),
688 dev
->cheat
, grub_util_fd_strerror ());
692 if (!dev
->source_disk
)
694 grub_dprintf ("cryptodisk", "Opening device %s\n", name
);
695 /* Try to open the source disk and populate the requested disk. */
696 dev
->source_disk
= grub_disk_open (dev
->source
);
697 if (!dev
->source_disk
)
702 disk
->total_sectors
= dev
->total_sectors
;
703 disk
->max_agglomerate
= GRUB_DISK_MAX_MAX_AGGLOMERATE
;
706 return GRUB_ERR_NONE
;
710 grub_cryptodisk_close (grub_disk_t disk
)
712 grub_cryptodisk_t dev
= (grub_cryptodisk_t
) disk
->data
;
713 grub_dprintf ("cryptodisk", "Closing disk\n");
722 grub_util_fd_close (dev
->cheat_fd
);
723 dev
->cheat_fd
= GRUB_UTIL_FD_INVALID
;
726 grub_disk_close (dev
->source_disk
);
727 dev
->source_disk
= NULL
;
731 grub_cryptodisk_read (grub_disk_t disk
, grub_disk_addr_t sector
,
732 grub_size_t size
, char *buf
)
734 grub_cryptodisk_t dev
= (grub_cryptodisk_t
) disk
->data
;
736 gcry_err_code_t gcry_err
;
742 r
= grub_util_fd_seek (dev
->cheat_fd
, sector
<< disk
->log_sector_size
);
744 return grub_error (GRUB_ERR_BAD_DEVICE
, N_("cannot seek `%s': %s"),
745 dev
->cheat
, grub_util_fd_strerror ());
746 if (grub_util_fd_read (dev
->cheat_fd
, buf
, size
<< disk
->log_sector_size
)
747 != (ssize_t
) (size
<< disk
->log_sector_size
))
748 return grub_error (GRUB_ERR_READ_ERROR
, N_("cannot read `%s': %s"),
749 dev
->cheat
, grub_util_fd_strerror ());
750 return GRUB_ERR_NONE
;
754 grub_dprintf ("cryptodisk",
755 "Reading %" PRIuGRUB_SIZE
" sectors from sector 0x%"
756 PRIxGRUB_UINT64_T
" with offset of %" PRIuGRUB_UINT64_T
"\n",
757 size
, sector
, dev
->offset
);
759 err
= grub_disk_read (dev
->source_disk
,
760 grub_disk_from_native_sector (disk
, sector
+ dev
->offset
),
761 0, size
<< disk
->log_sector_size
, buf
);
764 grub_dprintf ("cryptodisk", "grub_disk_read failed with error %d\n", err
);
767 gcry_err
= grub_cryptodisk_endecrypt (dev
, (grub_uint8_t
*) buf
,
768 size
<< disk
->log_sector_size
,
770 return grub_crypto_gcry_error (gcry_err
);
774 grub_cryptodisk_write (grub_disk_t disk
, grub_disk_addr_t sector
,
775 grub_size_t size
, const char *buf
)
777 grub_cryptodisk_t dev
= (grub_cryptodisk_t
) disk
->data
;
778 gcry_err_code_t gcry_err
;
786 r
= grub_util_fd_seek (dev
->cheat_fd
, sector
<< disk
->log_sector_size
);
788 return grub_error (GRUB_ERR_BAD_DEVICE
, N_("cannot seek `%s': %s"),
789 dev
->cheat
, grub_util_fd_strerror ());
790 if (grub_util_fd_write (dev
->cheat_fd
, buf
, size
<< disk
->log_sector_size
)
791 != (ssize_t
) (size
<< disk
->log_sector_size
))
792 return grub_error (GRUB_ERR_READ_ERROR
, N_("cannot read `%s': %s"),
793 dev
->cheat
, grub_util_fd_strerror ());
794 return GRUB_ERR_NONE
;
798 tmp
= grub_malloc (size
<< disk
->log_sector_size
);
801 grub_memcpy (tmp
, buf
, size
<< disk
->log_sector_size
);
803 grub_dprintf ("cryptodisk",
804 "Writing %" PRIuGRUB_SIZE
" sectors to sector 0x%"
805 PRIxGRUB_UINT64_T
" with offset of %" PRIuGRUB_UINT64_T
"\n",
806 size
, sector
, dev
->offset
);
808 gcry_err
= grub_cryptodisk_endecrypt (dev
, (grub_uint8_t
*) tmp
,
809 size
<< disk
->log_sector_size
,
814 return grub_crypto_gcry_error (gcry_err
);
817 /* Since ->write was called so disk.mod is loaded but be paranoid */
818 sector
= sector
+ dev
->offset
;
819 if (grub_disk_write_weak
)
820 err
= grub_disk_write_weak (dev
->source_disk
,
821 grub_disk_from_native_sector (disk
, sector
),
822 0, size
<< disk
->log_sector_size
, tmp
);
824 err
= grub_error (GRUB_ERR_BUG
, "disk.mod not loaded");
830 static grub_disk_memberlist_t
831 grub_cryptodisk_memberlist (grub_disk_t disk
)
833 grub_cryptodisk_t dev
= (grub_cryptodisk_t
) disk
->data
;
834 grub_disk_memberlist_t list
= NULL
;
836 list
= grub_malloc (sizeof (*list
));
839 list
->disk
= dev
->source_disk
;
848 cryptodisk_cleanup (void)
851 grub_cryptodisk_t dev
= cryptodisk_list
;
852 grub_cryptodisk_t tmp
;
856 grub_free (dev
->source
);
857 grub_free (dev
->cipher
);
858 grub_free (dev
->secondary_cipher
);
859 grub_free (dev
->essiv_cipher
);
868 grub_cryptodisk_insert (grub_cryptodisk_t newdev
, const char *name
,
871 newdev
->source
= grub_strdup (name
);
878 newdev
->id
= last_cryptodisk_id
++;
879 newdev
->source_id
= source
->id
;
880 newdev
->source_dev_id
= source
->dev
->id
;
881 newdev
->partition_start
= grub_partition_get_start (source
->partition
);
882 newdev
->next
= cryptodisk_list
;
883 cryptodisk_list
= newdev
;
885 return GRUB_ERR_NONE
;
889 grub_cryptodisk_get_by_uuid (const char *uuid
)
891 grub_cryptodisk_t dev
;
892 for (dev
= cryptodisk_list
; dev
!= NULL
; dev
= dev
->next
)
893 if (grub_strcasecmp (dev
->uuid
, uuid
) == 0)
899 grub_cryptodisk_get_by_source_disk (grub_disk_t disk
)
901 grub_cryptodisk_t dev
;
902 for (dev
= cryptodisk_list
; dev
!= NULL
; dev
= dev
->next
)
903 if (dev
->source_id
== disk
->id
&& dev
->source_dev_id
== disk
->dev
->id
)
904 if ((disk
->partition
&& grub_partition_get_start (disk
->partition
) == dev
->partition_start
) ||
905 (!disk
->partition
&& dev
->partition_start
== 0))
912 grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev
, const char *name
,
913 grub_disk_t source
, const char *cheat
)
915 newdev
->cheat
= grub_strdup (cheat
);
916 newdev
->source
= grub_strdup (name
);
917 if (!newdev
->source
|| !newdev
->cheat
)
919 grub_free (newdev
->source
);
920 grub_free (newdev
->cheat
);
924 newdev
->cheat_fd
= GRUB_UTIL_FD_INVALID
;
925 newdev
->source_id
= source
->id
;
926 newdev
->source_dev_id
= source
->dev
->id
;
927 newdev
->partition_start
= grub_partition_get_start (source
->partition
);
928 newdev
->id
= last_cryptodisk_id
++;
929 newdev
->next
= cryptodisk_list
;
930 cryptodisk_list
= newdev
;
932 return GRUB_ERR_NONE
;
936 grub_util_cryptodisk_get_abstraction (grub_disk_t disk
,
937 void (*cb
) (const char *val
, void *data
),
940 grub_cryptodisk_t dev
= (grub_cryptodisk_t
) disk
->data
;
942 cb ("cryptodisk", data
);
943 cb (dev
->modname
, data
);
946 cb (dev
->cipher
->cipher
->modname
, data
);
947 if (dev
->secondary_cipher
)
948 cb (dev
->secondary_cipher
->cipher
->modname
, data
);
949 if (dev
->essiv_cipher
)
950 cb (dev
->essiv_cipher
->cipher
->modname
, data
);
952 cb (dev
->hash
->modname
, data
);
954 cb (dev
->essiv_hash
->modname
, data
);
956 cb (dev
->iv_hash
->modname
, data
);
960 grub_util_cryptodisk_get_uuid (grub_disk_t disk
)
962 grub_cryptodisk_t dev
= (grub_cryptodisk_t
) disk
->data
;
968 static int check_boot
, have_it
;
969 static char *search_uuid
;
972 cryptodisk_close (grub_cryptodisk_t dev
)
974 grub_crypto_cipher_close (dev
->cipher
);
975 grub_crypto_cipher_close (dev
->secondary_cipher
);
976 grub_crypto_cipher_close (dev
->essiv_cipher
);
981 grub_cryptodisk_scan_device_real (const char *name
, grub_disk_t source
)
984 grub_cryptodisk_t dev
;
985 grub_cryptodisk_dev_t cr
;
987 dev
= grub_cryptodisk_get_by_source_disk (source
);
990 return GRUB_ERR_NONE
;
992 FOR_CRYPTODISK_DEVS (cr
)
994 dev
= cr
->scan (source
, search_uuid
, check_boot
);
1000 err
= cr
->recover_key (source
, dev
);
1003 cryptodisk_close (dev
);
1007 grub_cryptodisk_insert (dev
, name
, source
);
1011 return GRUB_ERR_NONE
;
1013 return GRUB_ERR_NONE
;
1017 #include <grub/util/misc.h>
1019 grub_cryptodisk_cheat_mount (const char *sourcedev
, const char *cheat
)
1022 grub_cryptodisk_t dev
;
1023 grub_cryptodisk_dev_t cr
;
1026 /* Try to open disk. */
1027 source
= grub_disk_open (sourcedev
);
1031 dev
= grub_cryptodisk_get_by_source_disk (source
);
1035 grub_disk_close (source
);
1036 return GRUB_ERR_NONE
;
1039 FOR_CRYPTODISK_DEVS (cr
)
1041 dev
= cr
->scan (source
, search_uuid
, check_boot
);
1047 grub_util_info ("cheatmounted %s (%s) at %s", sourcedev
, dev
->modname
,
1049 err
= grub_cryptodisk_cheat_insert (dev
, sourcedev
, source
, cheat
);
1050 grub_disk_close (source
);
1054 return GRUB_ERR_NONE
;
1057 grub_disk_close (source
);
1059 return GRUB_ERR_NONE
;
1064 grub_cryptodisk_scan_device (const char *name
,
1065 void *data
__attribute__ ((unused
)))
1070 /* Try to open disk. */
1071 source
= grub_disk_open (name
);
1074 grub_print_error ();
1078 err
= grub_cryptodisk_scan_device_real (name
, source
);
1080 grub_disk_close (source
);
1083 grub_print_error ();
1084 return have_it
&& search_uuid
? 1 : 0;
1088 grub_cmd_cryptomount (grub_extcmd_context_t ctxt
, int argc
, char **args
)
1090 struct grub_arg_list
*state
= ctxt
->state
;
1092 if (argc
< 1 && !state
[1].set
&& !state
[2].set
)
1093 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "device name required");
1098 grub_cryptodisk_t dev
;
1100 dev
= grub_cryptodisk_get_by_uuid (args
[0]);
1103 grub_dprintf ("cryptodisk",
1104 "already mounted as crypto%lu\n", dev
->id
);
1105 return GRUB_ERR_NONE
;
1108 check_boot
= state
[2].set
;
1109 search_uuid
= args
[0];
1110 grub_device_iterate (&grub_cryptodisk_scan_device
, NULL
);
1114 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "no such cryptodisk found");
1115 return GRUB_ERR_NONE
;
1117 else if (state
[1].set
|| (argc
== 0 && state
[2].set
))
1120 check_boot
= state
[2].set
;
1121 grub_device_iterate (&grub_cryptodisk_scan_device
, NULL
);
1123 return GRUB_ERR_NONE
;
1129 grub_cryptodisk_t dev
;
1131 char *disklast
= NULL
;
1135 check_boot
= state
[2].set
;
1137 len
= grub_strlen (diskname
);
1138 if (len
&& diskname
[0] == '(' && diskname
[len
- 1] == ')')
1140 disklast
= &diskname
[len
- 1];
1145 disk
= grub_disk_open (diskname
);
1153 dev
= grub_cryptodisk_get_by_source_disk (disk
);
1156 grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev
->id
);
1157 grub_disk_close (disk
);
1160 return GRUB_ERR_NONE
;
1163 err
= grub_cryptodisk_scan_device_real (diskname
, disk
);
1165 grub_disk_close (disk
);
1173 static struct grub_disk_dev grub_cryptodisk_dev
= {
1174 .name
= "cryptodisk",
1175 .id
= GRUB_DISK_DEVICE_CRYPTODISK_ID
,
1176 .disk_iterate
= grub_cryptodisk_iterate
,
1177 .disk_open
= grub_cryptodisk_open
,
1178 .disk_close
= grub_cryptodisk_close
,
1179 .disk_read
= grub_cryptodisk_read
,
1180 .disk_write
= grub_cryptodisk_write
,
1182 .disk_memberlist
= grub_cryptodisk_memberlist
,
1188 hex (grub_uint8_t val
)
1192 return 'a' + val
- 10;
1195 /* Open a file named NAME and initialize FILE. */
1197 luks_script_get (grub_size_t
*sz
)
1199 grub_cryptodisk_t i
;
1200 grub_size_t size
= 0;
1205 for (i
= cryptodisk_list
; i
!= NULL
; i
= i
->next
)
1206 if (grub_strcmp (i
->modname
, "luks") == 0)
1208 size
+= sizeof ("luks_mount ");
1209 size
+= grub_strlen (i
->uuid
);
1210 size
+= grub_strlen (i
->cipher
->cipher
->name
);
1213 size
+= grub_strlen (i
->essiv_hash
->name
);
1214 size
+= i
->keysize
* 2;
1217 ret
= grub_malloc (size
+ 1);
1223 for (i
= cryptodisk_list
; i
!= NULL
; i
= i
->next
)
1224 if (grub_strcmp (i
->modname
, "luks") == 0)
1228 ptr
= grub_stpcpy (ptr
, "luks_mount ");
1229 ptr
= grub_stpcpy (ptr
, i
->uuid
);
1231 grub_snprintf (ptr
, 21, "%" PRIuGRUB_UINT64_T
" ", i
->offset
);
1234 for (iptr
= i
->cipher
->cipher
->name
; *iptr
; iptr
++)
1235 *ptr
++ = grub_tolower (*iptr
);
1238 case GRUB_CRYPTODISK_MODE_ECB
:
1239 ptr
= grub_stpcpy (ptr
, "-ecb");
1241 case GRUB_CRYPTODISK_MODE_CBC
:
1242 ptr
= grub_stpcpy (ptr
, "-cbc");
1244 case GRUB_CRYPTODISK_MODE_PCBC
:
1245 ptr
= grub_stpcpy (ptr
, "-pcbc");
1247 case GRUB_CRYPTODISK_MODE_XTS
:
1248 ptr
= grub_stpcpy (ptr
, "-xts");
1250 case GRUB_CRYPTODISK_MODE_LRW
:
1251 ptr
= grub_stpcpy (ptr
, "-lrw");
1257 case GRUB_CRYPTODISK_MODE_IV_NULL
:
1258 ptr
= grub_stpcpy (ptr
, "-null");
1260 case GRUB_CRYPTODISK_MODE_IV_PLAIN
:
1261 ptr
= grub_stpcpy (ptr
, "-plain");
1263 case GRUB_CRYPTODISK_MODE_IV_PLAIN64
:
1264 ptr
= grub_stpcpy (ptr
, "-plain64");
1266 case GRUB_CRYPTODISK_MODE_IV_BENBI
:
1267 ptr
= grub_stpcpy (ptr
, "-benbi");
1269 case GRUB_CRYPTODISK_MODE_IV_ESSIV
:
1270 ptr
= grub_stpcpy (ptr
, "-essiv:");
1271 ptr
= grub_stpcpy (ptr
, i
->essiv_hash
->name
);
1273 case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64
:
1274 case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH
:
1278 for (j
= 0; j
< i
->keysize
; j
++)
1280 *ptr
++ = hex (i
->key
[j
] >> 4);
1281 *ptr
++ = hex (i
->key
[j
] & 0xf);
1290 struct grub_procfs_entry luks_script
=
1292 .name
= "luks_script",
1293 .get_contents
= luks_script_get
1296 static grub_extcmd_t cmd
;
1298 GRUB_MOD_INIT (cryptodisk
)
1300 grub_disk_dev_register (&grub_cryptodisk_dev
);
1301 cmd
= grub_register_extcmd ("cryptomount", grub_cmd_cryptomount
, 0,
1302 N_("SOURCE|-u UUID|-a|-b"),
1303 N_("Mount a crypto device."), options
);
1304 grub_procfs_register ("luks_script", &luks_script
);
1307 GRUB_MOD_FINI (cryptodisk
)
1309 grub_disk_dev_unregister (&grub_cryptodisk_dev
);
1310 cryptodisk_cleanup ();
1311 grub_unregister_extcmd (cmd
);
1312 grub_procfs_unregister (&luks_script
);