EncryptedClientHelloServer.cpp (6070B)
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 MOZ_RUNINIT 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 int32_t SetAlpnOptions(PRFileDesc* aFd, uint8_t flags) { 77 const std::vector<uint8_t> http1 = {0x08, 0x68, 0x74, 0x74, 0x70, 78 0x2f, 0x31, 0x2e, 0x31}; 79 const std::vector<uint8_t> http2 = {0x02, 0x68, 0x32}; 80 const std::vector<uint8_t> http3 = {0x02, 0x68, 0x33}; 81 std::vector<uint8_t> alpnVec = {}; 82 if (flags & 0b001) { 83 alpnVec.insert(alpnVec.end(), http1.begin(), http1.end()); 84 } 85 if (flags & 0b010) { 86 alpnVec.insert(alpnVec.end(), http2.begin(), http2.end()); 87 } 88 if (flags & 0b100) { 89 alpnVec.insert(alpnVec.end(), http3.begin(), http3.end()); 90 } 91 fprintf(stderr, "ALPN Flags: %u\n", flags); 92 fprintf(stderr, "ALPN length: %zu\n", alpnVec.size()); 93 if (SSL_SetNextProtoNego(aFd, alpnVec.data(), alpnVec.size()) != SECSuccess) { 94 fprintf(stderr, "Setting ALPN failed!\n"); 95 return 1; 96 } 97 98 return 0; 99 } 100 101 SECStatus ConfigureServer(PRFileDesc* aFd) { 102 const char* alpnFlag = PR_GetEnv("MOZ_TLS_ECH_ALPN_FLAG"); 103 if (alpnFlag) { 104 uint8_t flag = atoi(alpnFlag); 105 SetAlpnOptions(aFd, flag); 106 } 107 108 UniquePK11SlotInfo slot(PK11_GetInternalKeySlot()); 109 if (!slot) { 110 PrintPRError("PK11_GetInternalKeySlot failed"); 111 return SECFailure; 112 } 113 114 UniqueSECKEYPublicKey pubKey; 115 UniqueSECKEYPrivateKey privKey; 116 SECKEYPublicKey* tmpPubKey = nullptr; 117 SECKEYPrivateKey* tmpPrivKey = nullptr; 118 119 static const std::vector<uint8_t> pkcs8{ 120 0x30, 0x67, 0x02, 0x01, 0x00, 0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, 0x48, 121 0xce, 0x3d, 0x02, 0x01, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 122 0x47, 0x0f, 0x01, 0x04, 0x4c, 0x30, 0x4a, 0x02, 0x01, 0x01, 0x04, 0x20, 123 0x8c, 0x49, 0x0e, 0x5b, 0x0c, 0x7d, 0xbe, 0x0c, 0x6d, 0x21, 0x92, 0x48, 124 0x4d, 0x2b, 0x7a, 0x04, 0x23, 0xb3, 0xb4, 0x54, 0x4f, 0x24, 0x81, 0x09, 125 0x5a, 0x99, 0xdb, 0xf2, 0x38, 0xfb, 0x35, 0x0f, 0xa1, 0x23, 0x03, 0x21, 126 0x00, 0x8a, 0x07, 0x56, 0x39, 0x49, 0xfa, 0xc6, 0x23, 0x29, 0x36, 0xed, 127 0x6f, 0x36, 0xc4, 0xfa, 0x73, 0x59, 0x30, 0xec, 0xde, 0xae, 0xf6, 0x73, 128 0x4e, 0x31, 0x4a, 0xea, 0xc3, 0x5a, 0x56, 0xfd, 0x0a}; 129 130 SECItem pkcs8Item = {siBuffer, const_cast<uint8_t*>(pkcs8.data()), 131 static_cast<unsigned int>(pkcs8.size())}; 132 SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( 133 slot.get(), &pkcs8Item, nullptr, nullptr, false, false, KU_ALL, 134 &tmpPrivKey, nullptr); 135 136 if (rv != SECSuccess) { 137 PrintPRError("PK11_ImportDERPrivateKeyInfoAndReturnKey failed"); 138 return SECFailure; 139 } 140 privKey.reset(tmpPrivKey); 141 tmpPubKey = SECKEY_ConvertToPublicKey(privKey.get()); 142 pubKey.reset(tmpPubKey); 143 144 if (!privKey || !pubKey) { 145 PrintPRError("ECH/HPKE Public or Private key is null!"); 146 return SECFailure; 147 } 148 149 std::vector<uint8_t> echConfig(1000, 0); 150 unsigned int len = 0; 151 const PRUint8 configId = 77; 152 const HpkeSymmetricSuite echCipherSuite = {HpkeKdfHkdfSha256, 153 HpkeAeadChaCha20Poly1305}; 154 rv = SSL_EncodeEchConfigId(configId, "ech-public.example.com", 100, 155 HpkeDhKemX25519Sha256, pubKey.get(), 156 &echCipherSuite, 1, echConfig.data(), &len, 157 echConfig.size()); 158 if (rv != SECSuccess) { 159 PrintPRError("SSL_EncodeEchConfig failed"); 160 return rv; 161 } 162 163 rv = SSL_SetServerEchConfigs(aFd, pubKey.get(), privKey.get(), 164 echConfig.data(), len); 165 if (rv != SECSuccess) { 166 PrintPRError("SSL_SetServerEchConfigs failed"); 167 return rv; 168 } 169 170 return SECSuccess; 171 } 172 173 int main(int argc, char* argv[]) { 174 int rv = StartServer(argc, argv, DoSNISocketConfig, nullptr, ConfigureServer); 175 if (rv < 0) { 176 return rv; 177 } 178 }