| OLD | NEW |
| (Empty) |
| 1 diff --git a/mozilla/security/nss/lib/ssl/fnv1a64.c b/mozilla/security/nss/lib/s
sl/fnv1a64.c | |
| 2 new file mode 100644 | |
| 3 index 0000000..c7c4b08 | |
| 4 --- /dev/null | |
| 5 +++ b/mozilla/security/nss/lib/ssl/fnv1a64.c | |
| 6 @@ -0,0 +1,72 @@ | |
| 7 +/* | |
| 8 + * FNV1A64 Hash | |
| 9 + * http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param | |
| 10 + * | |
| 11 + * ***** BEGIN LICENSE BLOCK ***** | |
| 12 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | |
| 13 + * | |
| 14 + * The contents of this file are subject to the Mozilla Public License Version | |
| 15 + * 1.1 (the "License"); you may not use this file except in compliance with | |
| 16 + * the License. You may obtain a copy of the License at | |
| 17 + * http://www.mozilla.org/MPL/ | |
| 18 + * | |
| 19 + * Software distributed under the License is distributed on an "AS IS" basis, | |
| 20 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
| 21 + * for the specific language governing rights and limitations under the | |
| 22 + * License. | |
| 23 + * | |
| 24 + * The Original Code is the Netscape security libraries. | |
| 25 + * | |
| 26 + * The Initial Developer of the Original Code is | |
| 27 + * Netscape Communications Corporation. | |
| 28 + * Portions created by the Initial Developer are Copyright (C) 1994-2000 | |
| 29 + * the Initial Developer. All Rights Reserved. | |
| 30 + * | |
| 31 + * Contributor(s): | |
| 32 + * Adam Langley, Google Inc. | |
| 33 + * | |
| 34 + * Alternatively, the contents of this file may be used under the terms of | |
| 35 + * either the GNU General Public License Version 2 or later (the "GPL"), or | |
| 36 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | |
| 37 + * in which case the provisions of the GPL or the LGPL are applicable instead | |
| 38 + * of those above. If you wish to allow use of your version of this file only | |
| 39 + * under the terms of either the GPL or the LGPL, and not to allow others to | |
| 40 + * use your version of this file under the terms of the MPL, indicate your | |
| 41 + * decision by deleting the provisions above and replace them with the notice | |
| 42 + * and other provisions required by the GPL or the LGPL. If you do not delete | |
| 43 + * the provisions above, a recipient may use your version of this file under | |
| 44 + * the terms of any one of the MPL, the GPL or the LGPL. | |
| 45 + * | |
| 46 + * ***** END LICENSE BLOCK ***** */ | |
| 47 + | |
| 48 +/* $Id: fnv1a64.c,v 1.0 2010/08/09 13:00:00 agl%google.com Exp $ */ | |
| 49 + | |
| 50 +#include "prtypes.h" | |
| 51 +#include "prnetdb.h" | |
| 52 + | |
| 53 +/* Older versions of Visual C++ don't support the 'ull' suffix. */ | |
| 54 +#ifdef _MSC_VER | |
| 55 +static const PRUint64 FNV1A64_OFFSET_BASIS = 14695981039346656037ui64; | |
| 56 +static const PRUint64 FNV1A64_PRIME = 1099511628211ui64; | |
| 57 +#else | |
| 58 +static const PRUint64 FNV1A64_OFFSET_BASIS = 14695981039346656037ull; | |
| 59 +static const PRUint64 FNV1A64_PRIME = 1099511628211ull; | |
| 60 +#endif | |
| 61 + | |
| 62 +void FNV1A64_Init(PRUint64* digest) { | |
| 63 + *digest = FNV1A64_OFFSET_BASIS; | |
| 64 +} | |
| 65 + | |
| 66 +void FNV1A64_Update(PRUint64* digest, const unsigned char *data, | |
| 67 + unsigned int length) { | |
| 68 + unsigned int i; | |
| 69 + | |
| 70 + for (i = 0; i < length; i++) { | |
| 71 + *digest ^= data[i]; | |
| 72 + *digest *= FNV1A64_PRIME; | |
| 73 + } | |
| 74 +} | |
| 75 + | |
| 76 +void FNV1A64_Final(PRUint64 *digest) { | |
| 77 + *digest = PR_htonll(*digest); | |
| 78 +} | |
| 79 diff --git a/mozilla/security/nss/lib/ssl/snapstart.c b/mozilla/security/nss/lib
/ssl/snapstart.c | |
| 80 new file mode 100644 | |
| 81 index 0000000..ca2cafa | |
| 82 --- /dev/null | |
| 83 +++ b/mozilla/security/nss/lib/ssl/snapstart.c | |
| 84 @@ -0,0 +1,1062 @@ | |
| 85 +/* | |
| 86 + * TLS Snap Start | |
| 87 + * | |
| 88 + * ***** BEGIN LICENSE BLOCK ***** | |
| 89 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | |
| 90 + * | |
| 91 + * The contents of this file are subject to the Mozilla Public License Version | |
| 92 + * 1.1 (the "License"); you may not use this file except in compliance with | |
| 93 + * the License. You may obtain a copy of the License at | |
| 94 + * http://www.mozilla.org/MPL/ | |
| 95 + * | |
| 96 + * Software distributed under the License is distributed on an "AS IS" basis, | |
| 97 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
| 98 + * for the specific language governing rights and limitations under the | |
| 99 + * License. | |
| 100 + * | |
| 101 + * The Original Code is the Netscape security libraries. | |
| 102 + * | |
| 103 + * The Initial Developer of the Original Code is | |
| 104 + * Netscape Communications Corporation. | |
| 105 + * Portions created by the Initial Developer are Copyright (C) 1994-2000 | |
| 106 + * the Initial Developer. All Rights Reserved. | |
| 107 + * | |
| 108 + * Contributor(s): | |
| 109 + * Adam Langley, Google Inc. | |
| 110 + * | |
| 111 + * Alternatively, the contents of this file may be used under the terms of | |
| 112 + * either the GNU General Public License Version 2 or later (the "GPL"), or | |
| 113 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | |
| 114 + * in which case the provisions of the GPL or the LGPL are applicable instead | |
| 115 + * of those above. If you wish to allow use of your version of this file only | |
| 116 + * under the terms of either the GPL or the LGPL, and not to allow others to | |
| 117 + * use your version of this file under the terms of the MPL, indicate your | |
| 118 + * decision by deleting the provisions above and replace them with the notice | |
| 119 + * and other provisions required by the GPL or the LGPL. If you do not delete | |
| 120 + * the provisions above, a recipient may use your version of this file under | |
| 121 + * the terms of any one of the MPL, the GPL or the LGPL. | |
| 122 + * | |
| 123 + * ***** END LICENSE BLOCK ***** */ | |
| 124 + | |
| 125 +/* $Id: ssl3snap.c,v 1.0 2010/08/09 13:00:00 agl%google.com Exp $ */ | |
| 126 + | |
| 127 + | |
| 128 +/* TODO(agl): Refactor ssl3_CompressMACEncryptRecord so that it can write to | |
| 129 +** |sendBuf| directly and fix ssl3_AppendSnapStartHandshakeRecord and | |
| 130 +** ssl3_AppendSnapStartApplicationData. | |
| 131 +*/ | |
| 132 + | |
| 133 +/* TODO(agl): Add support for snap starting with compression. */ | |
| 134 + | |
| 135 +/* TODO(agl): Free snapStartApplicationData as soon as the handshake has | |
| 136 +** completed. | |
| 137 +*/ | |
| 138 + | |
| 139 +#include "pk11pub.h" | |
| 140 +#include "ssl.h" | |
| 141 +#include "sslimpl.h" | |
| 142 +#include "sslproto.h" | |
| 143 + | |
| 144 +static unsigned int GetBE16(const void *in) | |
| 145 +{ | |
| 146 + const unsigned char *p = in; | |
| 147 + return ((unsigned) p[0]) << 8 | | |
| 148 + p[1]; | |
| 149 +} | |
| 150 + | |
| 151 +static unsigned int GetBE24(const void *in) | |
| 152 +{ | |
| 153 + const unsigned char *p = in; | |
| 154 + return ((unsigned) p[0]) << 16 | | |
| 155 + ((unsigned) p[1]) << 8 | | |
| 156 + p[2]; | |
| 157 +} | |
| 158 + | |
| 159 +static void PutBE16(void *out, unsigned int value) | |
| 160 +{ | |
| 161 + unsigned char *p = out; | |
| 162 + p[0] = value >> 8; | |
| 163 + p[1] = value; | |
| 164 +} | |
| 165 + | |
| 166 +static void PutBE24(void *out, unsigned int value) | |
| 167 +{ | |
| 168 + unsigned char *p = out; | |
| 169 + p[0] = value >> 16; | |
| 170 + p[1] = value >> 8; | |
| 171 + p[2] = value; | |
| 172 +} | |
| 173 + | |
| 174 +/* ssl3_ForEachExtension calls a callback for each TLS extension in |extensions
| | |
| 175 +** extensions: points to a block of extensions which includes the two prefix | |
| 176 +** length bytes | |
| 177 +** is_resuming: if true, certain extensions will be omitted | |
| 178 +** f: a function which is called with the data of each extension, which | |
| 179 +** includes the four type and length bytes at the beginning. | |
| 180 +*/ | |
| 181 +static PRBool | |
| 182 +ssl3_ForEachExtension(const SECItem *extensions, PRBool is_resuming, | |
| 183 + void (*f) (const unsigned char *data, unsigned int length
, | |
| 184 + void *ctx), | |
| 185 + void *ctx) { | |
| 186 + unsigned int extensions_len, offset; | |
| 187 + | |
| 188 + if (extensions->len == 0) | |
| 189 + return PR_TRUE; | |
| 190 + | |
| 191 + if (extensions->len < 2) | |
| 192 + goto loser; | |
| 193 + | |
| 194 + extensions_len = GetBE16(extensions->data); | |
| 195 + offset = 2; | |
| 196 + | |
| 197 + if (extensions->len != 2 + extensions_len) | |
| 198 + goto loser; | |
| 199 + | |
| 200 + while (extensions_len) { | |
| 201 + unsigned int extension_num, extension_len; | |
| 202 + | |
| 203 + if (extensions->len - offset < 4) | |
| 204 + goto loser; | |
| 205 + | |
| 206 + extension_num = GetBE16(extensions->data + offset); | |
| 207 + extension_len = GetBE16(extensions->data + offset + 2); | |
| 208 + | |
| 209 + if (extensions->len - offset < 4 + extension_len) | |
| 210 + goto loser; | |
| 211 + | |
| 212 + /* When resuming, the server will omit some extensions from the | |
| 213 + * previous non-resume ServerHello. */ | |
| 214 + if (!is_resuming || | |
| 215 + (extension_num != ssl_server_name_xtn && | |
| 216 + extension_num != ssl_session_ticket_xtn)) { | |
| 217 + f(extensions->data + offset, 4 + extension_len, ctx); | |
| 218 + } | |
| 219 + | |
| 220 + offset += 4 + extension_len; | |
| 221 + extensions_len -= 4 + extension_len; | |
| 222 + } | |
| 223 + | |
| 224 + return PR_TRUE; | |
| 225 + | |
| 226 +loser: | |
| 227 + PORT_SetError(SEC_ERROR_INPUT_LEN); | |
| 228 + return PR_FALSE; | |
| 229 +} | |
| 230 + | |
| 231 +static void | |
| 232 +ssl3_AccumlateLengths(const unsigned char *data, unsigned int length, void *ptr
) | |
| 233 +{ | |
| 234 + unsigned int *sum = (unsigned int *) ptr; | |
| 235 + *sum += length; | |
| 236 +} | |
| 237 + | |
| 238 +/* ssl3_PredictServerResponse predicts the contents of the server's | |
| 239 +** ServerHello...ServerHelloDone (inclusive) and progressively calls a callback | |
| 240 +** with the contents of those messages. | |
| 241 +** previous_server_hello: the contents of a previous ServerHello from the | |
| 242 +** server where the 'random' field has been replaced with our suggested | |
| 243 +** server random. | |
| 244 +** is_resuming: if false, Certificate and ServerHelloDone messages will be | |
| 245 +** predicted | |
| 246 +** hashUpdate: a callback which is called repeated with the contents of the | |
| 247 +** predicted messages. | |
| 248 +*/ | |
| 249 +static PRBool | |
| 250 +ssl3_PredictServerResponse( | |
| 251 + sslSocket *ss, SECItem *previous_server_hello, PRBool is_resuming, | |
| 252 + void (*hashUpdate) (const unsigned char *data, unsigned int length, | |
| 253 + void *ctx), | |
| 254 + void *ctx) { | |
| 255 + unsigned int old_session_id_length, old_extensions_len; | |
| 256 + unsigned int extensions_len, server_hello_len; | |
| 257 + unsigned char session_id_len, header[4]; | |
| 258 + SECItem extensions; | |
| 259 + | |
| 260 + /* Keep the structure of a ServerHello in mind when reading the following: | |
| 261 + * | |
| 262 + * struct ServerHello { | |
| 263 + * uint16_t version; | |
| 264 + * uint8_t random[32]; | |
| 265 + * uint8_t session_id_len; | |
| 266 + * uint8_t session_id[session_id_len]; | |
| 267 + * uint16_t cipher | |
| 268 + * uint8_t compression | |
| 269 + * | |
| 270 + * // Optional: | |
| 271 + * uint16_t extensions_len; | |
| 272 + * struct Extension { | |
| 273 + * uint16_t num; | |
| 274 + * uint16_t len; | |
| 275 + * uint8_t payload[len]; | |
| 276 + * } | |
| 277 + */ | |
| 278 + | |
| 279 + /* 38 bytes is the shortest possible ServerHello with a zero-length | |
| 280 + * session_id and no extensions. */ | |
| 281 + if (previous_server_hello->len < 38) { | |
| 282 + PORT_SetError(SEC_ERROR_INPUT_LEN); | |
| 283 + return PR_FALSE; | |
| 284 + } | |
| 285 + | |
| 286 + /* First we need to figure out the length of the predicted ServerHello. Any | |
| 287 + * session id in |previous_server_hello| needs to be removed | |
| 288 + * (or replaced). */ | |
| 289 + old_session_id_length = previous_server_hello->data[34]; | |
| 290 + | |
| 291 + extensions.len = 0; | |
| 292 + | |
| 293 + if (previous_server_hello->len >= 35 + old_session_id_length + 3 + 2) { | |
| 294 + /* Extensions present */ | |
| 295 + unsigned int offset = 35 + old_session_id_length + 3; | |
| 296 + extensions.data = previous_server_hello->data + offset; | |
| 297 + extensions.len = previous_server_hello->len - offset; | |
| 298 + } | |
| 299 + | |
| 300 + /* Sum the lengths of all the extensions that we wish to include */ | |
| 301 + extensions_len = 0; | |
| 302 + if (!ssl3_ForEachExtension(&extensions, is_resuming, ssl3_AccumlateLengths, | |
| 303 + &extensions_len)) { | |
| 304 + return PR_FALSE; | |
| 305 + } | |
| 306 + | |
| 307 + old_extensions_len = | |
| 308 + (previous_server_hello->len - 35 - old_session_id_length - 3 - 2); | |
| 309 + | |
| 310 + session_id_len = 0; | |
| 311 + if (ss->sec.ci.sid) | |
| 312 + session_id_len = ss->sec.ci.sid->u.ssl3.sessionIDLength; | |
| 313 + server_hello_len = previous_server_hello->len + | |
| 314 + session_id_len - old_session_id_length + | |
| 315 + extensions_len - old_extensions_len; | |
| 316 + | |
| 317 + header[0] = server_hello; | |
| 318 + PutBE24(header + 1, server_hello_len); | |
| 319 + hashUpdate(header, 4, ctx); | |
| 320 + | |
| 321 + hashUpdate(previous_server_hello->data, 34, ctx); | |
| 322 + hashUpdate(&session_id_len, sizeof(session_id_len), ctx); | |
| 323 + if (session_id_len) | |
| 324 + hashUpdate(ss->sec.ci.sid->u.ssl3.sessionID, session_id_len, ctx); | |
| 325 + hashUpdate(previous_server_hello->data + 35 + old_session_id_length, 3, | |
| 326 + ctx); | |
| 327 + | |
| 328 + if (extensions.len) { | |
| 329 + PutBE16(header, extensions_len); | |
| 330 + hashUpdate(header, 2, ctx); | |
| 331 + | |
| 332 + if (!ssl3_ForEachExtension(&extensions, is_resuming, hashUpdate, ctx)) | |
| 333 + return PR_FALSE; | |
| 334 + } | |
| 335 + | |
| 336 + if (!is_resuming) { | |
| 337 + unsigned int certificate_message_len = 3, i; | |
| 338 + for (i = 0; ss->ssl3.predictedCertChain[i]; i++) { | |
| 339 + certificate_message_len += 3; | |
| 340 + certificate_message_len += | |
| 341 + ss->ssl3.predictedCertChain[i]->derCert.len; | |
| 342 + } | |
| 343 + | |
| 344 + header[0] = certificate; | |
| 345 + PutBE24(header + 1, certificate_message_len); | |
| 346 + hashUpdate(header, 4, ctx); | |
| 347 + | |
| 348 + PutBE24(header, certificate_message_len - 3); | |
| 349 + hashUpdate(header, 3, ctx); | |
| 350 + | |
| 351 + for (i = 0; ss->ssl3.predictedCertChain[i]; i++) { | |
| 352 + unsigned int len = ss->ssl3.predictedCertChain[i]->derCert.len; | |
| 353 + PutBE24(header, len); | |
| 354 + hashUpdate(header, 3, ctx); | |
| 355 + hashUpdate(ss->ssl3.predictedCertChain[i]->derCert.data, len, ctx); | |
| 356 + } | |
| 357 + | |
| 358 + header[0] = server_hello_done; | |
| 359 + header[1] = header[2] = header[3] = 0; | |
| 360 + hashUpdate(header, 4, ctx); | |
| 361 + } | |
| 362 + | |
| 363 + return PR_TRUE; | |
| 364 +} | |
| 365 + | |
| 366 +/* ssl3_SnapStartHash is called with the contents of the server's predicted | |
| 367 + * response and updates both the Finished hash and an FNV641a hash. */ | |
| 368 +static void | |
| 369 +ssl3_SnapStartHash(const unsigned char *data, unsigned int len, void *ctx) | |
| 370 +{ | |
| 371 + SECStatus rv; | |
| 372 + void **ptrs = (void **) ctx; | |
| 373 + sslSocket *ss = ptrs[0]; | |
| 374 + PRUint64 *fnv = ptrs[1]; | |
| 375 + | |
| 376 + FNV1A64_Update(fnv, data, len); | |
| 377 + rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char *) data, len); | |
| 378 + if (rv != SECSuccess) | |
| 379 + PR_Assert("rv == SECSuccess", __FILE__, __LINE__); | |
| 380 +} | |
| 381 + | |
| 382 +static PRInt32 | |
| 383 +ssl3_SendEmptySnapStartXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) | |
| 384 +{ | |
| 385 + SECStatus rv; | |
| 386 + | |
| 387 + if (maxBytes < 4) | |
| 388 + return 0; | |
| 389 + | |
| 390 + if (append) { | |
| 391 + rv = ssl3_AppendHandshakeNumber(ss, ssl_snap_start_xtn, 2); | |
| 392 + if (rv != SECSuccess) | |
| 393 + return -1; | |
| 394 + rv = ssl3_AppendHandshakeNumber(ss, 0 /* empty extension */, 2); | |
| 395 + if (rv != SECSuccess) | |
| 396 + return -1; | |
| 397 + if (!ss->sec.isServer) { | |
| 398 + TLSExtensionData *xtnData = &ss->xtnData; | |
| 399 + xtnData->advertised[xtnData->numAdvertised++] = ssl_snap_start_xtn; | |
| 400 + } | |
| 401 + } | |
| 402 + return 4; | |
| 403 +} | |
| 404 + | |
| 405 +static SECStatus | |
| 406 +ssl3_BufferEnsure(sslBuffer *buf, unsigned int extra_bytes) | |
| 407 +{ | |
| 408 + if (buf->space < buf->len + extra_bytes) | |
| 409 + return sslBuffer_Grow(buf, buf->len + extra_bytes); | |
| 410 + return SECSuccess; | |
| 411 +} | |
| 412 + | |
| 413 +/* ssl3_AppendSnapStartRecordHeader appends a 5 byte TLS record header to the | |
| 414 + * sendBuf of the given sslSocket. */ | |
| 415 +static SECStatus | |
| 416 +ssl3_AppendSnapStartRecordHeader(sslSocket *ss, SSL3ContentType type, | |
| 417 + unsigned int len) | |
| 418 +{ | |
| 419 + SECStatus rv; | |
| 420 + | |
| 421 + rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 5); | |
| 422 + if (rv != SECSuccess) | |
| 423 + return rv; | |
| 424 + ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 0] = type; | |
| 425 + PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 1], ss->version); | |
| 426 + PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 3], len); | |
| 427 + ss->sec.ci.sendBuf.len += 5; | |
| 428 + return SECSuccess; | |
| 429 +} | |
| 430 + | |
| 431 +/* ssl3_AppendSnapStartHandshakeRecord appends a (possibly encrypted) record to | |
| 432 +** the sendBuf of the given sslSocket. | |
| 433 +** f: a function which will append the bytes of the record (not including the | |
| 434 +** 5 byte header) to the sendBuf. | |
| 435 +*/ | |
| 436 +static SECStatus | |
| 437 +ssl3_AppendSnapStartHandshakeRecord(sslSocket *ss, SECStatus (*f) (sslSocket*), | |
| 438 + PRBool encrypt) | |
| 439 +{ | |
| 440 + SECStatus rv; | |
| 441 + unsigned int record_offset, record_len; | |
| 442 + | |
| 443 + /* ssl3_CompressMACEncryptRecord will deal with the record header if we are | |
| 444 + * encrypting. */ | |
| 445 + if (!encrypt) { | |
| 446 + /* The zero length argument here is a dummy value. We write the real | |
| 447 + * length once we know it, below. */ | |
| 448 + rv = ssl3_AppendSnapStartRecordHeader(ss, content_handshake, 0); | |
| 449 + if (rv != SECSuccess) | |
| 450 + return rv; | |
| 451 + } | |
| 452 + | |
| 453 + record_offset = ss->sec.ci.sendBuf.len; | |
| 454 + rv = f(ss); | |
| 455 + if (rv != SECSuccess) | |
| 456 + return rv; | |
| 457 + record_len = ss->sec.ci.sendBuf.len - record_offset; | |
| 458 + if (!encrypt) { | |
| 459 + PutBE16(&ss->sec.ci.sendBuf.buf[record_offset - 2], record_len); | |
| 460 + } else { | |
| 461 + /* ssl3_CompressMACEncryptRecord writes to |ss->sec.writeBuf| | |
| 462 + * so we copy it back to |ss->sec.ci.sendBuf| */ | |
| 463 + /* TODO(agl): the buffer copy here is a bodge. See TODO at the top of | |
| 464 + * the file. */ | |
| 465 + rv = ssl3_CompressMACEncryptRecord( | |
| 466 + ss, content_handshake, | |
| 467 + &ss->sec.ci.sendBuf.buf[record_offset], record_len); | |
| 468 + if (rv != SECSuccess) | |
| 469 + return rv; | |
| 470 + ss->sec.ci.sendBuf.len -= record_len; | |
| 471 + ssl3_BufferEnsure(&ss->sec.ci.sendBuf, ss->sec.writeBuf.len); | |
| 472 + memcpy(&ss->sec.ci.sendBuf.buf[record_offset], ss->sec.writeBuf.buf, | |
| 473 + ss->sec.writeBuf.len); | |
| 474 + ss->sec.ci.sendBuf.len += ss->sec.writeBuf.len; | |
| 475 + ss->sec.writeBuf.len = 0; | |
| 476 + } | |
| 477 + | |
| 478 + return SECSuccess; | |
| 479 +} | |
| 480 + | |
| 481 +/* ssl3_AppendSnapStartApplicationData appends an encrypted Application Data | |
| 482 +** record the sendBuf of the given sslSocket. | |
| 483 +*/ | |
| 484 +static SECStatus ssl3_AppendSnapStartApplicationData( | |
| 485 + sslSocket *ss, const SSL3Opaque *data, unsigned int len) | |
| 486 +{ | |
| 487 + SECStatus rv; | |
| 488 + | |
| 489 + /* TODO(agl): the buffer copy here is a bodge. See TODO at the top of the | |
| 490 + * file. */ | |
| 491 + rv = ssl3_CompressMACEncryptRecord(ss, content_application_data, data, len)
; | |
| 492 + if (rv != SECSuccess) | |
| 493 + return rv; | |
| 494 + rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, ss->sec.writeBuf.len); | |
| 495 + if (rv != SECSuccess) | |
| 496 + return rv; | |
| 497 + memcpy(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len], | |
| 498 + ss->sec.writeBuf.buf, ss->sec.writeBuf.len); | |
| 499 + ss->sec.ci.sendBuf.len += ss->sec.writeBuf.len; | |
| 500 + ss->sec.writeBuf.len = 0; | |
| 501 + | |
| 502 + return SECSuccess; | |
| 503 +} | |
| 504 + | |
| 505 +static SECStatus ssl3_SendSnapStartFinished(sslSocket *ss) | |
| 506 +{ | |
| 507 + /* We use ssl_SEND_FLAG_NO_FLUSH here because this finished message is | |
| 508 + * going to end up in the middle of the Snap Start extension. So | |
| 509 + * transmitting |sendBuf| at this point would result in an incomplete | |
| 510 + * ClientHello. */ | |
| 511 + return ssl3_SendFinished(ss, ssl_SEND_FLAG_NO_FLUSH); | |
| 512 +} | |
| 513 + | |
| 514 +/* ssl3_FindOrbit is called for each extension in a ServerHello message. It | |
| 515 +** tests for a Snap Start extension and records the server's orbit when found. | |
| 516 +** data: the extension data (including the four type and length bytes) | |
| 517 +** length: the length, in bytes, of |data| | |
| 518 +** ptr: a pointer to a uint8_t[9]. The orbit, if found, is copied into the | |
| 519 +** first 8 bytes and then the ninth byte is set to one. | |
| 520 +*/ | |
| 521 +static void | |
| 522 +ssl3_FindOrbit(const unsigned char *data, unsigned int length, void *ptr) | |
| 523 +{ | |
| 524 + unsigned char *orbit = (unsigned char *) ptr; | |
| 525 + | |
| 526 + unsigned int extension_num = GetBE16(data); | |
| 527 + if (extension_num == ssl_snap_start_xtn && | |
| 528 + length == 4 + 8 /* orbit */ + 2 /* snap start cipher suite */) { | |
| 529 + memcpy(orbit, data + 4, 8); | |
| 530 + /* A last byte of 1 indicates that the previous eight are valid. */ | |
| 531 + orbit[8] = 1; | |
| 532 + } | |
| 533 +} | |
| 534 + | |
| 535 +/* ssl3_CanSnapStart returns true if we are able to perform Snap Start on | |
| 536 +** the given socket. | |
| 537 +** extensions: on successful return, this is filled in with the contents of | |
| 538 +** the server's predicted extensions. This points within | |
| 539 +** |ss->ssl3.serverHelloPredictionData|. | |
| 540 +** resuming: PR_TRUE iff we wish to attempt a Snap Start resume | |
| 541 +** out_orbit: if this function returns PR_TRUE, then |out_orbit| is filled | |
| 542 +** with the server's predicted orbit value. | |
| 543 +** The |hs.cipher_suite|, |hs.cipher_def| and |hs.compression| fields of |ss| | |
| 544 +** are set to match the predicted ServerHello on successful exit (and may still | |
| 545 +** be modified on failure). | |
| 546 +*/ | |
| 547 +static PRBool | |
| 548 +ssl3_CanSnapStart(sslSocket *ss, SECItem *extensions, PRBool resuming, | |
| 549 + unsigned char out_orbit[8]) { | |
| 550 + const unsigned char *server_hello; | |
| 551 + unsigned int server_hello_len, session_id_len, cipher_suite_offset; | |
| 552 + unsigned int extensions_offset, cipher_suite, compression_method; | |
| 553 + unsigned char orbit[9]; | |
| 554 + SECStatus rv; | |
| 555 + SSL3ProtocolVersion version; | |
| 556 + | |
| 557 + /* If we don't have the information needed then we can't perform a Snap | |
| 558 + * Start. */ | |
| 559 + if (!ss->ssl3.predictedCertChain || !ss->ssl3.serverHelloPredictionData.dat
a) | |
| 560 + return PR_FALSE; | |
| 561 + | |
| 562 + /* When the sizes of the fields in the ClientHello are calculated, they'll | |
| 563 + * take the length of the Snap Start extension to be zero, so currently | |
| 564 + * it's as if this extension didn't exist, which is the state that we | |
| 565 + * need. */ | |
| 566 + | |
| 567 + server_hello = ss->ssl3.serverHelloPredictionData.data; | |
| 568 + server_hello_len = ss->ssl3.serverHelloPredictionData.len; | |
| 569 + | |
| 570 + if (server_hello_len < 2 + 32 + 1) | |
| 571 + return PR_FALSE; | |
| 572 + session_id_len = server_hello[2 + 32]; | |
| 573 + cipher_suite_offset = 2 + 32 + 1 + session_id_len; | |
| 574 + if (server_hello_len < cipher_suite_offset + 3) | |
| 575 + return PR_FALSE; | |
| 576 + extensions_offset = cipher_suite_offset + 3; | |
| 577 + | |
| 578 + version = (SSL3ProtocolVersion) GetBE16(server_hello); | |
| 579 + if (MSB(version) < MSB(SSL_LIBRARY_VERSION_3_0)) | |
| 580 + return PR_FALSE; | |
| 581 + rv = ssl3_NegotiateVersion(ss, version); | |
| 582 + if (rv != SECSuccess) | |
| 583 + return PR_FALSE; | |
| 584 + | |
| 585 + cipher_suite = GetBE16(&server_hello[cipher_suite_offset]); | |
| 586 + ss->ssl3.hs.cipher_suite = (ssl3CipherSuite)cipher_suite; | |
| 587 + ss->ssl3.hs.suite_def = ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite); | |
| 588 + if (!ss->ssl3.hs.suite_def) | |
| 589 + return PR_FALSE; | |
| 590 + compression_method = server_hello[cipher_suite_offset + 2]; | |
| 591 + if (compression_method != ssl_compression_null) { | |
| 592 + /* TODO(agl): support compression. */ | |
| 593 + return PR_FALSE; | |
| 594 + } | |
| 595 + ss->ssl3.hs.compression = ssl_compression_null; | |
| 596 + | |
| 597 + extensions->data = (unsigned char *) server_hello + extensions_offset; | |
| 598 + extensions->len = server_hello_len - extensions_offset; | |
| 599 + | |
| 600 + /* The last byte is used to indictate that the previous eight are valid. */ | |
| 601 + orbit[8] = 0; | |
| 602 + if (!ssl3_ForEachExtension(extensions, resuming, ssl3_FindOrbit, orbit)) | |
| 603 + return PR_FALSE; | |
| 604 + | |
| 605 + if (!orbit[8]) | |
| 606 + return PR_FALSE; | |
| 607 + | |
| 608 + memcpy(out_orbit, orbit, 8); | |
| 609 + | |
| 610 + return PR_TRUE; | |
| 611 +} | |
| 612 + | |
| 613 +/* ssl3_UpdateClientHelloLengths rewrites the handshake header length and | |
| 614 +** extensions length in the ClientHello to reflect the addition of the Snap | |
| 615 +** Start extension. | |
| 616 +** snap_start_extension_len_offset: the number of bytes of the ClientHello to | |
| 617 +** skip in order to find the embedded length of the Snap Start extension. | |
| 618 +*/ | |
| 619 +static void | |
| 620 +ssl3_UpdateClientHelloLengths(sslSocket *ss, | |
| 621 + unsigned int snap_start_extension_len_offset, | |
| 622 + sslSessionID *sid) { | |
| 623 + unsigned int extension_length, old_length, new_length, new_session_id_len; | |
| 624 + unsigned int offset, ciphers_length, compressions_len; | |
| 625 + | |
| 626 + extension_length = | |
| 627 + ss->sec.ci.sendBuf.len - snap_start_extension_len_offset - 2; | |
| 628 + PutBE16(&ss->sec.ci.sendBuf.buf[snap_start_extension_len_offset], | |
| 629 + extension_length); | |
| 630 + | |
| 631 + /* The length in the handshake header is short by extension_length + 4 | |
| 632 + * bytes. */ | |
| 633 + old_length = GetBE24(&ss->sec.ci.sendBuf.buf[1]); | |
| 634 + new_length = old_length + extension_length + 4; | |
| 635 + PutBE24(&ss->sec.ci.sendBuf.buf[1], new_length); | |
| 636 + | |
| 637 + /* The length of the extensions block is similarly wrong. */ | |
| 638 + new_session_id_len = 0; | |
| 639 + if (sid) | |
| 640 + new_session_id_len = sid->u.ssl3.sessionIDLength; | |
| 641 + offset = 4 + 2 + 32 + 1 + new_session_id_len; | |
| 642 + ciphers_length = GetBE16(&ss->sec.ci.sendBuf.buf[offset]); | |
| 643 + offset += 2 + ciphers_length; | |
| 644 + compressions_len = ss->sec.ci.sendBuf.buf[offset]; | |
| 645 + offset += 1 + compressions_len; | |
| 646 + old_length = GetBE16(&ss->sec.ci.sendBuf.buf[offset]); | |
| 647 + new_length = old_length + extension_length + 4; | |
| 648 + PutBE16(&ss->sec.ci.sendBuf.buf[offset], new_length); | |
| 649 +} | |
| 650 + | |
| 651 +/* ssl3_FindServerNPNExtension is a callback function for ssl3_ForEachExtension
. | |
| 652 + * It looks for a Next Protocol Negotiation and saves the payload of the | |
| 653 + * extension in the given SECItem */ | |
| 654 +static void | |
| 655 +ssl3_FindServerNPNExtension(const unsigned char* data, unsigned int length, | |
| 656 + void *ctx) | |
| 657 +{ | |
| 658 + SECItem *server_npn_extension = (SECItem*) ctx; | |
| 659 + | |
| 660 + unsigned int extension_num = GetBE16(data); | |
| 661 + if (extension_num == ssl_next_proto_neg_xtn && length >= 4) { | |
| 662 + server_npn_extension->data = (unsigned char*)data + 4; | |
| 663 + server_npn_extension->len = length - 4; | |
| 664 + } | |
| 665 +} | |
| 666 + | |
| 667 +/* ssl3_MaybeWriteNextProtocol deals with the interaction of Next Protocol | |
| 668 + * Negotiation and Snap Start. It's called just before we serialise the embedde
d | |
| 669 + * Finished message in the extension. At this point, if NPN is enabled, we have | |
| 670 + * to include a NextProtocol message. */ | |
| 671 +static SECStatus | |
| 672 +ssl3_MaybeWriteNextProtocol(sslSocket *ss, SECItem *server_hello_extensions) | |
| 673 +{ | |
| 674 + PRUint16 i16; | |
| 675 + SECItem server_npn_extension; | |
| 676 + | |
| 677 + for (i16 = 0; i16 < ss->xtnData.numAdvertised; i16++) { | |
| 678 + if (ss->xtnData.advertised[i16] == ssl_next_proto_neg_xtn) | |
| 679 + break; | |
| 680 + } | |
| 681 + | |
| 682 + if (i16 == ss->xtnData.numAdvertised) { | |
| 683 + /* We didn't send an NPN extension, so no need to do anything here. */ | |
| 684 + return SECSuccess; | |
| 685 + } | |
| 686 + | |
| 687 + memset(&server_npn_extension, 0, sizeof(server_npn_extension)); | |
| 688 + | |
| 689 + ssl3_ForEachExtension( | |
| 690 + server_hello_extensions, PR_FALSE /* is_resuming: value doesn't matter | |
| 691 + in this case */, ssl3_FindServerNPNExtension, &server_npn_extension); | |
| 692 + | |
| 693 + if (server_npn_extension.data == NULL) { | |
| 694 + /* We predicted that the server doesn't support NPN, so nothing to do | |
| 695 + * here. */ | |
| 696 + return SECSuccess; | |
| 697 + } | |
| 698 + | |
| 699 + ssl3_ClientHandleNextProtoNegoXtn(ss, ssl_next_proto_neg_xtn, | |
| 700 + &server_npn_extension); | |
| 701 + | |
| 702 + if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NO_SUPPORT) { | |
| 703 + /* The server's predicted NPN extension was malformed. We're didn't pic
k | |
| 704 + * a protocol so we won't send a NextProtocol message. However, this is | |
| 705 + * probably fatal to the connection. */ | |
| 706 + return SECSuccess; | |
| 707 + } | |
| 708 + | |
| 709 + return ssl3_AppendSnapStartHandshakeRecord(ss, ssl3_SendNextProto, | |
| 710 + PR_TRUE /* encrypt */); | |
| 711 +} | |
| 712 + | |
| 713 +/* ssl3_SendSnapStartXtn appends a Snap Start extension. It assumes that the | |
| 714 + * inchoate ClientHello is in |ss->sec.ci.sendBuf|. */ | |
| 715 +PRInt32 | |
| 716 +ssl3_SendSnapStartXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) | |
| 717 +{ | |
| 718 + unsigned char orbit[8]; | |
| 719 + PRBool resuming = PR_FALSE; | |
| 720 + unsigned char suggested_server_random[32]; | |
| 721 + SECStatus rv; | |
| 722 + PRUint64 fnv; | |
| 723 + /* The context for |ssl3_SnapStartHash|. The first pointer points to |ss| | |
| 724 + * and the second to the running FNV1A64 hash of the predicted server | |
| 725 + * response. */ | |
| 726 + void *ctx[2]; | |
| 727 + unsigned int snap_start_extension_len_offset, original_sendbuf_len; | |
| 728 + ssl3CipherSpec *temp; | |
| 729 + sslSessionID *sid; | |
| 730 + SECItem server_extensions; | |
| 731 + | |
| 732 + if (!ss->opt.enableSnapStart) | |
| 733 + return 0; | |
| 734 + | |
| 735 + original_sendbuf_len = ss->sec.ci.sendBuf.len; | |
| 736 + | |
| 737 + /* This function is called twice for each ClientHello emitted. The first | |
| 738 + * time around is to calculate the sizes of the extension (|append| is | |
| 739 + * false). The second time around is to actually write out the bytes | |
| 740 + * (|append| is true). | |
| 741 + * | |
| 742 + * We always return 0 bytes in each case because we want to be able to hash | |
| 743 + * the inchoate ClientHello as if this extension was missing: that's why | |
| 744 + * it's important that this always be the last extension serialised. */ | |
| 745 + sid = ss->sec.ci.sid; | |
| 746 + | |
| 747 + if (!ss->opt.enableSessionTickets || ss->sec.isServer) | |
| 748 + return 0; | |
| 749 + | |
| 750 + /* If we are sending a SessionTicket then the first time around | |
| 751 + * ticketTimestampVerified will be true but it's reset after serialising | |
| 752 + * the session ticket extension, so we have | |
| 753 + * |clientSentNonEmptySessionTicket|. */ | |
| 754 + if (ss->xtnData.clientSentNonEmptySessionTicket) { | |
| 755 + resuming = PR_TRUE; | |
| 756 + } else if (sid->u.ssl3.sessionTicket.ticket.data && | |
| 757 + ss->xtnData.ticketTimestampVerified) { | |
| 758 + resuming = PR_TRUE; | |
| 759 + } | |
| 760 + | |
| 761 + if (!ssl3_CanSnapStart(ss, &server_extensions, resuming, orbit)) | |
| 762 + return ssl3_SendEmptySnapStartXtn(ss, append, maxBytes); | |
| 763 + | |
| 764 + /* At this point we are happy that we are going to send a non-empty Snap | |
| 765 + * Start extension. If we are still calculating length then we lie and | |
| 766 + * return 0 so that everything is set up as if the extension didn't exist | |
| 767 + * when this function is called again later. */ | |
| 768 + | |
| 769 + if (!append) | |
| 770 + return 0; | |
| 771 + | |
| 772 + /* |ss->sec.ci.sendBuf.buf| contains the inchoate ClientHello. This copies | |
| 773 + * the ClientHello's gmt_unix_time into the suggested server random. */ | |
| 774 + memcpy(suggested_server_random, ss->sec.ci.sendBuf.buf + 6, 4); | |
| 775 + memcpy(suggested_server_random + 4, orbit, 8); | |
| 776 + rv = PK11_GenerateRandom(suggested_server_random + 12, 20); | |
| 777 + if (rv != SECSuccess) | |
| 778 + goto loser; | |
| 779 + memcpy(ss->ssl3.serverHelloPredictionData.data + 2, suggested_server_random
, | |
| 780 + 32); | |
| 781 + | |
| 782 + memcpy(&ss->ssl3.hs.server_random, suggested_server_random, 32); | |
| 783 + | |
| 784 + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); | |
| 785 + rv = ssl3_SetupPendingCipherSpec(ss); | |
| 786 + if (rv != SECSuccess) | |
| 787 + goto loser; | |
| 788 + ss->ssl3.hs.isResuming = resuming; | |
| 789 + | |
| 790 + FNV1A64_Init(&fnv); | |
| 791 + ctx[0] = ss; | |
| 792 + ctx[1] = &fnv; | |
| 793 + | |
| 794 + if (!ssl3_PredictServerResponse(ss, &ss->ssl3.serverHelloPredictionData, | |
| 795 + resuming, ssl3_SnapStartHash, ctx)) { | |
| 796 + /* It's not a fatal error if the predicted ServerHello was invalid. */ | |
| 797 + return 0; | |
| 798 + } | |
| 799 + FNV1A64_Final(&fnv); | |
| 800 + | |
| 801 + /* Now we grow the send buffer to accomodate the extension type and length, | |
| 802 + * orbit, suggested random and predicted server response hash without | |
| 803 + * calling ssl3_AppendHandshake (which would also update the Finished | |
| 804 + * hash). */ | |
| 805 + if (ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 4 + 8 + 20 + 8) != SECSuccess) | |
| 806 + goto loser; | |
| 807 + | |
| 808 + PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len], | |
| 809 + ssl_snap_start_xtn); | |
| 810 + ss->sec.ci.sendBuf.len += 2; | |
| 811 + /* Skip over the length for now. */ | |
| 812 + snap_start_extension_len_offset = ss->sec.ci.sendBuf.len; | |
| 813 + ss->sec.ci.sendBuf.len += 2; | |
| 814 + memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, orbit, 8); | |
| 815 + ss->sec.ci.sendBuf.len += 8; | |
| 816 + memcpy(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len], | |
| 817 + suggested_server_random + 12, 20); | |
| 818 + ss->sec.ci.sendBuf.len += 20; | |
| 819 + memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, &fnv, 8); | |
| 820 + ss->sec.ci.sendBuf.len += 8; | |
| 821 + | |
| 822 + if (!resuming) { | |
| 823 + /* Write ClientKeyExchange */ | |
| 824 + ss->sec.peerCert = | |
| 825 + CERT_DupCertificate(ss->ssl3.predictedCertChain[0]); | |
| 826 + rv = ssl3_AppendSnapStartHandshakeRecord( | |
| 827 + ss, ssl3_SendClientKeyExchange, PR_FALSE /* do not encrypt */); | |
| 828 + if (rv != SECSuccess) | |
| 829 + goto loser; | |
| 830 + } else { | |
| 831 + SSL3Finished hashes; | |
| 832 + TLSFinished tlsFinished; | |
| 833 + unsigned char hdr[4]; | |
| 834 + | |
| 835 + rv = ssl3_SetupMasterSecretFromSessionID(ss); | |
| 836 + if (rv == SECFailure) | |
| 837 + goto loser; | |
| 838 + | |
| 839 + if (sid->peerCert != NULL) { | |
| 840 + ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); | |
| 841 + ssl3_CopyPeerCertsFromSID(ss, sid); | |
| 842 + } | |
| 843 + | |
| 844 + rv = ssl3_InitPendingCipherSpec(ss, NULL /* re-use master secret */); | |
| 845 + if (rv != SECSuccess) | |
| 846 + goto loser; | |
| 847 + | |
| 848 + /* Need to add the server's predicted Finished message to our handshake | |
| 849 + * hash in order to be able to produce our own Finished message. */ | |
| 850 + rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, | |
| 851 + 0 /* only for SSL3 */); | |
| 852 + if (rv != SECSuccess) | |
| 853 + goto loser; | |
| 854 + | |
| 855 + rv = ssl3_ComputeTLSFinished(ss->ssl3.pwSpec, PR_TRUE /* isServer */, | |
| 856 + &hashes, &tlsFinished); | |
| 857 + if (rv != SECSuccess) | |
| 858 + goto loser; | |
| 859 + | |
| 860 + hdr[0] = (unsigned char) finished; | |
| 861 + hdr[1] = hdr[2] = 0; | |
| 862 + hdr[3] = sizeof(tlsFinished.verify_data); | |
| 863 + ssl3_UpdateHandshakeHashes(ss, hdr, sizeof(hdr)); | |
| 864 + ssl3_UpdateHandshakeHashes(ss, tlsFinished.verify_data, | |
| 865 + sizeof(tlsFinished.verify_data)); | |
| 866 + | |
| 867 + /* Store the Finished message so that we can verify it later */ | |
| 868 + memcpy(&ss->ssl3.hs.finishedMsgs.tFinished[1], tlsFinished.verify_data, | |
| 869 + sizeof(tlsFinished.verify_data)); | |
| 870 + } | |
| 871 + | |
| 872 + /* Write ChangeCipherSpec */ | |
| 873 + rv = ssl3_AppendSnapStartRecordHeader(ss, content_change_cipher_spec, 1); | |
| 874 + if (rv != SECSuccess) | |
| 875 + goto loser; | |
| 876 + rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 1); | |
| 877 + if (rv != SECSuccess) | |
| 878 + goto loser; | |
| 879 + ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len] = change_cipher_spec_choice; | |
| 880 + ss->sec.ci.sendBuf.len++; | |
| 881 + | |
| 882 + /* We swap |cwSpec| and |pwSpec| temporarily in order to encrypt some | |
| 883 + * records before switching them back so that the whole ClientHello doesn't | |
| 884 + * get encrypted. */ | |
| 885 + ssl_GetSpecWriteLock(ss); | |
| 886 + temp = ss->ssl3.cwSpec; | |
| 887 + ss->ssl3.cwSpec = ss->ssl3.pwSpec; | |
| 888 + ss->ssl3.pwSpec = temp; | |
| 889 + ss->ssl3.cwSpec->write_seq_num.high = 0; | |
| 890 + ss->ssl3.cwSpec->write_seq_num.low = 0; | |
| 891 + ssl_ReleaseSpecWriteLock(ss); | |
| 892 + | |
| 893 + rv = ssl3_MaybeWriteNextProtocol(ss, &server_extensions); | |
| 894 + if (rv != SECSuccess) | |
| 895 + goto loser; | |
| 896 + | |
| 897 + /* Write Finished */ | |
| 898 + rv = ssl3_AppendSnapStartHandshakeRecord(ss, ssl3_SendSnapStartFinished, | |
| 899 + PR_TRUE /* encrypt */); | |
| 900 + if (rv != SECSuccess) | |
| 901 + goto loser; | |
| 902 + | |
| 903 + /* Write application data */ | |
| 904 + if (ss->ssl3.snapStartApplicationData.data) { | |
| 905 + rv = ssl3_AppendSnapStartApplicationData( | |
| 906 + ss, ss->ssl3.snapStartApplicationData.data, | |
| 907 + ss->ssl3.snapStartApplicationData.len); | |
| 908 + if (rv != SECSuccess) | |
| 909 + goto loser; | |
| 910 + } | |
| 911 + | |
| 912 + /* Revert the write cipher spec because the ClientHello will get encrypted | |
| 913 + * with it otherwise. */ | |
| 914 + ssl_GetSpecWriteLock(ss); | |
| 915 + temp = ss->ssl3.cwSpec; | |
| 916 + ss->ssl3.cwSpec = ss->ssl3.pwSpec; | |
| 917 + ss->ssl3.pwSpec = temp; | |
| 918 + ssl_ReleaseSpecWriteLock(ss); | |
| 919 + | |
| 920 + /* Update the lengths in the ClientHello to reflect this extension. */ | |
| 921 + ssl3_UpdateClientHelloLengths(ss, snap_start_extension_len_offset, sid); | |
| 922 + | |
| 923 + /* Keep a copy of the ClientHello around so that we can hash it in the case | |
| 924 + * the the Snap Start handshake is rejected. */ | |
| 925 + | |
| 926 + if (SECITEM_AllocItem(NULL, &ss->ssl3.hs.origClientHello, | |
| 927 + ss->sec.ci.sendBuf.len) == NULL) { | |
| 928 + goto loser; | |
| 929 + } | |
| 930 + memcpy(ss->ssl3.hs.origClientHello.data, ss->sec.ci.sendBuf.buf, | |
| 931 + ss->sec.ci.sendBuf.len); | |
| 932 + ss->ssl3.hs.origClientHello.len = ss->sec.ci.sendBuf.len; | |
| 933 + | |
| 934 + ss->xtnData.advertised[ss->xtnData.numAdvertised++] = ssl_snap_start_xtn; | |
| 935 + | |
| 936 + if (resuming) { | |
| 937 + ss->ssl3.hs.snapStartType = snap_start_resume; | |
| 938 + } else { | |
| 939 + ss->ssl3.hs.snapStartType = snap_start_full; | |
| 940 + } | |
| 941 + | |
| 942 + return 0; | |
| 943 + | |
| 944 +loser: | |
| 945 + /* In the case of an error we revert the length of the sendBuf to remove | |
| 946 + * any partial data that we may have appended. */ | |
| 947 + ss->sec.ci.sendBuf.len = original_sendbuf_len; | |
| 948 + return -1; | |
| 949 +} | |
| 950 + | |
| 951 +SECStatus ssl3_ClientHandleSnapStartXtn(sslSocket *ss, PRUint16 ex_type, | |
| 952 + SECItem *data) { | |
| 953 + /* The work of saving the ServerHello is done in ssl3_HandleServerHello, | |
| 954 + * where its contents are available. Here we renognise that the saved | |
| 955 + * ServerHello message contains a Snap Start extension and mark it as | |
| 956 + * valid. */ | |
| 957 + ss->ssl3.serverHelloPredictionDataValid = PR_TRUE; | |
| 958 + return SECSuccess; | |
| 959 +} | |
| 960 + | |
| 961 +SECStatus | |
| 962 +SSL_SetPredictedPeerCertificates(PRFileDesc *fd, CERTCertificate **certs, | |
| 963 + unsigned int numCerts) | |
| 964 +{ | |
| 965 + sslSocket *ss; | |
| 966 + unsigned int i; | |
| 967 + | |
| 968 + ss = ssl_FindSocket(fd); | |
| 969 + if (!ss) { | |
| 970 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPredictedPeerCertificates", | |
| 971 + SSL_GETPID(), fd)); | |
| 972 + return SECFailure; | |
| 973 + } | |
| 974 + | |
| 975 + ss->ssl3.predictedCertChain = | |
| 976 + PORT_NewArray(CERTCertificate*, numCerts + 1); | |
| 977 + if (!ss->ssl3.predictedCertChain) | |
| 978 + return SECFailure; /* error code was set */ | |
| 979 + for (i = 0; i < numCerts; i++) | |
| 980 + ss->ssl3.predictedCertChain[i] = CERT_DupCertificate(certs[i]); | |
| 981 + ss->ssl3.predictedCertChain[numCerts] = NULL; | |
| 982 + | |
| 983 + return SECSuccess; | |
| 984 +} | |
| 985 + | |
| 986 +void | |
| 987 +ssl3_CleanupPredictedPeerCertificates(sslSocket *ss) { | |
| 988 + unsigned int i; | |
| 989 + | |
| 990 + if (!ss->ssl3.predictedCertChain) | |
| 991 + return; | |
| 992 + | |
| 993 + for (i = 0; ss->ssl3.predictedCertChain[i]; i++) { | |
| 994 + CERT_DestroyCertificate(ss->ssl3.predictedCertChain[i]); | |
| 995 + } | |
| 996 + | |
| 997 + PORT_Free(ss->ssl3.predictedCertChain); | |
| 998 + ss->ssl3.predictedCertChain = NULL; | |
| 999 +} | |
| 1000 + | |
| 1001 +SECStatus | |
| 1002 +SSL_GetPredictedServerHelloData(PRFileDesc *fd, const unsigned char **data, | |
| 1003 + unsigned int *data_len) | |
| 1004 +{ | |
| 1005 + sslSocket *ss; | |
| 1006 + | |
| 1007 + ss = ssl_FindSocket(fd); | |
| 1008 + if (!ss) { | |
| 1009 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetPredictedServerHelloData", | |
| 1010 + SSL_GETPID(), fd)); | |
| 1011 + *data = NULL; | |
| 1012 + *data_len = 0; | |
| 1013 + return SECFailure; | |
| 1014 + } | |
| 1015 + | |
| 1016 + if (!ss->ssl3.serverHelloPredictionDataValid) { | |
| 1017 + *data = NULL; | |
| 1018 + *data_len = 0; | |
| 1019 + } else { | |
| 1020 + *data = ss->ssl3.serverHelloPredictionData.data; | |
| 1021 + *data_len = ss->ssl3.serverHelloPredictionData.len; | |
| 1022 + } | |
| 1023 + return SECSuccess; | |
| 1024 +} | |
| 1025 + | |
| 1026 +SECStatus | |
| 1027 +SSL_SetPredictedServerHelloData(PRFileDesc *fd, const unsigned char *data, | |
| 1028 + unsigned int data_len) | |
| 1029 +{ | |
| 1030 + sslSocket *ss; | |
| 1031 + | |
| 1032 + ss = ssl_FindSocket(fd); | |
| 1033 + if (!ss) { | |
| 1034 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPredictedServerHelloData", | |
| 1035 + SSL_GETPID(), fd)); | |
| 1036 + return SECFailure; | |
| 1037 + } | |
| 1038 + | |
| 1039 + if (ss->ssl3.serverHelloPredictionData.data) | |
| 1040 + SECITEM_FreeItem(&ss->ssl3.serverHelloPredictionData, PR_FALSE); | |
| 1041 + if (!SECITEM_AllocItem(NULL, &ss->ssl3.serverHelloPredictionData, data_len)
) | |
| 1042 + return SECFailure; | |
| 1043 + memcpy(ss->ssl3.serverHelloPredictionData.data, data, data_len); | |
| 1044 + return SECSuccess; | |
| 1045 +} | |
| 1046 + | |
| 1047 +SECStatus | |
| 1048 +SSL_SetSnapStartApplicationData(PRFileDesc *fd, const unsigned char *data, | |
| 1049 + unsigned int data_len) | |
| 1050 +{ | |
| 1051 + sslSocket *ss; | |
| 1052 + | |
| 1053 + ss = ssl_FindSocket(fd); | |
| 1054 + if (!ss) { | |
| 1055 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetSnapStartApplicationData", | |
| 1056 + SSL_GETPID(), fd)); | |
| 1057 + return SECFailure; | |
| 1058 + } | |
| 1059 + | |
| 1060 + if (ss->ssl3.snapStartApplicationData.data) | |
| 1061 + SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE); | |
| 1062 + if (!SECITEM_AllocItem(NULL, &ss->ssl3.snapStartApplicationData, data_len)) | |
| 1063 + return SECFailure; | |
| 1064 + memcpy(ss->ssl3.snapStartApplicationData.data, data, data_len); | |
| 1065 + return SECSuccess; | |
| 1066 +} | |
| 1067 + | |
| 1068 +SECStatus | |
| 1069 +SSL_GetSnapStartResult(PRFileDesc *fd, SSLSnapStartResult *result) | |
| 1070 +{ | |
| 1071 + sslSocket *ss; | |
| 1072 + | |
| 1073 + ss = ssl_FindSocket(fd); | |
| 1074 + if (!ss) { | |
| 1075 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetSnapStartResult", | |
| 1076 + SSL_GETPID(), fd)); | |
| 1077 + return SECFailure; | |
| 1078 + } | |
| 1079 + | |
| 1080 + switch (ss->ssl3.hs.snapStartType) { | |
| 1081 + case snap_start_full: | |
| 1082 + *result = SSL_SNAP_START_FULL; | |
| 1083 + break; | |
| 1084 + case snap_start_recovery: | |
| 1085 + *result = SSL_SNAP_START_RECOVERY; | |
| 1086 + break; | |
| 1087 + case snap_start_resume: | |
| 1088 + *result = SSL_SNAP_START_RESUME; | |
| 1089 + break; | |
| 1090 + case snap_start_resume_recovery: | |
| 1091 + *result = SSL_SNAP_START_RESUME_RECOVERY; | |
| 1092 + break; | |
| 1093 + default: | |
| 1094 + PORT_Assert(ss->ssl3.hs.snapStartType == snap_start_none); | |
| 1095 + *result = SSL_SNAP_START_NONE; | |
| 1096 + break; | |
| 1097 + } | |
| 1098 + | |
| 1099 + return SECSuccess; | |
| 1100 +} | |
| 1101 + | |
| 1102 +/* Called form ssl3_HandleServerHello in the case that we sent a Snap Start | |
| 1103 +** ClientHello but received a ServerHello in reply. | |
| 1104 +*/ | |
| 1105 +SECStatus | |
| 1106 +ssl3_ResetForSnapStartRecovery(sslSocket *ss, SSL3Opaque *b, PRUint32 length) | |
| 1107 +{ | |
| 1108 + SECStatus rv; | |
| 1109 + PRUint8 hdr[4]; | |
| 1110 + | |
| 1111 + ss->ssl3.hs.ws = wait_server_hello; | |
| 1112 + | |
| 1113 + /* Need to reset the Finished hashes to include the full ClientHello | |
| 1114 + * message. */ | |
| 1115 + | |
| 1116 + rv = ssl3_RestartHandshakeHashes(ss); | |
| 1117 + if (rv != SECSuccess) | |
| 1118 + return rv; | |
| 1119 + rv = ssl3_UpdateHandshakeHashes(ss, ss->ssl3.hs.origClientHello.data, | |
| 1120 + ss->ssl3.hs.origClientHello.len); | |
| 1121 + SECITEM_FreeItem(&ss->ssl3.hs.origClientHello, PR_FALSE); | |
| 1122 + if (rv != SECSuccess) | |
| 1123 + return rv; | |
| 1124 + | |
| 1125 + hdr[0] = (PRUint8)server_hello; | |
| 1126 + hdr[1] = (PRUint8)(length >> 16); | |
| 1127 + hdr[2] = (PRUint8)(length >> 8); | |
| 1128 + hdr[3] = (PRUint8)(length ); | |
| 1129 + | |
| 1130 + rv = ssl3_UpdateHandshakeHashes(ss, hdr, sizeof(hdr)); | |
| 1131 + if (rv != SECSuccess) | |
| 1132 + return rv; | |
| 1133 + rv = ssl3_UpdateHandshakeHashes(ss, b, length); | |
| 1134 + if (rv != SECSuccess) | |
| 1135 + return rv; | |
| 1136 + | |
| 1137 + if (ss->ssl3.hs.snapStartType == snap_start_full) { | |
| 1138 + ss->ssl3.hs.snapStartType = snap_start_recovery; | |
| 1139 + } else { | |
| 1140 + ss->ssl3.hs.snapStartType = snap_start_resume_recovery; | |
| 1141 + } | |
| 1142 + | |
| 1143 + ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_TRUE/*freeSrvName*/); | |
| 1144 + | |
| 1145 + return SECSuccess; | |
| 1146 +} | |
| 1147 diff --git a/mozilla/security/nss/lib/ssl/ssl.def b/mozilla/security/nss/lib/ssl
/ssl.def | |
| 1148 index a1f4b51..effc35d 100644 | |
| 1149 --- a/mozilla/security/nss/lib/ssl/ssl.def | |
| 1150 +++ b/mozilla/security/nss/lib/ssl/ssl.def | |
| 1151 @@ -159,3 +159,13 @@ SSL_SetNextProtoNego; | |
| 1152 ;+ local: | |
| 1153 ;+*; | |
| 1154 ;+}; | |
| 1155 +;+NSS_3.13 { # NSS 3.13 release | |
| 1156 +;+ global: | |
| 1157 +SSL_GetPredictedServerHelloData; | |
| 1158 +SSL_GetSnapStartResult; | |
| 1159 +SSL_SetPredictedPeerCertificates; | |
| 1160 +SSL_SetPredictedServerHelloData; | |
| 1161 +SSL_SetSnapStartApplicationData; | |
| 1162 +;+ local: | |
| 1163 +;+*; | |
| 1164 +;+}; | |
| 1165 diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/s
sl.h | |
| 1166 index d87ae56..8217d2e 100644 | |
| 1167 --- a/mozilla/security/nss/lib/ssl/ssl.h | |
| 1168 +++ b/mozilla/security/nss/lib/ssl/ssl.h | |
| 1169 @@ -139,6 +139,15 @@ SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFi
leDesc *fd); | |
| 1170 /* occur on RSA or DH ciphersuites where the cipher's key length is >= 80 */ | |
| 1171 /* bits. The advantage of False Start is that it saves a round trip for */ | |
| 1172 /* client-speaks-first protocols when performing a full handshake. */ | |
| 1173 +#define SSL_ENABLE_SNAP_START 23 /* Enable SSL snap start (off by */ | |
| 1174 + /* default, applies only to */ | |
| 1175 + /* clients). Snap start is a way */ | |
| 1176 +/* of performing TLS handshakes with no round trips. The client's entire */ | |
| 1177 +/* handshake is included in the first handshake message, along with */ | |
| 1178 +/* optional application data. In order to do this, information from a */ | |
| 1179 +/* previous connection to the same server is required. See */ | |
| 1180 +/* SSL_GetPredictedServerHelloData, SSL_SetPredictedPeerCertificates and */ | |
| 1181 +/* SSL_SetSnapStartApplicationData. */ | |
| 1182 | |
| 1183 #ifdef SSL_DEPRECATED_FUNCTION | |
| 1184 /* Old deprecated function names */ | |
| 1185 @@ -376,6 +385,49 @@ SSL_IMPORT SECStatus SSL_BadCertHook(PRFileDesc *fd, SSLBad
CertHandler f, | |
| 1186 void *arg); | |
| 1187 | |
| 1188 /* | |
| 1189 +** Set the predicted chain of certificates for the peer. This is used for the | |
| 1190 +** TLS Snap Start extension. Note that the SSL_ENABLE_SNAP_START option must | |
| 1191 +** be set for this to occur. | |
| 1192 +** | |
| 1193 +** This function takes a reference to each of the given certificates. | |
| 1194 +*/ | |
| 1195 +SSL_IMPORT SECStatus SSL_SetPredictedPeerCertificates( | |
| 1196 + PRFileDesc *fd, CERTCertificate **certs, | |
| 1197 + unsigned int numCerts); | |
| 1198 + | |
| 1199 +/* | |
| 1200 +** Get the data needed to predict the server's hello message in the future. On | |
| 1201 +** return, |*data| will either be NULL (in which case no data is available and | |
| 1202 +** |*data_len| will be zero) or it will point to a buffer within the internal | |
| 1203 +** data of |fd| and |*data_len| will contain the number of bytes available. If | |
| 1204 +** non-NULL, |*data| will persist at least until the next handshake on |fd|. | |
| 1205 +*/ | |
| 1206 +SSL_IMPORT SECStatus SSL_GetPredictedServerHelloData( | |
| 1207 + PRFileDesc *fd, const unsigned char **data, | |
| 1208 + unsigned int *data_len); | |
| 1209 + | |
| 1210 +/* | |
| 1211 +** Set the predicted server hello data. This is used for the TLS Snap Start | |
| 1212 +** extension. Note that the SSL_ENABLE_SNAP_START option must be set for this | |
| 1213 +** to occur. | |
| 1214 +*/ | |
| 1215 +SSL_IMPORT SECStatus SSL_SetPredictedServerHelloData( | |
| 1216 + PRFileDesc *fd, const unsigned char *data, unsigned int data_len); | |
| 1217 + | |
| 1218 +/* Set the application data which will be transmitted in a Snap Start | |
| 1219 +** handshake. If the Snap Start handshake fails, this data will be | |
| 1220 +* retransmitted automatically. */ | |
| 1221 +SSL_IMPORT SECStatus SSL_SetSnapStartApplicationData( | |
| 1222 + PRFileDesc *fd, const unsigned char *data, unsigned int data_len); | |
| 1223 + | |
| 1224 +/* Get the result of a Snap Start handshake. It's valid to call then even if | |
| 1225 +** SSL_ENABLE_SNAP_START hasn't been set, although the result will always be | |
| 1226 +** SSL_SNAP_START_NONE. | |
| 1227 +*/ | |
| 1228 +SSL_IMPORT SECStatus SSL_GetSnapStartResult(PRFileDesc* socket, | |
| 1229 + SSLSnapStartResult* result); | |
| 1230 + | |
| 1231 +/* | |
| 1232 ** Configure SSL socket for running a secure server. Needs the | |
| 1233 ** certificate for the server and the servers private key. The arguments | |
| 1234 ** are copied. | |
| 1235 diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/s
sl/ssl3con.c | |
| 1236 index 64c3452..9ab2a1c 100644 | |
| 1237 --- a/mozilla/security/nss/lib/ssl/ssl3con.c | |
| 1238 +++ b/mozilla/security/nss/lib/ssl/ssl3con.c | |
| 1239 @@ -72,7 +72,8 @@ | |
| 1240 #endif | |
| 1241 | |
| 1242 static void ssl3_CleanupPeerCerts(sslSocket *ss); | |
| 1243 -static void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid); | |
| 1244 +static void ssl3_CopyPeerCertsToSID(ssl3CertNode *certs, | |
| 1245 + sslSessionID *sid); | |
| 1246 static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, | |
| 1247 PK11SlotInfo * serverKeySlot); | |
| 1248 static SECStatus ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms); | |
| 1249 @@ -82,14 +83,10 @@ static SECStatus ssl3_InitState( sslSocket *ss); | |
| 1250 static SECStatus ssl3_SendCertificate( sslSocket *ss); | |
| 1251 static SECStatus ssl3_SendEmptyCertificate( sslSocket *ss); | |
| 1252 static SECStatus ssl3_SendCertificateRequest(sslSocket *ss); | |
| 1253 -static SECStatus ssl3_SendNextProto( sslSocket *ss); | |
| 1254 -static SECStatus ssl3_SendFinished( sslSocket *ss, PRInt32 flags); | |
| 1255 static SECStatus ssl3_SendServerHello( sslSocket *ss); | |
| 1256 static SECStatus ssl3_SendServerHelloDone( sslSocket *ss); | |
| 1257 static SECStatus ssl3_SendServerKeyExchange( sslSocket *ss); | |
| 1258 static SECStatus ssl3_NewHandshakeHashes( sslSocket *ss); | |
| 1259 -static SECStatus ssl3_UpdateHandshakeHashes( sslSocket *ss, unsigned char *b, | |
| 1260 - unsigned int l); | |
| 1261 | |
| 1262 static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen, | |
| 1263 int maxOutputLen, const unsigned char *input, | |
| 1264 @@ -583,7 +580,7 @@ void SSL_AtomicIncrementLong(long * x) | |
| 1265 | |
| 1266 /* return pointer to ssl3CipherSuiteDef for suite, or NULL */ | |
| 1267 /* XXX This does a linear search. A binary search would be better. */ | |
| 1268 -static const ssl3CipherSuiteDef * | |
| 1269 +const ssl3CipherSuiteDef * | |
| 1270 ssl_LookupCipherSuiteDef(ssl3CipherSuite suite) | |
| 1271 { | |
| 1272 int cipher_suite_def_len = | |
| 1273 @@ -1169,7 +1166,7 @@ ssl3_CleanupKeyMaterial(ssl3KeyMaterial *mat) | |
| 1274 ** ssl3_DestroySSL3Info | |
| 1275 ** Caller must hold SpecWriteLock. | |
| 1276 */ | |
| 1277 -static void | |
| 1278 +void | |
| 1279 ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName) | |
| 1280 { | |
| 1281 PRBool freeit = (PRBool)(!spec->bypassCiphers); | |
| 1282 @@ -1211,7 +1208,7 @@ ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSr
vName) | |
| 1283 ** Caller must hold the ssl3 handshake lock. | |
| 1284 ** Acquires & releases SpecWriteLock. | |
| 1285 */ | |
| 1286 -static SECStatus | |
| 1287 +SECStatus | |
| 1288 ssl3_SetupPendingCipherSpec(sslSocket *ss) | |
| 1289 { | |
| 1290 ssl3CipherSpec * pwSpec; | |
| 1291 @@ -2039,7 +2036,7 @@ ssl3_ClientAuthTokenPresent(sslSessionID *sid) { | |
| 1292 return isPresent; | |
| 1293 } | |
| 1294 | |
| 1295 -static SECStatus | |
| 1296 +SECStatus | |
| 1297 ssl3_CompressMACEncryptRecord(sslSocket * ss, | |
| 1298 SSL3ContentType type, | |
| 1299 const SSL3Opaque * pIn, | |
| 1300 @@ -3097,7 +3094,7 @@ loser: | |
| 1301 return SECFailure; | |
| 1302 } | |
| 1303 | |
| 1304 -static SECStatus | |
| 1305 +SECStatus | |
| 1306 ssl3_RestartHandshakeHashes(sslSocket *ss) | |
| 1307 { | |
| 1308 SECStatus rv = SECSuccess; | |
| 1309 @@ -3175,7 +3172,7 @@ loser: | |
| 1310 ** ssl3_HandleHandshakeMessage() | |
| 1311 ** Caller must hold the ssl3Handshake lock. | |
| 1312 */ | |
| 1313 -static SECStatus | |
| 1314 +SECStatus | |
| 1315 ssl3_UpdateHandshakeHashes(sslSocket *ss, unsigned char *b, unsigned int l) | |
| 1316 { | |
| 1317 SECStatus rv = SECSuccess; | |
| 1318 @@ -3434,7 +3431,7 @@ ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, P
RInt32 bytes, | |
| 1319 * Caller must hold a read or write lock on the Spec R/W lock. | |
| 1320 * (There is presently no way to assert on a Read lock.) | |
| 1321 */ | |
| 1322 -static SECStatus | |
| 1323 +SECStatus | |
| 1324 ssl3_ComputeHandshakeHashes(sslSocket * ss, | |
| 1325 ssl3CipherSpec *spec, /* uses ->master_secret */ | |
| 1326 SSL3Hashes * hashes, /* output goes here. */ | |
| 1327 @@ -4032,7 +4029,18 @@ ssl3_SendClientHello(sslSocket *ss) | |
| 1328 return rv; /* error code set by ssl3_FlushHandshake */ | |
| 1329 } | |
| 1330 | |
| 1331 - ss->ssl3.hs.ws = wait_server_hello; | |
| 1332 + switch (ss->ssl3.hs.snapStartType) { | |
| 1333 + case snap_start_full: | |
| 1334 + ss->ssl3.hs.ws = wait_new_session_ticket; | |
| 1335 + break; | |
| 1336 + case snap_start_resume: | |
| 1337 + ss->ssl3.hs.ws = wait_change_cipher; | |
| 1338 + break; | |
| 1339 + default: | |
| 1340 + ss->ssl3.hs.ws = wait_server_hello; | |
| 1341 + break; | |
| 1342 + } | |
| 1343 + | |
| 1344 return rv; | |
| 1345 } | |
| 1346 | |
| 1347 @@ -4723,7 +4731,7 @@ loser: | |
| 1348 | |
| 1349 | |
| 1350 /* Called from ssl3_HandleServerHelloDone(). */ | |
| 1351 -static SECStatus | |
| 1352 +SECStatus | |
| 1353 ssl3_SendClientKeyExchange(sslSocket *ss) | |
| 1354 { | |
| 1355 SECKEYPublicKey * serverKey = NULL; | |
| 1356 @@ -4862,6 +4870,94 @@ done: | |
| 1357 return rv; | |
| 1358 } | |
| 1359 | |
| 1360 +/* Called from ssl3_HandleServerHello to set up the master secret in | |
| 1361 + * ss->ssl3.pwSpec and the auth algorithm and kea type in ss->sec in the case | |
| 1362 + * of a successful session resumption. */ | |
| 1363 +SECStatus ssl3_SetupMasterSecretFromSessionID(sslSocket* ss) { | |
| 1364 + sslSessionID *sid = ss->sec.ci.sid; | |
| 1365 + ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec; | |
| 1366 + SECItem wrappedMS; /* wrapped master secret. */ | |
| 1367 + | |
| 1368 + ss->sec.authAlgorithm = sid->authAlgorithm; | |
| 1369 + ss->sec.authKeyBits = sid->authKeyBits; | |
| 1370 + ss->sec.keaType = sid->keaType; | |
| 1371 + ss->sec.keaKeyBits = sid->keaKeyBits; | |
| 1372 + | |
| 1373 + /* 3 cases here: | |
| 1374 + * a) key is wrapped (implies using PKCS11) | |
| 1375 + * b) key is unwrapped, but we're still using PKCS11 | |
| 1376 + * c) key is unwrapped, and we're bypassing PKCS11. | |
| 1377 + */ | |
| 1378 + if (sid->u.ssl3.keys.msIsWrapped) { | |
| 1379 + PK11SlotInfo *slot; | |
| 1380 + PK11SymKey * wrapKey; /* wrapping key */ | |
| 1381 + CK_FLAGS keyFlags = 0; | |
| 1382 + | |
| 1383 + if (ss->opt.bypassPKCS11) { | |
| 1384 + /* we cannot restart a non-bypass session in a | |
| 1385 + ** bypass socket. | |
| 1386 + */ | |
| 1387 + return SECFailure; | |
| 1388 + } | |
| 1389 + /* unwrap master secret with PKCS11 */ | |
| 1390 + slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID, | |
| 1391 + sid->u.ssl3.masterSlotID); | |
| 1392 + if (slot == NULL) { | |
| 1393 + return SECFailure; | |
| 1394 + } | |
| 1395 + if (!PK11_IsPresent(slot)) { | |
| 1396 + PK11_FreeSlot(slot); | |
| 1397 + return SECFailure; | |
| 1398 + } | |
| 1399 + wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex, | |
| 1400 + sid->u.ssl3.masterWrapMech, | |
| 1401 + sid->u.ssl3.masterWrapSeries, | |
| 1402 + ss->pkcs11PinArg); | |
| 1403 + PK11_FreeSlot(slot); | |
| 1404 + if (wrapKey == NULL) { | |
| 1405 + return SECFailure; | |
| 1406 + } | |
| 1407 + | |
| 1408 + if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ | |
| 1409 + keyFlags = CKF_SIGN | CKF_VERIFY; | |
| 1410 + } | |
| 1411 + | |
| 1412 + wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; | |
| 1413 + wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; | |
| 1414 + pwSpec->master_secret = | |
| 1415 + PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech, | |
| 1416 + NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE, | |
| 1417 + CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags); | |
| 1418 + PK11_FreeSymKey(wrapKey); | |
| 1419 + if (pwSpec->master_secret == NULL) { | |
| 1420 + return SECFailure; | |
| 1421 + } | |
| 1422 + } else if (ss->opt.bypassPKCS11) { | |
| 1423 + /* MS is not wrapped */ | |
| 1424 + wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; | |
| 1425 + wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; | |
| 1426 + memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len); | |
| 1427 + pwSpec->msItem.data = pwSpec->raw_master_secret; | |
| 1428 + pwSpec->msItem.len = wrappedMS.len; | |
| 1429 + } else { | |
| 1430 + /* We CAN restart a bypass session in a non-bypass socket. */ | |
| 1431 + /* need to import the raw master secret to session object */ | |
| 1432 + PK11SlotInfo *slot = PK11_GetInternalSlot(); | |
| 1433 + wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; | |
| 1434 + wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; | |
| 1435 + pwSpec->master_secret = | |
| 1436 + PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, | |
| 1437 + PK11_OriginUnwrap, CKA_ENCRYPT, | |
| 1438 + &wrappedMS, NULL); | |
| 1439 + PK11_FreeSlot(slot); | |
| 1440 + if (pwSpec->master_secret == NULL) { | |
| 1441 + return SECFailure; | |
| 1442 + } | |
| 1443 + } | |
| 1444 + | |
| 1445 + return SECSuccess; | |
| 1446 +} | |
| 1447 + | |
| 1448 /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete | |
| 1449 * ssl3 ServerHello message. | |
| 1450 * Caller must hold Handshake and RecvBuf locks. | |
| 1451 @@ -4886,6 +4982,14 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUi
nt32 length) | |
| 1452 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | |
| 1453 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); | |
| 1454 | |
| 1455 + if (ss->ssl3.hs.snapStartType == snap_start_full || | |
| 1456 + ss->ssl3.hs.snapStartType == snap_start_resume) { | |
| 1457 + /* Snap Start handshake was rejected. */ | |
| 1458 + rv = ssl3_ResetForSnapStartRecovery(ss, b, length); | |
| 1459 + if (rv != SECSuccess) | |
| 1460 + return rv; | |
| 1461 + } | |
| 1462 + | |
| 1463 rv = ssl3_InitState(ss); | |
| 1464 if (rv != SECSuccess) { | |
| 1465 errCode = PORT_GetError(); /* ssl3_InitState has set the error code. */ | |
| 1466 @@ -4897,6 +5001,21 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUi
nt32 length) | |
| 1467 goto alert_loser; | |
| 1468 } | |
| 1469 | |
| 1470 + if (!ss->ssl3.serverHelloPredictionData.data) { | |
| 1471 + /* If this allocation fails it will only stop the application from | |
| 1472 + * recording the ServerHello information and performing future Snap | |
| 1473 + * Starts. */ | |
| 1474 + if (SECITEM_AllocItem(NULL, &ss->ssl3.serverHelloPredictionData, | |
| 1475 + length)) | |
| 1476 + memcpy(ss->ssl3.serverHelloPredictionData.data, b, length); | |
| 1477 + /* ss->ssl3.serverHelloPredictionDataValid is still false at this | |
| 1478 + * point. We have to record the contents of the ServerHello here | |
| 1479 + * because we don't have a pointer to the whole message when handling | |
| 1480 + * the extensions. However, we wait until the Snap Start extenion | |
| 1481 + * handler to recognise that the server supports Snap Start and to set | |
| 1482 + * serverHelloPredictionDataValid. */ | |
| 1483 + } | |
| 1484 + | |
| 1485 temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); | |
| 1486 if (temp < 0) { | |
| 1487 goto loser; /* alert has been sent */ | |
| 1488 @@ -5037,118 +5156,40 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PR
Uint32 length) | |
| 1489 | |
| 1490 if (sid_match && | |
| 1491 sid->version == ss->version && | |
| 1492 - sid->u.ssl3.cipherSuite == ss->ssl3.hs.cipher_suite) do { | |
| 1493 - ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec; | |
| 1494 - | |
| 1495 - SECItem wrappedMS; /* wrapped master secret. */ | |
| 1496 + sid->u.ssl3.cipherSuite == ss->ssl3.hs.cipher_suite) { | |
| 1497 + rv = ssl3_SetupMasterSecretFromSessionID(ss); | |
| 1498 + /* Failure of ssl3_SetupMasterSecretFromSessionID not considered an | |
| 1499 + * error. Continue with a full handshake. */ | |
| 1500 + if (rv == SECSuccess) { | |
| 1501 + /* Got a Match */ | |
| 1502 + SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_hits ); | |
| 1503 | |
| 1504 - ss->sec.authAlgorithm = sid->authAlgorithm; | |
| 1505 - ss->sec.authKeyBits = sid->authKeyBits; | |
| 1506 - ss->sec.keaType = sid->keaType; | |
| 1507 - ss->sec.keaKeyBits = sid->keaKeyBits; | |
| 1508 + /* If we sent a session ticket, then this is a stateless resume. */ | |
| 1509 + if (sid->version > SSL_LIBRARY_VERSION_3_0 && | |
| 1510 + sid->u.ssl3.sessionTicket.ticket.data != NULL) | |
| 1511 + SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_stateless_resumes ); | |
| 1512 | |
| 1513 - /* 3 cases here: | |
| 1514 - * a) key is wrapped (implies using PKCS11) | |
| 1515 - * b) key is unwrapped, but we're still using PKCS11 | |
| 1516 - * c) key is unwrapped, and we're bypassing PKCS11. | |
| 1517 - */ | |
| 1518 - if (sid->u.ssl3.keys.msIsWrapped) { | |
| 1519 - PK11SlotInfo *slot; | |
| 1520 - PK11SymKey * wrapKey; /* wrapping key */ | |
| 1521 - CK_FLAGS keyFlags = 0; | |
| 1522 + if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn)) | |
| 1523 + ss->ssl3.hs.ws = wait_new_session_ticket; | |
| 1524 + else | |
| 1525 + ss->ssl3.hs.ws = wait_change_cipher; | |
| 1526 | |
| 1527 - if (ss->opt.bypassPKCS11) { | |
| 1528 - /* we cannot restart a non-bypass session in a | |
| 1529 - ** bypass socket. | |
| 1530 - */ | |
| 1531 - break; | |
| 1532 - } | |
| 1533 - /* unwrap master secret with PKCS11 */ | |
| 1534 - slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID, | |
| 1535 - sid->u.ssl3.masterSlotID); | |
| 1536 - if (slot == NULL) { | |
| 1537 - break; /* not considered an error. */ | |
| 1538 - } | |
| 1539 - if (!PK11_IsPresent(slot)) { | |
| 1540 - PK11_FreeSlot(slot); | |
| 1541 - break; /* not considered an error. */ | |
| 1542 - } | |
| 1543 - wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex, | |
| 1544 - sid->u.ssl3.masterWrapMech, | |
| 1545 - sid->u.ssl3.masterWrapSeries, | |
| 1546 - ss->pkcs11PinArg); | |
| 1547 - PK11_FreeSlot(slot); | |
| 1548 - if (wrapKey == NULL) { | |
| 1549 - break; /* not considered an error. */ | |
| 1550 - } | |
| 1551 + ss->ssl3.hs.isResuming = PR_TRUE; | |
| 1552 | |
| 1553 - if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ | |
| 1554 - keyFlags = CKF_SIGN | CKF_VERIFY; | |
| 1555 + /* copy the peer cert from the SID */ | |
| 1556 + if (sid->peerCert != NULL) { | |
| 1557 + ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); | |
| 1558 + ssl3_CopyPeerCertsFromSID(ss, sid); | |
| 1559 } | |
| 1560 | |
| 1561 - wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; | |
| 1562 - wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; | |
| 1563 - pwSpec->master_secret = | |
| 1564 - PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech, | |
| 1565 - NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE, | |
| 1566 - CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags); | |
| 1567 - errCode = PORT_GetError(); | |
| 1568 - PK11_FreeSymKey(wrapKey); | |
| 1569 - if (pwSpec->master_secret == NULL) { | |
| 1570 - break; /* errorCode set just after call to UnwrapSymKey. */ | |
| 1571 - } | |
| 1572 - } else if (ss->opt.bypassPKCS11) { | |
| 1573 - /* MS is not wrapped */ | |
| 1574 - wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; | |
| 1575 - wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; | |
| 1576 - memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len); | |
| 1577 - pwSpec->msItem.data = pwSpec->raw_master_secret; | |
| 1578 - pwSpec->msItem.len = wrappedMS.len; | |
| 1579 - } else { | |
| 1580 - /* We CAN restart a bypass session in a non-bypass socket. */ | |
| 1581 - /* need to import the raw master secret to session object */ | |
| 1582 - PK11SlotInfo *slot = PK11_GetInternalSlot(); | |
| 1583 - wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; | |
| 1584 - wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; | |
| 1585 - pwSpec->master_secret = | |
| 1586 - PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, | |
| 1587 - PK11_OriginUnwrap, CKA_ENCRYPT, | |
| 1588 - &wrappedMS, NULL); | |
| 1589 - PK11_FreeSlot(slot); | |
| 1590 - if (pwSpec->master_secret == NULL) { | |
| 1591 - break; | |
| 1592 + /* NULL value for PMS signifies re-use of the old MS */ | |
| 1593 + rv = ssl3_InitPendingCipherSpec(ss, NULL); | |
| 1594 + if (rv != SECSuccess) { | |
| 1595 + goto alert_loser; | |
| 1596 } | |
| 1597 + return SECSuccess; | |
| 1598 } | |
| 1599 - | |
| 1600 - /* Got a Match */ | |
| 1601 - SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_hits ); | |
| 1602 - | |
| 1603 - /* If we sent a session ticket, then this is a stateless resume. */ | |
| 1604 - if (sid->version > SSL_LIBRARY_VERSION_3_0 && | |
| 1605 - sid->u.ssl3.sessionTicket.ticket.data != NULL) | |
| 1606 - SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_stateless_resumes ); | |
| 1607 - | |
| 1608 - if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn)) | |
| 1609 - ss->ssl3.hs.ws = wait_new_session_ticket; | |
| 1610 - else | |
| 1611 - ss->ssl3.hs.ws = wait_change_cipher; | |
| 1612 - | |
| 1613 - ss->ssl3.hs.isResuming = PR_TRUE; | |
| 1614 - | |
| 1615 - /* copy the peer cert from the SID */ | |
| 1616 - if (sid->peerCert != NULL) { | |
| 1617 - ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); | |
| 1618 - ssl3_CopyPeerCertsFromSID(ss, sid); | |
| 1619 - } | |
| 1620 - | |
| 1621 - | |
| 1622 - /* NULL value for PMS signifies re-use of the old MS */ | |
| 1623 - rv = ssl3_InitPendingCipherSpec(ss, NULL); | |
| 1624 - if (rv != SECSuccess) { | |
| 1625 - goto alert_loser; /* err code was set */ | |
| 1626 - } | |
| 1627 - return SECSuccess; | |
| 1628 - } while (0); | |
| 1629 + } | |
| 1630 | |
| 1631 if (sid_match) | |
| 1632 SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_not_ok ); | |
| 1633 @@ -6116,7 +6157,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUin
t32 length) | |
| 1634 * ticket extension, but sent an empty ticket. | |
| 1635 */ | |
| 1636 if (!ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) || | |
| 1637 - ss->xtnData.emptySessionTicket) { | |
| 1638 + ss->xtnData.serverReceivedEmptySessionTicket) { | |
| 1639 if (sidBytes.len > 0 && !ss->opt.noCache) { | |
| 1640 SSL_TRC(7, ("%d: SSL3[%d]: server, lookup client session-id for 0x%0
8x%08x%08x%08x", | |
| 1641 SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0], | |
| 1642 @@ -7569,6 +7610,12 @@ ssl3_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b,
PRUint32 length) | |
| 1643 return SECFailure; /* malformed */ | |
| 1644 } | |
| 1645 | |
| 1646 + if (ss->sec.ci.sid->peerCert == NULL) { | |
| 1647 + ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert); | |
| 1648 + ssl3_CopyPeerCertsToSID((ssl3CertNode *)ss->ssl3.peerCertChain, | |
| 1649 + ss->sec.ci.sid); | |
| 1650 + } | |
| 1651 + | |
| 1652 rv = ssl3_SetSIDSessionTicket(ss->sec.ci.sid, &session_ticket); | |
| 1653 if (rv != SECSuccess) { | |
| 1654 (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure); | |
| 1655 @@ -7760,7 +7807,7 @@ ssl3_CleanupPeerCerts(sslSocket *ss) | |
| 1656 ss->ssl3.peerCertChain = NULL; | |
| 1657 } | |
| 1658 | |
| 1659 -static void | |
| 1660 +void | |
| 1661 ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid) | |
| 1662 { | |
| 1663 PRArenaPool *arena; | |
| 1664 @@ -8163,7 +8210,7 @@ ssl3_RestartHandshakeAfterServerCert(sslSocket *ss) | |
| 1665 return rv; | |
| 1666 } | |
| 1667 | |
| 1668 -static SECStatus | |
| 1669 +SECStatus | |
| 1670 ssl3_ComputeTLSFinished(ssl3CipherSpec *spec, | |
| 1671 PRBool isServer, | |
| 1672 const SSL3Finished * hashes, | |
| 1673 @@ -8211,7 +8258,7 @@ ssl3_ComputeTLSFinished(ssl3CipherSpec *spec, | |
| 1674 | |
| 1675 /* called from ssl3_HandleServerHelloDone | |
| 1676 */ | |
| 1677 -static SECStatus | |
| 1678 +SECStatus | |
| 1679 ssl3_SendNextProto(sslSocket *ss) | |
| 1680 { | |
| 1681 SECStatus rv; | |
| 1682 @@ -8247,7 +8294,7 @@ ssl3_SendNextProto(sslSocket *ss) | |
| 1683 * ssl3_HandleClientHello | |
| 1684 * ssl3_HandleFinished | |
| 1685 */ | |
| 1686 -static SECStatus | |
| 1687 +SECStatus | |
| 1688 ssl3_SendFinished(sslSocket *ss, PRInt32 flags) | |
| 1689 { | |
| 1690 ssl3CipherSpec *cwSpec; | |
| 1691 @@ -8300,10 +8347,27 @@ ssl3_SendFinished(sslSocket *ss, PRInt32 flags) | |
| 1692 if (rv != SECSuccess) | |
| 1693 goto fail; /* err set by AppendHandshake. */ | |
| 1694 } | |
| 1695 - rv = ssl3_FlushHandshake(ss, flags); | |
| 1696 - if (rv != SECSuccess) { | |
| 1697 - goto fail; /* error code set by ssl3_FlushHandshake */ | |
| 1698 + if ((flags & ssl_SEND_FLAG_NO_FLUSH) == 0) { | |
| 1699 + rv = ssl3_FlushHandshake(ss, flags); | |
| 1700 + if (rv != SECSuccess) { | |
| 1701 + goto fail; /* error code set by ssl3_FlushHandshake */ | |
| 1702 + } | |
| 1703 } | |
| 1704 + | |
| 1705 + if ((ss->ssl3.hs.snapStartType == snap_start_recovery || | |
| 1706 + ss->ssl3.hs.snapStartType == snap_start_resume_recovery) && | |
| 1707 + ss->ssl3.snapStartApplicationData.data) { | |
| 1708 + /* In the event that the server ignored the application data in our | |
| 1709 + * snap start extension, we need to retransmit it now. */ | |
| 1710 + PRInt32 sent = ssl3_SendRecord(ss, content_application_data, | |
| 1711 + ss->ssl3.snapStartApplicationData.data, | |
| 1712 + ss->ssl3.snapStartApplicationData.len, | |
| 1713 + flags); | |
| 1714 + SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE); | |
| 1715 + if (sent < 0) | |
| 1716 + return (SECStatus)sent; /* error code set by ssl3_SendRecord */ | |
| 1717 + } | |
| 1718 + | |
| 1719 return SECSuccess; | |
| 1720 | |
| 1721 fail: | |
| 1722 @@ -8420,6 +8484,16 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint3
2 length, | |
| 1723 return SECFailure; | |
| 1724 } | |
| 1725 | |
| 1726 + if (ss->ssl3.hs.snapStartType == snap_start_full || | |
| 1727 + ss->ssl3.hs.snapStartType == snap_start_resume) { | |
| 1728 + /* Snap Start handshake was successful. Switch the cipher spec. */ | |
| 1729 + ssl_GetSpecWriteLock(ss); | |
| 1730 + ssl3_DestroyCipherSpec(ss->ssl3.cwSpec, PR_TRUE/*freeSrvName*/); | |
| 1731 + ss->ssl3.cwSpec = ss->ssl3.pwSpec; | |
| 1732 + ss->ssl3.pwSpec = NULL; | |
| 1733 + ssl_ReleaseSpecWriteLock(ss); | |
| 1734 + } | |
| 1735 + | |
| 1736 isTLS = (PRBool)(ss->ssl3.crSpec->version > SSL_LIBRARY_VERSION_3_0); | |
| 1737 if (isTLS) { | |
| 1738 TLSFinished tlsFinished; | |
| 1739 @@ -8429,12 +8503,21 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint
32 length, | |
| 1740 PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED); | |
| 1741 return SECFailure; | |
| 1742 } | |
| 1743 - rv = ssl3_ComputeTLSFinished(ss->ssl3.crSpec, !isServer, | |
| 1744 - hashes, &tlsFinished); | |
| 1745 - if (!isServer) | |
| 1746 - ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished; | |
| 1747 - else | |
| 1748 - ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished; | |
| 1749 + | |
| 1750 + if (ss->ssl3.hs.snapStartType == snap_start_resume) { | |
| 1751 + /* In this case we have already advanced the Finished hash past the | |
| 1752 + * server's verify_data because we needed to predict the server's | |
| 1753 + * Finished message in order to compute our own (which includes | |
| 1754 + * it). When we did this, we stored a copy in tFinished[1]. */ | |
| 1755 + tlsFinished = ss->ssl3.hs.finishedMsgs.tFinished[1]; | |
| 1756 + } else { | |
| 1757 + rv = ssl3_ComputeTLSFinished(ss->ssl3.crSpec, !isServer, | |
| 1758 + hashes, &tlsFinished); | |
| 1759 + if (!isServer) | |
| 1760 + ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished; | |
| 1761 + else | |
| 1762 + ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished; | |
| 1763 + } | |
| 1764 ss->ssl3.hs.finishedBytes = sizeof tlsFinished; | |
| 1765 if (rv != SECSuccess || | |
| 1766 0 != NSS_SecureMemcmp(&tlsFinished, b, length)) { | |
| 1767 @@ -8465,8 +8548,9 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32
length, | |
| 1768 | |
| 1769 ssl_GetXmitBufLock(ss); /*************************************/ | |
| 1770 | |
| 1771 - if ((isServer && !ss->ssl3.hs.isResuming) || | |
| 1772 - (!isServer && ss->ssl3.hs.isResuming)) { | |
| 1773 + if (ss->ssl3.hs.snapStartType != snap_start_resume && | |
| 1774 + ((isServer && !ss->ssl3.hs.isResuming) || | |
| 1775 + (!isServer && ss->ssl3.hs.isResuming))) { | |
| 1776 PRInt32 flags = 0; | |
| 1777 | |
| 1778 /* Send a NewSessionTicket message if the client sent us | |
| 1779 @@ -8582,7 +8666,10 @@ xmit_loser: | |
| 1780 ss->ssl3.hs.ws = idle_handshake; | |
| 1781 | |
| 1782 /* Do the handshake callback for sslv3 here, if we cannot false start. */ | |
| 1783 - if (ss->handshakeCallback != NULL && !ssl3_CanFalseStart(ss)) { | |
| 1784 + if (ss->handshakeCallback != NULL && | |
| 1785 + (!ssl3_CanFalseStart(ss) || | |
| 1786 + ss->ssl3.hs.snapStartType == snap_start_full || | |
| 1787 + ss->ssl3.hs.snapStartType == snap_start_resume)) { | |
| 1788 (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData); | |
| 1789 } | |
| 1790 | |
| 1791 @@ -8643,8 +8730,13 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b,
PRUint32 length) | |
| 1792 return rv; | |
| 1793 } | |
| 1794 } | |
| 1795 - /* We should not include hello_request messages in the handshake hashes */ | |
| 1796 - if (ss->ssl3.hs.msg_type != hello_request) { | |
| 1797 + /* We should not include hello_request messages in the handshake hashes. | |
| 1798 + * Likewise, for Finished messages from the server during a Snap Start | |
| 1799 + * resume, we have already predicted and included the message in our | |
| 1800 + * Finished hash. */ | |
| 1801 + if (ss->ssl3.hs.msg_type != hello_request && | |
| 1802 + !(ss->ssl3.hs.msg_type == finished && | |
| 1803 + ss->ssl3.hs.snapStartType == snap_start_resume)) { | |
| 1804 rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char*) hdr, 4); | |
| 1805 if (rv != SECSuccess) return rv; /* err code already set. */ | |
| 1806 rv = ssl3_UpdateHandshakeHashes(ss, b, length); | |
| 1807 @@ -9545,6 +9637,15 @@ ssl3_DestroySSL3Info(sslSocket *ss) | |
| 1808 ss->ssl3.clientCertChain = NULL; | |
| 1809 } | |
| 1810 | |
| 1811 + if (ss->ssl3.predictedCertChain != NULL) | |
| 1812 + ssl3_CleanupPredictedPeerCertificates(ss); | |
| 1813 + | |
| 1814 + if (ss->ssl3.serverHelloPredictionData.data) | |
| 1815 + SECITEM_FreeItem(&ss->ssl3.serverHelloPredictionData, PR_FALSE); | |
| 1816 + | |
| 1817 + if (ss->ssl3.snapStartApplicationData.data) | |
| 1818 + SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE); | |
| 1819 + | |
| 1820 /* clean up handshake */ | |
| 1821 if (ss->opt.bypassPKCS11) { | |
| 1822 SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE); | |
| 1823 @@ -9562,6 +9663,9 @@ ssl3_DestroySSL3Info(sslSocket *ss) | |
| 1824 ss->ssl3.hs.messages.len = 0; | |
| 1825 ss->ssl3.hs.messages.space = 0; | |
| 1826 } | |
| 1827 + if (ss->ssl3.hs.origClientHello.data) { | |
| 1828 + SECITEM_FreeItem(&ss->ssl3.hs.origClientHello, PR_FALSE); | |
| 1829 + } | |
| 1830 | |
| 1831 /* free the SSL3Buffer (msg_body) */ | |
| 1832 PORT_Free(ss->ssl3.hs.msg_body.buf); | |
| 1833 diff --git a/mozilla/security/nss/lib/ssl/ssl3ext.c b/mozilla/security/nss/lib/s
sl/ssl3ext.c | |
| 1834 index fbd5a91..a7ae062 100644 | |
| 1835 --- a/mozilla/security/nss/lib/ssl/ssl3ext.c | |
| 1836 +++ b/mozilla/security/nss/lib/ssl/ssl3ext.c | |
| 1837 @@ -247,6 +247,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTL
S[] = { | |
| 1838 { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn }, | |
| 1839 { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, | |
| 1840 { ssl_next_proto_neg_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, | |
| 1841 + { ssl_snap_start_xtn, &ssl3_ClientHandleSnapStartXtn }, | |
| 1842 { -1, NULL } | |
| 1843 }; | |
| 1844 | |
| 1845 @@ -270,7 +271,9 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTEN
SIONS] = { | |
| 1846 { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn }, | |
| 1847 #endif | |
| 1848 { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, | |
| 1849 - { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn } | |
| 1850 + { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn }, | |
| 1851 + { ssl_snap_start_xtn, &ssl3_SendSnapStartXtn } | |
| 1852 + /* NOTE: The Snap Start sender MUST be the last extension in the list. */ | |
| 1853 /* any extra entries will appear as { 0, NULL } */ | |
| 1854 }; | |
| 1855 | |
| 1856 @@ -298,7 +301,7 @@ ssl3_ExtensionNegotiated(sslSocket *ss, PRUint16 ex_type) { | |
| 1857 xtnData->numNegotiated, ex_type); | |
| 1858 } | |
| 1859 | |
| 1860 -static PRBool | |
| 1861 +PRBool | |
| 1862 ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type) { | |
| 1863 TLSExtensionData *xtnData = &ss->xtnData; | |
| 1864 return arrayContainsExtension(xtnData->advertised, | |
| 1865 @@ -515,6 +518,8 @@ ssl3_SendSessionTicketXtn( | |
| 1866 rv = ssl3_AppendHandshakeVariable(ss, session_ticket->ticket.data, | |
| 1867 session_ticket->ticket.len, 2); | |
| 1868 ss->xtnData.ticketTimestampVerified = PR_FALSE; | |
| 1869 + if (!ss->sec.isServer) | |
| 1870 + ss->xtnData.clientSentNonEmptySessionTicket = PR_TRUE; | |
| 1871 } else { | |
| 1872 rv = ssl3_AppendHandshakeNumber(ss, 0, 2); | |
| 1873 } | |
| 1874 @@ -573,7 +578,7 @@ ssl3_ValidateNextProtoNego(const unsigned char* data, unsign
ed short length) | |
| 1875 | |
| 1876 SECStatus | |
| 1877 ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type, | |
| 1878 - SECItem *data) | |
| 1879 + SECItem *data) | |
| 1880 { | |
| 1881 unsigned int i, j; | |
| 1882 SECStatus rv; | |
| 1883 @@ -1021,7 +1026,7 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16
ex_type, | |
| 1884 * instead of terminating the current connection. | |
| 1885 */ | |
| 1886 if (data->len == 0) { | |
| 1887 - ss->xtnData.emptySessionTicket = PR_TRUE; | |
| 1888 + ss->xtnData.serverReceivedEmptySessionTicket = PR_TRUE; | |
| 1889 } else { | |
| 1890 int i; | |
| 1891 SECItem extension_data; | |
| 1892 diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/s
sl/sslimpl.h | |
| 1893 index fe7ac7a..f708696 100644 | |
| 1894 --- a/mozilla/security/nss/lib/ssl/sslimpl.h | |
| 1895 +++ b/mozilla/security/nss/lib/ssl/sslimpl.h | |
| 1896 @@ -278,6 +278,7 @@ struct sslSocketOpsStr { | |
| 1897 /* Flags interpreted by ssl send functions. */ | |
| 1898 #define ssl_SEND_FLAG_FORCE_INTO_BUFFER 0x40000000 | |
| 1899 #define ssl_SEND_FLAG_NO_BUFFER 0x20000000 | |
| 1900 +#define ssl_SEND_FLAG_NO_FLUSH 0x10000000 | |
| 1901 #define ssl_SEND_FLAG_MASK 0x7f000000 | |
| 1902 | |
| 1903 /* | |
| 1904 @@ -339,6 +340,7 @@ typedef struct sslOptionsStr { | |
| 1905 unsigned int enableRenegotiation : 2; /* 20-21 */ | |
| 1906 unsigned int requireSafeNegotiation : 1; /* 22 */ | |
| 1907 unsigned int enableFalseStart : 1; /* 23 */ | |
| 1908 + unsigned int enableSnapStart : 1; /* 24 */ | |
| 1909 } sslOptions; | |
| 1910 | |
| 1911 typedef enum { sslHandshakingUndetermined = 0, | |
| 1912 @@ -743,7 +745,8 @@ struct TLSExtensionDataStr { | |
| 1913 | |
| 1914 /* SessionTicket Extension related data. */ | |
| 1915 PRBool ticketTimestampVerified; | |
| 1916 - PRBool emptySessionTicket; | |
| 1917 + PRBool serverReceivedEmptySessionTicket; | |
| 1918 + PRBool clientSentNonEmptySessionTicket; | |
| 1919 | |
| 1920 /* SNI Extension related data | |
| 1921 * Names data is not coppied from the input buffer. It can not be | |
| 1922 @@ -753,6 +756,14 @@ struct TLSExtensionDataStr { | |
| 1923 PRUint32 sniNameArrSize; | |
| 1924 }; | |
| 1925 | |
| 1926 +typedef enum { | |
| 1927 + snap_start_none = 0, | |
| 1928 + snap_start_full, | |
| 1929 + snap_start_recovery, | |
| 1930 + snap_start_resume, | |
| 1931 + snap_start_resume_recovery | |
| 1932 +} TLSSnapStartType; | |
| 1933 + | |
| 1934 /* | |
| 1935 ** This is the "hs" member of the "ssl3" struct. | |
| 1936 ** This entire struct is protected by ssl3HandshakeLock | |
| 1937 @@ -791,6 +802,14 @@ const ssl3CipherSuiteDef *suite_def; | |
| 1938 SSL3Hashes sFinished[2]; | |
| 1939 SSL3Opaque data[72]; | |
| 1940 } finishedMsgs; | |
| 1941 + | |
| 1942 + TLSSnapStartType snapStartType; | |
| 1943 + /* When we perform a Snap Start handshake, we hash our ClientHello as if | |
| 1944 + * the Snap Start extension wasn't included. However, if the server rejects | |
| 1945 + * our Snap Start attempt, then it will hash the whole ClientHello. Thus we | |
| 1946 + * store the original ClientHello that we sent in case we need to reset our | |
| 1947 + * Finished hash to cover it. */ | |
| 1948 + SECItem origClientHello; | |
| 1949 #ifdef NSS_ENABLE_ECC | |
| 1950 PRUint32 negotiatedECCurves; /* bit mask */ | |
| 1951 #endif /* NSS_ENABLE_ECC */ | |
| 1952 @@ -823,6 +842,17 @@ struct ssl3StateStr { | |
| 1953 CERTCertificateList *clientCertChain; /* used by client */ | |
| 1954 PRBool sendEmptyCert; /* used by client */ | |
| 1955 | |
| 1956 + /* TLS Snap Start: */ | |
| 1957 + CERTCertificate ** predictedCertChain; | |
| 1958 + /* An array terminated with a NULL. */ | |
| 1959 + SECItem serverHelloPredictionData; | |
| 1960 + PRBool serverHelloPredictionDataValid; | |
| 1961 + /* data needed to predict the ServerHello from | |
| 1962 + * this server. */ | |
| 1963 + SECItem snapStartApplicationData; | |
| 1964 + /* the application data to include in the Snap | |
| 1965 + * Start extension. */ | |
| 1966 + | |
| 1967 int policy; | |
| 1968 /* This says what cipher suites we can do, and should | |
| 1969 * be either SSL_ALLOWED or SSL_RESTRICTED | |
| 1970 @@ -1258,10 +1288,13 @@ extern sslSessionID *ssl3_NewSessionID(sslSocket *ss, PR
Bool is_server); | |
| 1971 extern sslSessionID *ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, | |
| 1972 const char *peerID, const char *urlSvrName); | |
| 1973 extern void ssl_FreeSID(sslSessionID *sid); | |
| 1974 +extern void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid); | |
| 1975 | |
| 1976 extern int ssl3_SendApplicationData(sslSocket *ss, const PRUint8 *in, | |
| 1977 int len, int flags); | |
| 1978 | |
| 1979 +extern SECStatus ssl3_RestartHandshakeHashes(sslSocket *ss); | |
| 1980 + | |
| 1981 extern PRBool ssl_FdIsBlocking(PRFileDesc *fd); | |
| 1982 | |
| 1983 extern PRBool ssl_SocketIsBlocking(sslSocket *ss); | |
| 1984 @@ -1434,6 +1467,9 @@ ECName ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk
, int requiredECCbits); | |
| 1985 | |
| 1986 #endif /* NSS_ENABLE_ECC */ | |
| 1987 | |
| 1988 +extern SECStatus ssl3_UpdateHandshakeHashes(sslSocket* ss, unsigned char *b, | |
| 1989 + unsigned int l); | |
| 1990 + | |
| 1991 extern SECStatus ssl3_CipherPrefSetDefault(ssl3CipherSuite which, PRBool on); | |
| 1992 extern SECStatus ssl3_CipherPrefGetDefault(ssl3CipherSuite which, PRBool *on); | |
| 1993 extern SECStatus ssl2_CipherPrefSetDefault(PRInt32 which, PRBool enabled); | |
| 1994 @@ -1454,6 +1490,7 @@ extern void ssl3_InitSocketPolicy(sslSocket *ss); | |
| 1995 | |
| 1996 extern SECStatus ssl3_ConstructV2CipherSpecsHack(sslSocket *ss, | |
| 1997 unsigned char *cs, int *size); | |
| 1998 +extern void ssl3_DestroyCipherSpec(ssl3CipherSpec* spec, PRBool freeSrvName); | |
| 1999 | |
| 2000 extern SECStatus ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache); | |
| 2001 | |
| 2002 @@ -1503,6 +1540,31 @@ extern SECStatus ssl3_VerifySignedHashes(SSL3Hashes *hash
, | |
| 2003 extern SECStatus ssl3_CacheWrappedMasterSecret(sslSocket *ss, | |
| 2004 sslSessionID *sid, ssl3CipherSpec *spec, | |
| 2005 SSL3KEAType effectiveExchKeyType); | |
| 2006 +extern void ssl3_CleanupPredictedPeerCertificates(sslSocket *ss); | |
| 2007 +extern const ssl3CipherSuiteDef* ssl_LookupCipherSuiteDef(ssl3CipherSuite suite
); | |
| 2008 +extern SECStatus ssl3_SetupPendingCipherSpec(sslSocket *ss); | |
| 2009 +extern SECStatus ssl3_SendClientKeyExchange(sslSocket *ss); | |
| 2010 +extern SECStatus ssl3_SendNextProto(sslSocket *ss); | |
| 2011 +extern SECStatus ssl3_SendFinished(sslSocket *ss, PRInt32 flags); | |
| 2012 +extern SECStatus ssl3_CompressMACEncryptRecord | |
| 2013 + (sslSocket * ss, | |
| 2014 + SSL3ContentType type, | |
| 2015 + const SSL3Opaque * pIn, | |
| 2016 + PRUint32 contentLen); | |
| 2017 +extern PRBool ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type); | |
| 2018 +extern SECStatus ssl3_SetupMasterSecretFromSessionID(sslSocket* ss); | |
| 2019 +extern SECStatus ssl3_ComputeHandshakeHashes( | |
| 2020 + sslSocket * ss, | |
| 2021 + ssl3CipherSpec *spec, /* uses ->master_secret */ | |
| 2022 + SSL3Hashes * hashes, /* output goes here. */ | |
| 2023 + PRUint32 sender); | |
| 2024 +extern SECStatus ssl3_UpdateHandshakeHashes(sslSocket* ss, unsigned char *b, | |
| 2025 + unsigned int l); | |
| 2026 +extern SECStatus ssl3_ComputeTLSFinished( | |
| 2027 + ssl3CipherSpec *spec, | |
| 2028 + PRBool isServer, | |
| 2029 + const SSL3Finished * hashes, | |
| 2030 + TLSFinished * tlsFinished); | |
| 2031 | |
| 2032 /* Functions that handle ClientHello and ServerHello extensions. */ | |
| 2033 extern SECStatus ssl3_HandleServerNameXtn(sslSocket * ss, | |
| 2034 @@ -1532,6 +1594,13 @@ extern PRInt32 ssl3_SendSessionTicketXtn(sslSocket *ss, P
RBool append, | |
| 2035 */ | |
| 2036 extern PRInt32 ssl3_SendServerNameXtn(sslSocket *ss, PRBool append, | |
| 2037 PRUint32 maxBytes); | |
| 2038 +extern PRInt32 ssl3_SendSnapStartXtn(sslSocket *ss, PRBool append, | |
| 2039 + PRUint32 maxBytes); | |
| 2040 +extern SECStatus ssl3_ClientHandleSnapStartXtn(sslSocket *ss, PRUint16 ex_type, | |
| 2041 + SECItem *data); | |
| 2042 + | |
| 2043 +extern SECStatus ssl3_ResetForSnapStartRecovery(sslSocket *ss, | |
| 2044 + SSL3Opaque *b, PRUint32 length); | |
| 2045 | |
| 2046 /* Assigns new cert, cert chain and keys to ss->serverCerts | |
| 2047 * struct. If certChain is NULL, tries to find one. Aborts if | |
| 2048 @@ -1635,6 +1704,12 @@ SECStatus SSL_DisableDefaultExportCipherSuites(void); | |
| 2049 SECStatus SSL_DisableExportCipherSuites(PRFileDesc * fd); | |
| 2050 PRBool SSL_IsExportCipherSuite(PRUint16 cipherSuite); | |
| 2051 | |
| 2052 +/********************** FNV hash *********************/ | |
| 2053 + | |
| 2054 +void FNV1A64_Init(PRUint64 *digest); | |
| 2055 +void FNV1A64_Update(PRUint64 *digest, const unsigned char *data, | |
| 2056 + unsigned int length); | |
| 2057 +void FNV1A64_Final(PRUint64 *digest); | |
| 2058 | |
| 2059 #ifdef TRACE | |
| 2060 #define SSL_TRACE(msg) ssl_Trace msg | |
| 2061 diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/s
sl/sslsock.c | |
| 2062 index ca0d714..2898b88 100644 | |
| 2063 --- a/mozilla/security/nss/lib/ssl/sslsock.c | |
| 2064 +++ b/mozilla/security/nss/lib/ssl/sslsock.c | |
| 2065 @@ -738,6 +738,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) | |
| 2066 ss->opt.enableFalseStart = on; | |
| 2067 break; | |
| 2068 | |
| 2069 + case SSL_ENABLE_SNAP_START: | |
| 2070 + ss->opt.enableSnapStart = on; | |
| 2071 + break; | |
| 2072 + | |
| 2073 default: | |
| 2074 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 2075 rv = SECFailure; | |
| 2076 @@ -802,6 +806,7 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn) | |
| 2077 case SSL_REQUIRE_SAFE_NEGOTIATION: | |
| 2078 on = ss->opt.requireSafeNegotiation; break; | |
| 2079 case SSL_ENABLE_FALSE_START: on = ss->opt.enableFalseStart; break; | |
| 2080 + case SSL_ENABLE_SNAP_START: on = ss->opt.enableSnapStart; break; | |
| 2081 | |
| 2082 default: | |
| 2083 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 2084 @@ -853,6 +858,7 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn) | |
| 2085 on = ssl_defaults.requireSafeNegotiation; | |
| 2086 break; | |
| 2087 case SSL_ENABLE_FALSE_START: on = ssl_defaults.enableFalseStart; break; | |
| 2088 + case SSL_ENABLE_SNAP_START: on = ssl_defaults.enableSnapStart; break; | |
| 2089 | |
| 2090 default: | |
| 2091 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 2092 @@ -1000,6 +1006,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on) | |
| 2093 ssl_defaults.enableFalseStart = on; | |
| 2094 break; | |
| 2095 | |
| 2096 + case SSL_ENABLE_SNAP_START: | |
| 2097 + ssl_defaults.enableSnapStart = on; | |
| 2098 + break; | |
| 2099 + | |
| 2100 default: | |
| 2101 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 2102 return SECFailure; | |
| 2103 diff --git a/mozilla/security/nss/lib/ssl/sslt.h b/mozilla/security/nss/lib/ssl/
sslt.h | |
| 2104 index f6e0b62..68cbf87 100644 | |
| 2105 --- a/mozilla/security/nss/lib/ssl/sslt.h | |
| 2106 +++ b/mozilla/security/nss/lib/ssl/sslt.h | |
| 2107 @@ -204,9 +204,23 @@ typedef enum { | |
| 2108 #endif | |
| 2109 ssl_session_ticket_xtn = 35, | |
| 2110 ssl_next_proto_neg_xtn = 13172, | |
| 2111 + ssl_snap_start_xtn = 13174, | |
| 2112 ssl_renegotiation_info_xtn = 0xff01 /* experimental number */ | |
| 2113 } SSLExtensionType; | |
| 2114 | |
| 2115 -#define SSL_MAX_EXTENSIONS 6 | |
| 2116 +#define SSL_MAX_EXTENSIONS 7 | |
| 2117 + | |
| 2118 +typedef enum { | |
| 2119 + /* No Snap Start handshake was attempted. */ | |
| 2120 + SSL_SNAP_START_NONE = 0, | |
| 2121 + /* A Snap Start full handshake was completed. */ | |
| 2122 + SSL_SNAP_START_FULL = 1, | |
| 2123 + /* A Snap Start full handshake was attempted, but failed. */ | |
| 2124 + SSL_SNAP_START_RECOVERY = 2, | |
| 2125 + /* A Snap Start resume handshake was completed. */ | |
| 2126 + SSL_SNAP_START_RESUME = 3, | |
| 2127 + /* A Snap Start resume handshake was attempted, but failed. */ | |
| 2128 + SSL_SNAP_START_RESUME_RECOVERY = 4 | |
| 2129 +} SSLSnapStartResult; | |
| 2130 | |
| 2131 #endif /* __sslt_h_ */ | |
| OLD | NEW |