2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2003,2007,2010,2011 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>
30 #include <grub/emu/hostdisk.h>
33 GRUB_MOD_LICENSE ("GPLv3+");
35 grub_cryptodisk_dev_t grub_cryptodisk_list
;
37 static const struct grub_arg_option options
[] =
39 {"uuid", 'u', 0, N_("Mount by UUID."), 0, 0},
40 /* TRANSLATORS: It's still restricted to cryptodisks only. */
41 {"all", 'a', 0, N_("Mount all."), 0, 0},
42 {"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0},
46 /* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is: */
47 #define GF_POLYNOM 0x87
48 static inline int GF_PER_SECTOR (const struct grub_cryptodisk
*dev
)
50 return 1U << (dev
->log_sector_size
- GRUB_CRYPTODISK_GF_LOG_BYTES
);
53 static grub_cryptodisk_t cryptodisk_list
= NULL
;
54 static grub_uint8_t last_cryptodisk_id
= 0;
57 gf_mul_x (grub_uint8_t
*g
)
59 int over
= 0, over2
= 0;
62 for (j
= 0; j
< GRUB_CRYPTODISK_GF_BYTES
; j
++)
64 over2
= !!(g
[j
] & 0x80);
75 gf_mul_x_be (grub_uint8_t
*g
)
77 int over
= 0, over2
= 0;
80 for (j
= (int) GRUB_CRYPTODISK_GF_BYTES
- 1; j
>= 0; j
--)
82 over2
= !!(g
[j
] & 0x80);
88 g
[GRUB_CRYPTODISK_GF_BYTES
- 1] ^= GF_POLYNOM
;
92 gf_mul_be (grub_uint8_t
*o
, const grub_uint8_t
*a
, const grub_uint8_t
*b
)
95 grub_uint8_t t
[GRUB_CRYPTODISK_GF_BYTES
];
96 grub_memset (o
, 0, GRUB_CRYPTODISK_GF_BYTES
);
97 grub_memcpy (t
, b
, GRUB_CRYPTODISK_GF_BYTES
);
98 for (i
= 0; i
< GRUB_CRYPTODISK_GF_SIZE
; i
++)
100 if (((a
[GRUB_CRYPTODISK_GF_BYTES
- i
/ GRUB_CHAR_BIT
- 1] >> (i
% GRUB_CHAR_BIT
))) & 1)
101 grub_crypto_xor (o
, o
, t
, GRUB_CRYPTODISK_GF_BYTES
);
106 static gcry_err_code_t
107 grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher
,
108 void *out
, void *in
, grub_size_t size
,
111 grub_uint8_t
*inptr
, *outptr
, *end
;
112 grub_uint8_t ivt
[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE
];
113 if (cipher
->cipher
->blocksize
> GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE
)
114 return GPG_ERR_INV_ARG
;
115 if (!cipher
->cipher
->decrypt
)
116 return GPG_ERR_NOT_SUPPORTED
;
117 if (size
% cipher
->cipher
->blocksize
!= 0)
118 return GPG_ERR_INV_ARG
;
119 end
= (grub_uint8_t
*) in
+ size
;
120 for (inptr
= in
, outptr
= out
; inptr
< end
;
121 inptr
+= cipher
->cipher
->blocksize
, outptr
+= cipher
->cipher
->blocksize
)
123 grub_memcpy (ivt
, inptr
, cipher
->cipher
->blocksize
);
124 cipher
->cipher
->decrypt (cipher
->ctx
, outptr
, inptr
);
125 grub_crypto_xor (outptr
, outptr
, iv
, cipher
->cipher
->blocksize
);
126 grub_crypto_xor (iv
, ivt
, outptr
, cipher
->cipher
->blocksize
);
128 return GPG_ERR_NO_ERROR
;
131 static gcry_err_code_t
132 grub_crypto_pcbc_encrypt (grub_crypto_cipher_handle_t cipher
,
133 void *out
, void *in
, grub_size_t size
,
136 grub_uint8_t
*inptr
, *outptr
, *end
;
137 grub_uint8_t ivt
[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE
];
138 if (cipher
->cipher
->blocksize
> GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE
)
139 return GPG_ERR_INV_ARG
;
140 if (!cipher
->cipher
->decrypt
)
141 return GPG_ERR_NOT_SUPPORTED
;
142 if (size
% cipher
->cipher
->blocksize
!= 0)
143 return GPG_ERR_INV_ARG
;
144 end
= (grub_uint8_t
*) in
+ size
;
145 for (inptr
= in
, outptr
= out
; inptr
< end
;
146 inptr
+= cipher
->cipher
->blocksize
, outptr
+= cipher
->cipher
->blocksize
)
148 grub_memcpy (ivt
, inptr
, cipher
->cipher
->blocksize
);
149 grub_crypto_xor (outptr
, outptr
, iv
, cipher
->cipher
->blocksize
);
150 cipher
->cipher
->encrypt (cipher
->ctx
, outptr
, inptr
);
151 grub_crypto_xor (iv
, ivt
, outptr
, cipher
->cipher
->blocksize
);
153 return GPG_ERR_NO_ERROR
;
158 grub_uint8_t low
[GRUB_CRYPTODISK_GF_BYTES
];
159 grub_uint8_t high
[GRUB_CRYPTODISK_GF_BYTES
];
160 grub_uint8_t low_byte
, low_byte_c
;
164 generate_lrw_sector (struct lrw_sector
*sec
,
165 const struct grub_cryptodisk
*dev
,
166 const grub_uint8_t
*iv
)
168 grub_uint8_t idx
[GRUB_CRYPTODISK_GF_BYTES
];
171 grub_memcpy (idx
, iv
, GRUB_CRYPTODISK_GF_BYTES
);
172 sec
->low_byte
= (idx
[GRUB_CRYPTODISK_GF_BYTES
- 1]
173 & (GF_PER_SECTOR (dev
) - 1));
174 sec
->low_byte_c
= (((GF_PER_SECTOR (dev
) - 1) & ~sec
->low_byte
) + 1);
175 idx
[GRUB_CRYPTODISK_GF_BYTES
- 1] &= ~(GF_PER_SECTOR (dev
) - 1);
176 gf_mul_be (sec
->low
, dev
->lrw_key
, idx
);
180 c
= idx
[GRUB_CRYPTODISK_GF_BYTES
- 1] + GF_PER_SECTOR (dev
);
183 for (j
= GRUB_CRYPTODISK_GF_BYTES
- 2; j
>= 0; j
--)
190 idx
[GRUB_CRYPTODISK_GF_BYTES
- 1] = c
;
191 gf_mul_be (sec
->high
, dev
->lrw_key
, idx
);
194 static void __attribute__ ((unused
))
195 lrw_xor (const struct lrw_sector
*sec
,
196 const struct grub_cryptodisk
*dev
,
201 for (i
= 0; i
< sec
->low_byte_c
* GRUB_CRYPTODISK_GF_BYTES
;
202 i
+= GRUB_CRYPTODISK_GF_BYTES
)
203 grub_crypto_xor (b
+ i
, b
+ i
, sec
->low
, GRUB_CRYPTODISK_GF_BYTES
);
204 grub_crypto_xor (b
, b
, dev
->lrw_precalc
+ GRUB_CRYPTODISK_GF_BYTES
* sec
->low_byte
,
205 sec
->low_byte_c
* GRUB_CRYPTODISK_GF_BYTES
);
209 for (i
= sec
->low_byte_c
* GRUB_CRYPTODISK_GF_BYTES
;
210 i
< (1U << dev
->log_sector_size
); i
+= GRUB_CRYPTODISK_GF_BYTES
)
211 grub_crypto_xor (b
+ i
, b
+ i
, sec
->high
, GRUB_CRYPTODISK_GF_BYTES
);
212 grub_crypto_xor (b
+ sec
->low_byte_c
* GRUB_CRYPTODISK_GF_BYTES
,
213 b
+ sec
->low_byte_c
* GRUB_CRYPTODISK_GF_BYTES
,
214 dev
->lrw_precalc
, sec
->low_byte
* GRUB_CRYPTODISK_GF_BYTES
);
217 static gcry_err_code_t
218 grub_cryptodisk_endecrypt (struct grub_cryptodisk
*dev
,
219 grub_uint8_t
* data
, grub_size_t len
,
220 grub_disk_addr_t sector
, int do_encrypt
)
225 if (dev
->cipher
->cipher
->blocksize
> GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE
)
226 return GPG_ERR_INV_ARG
;
228 /* The only mode without IV. */
229 if (dev
->mode
== GRUB_CRYPTODISK_MODE_ECB
&& !dev
->rekey
)
230 return (do_encrypt
? grub_crypto_ecb_encrypt (dev
->cipher
, data
, data
, len
)
231 : grub_crypto_ecb_decrypt (dev
->cipher
, data
, data
, len
));
233 for (i
= 0; i
< len
; i
+= (1U << dev
->log_sector_size
))
235 grub_size_t sz
= ((dev
->cipher
->cipher
->blocksize
236 + sizeof (grub_uint32_t
) - 1)
237 / sizeof (grub_uint32_t
));
238 grub_uint32_t iv
[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE
+ 3) / 4];
242 grub_uint64_t zone
= sector
>> dev
->rekey_shift
;
243 if (zone
!= dev
->last_rekey
)
245 err
= dev
->rekey (dev
, zone
);
248 dev
->last_rekey
= zone
;
252 grub_memset (iv
, 0, sizeof (iv
));
253 switch (dev
->mode_iv
)
255 case GRUB_CRYPTODISK_MODE_IV_NULL
:
257 case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH
:
262 ctx
= grub_zalloc (dev
->iv_hash
->contextsize
);
264 return GPG_ERR_OUT_OF_MEMORY
;
266 tmp
= grub_cpu_to_le64 (sector
<< dev
->log_sector_size
);
267 dev
->iv_hash
->init (ctx
);
268 dev
->iv_hash
->write (ctx
, dev
->iv_prefix
, dev
->iv_prefix_len
);
269 dev
->iv_hash
->write (ctx
, &tmp
, sizeof (tmp
));
270 dev
->iv_hash
->final (ctx
);
272 grub_memcpy (iv
, dev
->iv_hash
->read (ctx
), sizeof (iv
));
276 case GRUB_CRYPTODISK_MODE_IV_PLAIN64
:
277 iv
[1] = grub_cpu_to_le32 (sector
>> 32);
278 case GRUB_CRYPTODISK_MODE_IV_PLAIN
:
279 iv
[0] = grub_cpu_to_le32 (sector
& 0xFFFFFFFF);
281 case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64
:
282 iv
[1] = grub_cpu_to_le32 (sector
>> (32 - dev
->log_sector_size
));
283 iv
[0] = grub_cpu_to_le32 ((sector
<< dev
->log_sector_size
)
286 case GRUB_CRYPTODISK_MODE_IV_BENBI
:
288 grub_uint64_t num
= (sector
<< dev
->benbi_log
) + 1;
289 iv
[sz
- 2] = grub_cpu_to_be32 (num
>> 32);
290 iv
[sz
- 1] = grub_cpu_to_be32 (num
& 0xFFFFFFFF);
293 case GRUB_CRYPTODISK_MODE_IV_ESSIV
:
294 iv
[0] = grub_cpu_to_le32 (sector
& 0xFFFFFFFF);
295 err
= grub_crypto_ecb_encrypt (dev
->essiv_cipher
, iv
, iv
,
296 dev
->cipher
->cipher
->blocksize
);
303 case GRUB_CRYPTODISK_MODE_CBC
:
305 err
= grub_crypto_cbc_encrypt (dev
->cipher
, data
+ i
, data
+ i
,
306 (1U << dev
->log_sector_size
), iv
);
308 err
= grub_crypto_cbc_decrypt (dev
->cipher
, data
+ i
, data
+ i
,
309 (1U << dev
->log_sector_size
), iv
);
314 case GRUB_CRYPTODISK_MODE_PCBC
:
316 err
= grub_crypto_pcbc_encrypt (dev
->cipher
, data
+ i
, data
+ i
,
317 (1U << dev
->log_sector_size
), iv
);
319 err
= grub_crypto_pcbc_decrypt (dev
->cipher
, data
+ i
, data
+ i
,
320 (1U << dev
->log_sector_size
), iv
);
324 case GRUB_CRYPTODISK_MODE_XTS
:
327 err
= grub_crypto_ecb_encrypt (dev
->secondary_cipher
, iv
, iv
,
328 dev
->cipher
->cipher
->blocksize
);
332 for (j
= 0; j
< (1U << dev
->log_sector_size
);
333 j
+= dev
->cipher
->cipher
->blocksize
)
335 grub_crypto_xor (data
+ i
+ j
, data
+ i
+ j
, iv
,
336 dev
->cipher
->cipher
->blocksize
);
338 err
= grub_crypto_ecb_encrypt (dev
->cipher
, data
+ i
+ j
,
340 dev
->cipher
->cipher
->blocksize
);
342 err
= grub_crypto_ecb_decrypt (dev
->cipher
, data
+ i
+ j
,
344 dev
->cipher
->cipher
->blocksize
);
347 grub_crypto_xor (data
+ i
+ j
, data
+ i
+ j
, iv
,
348 dev
->cipher
->cipher
->blocksize
);
349 gf_mul_x ((grub_uint8_t
*) iv
);
353 case GRUB_CRYPTODISK_MODE_LRW
:
355 struct lrw_sector sec
;
357 generate_lrw_sector (&sec
, dev
, (grub_uint8_t
*) iv
);
358 lrw_xor (&sec
, dev
, data
+ i
);
361 err
= grub_crypto_ecb_encrypt (dev
->cipher
, data
+ i
,
363 (1U << dev
->log_sector_size
));
365 err
= grub_crypto_ecb_decrypt (dev
->cipher
, data
+ i
,
367 (1U << dev
->log_sector_size
));
370 lrw_xor (&sec
, dev
, data
+ i
);
373 case GRUB_CRYPTODISK_MODE_ECB
:
375 err
= grub_crypto_ecb_encrypt (dev
->cipher
, data
+ i
, data
+ i
,
376 (1U << dev
->log_sector_size
));
378 err
= grub_crypto_ecb_decrypt (dev
->cipher
, data
+ i
, data
+ i
,
379 (1U << dev
->log_sector_size
));
384 return GPG_ERR_NOT_IMPLEMENTED
;
388 return GPG_ERR_NO_ERROR
;
392 grub_cryptodisk_decrypt (struct grub_cryptodisk
*dev
,
393 grub_uint8_t
* data
, grub_size_t len
,
394 grub_disk_addr_t sector
)
396 return grub_cryptodisk_endecrypt (dev
, data
, len
, sector
, 0);
400 grub_cryptodisk_setkey (grub_cryptodisk_t dev
, grub_uint8_t
*key
, grub_size_t keysize
)
405 real_keysize
= keysize
;
406 if (dev
->mode
== GRUB_CRYPTODISK_MODE_XTS
)
408 if (dev
->mode
== GRUB_CRYPTODISK_MODE_LRW
)
409 real_keysize
-= dev
->cipher
->cipher
->blocksize
;
411 /* Set the PBKDF2 output as the cipher key. */
412 err
= grub_crypto_cipher_set_key (dev
->cipher
, key
, real_keysize
);
415 grub_memcpy (dev
->key
, key
, keysize
);
416 dev
->keysize
= keysize
;
418 /* Configure ESSIV if necessary. */
419 if (dev
->mode_iv
== GRUB_CRYPTODISK_MODE_IV_ESSIV
)
421 grub_size_t essiv_keysize
= dev
->essiv_hash
->mdlen
;
422 grub_uint8_t hashed_key
[GRUB_CRYPTO_MAX_MDLEN
];
423 if (essiv_keysize
> GRUB_CRYPTO_MAX_MDLEN
)
424 return GPG_ERR_INV_ARG
;
426 grub_crypto_hash (dev
->essiv_hash
, hashed_key
, key
, keysize
);
427 err
= grub_crypto_cipher_set_key (dev
->essiv_cipher
,
428 hashed_key
, essiv_keysize
);
432 if (dev
->mode
== GRUB_CRYPTODISK_MODE_XTS
)
434 err
= grub_crypto_cipher_set_key (dev
->secondary_cipher
,
441 if (dev
->mode
== GRUB_CRYPTODISK_MODE_LRW
)
444 grub_uint8_t idx
[GRUB_CRYPTODISK_GF_BYTES
];
446 grub_free (dev
->lrw_precalc
);
447 grub_memcpy (dev
->lrw_key
, key
+ real_keysize
,
448 dev
->cipher
->cipher
->blocksize
);
449 dev
->lrw_precalc
= grub_malloc ((1U << dev
->log_sector_size
));
450 if (!dev
->lrw_precalc
)
451 return GPG_ERR_OUT_OF_MEMORY
;
452 grub_memset (idx
, 0, GRUB_CRYPTODISK_GF_BYTES
);
453 for (i
= 0; i
< (1U << dev
->log_sector_size
);
454 i
+= GRUB_CRYPTODISK_GF_BYTES
)
456 idx
[GRUB_CRYPTODISK_GF_BYTES
- 1] = i
/ GRUB_CRYPTODISK_GF_BYTES
;
457 gf_mul_be (dev
->lrw_precalc
+ i
, idx
, dev
->lrw_key
);
460 return GPG_ERR_NO_ERROR
;
464 grub_cryptodisk_iterate (grub_disk_dev_iterate_hook_t hook
, void *hook_data
,
465 grub_disk_pull_t pull
)
469 if (pull
!= GRUB_DISK_PULL_NONE
)
472 for (i
= cryptodisk_list
; i
!= NULL
; i
= i
->next
)
475 grub_snprintf (buf
, sizeof (buf
), "crypto%lu", i
->id
);
476 if (hook (buf
, hook_data
))
480 return GRUB_ERR_NONE
;
484 grub_cryptodisk_open (const char *name
, grub_disk_t disk
)
486 grub_cryptodisk_t dev
;
488 if (grub_memcmp (name
, "crypto", sizeof ("crypto") - 1) != 0)
489 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "No such device");
491 if (grub_memcmp (name
, "cryptouuid/", sizeof ("cryptouuid/") - 1) == 0)
493 for (dev
= cryptodisk_list
; dev
!= NULL
; dev
= dev
->next
)
494 if (grub_strcasecmp (name
+ sizeof ("cryptouuid/") - 1, dev
->uuid
) == 0)
499 unsigned long id
= grub_strtoul (name
+ sizeof ("crypto") - 1, 0, 0);
501 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "No such device");
502 /* Search for requested device in the list of CRYPTODISK devices. */
503 for (dev
= cryptodisk_list
; dev
!= NULL
; dev
= dev
->next
)
508 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "No such device");
510 disk
->log_sector_size
= dev
->log_sector_size
;
515 if (!GRUB_UTIL_FD_IS_VALID (dev
->cheat_fd
))
516 dev
->cheat_fd
= grub_util_fd_open (dev
->cheat
, GRUB_UTIL_FD_O_RDONLY
);
517 if (!GRUB_UTIL_FD_IS_VALID (dev
->cheat_fd
))
518 return grub_error (GRUB_ERR_IO
, N_("cannot open `%s': %s"),
519 dev
->cheat
, grub_util_fd_strerror ());
523 if (!dev
->source_disk
)
525 grub_dprintf ("cryptodisk", "Opening device %s\n", name
);
526 /* Try to open the source disk and populate the requested disk. */
527 dev
->source_disk
= grub_disk_open (dev
->source
);
528 if (!dev
->source_disk
)
533 disk
->total_sectors
= dev
->total_length
;
534 disk
->max_agglomerate
= GRUB_DISK_MAX_MAX_AGGLOMERATE
;
537 return GRUB_ERR_NONE
;
541 grub_cryptodisk_close (grub_disk_t disk
)
543 grub_cryptodisk_t dev
= (grub_cryptodisk_t
) disk
->data
;
544 grub_dprintf ("cryptodisk", "Closing disk\n");
553 grub_util_fd_close (dev
->cheat_fd
);
554 dev
->cheat_fd
= GRUB_UTIL_FD_INVALID
;
557 grub_disk_close (dev
->source_disk
);
558 dev
->source_disk
= NULL
;
562 grub_cryptodisk_read (grub_disk_t disk
, grub_disk_addr_t sector
,
563 grub_size_t size
, char *buf
)
565 grub_cryptodisk_t dev
= (grub_cryptodisk_t
) disk
->data
;
567 gcry_err_code_t gcry_err
;
573 r
= grub_util_fd_seek (dev
->cheat_fd
, sector
<< disk
->log_sector_size
);
575 return grub_error (GRUB_ERR_BAD_DEVICE
, N_("cannot seek `%s': %s"),
576 dev
->cheat
, grub_util_fd_strerror ());
577 if (grub_util_fd_read (dev
->cheat_fd
, buf
, size
<< disk
->log_sector_size
)
578 != (ssize_t
) (size
<< disk
->log_sector_size
))
579 return grub_error (GRUB_ERR_READ_ERROR
, N_("cannot read `%s': %s"),
580 dev
->cheat
, grub_util_fd_strerror ());
581 return GRUB_ERR_NONE
;
585 grub_dprintf ("cryptodisk",
586 "Reading %" PRIuGRUB_SIZE
" sectors from sector 0x%"
587 PRIxGRUB_UINT64_T
" with offset of %" PRIuGRUB_UINT64_T
"\n",
588 size
, sector
, dev
->offset
);
590 err
= grub_disk_read (dev
->source_disk
,
591 (sector
<< (disk
->log_sector_size
592 - GRUB_DISK_SECTOR_BITS
)) + dev
->offset
, 0,
593 size
<< disk
->log_sector_size
, buf
);
596 grub_dprintf ("cryptodisk", "grub_disk_read failed with error %d\n", err
);
599 gcry_err
= grub_cryptodisk_endecrypt (dev
, (grub_uint8_t
*) buf
,
600 size
<< disk
->log_sector_size
,
602 return grub_crypto_gcry_error (gcry_err
);
606 grub_cryptodisk_write (grub_disk_t disk
, grub_disk_addr_t sector
,
607 grub_size_t size
, const char *buf
)
609 grub_cryptodisk_t dev
= (grub_cryptodisk_t
) disk
->data
;
610 gcry_err_code_t gcry_err
;
618 r
= grub_util_fd_seek (dev
->cheat_fd
, sector
<< disk
->log_sector_size
);
620 return grub_error (GRUB_ERR_BAD_DEVICE
, N_("cannot seek `%s': %s"),
621 dev
->cheat
, grub_util_fd_strerror ());
622 if (grub_util_fd_write (dev
->cheat_fd
, buf
, size
<< disk
->log_sector_size
)
623 != (ssize_t
) (size
<< disk
->log_sector_size
))
624 return grub_error (GRUB_ERR_READ_ERROR
, N_("cannot read `%s': %s"),
625 dev
->cheat
, grub_util_fd_strerror ());
626 return GRUB_ERR_NONE
;
630 tmp
= grub_malloc (size
<< disk
->log_sector_size
);
633 grub_memcpy (tmp
, buf
, size
<< disk
->log_sector_size
);
635 grub_dprintf ("cryptodisk",
636 "Writing %" PRIuGRUB_SIZE
" sectors to sector 0x%"
637 PRIxGRUB_UINT64_T
" with offset of %" PRIuGRUB_UINT64_T
"\n",
638 size
, sector
, dev
->offset
);
640 gcry_err
= grub_cryptodisk_endecrypt (dev
, (grub_uint8_t
*) tmp
,
641 size
<< disk
->log_sector_size
,
646 return grub_crypto_gcry_error (gcry_err
);
649 /* Since ->write was called so disk.mod is loaded but be paranoid */
651 if (grub_disk_write_weak
)
652 err
= grub_disk_write_weak (dev
->source_disk
,
653 (sector
<< (disk
->log_sector_size
654 - GRUB_DISK_SECTOR_BITS
))
656 0, size
<< disk
->log_sector_size
, tmp
);
658 err
= grub_error (GRUB_ERR_BUG
, "disk.mod not loaded");
664 static grub_disk_memberlist_t
665 grub_cryptodisk_memberlist (grub_disk_t disk
)
667 grub_cryptodisk_t dev
= (grub_cryptodisk_t
) disk
->data
;
668 grub_disk_memberlist_t list
= NULL
;
670 list
= grub_malloc (sizeof (*list
));
673 list
->disk
= dev
->source_disk
;
682 cryptodisk_cleanup (void)
685 grub_cryptodisk_t dev
= cryptodisk_list
;
686 grub_cryptodisk_t tmp
;
690 grub_free (dev
->source
);
691 grub_free (dev
->cipher
);
692 grub_free (dev
->secondary_cipher
);
693 grub_free (dev
->essiv_cipher
);
702 grub_cryptodisk_insert (grub_cryptodisk_t newdev
, const char *name
,
705 newdev
->source
= grub_strdup (name
);
712 newdev
->id
= last_cryptodisk_id
++;
713 newdev
->source_id
= source
->id
;
714 newdev
->source_dev_id
= source
->dev
->id
;
715 newdev
->next
= cryptodisk_list
;
716 cryptodisk_list
= newdev
;
718 return GRUB_ERR_NONE
;
722 grub_cryptodisk_get_by_uuid (const char *uuid
)
724 grub_cryptodisk_t dev
;
725 for (dev
= cryptodisk_list
; dev
!= NULL
; dev
= dev
->next
)
726 if (grub_strcasecmp (dev
->uuid
, uuid
) == 0)
732 grub_cryptodisk_get_by_source_disk (grub_disk_t disk
)
734 grub_cryptodisk_t dev
;
735 for (dev
= cryptodisk_list
; dev
!= NULL
; dev
= dev
->next
)
736 if (dev
->source_id
== disk
->id
&& dev
->source_dev_id
== disk
->dev
->id
)
743 grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev
, const char *name
,
744 grub_disk_t source
, const char *cheat
)
746 newdev
->cheat
= grub_strdup (cheat
);
747 newdev
->source
= grub_strdup (name
);
748 if (!newdev
->source
|| !newdev
->cheat
)
750 grub_free (newdev
->source
);
751 grub_free (newdev
->cheat
);
755 newdev
->cheat_fd
= GRUB_UTIL_FD_INVALID
;
756 newdev
->source_id
= source
->id
;
757 newdev
->source_dev_id
= source
->dev
->id
;
758 newdev
->id
= last_cryptodisk_id
++;
759 newdev
->next
= cryptodisk_list
;
760 cryptodisk_list
= newdev
;
762 return GRUB_ERR_NONE
;
766 grub_util_cryptodisk_get_abstraction (grub_disk_t disk
,
767 void (*cb
) (const char *val
, void *data
),
770 grub_cryptodisk_t dev
= (grub_cryptodisk_t
) disk
->data
;
772 cb ("cryptodisk", data
);
773 cb (dev
->modname
, data
);
776 cb (dev
->cipher
->cipher
->modname
, data
);
777 if (dev
->secondary_cipher
)
778 cb (dev
->secondary_cipher
->cipher
->modname
, data
);
779 if (dev
->essiv_cipher
)
780 cb (dev
->essiv_cipher
->cipher
->modname
, data
);
782 cb (dev
->hash
->modname
, data
);
784 cb (dev
->essiv_hash
->modname
, data
);
786 cb (dev
->iv_hash
->modname
, data
);
790 grub_util_cryptodisk_get_uuid (grub_disk_t disk
)
792 grub_cryptodisk_t dev
= (grub_cryptodisk_t
) disk
->data
;
798 static int check_boot
, have_it
;
799 static char *search_uuid
;
802 cryptodisk_close (grub_cryptodisk_t dev
)
804 grub_crypto_cipher_close (dev
->cipher
);
805 grub_crypto_cipher_close (dev
->secondary_cipher
);
806 grub_crypto_cipher_close (dev
->essiv_cipher
);
811 grub_cryptodisk_scan_device_real (const char *name
, grub_disk_t source
)
814 grub_cryptodisk_t dev
;
815 grub_cryptodisk_dev_t cr
;
817 dev
= grub_cryptodisk_get_by_source_disk (source
);
820 return GRUB_ERR_NONE
;
822 FOR_CRYPTODISK_DEVS (cr
)
824 dev
= cr
->scan (source
, search_uuid
, check_boot
);
830 err
= cr
->recover_key (source
, dev
);
833 cryptodisk_close (dev
);
837 grub_cryptodisk_insert (dev
, name
, source
);
841 return GRUB_ERR_NONE
;
843 return GRUB_ERR_NONE
;
847 #include <grub/util/misc.h>
849 grub_cryptodisk_cheat_mount (const char *sourcedev
, const char *cheat
)
852 grub_cryptodisk_t dev
;
853 grub_cryptodisk_dev_t cr
;
856 /* Try to open disk. */
857 source
= grub_disk_open (sourcedev
);
861 dev
= grub_cryptodisk_get_by_source_disk (source
);
865 grub_disk_close (source
);
866 return GRUB_ERR_NONE
;
869 FOR_CRYPTODISK_DEVS (cr
)
871 dev
= cr
->scan (source
, search_uuid
, check_boot
);
877 grub_util_info ("cheatmounted %s (%s) at %s", sourcedev
, dev
->modname
,
879 err
= grub_cryptodisk_cheat_insert (dev
, sourcedev
, source
, cheat
);
880 grub_disk_close (source
);
884 return GRUB_ERR_NONE
;
887 grub_disk_close (source
);
889 return GRUB_ERR_NONE
;
894 grub_cryptodisk_scan_device (const char *name
,
895 void *data
__attribute__ ((unused
)))
900 /* Try to open disk. */
901 source
= grub_disk_open (name
);
908 err
= grub_cryptodisk_scan_device_real (name
, source
);
910 grub_disk_close (source
);
914 return have_it
&& search_uuid
? 1 : 0;
918 grub_cmd_cryptomount (grub_extcmd_context_t ctxt
, int argc
, char **args
)
920 struct grub_arg_list
*state
= ctxt
->state
;
922 if (argc
< 1 && !state
[1].set
&& !state
[2].set
)
923 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "device name required");
928 grub_cryptodisk_t dev
;
930 dev
= grub_cryptodisk_get_by_uuid (args
[0]);
933 grub_dprintf ("cryptodisk",
934 "already mounted as crypto%lu\n", dev
->id
);
935 return GRUB_ERR_NONE
;
938 check_boot
= state
[2].set
;
939 search_uuid
= args
[0];
940 grub_device_iterate (&grub_cryptodisk_scan_device
, NULL
);
944 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "no such cryptodisk found");
945 return GRUB_ERR_NONE
;
947 else if (state
[1].set
|| (argc
== 0 && state
[2].set
))
950 check_boot
= state
[2].set
;
951 grub_device_iterate (&grub_cryptodisk_scan_device
, NULL
);
953 return GRUB_ERR_NONE
;
959 grub_cryptodisk_t dev
;
964 check_boot
= state
[2].set
;
966 if (diskname
[0] == '(' && *(disklast
= &diskname
[grub_strlen (diskname
) - 1]) == ')')
969 disk
= grub_disk_open (diskname
+ 1);
973 disk
= grub_disk_open (diskname
);
977 dev
= grub_cryptodisk_get_by_source_disk (disk
);
980 grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev
->id
);
981 grub_disk_close (disk
);
982 return GRUB_ERR_NONE
;
985 err
= grub_cryptodisk_scan_device_real (args
[0], disk
);
987 grub_disk_close (disk
);
993 static struct grub_disk_dev grub_cryptodisk_dev
= {
994 .name
= "cryptodisk",
995 .id
= GRUB_DISK_DEVICE_CRYPTODISK_ID
,
996 .iterate
= grub_cryptodisk_iterate
,
997 .open
= grub_cryptodisk_open
,
998 .close
= grub_cryptodisk_close
,
999 .read
= grub_cryptodisk_read
,
1000 .write
= grub_cryptodisk_write
,
1002 .memberlist
= grub_cryptodisk_memberlist
,
1008 hex (grub_uint8_t val
)
1012 return 'a' + val
- 10;
1015 /* Open a file named NAME and initialize FILE. */
1017 luks_script_get (grub_size_t
*sz
)
1019 grub_cryptodisk_t i
;
1020 grub_size_t size
= 0;
1025 for (i
= cryptodisk_list
; i
!= NULL
; i
= i
->next
)
1026 if (grub_strcmp (i
->modname
, "luks") == 0)
1028 size
+= sizeof ("luks_mount ");
1029 size
+= grub_strlen (i
->uuid
);
1030 size
+= grub_strlen (i
->cipher
->cipher
->name
);
1033 size
+= grub_strlen (i
->essiv_hash
->name
);
1034 size
+= i
->keysize
* 2;
1037 ret
= grub_malloc (size
+ 1);
1043 for (i
= cryptodisk_list
; i
!= NULL
; i
= i
->next
)
1044 if (grub_strcmp (i
->modname
, "luks") == 0)
1048 ptr
= grub_stpcpy (ptr
, "luks_mount ");
1049 ptr
= grub_stpcpy (ptr
, i
->uuid
);
1051 grub_snprintf (ptr
, 21, "%" PRIuGRUB_UINT64_T
" ", i
->offset
);
1054 for (iptr
= i
->cipher
->cipher
->name
; *iptr
; iptr
++)
1055 *ptr
++ = grub_tolower (*iptr
);
1058 case GRUB_CRYPTODISK_MODE_ECB
:
1059 ptr
= grub_stpcpy (ptr
, "-ecb");
1061 case GRUB_CRYPTODISK_MODE_CBC
:
1062 ptr
= grub_stpcpy (ptr
, "-cbc");
1064 case GRUB_CRYPTODISK_MODE_PCBC
:
1065 ptr
= grub_stpcpy (ptr
, "-pcbc");
1067 case GRUB_CRYPTODISK_MODE_XTS
:
1068 ptr
= grub_stpcpy (ptr
, "-xts");
1070 case GRUB_CRYPTODISK_MODE_LRW
:
1071 ptr
= grub_stpcpy (ptr
, "-lrw");
1077 case GRUB_CRYPTODISK_MODE_IV_NULL
:
1078 ptr
= grub_stpcpy (ptr
, "-null");
1080 case GRUB_CRYPTODISK_MODE_IV_PLAIN
:
1081 ptr
= grub_stpcpy (ptr
, "-plain");
1083 case GRUB_CRYPTODISK_MODE_IV_PLAIN64
:
1084 ptr
= grub_stpcpy (ptr
, "-plain64");
1086 case GRUB_CRYPTODISK_MODE_IV_BENBI
:
1087 ptr
= grub_stpcpy (ptr
, "-benbi");
1089 case GRUB_CRYPTODISK_MODE_IV_ESSIV
:
1090 ptr
= grub_stpcpy (ptr
, "-essiv:");
1091 ptr
= grub_stpcpy (ptr
, i
->essiv_hash
->name
);
1093 case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64
:
1094 case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH
:
1098 for (j
= 0; j
< i
->keysize
; j
++)
1100 *ptr
++ = hex (i
->key
[j
] >> 4);
1101 *ptr
++ = hex (i
->key
[j
] & 0xf);
1110 struct grub_procfs_entry luks_script
=
1112 .name
= "luks_script",
1113 .get_contents
= luks_script_get
1116 static grub_extcmd_t cmd
;
1118 GRUB_MOD_INIT (cryptodisk
)
1120 grub_disk_dev_register (&grub_cryptodisk_dev
);
1121 cmd
= grub_register_extcmd ("cryptomount", grub_cmd_cryptomount
, 0,
1122 N_("SOURCE|-u UUID|-a|-b"),
1123 N_("Mount a crypto device."), options
);
1124 grub_procfs_register ("luks_script", &luks_script
);
1127 GRUB_MOD_FINI (cryptodisk
)
1129 grub_disk_dev_unregister (&grub_cryptodisk_dev
);
1130 cryptodisk_cleanup ();
1131 grub_procfs_unregister (&luks_script
);