ssl_custext_unittest.cc (18654B)
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 "ssl3prot.h" 9 #include "sslerr.h" 10 #include "sslproto.h" 11 #include "sslexp.h" 12 13 #include <memory> 14 15 #include "tls_connect.h" 16 17 namespace nss_test { 18 19 static void IncrementCounterArg(void *arg) { 20 if (arg) { 21 auto *called = reinterpret_cast<size_t *>(arg); 22 ++*called; 23 } 24 } 25 26 static PRBool NoopExtensionWriter(PRFileDesc *fd, SSLHandshakeType message, 27 PRUint8 *data, unsigned int *len, 28 unsigned int maxLen, void *arg) { 29 IncrementCounterArg(arg); 30 return PR_FALSE; 31 } 32 33 static PRBool EmptyExtensionWriter(PRFileDesc *fd, SSLHandshakeType message, 34 PRUint8 *data, unsigned int *len, 35 unsigned int maxLen, void *arg) { 36 IncrementCounterArg(arg); 37 return PR_TRUE; 38 } 39 40 static SECStatus NoopExtensionHandler(PRFileDesc *fd, SSLHandshakeType message, 41 const PRUint8 *data, unsigned int len, 42 SSLAlertDescription *alert, void *arg) { 43 return SECSuccess; 44 } 45 46 // All of the (current) set of supported extensions, plus a few extra. 47 static const uint16_t kManyExtensions[] = { 48 ssl_server_name_xtn, 49 ssl_cert_status_xtn, 50 ssl_supported_groups_xtn, 51 ssl_ec_point_formats_xtn, 52 ssl_signature_algorithms_xtn, 53 ssl_signature_algorithms_cert_xtn, 54 ssl_use_srtp_xtn, 55 ssl_app_layer_protocol_xtn, 56 ssl_signed_cert_timestamp_xtn, 57 ssl_padding_xtn, 58 ssl_extended_master_secret_xtn, 59 ssl_certificate_compression_xtn, 60 ssl_session_ticket_xtn, 61 ssl_tls13_key_share_xtn, 62 ssl_tls13_pre_shared_key_xtn, 63 ssl_tls13_early_data_xtn, 64 ssl_tls13_supported_versions_xtn, 65 ssl_tls13_cookie_xtn, 66 ssl_tls13_psk_key_exchange_modes_xtn, 67 ssl_tls13_ticket_early_data_info_xtn, 68 ssl_tls13_certificate_authorities_xtn, 69 ssl_next_proto_nego_xtn, 70 ssl_renegotiation_info_xtn, 71 ssl_record_size_limit_xtn, 72 ssl_tls13_encrypted_client_hello_xtn, 73 1, 74 0xffff}; 75 // The list here includes all extensions we expect to use (SSL_MAX_EXTENSIONS), 76 // plus the deprecated values (see sslt.h), and two extra dummy values. 77 PR_STATIC_ASSERT((SSL_MAX_EXTENSIONS + 5) == PR_ARRAY_SIZE(kManyExtensions)); 78 79 void InstallManyWriters(std::shared_ptr<TlsAgent> agent, 80 SSLExtensionWriter writer, size_t *installed = nullptr, 81 size_t *called = nullptr) { 82 for (size_t i = 0; i < PR_ARRAY_SIZE(kManyExtensions); ++i) { 83 SSLExtensionSupport support = ssl_ext_none; 84 SECStatus rv = SSL_GetExtensionSupport(kManyExtensions[i], &support); 85 ASSERT_EQ(SECSuccess, rv) << "SSL_GetExtensionSupport cannot fail"; 86 87 rv = SSL_InstallExtensionHooks(agent->ssl_fd(), kManyExtensions[i], writer, 88 called, NoopExtensionHandler, nullptr); 89 if (support == ssl_ext_native_only) { 90 EXPECT_EQ(SECFailure, rv); 91 EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); 92 } else { 93 if (installed) { 94 ++*installed; 95 } 96 EXPECT_EQ(SECSuccess, rv); 97 } 98 } 99 } 100 101 TEST_F(TlsConnectStreamTls13, CustomExtensionAllNoopClient) { 102 EnsureTlsSetup(); 103 size_t installed = 0; 104 size_t called = 0; 105 InstallManyWriters(client_, NoopExtensionWriter, &installed, &called); 106 EXPECT_LT(0U, installed); 107 Connect(); 108 EXPECT_EQ(installed, called); 109 } 110 111 TEST_F(TlsConnectStreamTls13, CustomExtensionAllNoopServer) { 112 EnsureTlsSetup(); 113 size_t installed = 0; 114 size_t called = 0; 115 InstallManyWriters(server_, NoopExtensionWriter, &installed, &called); 116 EXPECT_LT(0U, installed); 117 Connect(); 118 // Extension writers are all called for each of ServerHello, 119 // EncryptedExtensions, and Certificate. 120 EXPECT_EQ(installed * 3, called); 121 } 122 123 TEST_F(TlsConnectStreamTls13, CustomExtensionEmptyWriterClient) { 124 EnsureTlsSetup(); 125 InstallManyWriters(client_, EmptyExtensionWriter); 126 InstallManyWriters(server_, EmptyExtensionWriter); 127 Connect(); 128 } 129 130 TEST_F(TlsConnectStreamTls13, CustomExtensionEmptyWriterServer) { 131 EnsureTlsSetup(); 132 InstallManyWriters(server_, EmptyExtensionWriter); 133 // Sending extensions that the client doesn't expect leads to extensions 134 // appearing even if the client didn't send one, or in the wrong messages. 135 client_->ExpectSendAlert(kTlsAlertUnsupportedExtension); 136 server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); 137 ConnectExpectFail(); 138 } 139 140 // Install an writer to disable sending of a natively-supported extension. 141 TEST_F(TlsConnectStreamTls13, CustomExtensionWriterDisable) { 142 EnsureTlsSetup(); 143 144 // This option enables sending the extension via the native support. 145 SECStatus rv = SSL_OptionSet(client_->ssl_fd(), 146 SSL_ENABLE_SIGNED_CERT_TIMESTAMPS, PR_TRUE); 147 EXPECT_EQ(SECSuccess, rv); 148 149 // This installs an override that doesn't do anything. You have to specify 150 // something; passing all nullptr values removes an existing handler. 151 rv = SSL_InstallExtensionHooks( 152 client_->ssl_fd(), ssl_signed_cert_timestamp_xtn, NoopExtensionWriter, 153 nullptr, NoopExtensionHandler, nullptr); 154 EXPECT_EQ(SECSuccess, rv); 155 auto capture = MakeTlsFilter<TlsExtensionCapture>( 156 client_, ssl_signed_cert_timestamp_xtn); 157 158 Connect(); 159 // So nothing will be sent. 160 EXPECT_FALSE(capture->captured()); 161 } 162 163 // An extension that is unlikely to be parsed as valid. 164 static uint8_t kNonsenseExtension[] = {91, 82, 73, 64, 55, 46, 37, 28, 19}; 165 166 static PRBool NonsenseExtensionWriter(PRFileDesc *fd, SSLHandshakeType message, 167 PRUint8 *data, unsigned int *len, 168 unsigned int maxLen, void *arg) { 169 TlsAgent *agent = reinterpret_cast<TlsAgent *>(arg); 170 EXPECT_NE(nullptr, agent); 171 EXPECT_NE(nullptr, data); 172 EXPECT_NE(nullptr, len); 173 EXPECT_EQ(0U, *len); 174 EXPECT_LT(0U, maxLen); 175 EXPECT_EQ(agent->ssl_fd(), fd); 176 177 if (message != ssl_hs_client_hello && message != ssl_hs_server_hello && 178 message != ssl_hs_encrypted_extensions) { 179 return PR_FALSE; 180 } 181 182 *len = static_cast<unsigned int>(sizeof(kNonsenseExtension)); 183 EXPECT_GE(maxLen, *len); 184 if (maxLen < *len) { 185 return PR_FALSE; 186 } 187 PORT_Memcpy(data, kNonsenseExtension, *len); 188 return PR_TRUE; 189 } 190 191 // Override the extension handler for an natively-supported and produce 192 // nonsense, which results in a handshake failure. 193 TEST_F(TlsConnectStreamTls13, CustomExtensionOverride) { 194 EnsureTlsSetup(); 195 196 // This option enables sending the extension via the native support. 197 SECStatus rv = SSL_OptionSet(client_->ssl_fd(), 198 SSL_ENABLE_SIGNED_CERT_TIMESTAMPS, PR_TRUE); 199 EXPECT_EQ(SECSuccess, rv); 200 201 // This installs an override that sends nonsense. 202 rv = SSL_InstallExtensionHooks( 203 client_->ssl_fd(), ssl_signed_cert_timestamp_xtn, NonsenseExtensionWriter, 204 client_.get(), NoopExtensionHandler, nullptr); 205 EXPECT_EQ(SECSuccess, rv); 206 207 // Capture it to see what we got. 208 auto capture = MakeTlsFilter<TlsExtensionCapture>( 209 client_, ssl_signed_cert_timestamp_xtn); 210 211 ConnectExpectAlert(server_, kTlsAlertDecodeError); 212 213 EXPECT_TRUE(capture->captured()); 214 EXPECT_EQ(DataBuffer(kNonsenseExtension, sizeof(kNonsenseExtension)), 215 capture->extension()); 216 } 217 218 static SECStatus NonsenseExtensionHandler(PRFileDesc *fd, 219 SSLHandshakeType message, 220 const PRUint8 *data, unsigned int len, 221 SSLAlertDescription *alert, 222 void *arg) { 223 TlsAgent *agent = reinterpret_cast<TlsAgent *>(arg); 224 EXPECT_EQ(agent->ssl_fd(), fd); 225 if (agent->role() == TlsAgent::SERVER) { 226 EXPECT_EQ(ssl_hs_client_hello, message); 227 } else { 228 EXPECT_TRUE(message == ssl_hs_server_hello || 229 message == ssl_hs_encrypted_extensions); 230 } 231 EXPECT_EQ(DataBuffer(kNonsenseExtension, sizeof(kNonsenseExtension)), 232 DataBuffer(data, len)); 233 EXPECT_NE(nullptr, alert); 234 return SECSuccess; 235 } 236 237 // Send nonsense in an extension from client to server. 238 TEST_F(TlsConnectStreamTls13, CustomExtensionClientToServer) { 239 EnsureTlsSetup(); 240 241 // This installs an override that sends nonsense. 242 const uint16_t extension_code = 0xffe5; 243 SECStatus rv = SSL_InstallExtensionHooks( 244 client_->ssl_fd(), extension_code, NonsenseExtensionWriter, client_.get(), 245 NoopExtensionHandler, nullptr); 246 EXPECT_EQ(SECSuccess, rv); 247 248 // Capture it to see what we got. 249 auto capture = MakeTlsFilter<TlsExtensionCapture>(client_, extension_code); 250 251 // Handle it so that the handshake completes. 252 rv = SSL_InstallExtensionHooks(server_->ssl_fd(), extension_code, 253 NoopExtensionWriter, nullptr, 254 NonsenseExtensionHandler, server_.get()); 255 EXPECT_EQ(SECSuccess, rv); 256 257 Connect(); 258 259 EXPECT_TRUE(capture->captured()); 260 EXPECT_EQ(DataBuffer(kNonsenseExtension, sizeof(kNonsenseExtension)), 261 capture->extension()); 262 } 263 264 static PRBool NonsenseExtensionWriterSH(PRFileDesc *fd, 265 SSLHandshakeType message, PRUint8 *data, 266 unsigned int *len, unsigned int maxLen, 267 void *arg) { 268 if (message == ssl_hs_server_hello) { 269 return NonsenseExtensionWriter(fd, message, data, len, maxLen, arg); 270 } 271 return PR_FALSE; 272 } 273 274 // Send nonsense in an extension from server to client, in ServerHello. 275 TEST_F(TlsConnectStreamTls13, CustomExtensionServerToClientSH) { 276 EnsureTlsSetup(); 277 278 // This installs an override that sends nothing but expects nonsense. 279 const uint16_t extension_code = 0xff5e; 280 SECStatus rv = SSL_InstallExtensionHooks( 281 client_->ssl_fd(), extension_code, EmptyExtensionWriter, nullptr, 282 NonsenseExtensionHandler, client_.get()); 283 EXPECT_EQ(SECSuccess, rv); 284 285 // Have the server send nonsense. 286 rv = SSL_InstallExtensionHooks(server_->ssl_fd(), extension_code, 287 NonsenseExtensionWriterSH, server_.get(), 288 NoopExtensionHandler, nullptr); 289 EXPECT_EQ(SECSuccess, rv); 290 291 // Capture the extension from the ServerHello only and check it. 292 auto capture = MakeTlsFilter<TlsExtensionCapture>(server_, extension_code); 293 capture->SetHandshakeTypes({kTlsHandshakeServerHello}); 294 295 Connect(); 296 297 EXPECT_TRUE(capture->captured()); 298 EXPECT_EQ(DataBuffer(kNonsenseExtension, sizeof(kNonsenseExtension)), 299 capture->extension()); 300 } 301 302 static PRBool NonsenseExtensionWriterEE(PRFileDesc *fd, 303 SSLHandshakeType message, PRUint8 *data, 304 unsigned int *len, unsigned int maxLen, 305 void *arg) { 306 if (message == ssl_hs_encrypted_extensions) { 307 return NonsenseExtensionWriter(fd, message, data, len, maxLen, arg); 308 } 309 return PR_FALSE; 310 } 311 312 // Send nonsense in an extension from server to client, in EncryptedExtensions. 313 TEST_F(TlsConnectStreamTls13, CustomExtensionServerToClientEE) { 314 EnsureTlsSetup(); 315 316 // This installs an override that sends nothing but expects nonsense. 317 const uint16_t extension_code = 0xff5e; 318 SECStatus rv = SSL_InstallExtensionHooks( 319 client_->ssl_fd(), extension_code, EmptyExtensionWriter, nullptr, 320 NonsenseExtensionHandler, client_.get()); 321 EXPECT_EQ(SECSuccess, rv); 322 323 // Have the server send nonsense. 324 rv = SSL_InstallExtensionHooks(server_->ssl_fd(), extension_code, 325 NonsenseExtensionWriterEE, server_.get(), 326 NoopExtensionHandler, nullptr); 327 EXPECT_EQ(SECSuccess, rv); 328 329 // Capture the extension from the EncryptedExtensions only and check it. 330 auto capture = MakeTlsFilter<TlsExtensionCapture>(server_, extension_code); 331 capture->SetHandshakeTypes({kTlsHandshakeEncryptedExtensions}); 332 capture->EnableDecryption(); 333 334 Connect(); 335 336 EXPECT_TRUE(capture->captured()); 337 EXPECT_EQ(DataBuffer(kNonsenseExtension, sizeof(kNonsenseExtension)), 338 capture->extension()); 339 } 340 341 TEST_F(TlsConnectStreamTls13, CustomExtensionUnsolicitedServer) { 342 EnsureTlsSetup(); 343 344 const uint16_t extension_code = 0xff5e; 345 SECStatus rv = SSL_InstallExtensionHooks( 346 server_->ssl_fd(), extension_code, NonsenseExtensionWriter, server_.get(), 347 NoopExtensionHandler, nullptr); 348 EXPECT_EQ(SECSuccess, rv); 349 350 // Capture it to see what we got. 351 auto capture = MakeTlsFilter<TlsExtensionCapture>(server_, extension_code); 352 353 client_->ExpectSendAlert(kTlsAlertUnsupportedExtension); 354 server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); 355 ConnectExpectFail(); 356 357 EXPECT_TRUE(capture->captured()); 358 EXPECT_EQ(DataBuffer(kNonsenseExtension, sizeof(kNonsenseExtension)), 359 capture->extension()); 360 } 361 362 SECStatus RejectExtensionHandler(PRFileDesc *fd, SSLHandshakeType message, 363 const PRUint8 *data, unsigned int len, 364 SSLAlertDescription *alert, void *arg) { 365 return SECFailure; 366 } 367 368 TEST_F(TlsConnectStreamTls13, CustomExtensionServerReject) { 369 EnsureTlsSetup(); 370 371 // This installs an override that sends nonsense. 372 const uint16_t extension_code = 0xffe7; 373 SECStatus rv = SSL_InstallExtensionHooks(client_->ssl_fd(), extension_code, 374 EmptyExtensionWriter, nullptr, 375 NoopExtensionHandler, nullptr); 376 EXPECT_EQ(SECSuccess, rv); 377 378 // Reject the extension for no good reason. 379 rv = SSL_InstallExtensionHooks(server_->ssl_fd(), extension_code, 380 NoopExtensionWriter, nullptr, 381 RejectExtensionHandler, nullptr); 382 EXPECT_EQ(SECSuccess, rv); 383 384 ConnectExpectAlert(server_, kTlsAlertHandshakeFailure); 385 } 386 387 // Send nonsense in an extension from client to server. 388 TEST_F(TlsConnectStreamTls13, CustomExtensionClientReject) { 389 EnsureTlsSetup(); 390 391 // This installs an override that sends nothing but expects nonsense. 392 const uint16_t extension_code = 0xff58; 393 SECStatus rv = SSL_InstallExtensionHooks(client_->ssl_fd(), extension_code, 394 EmptyExtensionWriter, nullptr, 395 RejectExtensionHandler, nullptr); 396 EXPECT_EQ(SECSuccess, rv); 397 398 // Have the server send nonsense. 399 rv = SSL_InstallExtensionHooks(server_->ssl_fd(), extension_code, 400 EmptyExtensionWriter, nullptr, 401 NoopExtensionHandler, nullptr); 402 EXPECT_EQ(SECSuccess, rv); 403 404 client_->ExpectSendAlert(kTlsAlertHandshakeFailure); 405 server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); 406 ConnectExpectFail(); 407 } 408 409 static const uint8_t kCustomAlert = 0xf6; 410 411 SECStatus AlertExtensionHandler(PRFileDesc *fd, SSLHandshakeType message, 412 const PRUint8 *data, unsigned int len, 413 SSLAlertDescription *alert, void *arg) { 414 *alert = kCustomAlert; 415 return SECFailure; 416 } 417 418 TEST_F(TlsConnectStreamTls13, CustomExtensionServerRejectAlert) { 419 EnsureTlsSetup(); 420 421 // This installs an override that sends nonsense. 422 const uint16_t extension_code = 0xffea; 423 SECStatus rv = SSL_InstallExtensionHooks(client_->ssl_fd(), extension_code, 424 EmptyExtensionWriter, nullptr, 425 NoopExtensionHandler, nullptr); 426 EXPECT_EQ(SECSuccess, rv); 427 428 // Reject the extension for no good reason. 429 rv = SSL_InstallExtensionHooks(server_->ssl_fd(), extension_code, 430 NoopExtensionWriter, nullptr, 431 AlertExtensionHandler, nullptr); 432 EXPECT_EQ(SECSuccess, rv); 433 434 ConnectExpectAlert(server_, kCustomAlert); 435 } 436 437 // Send nonsense in an extension from client to server. 438 TEST_F(TlsConnectStreamTls13, CustomExtensionClientRejectAlert) { 439 EnsureTlsSetup(); 440 441 // This installs an override that sends nothing but expects nonsense. 442 const uint16_t extension_code = 0xff5a; 443 SECStatus rv = SSL_InstallExtensionHooks(client_->ssl_fd(), extension_code, 444 EmptyExtensionWriter, nullptr, 445 AlertExtensionHandler, nullptr); 446 EXPECT_EQ(SECSuccess, rv); 447 448 // Have the server send nonsense. 449 rv = SSL_InstallExtensionHooks(server_->ssl_fd(), extension_code, 450 EmptyExtensionWriter, nullptr, 451 NoopExtensionHandler, nullptr); 452 EXPECT_EQ(SECSuccess, rv); 453 454 client_->ExpectSendAlert(kCustomAlert); 455 server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); 456 ConnectExpectFail(); 457 } 458 459 // Configure a custom extension hook badly. 460 TEST_F(TlsConnectStreamTls13, CustomExtensionOnlyWriter) { 461 EnsureTlsSetup(); 462 463 // This installs an override that sends nothing but expects nonsense. 464 SECStatus rv = 465 SSL_InstallExtensionHooks(client_->ssl_fd(), 0xff6c, EmptyExtensionWriter, 466 nullptr, nullptr, nullptr); 467 EXPECT_EQ(SECFailure, rv); 468 EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); 469 } 470 471 TEST_F(TlsConnectStreamTls13, CustomExtensionOnlyHandler) { 472 EnsureTlsSetup(); 473 474 // This installs an override that sends nothing but expects nonsense. 475 SECStatus rv = 476 SSL_InstallExtensionHooks(client_->ssl_fd(), 0xff6d, nullptr, nullptr, 477 NoopExtensionHandler, nullptr); 478 EXPECT_EQ(SECFailure, rv); 479 EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); 480 } 481 482 TEST_F(TlsConnectStreamTls13, CustomExtensionOverrunBuffer) { 483 EnsureTlsSetup(); 484 // This doesn't actually overrun the buffer, but it says that it does. 485 auto overrun_writer = [](PRFileDesc *fd, SSLHandshakeType message, 486 PRUint8 *data, unsigned int *len, 487 unsigned int maxLen, void *arg) -> PRBool { 488 *len = maxLen + 1; 489 return PR_TRUE; 490 }; 491 SECStatus rv = 492 SSL_InstallExtensionHooks(client_->ssl_fd(), 0xff71, overrun_writer, 493 nullptr, NoopExtensionHandler, nullptr); 494 EXPECT_EQ(SECSuccess, rv); 495 client_->StartConnect(); 496 client_->Handshake(); 497 client_->CheckErrorCode(SEC_ERROR_APPLICATION_CALLBACK_ERROR); 498 } 499 500 } // namespace nss_test