/*
- * 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"
#include <libsec.h>
typedef struct OneWay OneWay;
-typedef struct Secret Secret;
+typedef struct Secret Secret;
typedef struct TlsRec TlsRec;
typedef struct TlsErrs TlsErrs;
enum {
Statlen= 1024, /* max. length of status or stats message */
/* buffer limits */
- MaxRecLen = 1<<14, /* max payload length of a record layer message */
+ MaxRecLen = 1<<14, /* max payload length of a record layer message */
MaxCipherRecLen = MaxRecLen + 2048,
- RecHdrLen = 5,
- MaxMacLen = SHA1dlen,
+ RecHdrLen = 5,
+ MaxMacLen = SHA2_256dlen,
/* protocol versions we can accept */
- TLSVersion = 0x0301,
- SSL3Version = 0x0300,
- ProtocolVersion = 0x0301, /* maximum version we speak */
+ SSL3Version = 0x0300,
+ TLS10Version = 0x0301,
+ TLS11Version = 0x0302,
+ TLS12Version = 0x0303,
MinProtoVersion = 0x0300, /* limits on version we accept */
MaxProtoVersion = 0x03ff,
EInternalError = 80,
EUserCanceled = 90,
ENoRenegotiation = 100,
+ EUnrecognizedName = 112,
EMAX = 256
};
{
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*);
+ 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];
+ uchar mackey[MaxMacLen];
};
struct OneWay
{
QLock io; /* locks io access */
QLock seclock; /* locks secret paramaters */
- ulong seq;
+ u64int seq;
Secret *sec; /* cipher in use */
Secret *new; /* cipher waiting for enable */
};
int state;
int debug;
- /* record layer mac functions for different protocol versions */
- void (*packMac)(Secret*, uchar*, uchar*, uchar*, uchar*, int, uchar*);
+ /*
+ * function to genrate authenticated data blob for different
+ * protocol versions
+ */
+ int (*packAAD)(u64int, uchar*, uchar*);
/* input side -- protected by in.io */
OneWay in;
static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
static DigestState*nomac(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
-static void sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac);
-static void tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac);
-static void put64(uchar *p, vlong x);
+static int sslPackAAD(u64int, uchar*, uchar*);
+static int tlsPackAAD(u64int, uchar*, uchar*);
+static void packMac(Secret*, uchar*, int, uchar*, int, uchar*);
+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);
static int rc4enc(Secret *sec, uchar *buf, int n);
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 *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);
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);
c->mode = openmode(omode);
c->flag |= COPEN;
c->offset = 0;
- c->iounit = qiomaxatomic;
+ c->iounit = MaxRecLen;
return c;
}
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);
{
OneWay *volatile in;
Block *volatile b;
- uchar *p, seq[8], header[RecHdrLen], hmac[MD5dlen];
+ uchar *p, aad[8+RecHdrLen], header[RecHdrLen], hmac[MaxMacLen];
int volatile nconsumed;
- int len, type, ver, unpad_len;
+ int len, type, ver, unpad_len, aadlen, ivlen;
+ Secret *sec;
nconsumed = 0;
if(waserror()){
}
qlock(&in->seclock);
p = b->rp;
- if(in->sec != nil) {
+ sec = in->sec;
+ if(sec != nil) {
/* to avoid Canvel-Hiltgen-Vaudenay-Vuagnoux attack, all errors here
should look alike, including timing of the response. */
- unpad_len = (*in->sec->dec)(in->sec, p, len);
- if(unpad_len >= in->sec->maclen)
- len = unpad_len - in->sec->maclen;
+ if(sec->aead_dec != nil)
+ unpad_len = len;
+ else {
+ unpad_len = (*sec->dec)(sec, p, len);
if(tr->debug) pprint("decrypted %d\n", unpad_len);
if(tr->debug) pdump(unpad_len, p, "decrypted:");
+ }
+
+ ivlen = sec->recivlen;
+ if(tr->version >= TLS11Version){
+ 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;
/* update length */
put16(header+3, len);
- put64(seq, in->seq);
- in->seq++;
- (*tr->packMac)(in->sec, in->sec->mackey, seq, header, p, len, hmac);
- if(unpad_len < in->sec->maclen)
- rcvError(tr, EBadRecordMac, "short record mac");
- if(memcmp(hmac, p+len, in->sec->maclen) != 0)
- rcvError(tr, EBadRecordMac, "record mac mismatch");
- b->wp = b->rp + len;
+ aadlen = (*tr->packAAD)(in->seq++, header, aad);
+ if(sec->aead_dec != nil) {
+ len = (*sec->aead_dec)(sec, aad, aadlen, p - ivlen, p, unpad_len);
+ if(len < 0)
+ rcvError(tr, EBadRecordMac, "record mac mismatch");
+ } else {
+ packMac(sec, aad, aadlen, p, len, hmac);
+ if(unpad_len < sec->maclen)
+ rcvError(tr, EBadRecordMac, "short record mac");
+ if(tsmemcmp(hmac, p + len, sec->maclen) != 0)
+ rcvError(tr, EBadRecordMac, "record mac mismatch");
+ }
+ b->rp = p;
+ b->wp = p+len;
}
qunlock(&in->seclock);
poperror();
rcvError(tr, EIllegalParameter, "invalid alert fatal code");
/*
- * propate non-fatal alerts to handshaker
+ * propagate non-fatal alerts to handshaker
*/
- if(p[1] == ECloseNotify) {
+ switch(p[1]){
+ case ECloseNotify:
tlsclosed(tr, SRClose);
if(tr->opened)
error("tls hungup");
error("close notify");
- }
- if(p[1] == ENoRenegotiation)
+ break;
+ case ENoRenegotiation:
alertHand(tr, "no renegotiation");
- else if(p[1] == EUserCanceled)
+ break;
+ case EUserCanceled:
alertHand(tr, "handshake canceled by user");
- else
+ break;
+ case EUnrecognizedName:
+ /* happens in response to SNI, can be ignored. */
+ break;
+ default:
rcvError(tr, EIllegalParameter, "invalid alert code");
+ }
break;
case RHandshake:
/*
/* return at most what was asked for */
b = qgrab(&tr->processed, n);
-if(tr->debug) pprint("consumed processed %ld\n", BLEN(b));
+if(tr->debug) pprint("consumed processed %zd\n", BLEN(b));
if(tr->debug) pdump(BLEN(b), b->rp, "consumed:");
qunlock(&tr->in.io);
poperror();
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);
{
Block *volatile bb;
Block *nb;
- uchar *p, seq[8];
+ uchar *p, aad[8+RecHdrLen];
OneWay *volatile out;
- int n, maclen, pad, ok;
+ int n, ivlen, maclen, aadlen, pad, ok;
+ Secret *sec;
out = &tr->out;
bb = b;
nexterror();
}
qlock(&out->io);
-if(tr->debug)pprint("send %ld\n", BLEN(b));
+if(tr->debug)pprint("send %zd\n", BLEN(b));
if(tr->debug)pdump(BLEN(b), b->rp, "sent:");
qlock(&out->seclock);
maclen = 0;
pad = 0;
- if(out->sec != nil){
- maclen = out->sec->maclen;
- pad = maclen + out->sec->block;
+ ivlen = 0;
+ sec = out->sec;
+ if(sec != nil){
+ maclen = sec->maclen;
+ pad = maclen + sec->block;
+ ivlen = sec->recivlen;
+ if(tr->version >= TLS11Version){
+ if(ivlen == 0)
+ ivlen = sec->block;
+ }
}
n = BLEN(bb);
if(n > MaxRecLen){
n = MaxRecLen;
- nb = allocb(n + pad + RecHdrLen);
- memmove(nb->wp + RecHdrLen, bb->rp, n);
+ nb = allocb(RecHdrLen + ivlen + n + pad);
+ memmove(nb->wp + RecHdrLen + ivlen, bb->rp, n);
bb->rp += n;
}else{
/*
* carefully reuse bb so it will get freed if we're out of memory
*/
- bb = padblock(bb, RecHdrLen);
+ bb = padblock(bb, RecHdrLen + ivlen);
if(pad)
nb = padblock(bb, -pad);
else
put16(p+1, tr->version);
put16(p+3, n);
- if(out->sec != nil){
- put64(seq, out->seq);
- out->seq++;
- (*tr->packMac)(out->sec, out->sec->mackey, seq, p, p + RecHdrLen, n, p + RecHdrLen + n);
- n += maclen;
-
- /* encrypt */
- n = (*out->sec->enc)(out->sec, p + RecHdrLen, n);
+ if(sec != nil){
+ aadlen = (*tr->packAAD)(out->seq++, p, aad);
+ if(sec->aead_enc != nil)
+ 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);
+ }
nb->wp = p + RecHdrLen + n;
/* update length */
tr = tlsdevs[CONV(c->qid)];
if(tr == nil)
- panic("tlsbread");
+ panic("tlsbwrite");
ty = TYPE(c->qid);
switch(ty) {
static void
initclearmac(Hashalg *, int, Secret *s, uchar *)
{
- s->maclen = 0;
s->mac = nomac;
}
memmove(s->mackey, p, ha->maclen);
}
+static void
+initsha2_256key(Hashalg *ha, int version, Secret *s, uchar *p)
+{
+ if(version == SSL3Version)
+ error("sha256 cannot be used with SSL");
+ s->maclen = ha->maclen;
+ s->mac = hmac_sha2_256;
+ memmove(s->mackey, p, ha->maclen);
+}
+
static Hashalg hashtab[] =
{
- { "clear", 0, initclearmac, },
- { "md5", MD5dlen, initmd5key, },
- { "sha1", SHA1dlen, initsha1key, },
+ { "clear", 0, initclearmac, },
+ { "md5", MD5dlen, initmd5key, },
+ { "sha1", SHA1dlen, initsha1key, },
+ { "sha256", SHA2_256dlen, initsha2_256key, },
{ 0 }
};
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;
setupDES3state(s->enckey, (uchar(*)[8])p, iv);
}
+static void
+initAESkey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
+{
+ s->enckey = secalloc(sizeof(AESstate));
+ s->enc = aesenc;
+ s->dec = aesdec;
+ s->block = 16;
+ setupAESstate(s->enckey, p, ea->keylen, iv);
+}
+
+static void
+initccpolykey(Encalg *ea, Secret *s, uchar *p, uchar *iv)
+{
+ s->enckey = secalloc(sizeof(Chachastate));
+ s->aead_enc = ccpoly_aead_enc;
+ s->aead_dec = ccpoly_aead_dec;
+ s->maclen = Poly1305dlen;
+ if(ea->ivlen == 0) {
+ /* older draft version, iv is 64-bit sequence number */
+ setupChachastate(s->enckey, p, ea->keylen, nil, 64/8, 20);
+ } else {
+ /* IETF standard, 96-bit iv xored with sequence number */
+ memmove(s->mackey, iv, ea->ivlen);
+ setupChachastate(s->enckey, p, ea->keylen, iv, ea->ivlen, 20);
+ }
+}
+
+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[] =
{ "clear", 0, 0, initclearenc },
{ "rc4_128", 128/8, 0, initRC4key },
{ "3des_ede_cbc", 3 * 8, 8, initDES3key },
+ { "aes_128_cbc", 128/8, 16, initAESkey },
+ { "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 }
};
e = p + n;
do{
m = e - p;
- if(m > MaxRecLen)
- m = MaxRecLen;
+ if(m > c->iounit)
+ m = c->iounit;
b = allocb(m);
if(waserror()){
if(tr->verset)
error("version already set");
m = strtol(cb->f[1], nil, 0);
+ if(m < MinProtoVersion || m > MaxProtoVersion)
+ error("unsupported version");
if(m == SSL3Version)
- tr->packMac = sslPackMac;
- else if(m == TLSVersion)
- tr->packMac = tlsPackMac;
+ tr->packAAD = sslPackAAD;
else
- error("unsupported version");
+ tr->packAAD = tlsPackAAD;
tr->verset = 1;
tr->version = m;
}else if(strcmp(cb->f[0], "secret") == 0){
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;
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;
}
{
int s;
-if(tr->debug)pprint("tleError %s\n", msg);
+if(tr->debug)pprint("tlsError %s\n", msg);
lock(&tr->statelk);
s = tr->state;
tr->state = SError;
static void
freeSec(Secret *s)
{
- if(s != nil){
- free(s->enckey);
- free(s);
- }
+ if(s == nil)
+ return;
+ secfree(s->enckey);
+ secfree(s);
}
static int
des3CBCdecrypt(buf, n, sec->enckey);
return (*sec->unpad)(buf, n, 8);
}
+
+static int
+aesenc(Secret *sec, uchar *buf, int n)
+{
+ n = blockpad(buf, n, 16);
+ aesCBCencrypt(buf, n, sec->enckey);
+ return n;
+}
+
+static int
+aesdec(Secret *sec, uchar *buf, int n)
+{
+ aesCBCdecrypt(buf, n, sec->enckey);
+ return (*sec->unpad)(buf, n, 16);
+}
+
+static void
+ccpoly_aead_setiv(Secret *sec, uchar seq[8])
+{
+ uchar iv[ChachaIVlen];
+ Chachastate *cs;
+ int i;
+
+ cs = (Chachastate*)sec->enckey;
+ if(cs->ivwords == 2){
+ chacha_setiv(cs, seq);
+ return;
+ }
+
+ memmove(iv, sec->mackey, ChachaIVlen);
+ for(i=0; i<8; i++)
+ 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 *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 *reciv, uchar *data, int len)
+{
+ USED(reciv);
+ len -= sec->maclen;
+ if(len < 0)
+ return -1;
+ ccpoly_aead_setiv(sec, aad);
+ if(ccpoly_decrypt(data, len, aad, aadlen, data+len, sec->enckey) != 0)
+ return -1;
+ 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 *)
{
return sslmac_x(p, len, key, klen, digest, s, md5, MD5dlen, 48);
}
-static void
-sslPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac)
+static int
+sslPackAAD(u64int seq, uchar *hdr, uchar *aad)
{
- DigestState *s;
- uchar buf[11];
-
- memmove(buf, seq, 8);
- buf[8] = header[0];
- buf[9] = header[3];
- buf[10] = header[4];
+ put64(aad, seq);
+ aad[8] = hdr[0];
+ aad[9] = hdr[3];
+ aad[10] = hdr[4];
+ return 11;
+}
- s = (*sec->mac)(buf, 11, mackey, sec->maclen, 0, 0);
- (*sec->mac)(body, len, mackey, sec->maclen, mac, s);
+static int
+tlsPackAAD(u64int seq, uchar *hdr, uchar *aad)
+{
+ put64(aad, seq);
+ aad[8] = hdr[0];
+ aad[9] = hdr[1];
+ aad[10] = hdr[2];
+ aad[11] = hdr[3];
+ aad[12] = hdr[4];
+ return 13;
}
static void
-tlsPackMac(Secret *sec, uchar *mackey, uchar *seq, uchar *header, uchar *body, int len, uchar *mac)
+packMac(Secret *sec, uchar *aad, int aadlen, uchar *body, int bodylen, uchar *mac)
{
DigestState *s;
- uchar buf[13];
-
- memmove(buf, seq, 8);
- memmove(&buf[8], header, 5);
- s = (*sec->mac)(buf, 13, mackey, sec->maclen, 0, 0);
- (*sec->mac)(body, len, mackey, sec->maclen, mac, s);
+ s = (*sec->mac)(aad, aadlen, sec->mackey, sec->maclen, nil, nil);
+ (*sec->mac)(body, bodylen, sec->mackey, sec->maclen, mac, s);
}
static void
}
static void
-put64(uchar *p, vlong x)
+put64(uchar *p, u64int x)
{
- put32(p, (u32int)(x >> 32));
- put32(p+4, (u32int)x);
+ put32(p, x >> 32);
+ put32(p+4, x);
}
static void
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)
{