1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 // This is a standalone server that offers TLS 1.3 Encrypted
6 // Client Hello support.
7 
8 #include <stdio.h>
9 
10 #include "nspr.h"
11 #include "ScopedNSSTypes.h"
12 #include "ssl.h"
13 #include "sslexp.h"
14 #include "TLSServer.h"
15 #include <pk11pub.h>
16 #include <vector>
17 
18 using namespace mozilla;
19 using namespace mozilla::test;
20 
21 struct EchHost {
22   const char* mHostName;
23   const char* mCertName;
24 };
25 
26 const std::vector<uint32_t> kSuiteChaCha = {
27     (static_cast<uint32_t>(HpkeKdfHkdfSha256) << 16) |
28     HpkeAeadChaCha20Poly1305};
29 
30 // Hostname, cert nickname pairs.
31 const EchHost sEchHosts[] = {{"ech-public.example.com", "default-ee"},
32                              {"ech-private.example.com", "private-ee"},
33                              {"selfsigned.example.com", "selfsigned"},
34                              {nullptr, nullptr}};
35 
36 int32_t DoSNISocketConfigBySubjectCN(PRFileDesc* aFd,
37                                      const SECItem* aSrvNameArr,
38                                      uint32_t aSrvNameArrSize) {
39   for (uint32_t i = 0; i < aSrvNameArrSize; i++) {
40     UniquePORTString name(
41         static_cast<char*>(PORT_ZAlloc(aSrvNameArr[i].len + 1)));
42     if (name) {
43       PORT_Memcpy(name.get(), aSrvNameArr[i].data, aSrvNameArr[i].len);
44       if (ConfigSecureServerWithNamedCert(aFd, name.get(), nullptr, nullptr,
45                                           nullptr) == SECSuccess) {
46         return 0;
47       }
48     }
49   }
50 
51   return SSL_SNI_SEND_ALERT;
52 }
53 
54 int32_t DoSNISocketConfig(PRFileDesc* aFd, const SECItem* aSrvNameArr,
55                           uint32_t aSrvNameArrSize, void* aArg) {
56   const EchHost* host = GetHostForSNI(aSrvNameArr, aSrvNameArrSize, sEchHosts);
57   if (!host) {
58     PrintPRError("No cert found for hostname");
59     return SSL_SNI_SEND_ALERT;
60   }
61 
62   if (gDebugLevel >= DEBUG_VERBOSE) {
63     fprintf(stderr, "found pre-defined host '%s'\n", host->mHostName);
64   }
65 
66   UniqueCERTCertificate cert;
67   SSLKEAType certKEA;
68   if (SECSuccess != ConfigSecureServerWithNamedCert(aFd, host->mCertName, &cert,
69                                                     &certKEA, nullptr)) {
70     return SSL_SNI_SEND_ALERT;
71   }
72 
73   return 0;
74 }
75 
76 SECStatus ConfigureServer(PRFileDesc* aFd) {
77   UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
78   if (!slot) {
79     PrintPRError("PK11_GetInternalKeySlot failed");
80     return SECFailure;
81   }
82 
83   UniqueSECKEYPublicKey pubKey;
84   UniqueSECKEYPrivateKey privKey;
85   SECKEYPublicKey* tmpPubKey = nullptr;
86   SECKEYPrivateKey* tmpPrivKey = nullptr;
87 
88   static const std::vector<uint8_t> pkcs8{
89       0x30, 0x67, 0x02, 0x01, 0x00, 0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, 0x48,
90       0xce, 0x3d, 0x02, 0x01, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda,
91       0x47, 0x0f, 0x01, 0x04, 0x4c, 0x30, 0x4a, 0x02, 0x01, 0x01, 0x04, 0x20,
92       0x8c, 0x49, 0x0e, 0x5b, 0x0c, 0x7d, 0xbe, 0x0c, 0x6d, 0x21, 0x92, 0x48,
93       0x4d, 0x2b, 0x7a, 0x04, 0x23, 0xb3, 0xb4, 0x54, 0x4f, 0x24, 0x81, 0x09,
94       0x5a, 0x99, 0xdb, 0xf2, 0x38, 0xfb, 0x35, 0x0f, 0xa1, 0x23, 0x03, 0x21,
95       0x00, 0x8a, 0x07, 0x56, 0x39, 0x49, 0xfa, 0xc6, 0x23, 0x29, 0x36, 0xed,
96       0x6f, 0x36, 0xc4, 0xfa, 0x73, 0x59, 0x30, 0xec, 0xde, 0xae, 0xf6, 0x73,
97       0x4e, 0x31, 0x4a, 0xea, 0xc3, 0x5a, 0x56, 0xfd, 0x0a};
98 
99   SECItem pkcs8Item = {siBuffer, const_cast<uint8_t*>(pkcs8.data()),
100                        static_cast<unsigned int>(pkcs8.size())};
101   SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
102       slot.get(), &pkcs8Item, nullptr, nullptr, false, false, KU_ALL,
103       &tmpPrivKey, nullptr);
104 
105   if (rv != SECSuccess) {
106     PrintPRError("PK11_ImportDERPrivateKeyInfoAndReturnKey failed");
107     return SECFailure;
108   }
109   privKey.reset(tmpPrivKey);
110   tmpPubKey = SECKEY_ConvertToPublicKey(privKey.get());
111   pubKey.reset(tmpPubKey);
112 
113   if (!privKey || !pubKey) {
114     PrintPRError("ECH/HPKE Public or Private key is null!");
115     return SECFailure;
116   }
117 
118   std::vector<uint8_t> echConfig(1000, 0);
119   unsigned int len = 0;
120   const PRUint8 configId = 77;
121   const HpkeSymmetricSuite echCipherSuite = {HpkeKdfHkdfSha256,
122                                              HpkeAeadChaCha20Poly1305};
123   rv = SSL_EncodeEchConfigId(configId, "ech-public.example.com", 100,
124                              HpkeDhKemX25519Sha256, pubKey.get(),
125                              &echCipherSuite, 1, echConfig.data(), &len,
126                              echConfig.size());
127   if (rv != SECSuccess) {
128     PrintPRError("SSL_EncodeEchConfig failed");
129     return rv;
130   }
131 
132   rv = SSL_SetServerEchConfigs(aFd, pubKey.get(), privKey.get(),
133                                echConfig.data(), len);
134   if (rv != SECSuccess) {
135     PrintPRError("SSL_SetServerEchConfigs failed");
136     return rv;
137   }
138 
139   return SECSuccess;
140 }
141 
142 int main(int argc, char* argv[]) {
143   int rv = StartServer(argc, argv, DoSNISocketConfig, nullptr, ConfigureServer);
144   if (rv < 0) {
145     return rv;
146   }
147 }
148