summaryrefslogtreecommitdiffstats
path: root/examples/tls_client_context_picotls.cc
diff options
context:
space:
mode:
Diffstat (limited to 'examples/tls_client_context_picotls.cc')
-rw-r--r--examples/tls_client_context_picotls.cc155
1 files changed, 155 insertions, 0 deletions
diff --git a/examples/tls_client_context_picotls.cc b/examples/tls_client_context_picotls.cc
new file mode 100644
index 0000000..363f6c7
--- /dev/null
+++ b/examples/tls_client_context_picotls.cc
@@ -0,0 +1,155 @@
+/*
+ * ngtcp2
+ *
+ * Copyright (c) 2022 ngtcp2 contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "tls_client_context_picotls.h"
+
+#include <iostream>
+
+#include <ngtcp2/ngtcp2_crypto_picotls.h>
+
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+
+#include "client_base.h"
+#include "template.h"
+
+extern Config config;
+
+namespace {
+int save_ticket_cb(ptls_save_ticket_t *self, ptls_t *ptls, ptls_iovec_t input) {
+ auto f = BIO_new_file(config.session_file, "w");
+ if (f == nullptr) {
+ std::cerr << "Could not write TLS session in " << config.session_file
+ << std::endl;
+ return 0;
+ }
+
+ if (!PEM_write_bio(f, "PICOTLS SESSION PARAMETERS", "", input.base,
+ input.len)) {
+ std::cerr << "Unable to write TLS session to file" << std::endl;
+ }
+
+ BIO_free(f);
+
+ return 0;
+}
+
+ptls_save_ticket_t save_ticket = {save_ticket_cb};
+} // namespace
+
+namespace {
+ptls_key_exchange_algorithm_t *key_exchanges[] = {
+ &ptls_openssl_x25519,
+ &ptls_openssl_secp256r1,
+ &ptls_openssl_secp384r1,
+ &ptls_openssl_secp521r1,
+ nullptr,
+};
+} // namespace
+
+namespace {
+ptls_cipher_suite_t *cipher_suites[] = {
+ &ptls_openssl_aes128gcmsha256,
+ &ptls_openssl_aes256gcmsha384,
+ &ptls_openssl_chacha20poly1305sha256,
+ nullptr,
+};
+} // namespace
+
+TLSClientContext::TLSClientContext()
+ : ctx_{
+ .random_bytes = ptls_openssl_random_bytes,
+ .get_time = &ptls_get_time,
+ .key_exchanges = key_exchanges,
+ .cipher_suites = cipher_suites,
+ .require_dhe_on_psk = 1,
+ } {}
+
+TLSClientContext::~TLSClientContext() {
+ if (sign_cert_.key) {
+ ptls_openssl_dispose_sign_certificate(&sign_cert_);
+ }
+
+ for (size_t i = 0; i < ctx_.certificates.count; ++i) {
+ free(ctx_.certificates.list[i].base);
+ }
+ free(ctx_.certificates.list);
+}
+
+ptls_context_t *TLSClientContext::get_native_handle() { return &ctx_; }
+
+int TLSClientContext::init(const char *private_key_file,
+ const char *cert_file) {
+ if (ngtcp2_crypto_picotls_configure_client_context(&ctx_) != 0) {
+ std::cerr << "ngtcp2_crypto_picotls_configure_client_context failed"
+ << std::endl;
+ return -1;
+ }
+
+ if (config.session_file) {
+ ctx_.save_ticket = &save_ticket;
+ }
+
+ if (private_key_file && cert_file) {
+ if (ptls_load_certificates(&ctx_, cert_file) != 0) {
+ std::cerr << "ptls_load_certificates failed" << std::endl;
+ return -1;
+ }
+
+ if (load_private_key(private_key_file) != 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int TLSClientContext::load_private_key(const char *private_key_file) {
+ auto fp = fopen(private_key_file, "rb");
+ if (fp == nullptr) {
+ std::cerr << "Could not open private key file " << private_key_file << ": "
+ << strerror(errno) << std::endl;
+ return -1;
+ }
+
+ auto fp_d = defer(fclose, fp);
+
+ auto pkey = PEM_read_PrivateKey(fp, nullptr, nullptr, nullptr);
+ if (pkey == nullptr) {
+ std::cerr << "Could not read private key file " << private_key_file
+ << std::endl;
+ return -1;
+ }
+
+ auto pkey_d = defer(EVP_PKEY_free, pkey);
+
+ if (ptls_openssl_init_sign_certificate(&sign_cert_, pkey) != 0) {
+ std::cerr << "ptls_openssl_init_sign_certificate failed" << std::endl;
+ return -1;
+ }
+
+ ctx_.sign_certificate = &sign_cert_.super;
+
+ return 0;
+}