Chromium Code Reviews| 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; |
|
agl
2015/04/02 00:36:43
these could all be one line.
davidben
2015/04/02 16:48:31
Done.
| |
| 285 desired.cipher_suite = cipher_suite; | 308 int cipher; |
| 286 | 309 int mac; |
| 287 void* r = bsearch(&desired, kCipherSuites, | 310 if (!GetCipherProperties(cipher_suite, &key_exchange, &cipher, &mac)) |
| 288 arraysize(kCipherSuites), sizeof(kCipherSuites[0]), | |
| 289 CipherSuiteCmp); | |
| 290 | |
| 291 if (!r) | |
| 292 return; | 311 return; |
| 293 | 312 |
| 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; | 313 *key_exchange_str = kKeyExchangeNames[key_exchange].name; |
| 301 *cipher_str = kCipherNames[cipher].name; | 314 *cipher_str = kCipherNames[cipher].name; |
| 302 if (mac == kAEADMACValue) { | 315 if (mac == kAEADMACValue) { |
| 303 *is_aead = true; | 316 *is_aead = true; |
| 304 *mac_str = NULL; | 317 *mac_str = NULL; |
| 305 } else { | 318 } else { |
| 306 *mac_str = kMacNames[mac].name; | 319 *mac_str = kMacNames[mac].name; |
| 307 } | 320 } |
| 308 } | 321 } |
| 309 | 322 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 340 if (cipher_string.size() == 6 && | 353 if (cipher_string.size() == 6 && |
| 341 StartsWithASCII(cipher_string, "0x", false /* case insensitive */) && | 354 StartsWithASCII(cipher_string, "0x", false /* case insensitive */) && |
| 342 base::HexStringToInt(cipher_string, &value)) { | 355 base::HexStringToInt(cipher_string, &value)) { |
| 343 *cipher_suite = static_cast<uint16>(value); | 356 *cipher_suite = static_cast<uint16>(value); |
| 344 return true; | 357 return true; |
| 345 } | 358 } |
| 346 return false; | 359 return false; |
| 347 } | 360 } |
| 348 | 361 |
| 349 bool IsSecureTLSCipherSuite(uint16 cipher_suite) { | 362 bool IsSecureTLSCipherSuite(uint16 cipher_suite) { |
| 350 CipherSuite desired = {0}; | 363 int key_exchange; |
|
agl
2015/04/02 00:36:43
ditto.
davidben
2015/04/02 16:48:31
Done.
| |
| 351 desired.cipher_suite = cipher_suite; | 364 int cipher; |
| 352 | 365 int mac; |
| 353 void* r = bsearch(&desired, | 366 if (!GetCipherProperties(cipher_suite, &key_exchange, &cipher, &mac)) |
| 354 kCipherSuites, | |
| 355 arraysize(kCipherSuites), | |
| 356 sizeof(kCipherSuites[0]), | |
| 357 CipherSuiteCmp); | |
| 358 | |
| 359 if (!r) | |
| 360 return false; | 367 return false; |
| 361 | 368 |
| 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. | 369 // Only allow forward secure key exchanges. |
| 369 switch (key_exchange) { | 370 switch (key_exchange) { |
| 370 case 10: // DHE_RSA | 371 case 10: // DHE_RSA |
| 371 case 14: // ECDHE_ECDSA | 372 case 14: // ECDHE_ECDSA |
| 372 case 16: // ECDHE_RSA | 373 case 16: // ECDHE_RSA |
| 373 break; | 374 break; |
| 375 default: | |
| 376 return false; | |
| 377 } | |
| 378 | |
| 379 switch (cipher) { | |
| 380 case 13: // AES_128_GCM | |
| 381 case 14: // AES_256_GCM | |
| 382 case 17: // CHACHA20_POLY1305 | |
| 383 break; | |
| 384 default: | |
| 385 return false; | |
| 386 } | |
| 387 | |
| 388 // Only AEADs allowed. | |
| 389 if (mac != kAEADMACValue) | |
| 390 return false; | |
| 391 | |
| 392 return true; | |
| 393 } | |
| 394 | |
| 395 bool IsFalseStartableTLSCipherSuite(uint16 cipher_suite) { | |
| 396 int key_exchange; | |
|
agl
2015/04/02 00:36:43
ditto.
davidben
2015/04/02 16:48:31
Done.
| |
| 397 int cipher; | |
| 398 int mac; | |
| 399 if (!GetCipherProperties(cipher_suite, &key_exchange, &cipher, &mac)) | |
| 400 return false; | |
| 401 | |
| 402 // Only allow ECDHE key exchanges. | |
| 403 switch (key_exchange) { | |
| 404 case 14: // ECDHE_ECDSA | |
| 405 case 16: // ECDHE_RSA | |
| 406 break; | |
| 374 default: | 407 default: |
| 375 return false; | 408 return false; |
| 376 } | 409 } |
| 377 | 410 |
| 378 switch (cipher) { | 411 switch (cipher) { |
| 379 case 13: // AES_128_GCM | 412 case 13: // AES_128_GCM |
| 380 case 14: // AES_256_GCM | 413 case 14: // AES_256_GCM |
| 381 case 17: // CHACHA20_POLY1305 | 414 case 17: // CHACHA20_POLY1305 |
| 382 break; | 415 break; |
| 383 default: | 416 default: |
| 384 return false; | 417 return false; |
| 385 } | 418 } |
| 386 | 419 |
| 387 // Only AEADs allowed. | 420 // Only AEADs allowed. |
| 388 if (mac != kAEADMACValue) | 421 if (mac != kAEADMACValue) |
| 389 return false; | 422 return false; |
| 390 | 423 |
| 391 return true; | 424 return true; |
| 392 } | 425 } |
| 393 | 426 |
| 394 } // namespace net | 427 } // namespace net |
| OLD | NEW |