/*
- * 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"
{
char *encalg; /* name of encryption alg */
char *hashalg; /* name of hash alg */
- 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*, 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 block; /* encryption block len, 0 if none */
- int maclen;
- int recivlen;
+ int maclen; /* # bytes of record mac / authentication tag */
+ int recivlen; /* # bytes of record iv for AEAD ciphers */
void *enckey;
uchar mackey[MaxMacLen];
};
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);
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) {
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);
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);
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);
return n;
}
-static void
-randfill(uchar *buf, int len)
-{
- while(len-- > 0)
- *buf++ = nrand(256);
-}
-
/*
* write a block in tls records
*/
n = (*sec->aead_enc)(sec, aad, aadlen, p + RecHdrLen, p + RecHdrLen + ivlen, n) + ivlen;
else {
if(ivlen > 0)
- randfill(p + RecHdrLen, ivlen);
+ 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);
}
static void
initclearmac(Hashalg *, int, Secret *s, uchar *)
{
- s->maclen = 0;
s->mac = nomac;
}
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;
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;
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 */
static void
initaesgcmkey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
{
- s->enckey = smalloc(sizeof(AESGCMstate));
- s->enc = noenc;
- s->dec = noenc;
- s->mac = nomac;
+ s->enckey = secalloc(sizeof(AESGCMstate));
s->aead_enc = aesgcm_aead_enc;
s->aead_dec = aesgcm_aead_dec;
- s->block = 0;
s->maclen = 16;
s->recivlen = 8;
memmove(s->mackey, iv, ea->ivlen);
- randfill(s->mackey + ea->ivlen, s->recivlen);
+ prng(s->mackey + ea->ivlen, s->recivlen);
setupAESGCMstate(s->enckey, p, ea->keylen, nil, 0);
}
{
s->enc = noenc;
s->dec = noenc;
- s->block = 0;
}
static Encalg encrypttab[] =
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;
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)
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);
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;
}
static void
freeSec(Secret *s)
{
- if(s != nil){
- free(s->enckey);
- free(s);
- }
+ if(s == nil)
+ return;
+ secfree(s->enckey);
+ secfree(s);
}
static int
iv[i+(ChachaIVlen-8)] ^= seq[i];
chacha_setiv(cs, iv);
+
+ memset(iv, 0, sizeof(iv));
}
static int
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;
}
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;
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)
{