diff options
author | taruti <taruti@violetti.org> | 2011-05-24 22:19:33 +0000 |
---|---|---|
committer | taruti <taruti@violetti.org> | 2011-05-24 22:19:33 +0000 |
commit | 9655db255097b84cf742b7a33c74432d4eb3425a (patch) | |
tree | 81dd1509453d330ac9e94ca6f5b1a7fe7bdbba2d /sys/src/cmd/cryptsetup | |
parent | f34231e16a9780a1aa1b9fe5dad1776dd82caa44 (diff) |
devfs crypto code - alpha version
Diffstat (limited to 'sys/src/cmd/cryptsetup')
-rw-r--r-- | sys/src/cmd/cryptsetup/crypt.h | 14 | ||||
-rw-r--r-- | sys/src/cmd/cryptsetup/cryptsetup.c | 173 | ||||
-rw-r--r-- | sys/src/cmd/cryptsetup/mkfile | 10 | ||||
-rw-r--r-- | sys/src/cmd/cryptsetup/pbkdf2.c | 77 | ||||
-rw-r--r-- | sys/src/cmd/cryptsetup/readcons.c | 77 |
5 files changed, 351 insertions, 0 deletions
diff --git a/sys/src/cmd/cryptsetup/crypt.h b/sys/src/cmd/cryptsetup/crypt.h new file mode 100644 index 000000000..314077a31 --- /dev/null +++ b/sys/src/cmd/cryptsetup/crypt.h @@ -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; diff --git a/sys/src/cmd/cryptsetup/cryptsetup.c b/sys/src/cmd/cryptsetup/cryptsetup.c new file mode 100644 index 000000000..f3b0b43ee --- /dev/null +++ b/sys/src/cmd/cryptsetup/cryptsetup.c @@ -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); +}
\ No newline at end of file diff --git a/sys/src/cmd/cryptsetup/mkfile b/sys/src/cmd/cryptsetup/mkfile new file mode 100644 index 000000000..7dc3ede08 --- /dev/null +++ b/sys/src/cmd/cryptsetup/mkfile @@ -0,0 +1,10 @@ +</$objtype/mkfile + +BIN=/$objtype/bin +TARG=cryptsetup +OFILES=\ + cryptsetup.$O\ + readcons.$O\ + pbkdf2.$O\ + +</sys/src/cmd/mkone diff --git a/sys/src/cmd/cryptsetup/pbkdf2.c b/sys/src/cmd/cryptsetup/pbkdf2.c new file mode 100644 index 000000000..e1b0f4e89 --- /dev/null +++ b/sys/src/cmd/cryptsetup/pbkdf2.c @@ -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; +} diff --git a/sys/src/cmd/cryptsetup/readcons.c b/sys/src/cmd/cryptsetup/readcons.c new file mode 100644 index 000000000..cc2926cf0 --- /dev/null +++ b/sys/src/cmd/cryptsetup/readcons.c @@ -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]; + } + } +} + |