Пример #1
0
int
main(int argc, char **argv)
{
	int encrypt = 0;  /* 0=decrypt, 1=encrypt */
	int n, nkey, pass_stdin = 0, pass_nvram = 0;
	char *pass;
	unsigned char key[AESmaxkey], key2[SHA1dlen];
	unsigned char 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((unsigned char*)"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 */
}
Пример #2
0
static int
getfile(SConn *conn, char *gf, uchar **buf, ulong *buflen, uchar *key, int nkey)
{
	int fd = -1;
	int i, n, nr, nw, len;
	char s[Maxmsg+1];
	uchar skey[SHA1dlen], ib[Maxmsg+CHK], *ibr, *ibw, *bufw, *bufe;
	AESstate aes;
	DigestState *sha;

	if(strchr(gf, '/')){
		fprint(2, "simple filenames, not paths like %s\n", gf);
		return -1;
	}
	memset(&aes, 0, sizeof aes);

	snprint(s, Maxmsg, "GET %s\n", gf);
	conn->write(conn, (uchar*)s, strlen(s));

	/* get file size */
	s[0] = '\0';
	bufw = bufe = nil;
	if(readstr(conn, s) < 0){
		fprint(2, "remote: %s\n", s);
		return -1;
	}
	len = atoi(s);
	if(len == -1){
		fprint(2, "remote file %s does not exist\n", gf);
		return -1;
	}else if(len == -3){
		fprint(2, "implausible filesize for %s\n", gf);
		return -1;
	}else if(len < 0){
		fprint(2, "GET refused for %s\n", gf);
		return -1;
	}
	if(buf != nil){
		*buflen = len - AESbsize - CHK;
		*buf = bufw = emalloc(len);
		bufe = bufw + len;
	}

	/* directory listing */
	if(strcmp(gf,".")==0){
		if(buf != nil)
			*buflen = len;
		for(i=0; i < len; i += n){
			if((n = conn->read(conn, (uchar*)s, Maxmsg)) <= 0){
				fprint(2, "empty file chunk\n");
				return -1;
			}
			if(buf == nil)
				write(1, s, n);
			else
				memmove((*buf)+i, s, n);
		}
		return 0;
	}

	/* conn is already encrypted against wiretappers, 
		but gf is also encrypted against server breakin. */
	if(buf == nil && (fd =create(gf, OWRITE, 0600)) < 0){
		fprint(2, "can't open %s: %r\n", gf);
		return -1;
	}

	ibr = ibw = ib;
	for(nr=0; nr < len;){
		if((n = conn->read(conn, ibw, Maxmsg)) <= 0){
			fprint(2, "empty file chunk n=%d nr=%d len=%d: %r\n", n, nr, len);
			return -1;
		}
		nr += n;
		ibw += n;
		if(!aes.setup){ /* first time, read 16 byte IV */
			if(n < AESbsize){
				fprint(2, "no IV in file\n");
				return -1;
			}
			sha = sha1((uchar*)"aescbc file", 11, nil, nil);
			sha1(key, nkey, skey, sha);
			setupAESstate(&aes, skey, AESbsize, ibr);
			memset(skey, 0, sizeof skey);
			ibr += AESbsize;
			n -= AESbsize;
		}
		aesCBCdecrypt(ibw-n, n, &aes);
		n = ibw-ibr-CHK;
		if(n > 0){
			if(buf == nil){
				nw = write(fd, ibr, n);
				if(nw != n){
					fprint(2, "write error on %s", gf);
					return -1;
				}
			}else{
				assert(bufw+n <= bufe);
				memmove(bufw, ibr, n);
				bufw += n;
			}
			ibr += n;
		}
		memmove(ib, ibr, ibw-ibr);
		ibw = ib + (ibw-ibr);
		ibr = ib;
	}
	if(buf == nil)
		close(fd);
	n = ibw-ibr;
	if((n != CHK) || (memcmp(ib, "XXXXXXXXXXXXXXXX", CHK) != 0)){
			fprint(2,"decrypted file failed to authenticate!\n");
			return -1;
	}
	return 0;
}
Пример #3
0
int
convert(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;
}