security/nss/lib/ssl/ssl3gthr.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /*
michael@0 2 * Gather (Read) entire SSL3 records from socket into buffer.
michael@0 3 *
michael@0 4 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 5 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 7
michael@0 8 #include "cert.h"
michael@0 9 #include "ssl.h"
michael@0 10 #include "sslimpl.h"
michael@0 11 #include "ssl3prot.h"
michael@0 12
michael@0 13 /*
michael@0 14 * Attempt to read in an entire SSL3 record.
michael@0 15 * Blocks here for blocking sockets, otherwise returns -1 with
michael@0 16 * PR_WOULD_BLOCK_ERROR when socket would block.
michael@0 17 *
michael@0 18 * returns 1 if received a complete SSL3 record.
michael@0 19 * returns 0 if recv returns EOF
michael@0 20 * returns -1 if recv returns < 0
michael@0 21 * (The error value may have already been set to PR_WOULD_BLOCK_ERROR)
michael@0 22 *
michael@0 23 * Caller must hold the recv buf lock.
michael@0 24 *
michael@0 25 * The Gather state machine has 3 states: GS_INIT, GS_HEADER, GS_DATA.
michael@0 26 * GS_HEADER: waiting for the 5-byte SSL3 record header to come in.
michael@0 27 * GS_DATA: waiting for the body of the SSL3 record to come in.
michael@0 28 *
michael@0 29 * This loop returns when either
michael@0 30 * (a) an error or EOF occurs,
michael@0 31 * (b) PR_WOULD_BLOCK_ERROR,
michael@0 32 * (c) data (entire SSL3 record) has been received.
michael@0 33 */
michael@0 34 static int
michael@0 35 ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags)
michael@0 36 {
michael@0 37 unsigned char *bp;
michael@0 38 unsigned char *lbp;
michael@0 39 int nb;
michael@0 40 int err;
michael@0 41 int rv = 1;
michael@0 42
michael@0 43 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
michael@0 44 if (gs->state == GS_INIT) {
michael@0 45 gs->state = GS_HEADER;
michael@0 46 gs->remainder = 5;
michael@0 47 gs->offset = 0;
michael@0 48 gs->writeOffset = 0;
michael@0 49 gs->readOffset = 0;
michael@0 50 gs->inbuf.len = 0;
michael@0 51 }
michael@0 52
michael@0 53 lbp = gs->inbuf.buf;
michael@0 54 for(;;) {
michael@0 55 SSL_TRC(30, ("%d: SSL3[%d]: gather state %d (need %d more)",
michael@0 56 SSL_GETPID(), ss->fd, gs->state, gs->remainder));
michael@0 57 bp = ((gs->state != GS_HEADER) ? lbp : gs->hdr) + gs->offset;
michael@0 58 nb = ssl_DefRecv(ss, bp, gs->remainder, flags);
michael@0 59
michael@0 60 if (nb > 0) {
michael@0 61 PRINT_BUF(60, (ss, "raw gather data:", bp, nb));
michael@0 62 } else if (nb == 0) {
michael@0 63 /* EOF */
michael@0 64 SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd));
michael@0 65 rv = 0;
michael@0 66 break;
michael@0 67 } else /* if (nb < 0) */ {
michael@0 68 SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd,
michael@0 69 PR_GetError()));
michael@0 70 rv = SECFailure;
michael@0 71 break;
michael@0 72 }
michael@0 73
michael@0 74 PORT_Assert( nb <= gs->remainder );
michael@0 75 if (nb > gs->remainder) {
michael@0 76 /* ssl_DefRecv is misbehaving! this error is fatal to SSL. */
michael@0 77 gs->state = GS_INIT; /* so we don't crash next time */
michael@0 78 rv = SECFailure;
michael@0 79 break;
michael@0 80 }
michael@0 81
michael@0 82 gs->offset += nb;
michael@0 83 gs->remainder -= nb;
michael@0 84 if (gs->state == GS_DATA)
michael@0 85 gs->inbuf.len += nb;
michael@0 86
michael@0 87 /* if there's more to go, read some more. */
michael@0 88 if (gs->remainder > 0) {
michael@0 89 continue;
michael@0 90 }
michael@0 91
michael@0 92 /* have received entire record header, or entire record. */
michael@0 93 switch (gs->state) {
michael@0 94 case GS_HEADER:
michael@0 95 /*
michael@0 96 ** Have received SSL3 record header in gs->hdr.
michael@0 97 ** Now extract the length of the following encrypted data,
michael@0 98 ** and then read in the rest of the SSL3 record into gs->inbuf.
michael@0 99 */
michael@0 100 gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4];
michael@0 101
michael@0 102 /* This is the max fragment length for an encrypted fragment
michael@0 103 ** plus the size of the record header.
michael@0 104 */
michael@0 105 if(gs->remainder > (MAX_FRAGMENT_LENGTH + 2048 + 5)) {
michael@0 106 SSL3_SendAlert(ss, alert_fatal, unexpected_message);
michael@0 107 gs->state = GS_INIT;
michael@0 108 PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
michael@0 109 return SECFailure;
michael@0 110 }
michael@0 111
michael@0 112 gs->state = GS_DATA;
michael@0 113 gs->offset = 0;
michael@0 114 gs->inbuf.len = 0;
michael@0 115
michael@0 116 if (gs->remainder > gs->inbuf.space) {
michael@0 117 err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
michael@0 118 if (err) { /* realloc has set error code to no mem. */
michael@0 119 return err;
michael@0 120 }
michael@0 121 lbp = gs->inbuf.buf;
michael@0 122 }
michael@0 123 break; /* End this case. Continue around the loop. */
michael@0 124
michael@0 125
michael@0 126 case GS_DATA:
michael@0 127 /*
michael@0 128 ** SSL3 record has been completely received.
michael@0 129 */
michael@0 130 gs->state = GS_INIT;
michael@0 131 return 1;
michael@0 132 }
michael@0 133 }
michael@0 134
michael@0 135 return rv;
michael@0 136 }
michael@0 137
michael@0 138 /*
michael@0 139 * Read in an entire DTLS record.
michael@0 140 *
michael@0 141 * Blocks here for blocking sockets, otherwise returns -1 with
michael@0 142 * PR_WOULD_BLOCK_ERROR when socket would block.
michael@0 143 *
michael@0 144 * This is simpler than SSL because we are reading on a datagram socket
michael@0 145 * and datagrams must contain >=1 complete records.
michael@0 146 *
michael@0 147 * returns 1 if received a complete DTLS record.
michael@0 148 * returns 0 if recv returns EOF
michael@0 149 * returns -1 if recv returns < 0
michael@0 150 * (The error value may have already been set to PR_WOULD_BLOCK_ERROR)
michael@0 151 *
michael@0 152 * Caller must hold the recv buf lock.
michael@0 153 *
michael@0 154 * This loop returns when either
michael@0 155 * (a) an error or EOF occurs,
michael@0 156 * (b) PR_WOULD_BLOCK_ERROR,
michael@0 157 * (c) data (entire DTLS record) has been received.
michael@0 158 */
michael@0 159 static int
michael@0 160 dtls_GatherData(sslSocket *ss, sslGather *gs, int flags)
michael@0 161 {
michael@0 162 int nb;
michael@0 163 int err;
michael@0 164 int rv = 1;
michael@0 165
michael@0 166 SSL_TRC(30, ("dtls_GatherData"));
michael@0 167
michael@0 168 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
michael@0 169
michael@0 170 gs->state = GS_HEADER;
michael@0 171 gs->offset = 0;
michael@0 172
michael@0 173 if (gs->dtlsPacketOffset == gs->dtlsPacket.len) { /* No data left */
michael@0 174 gs->dtlsPacketOffset = 0;
michael@0 175 gs->dtlsPacket.len = 0;
michael@0 176
michael@0 177 /* Resize to the maximum possible size so we can fit a full datagram */
michael@0 178 /* This is the max fragment length for an encrypted fragment
michael@0 179 ** plus the size of the record header.
michael@0 180 ** This magic constant is copied from ssl3_GatherData, with 5 changed
michael@0 181 ** to 13 (the size of the record header).
michael@0 182 */
michael@0 183 if (gs->dtlsPacket.space < MAX_FRAGMENT_LENGTH + 2048 + 13) {
michael@0 184 err = sslBuffer_Grow(&gs->dtlsPacket,
michael@0 185 MAX_FRAGMENT_LENGTH + 2048 + 13);
michael@0 186 if (err) { /* realloc has set error code to no mem. */
michael@0 187 return err;
michael@0 188 }
michael@0 189 }
michael@0 190
michael@0 191 /* recv() needs to read a full datagram at a time */
michael@0 192 nb = ssl_DefRecv(ss, gs->dtlsPacket.buf, gs->dtlsPacket.space, flags);
michael@0 193
michael@0 194 if (nb > 0) {
michael@0 195 PRINT_BUF(60, (ss, "raw gather data:", gs->dtlsPacket.buf, nb));
michael@0 196 } else if (nb == 0) {
michael@0 197 /* EOF */
michael@0 198 SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd));
michael@0 199 rv = 0;
michael@0 200 return rv;
michael@0 201 } else /* if (nb < 0) */ {
michael@0 202 SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd,
michael@0 203 PR_GetError()));
michael@0 204 rv = SECFailure;
michael@0 205 return rv;
michael@0 206 }
michael@0 207
michael@0 208 gs->dtlsPacket.len = nb;
michael@0 209 }
michael@0 210
michael@0 211 /* At this point we should have >=1 complete records lined up in
michael@0 212 * dtlsPacket. Read off the header.
michael@0 213 */
michael@0 214 if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < 13) {
michael@0 215 SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet "
michael@0 216 "too short to contain header", SSL_GETPID(), ss->fd));
michael@0 217 PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
michael@0 218 gs->dtlsPacketOffset = 0;
michael@0 219 gs->dtlsPacket.len = 0;
michael@0 220 rv = SECFailure;
michael@0 221 return rv;
michael@0 222 }
michael@0 223 memcpy(gs->hdr, gs->dtlsPacket.buf + gs->dtlsPacketOffset, 13);
michael@0 224 gs->dtlsPacketOffset += 13;
michael@0 225
michael@0 226 /* Have received SSL3 record header in gs->hdr. */
michael@0 227 gs->remainder = (gs->hdr[11] << 8) | gs->hdr[12];
michael@0 228
michael@0 229 if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < gs->remainder) {
michael@0 230 SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet too short "
michael@0 231 "to contain rest of body", SSL_GETPID(), ss->fd));
michael@0 232 PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
michael@0 233 gs->dtlsPacketOffset = 0;
michael@0 234 gs->dtlsPacket.len = 0;
michael@0 235 rv = SECFailure;
michael@0 236 return rv;
michael@0 237 }
michael@0 238
michael@0 239 /* OK, we have at least one complete packet, copy into inbuf */
michael@0 240 if (gs->remainder > gs->inbuf.space) {
michael@0 241 err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
michael@0 242 if (err) { /* realloc has set error code to no mem. */
michael@0 243 return err;
michael@0 244 }
michael@0 245 }
michael@0 246
michael@0 247 memcpy(gs->inbuf.buf, gs->dtlsPacket.buf + gs->dtlsPacketOffset,
michael@0 248 gs->remainder);
michael@0 249 gs->inbuf.len = gs->remainder;
michael@0 250 gs->offset = gs->remainder;
michael@0 251 gs->dtlsPacketOffset += gs->remainder;
michael@0 252 gs->state = GS_INIT;
michael@0 253
michael@0 254 return 1;
michael@0 255 }
michael@0 256
michael@0 257 /* Gather in a record and when complete, Handle that record.
michael@0 258 * Repeat this until the handshake is complete,
michael@0 259 * or until application data is available.
michael@0 260 *
michael@0 261 * Returns 1 when the handshake is completed without error, or
michael@0 262 * application data is available.
michael@0 263 * Returns 0 if ssl3_GatherData hits EOF.
michael@0 264 * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error.
michael@0 265 * Returns -2 on SECWouldBlock return from ssl3_HandleRecord.
michael@0 266 *
michael@0 267 * Called from ssl_GatherRecord1stHandshake in sslcon.c,
michael@0 268 * and from SSL_ForceHandshake in sslsecur.c
michael@0 269 * and from ssl3_GatherAppDataRecord below (<- DoRecv in sslsecur.c).
michael@0 270 *
michael@0 271 * Caller must hold the recv buf lock.
michael@0 272 */
michael@0 273 int
michael@0 274 ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
michael@0 275 {
michael@0 276 SSL3Ciphertext cText;
michael@0 277 int rv;
michael@0 278 PRBool keepGoing = PR_TRUE;
michael@0 279
michael@0 280 SSL_TRC(30, ("ssl3_GatherCompleteHandshake"));
michael@0 281
michael@0 282 /* ssl3_HandleRecord may end up eventually calling ssl_FinishHandshake,
michael@0 283 * which requires the 1stHandshakeLock, which must be acquired before the
michael@0 284 * RecvBufLock.
michael@0 285 */
michael@0 286 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
michael@0 287 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
michael@0 288
michael@0 289 do {
michael@0 290 PRBool handleRecordNow = PR_FALSE;
michael@0 291
michael@0 292 ssl_GetSSL3HandshakeLock(ss);
michael@0 293
michael@0 294 /* Without this, we may end up wrongly reporting
michael@0 295 * SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the
michael@0 296 * peer while we are waiting to be restarted.
michael@0 297 */
michael@0 298 if (ss->ssl3.hs.restartTarget) {
michael@0 299 ssl_ReleaseSSL3HandshakeLock(ss);
michael@0 300 PORT_SetError(PR_WOULD_BLOCK_ERROR);
michael@0 301 return (int) SECFailure;
michael@0 302 }
michael@0 303
michael@0 304 /* Treat an empty msgState like a NULL msgState. (Most of the time
michael@0 305 * when ssl3_HandleHandshake returns SECWouldBlock, it leaves
michael@0 306 * behind a non-NULL but zero-length msgState).
michael@0 307 * Test: async_cert_restart_server_sends_hello_request_first_in_separate_record
michael@0 308 */
michael@0 309 if (ss->ssl3.hs.msgState.buf) {
michael@0 310 if (ss->ssl3.hs.msgState.len == 0) {
michael@0 311 ss->ssl3.hs.msgState.buf = NULL;
michael@0 312 } else {
michael@0 313 handleRecordNow = PR_TRUE;
michael@0 314 }
michael@0 315 }
michael@0 316
michael@0 317 ssl_ReleaseSSL3HandshakeLock(ss);
michael@0 318
michael@0 319 if (handleRecordNow) {
michael@0 320 /* ssl3_HandleHandshake previously returned SECWouldBlock and the
michael@0 321 * as-yet-unprocessed plaintext of that previous handshake record.
michael@0 322 * We need to process it now before we overwrite it with the next
michael@0 323 * handshake record.
michael@0 324 */
michael@0 325 rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf);
michael@0 326 } else {
michael@0 327 /* bring in the next sslv3 record. */
michael@0 328 if (ss->recvdCloseNotify) {
michael@0 329 /* RFC 5246 Section 7.2.1:
michael@0 330 * Any data received after a closure alert is ignored.
michael@0 331 */
michael@0 332 return 0;
michael@0 333 }
michael@0 334 if (!IS_DTLS(ss)) {
michael@0 335 rv = ssl3_GatherData(ss, &ss->gs, flags);
michael@0 336 } else {
michael@0 337 rv = dtls_GatherData(ss, &ss->gs, flags);
michael@0 338
michael@0 339 /* If we got a would block error, that means that no data was
michael@0 340 * available, so we check the timer to see if it's time to
michael@0 341 * retransmit */
michael@0 342 if (rv == SECFailure &&
michael@0 343 (PORT_GetError() == PR_WOULD_BLOCK_ERROR)) {
michael@0 344 ssl_GetSSL3HandshakeLock(ss);
michael@0 345 dtls_CheckTimer(ss);
michael@0 346 ssl_ReleaseSSL3HandshakeLock(ss);
michael@0 347 /* Restore the error in case something succeeded */
michael@0 348 PORT_SetError(PR_WOULD_BLOCK_ERROR);
michael@0 349 }
michael@0 350 }
michael@0 351
michael@0 352 if (rv <= 0) {
michael@0 353 return rv;
michael@0 354 }
michael@0 355
michael@0 356 /* decipher it, and handle it if it's a handshake.
michael@0 357 * If it's application data, ss->gs.buf will not be empty upon return.
michael@0 358 * If it's a change cipher spec, alert, or handshake message,
michael@0 359 * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSuccess.
michael@0 360 */
michael@0 361 cText.type = (SSL3ContentType)ss->gs.hdr[0];
michael@0 362 cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2];
michael@0 363
michael@0 364 if (IS_DTLS(ss)) {
michael@0 365 int i;
michael@0 366
michael@0 367 cText.version = dtls_DTLSVersionToTLSVersion(cText.version);
michael@0 368 /* DTLS sequence number */
michael@0 369 cText.seq_num.high = 0; cText.seq_num.low = 0;
michael@0 370 for (i = 0; i < 4; i++) {
michael@0 371 cText.seq_num.high <<= 8; cText.seq_num.low <<= 8;
michael@0 372 cText.seq_num.high |= ss->gs.hdr[3 + i];
michael@0 373 cText.seq_num.low |= ss->gs.hdr[7 + i];
michael@0 374 }
michael@0 375 }
michael@0 376
michael@0 377 cText.buf = &ss->gs.inbuf;
michael@0 378 rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf);
michael@0 379 }
michael@0 380 if (rv < 0) {
michael@0 381 return ss->recvdCloseNotify ? 0 : rv;
michael@0 382 }
michael@0 383 if (ss->gs.buf.len > 0) {
michael@0 384 /* We have application data to return to the application. This
michael@0 385 * prioritizes returning application data to the application over
michael@0 386 * completing any renegotiation handshake we may be doing.
michael@0 387 */
michael@0 388 PORT_Assert(ss->firstHsDone);
michael@0 389 PORT_Assert(cText.type == content_application_data);
michael@0 390 break;
michael@0 391 }
michael@0 392
michael@0 393 PORT_Assert(keepGoing);
michael@0 394 ssl_GetSSL3HandshakeLock(ss);
michael@0 395 if (ss->ssl3.hs.ws == idle_handshake) {
michael@0 396 /* We are done with the current handshake so stop trying to
michael@0 397 * handshake. Note that it would be safe to test ss->firstHsDone
michael@0 398 * instead of ss->ssl3.hs.ws. By testing ss->ssl3.hs.ws instead,
michael@0 399 * we prioritize completing a renegotiation handshake over sending
michael@0 400 * application data.
michael@0 401 */
michael@0 402 PORT_Assert(ss->firstHsDone);
michael@0 403 PORT_Assert(!ss->ssl3.hs.canFalseStart);
michael@0 404 keepGoing = PR_FALSE;
michael@0 405 } else if (ss->ssl3.hs.canFalseStart) {
michael@0 406 /* Prioritize sending application data over trying to complete
michael@0 407 * the handshake if we're false starting.
michael@0 408 *
michael@0 409 * If we were to do this check at the beginning of the loop instead
michael@0 410 * of here, then this function would become be a no-op after
michael@0 411 * receiving the ServerHelloDone in the false start case, and we
michael@0 412 * would never complete the handshake.
michael@0 413 */
michael@0 414 PORT_Assert(!ss->firstHsDone);
michael@0 415
michael@0 416 if (ssl3_WaitingForStartOfServerSecondRound(ss)) {
michael@0 417 keepGoing = PR_FALSE;
michael@0 418 } else {
michael@0 419 ss->ssl3.hs.canFalseStart = PR_FALSE;
michael@0 420 }
michael@0 421 }
michael@0 422 ssl_ReleaseSSL3HandshakeLock(ss);
michael@0 423 } while (keepGoing);
michael@0 424
michael@0 425 ss->gs.readOffset = 0;
michael@0 426 ss->gs.writeOffset = ss->gs.buf.len;
michael@0 427 return 1;
michael@0 428 }
michael@0 429
michael@0 430 /* Repeatedly gather in a record and when complete, Handle that record.
michael@0 431 * Repeat this until some application data is received.
michael@0 432 *
michael@0 433 * Returns 1 when application data is available.
michael@0 434 * Returns 0 if ssl3_GatherData hits EOF.
michael@0 435 * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error.
michael@0 436 * Returns -2 on SECWouldBlock return from ssl3_HandleRecord.
michael@0 437 *
michael@0 438 * Called from DoRecv in sslsecur.c
michael@0 439 * Caller must hold the recv buf lock.
michael@0 440 */
michael@0 441 int
michael@0 442 ssl3_GatherAppDataRecord(sslSocket *ss, int flags)
michael@0 443 {
michael@0 444 int rv;
michael@0 445
michael@0 446 /* ssl3_GatherCompleteHandshake requires both of these locks. */
michael@0 447 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
michael@0 448 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
michael@0 449
michael@0 450 do {
michael@0 451 rv = ssl3_GatherCompleteHandshake(ss, flags);
michael@0 452 } while (rv > 0 && ss->gs.buf.len == 0);
michael@0 453
michael@0 454 return rv;
michael@0 455 }

mercurial