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 */
|
||||
uchar *readcert(char *filename, int *pcertlen);
|
||||
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 "ureg.h"
|
||||
#include "../port/error.h"
|
||||
#include "libsec.h"
|
||||
|
||||
int dec16(uchar *out, int lim, char *in, int n);
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -32,6 +35,7 @@ enum
|
|||
Fclear, /* start over */
|
||||
Fdel, /* delete a configure device */
|
||||
Fdisk, /* set default tree and sector sz*/
|
||||
Fcrypt, /* encrypted device */
|
||||
|
||||
Sectorsz = 1,
|
||||
Blksize = 8*1024, /* for Finter only */
|
||||
|
@ -65,6 +69,7 @@ enum
|
|||
typedef struct Inner Inner;
|
||||
typedef struct Fsdev Fsdev;
|
||||
typedef struct Tree Tree;
|
||||
typedef struct Key Key;
|
||||
|
||||
struct Inner
|
||||
{
|
||||
|
@ -85,6 +90,7 @@ struct Fsdev
|
|||
vlong start; /* start address (for Fpart) */
|
||||
uint ndevs; /* number of inner devices */
|
||||
Inner *inner[Ndevs]; /* inner devices */
|
||||
void *extra; /* extra state for the device */
|
||||
};
|
||||
|
||||
struct Tree
|
||||
|
@ -95,6 +101,10 @@ struct Tree
|
|||
uint nadevs; /* number of allocated devices in devs */
|
||||
};
|
||||
|
||||
struct Key {
|
||||
AESstate tweak, ecb;
|
||||
};
|
||||
|
||||
#define dprint if(debug)print
|
||||
|
||||
extern Dev fsdevtab; /* forward */
|
||||
|
@ -121,6 +131,7 @@ static char* tnames[] = {
|
|||
[Fcat] "cat",
|
||||
[Finter] "inter",
|
||||
[Fpart] "part",
|
||||
[Fcrypt] "crypt",
|
||||
};
|
||||
|
||||
static Cmdtab configs[] = {
|
||||
|
@ -131,6 +142,7 @@ static Cmdtab configs[] = {
|
|||
Fclear, "clear", 1,
|
||||
Fdel, "del", 2,
|
||||
Fdisk, "disk", 0,
|
||||
Fcrypt, "crypt", 0,
|
||||
};
|
||||
|
||||
static char Egone[] = "device is gone"; /* file has been removed */
|
||||
|
@ -156,6 +168,7 @@ seprintdev(char *s, char *e, Fsdev *mp)
|
|||
case Fmirror:
|
||||
case Fcat:
|
||||
case Finter:
|
||||
case Fcrypt:
|
||||
s = strecpy(s, e, "\n");
|
||||
break;
|
||||
case Fpart:
|
||||
|
@ -434,6 +447,13 @@ setdsize(Fsdev* mp, vlong *ilen)
|
|||
mp->size = inlen - mp->start;
|
||||
}
|
||||
break;
|
||||
case Fcrypt:
|
||||
if(inlen > (64*1024)) {
|
||||
mp->size = inlen - (64 * 1024);
|
||||
} else {
|
||||
mp->size = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
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))
|
||||
error("ctl usage: part new [file] off len");
|
||||
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 *ilen;
|
||||
char *tname, *dname, *fakef[4];
|
||||
uchar key[32];
|
||||
Chan **idev;
|
||||
Cmdbuf *cb;
|
||||
Cmdtab *ct;
|
||||
|
@ -575,6 +600,10 @@ mconfig(char* a, long n)
|
|||
free(cb);
|
||||
mdelctl("*", "*"); /* del everything */
|
||||
return;
|
||||
case Fcrypt:
|
||||
dec16(key, 32, cb->f[2], 64);
|
||||
cb->nf -= 1;
|
||||
break;
|
||||
case Fpart:
|
||||
if(cb->nf == 3){
|
||||
/*
|
||||
|
@ -662,6 +691,15 @@ Fail:
|
|||
mp->start = start * 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++){
|
||||
inprv = mp->inner[i-1] = mallocz(sizeof(Inner), 1);
|
||||
if(inprv == nil)
|
||||
|
@ -673,6 +711,8 @@ Fail:
|
|||
}
|
||||
setdsize(mp, ilen);
|
||||
|
||||
|
||||
|
||||
poperror();
|
||||
wunlock(&lck);
|
||||
free(idev);
|
||||
|
@ -970,6 +1010,63 @@ io(Fsdev *mp, Inner *in, int isread, void *a, long l, vlong off)
|
|||
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 */
|
||||
static long
|
||||
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,
|
||||
(up && up->errstr? up->errstr: ""));
|
||||
break;
|
||||
case Fcrypt:
|
||||
res = cryptio(mp, Isread, a, n, off);
|
||||
break;
|
||||
}
|
||||
Done:
|
||||
poperror();
|
||||
|
@ -1235,6 +1335,9 @@ mwrite(Chan *c, void *a, long n, vlong off)
|
|||
(up && up->errstr? up->errstr: ""));
|
||||
|
||||
break;
|
||||
case Fcrypt:
|
||||
res = cryptio(mp, Iswrite, a, n, off);
|
||||
break;
|
||||
}
|
||||
Done:
|
||||
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 \
|
||||
dsagen.c dsaalloc.c dsaprivtopub.c dsasign.c dsaverify.c \
|
||||
tlshand.c thumb.c readcert.c \
|
||||
aes_xts.c \
|
||||
|
||||
ALLOFILES=${CFILES:%.c=%.$O}
|
||||
|
||||
|
|
Loading…
Reference in a new issue