Chromium Code Reviews| Index: net/third_party/nss/ssl/ssl3ext.c |
| =================================================================== |
| --- net/third_party/nss/ssl/ssl3ext.c (revision 88612) |
| +++ net/third_party/nss/ssl/ssl3ext.c (working copy) |
| @@ -247,6 +247,7 @@ |
| { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn }, |
| { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
| { ssl_next_proto_neg_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, |
| + { ssl_cached_info_xtn, &ssl3_ClientHandleCachedInfoXtn }, |
| { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, |
| { -1, NULL } |
| }; |
| @@ -272,6 +273,7 @@ |
| #endif |
| { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, |
| { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn }, |
| + { ssl_cached_info_xtn, &ssl3_ClientSendCachedInfoXtn }, |
| { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn } |
| /* any extra entries will appear as { 0, NULL } */ |
| }; |
| @@ -676,6 +678,153 @@ |
| return SECSuccess; |
| } |
| +/* ssl3_ClientSendCachedInfoXtn builds the cached_info extension on the |
| + * client side. */ |
| +PRInt32 |
| +ssl3_ClientSendCachedInfoXtn(sslSocket * ss, PRBool append, |
| + PRUint32 maxBytes) |
| +{ |
| + PRInt32 extension_length; |
| + PRBool send_empty; |
| + |
| + if (!ss->opt.enableCachedInfo) |
| + return 0; |
| + |
| + CERTCertificate ** predictedCertChain = ss->ssl3.predictedCertChain; |
| + //send_empty = (predictedCertChain == NULL || predictedCertChain[0] == NULL) |
| + // ? PR_TRUE : PR_FALSE; |
|
wtc
2011/06/17 22:57:09
Declare predictedCertChain at the beginning of the
rkn
2011/06/20 21:21:09
Done.
|
| + send_empty = (predictedCertChain == NULL) ? PR_TRUE : PR_FALSE; |
|
wtc
2011/06/17 22:57:09
This can be written simply as:
send_empty = (p
rkn
2011/06/20 21:21:09
Done.
|
| + |
| + /* minimum extension: |
| + * extension_type (2-bytes) + |
| + * length(extension_data) (2-bytes) + |
| + * length(cached_info) (2-bytes) + |
| + */ |
| + extension_length = send_empty ? 6 : 16; |
| + |
| + if (append && maxBytes >= extension_length) { |
| + SECStatus rv; |
| + |
| + /* ExtensionType */ |
| + rv = ssl3_AppendHandshakeNumber(ss, ssl_cached_info_xtn, 2); |
| + if (rv != SECSuccess) |
| + return -1; |
| + /* Extension Length */ |
| + rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); |
| + if (rv != SECSuccess) |
| + return -1; |
| + if (send_empty) { |
| + /* Cached Information Length */ |
| + rv = ssl3_AppendHandshakeNumber(ss, 0, 2); |
| + if (rv != SECSuccess) |
| + return -1; |
| + } else { |
| + /* Cached Information Length */ |
| + rv = ssl3_AppendHandshakeNumber(ss, 10, 2); |
| + if (rv != SECSuccess) |
| + return -1; |
| + /* Cached Information Type */ |
| + rv = ssl3_AppendHandshakeNumber(ss, 1 /* certificate_chain */, 1); |
| + if (rv != SECSuccess) |
| + return -1; |
| + /* hash length */ |
| + rv = ssl3_AppendHandshakeNumber(ss, 8, 1); |
| + if (rv != SECSuccess) |
| + return -1; |
| + /* hash */ |
| + PRUint64 certChainHash; |
| + FNV1A64_Init(&certChainHash); |
| + int i; |
| + for (i = 0; predictedCertChain[i] != NULL; i++) { |
| + unsigned int certLen = predictedCertChain[i]->derCert.len; |
| + unsigned char certLenArray[3] = |
| + {(certLen & 0xff0000) >> 16, (certLen & 0xff00) >> 8, |
| + certLen & 0xff}; |
|
wtc
2011/06/17 22:57:09
Nit: format this as:
unsigned char certLenArra
rkn
2011/06/20 21:21:09
Done.
|
| + FNV1A64_Update(&certChainHash, certLenArray, 3); |
| + FNV1A64_Update(&certChainHash, |
| + predictedCertChain[i]->derCert.data, certLen); |
| + } |
| + FNV1A64_Final(&certChainHash); |
| + rv = ssl3_AppendHandshake(ss, &certChainHash, 8); |
| + if (rv != SECSuccess) |
| + return -1; |
| + PRUint8* digestPtr = (PRUint8*) &certChainHash; |
| + for (i = 0; i < 8; i++) { |
| + ss->ssl3.certChainDigest[i] = digestPtr[i]; |
| + } |
| + } |
| + |
| + } else if (maxBytes < extension_length) { |
| + PORT_Assert(0); |
| + return 0; |
| + } |
| + ss->xtnData.advertised[ss->xtnData.numAdvertised++] = |
| + ssl_cached_info_xtn; |
| + return extension_length; |
| +} |
| + |
| +SECStatus |
| +ssl3_ClientHandleCachedInfoXtn(sslSocket *ss, PRUint16 ex_type, |
| + SECItem *data) |
| +{ |
| + /* If we didn't request this extension, then the server may not echo it. */ |
| + if (!ss->opt.enableCachedInfo) |
| + return SECFailure; |
| + |
| + if (data->len == 0) { |
| + /* The server supports information caching, but provides no information |
| + * about what information types it supports */ |
| + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; |
| + return SECSuccess; |
| + } |
| + |
| + if (data->len < 2) |
| + return SECFailure; |
| + unsigned char * cached_info = data->data; |
| + unsigned int remaining_cached_info_length = |
| + (cached_info[0] << 8) | cached_info[1]; |
| + if (remaining_cached_info_length != data->len - 2) |
| + return SECFailure; |
| + cached_info += 2; |
| + PRBool has_correct_cert_chain = PR_FALSE; |
| + while (remaining_cached_info_length >= 2) { |
| + /* The server supports only those CachedInformationType types that are |
| + * identified by a present CachedObject */ |
| + unsigned char cached_object_type; |
| + unsigned int cached_object_length; |
| + unsigned char cached_object_digest[8]; |
| + cached_object_type = *cached_info++; |
| + cached_object_length = *cached_info++; |
| + remaining_cached_info_length -= 2; |
| + if (remaining_cached_info_length < cached_object_length) |
| + return SECFailure; |
| + if (cached_object_length != 0 && cached_object_length != 8) |
| + return SECFailure; |
| + remaining_cached_info_length -= cached_object_length; |
| + if (cached_object_type == cached_info_certificate_chain) { |
| + if (cached_object_length == 0) |
| + has_correct_cert_chain = PR_TRUE; |
| + else { /* Hashes must match */ |
| + int i; |
| + for (i = 0; i < 8; i++) |
| + cached_object_digest[i] = *cached_info++; |
| + if (!memcmp(cached_object_digest, ss->ssl3.certChainDigest, 8)) |
| + has_correct_cert_chain = PR_TRUE; |
| + } |
| + } |
| + } |
| + |
| + if (remaining_cached_info_length != 0) |
| + return SECFailure; |
| + |
| + if (has_correct_cert_chain) { |
| + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; |
| + return SECSuccess; |
| + } |
| + |
| + return SECFailure; |
| +} |
| + |
| /* ssl3_ClientSendStatusRequestXtn builds the status_request extension on the |
| * client side. See RFC 4366 section 3.6. */ |
| PRInt32 |