Commit da7b6f8a authored by EKR's avatar EKR

Bug 1386096 - Semi-stateless HelloRetryRequest, r=mt

--HG--
branch : NSS_TLS13_DRAFT19_BRANCH
parent 3847b262
......@@ -119,6 +119,7 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionAllNoopServer) {
TEST_F(TlsConnectStreamTls13, CustomExtensionEmptyWriterClient) {
EnsureTlsSetup();
InstallManyWriters(client_, EmptyExtensionWriter);
InstallManyWriters(server_, EmptyExtensionWriter);
Connect();
}
......
......@@ -49,6 +49,7 @@ CSRCS = \
ssl3ecc.c \
tls13con.c \
tls13exthandle.c \
tls13hashstate.c \
tls13hkdf.c \
tls13replay.c \
sslcert.c \
......
......@@ -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,
......
......@@ -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);
......
......@@ -42,6 +42,7 @@
'sslver.c',
'tls13con.c',
'tls13exthandle.c',
'tls13hashstate.c',
'tls13hkdf.c',
'tls13replay.c',
],
......
......@@ -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);
......@@ -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},
......@@ -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. */
......@@ -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)));
......@@ -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);
......@@ -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) {
......@@ -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* */
}
......@@ -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));
......@@ -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) {
......@@ -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. */
......@@ -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();
......@@ -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;
......@@ -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.
......@@ -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];
......@@ -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;
......@@ -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.
......@@ -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:
......
......@@ -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. */
......@@ -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 }
};
......@@ -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;
......@@ -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);
......
......@@ -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 {
......
......@@ -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)
......@@ -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) {
......
......@@ -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"
......@@ -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. */
......@@ -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;
......@@ -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:
......@@ -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);
......
This diff is collapsed.
......@@ -49,6 +49,8 @@ unsigned int tls13_GetHashSize(const sslSocket *ss);
CK_MECHANISM_TYPE tls13_GetHkdfMechanism(sslSocket *ss);
SECStatus tls13_ComputeHash(sslSocket *ss, SSL3Hashes *hashes,
const PRUint8 *buf, unsigned int len);
SECStatus tls13_ComputeHandshakeHashes(sslSocket *ss,
SSL3Hashes *hashes);
SECStatus tls13_DeriveSecretNullHash(sslSocket *ss, PK11SymKey *key,
const char *label,
unsigned int labelLen,
......@@ -64,10 +66,16 @@ PRBool tls13_PskSuiteEnabled(sslSocket *ss);
SECStatus tls13_WriteExtensionsWithBinder(sslSocket *ss, sslBuffer *extensions);
SECStatus tls13_HandleClientHelloPart2(sslSocket *ss,
const SECItem *suites,
sslSessionID *sid);
sslSessionID *sid,
const PRUint8 *msg,
unsigned int len);
SECStatus tls13_HandleServerHelloPart2(sslSocket *ss);
SECStatus tls13_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b,
PRUint32 length);
SECStatus tls13_ConstructHelloRetryRequest(sslSocket *ss,
const sslNamedGroupDef *selectedGroup,
PRUint8 *cookie, unsigned int cookieLen,
sslBuffer *buffer);
SECStatus tls13_HandleHelloRetryRequest(sslSocket *ss, PRUint8 *b,
PRUint32 length);
void tls13_DestroyKeyShareEntry(TLS13KeyShareEntry *entry);
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is PRIVATE to SSL.
*
* 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/. */
#ifndef __tls13err_h_
#define __tls13err_h_
/* Use this instead of FATAL_ERROR when an alert isn't possible. */
#define LOG_ERROR(ss, prError) \
do { \
SSL_TRC(3, ("%d: TLS13[%d]: fatal error %d in %s (%s:%d)", \
SSL_GETPID(), ss->fd, prError, __func__, __FILE__, __LINE__)); \
PORT_SetError(prError); \
} while (0)
/* Log an error and generate an alert because something is irreparably wrong. */
#define FATAL_ERROR(ss, prError, desc) \
do { \
LOG_ERROR(ss, prError); \
tls13_FatalError(ss, prError, desc); \
} while (0)
void tls13_FatalError(sslSocket *ss, PRErrorCode prError, SSL3AlertDescription desc);
#endif
......@@ -517,7 +517,7 @@ tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData
++numIdentities;
}
xtnData->pskBinderPrefixLen = ss->ssl3.hs.messages.len - data->len;
xtnData->pskBindersLen = data->len;
/* Parse the binders list. */
rv = ssl3_ExtConsumeHandshakeVariable(ss,
......@@ -806,6 +806,37 @@ tls13_ClientSendHrrCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData,
return SECSuccess;
}
SECStatus
tls13_ServerHandleCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData,
SECItem *data)
{
SECStatus rv;
SSL_TRC(3, ("%d: TLS13[%d]: handle cookie extension",
SSL_GETPID(), ss->fd));
rv = ssl3_ExtConsumeHandshakeVariable(ss, &xtnData->cookie, 2,
&data->data, &data->len);
if (rv != SECSuccess) {
return SECFailure;
}
if (xtnData->cookie.len == 0) {
PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
return SECFailure;
}
if (data->len) {
PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
return SECFailure;
}
/* Keep track of negotiated extensions. */
xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_cookie_xtn;
return SECSuccess;
}
/*
* enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode;
*
......@@ -947,3 +978,47 @@ loser:
xtnData->certReqAuthorities.arena = NULL;
return SECFailure;
}
SECStatus
tls13_ServerSendHrrKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
sslBuffer *buf, PRBool *added)
{
SECStatus rv;
PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
/* In future, we may want to send HRRs w/o key_share but we don't
* currently do that. At that time, this assert can simply be
* removed. */
PORT_Assert(xtnData->selectedGroup != NULL);
if (!xtnData->selectedGroup) {
return SECSuccess;
}
rv = sslBuffer_AppendNumber(buf, xtnData->selectedGroup->name, 2);
if (rv != SECSuccess) {
return SECFailure;
}
*added = PR_TRUE;
return SECSuccess;
}
SECStatus
tls13_ServerSendHrrCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData,
sslBuffer *buf, PRBool *added)
{
SECStatus rv;
PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
PORT_Assert(xtnData->cookie.len > 0);
rv = sslBuffer_AppendVariable(buf,
xtnData->cookie.data, xtnData->cookie.len, 2);
if (rv != SECSuccess) {
return SECFailure;
}
*added = PR_TRUE;
return SECSuccess;
}
......@@ -72,5 +72,14 @@ SECStatus tls13_SendCertAuthoritiesXtn(const sslSocket *ss,
SECStatus tls13_ClientHandleCertAuthoritiesXtn(const sslSocket *ss,
TLSExtensionData *xtnData,
SECItem *data);
SECStatus tls13_ServerHandleCookieXtn(const sslSocket *ss,
TLSExtensionData *xtnData,
SECItem *data);
SECStatus tls13_ServerSendHrrKeyShareXtn(const sslSocket *ss,
TLSExtensionData *xtnData,
sslBuffer *buf, PRBool *added);
SECStatus tls13_ServerSendHrrCookieXtn(const sslSocket *ss,
TLSExtensionData *xtnData,
sslBuffer *buf, PRBool *added);
#endif
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is PRIVATE to SSL.
*
* 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 "pk11func.h"
#include "selfencrypt.h"
#include "ssl.h"
#include "sslt.h"
#include "sslencode.h"
#include "sslimpl.h"
#include "tls13con.h"
#include "tls13err.h"
#include "tls13hashstate.h"
/*
* The cookie is structured as a self-encrypted structure with the
* inner value being.
*
* struct {
* uint8 indicator = 0xff; // To disambiguate from tickets.
* uint16 cipherSuite; // Selected cipher suite.
* uint16 keyShare; // Key share we requested (0 if none)
* opaque ch_hash[rest_of_buffer]; // H(ClientHello)
* } CookieInner;
*/
SECStatus
tls13_MakeHrrCookie(sslSocket *ss, const sslNamedGroupDef *selectedGroup,
PRUint8 *buf, unsigned int *len, unsigned int maxlen)
{
SECStatus rv;
SSL3Hashes hashes;
PRUint8 encodedCookie[1024];
SECItem cookieItem = { siBuffer, encodedCookie, sizeof(encodedCookie) };
PORT_Assert(sizeof(encodedCookie) >= maxlen);
/* Encode header. */
rv = ssl3_AppendNumberToItem(&cookieItem, 0xff, 1);
if (rv != SECSuccess) {
return SECFailure;
}
rv = ssl3_AppendNumberToItem(&cookieItem, ss->ssl3.hs.cipher_suite, 2);
if (rv != SECSuccess) {
return SECFailure;
}
rv = ssl3_AppendNumberToItem(&cookieItem, selectedGroup ? selectedGroup->name : 0, 2);
if (rv != SECSuccess) {
return SECFailure;
}
/* Encode the hash state */
rv = tls13_ComputeHandshakeHashes(ss, &hashes);
if (rv != SECSuccess) {
return SECFailure;
}
rv = ssl3_AppendToItem(&cookieItem, hashes.u.raw, hashes.len);
if (rv != SECSuccess) {
return SECFailure;
}
/* Encrypt right into the buffer. */
rv = ssl_SelfEncryptProtect(ss,
encodedCookie, cookieItem.data - encodedCookie,
buf, len, maxlen);
if (rv != SECSuccess) {
return SECFailure;
}
return SECSuccess;
}
/* Recover the hash state from the cookie. */
SECStatus
tls13_RecoverHashState(sslSocket *ss,
unsigned char *cookie,
unsigned int cookieLen)
{
SECStatus rv;
unsigned char plaintext[1024];
SECItem ptItem = { siBuffer, plaintext, 0 };
sslBuffer messageBuf = { NULL, 0, 0 };
PRUint32 sentinel;
PRUint32 cipherSuite;
PRUint32 group;
const sslNamedGroupDef *selectedGroup;
rv = ssl_SelfEncryptUnprotect(ss, cookie, cookieLen,
ptItem.data, &ptItem.len, sizeof(plaintext));
if (rv != SECSuccess) {
return SECFailure;
}
/* Should start with 0xff. */
rv = ssl3_ConsumeNumberFromItem(&ptItem, &sentinel, 1);
if ((rv != SECSuccess) || (sentinel != 0xff)) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
return SECFailure;
}
/* The cipher suite should be the same or there are some shenanigans. */
rv = ssl3_ConsumeNumberFromItem(&ptItem, &cipherSuite, 2);
if ((rv != SECSuccess) || cipherSuite != ss->ssl3.hs.cipher_suite) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
return SECFailure;
}
/* The named group, if any. */
rv = ssl3_ConsumeNumberFromItem(&ptItem, &group, 2);
if (rv != SECSuccess) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
return SECFailure;
}
selectedGroup = ssl_LookupNamedGroup(group);
PORT_Assert(selectedGroup);
if (selectedGroup == NULL) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
return SECFailure;
}
/* The remainder is the hash. */
if (ptItem.len != tls13_GetHashSize(ss)) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
return SECFailure;
}
/* Now reinject the message. */
SSL_ASSERT_HASHES_EMPTY(ss);
rv = ssl_HashHandshakeMessageInt(ss, ssl_hs_message_hash, 0,
ptItem.data, ptItem.len);
if (rv != SECSuccess) {
return SECFailure;
}
/* And finally reinject the HRR. */
rv = tls13_ConstructHelloRetryRequest(ss, selectedGroup,
cookie, cookieLen,
&messageBuf);
if (rv != SECSuccess) {
return SECFailure;
}
rv = ssl_HashHandshakeMessageInt(ss, ssl_hs_hello_retry_request, 0,
messageBuf.buf, messageBuf.len);
sslBuffer_Clear(&messageBuf);
if (rv != SECSuccess) {
return SECFailure;
}
return SECSuccess;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is PRIVATE to SSL.
*
* 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/. */
#ifndef __tls13hashstate_h_
#define __tls13hashstate_h_
#include "ssl.h"
#include "sslt.h"
#include "sslimpl.h"
SECStatus tls13_MakeHrrCookie(sslSocket *ss, const sslNamedGroupDef *selectedGroup,
PRUint8 *buf, unsigned int *len, unsigned int maxlen);
SECStatus tls13_GetHrrCookieLength(sslSocket *ss, unsigned int *length);
SECStatus tls13_RecoverHashState(sslSocket *ss,
unsigned char *cookie,
unsigned int cookieLen);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment