ssl_cipherorder_unittest.cc (9416B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "ssl.h" 8 #include "sslerr.h" 9 #include "sslproto.h" 10 11 #include <memory> 12 13 #include "tls_connect.h" 14 #include "tls_filter.h" 15 16 namespace nss_test { 17 18 class TlsCipherOrderTest : public TlsConnectTestBase { 19 protected: 20 virtual void ConfigureTLS() { 21 EnsureTlsSetup(); 22 ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); 23 } 24 25 virtual SECStatus BuildTestLists(std::vector<uint16_t> &cs_initial_list, 26 std::vector<uint16_t> &cs_new_list) { 27 // This is the current CipherSuites order of enabled CipherSuites as defined 28 // in ssl3con.c 29 const PRUint16 *kCipherSuites = SSL_GetImplementedCiphers(); 30 31 for (unsigned int i = 0; i < kNumImplementedCiphers; i++) { 32 PRBool pref = PR_FALSE, policy = PR_FALSE; 33 SECStatus rv; 34 rv = SSL_CipherPolicyGet(kCipherSuites[i], &policy); 35 if (rv != SECSuccess) { 36 return SECFailure; 37 } 38 rv = SSL_CipherPrefGetDefault(kCipherSuites[i], &pref); 39 if (rv != SECSuccess) { 40 return SECFailure; 41 } 42 if (pref && policy) { 43 cs_initial_list.push_back(kCipherSuites[i]); 44 } 45 } 46 47 // We will test set function with the first 15 enabled ciphers. 48 const PRUint16 kNumCiphersToSet = 15; 49 for (unsigned int i = 0; i < kNumCiphersToSet; i++) { 50 cs_new_list.push_back(cs_initial_list[i]); 51 } 52 cs_new_list[0] = cs_initial_list[1]; 53 cs_new_list[1] = cs_initial_list[0]; 54 return SECSuccess; 55 } 56 57 public: 58 TlsCipherOrderTest() : TlsConnectTestBase(ssl_variant_stream, 0) {} 59 const unsigned int kNumImplementedCiphers = SSL_GetNumImplementedCiphers(); 60 }; 61 62 const PRUint16 kCSUnsupported[] = {20196, 10101}; 63 const PRUint16 kNumCSUnsupported = PR_ARRAY_SIZE(kCSUnsupported); 64 const PRUint16 kCSEmpty[] = {0}; 65 66 // Get the active CipherSuites odered as they were compiled 67 TEST_F(TlsCipherOrderTest, CipherOrderGet) { 68 std::vector<uint16_t> initial_cs_order; 69 std::vector<uint16_t> new_cs_order; 70 SECStatus result = BuildTestLists(initial_cs_order, new_cs_order); 71 ASSERT_EQ(result, SECSuccess); 72 ConfigureTLS(); 73 74 std::vector<uint16_t> current_cs_order(SSL_GetNumImplementedCiphers() + 1); 75 unsigned int current_num_active_cs = 0; 76 result = SSL_CipherSuiteOrderGet(client_->ssl_fd(), current_cs_order.data(), 77 ¤t_num_active_cs); 78 ASSERT_EQ(result, SECSuccess); 79 ASSERT_EQ(current_num_active_cs, initial_cs_order.size()); 80 for (unsigned int i = 0; i < initial_cs_order.size(); i++) { 81 EXPECT_EQ(initial_cs_order[i], current_cs_order[i]); 82 } 83 // Get the chosen CipherSuite during the Handshake without any modification. 84 Connect(); 85 SSLChannelInfo channel; 86 result = SSL_GetChannelInfo(client_->ssl_fd(), &channel, sizeof channel); 87 ASSERT_EQ(result, SECSuccess); 88 EXPECT_EQ(channel.cipherSuite, initial_cs_order[0]); 89 } 90 91 // The "server" used for gtests honor only its ciphersuites order. 92 // So, we apply the new set for the server instead of client. 93 // This is enough to test the effect of SSL_CipherSuiteOrderSet function. 94 TEST_F(TlsCipherOrderTest, CipherOrderSet) { 95 std::vector<uint16_t> initial_cs_order; 96 std::vector<uint16_t> new_cs_order; 97 SECStatus result = BuildTestLists(initial_cs_order, new_cs_order); 98 ASSERT_EQ(result, SECSuccess); 99 ConfigureTLS(); 100 101 // change the server_ ciphersuites order. 102 result = SSL_CipherSuiteOrderSet(server_->ssl_fd(), new_cs_order.data(), 103 new_cs_order.size()); 104 ASSERT_EQ(result, SECSuccess); 105 106 // The function expect an array. We are using vector for VStudio 107 // compatibility. 108 std::vector<uint16_t> current_cs_order(SSL_GetNumImplementedCiphers() + 1); 109 unsigned int current_num_active_cs = 0; 110 result = SSL_CipherSuiteOrderGet(server_->ssl_fd(), current_cs_order.data(), 111 ¤t_num_active_cs); 112 ASSERT_EQ(result, SECSuccess); 113 ASSERT_EQ(current_num_active_cs, new_cs_order.size()); 114 for (unsigned int i = 0; i < new_cs_order.size(); i++) { 115 ASSERT_EQ(new_cs_order[i], current_cs_order[i]); 116 } 117 118 Connect(); 119 SSLChannelInfo channel; 120 // changes in server_ order reflect in client chosen ciphersuite. 121 result = SSL_GetChannelInfo(client_->ssl_fd(), &channel, sizeof channel); 122 ASSERT_EQ(result, SECSuccess); 123 EXPECT_EQ(channel.cipherSuite, new_cs_order[0]); 124 } 125 126 // Duplicate socket configuration from a model. 127 TEST_F(TlsCipherOrderTest, CipherOrderCopySocket) { 128 std::vector<uint16_t> initial_cs_order; 129 std::vector<uint16_t> new_cs_order; 130 SECStatus result = BuildTestLists(initial_cs_order, new_cs_order); 131 ASSERT_EQ(result, SECSuccess); 132 ConfigureTLS(); 133 134 // Use the existing sockets for this test. 135 result = SSL_CipherSuiteOrderSet(client_->ssl_fd(), new_cs_order.data(), 136 new_cs_order.size()); 137 ASSERT_EQ(result, SECSuccess); 138 139 std::vector<uint16_t> current_cs_order(SSL_GetNumImplementedCiphers() + 1); 140 unsigned int current_num_active_cs = 0; 141 result = SSL_CipherSuiteOrderGet(server_->ssl_fd(), current_cs_order.data(), 142 ¤t_num_active_cs); 143 ASSERT_EQ(result, SECSuccess); 144 ASSERT_EQ(current_num_active_cs, initial_cs_order.size()); 145 for (unsigned int i = 0; i < current_num_active_cs; i++) { 146 ASSERT_EQ(initial_cs_order[i], current_cs_order[i]); 147 } 148 149 // Import/Duplicate configurations from client_ to server_ 150 PRFileDesc *rv = SSL_ImportFD(client_->ssl_fd(), server_->ssl_fd()); 151 EXPECT_NE(nullptr, rv); 152 153 result = SSL_CipherSuiteOrderGet(server_->ssl_fd(), current_cs_order.data(), 154 ¤t_num_active_cs); 155 ASSERT_EQ(result, SECSuccess); 156 ASSERT_EQ(current_num_active_cs, new_cs_order.size()); 157 for (unsigned int i = 0; i < new_cs_order.size(); i++) { 158 EXPECT_EQ(new_cs_order.data()[i], current_cs_order[i]); 159 } 160 } 161 162 // If the infomed num of elements is lower than the actual list size, only the 163 // first "informed num" elements will be considered. The rest is ignored. 164 TEST_F(TlsCipherOrderTest, CipherOrderSetLower) { 165 std::vector<uint16_t> initial_cs_order; 166 std::vector<uint16_t> new_cs_order; 167 SECStatus result = BuildTestLists(initial_cs_order, new_cs_order); 168 ASSERT_EQ(result, SECSuccess); 169 ConfigureTLS(); 170 171 result = SSL_CipherSuiteOrderSet(client_->ssl_fd(), new_cs_order.data(), 172 new_cs_order.size() - 1); 173 ASSERT_EQ(result, SECSuccess); 174 175 std::vector<uint16_t> current_cs_order(SSL_GetNumImplementedCiphers() + 1); 176 unsigned int current_num_active_cs = 0; 177 result = SSL_CipherSuiteOrderGet(client_->ssl_fd(), current_cs_order.data(), 178 ¤t_num_active_cs); 179 ASSERT_EQ(result, SECSuccess); 180 ASSERT_EQ(current_num_active_cs, new_cs_order.size() - 1); 181 for (unsigned int i = 0; i < new_cs_order.size() - 1; i++) { 182 ASSERT_EQ(new_cs_order.data()[i], current_cs_order[i]); 183 } 184 } 185 186 // Testing Errors Controls 187 TEST_F(TlsCipherOrderTest, CipherOrderSetControls) { 188 std::vector<uint16_t> initial_cs_order; 189 std::vector<uint16_t> new_cs_order; 190 SECStatus result = BuildTestLists(initial_cs_order, new_cs_order); 191 ASSERT_EQ(result, SECSuccess); 192 ConfigureTLS(); 193 194 // Create a new vector with diplicated entries 195 std::vector<uint16_t> repeated_cs_order(SSL_GetNumImplementedCiphers() + 1); 196 std::copy(initial_cs_order.begin(), initial_cs_order.end(), 197 repeated_cs_order.begin()); 198 repeated_cs_order[0] = repeated_cs_order[1]; 199 200 // Repeated ciphersuites in the list 201 result = SSL_CipherSuiteOrderSet(client_->ssl_fd(), repeated_cs_order.data(), 202 initial_cs_order.size()); 203 EXPECT_EQ(result, SECFailure); 204 205 // Zero size for the sent list 206 result = SSL_CipherSuiteOrderSet(client_->ssl_fd(), new_cs_order.data(), 0); 207 EXPECT_EQ(result, SECFailure); 208 209 // Wrong size, greater than actual 210 result = SSL_CipherSuiteOrderSet(client_->ssl_fd(), new_cs_order.data(), 211 SSL_GetNumImplementedCiphers() + 1); 212 EXPECT_EQ(result, SECFailure); 213 214 // Wrong ciphersuites, not implemented 215 result = SSL_CipherSuiteOrderSet(client_->ssl_fd(), kCSUnsupported, 216 kNumCSUnsupported); 217 EXPECT_EQ(result, SECFailure); 218 219 // Null list 220 result = 221 SSL_CipherSuiteOrderSet(client_->ssl_fd(), nullptr, new_cs_order.size()); 222 EXPECT_EQ(result, SECFailure); 223 224 // Empty list 225 result = 226 SSL_CipherSuiteOrderSet(client_->ssl_fd(), kCSEmpty, new_cs_order.size()); 227 EXPECT_EQ(result, SECFailure); 228 229 // Confirm that the controls are working, as the current ciphersuites 230 // remained untouched 231 std::vector<uint16_t> current_cs_order(SSL_GetNumImplementedCiphers() + 1); 232 unsigned int current_num_active_cs = 0; 233 result = SSL_CipherSuiteOrderGet(client_->ssl_fd(), current_cs_order.data(), 234 ¤t_num_active_cs); 235 ASSERT_EQ(result, SECSuccess); 236 ASSERT_EQ(current_num_active_cs, initial_cs_order.size()); 237 for (unsigned int i = 0; i < initial_cs_order.size(); i++) { 238 ASSERT_EQ(initial_cs_order[i], current_cs_order[i]); 239 } 240 } 241 } // namespace nss_test