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, 342 insertions, 471 deletions
diff --git a/security/nss/lib/ssl/tls13exthandle.c b/security/nss/lib/ssl/tls13exthandle.c
index c2ce390ff..899f23827 100644
--- a/security/nss/lib/ssl/tls13exthandle.c
+++ b/security/nss/lib/ssl/tls13exthandle.c
@@ -14,50 +14,35 @@
#include "ssl3exthandle.h"
#include "tls13exthandle.h"
-PRInt32
-tls13_ServerSendStatusRequestXtn(
- const sslSocket *ss,
- TLSExtensionData *xtnData,
- PRBool append,
- PRUint32 maxBytes)
+SECStatus
+tls13_ServerSendStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+ sslBuffer *buf, PRBool *added)
{
- PRInt32 extension_length;
const sslServerCert *serverCert = ss->sec.serverCert;
const SECItem *item;
SECStatus rv;
if (!serverCert->certStatusArray ||
!serverCert->certStatusArray->len) {
- return 0;
+ return SECSuccess;
}
item = &serverCert->certStatusArray->items[0];
/* Only send the first entry. */
- extension_length = 2 + 2 + 1 /* status_type */ + 3 + item->len;
- if (maxBytes < (PRUint32)extension_length) {
- return 0;
+ /* status_type == ocsp */
+ rv = sslBuffer_AppendNumber(buf, 1 /*ocsp*/, 1);
+ 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. */
+ /* opaque OCSPResponse<1..2^24-1> */
+ rv = sslBuffer_AppendVariable(buf, item->data, item->len, 3);
+ if (rv != SECSuccess) {
+ return SECFailure;
}
- return extension_length;
+ *added = PR_TRUE;
+ return SECSuccess;
}
/*
@@ -101,41 +86,27 @@ 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(const sslSocket *ss, const sslEphemeralKeyPair *keyPair)
+tls13_EncodeKeyShareEntry(sslBuffer *buf, const sslEphemeralKeyPair *keyPair)
{
SECStatus rv;
SECKEYPublicKey *pubKey = keyPair->keys->pubKey;
unsigned int size = tls13_SizeOfKeyShareEntry(pubKey);
- rv = ssl3_ExtAppendHandshakeNumber(ss, keyPair->group->name, 2);
+ rv = sslBuffer_AppendNumber(buf, keyPair->group->name, 2);
if (rv != SECSuccess)
return rv;
- rv = ssl3_ExtAppendHandshakeNumber(ss, size - 4, 2);
+ rv = sslBuffer_AppendNumber(buf, size - 4, 2);
if (rv != SECSuccess)
return rv;
switch (pubKey->keyType) {
case ecKey:
- rv = tls13_EncodeECDHEKeyShareKEX(ss, pubKey);
+ rv = sslBuffer_Append(buf, pubKey->u.ec.publicValue.data,
+ pubKey->u.ec.publicValue.len);
break;
case dhKey:
- rv = ssl_AppendPaddedDHKeyShare(ss, pubKey, PR_FALSE);
+ rv = ssl_AppendPaddedDHKeyShare(buf, pubKey, PR_FALSE);
break;
default:
PORT_Assert(0);
@@ -146,14 +117,16 @@ tls13_EncodeKeyShareEntry(const sslSocket *ss, const sslEphemeralKeyPair *keyPai
return rv;
}
-PRInt32
-tls13_ClientSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append,
- PRUint32 maxBytes)
+SECStatus
+tls13_ClientSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+ sslBuffer *buf, PRBool *added)
{
- PRUint32 extension_length;
+ SECStatus rv;
+ PRCList *cursor;
+ unsigned int lengthOffset;
if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) {
- return 0;
+ return SECSuccess;
}
/* Optimistically try to send an ECDHE key using the
@@ -161,47 +134,28 @@ tls13_ClientSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBo
SSL_TRC(3, ("%d: TLS13[%d]: send client key share xtn",
SSL_GETPID(), ss->fd));
- extension_length = tls13_SizeOfClientKeyShareExtension(ss);
- if (maxBytes < extension_length) {
- PORT_Assert(0);
- return 0;
+ /* Save the offset to the length. */
+ rv = sslBuffer_Skip(buf, 2, &lengthOffset);
+ 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;
+ 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;
}
-
- xtnData->advertised[xtnData->numAdvertised++] =
- ssl_tls13_key_share_xtn;
+ }
+ rv = sslBuffer_InsertLength(buf, lengthOffset, 2);
+ if (rv != SECSuccess) {
+ return SECFailure;
}
- return extension_length;
-
-loser:
- return -1;
+ *added = PR_TRUE;
+ return SECSuccess;
}
static SECStatus
@@ -250,7 +204,8 @@ loser:
* |xtnData->remoteKeyShares| for future use. The key
* share is processed in tls13_HandleServerKeyShare(). */
SECStatus
-tls13_ClientHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data)
+tls13_ClientHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+ SECItem *data)
{
SECStatus rv;
PORT_Assert(PR_CLIST_IS_EMPTY(&xtnData->remoteKeyShares));
@@ -281,7 +236,8 @@ tls13_ClientHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PR
}
SECStatus
-tls13_ClientHandleKeyShareXtnHrr(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data)
+tls13_ClientHandleKeyShareXtnHrr(const sslSocket *ss, TLSExtensionData *xtnData,
+ SECItem *data)
{
SECStatus rv;
PRUint32 tmp;
@@ -331,7 +287,8 @@ 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, PRUint16 ex_type, SECItem *data)
+tls13_ServerHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+ SECItem *data)
{
SECStatus rv;
PRUint32 length;
@@ -364,16 +321,6 @@ tls13_ServerHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PR
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:
@@ -381,12 +328,10 @@ loser:
return SECFailure;
}
-PRInt32
-tls13_ServerSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append,
- PRUint32 maxBytes)
+SECStatus
+tls13_ServerSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+ sslBuffer *buf, PRBool *added)
{
- PRUint32 extension_length;
- PRUint32 entry_length;
SECStatus rv;
sslEphemeralKeyPair *keyPair;
@@ -397,31 +342,13 @@ tls13_ServerSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBo
keyPair = (sslEphemeralKeyPair *)PR_NEXT_LINK(&ss->ephemeralKeyPairs);
- 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;
- }
-
- 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;
+ rv = tls13_EncodeKeyShareEntry(buf, keyPair);
+ if (rv != SECSuccess) {
+ return SECFailure;
}
- return extension_length;
-
-loser:
- return -1;
+ *added = PR_TRUE;
+ return SECSuccess;
}
/* Called by clients.
@@ -448,113 +375,83 @@ loser:
* 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.
*/
-PRInt32
+SECStatus
tls13_ClientSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- PRBool append,
- PRUint32 maxBytes)
+ sslBuffer *buf, PRBool *added)
{
- 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 0;
+ 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;
PORT_Assert(ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3);
- /* The length computations are simplified by the fact that there
- * is just one ticket at most. */
+ /* Send a single ticket identity. */
session_ticket = &ss->sec.ci.sid->u.ssl3.locked.sessionTicket;
- 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;
+ 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;
- /* 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;
+ /* 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;
- /* 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;
+ /* 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;
- 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;
- xtnData->advertised[xtnData->numAdvertised++] =
- ssl_tls13_pre_shared_key_xtn;
- }
- return extension_length;
+ xtnData->sentSessionTicketInClientHello = PR_TRUE;
+ *added = PR_TRUE;
+ return SECSuccess;
loser:
xtnData->ticketTimestampVerified = PR_FALSE;
- return -1;
+ return SECFailure;
}
/* Handle a TLS 1.3 PreSharedKey Extension. We only accept PSKs
* that contain session tickets. */
SECStatus
-tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
+tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData,
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));
@@ -564,16 +461,26 @@ 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 utmp;
+ PRUint32 obfuscatedAge;
rv = ssl3_ExtConsumeHandshakeVariable(ss, &label, 2,
&inner.data, &inner.len);
@@ -583,9 +490,8 @@ tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData
goto alert_loser;
}
- /* Read and discard session ticket age. Bug 1295163 */
- rv = ssl3_ExtConsumeHandshake(ss, &utmp, 4,
- &inner.data, &inner.len);
+ rv = ssl3_ExtConsumeHandshakeNumber(ss, &obfuscatedAge, 4,
+ &inner.data, &inner.len);
if (rv != SECSuccess)
return rv;
@@ -593,17 +499,29 @@ 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);
+ CONST_CAST(sslSocket, ss), &label, appToken);
/* 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->pskBinderPrefixLen = ss->ssl3.hs.messages.len - data->len;
+ xtnData->pskBindersLen = data->len;
/* Parse the binders list. */
rv = ssl3_ExtConsumeHandshakeVariable(ss,
@@ -635,7 +553,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++] = ex_type;
+ xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_pre_shared_key_xtn;
return SECSuccess;
@@ -645,43 +563,27 @@ alert_loser:
return SECFailure;
}
-PRInt32
+SECStatus
tls13_ServerSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- PRBool append,
- PRUint32 maxBytes)
+ sslBuffer *buf, PRBool *added)
{
- PRInt32 extension_length =
- 2 + 2 + 2; /* type + len + index */
SECStatus rv;
- if (maxBytes < (PRUint32)extension_length) {
- PORT_Assert(0);
- return 0;
- }
-
- 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;
+ /* 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;
}
- return extension_length;
+ *added = PR_TRUE;
+ return SECSuccess;
}
/* Handle a TLS 1.3 PreSharedKey Extension. We only accept PSKs
* that contain session tickets. */
SECStatus
-tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
+tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData,
SECItem *data)
{
PRUint32 index;
@@ -713,7 +615,7 @@ tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData
}
/* Keep track of negotiated extensions. */
- xtnData->negotiated[xtnData->numNegotiated++] = ex_type;
+ xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_pre_shared_key_xtn;
return SECSuccess;
}
@@ -721,43 +623,20 @@ tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData
/*
* struct { } EarlyDataIndication;
*/
-PRInt32
+SECStatus
tls13_ClientSendEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- PRBool append,
- PRUint32 maxBytes)
+ sslBuffer *buf, PRBool *added)
{
- 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;
- }
-
- 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;
+ if (!tls13_ClientAllow0Rtt(ss, ss->sec.ci.sid)) {
+ return SECSuccess;
}
- return extension_length;
+ *added = PR_TRUE;
+ return SECSuccess;
}
SECStatus
-tls13_ServerHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
+tls13_ServerHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData,
SECItem *data)
{
SSL_TRC(3, ("%d: TLS13[%d]: handle early_data extension",
@@ -779,44 +658,14 @@ tls13_ServerHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, P
return SECFailure;
}
- xtnData->negotiated[xtnData->numNegotiated++] = ex_type;
+ xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_early_data_xtn;
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, PRUint16 ex_type,
+tls13_ClientHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData,
SECItem *data)
{
SSL_TRC(3, ("%d: TLS13[%d]: handle early_data extension",
@@ -834,19 +683,19 @@ tls13_ClientHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, P
}
/* Keep track of negotiated extensions. */
- xtnData->negotiated[xtnData->numNegotiated++] = ex_type;
+ xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_early_data_xtn;
return SECSuccess;
}
SECStatus
-tls13_ClientHandleTicketEarlyDataInfoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
- SECItem *data)
+tls13_ClientHandleTicketEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+ SECItem *data)
{
PRUint32 utmp;
SECStatus rv;
- SSL_TRC(3, ("%d: TLS13[%d]: handle early_data_info extension",
+ SSL_TRC(3, ("%d: TLS13[%d]: handle ticket early_data extension",
SSL_GETPID(), ss->fd));
/* The server must not send this extension when negotiating < TLS 1.3. */
@@ -873,59 +722,71 @@ tls13_ClientHandleTicketEarlyDataInfoXtn(const sslSocket *ss, TLSExtensionData *
/*
* struct {
+ * select (Handshake.msg_type) {
+ * case client_hello:
* ProtocolVersion versions<2..254>;
+ * case server_hello:
+ * ProtocolVersion version;
+ * };
* } SupportedVersions;
*/
-PRInt32
-tls13_ClientSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append,
- PRUint32 maxBytes)
+SECStatus
+tls13_ClientSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+ sslBuffer *buf, PRBool *added)
{
- PRInt32 extensions_len;
PRUint16 version;
+ unsigned int lengthOffset;
SECStatus rv;
if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) {
- return 0;
+ return SECSuccess;
}
- SSL_TRC(3, ("%d: TLS13[%d]: send supported_versions extension",
+ SSL_TRC(3, ("%d: TLS13[%d]: client send supported_versions extension",
SSL_GETPID(), ss->fd));
- /* 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);
+ rv = sslBuffer_Skip(buf, 1, &lengthOffset);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
- if (maxBytes < (PRUint32)extensions_len) {
- PORT_Assert(0);
- return 0;
+ for (version = ss->vrange.max; version >= ss->vrange.min; --version) {
+ rv = sslBuffer_AppendNumber(buf, tls13_EncodeDraftVersion(version), 2);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
}
- if (append) {
- rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_supported_versions_xtn, 2);
- if (rv != SECSuccess)
- return -1;
+ rv = sslBuffer_InsertLength(buf, lengthOffset, 1);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
- rv = ssl3_ExtAppendHandshakeNumber(ss, extensions_len - 4, 2);
- if (rv != SECSuccess)
- return -1;
+ *added = PR_TRUE;
+ return SECSuccess;
+}
- rv = ssl3_ExtAppendHandshakeNumber(ss, extensions_len - 5, 1);
- if (rv != SECSuccess)
- return -1;
+SECStatus
+tls13_ServerSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+ sslBuffer *buf, PRBool *added)
+{
+ SECStatus rv;
- for (version = ss->vrange.max; version >= ss->vrange.min; --version) {
- rv = ssl3_ExtAppendHandshakeNumber(
- ss, tls13_EncodeDraftVersion(version), 2);
- if (rv != SECSuccess)
- return -1;
- }
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ return SECSuccess;
+ }
+
+ SSL_TRC(3, ("%d: TLS13[%d]: server send supported_versions extension",
+ SSL_GETPID(), ss->fd));
- xtnData->advertised[xtnData->numAdvertised++] =
- ssl_tls13_supported_versions_xtn;
+ rv = sslBuffer_AppendNumber(
+ buf, tls13_EncodeDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3), 2);
+ if (rv != SECSuccess) {
+ return SECFailure;
}
- return extensions_len;
+ *added = PR_TRUE;
+ return SECSuccess;
}
/*
@@ -934,7 +795,8 @@ tls13_ClientSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnD
* } Cookie;
*/
SECStatus
-tls13_ClientHandleHrrCookie(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data)
+tls13_ClientHandleHrrCookie(const sslSocket *ss, TLSExtensionData *xtnData,
+ SECItem *data)
{
SECStatus rv;
@@ -960,41 +822,57 @@ tls13_ClientHandleHrrCookie(const sslSocket *ss, TLSExtensionData *xtnData, PRUi
return SECSuccess;
}
-PRInt32
-tls13_ClientSendHrrCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes)
+SECStatus
+tls13_ClientSendHrrCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+ sslBuffer *buf, PRBool *added)
{
- PRInt32 extension_len;
+ SECStatus rv;
if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3 ||
!ss->ssl3.hs.cookie.len) {
- return 0;
+ return SECSuccess;
}
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;
+ }
- /* Extension type, length, cookie length, cookie value. */
- extension_len = 2 + 2 + 2 + ss->ssl3.hs.cookie.len;
+ *added = PR_TRUE;
+ return SECSuccess;
+}
- if (maxBytes < (PRUint32)extension_len) {
- PORT_Assert(0);
- return 0;
- }
+SECStatus
+tls13_ServerHandleCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+ SECItem *data)
+{
+ SECStatus rv;
- if (append) {
- SECStatus rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_cookie_xtn, 2);
- if (rv != SECSuccess)
- return -1;
+ SSL_TRC(3, ("%d: TLS13[%d]: handle cookie extension",
+ SSL_GETPID(), ss->fd));
- rv = ssl3_ExtAppendHandshakeNumber(ss, extension_len - 4, 2);
- if (rv != SECSuccess)
- return -1;
+ rv = ssl3_ExtConsumeHandshakeVariable(ss, &xtnData->cookie, 2,
+ &data->data, &data->len);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
- rv = ssl3_ExtAppendHandshakeVariable(ss, ss->ssl3.hs.cookie.data,
- ss->ssl3.hs.cookie.len, 2);
- if (rv != SECSuccess)
- return -1;
+ if (xtnData->cookie.len == 0) {
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
+ return SECFailure;
}
- return extension_len;
+
+ 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;
}
/*
@@ -1004,54 +882,33 @@ tls13_ClientSendHrrCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRB
* PskKeyExchangeMode ke_modes<1..255>;
* } PskKeyExchangeModes;
*/
-PRInt32
-tls13_ClientSendPskKeyExchangeModesXtn(const sslSocket *ss,
- TLSExtensionData *xtnData,
- PRBool append, PRUint32 maxBytes)
+SECStatus
+tls13_ClientSendPskModesXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+ sslBuffer *buf, PRBool *added)
{
static const PRUint8 ke_modes[] = { tls13_psk_dh_ke };
- static const unsigned long ke_modes_len = sizeof(ke_modes);
- PRInt32 extension_len;
+ SECStatus rv;
if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3 ||
ss->opt.noCache) {
- return 0;
+ return SECSuccess;
}
- 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));
- if (maxBytes < (PRUint32)extension_len) {
- PORT_Assert(0);
- return 0;
+ rv = sslBuffer_AppendVariable(buf, ke_modes, sizeof(ke_modes), 1);
+ if (rv != SECSuccess) {
+ return SECFailure;
}
- 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;
+ *added = PR_TRUE;
+ return SECSuccess;
}
SECStatus
-tls13_ServerHandlePskKeyExchangeModesXtn(const sslSocket *ss,
- TLSExtensionData *xtnData,
- PRUint16 ex_type, SECItem *data)
+tls13_ServerHandlePskModesXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+ SECItem *data)
{
SECStatus rv;
@@ -1076,112 +933,126 @@ tls13_ServerHandlePskKeyExchangeModesXtn(const sslSocket *ss,
}
/* Keep track of negotiated extensions. */
- xtnData->negotiated[xtnData->numNegotiated++] = ex_type;
+ xtnData->negotiated[xtnData->numNegotiated++] =
+ ssl_tls13_psk_key_exchange_modes_xtn;
return SECSuccess;
}
-PRInt32
-tls13_SendShortHeaderXtn(const sslSocket *ss,
- TLSExtensionData *xtnData,
- PRBool append, PRUint32 maxBytes)
+SECStatus
+tls13_SendCertAuthoritiesXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+ sslBuffer *buf, PRBool *added)
{
- PRUint32 extension_len = 2 + 2; /* Type + length (0). */
+ unsigned int calen;
+ const SECItem *name;
+ unsigned int nnames;
+ SECStatus rv;
- if (!ss->opt.enableShortHeaders) {
- return 0;
- }
+ PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
- /* Presently this is incompatible with 0-RTT. We will fix if
- * it becomes more than an experiment. */
- if (ss->opt.enable0RttData) {
- return 0;
+ rv = ssl_GetCertificateRequestCAs(ss, &calen, &name, &nnames);
+ if (rv != SECSuccess) {
+ return SECFailure;
}
- if (IS_DTLS(ss)) {
- return 0;
+ if (!calen) {
+ return SECSuccess;
}
- /* 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;
+ rv = sslBuffer_AppendNumber(buf, calen, 2);
+ if (rv != SECSuccess) {
+ return SECFailure;
}
- SSL_TRC(3, ("%d: TLS13[%d]: send short_header extension",
- SSL_GETPID(), ss->fd));
-
- if (maxBytes < extension_len) {
- PORT_Assert(0);
- return 0;
+ while (nnames) {
+ rv = sslBuffer_AppendVariable(buf, name->data, name->len, 2);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ ++name;
+ --nnames;
}
- if (append) {
- SECStatus rv;
+ *added = PR_TRUE;
+ return SECSuccess;
+}
- rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_short_header_xtn, 2);
- if (rv != SECSuccess)
- return -1;
+SECStatus
+tls13_ClientHandleCertAuthoritiesXtn(const sslSocket *ss,
+ TLSExtensionData *xtnData,
+ SECItem *data)
+{
+ SECStatus rv;
+ PLArenaPool *arena;
- rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2);
- if (rv != SECSuccess)
- return -1;
+ if (!data->len) {
+ ssl3_ExtSendAlert(ss, alert_fatal, decode_error);
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_CERT_REQUEST);
+ return SECFailure;
+ }
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
- xtnData->advertised[xtnData->numAdvertised++] =
- ssl_tls13_short_header_xtn;
+ 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;
+ }
+ return SECSuccess;
- return extension_len;
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ xtnData->certReqAuthorities.arena = NULL;
+ return SECFailure;
}
SECStatus
-tls13_HandleShortHeaderXtn(
- const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
- SECItem *data)
+tls13_ServerSendHrrKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+ sslBuffer *buf, PRBool *added)
{
- SSL_TRC(3, ("%d: TLS13[%d]: handle short_header extension",
- SSL_GETPID(), ss->fd));
+ SECStatus rv;
- /* 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;
- }
+ PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
- /* Presently this is incompatible with 0-RTT. We will fix if
- * it becomes more than an experiment. */
- if (ss->opt.enable0RttData) {
+ if (!xtnData->selectedGroup) {
return SECSuccess;
}
- if (IS_DTLS(ss)) {
- PORT_SetError(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION);
- return SECFailure;
- }
-
- if (data->len) {
- PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
+ rv = sslBuffer_AppendNumber(buf, xtnData->selectedGroup->name, 2);
+ if (rv != SECSuccess) {
return SECFailure;
}
- if (!ss->opt.enableShortHeaders) {
- /* Ignore. */
- return SECSuccess;
- }
+ *added = PR_TRUE;
+ return SECSuccess;
+}
- /* Keep track of negotiated extensions. */
- xtnData->negotiated[xtnData->numNegotiated++] = ex_type;
+SECStatus
+tls13_ServerSendHrrCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData,
+ sslBuffer *buf, PRBool *added)
+{
+ SECStatus rv;
- if (ss->sec.isServer) {
- SECStatus rv;
+ PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
+ PORT_Assert(xtnData->cookie.len > 0);
- rv = ssl3_RegisterExtensionSender(ss, xtnData,
- ssl_tls13_short_header_xtn,
- tls13_SendShortHeaderXtn);
- if (rv != SECSuccess) {
- return SECFailure;
- }
+ rv = sslBuffer_AppendVariable(buf,
+ xtnData->cookie.data, xtnData->cookie.len, 2);
+ if (rv != SECSuccess) {
+ return SECFailure;
}
+ *added = PR_TRUE;
return SECSuccess;
}