| 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 | |
| 30 struct CipherSuite { | 28 struct CipherSuite { |
| 31 uint16 cipher_suite, encoded; | 29 uint16 cipher_suite, encoded; |
| 32 }; | 30 }; |
| 33 | 31 |
| 34 const struct CipherSuite kCipherSuites[] = { | 32 static const struct CipherSuite kCipherSuites[] = { |
| 35 {0x0, 0x0}, // TLS_NULL_WITH_NULL_NULL | 33 {0x0, 0x0}, // TLS_NULL_WITH_NULL_NULL |
| 36 {0x1, 0x101}, // TLS_RSA_WITH_NULL_MD5 | 34 {0x1, 0x101}, // TLS_RSA_WITH_NULL_MD5 |
| 37 {0x2, 0x102}, // TLS_RSA_WITH_NULL_SHA | 35 {0x2, 0x102}, // TLS_RSA_WITH_NULL_SHA |
| 38 {0x3, 0x209}, // TLS_RSA_EXPORT_WITH_RC4_40_MD5 | 36 {0x3, 0x209}, // TLS_RSA_EXPORT_WITH_RC4_40_MD5 |
| 39 {0x4, 0x111}, // TLS_RSA_WITH_RC4_128_MD5 | 37 {0x4, 0x111}, // TLS_RSA_WITH_RC4_128_MD5 |
| 40 {0x5, 0x112}, // TLS_RSA_WITH_RC4_128_SHA | 38 {0x5, 0x112}, // TLS_RSA_WITH_RC4_128_SHA |
| 41 {0x6, 0x219}, // TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 | 39 {0x6, 0x219}, // TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 |
| 42 {0x7, 0x122}, // TLS_RSA_WITH_IDEA_CBC_SHA | 40 {0x7, 0x122}, // TLS_RSA_WITH_IDEA_CBC_SHA |
| 43 {0x8, 0x22a}, // TLS_RSA_EXPORT_WITH_DES40_CBC_SHA | 41 {0x8, 0x22a}, // TLS_RSA_EXPORT_WITH_DES40_CBC_SHA |
| 44 {0x9, 0x132}, // TLS_RSA_WITH_DES_CBC_SHA | 42 {0x9, 0x132}, // TLS_RSA_WITH_DES_CBC_SHA |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 {0xc089, 0xd87}, // TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 | 192 {0xc089, 0xd87}, // TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 |
| 195 {0xc08a, 0x107f}, // TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 | 193 {0xc08a, 0x107f}, // TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 |
| 196 {0xc08b, 0x1087}, // TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 | 194 {0xc08b, 0x1087}, // TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 |
| 197 {0xc08c, 0xf7f}, // TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 | 195 {0xc08c, 0xf7f}, // TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 |
| 198 {0xc08d, 0xf87}, // TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 | 196 {0xc08d, 0xf87}, // TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 |
| 199 {0xcc13, 0x108f}, // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 | 197 {0xcc13, 0x108f}, // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 |
| 200 {0xcc14, 0x0e8f}, // TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 | 198 {0xcc14, 0x0e8f}, // TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 |
| 201 {0xcc15, 0x0a8f}, // TLS_DHE_RSA_WITH_CHACHA20_POLY1305 | 199 {0xcc15, 0x0a8f}, // TLS_DHE_RSA_WITH_CHACHA20_POLY1305 |
| 202 }; | 200 }; |
| 203 | 201 |
| 204 const struct { | 202 static const struct { |
| 205 char name[15]; | 203 char name[15]; |
| 206 } kKeyExchangeNames[18] = { | 204 } kKeyExchangeNames[18] = { |
| 207 {"NULL"}, // 0 | 205 {"NULL"}, // 0 |
| 208 {"RSA"}, // 1 | 206 {"RSA"}, // 1 |
| 209 {"RSA_EXPORT"}, // 2 | 207 {"RSA_EXPORT"}, // 2 |
| 210 {"DH_DSS_EXPORT"}, // 3 | 208 {"DH_DSS_EXPORT"}, // 3 |
| 211 {"DH_DSS"}, // 4 | 209 {"DH_DSS"}, // 4 |
| 212 {"DH_RSA_EXPORT"}, // 5 | 210 {"DH_RSA_EXPORT"}, // 5 |
| 213 {"DH_RSA"}, // 6 | 211 {"DH_RSA"}, // 6 |
| 214 {"DHE_DSS_EXPORT"}, // 7 | 212 {"DHE_DSS_EXPORT"}, // 7 |
| 215 {"DHE_DSS"}, // 8 | 213 {"DHE_DSS"}, // 8 |
| 216 {"DHE_RSA_EXPORT"}, // 9 | 214 {"DHE_RSA_EXPORT"}, // 9 |
| 217 {"DHE_RSA"}, // 10 | 215 {"DHE_RSA"}, // 10 |
| 218 {"DH_anon_EXPORT"}, // 11 | 216 {"DH_anon_EXPORT"}, // 11 |
| 219 {"DH_anon"}, // 12 | 217 {"DH_anon"}, // 12 |
| 220 {"ECDH_ECDSA"}, // 13 | 218 {"ECDH_ECDSA"}, // 13 |
| 221 {"ECDHE_ECDSA"}, // 14 | 219 {"ECDHE_ECDSA"}, // 14 |
| 222 {"ECDH_RSA"}, // 15 | 220 {"ECDH_RSA"}, // 15 |
| 223 {"ECDHE_RSA"}, // 16 | 221 {"ECDHE_RSA"}, // 16 |
| 224 {"ECDH_anon"}, // 17 | 222 {"ECDH_anon"}, // 17 |
| 225 }; | 223 }; |
| 226 | 224 |
| 227 const struct { | 225 static const struct { |
| 228 char name[18]; | 226 char name[18]; |
| 229 } kCipherNames[18] = { | 227 } kCipherNames[18] = { |
| 230 {"NULL"}, // 0 | 228 {"NULL"}, // 0 |
| 231 {"RC4_40"}, // 1 | 229 {"RC4_40"}, // 1 |
| 232 {"RC4_128"}, // 2 | 230 {"RC4_128"}, // 2 |
| 233 {"RC2_CBC_40"}, // 3 | 231 {"RC2_CBC_40"}, // 3 |
| 234 {"IDEA_CBC"}, // 4 | 232 {"IDEA_CBC"}, // 4 |
| 235 {"DES40_CBC"}, // 5 | 233 {"DES40_CBC"}, // 5 |
| 236 {"DES_CBC"}, // 6 | 234 {"DES_CBC"}, // 6 |
| 237 {"3DES_EDE_CBC"}, // 7 | 235 {"3DES_EDE_CBC"}, // 7 |
| 238 {"AES_128_CBC"}, // 8 | 236 {"AES_128_CBC"}, // 8 |
| 239 {"AES_256_CBC"}, // 9 | 237 {"AES_256_CBC"}, // 9 |
| 240 {"CAMELLIA_128_CBC"}, // 10 | 238 {"CAMELLIA_128_CBC"}, // 10 |
| 241 {"CAMELLIA_256_CBC"}, // 11 | 239 {"CAMELLIA_256_CBC"}, // 11 |
| 242 {"SEED_CBC"}, // 12 | 240 {"SEED_CBC"}, // 12 |
| 243 {"AES_128_GCM"}, // 13 | 241 {"AES_128_GCM"}, // 13 |
| 244 {"AES_256_GCM"}, // 14 | 242 {"AES_256_GCM"}, // 14 |
| 245 {"CAMELLIA_128_GCM"}, // 15 | 243 {"CAMELLIA_128_GCM"}, // 15 |
| 246 {"CAMELLIA_256_GCM"}, // 16 | 244 {"CAMELLIA_256_GCM"}, // 16 |
| 247 {"CHACHA20_POLY1305"}, // 17 | 245 {"CHACHA20_POLY1305"}, // 17 |
| 248 }; | 246 }; |
| 249 | 247 |
| 250 const struct { | 248 static const struct { |
| 251 char name[7]; | 249 char name[7]; |
| 252 } kMacNames[5] = { | 250 } kMacNames[5] = { |
| 253 {"NULL"}, // 0 | 251 {"NULL"}, // 0 |
| 254 {"MD5"}, // 1 | 252 {"MD5"}, // 1 |
| 255 {"SHA1"}, // 2 | 253 {"SHA1"}, // 2 |
| 256 {"SHA256"}, // 3 | 254 {"SHA256"}, // 3 |
| 257 {"SHA384"}, // 4 | 255 {"SHA384"}, // 4 |
| 258 // 7 is reserved to indicate an AEAD cipher suite. | 256 // 7 is reserved to indicate an AEAD cipher suite. |
| 259 }; | 257 }; |
| 260 | 258 |
| 261 const int kAEADMACValue = 7; | 259 static const int kAEADMACValue = 7; |
| 262 | 260 |
| 263 int CipherSuiteCmp(const void* ia, const void* ib) { | 261 namespace net { |
| 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 | |
| 299 void SSLCipherSuiteToStrings(const char** key_exchange_str, | 276 void SSLCipherSuiteToStrings(const char** key_exchange_str, |
| 300 const char** cipher_str, | 277 const char** cipher_str, |
| 301 const char** mac_str, | 278 const char** mac_str, |
| 302 bool *is_aead, | 279 bool *is_aead, |
| 303 uint16 cipher_suite) { | 280 uint16 cipher_suite) { |
| 304 *key_exchange_str = *cipher_str = *mac_str = "???"; | 281 *key_exchange_str = *cipher_str = *mac_str = "???"; |
| 305 *is_aead = false; | 282 *is_aead = false; |
| 306 | 283 |
| 307 int key_exchange, cipher, mac; | 284 struct CipherSuite desired = {0}; |
| 308 if (!GetCipherProperties(cipher_suite, &key_exchange, &cipher, &mac)) | 285 desired.cipher_suite = cipher_suite; |
| 286 |
| 287 void* r = bsearch(&desired, kCipherSuites, |
| 288 arraysize(kCipherSuites), sizeof(kCipherSuites[0]), |
| 289 CipherSuiteCmp); |
| 290 |
| 291 if (!r) |
| 309 return; | 292 return; |
| 310 | 293 |
| 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 |
| 311 *key_exchange_str = kKeyExchangeNames[key_exchange].name; | 300 *key_exchange_str = kKeyExchangeNames[key_exchange].name; |
| 312 *cipher_str = kCipherNames[cipher].name; | 301 *cipher_str = kCipherNames[cipher].name; |
| 313 if (mac == kAEADMACValue) { | 302 if (mac == kAEADMACValue) { |
| 314 *is_aead = true; | 303 *is_aead = true; |
| 315 *mac_str = NULL; | 304 *mac_str = NULL; |
| 316 } else { | 305 } else { |
| 317 *mac_str = kMacNames[mac].name; | 306 *mac_str = kMacNames[mac].name; |
| 318 } | 307 } |
| 319 } | 308 } |
| 320 | 309 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 351 if (cipher_string.size() == 6 && | 340 if (cipher_string.size() == 6 && |
| 352 StartsWithASCII(cipher_string, "0x", false /* case insensitive */) && | 341 StartsWithASCII(cipher_string, "0x", false /* case insensitive */) && |
| 353 base::HexStringToInt(cipher_string, &value)) { | 342 base::HexStringToInt(cipher_string, &value)) { |
| 354 *cipher_suite = static_cast<uint16>(value); | 343 *cipher_suite = static_cast<uint16>(value); |
| 355 return true; | 344 return true; |
| 356 } | 345 } |
| 357 return false; | 346 return false; |
| 358 } | 347 } |
| 359 | 348 |
| 360 bool IsSecureTLSCipherSuite(uint16 cipher_suite) { | 349 bool IsSecureTLSCipherSuite(uint16 cipher_suite) { |
| 361 int key_exchange, cipher, mac; | 350 CipherSuite desired = {0}; |
| 362 if (!GetCipherProperties(cipher_suite, &key_exchange, &cipher, &mac)) | 351 desired.cipher_suite = cipher_suite; |
| 352 |
| 353 void* r = bsearch(&desired, |
| 354 kCipherSuites, |
| 355 arraysize(kCipherSuites), |
| 356 sizeof(kCipherSuites[0]), |
| 357 CipherSuiteCmp); |
| 358 |
| 359 if (!r) |
| 363 return false; | 360 return false; |
| 364 | 361 |
| 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 |
| 365 // Only allow forward secure key exchanges. | 368 // Only allow forward secure key exchanges. |
| 366 switch (key_exchange) { | 369 switch (key_exchange) { |
| 367 case 10: // DHE_RSA | 370 case 10: // DHE_RSA |
| 368 case 14: // ECDHE_ECDSA | 371 case 14: // ECDHE_ECDSA |
| 369 case 16: // ECDHE_RSA | 372 case 16: // ECDHE_RSA |
| 370 break; | 373 break; |
| 371 default: | 374 default: |
| 372 return false; | 375 return false; |
| 373 } | 376 } |
| 374 | 377 |
| 375 switch (cipher) { | 378 switch (cipher) { |
| 376 case 13: // AES_128_GCM | 379 case 13: // AES_128_GCM |
| 377 case 14: // AES_256_GCM | 380 case 14: // AES_256_GCM |
| 378 case 17: // CHACHA20_POLY1305 | 381 case 17: // CHACHA20_POLY1305 |
| 379 break; | 382 break; |
| 380 default: | 383 default: |
| 381 return false; | 384 return false; |
| 382 } | 385 } |
| 383 | 386 |
| 384 // Only AEADs allowed. | 387 // Only AEADs allowed. |
| 385 if (mac != kAEADMACValue) | 388 if (mac != kAEADMACValue) |
| 386 return false; | 389 return false; |
| 387 | 390 |
| 388 return true; | 391 return true; |
| 389 } | 392 } |
| 390 | 393 |
| 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; | |
| 401 default: | |
| 402 return false; | |
| 403 } | |
| 404 | |
| 405 switch (cipher) { | |
| 406 case 13: // AES_128_GCM | |
| 407 case 14: // AES_256_GCM | |
| 408 case 17: // CHACHA20_POLY1305 | |
| 409 break; | |
| 410 default: | |
| 411 return false; | |
| 412 } | |
| 413 | |
| 414 // Only AEADs allowed. | |
| 415 if (mac != kAEADMACValue) | |
| 416 return false; | |
| 417 | |
| 418 return true; | |
| 419 } | |
| 420 | |
| 421 } // namespace net | 394 } // namespace net |
| OLD | NEW |