diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-10-24 20:56:11 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-10-24 20:56:11 +0200 |
commit | 234137bce39a03eab02044234c8f970498ccc5b0 (patch) | |
tree | 85e2d2707d34ac7f19ee0f7c6b23ea309701b470 /sys/src/cmd/disk/cryptsetup.c | |
parent | f3feafc476ff108231dd6e0e3ac3cd420a62a81c (diff) |
fix bugs and cleanup cryptsetup code
devfs:
- fix memory leak in devfs leaking the aes key
- allocate aes-xts cipher state in secure memory
- actually check if the hexkey got fully parsed
cryptsetup:
- get rid of stupid "type YES" prompt
- use genrandom() to generate salts and keys
- rewrite cryptsetup to use common pbkdf2 and readcons routines
- fix alot of error handling and simplify the code
- move cryptsetup command to disk/cryptsetup
- update cryptsetup(8) manual page
Diffstat (limited to 'sys/src/cmd/disk/cryptsetup.c')
-rw-r--r-- | sys/src/cmd/disk/cryptsetup.c | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/sys/src/cmd/disk/cryptsetup.c b/sys/src/cmd/disk/cryptsetup.c new file mode 100644 index 000000000..7e537867d --- /dev/null +++ b/sys/src/cmd/disk/cryptsetup.c @@ -0,0 +1,212 @@ +// Original 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 <libsec.h> +#include <authsrv.h> + +typedef struct { + uchar Salt[16]; + uchar Key[32]; +} Slot; + +typedef struct { + uchar Master[32]; + Slot Slots[8]; + AESstate C1, C2; +} XtsState; + +uchar zeros[16] = {0}; +uchar buf[64*1024]; +AESstate cbc; +XtsState s; + +void +setupkey(char *pass, uchar salt[16], AESstate *aes) +{ + uchar tkey[32]; + + pbkdf2_x((uchar*)pass, strlen(pass), salt, 16, 9999, tkey, 32, hmac_sha1, SHA1dlen); + setupAESstate(aes, tkey, 16, zeros); + memset(tkey, 0, sizeof(tkey)); +} + +void +freepass(char *pass) +{ + if(pass != nil){ + memset(pass, 0, strlen(pass)); + free(pass); + } +} + +void +cformat(char *files[]) +{ + char *pass, *tmp; + int fd, i, j; + + pass = nil; + do { + freepass(pass); + pass = readcons("Password", nil, 1); + if(pass == nil || pass[0] == 0) + sysfatal("input aborted"); + tmp = readcons("Confirm", nil, 1); + if(tmp == nil || tmp[0] == 0) + sysfatal("input aborted"); + i = strcmp(pass, tmp); + freepass(tmp); + } while(i != 0); + + for(;*files != nil; files++) { + genrandom((uchar*)&s, sizeof(s)); + setupkey(pass, s.Slots[0].Salt, &cbc); + memcpy(s.Slots[0].Key, s.Master, 32); + aesCBCencrypt(s.Slots[0].Key, 32, &cbc); + + genrandom(buf, 16*4096); + for(i=0; i<16; i++) + for(j=0; j<8; j++) { + 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(*files, OWRITE)) < 0) + sysfatal("open disk: %r"); + + /* make the pad for checking crypto */ + for(i=0; i<8; i++) + buf[(64*1024)-8+i] = ~buf[(64*1024)-16+i]; + + setupAESstate(&cbc, s.Master, 16, zeros); + aes_encrypt(cbc.ekey, cbc.rounds, &buf[(64*1024)-16], &buf[(64*1024)-16]); + + if(write(fd, buf, 64*1024) != 64*1024) + sysfatal("writing disk: %r"); + } +} + +void +copen(char *files[], int ctl) +{ + char *pass, *name; + uchar cbuf[16]; + int fd, i, j; + + pass = nil; + for(;*files != nil; files++) { + memset(&s, 0, sizeof(s)); + if((fd = open(*files, OREAD)) < 0) + sysfatal("open disk: %r"); + + if(read(fd, buf, 1024*64) != 1024*64) + sysfatal("read disk: %r"); + + retrypass: + 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]; + } + + if(pass == nil){ + pass = readcons("Password", nil, 1); + if(pass == nil || pass[0] == 0) + sysfatal("input aborted"); + } + + setupkey(pass, s.Slots[0].Salt, &cbc); + memcpy(s.Master, s.Slots[0].Key, 32); + aesCBCdecrypt(s.Master, 32, &cbc); + setupAESstate(&cbc, s.Master, 16, zeros); + + memcpy(cbuf, &buf[(64*1024)-16], 16); + aes_decrypt(cbc.dkey, cbc.rounds, cbuf, cbuf); + + /* make the pad for checking crypto */ + for(i=0; i<8; i++) + if((cbuf[i] ^ cbuf[i+8]) != 255) { + freepass(pass); + pass = nil; + fprint(2, "wrong key\n"); + goto retrypass; + } + + fd2path(fd, (char*)buf, sizeof(buf)); + close(fd); + + if((name = strrchr(*files, '/')) != nil) + name++; + else + name = *files; + + if(fprint(ctl, "crypt %q %q %.32H\n", name, (char*)buf, s.Master) < 0) + sysfatal("write: %r"); + } +} + +void +usage(void) +{ + print("usage:\n" + "%s -f files\t\t# Format file or device\n" + "%s -o files\t\t# Print commandline for open\n" + "%s -i files\t\t# Install (open) files\n", + argv0, argv0, argv0); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + enum { + NoMode, + Format, + Open, + Install, + }; + int mode, ctl; + + quotefmtinstall(); + fmtinstall('H', encodefmt); + + ctl = 1; + mode = NoMode; + + ARGBEGIN { + default: + usage(); + case 'f': + mode = Format; + break; + case 'o': + mode = Open; + break; + case 'i': + mode = Install; + break; + } ARGEND; + + if(argc < 0) + usage(); + + switch(mode){ + default: + usage(); + case Format: + cformat(argv); + break; + case Install: + if((ctl = open("/dev/fs/ctl", OWRITE)) < 0) + sysfatal("open ctl: %r"); + /* no break */ + case Open: + copen(argv, ctl); + break; + } + + exits(nil); +} |