Page MenuHomeFreeBSD

D10236.id26933.diff
No OneTemporary

D10236.id26933.diff

Index: sys/boot/geli/geliboot.h
===================================================================
--- sys/boot/geli/geliboot.h
+++ sys/boot/geli/geliboot.h
@@ -53,7 +53,7 @@
void *buf, size_t bytes), struct dsk *dsk, daddr_t lastsector);
int geli_attach(struct dsk *dskp, const char *passphrase, const u_char *mkeyp);
int is_geli(struct dsk *dsk);
-int geli_read(struct dsk *dsk, off_t offset, u_char *buf, size_t bytes);
+int geli_io(struct dsk *dsk, int enc, off_t offset, u_char *buf, size_t bytes);
int geli_decrypt(u_int algo, u_char *data, size_t datasize,
const u_char *key, size_t keysize, const uint8_t* iv);
int geli_havekey(struct dsk *dskp);
Index: sys/boot/geli/geliboot.c
===================================================================
--- sys/boot/geli/geliboot.c
+++ sys/boot/geli/geliboot.c
@@ -334,7 +334,7 @@
}
int
-geli_read(struct dsk *dskp, off_t offset, u_char *buf, size_t bytes)
+geli_io(struct dsk *dskp, int enc, off_t offset, u_char *buf, size_t bytes)
{
u_char iv[G_ELI_IVKEYLEN];
u_char *pbuf;
@@ -372,13 +372,14 @@
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,
+ error = geliboot_crypt(geli_e->sc.sc_ealgo, enc, pbuf,
secsize, gkey.gek_key,
geli_e->sc.sc_ekeylen, iv);
if (error != 0) {
explicit_bzero(&gkey, sizeof(gkey));
- printf("Failed to decrypt in geli_read()!");
+ printf("Failed to %s in geli_io()!",
+ enc ? "encrypt" : "decrypt");
return (error);
}
pbuf += secsize;
Index: sys/boot/i386/gptboot/gptboot.c
===================================================================
--- sys/boot/i386/gptboot/gptboot.c
+++ sys/boot/i386/gptboot/gptboot.c
@@ -603,7 +603,7 @@
#ifdef LOADER_GELI_SUPPORT
if (err == 0 && is_geli(&dsk) == 0) {
/* Decrypt */
- if (geli_read(&dsk, lba * DEV_BSIZE, buf, nblk * DEV_BSIZE))
+ if (geli_io(&dsk, 0, lba * DEV_BSIZE, buf, nblk * DEV_BSIZE))
return (err);
}
#endif
Index: sys/boot/i386/libi386/biosdisk.c
===================================================================
--- sys/boot/i386/libi386/biosdisk.c
+++ sys/boot/i386/libi386/biosdisk.c
@@ -834,10 +834,6 @@
int err, n, alignblks;
char *tmpbuf;
- /* if we already know there is no GELI, skip the rest */
- if (geli_status[dev->d_unit][dev->d_slice] != ISGELI_YES)
- return (bd_io(dev, dblk, blks, dest, 0));
-
if (geli_status[dev->d_unit][dev->d_slice] == ISGELI_YES) {
/*
* Align reads to DEV_GELIBOOT_BSIZE bytes because partial
@@ -882,7 +878,7 @@
/* GELI needs the offset relative to the partition start */
p_off = alignlba - dskp.start;
- err = geli_read(&dskp, p_off * BD(dev).bd_sectorsize, tmpbuf,
+ err = geli_io(&dskp, 0, p_off * BD(dev).bd_sectorsize, tmpbuf,
alignblks * BD(dev).bd_sectorsize);
if (err)
return (err);
@@ -902,6 +898,78 @@
bd_write(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest)
{
+#ifdef LOADER_GELI_SUPPORT
+ struct dsk dskp;
+ off_t p_off, diff;
+ daddr_t alignlba;
+ int err, n, alignblks;
+ char *tmpbuf;
+
+ if (geli_status[dev->d_unit][dev->d_slice] == ISGELI_YES) {
+ dskp.drive = bd_unit2bios(dev->d_unit);
+ dskp.type = dev->d_type;
+ dskp.unit = dev->d_unit;
+ dskp.slice = dev->d_slice;
+ dskp.part = dev->d_partition;
+ dskp.start = dev->d_offset;
+ /*
+ * Align writes to DEV_GELIBOOT_BSIZE bytes because partial
+ * sectors cannot be encrypted. Round the requested LBA down to
+ * nearest multiple of DEV_GELIBOOT_BSIZE bytes.
+ */
+ alignlba = rounddown2(dblk * BD(dev).bd_sectorsize,
+ DEV_GELIBOOT_BSIZE) / BD(dev).bd_sectorsize;
+ /*
+ * Round number of blocks to read up to nearest multiple of
+ * DEV_GELIBOOT_BSIZE
+ */
+ diff = (dblk - alignlba) * BD(dev).bd_sectorsize;
+ alignblks = roundup2(blks * BD(dev).bd_sectorsize + diff,
+ DEV_GELIBOOT_BSIZE) / BD(dev).bd_sectorsize;
+ /* GELI needs the offset relative to the partition start */
+ p_off = alignlba - dskp.start;
+ /*
+ * If the read is rounded up to a larger size, use a temporary
+ * buffer here because the buffer provided by the caller may be
+ * too small.
+ */
+ if (diff == 0) {
+ tmpbuf = dest;
+ } else {
+ tmpbuf = malloc(alignblks * BD(dev).bd_sectorsize);
+ if (tmpbuf == NULL) {
+ return (-1);
+ }
+ /*
+ * Unaligned writes require read/modify/write.
+ */
+ err = bd_io(dev, alignlba, DEV_GELIBOOT_BSIZE, tmpbuf,
+ 0);
+ if (err)
+ return (err);
+ /* Decrypt */
+ err = geli_io(&dskp, 0, p_off * BD(dev).bd_sectorsize,
+ tmpbuf, DEV_GELIBOOT_BSIZE);
+ if (err)
+ return (err);
+ bcopy(dest, tmpbuf + diff, blks * BD(dev).bd_sectorsize);
+ }
+
+ err = geli_io(&dskp, 0, p_off * BD(dev).bd_sectorsize, tmpbuf,
+ alignblks * BD(dev).bd_sectorsize);
+ if (err)
+ return (err);
+
+ err = bd_io(dev, alignlba, alignblks, tmpbuf, 1);
+ if (err)
+ return (err);
+
+ if (tmpbuf != dest) {
+ free(tmpbuf);
+ }
+ return (0);
+ }
+#endif /* LOADER_GELI_SUPPORT */
return (bd_io(dev, dblk, blks, dest, 1));
}
Index: sys/boot/i386/zfsboot/zfsboot.c
===================================================================
--- sys/boot/i386/zfsboot/zfsboot.c
+++ sys/boot/i386/zfsboot/zfsboot.c
@@ -201,10 +201,14 @@
vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
{
char *p;
- daddr_t lba, alignlba;
- off_t diff;
- unsigned int nb, alignnb;
+ daddr_t lba;
+ unsigned int nb;
struct dsk *dsk = (struct dsk *) priv;
+#ifdef LOADER_GELI_SUPPORT
+ daddr_t alignlba;
+ off_t diff;
+ unsigned int alignnb;
+#endif
if ((off & (DEV_BSIZE - 1)) || (bytes & (DEV_BSIZE - 1)))
return -1;
@@ -212,6 +216,7 @@
p = buf;
lba = off / DEV_BSIZE;
lba += dsk->start;
+#ifdef LOADER_GELI_SUPPORT
/*
* Align reads to 4k else 4k sector GELIs will not decrypt.
* Round LBA down to nearest multiple of DEV_GELIBOOT_BSIZE bytes.
@@ -223,9 +228,11 @@
*/
alignlba += dsk->start;
diff = (lba - alignlba) * DEV_BSIZE;
+#endif
while (bytes > 0) {
nb = bytes / DEV_BSIZE;
+#ifdef LOADER_GELI_SUPPORT
/*
* Ensure that the read size plus the leading offset does not
* exceed the size of the read buffer.
@@ -241,21 +248,26 @@
if (drvread(dsk, dmadat->rdbuf, alignlba, alignnb))
return -1;
-#ifdef LOADER_GELI_SUPPORT
/* decrypt */
if (is_geli(dsk) == 0) {
- if (geli_read(dsk, ((alignlba - dsk->start) *
+ if (geli_io(dsk, 0, ((alignlba - dsk->start) *
DEV_BSIZE), dmadat->rdbuf, alignnb * DEV_BSIZE))
return (-1);
}
-#endif
memcpy(p, dmadat->rdbuf + diff, nb * DEV_BSIZE);
- p += nb * DEV_BSIZE;
- lba += nb;
alignlba += alignnb;
- bytes -= nb * DEV_BSIZE;
/* Don't need the leading offset after the first block. */
diff = 0;
+#else
+ if (nb > READ_BUF_SIZE / DEV_BSIZE)
+ nb = READ_BUF_SIZE / DEV_BSIZE;
+ if (drvread(dsk, dmadat->rdbuf, lba, nb))
+ return -1;
+ memcpy(p, dmadat->rdbuf, nb * DEV_BSIZE);
+#endif
+ p += nb * DEV_BSIZE;
+ lba += nb;
+ bytes -= nb * DEV_BSIZE;
}
return 0;
@@ -268,6 +280,11 @@
daddr_t lba;
unsigned int nb;
struct dsk *dsk = (struct dsk *) priv;
+#ifdef LOADER_GELI_SUPPORT
+ daddr_t alignlba;
+ off_t diff;
+ unsigned int alignnb;
+#endif
if ((off & (DEV_BSIZE - 1)) || (bytes & (DEV_BSIZE - 1)))
return -1;
@@ -275,13 +292,68 @@
p = buf;
lba = off / DEV_BSIZE;
lba += dsk->start;
+#ifdef LOADER_GELI_SUPPORT
+ /*
+ * Align writes to 4k else 4k sector GELIs will not decrypt.
+ * Round LBA down to nearest multiple of DEV_GELIBOOT_BSIZE bytes.
+ */
+ alignlba = rounddown2(off, DEV_GELIBOOT_BSIZE) / DEV_BSIZE;
+ /*
+ * The read must be aligned to DEV_GELIBOOT_BSIZE bytes relative to the
+ * start of the GELI partition, not the start of the actual disk.
+ */
+ alignlba += dsk->start;
+ diff = (lba - alignlba) * DEV_BSIZE;
+#endif
+
while (bytes > 0) {
nb = bytes / DEV_BSIZE;
+#ifdef LOADER_GELI_SUPPORT
+ /*
+ * Ensure that the write size plus the leading offset does not
+ * exceed the size of the buffer.
+ */
+ if (nb > (READ_BUF_SIZE - diff) / DEV_BSIZE)
+ nb = (READ_BUF_SIZE - diff) / DEV_BSIZE;
+ /*
+ * Round the number of blocks to read up to the nearest multiple
+ * of DEV_GELIBOOT_BSIZE.
+ */
+ alignnb = roundup2(nb * DEV_BSIZE + diff, DEV_GELIBOOT_BSIZE)
+ / DEV_BSIZE;
+
+ /*
+ * Unaligned writes require read/modify/write.
+ */
+ if (diff > 0) {
+ vdev_read(vdev, priv, alignlba * DEV_BSIZE,
+ dmadat->rdbuf, DEV_GELIBOOT_BSIZE);
+ if (is_geli(dsk) == 0) {
+ if (geli_io(dsk, 0, ((alignlba - dsk->start) *
+ DEV_BSIZE), dmadat->rdbuf,
+ DEV_GELIBOOT_BSIZE))
+ return (-1);
+ }
+ }
+ memcpy(dmadat->rdbuf + diff, p, nb * DEV_BSIZE);
+ /* encrypt */
+ if (is_geli(dsk) == 0) {
+ if (geli_io(dsk, 1, ((alignlba - dsk->start) *
+ DEV_BSIZE), dmadat->rdbuf, alignnb * DEV_BSIZE))
+ return (-1);
+ }
+ if (drvwrite(dsk, dmadat->rdbuf, alignlba, alignnb))
+ return -1;
+ alignlba += alignnb;
+ /* Don't need the leading offset after the first block. */
+ diff = 0;
+#else
if (nb > READ_BUF_SIZE / DEV_BSIZE)
nb = READ_BUF_SIZE / DEV_BSIZE;
memcpy(dmadat->rdbuf, p, nb * DEV_BSIZE);
if (drvwrite(dsk, dmadat->rdbuf, lba, nb))
return -1;
+#endif
p += nb * DEV_BSIZE;
lba += nb;
bytes -= nb * DEV_BSIZE;
@@ -717,7 +789,7 @@
primary_vdev = spa_get_primary_vdev(spa);
nextboot = 0;
- rc = vdev_read_pad2(primary_vdev, cmd, sizeof(cmd));
+ rc = vdev_read_pad2(primary_vdev, cmd, sizeof(cmd));
if (vdev_clear_pad2(primary_vdev))
printf("failed to clear pad2 area of primary vdev\n");
if (rc == 0) {

File Metadata

Mime Type
text/plain
Expires
Sat, Sep 12, 4:12 AM (15 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38763177
Default Alt Text
D10236.id26933.diff (9 KB)

Event Timeline