Follow ngtcp2 API changes and use libngtcp2_crypto_openssl
This commit is contained in:
parent
4861b41c8d
commit
ae05dd0e79
10
configure.ac
10
configure.ac
|
@ -374,6 +374,15 @@ if test "x${have_libngtcp2}" = "xno"; then
|
|||
AC_MSG_NOTICE($LIBNGTCP2_PKG_ERRORS)
|
||||
fi
|
||||
|
||||
# ngtcp2_crypto_openssl (for src)
|
||||
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_OPENSSL],
|
||||
[libngtcp2_crypto_openssl >= 0.0.0],
|
||||
[have_libngtcp2_crypto_openssl=yes],
|
||||
[have_libngtcp2_crypto_openssl=no])
|
||||
if test "x${have_libngtcp2_crypto_openssl}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBNGTCP2_CRYPTO_OPENSSL_PKG_ERRORS)
|
||||
fi
|
||||
|
||||
# nghttp3 (for src)
|
||||
PKG_CHECK_MODULES([LIBNGHTTP3], [libnghttp3 >= 0.0.0], [have_libnghttp3=yes],
|
||||
[have_libnghttp3=no])
|
||||
|
@ -917,6 +926,7 @@ AC_MSG_NOTICE([summary of build options:
|
|||
Libev: ${have_libev} (CFLAGS='${LIBEV_CFLAGS}' LIBS='${LIBEV_LIBS}')
|
||||
Libc-ares: ${have_libcares} (CFLAGS='${LIBCARES_CFLAGS}' LIBS='${LIBCARES_LIBS}')
|
||||
libngtcp2: ${have_libngtcp2} (CFLAGS='${LIBNGTCP2_CFLAGS}' LIBS='${LIBNGTCP2_LIBS}')
|
||||
libngtcp2_crypto_openssl: ${have_libngtcp2_crypto_openssl} (CFLAGS='${LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS}' LIBS='${LIBNGTCP2_CRYPTO_OPENSSL_LIBS}')
|
||||
libnghttp3: ${have_libnghttp3} (CFLAGS='${LIBNGHTTP3_CFLAGS}' LIBS='${LIBNGHTTP3_LIBS}')
|
||||
Libevent(SSL): ${have_libevent_openssl} (CFLAGS='${LIBEVENT_OPENSSL_CFLAGS}' LIBS='${LIBEVENT_OPENSSL_LIBS}')
|
||||
Jansson: ${have_jansson} (CFLAGS='${JANSSON_CFLAGS}' LIBS='${JANSSON_LIBS}')
|
||||
|
|
|
@ -46,6 +46,7 @@ AM_CPPFLAGS = \
|
|||
@OPENSSL_CFLAGS@ \
|
||||
@LIBCARES_CFLAGS@ \
|
||||
@LIBNGHTTP3_CFLAGS@ \
|
||||
@LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS@ \
|
||||
@LIBNGTCP2_CFLAGS@ \
|
||||
@JANSSON_CFLAGS@ \
|
||||
@ZLIB_CFLAGS@ \
|
||||
|
@ -60,6 +61,7 @@ LDADD = $(top_builddir)/lib/libnghttp2.la \
|
|||
@OPENSSL_LIBS@ \
|
||||
@LIBCARES_LIBS@ \
|
||||
@LIBNGHTTP3_LIBS@ \
|
||||
@LIBNGTCP2_CRYPTO_OPENSSL_LIBS@ \
|
||||
@LIBNGTCP2_LIBS@ \
|
||||
@SYSTEMD_LIBS@ \
|
||||
@JANSSON_LIBS@ \
|
||||
|
|
|
@ -2168,6 +2168,8 @@ Options:
|
|||
}
|
||||
} // namespace
|
||||
|
||||
extern ngtcp2_crypto_ctx in_crypto_ctx;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
tls::libssl_init();
|
||||
|
||||
|
@ -2808,6 +2810,8 @@ int main(int argc, char **argv) {
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ngtcp2_crypto_ctx_initial(&in_crypto_ctx);
|
||||
|
||||
resolve_host();
|
||||
|
||||
std::cout << "starting benchmark..." << std::endl;
|
||||
|
|
27
src/h2load.h
27
src/h2load.h
|
@ -46,6 +46,7 @@
|
|||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#include <ngtcp2/ngtcp2.h>
|
||||
#include <ngtcp2/ngtcp2_crypto.h>
|
||||
|
||||
#include <ev.h>
|
||||
|
||||
|
@ -328,6 +329,7 @@ struct Client {
|
|||
ngtcp2_crypto_level rx_crypto_level;
|
||||
std::vector<uint8_t> server_handshake;
|
||||
size_t server_handshake_nread;
|
||||
ngtcp2_crypto_ctx crypto_ctx;
|
||||
// Client never send CRYPTO in Short packet.
|
||||
std::array<Crypto, 2> crypto;
|
||||
size_t max_pktlen;
|
||||
|
@ -446,26 +448,23 @@ struct Client {
|
|||
int quic_recv_crypto_data(ngtcp2_crypto_level crypto_level,
|
||||
const uint8_t *data, size_t datalen);
|
||||
int quic_handshake_completed();
|
||||
int quic_in_encrypt(uint8_t *dest, size_t destlen, const uint8_t *plaintext,
|
||||
size_t plaintextlen, const uint8_t *key, size_t keylen,
|
||||
int quic_in_encrypt(uint8_t *dest, const uint8_t *plaintext,
|
||||
size_t plaintextlen, const uint8_t *key,
|
||||
const uint8_t *nonce, size_t noncelen, const uint8_t *ad,
|
||||
size_t adlen);
|
||||
int quic_in_decrypt(uint8_t *dest, size_t destlen, const uint8_t *ciphertext,
|
||||
size_t ciphertextlen, const uint8_t *key, size_t keylen,
|
||||
int quic_in_decrypt(uint8_t *dest, const uint8_t *ciphertext,
|
||||
size_t ciphertextlen, const uint8_t *key,
|
||||
const uint8_t *nonce, size_t noncelen, const uint8_t *ad,
|
||||
size_t adlen);
|
||||
int quic_encrypt(uint8_t *dest, size_t destlen, const uint8_t *plaintext,
|
||||
size_t plaintextlen, const uint8_t *key, size_t keylen,
|
||||
int quic_encrypt(uint8_t *dest, const uint8_t *plaintext, size_t plaintextlen,
|
||||
const uint8_t *key, const uint8_t *nonce, size_t noncelen,
|
||||
const uint8_t *ad, size_t adlen);
|
||||
int quic_decrypt(uint8_t *dest, const uint8_t *ciphertext,
|
||||
size_t ciphertextlen, const uint8_t *key,
|
||||
const uint8_t *nonce, size_t noncelen, const uint8_t *ad,
|
||||
size_t adlen);
|
||||
int quic_decrypt(uint8_t *dest, size_t destlen, const uint8_t *ciphertext,
|
||||
size_t ciphertextlen, const uint8_t *key, size_t keylen,
|
||||
const uint8_t *nonce, size_t noncelen, const uint8_t *ad,
|
||||
size_t adlen);
|
||||
int quic_in_hp_mask(uint8_t *dest, size_t destlen, const uint8_t *key,
|
||||
size_t keylen, const uint8_t *sample, size_t samplelen);
|
||||
int quic_hp_mask(uint8_t *dest, size_t destlen, const uint8_t *key,
|
||||
size_t keylen, const uint8_t *sample, size_t samplelen);
|
||||
int quic_in_hp_mask(uint8_t *dest, const uint8_t *key, const uint8_t *sample);
|
||||
int quic_hp_mask(uint8_t *dest, const uint8_t *key, const uint8_t *sample);
|
||||
int quic_recv_stream_data(int64_t stream_id, int fin, const uint8_t *data,
|
||||
size_t datalen);
|
||||
int quic_stream_close(int64_t stream_id, uint64_t app_error_code);
|
||||
|
|
|
@ -83,9 +83,6 @@ int64_t Http3Session::submit_request_internal() {
|
|||
return rv;
|
||||
}
|
||||
|
||||
rv = nghttp3_conn_end_stream(conn_, stream_id);
|
||||
assert(0 == rv);
|
||||
|
||||
client_->on_request(stream_id);
|
||||
auto req_stat = client_->get_req_stat(stream_id);
|
||||
assert(req_stat);
|
||||
|
|
|
@ -37,6 +37,8 @@ namespace {
|
|||
auto randgen = util::make_mt19937();
|
||||
} // namespace
|
||||
|
||||
ngtcp2_crypto_ctx in_crypto_ctx;
|
||||
|
||||
namespace {
|
||||
int client_initial(ngtcp2_conn *conn, void *user_data) {
|
||||
auto c = static_cast<Client *>(user_data);
|
||||
|
@ -123,156 +125,133 @@ int recv_retry(ngtcp2_conn *conn, const ngtcp2_pkt_hd *hd,
|
|||
} // namespace
|
||||
|
||||
namespace {
|
||||
ssize_t in_encrypt(ngtcp2_conn *conn, uint8_t *dest, size_t destlen,
|
||||
const uint8_t *plaintext, size_t plaintextlen,
|
||||
const uint8_t *key, size_t keylen, const uint8_t *nonce,
|
||||
int in_encrypt(ngtcp2_conn *conn, uint8_t *dest, const uint8_t *plaintext,
|
||||
size_t plaintextlen, const uint8_t *key, const uint8_t *nonce,
|
||||
size_t noncelen, const uint8_t *ad, size_t adlen,
|
||||
void *user_data) {
|
||||
auto c = static_cast<Client *>(user_data);
|
||||
|
||||
auto nwrite = c->quic_in_encrypt(dest, destlen, plaintext, plaintextlen, key,
|
||||
keylen, nonce, noncelen, ad, adlen);
|
||||
if (nwrite < 0) {
|
||||
if (c->quic_in_encrypt(dest, plaintext, plaintextlen, key, nonce, noncelen,
|
||||
ad, adlen) != 0) {
|
||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
return nwrite;
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int Client::quic_in_encrypt(uint8_t *dest, size_t destlen,
|
||||
const uint8_t *plaintext, size_t plaintextlen,
|
||||
const uint8_t *key, size_t keylen,
|
||||
int Client::quic_in_encrypt(uint8_t *dest, const uint8_t *plaintext,
|
||||
size_t plaintextlen, const uint8_t *key,
|
||||
const uint8_t *nonce, size_t noncelen,
|
||||
const uint8_t *ad, size_t adlen) {
|
||||
return quic::encrypt(dest, destlen, plaintext, plaintextlen, key, keylen,
|
||||
nonce, noncelen, ad, adlen, EVP_aes_128_gcm());
|
||||
return ngtcp2_crypto_encrypt(dest, &in_crypto_ctx.aead, plaintext,
|
||||
plaintextlen, key, nonce, noncelen, ad, adlen);
|
||||
}
|
||||
|
||||
namespace {
|
||||
ssize_t in_decrypt(ngtcp2_conn *conn, uint8_t *dest, size_t destlen,
|
||||
const uint8_t *ciphertext, size_t ciphertextlen,
|
||||
const uint8_t *key, size_t keylen, const uint8_t *nonce,
|
||||
int in_decrypt(ngtcp2_conn *conn, uint8_t *dest, const uint8_t *ciphertext,
|
||||
size_t ciphertextlen, const uint8_t *key, const uint8_t *nonce,
|
||||
size_t noncelen, const uint8_t *ad, size_t adlen,
|
||||
void *user_data) {
|
||||
auto c = static_cast<Client *>(user_data);
|
||||
|
||||
auto nwrite = c->quic_in_decrypt(dest, destlen, ciphertext, ciphertextlen,
|
||||
key, keylen, nonce, noncelen, ad, adlen);
|
||||
if (nwrite < 0) {
|
||||
if (c->quic_in_decrypt(dest, ciphertext, ciphertextlen, key, nonce, noncelen,
|
||||
ad, adlen) != 0) {
|
||||
return NGTCP2_ERR_TLS_DECRYPT;
|
||||
}
|
||||
|
||||
return nwrite;
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int Client::quic_in_decrypt(uint8_t *dest, size_t destlen,
|
||||
const uint8_t *ciphertext, size_t ciphertextlen,
|
||||
const uint8_t *key, size_t keylen,
|
||||
int Client::quic_in_decrypt(uint8_t *dest, const uint8_t *ciphertext,
|
||||
size_t ciphertextlen, const uint8_t *key,
|
||||
const uint8_t *nonce, size_t noncelen,
|
||||
const uint8_t *ad, size_t adlen) {
|
||||
return quic::decrypt(dest, destlen, ciphertext, ciphertextlen, key, keylen,
|
||||
nonce, noncelen, ad, adlen, EVP_aes_128_gcm());
|
||||
return ngtcp2_crypto_decrypt(dest, &in_crypto_ctx.aead, ciphertext,
|
||||
ciphertextlen, key, nonce, noncelen, ad, adlen);
|
||||
}
|
||||
|
||||
namespace {
|
||||
ssize_t encrypt(ngtcp2_conn *conn, uint8_t *dest, size_t destlen,
|
||||
const uint8_t *plaintext, size_t plaintextlen,
|
||||
const uint8_t *key, size_t keylen, const uint8_t *nonce,
|
||||
size_t noncelen, const uint8_t *ad, size_t adlen,
|
||||
void *user_data) {
|
||||
int encrypt(ngtcp2_conn *conn, uint8_t *dest, const uint8_t *plaintext,
|
||||
size_t plaintextlen, const uint8_t *key, const uint8_t *nonce,
|
||||
size_t noncelen, const uint8_t *ad, size_t adlen, void *user_data) {
|
||||
auto c = static_cast<Client *>(user_data);
|
||||
|
||||
auto nwrite = c->quic_encrypt(dest, destlen, plaintext, plaintextlen, key,
|
||||
keylen, nonce, noncelen, ad, adlen);
|
||||
if (nwrite < 0) {
|
||||
if (c->quic_encrypt(dest, plaintext, plaintextlen, key, nonce, noncelen, ad,
|
||||
adlen) != 0) {
|
||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
return nwrite;
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int Client::quic_encrypt(uint8_t *dest, size_t destlen,
|
||||
const uint8_t *plaintext, size_t plaintextlen,
|
||||
const uint8_t *key, size_t keylen,
|
||||
int Client::quic_encrypt(uint8_t *dest, const uint8_t *plaintext,
|
||||
size_t plaintextlen, const uint8_t *key,
|
||||
const uint8_t *nonce, size_t noncelen,
|
||||
const uint8_t *ad, size_t adlen) {
|
||||
return quic::encrypt(dest, destlen, plaintext, plaintextlen, key, keylen,
|
||||
nonce, noncelen, ad, adlen, quic::aead(ssl));
|
||||
return ngtcp2_crypto_encrypt(dest, &quic.crypto_ctx.aead, plaintext,
|
||||
plaintextlen, key, nonce, noncelen, ad, adlen);
|
||||
}
|
||||
|
||||
namespace {
|
||||
ssize_t decrypt(ngtcp2_conn *conn, uint8_t *dest, size_t destlen,
|
||||
const uint8_t *ciphertext, size_t ciphertextlen,
|
||||
const uint8_t *key, size_t keylen, const uint8_t *nonce,
|
||||
size_t noncelen, const uint8_t *ad, size_t adlen,
|
||||
void *user_data) {
|
||||
int decrypt(ngtcp2_conn *conn, uint8_t *dest, const uint8_t *ciphertext,
|
||||
size_t ciphertextlen, const uint8_t *key, const uint8_t *nonce,
|
||||
size_t noncelen, const uint8_t *ad, size_t adlen, void *user_data) {
|
||||
auto c = static_cast<Client *>(user_data);
|
||||
|
||||
auto nwrite = c->quic_decrypt(dest, destlen, ciphertext, ciphertextlen, key,
|
||||
keylen, nonce, noncelen, ad, adlen);
|
||||
if (nwrite < 0) {
|
||||
if (c->quic_decrypt(dest, ciphertext, ciphertextlen, key, nonce, noncelen, ad,
|
||||
adlen) != 0) {
|
||||
return NGTCP2_ERR_TLS_DECRYPT;
|
||||
}
|
||||
|
||||
return nwrite;
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int Client::quic_decrypt(uint8_t *dest, size_t destlen,
|
||||
const uint8_t *ciphertext, size_t ciphertextlen,
|
||||
const uint8_t *key, size_t keylen,
|
||||
int Client::quic_decrypt(uint8_t *dest, const uint8_t *ciphertext,
|
||||
size_t ciphertextlen, const uint8_t *key,
|
||||
const uint8_t *nonce, size_t noncelen,
|
||||
const uint8_t *ad, size_t adlen) {
|
||||
return quic::decrypt(dest, destlen, ciphertext, ciphertextlen, key, keylen,
|
||||
nonce, noncelen, ad, adlen, quic::aead(ssl));
|
||||
return ngtcp2_crypto_decrypt(dest, &quic.crypto_ctx.aead, ciphertext,
|
||||
ciphertextlen, key, nonce, noncelen, ad, adlen);
|
||||
}
|
||||
|
||||
namespace {
|
||||
ssize_t in_hp_mask(ngtcp2_conn *conn, uint8_t *dest, size_t destlen,
|
||||
const uint8_t *key, size_t keylen, const uint8_t *sample,
|
||||
size_t samplelen, void *user_data) {
|
||||
int in_hp_mask(ngtcp2_conn *conn, uint8_t *dest, const uint8_t *key,
|
||||
const uint8_t *sample, void *user_data) {
|
||||
auto c = static_cast<Client *>(user_data);
|
||||
|
||||
auto nwrite =
|
||||
c->quic_in_hp_mask(dest, destlen, key, keylen, sample, samplelen);
|
||||
if (nwrite < 0) {
|
||||
if (c->quic_in_hp_mask(dest, key, sample) != 0) {
|
||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
return nwrite;
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int Client::quic_in_hp_mask(uint8_t *dest, size_t destlen, const uint8_t *key,
|
||||
size_t keylen, const uint8_t *sample,
|
||||
size_t samplelen) {
|
||||
return quic::hp_mask(dest, destlen, key, keylen, sample, samplelen,
|
||||
EVP_aes_128_ctr());
|
||||
int Client::quic_in_hp_mask(uint8_t *dest, const uint8_t *key,
|
||||
const uint8_t *sample) {
|
||||
return ngtcp2_crypto_hp_mask(dest, &in_crypto_ctx.hp, key, sample);
|
||||
}
|
||||
|
||||
namespace {
|
||||
ssize_t hp_mask(ngtcp2_conn *conn, uint8_t *dest, size_t destlen,
|
||||
const uint8_t *key, size_t keylen, const uint8_t *sample,
|
||||
size_t samplelen, void *user_data) {
|
||||
int hp_mask(ngtcp2_conn *conn, uint8_t *dest, const uint8_t *key,
|
||||
const uint8_t *sample, void *user_data) {
|
||||
auto c = static_cast<Client *>(user_data);
|
||||
|
||||
auto nwrite = c->quic_hp_mask(dest, destlen, key, keylen, sample, samplelen);
|
||||
if (nwrite < 0) {
|
||||
if (c->quic_hp_mask(dest, key, sample) != 0) {
|
||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
return nwrite;
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int Client::quic_hp_mask(uint8_t *dest, size_t destlen, const uint8_t *key,
|
||||
size_t keylen, const uint8_t *sample,
|
||||
size_t samplelen) {
|
||||
return quic::hp_mask(dest, destlen, key, keylen, sample, samplelen,
|
||||
quic::hp(ssl));
|
||||
int Client::quic_hp_mask(uint8_t *dest, const uint8_t *key,
|
||||
const uint8_t *sample) {
|
||||
return ngtcp2_crypto_hp_mask(dest, &quic.crypto_ctx.hp, key, sample);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -669,71 +648,45 @@ void Client::quic_close_connection() {
|
|||
}
|
||||
|
||||
int Client::quic_setup_initial_crypto() {
|
||||
int rv;
|
||||
|
||||
std::array<uint8_t, 32> initial_secret, secret;
|
||||
std::array<uint8_t, 32> tx_secret, rx_secret;
|
||||
auto dcid = ngtcp2_conn_get_dcid(quic.conn);
|
||||
rv = quic::derive_initial_secret(
|
||||
initial_secret.data(), initial_secret.size(), dcid->data, dcid->datalen,
|
||||
reinterpret_cast<const uint8_t *>(NGTCP2_INITIAL_SALT),
|
||||
str_size(NGTCP2_INITIAL_SALT));
|
||||
if (rv != 0) {
|
||||
std::cerr << "quic::derive_initial_secret() failed" << std::endl;
|
||||
if (ngtcp2_crypto_derive_initial_secrets(rx_secret.data(), tx_secret.data(),
|
||||
nullptr, dcid,
|
||||
NGTCP2_CRYPTO_SIDE_CLIENT) != 0) {
|
||||
std::cerr << "ngtcp2_crypto_derive_initial_secrets() failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto aead = EVP_aes_128_gcm();
|
||||
auto prf = EVP_sha256();
|
||||
|
||||
rv = quic::derive_client_initial_secret(secret.data(), secret.size(),
|
||||
initial_secret.data(),
|
||||
initial_secret.size());
|
||||
if (rv != 0) {
|
||||
std::cerr << "quic::derive_client_initial_secret() failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
auto aead = &in_crypto_ctx.aead;
|
||||
auto md = &in_crypto_ctx.md;
|
||||
|
||||
std::array<uint8_t, 16> key, iv, hp;
|
||||
auto keylen = key.size();
|
||||
auto ivlen = iv.size();
|
||||
rv = quic::derive_packet_protection_key(key.data(), keylen, iv.data(), ivlen,
|
||||
secret.data(), secret.size(), aead,
|
||||
prf);
|
||||
if (rv != 0) {
|
||||
auto keylen = ngtcp2_crypto_aead_keylen(aead);
|
||||
auto ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
|
||||
auto hplen = keylen;
|
||||
|
||||
if (ngtcp2_crypto_derive_packet_protection_key(key.data(), iv.data(), aead,
|
||||
md, tx_secret.data(),
|
||||
tx_secret.size()) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto hplen = hp.size();
|
||||
rv = quic::derive_header_protection_key(hp.data(), hplen, secret.data(),
|
||||
secret.size(), aead, prf);
|
||||
if (rv != 0) {
|
||||
if (ngtcp2_crypto_derive_header_protection_key(
|
||||
hp.data(), aead, md, tx_secret.data(), tx_secret.size()) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ngtcp2_conn_install_initial_tx_keys(quic.conn, key.data(), keylen, iv.data(),
|
||||
ivlen, hp.data(), hplen);
|
||||
|
||||
rv = quic::derive_server_initial_secret(secret.data(), secret.size(),
|
||||
initial_secret.data(),
|
||||
initial_secret.size());
|
||||
if (rv != 0) {
|
||||
std::cerr << "quic::derive_server_initial_secret() failed" << std::endl;
|
||||
if (ngtcp2_crypto_derive_packet_protection_key(key.data(), iv.data(), aead,
|
||||
md, rx_secret.data(),
|
||||
rx_secret.size()) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
keylen = key.size();
|
||||
ivlen = iv.size();
|
||||
rv = quic::derive_packet_protection_key(key.data(), keylen, iv.data(), ivlen,
|
||||
secret.data(), secret.size(), aead,
|
||||
prf);
|
||||
if (rv != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
hplen = hp.size();
|
||||
rv = quic::derive_header_protection_key(hp.data(), hplen, secret.data(),
|
||||
secret.size(), aead, prf);
|
||||
if (rv != 0) {
|
||||
if (ngtcp2_crypto_derive_header_protection_key(
|
||||
hp.data(), aead, md, rx_secret.data(), rx_secret.size()) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -744,8 +697,6 @@ int Client::quic_setup_initial_crypto() {
|
|||
}
|
||||
|
||||
int Client::quic_on_key(int name, const uint8_t *secret, size_t secretlen) {
|
||||
int rv;
|
||||
|
||||
switch (name) {
|
||||
case SSL_KEY_CLIENT_EARLY_TRAFFIC:
|
||||
case SSL_KEY_CLIENT_HANDSHAKE_TRAFFIC:
|
||||
|
@ -757,28 +708,30 @@ int Client::quic_on_key(int name, const uint8_t *secret, size_t secretlen) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
auto aead = quic::aead(ssl);
|
||||
auto prf = quic::prf(ssl);
|
||||
if (quic.crypto_ctx.aead.native_handle == nullptr) {
|
||||
ngtcp2_crypto_ctx_tls(&quic.crypto_ctx, ssl);
|
||||
ngtcp2_conn_set_aead_overhead(
|
||||
quic.conn, ngtcp2_crypto_aead_taglen(&quic.crypto_ctx.aead));
|
||||
}
|
||||
|
||||
auto aead = &quic.crypto_ctx.aead;
|
||||
auto md = &quic.crypto_ctx.md;
|
||||
|
||||
std::array<uint8_t, 64> key, iv, hp;
|
||||
auto keylen = key.size();
|
||||
auto ivlen = iv.size();
|
||||
rv = quic::derive_packet_protection_key(key.data(), keylen, iv.data(), ivlen,
|
||||
secret, secretlen, aead, prf);
|
||||
if (rv != 0) {
|
||||
auto keylen = ngtcp2_crypto_aead_keylen(aead);
|
||||
auto ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
|
||||
auto hplen = keylen;
|
||||
|
||||
if (ngtcp2_crypto_derive_packet_protection_key(key.data(), iv.data(), aead,
|
||||
md, secret, secretlen) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto hplen = hp.size();
|
||||
rv = quic::derive_header_protection_key(hp.data(), hplen, secret, secretlen,
|
||||
aead, prf);
|
||||
if (rv != 0) {
|
||||
if (ngtcp2_crypto_derive_header_protection_key(hp.data(), aead, md, secret,
|
||||
secretlen) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO Just call this once.
|
||||
ngtcp2_conn_set_aead_overhead(quic.conn, quic::aead_max_overhead(aead));
|
||||
|
||||
switch (name) {
|
||||
case SSL_KEY_CLIENT_EARLY_TRAFFIC:
|
||||
ngtcp2_conn_install_early_keys(quic.conn, key.data(), keylen, iv.data(),
|
||||
|
|
398
src/quic.cc
398
src/quic.cc
|
@ -26,8 +26,6 @@
|
|||
|
||||
#include <cassert>
|
||||
|
||||
#include <openssl/kdf.h>
|
||||
|
||||
#include <ngtcp2/ngtcp2.h>
|
||||
#include <nghttp3/nghttp3.h>
|
||||
|
||||
|
@ -37,402 +35,6 @@ using namespace nghttp2;
|
|||
|
||||
namespace quic {
|
||||
|
||||
const EVP_CIPHER *aead(SSL *ssl) {
|
||||
switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) {
|
||||
case 0x03001301u: // TLS_AES_128_GCM_SHA256
|
||||
return EVP_aes_128_gcm();
|
||||
case 0x03001302u: // TLS_AES_256_GCM_SHA384
|
||||
return EVP_aes_256_gcm();
|
||||
case 0x03001303u: // TLS_CHACHA20_POLY1305_SHA256
|
||||
return EVP_chacha20_poly1305();
|
||||
case 0x03001304u: // TLS_AES_128_CCM_SHA256
|
||||
return EVP_aes_128_ccm();
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
const EVP_CIPHER *hp(SSL *ssl) {
|
||||
switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) {
|
||||
case 0x03001301u: // TLS_AES_128_GCM_SHA256
|
||||
case 0x03001304u: // TLS_AES_128_CCM_SHA256
|
||||
return EVP_aes_128_ctr();
|
||||
case 0x03001302u: // TLS_AES_256_GCM_SHA384
|
||||
return EVP_aes_256_ctr();
|
||||
case 0x03001303u: // TLS_CHACHA20_POLY1305_SHA256
|
||||
return EVP_chacha20();
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
const EVP_MD *prf(SSL *ssl) {
|
||||
switch (SSL_CIPHER_get_id(SSL_get_current_cipher(ssl))) {
|
||||
case 0x03001301u: // TLS_AES_128_GCM_SHA256
|
||||
case 0x03001303u: // TLS_CHACHA20_POLY1305_SHA256
|
||||
case 0x03001304u: // TLS_AES_128_CCM_SHA256
|
||||
return EVP_sha256();
|
||||
case 0x03001302u: // TLS_AES_256_GCM_SHA384
|
||||
return EVP_sha384();
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
size_t aead_key_length(const EVP_CIPHER *aead) {
|
||||
return EVP_CIPHER_key_length(aead);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
size_t aead_nonce_length(const EVP_CIPHER *aead) {
|
||||
return EVP_CIPHER_iv_length(aead);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
size_t aead_tag_length(const EVP_CIPHER *aead) {
|
||||
if (aead == EVP_aes_128_gcm() || aead == EVP_aes_256_gcm()) {
|
||||
return EVP_GCM_TLS_TAG_LEN;
|
||||
}
|
||||
if (aead == EVP_chacha20_poly1305()) {
|
||||
return EVP_CHACHAPOLY_TLS_TAG_LEN;
|
||||
}
|
||||
if (aead == EVP_aes_128_ccm()) {
|
||||
return EVP_CCM_TLS_TAG_LEN;
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
size_t aead_max_overhead(const EVP_CIPHER *aead) {
|
||||
return aead_tag_length(aead);
|
||||
}
|
||||
|
||||
int hkdf_extract(uint8_t *dest, size_t destlen, const uint8_t *secret,
|
||||
size_t secretlen, const uint8_t *salt, size_t saltlen,
|
||||
const EVP_MD *prf) {
|
||||
auto pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr);
|
||||
if (pctx == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto pctx_d = defer(EVP_PKEY_CTX_free, pctx);
|
||||
|
||||
if (EVP_PKEY_derive_init(pctx) != 1 ||
|
||||
EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) != 1 ||
|
||||
EVP_PKEY_CTX_set_hkdf_md(pctx, prf) != 1 ||
|
||||
EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, saltlen) != 1 ||
|
||||
EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, secretlen) != 1 ||
|
||||
EVP_PKEY_derive(pctx, dest, &destlen) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hkdf_expand(uint8_t *dest, size_t destlen, const uint8_t *secret,
|
||||
size_t secretlen, const uint8_t *info, size_t infolen,
|
||||
const EVP_MD *prf) {
|
||||
auto pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr);
|
||||
if (pctx == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto pctx_d = defer(EVP_PKEY_CTX_free, pctx);
|
||||
|
||||
if (EVP_PKEY_derive_init(pctx) != 1 ||
|
||||
EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) != 1 ||
|
||||
EVP_PKEY_CTX_set_hkdf_md(pctx, prf) != 1 ||
|
||||
EVP_PKEY_CTX_set1_hkdf_salt(pctx, "", 0) != 1 ||
|
||||
EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, secretlen) != 1 ||
|
||||
EVP_PKEY_CTX_add1_hkdf_info(pctx, info, infolen) != 1 ||
|
||||
EVP_PKEY_derive(pctx, dest, &destlen) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hkdf_expand_label(uint8_t *dest, size_t destlen, const uint8_t *secret,
|
||||
size_t secretlen, const uint8_t *label, size_t labellen,
|
||||
const EVP_MD *prf) {
|
||||
std::array<uint8_t, 256> info;
|
||||
static constexpr const uint8_t LABEL[] = "tls13 ";
|
||||
|
||||
auto p = std::begin(info);
|
||||
*p++ = destlen / 256;
|
||||
*p++ = destlen % 256;
|
||||
*p++ = str_size(LABEL) + labellen;
|
||||
p = std::copy_n(LABEL, str_size(LABEL), p);
|
||||
p = std::copy_n(label, labellen, p);
|
||||
*p++ = 0;
|
||||
|
||||
return hkdf_expand(dest, destlen, secret, secretlen, info.data(),
|
||||
p - std::begin(info), prf);
|
||||
}
|
||||
|
||||
int derive_initial_secret(uint8_t *dest, size_t destlen, const uint8_t *secret,
|
||||
size_t secretlen, const uint8_t *salt,
|
||||
size_t saltlen) {
|
||||
return hkdf_extract(dest, destlen, secret, secretlen, salt, saltlen,
|
||||
EVP_sha256());
|
||||
}
|
||||
|
||||
int derive_client_initial_secret(uint8_t *dest, size_t destlen,
|
||||
const uint8_t *secret, size_t secretlen) {
|
||||
static constexpr uint8_t LABEL[] = "client in";
|
||||
return hkdf_expand_label(dest, destlen, secret, secretlen, LABEL,
|
||||
str_size(LABEL), EVP_sha256());
|
||||
}
|
||||
|
||||
int derive_server_initial_secret(uint8_t *dest, size_t destlen,
|
||||
const uint8_t *secret, size_t secretlen) {
|
||||
static constexpr uint8_t LABEL[] = "server in";
|
||||
return hkdf_expand_label(dest, destlen, secret, secretlen, LABEL,
|
||||
str_size(LABEL), EVP_sha256());
|
||||
}
|
||||
|
||||
int derive_packet_protection_key(uint8_t *key, size_t &keylen, uint8_t *iv,
|
||||
size_t &ivlen, const uint8_t *secret,
|
||||
size_t secretlen, const EVP_CIPHER *aead,
|
||||
const EVP_MD *prf) {
|
||||
int rv;
|
||||
static constexpr uint8_t KEY_LABEL[] = "quic key";
|
||||
static constexpr uint8_t IV_LABEL[] = "quic iv";
|
||||
|
||||
auto req_keylen = aead_key_length(aead);
|
||||
if (req_keylen > keylen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
keylen = req_keylen;
|
||||
rv = hkdf_expand_label(key, keylen, secret, secretlen, KEY_LABEL,
|
||||
str_size(KEY_LABEL), prf);
|
||||
if (rv != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto req_ivlen = std::max(static_cast<size_t>(8), aead_nonce_length(aead));
|
||||
if (req_ivlen > ivlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ivlen = req_ivlen;
|
||||
rv = hkdf_expand_label(iv, ivlen, secret, secretlen, IV_LABEL,
|
||||
str_size(IV_LABEL), prf);
|
||||
if (rv != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int derive_header_protection_key(uint8_t *key, size_t &keylen,
|
||||
const uint8_t *secret, size_t secretlen,
|
||||
const EVP_CIPHER *aead, const EVP_MD *prf) {
|
||||
int rv;
|
||||
static constexpr uint8_t LABEL[] = "quic hp";
|
||||
|
||||
auto req_keylen = aead_key_length(aead);
|
||||
if (req_keylen > keylen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
keylen = req_keylen;
|
||||
rv = hkdf_expand_label(key, keylen, secret, secretlen, LABEL, str_size(LABEL),
|
||||
prf);
|
||||
if (rv != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t encrypt(uint8_t *dest, size_t destlen, const uint8_t *plaintext,
|
||||
size_t plaintextlen, const uint8_t *key, size_t keylen,
|
||||
const uint8_t *nonce, size_t noncelen, const uint8_t *ad,
|
||||
size_t adlen, const EVP_CIPHER *aead) {
|
||||
auto taglen = aead_tag_length(aead);
|
||||
|
||||
if (destlen < plaintextlen + taglen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto actx = EVP_CIPHER_CTX_new();
|
||||
if (actx == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto actx_d = defer(EVP_CIPHER_CTX_free, actx);
|
||||
|
||||
if (EVP_EncryptInit_ex(actx, aead, nullptr, nullptr, nullptr) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_IVLEN, noncelen, nullptr) !=
|
||||
1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (aead == EVP_aes_128_ccm() &&
|
||||
EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_TAG, taglen, nullptr) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (EVP_EncryptInit_ex(actx, nullptr, nullptr, key, nonce) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t outlen = 0;
|
||||
int len;
|
||||
|
||||
if (aead == EVP_aes_128_ccm() &&
|
||||
EVP_EncryptUpdate(actx, nullptr, &len, nullptr, plaintextlen) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (EVP_EncryptUpdate(actx, nullptr, &len, ad, adlen) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (EVP_EncryptUpdate(actx, dest, &len, plaintext, plaintextlen) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
outlen = len;
|
||||
|
||||
if (EVP_EncryptFinal_ex(actx, dest + outlen, &len) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
outlen += len;
|
||||
|
||||
assert(outlen + taglen <= destlen);
|
||||
|
||||
if (EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_GET_TAG, taglen, dest + outlen) !=
|
||||
1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
outlen += taglen;
|
||||
|
||||
return outlen;
|
||||
}
|
||||
|
||||
ssize_t decrypt(uint8_t *dest, size_t destlen, const uint8_t *ciphertext,
|
||||
size_t ciphertextlen, const uint8_t *key, size_t keylen,
|
||||
const uint8_t *nonce, size_t noncelen, const uint8_t *ad,
|
||||
size_t adlen, const EVP_CIPHER *aead) {
|
||||
auto taglen = aead_tag_length(aead);
|
||||
|
||||
if (taglen > ciphertextlen || destlen + taglen < ciphertextlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ciphertextlen -= taglen;
|
||||
auto tag = ciphertext + ciphertextlen;
|
||||
|
||||
auto actx = EVP_CIPHER_CTX_new();
|
||||
if (actx == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto actx_d = defer(EVP_CIPHER_CTX_free, actx);
|
||||
|
||||
if (EVP_DecryptInit_ex(actx, aead, nullptr, nullptr, nullptr) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_IVLEN, noncelen, nullptr) !=
|
||||
1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (aead == EVP_aes_128_ccm() &&
|
||||
EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_TAG, taglen,
|
||||
const_cast<uint8_t *>(tag)) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (EVP_DecryptInit_ex(actx, nullptr, nullptr, key, nonce) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t outlen;
|
||||
int len;
|
||||
|
||||
if (aead == EVP_aes_128_ccm() &&
|
||||
EVP_DecryptUpdate(actx, nullptr, &len, nullptr, ciphertextlen) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (EVP_DecryptUpdate(actx, nullptr, &len, ad, adlen) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (EVP_DecryptUpdate(actx, dest, &len, ciphertext, ciphertextlen) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
outlen = len;
|
||||
|
||||
if (aead == EVP_aes_128_ccm()) {
|
||||
return outlen;
|
||||
}
|
||||
|
||||
if (EVP_CIPHER_CTX_ctrl(actx, EVP_CTRL_AEAD_SET_TAG, taglen,
|
||||
const_cast<uint8_t *>(tag)) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (EVP_DecryptFinal_ex(actx, dest + outlen, &len) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
outlen += len;
|
||||
|
||||
return outlen;
|
||||
}
|
||||
|
||||
ssize_t hp_mask(uint8_t *dest, size_t destlen, const uint8_t *key,
|
||||
size_t keylen, const uint8_t *sample, size_t samplelen,
|
||||
const EVP_CIPHER *cipher) {
|
||||
static constexpr uint8_t PLAINTEXT[] = "\x00\x00\x00\x00\x00";
|
||||
|
||||
auto actx = EVP_CIPHER_CTX_new();
|
||||
if (actx == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto actx_d = defer(EVP_CIPHER_CTX_free, actx);
|
||||
|
||||
if (EVP_EncryptInit_ex(actx, cipher, nullptr, key, sample) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t outlen = 0;
|
||||
int len;
|
||||
|
||||
if (EVP_EncryptUpdate(actx, dest, &len, PLAINTEXT, str_size(PLAINTEXT)) !=
|
||||
1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(len == 5);
|
||||
|
||||
outlen = len;
|
||||
|
||||
if (EVP_EncryptFinal_ex(actx, dest + outlen, &len) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(len == 0);
|
||||
|
||||
return outlen;
|
||||
}
|
||||
|
||||
Error err_transport(int liberr) {
|
||||
if (liberr == NGTCP2_ERR_RECV_VERSION_NEGOTIATION) {
|
||||
return {ErrorType::TransportVersionNegotiation, 0};
|
||||
|
|
52
src/quic.h
52
src/quic.h
|
@ -27,60 +27,10 @@
|
|||
|
||||
#include "nghttp2_config.h"
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include "stdint.h"
|
||||
|
||||
namespace quic {
|
||||
|
||||
const EVP_CIPHER *aead(SSL *ssl);
|
||||
const EVP_CIPHER *hp(SSL *ssl);
|
||||
const EVP_MD *prf(SSL *ssl);
|
||||
size_t aead_max_overhead(const EVP_CIPHER *aead);
|
||||
|
||||
int hkdf_extract(uint8_t *dest, size_t destlen, const uint8_t *secret,
|
||||
size_t secretlen, const uint8_t *salt, size_t saltlen,
|
||||
const EVP_MD *prf);
|
||||
|
||||
int hkdf_expand(uint8_t *dest, size_t destlen, const uint8_t *secret,
|
||||
size_t secretlen, const uint8_t *info, size_t infolen,
|
||||
const EVP_MD *prf);
|
||||
|
||||
int hkdf_expand_label(uint8_t *dest, size_t destlen, const uint8_t *secret,
|
||||
size_t secretlen, const uint8_t *label, size_t labellen,
|
||||
const EVP_MD *prf);
|
||||
|
||||
int derive_initial_secret(uint8_t *dest, size_t destlen, const uint8_t *secret,
|
||||
size_t secretlen, const uint8_t *salt,
|
||||
size_t saltlen);
|
||||
|
||||
int derive_client_initial_secret(uint8_t *dest, size_t destlen,
|
||||
const uint8_t *secret, size_t secretlen);
|
||||
|
||||
int derive_server_initial_secret(uint8_t *dest, size_t destlen,
|
||||
const uint8_t *secret, size_t secretlen);
|
||||
|
||||
int derive_packet_protection_key(uint8_t *key, size_t &keylen, uint8_t *iv,
|
||||
size_t &ivlen, const uint8_t *secret,
|
||||
size_t secretlen, const EVP_CIPHER *aead,
|
||||
const EVP_MD *prf);
|
||||
|
||||
int derive_header_protection_key(uint8_t *key, size_t &keylen,
|
||||
const uint8_t *secret, size_t secretlen,
|
||||
const EVP_CIPHER *aead, const EVP_MD *prf);
|
||||
|
||||
ssize_t encrypt(uint8_t *dest, size_t destlen, const uint8_t *plaintext,
|
||||
size_t plaintextlen, const uint8_t *key, size_t keylen,
|
||||
const uint8_t *nonce, size_t noncelen, const uint8_t *ad,
|
||||
size_t adlen, const EVP_CIPHER *aead);
|
||||
|
||||
ssize_t decrypt(uint8_t *dest, size_t destlen, const uint8_t *ciphertext,
|
||||
size_t ciphertextlen, const uint8_t *key, size_t keylen,
|
||||
const uint8_t *nonce, size_t noncelen, const uint8_t *ad,
|
||||
size_t adlen, const EVP_CIPHER *aead);
|
||||
|
||||
ssize_t hp_mask(uint8_t *dest, size_t destlen, const uint8_t *key,
|
||||
size_t keylen, const uint8_t *sample, size_t samplelen,
|
||||
const EVP_CIPHER *cipher);
|
||||
|
||||
enum class ErrorType {
|
||||
Transport,
|
||||
TransportVersionNegotiation,
|
||||
|
|
Loading…
Reference in New Issue