summaryrefslogtreecommitdiff
path: root/lib/ssl/tls13exthandle.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl/tls13exthandle.c')
-rw-r--r--lib/ssl/tls13exthandle.c192
1 files changed, 122 insertions, 70 deletions
diff --git a/lib/ssl/tls13exthandle.c b/lib/ssl/tls13exthandle.c
index bf766a429..37e009a4e 100644
--- a/lib/ssl/tls13exthandle.c
+++ b/lib/ssl/tls13exthandle.c
@@ -427,23 +427,27 @@ loser:
/* Called by clients.
*
- * struct {
- * PskKeyExchangeMode ke_modes<1..255>;
- * PskAuthMode auth_modes<1..255>;
- * opaque identity<0..2^16-1>;
- * } PskIdentity;
+ * struct {
+ * opaque identity<0..2^16-1>;
+ * uint32 obfuscated_ticket_age;
+ * } PskIdentity;
*
- * struct {
- * select (Role) {
- * case client:
- * PskIdentity identities<2..2^16-1>;
- * case server:
- * uint16 selected_identity;
- * }
- * } PreSharedKeyExtension;
+ * opaque PskBinderEntry<32..255>;
*
+ * struct {
+ * select (Handshake.msg_type) {
+ * case client_hello:
+ * PskIdentity identities<6..2^16-1>;
+ * PskBinderEntry binders<33..2^16-1>;
+ *
+ * case server_hello:
+ * uint16 selected_identity;
+ * };
+ *
+ * } PreSharedKeyExtension;
+
* Presently the only way to get a PSK is by resumption, so this is
- * really a ticket label and there wll be at most one.
+ * really a ticket label and there will be at most one.
*/
PRInt32
tls13_ClientSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData,
@@ -451,6 +455,8 @@ tls13_ClientSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData,
PRUint32 maxBytes)
{
PRInt32 extension_length;
+ PRInt32 identities_length;
+ PRInt32 binders_length;
NewSessionTicket *session_ticket;
/* We only set statelessResume on the client in TLS 1.3 code. */
@@ -459,11 +465,20 @@ tls13_ClientSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData,
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. */
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 + 2 + /* Type + length + vector length */
- 2 + session_ticket->ticket.len; /* identity length + ticket len */
+ 2 + 2 + /* Type + length */
+ identities_length + binders_length;
if (maxBytes < (PRUint32)extension_length) {
PORT_Assert(0);
@@ -472,6 +487,11 @@ tls13_ClientSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData,
if (append) {
SECStatus rv;
+ PRUint32 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)
@@ -479,11 +499,37 @@ tls13_ClientSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData,
rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2);
if (rv != SECSuccess)
goto loser;
- rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 6, 2);
+ 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);
+ session_ticket->ticket.len, 2);
+ if (rv != SECSuccess)
+ goto loser;
+
+ /* Obfuscated age. */
+ age = ssl_Time() - session_ticket->received_timestamp;
+ age += session_ticket->ticket_age_add;
+ rv = ssl3_ExtAppendHandshakeNumber(ss, 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;
+
PRINT_BUF(50, (ss, "Sending PreSharedKey value",
session_ticket->ticket.data,
session_ticket->ticket.len));
@@ -507,9 +553,10 @@ SECStatus
tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
SECItem *data)
{
- PRInt32 len;
- PRBool first = PR_TRUE;
+ SECItem inner;
SECStatus rv;
+ unsigned int numIdentities = 0;
+ unsigned int numBinders = 0;
SSL_TRC(3, ("%d: SSL3[%d]: handle pre_shared_key extension",
SSL_GETPID(), ss->fd));
@@ -519,41 +566,75 @@ tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData
return SECSuccess;
}
- len = ssl3_ExtConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
- if (len < 0)
- return SECFailure;
-
- if (len != data->len) {
- PORT_SetError(SSL_ERROR_MALFORMED_PRE_SHARED_KEY);
+ /* Parse the identities list. */
+ rv = ssl3_ExtConsumeHandshakeVariable(ss,
+ &inner, 2, &data->data, &data->len);
+ if (rv != SECSuccess) {
return SECFailure;
}
- while (data->len) {
+ while (inner.len) {
SECItem label;
+ PRUint32 utmp;
rv = ssl3_ExtConsumeHandshakeVariable(ss, &label, 2,
- &data->data, &data->len);
+ &inner.data, &inner.len);
if (rv != SECSuccess)
return rv;
if (!label.len) {
goto alert_loser;
}
- if (first) {
- first = PR_FALSE; /* Continue to read through the extension to check
- * the format. */
+ /* Read and discard session ticket age. Bug 1295163 */
+ rv = ssl3_ExtConsumeHandshake(ss, &utmp, 4,
+ &inner.data, &inner.len);
+ if (rv != SECSuccess)
+ return rv;
+
+ if (!numIdentities) {
PRINT_BUF(50, (ss, "Handling PreSharedKey value",
label.data, label.len));
- rv = ssl3_ProcessSessionTicketCommon(CONST_CAST(sslSocket, ss),
- &label);
+ rv = ssl3_ProcessSessionTicketCommon(
+ 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 rv;
+ return SECFailure;
}
+ ++numIdentities;
}
+ xtnData->pskBinderPrefixLen = ss->ssl3.hs.messages.len - data->len;
+
+ /* Parse the binders list. */
+ rv = ssl3_ExtConsumeHandshakeVariable(ss,
+ &inner, 2, &data->data, &data->len);
+ if (rv != SECSuccess)
+ return SECFailure;
+ if (data->len) {
+ goto alert_loser;
+ }
+
+ while (inner.len) {
+ SECItem binder;
+ rv = ssl3_ExtConsumeHandshakeVariable(ss, &binder, 1,
+ &inner.data, &inner.len);
+ if (rv != SECSuccess)
+ return rv;
+ if (binder.len < 32) {
+ goto alert_loser;
+ }
+
+ if (!numBinders) {
+ xtnData->pskBinder = binder;
+ }
+ ++numBinders;
+ }
+
+ if (numBinders != numIdentities)
+ goto alert_loser;
+
/* Keep track of negotiated extensions. Note that this does not
* mean we are resuming. */
xtnData->negotiated[xtnData->numNegotiated++] = ex_type;
@@ -637,54 +718,35 @@ tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData
return SECSuccess;
}
+
/*
- * struct {
- * select (Role) {
- * case client:
- * uint32 obfuscated_ticket_age;
- *
- * case server:
- * struct {};
- * }
- * } EarlyDataIndication;
+ * struct { } EarlyDataIndication;
*/
PRInt32
tls13_ClientSendEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData,
PRBool append,
PRUint32 maxBytes)
{
- PRInt32 extension_length;
SECStatus rv;
- NewSessionTicket *session_ticket;
+ PRInt32 extension_length;
if (!tls13_ClientAllow0Rtt(ss, ss->sec.ci.sid))
return 0;
- /* type + length + obfuscated ticket age. */
- extension_length = 2 + 2 + 4;
+ /* type + length */
+ extension_length = 2 + 2;
if (maxBytes < (PRUint32)extension_length) {
PORT_Assert(0);
return 0;
}
- session_ticket = &ss->sec.ci.sid->u.ssl3.locked.sessionTicket;
if (append) {
- PRUint32 age;
-
rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_early_data_xtn, 2);
if (rv != SECSuccess)
return -1;
- rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2);
- if (rv != SECSuccess)
- return -1;
-
- /* Obfuscated age. */
- age = ssl_Time() - session_ticket->received_timestamp;
- age += session_ticket->ticket_age_add;
-
- rv = ssl3_ExtAppendHandshakeNumber(ss, age, 4);
+ rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2);
if (rv != SECSuccess)
return -1;
}
@@ -699,9 +761,6 @@ SECStatus
tls13_ServerHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
SECItem *data)
{
- PRUint32 obfuscated_ticket_age;
- SECStatus rv;
-
SSL_TRC(3, ("%d: TLS13[%d]: handle early_data extension",
SSL_GETPID(), ss->fd));
@@ -710,13 +769,6 @@ tls13_ServerHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, P
return SECSuccess;
}
- /* Obfuscated ticket age. Ignore. Bug 1295163. */
- rv = ssl3_ExtConsumeHandshake(ss, &obfuscated_ticket_age, 4,
- &data->data, &data->len);
- if (rv != SECSuccess) {
- return SECFailure;
- }
-
if (data->len) {
PORT_SetError(SSL_ERROR_MALFORMED_EARLY_DATA);
return SECFailure;