Skip to content

Commit

Permalink
Bug 1386096 - Semi-stateless HelloRetryRequest, r=mt
Browse files Browse the repository at this point in the history
--HG--
branch : NSS_TLS13_DRAFT19_BRANCH
  • Loading branch information
ekr committed Aug 1, 2017
1 parent 3847b26 commit da7b6f8
Show file tree
Hide file tree
Showing 17 changed files with 531 additions and 77 deletions.
1 change: 1 addition & 0 deletions gtests/ssl_gtest/ssl_custext_unittest.cc
Expand Up @@ -119,6 +119,7 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionAllNoopServer) {
TEST_F(TlsConnectStreamTls13, CustomExtensionEmptyWriterClient) {
EnsureTlsSetup();
InstallManyWriters(client_, EmptyExtensionWriter);
InstallManyWriters(server_, EmptyExtensionWriter);
Connect();
}

Expand Down
1 change: 1 addition & 0 deletions lib/ssl/manifest.mn
Expand Up @@ -49,6 +49,7 @@ CSRCS = \
ssl3ecc.c \
tls13con.c \
tls13exthandle.c \
tls13hashstate.c \
tls13hkdf.c \
tls13replay.c \
sslcert.c \
Expand Down
13 changes: 13 additions & 0 deletions lib/ssl/selfencrypt.c
Expand Up @@ -269,6 +269,19 @@ ssl_SelfEncryptUnprotectInt(
}
#endif

/* Predict the size of the encrypted data, including padding */
SECStatus
ssl_SelfEncryptGetProtectedSize(unsigned int inLen, unsigned int *outLen)
{
*outLen = SELF_ENCRYPT_KEY_NAME_LEN +
AES_BLOCK_SIZE +
2 +
((inLen / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE + /* Padded */
SHA256_LENGTH;

return SECSuccess;
}

SECStatus
ssl_SelfEncryptProtect(
sslSocket *ss, const PRUint8 *in, unsigned int inLen,
Expand Down
4 changes: 4 additions & 0 deletions lib/ssl/selfencrypt.h
Expand Up @@ -11,6 +11,10 @@

#include "secmodt.h"

typedef struct sslSocketStr sslSocket;

SECStatus ssl_SelfEncryptGetProtectedSize(unsigned int inLen,
unsigned int *outLen);
SECStatus ssl_SelfEncryptProtect(
sslSocket *ss, const PRUint8 *in, unsigned int inLen,
PRUint8 *out, unsigned int *outLen, unsigned int maxOutLen);
Expand Down
1 change: 1 addition & 0 deletions lib/ssl/ssl.gyp
Expand Up @@ -42,6 +42,7 @@
'sslver.c',
'tls13con.c',
'tls13exthandle.c',
'tls13hashstate.c',
'tls13hkdf.c',
'tls13replay.c',
],
Expand Down
62 changes: 47 additions & 15 deletions lib/ssl/ssl3con.c
Expand Up @@ -52,7 +52,9 @@ static SECStatus ssl3_SendServerKeyExchange(sslSocket *ss);
static SECStatus ssl3_HandleClientHelloPart2(sslSocket *ss,
SECItem *suites,
SECItem *comps,
sslSessionID *sid);
sslSessionID *sid,
const PRUint8 *msg,
unsigned int len);
static SECStatus ssl3_HandleServerHelloPart2(sslSocket *ss,
const SECItem *sidBytes,
int *retErrCode);
Expand Down Expand Up @@ -355,8 +357,7 @@ static const ssl3CipherSuiteDef cipher_suite_defs[] =
{TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
cipher_3des, mac_sha, kea_dhe_rsa, ssl_hash_none},


/* New TLS cipher suites */
/* New TLS cipher suites */
{TLS_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_rsa, ssl_hash_none},
{TLS_RSA_WITH_AES_128_CBC_SHA256, cipher_aes_128, hmac_sha256, kea_rsa, ssl_hash_sha256},
{TLS_DHE_DSS_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dhe_dss, ssl_hash_none},
Expand Down Expand Up @@ -4004,11 +4005,11 @@ ssl3_InitHandshakeHashes(sslSocket *ss)
return SECFailure;
}
ss->ssl3.hs.hashType = handshake_hash_single;

if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
return SECFailure;
}

} else {
/* Both ss->ssl3.hs.md5 and ss->ssl3.hs.sha should be NULL or
* created successfully. */
Expand Down Expand Up @@ -4931,6 +4932,7 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
unsigned numCompressionMethods;
PRUint16 version;
PRInt32 flags;
unsigned int cookieLen = ss->ssl3.hs.cookie.len;

SSL_TRC(3, ("%d: SSL3[%d]: send %s ClientHello handshake", SSL_GETPID(),
ss->fd, ssl_ClientHelloTypeName(type)));
Expand All @@ -4949,6 +4951,9 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
* to maintain the handshake hashes. */
if (ss->ssl3.hs.helloRetry) {
PORT_Assert(type == client_hello_retry);
/* This cookieLen applies to the cookie that appears in the DTLS
ClientHello, which isn't used in DTLS 1.3. */
cookieLen = 0;
} else {
ssl3_InitState(ss);
ssl3_RestartHandshakeHashes(ss);
Expand Down Expand Up @@ -5208,7 +5213,7 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
2 + num_suites * sizeof(ssl3CipherSuite) +
1 + numCompressionMethods;
if (IS_DTLS(ss)) {
length += 1 + ss->ssl3.hs.cookie.len;
length += 1 + cookieLen;
}

if (extensionBuf.len) {
Expand Down Expand Up @@ -5266,7 +5271,7 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)

if (IS_DTLS(ss)) {
rv = ssl3_AppendHandshakeVariable(
ss, ss->ssl3.hs.cookie.data, ss->ssl3.hs.cookie.len, 1);
ss, ss->ssl3.hs.cookie.data, cookieLen, 1);
if (rv != SECSuccess) {
goto loser; /* err set by ssl3_AppendHandshake* */
}
Expand Down Expand Up @@ -8234,6 +8239,8 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length)
SECItem suites = { siBuffer, NULL, 0 };
SECItem comps = { siBuffer, NULL, 0 };
PRBool isTLS13;
const PRUint8 *savedMsg = b;
const PRUint32 savedLen = length;

SSL_TRC(3, ("%d: SSL3[%d]: handle client_hello handshake",
SSL_GETPID(), ss->fd));
Expand Down Expand Up @@ -8265,6 +8272,9 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length)
}
}

/* We should always be in a fresh state. */
SSL_ASSERT_HASHES_EMPTY(ss);

/* Get peer name of client */
rv = ssl_GetPeerInfo(ss);
if (rv != SECSuccess) {
Expand Down Expand Up @@ -8312,6 +8322,9 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length)
if (rv != SECSuccess) {
goto loser; /* malformed */
}
if (cookieBytes.len != 0) {
goto loser; /* We never send cookies in DTLS 1.2. */
}
}

/* Grab the list of cipher suites. */
Expand Down Expand Up @@ -8579,9 +8592,10 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length)
#endif

if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
rv = tls13_HandleClientHelloPart2(ss, &suites, sid);
rv = tls13_HandleClientHelloPart2(ss, &suites, sid, savedMsg, savedLen);
} else {
rv = ssl3_HandleClientHelloPart2(ss, &suites, &comps, sid);
rv = ssl3_HandleClientHelloPart2(ss, &suites, &comps, sid,
savedMsg, savedLen);
}
if (rv != SECSuccess) {
errCode = PORT_GetError();
Expand All @@ -8601,7 +8615,9 @@ static SECStatus
ssl3_HandleClientHelloPart2(sslSocket *ss,
SECItem *suites,
SECItem *comps,
sslSessionID *sid)
sslSessionID *sid,
const PRUint8 *msg,
unsigned int len)
{
PRBool haveSpecWriteLock = PR_FALSE;
PRBool haveXmitBufLock = PR_FALSE;
Expand All @@ -8611,6 +8627,13 @@ ssl3_HandleClientHelloPart2(sslSocket *ss,
unsigned int i;
int j;

rv = ssl_HashHandshakeMessage(ss, ssl_hs_client_hello, msg, len);
if (rv != SECSuccess) {
errCode = SEC_ERROR_LIBRARY_FAILURE;
desc = internal_error;
goto alert_loser;
}

/* If we already have a session for this client, be sure to pick the
** same cipher suite and compression method we picked before.
** This is not a loop, despite appearances.
Expand Down Expand Up @@ -11571,8 +11594,9 @@ ssl3_FinishHandshake(sslSocket *ss)
}

SECStatus
ssl_HashHandshakeMessage(sslSocket *ss, SSLHandshakeType type,
const PRUint8 *b, PRUint32 length)
ssl_HashHandshakeMessageInt(sslSocket *ss, SSLHandshakeType type,
PRUint32 dtlsSeq,
const PRUint8 *b, PRUint32 length)
{
PRUint8 hdr[4];
PRUint8 dtlsData[8];
Expand All @@ -11590,8 +11614,8 @@ ssl_HashHandshakeMessage(sslSocket *ss, SSLHandshakeType type,
/* Extra data to simulate a complete DTLS handshake fragment */
if (IS_DTLS(ss)) {
/* Sequence number */
dtlsData[0] = MSB(ss->ssl3.hs.recvMessageSeq);
dtlsData[1] = LSB(ss->ssl3.hs.recvMessageSeq);
dtlsData[0] = MSB(dtlsSeq);
dtlsData[1] = LSB(dtlsSeq);

/* Fragment offset */
dtlsData[2] = 0;
Expand All @@ -11617,6 +11641,14 @@ ssl_HashHandshakeMessage(sslSocket *ss, SSLHandshakeType type,
return SECSuccess;
}

SECStatus
ssl_HashHandshakeMessage(sslSocket *ss, SSLHandshakeType type,
const PRUint8 *b, PRUint32 length)
{
return ssl_HashHandshakeMessageInt(ss, type, ss->ssl3.hs.recvMessageSeq,
b, length);
}

/* Called from ssl3_HandleHandshake() when it has gathered a complete ssl3
* handshake message.
* Caller must hold Handshake and RecvBuf locks.
Expand Down Expand Up @@ -11646,11 +11678,11 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length,
* in the handshake hashes */
break;

/* Defer hashing of these messages until the message handlers. */
case ssl_hs_client_hello:
case ssl_hs_hello_retry_request:
case ssl_hs_certificate_verify:
case ssl_hs_finished:
/* Defer hashing of these messages until the message handlers
* we need to finalize the hashes there. */
break;

default:
Expand Down
13 changes: 13 additions & 0 deletions lib/ssl/ssl3ext.c
Expand Up @@ -14,6 +14,7 @@
#include "sslimpl.h"
#include "sslproto.h"
#include "ssl3exthandle.h"
#include "tls13err.h"
#include "tls13exthandle.h"

/* Callback function that handles a received extension. */
Expand Down Expand Up @@ -49,6 +50,7 @@ static const ssl3ExtensionHandler clientHelloHandlers[] = {
{ ssl_tls13_pre_shared_key_xtn, &tls13_ServerHandlePreSharedKeyXtn },
{ ssl_tls13_early_data_xtn, &tls13_ServerHandleEarlyDataXtn },
{ ssl_tls13_psk_key_exchange_modes_xtn, &tls13_ServerHandlePskModesXtn },
{ ssl_tls13_cookie_xtn, &tls13_ServerHandleCookieXtn },
{ 0, NULL }
};

Expand Down Expand Up @@ -151,6 +153,12 @@ static const sslExtensionBuilder tls13_cert_req_senders[] = {
{ 0, NULL }
};

static const sslExtensionBuilder tls13_hrr_senders[] = {
{ ssl_tls13_key_share_xtn, &tls13_ServerSendHrrKeyShareXtn },
{ ssl_tls13_cookie_xtn, &tls13_ServerSendHrrCookieXtn },
{ 0, NULL }
};

static const struct {
SSLExtensionType type;
SSLExtensionSupport support;
Expand Down Expand Up @@ -714,6 +722,11 @@ ssl_ConstructExtensions(sslSocket *ss, sslBuffer *buf, SSLHandshakeType message)
sender = ss->xtnData.encryptedExtensionsSenders;
break;

case ssl_hs_hello_retry_request:
PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
sender = tls13_hrr_senders;
break;

default:
PORT_Assert(0);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
Expand Down
15 changes: 9 additions & 6 deletions lib/ssl/ssl3ext.h
Expand Up @@ -86,12 +86,15 @@ struct TLSExtensionDataStr {

PRUint16 dtlsSRTPCipherSuite; /* 0 if not selected */

unsigned int lastXtnOffset; /* Where to insert padding. 0 = end. */
SECItem pskBinder; /* The PSK binder for the first PSK (TLS 1.3) */
unsigned int pskBinderPrefixLen; /* The length of the binder input. */
PRCList remoteKeyShares; /* The other side's public keys (TLS 1.3) */
/* This is used when deciding whether to accept early data. */
PRUint32 ticketAge;
unsigned int lastXtnOffset; /* Where to insert padding. 0 = end. */
PRCList remoteKeyShares; /* The other side's public keys (TLS 1.3) */

/* The following are used by a TLS 1.3 server. */
SECItem pskBinder; /* The binder for the first PSK. */
unsigned int pskBindersLen; /* The length of the binders. */
PRUint32 ticketAge; /* Used to accept early data. */
SECItem cookie; /* HRR Cookie. */
const sslNamedGroupDef *selectedGroup; /* For HRR. */
};

typedef struct TLSExtensionStr {
Expand Down
8 changes: 8 additions & 0 deletions lib/ssl/ssl3exthandle.c
Expand Up @@ -971,6 +971,8 @@ ssl3_ClientHandleSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData
return SECSuccess;
}

PR_STATIC_ASSERT((TLS_EX_SESS_TICKET_VERSION >> 8) == 1);

static SECStatus
ssl_ParseSessionTicket(sslSocket *ss, const SECItem *decryptedTicket,
SessionTicket *parsedTicket)
Expand All @@ -997,6 +999,12 @@ ssl_ParseSessionTicket(sslSocket *ss, const SECItem *decryptedTicket,
return SECFailure;
}

/* All ticket versions start with 0x01, so check to see if this
* is a ticket or some other self-encrypted thing. */
if ((temp >> 8) != 1) {
PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
return SECFailure;
}
/* Skip the ticket if the version is wrong. This won't result in a
* handshake failure, just a failure to resume. */
if (temp != TLS_EX_SESS_TICKET_VERSION) {
Expand Down
15 changes: 13 additions & 2 deletions lib/ssl/sslimpl.h
Expand Up @@ -35,6 +35,7 @@

typedef struct sslSocketStr sslSocket;
typedef struct ssl3CipherSpecStr ssl3CipherSpec;
typedef struct sslNamedGroupDefStr sslNamedGroupDef;
#include "sslexp.h"
#include "ssl3ext.h"
#include "sslencode.h"
Expand Down Expand Up @@ -162,7 +163,7 @@ typedef enum {
ticket_allow_psk_sign_auth = 16
} TLS13SessionTicketFlags;

typedef struct {
struct sslNamedGroupDefStr {
/* The name is the value that is encoded on the wire in TLS. */
SSLNamedGroup name;
/* The number of bits in the group. */
Expand All @@ -174,7 +175,7 @@ typedef struct {
SECOidTag oidTag;
/* Assume that the group is always supported. */
PRBool assumeSupported;
} sslNamedGroupDef;
};

typedef struct sslConnectInfoStr sslConnectInfo;
typedef struct sslGatherStr sslGather;
Expand Down Expand Up @@ -869,6 +870,12 @@ typedef struct SSL3HandshakeStateStr {
PRUint16 ticketNonce; /* A counter we use for tickets. */
} SSL3HandshakeState;

#define SSL_ASSERT_HASHES_EMPTY(ss) \
do { \
PORT_Assert(ss->ssl3.hs.hashType == handshake_hash_unknown); \
PORT_Assert(ss->ssl3.hs.messages.len == 0); \
} while (0)

/*
** This is the "ssl3" struct, as in "ss->ssl3".
** note:
Expand Down Expand Up @@ -1350,6 +1357,10 @@ extern void ssl3_RestartHandshakeHashes(sslSocket *ss);
extern SECStatus ssl3_UpdateHandshakeHashes(sslSocket *ss,
const unsigned char *b,
unsigned int l);
SECStatus
ssl_HashHandshakeMessageInt(sslSocket *ss, SSLHandshakeType type,
PRUint32 dtlsSeq,
const PRUint8 *b, PRUint32 length);
SECStatus ssl_HashHandshakeMessage(sslSocket *ss, SSLHandshakeType type,
const PRUint8 *b, PRUint32 length);

Expand Down

0 comments on commit da7b6f8

Please sign in to comment.