X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=sys%2Fsrc%2F9%2Fport%2Fdevtls.c;h=177d8ecb4243f2be49f892b4fd988265ec995527;hb=c2297ce5c180e98f2217a691a25d19a300956d9f;hp=93bd8225ef8d11ae7425825cb292f5734442c60e;hpb=3e52ada202e1e3d27c532921bd38934ec0db1b74;p=plan9front.git diff --git a/sys/src/9/port/devtls.c b/sys/src/9/port/devtls.c index 93bd8225e..177d8ecb4 100644 --- a/sys/src/9/port/devtls.c +++ b/sys/src/9/port/devtls.c @@ -1,5 +1,5 @@ /* - * devtls - record layer for transport layer security 1.0 and secure sockets layer 3.0 + * devtls - record layer for transport layer security 1.2 and secure sockets layer 3.0 */ #include "u.h" #include "../port/lib.h" @@ -83,16 +83,18 @@ struct Secret { char *encalg; /* name of encryption alg */ char *hashalg; /* name of hash alg */ + + int (*aead_enc)(Secret*, uchar*, int, uchar*, uchar*, int); + int (*aead_dec)(Secret*, uchar*, int, uchar*, uchar*, int); + int (*enc)(Secret*, uchar*, int); int (*dec)(Secret*, uchar*, int); int (*unpad)(uchar*, int, int); - DigestState *(*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*); - - int (*aead_enc)(Secret*, uchar*, int, uchar*, int); - int (*aead_dec)(Secret*, uchar*, int, uchar*, int); + DigestState* (*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*); int block; /* encryption block len, 0 if none */ - int maclen; + int maclen; /* # bytes of record mac / authentication tag */ + int recivlen; /* # bytes of record iv for AEAD ciphers */ void *enckey; uchar mackey[MaxMacLen]; }; @@ -235,7 +237,6 @@ static void put64(uchar *p, u64int); static void put32(uchar *p, u32int); static void put24(uchar *p, int); static void put16(uchar *p, int); -static u32int get32(uchar *p); static int get16(uchar *p); static void tlsSetState(TlsRec *tr, int new, int old); static void rcvAlert(TlsRec *tr, int err); @@ -246,8 +247,10 @@ static int des3enc(Secret *sec, uchar *buf, int n); static int des3dec(Secret *sec, uchar *buf, int n); static int aesenc(Secret *sec, uchar *buf, int n); static int aesdec(Secret *sec, uchar *buf, int n); -static int ccpoly_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *data, int len); -static int ccpoly_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *data, int len); +static int ccpoly_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len); +static int ccpoly_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len); +static int aesgcm_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len); +static int aesgcm_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len); static int noenc(Secret *sec, uchar *buf, int n); static int sslunpad(uchar *buf, int n, int block); static int tlsunpad(uchar *buf, int n, int block); @@ -420,21 +423,7 @@ static Chan* tlsopen(Chan *c, int omode) { TlsRec *tr, **pp; - int t, perm; - - perm = 0; - omode &= 3; - switch(omode) { - case OREAD: - perm = 4; - break; - case OWRITE: - perm = 2; - break; - case ORDWR: - perm = 6; - break; - } + int t; t = TYPE(c->qid); switch(t) { @@ -467,10 +456,7 @@ tlsopen(Chan *c, int omode) tr = *pp; if(tr == nil) error("must open connection using clone"); - if((perm & (tr->perm>>6)) != perm - && (strcmp(up->user, tr->user) != 0 - || (perm & tr->perm) != perm)) - error(Eperm); + devpermcheck(tr->user, tr->perm, omode); if(t == Qhand){ if(waserror()){ unlock(&tr->hqlock); @@ -530,7 +516,7 @@ tlswstat(Chan *c, uchar *dp, int n) error(Eshortstat); if(!emptystr(d->uid)) kstrdup(&tr->user, d->uid); - if(d->mode != ~0UL) + if(d->mode != -1) tr->perm = d->mode; free(d); @@ -821,14 +807,16 @@ if(tr->debug) pprint("decrypted %d\n", unpad_len); if(tr->debug) pdump(unpad_len, p, "decrypted:"); } + ivlen = sec->recivlen; if(tr->version >= TLS11Version){ - ivlen = sec->block; - len -= ivlen; - if(len < 0) - rcvError(tr, EDecodeError, "runt record message"); - unpad_len -= ivlen; - p += ivlen; + if(ivlen == 0) + ivlen = sec->block; } + len -= ivlen; + if(len < 0) + rcvError(tr, EDecodeError, "runt record message"); + unpad_len -= ivlen; + p += ivlen; if(unpad_len >= sec->maclen) len = unpad_len - sec->maclen; @@ -837,7 +825,7 @@ if(tr->debug) pdump(unpad_len, p, "decrypted:"); put16(header+3, len); aadlen = (*tr->packAAD)(in->seq++, header, aad); if(sec->aead_dec != nil) { - len = (*sec->aead_dec)(sec, aad, aadlen, p, unpad_len); + len = (*sec->aead_dec)(sec, aad, aadlen, p - ivlen, p, unpad_len); if(len < 0) rcvError(tr, EBadRecordMac, "record mac mismatch"); } else { @@ -1191,7 +1179,9 @@ tlsread(Chan *c, void *a, long n, vlong off) if(tr->out.sec != nil) s = seprint(s, e, "EncOut: %s\nHashOut: %s\n", tr->out.sec->encalg, tr->out.sec->hashalg); if(tr->out.new != nil) - seprint(s, e, "NewEncOut: %s\nNewHashOut: %s\n", tr->out.new->encalg, tr->out.new->hashalg); + s = seprint(s, e, "NewEncOut: %s\nNewHashOut: %s\n", tr->out.new->encalg, tr->out.new->hashalg); + if(tr->c != nil) + seprint(s, e, "Chan: %s\n", chanpath(tr->c)); qunlock(&tr->in.seclock); qunlock(&tr->out.seclock); n = readstr(offset, a, n, buf); @@ -1243,13 +1233,6 @@ tlsread(Chan *c, void *a, long n, vlong off) return n; } -static void -randfill(uchar *buf, int len) -{ - while(len-- > 0) - *buf++ = nrand(256); -} - /* * write a block in tls records */ @@ -1299,8 +1282,11 @@ if(tr->debug)pdump(BLEN(b), b->rp, "sent:"); if(sec != nil){ maclen = sec->maclen; pad = maclen + sec->block; - if(tr->version >= TLS11Version) - ivlen = sec->block; + ivlen = sec->recivlen; + if(tr->version >= TLS11Version){ + if(ivlen == 0) + ivlen = sec->block; + } } n = BLEN(bb); if(n > MaxRecLen){ @@ -1326,12 +1312,12 @@ if(tr->debug)pdump(BLEN(b), b->rp, "sent:"); put16(p+3, n); if(sec != nil){ - if(ivlen > 0) - randfill(p + RecHdrLen, ivlen); aadlen = (*tr->packAAD)(out->seq++, p, aad); if(sec->aead_enc != nil) - n = (*sec->aead_enc)(sec, aad, aadlen, p + RecHdrLen + ivlen, n) + ivlen; + n = (*sec->aead_enc)(sec, aad, aadlen, p + RecHdrLen, p + RecHdrLen + ivlen, n) + ivlen; else { + if(ivlen > 0) + prng(p + RecHdrLen, ivlen); packMac(sec, aad, aadlen, p + RecHdrLen + ivlen, n, p + RecHdrLen + ivlen + n); n = (*sec->enc)(sec, p + RecHdrLen, ivlen + n + maclen); } @@ -1420,7 +1406,6 @@ initmd5key(Hashalg *ha, int version, Secret *s, uchar *p) static void initclearmac(Hashalg *, int, Secret *s, uchar *) { - s->maclen = 0; s->mac = nomac; } @@ -1478,17 +1463,16 @@ struct Encalg static void initRC4key(Encalg *ea, Secret *s, uchar *p, uchar *) { - s->enckey = smalloc(sizeof(RC4state)); + s->enckey = secalloc(sizeof(RC4state)); s->enc = rc4enc; s->dec = rc4enc; - s->block = 0; setupRC4state(s->enckey, p, ea->keylen); } static void initDES3key(Encalg *, Secret *s, uchar *p, uchar *iv) { - s->enckey = smalloc(sizeof(DES3state)); + s->enckey = secalloc(sizeof(DES3state)); s->enc = des3enc; s->dec = des3dec; s->block = 8; @@ -1498,7 +1482,7 @@ initDES3key(Encalg *, Secret *s, uchar *p, uchar *iv) static void initAESkey(Encalg *ea, Secret *s, uchar *p, uchar *iv) { - s->enckey = smalloc(sizeof(AESstate)); + s->enckey = secalloc(sizeof(AESstate)); s->enc = aesenc; s->dec = aesdec; s->block = 16; @@ -1508,13 +1492,9 @@ initAESkey(Encalg *ea, Secret *s, uchar *p, uchar *iv) static void initccpolykey(Encalg *ea, Secret *s, uchar *p, uchar *iv) { - s->enckey = smalloc(sizeof(Chachastate)); - s->enc = noenc; - s->dec = noenc; - s->mac = nomac; + s->enckey = secalloc(sizeof(Chachastate)); s->aead_enc = ccpoly_aead_enc; s->aead_dec = ccpoly_aead_dec; - s->block = 0; s->maclen = Poly1305dlen; if(ea->ivlen == 0) { /* older draft version, iv is 64-bit sequence number */ @@ -1526,12 +1506,24 @@ initccpolykey(Encalg *ea, Secret *s, uchar *p, uchar *iv) } } +static void +initaesgcmkey(Encalg *ea, Secret *s, uchar *p, uchar *iv) +{ + s->enckey = secalloc(sizeof(AESGCMstate)); + s->aead_enc = aesgcm_aead_enc; + s->aead_dec = aesgcm_aead_dec; + s->maclen = 16; + s->recivlen = 8; + memmove(s->mackey, iv, ea->ivlen); + prng(s->mackey + ea->ivlen, s->recivlen); + setupAESGCMstate(s->enckey, p, ea->keylen, nil, 0); +} + static void initclearenc(Encalg *, Secret *s, uchar *, uchar *) { s->enc = noenc; s->dec = noenc; - s->block = 0; } static Encalg encrypttab[] = @@ -1543,6 +1535,8 @@ static Encalg encrypttab[] = { "aes_256_cbc", 256/8, 16, initAESkey }, { "ccpoly64_aead", 256/8, 0, initccpolykey }, { "ccpoly96_aead", 256/8, 96/8, initccpolykey }, + { "aes_128_gcm_aead", 128/8, 4, initaesgcmkey }, + { "aes_256_gcm_aead", 256/8, 4, initaesgcmkey }, { 0 } }; @@ -1671,32 +1665,34 @@ tlswrite(Chan *c, void *a, long n, vlong off) ea = parseencalg(cb->f[2]); p = cb->f[4]; - m = (strlen(p)*3)/2; - x = smalloc(m); - tos = nil; - toc = nil; + m = (strlen(p)*3)/2 + 1; + x = secalloc(m); + tos = secalloc(sizeof(Secret)); + toc = secalloc(sizeof(Secret)); if(waserror()){ + secfree(x); freeSec(tos); freeSec(toc); - free(x); nexterror(); } + m = dec64(x, m, p, strlen(p)); + memset(p, 0, strlen(p)); if(m < 2 * ha->maclen + 2 * ea->keylen + 2 * ea->ivlen) error("not enough secret data provided"); - tos = smalloc(sizeof(Secret)); - toc = smalloc(sizeof(Secret)); if(!ha->initkey || !ea->initkey) error("misimplemented secret algorithm"); + (*ha->initkey)(ha, tr->version, tos, &x[0]); (*ha->initkey)(ha, tr->version, toc, &x[ha->maclen]); (*ea->initkey)(ea, tos, &x[2 * ha->maclen], &x[2 * ha->maclen + 2 * ea->keylen]); (*ea->initkey)(ea, toc, &x[2 * ha->maclen + ea->keylen], &x[2 * ha->maclen + 2 * ea->keylen + ea->ivlen]); - if(!tos->mac || !tos->enc || !tos->dec - || !toc->mac || !toc->enc || !toc->dec) - error("missing algorithm implementations"); + if(!tos->aead_enc || !tos->aead_dec || !toc->aead_enc || !toc->aead_dec) + if(!tos->mac || !tos->enc || !tos->dec || !toc->mac || !toc->enc || !toc->dec) + error("missing algorithm implementations"); + if(strtol(cb->f[3], nil, 0) == 0){ tr->in.new = tos; tr->out.new = toc; @@ -1716,7 +1712,7 @@ tlswrite(Chan *c, void *a, long n, vlong off) tos->encalg = ea->name; tos->hashalg = ha->name; - free(x); + secfree(x); poperror(); }else if(strcmp(cb->f[0], "changecipher") == 0){ if(cb->nf != 1) @@ -1797,12 +1793,8 @@ tlsinit(void) struct Hashalg *h; int n; char *cp; - static int already; - if(!already){ - fmtinstall('H', encodefmt); - already = 1; - } + fmtinstall('H', encodefmt); tlsdevs = smalloc(sizeof(TlsRec*) * maxtlsdevs); trnames = smalloc((sizeof *trnames) * maxtlsdevs); @@ -1869,7 +1861,7 @@ buftochan(char *p) fd = strtoul(p, 0, 0); if(fd < 0) error(Ebadarg); - c = fdtochan(fd, -1, 0, 1); /* error check and inc ref */ + c = fdtochan(fd, ORDWR, 1, 1); /* error check and inc ref */ return c; } @@ -2045,10 +2037,10 @@ tlsstate(int s) static void freeSec(Secret *s) { - if(s != nil){ - free(s->enckey); - free(s); - } + if(s == nil) + return; + secfree(s->enckey); + secfree(s); } static int @@ -2152,19 +2144,23 @@ ccpoly_aead_setiv(Secret *sec, uchar seq[8]) iv[i+(ChachaIVlen-8)] ^= seq[i]; chacha_setiv(cs, iv); + + memset(iv, 0, sizeof(iv)); } static int -ccpoly_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *data, int len) +ccpoly_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len) { + USED(reciv); ccpoly_aead_setiv(sec, aad); ccpoly_encrypt(data, len, aad, aadlen, data+len, sec->enckey); return len + sec->maclen; } static int -ccpoly_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *data, int len) +ccpoly_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len) { + USED(reciv); len -= sec->maclen; if(len < 0) return -1; @@ -2174,6 +2170,39 @@ ccpoly_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *data, int len) return len; } +static int +aesgcm_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len) +{ + uchar iv[12]; + int i; + + memmove(iv, sec->mackey, 4+8); + for(i=0; i<8; i++) iv[4+i] ^= aad[i]; + memmove(reciv, iv+4, 8); + aesgcm_setiv(sec->enckey, iv, 12); + memset(iv, 0, sizeof(iv)); + aesgcm_encrypt(data, len, aad, aadlen, data+len, sec->enckey); + return len + sec->maclen; +} + +static int +aesgcm_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len) +{ + uchar iv[12]; + + len -= sec->maclen; + if(len < 0) + return -1; + memmove(iv, sec->mackey, 4); + memmove(iv+4, reciv, 8); + aesgcm_setiv(sec->enckey, iv, 12); + memset(iv, 0, sizeof(iv)); + if(aesgcm_decrypt(data, len, aad, aadlen, data+len, sec->enckey) != 0) + return -1; + return len; +} + + static DigestState* nomac(uchar *, ulong, uchar *, ulong, uchar *, DigestState *) { @@ -2295,12 +2324,6 @@ put16(uchar *p, int x) p[1] = x; } -static u32int -get32(uchar *p) -{ - return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]; -} - static int get16(uchar *p) {