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 |