diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/auth/secstore/aescbc.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/auth/secstore/aescbc.c')
-rwxr-xr-x | sys/src/cmd/auth/secstore/aescbc.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/sys/src/cmd/auth/secstore/aescbc.c b/sys/src/cmd/auth/secstore/aescbc.c new file mode 100755 index 000000000..a7a0e984a --- /dev/null +++ b/sys/src/cmd/auth/secstore/aescbc.c @@ -0,0 +1,150 @@ +/* encrypt file by writing + v2hdr, + 16byte initialization vector, + AES-CBC(key, random | file), + HMAC_SHA1(md5(key), AES-CBC(random | file)) +*/ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <mp.h> +#include <libsec.h> +#include <authsrv.h> + +extern char* getpassm(char*); + +enum{ CHK = 16, BUF = 4096 }; + +uchar v2hdr[AESbsize+1] = "AES CBC SHA1 2\n"; +Biobuf bin; +Biobuf bout; + +void +safewrite(uchar *buf, int n) +{ + if(Bwrite(&bout, buf, n) != n) + sysfatal("write error"); +} + +void +saferead(uchar *buf, int n) +{ + if(Bread(&bin, buf, n) != n) + sysfatal("read error"); +} + +int +main(int argc, char **argv) +{ + int encrypt = 0; /* 0=decrypt, 1=encrypt */ + int n, nkey, pass_stdin = 0, pass_nvram = 0; + char *pass; + uchar key[AESmaxkey], key2[SHA1dlen]; + uchar buf[BUF+SHA1dlen]; /* assumption: CHK <= SHA1dlen */ + AESstate aes; + DigestState *dstate; + Nvrsafe nvr; + + ARGBEGIN{ + case 'e': + encrypt = 1; + break; + case 'i': + pass_stdin = 1; + break; + case 'n': + pass_nvram = 1; + break; + }ARGEND; + if(argc!=0){ + fprint(2,"usage: %s -d < cipher.aes > clear.txt\n", argv0); + fprint(2," or: %s -e < clear.txt > cipher.aes\n", argv0); + exits("usage"); + } + Binit(&bin, 0, OREAD); + Binit(&bout, 1, OWRITE); + + if(pass_stdin){ + n = readn(3, buf, (sizeof buf)-1); + if(n < 1) + exits("usage: echo password |[3=1] auth/aescbc -i ..."); + buf[n] = 0; + while(buf[n-1] == '\n') + buf[--n] = 0; + }else if(pass_nvram){ + if(readnvram(&nvr, 0) < 0) + exits("readnvram: %r"); + strecpy((char*)buf, (char*)buf+sizeof buf, (char*)nvr.config); + n = strlen((char*)buf); + }else{ + pass = getpassm("aescbc key:"); + n = strlen(pass); + if(n >= BUF) + exits("key too long"); + strcpy((char*)buf, pass); + memset(pass, 0, n); + free(pass); + } + if(n <= 0) + sysfatal("no key"); + dstate = sha1((uchar*)"aescbc file", 11, nil, nil); + sha1(buf, n, key2, dstate); + memcpy(key, key2, 16); + nkey = 16; + md5(key, nkey, key2, 0); /* so even if HMAC_SHA1 is broken, encryption key is protected */ + + if(encrypt){ + safewrite(v2hdr, AESbsize); + genrandom(buf,2*AESbsize); /* CBC is semantically secure if IV is unpredictable. */ + setupAESstate(&aes, key, nkey, buf); /* use first AESbsize bytes as IV */ + aesCBCencrypt(buf+AESbsize, AESbsize, &aes); /* use second AESbsize bytes as initial plaintext */ + safewrite(buf, 2*AESbsize); + dstate = hmac_sha1(buf+AESbsize, AESbsize, key2, MD5dlen, 0, 0); + for(;;){ + n = Bread(&bin, buf, BUF); + if(n < 0) + sysfatal("read error"); + aesCBCencrypt(buf, n, &aes); + safewrite(buf, n); + dstate = hmac_sha1(buf, n, key2, MD5dlen, 0, dstate); + if(n < BUF) + break; /* EOF */ + } + hmac_sha1(0, 0, key2, MD5dlen, buf, dstate); + safewrite(buf, SHA1dlen); + }else{ /* decrypt */ + saferead(buf, AESbsize); + if(memcmp(buf, v2hdr, AESbsize) == 0){ + saferead(buf, 2*AESbsize); /* read IV and random initial plaintext */ + setupAESstate(&aes, key, nkey, buf); + dstate = hmac_sha1(buf+AESbsize, AESbsize, key2, MD5dlen, 0, 0); + aesCBCdecrypt(buf+AESbsize, AESbsize, &aes); + saferead(buf, SHA1dlen); + while((n = Bread(&bin, buf+SHA1dlen, BUF)) > 0){ + dstate = hmac_sha1(buf, n, key2, MD5dlen, 0, dstate); + aesCBCdecrypt(buf, n, &aes); + safewrite(buf, n); + memmove(buf, buf+n, SHA1dlen); /* these bytes are not yet decrypted */ + } + hmac_sha1(0, 0, key2, MD5dlen, buf+SHA1dlen, dstate); + if(memcmp(buf, buf+SHA1dlen, SHA1dlen) != 0) + sysfatal("decrypted file failed to authenticate"); + }else{ /* compatibility with past mistake */ + // if file was encrypted with bad aescbc use this: + // memset(key, 0, AESmaxkey); + // else assume we're decrypting secstore files + setupAESstate(&aes, key, AESbsize, buf); + saferead(buf, CHK); + aesCBCdecrypt(buf, CHK, &aes); + while((n = Bread(&bin, buf+CHK, BUF)) > 0){ + aesCBCdecrypt(buf+CHK, n, &aes); + safewrite(buf, n); + memmove(buf, buf+n, CHK); + } + if(memcmp(buf, "XXXXXXXXXXXXXXXX", CHK) != 0) + sysfatal("decrypted file failed to authenticate"); + } + } + exits(""); + return 1; /* keep other compilers happy */ +} |