OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived | 5 // This file includes code SSLClientSocketNSS::DoVerifyCertComplete() derived |
6 // from AuthCertificateCallback() in | 6 // from AuthCertificateCallback() in |
7 // mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp. | 7 // mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp. |
8 | 8 |
9 /* ***** BEGIN LICENSE BLOCK ***** | 9 /* ***** BEGIN LICENSE BLOCK ***** |
10 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 10 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
61 #include <sslproto.h> | 61 #include <sslproto.h> |
62 | 62 |
63 #include <algorithm> | 63 #include <algorithm> |
64 #include <limits> | 64 #include <limits> |
65 #include <map> | 65 #include <map> |
66 | 66 |
67 #include "base/bind.h" | 67 #include "base/bind.h" |
68 #include "base/bind_helpers.h" | 68 #include "base/bind_helpers.h" |
69 #include "base/callback_helpers.h" | 69 #include "base/callback_helpers.h" |
70 #include "base/compiler_specific.h" | 70 #include "base/compiler_specific.h" |
71 #include "base/cpu.h" | |
71 #include "base/logging.h" | 72 #include "base/logging.h" |
72 #include "base/memory/singleton.h" | 73 #include "base/memory/singleton.h" |
73 #include "base/metrics/histogram.h" | 74 #include "base/metrics/histogram.h" |
74 #include "base/single_thread_task_runner.h" | 75 #include "base/single_thread_task_runner.h" |
75 #include "base/stl_util.h" | 76 #include "base/stl_util.h" |
76 #include "base/strings/string_number_conversions.h" | 77 #include "base/strings/string_number_conversions.h" |
77 #include "base/strings/string_util.h" | 78 #include "base/strings/string_util.h" |
78 #include "base/strings/stringprintf.h" | 79 #include "base/strings/stringprintf.h" |
79 #include "base/thread_task_runner_handle.h" | 80 #include "base/thread_task_runner_handle.h" |
80 #include "base/threading/thread_restrictions.h" | 81 #include "base/threading/thread_restrictions.h" |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
483 switch (err) { | 484 switch (err) { |
484 // If the server closed on us, it is a protocol error. | 485 // If the server closed on us, it is a protocol error. |
485 // Some TLS-intolerant servers do this when we request TLS. | 486 // Some TLS-intolerant servers do this when we request TLS. |
486 case PR_END_OF_FILE_ERROR: | 487 case PR_END_OF_FILE_ERROR: |
487 return ERR_SSL_PROTOCOL_ERROR; | 488 return ERR_SSL_PROTOCOL_ERROR; |
488 default: | 489 default: |
489 return MapNSSClientError(err); | 490 return MapNSSClientError(err); |
490 } | 491 } |
491 } | 492 } |
492 | 493 |
494 // CiphersRemove takes a zero-terminated array of cipher suite ids in | |
495 // |to_remove| and sets every instance of them in |ciphers| to zero. It returns | |
496 // true if it found and removed every element of |to_remove|. It assumes that | |
497 // there are no duplicates in |ciphers| nor in |to_remove|. | |
498 bool CiphersRemove(const uint16* to_remove, uint16* ciphers, size_t num) { | |
499 size_t num_remove, found = 0; | |
500 | |
501 for (num_remove = 0; ; num_remove++) { | |
502 if (to_remove[num_remove] == 0) | |
503 break; | |
504 } | |
505 | |
506 for (size_t i = 0; i < num; i++) { | |
507 for (size_t j = 0; j < num_remove; j++) { | |
508 if (to_remove[j] == ciphers[i]) { | |
509 ciphers[i] = 0; | |
510 found++; | |
511 break; | |
512 } | |
513 } | |
514 } | |
515 | |
516 return found == num_remove; | |
517 } | |
518 | |
519 // CiphersCompact takes an array of cipher suite ids in |ciphers|, where some | |
520 // entries are zero, and moves the entries so that all the non-zero elements | |
521 // are compacted at the end of the array. | |
522 size_t CiphersCompact(uint16* ciphers, size_t num) { | |
523 size_t j = num - 1; | |
524 | |
525 for (size_t i = num - 1; i < num; i--) { | |
526 printf("@%u %d %u\n", (unsigned) i, ciphers[i], (unsigned) j); | |
527 if (ciphers[i] == 0) | |
528 continue; | |
529 ciphers[j--] = ciphers[i]; | |
530 } | |
531 return j+1; | |
532 } | |
533 | |
534 // CiphersCopy copies the zero-terminated array |in| to |out|. | |
535 size_t CiphersCopy(const uint16* in, uint16* out) { | |
536 for (size_t i = 0; ; i++) { | |
537 if (in[i] == 0) | |
538 return i; | |
539 out[i] = in[i]; | |
540 } | |
541 } | |
542 | |
493 } // namespace | 543 } // namespace |
494 | 544 |
495 // SSLClientSocketNSS::Core provides a thread-safe, ref-counted core that is | 545 // SSLClientSocketNSS::Core provides a thread-safe, ref-counted core that is |
496 // able to marshal data between NSS functions and an underlying transport | 546 // able to marshal data between NSS functions and an underlying transport |
497 // socket. | 547 // socket. |
498 // | 548 // |
499 // All public functions are meant to be called from the network task runner, | 549 // All public functions are meant to be called from the network task runner, |
500 // and any callbacks supplied will be invoked there as well, provided that | 550 // and any callbacks supplied will be invoked there as well, provided that |
501 // Detach() has not been called yet. | 551 // Detach() has not been called yet. |
502 // | 552 // |
(...skipping 2608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3111 } | 3161 } |
3112 | 3162 |
3113 for (std::vector<uint16>::const_iterator it = | 3163 for (std::vector<uint16>::const_iterator it = |
3114 ssl_config_.disabled_cipher_suites.begin(); | 3164 ssl_config_.disabled_cipher_suites.begin(); |
3115 it != ssl_config_.disabled_cipher_suites.end(); ++it) { | 3165 it != ssl_config_.disabled_cipher_suites.end(); ++it) { |
3116 // This will fail if the specified cipher is not implemented by NSS, but | 3166 // This will fail if the specified cipher is not implemented by NSS, but |
3117 // the failure is harmless. | 3167 // the failure is harmless. |
3118 SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE); | 3168 SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE); |
3119 } | 3169 } |
3120 | 3170 |
3171 /* Our top preference cipher suites are either forward-secure AES-GCM or | |
3172 * forward secure ChaCha20-Poly1305. If the local machine has AES-NI then we | |
3173 * prefer AES-GCM, otherwise ChaCha20. The remainder of the cipher suite | |
3174 * preference is inheriented from NSS. */ | |
3175 static const uint16 chacha_ciphers[] = { | |
3176 0xcc14 /* TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 */, | |
3177 0xcc13 /* TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 */, | |
3178 0, | |
3179 }; | |
3180 static const uint16 aes_gcm_ciphers[] = { | |
3181 0xc02b /* TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 */, | |
3182 0xc02f /* TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 */, | |
3183 0x9e /* TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 */, | |
3184 0, | |
3185 }; | |
3186 const PRUint16 *all_ciphers = SSL_GetImplementedCiphers(); | |
3187 const size_t num_ciphers = SSL_GetNumImplementedCiphers(); | |
3188 scoped_ptr<uint16[]> ciphers(new uint16[num_ciphers]); | |
3189 memcpy(ciphers.get(), all_ciphers, sizeof(uint16)*num_ciphers); | |
3190 | |
3191 if (CiphersRemove(chacha_ciphers, ciphers.get(), num_ciphers) && | |
3192 CiphersRemove(aes_gcm_ciphers, ciphers.get(), num_ciphers)) { | |
3193 CiphersCompact(ciphers.get(), num_ciphers); | |
3194 | |
3195 const uint16 *preference_ciphers = chacha_ciphers; | |
3196 const uint16 *other_ciphers = aes_gcm_ciphers; | |
3197 if (base::CPU().has_aesni()) { | |
wtc
2013/11/19 23:00:44
Since this won't change over time, we should ideal
agl
2013/11/20 18:21:07
Done.
| |
3198 preference_ciphers = aes_gcm_ciphers; | |
3199 other_ciphers = chacha_ciphers; | |
3200 } | |
3201 unsigned i = CiphersCopy(preference_ciphers, ciphers.get()); | |
3202 CiphersCopy(other_ciphers, &ciphers[i]); | |
3203 | |
3204 rv = SSL_CipherOrderSet(nss_fd_, ciphers.get(), num_ciphers); | |
3205 if (rv != SECSuccess) { | |
3206 LogFailedNSSFunction(net_log_, "SSL_CipherOrderSet", ""); | |
3207 } | |
3208 } | |
3209 | |
3121 // Support RFC 5077 | 3210 // Support RFC 5077 |
3122 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE); | 3211 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE); |
3123 if (rv != SECSuccess) { | 3212 if (rv != SECSuccess) { |
3124 LogFailedNSSFunction( | 3213 LogFailedNSSFunction( |
3125 net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS"); | 3214 net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS"); |
3126 } | 3215 } |
3127 | 3216 |
3128 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALSE_START, | 3217 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALSE_START, |
3129 ssl_config_.false_start_enabled); | 3218 ssl_config_.false_start_enabled); |
3130 if (rv != SECSuccess) | 3219 if (rv != SECSuccess) |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3479 EnsureThreadIdAssigned(); | 3568 EnsureThreadIdAssigned(); |
3480 base::AutoLock auto_lock(lock_); | 3569 base::AutoLock auto_lock(lock_); |
3481 return valid_thread_id_ == base::PlatformThread::CurrentId(); | 3570 return valid_thread_id_ == base::PlatformThread::CurrentId(); |
3482 } | 3571 } |
3483 | 3572 |
3484 ServerBoundCertService* SSLClientSocketNSS::GetServerBoundCertService() const { | 3573 ServerBoundCertService* SSLClientSocketNSS::GetServerBoundCertService() const { |
3485 return server_bound_cert_service_; | 3574 return server_bound_cert_service_; |
3486 } | 3575 } |
3487 | 3576 |
3488 } // namespace net | 3577 } // namespace net |
OLD | NEW |