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
9 #include "gtest_utils.h"
10 #include "tls_connect.h"
11
12 namespace nss_test {
13
14 static const char* kExporterLabel = "EXPORTER-duck";
15 static const uint8_t kExporterContext[] = {0x12, 0x34, 0x56};
16
ExportAndCompare(std::shared_ptr<TlsAgent> & client,std::shared_ptr<TlsAgent> & server,bool context)17 static void ExportAndCompare(std::shared_ptr<TlsAgent>& client,
18 std::shared_ptr<TlsAgent>& server, bool context) {
19 static const size_t exporter_len = 10;
20 uint8_t client_value[exporter_len] = {0};
21 EXPECT_EQ(SECSuccess,
22 SSL_ExportKeyingMaterial(
23 client->ssl_fd(), kExporterLabel, strlen(kExporterLabel),
24 context ? PR_TRUE : PR_FALSE, kExporterContext,
25 sizeof(kExporterContext), client_value, sizeof(client_value)));
26 uint8_t server_value[exporter_len] = {0xff};
27 EXPECT_EQ(SECSuccess,
28 SSL_ExportKeyingMaterial(
29 server->ssl_fd(), kExporterLabel, strlen(kExporterLabel),
30 context ? PR_TRUE : PR_FALSE, kExporterContext,
31 sizeof(kExporterContext), server_value, sizeof(server_value)));
32 EXPECT_EQ(0, memcmp(client_value, server_value, sizeof(client_value)));
33 }
34
TEST_P(TlsConnectGeneric,ExporterBasic)35 TEST_P(TlsConnectGeneric, ExporterBasic) {
36 EnsureTlsSetup();
37 if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
38 server_->EnableSingleCipher(TLS_AES_128_GCM_SHA256);
39 } else {
40 server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
41 }
42 Connect();
43 CheckKeys();
44 ExportAndCompare(client_, server_, false);
45 }
46
TEST_P(TlsConnectGeneric,ExporterContext)47 TEST_P(TlsConnectGeneric, ExporterContext) {
48 EnsureTlsSetup();
49 if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
50 server_->EnableSingleCipher(TLS_AES_128_GCM_SHA256);
51 } else {
52 server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
53 }
54 Connect();
55 CheckKeys();
56 ExportAndCompare(client_, server_, true);
57 }
58
59 // Bug 1312976 - SHA-384 doesn't work in 1.2 right now.
TEST_P(TlsConnectTls13,ExporterSha384)60 TEST_P(TlsConnectTls13, ExporterSha384) {
61 EnsureTlsSetup();
62 client_->EnableSingleCipher(TLS_AES_256_GCM_SHA384);
63 Connect();
64 CheckKeys();
65 ExportAndCompare(client_, server_, false);
66 }
67
TEST_P(TlsConnectTls13,ExporterContextEmptyIsSameAsNone)68 TEST_P(TlsConnectTls13, ExporterContextEmptyIsSameAsNone) {
69 EnsureTlsSetup();
70 if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
71 server_->EnableSingleCipher(TLS_AES_128_GCM_SHA256);
72 } else {
73 server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
74 }
75 Connect();
76 CheckKeys();
77 ExportAndCompare(client_, server_, false);
78 }
79
TEST_P(TlsConnectGenericPre13,ExporterContextLengthTooLong)80 TEST_P(TlsConnectGenericPre13, ExporterContextLengthTooLong) {
81 static const uint8_t kExporterContextTooLong[PR_UINT16_MAX] = {
82 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF};
83
84 EnsureTlsSetup();
85 Connect();
86 CheckKeys();
87
88 static const size_t exporter_len = 10;
89 uint8_t client_value[exporter_len] = {0};
90 EXPECT_EQ(SECFailure,
91 SSL_ExportKeyingMaterial(client_->ssl_fd(), kExporterLabel,
92 strlen(kExporterLabel), PR_TRUE,
93 kExporterContextTooLong,
94 sizeof(kExporterContextTooLong),
95 client_value, sizeof(client_value)));
96 EXPECT_EQ(PORT_GetError(), SEC_ERROR_INVALID_ARGS);
97 uint8_t server_value[exporter_len] = {0xff};
98 EXPECT_EQ(SECFailure,
99 SSL_ExportKeyingMaterial(server_->ssl_fd(), kExporterLabel,
100 strlen(kExporterLabel), PR_TRUE,
101 kExporterContextTooLong,
102 sizeof(kExporterContextTooLong),
103 server_value, sizeof(server_value)));
104 EXPECT_EQ(PORT_GetError(), SEC_ERROR_INVALID_ARGS);
105 }
106
107 // This has a weird signature so that it can be passed to the SNI callback.
RegularExporterShouldFail(TlsAgent * agent,const SECItem * srvNameArr,PRUint32 srvNameArrSize)108 int32_t RegularExporterShouldFail(TlsAgent* agent, const SECItem* srvNameArr,
109 PRUint32 srvNameArrSize) {
110 uint8_t val[10];
111 EXPECT_EQ(SECFailure, SSL_ExportKeyingMaterial(
112 agent->ssl_fd(), kExporterLabel,
113 strlen(kExporterLabel), PR_TRUE, kExporterContext,
114 sizeof(kExporterContext), val, sizeof(val)))
115 << "regular exporter should fail";
116 return 0;
117 }
118
TEST_P(TlsConnectTls13,EarlyExporter)119 TEST_P(TlsConnectTls13, EarlyExporter) {
120 SetupForZeroRtt();
121 client_->Set0RttEnabled(true);
122 server_->Set0RttEnabled(true);
123 ExpectResumption(RESUME_TICKET);
124
125 client_->Handshake(); // Send ClientHello.
126 uint8_t client_value[10] = {0};
127 RegularExporterShouldFail(client_.get(), nullptr, 0);
128
129 EXPECT_EQ(SECSuccess,
130 SSL_ExportEarlyKeyingMaterial(
131 client_->ssl_fd(), kExporterLabel, strlen(kExporterLabel),
132 kExporterContext, sizeof(kExporterContext), client_value,
133 sizeof(client_value)));
134
135 server_->SetSniCallback(RegularExporterShouldFail);
136 server_->Handshake(); // Handle ClientHello.
137 uint8_t server_value[10] = {0};
138 EXPECT_EQ(SECSuccess,
139 SSL_ExportEarlyKeyingMaterial(
140 server_->ssl_fd(), kExporterLabel, strlen(kExporterLabel),
141 kExporterContext, sizeof(kExporterContext), server_value,
142 sizeof(server_value)));
143 EXPECT_EQ(0, memcmp(client_value, server_value, sizeof(client_value)));
144
145 Handshake();
146 ExpectEarlyDataAccepted(true);
147 CheckConnected();
148 SendReceive();
149 }
150
TEST_P(TlsConnectTls13,EarlyExporterExternalPsk)151 TEST_P(TlsConnectTls13, EarlyExporterExternalPsk) {
152 RolloverAntiReplay();
153 ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
154 ASSERT_TRUE(!!slot);
155 ScopedPK11SymKey scoped_psk(
156 PK11_KeyGen(slot.get(), CKM_HKDF_KEY_GEN, nullptr, 16, nullptr));
157 AddPsk(scoped_psk, std::string("foo"), ssl_hash_sha256,
158 TLS_CHACHA20_POLY1305_SHA256);
159 StartConnect();
160 client_->Set0RttEnabled(true);
161 server_->Set0RttEnabled(true);
162 client_->Handshake(); // Send ClientHello.
163 uint8_t client_value[10] = {0};
164 RegularExporterShouldFail(client_.get(), nullptr, 0);
165
166 EXPECT_EQ(SECSuccess,
167 SSL_ExportEarlyKeyingMaterial(
168 client_->ssl_fd(), kExporterLabel, strlen(kExporterLabel),
169 kExporterContext, sizeof(kExporterContext), client_value,
170 sizeof(client_value)));
171
172 server_->SetSniCallback(RegularExporterShouldFail);
173 server_->Handshake(); // Handle ClientHello.
174 uint8_t server_value[10] = {0};
175 EXPECT_EQ(SECSuccess,
176 SSL_ExportEarlyKeyingMaterial(
177 server_->ssl_fd(), kExporterLabel, strlen(kExporterLabel),
178 kExporterContext, sizeof(kExporterContext), server_value,
179 sizeof(server_value)));
180 EXPECT_EQ(0, memcmp(client_value, server_value, sizeof(client_value)));
181
182 Handshake();
183 ExpectEarlyDataAccepted(true);
184 CheckConnected();
185 SendReceive();
186 }
187
188 } // namespace nss_test
189