Changeset View
Changeset View
Standalone View
Standalone View
stand/libsa/geli/gelidev.c
Show First 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | geli_dev_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf, | ||||
size_t *rsize) | size_t *rsize) | ||||
{ | { | ||||
struct geli_devdesc *gdesc; | struct geli_devdesc *gdesc; | ||||
off_t alnend, alnstart, reqend, reqstart; | off_t alnend, alnstart, reqend, reqstart; | ||||
size_t alnsize; | size_t alnsize; | ||||
char *iobuf; | char *iobuf; | ||||
int rc; | int rc; | ||||
/* We only handle reading; no write support. */ | |||||
if ((rw & F_MASK) != F_READ) | |||||
return (EOPNOTSUPP); | |||||
gdesc = (struct geli_devdesc *)devdata; | gdesc = (struct geli_devdesc *)devdata; | ||||
/* | /* | ||||
* We can only decrypt full geli blocks. The blk arg is expressed in | * We can only decrypt full geli blocks. The blk arg is expressed in | ||||
* units of DEV_BSIZE blocks, while size is in bytes. Convert | * units of DEV_BSIZE blocks, while size is in bytes. Convert | ||||
* everything to bytes, and calculate the geli-blocksize-aligned start | * everything to bytes, and calculate the geli-blocksize-aligned start | ||||
* and end points. | * and end points. | ||||
* | * | ||||
* Note: md_sectorsize must be cast to a signed type for the round2 | * Note: md_sectorsize must be cast to a signed type for the round2 | ||||
* macros to work correctly (otherwise they get zero-extended to 64 bits | * macros to work correctly (otherwise they get zero-extended to 64 bits | ||||
* and mask off the high order 32 bits of the requested start/end). | * and mask off the high order 32 bits of the requested start/end). | ||||
*/ | */ | ||||
reqstart = blk * DEV_BSIZE; | reqstart = blk * DEV_BSIZE; | ||||
reqend = reqstart + size; | reqend = reqstart + size; | ||||
alnstart = rounddown2(reqstart, (int)gdesc->gdev->md.md_sectorsize); | alnstart = rounddown2(reqstart, (int)gdesc->gdev->md.md_sectorsize); | ||||
alnend = roundup2(reqend, (int)gdesc->gdev->md.md_sectorsize); | alnend = roundup2(reqend, (int)gdesc->gdev->md.md_sectorsize); | ||||
alnsize = alnend - alnstart; | alnsize = alnend - alnstart; | ||||
/* | /* | ||||
* If alignment requires us to read more than the size of the provided | * If alignment requires us to read/write more than the size of the | ||||
* buffer, allocate a temporary buffer. | * provided buffer, allocate a temporary buffer. | ||||
* The writes will always get temporary buffer because of encryption. | |||||
*/ | */ | ||||
if (alnsize <= size) | if (alnsize <= size && (rw & F_MASK) == F_READ) | ||||
iobuf = buf; | iobuf = buf; | ||||
else if ((iobuf = malloc(alnsize)) == NULL) | else if ((iobuf = malloc(alnsize)) == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
switch (rw & F_MASK) { | |||||
case F_READ: | |||||
/* | /* | ||||
* Read the encrypted data using the host provider, then decrypt it. | * Read the encrypted data using the host provider, | ||||
* then decrypt it. | |||||
*/ | */ | ||||
rc = gdesc->hdesc->dd.d_dev->dv_strategy(gdesc->hdesc, rw, | rc = gdesc->hdesc->dd.d_dev->dv_strategy(gdesc->hdesc, rw, | ||||
alnstart / DEV_BSIZE, alnsize, iobuf, NULL); | alnstart / DEV_BSIZE, alnsize, iobuf, NULL); | ||||
if (rc != 0) | if (rc != 0) | ||||
goto out; | goto out; | ||||
rc = geli_read(gdesc->gdev, alnstart, iobuf, alnsize); | rc = geli_io(gdesc->gdev, GELI_DECRYPT, alnstart, iobuf, | ||||
alnsize); | |||||
if (rc != 0) | if (rc != 0) | ||||
goto out; | goto out; | ||||
/* | /* | ||||
* If we had to use a temporary buffer, copy the requested part of the | * If we had to use a temporary buffer, copy the requested | ||||
* data to the caller's buffer. | * part of the data to the caller's buffer. | ||||
*/ | */ | ||||
if (iobuf != buf) | if (iobuf != buf) | ||||
memcpy(buf, iobuf + (reqstart - alnstart), size); | memcpy(buf, iobuf + (reqstart - alnstart), size); | ||||
if (rsize != NULL) | if (rsize != NULL) | ||||
*rsize = size; | *rsize = size; | ||||
break; | |||||
case F_WRITE: | |||||
if (iobuf != buf) { | |||||
/* Read data and decrypt it */ | |||||
rpokala: "Need to read/modify/write, so read and decrypt, then modify." | |||||
rc = gdesc->hdesc->dd.d_dev->dv_strategy(gdesc->hdesc, | |||||
F_READ, alnstart / DEV_BSIZE, alnsize, iobuf, NULL); | |||||
if (rc != 0) | |||||
goto out; | |||||
rc = geli_io(gdesc->gdev, GELI_DECRYPT, alnstart, iobuf, | |||||
alnsize); | |||||
if (rc != 0) | |||||
goto out; | |||||
/* Copy data to iobuf */ | |||||
memcpy(iobuf + (reqstart - alnstart), buf, size); | |||||
} | |||||
/* Encrypt and write it. */ | |||||
rc = geli_io(gdesc->gdev, GELI_ENCRYPT, alnstart, iobuf, | |||||
alnsize); | |||||
if (rc != 0) | |||||
goto out; | |||||
rc = gdesc->hdesc->dd.d_dev->dv_strategy(gdesc->hdesc, | |||||
rw, alnstart / DEV_BSIZE, alnsize, iobuf, NULL); | |||||
} | |||||
out: | out: | ||||
if (iobuf != buf) | if (iobuf != buf) | ||||
free(iobuf); | free(iobuf); | ||||
return (rc); | return (rc); | ||||
} | } | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 146 Lines • Show Last 20 Lines |
"Need to read/modify/write, so read and decrypt, then modify."