diff options
author | Martin Thomson <martin.thomson@gmail.com> | 2016-11-12 13:52:44 +0900 |
---|---|---|
committer | Martin Thomson <martin.thomson@gmail.com> | 2016-11-12 13:52:44 +0900 |
commit | b34e6eb163ad1893fc9f71b8a0d8c6e29bff855f (patch) | |
tree | ce409cce14a389c3a92936db86df22d8642ee012 /lib | |
parent | c8757ce8949d52487522924a76cd6c98872684e6 (diff) | |
download | nss-hg-b34e6eb163ad1893fc9f71b8a0d8c6e29bff855f.tar.gz |
Bug 1310610 - Exporters for TLS 1.3, r=ekr
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ssl/ssl.def | 6 | ||||
-rw-r--r-- | lib/ssl/ssl.h | 10 | ||||
-rw-r--r-- | lib/ssl/ssl3con.c | 4 | ||||
-rw-r--r-- | lib/ssl/sslimpl.h | 8 | ||||
-rw-r--r-- | lib/ssl/sslinfo.c | 59 | ||||
-rw-r--r-- | lib/ssl/tls13con.c | 15 | ||||
-rw-r--r-- | lib/ssl/tls13hkdf.c | 6 |
7 files changed, 102 insertions, 6 deletions
diff --git a/lib/ssl/ssl.def b/lib/ssl/ssl.def index 8c77e1033..5fb92cf0e 100644 --- a/lib/ssl/ssl.def +++ b/lib/ssl/ssl.def @@ -220,3 +220,9 @@ SSL_SignatureSchemePrefGet; ;+ local: ;+*; ;+}; +;+NSS_3.29 { # NSS 3.29 release +;+ global: +SSL_ExportEarlyKeyingMaterial; +;+ local: +;+*; +;+}; diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h index 49fff1a2c..b4af0e1f2 100644 --- a/lib/ssl/ssl.h +++ b/lib/ssl/ssl.h @@ -1216,6 +1216,16 @@ SSL_IMPORT SECStatus SSL_ExportKeyingMaterial(PRFileDesc *fd, unsigned char *out, unsigned int outLen); +/* Early exporters are used if 0-RTT is enabled. This is TLS 1.3 only. Note + * that in TLS 1.3, an empty context is equivalent to an absent context. */ +SSL_IMPORT SECStatus SSL_ExportEarlyKeyingMaterial(PRFileDesc *fd, + const char *label, + unsigned int labelLen, + const unsigned char *context, + unsigned int contextLen, + unsigned char *out, + unsigned int outLen); + /* ** Return a new reference to the certificate that was most recently sent ** to the peer on this SSL/TLS connection, or NULL if none has been sent. diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c index f0f4ba51e..8f99643b3 100644 --- a/lib/ssl/ssl3con.c +++ b/lib/ssl/ssl3con.c @@ -13229,6 +13229,10 @@ ssl3_DestroySSL3Info(sslSocket *ss) PK11_FreeSymKey(ss->ssl3.hs.clientTrafficSecret); if (ss->ssl3.hs.serverTrafficSecret) PK11_FreeSymKey(ss->ssl3.hs.serverTrafficSecret); + if (ss->ssl3.hs.earlyExporterSecret) + PK11_FreeSymKey(ss->ssl3.hs.earlyExporterSecret); + if (ss->ssl3.hs.exporterSecret) + PK11_FreeSymKey(ss->ssl3.hs.exporterSecret); ss->ssl3.hs.zeroRttState = ssl_0rtt_none; /* Destroy TLS 1.3 buffered early data. */ diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h index 8b7077c31..883b7d763 100644 --- a/lib/ssl/sslimpl.h +++ b/lib/ssl/sslimpl.h @@ -841,8 +841,8 @@ typedef struct SSL3HandshakeStateStr { * used for backoff (in ms) */ PRUint32 rtRetries; /* The retry counter */ SECItem srvVirtName; /* for server: name that was negotiated - * with a client. For client - is - * always set to NULL.*/ + * with a client. For client - is + * always set to NULL.*/ /* This group of values is used for TLS 1.3 and above */ PK11SymKey *currentSecret; /* The secret down the "left hand side" @@ -855,10 +855,12 @@ typedef struct SSL3HandshakeStateStr { PK11SymKey *serverHsTrafficSecret; /* traffic keys. */ PK11SymKey *clientTrafficSecret; /* The source keys for application */ PK11SymKey *serverTrafficSecret; /* traffic keys */ + PK11SymKey *earlyExporterSecret; /* for 0-RTT exporters */ + PK11SymKey *exporterSecret; /* for exporters */ /* The certificate request from the server. */ TLS13CertificateRequest *certificateRequest; PRCList cipherSpecs; /* The cipher specs in the sequence they - * will be applied. */ + * will be applied. */ ssl3CipherSpec *nullSpec; /* In case 0-RTT is rejected. */ sslZeroRttState zeroRttState; /* Are we doing a 0-RTT handshake? */ sslZeroRttIgnore zeroRttIgnore; /* Are we ignoring 0-RTT? */ diff --git a/lib/ssl/sslinfo.c b/lib/ssl/sslinfo.c index f3033d8e9..665109d65 100644 --- a/lib/ssl/sslinfo.c +++ b/lib/ssl/sslinfo.c @@ -1,9 +1,11 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ssl.h" #include "sslimpl.h" #include "sslproto.h" +#include "tls13hkdf.h" static const char * ssl_GetCompressionMethodName(SSLCompressionMethod compression) @@ -373,6 +375,24 @@ SSL_GetNegotiatedHostInfo(PRFileDesc *fd) return sniName; } +static SECStatus +tls13_Exporter(sslSocket *ss, PK11SymKey *secret, + const char *label, unsigned int labelLen, + const unsigned char *context, unsigned int contextLen, + unsigned char *out, unsigned int outLen) +{ + if (!secret) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + return tls13_HkdfExpandLabelRaw(secret, + tls13_GetHash(ss), + context, contextLen, + label, labelLen, + out, outLen); +} + SECStatus SSL_ExportKeyingMaterial(PRFileDesc *fd, const char *label, unsigned int labelLen, @@ -392,11 +412,19 @@ SSL_ExportKeyingMaterial(PRFileDesc *fd, return SECFailure; } - if (ss->version < SSL_LIBRARY_VERSION_3_1_TLS) { - PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION); + if (!label || !labelLen || !out || !outLen || + (hasContext && (!context || !contextLen))) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } + if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) { + return tls13_Exporter(ss, ss->ssl3.hs.exporterSecret, + label, labelLen, + context, hasContext ? contextLen : 0, + out, outLen); + } + /* construct PRF arguments */ valLen = SSL3_RANDOM_LENGTH * 2; if (hasContext) { @@ -436,3 +464,30 @@ SSL_ExportKeyingMaterial(PRFileDesc *fd, PORT_ZFree(val, valLen); return rv; } + +SECStatus +SSL_ExportEarlyKeyingMaterial(PRFileDesc *fd, + const char *label, unsigned int labelLen, + const unsigned char *context, + unsigned int contextLen, + unsigned char *out, unsigned int outLen) +{ + sslSocket *ss; + + ss = ssl_FindSocket(fd); + if (!ss) { + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_ExportEarlyKeyingMaterial", + SSL_GETPID(), fd)); + return SECFailure; + } + + if (!label || !labelLen || !out || !outLen || + (!context && contextLen)) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + return tls13_Exporter(ss, ss->ssl3.hs.earlyExporterSecret, + label, labelLen, context, contextLen, + out, outLen); +} diff --git a/lib/ssl/tls13con.c b/lib/ssl/tls13con.c index 3e5d8fda2..62e5d2afd 100644 --- a/lib/ssl/tls13con.c +++ b/lib/ssl/tls13con.c @@ -111,6 +111,7 @@ const char kHkdfLabelClient[] = "client"; const char kHkdfLabelServer[] = "server"; const char kHkdfLabelPskBinderKey[] = "resumption psk binder key"; const char kHkdfLabelEarlyTrafficSecret[] = "early traffic secret"; +const char kHkdfLabelEarlyExporterSecret[] = "early exporter master secret"; const char kHkdfLabelHandshakeTrafficSecret[] = "handshake traffic secret"; const char kHkdfLabelApplicationTrafficSecret[] = "application traffic secret"; const char kHkdfLabelFinishedSecret[] = "finished"; @@ -754,6 +755,13 @@ tls13_ComputeEarlySecrets(sslSocket *ss) if (rv != SECSuccess) { return SECFailure; } + + rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret, + NULL, kHkdfLabelEarlyExporterSecret, + &hashes, &ss->ssl3.hs.earlyExporterSecret); + if (rv != SECSuccess) { + return SECFailure; + } } else { PORT_Assert(!ss->ssl3.hs.resumptionMasterSecret); } @@ -844,6 +852,13 @@ tls13_ComputeApplicationSecrets(sslSocket *ss) return SECFailure; } + rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret, + NULL, kHkdfLabelExporterMasterSecret, + NULL, &ss->ssl3.hs.exporterSecret); + if (rv != SECSuccess) { + return SECFailure; + } + return SECSuccess; } diff --git a/lib/ssl/tls13hkdf.c b/lib/ssl/tls13hkdf.c index 97c98a43e..7e69bb882 100644 --- a/lib/ssl/tls13hkdf.c +++ b/lib/ssl/tls13hkdf.c @@ -141,7 +141,11 @@ tls13_HkdfExpandLabel(PK11SymKey *prk, SSLHashType baseHash, const unsigned int kLabelPrefixLen = strlen(kLabelPrefix); if (handshakeHash) { - PORT_Assert(handshakeHashLen == kTlsHkdfInfo[baseHash].hashSize); + if (handshakeHashLen > 255) { + PORT_Assert(0); + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } } else { PORT_Assert(!handshakeHashLen); } |