summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/ssl/tls13exthandle.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/ssl/tls13exthandle.c')
-rw-r--r--security/nss/lib/ssl/tls13exthandle.c813
1 files changed, 471 insertions, 342 deletions
diff --git a/security/nss/lib/ssl/tls13exthandle.c b/security/nss/lib/ssl/tls13exthandle.c
index 899f23827..c2ce390ff 100644
--- a/security/nss/lib/ssl/tls13exthandle.c
+++ b/security/nss/lib/ssl/tls13exthandle.c
@@ -14,35 +14,50 @@
#include "ssl3exthandle.h"
#include "tls13exthandle.h"
-SECStatus
-tls13_ServerSendStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- sslBuffer *buf, PRBool *added)
+PRInt32
+tls13_ServerSendStatusRequestXtn(
+ const sslSocket *ss,
+ TLSExtensionData *xtnData,
+ PRBool append,
+ PRUint32 maxBytes)
{
+ PRInt32 extension_length;
const sslServerCert *serverCert = ss->sec.serverCert;
const SECItem *item;
SECStatus rv;
if (!serverCert->certStatusArray ||
!serverCert->certStatusArray->len) {
- return SECSuccess;
+ return 0;
}
item = &serverCert->certStatusArray->items[0];
/* Only send the first entry. */
- /* status_type == ocsp */
- rv = sslBuffer_AppendNumber(buf, 1 /*ocsp*/, 1);
- if (rv != SECSuccess) {
- return SECFailure;
+ extension_length = 2 + 2 + 1 /* status_type */ + 3 + item->len;
+ if (maxBytes < (PRUint32)extension_length) {
+ return 0;
}
- /* opaque OCSPResponse<1..2^24-1> */
- rv = sslBuffer_AppendVariable(buf, item->data, item->len, 3);
- if (rv != SECSuccess) {
- return SECFailure;
+ if (append) {
+ /* extension_type */
+ rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_cert_status_xtn, 2);
+ if (rv != SECSuccess)
+ return -1;
+ /* length of extension_data */
+ rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2);
+ if (rv != SECSuccess)
+ return -1;
+ /* status_type == ocsp */
+ rv = ssl3_ExtAppendHandshakeNumber(ss, 1 /*ocsp*/, 1);
+ if (rv != SECSuccess)
+ return rv; /* err set by AppendHandshake. */
+ /* opaque OCSPResponse<1..2^24-1> */
+ rv = ssl3_ExtAppendHandshakeVariable(ss, item->data, item->len, 3);
+ if (rv != SECSuccess)
+ return rv; /* err set by AppendHandshake. */
}
- *added = PR_TRUE;
- return SECSuccess;
+ return extension_length;
}
/*
@@ -86,27 +101,41 @@ tls13_SizeOfKeyShareEntry(const SECKEYPublicKey *pubKey)
return 0;
}
+static PRUint32
+tls13_SizeOfClientKeyShareExtension(const sslSocket *ss)
+{
+ PRCList *cursor;
+ /* Size is: extension(2) + extension_len(2) + client_shares(2) */
+ PRUint32 size = 2 + 2 + 2;
+ for (cursor = PR_NEXT_LINK(&ss->ephemeralKeyPairs);
+ cursor != &ss->ephemeralKeyPairs;
+ cursor = PR_NEXT_LINK(cursor)) {
+ sslEphemeralKeyPair *keyPair = (sslEphemeralKeyPair *)cursor;
+ size += tls13_SizeOfKeyShareEntry(keyPair->keys->pubKey);
+ }
+ return size;
+}
+
static SECStatus
-tls13_EncodeKeyShareEntry(sslBuffer *buf, const sslEphemeralKeyPair *keyPair)
+tls13_EncodeKeyShareEntry(const sslSocket *ss, const sslEphemeralKeyPair *keyPair)
{
SECStatus rv;
SECKEYPublicKey *pubKey = keyPair->keys->pubKey;
unsigned int size = tls13_SizeOfKeyShareEntry(pubKey);
- rv = sslBuffer_AppendNumber(buf, keyPair->group->name, 2);
+ rv = ssl3_ExtAppendHandshakeNumber(ss, keyPair->group->name, 2);
if (rv != SECSuccess)
return rv;
- rv = sslBuffer_AppendNumber(buf, size - 4, 2);
+ rv = ssl3_ExtAppendHandshakeNumber(ss, size - 4, 2);
if (rv != SECSuccess)
return rv;
switch (pubKey->keyType) {
case ecKey:
- rv = sslBuffer_Append(buf, pubKey->u.ec.publicValue.data,
- pubKey->u.ec.publicValue.len);
+ rv = tls13_EncodeECDHEKeyShareKEX(ss, pubKey);
break;
case dhKey:
- rv = ssl_AppendPaddedDHKeyShare(buf, pubKey, PR_FALSE);
+ rv = ssl_AppendPaddedDHKeyShare(ss, pubKey, PR_FALSE);
break;
default:
PORT_Assert(0);
@@ -117,16 +146,14 @@ tls13_EncodeKeyShareEntry(sslBuffer *buf, const sslEphemeralKeyPair *keyPair)
return rv;
}
-SECStatus
-tls13_ClientSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- sslBuffer *buf, PRBool *added)
+PRInt32
+tls13_ClientSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append,
+ PRUint32 maxBytes)
{
- SECStatus rv;
- PRCList *cursor;
- unsigned int lengthOffset;
+ PRUint32 extension_length;
if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) {
- return SECSuccess;
+ return 0;
}
/* Optimistically try to send an ECDHE key using the
@@ -134,28 +161,47 @@ tls13_ClientSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
SSL_TRC(3, ("%d: TLS13[%d]: send client key share xtn",
SSL_GETPID(), ss->fd));
- /* Save the offset to the length. */
- rv = sslBuffer_Skip(buf, 2, &lengthOffset);
- if (rv != SECSuccess) {
- return SECFailure;
+ extension_length = tls13_SizeOfClientKeyShareExtension(ss);
+ if (maxBytes < extension_length) {
+ PORT_Assert(0);
+ return 0;
}
- for (cursor = PR_NEXT_LINK(&ss->ephemeralKeyPairs);
- cursor != &ss->ephemeralKeyPairs;
- cursor = PR_NEXT_LINK(cursor)) {
- sslEphemeralKeyPair *keyPair = (sslEphemeralKeyPair *)cursor;
- rv = tls13_EncodeKeyShareEntry(buf, keyPair);
- if (rv != SECSuccess) {
- return SECFailure;
+ if (append) {
+ SECStatus rv;
+ PRCList *cursor;
+
+ rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_key_share_xtn, 2);
+ if (rv != SECSuccess)
+ goto loser;
+
+ /* The extension length */
+ rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2);
+ if (rv != SECSuccess)
+ goto loser;
+
+ /* The length of KeyShares */
+ rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 6, 2);
+ if (rv != SECSuccess)
+ goto loser;
+
+ for (cursor = PR_NEXT_LINK(&ss->ephemeralKeyPairs);
+ cursor != &ss->ephemeralKeyPairs;
+ cursor = PR_NEXT_LINK(cursor)) {
+ sslEphemeralKeyPair *keyPair = (sslEphemeralKeyPair *)cursor;
+ rv = tls13_EncodeKeyShareEntry(ss, keyPair);
+ if (rv != SECSuccess)
+ goto loser;
}
- }
- rv = sslBuffer_InsertLength(buf, lengthOffset, 2);
- if (rv != SECSuccess) {
- return SECFailure;
+
+ xtnData->advertised[xtnData->numAdvertised++] =
+ ssl_tls13_key_share_xtn;
}
- *added = PR_TRUE;
- return SECSuccess;
+ return extension_length;
+
+loser:
+ return -1;
}
static SECStatus
@@ -204,8 +250,7 @@ loser:
* |xtnData->remoteKeyShares| for future use. The key
* share is processed in tls13_HandleServerKeyShare(). */
SECStatus
-tls13_ClientHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- SECItem *data)
+tls13_ClientHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data)
{
SECStatus rv;
PORT_Assert(PR_CLIST_IS_EMPTY(&xtnData->remoteKeyShares));
@@ -236,8 +281,7 @@ tls13_ClientHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
}
SECStatus
-tls13_ClientHandleKeyShareXtnHrr(const sslSocket *ss, TLSExtensionData *xtnData,
- SECItem *data)
+tls13_ClientHandleKeyShareXtnHrr(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data)
{
SECStatus rv;
PRUint32 tmp;
@@ -287,8 +331,7 @@ tls13_ClientHandleKeyShareXtnHrr(const sslSocket *ss, TLSExtensionData *xtnData,
* |xtnData->remoteKeyShares| for future use. The key
* share is processed in tls13_HandleClientKeyShare(). */
SECStatus
-tls13_ServerHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- SECItem *data)
+tls13_ServerHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data)
{
SECStatus rv;
PRUint32 length;
@@ -321,6 +364,16 @@ tls13_ServerHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
goto loser;
}
+ /* Check that the client only offered one share if this is
+ * after HRR. */
+ if (ss->ssl3.hs.helloRetry) {
+ if (PR_PREV_LINK(&xtnData->remoteKeyShares) !=
+ PR_NEXT_LINK(&xtnData->remoteKeyShares)) {
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
+ goto loser;
+ }
+ }
+
return SECSuccess;
loser:
@@ -328,10 +381,12 @@ loser:
return SECFailure;
}
-SECStatus
-tls13_ServerSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- sslBuffer *buf, PRBool *added)
+PRInt32
+tls13_ServerSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append,
+ PRUint32 maxBytes)
{
+ PRUint32 extension_length;
+ PRUint32 entry_length;
SECStatus rv;
sslEphemeralKeyPair *keyPair;
@@ -342,13 +397,31 @@ tls13_ServerSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
keyPair = (sslEphemeralKeyPair *)PR_NEXT_LINK(&ss->ephemeralKeyPairs);
- rv = tls13_EncodeKeyShareEntry(buf, keyPair);
- if (rv != SECSuccess) {
- return SECFailure;
+ entry_length = tls13_SizeOfKeyShareEntry(keyPair->keys->pubKey);
+ extension_length = 2 + 2 + entry_length; /* Type + length + entry_length */
+ if (maxBytes < extension_length) {
+ PORT_Assert(0);
+ return 0;
}
- *added = PR_TRUE;
- return SECSuccess;
+ if (append) {
+ rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_key_share_xtn, 2);
+ if (rv != SECSuccess)
+ goto loser;
+
+ rv = ssl3_ExtAppendHandshakeNumber(ss, entry_length, 2);
+ if (rv != SECSuccess)
+ goto loser;
+
+ rv = tls13_EncodeKeyShareEntry(ss, keyPair);
+ if (rv != SECSuccess)
+ goto loser;
+ }
+
+ return extension_length;
+
+loser:
+ return -1;
}
/* Called by clients.
@@ -375,83 +448,113 @@ tls13_ServerSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
* Presently the only way to get a PSK is by resumption, so this is
* really a ticket label and there will be at most one.
*/
-SECStatus
+PRInt32
tls13_ClientSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- sslBuffer *buf, PRBool *added)
+ PRBool append,
+ PRUint32 maxBytes)
{
+ PRInt32 extension_length;
+ PRInt32 identities_length;
+ PRInt32 binders_length;
NewSessionTicket *session_ticket;
- PRTime age;
- const static PRUint8 binder[TLS13_MAX_FINISHED_SIZE] = { 0 };
- unsigned int binderLen;
- SECStatus rv;
/* We only set statelessResume on the client in TLS 1.3 code. */
- if (!ss->statelessResume) {
- return SECSuccess;
- }
-
- /* Save where this extension starts so that if we have to add padding, it
- * can be inserted before this extension. */
- PORT_Assert(buf->len >= 4);
- xtnData->lastXtnOffset = buf->len - 4;
+ if (!ss->statelessResume)
+ return 0;
PORT_Assert(ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3);
- /* Send a single ticket identity. */
+ /* The length computations are simplified by the fact that there
+ * is just one ticket at most. */
session_ticket = &ss->sec.ci.sid->u.ssl3.locked.sessionTicket;
- rv = sslBuffer_AppendNumber(buf, 2 + /* identity length */
- session_ticket->ticket.len + /* ticket */
- 4 /* obfuscated_ticket_age */,
- 2);
- if (rv != SECSuccess)
- goto loser;
- rv = sslBuffer_AppendVariable(buf, session_ticket->ticket.data,
- session_ticket->ticket.len, 2);
- if (rv != SECSuccess)
- goto loser;
+ identities_length =
+ 2 + /* vector length */
+ 2 + session_ticket->ticket.len + /* identity length + ticket len */
+ 4; /* obfuscated_ticket_age */
+ binders_length =
+ 2 + /* vector length */
+ 1 + tls13_GetHashSizeForHash(
+ tls13_GetHashForCipherSuite(ss->sec.ci.sid->u.ssl3.cipherSuite));
+ extension_length =
+ 2 + 2 + /* Type + length */
+ identities_length + binders_length;
+
+ if (maxBytes < (PRUint32)extension_length) {
+ PORT_Assert(0);
+ return 0;
+ }
+
+ if (append) {
+ SECStatus rv;
+ PRTime age;
+ unsigned int prefixLength;
+ PRUint8 binder[TLS13_MAX_FINISHED_SIZE];
+ unsigned int binderLen;
+
+ /* extension_type */
+ rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_pre_shared_key_xtn, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ rv = ssl3_ExtAppendHandshakeNumber(ss, identities_length - 2, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ rv = ssl3_ExtAppendHandshakeVariable(ss, session_ticket->ticket.data,
+ session_ticket->ticket.len, 2);
+ if (rv != SECSuccess)
+ goto loser;
- /* Obfuscated age. */
- age = ssl_TimeUsec() - session_ticket->received_timestamp;
- age /= PR_USEC_PER_MSEC;
- age += session_ticket->ticket_age_add;
- rv = sslBuffer_AppendNumber(buf, age, 4);
- if (rv != SECSuccess)
- goto loser;
+ /* Obfuscated age. */
+ age = PR_Now() - session_ticket->received_timestamp;
+ age /= PR_USEC_PER_MSEC;
+ age += session_ticket->ticket_age_add;
+ rv = ssl3_ExtAppendHandshakeNumber(ss, age, 4);
+ if (rv != SECSuccess)
+ goto loser;
- /* Write out the binder list length. */
- binderLen = tls13_GetHashSize(ss);
- rv = sslBuffer_AppendNumber(buf, binderLen + 1, 2);
- if (rv != SECSuccess)
- goto loser;
- /* Write zeroes for the binder for the moment. */
- rv = sslBuffer_AppendVariable(buf, binder, binderLen, 1);
- if (rv != SECSuccess)
- goto loser;
+ /* Now the binders. */
+ prefixLength = ss->ssl3.hs.messages.len;
+ rv = tls13_ComputePskBinder(CONST_CAST(sslSocket, ss), PR_TRUE,
+ prefixLength, binder, &binderLen,
+ sizeof(binder));
+ if (rv != SECSuccess)
+ goto loser;
+ PORT_Assert(binderLen == tls13_GetHashSize(ss));
+ rv = ssl3_ExtAppendHandshakeNumber(ss, binders_length - 2, 2);
+ if (rv != SECSuccess)
+ goto loser;
+ rv = ssl3_ExtAppendHandshakeVariable(ss,
+ binder, binderLen, 1);
+ if (rv != SECSuccess)
+ goto loser;
- PRINT_BUF(50, (ss, "Sending PreSharedKey value",
- session_ticket->ticket.data,
- session_ticket->ticket.len));
+ PRINT_BUF(50, (ss, "Sending PreSharedKey value",
+ session_ticket->ticket.data,
+ session_ticket->ticket.len));
- xtnData->sentSessionTicketInClientHello = PR_TRUE;
- *added = PR_TRUE;
- return SECSuccess;
+ xtnData->sentSessionTicketInClientHello = PR_TRUE;
+ xtnData->advertised[xtnData->numAdvertised++] =
+ ssl_tls13_pre_shared_key_xtn;
+ }
+ return extension_length;
loser:
xtnData->ticketTimestampVerified = PR_FALSE;
- return SECFailure;
+ return -1;
}
/* Handle a TLS 1.3 PreSharedKey Extension. We only accept PSKs
* that contain session tickets. */
SECStatus
-tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
SECItem *data)
{
SECItem inner;
SECStatus rv;
unsigned int numIdentities = 0;
unsigned int numBinders = 0;
- SECItem *appToken;
SSL_TRC(3, ("%d: SSL3[%d]: handle pre_shared_key extension",
SSL_GETPID(), ss->fd));
@@ -461,26 +564,16 @@ tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData
return SECSuccess;
}
- /* The application token is set via the cookie extension if this is the
- * second ClientHello. Don't set it twice. The cookie extension handler
- * sets |helloRetry| and that will have been called already because this
- * extension always comes last. */
- if (!ss->ssl3.hs.helloRetry) {
- appToken = &xtnData->applicationToken;
- } else {
- appToken = NULL;
- }
-
/* Parse the identities list. */
- rv = ssl3_ExtConsumeHandshakeVariable(ss, &inner, 2,
- &data->data, &data->len);
+ rv = ssl3_ExtConsumeHandshakeVariable(ss,
+ &inner, 2, &data->data, &data->len);
if (rv != SECSuccess) {
return SECFailure;
}
while (inner.len) {
SECItem label;
- PRUint32 obfuscatedAge;
+ PRUint32 utmp;
rv = ssl3_ExtConsumeHandshakeVariable(ss, &label, 2,
&inner.data, &inner.len);
@@ -490,8 +583,9 @@ tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData
goto alert_loser;
}
- rv = ssl3_ExtConsumeHandshakeNumber(ss, &obfuscatedAge, 4,
- &inner.data, &inner.len);
+ /* Read and discard session ticket age. Bug 1295163 */
+ rv = ssl3_ExtConsumeHandshake(ss, &utmp, 4,
+ &inner.data, &inner.len);
if (rv != SECSuccess)
return rv;
@@ -499,29 +593,17 @@ tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData
PRINT_BUF(50, (ss, "Handling PreSharedKey value",
label.data, label.len));
rv = ssl3_ProcessSessionTicketCommon(
- CONST_CAST(sslSocket, ss), &label, appToken);
+ CONST_CAST(sslSocket, ss), &label);
/* This only happens if we have an internal error, not
* a malformed ticket. Bogus tickets just don't resume
* and return SECSuccess. */
if (rv != SECSuccess)
return SECFailure;
-
- if (ss->sec.ci.sid) {
- /* xtnData->ticketAge contains the baseline we use for
- * calculating the ticket age (i.e., our RTT estimate less the
- * value of ticket_age_add).
- *
- * Add that to the obfuscated ticket age to recover the client's
- * view of the ticket age plus the estimated RTT.
- *
- * See ssl3_EncodeSessionTicket() for details. */
- xtnData->ticketAge += obfuscatedAge;
- }
}
++numIdentities;
}
- xtnData->pskBindersLen = data->len;
+ xtnData->pskBinderPrefixLen = ss->ssl3.hs.messages.len - data->len;
/* Parse the binders list. */
rv = ssl3_ExtConsumeHandshakeVariable(ss,
@@ -553,7 +635,7 @@ tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData
/* Keep track of negotiated extensions. Note that this does not
* mean we are resuming. */
- xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_pre_shared_key_xtn;
+ xtnData->negotiated[xtnData->numNegotiated++] = ex_type;
return SECSuccess;
@@ -563,27 +645,43 @@ alert_loser:
return SECFailure;
}
-SECStatus
+PRInt32
tls13_ServerSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- sslBuffer *buf, PRBool *added)
+ PRBool append,
+ PRUint32 maxBytes)
{
+ PRInt32 extension_length =
+ 2 + 2 + 2; /* type + len + index */
SECStatus rv;
- /* We only process the first session ticket the client sends,
- * so the index is always 0. */
- rv = sslBuffer_AppendNumber(buf, 0, 2);
- if (rv != SECSuccess) {
- return SECFailure;
+ if (maxBytes < (PRUint32)extension_length) {
+ PORT_Assert(0);
+ return 0;
}
- *added = PR_TRUE;
- return SECSuccess;
+ if (append) {
+ rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_pre_shared_key_xtn, 2);
+ if (rv != SECSuccess)
+ return -1;
+
+ rv = ssl3_ExtAppendHandshakeNumber(ss, 2, 2);
+ if (rv != SECSuccess)
+ return -1;
+
+ /* We only process the first session ticket the client sends,
+ * so the index is always 0. */
+ rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2);
+ if (rv != SECSuccess)
+ return -1;
+ }
+
+ return extension_length;
}
/* Handle a TLS 1.3 PreSharedKey Extension. We only accept PSKs
* that contain session tickets. */
SECStatus
-tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
SECItem *data)
{
PRUint32 index;
@@ -615,7 +713,7 @@ tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData
}
/* Keep track of negotiated extensions. */
- xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_pre_shared_key_xtn;
+ xtnData->negotiated[xtnData->numNegotiated++] = ex_type;
return SECSuccess;
}
@@ -623,20 +721,43 @@ tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData
/*
* struct { } EarlyDataIndication;
*/
-SECStatus
+PRInt32
tls13_ClientSendEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- sslBuffer *buf, PRBool *added)
+ PRBool append,
+ PRUint32 maxBytes)
{
- if (!tls13_ClientAllow0Rtt(ss, ss->sec.ci.sid)) {
- return SECSuccess;
+ SECStatus rv;
+ PRInt32 extension_length;
+
+ if (!tls13_ClientAllow0Rtt(ss, ss->sec.ci.sid))
+ return 0;
+
+ /* type + length */
+ extension_length = 2 + 2;
+
+ if (maxBytes < (PRUint32)extension_length) {
+ PORT_Assert(0);
+ return 0;
}
- *added = PR_TRUE;
- return SECSuccess;
+ if (append) {
+ rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_early_data_xtn, 2);
+ if (rv != SECSuccess)
+ return -1;
+
+ rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2);
+ if (rv != SECSuccess)
+ return -1;
+
+ xtnData->advertised[xtnData->numAdvertised++] =
+ ssl_tls13_early_data_xtn;
+ }
+
+ return extension_length;
}
SECStatus
-tls13_ServerHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+tls13_ServerHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
SECItem *data)
{
SSL_TRC(3, ("%d: TLS13[%d]: handle early_data extension",
@@ -658,14 +779,44 @@ tls13_ServerHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData,
return SECFailure;
}
- xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_early_data_xtn;
+ xtnData->negotiated[xtnData->numNegotiated++] = ex_type;
return SECSuccess;
}
+/* This is only registered if we are sending it. */
+PRInt32
+tls13_ServerSendEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+ PRBool append,
+ PRUint32 maxBytes)
+{
+ SSL_TRC(3, ("%d: TLS13[%d]: send early_data extension",
+ SSL_GETPID(), ss->fd));
+
+ PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted);
+ if (maxBytes < 4) {
+ PORT_Assert(0);
+ return 0;
+ }
+
+ if (append) {
+ SECStatus rv;
+
+ rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_early_data_xtn, 2);
+ if (rv != SECSuccess)
+ return -1;
+
+ rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2);
+ if (rv != SECSuccess)
+ return -1;
+ }
+
+ return 4;
+}
+
/* This will only be called if we also offered the extension. */
SECStatus
-tls13_ClientHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+tls13_ClientHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
SECItem *data)
{
SSL_TRC(3, ("%d: TLS13[%d]: handle early_data extension",
@@ -683,19 +834,19 @@ tls13_ClientHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData,
}
/* Keep track of negotiated extensions. */
- xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_early_data_xtn;
+ xtnData->negotiated[xtnData->numNegotiated++] = ex_type;
return SECSuccess;
}
SECStatus
-tls13_ClientHandleTicketEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- SECItem *data)
+tls13_ClientHandleTicketEarlyDataInfoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
+ SECItem *data)
{
PRUint32 utmp;
SECStatus rv;
- SSL_TRC(3, ("%d: TLS13[%d]: handle ticket early_data extension",
+ SSL_TRC(3, ("%d: TLS13[%d]: handle early_data_info extension",
SSL_GETPID(), ss->fd));
/* The server must not send this extension when negotiating < TLS 1.3. */
@@ -722,71 +873,59 @@ tls13_ClientHandleTicketEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnD
/*
* struct {
- * select (Handshake.msg_type) {
- * case client_hello:
* ProtocolVersion versions<2..254>;
- * case server_hello:
- * ProtocolVersion version;
- * };
* } SupportedVersions;
*/
-SECStatus
-tls13_ClientSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- sslBuffer *buf, PRBool *added)
+PRInt32
+tls13_ClientSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append,
+ PRUint32 maxBytes)
{
+ PRInt32 extensions_len;
PRUint16 version;
- unsigned int lengthOffset;
SECStatus rv;
if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) {
- return SECSuccess;
+ return 0;
}
- SSL_TRC(3, ("%d: TLS13[%d]: client send supported_versions extension",
+ SSL_TRC(3, ("%d: TLS13[%d]: send supported_versions extension",
SSL_GETPID(), ss->fd));
- rv = sslBuffer_Skip(buf, 1, &lengthOffset);
- if (rv != SECSuccess) {
- return SECFailure;
- }
+ /* Extension type, extension len fiels, vector len field,
+ * length of the values. */
+ extensions_len = 2 + 2 + 1 +
+ 2 * (ss->vrange.max - ss->vrange.min + 1);
- for (version = ss->vrange.max; version >= ss->vrange.min; --version) {
- rv = sslBuffer_AppendNumber(buf, tls13_EncodeDraftVersion(version), 2);
- if (rv != SECSuccess) {
- return SECFailure;
- }
+ if (maxBytes < (PRUint32)extensions_len) {
+ PORT_Assert(0);
+ return 0;
}
- rv = sslBuffer_InsertLength(buf, lengthOffset, 1);
- if (rv != SECSuccess) {
- return SECFailure;
- }
-
- *added = PR_TRUE;
- return SECSuccess;
-}
+ if (append) {
+ rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_supported_versions_xtn, 2);
+ if (rv != SECSuccess)
+ return -1;
-SECStatus
-tls13_ServerSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- sslBuffer *buf, PRBool *added)
-{
- SECStatus rv;
+ rv = ssl3_ExtAppendHandshakeNumber(ss, extensions_len - 4, 2);
+ if (rv != SECSuccess)
+ return -1;
- if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
- return SECSuccess;
- }
+ rv = ssl3_ExtAppendHandshakeNumber(ss, extensions_len - 5, 1);
+ if (rv != SECSuccess)
+ return -1;
- SSL_TRC(3, ("%d: TLS13[%d]: server send supported_versions extension",
- SSL_GETPID(), ss->fd));
+ for (version = ss->vrange.max; version >= ss->vrange.min; --version) {
+ rv = ssl3_ExtAppendHandshakeNumber(
+ ss, tls13_EncodeDraftVersion(version), 2);
+ if (rv != SECSuccess)
+ return -1;
+ }
- rv = sslBuffer_AppendNumber(
- buf, tls13_EncodeDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3), 2);
- if (rv != SECSuccess) {
- return SECFailure;
+ xtnData->advertised[xtnData->numAdvertised++] =
+ ssl_tls13_supported_versions_xtn;
}
- *added = PR_TRUE;
- return SECSuccess;
+ return extensions_len;
}
/*
@@ -795,8 +934,7 @@ tls13_ServerSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnD
* } Cookie;
*/
SECStatus
-tls13_ClientHandleHrrCookie(const sslSocket *ss, TLSExtensionData *xtnData,
- SECItem *data)
+tls13_ClientHandleHrrCookie(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data)
{
SECStatus rv;
@@ -822,57 +960,41 @@ tls13_ClientHandleHrrCookie(const sslSocket *ss, TLSExtensionData *xtnData,
return SECSuccess;
}
-SECStatus
-tls13_ClientSendHrrCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- sslBuffer *buf, PRBool *added)
+PRInt32
+tls13_ClientSendHrrCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes)
{
- SECStatus rv;
+ PRInt32 extension_len;
if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3 ||
!ss->ssl3.hs.cookie.len) {
- return SECSuccess;
+ return 0;
}
SSL_TRC(3, ("%d: TLS13[%d]: send cookie extension", SSL_GETPID(), ss->fd));
- rv = sslBuffer_AppendVariable(buf, ss->ssl3.hs.cookie.data,
- ss->ssl3.hs.cookie.len, 2);
- if (rv != SECSuccess) {
- return SECFailure;
- }
-
- *added = PR_TRUE;
- return SECSuccess;
-}
-SECStatus
-tls13_ServerHandleCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- SECItem *data)
-{
- SECStatus rv;
+ /* Extension type, length, cookie length, cookie value. */
+ extension_len = 2 + 2 + 2 + ss->ssl3.hs.cookie.len;
- 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 (maxBytes < (PRUint32)extension_len) {
+ PORT_Assert(0);
+ return 0;
}
- if (data->len) {
- PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
- return SECFailure;
- }
+ if (append) {
+ SECStatus rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_cookie_xtn, 2);
+ if (rv != SECSuccess)
+ return -1;
- /* Keep track of negotiated extensions. */
- xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_cookie_xtn;
+ rv = ssl3_ExtAppendHandshakeNumber(ss, extension_len - 4, 2);
+ if (rv != SECSuccess)
+ return -1;
- return SECSuccess;
+ rv = ssl3_ExtAppendHandshakeVariable(ss, ss->ssl3.hs.cookie.data,
+ ss->ssl3.hs.cookie.len, 2);
+ if (rv != SECSuccess)
+ return -1;
+ }
+ return extension_len;
}
/*
@@ -882,33 +1004,54 @@ tls13_ServerHandleCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData,
* PskKeyExchangeMode ke_modes<1..255>;
* } PskKeyExchangeModes;
*/
-SECStatus
-tls13_ClientSendPskModesXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- sslBuffer *buf, PRBool *added)
+PRInt32
+tls13_ClientSendPskKeyExchangeModesXtn(const sslSocket *ss,
+ TLSExtensionData *xtnData,
+ PRBool append, PRUint32 maxBytes)
{
static const PRUint8 ke_modes[] = { tls13_psk_dh_ke };
- SECStatus rv;
+ static const unsigned long ke_modes_len = sizeof(ke_modes);
+ PRInt32 extension_len;
if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3 ||
ss->opt.noCache) {
- return SECSuccess;
+ return 0;
}
+ extension_len =
+ 2 + 2 + /* Type + length */
+ 1 + ke_modes_len; /* key exchange modes vector */
+
SSL_TRC(3, ("%d: TLS13[%d]: send psk key exchange modes extension",
SSL_GETPID(), ss->fd));
- rv = sslBuffer_AppendVariable(buf, ke_modes, sizeof(ke_modes), 1);
- if (rv != SECSuccess) {
- return SECFailure;
+ if (maxBytes < (PRUint32)extension_len) {
+ PORT_Assert(0);
+ return 0;
}
- *added = PR_TRUE;
- return SECSuccess;
+ if (append) {
+ SECStatus rv = ssl3_ExtAppendHandshakeNumber(
+ ss, ssl_tls13_psk_key_exchange_modes_xtn, 2);
+ if (rv != SECSuccess)
+ return -1;
+
+ rv = ssl3_ExtAppendHandshakeNumber(ss, extension_len - 4, 2);
+ if (rv != SECSuccess)
+ return -1;
+
+ rv = ssl3_ExtAppendHandshakeVariable(
+ ss, ke_modes, ke_modes_len, 1);
+ if (rv != SECSuccess)
+ return -1;
+ }
+ return extension_len;
}
SECStatus
-tls13_ServerHandlePskModesXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- SECItem *data)
+tls13_ServerHandlePskKeyExchangeModesXtn(const sslSocket *ss,
+ TLSExtensionData *xtnData,
+ PRUint16 ex_type, SECItem *data)
{
SECStatus rv;
@@ -933,126 +1076,112 @@ tls13_ServerHandlePskModesXtn(const sslSocket *ss, TLSExtensionData *xtnData,
}
/* Keep track of negotiated extensions. */
- xtnData->negotiated[xtnData->numNegotiated++] =
- ssl_tls13_psk_key_exchange_modes_xtn;
+ xtnData->negotiated[xtnData->numNegotiated++] = ex_type;
return SECSuccess;
}
-SECStatus
-tls13_SendCertAuthoritiesXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- sslBuffer *buf, PRBool *added)
+PRInt32
+tls13_SendShortHeaderXtn(const sslSocket *ss,
+ TLSExtensionData *xtnData,
+ PRBool append, PRUint32 maxBytes)
{
- unsigned int calen;
- const SECItem *name;
- unsigned int nnames;
- SECStatus rv;
+ PRUint32 extension_len = 2 + 2; /* Type + length (0). */
- PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
-
- rv = ssl_GetCertificateRequestCAs(ss, &calen, &name, &nnames);
- if (rv != SECSuccess) {
- return SECFailure;
+ if (!ss->opt.enableShortHeaders) {
+ return 0;
}
- if (!calen) {
- return SECSuccess;
+ /* Presently this is incompatible with 0-RTT. We will fix if
+ * it becomes more than an experiment. */
+ if (ss->opt.enable0RttData) {
+ return 0;
}
- rv = sslBuffer_AppendNumber(buf, calen, 2);
- if (rv != SECSuccess) {
- return SECFailure;
+ if (IS_DTLS(ss)) {
+ return 0;
}
- while (nnames) {
- rv = sslBuffer_AppendVariable(buf, name->data, name->len, 2);
- if (rv != SECSuccess) {
- return SECFailure;
- }
- ++name;
- --nnames;
+ /* Don't send this if TLS 1.3 isn't at least possible. */
+ if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) {
+ /* This should only happen on the client. */
+ PORT_Assert(!ss->sec.isServer);
+ return 0;
}
- *added = PR_TRUE;
- return SECSuccess;
-}
-
-SECStatus
-tls13_ClientHandleCertAuthoritiesXtn(const sslSocket *ss,
- TLSExtensionData *xtnData,
- SECItem *data)
-{
- SECStatus rv;
- PLArenaPool *arena;
+ SSL_TRC(3, ("%d: TLS13[%d]: send short_header extension",
+ SSL_GETPID(), ss->fd));
- if (!data->len) {
- ssl3_ExtSendAlert(ss, alert_fatal, decode_error);
- PORT_SetError(SSL_ERROR_RX_MALFORMED_CERT_REQUEST);
- return SECFailure;
+ if (maxBytes < extension_len) {
+ PORT_Assert(0);
+ return 0;
}
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (!arena) {
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return SECFailure;
- }
+ if (append) {
+ SECStatus rv;
- xtnData->certReqAuthorities.arena = arena;
- rv = ssl3_ParseCertificateRequestCAs((sslSocket *)ss,
- &data->data, &data->len,
- &xtnData->certReqAuthorities);
- if (rv != SECSuccess) {
- goto loser;
- }
- if (data->len) {
- ssl3_ExtSendAlert(ss, alert_fatal, decode_error);
- PORT_SetError(SSL_ERROR_RX_MALFORMED_CERT_REQUEST);
- goto loser;
+ rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_short_header_xtn, 2);
+ if (rv != SECSuccess)
+ return -1;
+
+ rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2);
+ if (rv != SECSuccess)
+ return -1;
+
+ xtnData->advertised[xtnData->numAdvertised++] =
+ ssl_tls13_short_header_xtn;
}
- return SECSuccess;
-loser:
- PORT_FreeArena(arena, PR_FALSE);
- xtnData->certReqAuthorities.arena = NULL;
- return SECFailure;
+ return extension_len;
}
SECStatus
-tls13_ServerSendHrrKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- sslBuffer *buf, PRBool *added)
+tls13_HandleShortHeaderXtn(
+ const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
+ SECItem *data)
{
- SECStatus rv;
+ SSL_TRC(3, ("%d: TLS13[%d]: handle short_header extension",
+ SSL_GETPID(), ss->fd));
- PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
+ /* The client might have asked for this, but we didn't negotiate TLS 1.3. */
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ return SECSuccess;
+ }
- if (!xtnData->selectedGroup) {
+ /* Presently this is incompatible with 0-RTT. We will fix if
+ * it becomes more than an experiment. */
+ if (ss->opt.enable0RttData) {
return SECSuccess;
}
- rv = sslBuffer_AppendNumber(buf, xtnData->selectedGroup->name, 2);
- if (rv != SECSuccess) {
+ if (IS_DTLS(ss)) {
+ PORT_SetError(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION);
return SECFailure;
}
- *added = PR_TRUE;
- return SECSuccess;
-}
+ if (data->len) {
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
+ return SECFailure;
+ }
-SECStatus
-tls13_ServerSendHrrCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- sslBuffer *buf, PRBool *added)
-{
- SECStatus rv;
+ if (!ss->opt.enableShortHeaders) {
+ /* Ignore. */
+ return SECSuccess;
+ }
- PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
- PORT_Assert(xtnData->cookie.len > 0);
+ /* Keep track of negotiated extensions. */
+ xtnData->negotiated[xtnData->numNegotiated++] = ex_type;
- rv = sslBuffer_AppendVariable(buf,
- xtnData->cookie.data, xtnData->cookie.len, 2);
- if (rv != SECSuccess) {
- return SECFailure;
+ if (ss->sec.isServer) {
+ SECStatus rv;
+
+ rv = ssl3_RegisterExtensionSender(ss, xtnData,
+ ssl_tls13_short_header_xtn,
+ tls13_SendShortHeaderXtn);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
}
- *added = PR_TRUE;
return SECSuccess;
}