| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * TLS Snap Start | |
| 3 * | |
| 4 * ***** BEGIN LICENSE BLOCK ***** | |
| 5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | |
| 6 * | |
| 7 * The contents of this file are subject to the Mozilla Public License Version | |
| 8 * 1.1 (the "License"); you may not use this file except in compliance with | |
| 9 * the License. You may obtain a copy of the License at | |
| 10 * http://www.mozilla.org/MPL/ | |
| 11 * | |
| 12 * Software distributed under the License is distributed on an "AS IS" basis, | |
| 13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
| 14 * for the specific language governing rights and limitations under the | |
| 15 * License. | |
| 16 * | |
| 17 * The Original Code is the Netscape security libraries. | |
| 18 * | |
| 19 * The Initial Developer of the Original Code is | |
| 20 * Netscape Communications Corporation. | |
| 21 * Portions created by the Initial Developer are Copyright (C) 1994-2000 | |
| 22 * the Initial Developer. All Rights Reserved. | |
| 23 * | |
| 24 * Contributor(s): | |
| 25 * Adam Langley, Google Inc. | |
| 26 * | |
| 27 * Alternatively, the contents of this file may be used under the terms of | |
| 28 * either the GNU General Public License Version 2 or later (the "GPL"), or | |
| 29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | |
| 30 * in which case the provisions of the GPL or the LGPL are applicable instead | |
| 31 * of those above. If you wish to allow use of your version of this file only | |
| 32 * under the terms of either the GPL or the LGPL, and not to allow others to | |
| 33 * use your version of this file under the terms of the MPL, indicate your | |
| 34 * decision by deleting the provisions above and replace them with the notice | |
| 35 * and other provisions required by the GPL or the LGPL. If you do not delete | |
| 36 * the provisions above, a recipient may use your version of this file under | |
| 37 * the terms of any one of the MPL, the GPL or the LGPL. | |
| 38 * | |
| 39 * ***** END LICENSE BLOCK ***** */ | |
| 40 | |
| 41 /* $Id: ssl3snap.c,v 1.0 2010/08/09 13:00:00 agl%google.com Exp $ */ | |
| 42 | |
| 43 | |
| 44 /* TODO(agl): Refactor ssl3_CompressMACEncryptRecord so that it can write to | |
| 45 ** |sendBuf| directly and fix ssl3_AppendSnapStartHandshakeRecord and | |
| 46 ** ssl3_AppendSnapStartApplicationData. | |
| 47 */ | |
| 48 | |
| 49 /* TODO(agl): Add support for snap starting with compression. */ | |
| 50 | |
| 51 #include "pk11pub.h" | |
| 52 #include "ssl.h" | |
| 53 #include "sslimpl.h" | |
| 54 #include "sslproto.h" | |
| 55 | |
| 56 static unsigned int GetBE16(const void *in) | |
| 57 { | |
| 58 const unsigned char *p = in; | |
| 59 return ((unsigned) p[0]) << 8 | | |
| 60 p[1]; | |
| 61 } | |
| 62 | |
| 63 static unsigned int GetBE24(const void *in) | |
| 64 { | |
| 65 const unsigned char *p = in; | |
| 66 return ((unsigned) p[0]) << 16 | | |
| 67 ((unsigned) p[1]) << 8 | | |
| 68 p[2]; | |
| 69 } | |
| 70 | |
| 71 static void PutBE16(void *out, unsigned int value) | |
| 72 { | |
| 73 unsigned char *p = out; | |
| 74 p[0] = value >> 8; | |
| 75 p[1] = value; | |
| 76 } | |
| 77 | |
| 78 static void PutBE24(void *out, unsigned int value) | |
| 79 { | |
| 80 unsigned char *p = out; | |
| 81 p[0] = value >> 16; | |
| 82 p[1] = value >> 8; | |
| 83 p[2] = value; | |
| 84 } | |
| 85 | |
| 86 /* ssl3_ForEachExtension calls a callback for each TLS extension in |extensions| | |
| 87 ** extensions: points to a block of extensions which includes the two prefix | |
| 88 ** length bytes | |
| 89 ** is_resuming: if true, certain extensions will be omitted | |
| 90 ** f: a function which is called with the data of each extension, which | |
| 91 ** includes the four type and length bytes at the beginning. | |
| 92 */ | |
| 93 static PRBool | |
| 94 ssl3_ForEachExtension(const SECItem *extensions, PRBool is_resuming, | |
| 95 void (*f) (const unsigned char *data, unsigned int length, | |
| 96 void *ctx), | |
| 97 void *ctx) { | |
| 98 unsigned int extensions_len, offset; | |
| 99 | |
| 100 if (extensions->len == 0) | |
| 101 return PR_TRUE; | |
| 102 | |
| 103 if (extensions->len < 2) | |
| 104 goto loser; | |
| 105 | |
| 106 extensions_len = GetBE16(extensions->data); | |
| 107 offset = 2; | |
| 108 | |
| 109 if (extensions->len != 2 + extensions_len) | |
| 110 goto loser; | |
| 111 | |
| 112 while (extensions_len) { | |
| 113 unsigned int extension_num, extension_len; | |
| 114 | |
| 115 if (extensions->len - offset < 4) | |
| 116 goto loser; | |
| 117 | |
| 118 extension_num = GetBE16(extensions->data + offset); | |
| 119 extension_len = GetBE16(extensions->data + offset + 2); | |
| 120 | |
| 121 if (extensions->len - offset < 4 + extension_len) | |
| 122 goto loser; | |
| 123 | |
| 124 /* When resuming, the server will omit some extensions from the | |
| 125 * previous non-resume ServerHello. */ | |
| 126 if (!is_resuming || | |
| 127 (extension_num != ssl_server_name_xtn && | |
| 128 extension_num != ssl_session_ticket_xtn)) { | |
| 129 f(extensions->data + offset, 4 + extension_len, ctx); | |
| 130 } | |
| 131 | |
| 132 offset += 4 + extension_len; | |
| 133 extensions_len -= 4 + extension_len; | |
| 134 } | |
| 135 | |
| 136 return PR_TRUE; | |
| 137 | |
| 138 loser: | |
| 139 PORT_SetError(SEC_ERROR_INPUT_LEN); | |
| 140 return PR_FALSE; | |
| 141 } | |
| 142 | |
| 143 static void | |
| 144 ssl3_AccumlateLengths(const unsigned char *data, unsigned int length, void *ptr) | |
| 145 { | |
| 146 unsigned int *sum = (unsigned int *) ptr; | |
| 147 *sum += length; | |
| 148 } | |
| 149 | |
| 150 /* ssl3_PredictServerResponse predicts the contents of the server's | |
| 151 ** ServerHello...ServerHelloDone (inclusive) and progressively calls a callback | |
| 152 ** with the contents of those messages. | |
| 153 ** previous_server_hello: the contents of a previous ServerHello from the | |
| 154 ** server where the 'random' field has been replaced with our suggested | |
| 155 ** server random. | |
| 156 ** is_resuming: if false, Certificate and ServerHelloDone messages will be | |
| 157 ** predicted | |
| 158 ** hashUpdate: a callback which is called repeated with the contents of the | |
| 159 ** predicted messages. | |
| 160 */ | |
| 161 static PRBool | |
| 162 ssl3_PredictServerResponse( | |
| 163 sslSocket *ss, SECItem *previous_server_hello, PRBool is_resuming, | |
| 164 void (*hashUpdate) (const unsigned char *data, unsigned int length, | |
| 165 void *ctx), | |
| 166 void *ctx) { | |
| 167 unsigned int old_session_id_length, old_extensions_len; | |
| 168 unsigned int extensions_len, server_hello_len; | |
| 169 unsigned char session_id_len, header[4]; | |
| 170 SECItem extensions; | |
| 171 | |
| 172 /* Keep the structure of a ServerHello in mind when reading the following: | |
| 173 * | |
| 174 * struct ServerHello { | |
| 175 * uint16_t version; | |
| 176 * uint8_t random[32]; | |
| 177 * uint8_t session_id_len; | |
| 178 * uint8_t session_id[session_id_len]; | |
| 179 * uint16_t cipher | |
| 180 * uint8_t compression | |
| 181 * | |
| 182 * // Optional: | |
| 183 * uint16_t extensions_len; | |
| 184 * struct Extension { | |
| 185 * uint16_t num; | |
| 186 * uint16_t len; | |
| 187 * uint8_t payload[len]; | |
| 188 * } | |
| 189 */ | |
| 190 | |
| 191 /* 38 bytes is the shortest possible ServerHello with a zero-length | |
| 192 * session_id and no extensions. */ | |
| 193 if (previous_server_hello->len < 38) { | |
| 194 PORT_SetError(SEC_ERROR_INPUT_LEN); | |
| 195 return PR_FALSE; | |
| 196 } | |
| 197 | |
| 198 /* First we need to figure out the length of the predicted ServerHello. Any | |
| 199 * session id in |previous_server_hello| needs to be removed | |
| 200 * (or replaced). */ | |
| 201 old_session_id_length = previous_server_hello->data[34]; | |
| 202 | |
| 203 extensions.len = 0; | |
| 204 | |
| 205 if (previous_server_hello->len >= 35 + old_session_id_length + 3 + 2) { | |
| 206 /* Extensions present */ | |
| 207 unsigned int offset = 35 + old_session_id_length + 3; | |
| 208 extensions.data = previous_server_hello->data + offset; | |
| 209 extensions.len = previous_server_hello->len - offset; | |
| 210 } | |
| 211 | |
| 212 /* Sum the lengths of all the extensions that we wish to include */ | |
| 213 extensions_len = 0; | |
| 214 if (!ssl3_ForEachExtension(&extensions, is_resuming, ssl3_AccumlateLengths, | |
| 215 &extensions_len)) { | |
| 216 return PR_FALSE; | |
| 217 } | |
| 218 | |
| 219 old_extensions_len = | |
| 220 (previous_server_hello->len - 35 - old_session_id_length - 3 - 2); | |
| 221 | |
| 222 session_id_len = 0; | |
| 223 if (ss->sec.ci.sid) | |
| 224 session_id_len = ss->sec.ci.sid->u.ssl3.sessionIDLength; | |
| 225 server_hello_len = previous_server_hello->len + | |
| 226 session_id_len - old_session_id_length + | |
| 227 extensions_len - old_extensions_len; | |
| 228 | |
| 229 header[0] = server_hello; | |
| 230 PutBE24(header + 1, server_hello_len); | |
| 231 hashUpdate(header, 4, ctx); | |
| 232 | |
| 233 hashUpdate(previous_server_hello->data, 34, ctx); | |
| 234 hashUpdate(&session_id_len, sizeof(session_id_len), ctx); | |
| 235 if (session_id_len) | |
| 236 hashUpdate(ss->sec.ci.sid->u.ssl3.sessionID, session_id_len, ctx); | |
| 237 hashUpdate(previous_server_hello->data + 35 + old_session_id_length, 3, | |
| 238 ctx); | |
| 239 | |
| 240 if (extensions.len) { | |
| 241 PutBE16(header, extensions_len); | |
| 242 hashUpdate(header, 2, ctx); | |
| 243 | |
| 244 if (!ssl3_ForEachExtension(&extensions, is_resuming, hashUpdate, ctx)) | |
| 245 return PR_FALSE; | |
| 246 } | |
| 247 | |
| 248 if (!is_resuming) { | |
| 249 unsigned int certificate_message_len = 3, i; | |
| 250 for (i = 0; ss->ssl3.predictedCertChain[i]; i++) { | |
| 251 certificate_message_len += 3; | |
| 252 certificate_message_len += | |
| 253 ss->ssl3.predictedCertChain[i]->derCert.len; | |
| 254 } | |
| 255 | |
| 256 header[0] = certificate; | |
| 257 PutBE24(header + 1, certificate_message_len); | |
| 258 hashUpdate(header, 4, ctx); | |
| 259 | |
| 260 PutBE24(header, certificate_message_len - 3); | |
| 261 hashUpdate(header, 3, ctx); | |
| 262 | |
| 263 for (i = 0; ss->ssl3.predictedCertChain[i]; i++) { | |
| 264 unsigned int len = ss->ssl3.predictedCertChain[i]->derCert.len; | |
| 265 PutBE24(header, len); | |
| 266 hashUpdate(header, 3, ctx); | |
| 267 hashUpdate(ss->ssl3.predictedCertChain[i]->derCert.data, len, ctx); | |
| 268 } | |
| 269 | |
| 270 header[0] = server_hello_done; | |
| 271 header[1] = header[2] = header[3] = 0; | |
| 272 hashUpdate(header, 4, ctx); | |
| 273 } | |
| 274 | |
| 275 return PR_TRUE; | |
| 276 } | |
| 277 | |
| 278 /* ssl3_SnapStartHash is called with the contents of the server's predicted | |
| 279 * response and updates both the Finished hash and an FNV641a hash. */ | |
| 280 static void | |
| 281 ssl3_SnapStartHash(const unsigned char *data, unsigned int len, void *ctx) | |
| 282 { | |
| 283 SECStatus rv; | |
| 284 void **ptrs = (void **) ctx; | |
| 285 sslSocket *ss = ptrs[0]; | |
| 286 PRUint64 *fnv = ptrs[1]; | |
| 287 | |
| 288 FNV1A64_Update(fnv, data, len); | |
| 289 rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char *) data, len); | |
| 290 if (rv != SECSuccess) | |
| 291 PR_Assert("rv == SECSuccess", __FILE__, __LINE__); | |
| 292 } | |
| 293 | |
| 294 static PRInt32 | |
| 295 ssl3_SendEmptySnapStartXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) | |
| 296 { | |
| 297 SECStatus rv; | |
| 298 | |
| 299 if (maxBytes < 4) | |
| 300 return 0; | |
| 301 | |
| 302 if (append) { | |
| 303 rv = ssl3_AppendHandshakeNumber(ss, ssl_snap_start_xtn, 2); | |
| 304 if (rv != SECSuccess) | |
| 305 return -1; | |
| 306 rv = ssl3_AppendHandshakeNumber(ss, 0 /* empty extension */, 2); | |
| 307 if (rv != SECSuccess) | |
| 308 return -1; | |
| 309 if (!ss->sec.isServer) { | |
| 310 TLSExtensionData *xtnData = &ss->xtnData; | |
| 311 xtnData->advertised[xtnData->numAdvertised++] = ssl_snap_start_xtn; | |
| 312 } | |
| 313 } | |
| 314 return 4; | |
| 315 } | |
| 316 | |
| 317 static SECStatus | |
| 318 ssl3_BufferEnsure(sslBuffer *buf, unsigned int extra_bytes) | |
| 319 { | |
| 320 if (buf->space < buf->len + extra_bytes) | |
| 321 return sslBuffer_Grow(buf, buf->len + extra_bytes); | |
| 322 return SECSuccess; | |
| 323 } | |
| 324 | |
| 325 /* ssl3_AppendSnapStartRecordHeader appends a 5 byte TLS record header to the | |
| 326 * sendBuf of the given sslSocket. */ | |
| 327 static SECStatus | |
| 328 ssl3_AppendSnapStartRecordHeader(sslSocket *ss, SSL3ContentType type, | |
| 329 unsigned int len) | |
| 330 { | |
| 331 SECStatus rv; | |
| 332 | |
| 333 rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 5); | |
| 334 if (rv != SECSuccess) | |
| 335 return rv; | |
| 336 ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 0] = type; | |
| 337 PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 1], ss->version); | |
| 338 PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 3], len); | |
| 339 ss->sec.ci.sendBuf.len += 5; | |
| 340 return SECSuccess; | |
| 341 } | |
| 342 | |
| 343 /* ssl3_AppendSnapStartHandshakeRecord appends a (possibly encrypted) record to | |
| 344 ** the sendBuf of the given sslSocket. | |
| 345 ** f: a function which will append the bytes of the record (not including the | |
| 346 ** 5 byte header) to the sendBuf. | |
| 347 */ | |
| 348 static SECStatus | |
| 349 ssl3_AppendSnapStartHandshakeRecord(sslSocket *ss, SECStatus (*f) (sslSocket*), | |
| 350 PRBool encrypt) | |
| 351 { | |
| 352 SECStatus rv; | |
| 353 unsigned int record_offset, record_len; | |
| 354 | |
| 355 /* ssl3_CompressMACEncryptRecord will deal with the record header if we are | |
| 356 * encrypting. */ | |
| 357 if (!encrypt) { | |
| 358 /* The zero length argument here is a dummy value. We write the real | |
| 359 * length once we know it, below. */ | |
| 360 rv = ssl3_AppendSnapStartRecordHeader(ss, content_handshake, 0); | |
| 361 if (rv != SECSuccess) | |
| 362 return rv; | |
| 363 } | |
| 364 | |
| 365 record_offset = ss->sec.ci.sendBuf.len; | |
| 366 rv = f(ss); | |
| 367 if (rv != SECSuccess) | |
| 368 return rv; | |
| 369 record_len = ss->sec.ci.sendBuf.len - record_offset; | |
| 370 if (!encrypt) { | |
| 371 PutBE16(&ss->sec.ci.sendBuf.buf[record_offset - 2], record_len); | |
| 372 } else { | |
| 373 /* ssl3_CompressMACEncryptRecord writes to |ss->sec.writeBuf| | |
| 374 * so we copy it back to |ss->sec.ci.sendBuf| */ | |
| 375 /* TODO(agl): the buffer copy here is a bodge. See TODO at the top of | |
| 376 * the file. */ | |
| 377 rv = ssl3_CompressMACEncryptRecord( | |
| 378 ss, content_handshake, | |
| 379 &ss->sec.ci.sendBuf.buf[record_offset], record_len); | |
| 380 if (rv != SECSuccess) | |
| 381 return rv; | |
| 382 ss->sec.ci.sendBuf.len -= record_len; | |
| 383 ssl3_BufferEnsure(&ss->sec.ci.sendBuf, ss->sec.writeBuf.len); | |
| 384 memcpy(&ss->sec.ci.sendBuf.buf[record_offset], ss->sec.writeBuf.buf, | |
| 385 ss->sec.writeBuf.len); | |
| 386 ss->sec.ci.sendBuf.len += ss->sec.writeBuf.len; | |
| 387 ss->sec.writeBuf.len = 0; | |
| 388 } | |
| 389 | |
| 390 return SECSuccess; | |
| 391 } | |
| 392 | |
| 393 /* ssl3_AppendSnapStartApplicationData appends an encrypted Application Data | |
| 394 ** record the sendBuf of the given sslSocket. | |
| 395 */ | |
| 396 static SECStatus ssl3_AppendSnapStartApplicationData( | |
| 397 sslSocket *ss, const SSL3Opaque *data, unsigned int len) | |
| 398 { | |
| 399 SECStatus rv; | |
| 400 | |
| 401 /* TODO(agl): the buffer copy here is a bodge. See TODO at the top of the | |
| 402 * file. */ | |
| 403 rv = ssl3_CompressMACEncryptRecord(ss, content_application_data, data, len); | |
| 404 if (rv != SECSuccess) | |
| 405 return rv; | |
| 406 rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, ss->sec.writeBuf.len); | |
| 407 if (rv != SECSuccess) | |
| 408 return rv; | |
| 409 memcpy(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len], | |
| 410 ss->sec.writeBuf.buf, ss->sec.writeBuf.len); | |
| 411 ss->sec.ci.sendBuf.len += ss->sec.writeBuf.len; | |
| 412 ss->sec.writeBuf.len = 0; | |
| 413 | |
| 414 return SECSuccess; | |
| 415 } | |
| 416 | |
| 417 static SECStatus ssl3_SendSnapStartFinished(sslSocket *ss) | |
| 418 { | |
| 419 /* We use ssl_SEND_FLAG_NO_FLUSH here because this finished message is | |
| 420 * going to end up in the middle of the Snap Start extension. So | |
| 421 * transmitting |sendBuf| at this point would result in an incomplete | |
| 422 * ClientHello. */ | |
| 423 return ssl3_SendFinished(ss, ssl_SEND_FLAG_NO_FLUSH); | |
| 424 } | |
| 425 | |
| 426 /* ssl3_FindOrbit is called for each extension in a ServerHello message. It | |
| 427 ** tests for a Snap Start extension and records the server's orbit when found. | |
| 428 ** data: the extension data (including the four type and length bytes) | |
| 429 ** length: the length, in bytes, of |data| | |
| 430 ** ptr: a pointer to a uint8_t[9]. The orbit, if found, is copied into the | |
| 431 ** first 8 bytes and then the ninth byte is set to one. | |
| 432 */ | |
| 433 static void | |
| 434 ssl3_FindOrbit(const unsigned char *data, unsigned int length, void *ptr) | |
| 435 { | |
| 436 unsigned char *orbit = (unsigned char *) ptr; | |
| 437 | |
| 438 unsigned int extension_num = GetBE16(data); | |
| 439 if (extension_num == ssl_snap_start_xtn && | |
| 440 length == 4 + 8 /* orbit */ + 2 /* snap start cipher suite */) { | |
| 441 memcpy(orbit, data + 4, 8); | |
| 442 /* A last byte of 1 indicates that the previous eight are valid. */ | |
| 443 orbit[8] = 1; | |
| 444 } | |
| 445 } | |
| 446 | |
| 447 /* ssl3_CanSnapStart returns true if we are able to perform Snap Start on | |
| 448 ** the given socket. | |
| 449 ** extensions: on successful return, this is filled in with the contents of | |
| 450 ** the server's predicted extensions. This points within | |
| 451 ** |ss->ssl3.serverHelloPredictionData|. | |
| 452 ** resuming: PR_TRUE iff we wish to attempt a Snap Start resume | |
| 453 ** out_orbit: if this function returns PR_TRUE, then |out_orbit| is filled | |
| 454 ** with the server's predicted orbit value. | |
| 455 ** The |hs.cipher_suite|, |hs.cipher_def| and |hs.compression| fields of |ss| | |
| 456 ** are set to match the predicted ServerHello on successful exit (and may still | |
| 457 ** be modified on failure). | |
| 458 */ | |
| 459 static PRBool | |
| 460 ssl3_CanSnapStart(sslSocket *ss, SECItem *extensions, PRBool resuming, | |
| 461 unsigned char out_orbit[8]) { | |
| 462 const unsigned char *server_hello; | |
| 463 unsigned int server_hello_len, session_id_len, cipher_suite_offset; | |
| 464 unsigned int extensions_offset, cipher_suite, compression_method; | |
| 465 unsigned char orbit[9]; | |
| 466 SECStatus rv; | |
| 467 SSL3ProtocolVersion version; | |
| 468 | |
| 469 /* If we don't have the information needed then we can't perform a Snap | |
| 470 * Start. */ | |
| 471 if (!ss->ssl3.predictedCertChain || !ss->ssl3.serverHelloPredictionData.data
) | |
| 472 return PR_FALSE; | |
| 473 | |
| 474 /* When the sizes of the fields in the ClientHello are calculated, they'll | |
| 475 * take the length of the Snap Start extension to be zero, so currently | |
| 476 * it's as if this extension didn't exist, which is the state that we | |
| 477 * need. */ | |
| 478 | |
| 479 server_hello = ss->ssl3.serverHelloPredictionData.data; | |
| 480 server_hello_len = ss->ssl3.serverHelloPredictionData.len; | |
| 481 | |
| 482 if (server_hello_len < 2 + 32 + 1) | |
| 483 return PR_FALSE; | |
| 484 session_id_len = server_hello[2 + 32]; | |
| 485 cipher_suite_offset = 2 + 32 + 1 + session_id_len; | |
| 486 if (server_hello_len < cipher_suite_offset + 3) | |
| 487 return PR_FALSE; | |
| 488 extensions_offset = cipher_suite_offset + 3; | |
| 489 | |
| 490 version = (SSL3ProtocolVersion) GetBE16(server_hello); | |
| 491 if (MSB(version) < MSB(SSL_LIBRARY_VERSION_3_0)) | |
| 492 return PR_FALSE; | |
| 493 rv = ssl3_NegotiateVersion(ss, version); | |
| 494 if (rv != SECSuccess) | |
| 495 return PR_FALSE; | |
| 496 | |
| 497 cipher_suite = GetBE16(&server_hello[cipher_suite_offset]); | |
| 498 ss->ssl3.hs.cipher_suite = (ssl3CipherSuite)cipher_suite; | |
| 499 ss->ssl3.hs.suite_def = ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite); | |
| 500 if (!ss->ssl3.hs.suite_def) | |
| 501 return PR_FALSE; | |
| 502 compression_method = server_hello[cipher_suite_offset + 2]; | |
| 503 if (compression_method != ssl_compression_null) { | |
| 504 /* TODO(agl): support compression. */ | |
| 505 return PR_FALSE; | |
| 506 } | |
| 507 ss->ssl3.hs.compression = ssl_compression_null; | |
| 508 | |
| 509 extensions->data = (unsigned char *) server_hello + extensions_offset; | |
| 510 extensions->len = server_hello_len - extensions_offset; | |
| 511 | |
| 512 /* The last byte is used to indictate that the previous eight are valid. */ | |
| 513 orbit[8] = 0; | |
| 514 if (!ssl3_ForEachExtension(extensions, resuming, ssl3_FindOrbit, orbit)) | |
| 515 return PR_FALSE; | |
| 516 | |
| 517 if (!orbit[8]) | |
| 518 return PR_FALSE; | |
| 519 | |
| 520 memcpy(out_orbit, orbit, 8); | |
| 521 | |
| 522 return PR_TRUE; | |
| 523 } | |
| 524 | |
| 525 /* ssl3_UpdateClientHelloLengths rewrites the handshake header length and | |
| 526 ** extensions length in the ClientHello to reflect the addition of the Snap | |
| 527 ** Start extension. | |
| 528 ** snap_start_extension_len_offset: the number of bytes of the ClientHello to | |
| 529 ** skip in order to find the embedded length of the Snap Start extension. | |
| 530 */ | |
| 531 static void | |
| 532 ssl3_UpdateClientHelloLengths(sslSocket *ss, | |
| 533 unsigned int snap_start_extension_len_offset, | |
| 534 sslSessionID *sid) { | |
| 535 unsigned int extension_length, old_length, new_length, new_session_id_len; | |
| 536 unsigned int offset, ciphers_length, compressions_len; | |
| 537 | |
| 538 extension_length = | |
| 539 ss->sec.ci.sendBuf.len - snap_start_extension_len_offset - 2; | |
| 540 PutBE16(&ss->sec.ci.sendBuf.buf[snap_start_extension_len_offset], | |
| 541 extension_length); | |
| 542 | |
| 543 /* The length in the handshake header is short by extension_length + 4 | |
| 544 * bytes. */ | |
| 545 old_length = GetBE24(&ss->sec.ci.sendBuf.buf[1]); | |
| 546 new_length = old_length + extension_length + 4; | |
| 547 PutBE24(&ss->sec.ci.sendBuf.buf[1], new_length); | |
| 548 | |
| 549 /* The length of the extensions block is similarly wrong. */ | |
| 550 new_session_id_len = 0; | |
| 551 if (sid) | |
| 552 new_session_id_len = sid->u.ssl3.sessionIDLength; | |
| 553 offset = 4 + 2 + 32 + 1 + new_session_id_len; | |
| 554 ciphers_length = GetBE16(&ss->sec.ci.sendBuf.buf[offset]); | |
| 555 offset += 2 + ciphers_length; | |
| 556 compressions_len = ss->sec.ci.sendBuf.buf[offset]; | |
| 557 offset += 1 + compressions_len; | |
| 558 old_length = GetBE16(&ss->sec.ci.sendBuf.buf[offset]); | |
| 559 new_length = old_length + extension_length + 4; | |
| 560 PutBE16(&ss->sec.ci.sendBuf.buf[offset], new_length); | |
| 561 } | |
| 562 | |
| 563 /* ssl3_FindServerNPNExtension is a callback function for ssl3_ForEachExtension. | |
| 564 * It looks for a Next Protocol Negotiation and saves the payload of the | |
| 565 * extension in the given SECItem */ | |
| 566 static void | |
| 567 ssl3_FindServerNPNExtension(const unsigned char* data, unsigned int length, | |
| 568 void *ctx) | |
| 569 { | |
| 570 SECItem *server_npn_extension = (SECItem*) ctx; | |
| 571 | |
| 572 unsigned int extension_num = GetBE16(data); | |
| 573 if (extension_num == ssl_next_proto_neg_xtn && length >= 4) { | |
| 574 server_npn_extension->data = (unsigned char*)data + 4; | |
| 575 server_npn_extension->len = length - 4; | |
| 576 } | |
| 577 } | |
| 578 | |
| 579 /* ssl3_MaybeWriteNextProtocol deals with the interaction of Next Protocol | |
| 580 * Negotiation and Snap Start. It's called just before we serialise the embedded | |
| 581 * Finished message in the extension. At this point, if NPN is enabled, we have | |
| 582 * to include a NextProtocol message. */ | |
| 583 static SECStatus | |
| 584 ssl3_MaybeWriteNextProtocol(sslSocket *ss, SECItem *server_hello_extensions) | |
| 585 { | |
| 586 PRUint16 i16; | |
| 587 SECItem server_npn_extension; | |
| 588 | |
| 589 for (i16 = 0; i16 < ss->xtnData.numAdvertised; i16++) { | |
| 590 if (ss->xtnData.advertised[i16] == ssl_next_proto_neg_xtn) | |
| 591 break; | |
| 592 } | |
| 593 | |
| 594 if (i16 == ss->xtnData.numAdvertised) { | |
| 595 /* We didn't send an NPN extension, so no need to do anything here. */ | |
| 596 return SECSuccess; | |
| 597 } | |
| 598 | |
| 599 memset(&server_npn_extension, 0, sizeof(server_npn_extension)); | |
| 600 | |
| 601 ssl3_ForEachExtension( | |
| 602 server_hello_extensions, PR_FALSE /* is_resuming: value doesn't matter | |
| 603 in this case */, ssl3_FindServerNPNExtension, &server_npn_extension); | |
| 604 | |
| 605 if (server_npn_extension.data == NULL) { | |
| 606 /* We predicted that the server doesn't support NPN, so nothing to do | |
| 607 * here. */ | |
| 608 return SECSuccess; | |
| 609 } | |
| 610 | |
| 611 ssl3_ClientHandleNextProtoNegoXtn(ss, ssl_next_proto_neg_xtn, | |
| 612 &server_npn_extension); | |
| 613 | |
| 614 if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NO_SUPPORT) { | |
| 615 /* The server's predicted NPN extension was malformed. We're didn't pick | |
| 616 * a protocol so we won't send a NextProtocol message. However, this is | |
| 617 * probably fatal to the connection. */ | |
| 618 return SECSuccess; | |
| 619 } | |
| 620 | |
| 621 return ssl3_AppendSnapStartHandshakeRecord(ss, ssl3_SendNextProto, | |
| 622 PR_TRUE /* encrypt */); | |
| 623 } | |
| 624 | |
| 625 /* ssl3_SendSnapStartXtn appends a Snap Start extension. It assumes that the | |
| 626 * inchoate ClientHello is in |ss->sec.ci.sendBuf|. */ | |
| 627 PRInt32 | |
| 628 ssl3_SendSnapStartXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) | |
| 629 { | |
| 630 unsigned char orbit[8]; | |
| 631 PRBool resuming = PR_FALSE; | |
| 632 unsigned char suggested_server_random[32]; | |
| 633 SECStatus rv; | |
| 634 PRUint64 fnv; | |
| 635 /* The context for |ssl3_SnapStartHash|. The first pointer points to |ss| | |
| 636 * and the second to the running FNV1A64 hash of the predicted server | |
| 637 * response. */ | |
| 638 void *ctx[2]; | |
| 639 unsigned int snap_start_extension_len_offset, original_sendbuf_len; | |
| 640 ssl3CipherSpec *temp; | |
| 641 sslSessionID *sid; | |
| 642 SECItem server_extensions; | |
| 643 | |
| 644 if (!ss->opt.enableSnapStart) | |
| 645 return 0; | |
| 646 | |
| 647 original_sendbuf_len = ss->sec.ci.sendBuf.len; | |
| 648 | |
| 649 /* This function is called twice for each ClientHello emitted. The first | |
| 650 * time around is to calculate the sizes of the extension (|append| is | |
| 651 * false). The second time around is to actually write out the bytes | |
| 652 * (|append| is true). | |
| 653 * | |
| 654 * We always return 0 bytes in each case because we want to be able to hash | |
| 655 * the inchoate ClientHello as if this extension was missing: that's why | |
| 656 * it's important that this always be the last extension serialised. */ | |
| 657 sid = ss->sec.ci.sid; | |
| 658 | |
| 659 if (!ss->opt.enableSessionTickets || ss->sec.isServer) | |
| 660 return 0; | |
| 661 | |
| 662 /* If we are sending a SessionTicket then the first time around | |
| 663 * ticketTimestampVerified will be true but it's reset after serialising | |
| 664 * the session ticket extension, so we have | |
| 665 * |clientSentNonEmptySessionTicket|. */ | |
| 666 if (ss->xtnData.clientSentNonEmptySessionTicket) { | |
| 667 resuming = PR_TRUE; | |
| 668 } else if (sid->u.ssl3.sessionTicket.ticket.data && | |
| 669 ss->xtnData.ticketTimestampVerified) { | |
| 670 resuming = PR_TRUE; | |
| 671 } | |
| 672 | |
| 673 if (!ssl3_CanSnapStart(ss, &server_extensions, resuming, orbit)) | |
| 674 return ssl3_SendEmptySnapStartXtn(ss, append, maxBytes); | |
| 675 | |
| 676 /* At this point we are happy that we are going to send a non-empty Snap | |
| 677 * Start extension. If we are still calculating length then we lie and | |
| 678 * return 0 so that everything is set up as if the extension didn't exist | |
| 679 * when this function is called again later. */ | |
| 680 | |
| 681 if (!append) | |
| 682 return 0; | |
| 683 | |
| 684 /* |ss->sec.ci.sendBuf.buf| contains the inchoate ClientHello. This copies | |
| 685 * the ClientHello's gmt_unix_time into the suggested server random. */ | |
| 686 memcpy(suggested_server_random, ss->sec.ci.sendBuf.buf + 6, 4); | |
| 687 memcpy(suggested_server_random + 4, orbit, 8); | |
| 688 rv = PK11_GenerateRandom(suggested_server_random + 12, 20); | |
| 689 if (rv != SECSuccess) | |
| 690 goto loser; | |
| 691 memcpy(ss->ssl3.serverHelloPredictionData.data + 2, suggested_server_random, | |
| 692 32); | |
| 693 | |
| 694 memcpy(&ss->ssl3.hs.server_random, suggested_server_random, 32); | |
| 695 | |
| 696 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); | |
| 697 rv = ssl3_SetupPendingCipherSpec(ss); | |
| 698 if (rv != SECSuccess) | |
| 699 goto loser; | |
| 700 ss->ssl3.hs.isResuming = resuming; | |
| 701 | |
| 702 FNV1A64_Init(&fnv); | |
| 703 ctx[0] = ss; | |
| 704 ctx[1] = &fnv; | |
| 705 | |
| 706 if (!ssl3_PredictServerResponse(ss, &ss->ssl3.serverHelloPredictionData, | |
| 707 resuming, ssl3_SnapStartHash, ctx)) { | |
| 708 /* It's not a fatal error if the predicted ServerHello was invalid. */ | |
| 709 return 0; | |
| 710 } | |
| 711 FNV1A64_Final(&fnv); | |
| 712 | |
| 713 /* Now we grow the send buffer to accomodate the extension type and length, | |
| 714 * orbit, suggested random and predicted server response hash without | |
| 715 * calling ssl3_AppendHandshake (which would also update the Finished | |
| 716 * hash). */ | |
| 717 if (ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 4 + 8 + 20 + 8) != SECSuccess) | |
| 718 goto loser; | |
| 719 | |
| 720 PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len], | |
| 721 ssl_snap_start_xtn); | |
| 722 ss->sec.ci.sendBuf.len += 2; | |
| 723 /* Skip over the length for now. */ | |
| 724 snap_start_extension_len_offset = ss->sec.ci.sendBuf.len; | |
| 725 ss->sec.ci.sendBuf.len += 2; | |
| 726 memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, orbit, 8); | |
| 727 ss->sec.ci.sendBuf.len += 8; | |
| 728 memcpy(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len], | |
| 729 suggested_server_random + 12, 20); | |
| 730 ss->sec.ci.sendBuf.len += 20; | |
| 731 memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, &fnv, 8); | |
| 732 ss->sec.ci.sendBuf.len += 8; | |
| 733 | |
| 734 if (!resuming) { | |
| 735 /* Write ClientKeyExchange */ | |
| 736 ss->sec.peerCert = | |
| 737 CERT_DupCertificate(ss->ssl3.predictedCertChain[0]); | |
| 738 rv = ssl3_AppendSnapStartHandshakeRecord( | |
| 739 ss, ssl3_SendClientKeyExchange, PR_FALSE /* do not encrypt */); | |
| 740 if (rv != SECSuccess) | |
| 741 goto loser; | |
| 742 } else { | |
| 743 SSL3Finished hashes; | |
| 744 TLSFinished tlsFinished; | |
| 745 unsigned char hdr[4]; | |
| 746 | |
| 747 rv = ssl3_SetupMasterSecretFromSessionID(ss); | |
| 748 if (rv == SECFailure) | |
| 749 goto loser; | |
| 750 | |
| 751 if (sid->peerCert != NULL) { | |
| 752 ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); | |
| 753 ssl3_CopyPeerCertsFromSID(ss, sid); | |
| 754 } | |
| 755 | |
| 756 rv = ssl3_InitPendingCipherSpec(ss, NULL /* re-use master secret */); | |
| 757 if (rv != SECSuccess) | |
| 758 goto loser; | |
| 759 | |
| 760 /* Need to add the server's predicted Finished message to our handshake | |
| 761 * hash in order to be able to produce our own Finished message. */ | |
| 762 rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, | |
| 763 0 /* only for SSL3 */); | |
| 764 if (rv != SECSuccess) | |
| 765 goto loser; | |
| 766 | |
| 767 rv = ssl3_ComputeTLSFinished(ss->ssl3.pwSpec, PR_TRUE /* isServer */, | |
| 768 &hashes, &tlsFinished); | |
| 769 if (rv != SECSuccess) | |
| 770 goto loser; | |
| 771 | |
| 772 hdr[0] = (unsigned char) finished; | |
| 773 hdr[1] = hdr[2] = 0; | |
| 774 hdr[3] = sizeof(tlsFinished.verify_data); | |
| 775 ssl3_UpdateHandshakeHashes(ss, hdr, sizeof(hdr)); | |
| 776 ssl3_UpdateHandshakeHashes(ss, tlsFinished.verify_data, | |
| 777 sizeof(tlsFinished.verify_data)); | |
| 778 | |
| 779 /* Store the Finished message so that we can verify it later */ | |
| 780 memcpy(&ss->ssl3.hs.finishedMsgs.tFinished[1], tlsFinished.verify_data, | |
| 781 sizeof(tlsFinished.verify_data)); | |
| 782 } | |
| 783 | |
| 784 /* Write ChangeCipherSpec */ | |
| 785 rv = ssl3_AppendSnapStartRecordHeader(ss, content_change_cipher_spec, 1); | |
| 786 if (rv != SECSuccess) | |
| 787 goto loser; | |
| 788 rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 1); | |
| 789 if (rv != SECSuccess) | |
| 790 goto loser; | |
| 791 ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len] = change_cipher_spec_choice; | |
| 792 ss->sec.ci.sendBuf.len++; | |
| 793 | |
| 794 /* We swap |cwSpec| and |pwSpec| temporarily in order to encrypt some | |
| 795 * records before switching them back so that the whole ClientHello doesn't | |
| 796 * get encrypted. */ | |
| 797 ssl_GetSpecWriteLock(ss); | |
| 798 temp = ss->ssl3.cwSpec; | |
| 799 ss->ssl3.cwSpec = ss->ssl3.pwSpec; | |
| 800 ss->ssl3.pwSpec = temp; | |
| 801 ss->ssl3.cwSpec->write_seq_num.high = 0; | |
| 802 ss->ssl3.cwSpec->write_seq_num.low = 0; | |
| 803 ssl_ReleaseSpecWriteLock(ss); | |
| 804 | |
| 805 rv = ssl3_MaybeWriteNextProtocol(ss, &server_extensions); | |
| 806 if (rv != SECSuccess) | |
| 807 goto loser; | |
| 808 | |
| 809 /* Write Finished */ | |
| 810 rv = ssl3_AppendSnapStartHandshakeRecord(ss, ssl3_SendSnapStartFinished, | |
| 811 PR_TRUE /* encrypt */); | |
| 812 if (rv != SECSuccess) | |
| 813 goto loser; | |
| 814 | |
| 815 /* Write application data */ | |
| 816 if (ss->ssl3.snapStartApplicationData.data) { | |
| 817 rv = ssl3_AppendSnapStartApplicationData( | |
| 818 ss, ss->ssl3.snapStartApplicationData.data, | |
| 819 ss->ssl3.snapStartApplicationData.len); | |
| 820 SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE); | |
| 821 if (rv != SECSuccess) | |
| 822 goto loser; | |
| 823 } | |
| 824 | |
| 825 /* Revert the write cipher spec because the ClientHello will get encrypted | |
| 826 * with it otherwise. */ | |
| 827 ssl_GetSpecWriteLock(ss); | |
| 828 temp = ss->ssl3.cwSpec; | |
| 829 ss->ssl3.cwSpec = ss->ssl3.pwSpec; | |
| 830 ss->ssl3.pwSpec = temp; | |
| 831 ssl_ReleaseSpecWriteLock(ss); | |
| 832 | |
| 833 /* Update the lengths in the ClientHello to reflect this extension. */ | |
| 834 ssl3_UpdateClientHelloLengths(ss, snap_start_extension_len_offset, sid); | |
| 835 | |
| 836 /* Keep a copy of the ClientHello around so that we can hash it in the case | |
| 837 * the the Snap Start handshake is rejected. */ | |
| 838 | |
| 839 if (SECITEM_AllocItem(NULL, &ss->ssl3.hs.origClientHello, | |
| 840 ss->sec.ci.sendBuf.len) == NULL) { | |
| 841 goto loser; | |
| 842 } | |
| 843 memcpy(ss->ssl3.hs.origClientHello.data, ss->sec.ci.sendBuf.buf, | |
| 844 ss->sec.ci.sendBuf.len); | |
| 845 ss->ssl3.hs.origClientHello.len = ss->sec.ci.sendBuf.len; | |
| 846 | |
| 847 ss->xtnData.advertised[ss->xtnData.numAdvertised++] = ssl_snap_start_xtn; | |
| 848 | |
| 849 if (resuming) { | |
| 850 ss->ssl3.hs.snapStartType = snap_start_resume; | |
| 851 } else { | |
| 852 ss->ssl3.hs.snapStartType = snap_start_full; | |
| 853 } | |
| 854 | |
| 855 return 0; | |
| 856 | |
| 857 loser: | |
| 858 /* In the case of an error we revert the length of the sendBuf to remove | |
| 859 * any partial data that we may have appended. */ | |
| 860 ss->sec.ci.sendBuf.len = original_sendbuf_len; | |
| 861 return -1; | |
| 862 } | |
| 863 | |
| 864 SECStatus ssl3_ClientHandleSnapStartXtn(sslSocket *ss, PRUint16 ex_type, | |
| 865 SECItem *data) { | |
| 866 /* The work of saving the ServerHello is done in ssl3_HandleServerHello, | |
| 867 * where its contents are available. Here we renognise that the saved | |
| 868 * ServerHello message contains a Snap Start extension and mark it as | |
| 869 * valid. */ | |
| 870 ss->ssl3.serverHelloPredictionDataValid = PR_TRUE; | |
| 871 return SECSuccess; | |
| 872 } | |
| 873 | |
| 874 SECStatus | |
| 875 SSL_SetPredictedPeerCertificates(PRFileDesc *fd, CERTCertificate **certs, | |
| 876 unsigned int numCerts) | |
| 877 { | |
| 878 sslSocket *ss; | |
| 879 unsigned int i; | |
| 880 | |
| 881 ss = ssl_FindSocket(fd); | |
| 882 if (!ss) { | |
| 883 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPredictedPeerCertificates", | |
| 884 SSL_GETPID(), fd)); | |
| 885 return SECFailure; | |
| 886 } | |
| 887 | |
| 888 ss->ssl3.predictedCertChain = | |
| 889 PORT_NewArray(CERTCertificate*, numCerts + 1); | |
| 890 if (!ss->ssl3.predictedCertChain) | |
| 891 return SECFailure; /* error code was set */ | |
| 892 for (i = 0; i < numCerts; i++) | |
| 893 ss->ssl3.predictedCertChain[i] = CERT_DupCertificate(certs[i]); | |
| 894 ss->ssl3.predictedCertChain[numCerts] = NULL; | |
| 895 | |
| 896 return SECSuccess; | |
| 897 } | |
| 898 | |
| 899 void | |
| 900 ssl3_CleanupPredictedPeerCertificates(sslSocket *ss) { | |
| 901 unsigned int i; | |
| 902 | |
| 903 if (!ss->ssl3.predictedCertChain) | |
| 904 return; | |
| 905 | |
| 906 for (i = 0; ss->ssl3.predictedCertChain[i]; i++) { | |
| 907 CERT_DestroyCertificate(ss->ssl3.predictedCertChain[i]); | |
| 908 } | |
| 909 | |
| 910 PORT_Free(ss->ssl3.predictedCertChain); | |
| 911 ss->ssl3.predictedCertChain = NULL; | |
| 912 } | |
| 913 | |
| 914 SECStatus | |
| 915 SSL_GetPredictedServerHelloData(PRFileDesc *fd, const unsigned char **data, | |
| 916 unsigned int *data_len) | |
| 917 { | |
| 918 sslSocket *ss; | |
| 919 | |
| 920 ss = ssl_FindSocket(fd); | |
| 921 if (!ss) { | |
| 922 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetPredictedServerHelloData", | |
| 923 SSL_GETPID(), fd)); | |
| 924 *data = NULL; | |
| 925 *data_len = 0; | |
| 926 return SECFailure; | |
| 927 } | |
| 928 | |
| 929 if (!ss->ssl3.serverHelloPredictionDataValid) { | |
| 930 *data = NULL; | |
| 931 *data_len = 0; | |
| 932 } else { | |
| 933 *data = ss->ssl3.serverHelloPredictionData.data; | |
| 934 *data_len = ss->ssl3.serverHelloPredictionData.len; | |
| 935 } | |
| 936 return SECSuccess; | |
| 937 } | |
| 938 | |
| 939 SECStatus | |
| 940 SSL_SetPredictedServerHelloData(PRFileDesc *fd, const unsigned char *data, | |
| 941 unsigned int data_len) | |
| 942 { | |
| 943 sslSocket *ss; | |
| 944 | |
| 945 ss = ssl_FindSocket(fd); | |
| 946 if (!ss) { | |
| 947 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPredictedServerHelloData", | |
| 948 SSL_GETPID(), fd)); | |
| 949 return SECFailure; | |
| 950 } | |
| 951 | |
| 952 if (ss->ssl3.serverHelloPredictionData.data) | |
| 953 SECITEM_FreeItem(&ss->ssl3.serverHelloPredictionData, PR_FALSE); | |
| 954 if (!SECITEM_AllocItem(NULL, &ss->ssl3.serverHelloPredictionData, data_len)) | |
| 955 return SECFailure; | |
| 956 memcpy(ss->ssl3.serverHelloPredictionData.data, data, data_len); | |
| 957 return SECSuccess; | |
| 958 } | |
| 959 | |
| 960 SECStatus | |
| 961 SSL_SetSnapStartApplicationData(PRFileDesc *fd, const unsigned char *data, | |
| 962 unsigned int data_len) | |
| 963 { | |
| 964 sslSocket *ss; | |
| 965 | |
| 966 ss = ssl_FindSocket(fd); | |
| 967 if (!ss) { | |
| 968 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetSnapStartApplicationData", | |
| 969 SSL_GETPID(), fd)); | |
| 970 return SECFailure; | |
| 971 } | |
| 972 | |
| 973 if (ss->ssl3.snapStartApplicationData.data) | |
| 974 SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE); | |
| 975 if (!SECITEM_AllocItem(NULL, &ss->ssl3.snapStartApplicationData, data_len)) | |
| 976 return SECFailure; | |
| 977 memcpy(ss->ssl3.snapStartApplicationData.data, data, data_len); | |
| 978 return SECSuccess; | |
| 979 } | |
| 980 | |
| 981 SECStatus | |
| 982 SSL_GetSnapStartResult(PRFileDesc *fd, SSLSnapStartResult *result) | |
| 983 { | |
| 984 sslSocket *ss; | |
| 985 | |
| 986 ss = ssl_FindSocket(fd); | |
| 987 if (!ss) { | |
| 988 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetSnapStartResult", | |
| 989 SSL_GETPID(), fd)); | |
| 990 return SECFailure; | |
| 991 } | |
| 992 | |
| 993 switch (ss->ssl3.hs.snapStartType) { | |
| 994 case snap_start_full: | |
| 995 *result = SSL_SNAP_START_FULL; | |
| 996 break; | |
| 997 case snap_start_recovery: | |
| 998 *result = SSL_SNAP_START_RECOVERY; | |
| 999 break; | |
| 1000 case snap_start_resume: | |
| 1001 *result = SSL_SNAP_START_RESUME; | |
| 1002 break; | |
| 1003 case snap_start_resume_recovery: | |
| 1004 *result = SSL_SNAP_START_RESUME_RECOVERY; | |
| 1005 break; | |
| 1006 default: | |
| 1007 PORT_Assert(ss->ssl3.hs.snapStartType == snap_start_none); | |
| 1008 *result = SSL_SNAP_START_NONE; | |
| 1009 break; | |
| 1010 } | |
| 1011 | |
| 1012 return SECSuccess; | |
| 1013 } | |
| 1014 | |
| 1015 /* Called form ssl3_HandleServerHello in the case that we sent a Snap Start | |
| 1016 ** ClientHello but received a ServerHello in reply. | |
| 1017 */ | |
| 1018 SECStatus | |
| 1019 ssl3_ResetForSnapStartRecovery(sslSocket *ss, SSL3Opaque *b, PRUint32 length) | |
| 1020 { | |
| 1021 SECStatus rv; | |
| 1022 PRUint8 hdr[4]; | |
| 1023 | |
| 1024 ss->ssl3.hs.ws = wait_server_hello; | |
| 1025 | |
| 1026 /* Need to reset the Finished hashes to include the full ClientHello | |
| 1027 * message. */ | |
| 1028 | |
| 1029 rv = ssl3_RestartHandshakeHashes(ss); | |
| 1030 if (rv != SECSuccess) | |
| 1031 return rv; | |
| 1032 rv = ssl3_UpdateHandshakeHashes(ss, ss->ssl3.hs.origClientHello.data, | |
| 1033 ss->ssl3.hs.origClientHello.len); | |
| 1034 SECITEM_FreeItem(&ss->ssl3.hs.origClientHello, PR_FALSE); | |
| 1035 if (rv != SECSuccess) | |
| 1036 return rv; | |
| 1037 | |
| 1038 hdr[0] = (PRUint8)server_hello; | |
| 1039 hdr[1] = (PRUint8)(length >> 16); | |
| 1040 hdr[2] = (PRUint8)(length >> 8); | |
| 1041 hdr[3] = (PRUint8)(length ); | |
| 1042 | |
| 1043 rv = ssl3_UpdateHandshakeHashes(ss, hdr, sizeof(hdr)); | |
| 1044 if (rv != SECSuccess) | |
| 1045 return rv; | |
| 1046 rv = ssl3_UpdateHandshakeHashes(ss, b, length); | |
| 1047 if (rv != SECSuccess) | |
| 1048 return rv; | |
| 1049 | |
| 1050 if (ss->ssl3.hs.snapStartType == snap_start_full) { | |
| 1051 ss->ssl3.hs.snapStartType = snap_start_recovery; | |
| 1052 } else { | |
| 1053 ss->ssl3.hs.snapStartType = snap_start_resume_recovery; | |
| 1054 } | |
| 1055 | |
| 1056 ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_SUPPORT; | |
| 1057 | |
| 1058 ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_TRUE/*freeSrvName*/); | |
| 1059 | |
| 1060 return SECSuccess; | |
| 1061 } | |
| OLD | NEW |