Plan 9 from Bell Labs’s /usr/web/sources/contrib/mospak/tls-1.2/tls-server-reneg-info.diff

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


--- sys/src/libsec/port/tlshand.c
+++ sys/src/libsec/port/tlshand.c
@@ -98,6 +98,7 @@ typedef struct TlsConnection{
 	 * detection on ServerHello (RFC 5246 Section 7.4.1.4). */
 	int	nClientOffered;
 	int	clientOffered[16];
+	int	extRenegInfoSeen;	/* client signaled RFC 5746 (ext or SCSV) */
 } TlsConnection;
 
 typedef struct Msg{
@@ -710,6 +711,14 @@ tlsServer2(int ctl, int hand, uchar *cert, int ncert, 
 		tlsError(c, EHandshakeFailure, "no matching compressor");
 		goto Err;
 	}
+	/*
+	 * RFC 5746 Section 3.4: TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the
+	 * cipher list is equivalent to an empty renegotiation_info
+	 * extension; either signal obliges the server to echo.
+	 */
+	for(i = 0; i < m.u.clientHello.ciphers->len; i++)
+		if(m.u.clientHello.ciphers->data[i] == TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
+			c->extRenegInfoSeen = 1;
 
 	/* Walk client's offered extensions through the parser table.
 	 * Unknown types are silently skipped per RFC 5246 Section 7.4.1.4. */
@@ -2757,6 +2766,41 @@ buildEcPointFormatsAck(TlsConnection *c, ExtCtx *ctx,
 	return 2;
 }
 
+/*
+ * RFC 5746 Section 3.6 server side: client may signal initial-handshake
+ * renegotiation_info via the empty extension (length 1, payload 0x00) or
+ * via TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the cipher list.  Either path
+ * obliges the server to echo an empty renegotiation_info in ServerHello.
+ * Plan 9 has no renegotiation primitive (devtls drops the handshake fd
+ * after `opened`); only initial-handshake echo matters.
+ */
+static int
+parseRenegInfoServer(TlsConnection *c, ExtCtx *ctx, uchar *in, int inlen)
+{
+	USED(ctx);
+	if(inlen != 1 || in[0] != 0)
+		return -1;
+	c->extRenegInfoSeen = 1;
+	return 0;
+}
+
+/*
+ * RFC 5746 Section 3.6: emit empty renegotiation_info ack iff client
+ * signaled (extension or SCSV); declined otherwise.  Payload is a single
+ * length-prefix byte (0x00) for an empty renegotiated_connection.
+ */
+static int
+buildRenegInfoServer(TlsConnection *c, ExtCtx *ctx, uchar *out, int outsize)
+{
+	USED(ctx);
+	if(!c->extRenegInfoSeen)
+		return -1;
+	if(outsize < 1)
+		return -1;
+	out[0] = 0;
+	return 1;
+}
+
 static ExtAlg clientHelloBuilders[] = {
 	{ ExtSni,		buildSni,		nil },
 	{ ExtSupportedGroups,	buildSupportedGroups,	nil },
@@ -2767,10 +2811,12 @@ static ExtAlg clientHelloParsers[] = {
 	{ ExtSni,		nil,			parseSniServer },
 	{ ExtEcPointFormats,	nil,			parseEcPointFormatsServer },
 	{ ExtSigalgs,		nil,			parseSigalgsServer },
+	{ ExtRenegotiationInfo,	nil,			parseRenegInfoServer },
 };
 static ExtAlg serverHelloBuilders[] = {
 	{ ExtSni,		buildSniAck,			nil },
 	{ ExtEcPointFormats,	buildEcPointFormatsAck,	nil },
+	{ ExtRenegotiationInfo,	buildRenegInfoServer,	nil },
 };
 /*
  * serverHelloParsers is empty in this baseline -- the client side has
@@ -2862,6 +2908,11 @@ clientHelloBuildExt(TlsConnection *c, ExtCtx *ctx, uch
 static int
 clientHelloBuildExt(TlsConnection *c, ExtCtx *ctx, uchar *out, int outsize)
 {
+	/* RFC 5746 Section 3.6: SCSV in the cipher list (makeciphers) is the
+	 * RFC-equivalent signal of an empty renegotiation_info; the server
+	 * MUST echo, so record the type up front to keep serverHelloParseExt's
+	 * unsupported_extension(110) check from firing on the echo. */
+	c->clientOffered[c->nClientOffered++] = ExtRenegotiationInfo;
 	return buildExtensionBlock(c, ctx, clientHelloBuilders,
 		nelem(clientHelloBuilders), out, outsize);
 }

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.