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