ref: a8a35ee8f3dd514407206a3b09578bb66f06f097
parent: 1f4e0bdb4084f1e56282f2bf6c55170de12aec23
author: igor <igor@mux>
date: Thu Jan 25 05:41:10 EST 2024
Merge tlshand.c from front adding TLS renegotiation capability.
--- a/tlshand.c
+++ b/tlshand.c
@@ -68,6 +68,7 @@
uchar sec[MasterSecretSize]; // master secret
uchar srandom[RandomSize]; // server random
uchar crandom[RandomSize]; // client random
+ int reneg; // secure renegotiation flag
Namedcurve *nc; // selected curve for ECDHE
// diffie hellman state
@@ -253,6 +254,7 @@
TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C,
TLS_FALLBACK_SCSV = 0x5600,
+ TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF,
};
// compression methods
@@ -273,6 +275,7 @@
Extec = 0x000a,
Extecp = 0x000b,
Extsigalgs = 0x000d,
+ Extreneg = 0xff01,
};
static Algs cipherAlgs[] = {
@@ -429,7 +432,7 @@
tlsServer(int fd, TLSconn *conn)
{
char buf[8];
- char dname[64];
+ char dname[32];
uchar seed[2*RandomSize];
int n, data, ctl, hand;
TlsConnection *tls;
@@ -436,7 +439,7 @@
if(conn == nil)
return -1;
- ctl = open("#a/tls/clone", ORDWR|OCEXEC);
+ ctl = open("/net/tls/clone", ORDWR|OCEXEC);
if(ctl < 0)
return -1;
n = read(ctl, buf, sizeof(buf)-1);
@@ -445,8 +448,8 @@
return -1;
}
buf[n] = 0;
- snprint(conn->dir, sizeof(conn->dir), "#a/tls/%s", buf);
- snprint(dname, sizeof(dname), "#a/tls/%s/hand", buf);
+ snprint(conn->dir, sizeof(conn->dir), "/net/tls/%s", buf);
+ snprint(dname, sizeof(dname), "/net/tls/%s/hand", buf);
hand = open(dname, ORDWR|OCEXEC);
if(hand < 0){
close(ctl);
@@ -459,7 +462,7 @@
conn->pskID, conn->psk, conn->psklen,
conn->trace, conn->chain);
if(tls != nil){
- snprint(dname, sizeof(dname), "#a/tls/%s/data", buf);
+ snprint(dname, sizeof(dname), "/net/tls/%s/data", buf);
data = open(dname, ORDWR);
}
close(hand);
@@ -562,7 +565,7 @@
tlsClient(int fd, TLSconn *conn)
{
char buf[8];
- char dname[64];
+ char dname[32];
uchar seed[2*RandomSize];
int n, data, ctl, hand;
TlsConnection *tls;
@@ -570,7 +573,7 @@
if(conn == nil)
return -1;
- ctl = open("#a/tls/clone", ORDWR|OCEXEC);
+ ctl = open("/net/tls/clone", ORDWR|OCEXEC);
if(ctl < 0)
return -1;
n = read(ctl, buf, sizeof(buf)-1);
@@ -579,14 +582,14 @@
return -1;
}
buf[n] = 0;
- snprint(conn->dir, sizeof(conn->dir), "#a/tls/%s", buf);
- snprint(dname, sizeof(dname), "#a/tls/%s/hand", buf);
+ snprint(conn->dir, sizeof(conn->dir), "/net/tls/%s", buf);
+ snprint(dname, sizeof(dname), "/net/tls/%s/hand", buf);
hand = open(dname, ORDWR|OCEXEC);
if(hand < 0){
close(ctl);
return -1;
}
- snprint(dname, sizeof(dname), "#a/tls/%s/data", buf);
+ snprint(dname, sizeof(dname), "/net/tls/%s/data", buf);
data = open(dname, ORDWR);
if(data < 0){
close(hand);
@@ -686,6 +689,16 @@
break;
}
break;
+ case Extreneg:
+ if(n < 1 || *p != (n -= 1))
+ goto Short;
+ if(*p != 0){
+ tlsError(c, EHandshakeFailure, "invalid renegotiation extension");
+ return -1;
+ }
+ c->sec->reneg = 1;
+ p++;
+
}
}
@@ -695,6 +708,29 @@
return -1;
}
+static uchar*
+tlsServerExtensions(TlsConnection *c, int *plen)
+{
+ uchar *b, *p;
+ int m;
+
+ p = b = nil;
+
+ // RFC5746 - Renegotiation Indication
+ if(c->sec->reneg){
+ m = p - b;
+ b = erealloc(b, m + 2+2+1);
+ p = b + m;
+
+ put16(p, Extreneg), p += 2; /* Type: renegotiation_info */
+ put16(p, 1), p += 2; /* Length */
+ *p++ = 0; /* Renegotiated Connection Length */
+ }
+
+ *plen = p - b;
+ return b;
+}
+
static TlsConnection *
tlsServer2(int ctl, int hand,
uchar **cert, int certlen,
@@ -701,7 +737,8 @@
char *pskid, uchar *psk, int psklen,
int (*trace)(char*fmt, ...), PEMChain *chp)
{
- int cipher, compressor, numcerts, i;
+ int cipher, compressor, numcerts, i, extlen;
+ uchar *ext;
TlsConnection *c;
Msg m;
@@ -774,6 +811,8 @@
goto Err;
}
}
+ if(lookupid(m.u.clientHello.ciphers, TLS_EMPTY_RENEGOTIATION_INFO_SCSV) >= 0)
+ c->sec->reneg = 1;
cipher = okCipher(m.u.clientHello.ciphers, psklen > 0, c->sec->nc != nil);
if(cipher < 0 || !setAlgs(c, cipher)) {
tlsError(c, EHandshakeFailure, "no matching cipher suite");
@@ -794,6 +833,9 @@
m.u.serverHello.cipher = cipher;
m.u.serverHello.compressor = compressor;
m.u.serverHello.sid = makebytes(nil, 0);
+ ext = tlsServerExtensions(c, &extlen);
+ m.u.serverHello.extensions = makebytes(ext, extlen);
+ free(ext);
if(!msgSend(c, &m, AQueue))
goto Err;
@@ -2241,15 +2283,15 @@
unlock(&ciphLock);
return nciphers;
}
- j = open("#a/tls/encalgs", OREAD|OCEXEC);
+ j = open("/net/tls/encalgs", OREAD|OCEXEC);
if(j < 0){
- werrstr("can't open #a/tls/encalgs: %r");
+ werrstr("can't open /net/tls/encalgs: %r");
goto out;
}
n = read(j, s, MaxAlgF-1);
close(j);
if(n <= 0){
- werrstr("nothing in #a/tls/encalgs: %r");
+ werrstr("nothing in /net/tls/encalgs: %r");
goto out;
}
s[n] = 0;
@@ -2265,15 +2307,15 @@
cipherAlgs[i].ok = ok;
}
- j = open("#a/tls/hashalgs", OREAD|OCEXEC);
+ j = open("/net/tls/hashalgs", OREAD|OCEXEC);
if(j < 0){
- werrstr("can't open #a/tls/hashalgs: %r");
+ werrstr("can't open /net/tls/hashalgs: %r");
goto out;
}
n = read(j, s, MaxAlgF-1);
close(j);
if(n <= 0){
- werrstr("nothing in #a/tls/hashalgs: %r");
+ werrstr("nothing in /net/tls/hashalgs: %r");
goto out;
}
s[n] = 0;
@@ -2306,6 +2348,7 @@
for(i = 0; i < nelem(cipherAlgs); i++)
if(cipherAlgs[i].ok && isPSK(cipherAlgs[i].tlsid) == ispsk)
is->data[j++] = cipherAlgs[i].tlsid;
+ is->data[j++] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV;
is->len = j;
return is;
}