Chromium Code Reviews| Index: net/third_party/nss/ssl/ssl3ext.c |
| =================================================================== |
| --- net/third_party/nss/ssl/ssl3ext.c (revision 130750) |
| +++ net/third_party/nss/ssl/ssl3ext.c (working copy) |
| @@ -90,6 +90,10 @@ |
| PRUint16 ex_type, SECItem *data); |
| static PRInt32 ssl3_SendEncryptedClientCertsXtn(sslSocket *ss, |
| PRBool append, PRUint32 maxBytes); |
| +static PRInt32 ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append, |
| + PRUint32 maxBytes); |
| +static SECStatus ssl3_HandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type, |
| + SECItem *data); |
| /* |
| * Write bytes. Using this function means the SECItem structure |
| @@ -250,6 +254,7 @@ |
| { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
| { ssl_next_proto_nego_xtn, &ssl3_ServerHandleNextProtoNegoXtn }, |
| { ssl_ob_cert_xtn, &ssl3_ServerHandleOBCertXtn }, |
| + { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn }, |
| { -1, NULL } |
| }; |
| @@ -264,6 +269,7 @@ |
| { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, |
| { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, |
| { ssl_ob_cert_xtn, &ssl3_ClientHandleOBCertXtn }, |
| + { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn}, |
| { -1, NULL } |
| }; |
| @@ -290,7 +296,8 @@ |
| { ssl_encrypted_client_certs, &ssl3_SendEncryptedClientCertsXtn }, |
| { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn }, |
| { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, |
| - { ssl_ob_cert_xtn, &ssl3_SendOBCertXtn } |
| + { ssl_ob_cert_xtn, &ssl3_SendOBCertXtn }, |
| + { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn } |
| /* any extra entries will appear as { 0, NULL } */ |
| }; |
| @@ -1868,3 +1875,189 @@ |
| return SECSuccess; |
| } |
| + |
| +static PRInt32 |
| +ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) |
| +{ |
| + PRUint32 ext_data_len; |
| + PRInt16 i; |
| + SECStatus rv; |
| + |
| + if (!ss) |
| + return 0; |
| + |
| + if (!ss->sec.isServer) { |
| + /* Client side */ |
| + |
| + if (!IS_DTLS(ss) || !ss->ssl3.dtlsSRTPCipherCount) |
| + return 0; /* Not relevant */ |
| + |
| + ext_data_len = 2 + 2 * ss->ssl3.dtlsSRTPCipherCount + 1; |
| + |
| + if (append && maxBytes >= 4 + ext_data_len) { |
|
ekr
2012/04/26 14:33:42
As a matter of style, I tend to add parentheses wh
wtc
2012/04/27 01:06:09
I removed these parentheses because I found the ot
ekr
2012/04/27 03:36:34
If it were me, I would do the first of these, but
|
| + /* Extension type */ |
| + rv = ssl3_AppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2); |
| + if (rv != SECSuccess) return -1; |
| + /* Length of extension data */ |
| + rv = ssl3_AppendHandshakeNumber(ss, ext_data_len, 2); |
| + if (rv != SECSuccess) return -1; |
| + /* Length of the SRTP cipher list */ |
| + rv = ssl3_AppendHandshakeNumber(ss, |
| + 2 * ss->ssl3.dtlsSRTPCipherCount, |
| + 2); |
| + if (rv != SECSuccess) return -1; |
| + /* The SRTP ciphers */ |
| + for (i = 0; i < ss->ssl3.dtlsSRTPCipherCount; i++) { |
| + rv = ssl3_AppendHandshakeNumber(ss, |
| + ss->ssl3.dtlsSRTPCiphers[i], |
| + 2); |
| + } |
| + /* Empty MKI value */ |
| + ssl3_AppendHandshakeVariable(ss, NULL, 0, 1); |
| + |
| + ss->xtnData.advertised[ss->xtnData.numAdvertised++] = |
| + ssl_use_srtp_xtn; |
| + } |
| + |
| + return 4 + ext_data_len; |
| + } |
| + |
| + /* Server side */ |
| + if (append && maxBytes >= 9) { |
| + /* Extension type */ |
| + rv = ssl3_AppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2); |
| + if (rv != SECSuccess) return -1; |
| + /* Length of extension data */ |
| + rv = ssl3_AppendHandshakeNumber(ss, 5, 2); |
| + if (rv != SECSuccess) return -1; |
| + /* Length of the SRTP cipher list */ |
| + rv = ssl3_AppendHandshakeNumber(ss, 2, 2); |
| + if (rv != SECSuccess) return -1; |
| + /* The selected cipher */ |
| + rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.dtlsSRTPCipherSuite, 2); |
| + if (rv != SECSuccess) return -1; |
| + /* Empty MKI value */ |
| + ssl3_AppendHandshakeVariable(ss, NULL, 0, 1); |
| + } |
| + |
| + return 9; |
| +} |
| + |
| +static SECStatus |
| +ssl3_HandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data) |
| +{ |
| + SECStatus rv; |
| + PRInt16 i; |
| + PRInt16 bestIndex; |
| + PRBool found = PR_FALSE; |
| + SECItem litem; |
| + PRInt32 cipherLenBytes; |
| + PRInt32 cipher; |
| + |
|
ekr
2012/04/26 14:33:42
Why are these signed? Doesn't the encoding require
wtc
2012/04/27 01:06:09
These two variables are used to store the return v
ekr
2012/04/27 03:36:34
Ouch, that's not a good state of affairs, esp. sin
wtc
2012/04/27 17:32:55
We can also do
if (x < 0)
return SECFailure;
|
| + if (!ss->sec.isServer) { |
| + /* Client side */ |
| + if (!data->data || !data->len) { |
| + /* malformed */ |
| + return SECFailure; |
| + } |
| + |
| + if (data->len != 5) { /* Must always be 5 since we don't offer MKI */ |
| + /* malformed */ |
| + return SECFailure; |
| + } |
| + |
| + /* Now check that the number of ciphers listed is 1 (len = 2) */ |
| + cipherLenBytes = ssl3_ConsumeHandshakeNumber(ss, 2, |
| + &data->data, &data->len); |
| + if (cipherLenBytes != 2) |
| + return SECFailure; |
| + |
| + /* Get the selected cipher */ |
| + cipher = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); |
| + |
| + /* Now check that this is one of the ciphers we offered */ |
| + for (i = 0; i < ss->ssl3.dtlsSRTPCipherCount; i++) { |
| + if (cipher == ss->ssl3.dtlsSRTPCiphers[i]) { |
| + found = PR_TRUE; |
| + break; |
| + } |
| + } |
| + |
| + if (!found) |
| + return SECFailure; |
| + |
| + /* Get the srtp_mki value */ |
| + rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 1, |
| + &data->data, &data->len); |
| + if (rv != SECSuccess) { |
| + return SECFailure; |
| + } |
| + /* We didn't offer an MKI, so this must be 0 length */ |
|
wtc
2012/04/20 02:02:13
The RFC says:
If the client detects a nonzero-le
ekr
2012/04/26 14:33:42
Did I misread your comment in c55 where it sounded
wtc
2012/04/27 01:06:09
You read my comment in c55 correctly. I did volun
ekr
2012/04/27 03:36:34
I think failing with no alert would be satisfactor
|
| + if (litem.len != 0) |
| + return SECFailure; |
| + |
| + /* OK, this looks fine. */ |
| + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ssl_use_srtp_xtn; |
| + ss->ssl3.dtlsSRTPCipherSuite = cipher; |
| + return SECSuccess; |
| + } |
| + |
| + /* Server side */ |
| + if (!IS_DTLS(ss) || !ss->ssl3.dtlsSRTPCipherCount) { |
| + /* Ignore the extension. */ |
| + return SECSuccess; |
|
ekr
2012/04/26 14:33:42
I would change this comment to say
/* Ignore the e
|
| + } |
| + |
| + if (!data->data || data->len < 5) { |
| + /* malformed */ |
| + return SECFailure; |
| + } |
| + |
| + /* Get the length of the cipher list */ |
| + cipherLenBytes = ssl3_ConsumeHandshakeNumber(ss, 2, |
| + &data->data, &data->len); |
| + /* Check that there is room for the ciphers and that the list is even |
| + * length */ |
| + if ((cipherLenBytes > (data->len - 1)) || (cipherLenBytes % 2)) |
| + return SECFailure; |
| + |
| + /* Walk through the offered list one at a time and pick the most preferred |
| + * of our ciphers, if any */ |
| + while (cipherLenBytes > 0) { |
| + cipher = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); |
| + cipherLenBytes -= 2; |
| + |
| + for (i = 0; i < ss->ssl3.dtlsSRTPCipherCount; i++) { |
| + /* Unknown ciphers just go through the entire list */ |
| + if (cipher == ss->ssl3.dtlsSRTPCiphers[i]) { |
| + if (!found || i < bestIndex) { |
| + bestIndex = i; |
| + } |
| + found = PR_TRUE; |
| + break; |
| + } |
|
ekr
2012/04/26 14:33:42
This is arguably slightly less clear because it in
wtc
2012/04/27 01:06:09
This was my attempt to do
bestIndex = i;
in on
ekr
2012/04/27 03:36:34
I'm not sure I'm knowledgeable enough about SECIte
wtc
2012/04/27 17:32:55
Yes, I'll be happy to do that. I can make all the
|
| + } |
| + } |
| + |
| + /* Get the srtp_mki value */ |
| + rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 1, &data->data, &data->len); |
| + if (rv != SECSuccess) { |
| + return SECFailure; |
| + } |
| + |
| + if (data->len) |
| + return SECFailure; /* Malformed */ |
| + |
| + /* Now figure out what to do */ |
| + if (!found) { |
| + /* No matching ciphers */ |
| + return SECSuccess; |
| + } |
| + |
| + /* OK, we have a valid cipher and we've selected it */ |
| + ss->ssl3.dtlsSRTPCipherSuite = ss->ssl3.dtlsSRTPCiphers[bestIndex]; |
| + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ssl_use_srtp_xtn; |
| + |
| + return ssl3_RegisterServerHelloExtensionSender(ss, ssl_use_srtp_xtn, |
| + ssl3_SendUseSRTPXtn); |
| +} |