ref: 93117262c2e377d9d4f1588924032d1b69e7e2f9
parent: c021390e218066ca01828917dd940dff26ceff3b
author: cinap_lenrek <[email protected]>
date: Sun Oct 29 18:01:58 EDT 2017
devfs: rewrite cryptio() adjust to new aes_xts routines. allow optional offset in the 4th argument where the encrypted sectors start instead of hardcoding the 64K header area for cryptsetup. avoid allocating temporary buffer for cryptio() reads, we can just decrypt in place there. use sdmalloc() to allocate the temporary buffer for cryptio() writes so that devsd wont need to allocate and copy in case it didnt like our alignment. do not duplicate the error reporting code, just use io() that is what it is for. allow 2*256 bit keys in addition to 2*128 bit keys.
--- a/sys/src/9/port/devfs.c
+++ b/sys/src/9/port/devfs.c
@@ -21,10 +21,9 @@
#include "io.h"
#include "ureg.h"
#include "../port/error.h"
+#include "../port/sd.h"
#include <libsec.h>
-int dec16(uchar *out, int lim, char *in, int n);
-
enum
{
Fnone,
@@ -39,6 +38,7 @@
Sectorsz = 1,
Blksize = 8*1024, /* for Finter only */
+ Cryptsectsz = 512, /* for Fcrypt only */
Incr = 5, /* Increments for the dev array */
@@ -447,11 +447,9 @@
}
break;
case Fcrypt:
- if(inlen > (64*1024)) {
- mp->size = inlen - (64 * 1024);
- } else {
- mp->size = 0;
- }
+ if(mp->start > inlen)
+ error("crypt starts after device end");
+ mp->size = (inlen - mp->start) & ~((vlong)Cryptsectsz-1);
break;
}
}
@@ -552,7 +550,8 @@
vlong size, start;
vlong *ilen;
char *tname, *dname, *fakef[4];
- uchar key[32];
+ uchar key[2*256/8];
+ int keylen;
Chan **idev;
Cmdbuf *cb;
Cmdtab *ct;
@@ -571,6 +570,7 @@
cb = nil;
idev = nil;
ilen = nil;
+ keylen = 0;
if(waserror()){
free(cb);
@@ -600,8 +600,19 @@
mdelctl("*", "*"); /* del everything */
return;
case Fcrypt:
- if(dec16(key, 32, cb->f[2], strlen(cb->f[2])) != 32)
+ if(cb->nf >= 4) {
+ start = strtoul(cb->f[3], 0, 0);
+ cb->nf = 3;
+ } else
+ start = 64*1024; /* cryptsetup header */
+ keylen = dec16(key, sizeof(key), cb->f[2], strlen(cb->f[2]));
+ switch(keylen){
+ default:
error("bad hexkey");
+ case 2*128/8:
+ case 2*256/8:
+ break;
+ }
cb->nf -= 1;
break;
case Fpart:
@@ -694,10 +705,11 @@
}
if(mp->type == Fcrypt) {
Key *k = secalloc(sizeof(Key));
- setupAESstate(&k->tweak, &key[0], 16, nil);
- setupAESstate(&k->ecb, &key[16], 16, nil);
- memset(key, 0, 32);
+ setupAESstate(&k->tweak, &key[0], keylen/2, nil);
+ setupAESstate(&k->ecb, &key[keylen/2], keylen/2, nil);
+ memset(key, 0, sizeof(key));
mp->key = k;
+ mp->start = start;
}
for(i = 1; i < cb->nf; i++){
inprv = mp->inner[i-1] = mallocz(sizeof(Inner), 1);
@@ -1014,62 +1026,47 @@
}
static long
-cryptio(Fsdev *mp, int isread, uchar *a, long l, vlong off)
+cryptio(Fsdev *mp, int isread, uchar *a, long n, vlong off)
{
- long wl, ws, wo, wb;
- uchar *buf;
- Chan *mc;
- Inner *in;
- Key *k;
- enum {
- Sectsz = 512,
- Maxbuf = 32*Sectsz,
- };
+ long l, m, o, nb;
+ uchar *b;
- if(off < 0 || l <= 0 || ((off|l) & (Sectsz-1)))
+ if((((ulong)off|n) & (Cryptsectsz-1)))
error(Ebadarg);
-
- k = mp->key;
- in = mp->inner[0];
- mc = in->idev;
- if(mc == nil)
- error(Egone);
- off += 64*1024; // Header
- wb = l;
- if(wb > Maxbuf)
- wb = Maxbuf;
- buf = smalloc(wb);
+ if(isread){
+ l = io(mp, mp->inner[0], Isread, a, n, off);
+ if(l > 0){
+ l &= ~(Cryptsectsz-1);
+ for(o=0; o<l; o+=Cryptsectsz)
+ aes_xts_decrypt(&mp->key->tweak, &mp->key->ecb,
+ off+o, a+o, a+o, Cryptsectsz);
+ }
+ return l;
+ }
+ nb = n < SDmaxio ? n : SDmaxio;
+ while((b = sdmalloc(nb)) == nil){
+ if(!waserror()){
+ resrcwait("no memory for cryptio");
+ poperror();
+ }
+ }
if(waserror()) {
- free(buf);
- print("#k: %s: byte %,lld count %ld (of #k/%s): %s error: %s\n",
- in->iname, off, l, mp->name, (isread? "read": "write"),
- (up && up->errstr? up->errstr: ""));
+ sdfree(b);
nexterror();
}
- for(ws = 0; ws < l; ws += wo){
- wo = l - ws;
- if(wo > wb)
- wo = wb;
- if (isread) {
- wo = devtab[mc->type]->read(mc, buf, wo, off);
- if(wo < Sectsz)
- break;
- wo &= ~(Sectsz-1);
- for(wl=0; wl<wo; wl+=Sectsz)
- aes_xts_decrypt(k->tweak.ekey, k->ecb.dkey, off+wl, buf+wl, a+wl, Sectsz);
- } else {
- for(wl=0; wl<wo; wl+=Sectsz)
- aes_xts_encrypt(k->tweak.ekey, k->ecb.ekey, off+wl, a+wl, buf+wl, Sectsz);
- if(devtab[mc->type]->write(mc, buf, wo, off) != wo)
- error(Eio);
- }
- off += wo;
- a += wo;
+ for(l = 0; (m = n - l) > 0; l += m){
+ if(m > nb) m = nb;
+ for(o=0; o<m; o+=Cryptsectsz)
+ aes_xts_encrypt(&mp->key->tweak, &mp->key->ecb,
+ off+o, a+o, b+o, Cryptsectsz);
+ if(io(mp, mp->inner[0], Iswrite, b, m, off) != m)
+ error(Eio);
+ off += m;
+ a += m;
}
+ sdfree(b);
poperror();
- free(buf);
-
- return ws;
+ return l;
}
/* NB: a transfer could span multiple inner devices */
@@ -1243,7 +1240,7 @@
(up && up->errstr? up->errstr: ""));
break;
case Fcrypt:
- res = cryptio(mp, Isread, a, n, off);
+ res = cryptio(mp, Isread, a, n, mp->start + off);
break;
}
Done:
@@ -1341,7 +1338,7 @@
break;
case Fcrypt:
- res = cryptio(mp, Iswrite, a, n, off);
+ res = cryptio(mp, Iswrite, a, n, mp->start + off);
break;
}
Done:
--- a/sys/src/9/port/lib.h
+++ b/sys/src/9/port/lib.h
@@ -155,6 +155,7 @@
extern int getfields(char*, char**, int, int, char*);
extern int tokenize(char*, char**, int);
extern int dec64(uchar*, int, char*, int);
+extern int dec16(uchar*, int, char*, int);
extern int encodefmt(Fmt*);
extern void qsort(void*, long, long, int (*)(void*, void*));