190 lines · 3.3 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <bio.h>#include <libsec.h>#include <authsrv.h>#include "authcmdlib.h" Authkey	okey, nkey; int	verb;int	usepass;int	convaes; uchar	zeros[16]; int	convert(char**, int);void	usage(void); voidmain(int argc, char *argv[]){	Dir *d;	char *p, *file;	int fd, len; 	ARGBEGIN{	case 'p':		usepass = 1;		break;	case 'v':		verb = 1;		break;	case 'a':		convaes = 1;		break;	default:		usage();	}ARGEND 	if(argc != 1)		usage();	file = argv[0]; 	private(); 	/* get original key */	if(usepass){		print("enter password file is encoded with\n");		getpass(&okey, nil, 0, 1);	} else {		getauthkey(&okey);	}	if(!verb){		print("enter password to reencode with\n");		getpass(&nkey, nil, 0, 1);	} 	fd = open(file, ORDWR);	if(fd < 0)		error("can't open %s: %r\n", file);	d = dirfstat(fd);	if(d == nil)		error("can't stat %s: %r\n", file);	len = d->length;	p = malloc(len);	if(p == nil)		error("out of memory");	if(read(fd, p, len) != len)		error("can't read key file: %r\n");	len = convert(&p, len);	if(pwrite(fd, p, len, 0) != len)		error("can't write key file: %r\n");	close(fd);	exits(nil);} intbadname(char *s){	int n;	Rune r; 	for (; *s != '\0'; s += n) {		n = chartorune(&r, s);		if (r == Runeerror)			return 1;	}	return 0;} intconvert(char **db, int len){	int i, nu, keydblen, keydboff, keydbaes;	char *p = *db; 	keydblen = KEYDBLEN;	keydboff = KEYDBOFF;	keydbaes = len > 24 && memcmp(p, "AES KEYS", 8) == 0;	if(keydbaes){		keydblen += AESKEYLEN;		keydboff = 8+16;		/* signature[8] + iv[16] */	} 	len -= keydboff;	if(len % keydblen){		fprint(2, "%s: file odd length; not converting %d bytes\n", argv0, len % keydblen);		len -= len % keydblen;	}	len += keydboff; 	if(keydbaes){		AESstate s; 		/* make sure we have aes key for decryption */		if(memcmp(okey.aes, zeros, AESKEYLEN) == 0){			fprint(2, "%s: no aes key in NVRAM\n", argv0);			exits("no aes key");		}		setupAESstate(&s, okey.aes, AESKEYLEN, zeros);		aesCBCdecrypt((uchar*)p+8, len-8, &s);	} else {		DESstate s;		uchar k[8]; 		des56to64((uchar*)okey.des, k);		setupDESstate(&s, k, zeros);		desCBCdecrypt((uchar*)p, len, &s);	} 	nu = 0;	for(i = keydboff; i < len; i += keydblen) {		if (badname(&p[i])) {			fprint(2, "%s: bad name %.30s... - aborting\n", argv0, &p[i]);			exits("bad name");		}		nu++;	} 	if(verb){		for(i = keydboff; i < len; i += keydblen)			print("%s\n", &p[i]);		exits(nil);	} 	if(convaes && !keydbaes){		char *s, *d; 		keydboff = 8+16;		keydblen += AESKEYLEN;		len = keydboff + keydblen*nu;		p = realloc(p, len);		if(p == nil)			error("out of memory");		*db = p;		s = p + KEYDBOFF + nu*KEYDBLEN;		d = p + keydboff + nu*keydblen;		for(i=0; i<nu; i++){			s -= KEYDBLEN;			d -= keydblen;			memmove(d, s, KEYDBLEN);			memset(d + KEYDBLEN, 0, keydblen-KEYDBLEN);		}		keydbaes = 1;	} 	genrandom((uchar*)p, keydboff);	if(keydbaes){		AESstate s; 		memmove(p, "AES KEYS", 8);		setupAESstate(&s, nkey.aes, AESKEYLEN, zeros);		aesCBCencrypt((uchar*)p+8, len-8, &s);	} else {		DESstate s;		uchar k[8]; 		des56to64((uchar*)nkey.des, k);		setupDESstate(&s, k, zeros);		desCBCencrypt((uchar*)p, len, &s);	}	return len;} voidusage(void){	fprint(2, "usage: %s [-pva] keyfile\n", argv0);	exits("usage");}