diff options
Diffstat (limited to 'lib/ssl/tls13exthandle.c')
-rw-r--r-- | lib/ssl/tls13exthandle.c | 192 |
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; |