• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2014, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14 
15 #include <openssl/base.h>
16 
17 #include <memory>
18 
19 #include <openssl/err.h>
20 #include <openssl/hpke.h>
21 #include <openssl/rand.h>
22 #include <openssl/ssl.h>
23 
24 #include "internal.h"
25 #include "transport_common.h"
26 
27 
28 static const struct argument kArguments[] = {
29     {
30         "-accept", kRequiredArgument,
31         "The port of the server to bind on; eg 45102",
32     },
33     {
34         "-cipher", kOptionalArgument,
35         "An OpenSSL-style cipher suite string that configures the offered "
36         "ciphers",
37     },
38     {
39         "-curves", kOptionalArgument,
40         "An OpenSSL-style ECDH curves list that configures the offered curves",
41     },
42     {
43         "-max-version", kOptionalArgument,
44         "The maximum acceptable protocol version",
45     },
46     {
47         "-min-version", kOptionalArgument,
48         "The minimum acceptable protocol version",
49     },
50     {
51         "-key", kOptionalArgument,
52         "PEM-encoded file containing the private key. A self-signed "
53         "certificate is generated at runtime if this argument is not provided.",
54     },
55     {
56         "-cert", kOptionalArgument,
57         "PEM-encoded file containing the leaf certificate and optional "
58         "certificate chain. This is taken from the -key argument if this "
59         "argument is not provided.",
60     },
61     {
62         "-ocsp-response", kOptionalArgument, "OCSP response file to send",
63     },
64     {
65         "-ech-key",
66         kOptionalArgument,
67         "File containing the private key corresponding to the ECHConfig.",
68     },
69     {
70         "-ech-config",
71         kOptionalArgument,
72         "File containing one ECHConfig.",
73     },
74     {
75         "-loop", kBooleanArgument,
76         "The server will continue accepting new sequential connections.",
77     },
78     {
79         "-early-data", kBooleanArgument, "Allow early data",
80     },
81     {
82         "-www", kBooleanArgument,
83         "The server will print connection information in response to a "
84         "HTTP GET request.",
85     },
86     {
87         "-debug", kBooleanArgument,
88         "Print debug information about the handshake",
89     },
90     {
91         "-require-any-client-cert", kBooleanArgument,
92         "The server will require a client certificate.",
93     },
94     {
95         "-jdk11-workaround", kBooleanArgument,
96         "Enable the JDK 11 workaround",
97     },
98     {
99         "", kOptionalArgument, "",
100     },
101 };
102 
LoadOCSPResponse(SSL_CTX * ctx,const char * filename)103 static bool LoadOCSPResponse(SSL_CTX *ctx, const char *filename) {
104   ScopedFILE f(fopen(filename, "rb"));
105   std::vector<uint8_t> data;
106   if (f == nullptr ||
107       !ReadAll(&data, f.get())) {
108     fprintf(stderr, "Error reading %s.\n", filename);
109     return false;
110   }
111 
112   if (!SSL_CTX_set_ocsp_response(ctx, data.data(), data.size())) {
113     return false;
114   }
115 
116   return true;
117 }
118 
MakeKeyPairForSelfSignedCert()119 static bssl::UniquePtr<EVP_PKEY> MakeKeyPairForSelfSignedCert() {
120   bssl::UniquePtr<EC_KEY> ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
121   if (!ec_key || !EC_KEY_generate_key(ec_key.get())) {
122     fprintf(stderr, "Failed to generate key pair.\n");
123     return nullptr;
124   }
125   bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
126   if (!evp_pkey || !EVP_PKEY_assign_EC_KEY(evp_pkey.get(), ec_key.release())) {
127     fprintf(stderr, "Failed to assign key pair.\n");
128     return nullptr;
129   }
130   return evp_pkey;
131 }
132 
MakeSelfSignedCert(EVP_PKEY * evp_pkey,const int valid_days)133 static bssl::UniquePtr<X509> MakeSelfSignedCert(EVP_PKEY *evp_pkey,
134                                                 const int valid_days) {
135   bssl::UniquePtr<X509> x509(X509_new());
136   uint32_t serial;
137   RAND_bytes(reinterpret_cast<uint8_t*>(&serial), sizeof(serial));
138   ASN1_INTEGER_set(X509_get_serialNumber(x509.get()), serial >> 1);
139   X509_gmtime_adj(X509_get_notBefore(x509.get()), 0);
140   X509_gmtime_adj(X509_get_notAfter(x509.get()), 60 * 60 * 24 * valid_days);
141 
142   X509_NAME* subject = X509_get_subject_name(x509.get());
143   X509_NAME_add_entry_by_txt(subject, "C", MBSTRING_ASC,
144                              reinterpret_cast<const uint8_t *>("US"), -1, -1,
145                              0);
146   X509_NAME_add_entry_by_txt(subject, "O", MBSTRING_ASC,
147                              reinterpret_cast<const uint8_t *>("BoringSSL"), -1,
148                              -1, 0);
149   X509_set_issuer_name(x509.get(), subject);
150 
151   if (!X509_set_pubkey(x509.get(), evp_pkey)) {
152     fprintf(stderr, "Failed to set public key.\n");
153     return nullptr;
154   }
155   if (!X509_sign(x509.get(), evp_pkey, EVP_sha256())) {
156     fprintf(stderr, "Failed to sign certificate.\n");
157     return nullptr;
158   }
159   return x509;
160 }
161 
InfoCallback(const SSL * ssl,int type,int value)162 static void InfoCallback(const SSL *ssl, int type, int value) {
163   switch (type) {
164     case SSL_CB_HANDSHAKE_START:
165       fprintf(stderr, "Handshake started.\n");
166       break;
167     case SSL_CB_HANDSHAKE_DONE:
168       fprintf(stderr, "Handshake done.\n");
169       break;
170     case SSL_CB_ACCEPT_LOOP:
171       fprintf(stderr, "Handshake progress: %s\n", SSL_state_string_long(ssl));
172       break;
173   }
174 }
175 
176 static FILE *g_keylog_file = nullptr;
177 
KeyLogCallback(const SSL * ssl,const char * line)178 static void KeyLogCallback(const SSL *ssl, const char *line) {
179   fprintf(g_keylog_file, "%s\n", line);
180   fflush(g_keylog_file);
181 }
182 
HandleWWW(SSL * ssl)183 static bool HandleWWW(SSL *ssl) {
184   bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
185   if (!bio) {
186     fprintf(stderr, "Cannot create BIO for response\n");
187     return false;
188   }
189 
190   BIO_puts(bio.get(), "HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\n");
191   PrintConnectionInfo(bio.get(), ssl);
192 
193   char request[4];
194   size_t request_len = 0;
195   while (request_len < sizeof(request)) {
196     int ssl_ret =
197         SSL_read(ssl, request + request_len, sizeof(request) - request_len);
198     if (ssl_ret <= 0) {
199       int ssl_err = SSL_get_error(ssl, ssl_ret);
200       PrintSSLError(stderr, "Error while reading", ssl_err, ssl_ret);
201       return false;
202     }
203     request_len += static_cast<size_t>(ssl_ret);
204   }
205 
206   // Assume simple HTTP request, print status.
207   if (memcmp(request, "GET ", 4) == 0) {
208     const uint8_t *response;
209     size_t response_len;
210     if (BIO_mem_contents(bio.get(), &response, &response_len)) {
211       SSL_write(ssl, response, response_len);
212     }
213   }
214   return true;
215 }
216 
Server(const std::vector<std::string> & args)217 bool Server(const std::vector<std::string> &args) {
218   if (!InitSocketLibrary()) {
219     return false;
220   }
221 
222   std::map<std::string, std::string> args_map;
223 
224   if (!ParseKeyValueArguments(&args_map, args, kArguments)) {
225     PrintUsage(kArguments);
226     return false;
227   }
228 
229   bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
230 
231   const char *keylog_file = getenv("SSLKEYLOGFILE");
232   if (keylog_file) {
233     g_keylog_file = fopen(keylog_file, "a");
234     if (g_keylog_file == nullptr) {
235       perror("fopen");
236       return false;
237     }
238     SSL_CTX_set_keylog_callback(ctx.get(), KeyLogCallback);
239   }
240 
241   // Server authentication is required.
242   if (args_map.count("-key") != 0) {
243     std::string key = args_map["-key"];
244     if (!SSL_CTX_use_PrivateKey_file(ctx.get(), key.c_str(),
245                                      SSL_FILETYPE_PEM)) {
246       fprintf(stderr, "Failed to load private key: %s\n", key.c_str());
247       return false;
248     }
249     const std::string &cert =
250         args_map.count("-cert") != 0 ? args_map["-cert"] : key;
251     if (!SSL_CTX_use_certificate_chain_file(ctx.get(), cert.c_str())) {
252       fprintf(stderr, "Failed to load cert chain: %s\n", cert.c_str());
253       return false;
254     }
255   } else {
256     bssl::UniquePtr<EVP_PKEY> evp_pkey = MakeKeyPairForSelfSignedCert();
257     if (!evp_pkey) {
258       return false;
259     }
260     bssl::UniquePtr<X509> cert =
261         MakeSelfSignedCert(evp_pkey.get(), 365 /* valid_days */);
262     if (!cert) {
263       return false;
264     }
265     if (!SSL_CTX_use_PrivateKey(ctx.get(), evp_pkey.get())) {
266       fprintf(stderr, "Failed to set private key.\n");
267       return false;
268     }
269     if (!SSL_CTX_use_certificate(ctx.get(), cert.get())) {
270       fprintf(stderr, "Failed to set certificate.\n");
271       return false;
272     }
273   }
274 
275   if (args_map.count("-ech-key") + args_map.count("-ech-config") == 1) {
276     fprintf(stderr,
277             "-ech-config and -ech-key must be specified together.\n");
278     return false;
279   }
280 
281   if (args_map.count("-ech-key") != 0) {
282     // Load the ECH private key.
283     std::string ech_key_path = args_map["-ech-key"];
284     ScopedFILE ech_key_file(fopen(ech_key_path.c_str(), "rb"));
285     std::vector<uint8_t> ech_key;
286     if (ech_key_file == nullptr ||
287         !ReadAll(&ech_key, ech_key_file.get())) {
288       fprintf(stderr, "Error reading %s\n", ech_key_path.c_str());
289       return false;
290     }
291 
292     // Load the ECHConfig.
293     std::string ech_config_path = args_map["-ech-config"];
294     ScopedFILE ech_config_file(fopen(ech_config_path.c_str(), "rb"));
295     std::vector<uint8_t> ech_config;
296     if (ech_config_file == nullptr ||
297         !ReadAll(&ech_config, ech_config_file.get())) {
298       fprintf(stderr, "Error reading %s\n", ech_config_path.c_str());
299       return false;
300     }
301 
302     bssl::UniquePtr<SSL_ECH_KEYS> keys(SSL_ECH_KEYS_new());
303     bssl::ScopedEVP_HPKE_KEY key;
304     if (!keys ||
305         !EVP_HPKE_KEY_init(key.get(), EVP_hpke_x25519_hkdf_sha256(),
306                            ech_key.data(), ech_key.size()) ||
307         !SSL_ECH_KEYS_add(keys.get(),
308                           /*is_retry_config=*/1, ech_config.data(),
309                           ech_config.size(), key.get()) ||
310         !SSL_CTX_set1_ech_keys(ctx.get(), keys.get())) {
311       fprintf(stderr, "Error setting server's ECHConfig and private key\n");
312       return false;
313     }
314   }
315 
316   if (args_map.count("-cipher") != 0 &&
317       !SSL_CTX_set_strict_cipher_list(ctx.get(), args_map["-cipher"].c_str())) {
318     fprintf(stderr, "Failed setting cipher list\n");
319     return false;
320   }
321 
322   if (args_map.count("-curves") != 0 &&
323       !SSL_CTX_set1_curves_list(ctx.get(), args_map["-curves"].c_str())) {
324     fprintf(stderr, "Failed setting curves list\n");
325     return false;
326   }
327 
328   uint16_t max_version = TLS1_3_VERSION;
329   if (args_map.count("-max-version") != 0 &&
330       !VersionFromString(&max_version, args_map["-max-version"])) {
331     fprintf(stderr, "Unknown protocol version: '%s'\n",
332             args_map["-max-version"].c_str());
333     return false;
334   }
335 
336   if (!SSL_CTX_set_max_proto_version(ctx.get(), max_version)) {
337     return false;
338   }
339 
340   if (args_map.count("-min-version") != 0) {
341     uint16_t version;
342     if (!VersionFromString(&version, args_map["-min-version"])) {
343       fprintf(stderr, "Unknown protocol version: '%s'\n",
344               args_map["-min-version"].c_str());
345       return false;
346     }
347     if (!SSL_CTX_set_min_proto_version(ctx.get(), version)) {
348       return false;
349     }
350   }
351 
352   if (args_map.count("-ocsp-response") != 0 &&
353       !LoadOCSPResponse(ctx.get(), args_map["-ocsp-response"].c_str())) {
354     fprintf(stderr, "Failed to load OCSP response: %s\n", args_map["-ocsp-response"].c_str());
355     return false;
356   }
357 
358   if (args_map.count("-early-data") != 0) {
359     SSL_CTX_set_early_data_enabled(ctx.get(), 1);
360   }
361 
362   if (args_map.count("-debug") != 0) {
363     SSL_CTX_set_info_callback(ctx.get(), InfoCallback);
364   }
365 
366   if (args_map.count("-require-any-client-cert") != 0) {
367     SSL_CTX_set_verify(
368         ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
369     SSL_CTX_set_cert_verify_callback(
370         ctx.get(), [](X509_STORE_CTX *store, void *arg) -> int { return 1; },
371         nullptr);
372   }
373 
374   Listener listener;
375   if (!listener.Init(args_map["-accept"])) {
376     return false;
377   }
378 
379   bool result = true;
380   do {
381     int sock = -1;
382     if (!listener.Accept(&sock)) {
383       return false;
384     }
385 
386     BIO *bio = BIO_new_socket(sock, BIO_CLOSE);
387     bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
388     SSL_set_bio(ssl.get(), bio, bio);
389 
390     if (args_map.count("-jdk11-workaround") != 0) {
391       SSL_set_jdk11_workaround(ssl.get(), 1);
392     }
393 
394     int ret = SSL_accept(ssl.get());
395     if (ret != 1) {
396       int ssl_err = SSL_get_error(ssl.get(), ret);
397       PrintSSLError(stderr, "Error while connecting", ssl_err, ret);
398       result = false;
399       continue;
400     }
401 
402     fprintf(stderr, "Connected.\n");
403     bssl::UniquePtr<BIO> bio_stderr(BIO_new_fp(stderr, BIO_NOCLOSE));
404     PrintConnectionInfo(bio_stderr.get(), ssl.get());
405 
406     if (args_map.count("-www") != 0) {
407       result = HandleWWW(ssl.get());
408     } else {
409       result = TransferData(ssl.get(), sock);
410     }
411   } while (args_map.count("-loop") != 0);
412 
413   return result;
414 }
415