189 lines · 4.1 KB · C
RawDownload
// 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[], int);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 files \t\t# Format file or device\ncryptsetup -o files \t\t# Print commandline for open\ncryptsetup -i files\t\t# Install (open) files\n");	exits("usage");} enum{	NoMode,	Format,	Open,	Install,};  voidmain(int argc, char *argv[]){	int mode; 	mode = 0; 	ARGBEGIN {	default:		usage();	case 'f':		mode = Format;		break;	case 'o':		mode = Open;		break;	case 'i':		mode = Install;		break;	} ARGEND; 	if((mode == NoMode) || (argc < 1))		usage(); 	switch(mode) {	case Format:		format(argv);		break;	case Install:	case Open:		copen(argv, mode);		break;	}} voidformat(char *files[]){	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(;*files;files++) { 		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(*files, 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 %s written\n", *files);	}} void copen(char *files[], int mode) {	unsigned char pass[32], buf[1024*64], tkey[16], tivec[16], cbuf[16];	XtsState s;	int i,j,fd, oldpass;	AESstate cbc;	char *base, fdpath[1024]; 	oldpass = 0;	for(;*files; files++) {		if((fd = open(*files, OREAD)) < 0)			exits("Cannot open disk");			if(read(fd, buf, 1024*64) != 1024*64) 			exits("Cannot read disk");			openpass:			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(!oldpass)				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); 			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) {					oldpass=0;					goto openpass;				} 		base = utfrrune(*files, '/');		fd2path(fd, fdpath, 1024);		j = sprint((char*)buf, "crypt %s %s ", base ? base+1 : *files, fdpath);			for(i=0; i<32; i++) {			sprint((char*)&buf[j], "%02X", s.Master[i]);			j += 2; 		}		buf[j++] = '\n';		close(fd);		if(mode == Install) {			fd = open("/dev/fs/ctl", OWRITE);			write(fd, buf, j);			close(fd);		} else {			write(1, buf, j);		}		oldpass=1;	}}