From: kemal Date: Sun, 17 Oct 2021 17:30:15 +0000 Subject: [PATCH] libsec: fix bugs in tls extension handling this patch fixes bugs in tls extension handling: 1. if conn->serverName is an empty string, tlsClientExtensions will generate a SNI with an empty hostname, which is forbidden according to RFC 6066: opaque HostName<1..2^16-1>; check if conn->serverName has at least one char. 2. checkClientExtensions fail with clients that doesn't have extensions, because it doesn't check if ext is nil. fix that up. 3. rewrite checkClientExtensions. some parts of the code does not check the length properly, and it could be simplified heavily. --- diff 72d08816abaa2935e8055d9cdfd73b59df5f9bd3 ae64fa53dc98de6c51c4b2631da1114082641196 --- a/sys/src/libsec/port/tlshand.c Sat Oct 16 18:07:39 2021 +++ b/sys/src/libsec/port/tlshand.c Sun Oct 17 20:30:15 2021 @@ -321,10 +321,6 @@ 0x0018, secp384r1, }; -static uchar pointformats[] = { - CompressionNull /* support of uncompressed point format is mandatory */ -}; - static struct { DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*); int len; @@ -496,9 +492,7 @@ p = b = nil; // RFC6066 - Server Name Identification - if(conn->serverName != nil){ - n = strlen(conn->serverName); - + if(conn->serverName != nil && (n = strlen(conn->serverName)) > 0){ m = p - b; b = erealloc(b, m + 2+2+2+1+2+n); p = b + m; @@ -514,11 +508,12 @@ // Elliptic Curves (also called Supported Groups) if(ProtocolVersion >= TLS10Version){ + n = nelem(namedcurves); + m = p - b; - b = erealloc(b, m + 2+2+2+nelem(namedcurves)*2 + 2+2+1+nelem(pointformats)); + b = erealloc(b, m + 2+2+2+n*2 + 2+2+1+n); p = b + m; - n = nelem(namedcurves); put16(p, Extec), p += 2; /* Type: elliptic_curves / supported_groups */ put16(p, (n+1)*2), p += 2; /* Length */ put16(p, n*2), p += 2; /* Elliptic Curves Length */ @@ -527,12 +522,10 @@ p += 2; } - n = nelem(pointformats); put16(p, Extecp), p += 2; /* Type: ec_point_formats */ - put16(p, n+1), p += 2; /* Length */ - *p++ = n; /* EC point formats Length */ - for(i=0; i < n; i++) /* EC point formats */ - *p++ = pointformats[i]; + put16(p, 2), p += 2; /* Length */ + *p++ = 1; /* EC Point Formats Length */ + *p++ = 0; /* Point Format: uncompressed */ } // signature algorithms @@ -651,37 +644,26 @@ uchar *p, *e; int i, j, n; - p = ext->data; - e = p+ext->len; - while(p < e){ - if(e-p < 2) + if(ext == nil) + return 0; + + for(p = ext->data, e = p+ext->len; p < e; p += n){ + if(e-p < 4) goto Short; - switch(get16(p)){ - case Extec: - p += 2; - n = get16(p); - if(e-p < n || n < 2) + p += 4; + if(e-p < (n = get16(p-2))) + goto Short; + switch(get16(p-4)){ + case Extec: + if(n < 4 || n % 2 || get16(p) != (n -= 2)) goto Short; p += 2; - n = get16(p); - p += 2; - if(e-p < n || n & 1 || n == 0) - goto Short; for(i = 0; i < nelem(namedcurves) && c->sec->nc == nil; i++) for(j = 0; j < n; j += 2) if(namedcurves[i].tlsid == get16(p+j)){ c->sec->nc = &namedcurves[i]; break; } - p += n; - break; - default: - p += 2; - n = get16(p); - p += 2; - if(e-p < n) - goto Short; - p += n; break; } } @@ -689,8 +671,8 @@ return 0; Short: tlsError(c, EDecodeError, "clienthello extensions has invalid length"); - return -1; -} + return -1; +} static TlsConnection * tlsServer2(int ctl, int hand, @@ -1587,7 +1569,7 @@ nn = get16(p); p += 2, n -= 2; - if((nn & 1) || n < nn || nn < 2) + if(nn % 2 || n < nn || nn < 2) goto Short; m->u.clientHello.ciphers = newints(nn >> 1); for(i = 0; i < nn; i += 2) @@ -1676,7 +1658,7 @@ goto Short; nn = get16(p); p += 2, n -= 2; - if(nn & 1) + if(nn % 2) goto Short; m->u.certificateRequest.sigalgs = newints(nn>>1); for(i = 0; i < nn; i += 2)