| OLD | NEW |
| (Empty) |
| 1 Index: net/third_party/nss/ssl/SSLerrs.h | |
| 2 =================================================================== | |
| 3 --- net/third_party/nss/ssl/SSLerrs.h (revision 127709) | |
| 4 +++ net/third_party/nss/ssl/SSLerrs.h (working copy) | |
| 5 @@ -423,3 +423,9 @@ | |
| 6 | |
| 7 ER3(SSL_ERROR_RX_UNEXPECTED_CERT_STATUS, (SSL_ERROR_BASE + 121), | |
| 8 "SSL received an unexpected Certificate Status handshake message.") | |
| 9 + | |
| 10 +ER3(SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST, (SSL_ERROR_BASE + 122), | |
| 11 +"SSL received a malformed Hello Verify Request handshake message.") | |
| 12 + | |
| 13 +ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST, (SSL_ERROR_BASE + 123), | |
| 14 +"SSL received an unexpected Hello Verify Request handshake message.") | |
| 15 Index: net/third_party/nss/ssl/ssl.h | |
| 16 =================================================================== | |
| 17 --- net/third_party/nss/ssl/ssl.h (revision 127709) | |
| 18 +++ net/third_party/nss/ssl/ssl.h (working copy) | |
| 19 @@ -80,6 +80,12 @@ | |
| 20 SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd); | |
| 21 | |
| 22 /* | |
| 23 +** Imports fd into DTLS, returning a new socket. Copies DTLS configuration | |
| 24 +** from model. | |
| 25 +*/ | |
| 26 +SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd); | |
| 27 + | |
| 28 +/* | |
| 29 ** Enable/disable an ssl mode | |
| 30 ** | |
| 31 ** SSL_SECURITY: | |
| 32 @@ -942,6 +948,14 @@ | |
| 33 PRBool *last_handshake_resumed
); | |
| 34 | |
| 35 /* | |
| 36 +** How long should we wait before retransmitting the next flight of | |
| 37 +** the DTLS handshake? Returns SECFailure if not DTLS or not in a | |
| 38 +** handshake. | |
| 39 +*/ | |
| 40 +SSL_IMPORT SECStatus DTLS_GetHandshakeTimeout(PRFileDesc *socket, | |
| 41 + PRIntervalTime *timeout); | |
| 42 + | |
| 43 +/* | |
| 44 * Return a boolean that indicates whether the underlying library | |
| 45 * will perform as the caller expects. | |
| 46 * | |
| 47 Index: net/third_party/nss/ssl/ssl3gthr.c | |
| 48 =================================================================== | |
| 49 --- net/third_party/nss/ssl/ssl3gthr.c (revision 127709) | |
| 50 +++ net/third_party/nss/ssl/ssl3gthr.c (working copy) | |
| 51 @@ -50,7 +50,7 @@ | |
| 52 * | |
| 53 * returns 1 if received a complete SSL3 record. | |
| 54 * returns 0 if recv returns EOF | |
| 55 - * returns -1 if recv returns <0 | |
| 56 + * returns -1 if recv returns < 0 | |
| 57 * (The error value may have already been set to PR_WOULD_BLOCK_ERROR) | |
| 58 * | |
| 59 * Caller must hold the recv buf lock. | |
| 60 @@ -59,7 +59,8 @@ | |
| 61 * GS_HEADER: waiting for the 5-byte SSL3 record header to come in. | |
| 62 * GS_DATA: waiting for the body of the SSL3 record to come in. | |
| 63 * | |
| 64 - * This loop returns when either (a) an error or EOF occurs, | |
| 65 + * This loop returns when either | |
| 66 + * (a) an error or EOF occurs, | |
| 67 * (b) PR_WOULD_BLOCK_ERROR, | |
| 68 * (c) data (entire SSL3 record) has been received. | |
| 69 */ | |
| 70 @@ -167,6 +168,125 @@ | |
| 71 return rv; | |
| 72 } | |
| 73 | |
| 74 +/* | |
| 75 + * Read in an entire DTLS record. | |
| 76 + * | |
| 77 + * Blocks here for blocking sockets, otherwise returns -1 with | |
| 78 + * PR_WOULD_BLOCK_ERROR when socket would block. | |
| 79 + * | |
| 80 + * This is simpler than SSL because we are reading on a datagram socket | |
| 81 + * and datagrams must contain >=1 complete records. | |
| 82 + * | |
| 83 + * returns 1 if received a complete DTLS record. | |
| 84 + * returns 0 if recv returns EOF | |
| 85 + * returns -1 if recv returns < 0 | |
| 86 + * (The error value may have already been set to PR_WOULD_BLOCK_ERROR) | |
| 87 + * | |
| 88 + * Caller must hold the recv buf lock. | |
| 89 + * | |
| 90 + * This loop returns when either | |
| 91 + * (a) an error or EOF occurs, | |
| 92 + * (b) PR_WOULD_BLOCK_ERROR, | |
| 93 + * (c) data (entire DTLS record) has been received. | |
| 94 + */ | |
| 95 +static int | |
| 96 +dtls_GatherData(sslSocket *ss, sslGather *gs, int flags) | |
| 97 +{ | |
| 98 + int nb; | |
| 99 + int err; | |
| 100 + int rv = 1; | |
| 101 + | |
| 102 + SSL_TRC(30, ("dtls_GatherData")); | |
| 103 + | |
| 104 + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | |
| 105 + | |
| 106 + gs->state = GS_HEADER; | |
| 107 + gs->offset = 0; | |
| 108 + | |
| 109 + if (gs->dtlsPacketOffset == gs->dtlsPacket.len) { /* No data left */ | |
| 110 + gs->dtlsPacketOffset = 0; | |
| 111 + gs->dtlsPacket.len = 0; | |
| 112 + | |
| 113 + /* Resize to the maximum possible size so we can fit a full datagram */ | |
| 114 + /* This is the max fragment length for an encrypted fragment | |
| 115 + ** plus the size of the record header. | |
| 116 + ** This magic constant is copied from ssl3_GatherData, with 5 changed | |
| 117 + ** to 13 (the size of the record header). | |
| 118 + */ | |
| 119 + if (gs->dtlsPacket.space < MAX_FRAGMENT_LENGTH + 2048 + 13) { | |
| 120 + err = sslBuffer_Grow(&gs->dtlsPacket, | |
| 121 + MAX_FRAGMENT_LENGTH + 2048 + 13); | |
| 122 + if (err) { /* realloc has set error code to no mem. */ | |
| 123 + return err; | |
| 124 + } | |
| 125 + } | |
| 126 + | |
| 127 + /* recv() needs to read a full datagram at a time */ | |
| 128 + nb = ssl_DefRecv(ss, gs->dtlsPacket.buf, gs->dtlsPacket.space, flags); | |
| 129 + | |
| 130 + if (nb > 0) { | |
| 131 + PRINT_BUF(60, (ss, "raw gather data:", gs->dtlsPacket.buf, nb)); | |
| 132 + } else if (nb == 0) { | |
| 133 + /* EOF */ | |
| 134 + SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd)); | |
| 135 + rv = 0; | |
| 136 + return rv; | |
| 137 + } else /* if (nb < 0) */ { | |
| 138 + SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd, | |
| 139 + PR_GetError())); | |
| 140 + rv = SECFailure; | |
| 141 + return rv; | |
| 142 + } | |
| 143 + | |
| 144 + gs->dtlsPacket.len = nb; | |
| 145 + } | |
| 146 + | |
| 147 + /* At this point we should have >=1 complete records lined up in | |
| 148 + * dtlsPacket. Read off the header. | |
| 149 + */ | |
| 150 + if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < 13) { | |
| 151 + SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet " | |
| 152 + "too short to contain header", SSL_GETPID(), ss->fd)); | |
| 153 + PR_SetError(PR_WOULD_BLOCK_ERROR, 0); | |
| 154 + gs->dtlsPacketOffset = 0; | |
| 155 + gs->dtlsPacket.len = 0; | |
| 156 + rv = SECFailure; | |
| 157 + return rv; | |
| 158 + } | |
| 159 + memcpy(gs->hdr, gs->dtlsPacket.buf + gs->dtlsPacketOffset, 13); | |
| 160 + gs->dtlsPacketOffset += 13; | |
| 161 + | |
| 162 + /* Have received SSL3 record header in gs->hdr. */ | |
| 163 + gs->remainder = (gs->hdr[11] << 8) | gs->hdr[12]; | |
| 164 + | |
| 165 + if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < gs->remainder) { | |
| 166 + SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet too short " | |
| 167 + "to contain rest of body", SSL_GETPID(), ss->fd)); | |
| 168 + PR_SetError(PR_WOULD_BLOCK_ERROR, 0); | |
| 169 + gs->dtlsPacketOffset = 0; | |
| 170 + gs->dtlsPacket.len = 0; | |
| 171 + rv = SECFailure; | |
| 172 + return rv; | |
| 173 + } | |
| 174 + | |
| 175 + /* OK, we have at least one complete packet, copy into inbuf */ | |
| 176 + if (gs->remainder > gs->inbuf.space) { | |
| 177 + err = sslBuffer_Grow(&gs->inbuf, gs->remainder); | |
| 178 + if (err) { /* realloc has set error code to no mem. */ | |
| 179 + return err; | |
| 180 + } | |
| 181 + } | |
| 182 + | |
| 183 + memcpy(gs->inbuf.buf, gs->dtlsPacket.buf + gs->dtlsPacketOffset, | |
| 184 + gs->remainder); | |
| 185 + gs->inbuf.len = gs->remainder; | |
| 186 + gs->offset = gs->remainder; | |
| 187 + gs->dtlsPacketOffset += gs->remainder; | |
| 188 + gs->state = GS_INIT; | |
| 189 + | |
| 190 + return 1; | |
| 191 +} | |
| 192 + | |
| 193 /* Gather in a record and when complete, Handle that record. | |
| 194 * Repeat this until the handshake is complete, | |
| 195 * or until application data is available. | |
| 196 @@ -190,6 +310,8 @@ | |
| 197 int rv; | |
| 198 PRBool canFalseStart = PR_FALSE; | |
| 199 | |
| 200 + SSL_TRC(30, ("ssl3_GatherCompleteHandshake")); | |
| 201 + | |
| 202 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | |
| 203 do { | |
| 204 /* Without this, we may end up wrongly reporting | |
| 205 @@ -224,7 +346,24 @@ | |
| 206 rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf); | |
| 207 } else { | |
| 208 /* bring in the next sslv3 record. */ | |
| 209 - rv = ssl3_GatherData(ss, &ss->gs, flags); | |
| 210 + if (!IS_DTLS(ss)) { | |
| 211 + rv = ssl3_GatherData(ss, &ss->gs, flags); | |
| 212 + } else { | |
| 213 + rv = dtls_GatherData(ss, &ss->gs, flags); | |
| 214 + | |
| 215 + /* If we got a would block error, that means that no data was | |
| 216 + * available, so we check the timer to see if it's time to | |
| 217 + * retransmit */ | |
| 218 + if (rv == SECFailure && | |
| 219 + (PORT_GetError() == PR_WOULD_BLOCK_ERROR)) { | |
| 220 + ssl_GetSSL3HandshakeLock(ss); | |
| 221 + dtls_CheckTimer(ss); | |
| 222 + ssl_ReleaseSSL3HandshakeLock(ss); | |
| 223 + /* Restore the error in case something succeeded */ | |
| 224 + PORT_SetError(PR_WOULD_BLOCK_ERROR); | |
| 225 + } | |
| 226 + } | |
| 227 + | |
| 228 if (rv <= 0) { | |
| 229 return rv; | |
| 230 } | |
| 231 @@ -236,6 +375,20 @@ | |
| 232 */ | |
| 233 cText.type = (SSL3ContentType)ss->gs.hdr[0]; | |
| 234 cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2]; | |
| 235 + | |
| 236 + if (IS_DTLS(ss)) { | |
| 237 + int i; | |
| 238 + | |
| 239 + cText.version = dtls_DTLSVersionToTLSVersion(cText.version); | |
| 240 + /* DTLS sequence number */ | |
| 241 + cText.seq_num.high = 0; cText.seq_num.low = 0; | |
| 242 + for (i = 0; i < 4; i++) { | |
| 243 + cText.seq_num.high <<= 8; cText.seq_num.low <<= 8; | |
| 244 + cText.seq_num.high |= ss->gs.hdr[3 + i]; | |
| 245 + cText.seq_num.low |= ss->gs.hdr[7 + i]; | |
| 246 + } | |
| 247 + } | |
| 248 + | |
| 249 cText.buf = &ss->gs.inbuf; | |
| 250 rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf); | |
| 251 } | |
| 252 Index: net/third_party/nss/ssl/derive.c | |
| 253 =================================================================== | |
| 254 --- net/third_party/nss/ssl/derive.c (revision 127709) | |
| 255 +++ net/third_party/nss/ssl/derive.c (working copy) | |
| 256 @@ -583,6 +583,8 @@ | |
| 257 * arguments were all valid but the slot cannot be bypassed. | |
| 258 */ | |
| 259 | |
| 260 +/* XXX Add SSL_CBP_TLS1_1 and test it in protocolmask when setting isTLS. */ | |
| 261 + | |
| 262 SECStatus | |
| 263 SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey, | |
| 264 PRUint32 protocolmask, PRUint16 *ciphersuites, int nsuites, | |
| 265 Index: net/third_party/nss/ssl/sslerr.h | |
| 266 =================================================================== | |
| 267 --- net/third_party/nss/ssl/sslerr.h (revision 127709) | |
| 268 +++ net/third_party/nss/ssl/sslerr.h (working copy) | |
| 269 @@ -215,6 +215,9 @@ | |
| 270 | |
| 271 SSL_ERROR_RX_UNEXPECTED_CERT_STATUS = (SSL_ERROR_BASE + 121), | |
| 272 | |
| 273 +SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST = (SSL_ERROR_BASE + 122), | |
| 274 +SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST = (SSL_ERROR_BASE + 123), | |
| 275 + | |
| 276 SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */ | |
| 277 } SSLErrorCodes; | |
| 278 #endif /* NO_SECURITY_ERROR_ENUM */ | |
| 279 Index: net/third_party/nss/ssl/ssldef.c | |
| 280 =================================================================== | |
| 281 --- net/third_party/nss/ssl/ssldef.c (revision 127709) | |
| 282 +++ net/third_party/nss/ssl/ssldef.c (working copy) | |
| 283 @@ -138,6 +138,11 @@ | |
| 284 return rv; | |
| 285 } | |
| 286 sent += rv; | |
| 287 + | |
| 288 + if (IS_DTLS(ss) && (len > sent)) { | |
| 289 + /* We got a partial write so just return it */ | |
| 290 + return sent; | |
| 291 + } | |
| 292 } while (len > sent); | |
| 293 ss->lastWriteBlocked = 0; | |
| 294 return sent; | |
| 295 Index: net/third_party/nss/ssl/sslimpl.h | |
| 296 =================================================================== | |
| 297 --- net/third_party/nss/ssl/sslimpl.h (revision 127709) | |
| 298 +++ net/third_party/nss/ssl/sslimpl.h (working copy) | |
| 299 @@ -62,6 +62,7 @@ | |
| 300 #endif | |
| 301 #include "nssrwlk.h" | |
| 302 #include "prthread.h" | |
| 303 +#include "prclist.h" | |
| 304 | |
| 305 #include "sslt.h" /* for some formerly private types, now public */ | |
| 306 | |
| 307 @@ -195,6 +196,10 @@ | |
| 308 | |
| 309 #define EXPORT_RSA_KEY_LENGTH 64 /* bytes */ | |
| 310 | |
| 311 +#define INITIAL_DTLS_TIMEOUT_MS 1000 /* Default value from RFC 4347 = 1s*/ | |
| 312 +#define MAX_DTLS_TIMEOUT_MS 60000 /* 1 minute */ | |
| 313 +#define DTLS_FINISHED_TIMER_MS 120000 /* Time to wait in FINISHED state */ | |
| 314 + | |
| 315 typedef struct sslBufferStr sslBuffer; | |
| 316 typedef struct sslConnectInfoStr sslConnectInfo; | |
| 317 typedef struct sslGatherStr sslGather; | |
| 318 @@ -287,6 +292,8 @@ | |
| 319 /* Flags interpreted by ssl send functions. */ | |
| 320 #define ssl_SEND_FLAG_FORCE_INTO_BUFFER 0x40000000 | |
| 321 #define ssl_SEND_FLAG_NO_BUFFER 0x20000000 | |
| 322 +#define ssl_SEND_FLAG_USE_EPOCH 0x10000000 /* DTLS only */ | |
| 323 +#define ssl_SEND_FLAG_NO_RETRANSMIT 0x08000000 /* DTLS only */ | |
| 324 #define ssl_SEND_FLAG_MASK 0x7f000000 | |
| 325 | |
| 326 /* | |
| 327 @@ -448,8 +455,15 @@ | |
| 328 ** The portion of the SSL record header put here always comes off the wire | |
| 329 ** as plaintext, never ciphertext. | |
| 330 ** For SSL2, the plaintext portion is two bytes long. For SSl3 it is 5. | |
| 331 + ** For DTLS it is 13. | |
| 332 */ | |
| 333 - unsigned char hdr[5]; /* ssl 2 & 3 */ | |
| 334 + unsigned char hdr[13]; /* ssl 2 & 3 or dtls */ | |
| 335 + | |
| 336 + /* Buffer for DTLS data read off the wire as a single datagram */ | |
| 337 + sslBuffer dtlsPacket; | |
| 338 + | |
| 339 + /* the start of the buffered DTLS record in dtlsPacket */ | |
| 340 + unsigned int dtlsPacketOffset; | |
| 341 }; | |
| 342 | |
| 343 /* sslGather.state */ | |
| 344 @@ -521,6 +535,10 @@ | |
| 345 PRUint32 low; | |
| 346 } SSL3SequenceNumber; | |
| 347 | |
| 348 +typedef PRUint16 DTLSEpoch; | |
| 349 + | |
| 350 +typedef void (*DTLSTimerCb)(sslSocket *); | |
| 351 + | |
| 352 #define MAX_MAC_CONTEXT_BYTES 400 | |
| 353 #define MAX_MAC_CONTEXT_LLONGS (MAX_MAC_CONTEXT_BYTES / 8) | |
| 354 | |
| 355 @@ -547,6 +565,20 @@ | |
| 356 PRUint64 cipher_context[MAX_CIPHER_CONTEXT_LLONGS]; | |
| 357 } ssl3KeyMaterial; | |
| 358 | |
| 359 +/* The DTLS anti-replay window. Defined here because we need it in | |
| 360 + * the cipher spec. Note that this is a ring buffer but left and | |
| 361 + * right represent the true window, with modular arithmetic used to | |
| 362 + * map them onto the buffer. | |
| 363 + */ | |
| 364 +#define DTLS_RECVD_RECORDS_WINDOW 1024 /* Packets; approximate | |
| 365 + * Must be divisible by 8 | |
| 366 + */ | |
| 367 +typedef struct DTLSRecvdRecordsStr { | |
| 368 + unsigned char data[DTLS_RECVD_RECORDS_WINDOW/8]; | |
| 369 + PRUint64 left; | |
| 370 + PRUint64 right; | |
| 371 +} DTLSRecvdRecords; | |
| 372 + | |
| 373 /* | |
| 374 ** These are the "specs" in the "ssl3" struct. | |
| 375 ** Access to the pointers to these specs, and all the specs' contents | |
| 376 @@ -582,6 +614,8 @@ | |
| 377 SECItem srvVirtName; /* for server: name that was negotiated | |
| 378 * with a client. For client - is | |
| 379 * always set to NULL.*/ | |
| 380 + DTLSEpoch epoch; | |
| 381 + DTLSRecvdRecords recvdRecords; | |
| 382 } ssl3CipherSpec; | |
| 383 | |
| 384 typedef enum { never_cached, | |
| 385 @@ -777,6 +811,17 @@ | |
| 386 typedef SECStatus (*sslRestartTarget)(sslSocket *); | |
| 387 | |
| 388 /* | |
| 389 +** A DTLS queued message (potentially to be retransmitted) | |
| 390 +*/ | |
| 391 +typedef struct DTLSQueuedMessageStr { | |
| 392 + PRCList link; /* The linked list link */ | |
| 393 + DTLSEpoch epoch; /* The epoch to use */ | |
| 394 + SSL3ContentType type; /* The message type */ | |
| 395 + unsigned char *data; /* The data */ | |
| 396 + PRUint16 len; /* The data length */ | |
| 397 +} DTLSQueuedMessage; | |
| 398 + | |
| 399 +/* | |
| 400 ** This is the "hs" member of the "ssl3" struct. | |
| 401 ** This entire struct is protected by ssl3HandshakeLock | |
| 402 */ | |
| 403 @@ -831,6 +876,30 @@ | |
| 404 sslRestartTarget restartTarget; | |
| 405 /* Shared state between ssl3_HandleFinished and ssl3_FinishHandshake */ | |
| 406 PRBool cacheSID; | |
| 407 + | |
| 408 + /* This group of values is used for DTLS */ | |
| 409 + PRUint16 sendMessageSeq; /* The sending message sequence | |
| 410 + * number */ | |
| 411 + PRCList * lastMessageFlight; /* The last message flight we sent
. | |
| 412 + * This is a pointer because | |
| 413 + * ssl_FreeSocket relocates the | |
| 414 + * structure in DEBUG mode, which | |
| 415 + * messes up the list macros */ | |
| 416 + PRUint16 maxMessageSent; /* The largest message we sent */ | |
| 417 + PRUint16 recvMessageSeq; /* The receiving message sequence | |
| 418 + * number */ | |
| 419 + sslBuffer recvdFragments; /* The fragments we have received in | |
| 420 + * a bitmask */ | |
| 421 + PRInt32 recvdHighWater; /* The high water mark for fragments | |
| 422 + * received. -1 means no reassembly | |
| 423 + * in progress. */ | |
| 424 + unsigned char cookie[32]; /* The cookie */ | |
| 425 + unsigned char cookieLen; /* The length of the cookie */ | |
| 426 + PRIntervalTime rtTimerStarted; /* When the timer was started */ | |
| 427 + DTLSTimerCb rtTimerCb; /* The function to call on expiry */ | |
| 428 + PRUint32 rtTimeoutMs; /* The length of the current timeout | |
| 429 + * used for backoff (in ms) */ | |
| 430 + PRUint32 rtRetries; /* The retry counter */ | |
| 431 } SSL3HandshakeState; | |
| 432 | |
| 433 | |
| 434 @@ -882,11 +951,18 @@ | |
| 435 */ | |
| 436 SECItem nextProto; | |
| 437 SSLNextProtoState nextProtoState; | |
| 438 + | |
| 439 + PRUint16 mtu; /* Our estimate of the MTU */ | |
| 440 }; | |
| 441 | |
| 442 +#define DTLS_MAX_MTU 1500 /* Ethernet MTU but without subtracting the | |
| 443 + * headers, so slightly larger than expected */ | |
| 444 +#define IS_DTLS(ss) (ss->protocolVariant == ssl_variant_datagram) | |
| 445 + | |
| 446 typedef struct { | |
| 447 SSL3ContentType type; | |
| 448 SSL3ProtocolVersion version; | |
| 449 + SSL3SequenceNumber seq_num; /* DTLS only */ | |
| 450 sslBuffer * buf; | |
| 451 } SSL3Ciphertext; | |
| 452 | |
| 453 @@ -1188,6 +1264,9 @@ | |
| 454 /* True when the current session is a stateless resume. */ | |
| 455 PRBool statelessResume; | |
| 456 TLSExtensionData xtnData; | |
| 457 + | |
| 458 + /* Whether we are doing stream or datagram mode */ | |
| 459 + SSLProtocolVariant protocolVariant; | |
| 460 }; | |
| 461 | |
| 462 | |
| 463 @@ -1321,7 +1400,35 @@ | |
| 464 extern SECStatus ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled); | |
| 465 | |
| 466 extern PRBool ssl3_CanFalseStart(sslSocket *ss); | |
| 467 +extern SECStatus | |
| 468 +ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec, | |
| 469 + PRBool isServer, | |
| 470 + PRBool isDTLS, | |
| 471 + SSL3ContentType type, | |
| 472 + const SSL3Opaque * pIn, | |
| 473 + PRUint32 contentLen, | |
| 474 + sslBuffer * wrBuf); | |
| 475 +extern PRInt32 ssl3_SendRecord(sslSocket *ss, DTLSEpoch epoch, | |
| 476 + SSL3ContentType type, | |
| 477 + const SSL3Opaque* pIn, PRInt32 nIn, | |
| 478 + PRInt32 flags); | |
| 479 | |
| 480 +#ifdef NSS_ENABLE_ZLIB | |
| 481 +/* | |
| 482 + * The DEFLATE algorithm can result in an expansion of 0.1% + 12 bytes. For a | |
| 483 + * maximum TLS record payload of 2**14 bytes, that's 29 bytes. | |
| 484 + */ | |
| 485 +#define SSL3_COMPRESSION_MAX_EXPANSION 29 | |
| 486 +#else /* !NSS_ENABLE_ZLIB */ | |
| 487 +#define SSL3_COMPRESSION_MAX_EXPANSION 0 | |
| 488 +#endif | |
| 489 + | |
| 490 +/* | |
| 491 + * make sure there is room in the write buffer for padding and | |
| 492 + * other compression and cryptographic expansions. | |
| 493 + */ | |
| 494 +#define SSL3_BUFFER_FUDGE 100 + SSL3_COMPRESSION_MAX_EXPANSION | |
| 495 + | |
| 496 #define SSL_LOCK_READER(ss) if (ss->recvLock) PZ_Lock(ss->recvLock) | |
| 497 #define SSL_UNLOCK_READER(ss) if (ss->recvLock) PZ_Unlock(ss->recvLock
) | |
| 498 #define SSL_LOCK_WRITER(ss) if (ss->sendLock) PZ_Lock(ss->sendLock) | |
| 499 @@ -1417,6 +1524,7 @@ | |
| 500 extern void ssl_FreeSocket(struct sslSocketStr *ssl); | |
| 501 extern SECStatus SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, | |
| 502 SSL3AlertDescription desc); | |
| 503 +extern SECStatus ssl3_DecodeError(sslSocket *ss); | |
| 504 | |
| 505 extern SECStatus ssl3_RestartHandshakeAfterCertReq(sslSocket * ss, | |
| 506 CERTCertificate * cert, | |
| 507 @@ -1436,7 +1544,7 @@ | |
| 508 /* | |
| 509 * SSL3 specific routines | |
| 510 */ | |
| 511 -SECStatus ssl3_SendClientHello(sslSocket *ss); | |
| 512 +SECStatus ssl3_SendClientHello(sslSocket *ss, PRBool resending); | |
| 513 | |
| 514 /* | |
| 515 * input into the SSL3 machinery from the actualy network reading code | |
| 516 @@ -1531,6 +1639,8 @@ | |
| 517 unsigned char *cs, int *size); | |
| 518 | |
| 519 extern SECStatus ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache); | |
| 520 +extern SECStatus ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, | |
| 521 + PRUint32 length); | |
| 522 | |
| 523 extern void ssl3_DestroySSL3Info(sslSocket *ss); | |
| 524 | |
| 525 @@ -1556,6 +1666,7 @@ | |
| 526 extern SECStatus ssl3_ComputeCommonKeyHash(PRUint8 * hashBuf, | |
| 527 unsigned int bufLen, SSL3Hashes *hashes, | |
| 528 PRBool bypassPKCS11); | |
| 529 +extern void ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName); | |
| 530 extern SECStatus ssl3_InitPendingCipherSpec(sslSocket *ss, PK11SymKey *pms); | |
| 531 extern SECStatus ssl3_AppendHandshake(sslSocket *ss, const void *void_src, | |
| 532 PRInt32 bytes); | |
| 533 @@ -1724,6 +1835,42 @@ | |
| 534 CERTCertList* list); | |
| 535 #endif /* NSS_PLATFORM_CLIENT_AUTH */ | |
| 536 | |
| 537 +/**************** DTLS-specific functions **************/ | |
| 538 +extern void dtls_FreeQueuedMessage(DTLSQueuedMessage *msg); | |
| 539 +extern void dtls_FreeQueuedMessages(PRCList *lst); | |
| 540 +extern void dtls_FreeHandshakeMessages(PRCList *lst); | |
| 541 + | |
| 542 +extern SECStatus dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf); | |
| 543 +extern SECStatus dtls_HandleHelloVerifyRequest(sslSocket *ss, | |
| 544 + SSL3Opaque *b, PRUint32 length); | |
| 545 +extern SECStatus dtls_StageHandshakeMessage(sslSocket *ss); | |
| 546 +extern SECStatus dtls_QueueMessage(sslSocket *ss, SSL3ContentType type, | |
| 547 + const SSL3Opaque *pIn, PRInt32 nIn); | |
| 548 +extern SECStatus dtls_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags); | |
| 549 +extern SECStatus dtls_CompressMACEncryptRecord(sslSocket *ss, | |
| 550 + DTLSEpoch epoch, | |
| 551 + PRBool use_epoch, | |
| 552 + SSL3ContentType type, | |
| 553 + const SSL3Opaque *pIn, | |
| 554 + PRUint32 contentLen, | |
| 555 + sslBuffer *wrBuf); | |
| 556 +SECStatus ssl3_DisableNonDTLSSuites(sslSocket * ss); | |
| 557 +extern SECStatus dtls_StartTimer(sslSocket *ss, DTLSTimerCb cb); | |
| 558 +extern SECStatus dtls_RestartTimer(sslSocket *ss, PRBool backoff, | |
| 559 + DTLSTimerCb cb); | |
| 560 +extern void dtls_CheckTimer(sslSocket *ss); | |
| 561 +extern void dtls_CancelTimer(sslSocket *ss); | |
| 562 +extern void dtls_FinishedTimerCb(sslSocket *ss); | |
| 563 +extern void dtls_SetMTU(sslSocket *ss, PRUint16 advertised); | |
| 564 +extern void dtls_InitRecvdRecords(DTLSRecvdRecords *records); | |
| 565 +extern int dtls_RecordGetRecvd(DTLSRecvdRecords *records, PRUint64 seq); | |
| 566 +extern void dtls_RecordSetRecvd(DTLSRecvdRecords *records, PRUint64 seq); | |
| 567 +extern void dtls_RehandshakeCleanup(sslSocket *ss); | |
| 568 +extern SSL3ProtocolVersion | |
| 569 +dtls_TLSVersionToDTLSVersion(SSL3ProtocolVersion tlsv); | |
| 570 +extern SSL3ProtocolVersion | |
| 571 +dtls_DTLSVersionToTLSVersion(SSL3ProtocolVersion dtlsv); | |
| 572 + | |
| 573 /********************** misc calls *********************/ | |
| 574 | |
| 575 extern int ssl_MapLowLevelError(int hiLevelError); | |
| 576 Index: net/third_party/nss/ssl/manifest.mn | |
| 577 =================================================================== | |
| 578 --- net/third_party/nss/ssl/manifest.mn (revision 127709) | |
| 579 +++ net/third_party/nss/ssl/manifest.mn (working copy) | |
| 580 @@ -51,6 +51,7 @@ | |
| 581 | |
| 582 CSRCS = \ | |
| 583 derive.c \ | |
| 584 + dtls1con.c \ | |
| 585 prelib.c \ | |
| 586 ssl3con.c \ | |
| 587 ssl3gthr.c \ | |
| 588 Index: net/third_party/nss/ssl/ssl3prot.h | |
| 589 =================================================================== | |
| 590 --- net/third_party/nss/ssl/ssl3prot.h (revision 127709) | |
| 591 +++ net/third_party/nss/ssl/ssl3prot.h (working copy) | |
| 592 @@ -61,6 +61,9 @@ | |
| 593 | |
| 594 #define SSL3_RECORD_HEADER_LENGTH 5 | |
| 595 | |
| 596 +/* SSL3_RECORD_HEADER_LENGTH + epoch/sequence_number */ | |
| 597 +#define DTLS_RECORD_HEADER_LENGTH 13 | |
| 598 + | |
| 599 #define MAX_FRAGMENT_LENGTH 16384 | |
| 600 | |
| 601 typedef enum { | |
| 602 @@ -150,6 +153,7 @@ | |
| 603 hello_request = 0, | |
| 604 client_hello = 1, | |
| 605 server_hello = 2, | |
| 606 + hello_verify_request = 3, | |
| 607 new_session_ticket = 4, | |
| 608 certificate = 11, | |
| 609 server_key_exchange = 12, | |
| 610 Index: net/third_party/nss/ssl/sslcon.c | |
| 611 =================================================================== | |
| 612 --- net/third_party/nss/ssl/sslcon.c (revision 127709) | |
| 613 +++ net/third_party/nss/ssl/sslcon.c (working copy) | |
| 614 @@ -1249,7 +1249,12 @@ | |
| 615 | |
| 616 ssl_GetRecvBufLock(ss); | |
| 617 | |
| 618 - if (ss->version >= SSL_LIBRARY_VERSION_3_0) { | |
| 619 + /* The special case DTLS logic is needed here because the SSL/TLS | |
| 620 + * version wants to auto-detect SSL2 vs. SSL3 on the initial handshake | |
| 621 + * (ss->version == 0) but with DTLS it gets confused, so we force the | |
| 622 + * SSL3 version. | |
| 623 + */ | |
| 624 + if ((ss->version >= SSL_LIBRARY_VERSION_3_0) || IS_DTLS(ss)) { | |
| 625 /* Wait for handshake to complete, or application data to arrive. */ | |
| 626 rv = ssl3_GatherCompleteHandshake(ss, 0); | |
| 627 } else { | |
| 628 @@ -3120,7 +3125,7 @@ | |
| 629 | |
| 630 ssl_GetSSL3HandshakeLock(ss); | |
| 631 ssl_GetXmitBufLock(ss); | |
| 632 - rv = ssl3_SendClientHello(ss); | |
| 633 + rv = ssl3_SendClientHello(ss, PR_FALSE); | |
| 634 ssl_ReleaseXmitBufLock(ss); | |
| 635 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 636 | |
| 637 Index: net/third_party/nss/ssl/sslsecur.c | |
| 638 =================================================================== | |
| 639 --- net/third_party/nss/ssl/sslsecur.c (revision 127709) | |
| 640 +++ net/third_party/nss/ssl/sslsecur.c (working copy) | |
| 641 @@ -615,6 +615,7 @@ | |
| 642 if (!(flags & PR_MSG_PEEK)) { | |
| 643 ss->gs.readOffset += amount; | |
| 644 } | |
| 645 + PORT_Assert(ss->gs.readOffset <= ss->gs.writeOffset); | |
| 646 rv = amount; | |
| 647 | |
| 648 SSL_TRC(30, ("%d: SSL[%d]: amount=%d available=%d", | |
| 649 Index: net/third_party/nss/ssl/sslsock.c | |
| 650 =================================================================== | |
| 651 --- net/third_party/nss/ssl/sslsock.c (revision 127709) | |
| 652 +++ net/third_party/nss/ssl/sslsock.c (working copy) | |
| 653 @@ -194,11 +194,20 @@ | |
| 654 /* | |
| 655 * default range of enabled SSL/TLS protocols | |
| 656 */ | |
| 657 -static SSLVersionRange versions_defaults = { | |
| 658 +static SSLVersionRange versions_defaults_stream = { | |
| 659 SSL_LIBRARY_VERSION_3_0, | |
| 660 SSL_LIBRARY_VERSION_TLS_1_0 | |
| 661 }; | |
| 662 | |
| 663 +static SSLVersionRange versions_defaults_datagram = { | |
| 664 + SSL_LIBRARY_VERSION_TLS_1_1, | |
| 665 + SSL_LIBRARY_VERSION_TLS_1_1 | |
| 666 +}; | |
| 667 + | |
| 668 +#define VERSIONS_DEFAULTS(variant) \ | |
| 669 + (variant == ssl_variant_stream ? &versions_defaults_stream : \ | |
| 670 + &versions_defaults_datagram) | |
| 671 + | |
| 672 sslSessionIDLookupFunc ssl_sid_lookup; | |
| 673 sslSessionIDCacheFunc ssl_sid_cache; | |
| 674 sslSessionIDUncacheFunc ssl_sid_uncache; | |
| 675 @@ -217,7 +226,7 @@ | |
| 676 #define LOCKSTATUS_OFFSET 10 /* offset of ENABLED */ | |
| 677 | |
| 678 /* forward declarations. */ | |
| 679 -static sslSocket *ssl_NewSocket(PRBool makeLocks); | |
| 680 +static sslSocket *ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant variant); | |
| 681 static SECStatus ssl_MakeLocks(sslSocket *ss); | |
| 682 static void ssl_SetDefaultsFromEnvironment(void); | |
| 683 static PRStatus ssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack, | |
| 684 @@ -281,7 +290,13 @@ | |
| 685 sslSocket *ss; | |
| 686 SECStatus rv; | |
| 687 | |
| 688 - ss = ssl_NewSocket((PRBool)(!os->opt.noLocks)); | |
| 689 + /* Not implemented for datagram */ | |
| 690 + if (IS_DTLS(os)) { | |
| 691 + PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | |
| 692 + return NULL; | |
| 693 + } | |
| 694 + | |
| 695 + ss = ssl_NewSocket((PRBool)(!os->opt.noLocks), os->protocolVariant); | |
| 696 if (ss) { | |
| 697 ss->opt = os->opt; | |
| 698 ss->opt.useSocks = PR_FALSE; | |
| 699 @@ -698,6 +713,13 @@ | |
| 700 break; | |
| 701 | |
| 702 case SSL_ENABLE_TLS: | |
| 703 + if (IS_DTLS(ss)) { | |
| 704 + if (on) { | |
| 705 + PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 706 + rv = SECFailure; /* not allowed */ | |
| 707 + } | |
| 708 + break; | |
| 709 + } | |
| 710 ssl_EnableTLS(&ss->vrange, on); | |
| 711 ss->preferredCipher = NULL; | |
| 712 if (ss->cipherSpecs) { | |
| 713 @@ -708,6 +730,13 @@ | |
| 714 break; | |
| 715 | |
| 716 case SSL_ENABLE_SSL3: | |
| 717 + if (IS_DTLS(ss)) { | |
| 718 + if (on) { | |
| 719 + PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 720 + rv = SECFailure; /* not allowed */ | |
| 721 + } | |
| 722 + break; | |
| 723 + } | |
| 724 ssl_EnableSSL3(&ss->vrange, on); | |
| 725 ss->preferredCipher = NULL; | |
| 726 if (ss->cipherSpecs) { | |
| 727 @@ -718,6 +747,13 @@ | |
| 728 break; | |
| 729 | |
| 730 case SSL_ENABLE_SSL2: | |
| 731 + if (IS_DTLS(ss)) { | |
| 732 + if (on) { | |
| 733 + PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 734 + rv = SECFailure; /* not allowed */ | |
| 735 + } | |
| 736 + break; | |
| 737 + } | |
| 738 ss->opt.enableSSL2 = on; | |
| 739 if (on) { | |
| 740 ss->opt.v2CompatibleHello = on; | |
| 741 @@ -743,6 +779,13 @@ | |
| 742 break; | |
| 743 | |
| 744 case SSL_V2_COMPATIBLE_HELLO: | |
| 745 + if (IS_DTLS(ss)) { | |
| 746 + if (on) { | |
| 747 + PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 748 + rv = SECFailure; /* not allowed */ | |
| 749 + } | |
| 750 + break; | |
| 751 + } | |
| 752 ss->opt.v2CompatibleHello = on; | |
| 753 if (!on) { | |
| 754 ss->opt.enableSSL2 = on; | |
| 755 @@ -938,10 +981,10 @@ | |
| 756 case SSL_HANDSHAKE_AS_CLIENT: on = ssl_defaults.handshakeAsClient; break; | |
| 757 case SSL_HANDSHAKE_AS_SERVER: on = ssl_defaults.handshakeAsServer; break; | |
| 758 case SSL_ENABLE_TLS: | |
| 759 - on = versions_defaults.max >= SSL_LIBRARY_VERSION_TLS_1_0; | |
| 760 + on = versions_defaults_stream.max >= SSL_LIBRARY_VERSION_TLS_1_0; | |
| 761 break; | |
| 762 case SSL_ENABLE_SSL3: | |
| 763 - on = versions_defaults.min == SSL_LIBRARY_VERSION_3_0; | |
| 764 + on = versions_defaults_stream.min == SSL_LIBRARY_VERSION_3_0; | |
| 765 break; | |
| 766 case SSL_ENABLE_SSL2: on = ssl_defaults.enableSSL2; break; | |
| 767 case SSL_NO_CACHE: on = ssl_defaults.noCache; break; | |
| 768 @@ -1034,11 +1077,11 @@ | |
| 769 break; | |
| 770 | |
| 771 case SSL_ENABLE_TLS: | |
| 772 - ssl_EnableTLS(&versions_defaults, on); | |
| 773 + ssl_EnableTLS(&versions_defaults_stream, on); | |
| 774 break; | |
| 775 | |
| 776 case SSL_ENABLE_SSL3: | |
| 777 - ssl_EnableSSL3(&versions_defaults, on); | |
| 778 + ssl_EnableSSL3(&versions_defaults_stream, on); | |
| 779 break; | |
| 780 | |
| 781 case SSL_ENABLE_SSL2: | |
| 782 @@ -1360,8 +1403,8 @@ | |
| 783 | |
| 784 | |
| 785 /* LOCKS ??? XXX */ | |
| 786 -PRFileDesc * | |
| 787 -SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd) | |
| 788 +static PRFileDesc * | |
| 789 +ssl_ImportFD(PRFileDesc *model, PRFileDesc *fd, SSLProtocolVariant variant) | |
| 790 { | |
| 791 sslSocket * ns = NULL; | |
| 792 PRStatus rv; | |
| 793 @@ -1374,10 +1417,10 @@ | |
| 794 | |
| 795 if (model == NULL) { | |
| 796 /* Just create a default socket if we're given NULL for the model */ | |
| 797 - ns = ssl_NewSocket((PRBool)(!ssl_defaults.noLocks)); | |
| 798 + ns = ssl_NewSocket((PRBool)(!ssl_defaults.noLocks), variant); | |
| 799 } else { | |
| 800 sslSocket * ss = ssl_FindSocket(model); | |
| 801 - if (ss == NULL) { | |
| 802 + if (ss == NULL || ss->protocolVariant != variant) { | |
| 803 SSL_DBG(("%d: SSL[%d]: bad model socket in ssl_ImportFD", | |
| 804 SSL_GETPID(), model)); | |
| 805 return NULL; | |
| 806 @@ -1403,6 +1446,18 @@ | |
| 807 return fd; | |
| 808 } | |
| 809 | |
| 810 +PRFileDesc * | |
| 811 +SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd) | |
| 812 +{ | |
| 813 + return ssl_ImportFD(model, fd, ssl_variant_stream); | |
| 814 +} | |
| 815 + | |
| 816 +PRFileDesc * | |
| 817 +DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd) | |
| 818 +{ | |
| 819 + return ssl_ImportFD(model, fd, ssl_variant_datagram); | |
| 820 +} | |
| 821 + | |
| 822 SECStatus | |
| 823 SSL_SetNextProtoCallback(PRFileDesc *fd, SSLNextProtoCallback callback, | |
| 824 void *arg) | |
| 825 @@ -1667,9 +1722,18 @@ | |
| 826 ssl3_VersionIsSupported(SSLProtocolVariant protocolVariant, | |
| 827 SSL3ProtocolVersion version) | |
| 828 { | |
| 829 - return protocolVariant == ssl_variant_stream && | |
| 830 - version >= SSL_LIBRARY_VERSION_3_0 && | |
| 831 - version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED; | |
| 832 + switch (protocolVariant) { | |
| 833 + case ssl_variant_stream: | |
| 834 + return (version >= SSL_LIBRARY_VERSION_3_0 && | |
| 835 + version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED); | |
| 836 + case ssl_variant_datagram: | |
| 837 + return (version >= SSL_LIBRARY_VERSION_TLS_1_1 && | |
| 838 + version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED); | |
| 839 + default: | |
| 840 + /* Can't get here */ | |
| 841 + PORT_Assert(PR_FALSE); | |
| 842 + return PR_FALSE; | |
| 843 + } | |
| 844 } | |
| 845 | |
| 846 /* Returns PR_TRUE if the given version range is valid and | |
| 847 @@ -1689,13 +1753,24 @@ | |
| 848 SSL_VersionRangeGetSupported(SSLProtocolVariant protocolVariant, | |
| 849 SSLVersionRange *vrange) | |
| 850 { | |
| 851 - if (protocolVariant != ssl_variant_stream || !vrange) { | |
| 852 + if (!vrange) { | |
| 853 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 854 return SECFailure; | |
| 855 } | |
| 856 | |
| 857 - vrange->min = SSL_LIBRARY_VERSION_3_0; | |
| 858 - vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED; | |
| 859 + switch (protocolVariant) { | |
| 860 + case ssl_variant_stream: | |
| 861 + vrange->min = SSL_LIBRARY_VERSION_3_0; | |
| 862 + vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED; | |
| 863 + break; | |
| 864 + case ssl_variant_datagram: | |
| 865 + vrange->min = SSL_LIBRARY_VERSION_TLS_1_1; | |
| 866 + vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED; | |
| 867 + break; | |
| 868 + default: | |
| 869 + PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 870 + return SECFailure; | |
| 871 + } | |
| 872 | |
| 873 return SECSuccess; | |
| 874 } | |
| 875 @@ -1704,12 +1779,13 @@ | |
| 876 SSL_VersionRangeGetDefault(SSLProtocolVariant protocolVariant, | |
| 877 SSLVersionRange *vrange) | |
| 878 { | |
| 879 - if (protocolVariant != ssl_variant_stream || !vrange) { | |
| 880 + if ((protocolVariant != ssl_variant_stream && | |
| 881 + protocolVariant != ssl_variant_datagram) || !vrange) { | |
| 882 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 883 return SECFailure; | |
| 884 } | |
| 885 | |
| 886 - *vrange = versions_defaults; | |
| 887 + *vrange = *VERSIONS_DEFAULTS(protocolVariant); | |
| 888 | |
| 889 return SECSuccess; | |
| 890 } | |
| 891 @@ -1723,7 +1799,7 @@ | |
| 892 return SECFailure; | |
| 893 } | |
| 894 | |
| 895 - versions_defaults = *vrange; | |
| 896 + *VERSIONS_DEFAULTS(protocolVariant) = *vrange; | |
| 897 | |
| 898 return SECSuccess; | |
| 899 } | |
| 900 @@ -2830,7 +2906,7 @@ | |
| 901 ** Create a newsocket structure for a file descriptor. | |
| 902 */ | |
| 903 static sslSocket * | |
| 904 -ssl_NewSocket(PRBool makeLocks) | |
| 905 +ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant) | |
| 906 { | |
| 907 sslSocket *ss; | |
| 908 | |
| 909 @@ -2851,7 +2927,7 @@ | |
| 910 ss->opt = ssl_defaults; | |
| 911 ss->opt.useSocks = PR_FALSE; | |
| 912 ss->opt.noLocks = !makeLocks; | |
| 913 - ss->vrange = versions_defaults; | |
| 914 + ss->vrange = *VERSIONS_DEFAULTS(protocolVariant); | |
| 915 | |
| 916 ss->peerID = NULL; | |
| 917 ss->rTimeout = PR_INTERVAL_NO_TIMEOUT; | |
| 918 @@ -2907,6 +2983,7 @@ | |
| 919 PORT_Free(ss); | |
| 920 ss = NULL; | |
| 921 } | |
| 922 + ss->protocolVariant = protocolVariant; | |
| 923 } | |
| 924 return ss; | |
| 925 } | |
| 926 Index: net/third_party/nss/ssl/ssl3con.c | |
| 927 =================================================================== | |
| 928 --- net/third_party/nss/ssl/ssl3con.c (revision 127709) | |
| 929 +++ net/third_party/nss/ssl/ssl3con.c (working copy) | |
| 930 @@ -42,6 +42,8 @@ | |
| 931 * ***** END LICENSE BLOCK ***** */ | |
| 932 /* $Id: ssl3con.c,v 1.173 2012/03/18 00:31:19 wtc%google.com Exp $ */ | |
| 933 | |
| 934 +/* TODO(ekr): Implement HelloVerifyRequest on server side. OK for now. */ | |
| 935 + | |
| 936 #include "cert.h" | |
| 937 #include "ssl.h" | |
| 938 #include "cryptohi.h" /* for DSAU_ stuff */ | |
| 939 @@ -92,6 +94,7 @@ | |
| 940 static SECStatus ssl3_UpdateHandshakeHashes( sslSocket *ss, | |
| 941 const unsigned char *b, | |
| 942 unsigned int l); | |
| 943 +static SECStatus ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags); | |
| 944 | |
| 945 static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen, | |
| 946 int maxOutputLen, const unsigned char *input, | |
| 947 @@ -221,22 +224,6 @@ | |
| 948 #endif /* NSS_ENABLE_ECC */ | |
| 949 }; | |
| 950 | |
| 951 -#ifdef NSS_ENABLE_ZLIB | |
| 952 -/* | |
| 953 - * The DEFLATE algorithm can result in an expansion of 0.1% + 12 bytes. For a | |
| 954 - * maximum TLS record payload of 2**14 bytes, that's 29 bytes. | |
| 955 - */ | |
| 956 -#define SSL3_COMPRESSION_MAX_EXPANSION 29 | |
| 957 -#else /* !NSS_ENABLE_ZLIB */ | |
| 958 -#define SSL3_COMPRESSION_MAX_EXPANSION 0 | |
| 959 -#endif | |
| 960 - | |
| 961 -/* | |
| 962 - * make sure there is room in the write buffer for padding and | |
| 963 - * other compression and cryptographic expansions. | |
| 964 - */ | |
| 965 -#define SSL3_BUFFER_FUDGE 100 + SSL3_COMPRESSION_MAX_EXPANSION | |
| 966 - | |
| 967 #define EXPORT_RSA_KEY_LENGTH 64 /* bytes */ | |
| 968 | |
| 969 | |
| 970 @@ -517,6 +504,7 @@ | |
| 971 case hello_request: rv = "hello_request (0)";
break; | |
| 972 case client_hello: rv = "client_hello (1)"; break; | |
| 973 case server_hello: rv = "server_hello (2)"; break; | |
| 974 + case hello_verify_request: rv = "hello_verify_request (3)"; break; | |
| 975 case certificate: rv = "certificate (11)"; break; | |
| 976 case server_key_exchange: rv = "server_key_exchange (12)"; break; | |
| 977 case certificate_request: rv = "certificate_request (13)"; break; | |
| 978 @@ -656,7 +644,7 @@ | |
| 979 suite->isPresent = PR_FALSE; | |
| 980 continue; | |
| 981 } | |
| 982 - cipher_alg=bulk_cipher_defs[cipher_def->bulk_cipher_alg ].calg; | |
| 983 + cipher_alg = bulk_cipher_defs[cipher_def->bulk_cipher_alg].calg; | |
| 984 PORT_Assert( alg2Mech[cipher_alg].calg == cipher_alg); | |
| 985 cipher_mech = alg2Mech[cipher_alg].cmech; | |
| 986 exchKeyType = | |
| 987 @@ -1148,7 +1136,7 @@ | |
| 988 ** ssl3_DestroySSL3Info | |
| 989 ** Caller must hold SpecWriteLock. | |
| 990 */ | |
| 991 -static void | |
| 992 +void | |
| 993 ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName) | |
| 994 { | |
| 995 PRBool freeit = (PRBool)(!spec->bypassCiphers); | |
| 996 @@ -1228,6 +1216,12 @@ | |
| 997 return SECFailure; /* error code set by ssl_LookupCipherSuiteDef */ | |
| 998 } | |
| 999 | |
| 1000 + if (IS_DTLS(ss)) { | |
| 1001 + /* Double-check that we did not pick an RC4 suite */ | |
| 1002 + PORT_Assert((suite_def->bulk_cipher_alg != cipher_rc4) && | |
| 1003 + (suite_def->bulk_cipher_alg != cipher_rc4_40) && | |
| 1004 + (suite_def->bulk_cipher_alg != cipher_rc4_56)); | |
| 1005 + } | |
| 1006 | |
| 1007 cipher = suite_def->bulk_cipher_alg; | |
| 1008 kea = suite_def->key_exchange_alg; | |
| 1009 @@ -1754,6 +1748,7 @@ | |
| 1010 ssl3_InitPendingCipherSpec(sslSocket *ss, PK11SymKey *pms) | |
| 1011 { | |
| 1012 ssl3CipherSpec * pwSpec; | |
| 1013 + ssl3CipherSpec * cwSpec; | |
| 1014 SECStatus rv; | |
| 1015 | |
| 1016 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); | |
| 1017 @@ -1763,6 +1758,7 @@ | |
| 1018 PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); | |
| 1019 | |
| 1020 pwSpec = ss->ssl3.pwSpec; | |
| 1021 + cwSpec = ss->ssl3.cwSpec; | |
| 1022 | |
| 1023 if (pms || (!pwSpec->msItem.len && !pwSpec->master_secret)) { | |
| 1024 rv = ssl3_DeriveMasterSecret(ss, pms); | |
| 1025 @@ -1794,7 +1790,32 @@ | |
| 1026 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
| 1027 rv = SECFailure; | |
| 1028 } | |
| 1029 + if (rv != SECSuccess) { | |
| 1030 + goto done; | |
| 1031 + } | |
| 1032 | |
| 1033 + /* Generic behaviors -- common to all crypto methods */ | |
| 1034 + if (!IS_DTLS(ss)) { | |
| 1035 + pwSpec->read_seq_num.high = pwSpec->write_seq_num.high = 0; | |
| 1036 + } else { | |
| 1037 + if (cwSpec->epoch == PR_UINT16_MAX) { | |
| 1038 + /* The problem here is that we have rehandshaked too many | |
| 1039 + * times (you are not allowed to wrap the epoch). The | |
| 1040 + * spec says you should be discarding the connection | |
| 1041 + * and start over, so not much we can do here. */ | |
| 1042 + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
| 1043 + rv = SECFailure; | |
| 1044 + goto done; | |
| 1045 + } | |
| 1046 + /* The sequence number has the high 16 bits as the epoch. */ | |
| 1047 + pwSpec->epoch = cwSpec->epoch + 1; | |
| 1048 + pwSpec->read_seq_num.high = pwSpec->write_seq_num.high = | |
| 1049 + pwSpec->epoch << 16; | |
| 1050 + | |
| 1051 + dtls_InitRecvdRecords(&pwSpec->recvdRecords); | |
| 1052 + } | |
| 1053 + pwSpec->read_seq_num.low = pwSpec->write_seq_num.low = 0; | |
| 1054 + | |
| 1055 done: | |
| 1056 ssl_ReleaseSpecWriteLock(ss); /******************************/ | |
| 1057 if (rv != SECSuccess) | |
| 1058 @@ -1834,6 +1855,7 @@ | |
| 1059 ssl3_ComputeRecordMAC( | |
| 1060 ssl3CipherSpec * spec, | |
| 1061 PRBool useServerMacKey, | |
| 1062 + PRBool isDTLS, | |
| 1063 SSL3ContentType type, | |
| 1064 SSL3ProtocolVersion version, | |
| 1065 SSL3SequenceNumber seq_num, | |
| 1066 @@ -1871,8 +1893,16 @@ | |
| 1067 isTLS = PR_FALSE; | |
| 1068 } else { | |
| 1069 /* New TLS hash includes version. */ | |
| 1070 - temp[9] = MSB(version); | |
| 1071 - temp[10] = LSB(version); | |
| 1072 + if (isDTLS) { | |
| 1073 + SSL3ProtocolVersion dtls_version; | |
| 1074 + | |
| 1075 + dtls_version = dtls_TLSVersionToDTLSVersion(version); | |
| 1076 + temp[9] = MSB(dtls_version); | |
| 1077 + temp[10] = LSB(dtls_version); | |
| 1078 + } else { | |
| 1079 + temp[9] = MSB(version); | |
| 1080 + temp[10] = LSB(version); | |
| 1081 + } | |
| 1082 temp[11] = MSB(inputLength); | |
| 1083 temp[12] = LSB(inputLength); | |
| 1084 tempLen = 13; | |
| 1085 @@ -2022,9 +2052,10 @@ | |
| 1086 } | |
| 1087 | |
| 1088 /* Caller must hold the spec read lock. */ | |
| 1089 -static SECStatus | |
| 1090 +SECStatus | |
| 1091 ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec, | |
| 1092 PRBool isServer, | |
| 1093 + PRBool isDTLS, | |
| 1094 SSL3ContentType type, | |
| 1095 const SSL3Opaque * pIn, | |
| 1096 PRUint32 contentLen, | |
| 1097 @@ -2035,10 +2066,12 @@ | |
| 1098 PRUint32 macLen = 0; | |
| 1099 PRUint32 fragLen; | |
| 1100 PRUint32 p1Len, p2Len, oddLen = 0; | |
| 1101 + PRUint16 headerLen; | |
| 1102 int ivLen = 0; | |
| 1103 int cipherBytes = 0; | |
| 1104 | |
| 1105 cipher_def = cwSpec->cipher_def; | |
| 1106 + headerLen = isDTLS ? DTLS_RECORD_HEADER_LENGTH : SSL3_RECORD_HEADER_LENGTH; | |
| 1107 | |
| 1108 if (cipher_def->type == type_block && | |
| 1109 cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { | |
| 1110 @@ -2048,20 +2081,20 @@ | |
| 1111 * record. | |
| 1112 */ | |
| 1113 ivLen = cipher_def->iv_size; | |
| 1114 - if (ivLen > wrBuf->space - SSL3_RECORD_HEADER_LENGTH) { | |
| 1115 + if (ivLen > wrBuf->space - headerLen) { | |
| 1116 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
| 1117 return SECFailure; | |
| 1118 } | |
| 1119 - rv = PK11_GenerateRandom(wrBuf->buf + SSL3_RECORD_HEADER_LENGTH, ivLen); | |
| 1120 + rv = PK11_GenerateRandom(wrBuf->buf + headerLen, ivLen); | |
| 1121 if (rv != SECSuccess) { | |
| 1122 ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE); | |
| 1123 return rv; | |
| 1124 } | |
| 1125 rv = cwSpec->encode( cwSpec->encodeContext, | |
| 1126 - wrBuf->buf + SSL3_RECORD_HEADER_LENGTH, | |
| 1127 + wrBuf->buf + headerLen, | |
| 1128 &cipherBytes, /* output and actual outLen */ | |
| 1129 ivLen, /* max outlen */ | |
| 1130 - wrBuf->buf + SSL3_RECORD_HEADER_LENGTH, | |
| 1131 + wrBuf->buf + headerLen, | |
| 1132 ivLen); /* input and inputLen*/ | |
| 1133 if (rv != SECSuccess || cipherBytes != ivLen) { | |
| 1134 PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); | |
| 1135 @@ -2073,20 +2106,20 @@ | |
| 1136 int outlen; | |
| 1137 rv = cwSpec->compressor( | |
| 1138 cwSpec->compressContext, | |
| 1139 - wrBuf->buf + SSL3_RECORD_HEADER_LENGTH + ivLen, &outlen, | |
| 1140 - wrBuf->space - SSL3_RECORD_HEADER_LENGTH - ivLen, pIn, contentLen); | |
| 1141 + wrBuf->buf + headerLen + ivLen, &outlen, | |
| 1142 + wrBuf->space - headerLen - ivLen, pIn, contentLen); | |
| 1143 if (rv != SECSuccess) | |
| 1144 return rv; | |
| 1145 - pIn = wrBuf->buf + SSL3_RECORD_HEADER_LENGTH + ivLen; | |
| 1146 + pIn = wrBuf->buf + headerLen + ivLen; | |
| 1147 contentLen = outlen; | |
| 1148 } | |
| 1149 | |
| 1150 /* | |
| 1151 * Add the MAC | |
| 1152 */ | |
| 1153 - rv = ssl3_ComputeRecordMAC( cwSpec, isServer, | |
| 1154 + rv = ssl3_ComputeRecordMAC( cwSpec, isServer, isDTLS, | |
| 1155 type, cwSpec->version, cwSpec->write_seq_num, pIn, contentLen, | |
| 1156 - wrBuf->buf + SSL3_RECORD_HEADER_LENGTH + ivLen + contentLen, &macLen); | |
| 1157 + wrBuf->buf + headerLen + ivLen + contentLen, &macLen); | |
| 1158 if (rv != SECSuccess) { | |
| 1159 ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); | |
| 1160 return SECFailure; | |
| 1161 @@ -2113,7 +2146,7 @@ | |
| 1162 PORT_Assert((fragLen % cipher_def->block_size) == 0); | |
| 1163 | |
| 1164 /* Pad according to TLS rules (also acceptable to SSL3). */ | |
| 1165 - pBuf = &wrBuf->buf[SSL3_RECORD_HEADER_LENGTH + ivLen + fragLen - 1]; | |
| 1166 + pBuf = &wrBuf->buf[headerLen + ivLen + fragLen - 1]; | |
| 1167 for (i = padding_length + 1; i > 0; --i) { | |
| 1168 *pBuf-- = padding_length; | |
| 1169 } | |
| 1170 @@ -2130,13 +2163,12 @@ | |
| 1171 p2Len += oddLen; | |
| 1172 PORT_Assert( (cipher_def->block_size < 2) || \ | |
| 1173 (p2Len % cipher_def->block_size) == 0); | |
| 1174 - memmove(wrBuf->buf + SSL3_RECORD_HEADER_LENGTH + ivLen + p1Len, | |
| 1175 - pIn + p1Len, oddLen); | |
| 1176 + memmove(wrBuf->buf + headerLen + ivLen + p1Len, pIn + p1Len, oddLen); | |
| 1177 } | |
| 1178 if (p1Len > 0) { | |
| 1179 int cipherBytesPart1 = -1; | |
| 1180 rv = cwSpec->encode( cwSpec->encodeContext, | |
| 1181 - wrBuf->buf + SSL3_RECORD_HEADER_LENGTH + ivLen, /* output */ | |
| 1182 + wrBuf->buf + headerLen + ivLen, /* output */ | |
| 1183 &cipherBytesPart1, /* actual outlen */ | |
| 1184 p1Len, /* max outlen */ | |
| 1185 pIn, p1Len); /* input, and inputlen */ | |
| 1186 @@ -2150,10 +2182,10 @@ | |
| 1187 if (p2Len > 0) { | |
| 1188 int cipherBytesPart2 = -1; | |
| 1189 rv = cwSpec->encode( cwSpec->encodeContext, | |
| 1190 - wrBuf->buf + SSL3_RECORD_HEADER_LENGTH + ivLen + p1Len, | |
| 1191 + wrBuf->buf + headerLen + ivLen + p1Len, | |
| 1192 &cipherBytesPart2, /* output and actual outLen */ | |
| 1193 p2Len, /* max outlen */ | |
| 1194 - wrBuf->buf + SSL3_RECORD_HEADER_LENGTH + ivLen + p1Len, | |
| 1195 + wrBuf->buf + headerLen + ivLen + p1Len, | |
| 1196 p2Len); /* input and inputLen*/ | |
| 1197 PORT_Assert(rv == SECSuccess && cipherBytesPart2 == (int) p2Len); | |
| 1198 if (rv != SECSuccess || cipherBytesPart2 != (int) p2Len) { | |
| 1199 @@ -2164,15 +2196,33 @@ | |
| 1200 } | |
| 1201 PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 1024); | |
| 1202 | |
| 1203 + wrBuf->len = cipherBytes + headerLen; | |
| 1204 + wrBuf->buf[0] = type; | |
| 1205 + if (isDTLS) { | |
| 1206 + SSL3ProtocolVersion version; | |
| 1207 + | |
| 1208 + version = dtls_TLSVersionToDTLSVersion(cwSpec->version); | |
| 1209 + wrBuf->buf[1] = MSB(version); | |
| 1210 + wrBuf->buf[2] = LSB(version); | |
| 1211 + wrBuf->buf[3] = (unsigned char)(cwSpec->write_seq_num.high >> 24); | |
| 1212 + wrBuf->buf[4] = (unsigned char)(cwSpec->write_seq_num.high >> 16); | |
| 1213 + wrBuf->buf[5] = (unsigned char)(cwSpec->write_seq_num.high >> 8); | |
| 1214 + wrBuf->buf[6] = (unsigned char)(cwSpec->write_seq_num.high >> 0); | |
| 1215 + wrBuf->buf[7] = (unsigned char)(cwSpec->write_seq_num.low >> 24); | |
| 1216 + wrBuf->buf[8] = (unsigned char)(cwSpec->write_seq_num.low >> 16); | |
| 1217 + wrBuf->buf[9] = (unsigned char)(cwSpec->write_seq_num.low >> 8); | |
| 1218 + wrBuf->buf[10] = (unsigned char)(cwSpec->write_seq_num.low >> 0); | |
| 1219 + wrBuf->buf[11] = MSB(cipherBytes); | |
| 1220 + wrBuf->buf[12] = LSB(cipherBytes); | |
| 1221 + } else { | |
| 1222 + wrBuf->buf[1] = MSB(cwSpec->version); | |
| 1223 + wrBuf->buf[2] = LSB(cwSpec->version); | |
| 1224 + wrBuf->buf[3] = MSB(cipherBytes); | |
| 1225 + wrBuf->buf[4] = LSB(cipherBytes); | |
| 1226 + } | |
| 1227 + | |
| 1228 ssl3_BumpSequenceNumber(&cwSpec->write_seq_num); | |
| 1229 | |
| 1230 - wrBuf->len = cipherBytes + SSL3_RECORD_HEADER_LENGTH; | |
| 1231 - wrBuf->buf[0] = type; | |
| 1232 - wrBuf->buf[1] = MSB(cwSpec->version); | |
| 1233 - wrBuf->buf[2] = LSB(cwSpec->version); | |
| 1234 - wrBuf->buf[3] = MSB(cipherBytes); | |
| 1235 - wrBuf->buf[4] = LSB(cipherBytes); | |
| 1236 - | |
| 1237 return SECSuccess; | |
| 1238 } | |
| 1239 | |
| 1240 @@ -2194,10 +2244,13 @@ | |
| 1241 * ssl_SEND_FLAG_FORCE_INTO_BUFFER | |
| 1242 * As above, except this suppresses all write attempts, and forces | |
| 1243 * all ciphertext into the pending ciphertext buffer. | |
| 1244 + * ssl_SEND_FLAG_USE_EPOCH (for DTLS) | |
| 1245 + * Forces the use of the provided epoch | |
| 1246 * | |
| 1247 */ | |
| 1248 -static PRInt32 | |
| 1249 +PRInt32 | |
| 1250 ssl3_SendRecord( sslSocket * ss, | |
| 1251 + DTLSEpoch epoch, /* DTLS only */ | |
| 1252 SSL3ContentType type, | |
| 1253 const SSL3Opaque * pIn, /* input buffer */ | |
| 1254 PRInt32 nIn, /* bytes of input */ | |
| 1255 @@ -2269,8 +2322,8 @@ | |
| 1256 sslBuffer secondRecord; | |
| 1257 | |
| 1258 rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, | |
| 1259 - ss->sec.isServer, type, pIn, 1, | |
| 1260 - wrBuf); | |
| 1261 + ss->sec.isServer, IS_DTLS(ss), | |
| 1262 + type, pIn, 1, wrBuf); | |
| 1263 if (rv != SECSuccess) | |
| 1264 goto spec_locked_loser; | |
| 1265 | |
| 1266 @@ -2282,17 +2335,28 @@ | |
| 1267 secondRecord.space = wrBuf->space - wrBuf->len; | |
| 1268 | |
| 1269 rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, | |
| 1270 - ss->sec.isServer, type, pIn + 1, | |
| 1271 - contentLen - 1, &secondRecord); | |
| 1272 + ss->sec.isServer, IS_DTLS(ss), | |
| 1273 + type, pIn + 1, contentLen - 1, | |
| 1274 + &secondRecord); | |
| 1275 if (rv == SECSuccess) { | |
| 1276 PRINT_BUF(50, (ss, "send (encrypted) record data [2/2]:", | |
| 1277 secondRecord.buf, secondRecord.len)); | |
| 1278 wrBuf->len += secondRecord.len; | |
| 1279 } | |
| 1280 } else { | |
| 1281 - rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, | |
| 1282 - ss->sec.isServer, type, pIn, | |
| 1283 - contentLen, wrBuf); | |
| 1284 + if (!IS_DTLS(ss)) { | |
| 1285 + rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, | |
| 1286 + ss->sec.isServer, | |
| 1287 + IS_DTLS(ss), | |
| 1288 + type, pIn, | |
| 1289 + contentLen, wrBuf); | |
| 1290 + } else { | |
| 1291 + rv = dtls_CompressMACEncryptRecord(ss, epoch, | |
| 1292 + !!(flags & ssl_SEND_FLAG_USE_
EPOCH), | |
| 1293 + type, pIn, | |
| 1294 + contentLen, wrBuf); | |
| 1295 + } | |
| 1296 + | |
| 1297 if (rv == SECSuccess) { | |
| 1298 PRINT_BUF(50, (ss, "send (encrypted) record data:", | |
| 1299 wrBuf->buf, wrBuf->len)); | |
| 1300 @@ -2350,6 +2414,11 @@ | |
| 1301 } | |
| 1302 wrBuf->len -= sent; | |
| 1303 if (wrBuf->len) { | |
| 1304 + if (IS_DTLS(ss)) { | |
| 1305 + /* DTLS just says no in this case. No buffering */ | |
| 1306 + PR_SetError(PR_WOULD_BLOCK_ERROR, 0); | |
| 1307 + return SECFailure; | |
| 1308 + } | |
| 1309 /* now take all the remaining unsent new ciphertext and | |
| 1310 * append it to the buffer of previously unsent ciphertext. | |
| 1311 */ | |
| 1312 @@ -2378,6 +2447,9 @@ | |
| 1313 PRInt32 discarded = 0; | |
| 1314 | |
| 1315 PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); | |
| 1316 + /* These flags for internal use only */ | |
| 1317 + PORT_Assert(!(flags & (ssl_SEND_FLAG_USE_EPOCH | | |
| 1318 + ssl_SEND_FLAG_NO_RETRANSMIT))); | |
| 1319 if (len < 0 || !in) { | |
| 1320 PORT_SetError(PR_INVALID_ARGUMENT_ERROR); | |
| 1321 return SECFailure; | |
| 1322 @@ -2415,7 +2487,11 @@ | |
| 1323 ssl_GetXmitBufLock(ss); | |
| 1324 } | |
| 1325 toSend = PR_MIN(len - totalSent, MAX_FRAGMENT_LENGTH); | |
| 1326 - sent = ssl3_SendRecord(ss, content_application_data, | |
| 1327 + /* | |
| 1328 + * Note that the 0 epoch is OK because flags will never require | |
| 1329 + * its use, as guaranteed by the PORT_Assert above. | |
| 1330 + */ | |
| 1331 + sent = ssl3_SendRecord(ss, 0, content_application_data, | |
| 1332 in + totalSent, toSend, flags); | |
| 1333 if (sent < 0) { | |
| 1334 if (totalSent > 0 && PR_GetError() == PR_WOULD_BLOCK_ERROR) { | |
| 1335 @@ -2450,10 +2526,15 @@ | |
| 1336 return totalSent + discarded; | |
| 1337 } | |
| 1338 | |
| 1339 -/* Attempt to send the content of sendBuf buffer in an SSL handshake record. | |
| 1340 +/* Attempt to send buffered handshake messages. | |
| 1341 * This function returns SECSuccess or SECFailure, never SECWouldBlock. | |
| 1342 * Always set sendBuf.len to 0, even when returning SECFailure. | |
| 1343 * | |
| 1344 + * Depending on whether we are doing DTLS or not, this either calls | |
| 1345 + * | |
| 1346 + * - ssl3_FlushHandshakeMessages if non-DTLS | |
| 1347 + * - dtls_FlushHandshakeMessages if DTLS | |
| 1348 + * | |
| 1349 * Called from SSL3_SendAlert(), ssl3_SendChangeCipherSpecs(), | |
| 1350 * ssl3_AppendHandshake(), ssl3_SendClientHello(), | |
| 1351 * ssl3_SendHelloRequest(), ssl3_SendServerHelloDone(), | |
| 1352 @@ -2462,6 +2543,22 @@ | |
| 1353 static SECStatus | |
| 1354 ssl3_FlushHandshake(sslSocket *ss, PRInt32 flags) | |
| 1355 { | |
| 1356 + if (IS_DTLS(ss)) { | |
| 1357 + return dtls_FlushHandshakeMessages(ss, flags); | |
| 1358 + } else { | |
| 1359 + return ssl3_FlushHandshakeMessages(ss, flags); | |
| 1360 + } | |
| 1361 +} | |
| 1362 + | |
| 1363 +/* Attempt to send the content of sendBuf buffer in an SSL handshake record. | |
| 1364 + * This function returns SECSuccess or SECFailure, never SECWouldBlock. | |
| 1365 + * Always set sendBuf.len to 0, even when returning SECFailure. | |
| 1366 + * | |
| 1367 + * Called from ssl3_FlushHandshake | |
| 1368 + */ | |
| 1369 +static SECStatus | |
| 1370 +ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags) | |
| 1371 +{ | |
| 1372 PRInt32 rv = SECSuccess; | |
| 1373 | |
| 1374 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); | |
| 1375 @@ -2476,7 +2573,7 @@ | |
| 1376 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 1377 rv = SECFailure; | |
| 1378 } else { | |
| 1379 - rv = ssl3_SendRecord(ss, content_handshake, ss->sec.ci.sendBuf.buf, | |
| 1380 + rv = ssl3_SendRecord(ss, 0, content_handshake, ss->sec.ci.sendBuf.buf, | |
| 1381 ss->sec.ci.sendBuf.len, flags); | |
| 1382 } | |
| 1383 if (rv < 0) { | |
| 1384 @@ -2593,7 +2690,7 @@ | |
| 1385 rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER); | |
| 1386 if (rv == SECSuccess) { | |
| 1387 PRInt32 sent; | |
| 1388 - sent = ssl3_SendRecord(ss, content_alert, bytes, 2, | |
| 1389 + sent = ssl3_SendRecord(ss, 0, content_alert, bytes, 2, | |
| 1390 desc == no_certificate | |
| 1391 ? ssl_SEND_FLAG_FORCE_INTO_BUFFER : 0); | |
| 1392 rv = (sent >= 0) ? SECSuccess : (SECStatus)sent; | |
| 1393 @@ -2667,7 +2764,7 @@ | |
| 1394 /* | |
| 1395 * Send handshake_Failure alert. Set generic error number. | |
| 1396 */ | |
| 1397 -static SECStatus | |
| 1398 +SECStatus | |
| 1399 ssl3_DecodeError(sslSocket *ss) | |
| 1400 { | |
| 1401 (void)SSL3_SendAlert(ss, alert_fatal, | |
| 1402 @@ -2755,7 +2852,8 @@ | |
| 1403 default: error = SSL_ERROR_RX_UNKNOWN_ALERT; break; | |
| 1404 } | |
| 1405 if (level == alert_fatal) { | |
| 1406 - ss->sec.uncache(ss->sec.ci.sid); | |
| 1407 + if (!ss->opt.noCache) | |
| 1408 + ss->sec.uncache(ss->sec.ci.sid); | |
| 1409 if ((ss->ssl3.hs.ws == wait_server_hello) && | |
| 1410 (desc == handshake_failure)) { | |
| 1411 /* XXX This is a hack. We're assuming that any handshake failure | |
| 1412 @@ -2806,17 +2904,22 @@ | |
| 1413 if (rv != SECSuccess) { | |
| 1414 return rv; /* error code set by ssl3_FlushHandshake */ | |
| 1415 } | |
| 1416 - sent = ssl3_SendRecord(ss, content_change_cipher_spec, &change, 1, | |
| 1417 - ssl_SEND_FLAG_FORCE_INTO_BUFFER); | |
| 1418 - if (sent < 0) { | |
| 1419 - return (SECStatus)sent; /* error code set by ssl3_SendRecord */ | |
| 1420 + if (!IS_DTLS(ss)) { | |
| 1421 + sent = ssl3_SendRecord(ss, 0, content_change_cipher_spec, &change, 1, | |
| 1422 + ssl_SEND_FLAG_FORCE_INTO_BUFFER); | |
| 1423 + if (sent < 0) { | |
| 1424 + return (SECStatus)sent; /* error code set by ssl3_SendRecord */ | |
| 1425 + } | |
| 1426 + } else { | |
| 1427 + rv = dtls_QueueMessage(ss, content_change_cipher_spec, &change, 1); | |
| 1428 + if (rv != SECSuccess) { | |
| 1429 + return rv; | |
| 1430 + } | |
| 1431 } | |
| 1432 | |
| 1433 /* swap the pending and current write specs. */ | |
| 1434 ssl_GetSpecWriteLock(ss); /**************************************/ | |
| 1435 pwSpec = ss->ssl3.pwSpec; | |
| 1436 - pwSpec->write_seq_num.high = 0; | |
| 1437 - pwSpec->write_seq_num.low = 0; | |
| 1438 | |
| 1439 ss->ssl3.pwSpec = ss->ssl3.cwSpec; | |
| 1440 ss->ssl3.cwSpec = pwSpec; | |
| 1441 @@ -2829,7 +2932,14 @@ | |
| 1442 * (Both the read and write sides have changed) destroy it. | |
| 1443 */ | |
| 1444 if (ss->ssl3.prSpec == ss->ssl3.pwSpec) { | |
| 1445 - ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE/*freeSrvName*/); | |
| 1446 + if (!IS_DTLS(ss)) { | |
| 1447 + ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE/*freeSrvName*/); | |
| 1448 + } else { | |
| 1449 + /* With DTLS, we need to set a holddown timer in case the final | |
| 1450 + * message got lost */ | |
| 1451 + ss->ssl3.hs.rtTimeoutMs = DTLS_FINISHED_TIMER_MS; | |
| 1452 + dtls_StartTimer(ss, dtls_FinishedTimerCb); | |
| 1453 + } | |
| 1454 } | |
| 1455 ssl_ReleaseSpecWriteLock(ss); /**************************************/ | |
| 1456 | |
| 1457 @@ -2878,7 +2988,6 @@ | |
| 1458 /* Swap the pending and current read specs. */ | |
| 1459 ssl_GetSpecWriteLock(ss); /*************************************/ | |
| 1460 prSpec = ss->ssl3.prSpec; | |
| 1461 - prSpec->read_seq_num.high = prSpec->read_seq_num.low = 0; | |
| 1462 | |
| 1463 ss->ssl3.prSpec = ss->ssl3.crSpec; | |
| 1464 ss->ssl3.crSpec = prSpec; | |
| 1465 @@ -2981,6 +3090,11 @@ | |
| 1466 if (!isDH && pwSpec->master_secret && ss->opt.detectRollBack) { | |
| 1467 SSL3ProtocolVersion client_version; | |
| 1468 client_version = pms_version.major << 8 | pms_version.minor; | |
| 1469 + | |
| 1470 + if (IS_DTLS(ss)) { | |
| 1471 + client_version = dtls_DTLSVersionToTLSVersion(client_version); | |
| 1472 + } | |
| 1473 + | |
| 1474 if (client_version != ss->clientHelloVersion) { | |
| 1475 /* Destroy it. Version roll-back detected. */ | |
| 1476 PK11_FreeSymKey(pwSpec->master_secret); | |
| 1477 @@ -3405,6 +3519,17 @@ | |
| 1478 { | |
| 1479 SECStatus rv; | |
| 1480 | |
| 1481 + /* If we already have a message in place, we need to enqueue it. | |
| 1482 + * This empties the buffer. This is a convenient place to call | |
| 1483 + * dtls_StageHandshakeMessage to mark the message boundary. | |
| 1484 + */ | |
| 1485 + if (IS_DTLS(ss)) { | |
| 1486 + rv = dtls_StageHandshakeMessage(ss); | |
| 1487 + if (rv != SECSuccess) { | |
| 1488 + return rv; | |
| 1489 + } | |
| 1490 + } | |
| 1491 + | |
| 1492 SSL_TRC(30,("%d: SSL3[%d]: append handshake header: type %s", | |
| 1493 SSL_GETPID(), ss->fd, ssl3_DecodeHandshakeType(t))); | |
| 1494 PRINT_BUF(60, (ss, "MD5 handshake hash:", | |
| 1495 @@ -3417,6 +3542,32 @@ | |
| 1496 return rv; /* error code set by AppendHandshake, if applicable. */ | |
| 1497 } | |
| 1498 rv = ssl3_AppendHandshakeNumber(ss, length, 3); | |
| 1499 + if (rv != SECSuccess) { | |
| 1500 + return rv; /* error code set by AppendHandshake, if applicable. */ | |
| 1501 + } | |
| 1502 + | |
| 1503 + if (IS_DTLS(ss)) { | |
| 1504 + /* Note that we make an unfragmented message here. We fragment in the | |
| 1505 + * transmission code, if necessary */ | |
| 1506 + rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.sendMessageSeq, 2); | |
| 1507 + if (rv != SECSuccess) { | |
| 1508 + return rv; /* error code set by AppendHandshake, if applicable. */ | |
| 1509 + } | |
| 1510 + ss->ssl3.hs.sendMessageSeq++; | |
| 1511 + | |
| 1512 + /* 0 is the fragment offset, because it's not fragmented yet */ | |
| 1513 + rv = ssl3_AppendHandshakeNumber(ss, 0, 3); | |
| 1514 + if (rv != SECSuccess) { | |
| 1515 + return rv; /* error code set by AppendHandshake, if applicable. */ | |
| 1516 + } | |
| 1517 + | |
| 1518 + /* Fragment length -- set to the packet length because not fragmented */ | |
| 1519 + rv = ssl3_AppendHandshakeNumber(ss, length, 3); | |
| 1520 + if (rv != SECSuccess) { | |
| 1521 + return rv; /* error code set by AppendHandshake, if applicable. */ | |
| 1522 + } | |
| 1523 + } | |
| 1524 + | |
| 1525 return rv; /* error code set by AppendHandshake, if applicable. */ | |
| 1526 } | |
| 1527 | |
| 1528 @@ -3823,9 +3974,10 @@ | |
| 1529 /* Called from ssl3_HandleHelloRequest(), | |
| 1530 * ssl3_RedoHandshake() | |
| 1531 * ssl2_BeginClientHandshake (when resuming ssl3 session) | |
| 1532 + * dtls_HandleHelloVerifyRequest(with resending=PR_TRUE) | |
| 1533 */ | |
| 1534 SECStatus | |
| 1535 -ssl3_SendClientHello(sslSocket *ss) | |
| 1536 +ssl3_SendClientHello(sslSocket *ss, PRBool resending) | |
| 1537 { | |
| 1538 sslSessionID * sid; | |
| 1539 ssl3CipherSpec * cwSpec; | |
| 1540 @@ -3849,6 +4001,7 @@ | |
| 1541 return rv; /* ssl3_InitState has set the error code. */ | |
| 1542 } | |
| 1543 ss->ssl3.hs.sendingSCSV = PR_FALSE; /* Must be reset every handshake */ | |
| 1544 + PORT_Assert(IS_DTLS(ss) || !resending); | |
| 1545 | |
| 1546 /* We might be starting a session renegotiation in which case we should | |
| 1547 * clear previous state. | |
| 1548 @@ -4008,6 +4161,10 @@ | |
| 1549 } | |
| 1550 #endif | |
| 1551 | |
| 1552 + if (IS_DTLS(ss)) { | |
| 1553 + ssl3_DisableNonDTLSSuites(ss); | |
| 1554 + } | |
| 1555 + | |
| 1556 /* how many suites are permitted by policy and user preference? */ | |
| 1557 num_suites = count_cipher_suites(ss, ss->ssl3.policy, PR_TRUE); | |
| 1558 if (!num_suites) | |
| 1559 @@ -4027,6 +4184,9 @@ | |
| 1560 1 + ((sid == NULL) ? 0 : sid->u.ssl3.sessionIDLength) + | |
| 1561 2 + num_suites*sizeof(ssl3CipherSuite) + | |
| 1562 1 + numCompressionMethods + total_exten_len; | |
| 1563 + if (IS_DTLS(ss)) { | |
| 1564 + length += 1 + ss->ssl3.hs.cookieLen; | |
| 1565 + } | |
| 1566 | |
| 1567 rv = ssl3_AppendHandshakeHeader(ss, client_hello, length); | |
| 1568 if (rv != SECSuccess) { | |
| 1569 @@ -4034,13 +4194,23 @@ | |
| 1570 } | |
| 1571 | |
| 1572 ss->clientHelloVersion = ss->version; | |
| 1573 - rv = ssl3_AppendHandshakeNumber(ss, ss->clientHelloVersion, 2); | |
| 1574 + if (IS_DTLS(ss)) { | |
| 1575 + PRUint16 version; | |
| 1576 + | |
| 1577 + version = dtls_TLSVersionToDTLSVersion(ss->clientHelloVersion); | |
| 1578 + rv = ssl3_AppendHandshakeNumber(ss, version, 2); | |
| 1579 + } else { | |
| 1580 + rv = ssl3_AppendHandshakeNumber(ss, ss->clientHelloVersion, 2); | |
| 1581 + } | |
| 1582 if (rv != SECSuccess) { | |
| 1583 return rv; /* err set by ssl3_AppendHandshake* */ | |
| 1584 } | |
| 1585 - rv = ssl3_GetNewRandom(&ss->ssl3.hs.client_random); | |
| 1586 - if (rv != SECSuccess) { | |
| 1587 - return rv; /* err set by GetNewRandom. */ | |
| 1588 + | |
| 1589 + if (!resending) { /* Don't re-generate if we are in DTLS re-sending mode */ | |
| 1590 + rv = ssl3_GetNewRandom(&ss->ssl3.hs.client_random); | |
| 1591 + if (rv != SECSuccess) { | |
| 1592 + return rv; /* err set by GetNewRandom. */ | |
| 1593 + } | |
| 1594 } | |
| 1595 rv = ssl3_AppendHandshake(ss, &ss->ssl3.hs.client_random, | |
| 1596 SSL3_RANDOM_LENGTH); | |
| 1597 @@ -4057,6 +4227,14 @@ | |
| 1598 return rv; /* err set by ssl3_AppendHandshake* */ | |
| 1599 } | |
| 1600 | |
| 1601 + if (IS_DTLS(ss)) { | |
| 1602 + rv = ssl3_AppendHandshakeVariable( | |
| 1603 + ss, ss->ssl3.hs.cookie, ss->ssl3.hs.cookieLen, 1); | |
| 1604 + if (rv != SECSuccess) { | |
| 1605 + return rv; /* err set by ssl3_AppendHandshake* */ | |
| 1606 + } | |
| 1607 + } | |
| 1608 + | |
| 1609 rv = ssl3_AppendHandshakeNumber(ss, num_suites*sizeof(ssl3CipherSuite), 2); | |
| 1610 if (rv != SECSuccess) { | |
| 1611 return rv; /* err set by ssl3_AppendHandshake* */ | |
| 1612 @@ -4180,8 +4358,12 @@ | |
| 1613 ss->sec.ci.sid = NULL; | |
| 1614 } | |
| 1615 | |
| 1616 + if (IS_DTLS(ss)) { | |
| 1617 + dtls_RehandshakeCleanup(ss); | |
| 1618 + } | |
| 1619 + | |
| 1620 ssl_GetXmitBufLock(ss); | |
| 1621 - rv = ssl3_SendClientHello(ss); | |
| 1622 + rv = ssl3_SendClientHello(ss, PR_FALSE); | |
| 1623 ssl_ReleaseXmitBufLock(ss); | |
| 1624 | |
| 1625 return rv; | |
| 1626 @@ -5036,6 +5218,23 @@ | |
| 1627 } | |
| 1628 version = (SSL3ProtocolVersion)temp; | |
| 1629 | |
| 1630 + if (IS_DTLS(ss)) { | |
| 1631 + /* RFC 4347 required that you verify that the server versions | |
| 1632 + * match (Section 4.2.1) in the HelloVerifyRequest and the | |
| 1633 + * ServerHello. | |
| 1634 + * | |
| 1635 + * RFC 6347 suggests (SHOULD) that servers always use 1.0 | |
| 1636 + * in HelloVerifyRequest and allows the versions not to match, | |
| 1637 + * especially when 1.2 is being negotiated. | |
| 1638 + * | |
| 1639 + * Therefore we do not check for matching here. | |
| 1640 + */ | |
| 1641 + version = dtls_DTLSVersionToTLSVersion(version); | |
| 1642 + if (version == 0) { /* Insane version number */ | |
| 1643 + goto alert_loser; | |
| 1644 + } | |
| 1645 + } | |
| 1646 + | |
| 1647 rv = ssl3_NegotiateVersion(ss, version, PR_FALSE); | |
| 1648 if (rv != SECSuccess) { | |
| 1649 desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version | |
| 1650 @@ -6264,6 +6463,7 @@ | |
| 1651 SSL3AlertLevel level = alert_fatal; | |
| 1652 SSL3ProtocolVersion version; | |
| 1653 SECItem sidBytes = {siBuffer, NULL, 0}; | |
| 1654 + SECItem cookieBytes = {siBuffer, NULL, 0}; | |
| 1655 SECItem suites = {siBuffer, NULL, 0}; | |
| 1656 SECItem comps = {siBuffer, NULL, 0}; | |
| 1657 PRBool haveSpecWriteLock = PR_FALSE; | |
| 1658 @@ -6281,6 +6481,20 @@ | |
| 1659 return rv; /* error code is set. */ | |
| 1660 } | |
| 1661 | |
| 1662 + /* Clearing the handshake pointers so that ssl_Do1stHandshake won't | |
| 1663 + * call ssl2_HandleMessage. | |
| 1664 + * | |
| 1665 + * The issue here is that TLS ordinarily starts out in | |
| 1666 + * ssl2_HandleV3HandshakeRecord() because of the backward-compatibility | |
| 1667 + * code paths. That function zeroes these next pointers. But with DTLS, | |
| 1668 + * we don't even try to do the v2 ClientHello so we skip that function | |
| 1669 + * and need to reset these values here. | |
| 1670 + */ | |
| 1671 + if (IS_DTLS(ss)) { | |
| 1672 + ss->nextHandshake = 0; | |
| 1673 + ss->securityHandshake = 0; | |
| 1674 + } | |
| 1675 + | |
| 1676 /* We might be starting session renegotiation in which case we should | |
| 1677 * clear previous state. | |
| 1678 */ | |
| 1679 @@ -6306,10 +6520,22 @@ | |
| 1680 goto alert_loser; | |
| 1681 } | |
| 1682 | |
| 1683 + if (IS_DTLS(ss)) { | |
| 1684 + dtls_RehandshakeCleanup(ss); | |
| 1685 + } | |
| 1686 + | |
| 1687 tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); | |
| 1688 if (tmp < 0) | |
| 1689 goto loser; /* malformed, alert already sent */ | |
| 1690 - ss->clientHelloVersion = version = (SSL3ProtocolVersion)tmp; | |
| 1691 + | |
| 1692 + /* Translate the version */ | |
| 1693 + if (IS_DTLS(ss)) { | |
| 1694 + ss->clientHelloVersion = version = | |
| 1695 + dtls_DTLSVersionToTLSVersion((SSL3ProtocolVersion)tmp); | |
| 1696 + } else { | |
| 1697 + ss->clientHelloVersion = version = (SSL3ProtocolVersion)tmp; | |
| 1698 + } | |
| 1699 + | |
| 1700 rv = ssl3_NegotiateVersion(ss, version, PR_TRUE); | |
| 1701 if (rv != SECSuccess) { | |
| 1702 desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version | |
| 1703 @@ -6331,6 +6557,14 @@ | |
| 1704 goto loser; /* malformed */ | |
| 1705 } | |
| 1706 | |
| 1707 + /* grab the client's cookie, if present. */ | |
| 1708 + if (IS_DTLS(ss)) { | |
| 1709 + rv = ssl3_ConsumeHandshakeVariable(ss, &cookieBytes, 1, &b, &length); | |
| 1710 + if (rv != SECSuccess) { | |
| 1711 + goto loser; /* malformed */ | |
| 1712 + } | |
| 1713 + } | |
| 1714 + | |
| 1715 /* grab the list of cipher suites. */ | |
| 1716 rv = ssl3_ConsumeHandshakeVariable(ss, &suites, 2, &b, &length); | |
| 1717 if (rv != SECSuccess) { | |
| 1718 @@ -6479,6 +6713,10 @@ | |
| 1719 ssl3_FilterECCipherSuitesByServerCerts(ss); | |
| 1720 #endif | |
| 1721 | |
| 1722 + if (IS_DTLS(ss)) { | |
| 1723 + ssl3_DisableNonDTLSSuites(ss); | |
| 1724 + } | |
| 1725 + | |
| 1726 #ifdef PARANOID | |
| 1727 /* Look for a matching cipher suite. */ | |
| 1728 j = ssl3_config_match_init(ss); | |
| 1729 @@ -7166,17 +7404,28 @@ | |
| 1730 PRUint32 maxBytes = 65535; | |
| 1731 PRUint32 length; | |
| 1732 PRInt32 extensions_len = 0; | |
| 1733 + SSL3ProtocolVersion version; | |
| 1734 | |
| 1735 SSL_TRC(3, ("%d: SSL3[%d]: send server_hello handshake", SSL_GETPID(), | |
| 1736 ss->fd)); | |
| 1737 | |
| 1738 PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); | |
| 1739 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); | |
| 1740 - PORT_Assert( MSB(ss->version) == MSB(SSL_LIBRARY_VERSION_3_0)); | |
| 1741 | |
| 1742 - if (MSB(ss->version) != MSB(SSL_LIBRARY_VERSION_3_0)) { | |
| 1743 - PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); | |
| 1744 - return SECFailure; | |
| 1745 + if (!IS_DTLS(ss)) { | |
| 1746 + PORT_Assert(MSB(ss->version) == MSB(SSL_LIBRARY_VERSION_3_0)); | |
| 1747 + | |
| 1748 + if (MSB(ss->version) != MSB(SSL_LIBRARY_VERSION_3_0)) { | |
| 1749 + PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); | |
| 1750 + return SECFailure; | |
| 1751 + } | |
| 1752 + } else { | |
| 1753 + PORT_Assert(MSB(ss->version) == MSB(SSL_LIBRARY_VERSION_DTLS_1_0)); | |
| 1754 + | |
| 1755 + if (MSB(ss->version) != MSB(SSL_LIBRARY_VERSION_DTLS_1_0)) { | |
| 1756 + PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); | |
| 1757 + return SECFailure; | |
| 1758 + } | |
| 1759 } | |
| 1760 | |
| 1761 sid = ss->sec.ci.sid; | |
| 1762 @@ -7194,7 +7443,13 @@ | |
| 1763 return rv; /* err set by AppendHandshake. */ | |
| 1764 } | |
| 1765 | |
| 1766 - rv = ssl3_AppendHandshakeNumber(ss, ss->version, 2); | |
| 1767 + if (IS_DTLS(ss)) { | |
| 1768 + version = dtls_TLSVersionToDTLSVersion(ss->version); | |
| 1769 + } else { | |
| 1770 + version = ss->version; | |
| 1771 + } | |
| 1772 + | |
| 1773 + rv = ssl3_AppendHandshakeNumber(ss, version, 2); | |
| 1774 if (rv != SECSuccess) { | |
| 1775 return rv; /* err set by AppendHandshake. */ | |
| 1776 } | |
| 1777 @@ -7379,11 +7634,8 @@ | |
| 1778 nnames = ca_list->nnames; | |
| 1779 } | |
| 1780 | |
| 1781 - if (!nnames) { | |
| 1782 - PORT_SetError(SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA); | |
| 1783 - return SECFailure; | |
| 1784 - } | |
| 1785 - | |
| 1786 + /* There used to be a test here to require a CA, but there | |
| 1787 + * are cases where you want to have no CAs offered. */ | |
| 1788 for (i = 0, name = names; i < nnames; i++, name++) { | |
| 1789 calen += 2 + name->len; | |
| 1790 } | |
| 1791 @@ -7551,9 +7803,17 @@ | |
| 1792 } | |
| 1793 | |
| 1794 /* Generate the pre-master secret ... */ | |
| 1795 - version.major = MSB(ss->clientHelloVersion); | |
| 1796 - version.minor = LSB(ss->clientHelloVersion); | |
| 1797 + if (IS_DTLS(ss)) { | |
| 1798 + SSL3ProtocolVersion temp; | |
| 1799 | |
| 1800 + temp = dtls_TLSVersionToDTLSVersion(ss->clientHelloVersion); | |
| 1801 + version.major = MSB(temp); | |
| 1802 + version.minor = LSB(temp); | |
| 1803 + } else { | |
| 1804 + version.major = MSB(ss->clientHelloVersion); | |
| 1805 + version.minor = LSB(ss->clientHelloVersion); | |
| 1806 + } | |
| 1807 + | |
| 1808 param.data = (unsigned char *)&version; | |
| 1809 param.len = sizeof version; | |
| 1810 | |
| 1811 @@ -7635,6 +7895,11 @@ | |
| 1812 } else if (ss->opt.detectRollBack) { | |
| 1813 SSL3ProtocolVersion client_version = | |
| 1814 (rsaPmsBuf[0] << 8) | rsaPmsBuf[1]; | |
| 1815 + | |
| 1816 + if (IS_DTLS(ss)) { | |
| 1817 + client_version = dtls_DTLSVersionToTLSVersion(client_version); | |
| 1818 + } | |
| 1819 + | |
| 1820 if (client_version != ss->clientHelloVersion) { | |
| 1821 /* Version roll-back detected. ensure failure. */ | |
| 1822 rv = PK11_GenerateRandom(rsaPmsBuf, sizeof rsaPmsBuf); | |
| 1823 @@ -8851,6 +9116,10 @@ | |
| 1824 } | |
| 1825 } | |
| 1826 | |
| 1827 + if (IS_DTLS(ss)) { | |
| 1828 + flags |= ssl_SEND_FLAG_NO_RETRANSMIT; | |
| 1829 + } | |
| 1830 + | |
| 1831 rv = ssl3_SendFinished(ss, flags); | |
| 1832 if (rv != SECSuccess) { | |
| 1833 goto xmit_loser; /* err is set. */ | |
| 1834 @@ -8980,13 +9249,14 @@ | |
| 1835 * hanshake message. | |
| 1836 * Caller must hold Handshake and RecvBuf locks. | |
| 1837 */ | |
| 1838 -static SECStatus | |
| 1839 +SECStatus | |
| 1840 ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length) | |
| 1841 { | |
| 1842 SECStatus rv = SECSuccess; | |
| 1843 SSL3HandshakeType type = ss->ssl3.hs.msg_type; | |
| 1844 SSL3Hashes hashes; /* computed hashes are put here. */ | |
| 1845 PRUint8 hdr[4]; | |
| 1846 + PRUint8 dtlsData[8]; | |
| 1847 | |
| 1848 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | |
| 1849 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); | |
| 1850 @@ -9032,10 +9302,35 @@ | |
| 1851 return rv; | |
| 1852 } | |
| 1853 } | |
| 1854 - /* We should not include hello_request messages in the handshake hashes */ | |
| 1855 - if (ss->ssl3.hs.msg_type != hello_request) { | |
| 1856 + /* We should not include hello_request and hello_verify_request messages | |
| 1857 + * in the handshake hashes */ | |
| 1858 + if ((ss->ssl3.hs.msg_type != hello_request) && | |
| 1859 + (ss->ssl3.hs.msg_type != hello_verify_request)) { | |
| 1860 rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char*) hdr, 4); | |
| 1861 if (rv != SECSuccess) return rv; /* err code already set. */ | |
| 1862 + | |
| 1863 + /* Extra data to simulate a complete DTLS handshake fragment */ | |
| 1864 + if (IS_DTLS(ss)) { | |
| 1865 + /* Sequence number */ | |
| 1866 + dtlsData[0] = MSB(ss->ssl3.hs.recvMessageSeq); | |
| 1867 + dtlsData[1] = LSB(ss->ssl3.hs.recvMessageSeq); | |
| 1868 + | |
| 1869 + /* Fragment offset */ | |
| 1870 + dtlsData[2] = 0; | |
| 1871 + dtlsData[3] = 0; | |
| 1872 + dtlsData[4] = 0; | |
| 1873 + | |
| 1874 + /* Fragment length */ | |
| 1875 + dtlsData[5] = (PRUint8)(length >> 16); | |
| 1876 + dtlsData[6] = (PRUint8)(length >> 8); | |
| 1877 + dtlsData[7] = (PRUint8)(length ); | |
| 1878 + | |
| 1879 + rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char*) dtlsData, | |
| 1880 + sizeof(dtlsData)); | |
| 1881 + if (rv != SECSuccess) return rv; /* err code already set. */ | |
| 1882 + } | |
| 1883 + | |
| 1884 + /* The message body */ | |
| 1885 rv = ssl3_UpdateHandshakeHashes(ss, b, length); | |
| 1886 if (rv != SECSuccess) return rv; /* err code already set. */ | |
| 1887 } | |
| 1888 @@ -9071,6 +9366,14 @@ | |
| 1889 } | |
| 1890 rv = ssl3_HandleServerHello(ss, b, length); | |
| 1891 break; | |
| 1892 + case hello_verify_request: | |
| 1893 + if (!IS_DTLS(ss) || ss->sec.isServer) { | |
| 1894 + (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); | |
| 1895 + PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST); | |
| 1896 + return SECFailure; | |
| 1897 + } | |
| 1898 + rv = dtls_HandleHelloVerifyRequest(ss, b, length); | |
| 1899 + break; | |
| 1900 case certificate: | |
| 1901 if (ss->ssl3.hs.may_get_cert_status) { | |
| 1902 /* If we might get a CertificateStatus then we want to postpone the | |
| 1903 @@ -9169,6 +9472,12 @@ | |
| 1904 PORT_SetError(SSL_ERROR_RX_UNKNOWN_HANDSHAKE); | |
| 1905 rv = SECFailure; | |
| 1906 } | |
| 1907 + | |
| 1908 + if (IS_DTLS(ss) && (rv == SECSuccess)) { | |
| 1909 + /* Increment the expected sequence number */ | |
| 1910 + ss->ssl3.hs.recvMessageSeq++; | |
| 1911 + } | |
| 1912 + | |
| 1913 return rv; | |
| 1914 } | |
| 1915 | |
| 1916 @@ -9331,6 +9640,7 @@ | |
| 1917 SSL3Opaque hash[MAX_MAC_LENGTH]; | |
| 1918 sslBuffer *plaintext; | |
| 1919 sslBuffer temp_buf; | |
| 1920 + PRUint64 dtls_seq_num; | |
| 1921 unsigned int ivLen = 0; | |
| 1922 | |
| 1923 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | |
| 1924 @@ -9366,6 +9676,39 @@ | |
| 1925 crSpec = ss->ssl3.crSpec; | |
| 1926 cipher_def = crSpec->cipher_def; | |
| 1927 | |
| 1928 + /* | |
| 1929 + * DTLS relevance checks: | |
| 1930 + * Note that this code currently ignores all out-of-epoch packets, | |
| 1931 + * which means we lose some in the case of rehandshake + | |
| 1932 + * loss/reordering. Since DTLS is explicitly unreliable, this | |
| 1933 + * seems like a good tradeoff for implementation effort and is | |
| 1934 + * consistent with the guidance of RFC 6347 Sections 4.1 and 4.2.4.1 | |
| 1935 + */ | |
| 1936 + if (IS_DTLS(ss)) { | |
| 1937 + DTLSEpoch epoch = (cText->seq_num.high >> 16) & 0xffff; | |
| 1938 + | |
| 1939 + if (crSpec->epoch != epoch) { | |
| 1940 + ssl_ReleaseSpecReadLock(ss); | |
| 1941 + SSL_DBG(("%d: SSL3[%d]: HandleRecord, received packet " | |
| 1942 + "from irrelevant epoch %d", SSL_GETPID(), ss->fd, epoch)); | |
| 1943 + /* Silently drop the packet */ | |
| 1944 + databuf->len = 0; /* Needed to ensure data not left around */ | |
| 1945 + return SECSuccess; | |
| 1946 + } | |
| 1947 + | |
| 1948 + dtls_seq_num = (((PRUint64)(cText->seq_num.high & 0xffff)) << 32) | | |
| 1949 + ((PRUint64)cText->seq_num.low); | |
| 1950 + | |
| 1951 + if (dtls_RecordGetRecvd(&crSpec->recvdRecords, dtls_seq_num) != 0) { | |
| 1952 + ssl_ReleaseSpecReadLock(ss); | |
| 1953 + SSL_DBG(("%d: SSL3[%d]: HandleRecord, rejecting " | |
| 1954 + "potentially replayed packet", SSL_GETPID(), ss->fd)); | |
| 1955 + /* Silently drop the packet */ | |
| 1956 + databuf->len = 0; /* Needed to ensure data not left around */ | |
| 1957 + return SECSuccess; | |
| 1958 + } | |
| 1959 + } | |
| 1960 + | |
| 1961 if (cipher_def->type == type_block && | |
| 1962 crSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { | |
| 1963 /* Consume the per-record explicit IV. RFC 4346 Section 6.2.3.2 states | |
| 1964 @@ -9487,7 +9830,8 @@ | |
| 1965 /* compute the MAC */ | |
| 1966 rType = cText->type; | |
| 1967 rv = ssl3_ComputeRecordMAC( crSpec, (PRBool)(!ss->sec.isServer), | |
| 1968 - rType, cText->version, crSpec->read_seq_num, | |
| 1969 + IS_DTLS(ss), rType, cText->version, | |
| 1970 + IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num, | |
| 1971 plaintext->buf, plaintext->len, hash, &hashBytes); | |
| 1972 if (rv != SECSuccess) { | |
| 1973 padIsBad = PR_TRUE; /* really macIsBad */ | |
| 1974 @@ -9499,19 +9843,27 @@ | |
| 1975 crSpec->mac_size) != 0) { | |
| 1976 /* must not hold spec lock when calling SSL3_SendAlert. */ | |
| 1977 ssl_ReleaseSpecReadLock(ss); | |
| 1978 - SSL3_SendAlert(ss, alert_fatal, bad_record_mac); | |
| 1979 - /* always log mac error, in case attacker can read server logs. */ | |
| 1980 - PORT_SetError(SSL_ERROR_BAD_MAC_READ); | |
| 1981 | |
| 1982 SSL_DBG(("%d: SSL3[%d]: mac check failed", SSL_GETPID(), ss->fd)); | |
| 1983 | |
| 1984 - return SECFailure; | |
| 1985 + if (!IS_DTLS(ss)) { | |
| 1986 + SSL3_SendAlert(ss, alert_fatal, bad_record_mac); | |
| 1987 + /* always log mac error, in case attacker can read server logs. */ | |
| 1988 + PORT_SetError(SSL_ERROR_BAD_MAC_READ); | |
| 1989 + return SECFailure; | |
| 1990 + } else { | |
| 1991 + /* Silently drop the packet */ | |
| 1992 + databuf->len = 0; /* Needed to ensure data not left around */ | |
| 1993 + return SECSuccess; | |
| 1994 + } | |
| 1995 } | |
| 1996 | |
| 1997 + if (!IS_DTLS(ss)) { | |
| 1998 + ssl3_BumpSequenceNumber(&crSpec->read_seq_num); | |
| 1999 + } else { | |
| 2000 + dtls_RecordSetRecvd(&crSpec->recvdRecords, dtls_seq_num); | |
| 2001 + } | |
| 2002 | |
| 2003 - | |
| 2004 - ssl3_BumpSequenceNumber(&crSpec->read_seq_num); | |
| 2005 - | |
| 2006 ssl_ReleaseSpecReadLock(ss); /*****************************************/ | |
| 2007 | |
| 2008 /* | |
| 2009 @@ -9615,7 +9967,11 @@ | |
| 2010 rv = ssl3_HandleAlert(ss, databuf); | |
| 2011 break; | |
| 2012 case content_handshake: | |
| 2013 - rv = ssl3_HandleHandshake(ss, databuf); | |
| 2014 + if (!IS_DTLS(ss)) { | |
| 2015 + rv = ssl3_HandleHandshake(ss, databuf); | |
| 2016 + } else { | |
| 2017 + rv = dtls_HandleHandshake(ss, databuf); | |
| 2018 + } | |
| 2019 break; | |
| 2020 /* | |
| 2021 case content_application_data is handled before this switch | |
| 2022 @@ -9675,6 +10031,9 @@ | |
| 2023 spec->read_seq_num.high = 0; | |
| 2024 spec->read_seq_num.low = 0; | |
| 2025 | |
| 2026 + spec->epoch = 0; | |
| 2027 + dtls_InitRecvdRecords(&spec->recvdRecords); | |
| 2028 + | |
| 2029 spec->version = ss->vrange.max; | |
| 2030 } | |
| 2031 | |
| 2032 @@ -9716,6 +10075,21 @@ | |
| 2033 | |
| 2034 PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData)); | |
| 2035 | |
| 2036 + if (IS_DTLS(ss)) { | |
| 2037 + ss->ssl3.hs.sendMessageSeq = 0; | |
| 2038 + ss->ssl3.hs.recvMessageSeq = 0; | |
| 2039 + ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS; | |
| 2040 + ss->ssl3.hs.rtRetries = 0; | |
| 2041 + | |
| 2042 + /* Have to allocate this because ssl_FreeSocket relocates | |
| 2043 + * this structure in DEBUG mode */ | |
| 2044 + if (!(ss->ssl3.hs.lastMessageFlight = PORT_New(PRCList))) | |
| 2045 + return SECFailure; | |
| 2046 + ss->ssl3.hs.recvdHighWater = -1; | |
| 2047 + PR_INIT_CLIST(ss->ssl3.hs.lastMessageFlight); | |
| 2048 + dtls_SetMTU(ss, 0); /* Set the MTU to the highest plateau */ | |
| 2049 + } | |
| 2050 + | |
| 2051 rv = ssl3_NewHandshakeHashes(ss); | |
| 2052 if (rv == SECSuccess) { | |
| 2053 ss->ssl3.initialized = PR_TRUE; | |
| 2054 @@ -9968,6 +10342,11 @@ | |
| 2055 PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED); | |
| 2056 return SECFailure; | |
| 2057 } | |
| 2058 + | |
| 2059 + if (IS_DTLS(ss)) { | |
| 2060 + dtls_RehandshakeCleanup(ss); | |
| 2061 + } | |
| 2062 + | |
| 2063 if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) { | |
| 2064 PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED); | |
| 2065 return SECFailure; | |
| 2066 @@ -9982,7 +10361,7 @@ | |
| 2067 | |
| 2068 /* start off a new handshake. */ | |
| 2069 rv = (ss->sec.isServer) ? ssl3_SendHelloRequest(ss) | |
| 2070 - : ssl3_SendClientHello(ss); | |
| 2071 + : ssl3_SendClientHello(ss, PR_FALSE); | |
| 2072 | |
| 2073 ssl_ReleaseXmitBufLock(ss); /**************************************/ | |
| 2074 return rv; | |
| 2075 @@ -10042,6 +10421,17 @@ | |
| 2076 ssl3_DestroyCipherSpec(&ss->ssl3.specs[0], PR_TRUE/*freeSrvName*/); | |
| 2077 ssl3_DestroyCipherSpec(&ss->ssl3.specs[1], PR_TRUE/*freeSrvName*/); | |
| 2078 | |
| 2079 + /* Destroy the DTLS data */ | |
| 2080 + if (IS_DTLS(ss)) { | |
| 2081 + if (ss->ssl3.hs.lastMessageFlight) { | |
| 2082 + dtls_FreeHandshakeMessages(ss->ssl3.hs.lastMessageFlight); | |
| 2083 + PORT_Free(ss->ssl3.hs.lastMessageFlight); | |
| 2084 + } | |
| 2085 + if (ss->ssl3.hs.recvdFragments.buf) { | |
| 2086 + PORT_Free(ss->ssl3.hs.recvdFragments.buf); | |
| 2087 + } | |
| 2088 + } | |
| 2089 + | |
| 2090 ss->ssl3.initialized = PR_FALSE; | |
| 2091 | |
| 2092 SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE); | |
| 2093 Index: net/third_party/nss/ssl/sslgathr.c | |
| 2094 =================================================================== | |
| 2095 --- net/third_party/nss/ssl/sslgathr.c (revision 127709) | |
| 2096 +++ net/third_party/nss/ssl/sslgathr.c (working copy) | |
| 2097 @@ -434,6 +434,8 @@ | |
| 2098 gs->state = GS_INIT; | |
| 2099 gs->writeOffset = 0; | |
| 2100 gs->readOffset = 0; | |
| 2101 + gs->dtlsPacketOffset = 0; | |
| 2102 + gs->dtlsPacket.len = 0; | |
| 2103 status = sslBuffer_Grow(&gs->buf, 4096); | |
| 2104 return status; | |
| 2105 } | |
| 2106 @@ -445,6 +447,7 @@ | |
| 2107 if (gs) { /* the PORT_*Free functions check for NULL pointers. */ | |
| 2108 PORT_ZFree(gs->buf.buf, gs->buf.space); | |
| 2109 PORT_Free(gs->inbuf.buf); | |
| 2110 + PORT_Free(gs->dtlsPacket.buf); | |
| 2111 } | |
| 2112 } | |
| 2113 | |
| 2114 Index: net/third_party/nss/ssl/dtls1con.c | |
| 2115 =================================================================== | |
| 2116 --- net/third_party/nss/ssl/dtls1con.c (revision 0) | |
| 2117 +++ net/third_party/nss/ssl/dtls1con.c (revision 0) | |
| 2118 @@ -0,0 +1,1164 @@ | |
| 2119 +/* | |
| 2120 + * DTLS Protocol | |
| 2121 + * | |
| 2122 + * ***** BEGIN LICENSE BLOCK ***** | |
| 2123 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | |
| 2124 + * | |
| 2125 + * The contents of this file are subject to the Mozilla Public License Version | |
| 2126 + * 1.1 (the "License"); you may not use this file except in compliance with | |
| 2127 + * the License. You may obtain a copy of the License at | |
| 2128 + * http://www.mozilla.org/MPL/ | |
| 2129 + * | |
| 2130 + * Software distributed under the License is distributed on an "AS IS" basis, | |
| 2131 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |
| 2132 + * for the specific language governing rights and limitations under the | |
| 2133 + * License. | |
| 2134 + * | |
| 2135 + * The Original Code is the Netscape security libraries. | |
| 2136 + * | |
| 2137 + * The Initial Developer of the Original Code is | |
| 2138 + * Netscape Communications Corporation. | |
| 2139 + * Portions created by the Initial Developer are Copyright (C) 1994-2000 | |
| 2140 + * the Initial Developer. All Rights Reserved. | |
| 2141 + * | |
| 2142 + * Contributor(s): | |
| 2143 + * Eric Rescorla <ekr@rtfm.com> | |
| 2144 + * | |
| 2145 + * Alternatively, the contents of this file may be used under the terms of | |
| 2146 + * either the GNU General Public License Version 2 or later (the "GPL"), or | |
| 2147 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | |
| 2148 + * in which case the provisions of the GPL or the LGPL are applicable instead | |
| 2149 + * of those above. If you wish to allow use of your version of this file only | |
| 2150 + * under the terms of either the GPL or the LGPL, and not to allow others to | |
| 2151 + * use your version of this file under the terms of the MPL, indicate your | |
| 2152 + * decision by deleting the provisions above and replace them with the notice | |
| 2153 + * and other provisions required by the GPL or the LGPL. If you do not delete | |
| 2154 + * the provisions above, a recipient may use your version of this file under | |
| 2155 + * the terms of any one of the MPL, the GPL or the LGPL. | |
| 2156 + * | |
| 2157 + * ***** END LICENSE BLOCK ***** */ | |
| 2158 +/* $Id: $ */ | |
| 2159 + | |
| 2160 +#include "ssl.h" | |
| 2161 +#include "sslimpl.h" | |
| 2162 +#include "sslproto.h" | |
| 2163 + | |
| 2164 +#ifndef PR_ARRAY_SIZE | |
| 2165 +#define PR_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) | |
| 2166 +#endif | |
| 2167 + | |
| 2168 +static SECStatus dtls_TransmitMessageFlight(sslSocket *ss); | |
| 2169 +static void dtls_RetransmitTimerExpiredCb(sslSocket *ss); | |
| 2170 +static SECStatus dtls_SendSavedWriteData(sslSocket *ss); | |
| 2171 + | |
| 2172 +/* -28 adjusts for the IP/UDP header */ | |
| 2173 +static const PRUint16 COMMON_MTU_VALUES[] = { | |
| 2174 + 1500 - 28, /* Ethernet MTU */ | |
| 2175 + 1280 - 28, /* IPv6 minimum MTU */ | |
| 2176 + 576 - 28, /* Common assumption */ | |
| 2177 + 256 - 28 /* We're in serious trouble now */ | |
| 2178 +}; | |
| 2179 + | |
| 2180 +#define DTLS_COOKIE_BYTES 32 | |
| 2181 + | |
| 2182 +/* List copied from ssl3con.c:cipherSuites */ | |
| 2183 +static const ssl3CipherSuite nonDTLSSuites[] = { | |
| 2184 +#ifdef NSS_ENABLE_ECC | |
| 2185 + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, | |
| 2186 + TLS_ECDHE_RSA_WITH_RC4_128_SHA, | |
| 2187 +#endif /* NSS_ENABLE_ECC */ | |
| 2188 + TLS_DHE_DSS_WITH_RC4_128_SHA, | |
| 2189 +#ifdef NSS_ENABLE_ECC | |
| 2190 + TLS_ECDH_RSA_WITH_RC4_128_SHA, | |
| 2191 + TLS_ECDH_ECDSA_WITH_RC4_128_SHA, | |
| 2192 +#endif /* NSS_ENABLE_ECC */ | |
| 2193 + SSL_RSA_WITH_RC4_128_MD5, | |
| 2194 + SSL_RSA_WITH_RC4_128_SHA, | |
| 2195 + TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, | |
| 2196 + SSL_RSA_EXPORT_WITH_RC4_40_MD5, | |
| 2197 + 0 /* End of list marker */ | |
| 2198 +}; | |
| 2199 + | |
| 2200 +/* Map back and forth between TLS and DTLS versions in wire format. | |
| 2201 + * Mapping table is: | |
| 2202 + * | |
| 2203 + * TLS DTLS | |
| 2204 + * 1.1 (0302) 1.0 (feff) | |
| 2205 + */ | |
| 2206 +SSL3ProtocolVersion | |
| 2207 +dtls_TLSVersionToDTLSVersion(SSL3ProtocolVersion tlsv) | |
| 2208 +{ | |
| 2209 + /* Anything other than TLS 1.1 is an error, so return | |
| 2210 + * the invalid version ffff. */ | |
| 2211 + if (tlsv != SSL_LIBRARY_VERSION_TLS_1_1) | |
| 2212 + return 0xffff; | |
| 2213 + | |
| 2214 + return SSL_LIBRARY_VERSION_DTLS_1_0_WIRE; | |
| 2215 +} | |
| 2216 + | |
| 2217 +/* Map known DTLS versions to known TLS versions. | |
| 2218 + * - Invalid versions (< 1.0) return a version of 0 | |
| 2219 + * - Versions > known return a version one higher than we know of | |
| 2220 + * to accomodate a theoretically newer version */ | |
| 2221 +SSL3ProtocolVersion | |
| 2222 +dtls_DTLSVersionToTLSVersion(SSL3ProtocolVersion dtlsv) | |
| 2223 +{ | |
| 2224 + if (MSB(dtlsv) == 0xff) { | |
| 2225 + return 0; | |
| 2226 + } | |
| 2227 + | |
| 2228 + if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_0_WIRE) | |
| 2229 + return SSL_LIBRARY_VERSION_TLS_1_1; | |
| 2230 + | |
| 2231 + /* Return a fictional higher version than we know of */ | |
| 2232 + return SSL_LIBRARY_VERSION_TLS_1_1 + 1; | |
| 2233 +} | |
| 2234 + | |
| 2235 +/* On this socket, Disable non-DTLS cipher suites in the argument's list */ | |
| 2236 +SECStatus | |
| 2237 +ssl3_DisableNonDTLSSuites(sslSocket * ss) | |
| 2238 +{ | |
| 2239 + const ssl3CipherSuite * suite; | |
| 2240 + | |
| 2241 + for (suite = nonDTLSSuites; *suite; ++suite) { | |
| 2242 + SECStatus rv = ssl3_CipherPrefSet(ss, *suite, PR_FALSE); | |
| 2243 + | |
| 2244 + PORT_Assert(rv == SECSuccess); /* else is coding error */ | |
| 2245 + } | |
| 2246 + return SECSuccess; | |
| 2247 +} | |
| 2248 + | |
| 2249 +/* Allocate a DTLSQueuedMessage. | |
| 2250 + * | |
| 2251 + * Called from dtls_QueueMessage() | |
| 2252 + */ | |
| 2253 +static DTLSQueuedMessage * | |
| 2254 +dtls_AllocQueuedMessage(PRUint16 epoch, SSL3ContentType type, | |
| 2255 + const unsigned char *data, PRUint32 len) | |
| 2256 +{ | |
| 2257 + DTLSQueuedMessage *msg = NULL; | |
| 2258 + | |
| 2259 + msg = PORT_ZAlloc(sizeof(DTLSQueuedMessage)); | |
| 2260 + if (!msg) | |
| 2261 + return NULL; | |
| 2262 + | |
| 2263 + msg->data = PORT_Alloc(len); | |
| 2264 + if (!msg->data) { | |
| 2265 + PORT_Free(msg); | |
| 2266 + return NULL; | |
| 2267 + } | |
| 2268 + PORT_Memcpy(msg->data, data, len); | |
| 2269 + | |
| 2270 + msg->len = len; | |
| 2271 + msg->epoch = epoch; | |
| 2272 + msg->type = type; | |
| 2273 + | |
| 2274 + return msg; | |
| 2275 +} | |
| 2276 + | |
| 2277 +/* | |
| 2278 + * Free a handshake message | |
| 2279 + * | |
| 2280 + * Called from dtls_FreeHandshakeMessages() | |
| 2281 + */ | |
| 2282 +static void | |
| 2283 +dtls_FreeHandshakeMessage(DTLSQueuedMessage *msg) | |
| 2284 +{ | |
| 2285 + if (!msg) | |
| 2286 + return; | |
| 2287 + | |
| 2288 + PORT_ZFree(msg->data, msg->len); | |
| 2289 + PORT_Free(msg); | |
| 2290 +} | |
| 2291 + | |
| 2292 +/* | |
| 2293 + * Free a list of handshake messages | |
| 2294 + * | |
| 2295 + * Called from: | |
| 2296 + * dtls_HandleHandshake() | |
| 2297 + * ssl3_DestroySSL3Info() | |
| 2298 + */ | |
| 2299 +void | |
| 2300 +dtls_FreeHandshakeMessages(PRCList *list) | |
| 2301 +{ | |
| 2302 + PRCList *cur_p; | |
| 2303 + | |
| 2304 + while (!PR_CLIST_IS_EMPTY(list)) { | |
| 2305 + cur_p = PR_LIST_TAIL(list); | |
| 2306 + PR_REMOVE_LINK(cur_p); | |
| 2307 + dtls_FreeHandshakeMessage((DTLSQueuedMessage *)cur_p); | |
| 2308 + } | |
| 2309 +} | |
| 2310 + | |
| 2311 +/* Called only from ssl3_HandleRecord, for each (deciphered) DTLS record. | |
| 2312 + * origBuf is the decrypted ssl record content and is expected to contain | |
| 2313 + * complete handshake records | |
| 2314 + * Caller must hold the handshake and RecvBuf locks. | |
| 2315 + * | |
| 2316 + * Note that this code uses msg_len for two purposes: | |
| 2317 + * | |
| 2318 + * (1) To pass the length to ssl3_HandleHandshakeMessage() | |
| 2319 + * (2) To carry the length of a message currently being reassembled | |
| 2320 + * | |
| 2321 + * However, unlike ssl3_HandleHandshake(), it is not used to carry | |
| 2322 + * the state of reassembly (i.e., whether one is in progress). That | |
| 2323 + * is carried in recvdHighWater and recvdFragments. | |
| 2324 + */ | |
| 2325 +#define OFFSET_BYTE(o) (o/8) | |
| 2326 +#define OFFSET_MASK(o) (1 << (o%8)) | |
| 2327 + | |
| 2328 +SECStatus | |
| 2329 +dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) | |
| 2330 +{ | |
| 2331 + /* XXX OK for now. | |
| 2332 + * This doesn't work properly with asynchronous certificate validation. | |
| 2333 + * because that returns a WOULDBLOCK error. The current DTLS | |
| 2334 + * applications do not need asynchronous validation, but in the | |
| 2335 + * future we will need to add this. | |
| 2336 + */ | |
| 2337 + sslBuffer buf = *origBuf; | |
| 2338 + SECStatus rv = SECSuccess; | |
| 2339 + | |
| 2340 + PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); | |
| 2341 + PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); | |
| 2342 + | |
| 2343 + while (buf.len > 0) { | |
| 2344 + PRUint8 type; | |
| 2345 + PRUint32 message_length; | |
| 2346 + PRUint16 message_seq; | |
| 2347 + PRUint32 fragment_offset; | |
| 2348 + PRUint32 fragment_length; | |
| 2349 + PRUint32 offset; | |
| 2350 + | |
| 2351 + if (buf.len < 12) { | |
| 2352 + PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE); | |
| 2353 + rv = SECFailure; | |
| 2354 + break; | |
| 2355 + } | |
| 2356 + | |
| 2357 + /* Parse the header */ | |
| 2358 + type = buf.buf[0]; | |
| 2359 + message_length = (buf.buf[1] << 16) | (buf.buf[2] << 8) | buf.buf[3]; | |
| 2360 + message_seq = (buf.buf[4] << 8) | buf.buf[5]; | |
| 2361 + fragment_offset = (buf.buf[6] << 16) | (buf.buf[7] << 8) | buf.buf[8]; | |
| 2362 + fragment_length = (buf.buf[9] << 16) | (buf.buf[10] << 8) | buf.buf[11]
; | |
| 2363 + | |
| 2364 +#define MAX_HANDSHAKE_MSG_LEN 0x1ffff /* 128k - 1 */ | |
| 2365 + if (message_length > MAX_HANDSHAKE_MSG_LEN) { | |
| 2366 + (void)ssl3_DecodeError(ss); | |
| 2367 + PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); | |
| 2368 + return SECFailure; | |
| 2369 + } | |
| 2370 +#undef MAX_HANDSHAKE_MSG_LEN | |
| 2371 + | |
| 2372 + buf.buf += 12; | |
| 2373 + buf.len -= 12; | |
| 2374 + | |
| 2375 + /* This fragment must be complete */ | |
| 2376 + if (buf.len < fragment_length) { | |
| 2377 + PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE); | |
| 2378 + rv = SECFailure; | |
| 2379 + break; | |
| 2380 + } | |
| 2381 + | |
| 2382 + /* Sanity check the packet contents */ | |
| 2383 + if ((fragment_length + fragment_offset) > message_length) { | |
| 2384 + PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE); | |
| 2385 + rv = SECFailure; | |
| 2386 + break; | |
| 2387 + } | |
| 2388 + | |
| 2389 + /* There are three ways we could not be ready for this packet. | |
| 2390 + * | |
| 2391 + * 1. It's a partial next message. | |
| 2392 + * 2. It's a partial or complete message beyond the next | |
| 2393 + * 3. It's a message we've already seen | |
| 2394 + * | |
| 2395 + * If it's the complete next message we accept it right away. | |
| 2396 + * This is the common case for short messages | |
| 2397 + */ | |
| 2398 + if ((message_seq == ss->ssl3.hs.recvMessageSeq) | |
| 2399 + && (fragment_offset == 0) | |
| 2400 + && (fragment_length == message_length)) { | |
| 2401 + /* Complete next message. Process immediately */ | |
| 2402 + ss->ssl3.hs.msg_type = (SSL3HandshakeType)type; | |
| 2403 + ss->ssl3.hs.msg_len = message_length; | |
| 2404 + | |
| 2405 + /* At this point we are advancing our state machine, so | |
| 2406 + * we can free our last flight of messages */ | |
| 2407 + dtls_FreeHandshakeMessages(ss->ssl3.hs.lastMessageFlight); | |
| 2408 + ss->ssl3.hs.recvdHighWater = -1; | |
| 2409 + dtls_CancelTimer(ss); | |
| 2410 + | |
| 2411 + /* Reset the timer to the initial value if the retry counter | |
| 2412 + * is 0, per Sec. 4.2.4.1 */ | |
| 2413 + if (ss->ssl3.hs.rtRetries == 0) { | |
| 2414 + ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS; | |
| 2415 + } | |
| 2416 + | |
| 2417 + rv = ssl3_HandleHandshakeMessage(ss, buf.buf, ss->ssl3.hs.msg_len); | |
| 2418 + if (rv == SECFailure) { | |
| 2419 + /* Do not attempt to process rest of messages in this record */ | |
| 2420 + break; | |
| 2421 + } | |
| 2422 + } else { | |
| 2423 + if (message_seq < ss->ssl3.hs.recvMessageSeq) { | |
| 2424 + /* Case 3: we do an immediate retransmit if we're | |
| 2425 + * in a waiting state*/ | |
| 2426 + if (ss->ssl3.hs.rtTimerCb == NULL) { | |
| 2427 + /* Ignore */ | |
| 2428 + } else if (ss->ssl3.hs.rtTimerCb == | |
| 2429 + dtls_RetransmitTimerExpiredCb) { | |
| 2430 + SSL_TRC(30, ("%d: SSL3[%d]: Retransmit detected", | |
| 2431 + SSL_GETPID(), ss->fd)); | |
| 2432 + /* Check to see if we retransmitted recently. If so, | |
| 2433 + * suppress the triggered retransmit. This avoids | |
| 2434 + * retransmit wars after packet loss. | |
| 2435 + * This is not in RFC 5346 but should be | |
| 2436 + */ | |
| 2437 + if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) > | |
| 2438 + (ss->ssl3.hs.rtTimeoutMs / 4)) { | |
| 2439 + SSL_TRC(30, | |
| 2440 + ("%d: SSL3[%d]: Shortcutting retransmit timer", | |
| 2441 + SSL_GETPID(), ss->fd)); | |
| 2442 + | |
| 2443 + /* Cancel the timer and call the CB, | |
| 2444 + * which re-arms the timer */ | |
| 2445 + dtls_CancelTimer(ss); | |
| 2446 + dtls_RetransmitTimerExpiredCb(ss); | |
| 2447 + rv = SECSuccess; | |
| 2448 + break; | |
| 2449 + } else { | |
| 2450 + SSL_TRC(30, | |
| 2451 + ("%d: SSL3[%d]: We just retransmitted. Ignoring.", | |
| 2452 + SSL_GETPID(), ss->fd)); | |
| 2453 + rv = SECSuccess; | |
| 2454 + break; | |
| 2455 + } | |
| 2456 + } else if (ss->ssl3.hs.rtTimerCb == dtls_FinishedTimerCb) { | |
| 2457 + /* Retransmit the messages and re-arm the timer | |
| 2458 + * Note that we are not backing off the timer here. | |
| 2459 + * The spec isn't clear and my reasoning is that this | |
| 2460 + * may be a re-ordered packet rather than slowness, | |
| 2461 + * so let's be aggressive. */ | |
| 2462 + dtls_CancelTimer(ss); | |
| 2463 + rv = dtls_TransmitMessageFlight(ss); | |
| 2464 + if (rv == SECSuccess) { | |
| 2465 + rv = dtls_StartTimer(ss, dtls_FinishedTimerCb); | |
| 2466 + } | |
| 2467 + if (rv != SECSuccess) | |
| 2468 + return rv; | |
| 2469 + break; | |
| 2470 + } | |
| 2471 + } else if (message_seq > ss->ssl3.hs.recvMessageSeq) { | |
| 2472 + /* Case 2 | |
| 2473 + * | |
| 2474 + * Ignore this message. This means we don't handle out of | |
| 2475 + * order complete messages that well, but we're still | |
| 2476 + * compliant and this probably does not happen often | |
| 2477 + * | |
| 2478 + * XXX OK for now. Maybe do something smarter at some point? | |
| 2479 + */ | |
| 2480 + } else { | |
| 2481 + /* Case 1 | |
| 2482 + * | |
| 2483 + * Buffer the fragment for reassembly | |
| 2484 + */ | |
| 2485 + /* Make room for the message */ | |
| 2486 + if (ss->ssl3.hs.recvdHighWater == -1) { | |
| 2487 + PRUint32 map_length = OFFSET_BYTE(message_length) + 1; | |
| 2488 + | |
| 2489 + rv = sslBuffer_Grow(&ss->ssl3.hs.msg_body, message_length); | |
| 2490 + if (rv != SECSuccess) | |
| 2491 + break; | |
| 2492 + /* Make room for the fragment map */ | |
| 2493 + rv = sslBuffer_Grow(&ss->ssl3.hs.recvdFragments, | |
| 2494 + map_length); | |
| 2495 + if (rv != SECSuccess) | |
| 2496 + break; | |
| 2497 + | |
| 2498 + /* Reset the reassembly map */ | |
| 2499 + ss->ssl3.hs.recvdHighWater = 0; | |
| 2500 + PORT_Memset(ss->ssl3.hs.recvdFragments.buf, 0, | |
| 2501 + ss->ssl3.hs.recvdFragments.space); | |
| 2502 + ss->ssl3.hs.msg_type = (SSL3HandshakeType)type; | |
| 2503 + ss->ssl3.hs.msg_len = message_length; | |
| 2504 + } | |
| 2505 + | |
| 2506 + /* If we have a message length mismatch, abandon the reassembly | |
| 2507 + * in progress and hope that the next retransmit will give us | |
| 2508 + * something sane | |
| 2509 + */ | |
| 2510 + if (message_length != ss->ssl3.hs.msg_len) { | |
| 2511 + ss->ssl3.hs.recvdHighWater = -1; | |
| 2512 + PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE); | |
| 2513 + rv = SECFailure; | |
| 2514 + break; | |
| 2515 + } | |
| 2516 + | |
| 2517 + /* Now copy this fragment into the buffer */ | |
| 2518 + PORT_Assert((fragment_offset + fragment_length) <= | |
| 2519 + ss->ssl3.hs.msg_body.space); | |
| 2520 + PORT_Memcpy(ss->ssl3.hs.msg_body.buf + fragment_offset, | |
| 2521 + buf.buf, fragment_length); | |
| 2522 + | |
| 2523 + /* This logic is a bit tricky. We have two values for | |
| 2524 + * reassembly state: | |
| 2525 + * | |
| 2526 + * - recvdHighWater contains the highest contiguous number of | |
| 2527 + * bytes received | |
| 2528 + * - recvdFragments contains a bitmask of packets received | |
| 2529 + * above recvdHighWater | |
| 2530 + * | |
| 2531 + * This avoids having to fill in the bitmask in the common | |
| 2532 + * case of adjacent fragments received in sequence | |
| 2533 + */ | |
| 2534 + if (fragment_offset <= ss->ssl3.hs.recvdHighWater) { | |
| 2535 + /* Either this is the adjacent fragment or an overlapping | |
| 2536 + * fragment */ | |
| 2537 + ss->ssl3.hs.recvdHighWater = fragment_offset + | |
| 2538 + fragment_length; | |
| 2539 + } else { | |
| 2540 + for (offset = fragment_offset; | |
| 2541 + offset < fragment_offset + fragment_length; | |
| 2542 + offset++) { | |
| 2543 + ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] |= | |
| 2544 + OFFSET_MASK(offset); | |
| 2545 + } | |
| 2546 + } | |
| 2547 + | |
| 2548 + /* Now figure out the new high water mark if appropriate */ | |
| 2549 + for (offset = ss->ssl3.hs.recvdHighWater; | |
| 2550 + offset < ss->ssl3.hs.msg_len; offset++) { | |
| 2551 + /* Note that this loop is not efficient, since it counts | |
| 2552 + * bit by bit. If we have a lot of out-of-order packets, | |
| 2553 + * we should optimize this */ | |
| 2554 + if (ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] & | |
| 2555 + OFFSET_MASK(offset)) { | |
| 2556 + ss->ssl3.hs.recvdHighWater++; | |
| 2557 + } else { | |
| 2558 + break; | |
| 2559 + } | |
| 2560 + } | |
| 2561 + | |
| 2562 + /* If we have all the bytes, then we are good to go */ | |
| 2563 + if (ss->ssl3.hs.recvdHighWater == ss->ssl3.hs.msg_len) { | |
| 2564 + ss->ssl3.hs.recvdHighWater = -1; | |
| 2565 + | |
| 2566 + rv = ssl3_HandleHandshakeMessage(ss, | |
| 2567 + ss->ssl3.hs.msg_body.buf, | |
| 2568 + ss->ssl3.hs.msg_len); | |
| 2569 + if (rv == SECFailure) | |
| 2570 + break; /* Skip rest of record */ | |
| 2571 + | |
| 2572 + /* At this point we are advancing our state machine, so | |
| 2573 + * we can free our last flight of messages */ | |
| 2574 + dtls_FreeHandshakeMessages(ss->ssl3.hs.lastMessageFlight); | |
| 2575 + dtls_CancelTimer(ss); | |
| 2576 + | |
| 2577 + /* If there have been no retries this time, reset the | |
| 2578 + * timer value to the default per Section 4.2.4.1 */ | |
| 2579 + if (ss->ssl3.hs.rtRetries == 0) { | |
| 2580 + ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS; | |
| 2581 + } | |
| 2582 + } | |
| 2583 + } | |
| 2584 + } | |
| 2585 + | |
| 2586 + buf.buf += fragment_length; | |
| 2587 + buf.len -= fragment_length; | |
| 2588 + } | |
| 2589 + | |
| 2590 + origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */ | |
| 2591 + | |
| 2592 + /* XXX OK for now. In future handle rv == SECWouldBlock safely in order | |
| 2593 + * to deal with asynchronous certificate verification */ | |
| 2594 + return rv; | |
| 2595 +} | |
| 2596 + | |
| 2597 +/* Enqueue a message (either handshake or CCS) | |
| 2598 + * | |
| 2599 + * Called from: | |
| 2600 + * dtls_StageHandshakeMessage() | |
| 2601 + * ssl3_SendChangeCipherSpecs() | |
| 2602 + */ | |
| 2603 +SECStatus dtls_QueueMessage(sslSocket *ss, SSL3ContentType type, | |
| 2604 + const SSL3Opaque *pIn, PRInt32 nIn) | |
| 2605 +{ | |
| 2606 + SECStatus rv = SECSuccess; | |
| 2607 + DTLSQueuedMessage *msg = NULL; | |
| 2608 + | |
| 2609 + PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); | |
| 2610 + PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); | |
| 2611 + | |
| 2612 + msg = dtls_AllocQueuedMessage(ss->ssl3.cwSpec->epoch, type, pIn, nIn); | |
| 2613 + | |
| 2614 + if (!msg) { | |
| 2615 + PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 2616 + rv = SECFailure; | |
| 2617 + } else { | |
| 2618 + PR_APPEND_LINK(&msg->link, ss->ssl3.hs.lastMessageFlight); | |
| 2619 + } | |
| 2620 + | |
| 2621 + return rv; | |
| 2622 +} | |
| 2623 + | |
| 2624 +/* Add DTLS handshake message to the pending queue | |
| 2625 + * Empty the sendBuf buffer. | |
| 2626 + * This function returns SECSuccess or SECFailure, never SECWouldBlock. | |
| 2627 + * Always set sendBuf.len to 0, even when returning SECFailure. | |
| 2628 + * | |
| 2629 + * Called from: | |
| 2630 + * ssl3_AppendHandshakeHeader() | |
| 2631 + * dtls_FlushHandshake() | |
| 2632 + */ | |
| 2633 +SECStatus | |
| 2634 +dtls_StageHandshakeMessage(sslSocket *ss) | |
| 2635 +{ | |
| 2636 + SECStatus rv = SECSuccess; | |
| 2637 + | |
| 2638 + PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); | |
| 2639 + PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); | |
| 2640 + | |
| 2641 + /* This function is sometimes called when no data is actually to | |
| 2642 + * be staged, so just return SECSuccess. */ | |
| 2643 + if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len) | |
| 2644 + return rv; | |
| 2645 + | |
| 2646 + rv = dtls_QueueMessage(ss, content_handshake, | |
| 2647 + ss->sec.ci.sendBuf.buf, ss->sec.ci.sendBuf.len); | |
| 2648 + | |
| 2649 + /* Whether we succeeded or failed, toss the old handshake data. */ | |
| 2650 + ss->sec.ci.sendBuf.len = 0; | |
| 2651 + return rv; | |
| 2652 +} | |
| 2653 + | |
| 2654 +/* Enqueue the handshake message in sendBuf (if any) and then | |
| 2655 + * transmit the resulting flight of handshake messages. | |
| 2656 + * | |
| 2657 + * Called from: | |
| 2658 + * ssl3_FlushHandshake() | |
| 2659 + */ | |
| 2660 +SECStatus | |
| 2661 +dtls_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags) | |
| 2662 +{ | |
| 2663 + SECStatus rv = SECSuccess; | |
| 2664 + | |
| 2665 + PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); | |
| 2666 + PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); | |
| 2667 + | |
| 2668 + rv = dtls_StageHandshakeMessage(ss); | |
| 2669 + if (rv != SECSuccess) | |
| 2670 + return rv; | |
| 2671 + | |
| 2672 + if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) { | |
| 2673 + rv = dtls_TransmitMessageFlight(ss); | |
| 2674 + if (rv != SECSuccess) | |
| 2675 + return rv; | |
| 2676 + | |
| 2677 + if (!(flags & ssl_SEND_FLAG_NO_RETRANSMIT)) { | |
| 2678 + ss->ssl3.hs.rtRetries = 0; | |
| 2679 + rv = dtls_StartTimer(ss, dtls_RetransmitTimerExpiredCb); | |
| 2680 + } | |
| 2681 + } | |
| 2682 + | |
| 2683 + return rv; | |
| 2684 +} | |
| 2685 + | |
| 2686 +/* The callback for when the retransmit timer expires | |
| 2687 + * | |
| 2688 + * Called from: | |
| 2689 + * dtls_CheckTimer() | |
| 2690 + * dtls_HandleHandshake() | |
| 2691 + */ | |
| 2692 +static void | |
| 2693 +dtls_RetransmitTimerExpiredCb(sslSocket *ss) | |
| 2694 +{ | |
| 2695 + SECStatus rv = SECFailure; | |
| 2696 + | |
| 2697 + ss->ssl3.hs.rtRetries++; | |
| 2698 + | |
| 2699 + if (!(ss->ssl3.hs.rtRetries % 3)) { | |
| 2700 + /* If one of the messages was potentially greater than > MTU, | |
| 2701 + * then downgrade. Do this every time we have retransmitted a | |
| 2702 + * message twice, per RFC 6347 Sec. 4.1.1 */ | |
| 2703 + dtls_SetMTU(ss, ss->ssl3.hs.maxMessageSent - 1); | |
| 2704 + } | |
| 2705 + | |
| 2706 + rv = dtls_TransmitMessageFlight(ss); | |
| 2707 + if (rv == SECSuccess) { | |
| 2708 + | |
| 2709 + /* Re-arm the timer */ | |
| 2710 + rv = dtls_RestartTimer(ss, PR_TRUE, dtls_RetransmitTimerExpiredCb); | |
| 2711 + } | |
| 2712 + | |
| 2713 + if (rv == SECFailure) { | |
| 2714 + /* XXX OK for now. In future maybe signal the stack that we couldn't | |
| 2715 + * transmit. For now, let the read handle any real network errors */ | |
| 2716 + } | |
| 2717 +} | |
| 2718 + | |
| 2719 +/* Transmit a flight of handshake messages, stuffing them | |
| 2720 + * into as few records as seems reasonable | |
| 2721 + * | |
| 2722 + * Called from: | |
| 2723 + * dtls_FlushHandshake() | |
| 2724 + * dtls_RetransmitTimerExpiredCb() | |
| 2725 + */ | |
| 2726 +static SECStatus | |
| 2727 +dtls_TransmitMessageFlight(sslSocket *ss) | |
| 2728 +{ | |
| 2729 + SECStatus rv = SECSuccess; | |
| 2730 + PRCList *msg_p; | |
| 2731 + PRUint16 room_left = ss->ssl3.mtu; | |
| 2732 + PRInt32 sent; | |
| 2733 + | |
| 2734 + ssl_GetXmitBufLock(ss); | |
| 2735 + ssl_GetSpecReadLock(ss); | |
| 2736 + | |
| 2737 + /* DTLS does not buffer its handshake messages in | |
| 2738 + * ss->pendingBuf, but rather in the lastMessageFlight | |
| 2739 + * structure. This is just a sanity check that | |
| 2740 + * some programming error hasn't inadvertantly | |
| 2741 + * stuffed something in ss->pendingBuf | |
| 2742 + */ | |
| 2743 + PORT_Assert(!ss->pendingBuf.len); | |
| 2744 + for (msg_p = PR_LIST_HEAD(ss->ssl3.hs.lastMessageFlight); | |
| 2745 + msg_p != ss->ssl3.hs.lastMessageFlight; | |
| 2746 + msg_p = PR_NEXT_LINK(msg_p)) { | |
| 2747 + DTLSQueuedMessage *msg = (DTLSQueuedMessage *)msg_p; | |
| 2748 + | |
| 2749 + /* The logic here is: | |
| 2750 + * | |
| 2751 + * 1. If this is a message that will not fit into the remaining | |
| 2752 + * space, then flush. | |
| 2753 + * 2. If the message will now fit into the remaining space, | |
| 2754 + * encrypt, buffer, and loop. | |
| 2755 + * 3. If the message will not fit, then fragment. | |
| 2756 + * | |
| 2757 + * At the end of the function, flush. | |
| 2758 + */ | |
| 2759 + if ((msg->len + SSL3_BUFFER_FUDGE) > room_left) { | |
| 2760 + /* The message will not fit into the remaining space, so flush */ | |
| 2761 + rv = dtls_SendSavedWriteData(ss); | |
| 2762 + if (rv != SECSuccess) | |
| 2763 + break; | |
| 2764 + | |
| 2765 + room_left = ss->ssl3.mtu; | |
| 2766 + } | |
| 2767 + | |
| 2768 + if ((msg->len + SSL3_BUFFER_FUDGE) <= room_left) { | |
| 2769 + /* The message will fit, so encrypt and then continue with the | |
| 2770 + * next packet */ | |
| 2771 + sent = ssl3_SendRecord(ss, msg->epoch, msg->type, | |
| 2772 + msg->data, msg->len, | |
| 2773 + ssl_SEND_FLAG_FORCE_INTO_BUFFER | | |
| 2774 + ssl_SEND_FLAG_USE_EPOCH); | |
| 2775 + if (sent != msg->len) { | |
| 2776 + rv = SECFailure; | |
| 2777 + if (sent != -1) { | |
| 2778 + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
| 2779 + } | |
| 2780 + break; | |
| 2781 + } | |
| 2782 + | |
| 2783 + room_left = ss->ssl3.mtu - ss->pendingBuf.len; | |
| 2784 + } else { | |
| 2785 + /* The message will not fit, so fragment. | |
| 2786 + * | |
| 2787 + * XXX OK for now. Arrange to coalesce the last fragment | |
| 2788 + * of this message with the next message if possible. | |
| 2789 + * That would be more efficient. | |
| 2790 + */ | |
| 2791 + PRUint32 fragment_offset = 0; | |
| 2792 + unsigned char fragment[DTLS_MAX_MTU]; /* >= than largest | |
| 2793 + * plausible MTU */ | |
| 2794 + | |
| 2795 + /* Assert that we have already flushed */ | |
| 2796 + PORT_Assert(room_left == ss->ssl3.mtu); | |
| 2797 + | |
| 2798 + /* Case 3: We now need to fragment this message | |
| 2799 + * DTLS only supports fragmenting handshaking messages */ | |
| 2800 + PORT_Assert(msg->type == content_handshake); | |
| 2801 + | |
| 2802 + /* The headers consume 12 bytes so the smalles possible | |
| 2803 + * message (i.e., an empty one) is 12 bytes | |
| 2804 + */ | |
| 2805 + PORT_Assert(msg->len >= 12); | |
| 2806 + | |
| 2807 + while ((fragment_offset + 12) < msg->len) { | |
| 2808 + PRUint32 fragment_len; | |
| 2809 + const unsigned char *content = msg->data + 12; | |
| 2810 + PRUint32 content_len = msg->len - 12; | |
| 2811 + | |
| 2812 + /* The reason we use 8 here is that that's the length of | |
| 2813 + * the new DTLS data that we add to the header */ | |
| 2814 + fragment_len = PR_MIN(room_left - (SSL3_BUFFER_FUDGE + 8), | |
| 2815 + content_len - fragment_offset); | |
| 2816 + PORT_Assert(fragment_len < DTLS_MAX_MTU - 12); | |
| 2817 + /* Make totally sure that we are within the buffer. | |
| 2818 + * Note that the only way that fragment len could get | |
| 2819 + * adjusted here is if | |
| 2820 + * | |
| 2821 + * (a) we are in release mode so the PORT_Assert is compiled out | |
| 2822 + * (b) either the MTU table is inconsistent with DTLS_MAX_MTU | |
| 2823 + * or ss->ssl3.mtu has become corrupt. | |
| 2824 + */ | |
| 2825 + fragment_len = PR_MIN(fragment_len, DTLS_MAX_MTU - 12); | |
| 2826 + | |
| 2827 + /* Construct an appropriate-sized fragment */ | |
| 2828 + /* Type, length, sequence */ | |
| 2829 + PORT_Memcpy(fragment, msg->data, 6); | |
| 2830 + | |
| 2831 + /* Offset */ | |
| 2832 + fragment[6] = (fragment_offset >> 16) & 0xff; | |
| 2833 + fragment[7] = (fragment_offset >> 8) & 0xff; | |
| 2834 + fragment[8] = (fragment_offset) & 0xff; | |
| 2835 + | |
| 2836 + /* Fragment length */ | |
| 2837 + fragment[9] = (fragment_len >> 16) & 0xff; | |
| 2838 + fragment[10] = (fragment_len >> 8) & 0xff; | |
| 2839 + fragment[11] = (fragment_len) & 0xff; | |
| 2840 + | |
| 2841 + PORT_Memcpy(fragment + 12, content + fragment_offset, | |
| 2842 + fragment_len); | |
| 2843 + | |
| 2844 + /* | |
| 2845 + * Send the record. We do this in two stages | |
| 2846 + * 1. Encrypt | |
| 2847 + */ | |
| 2848 + sent = ssl3_SendRecord(ss, msg->epoch, msg->type, | |
| 2849 + fragment, fragment_len + 12, | |
| 2850 + ssl_SEND_FLAG_FORCE_INTO_BUFFER | | |
| 2851 + ssl_SEND_FLAG_USE_EPOCH); | |
| 2852 + if (sent != (fragment_len + 12)) { | |
| 2853 + rv = SECFailure; | |
| 2854 + if (sent != -1) { | |
| 2855 + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
| 2856 + } | |
| 2857 + break; | |
| 2858 + } | |
| 2859 + | |
| 2860 + /* 2. Flush */ | |
| 2861 + rv = dtls_SendSavedWriteData(ss); | |
| 2862 + if (rv != SECSuccess) | |
| 2863 + break; | |
| 2864 + | |
| 2865 + fragment_offset += fragment_len; | |
| 2866 + } | |
| 2867 + } | |
| 2868 + } | |
| 2869 + | |
| 2870 + /* Finally, we need to flush */ | |
| 2871 + if (rv == SECSuccess) | |
| 2872 + rv = dtls_SendSavedWriteData(ss); | |
| 2873 + | |
| 2874 + /* Give up the locks */ | |
| 2875 + ssl_ReleaseSpecReadLock(ss); | |
| 2876 + ssl_ReleaseXmitBufLock(ss); | |
| 2877 + | |
| 2878 + return rv; | |
| 2879 +} | |
| 2880 + | |
| 2881 +/* Flush the data in the pendingBuf and update the max message sent | |
| 2882 + * so we can adjust the MTU estimate if we need to. | |
| 2883 + * Wrapper for ssl_SendSavedWriteData. | |
| 2884 + * | |
| 2885 + * Called from dtls_TransmitMessageFlight() | |
| 2886 + */ | |
| 2887 +static | |
| 2888 +SECStatus dtls_SendSavedWriteData(sslSocket *ss) | |
| 2889 +{ | |
| 2890 + PRInt32 sent; | |
| 2891 + | |
| 2892 + sent = ssl_SendSavedWriteData(ss); | |
| 2893 + if (sent < 0) | |
| 2894 + return SECFailure; | |
| 2895 + | |
| 2896 + /* We should always have complete writes b/c datagram sockets | |
| 2897 + * don't really block */ | |
| 2898 + if (ss->pendingBuf.len > 0) { | |
| 2899 + ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE); | |
| 2900 + return SECFailure; | |
| 2901 + } | |
| 2902 + | |
| 2903 + /* Update the largest message sent so we can adjust the MTU | |
| 2904 + * estimate if necessary */ | |
| 2905 + if (sent > ss->ssl3.hs.maxMessageSent) | |
| 2906 + ss->ssl3.hs.maxMessageSent = sent; | |
| 2907 + | |
| 2908 + return SECSuccess; | |
| 2909 +} | |
| 2910 + | |
| 2911 +/* Compress, MAC, encrypt a DTLS record. Allows specification of | |
| 2912 + * the epoch using epoch value. If use_epoch is PR_TRUE then | |
| 2913 + * we use the provided epoch. If use_epoch is PR_FALSE then | |
| 2914 + * whatever the current value is in effect is used. | |
| 2915 + * | |
| 2916 + * Called from ssl3_SendRecord() | |
| 2917 + */ | |
| 2918 +SECStatus | |
| 2919 +dtls_CompressMACEncryptRecord(sslSocket * ss, | |
| 2920 + DTLSEpoch epoch, | |
| 2921 + PRBool use_epoch, | |
| 2922 + SSL3ContentType type, | |
| 2923 + const SSL3Opaque * pIn, | |
| 2924 + PRUint32 contentLen, | |
| 2925 + sslBuffer * wrBuf) | |
| 2926 +{ | |
| 2927 + SECStatus rv = SECFailure; | |
| 2928 + ssl3CipherSpec * cwSpec; | |
| 2929 + | |
| 2930 + ssl_GetSpecReadLock(ss); /********************************/ | |
| 2931 + | |
| 2932 + /* The reason for this switch-hitting code is that we might have | |
| 2933 + * a flight of records spanning an epoch boundary, e.g., | |
| 2934 + * | |
| 2935 + * ClientKeyExchange (epoch = 0) | |
| 2936 + * ChangeCipherSpec (epoch = 0) | |
| 2937 + * Finished (epoch = 1) | |
| 2938 + * | |
| 2939 + * Thus, each record needs a different cipher spec. The information | |
| 2940 + * about which epoch to use is carried with the record. | |
| 2941 + */ | |
| 2942 + if (use_epoch) { | |
| 2943 + if (ss->ssl3.cwSpec->epoch == epoch) | |
| 2944 + cwSpec = ss->ssl3.cwSpec; | |
| 2945 + else if (ss->ssl3.pwSpec->epoch == epoch) | |
| 2946 + cwSpec = ss->ssl3.pwSpec; | |
| 2947 + else | |
| 2948 + cwSpec = NULL; | |
| 2949 + } else { | |
| 2950 + cwSpec = ss->ssl3.cwSpec; | |
| 2951 + } | |
| 2952 + | |
| 2953 + if (cwSpec) { | |
| 2954 + rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer, PR_TRUE, | |
| 2955 + type, pIn, contentLen, wrBuf); | |
| 2956 + } else { | |
| 2957 + PR_NOT_REACHED("Couldn't find a cipher spec matching epoch"); | |
| 2958 + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
| 2959 + } | |
| 2960 + ssl_ReleaseSpecReadLock(ss); /************************************/ | |
| 2961 + | |
| 2962 + return rv; | |
| 2963 +} | |
| 2964 + | |
| 2965 +/* Start a timer | |
| 2966 + * | |
| 2967 + * Called from: | |
| 2968 + * dtls_HandleHandshake() | |
| 2969 + * dtls_FlushHAndshake() | |
| 2970 + * dtls_RestartTimer() | |
| 2971 + */ | |
| 2972 +SECStatus | |
| 2973 +dtls_StartTimer(sslSocket *ss, DTLSTimerCb cb) | |
| 2974 +{ | |
| 2975 + PORT_Assert(ss->ssl3.hs.rtTimerCb == NULL); | |
| 2976 + | |
| 2977 + ss->ssl3.hs.rtTimerStarted = PR_IntervalNow(); | |
| 2978 + ss->ssl3.hs.rtTimerCb = cb; | |
| 2979 + | |
| 2980 + return SECSuccess; | |
| 2981 +} | |
| 2982 + | |
| 2983 +/* Restart a timer with optional backoff | |
| 2984 + * | |
| 2985 + * Called from dtls_RetransmitTimerExpiredCb() | |
| 2986 + */ | |
| 2987 +SECStatus | |
| 2988 +dtls_RestartTimer(sslSocket *ss, PRBool backoff, DTLSTimerCb cb) | |
| 2989 +{ | |
| 2990 + if (backoff) { | |
| 2991 + ss->ssl3.hs.rtTimeoutMs *= 2; | |
| 2992 + if (ss->ssl3.hs.rtTimeoutMs > MAX_DTLS_TIMEOUT_MS) | |
| 2993 + ss->ssl3.hs.rtTimeoutMs = MAX_DTLS_TIMEOUT_MS; | |
| 2994 + } | |
| 2995 + | |
| 2996 + return dtls_StartTimer(ss, cb); | |
| 2997 +} | |
| 2998 + | |
| 2999 +/* Cancel a pending timer | |
| 3000 + * | |
| 3001 + * Called from: | |
| 3002 + * dtls_HandleHandshake() | |
| 3003 + * dtls_CheckTimer() | |
| 3004 + */ | |
| 3005 +void | |
| 3006 +dtls_CancelTimer(sslSocket *ss) | |
| 3007 +{ | |
| 3008 + PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); | |
| 3009 + | |
| 3010 + ss->ssl3.hs.rtTimerCb = NULL; | |
| 3011 +} | |
| 3012 + | |
| 3013 +/* Check the pending timer and fire the callback if it expired | |
| 3014 + * | |
| 3015 + * Called from ssl3_GatherCompleteHandshake() | |
| 3016 + */ | |
| 3017 +void | |
| 3018 +dtls_CheckTimer(sslSocket *ss) | |
| 3019 +{ | |
| 3020 + if (!ss->ssl3.hs.rtTimerCb) | |
| 3021 + return; | |
| 3022 + | |
| 3023 + if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) > | |
| 3024 + PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs)) { | |
| 3025 + /* Timer has expired */ | |
| 3026 + DTLSTimerCb cb = ss->ssl3.hs.rtTimerCb; | |
| 3027 + | |
| 3028 + /* Cancel the timer so that we can call the CB safely */ | |
| 3029 + dtls_CancelTimer(ss); | |
| 3030 + | |
| 3031 + /* Now call the CB */ | |
| 3032 + cb(ss); | |
| 3033 + } | |
| 3034 +} | |
| 3035 + | |
| 3036 +/* The callback to fire when the holddown timer for the Finished | |
| 3037 + * message expires and we can delete it | |
| 3038 + * | |
| 3039 + * Called from dtls_CheckTimer() | |
| 3040 + */ | |
| 3041 +void | |
| 3042 +dtls_FinishedTimerCb(sslSocket *ss) | |
| 3043 +{ | |
| 3044 + ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE); | |
| 3045 +} | |
| 3046 + | |
| 3047 +/* Cancel the Finished hold-down timer and destroy the | |
| 3048 + * pending cipher spec. Note that this means that | |
| 3049 + * successive rehandshakes will fail if the Finished is | |
| 3050 + * lost. | |
| 3051 + * | |
| 3052 + * XXX OK for now. Figure out how to handle the combination | |
| 3053 + * of Finished lost and rehandshake | |
| 3054 + */ | |
| 3055 +void | |
| 3056 +dtls_RehandshakeCleanup(sslSocket *ss) | |
| 3057 +{ | |
| 3058 + dtls_CancelTimer(ss); | |
| 3059 + ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE); | |
| 3060 + ss->ssl3.hs.sendMessageSeq = 0; | |
| 3061 + ss->ssl3.hs.recvMessageSeq = 0; | |
| 3062 +} | |
| 3063 + | |
| 3064 +/* Set the MTU to the next step less than or equal to the | |
| 3065 + * advertised value. Also used to downgrade the MTU by | |
| 3066 + * doing dtls_SetMTU(ss, biggest packet set). | |
| 3067 + * | |
| 3068 + * Passing 0 means set this to the largest MTU known | |
| 3069 + * (effectively resetting the PMTU backoff value). | |
| 3070 + * | |
| 3071 + * Called by: | |
| 3072 + * ssl3_InitState() | |
| 3073 + * dtls_RetransmitTimerExpiredCb() | |
| 3074 + */ | |
| 3075 +void | |
| 3076 +dtls_SetMTU(sslSocket *ss, PRUint16 advertised) | |
| 3077 +{ | |
| 3078 + int i; | |
| 3079 + | |
| 3080 + if (advertised == 0) { | |
| 3081 + ss->ssl3.mtu = COMMON_MTU_VALUES[0]; | |
| 3082 + SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu)); | |
| 3083 + return; | |
| 3084 + } | |
| 3085 + | |
| 3086 + for (i = 0; i < PR_ARRAY_SIZE(COMMON_MTU_VALUES); i++) { | |
| 3087 + if (COMMON_MTU_VALUES[i] <= advertised) { | |
| 3088 + ss->ssl3.mtu = COMMON_MTU_VALUES[i]; | |
| 3089 + SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu)); | |
| 3090 + return; | |
| 3091 + } | |
| 3092 + } | |
| 3093 + | |
| 3094 + /* Fallback */ | |
| 3095 + ss->ssl3.mtu = COMMON_MTU_VALUES[PR_ARRAY_SIZE(COMMON_MTU_VALUES)-1]; | |
| 3096 + SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu)); | |
| 3097 +} | |
| 3098 + | |
| 3099 +/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a | |
| 3100 + * DTLS hello_verify_request | |
| 3101 + * Caller must hold Handshake and RecvBuf locks. | |
| 3102 + */ | |
| 3103 +SECStatus | |
| 3104 +dtls_HandleHelloVerifyRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) | |
| 3105 +{ | |
| 3106 + int errCode = SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_RE
QUEST; | |
| 3107 + SECStatus rv; | |
| 3108 + PRInt32 temp; | |
| 3109 + SECItem cookie = {siBuffer, NULL, 0}; | |
| 3110 + SSL3AlertDescription desc = illegal_parameter; | |
| 3111 + | |
| 3112 + SSL_TRC(3, ("%d: SSL3[%d]: handle hello_verify_request handshake", | |
| 3113 + SSL_GETPID(), ss->fd)); | |
| 3114 + PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); | |
| 3115 + PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); | |
| 3116 + | |
| 3117 + if (ss->ssl3.hs.ws != wait_server_hello) { | |
| 3118 + errCode = SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST; | |
| 3119 + desc = unexpected_message; | |
| 3120 + goto alert_loser; | |
| 3121 + } | |
| 3122 + | |
| 3123 + /* The version */ | |
| 3124 + temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); | |
| 3125 + if (temp < 0) { | |
| 3126 + goto loser; /* alert has been sent */ | |
| 3127 + } | |
| 3128 + | |
| 3129 + if (temp != SSL_LIBRARY_VERSION_DTLS_1_0_WIRE) { | |
| 3130 + /* Note: this will need adjustment for DTLS 1.2 per Section 4.2.1 */ | |
| 3131 + goto alert_loser; | |
| 3132 + } | |
| 3133 + | |
| 3134 + /* The cookie */ | |
| 3135 + rv = ssl3_ConsumeHandshakeVariable(ss, &cookie, 1, &b, &length); | |
| 3136 + if (rv != SECSuccess) { | |
| 3137 + goto loser; /* alert has been sent */ | |
| 3138 + } | |
| 3139 + if (cookie.len > DTLS_COOKIE_BYTES) { | |
| 3140 + desc = decode_error; | |
| 3141 + goto alert_loser; /* malformed. */ | |
| 3142 + } | |
| 3143 + | |
| 3144 + PORT_Memcpy(ss->ssl3.hs.cookie, cookie.data, cookie.len); | |
| 3145 + ss->ssl3.hs.cookieLen = cookie.len; | |
| 3146 + | |
| 3147 + | |
| 3148 + ssl_GetXmitBufLock(ss); /*******************************/ | |
| 3149 + | |
| 3150 + /* Now re-send the client hello */ | |
| 3151 + rv = ssl3_SendClientHello(ss, PR_TRUE); | |
| 3152 + | |
| 3153 + ssl_ReleaseXmitBufLock(ss); /*******************************
/ | |
| 3154 + | |
| 3155 + if (rv == SECSuccess) | |
| 3156 + return rv; | |
| 3157 + | |
| 3158 +alert_loser: | |
| 3159 + (void)SSL3_SendAlert(ss, alert_fatal, desc); | |
| 3160 + | |
| 3161 +loser: | |
| 3162 + errCode = ssl_MapLowLevelError(errCode); | |
| 3163 + return SECFailure; | |
| 3164 +} | |
| 3165 + | |
| 3166 +/* Initialize the DTLS anti-replay window | |
| 3167 + * | |
| 3168 + * Called from: | |
| 3169 + * ssl3_SetupPendingCipherSpec() | |
| 3170 + * ssl3_InitCipherSpec() | |
| 3171 + */ | |
| 3172 +void | |
| 3173 +dtls_InitRecvdRecords(DTLSRecvdRecords *records) | |
| 3174 +{ | |
| 3175 + PORT_Memset(records->data, 0, sizeof(records->data)); | |
| 3176 + records->left = 0; | |
| 3177 + records->right = DTLS_RECVD_RECORDS_WINDOW - 1; | |
| 3178 +} | |
| 3179 + | |
| 3180 +/* | |
| 3181 + * Has this DTLS record been received? Return values are: | |
| 3182 + * -1 -- out of range to the left | |
| 3183 + * 0 -- not received yet | |
| 3184 + * 1 -- replay | |
| 3185 + * | |
| 3186 + * Called from: dtls_HandleRecord() | |
| 3187 + */ | |
| 3188 +int | |
| 3189 +dtls_RecordGetRecvd(DTLSRecvdRecords *records, PRUint64 seq) | |
| 3190 +{ | |
| 3191 + PRUint64 offset; | |
| 3192 + | |
| 3193 + /* Out of range to the left */ | |
| 3194 + if (seq < records->left) { | |
| 3195 + return -1; | |
| 3196 + } | |
| 3197 + | |
| 3198 + /* Out of range to the right; since we advance the window on | |
| 3199 + * receipt, that means that this packet has not been received | |
| 3200 + * yet */ | |
| 3201 + if (seq > records->right) | |
| 3202 + return 0; | |
| 3203 + | |
| 3204 + offset = seq % DTLS_RECVD_RECORDS_WINDOW; | |
| 3205 + | |
| 3206 + return !!(records->data[offset / 8] & (1 << (offset % 8))); | |
| 3207 +} | |
| 3208 + | |
| 3209 +/* Update the DTLS anti-replay window | |
| 3210 + * | |
| 3211 + * Called from ssl3_HandleRecord() | |
| 3212 + */ | |
| 3213 +void | |
| 3214 +dtls_RecordSetRecvd(DTLSRecvdRecords *records, PRUint64 seq) | |
| 3215 +{ | |
| 3216 + PRUint64 offset; | |
| 3217 + | |
| 3218 + if (seq < records->left) | |
| 3219 + return; | |
| 3220 + | |
| 3221 + if (seq > records->right) { | |
| 3222 + PRUint64 new_left; | |
| 3223 + PRUint64 new_right; | |
| 3224 + PRUint64 right; | |
| 3225 + | |
| 3226 + /* Slide to the right; this is the tricky part | |
| 3227 + * | |
| 3228 + * 1. new_top is set to have room for seq, on the | |
| 3229 + * next byte boundary by setting the right 8 | |
| 3230 + * bits of seq | |
| 3231 + * 2. new_left is set to compensate. | |
| 3232 + * 3. Zero all bits between top and new_top. Since | |
| 3233 + * this is a ring, this zeroes everything as-yet | |
| 3234 + * unseen. Because we always operate on byte | |
| 3235 + * boundaries, we can zero one byte at a time | |
| 3236 + */ | |
| 3237 + new_right = seq | 0x07; | |
| 3238 + new_left = (new_right - DTLS_RECVD_RECORDS_WINDOW) + 1; | |
| 3239 + | |
| 3240 + for (right = records->right + 8; right <= new_right; right += 8) { | |
| 3241 + offset = right % DTLS_RECVD_RECORDS_WINDOW; | |
| 3242 + records->data[offset / 8] = 0; | |
| 3243 + } | |
| 3244 + | |
| 3245 + records->right = new_right; | |
| 3246 + records->left = new_left; | |
| 3247 + } | |
| 3248 + | |
| 3249 + offset = seq % DTLS_RECVD_RECORDS_WINDOW; | |
| 3250 + | |
| 3251 + records->data[offset / 8] |= (1 << (offset % 8)); | |
| 3252 +} | |
| 3253 + | |
| 3254 +SECStatus | |
| 3255 +DTLS_GetHandshakeTimeout(PRFileDesc *socket, PRIntervalTime *timeout) | |
| 3256 +{ | |
| 3257 + sslSocket * ss = NULL; | |
| 3258 + PRIntervalTime elapsed; | |
| 3259 + PRIntervalTime desired; | |
| 3260 + | |
| 3261 + ss = ssl_FindSocket(socket); | |
| 3262 + | |
| 3263 + if (!ss) | |
| 3264 + return SECFailure; | |
| 3265 + | |
| 3266 + if (!IS_DTLS(ss)) | |
| 3267 + return SECFailure; | |
| 3268 + | |
| 3269 + if (!ss->ssl3.hs.rtTimerCb) | |
| 3270 + return SECFailure; | |
| 3271 + | |
| 3272 + elapsed = PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted; | |
| 3273 + desired = PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs); | |
| 3274 + if (elapsed > desired) { | |
| 3275 + /* Timer expired */ | |
| 3276 + *timeout = PR_INTERVAL_NO_WAIT; | |
| 3277 + } else { | |
| 3278 + *timeout = desired - elapsed; | |
| 3279 + } | |
| 3280 + | |
| 3281 + return SECSuccess; | |
| 3282 +} | |
| 3283 | |
| 3284 Property changes on: net/third_party/nss/ssl/dtls1con.c | |
| 3285 ___________________________________________________________________ | |
| 3286 Added: svn:eol-style | |
| 3287 + LF | |
| 3288 | |
| 3289 Index: net/third_party/nss/ssl/sslproto.h | |
| 3290 =================================================================== | |
| 3291 --- net/third_party/nss/ssl/sslproto.h (revision 127709) | |
| 3292 +++ net/third_party/nss/ssl/sslproto.h (working copy) | |
| 3293 @@ -49,10 +49,15 @@ | |
| 3294 #define SSL_LIBRARY_VERSION_3_0 0x0300 | |
| 3295 #define SSL_LIBRARY_VERSION_TLS_1_0 0x0301 | |
| 3296 #define SSL_LIBRARY_VERSION_TLS_1_1 0x0302 | |
| 3297 +/* Note: this is the internal format, not the wire format */ | |
| 3298 +#define SSL_LIBRARY_VERSION_DTLS_1_0 0x0302 | |
| 3299 | |
| 3300 /* deprecated old name */ | |
| 3301 #define SSL_LIBRARY_VERSION_3_1_TLS SSL_LIBRARY_VERSION_TLS_1_0 | |
| 3302 | |
| 3303 +/* The DTLS version used in the spec */ | |
| 3304 +#define SSL_LIBRARY_VERSION_DTLS_1_0_WIRE ((~0x0100) & 0xffff) | |
| 3305 + | |
| 3306 /* Header lengths of some of the messages */ | |
| 3307 #define SSL_HL_ERROR_HBYTES 3 | |
| 3308 #define SSL_HL_CLIENT_HELLO_HBYTES 9 | |
| 3309 Index: net/third_party/nss/ssl/sslt.h | |
| 3310 =================================================================== | |
| 3311 --- net/third_party/nss/ssl/sslt.h (revision 127709) | |
| 3312 +++ net/third_party/nss/ssl/sslt.h (working copy) | |
| 3313 @@ -190,7 +190,8 @@ | |
| 3314 } SSLCipherSuiteInfo; | |
| 3315 | |
| 3316 typedef enum { | |
| 3317 - ssl_variant_stream = 0 | |
| 3318 + ssl_variant_stream = 0, | |
| 3319 + ssl_variant_datagram = 1 | |
| 3320 } SSLProtocolVariant; | |
| 3321 | |
| 3322 typedef struct SSLVersionRangeStr { | |
| OLD | NEW |