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