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(TlsAgent * client,TlsAgent * server,bool context)17 static void ExportAndCompare(TlsAgent* client, TlsAgent* server, bool context) {
18   static const size_t exporter_len = 10;
19   uint8_t client_value[exporter_len] = {0};
20   EXPECT_EQ(SECSuccess,
21             SSL_ExportKeyingMaterial(
22                 client->ssl_fd(), kExporterLabel, strlen(kExporterLabel),
23                 context ? PR_TRUE : PR_FALSE, kExporterContext,
24                 sizeof(kExporterContext), client_value, sizeof(client_value)));
25   uint8_t server_value[exporter_len] = {0xff};
26   EXPECT_EQ(SECSuccess,
27             SSL_ExportKeyingMaterial(
28                 server->ssl_fd(), kExporterLabel, strlen(kExporterLabel),
29                 context ? PR_TRUE : PR_FALSE, kExporterContext,
30                 sizeof(kExporterContext), server_value, sizeof(server_value)));
31   EXPECT_EQ(0, memcmp(client_value, server_value, sizeof(client_value)));
32 }
33 
TEST_P(TlsConnectGeneric,ExporterBasic)34 TEST_P(TlsConnectGeneric, ExporterBasic) {
35   EnsureTlsSetup();
36   if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
37     server_->EnableSingleCipher(TLS_AES_128_GCM_SHA256);
38   } else {
39     server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
40   }
41   Connect();
42   CheckKeys();
43   ExportAndCompare(client_, server_, false);
44 }
45 
TEST_P(TlsConnectGeneric,ExporterContext)46 TEST_P(TlsConnectGeneric, ExporterContext) {
47   EnsureTlsSetup();
48   if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
49     server_->EnableSingleCipher(TLS_AES_128_GCM_SHA256);
50   } else {
51     server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
52   }
53   Connect();
54   CheckKeys();
55   ExportAndCompare(client_, server_, true);
56 }
57 
58 // Bug 1312976 - SHA-384 doesn't work in 1.2 right now.
TEST_P(TlsConnectTls13,ExporterSha384)59 TEST_P(TlsConnectTls13, ExporterSha384) {
60   EnsureTlsSetup();
61   client_->EnableSingleCipher(TLS_AES_256_GCM_SHA384);
62   Connect();
63   CheckKeys();
64   ExportAndCompare(client_, server_, false);
65 }
66 
TEST_P(TlsConnectTls13,ExporterContextEmptyIsSameAsNone)67 TEST_P(TlsConnectTls13, ExporterContextEmptyIsSameAsNone) {
68   EnsureTlsSetup();
69   if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
70     server_->EnableSingleCipher(TLS_AES_128_GCM_SHA256);
71   } else {
72     server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
73   }
74   Connect();
75   CheckKeys();
76   ExportAndCompare(client_, server_, false);
77 }
78 
79 // This has a weird signature so that it can be passed to the SNI callback.
RegularExporterShouldFail(TlsAgent * agent,const SECItem * srvNameArr,PRUint32 srvNameArrSize)80 int32_t RegularExporterShouldFail(TlsAgent* agent, const SECItem* srvNameArr,
81                                   PRUint32 srvNameArrSize) {
82   uint8_t val[10];
83   EXPECT_EQ(SECFailure, SSL_ExportKeyingMaterial(
84                             agent->ssl_fd(), kExporterLabel,
85                             strlen(kExporterLabel), PR_TRUE, kExporterContext,
86                             sizeof(kExporterContext), val, sizeof(val)))
87       << "regular exporter should fail";
88   return 0;
89 }
90 
TEST_P(TlsConnectTls13,EarlyExporter)91 TEST_P(TlsConnectTls13, EarlyExporter) {
92   SetupForZeroRtt();
93   client_->Set0RttEnabled(true);
94   server_->Set0RttEnabled(true);
95   ExpectResumption(RESUME_TICKET);
96 
97   client_->Handshake();  // Send ClientHello.
98   uint8_t client_value[10] = {0};
99   RegularExporterShouldFail(client_, nullptr, 0);
100   EXPECT_EQ(SECSuccess,
101             SSL_ExportEarlyKeyingMaterial(
102                 client_->ssl_fd(), kExporterLabel, strlen(kExporterLabel),
103                 kExporterContext, sizeof(kExporterContext), client_value,
104                 sizeof(client_value)));
105 
106   server_->SetSniCallback(RegularExporterShouldFail);
107   server_->Handshake();  // Handle ClientHello.
108   uint8_t server_value[10] = {0};
109   EXPECT_EQ(SECSuccess,
110             SSL_ExportEarlyKeyingMaterial(
111                 server_->ssl_fd(), kExporterLabel, strlen(kExporterLabel),
112                 kExporterContext, sizeof(kExporterContext), server_value,
113                 sizeof(server_value)));
114   EXPECT_EQ(0, memcmp(client_value, server_value, sizeof(client_value)));
115 
116   Handshake();
117   ExpectEarlyDataAccepted(true);
118   CheckConnected();
119   SendReceive();
120 }
121 
122 }  // namespace nss_test
123