summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/src/9/port/devfs.c123
-rw-r--r--sys/src/9/port/lib.h1
2 files changed, 61 insertions, 63 deletions
diff --git a/sys/src/9/port/devfs.c b/sys/src/9/port/devfs.c
index 1dcbcf28e..e5d1abe2f 100644
--- 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 @@ enum
Sectorsz = 1,
Blksize = 8*1024, /* for Finter only */
+ Cryptsectsz = 512, /* for Fcrypt only */
Incr = 5, /* Increments for the dev array */
@@ -447,11 +447,9 @@ setdsize(Fsdev* mp, vlong *ilen)
}
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 @@ mconfig(char* a, long n)
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 @@ mconfig(char* a, long n)
cb = nil;
idev = nil;
ilen = nil;
+ keylen = 0;
if(waserror()){
free(cb);
@@ -600,8 +600,19 @@ mconfig(char* a, long n)
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 @@ Fail:
}
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 @@ io(Fsdev *mp, Inner *in, int isread, void *a, long l, vlong off)
}
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,
- };
-
- if(off < 0 || l <= 0 || ((off|l) & (Sectsz-1)))
- error(Ebadarg);
+ long l, m, o, nb;
+ uchar *b;
- 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((((ulong)off|n) & (Cryptsectsz-1)))
+ error(Ebadarg);
+ 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 @@ mread(Chan *c, void *a, long n, vlong off)
(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 @@ mwrite(Chan *c, void *a, long n, vlong off)
break;
case Fcrypt:
- res = cryptio(mp, Iswrite, a, n, off);
+ res = cryptio(mp, Iswrite, a, n, mp->start + off);
break;
}
Done:
diff --git a/sys/src/9/port/lib.h b/sys/src/9/port/lib.h
index e0a17bfee..f991285ce 100644
--- a/sys/src/9/port/lib.h
+++ b/sys/src/9/port/lib.h
@@ -155,6 +155,7 @@ extern char end[];
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*));