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)
|
AC_MSG_NOTICE($LIBNGTCP2_PKG_ERRORS)
|
||||||
fi
|
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)
|
# nghttp3 (for src)
|
||||||
PKG_CHECK_MODULES([LIBNGHTTP3], [libnghttp3 >= 0.0.0], [have_libnghttp3=yes],
|
PKG_CHECK_MODULES([LIBNGHTTP3], [libnghttp3 >= 0.0.0], [have_libnghttp3=yes],
|
||||||
[have_libnghttp3=no])
|
[have_libnghttp3=no])
|
||||||
|
@ -917,6 +926,7 @@ AC_MSG_NOTICE([summary of build options:
|
||||||
Libev: ${have_libev} (CFLAGS='${LIBEV_CFLAGS}' LIBS='${LIBEV_LIBS}')
|
Libev: ${have_libev} (CFLAGS='${LIBEV_CFLAGS}' LIBS='${LIBEV_LIBS}')
|
||||||
Libc-ares: ${have_libcares} (CFLAGS='${LIBCARES_CFLAGS}' LIBS='${LIBCARES_LIBS}')
|
Libc-ares: ${have_libcares} (CFLAGS='${LIBCARES_CFLAGS}' LIBS='${LIBCARES_LIBS}')
|
||||||
libngtcp2: ${have_libngtcp2} (CFLAGS='${LIBNGTCP2_CFLAGS}' LIBS='${LIBNGTCP2_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}')
|
libnghttp3: ${have_libnghttp3} (CFLAGS='${LIBNGHTTP3_CFLAGS}' LIBS='${LIBNGHTTP3_LIBS}')
|
||||||
Libevent(SSL): ${have_libevent_openssl} (CFLAGS='${LIBEVENT_OPENSSL_CFLAGS}' LIBS='${LIBEVENT_OPENSSL_LIBS}')
|
Libevent(SSL): ${have_libevent_openssl} (CFLAGS='${LIBEVENT_OPENSSL_CFLAGS}' LIBS='${LIBEVENT_OPENSSL_LIBS}')
|
||||||
Jansson: ${have_jansson} (CFLAGS='${JANSSON_CFLAGS}' LIBS='${JANSSON_LIBS}')
|
Jansson: ${have_jansson} (CFLAGS='${JANSSON_CFLAGS}' LIBS='${JANSSON_LIBS}')
|
||||||
|
|
|
@ -46,6 +46,7 @@ AM_CPPFLAGS = \
|
||||||
@OPENSSL_CFLAGS@ \
|
@OPENSSL_CFLAGS@ \
|
||||||
@LIBCARES_CFLAGS@ \
|
@LIBCARES_CFLAGS@ \
|
||||||
@LIBNGHTTP3_CFLAGS@ \
|
@LIBNGHTTP3_CFLAGS@ \
|
||||||
|
@LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS@ \
|
||||||
@LIBNGTCP2_CFLAGS@ \
|
@LIBNGTCP2_CFLAGS@ \
|
||||||
@JANSSON_CFLAGS@ \
|
@JANSSON_CFLAGS@ \
|
||||||
@ZLIB_CFLAGS@ \
|
@ZLIB_CFLAGS@ \
|
||||||
|
@ -60,6 +61,7 @@ LDADD = $(top_builddir)/lib/libnghttp2.la \
|
||||||
@OPENSSL_LIBS@ \
|
@OPENSSL_LIBS@ \
|
||||||
@LIBCARES_LIBS@ \
|
@LIBCARES_LIBS@ \
|
||||||
@LIBNGHTTP3_LIBS@ \
|
@LIBNGHTTP3_LIBS@ \
|
||||||
|
@LIBNGTCP2_CRYPTO_OPENSSL_LIBS@ \
|
||||||
@LIBNGTCP2_LIBS@ \
|
@LIBNGTCP2_LIBS@ \
|
||||||
@SYSTEMD_LIBS@ \
|
@SYSTEMD_LIBS@ \
|
||||||
@JANSSON_LIBS@ \
|
@JANSSON_LIBS@ \
|
||||||
|
|
|
@ -2168,6 +2168,8 @@ Options:
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
extern ngtcp2_crypto_ctx in_crypto_ctx;
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
tls::libssl_init();
|
tls::libssl_init();
|
||||||
|
|
||||||
|
@ -2808,6 +2810,8 @@ int main(int argc, char **argv) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngtcp2_crypto_ctx_initial(&in_crypto_ctx);
|
||||||
|
|
||||||
resolve_host();
|
resolve_host();
|
||||||
|
|
||||||
std::cout << "starting benchmark..." << std::endl;
|
std::cout << "starting benchmark..." << std::endl;
|
||||||
|
|
27
src/h2load.h
27
src/h2load.h
|
@ -46,6 +46,7 @@
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|
||||||
#include <ngtcp2/ngtcp2.h>
|
#include <ngtcp2/ngtcp2.h>
|
||||||
|
#include <ngtcp2/ngtcp2_crypto.h>
|
||||||
|
|
||||||
#include <ev.h>
|
#include <ev.h>
|
||||||
|
|
||||||
|
@ -328,6 +329,7 @@ struct Client {
|
||||||
ngtcp2_crypto_level rx_crypto_level;
|
ngtcp2_crypto_level rx_crypto_level;
|
||||||
std::vector<uint8_t> server_handshake;
|
std::vector<uint8_t> server_handshake;
|
||||||
size_t server_handshake_nread;
|
size_t server_handshake_nread;
|
||||||
|
ngtcp2_crypto_ctx crypto_ctx;
|
||||||
// Client never send CRYPTO in Short packet.
|
// Client never send CRYPTO in Short packet.
|
||||||
std::array<Crypto, 2> crypto;
|
std::array<Crypto, 2> crypto;
|
||||||
size_t max_pktlen;
|
size_t max_pktlen;
|
||||||
|
@ -446,26 +448,23 @@ struct Client {
|
||||||
int quic_recv_crypto_data(ngtcp2_crypto_level crypto_level,
|
int quic_recv_crypto_data(ngtcp2_crypto_level crypto_level,
|
||||||
const uint8_t *data, size_t datalen);
|
const uint8_t *data, size_t datalen);
|
||||||
int quic_handshake_completed();
|
int quic_handshake_completed();
|
||||||
int quic_in_encrypt(uint8_t *dest, size_t destlen, const uint8_t *plaintext,
|
int quic_in_encrypt(uint8_t *dest, const uint8_t *plaintext,
|
||||||
size_t plaintextlen, const uint8_t *key, size_t keylen,
|
size_t plaintextlen, const uint8_t *key,
|
||||||
const uint8_t *nonce, size_t noncelen, const uint8_t *ad,
|
const uint8_t *nonce, size_t noncelen, const uint8_t *ad,
|
||||||
size_t adlen);
|
size_t adlen);
|
||||||
int quic_in_decrypt(uint8_t *dest, size_t destlen, const uint8_t *ciphertext,
|
int quic_in_decrypt(uint8_t *dest, const uint8_t *ciphertext,
|
||||||
size_t ciphertextlen, const uint8_t *key, size_t keylen,
|
size_t ciphertextlen, const uint8_t *key,
|
||||||
const uint8_t *nonce, size_t noncelen, const uint8_t *ad,
|
const uint8_t *nonce, size_t noncelen, const uint8_t *ad,
|
||||||
size_t adlen);
|
size_t adlen);
|
||||||
int quic_encrypt(uint8_t *dest, size_t destlen, const uint8_t *plaintext,
|
int quic_encrypt(uint8_t *dest, const uint8_t *plaintext, size_t plaintextlen,
|
||||||
size_t plaintextlen, const uint8_t *key, size_t keylen,
|
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,
|
const uint8_t *nonce, size_t noncelen, const uint8_t *ad,
|
||||||
size_t adlen);
|
size_t adlen);
|
||||||
int quic_decrypt(uint8_t *dest, size_t destlen, const uint8_t *ciphertext,
|
int quic_in_hp_mask(uint8_t *dest, const uint8_t *key, const uint8_t *sample);
|
||||||
size_t ciphertextlen, const uint8_t *key, size_t keylen,
|
int quic_hp_mask(uint8_t *dest, const uint8_t *key, const uint8_t *sample);
|
||||||
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_recv_stream_data(int64_t stream_id, int fin, const uint8_t *data,
|
int quic_recv_stream_data(int64_t stream_id, int fin, const uint8_t *data,
|
||||||
size_t datalen);
|
size_t datalen);
|
||||||
int quic_stream_close(int64_t stream_id, uint64_t app_error_code);
|
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;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = nghttp3_conn_end_stream(conn_, stream_id);
|
|
||||||
assert(0 == rv);
|
|
||||||
|
|
||||||
client_->on_request(stream_id);
|
client_->on_request(stream_id);
|
||||||
auto req_stat = client_->get_req_stat(stream_id);
|
auto req_stat = client_->get_req_stat(stream_id);
|
||||||
assert(req_stat);
|
assert(req_stat);
|
||||||
|
|
|
@ -37,6 +37,8 @@ namespace {
|
||||||
auto randgen = util::make_mt19937();
|
auto randgen = util::make_mt19937();
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
ngtcp2_crypto_ctx in_crypto_ctx;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int client_initial(ngtcp2_conn *conn, void *user_data) {
|
int client_initial(ngtcp2_conn *conn, void *user_data) {
|
||||||
auto c = static_cast<Client *>(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
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
ssize_t in_encrypt(ngtcp2_conn *conn, uint8_t *dest, size_t destlen,
|
int in_encrypt(ngtcp2_conn *conn, uint8_t *dest, const uint8_t *plaintext,
|
||||||
const uint8_t *plaintext, size_t plaintextlen,
|
size_t plaintextlen, const uint8_t *key, const uint8_t *nonce,
|
||||||
const uint8_t *key, size_t keylen, const uint8_t *nonce,
|
size_t noncelen, const uint8_t *ad, size_t adlen,
|
||||||
size_t noncelen, const uint8_t *ad, size_t adlen,
|
void *user_data) {
|
||||||
void *user_data) {
|
|
||||||
auto c = static_cast<Client *>(user_data);
|
auto c = static_cast<Client *>(user_data);
|
||||||
|
|
||||||
auto nwrite = c->quic_in_encrypt(dest, destlen, plaintext, plaintextlen, key,
|
if (c->quic_in_encrypt(dest, plaintext, plaintextlen, key, nonce, noncelen,
|
||||||
keylen, nonce, noncelen, ad, adlen);
|
ad, adlen) != 0) {
|
||||||
if (nwrite < 0) {
|
|
||||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nwrite;
|
return 0;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int Client::quic_in_encrypt(uint8_t *dest, size_t destlen,
|
int Client::quic_in_encrypt(uint8_t *dest, const uint8_t *plaintext,
|
||||||
const uint8_t *plaintext, size_t plaintextlen,
|
size_t plaintextlen, const uint8_t *key,
|
||||||
const uint8_t *key, size_t keylen,
|
|
||||||
const uint8_t *nonce, size_t noncelen,
|
const uint8_t *nonce, size_t noncelen,
|
||||||
const uint8_t *ad, size_t adlen) {
|
const uint8_t *ad, size_t adlen) {
|
||||||
return quic::encrypt(dest, destlen, plaintext, plaintextlen, key, keylen,
|
return ngtcp2_crypto_encrypt(dest, &in_crypto_ctx.aead, plaintext,
|
||||||
nonce, noncelen, ad, adlen, EVP_aes_128_gcm());
|
plaintextlen, key, nonce, noncelen, ad, adlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
ssize_t in_decrypt(ngtcp2_conn *conn, uint8_t *dest, size_t destlen,
|
int in_decrypt(ngtcp2_conn *conn, uint8_t *dest, const uint8_t *ciphertext,
|
||||||
const uint8_t *ciphertext, size_t ciphertextlen,
|
size_t ciphertextlen, const uint8_t *key, const uint8_t *nonce,
|
||||||
const uint8_t *key, size_t keylen, const uint8_t *nonce,
|
size_t noncelen, const uint8_t *ad, size_t adlen,
|
||||||
size_t noncelen, const uint8_t *ad, size_t adlen,
|
void *user_data) {
|
||||||
void *user_data) {
|
|
||||||
auto c = static_cast<Client *>(user_data);
|
auto c = static_cast<Client *>(user_data);
|
||||||
|
|
||||||
auto nwrite = c->quic_in_decrypt(dest, destlen, ciphertext, ciphertextlen,
|
if (c->quic_in_decrypt(dest, ciphertext, ciphertextlen, key, nonce, noncelen,
|
||||||
key, keylen, nonce, noncelen, ad, adlen);
|
ad, adlen) != 0) {
|
||||||
if (nwrite < 0) {
|
|
||||||
return NGTCP2_ERR_TLS_DECRYPT;
|
return NGTCP2_ERR_TLS_DECRYPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nwrite;
|
return 0;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int Client::quic_in_decrypt(uint8_t *dest, size_t destlen,
|
int Client::quic_in_decrypt(uint8_t *dest, const uint8_t *ciphertext,
|
||||||
const uint8_t *ciphertext, size_t ciphertextlen,
|
size_t ciphertextlen, const uint8_t *key,
|
||||||
const uint8_t *key, size_t keylen,
|
|
||||||
const uint8_t *nonce, size_t noncelen,
|
const uint8_t *nonce, size_t noncelen,
|
||||||
const uint8_t *ad, size_t adlen) {
|
const uint8_t *ad, size_t adlen) {
|
||||||
return quic::decrypt(dest, destlen, ciphertext, ciphertextlen, key, keylen,
|
return ngtcp2_crypto_decrypt(dest, &in_crypto_ctx.aead, ciphertext,
|
||||||
nonce, noncelen, ad, adlen, EVP_aes_128_gcm());
|
ciphertextlen, key, nonce, noncelen, ad, adlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
ssize_t encrypt(ngtcp2_conn *conn, uint8_t *dest, size_t destlen,
|
int encrypt(ngtcp2_conn *conn, uint8_t *dest, const uint8_t *plaintext,
|
||||||
const uint8_t *plaintext, size_t plaintextlen,
|
size_t plaintextlen, const uint8_t *key, const uint8_t *nonce,
|
||||||
const uint8_t *key, size_t keylen, const uint8_t *nonce,
|
size_t noncelen, const uint8_t *ad, size_t adlen, void *user_data) {
|
||||||
size_t noncelen, const uint8_t *ad, size_t adlen,
|
|
||||||
void *user_data) {
|
|
||||||
auto c = static_cast<Client *>(user_data);
|
auto c = static_cast<Client *>(user_data);
|
||||||
|
|
||||||
auto nwrite = c->quic_encrypt(dest, destlen, plaintext, plaintextlen, key,
|
if (c->quic_encrypt(dest, plaintext, plaintextlen, key, nonce, noncelen, ad,
|
||||||
keylen, nonce, noncelen, ad, adlen);
|
adlen) != 0) {
|
||||||
if (nwrite < 0) {
|
|
||||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nwrite;
|
return 0;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int Client::quic_encrypt(uint8_t *dest, size_t destlen,
|
int Client::quic_encrypt(uint8_t *dest, const uint8_t *plaintext,
|
||||||
const uint8_t *plaintext, size_t plaintextlen,
|
size_t plaintextlen, const uint8_t *key,
|
||||||
const uint8_t *key, size_t keylen,
|
|
||||||
const uint8_t *nonce, size_t noncelen,
|
const uint8_t *nonce, size_t noncelen,
|
||||||
const uint8_t *ad, size_t adlen) {
|
const uint8_t *ad, size_t adlen) {
|
||||||
return quic::encrypt(dest, destlen, plaintext, plaintextlen, key, keylen,
|
return ngtcp2_crypto_encrypt(dest, &quic.crypto_ctx.aead, plaintext,
|
||||||
nonce, noncelen, ad, adlen, quic::aead(ssl));
|
plaintextlen, key, nonce, noncelen, ad, adlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
ssize_t decrypt(ngtcp2_conn *conn, uint8_t *dest, size_t destlen,
|
int decrypt(ngtcp2_conn *conn, uint8_t *dest, const uint8_t *ciphertext,
|
||||||
const uint8_t *ciphertext, size_t ciphertextlen,
|
size_t ciphertextlen, const uint8_t *key, const uint8_t *nonce,
|
||||||
const uint8_t *key, size_t keylen, const uint8_t *nonce,
|
size_t noncelen, const uint8_t *ad, size_t adlen, void *user_data) {
|
||||||
size_t noncelen, const uint8_t *ad, size_t adlen,
|
|
||||||
void *user_data) {
|
|
||||||
auto c = static_cast<Client *>(user_data);
|
auto c = static_cast<Client *>(user_data);
|
||||||
|
|
||||||
auto nwrite = c->quic_decrypt(dest, destlen, ciphertext, ciphertextlen, key,
|
if (c->quic_decrypt(dest, ciphertext, ciphertextlen, key, nonce, noncelen, ad,
|
||||||
keylen, nonce, noncelen, ad, adlen);
|
adlen) != 0) {
|
||||||
if (nwrite < 0) {
|
|
||||||
return NGTCP2_ERR_TLS_DECRYPT;
|
return NGTCP2_ERR_TLS_DECRYPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nwrite;
|
return 0;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int Client::quic_decrypt(uint8_t *dest, size_t destlen,
|
int Client::quic_decrypt(uint8_t *dest, const uint8_t *ciphertext,
|
||||||
const uint8_t *ciphertext, size_t ciphertextlen,
|
size_t ciphertextlen, const uint8_t *key,
|
||||||
const uint8_t *key, size_t keylen,
|
|
||||||
const uint8_t *nonce, size_t noncelen,
|
const uint8_t *nonce, size_t noncelen,
|
||||||
const uint8_t *ad, size_t adlen) {
|
const uint8_t *ad, size_t adlen) {
|
||||||
return quic::decrypt(dest, destlen, ciphertext, ciphertextlen, key, keylen,
|
return ngtcp2_crypto_decrypt(dest, &quic.crypto_ctx.aead, ciphertext,
|
||||||
nonce, noncelen, ad, adlen, quic::aead(ssl));
|
ciphertextlen, key, nonce, noncelen, ad, adlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
ssize_t in_hp_mask(ngtcp2_conn *conn, uint8_t *dest, size_t destlen,
|
int in_hp_mask(ngtcp2_conn *conn, uint8_t *dest, const uint8_t *key,
|
||||||
const uint8_t *key, size_t keylen, const uint8_t *sample,
|
const uint8_t *sample, void *user_data) {
|
||||||
size_t samplelen, void *user_data) {
|
|
||||||
auto c = static_cast<Client *>(user_data);
|
auto c = static_cast<Client *>(user_data);
|
||||||
|
|
||||||
auto nwrite =
|
if (c->quic_in_hp_mask(dest, key, sample) != 0) {
|
||||||
c->quic_in_hp_mask(dest, destlen, key, keylen, sample, samplelen);
|
|
||||||
if (nwrite < 0) {
|
|
||||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nwrite;
|
return 0;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int Client::quic_in_hp_mask(uint8_t *dest, size_t destlen, const uint8_t *key,
|
int Client::quic_in_hp_mask(uint8_t *dest, const uint8_t *key,
|
||||||
size_t keylen, const uint8_t *sample,
|
const uint8_t *sample) {
|
||||||
size_t samplelen) {
|
return ngtcp2_crypto_hp_mask(dest, &in_crypto_ctx.hp, key, sample);
|
||||||
return quic::hp_mask(dest, destlen, key, keylen, sample, samplelen,
|
|
||||||
EVP_aes_128_ctr());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
ssize_t hp_mask(ngtcp2_conn *conn, uint8_t *dest, size_t destlen,
|
int hp_mask(ngtcp2_conn *conn, uint8_t *dest, const uint8_t *key,
|
||||||
const uint8_t *key, size_t keylen, const uint8_t *sample,
|
const uint8_t *sample, void *user_data) {
|
||||||
size_t samplelen, void *user_data) {
|
|
||||||
auto c = static_cast<Client *>(user_data);
|
auto c = static_cast<Client *>(user_data);
|
||||||
|
|
||||||
auto nwrite = c->quic_hp_mask(dest, destlen, key, keylen, sample, samplelen);
|
if (c->quic_hp_mask(dest, key, sample) != 0) {
|
||||||
if (nwrite < 0) {
|
|
||||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nwrite;
|
return 0;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int Client::quic_hp_mask(uint8_t *dest, size_t destlen, const uint8_t *key,
|
int Client::quic_hp_mask(uint8_t *dest, const uint8_t *key,
|
||||||
size_t keylen, const uint8_t *sample,
|
const uint8_t *sample) {
|
||||||
size_t samplelen) {
|
return ngtcp2_crypto_hp_mask(dest, &quic.crypto_ctx.hp, key, sample);
|
||||||
return quic::hp_mask(dest, destlen, key, keylen, sample, samplelen,
|
|
||||||
quic::hp(ssl));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -669,71 +648,45 @@ void Client::quic_close_connection() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int Client::quic_setup_initial_crypto() {
|
int Client::quic_setup_initial_crypto() {
|
||||||
int rv;
|
std::array<uint8_t, 32> tx_secret, rx_secret;
|
||||||
|
|
||||||
std::array<uint8_t, 32> initial_secret, secret;
|
|
||||||
auto dcid = ngtcp2_conn_get_dcid(quic.conn);
|
auto dcid = ngtcp2_conn_get_dcid(quic.conn);
|
||||||
rv = quic::derive_initial_secret(
|
if (ngtcp2_crypto_derive_initial_secrets(rx_secret.data(), tx_secret.data(),
|
||||||
initial_secret.data(), initial_secret.size(), dcid->data, dcid->datalen,
|
nullptr, dcid,
|
||||||
reinterpret_cast<const uint8_t *>(NGTCP2_INITIAL_SALT),
|
NGTCP2_CRYPTO_SIDE_CLIENT) != 0) {
|
||||||
str_size(NGTCP2_INITIAL_SALT));
|
std::cerr << "ngtcp2_crypto_derive_initial_secrets() failed" << std::endl;
|
||||||
if (rv != 0) {
|
|
||||||
std::cerr << "quic::derive_initial_secret() failed" << std::endl;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto aead = EVP_aes_128_gcm();
|
auto aead = &in_crypto_ctx.aead;
|
||||||
auto prf = EVP_sha256();
|
auto md = &in_crypto_ctx.md;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::array<uint8_t, 16> key, iv, hp;
|
std::array<uint8_t, 16> key, iv, hp;
|
||||||
auto keylen = key.size();
|
auto keylen = ngtcp2_crypto_aead_keylen(aead);
|
||||||
auto ivlen = iv.size();
|
auto ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
|
||||||
rv = quic::derive_packet_protection_key(key.data(), keylen, iv.data(), ivlen,
|
auto hplen = keylen;
|
||||||
secret.data(), secret.size(), aead,
|
|
||||||
prf);
|
if (ngtcp2_crypto_derive_packet_protection_key(key.data(), iv.data(), aead,
|
||||||
if (rv != 0) {
|
md, tx_secret.data(),
|
||||||
|
tx_secret.size()) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto hplen = hp.size();
|
if (ngtcp2_crypto_derive_header_protection_key(
|
||||||
rv = quic::derive_header_protection_key(hp.data(), hplen, secret.data(),
|
hp.data(), aead, md, tx_secret.data(), tx_secret.size()) != 0) {
|
||||||
secret.size(), aead, prf);
|
|
||||||
if (rv != 0) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngtcp2_conn_install_initial_tx_keys(quic.conn, key.data(), keylen, iv.data(),
|
ngtcp2_conn_install_initial_tx_keys(quic.conn, key.data(), keylen, iv.data(),
|
||||||
ivlen, hp.data(), hplen);
|
ivlen, hp.data(), hplen);
|
||||||
|
|
||||||
rv = quic::derive_server_initial_secret(secret.data(), secret.size(),
|
if (ngtcp2_crypto_derive_packet_protection_key(key.data(), iv.data(), aead,
|
||||||
initial_secret.data(),
|
md, rx_secret.data(),
|
||||||
initial_secret.size());
|
rx_secret.size()) != 0) {
|
||||||
if (rv != 0) {
|
|
||||||
std::cerr << "quic::derive_server_initial_secret() failed" << std::endl;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
keylen = key.size();
|
if (ngtcp2_crypto_derive_header_protection_key(
|
||||||
ivlen = iv.size();
|
hp.data(), aead, md, rx_secret.data(), rx_secret.size()) != 0) {
|
||||||
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) {
|
|
||||||
return -1;
|
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 Client::quic_on_key(int name, const uint8_t *secret, size_t secretlen) {
|
||||||
int rv;
|
|
||||||
|
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case SSL_KEY_CLIENT_EARLY_TRAFFIC:
|
case SSL_KEY_CLIENT_EARLY_TRAFFIC:
|
||||||
case SSL_KEY_CLIENT_HANDSHAKE_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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto aead = quic::aead(ssl);
|
if (quic.crypto_ctx.aead.native_handle == nullptr) {
|
||||||
auto prf = quic::prf(ssl);
|
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;
|
std::array<uint8_t, 64> key, iv, hp;
|
||||||
auto keylen = key.size();
|
auto keylen = ngtcp2_crypto_aead_keylen(aead);
|
||||||
auto ivlen = iv.size();
|
auto ivlen = ngtcp2_crypto_packet_protection_ivlen(aead);
|
||||||
rv = quic::derive_packet_protection_key(key.data(), keylen, iv.data(), ivlen,
|
auto hplen = keylen;
|
||||||
secret, secretlen, aead, prf);
|
|
||||||
if (rv != 0) {
|
if (ngtcp2_crypto_derive_packet_protection_key(key.data(), iv.data(), aead,
|
||||||
|
md, secret, secretlen) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto hplen = hp.size();
|
if (ngtcp2_crypto_derive_header_protection_key(hp.data(), aead, md, secret,
|
||||||
rv = quic::derive_header_protection_key(hp.data(), hplen, secret, secretlen,
|
secretlen) != 0) {
|
||||||
aead, prf);
|
|
||||||
if (rv != 0) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Just call this once.
|
|
||||||
ngtcp2_conn_set_aead_overhead(quic.conn, quic::aead_max_overhead(aead));
|
|
||||||
|
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case SSL_KEY_CLIENT_EARLY_TRAFFIC:
|
case SSL_KEY_CLIENT_EARLY_TRAFFIC:
|
||||||
ngtcp2_conn_install_early_keys(quic.conn, key.data(), keylen, iv.data(),
|
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 <cassert>
|
||||||
|
|
||||||
#include <openssl/kdf.h>
|
|
||||||
|
|
||||||
#include <ngtcp2/ngtcp2.h>
|
#include <ngtcp2/ngtcp2.h>
|
||||||
#include <nghttp3/nghttp3.h>
|
#include <nghttp3/nghttp3.h>
|
||||||
|
|
||||||
|
@ -37,402 +35,6 @@ using namespace nghttp2;
|
||||||
|
|
||||||
namespace quic {
|
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) {
|
Error err_transport(int liberr) {
|
||||||
if (liberr == NGTCP2_ERR_RECV_VERSION_NEGOTIATION) {
|
if (liberr == NGTCP2_ERR_RECV_VERSION_NEGOTIATION) {
|
||||||
return {ErrorType::TransportVersionNegotiation, 0};
|
return {ErrorType::TransportVersionNegotiation, 0};
|
||||||
|
|
52
src/quic.h
52
src/quic.h
|
@ -27,60 +27,10 @@
|
||||||
|
|
||||||
#include "nghttp2_config.h"
|
#include "nghttp2_config.h"
|
||||||
|
|
||||||
#include <openssl/ssl.h>
|
#include "stdint.h"
|
||||||
|
|
||||||
namespace quic {
|
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 {
|
enum class ErrorType {
|
||||||
Transport,
|
Transport,
|
||||||
TransportVersionNegotiation,
|
TransportVersionNegotiation,
|
||||||
|
|
Loading…
Reference in New Issue