1 diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c 2 --- a/nss/lib/ssl/ssl3con.c 2014-01-17 18:46:51.999581198 -0800 3 +++ b/nss/lib/ssl/ssl3con.c 2014-01-17 18:47:05.509804656 -0800 4 @@ -3473,6 +3473,9 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffe 5 case certificate_unknown: error = SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT; 6 break; 7 case illegal_parameter: error = SSL_ERROR_ILLEGAL_PARAMETER_ALERT;break; 8 + case inappropriate_fallback: 9 + error = SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT; 10 + break; 11 12 /* All alerts below are TLS only. */ 13 case unknown_ca: error = SSL_ERROR_UNKNOWN_CA_ALERT; break; 14 @@ -4986,6 +4989,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBo 15 int num_suites; 16 int actual_count = 0; 17 PRBool isTLS = PR_FALSE; 18 + PRBool requestingResume = PR_FALSE, fallbackSCSV = PR_FALSE; 19 PRInt32 total_exten_len = 0; 20 unsigned paddingExtensionLen; 21 unsigned numCompressionMethods; 22 @@ -5128,6 +5132,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBo 23 } 24 25 if (sid) { 26 + requestingResume = PR_TRUE; 27 SSL_AtomicIncrementLong(& ssl3stats.sch_sid_cache_hits ); 28 29 PRINT_BUF(4, (ss, "client, found session-id:", sid->u.ssl3.sessionID, 30 @@ -5246,8 +5251,15 @@ ssl3_SendClientHello(sslSocket *ss, PRBo 31 if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } 32 return SECFailure; /* count_cipher_suites has set error code. */ 33 } 34 + 35 + fallbackSCSV = ss->opt.enableFallbackSCSV && (!requestingResume || 36 + ss->version < sid->version); 37 + /* make room for SCSV */ 38 if (ss->ssl3.hs.sendingSCSV) { 39 - ++num_suites; /* make room for SCSV */ 40 + ++num_suites; 41 + } 42 + if (fallbackSCSV) { 43 + ++num_suites; 44 } 45 46 /* count compression methods */ 47 @@ -5353,6 +5365,15 @@ ssl3_SendClientHello(sslSocket *ss, PRBo 48 } 49 actual_count++; 50 } 51 + if (fallbackSCSV) { 52 + rv = ssl3_AppendHandshakeNumber(ss, TLS_FALLBACK_SCSV, 53 + sizeof(ssl3CipherSuite)); 54 + if (rv != SECSuccess) { 55 + if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } 56 + return rv; /* err set by ssl3_AppendHandshake* */ 57 + } 58 + actual_count++; 59 + } 60 for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) { 61 ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i]; 62 if (config_match(suite, ss->ssl3.policy, PR_TRUE, &ss->vrange)) { 63 @@ -8084,6 +8105,19 @@ ssl3_HandleClientHello(sslSocket *ss, SS 64 goto loser; /* malformed */ 65 } 66 67 + /* If the ClientHello version is less than our maximum version, check for a 68 + * TLS_FALLBACK_SCSV and reject the connection if found. */ 69 + if (ss->vrange.max > ss->clientHelloVersion) { 70 + for (i = 0; i + 1 < suites.len; i += 2) { 71 + PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1]; 72 + if (suite_i != TLS_FALLBACK_SCSV) 73 + continue; 74 + desc = inappropriate_fallback; 75 + errCode = SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT; 76 + goto alert_loser; 77 + } 78 + } 79 + 80 /* grab the list of compression methods. */ 81 rv = ssl3_ConsumeHandshakeVariable(ss, &comps, 1, &b, &length); 82 if (rv != SECSuccess) { 83 diff -pu a/nss/lib/ssl/ssl3prot.h b/nss/lib/ssl/ssl3prot.h 84 --- a/nss/lib/ssl/ssl3prot.h 2014-01-17 17:59:03.242109996 -0800 85 +++ b/nss/lib/ssl/ssl3prot.h 2014-01-17 18:47:05.509804656 -0800 86 @@ -98,6 +98,7 @@ typedef enum { 87 protocol_version = 70, 88 insufficient_security = 71, 89 internal_error = 80, 90 + inappropriate_fallback = 86, /* could also be sent for SSLv3 */ 91 user_canceled = 90, 92 no_renegotiation = 100, 93 94 diff -pu a/nss/lib/ssl/sslerr.h b/nss/lib/ssl/sslerr.h 95 --- a/nss/lib/ssl/sslerr.h 2014-01-17 17:59:03.242109996 -0800 96 +++ b/nss/lib/ssl/sslerr.h 2014-01-17 18:47:05.509804656 -0800 97 @@ -196,6 +196,7 @@ SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM 98 SSL_ERROR_BAD_CHANNEL_ID_DATA = (SSL_ERROR_BASE + 129), 99 SSL_ERROR_INVALID_CHANNEL_ID_KEY = (SSL_ERROR_BASE + 130), 100 SSL_ERROR_GET_CHANNEL_ID_FAILED = (SSL_ERROR_BASE + 131), 101 +SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT = (SSL_ERROR_BASE + 132), 102 103 SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */ 104 } SSLErrorCodes; 105 diff -pu a/nss/lib/ssl/SSLerrs.h b/nss/lib/ssl/SSLerrs.h 106 --- a/nss/lib/ssl/SSLerrs.h 2014-01-17 17:59:03.242109996 -0800 107 +++ b/nss/lib/ssl/SSLerrs.h 2014-01-17 18:47:05.509804656 -0800 108 @@ -421,3 +421,8 @@ ER3(SSL_ERROR_INVALID_CHANNEL_ID_KEY, (S 109 110 ER3(SSL_ERROR_GET_CHANNEL_ID_FAILED, (SSL_ERROR_BASE + 131), 111 "The application could not get a TLS Channel ID.") 112 + 113 +ER3(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT, (SSL_ERROR_BASE + 132), 114 +"The connection was using a lesser TLS version as a result of a previous" 115 +" handshake failure, but the server indicated that it should not have been" 116 +" needed.") 117 diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h 118 --- a/nss/lib/ssl/ssl.h 2014-01-17 18:46:51.999581198 -0800 119 +++ b/nss/lib/ssl/ssl.h 2014-01-17 18:48:54.971613341 -0800 120 @@ -183,6 +183,8 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRF 121 122 /* Request Signed Certificate Timestamps via TLS extension (client) */ 123 #define SSL_ENABLE_SIGNED_CERT_TIMESTAMPS 27 124 +#define SSL_ENABLE_FALLBACK_SCSV 28 /* Send fallback SCSV in 125 + * handshakes. */ 126 127 #ifdef SSL_DEPRECATED_FUNCTION 128 /* Old deprecated function names */ 129 diff -pu a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h 130 --- a/nss/lib/ssl/sslimpl.h 2014-01-17 18:46:51.999581198 -0800 131 +++ b/nss/lib/ssl/sslimpl.h 2014-01-17 18:51:17.963962287 -0800 132 @@ -338,6 +338,7 @@ typedef struct sslOptionsStr { 133 unsigned int enableNPN : 1; /* 26 */ 134 unsigned int enableALPN : 1; /* 27 */ 135 unsigned int enableSignedCertTimestamps : 1; /* 28 */ 136 + unsigned int enableFallbackSCSV : 1; /* 29 */ 137 } sslOptions; 138 139 typedef enum { sslHandshakingUndetermined = 0, 140 diff -pu a/nss/lib/ssl/sslproto.h b/nss/lib/ssl/sslproto.h 141 --- a/nss/lib/ssl/sslproto.h 2014-01-17 18:10:16.793281867 -0800 142 +++ b/nss/lib/ssl/sslproto.h 2014-01-17 18:47:05.509804656 -0800 143 @@ -172,6 +172,11 @@ 144 */ 145 #define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF 146 147 +/* TLS_FALLBACK_SCSV is a signaling cipher suite value that indicates that a 148 + * handshake is the result of TLS version fallback. This value is not IANA 149 + * assigned. */ 150 +#define TLS_FALLBACK_SCSV 0x5600 151 + 152 /* Cipher Suite Values starting with 0xC000 are defined in informational 153 * RFCs. 154 */ 155 diff -pu a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c 156 --- a/nss/lib/ssl/sslsock.c 2014-01-17 18:46:52.009581364 -0800 157 +++ b/nss/lib/ssl/sslsock.c 2014-01-17 18:59:17.931852364 -0800 158 @@ -88,7 +88,8 @@ static sslOptions ssl_defaults = { 159 PR_FALSE, /* enableOCSPStapling */ 160 PR_TRUE, /* enableNPN */ 161 PR_FALSE, /* enableALPN */ 162 - PR_FALSE /* enableSignedCertTimestamps */ 163 + PR_FALSE, /* enableSignedCertTimestamps */ 164 + PR_FALSE /* enableFallbackSCSV */ 165 }; 166 167 /* 168 @@ -792,6 +793,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 wh 169 ss->opt.enableSignedCertTimestamps = on; 170 break; 171 172 + case SSL_ENABLE_FALLBACK_SCSV: 173 + ss->opt.enableFallbackSCSV = on; 174 + break; 175 + 176 default: 177 PORT_SetError(SEC_ERROR_INVALID_ARGS); 178 rv = SECFailure; 179 @@ -867,6 +872,7 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 wh 180 case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS: 181 on = ss->opt.enableSignedCertTimestamps; 182 break; 183 + case SSL_ENABLE_FALLBACK_SCSV: on = ss->opt.enableFallbackSCSV; break; 184 185 default: 186 PORT_SetError(SEC_ERROR_INVALID_ARGS); 187 @@ -933,6 +939,9 @@ SSL_OptionGetDefault(PRInt32 which, PRBo 188 case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS: 189 on = ssl_defaults.enableSignedCertTimestamps; 190 break; 191 + case SSL_ENABLE_FALLBACK_SCSV: 192 + on = ssl_defaults.enableFallbackSCSV; 193 + break; 194 195 default: 196 PORT_SetError(SEC_ERROR_INVALID_ARGS); 197 @@ -1112,6 +1121,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBo 198 ssl_defaults.enableSignedCertTimestamps = on; 199 break; 200 201 + case SSL_ENABLE_FALLBACK_SCSV: 202 + ssl_defaults.enableFallbackSCSV = on; 203 + break; 204 + 205 default: 206 PORT_SetError(SEC_ERROR_INVALID_ARGS); 207 return SECFailure; 208