summaryrefslogtreecommitdiffstats
path: root/sys/boot/geli/geliboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/boot/geli/geliboot.c')
-rw-r--r--sys/boot/geli/geliboot.c68
1 files changed, 43 insertions, 25 deletions
diff --git a/sys/boot/geli/geliboot.c b/sys/boot/geli/geliboot.c
index becbc5f..df40c3b 100644
--- a/sys/boot/geli/geliboot.c
+++ b/sys/boot/geli/geliboot.c
@@ -73,30 +73,34 @@ geli_taste(int read_func(void *vdev, void *priv, off_t off, void *buf,
size_t bytes), struct dsk *dskp, daddr_t lastsector)
{
struct g_eli_metadata md;
- u_char buf[DEV_BSIZE];
+ u_char buf[DEV_GELIBOOT_BSIZE];
int error;
+ off_t alignsector;
- error = read_func(NULL, dskp, (off_t) lastsector * DEV_BSIZE, &buf,
- (size_t) DEV_BSIZE);
+ alignsector = (lastsector * DEV_BSIZE) &
+ ~(off_t)(DEV_GELIBOOT_BSIZE - 1);
+ error = read_func(NULL, dskp, alignsector, &buf, DEV_GELIBOOT_BSIZE);
if (error != 0) {
return (error);
}
- error = eli_metadata_decode(buf, &md);
+ /* Extract the last DEV_BSIZE bytes from the block. */
+ error = eli_metadata_decode(buf + (DEV_GELIBOOT_BSIZE - DEV_BSIZE),
+ &md);
if (error != 0) {
return (error);
}
- if ((md.md_flags & G_ELI_FLAG_ONETIME)) {
- /* Swap device, skip it */
+ if (!(md.md_flags & G_ELI_FLAG_GELIBOOT)) {
+ /* The GELIBOOT feature is not activated */
return (1);
}
- if (!(md.md_flags & G_ELI_FLAG_BOOT)) {
- /* Disk is not GELI boot device, skip it */
+ if ((md.md_flags & G_ELI_FLAG_ONETIME)) {
+ /* Swap device, skip it. */
return (1);
}
if (md.md_iterations < 0) {
- /* XXX TODO: Support loading key files */
- /* Disk does not have a passphrase, skip it */
+ /* XXX TODO: Support loading key files. */
+ /* Disk does not have a passphrase, skip it. */
return (1);
}
geli_e = malloc(sizeof(struct geli_entry));
@@ -143,7 +147,7 @@ geli_attach(struct dsk *dskp, const char *passphrase)
* Prepare Derived-Key from the user passphrase.
*/
if (geli_e->md.md_iterations < 0) {
- /* XXX TODO: Support loading key files */
+ /* XXX TODO: Support loading key files. */
return (1);
} else if (geli_e->md.md_iterations == 0) {
g_eli_crypto_hmac_update(&ctx, geli_e->md.md_salt,
@@ -151,8 +155,8 @@ geli_attach(struct dsk *dskp, const char *passphrase)
g_eli_crypto_hmac_update(&ctx, passphrase,
strlen(passphrase));
} else if (geli_e->md.md_iterations > 0) {
- printf("Calculating GELI Decryption Key disk%dp%d @ %lu "
- "iterations...\n", dskp->unit,
+ printf("Calculating GELI Decryption Key disk%dp%d @ %lu"
+ " iterations...\n", dskp->unit,
(dskp->slice > 0 ? dskp->slice : dskp->part),
geli_e->md.md_iterations);
u_char dkey[G_ELI_USERKEYLEN];
@@ -193,7 +197,7 @@ geli_attach(struct dsk *dskp, const char *passphrase)
}
bzero(&mkey, sizeof(mkey));
- /* Initialize the per-sector IV */
+ /* Initialize the per-sector IV. */
switch (geli_e->sc.sc_ealgo) {
case CRYPTO_AES_XTS:
break;
@@ -207,7 +211,7 @@ geli_attach(struct dsk *dskp, const char *passphrase)
return (0);
}
- /* Disk not found */
+ /* Disk not found. */
return (2);
}
@@ -229,35 +233,49 @@ geli_read(struct dsk *dskp, off_t offset, u_char *buf, size_t bytes)
u_char iv[G_ELI_IVKEYLEN];
u_char *pbuf;
int error;
- off_t os;
+ off_t dstoff;
uint64_t keyno;
- size_t n, nb;
+ size_t n, nsec, secsize;
struct g_eli_key gkey;
+ pbuf = buf;
SLIST_FOREACH_SAFE(geli_e, &geli_head, entries, geli_e_tmp) {
if (geli_same_device(geli_e, dskp) != 0) {
continue;
}
- nb = bytes / DEV_BSIZE;
- for (n = 0; n < nb; n++) {
- os = offset + (n * DEV_BSIZE);
- pbuf = buf + (n * DEV_BSIZE);
+ secsize = geli_e->sc.sc_sectorsize;
+ nsec = bytes / secsize;
+ if (nsec == 0) {
+ /*
+ * A read of less than the GELI sector size has been
+ * requested. The caller provided destination buffer may
+ * not be big enough to boost the read to a full sector,
+ * so just attempt to decrypt the truncated sector.
+ */
+ secsize = bytes;
+ nsec = 1;
+ }
+
+ for (n = 0, dstoff = offset; n < nsec; n++, dstoff += secsize) {
- g_eli_crypto_ivgen(&geli_e->sc, os, iv, G_ELI_IVKEYLEN);
+ g_eli_crypto_ivgen(&geli_e->sc, dstoff, iv,
+ G_ELI_IVKEYLEN);
- /* Get the key that corresponds to this offset */
- keyno = (os >> G_ELI_KEY_SHIFT) / DEV_BSIZE;
+ /* Get the key that corresponds to this offset. */
+ keyno = (dstoff >> G_ELI_KEY_SHIFT) / secsize;
g_eli_key_fill(&geli_e->sc, &gkey, keyno);
error = geliboot_crypt(geli_e->sc.sc_ealgo, 0, pbuf,
- DEV_BSIZE, gkey.gek_key, geli_e->sc.sc_ekeylen, iv);
+ secsize, gkey.gek_key,
+ geli_e->sc.sc_ekeylen, iv);
if (error != 0) {
bzero(&gkey, sizeof(gkey));
printf("Failed to decrypt in geli_read()!");
return (error);
}
+ pbuf += secsize;
}
bzero(&gkey, sizeof(gkey));
return (0);
OpenPOWER on IntegriCloud