OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/ssl/ssl_cipher_suite_names.h" | 5 #include "net/ssl/ssl_cipher_suite_names.h" |
6 | 6 |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
12 #include "net/ssl/ssl_connection_status_flags.h" | 12 #include "net/ssl/ssl_connection_status_flags.h" |
13 | 13 |
14 // Rather than storing the names of all the ciphersuites we eliminate the | 14 // Rather than storing the names of all the ciphersuites we eliminate the |
15 // redundancy and break each cipher suite into a key exchange method, cipher | 15 // redundancy and break each cipher suite into a key exchange method, cipher |
16 // and mac. For all the ciphersuites in the IANA registry, we extract each of | 16 // and mac. For all the ciphersuites in the IANA registry, we extract each of |
17 // those components from the name, number them and pack the result into a | 17 // those components from the name, number them and pack the result into a |
18 // 16-bit number thus: | 18 // 16-bit number thus: |
19 // (MSB to LSB) | 19 // (MSB to LSB) |
20 // <3 bits> unused | 20 // <3 bits> unused |
21 // <5 bits> key exchange | 21 // <5 bits> key exchange |
22 // <5 bits> cipher | 22 // <5 bits> cipher |
23 // <3 bits> mac | 23 // <3 bits> mac |
24 | 24 |
25 // The following tables were generated by ssl_cipher_suite_names_generate.go, | 25 // The following tables were generated by ssl_cipher_suite_names_generate.go, |
26 // found in the same directory as this file. | 26 // found in the same directory as this file. |
27 | 27 |
| 28 namespace { |
| 29 |
28 struct CipherSuite { | 30 struct CipherSuite { |
29 uint16 cipher_suite, encoded; | 31 uint16 cipher_suite, encoded; |
30 }; | 32 }; |
31 | 33 |
32 static const struct CipherSuite kCipherSuites[] = { | 34 const struct CipherSuite kCipherSuites[] = { |
33 {0x0, 0x0}, // TLS_NULL_WITH_NULL_NULL | 35 {0x0, 0x0}, // TLS_NULL_WITH_NULL_NULL |
34 {0x1, 0x101}, // TLS_RSA_WITH_NULL_MD5 | 36 {0x1, 0x101}, // TLS_RSA_WITH_NULL_MD5 |
35 {0x2, 0x102}, // TLS_RSA_WITH_NULL_SHA | 37 {0x2, 0x102}, // TLS_RSA_WITH_NULL_SHA |
36 {0x3, 0x209}, // TLS_RSA_EXPORT_WITH_RC4_40_MD5 | 38 {0x3, 0x209}, // TLS_RSA_EXPORT_WITH_RC4_40_MD5 |
37 {0x4, 0x111}, // TLS_RSA_WITH_RC4_128_MD5 | 39 {0x4, 0x111}, // TLS_RSA_WITH_RC4_128_MD5 |
38 {0x5, 0x112}, // TLS_RSA_WITH_RC4_128_SHA | 40 {0x5, 0x112}, // TLS_RSA_WITH_RC4_128_SHA |
39 {0x6, 0x219}, // TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 | 41 {0x6, 0x219}, // TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 |
40 {0x7, 0x122}, // TLS_RSA_WITH_IDEA_CBC_SHA | 42 {0x7, 0x122}, // TLS_RSA_WITH_IDEA_CBC_SHA |
41 {0x8, 0x22a}, // TLS_RSA_EXPORT_WITH_DES40_CBC_SHA | 43 {0x8, 0x22a}, // TLS_RSA_EXPORT_WITH_DES40_CBC_SHA |
42 {0x9, 0x132}, // TLS_RSA_WITH_DES_CBC_SHA | 44 {0x9, 0x132}, // TLS_RSA_WITH_DES_CBC_SHA |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 {0xc089, 0xd87}, // TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 | 194 {0xc089, 0xd87}, // TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 |
193 {0xc08a, 0x107f}, // TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 | 195 {0xc08a, 0x107f}, // TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 |
194 {0xc08b, 0x1087}, // TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 | 196 {0xc08b, 0x1087}, // TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 |
195 {0xc08c, 0xf7f}, // TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 | 197 {0xc08c, 0xf7f}, // TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 |
196 {0xc08d, 0xf87}, // TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 | 198 {0xc08d, 0xf87}, // TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 |
197 {0xcc13, 0x108f}, // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 | 199 {0xcc13, 0x108f}, // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 |
198 {0xcc14, 0x0e8f}, // TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 | 200 {0xcc14, 0x0e8f}, // TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 |
199 {0xcc15, 0x0a8f}, // TLS_DHE_RSA_WITH_CHACHA20_POLY1305 | 201 {0xcc15, 0x0a8f}, // TLS_DHE_RSA_WITH_CHACHA20_POLY1305 |
200 }; | 202 }; |
201 | 203 |
202 static const struct { | 204 const struct { |
203 char name[15]; | 205 char name[15]; |
204 } kKeyExchangeNames[18] = { | 206 } kKeyExchangeNames[18] = { |
205 {"NULL"}, // 0 | 207 {"NULL"}, // 0 |
206 {"RSA"}, // 1 | 208 {"RSA"}, // 1 |
207 {"RSA_EXPORT"}, // 2 | 209 {"RSA_EXPORT"}, // 2 |
208 {"DH_DSS_EXPORT"}, // 3 | 210 {"DH_DSS_EXPORT"}, // 3 |
209 {"DH_DSS"}, // 4 | 211 {"DH_DSS"}, // 4 |
210 {"DH_RSA_EXPORT"}, // 5 | 212 {"DH_RSA_EXPORT"}, // 5 |
211 {"DH_RSA"}, // 6 | 213 {"DH_RSA"}, // 6 |
212 {"DHE_DSS_EXPORT"}, // 7 | 214 {"DHE_DSS_EXPORT"}, // 7 |
213 {"DHE_DSS"}, // 8 | 215 {"DHE_DSS"}, // 8 |
214 {"DHE_RSA_EXPORT"}, // 9 | 216 {"DHE_RSA_EXPORT"}, // 9 |
215 {"DHE_RSA"}, // 10 | 217 {"DHE_RSA"}, // 10 |
216 {"DH_anon_EXPORT"}, // 11 | 218 {"DH_anon_EXPORT"}, // 11 |
217 {"DH_anon"}, // 12 | 219 {"DH_anon"}, // 12 |
218 {"ECDH_ECDSA"}, // 13 | 220 {"ECDH_ECDSA"}, // 13 |
219 {"ECDHE_ECDSA"}, // 14 | 221 {"ECDHE_ECDSA"}, // 14 |
220 {"ECDH_RSA"}, // 15 | 222 {"ECDH_RSA"}, // 15 |
221 {"ECDHE_RSA"}, // 16 | 223 {"ECDHE_RSA"}, // 16 |
222 {"ECDH_anon"}, // 17 | 224 {"ECDH_anon"}, // 17 |
223 }; | 225 }; |
224 | 226 |
225 static const struct { | 227 const struct { |
226 char name[18]; | 228 char name[18]; |
227 } kCipherNames[18] = { | 229 } kCipherNames[18] = { |
228 {"NULL"}, // 0 | 230 {"NULL"}, // 0 |
229 {"RC4_40"}, // 1 | 231 {"RC4_40"}, // 1 |
230 {"RC4_128"}, // 2 | 232 {"RC4_128"}, // 2 |
231 {"RC2_CBC_40"}, // 3 | 233 {"RC2_CBC_40"}, // 3 |
232 {"IDEA_CBC"}, // 4 | 234 {"IDEA_CBC"}, // 4 |
233 {"DES40_CBC"}, // 5 | 235 {"DES40_CBC"}, // 5 |
234 {"DES_CBC"}, // 6 | 236 {"DES_CBC"}, // 6 |
235 {"3DES_EDE_CBC"}, // 7 | 237 {"3DES_EDE_CBC"}, // 7 |
236 {"AES_128_CBC"}, // 8 | 238 {"AES_128_CBC"}, // 8 |
237 {"AES_256_CBC"}, // 9 | 239 {"AES_256_CBC"}, // 9 |
238 {"CAMELLIA_128_CBC"}, // 10 | 240 {"CAMELLIA_128_CBC"}, // 10 |
239 {"CAMELLIA_256_CBC"}, // 11 | 241 {"CAMELLIA_256_CBC"}, // 11 |
240 {"SEED_CBC"}, // 12 | 242 {"SEED_CBC"}, // 12 |
241 {"AES_128_GCM"}, // 13 | 243 {"AES_128_GCM"}, // 13 |
242 {"AES_256_GCM"}, // 14 | 244 {"AES_256_GCM"}, // 14 |
243 {"CAMELLIA_128_GCM"}, // 15 | 245 {"CAMELLIA_128_GCM"}, // 15 |
244 {"CAMELLIA_256_GCM"}, // 16 | 246 {"CAMELLIA_256_GCM"}, // 16 |
245 {"CHACHA20_POLY1305"}, // 17 | 247 {"CHACHA20_POLY1305"}, // 17 |
246 }; | 248 }; |
247 | 249 |
248 static const struct { | 250 const struct { |
249 char name[7]; | 251 char name[7]; |
250 } kMacNames[5] = { | 252 } kMacNames[5] = { |
251 {"NULL"}, // 0 | 253 {"NULL"}, // 0 |
252 {"MD5"}, // 1 | 254 {"MD5"}, // 1 |
253 {"SHA1"}, // 2 | 255 {"SHA1"}, // 2 |
254 {"SHA256"}, // 3 | 256 {"SHA256"}, // 3 |
255 {"SHA384"}, // 4 | 257 {"SHA384"}, // 4 |
256 // 7 is reserved to indicate an AEAD cipher suite. | 258 // 7 is reserved to indicate an AEAD cipher suite. |
257 }; | 259 }; |
258 | 260 |
259 static const int kAEADMACValue = 7; | 261 const int kAEADMACValue = 7; |
260 | 262 |
261 namespace net { | 263 int CipherSuiteCmp(const void* ia, const void* ib) { |
262 | |
263 static int CipherSuiteCmp(const void* ia, const void* ib) { | |
264 const CipherSuite* a = static_cast<const CipherSuite*>(ia); | 264 const CipherSuite* a = static_cast<const CipherSuite*>(ia); |
265 const CipherSuite* b = static_cast<const CipherSuite*>(ib); | 265 const CipherSuite* b = static_cast<const CipherSuite*>(ib); |
266 | 266 |
267 if (a->cipher_suite < b->cipher_suite) { | 267 if (a->cipher_suite < b->cipher_suite) { |
268 return -1; | 268 return -1; |
269 } else if (a->cipher_suite == b->cipher_suite) { | 269 } else if (a->cipher_suite == b->cipher_suite) { |
270 return 0; | 270 return 0; |
271 } else { | 271 } else { |
272 return 1; | 272 return 1; |
273 } | 273 } |
274 } | 274 } |
275 | 275 |
| 276 bool GetCipherProperties(uint16 cipher_suite, |
| 277 int* out_key_exchange, |
| 278 int* out_cipher, |
| 279 int* out_mac) { |
| 280 CipherSuite desired = {0}; |
| 281 desired.cipher_suite = cipher_suite; |
| 282 void* r = bsearch(&desired, kCipherSuites, arraysize(kCipherSuites), |
| 283 sizeof(kCipherSuites[0]), CipherSuiteCmp); |
| 284 |
| 285 if (!r) |
| 286 return false; |
| 287 |
| 288 const CipherSuite* cs = static_cast<const CipherSuite*>(r); |
| 289 *out_key_exchange = cs->encoded >> 8; |
| 290 *out_cipher = (cs->encoded >> 3) & 0x1f; |
| 291 *out_mac = cs->encoded & 0x7; |
| 292 return true; |
| 293 } |
| 294 |
| 295 } // namespace |
| 296 |
| 297 namespace net { |
| 298 |
276 void SSLCipherSuiteToStrings(const char** key_exchange_str, | 299 void SSLCipherSuiteToStrings(const char** key_exchange_str, |
277 const char** cipher_str, | 300 const char** cipher_str, |
278 const char** mac_str, | 301 const char** mac_str, |
279 bool *is_aead, | 302 bool *is_aead, |
280 uint16 cipher_suite) { | 303 uint16 cipher_suite) { |
281 *key_exchange_str = *cipher_str = *mac_str = "???"; | 304 *key_exchange_str = *cipher_str = *mac_str = "???"; |
282 *is_aead = false; | 305 *is_aead = false; |
283 | 306 |
284 struct CipherSuite desired = {0}; | 307 int key_exchange, cipher, mac; |
285 desired.cipher_suite = cipher_suite; | 308 if (!GetCipherProperties(cipher_suite, &key_exchange, &cipher, &mac)) |
286 | |
287 void* r = bsearch(&desired, kCipherSuites, | |
288 arraysize(kCipherSuites), sizeof(kCipherSuites[0]), | |
289 CipherSuiteCmp); | |
290 | |
291 if (!r) | |
292 return; | 309 return; |
293 | 310 |
294 const CipherSuite* cs = static_cast<CipherSuite*>(r); | |
295 | |
296 const int key_exchange = cs->encoded >> 8; | |
297 const int cipher = (cs->encoded >> 3) & 0x1f; | |
298 const int mac = cs->encoded & 0x7; | |
299 | |
300 *key_exchange_str = kKeyExchangeNames[key_exchange].name; | 311 *key_exchange_str = kKeyExchangeNames[key_exchange].name; |
301 *cipher_str = kCipherNames[cipher].name; | 312 *cipher_str = kCipherNames[cipher].name; |
302 if (mac == kAEADMACValue) { | 313 if (mac == kAEADMACValue) { |
303 *is_aead = true; | 314 *is_aead = true; |
304 *mac_str = NULL; | 315 *mac_str = NULL; |
305 } else { | 316 } else { |
306 *mac_str = kMacNames[mac].name; | 317 *mac_str = kMacNames[mac].name; |
307 } | 318 } |
308 } | 319 } |
309 | 320 |
(...skipping 30 matching lines...) Expand all Loading... |
340 if (cipher_string.size() == 6 && | 351 if (cipher_string.size() == 6 && |
341 StartsWithASCII(cipher_string, "0x", false /* case insensitive */) && | 352 StartsWithASCII(cipher_string, "0x", false /* case insensitive */) && |
342 base::HexStringToInt(cipher_string, &value)) { | 353 base::HexStringToInt(cipher_string, &value)) { |
343 *cipher_suite = static_cast<uint16>(value); | 354 *cipher_suite = static_cast<uint16>(value); |
344 return true; | 355 return true; |
345 } | 356 } |
346 return false; | 357 return false; |
347 } | 358 } |
348 | 359 |
349 bool IsSecureTLSCipherSuite(uint16 cipher_suite) { | 360 bool IsSecureTLSCipherSuite(uint16 cipher_suite) { |
350 CipherSuite desired = {0}; | 361 int key_exchange, cipher, mac; |
351 desired.cipher_suite = cipher_suite; | 362 if (!GetCipherProperties(cipher_suite, &key_exchange, &cipher, &mac)) |
352 | |
353 void* r = bsearch(&desired, | |
354 kCipherSuites, | |
355 arraysize(kCipherSuites), | |
356 sizeof(kCipherSuites[0]), | |
357 CipherSuiteCmp); | |
358 | |
359 if (!r) | |
360 return false; | 363 return false; |
361 | 364 |
362 const CipherSuite* cs = static_cast<const CipherSuite*>(r); | |
363 | |
364 const int key_exchange = cs->encoded >> 8; | |
365 const int cipher = (cs->encoded >> 3) & 0x1f; | |
366 const int mac = cs->encoded & 0x7; | |
367 | |
368 // Only allow forward secure key exchanges. | 365 // Only allow forward secure key exchanges. |
369 switch (key_exchange) { | 366 switch (key_exchange) { |
370 case 10: // DHE_RSA | 367 case 10: // DHE_RSA |
371 case 14: // ECDHE_ECDSA | 368 case 14: // ECDHE_ECDSA |
372 case 16: // ECDHE_RSA | 369 case 16: // ECDHE_RSA |
373 break; | 370 break; |
| 371 default: |
| 372 return false; |
| 373 } |
| 374 |
| 375 switch (cipher) { |
| 376 case 13: // AES_128_GCM |
| 377 case 14: // AES_256_GCM |
| 378 case 17: // CHACHA20_POLY1305 |
| 379 break; |
| 380 default: |
| 381 return false; |
| 382 } |
| 383 |
| 384 // Only AEADs allowed. |
| 385 if (mac != kAEADMACValue) |
| 386 return false; |
| 387 |
| 388 return true; |
| 389 } |
| 390 |
| 391 bool IsFalseStartableTLSCipherSuite(uint16 cipher_suite) { |
| 392 int key_exchange, cipher, mac; |
| 393 if (!GetCipherProperties(cipher_suite, &key_exchange, &cipher, &mac)) |
| 394 return false; |
| 395 |
| 396 // Only allow ECDHE key exchanges. |
| 397 switch (key_exchange) { |
| 398 case 14: // ECDHE_ECDSA |
| 399 case 16: // ECDHE_RSA |
| 400 break; |
374 default: | 401 default: |
375 return false; | 402 return false; |
376 } | 403 } |
377 | 404 |
378 switch (cipher) { | 405 switch (cipher) { |
379 case 13: // AES_128_GCM | 406 case 13: // AES_128_GCM |
380 case 14: // AES_256_GCM | 407 case 14: // AES_256_GCM |
381 case 17: // CHACHA20_POLY1305 | 408 case 17: // CHACHA20_POLY1305 |
382 break; | 409 break; |
383 default: | 410 default: |
384 return false; | 411 return false; |
385 } | 412 } |
386 | 413 |
387 // Only AEADs allowed. | 414 // Only AEADs allowed. |
388 if (mac != kAEADMACValue) | 415 if (mac != kAEADMACValue) |
389 return false; | 416 return false; |
390 | 417 |
391 return true; | 418 return true; |
392 } | 419 } |
393 | 420 |
394 } // namespace net | 421 } // namespace net |
OLD | NEW |