/* * ngtcp2 * * Copyright (c) 2020 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 "util.h" #include #include #include #include #include #include #include "template.h" // Based on https://github.com/ueno/ngtcp2-gnutls-examples namespace ngtcp2 { namespace util { int generate_secure_random(uint8_t *data, size_t datalen) { if (gnutls_rnd(GNUTLS_RND_RANDOM, data, datalen) != 0) { return -1; } return 0; } int generate_secret(uint8_t *secret, size_t secretlen) { std::array rand; std::array md; assert(md.size() == secretlen); if (generate_secure_random(rand.data(), rand.size()) != 0) { return -1; } if (gnutls_hash_fast(GNUTLS_DIG_SHA256, rand.data(), rand.size(), md.data()) != 0) { return -1; } std::copy_n(std::begin(md), secretlen, secret); return 0; } std::optional read_token(const std::string_view &filename) { auto f = std::ifstream(filename.data()); if (!f) { std::cerr << "Could not read token file " << filename << std::endl; return {}; } auto pos = f.tellg(); std::vector content(pos); f.seekg(0, std::ios::beg); f.read(content.data(), pos); gnutls_datum_t s; s.data = reinterpret_cast(content.data()); s.size = content.size(); gnutls_datum_t d; if (auto rv = gnutls_pem_base64_decode2("QUIC TOKEN", &s, &d); rv < 0) { std::cerr << "Could not read token in " << filename << std::endl; return {}; } auto res = std::string{d.data, d.data + d.size}; gnutls_free(d.data); return res; } int write_token(const std::string_view &filename, const uint8_t *token, size_t tokenlen) { auto f = std::ofstream(filename.data()); if (!f) { std::cerr << "Could not write token in " << filename << std::endl; return -1; } gnutls_datum_t s; s.data = const_cast(token); s.size = tokenlen; gnutls_datum_t d; if (auto rv = gnutls_pem_base64_encode2("QUIC TOKEN", &s, &d); rv < 0) { std::cerr << "Could not encode token in " << filename << std::endl; return -1; } f.write(reinterpret_cast(d.data), d.size); gnutls_free(d.data); return 0; } const char *crypto_default_ciphers() { return "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" "+CHACHA20-POLY1305:+AES-128-CCM"; } const char *crypto_default_groups() { return "-GROUP-ALL:+GROUP-X25519:+GROUP-SECP256R1:+GROUP-SECP384R1:" "+GROUP-SECP521R1"; } } // namespace util } // namespace ngtcp2