devfs crypto code - alpha version
This commit is contained in:
parent
f34231e16a
commit
9655db2550
9 changed files with 528 additions and 0 deletions
|
@ -400,3 +400,7 @@ int okThumbprint(uchar *sha1, Thumbprint *ok);
|
||||||
/* readcert.c */
|
/* readcert.c */
|
||||||
uchar *readcert(char *filename, int *pcertlen);
|
uchar *readcert(char *filename, int *pcertlen);
|
||||||
PEMChain*readcertchain(char *filename);
|
PEMChain*readcertchain(char *filename);
|
||||||
|
|
||||||
|
/* aes_xts.c */
|
||||||
|
int aes_xts_encrypt(ulong tweak[], ulong ecb[], vlong sectorNumber, uchar *input, uchar *output, ulong len) ;
|
||||||
|
int aes_xts_decrypt(ulong tweak[], ulong ecb[], vlong sectorNumber, uchar *input, uchar *output, ulong len);
|
|
@ -21,6 +21,9 @@
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "ureg.h"
|
#include "ureg.h"
|
||||||
#include "../port/error.h"
|
#include "../port/error.h"
|
||||||
|
#include "libsec.h"
|
||||||
|
|
||||||
|
int dec16(uchar *out, int lim, char *in, int n);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -32,6 +35,7 @@ enum
|
||||||
Fclear, /* start over */
|
Fclear, /* start over */
|
||||||
Fdel, /* delete a configure device */
|
Fdel, /* delete a configure device */
|
||||||
Fdisk, /* set default tree and sector sz*/
|
Fdisk, /* set default tree and sector sz*/
|
||||||
|
Fcrypt, /* encrypted device */
|
||||||
|
|
||||||
Sectorsz = 1,
|
Sectorsz = 1,
|
||||||
Blksize = 8*1024, /* for Finter only */
|
Blksize = 8*1024, /* for Finter only */
|
||||||
|
@ -65,6 +69,7 @@ enum
|
||||||
typedef struct Inner Inner;
|
typedef struct Inner Inner;
|
||||||
typedef struct Fsdev Fsdev;
|
typedef struct Fsdev Fsdev;
|
||||||
typedef struct Tree Tree;
|
typedef struct Tree Tree;
|
||||||
|
typedef struct Key Key;
|
||||||
|
|
||||||
struct Inner
|
struct Inner
|
||||||
{
|
{
|
||||||
|
@ -85,6 +90,7 @@ struct Fsdev
|
||||||
vlong start; /* start address (for Fpart) */
|
vlong start; /* start address (for Fpart) */
|
||||||
uint ndevs; /* number of inner devices */
|
uint ndevs; /* number of inner devices */
|
||||||
Inner *inner[Ndevs]; /* inner devices */
|
Inner *inner[Ndevs]; /* inner devices */
|
||||||
|
void *extra; /* extra state for the device */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Tree
|
struct Tree
|
||||||
|
@ -95,6 +101,10 @@ struct Tree
|
||||||
uint nadevs; /* number of allocated devices in devs */
|
uint nadevs; /* number of allocated devices in devs */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Key {
|
||||||
|
AESstate tweak, ecb;
|
||||||
|
};
|
||||||
|
|
||||||
#define dprint if(debug)print
|
#define dprint if(debug)print
|
||||||
|
|
||||||
extern Dev fsdevtab; /* forward */
|
extern Dev fsdevtab; /* forward */
|
||||||
|
@ -121,6 +131,7 @@ static char* tnames[] = {
|
||||||
[Fcat] "cat",
|
[Fcat] "cat",
|
||||||
[Finter] "inter",
|
[Finter] "inter",
|
||||||
[Fpart] "part",
|
[Fpart] "part",
|
||||||
|
[Fcrypt] "crypt",
|
||||||
};
|
};
|
||||||
|
|
||||||
static Cmdtab configs[] = {
|
static Cmdtab configs[] = {
|
||||||
|
@ -131,6 +142,7 @@ static Cmdtab configs[] = {
|
||||||
Fclear, "clear", 1,
|
Fclear, "clear", 1,
|
||||||
Fdel, "del", 2,
|
Fdel, "del", 2,
|
||||||
Fdisk, "disk", 0,
|
Fdisk, "disk", 0,
|
||||||
|
Fcrypt, "crypt", 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static char Egone[] = "device is gone"; /* file has been removed */
|
static char Egone[] = "device is gone"; /* file has been removed */
|
||||||
|
@ -156,6 +168,7 @@ seprintdev(char *s, char *e, Fsdev *mp)
|
||||||
case Fmirror:
|
case Fmirror:
|
||||||
case Fcat:
|
case Fcat:
|
||||||
case Finter:
|
case Finter:
|
||||||
|
case Fcrypt:
|
||||||
s = strecpy(s, e, "\n");
|
s = strecpy(s, e, "\n");
|
||||||
break;
|
break;
|
||||||
case Fpart:
|
case Fpart:
|
||||||
|
@ -434,6 +447,13 @@ setdsize(Fsdev* mp, vlong *ilen)
|
||||||
mp->size = inlen - mp->start;
|
mp->size = inlen - mp->start;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Fcrypt:
|
||||||
|
if(inlen > (64*1024)) {
|
||||||
|
mp->size = inlen - (64 * 1024);
|
||||||
|
} else {
|
||||||
|
mp->size = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(mp->type == Finter)
|
if(mp->type == Finter)
|
||||||
|
@ -478,6 +498,10 @@ parseconfig(char *a, long n, Cmdbuf **cbp, Cmdtab **ctp)
|
||||||
if(cb->nf != 4 && (cb->nf != 3 || source == nil))
|
if(cb->nf != 4 && (cb->nf != 3 || source == nil))
|
||||||
error("ctl usage: part new [file] off len");
|
error("ctl usage: part new [file] off len");
|
||||||
break;
|
break;
|
||||||
|
case Fcrypt:
|
||||||
|
if(cb->nf != 3)
|
||||||
|
error("ctl usage: crypt newname device keyhex");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,6 +553,7 @@ mconfig(char* a, long n)
|
||||||
vlong size, start;
|
vlong size, start;
|
||||||
vlong *ilen;
|
vlong *ilen;
|
||||||
char *tname, *dname, *fakef[4];
|
char *tname, *dname, *fakef[4];
|
||||||
|
uchar key[32];
|
||||||
Chan **idev;
|
Chan **idev;
|
||||||
Cmdbuf *cb;
|
Cmdbuf *cb;
|
||||||
Cmdtab *ct;
|
Cmdtab *ct;
|
||||||
|
@ -575,6 +600,10 @@ mconfig(char* a, long n)
|
||||||
free(cb);
|
free(cb);
|
||||||
mdelctl("*", "*"); /* del everything */
|
mdelctl("*", "*"); /* del everything */
|
||||||
return;
|
return;
|
||||||
|
case Fcrypt:
|
||||||
|
dec16(key, 32, cb->f[2], 64);
|
||||||
|
cb->nf -= 1;
|
||||||
|
break;
|
||||||
case Fpart:
|
case Fpart:
|
||||||
if(cb->nf == 3){
|
if(cb->nf == 3){
|
||||||
/*
|
/*
|
||||||
|
@ -662,6 +691,15 @@ Fail:
|
||||||
mp->start = start * sectorsz;
|
mp->start = start * sectorsz;
|
||||||
mp->size = size * sectorsz;
|
mp->size = size * sectorsz;
|
||||||
}
|
}
|
||||||
|
if(mp->type == Fcrypt) {
|
||||||
|
Key *k = mallocz(sizeof(Key), 1);
|
||||||
|
if(k == nil)
|
||||||
|
error(Enomem);
|
||||||
|
setupAESstate(&k->tweak, &key[0], 16, nil);
|
||||||
|
setupAESstate(&k->ecb, &key[16], 16, nil);
|
||||||
|
memset(key, 0, 32);
|
||||||
|
mp->extra = k;
|
||||||
|
}
|
||||||
for(i = 1; i < cb->nf; i++){
|
for(i = 1; i < cb->nf; i++){
|
||||||
inprv = mp->inner[i-1] = mallocz(sizeof(Inner), 1);
|
inprv = mp->inner[i-1] = mallocz(sizeof(Inner), 1);
|
||||||
if(inprv == nil)
|
if(inprv == nil)
|
||||||
|
@ -673,6 +711,8 @@ Fail:
|
||||||
}
|
}
|
||||||
setdsize(mp, ilen);
|
setdsize(mp, ilen);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
poperror();
|
poperror();
|
||||||
wunlock(&lck);
|
wunlock(&lck);
|
||||||
free(idev);
|
free(idev);
|
||||||
|
@ -970,6 +1010,63 @@ io(Fsdev *mp, Inner *in, int isread, void *a, long l, vlong off)
|
||||||
return wl;
|
return wl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
cryptio(Fsdev *mp, int isread, uchar *a, long l, vlong off)
|
||||||
|
{
|
||||||
|
long wl, ws, wo;
|
||||||
|
uchar *buf;
|
||||||
|
Chan *mc;
|
||||||
|
Inner *in;
|
||||||
|
Key *k;
|
||||||
|
|
||||||
|
in = mp->inner[0];
|
||||||
|
// Header
|
||||||
|
off += 64*1024;
|
||||||
|
|
||||||
|
mc = in->idev;
|
||||||
|
if(mc == nil)
|
||||||
|
error(Egone);
|
||||||
|
if (waserror()) {
|
||||||
|
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: ""));
|
||||||
|
nexterror();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(off % 512 != 0 || l%512 !=0)
|
||||||
|
error(Eio);
|
||||||
|
|
||||||
|
wo = (l > 16384) ? 16384 : l;
|
||||||
|
buf = mallocz(wo, 1);
|
||||||
|
if(!buf)
|
||||||
|
error(Enomem);
|
||||||
|
k = (Key*)(mp->extra);
|
||||||
|
|
||||||
|
for(ws = 0; ws < l; ws+=wo) {
|
||||||
|
if (isread) {
|
||||||
|
wl = devtab[mc->type]->read(mc, buf, wo, off);
|
||||||
|
if(wl!=wo)
|
||||||
|
error(Eio);
|
||||||
|
for(wl=0; wl<wo; wl+=512) {
|
||||||
|
aes_xts_decrypt(k->tweak.ekey, k->ecb.dkey, off, buf+wl, a+ws+wl, 512);
|
||||||
|
off += 512;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(wl=0; wl<wo; wl+=512) {
|
||||||
|
aes_xts_encrypt(k->tweak.ekey, k->ecb.ekey, off, a+ws+wl, buf+wl, 512);
|
||||||
|
off += 512;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl = devtab[mc->type]->write(mc, buf, wo, off-wo);
|
||||||
|
if(wl!=wo)
|
||||||
|
error(Eio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
poperror();
|
||||||
|
return ws;
|
||||||
|
}
|
||||||
|
|
||||||
/* NB: a transfer could span multiple inner devices */
|
/* NB: a transfer could span multiple inner devices */
|
||||||
static long
|
static long
|
||||||
catio(Fsdev *mp, int isread, void *a, long n, vlong off)
|
catio(Fsdev *mp, int isread, void *a, long n, vlong off)
|
||||||
|
@ -1140,6 +1237,9 @@ mread(Chan *c, void *a, long n, vlong off)
|
||||||
"from mirror: %s\n", mp->name, off, n,
|
"from mirror: %s\n", mp->name, off, n,
|
||||||
(up && up->errstr? up->errstr: ""));
|
(up && up->errstr? up->errstr: ""));
|
||||||
break;
|
break;
|
||||||
|
case Fcrypt:
|
||||||
|
res = cryptio(mp, Isread, a, n, off);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
Done:
|
Done:
|
||||||
poperror();
|
poperror();
|
||||||
|
@ -1235,6 +1335,9 @@ mwrite(Chan *c, void *a, long n, vlong off)
|
||||||
(up && up->errstr? up->errstr: ""));
|
(up && up->errstr? up->errstr: ""));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
case Fcrypt:
|
||||||
|
res = cryptio(mp, Iswrite, a, n, off);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
Done:
|
Done:
|
||||||
poperror();
|
poperror();
|
||||||
|
|
14
sys/src/cmd/cryptsetup/crypt.h
Normal file
14
sys/src/cmd/cryptsetup/crypt.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// Author Taru Karttunen <taruti@taruti.net>
|
||||||
|
// This file can be used as both Public Domain or Creative Commons CC0.
|
||||||
|
#include <libsec.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char Salt[16];
|
||||||
|
unsigned char Key[32];
|
||||||
|
} Slot;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char Master[32];
|
||||||
|
Slot Slots[8];
|
||||||
|
AESstate C1, C2;
|
||||||
|
} XtsState;
|
173
sys/src/cmd/cryptsetup/cryptsetup.c
Normal file
173
sys/src/cmd/cryptsetup/cryptsetup.c
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
// Author Taru Karttunen <taruti@taruti.net>
|
||||||
|
// This file can be used as both Public Domain or Creative Commons CC0.
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include "crypt.h"
|
||||||
|
|
||||||
|
void format(char *file);
|
||||||
|
void copen(char *file);
|
||||||
|
char*readcons(char *prompt, char *def, int raw, char *buf, int nbuf);
|
||||||
|
int pkcs5_pbkdf2(const unsigned char *pass, int pass_len, const unsigned char *salt, int salt_len, unsigned char *key, int key_len, int rounds);
|
||||||
|
|
||||||
|
void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
print("usage: \ncryptsetup -f deviceorfile \t\t\t\t\t# Format file or device\ncryptsetup -o deviceorfile >> /dev/fs/ctl \t# Open file or device\n");
|
||||||
|
exits("usage");
|
||||||
|
}
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
NoMode,
|
||||||
|
Format,
|
||||||
|
Open,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int mode;
|
||||||
|
char *file;
|
||||||
|
|
||||||
|
mode = 0;
|
||||||
|
|
||||||
|
ARGBEGIN {
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
case 'f':
|
||||||
|
mode = Format;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
mode = Open;
|
||||||
|
break;
|
||||||
|
} ARGEND;
|
||||||
|
|
||||||
|
if((mode == NoMode) || (argc != 1))
|
||||||
|
usage();
|
||||||
|
|
||||||
|
file = argv[0];
|
||||||
|
|
||||||
|
switch(mode) {
|
||||||
|
case Format:
|
||||||
|
format(file);
|
||||||
|
break;
|
||||||
|
case Open:
|
||||||
|
copen(file);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
format(char *file)
|
||||||
|
{
|
||||||
|
char trand[48], pass1[64], pass2[64];
|
||||||
|
unsigned char tkey[16], tivec[16], buf[64*1024];
|
||||||
|
XtsState s;
|
||||||
|
AESstate cbc;
|
||||||
|
int i,j, fd;
|
||||||
|
|
||||||
|
do {
|
||||||
|
readcons("password", nil, 1, pass1, 64);
|
||||||
|
readcons("confirm", nil, 1, pass2, 64);
|
||||||
|
} while(strcmp(pass1, pass2) != 0);
|
||||||
|
|
||||||
|
do {
|
||||||
|
readcons("Are you sure you want to delete all data? (YES to procees)", nil, 0, (char*)buf, 4);
|
||||||
|
} while(strcmp((char*)buf, "YES") != 0);
|
||||||
|
|
||||||
|
srand(truerand());
|
||||||
|
|
||||||
|
for(i = 0; i < 16*4096; i++)
|
||||||
|
buf[i] = rand();
|
||||||
|
|
||||||
|
for(i = 0; i < 48; i+=4)
|
||||||
|
*((unsigned*)&trand[i]) = truerand();
|
||||||
|
memcpy(s.Master, trand, 32);
|
||||||
|
memcpy(s.Slots[0].Salt, trand+32, 16);
|
||||||
|
|
||||||
|
pkcs5_pbkdf2((unsigned char*)pass1, strlen(pass1), s.Slots[0].Salt, 16, (unsigned char*)tkey, 16, 9999);
|
||||||
|
memset(tivec, 0, 16);
|
||||||
|
setupAESstate(&cbc, tkey, 16, tivec);
|
||||||
|
memcpy(s.Slots[0].Key, s.Master, 32);
|
||||||
|
aesCBCencrypt(s.Slots[0].Key, 32, &cbc);
|
||||||
|
|
||||||
|
for(i=0; i<16; i++)
|
||||||
|
for(j=0; j<8; j++) {
|
||||||
|
buf[(4096*i)] = 1;
|
||||||
|
buf[(4096*i)+(4*j)+1] = s.Slots[j].Salt[i];
|
||||||
|
buf[(4096*i)+(4*j)+2] = s.Slots[j].Key[i];
|
||||||
|
buf[(4096*i)+(4*j)+3] = s.Slots[j].Key[i+16];
|
||||||
|
}
|
||||||
|
|
||||||
|
if((fd = open(file, OWRITE)) < 0)
|
||||||
|
exits("Cannot open disk");
|
||||||
|
|
||||||
|
/* make the pad for checking crypto */
|
||||||
|
for(i=0; i<8; i++) {
|
||||||
|
buf[(64*1024)-8+i] = ~buf[(64*1024)-16+i];
|
||||||
|
}
|
||||||
|
memset(tivec, 0, 16);
|
||||||
|
setupAESstate(&cbc, s.Master, 16, tivec);
|
||||||
|
aes_encrypt(cbc.ekey, cbc.rounds, &buf[(64*1024)-16], &buf[(64*1024)-16]);
|
||||||
|
|
||||||
|
write(fd, buf, 16*4096);
|
||||||
|
|
||||||
|
print("Disk written\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void copen(char *file) {
|
||||||
|
unsigned char pass[32], buf[1024*64], tkey[16], tivec[16];
|
||||||
|
XtsState s;
|
||||||
|
int i,j,fd;
|
||||||
|
AESstate cbc;
|
||||||
|
char *base, fdpath[1024];
|
||||||
|
|
||||||
|
|
||||||
|
if((fd = open(file, OREAD)) < 0)
|
||||||
|
exits("Cannot open disk");
|
||||||
|
|
||||||
|
if(read(fd, buf, 1024*64) != 1024*64)
|
||||||
|
exits("Cannot read disk");
|
||||||
|
|
||||||
|
for(i=0; i<16; i++)
|
||||||
|
for(j=0; j<8; j++) {
|
||||||
|
s.Slots[j].Salt[i] = buf[(4096*i)+(4*j)+1];
|
||||||
|
s.Slots[j].Key[i] = buf[(4096*i)+(4*j)+2];
|
||||||
|
s.Slots[j].Key[i+16] = buf[(4096*i)+(4*j)+3];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
openpass:
|
||||||
|
readcons("Password", nil, 1, (char*)pass, 32);
|
||||||
|
|
||||||
|
memcpy(s.Master, s.Slots[0].Key, 32);
|
||||||
|
|
||||||
|
pkcs5_pbkdf2(pass, strlen((char*)pass), s.Slots[0].Salt, 16, tkey, 16, 9999);
|
||||||
|
memset(tivec, 0, 16);
|
||||||
|
setupAESstate(&cbc, tkey, 16, tivec);
|
||||||
|
aesCBCdecrypt(s.Master, 32, &cbc);
|
||||||
|
|
||||||
|
memset(tivec, 0, 16);
|
||||||
|
setupAESstate(&cbc, s.Master, 16, tivec);
|
||||||
|
|
||||||
|
aes_decrypt(cbc.dkey, cbc.rounds, &buf[(64*1024)-16], &buf[(64*1024)-16]);
|
||||||
|
|
||||||
|
/* make the pad for checking crypto */
|
||||||
|
for(i=0; i<8; i++)
|
||||||
|
if((buf[(64*1024)-8+i] ^ buf[(64*1024)-16+i]) != 255) {
|
||||||
|
goto openpass;
|
||||||
|
}
|
||||||
|
|
||||||
|
base = utfrrune(file, '/');
|
||||||
|
fd2path(fd, fdpath, 1024);
|
||||||
|
j = sprint((char*)buf, "crypt %s %s ", base ? base+1 : file, fdpath);
|
||||||
|
|
||||||
|
for(i=0; i<32; i++) {
|
||||||
|
sprint((char*)&buf[j], "%02X", s.Master[i]);
|
||||||
|
j += 2;
|
||||||
|
}
|
||||||
|
sprint((char*)&buf[j], "\n");
|
||||||
|
print("%s\n", (char*)buf);
|
||||||
|
}
|
10
sys/src/cmd/cryptsetup/mkfile
Normal file
10
sys/src/cmd/cryptsetup/mkfile
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
</$objtype/mkfile
|
||||||
|
|
||||||
|
BIN=/$objtype/bin
|
||||||
|
TARG=cryptsetup
|
||||||
|
OFILES=\
|
||||||
|
cryptsetup.$O\
|
||||||
|
readcons.$O\
|
||||||
|
pbkdf2.$O\
|
||||||
|
|
||||||
|
</sys/src/cmd/mkone
|
77
sys/src/cmd/cryptsetup/pbkdf2.c
Normal file
77
sys/src/cmd/cryptsetup/pbkdf2.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/* $OpenBSD: pbkdf2.c,v 1.1 2008/06/14 06:28:27 djm Exp $ */
|
||||||
|
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <mp.h>
|
||||||
|
#include <libsec.h>
|
||||||
|
#define DS DigestState /* only to abbreviate SYNOPSIS */
|
||||||
|
#define SHA1_DIGEST_LENGTH 20
|
||||||
|
#define MIN(a,b) ((a < b) ? a : b)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Password-Based Key Derivation Function 2 (PKCS #5 v2.0).
|
||||||
|
* Code based on IEEE Std 802.11-2007, Annex H.4.2.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
pkcs5_pbkdf2(const unsigned char *pass, int pass_len, const unsigned char *salt, int salt_len,
|
||||||
|
unsigned char *key, int key_len, int rounds)
|
||||||
|
{
|
||||||
|
unsigned char *asalt, obuf[SHA1_DIGEST_LENGTH];
|
||||||
|
unsigned char d1[SHA1_DIGEST_LENGTH], d2[SHA1_DIGEST_LENGTH];
|
||||||
|
unsigned i, j;
|
||||||
|
unsigned count;
|
||||||
|
unsigned r;
|
||||||
|
|
||||||
|
if (rounds < 1 || key_len == 0)
|
||||||
|
return -1;
|
||||||
|
if (salt_len == 0)
|
||||||
|
return -1;
|
||||||
|
if ((asalt = malloc(salt_len + 4)) == nil)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memcpy(asalt, salt, salt_len);
|
||||||
|
|
||||||
|
for (count = 1; key_len > 0; count++) {
|
||||||
|
asalt[salt_len + 0] = (count >> 24) & 0xff;
|
||||||
|
asalt[salt_len + 1] = (count >> 16) & 0xff;
|
||||||
|
asalt[salt_len + 2] = (count >> 8) & 0xff;
|
||||||
|
asalt[salt_len + 3] = count & 0xff;
|
||||||
|
hmac_sha1(asalt, salt_len + 4, pass, pass_len, d1, nil);
|
||||||
|
memcpy(obuf, d1, sizeof(obuf));
|
||||||
|
|
||||||
|
for (i = 1; i < rounds; i++) {
|
||||||
|
hmac_sha1(d1, sizeof(d1), pass, pass_len, d2, nil);
|
||||||
|
memcpy(d1, d2, sizeof(d1));
|
||||||
|
for (j = 0; j < sizeof(obuf); j++)
|
||||||
|
obuf[j] ^= d1[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
r = MIN(key_len, SHA1_DIGEST_LENGTH);
|
||||||
|
memcpy(key, obuf, r);
|
||||||
|
key += r;
|
||||||
|
key_len -= r;
|
||||||
|
};
|
||||||
|
memset(asalt, 0, salt_len + 4);
|
||||||
|
free(asalt);
|
||||||
|
memset(d1, 0, sizeof(d1));
|
||||||
|
memset(d2, 0, sizeof(d2));
|
||||||
|
memset(obuf, 0, sizeof(obuf));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
77
sys/src/cmd/cryptsetup/readcons.c
Normal file
77
sys/src/cmd/cryptsetup/readcons.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/* From /sys/src/libauthsrv/readnvram.c, LPL licensed */
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
|
||||||
|
|
||||||
|
char*
|
||||||
|
readcons(char *prompt, char *def, int raw, char *buf, int nbuf)
|
||||||
|
{
|
||||||
|
int fdin, fdout, ctl, n, m;
|
||||||
|
char line[10];
|
||||||
|
|
||||||
|
fdin = open("/dev/cons", OREAD);
|
||||||
|
if(fdin < 0)
|
||||||
|
fdin = 0;
|
||||||
|
fdout = open("/dev/cons", OWRITE);
|
||||||
|
if(fdout < 0)
|
||||||
|
fdout = 1;
|
||||||
|
if(def != nil)
|
||||||
|
fprint(fdout, "%s[%s]: ", prompt, def);
|
||||||
|
else
|
||||||
|
fprint(fdout, "%s: ", prompt);
|
||||||
|
if(raw){
|
||||||
|
ctl = open("/dev/consctl", OWRITE);
|
||||||
|
if(ctl >= 0)
|
||||||
|
write(ctl, "rawon", 5);
|
||||||
|
} else
|
||||||
|
ctl = -1;
|
||||||
|
|
||||||
|
m = 0;
|
||||||
|
for(;;){
|
||||||
|
n = read(fdin, line, 1);
|
||||||
|
if(n == 0){
|
||||||
|
close(ctl);
|
||||||
|
werrstr("readcons: EOF");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
if(n < 0){
|
||||||
|
close(ctl);
|
||||||
|
werrstr("can't read cons");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
if(line[0] == 0x7f)
|
||||||
|
exits(0);
|
||||||
|
if(n == 0 || line[0] == '\n' || line[0] == '\r'){
|
||||||
|
if(raw){
|
||||||
|
write(ctl, "rawoff", 6);
|
||||||
|
write(fdout, "\n", 1);
|
||||||
|
close(ctl);
|
||||||
|
}
|
||||||
|
buf[m] = '\0';
|
||||||
|
if(buf[0]=='\0' && def)
|
||||||
|
strcpy(buf, def);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
if(line[0] == '\b'){
|
||||||
|
if(m > 0)
|
||||||
|
m--;
|
||||||
|
}else if(line[0] == 0x15){ /* ^U: line kill */
|
||||||
|
m = 0;
|
||||||
|
if(def != nil)
|
||||||
|
fprint(fdout, "%s[%s]: ", prompt, def);
|
||||||
|
else
|
||||||
|
fprint(fdout, "%s: ", prompt);
|
||||||
|
}else{
|
||||||
|
if(m >= nbuf-1){
|
||||||
|
fprint(fdout, "line too long\n");
|
||||||
|
m = 0;
|
||||||
|
if(def != nil)
|
||||||
|
fprint(fdout, "%s[%s]: ", prompt, def);
|
||||||
|
else
|
||||||
|
fprint(fdout, "%s: ", prompt);
|
||||||
|
}else
|
||||||
|
buf[m++] = line[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
69
sys/src/libsec/port/aes_xts.c
Normal file
69
sys/src/libsec/port/aes_xts.c
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
// Author Taru Karttunen <taruti@taruti.net>
|
||||||
|
// This file can be used as both Public Domain or Creative Commons CC0.
|
||||||
|
#include <u.h>
|
||||||
|
#include <libsec.h>
|
||||||
|
|
||||||
|
#define AesBlockSize 16
|
||||||
|
|
||||||
|
static void xor128(uchar* o,uchar* i1,uchar* i2) {
|
||||||
|
((ulong*)o)[0] = ((ulong*)i1)[0] ^ ((ulong*)i2)[0];
|
||||||
|
((ulong*)o)[1] = ((ulong*)i1)[1] ^ ((ulong*)i2)[1];
|
||||||
|
((ulong*)o)[2] = ((ulong*)i1)[2] ^ ((ulong*)i2)[2];
|
||||||
|
((ulong*)o)[3] = ((ulong*)i1)[3] ^ ((ulong*)i2)[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gf_mulx(uchar* x) {
|
||||||
|
ulong t = ((((ulong*)(x))[3] & 0x80000000u) ? 0x00000087u : 0);;
|
||||||
|
((ulong*)(x))[3] = (((ulong*)(x))[3] << 1) | (((ulong*)(x))[2] & 0x80000000u ? 1 : 0);
|
||||||
|
((ulong*)(x))[2] = (((ulong*)(x))[2] << 1) | (((ulong*)(x))[1] & 0x80000000u ? 1 : 0);
|
||||||
|
((ulong*)(x))[1] = (((ulong*)(x))[1] << 1) | (((ulong*)(x))[0] & 0x80000000u ? 1 : 0);
|
||||||
|
((ulong*)(x))[0] = (((ulong*)(x))[0] << 1) ^ t;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int aes_xts_encrypt(ulong tweak[], ulong ecb[], vlong sectorNumber, uchar *input, uchar *output, ulong len) {
|
||||||
|
uchar T[16], x[16];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(len % 16 != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for(i=0; i<AesBlockSize; i++) {
|
||||||
|
T[i] = (uchar)(sectorNumber & 0xFF);
|
||||||
|
sectorNumber = sectorNumber >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
aes_encrypt(tweak, 10, T, T);
|
||||||
|
|
||||||
|
for (i=0; i<len; i+=AesBlockSize) {
|
||||||
|
xor128(&x[0], &input[i], &T[0]);
|
||||||
|
aes_encrypt(ecb, 10, x, x);
|
||||||
|
xor128(&output[i], &x[0], &T[0]);
|
||||||
|
gf_mulx(&T[0]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int aes_xts_decrypt(ulong tweak[], ulong ecb[], vlong sectorNumber, uchar *input, uchar *output, ulong len) {
|
||||||
|
uchar T[16], x[16];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(len % 16 != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for(i=0; i<AesBlockSize; i++) {
|
||||||
|
T[i] = (uchar)(sectorNumber & 0xFF);
|
||||||
|
sectorNumber = sectorNumber >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
aes_encrypt(tweak, 10, T, T);
|
||||||
|
|
||||||
|
for (i=0; i<len; i+=AesBlockSize) {
|
||||||
|
xor128(&x[0], &input[i], &T[0]);
|
||||||
|
aes_decrypt(ecb, 10, x, x);
|
||||||
|
xor128(&output[i], &x[0], &T[0]);
|
||||||
|
gf_mulx(&T[0]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ CFILES = des.c desmodes.c desECB.c desCBC.c des3ECB.c des3CBC.c\
|
||||||
egsign.c egverify.c \
|
egsign.c egverify.c \
|
||||||
dsagen.c dsaalloc.c dsaprivtopub.c dsasign.c dsaverify.c \
|
dsagen.c dsaalloc.c dsaprivtopub.c dsasign.c dsaverify.c \
|
||||||
tlshand.c thumb.c readcert.c \
|
tlshand.c thumb.c readcert.c \
|
||||||
|
aes_xts.c \
|
||||||
|
|
||||||
ALLOFILES=${CFILES:%.c=%.$O}
|
ALLOFILES=${CFILES:%.c=%.$O}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue