diff --git a/CMakeLists.txt b/CMakeLists.txt index d4efd0e25f56180462831d5c315734d6ad834d2d..a3c9d49465ed49a1dfc985492f9bea4c6547053e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,6 +67,7 @@ foreach(_build_type "Release" "MinSizeRel" "RelWithDebInfo") endforeach() +find_package(GnuTLS 3.6.12) find_package(OpenSSL 1.1.1) find_package(Libev 4.11) find_package(Libnghttp3 0.0.0) @@ -81,6 +82,7 @@ endif() set(HAVE_OPENSSL ${OPENSSL_FOUND}) if(OPENSSL_FOUND) set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR}) + set(HAVE_CRYPTO 1) else() set(OPENSSL_INCLUDE_DIRS "") set(OPENSSL_LIBRARIES "") @@ -90,6 +92,16 @@ set(HAVE_LIBEV ${LIBEV_FOUND}) # libnghttp3 (for examples) set(HAVE_LIBNGHTTP3 ${LIBNGHTTP3_FOUND}) +# GnuTLS (for examples) +set(HAVE_GNUTLS ${GNUTLS_FOUND}) +if(GNUTLS_FOUND) + set(GNUTLS_INCLUDE_DIRS ${GNUTLS_INCLUDE_DIR}) + set(HAVE_CRYPTO 1) +else() + set(GNUTLS_INCLUDE_DIRS "") + set(GNUTLS_LIBRARIES "") +endif() + # Checks for header files. include(CheckIncludeFile) check_include_file("arpa/inet.h" HAVE_ARPA_INET_H) @@ -280,4 +292,5 @@ message(STATUS "summary of build options: OpenSSL: ${HAVE_OPENSSL} (LIBS='${OPENSSL_LIBRARIES}') Libev: ${HAVE_LIBEV} (LIBS='${LIBEV_LIBRARIES}') Libnghttp3: ${HAVE_LIBNGHTTP3} (LIBS='${LIBNGHTTP3_LIBRARIES}') + GnuTLS: ${HAVE_GNUTLS} (LIBS='${GNUTLS_LIBRARIES}') ") diff --git a/Makefile.am b/Makefile.am index 2359589bf1f39b3824b8c807f50f83401958c4ac..42bc1d8ba618537222c15f324887a92dde04a302 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,7 +22,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SUBDIRS = lib tests -if HAVE_OPENSSL +if HAVE_CRYPTO SUBDIRS += crypto endif diff --git a/configure.ac b/configure.ac index dd9e7c3a701cb20563300f314d4d7fbaee03a3cf..8701840fd467cd49a12d0dce59ac4d2556b72ba8 100644 --- a/configure.ac +++ b/configure.ac @@ -49,6 +49,10 @@ AC_SUBST(CRYPTO_OPENSSL_LT_CURRENT, 0) AC_SUBST(CRYPTO_OPENSSL_LT_REVISION, 0) AC_SUBST(CRYPTO_OPENSSL_LT_AGE, 0) +AC_SUBST(CRYPTO_GNUTLS_LT_CURRENT, 0) +AC_SUBST(CRYPTO_GNUTLS_LT_REVISION, 0) +AC_SUBST(CRYPTO_GNUTLS_LT_AGE, 0) + # from nghttp2 major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"` minor=`echo $PACKAGE_VERSION |cut -d. -f2 | sed -e "s/[^0-9]//g"` @@ -144,6 +148,16 @@ if test "x${have_openssl}" = "xno"; then fi AM_CONDITIONAL([HAVE_OPENSSL], [ test "x${have_openssl}" = "xyes" ]) +# GnuTLS (for examples) +PKG_CHECK_MODULES([GNUTLS], [gnutls >= 3.6.11], + [have_gnutls=yes], [have_gnutls=no]) +if test "x${have_gnutls}" = "xno"; then + AC_MSG_NOTICE($GNUTLS_PKG_ERRORS) +fi +AM_CONDITIONAL([HAVE_GNUTLS], [ test "x${have_gnutls}" = "xyes" ]) + +AM_CONDITIONAL([HAVE_CRYPTO], [ test "x${have_openssl}" = "xyes" || test "x${have_gnutls}" = "xyes" ]) + # libnghttp3 (for examples) PKG_CHECK_MODULES([LIBNGHTTP3], [libnghttp3 >= 0.0.0], [have_libnghttp3=yes], [have_libnghttp3=no]) @@ -368,6 +382,8 @@ AC_CONFIG_FILES([ crypto/openssl/Makefile crypto/openssl/libngtcp2_crypto_openssl.pc crypto/includes/Makefile + crypto/gnutls/Makefile + crypto/gnutls/libngtcp2_crypto_gnutls.pc third-party/Makefile examples/Makefile ]) @@ -399,6 +415,7 @@ AC_MSG_NOTICE([summary of build options: Static: ${enable_static} Crypto helper libraries: libngtcp2_crypto_openssl: ${have_openssl} + libngtcp2_crypto_gnutls: ${have_gnutls} Test: CUnit: ${have_cunit} (CFLAGS='${CUNIT_CFLAGS}' LIBS='${CUNIT_LIBS}') Debug: @@ -408,5 +425,6 @@ AC_MSG_NOTICE([summary of build options: Libev: ${have_libev} (CFLAGS='${LIBEV_CFLAGS}' LIBS='${LIBEV_LIBS}') Libnghttp3: ${have_libnghttp3} (CFLAGS='${LIBNGHTTP3_CFLAGS}' LIBS='${LIBNGHTTP3_LIBS}') Jemalloc: ${have_jemalloc} (LIBS='${JEMALLOC_LIBS}') + GnuTLS: ${have_gnutls} (CFLAGS='${GNUTLS_CFLAGS}' LIBS='${GNUTLS_LIBS}') Examples: ${enable_examples} ]) diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt index 0e7059691f46d4e1ab3b0b2c0417f838ae7f690b..f916455e3848efe36606a672a4b531e1fe77a872 100644 --- a/crypto/CMakeLists.txt +++ b/crypto/CMakeLists.txt @@ -21,9 +21,18 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -if(OPENSSL_FOUND) +if(HAVE_CRYPTO) add_subdirectory(includes) +endif() + +if(OPENSSL_FOUND) add_subdirectory(openssl) else() message(WARNING "libngtcp2_crypto_openssl library is disabled due to lack of good OpenSSL") endif() + +if(GNUTLS_FOUND) + add_subdirectory(gnutls) +else() + message(WARNING "libngtcp2_crypto_gnutls library is disabled due to lack of good GnuTLS") +endif() diff --git a/crypto/Makefile.am b/crypto/Makefile.am index a3468643aba6dace2ae7172b0d794c2ac9333588..fc7cb8f220ac0cfac8f48550d9cdccca3218a056 100644 --- a/crypto/Makefile.am +++ b/crypto/Makefile.am @@ -22,6 +22,14 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SUBDIRS = +if HAVE_CRYPTO +SUBDIRS += includes +endif + if HAVE_OPENSSL -SUBDIRS += includes openssl +SUBDIRS += openssl +endif + +if HAVE_GNUTLS +SUBDIRS += gnutls endif diff --git a/crypto/gnutls/.gitignore b/crypto/gnutls/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b11bf3d7ff2ba75d205ce8086be6211f890300fc --- /dev/null +++ b/crypto/gnutls/.gitignore @@ -0,0 +1 @@ +/libngtcp2_crypto_gnutls.pc diff --git a/crypto/gnutls/CMakeLists.txt b/crypto/gnutls/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..d78b3f2a4500a4ce85a83dafc8fdd2a379fb99c5 --- /dev/null +++ b/crypto/gnutls/CMakeLists.txt @@ -0,0 +1,62 @@ +# ngtcp2 + +# Copyright (c) 2020 ngtcp2 + +# 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. + +add_definitions(-DBUILDING_NGTCP2) + +set(ngtcp2_crypto_gnutls_SOURCES + gnutls.c + ../shared.c +) + +set(ngtcp2_crypto_gnutls_INCLUDE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}/../../lib/includes" + "${CMAKE_CURRENT_BINARY_DIR}/../../lib/includes" + "${CMAKE_CURRENT_SOURCE_DIR}/../../lib" + "${CMAKE_CURRENT_SOURCE_DIR}/../../crypto/includes" + "${CMAKE_CURRENT_BINARY_DIR}/../../crypto/includes" + "${GNUTLS_INCLUDE_DIRS}" +) + +foreach(name libngtcp2_crypto_gnutls.pc) + configure_file("${name}.in" "${name}" @ONLY) +endforeach() + +# Public shared library +add_library(ngtcp2_crypto_gnutls ${ngtcp2_crypto_gnutls_SOURCES}) +set_target_properties(ngtcp2_crypto_gnutls PROPERTIES + COMPILE_FLAGS "${WARNCFLAGS}" + VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION} + C_VISIBILITY_PRESET hidden +) + +target_include_directories(ngtcp2_crypto_gnutls PUBLIC + ${ngtcp2_crypto_gnutls_INCLUDE_DIRS}) +if(NOT BUILD_SHARED_LIBS) + target_compile_definitions(ngtcp2_crypto_gnutls PUBLIC "-DNGTCP2_STATICLIB") +endif() + +install(TARGETS ngtcp2_crypto_gnutls + DESTINATION "${CMAKE_INSTALL_LIBDIR}") + +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libngtcp2_crypto_gnutls.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") diff --git a/crypto/gnutls/Makefile.am b/crypto/gnutls/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..b2310ef59ac3fd693a70bf1396bce571d13e9020 --- /dev/null +++ b/crypto/gnutls/Makefile.am @@ -0,0 +1,39 @@ +# 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. +AM_CFLAGS = $(WARNCFLAGS) $(DEBUGCFLAGS) $(EXTRACFLAG) +AM_CPPFLAGS = -I$(top_srcdir)/lib/includes -I$(top_builddir)/lib/includes \ + -I$(top_srcdir)/lib -DBUILDING_NGTCP2 \ + -I$(top_srcdir)/crypto/includes -I$(top_builddir)/crypto/includes \ + @GNUTLS_CFLAGS@ + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libngtcp2_crypto_gnutls.pc +DISTCLEANFILES = $(pkgconfig_DATA) + +lib_LTLIBRARIES = libngtcp2_crypto_gnutls.la + +libngtcp2_crypto_gnutls_la_SOURCES = gnutls.c ../shared.c ../shared.h +libngtcp2_crypto_gnutls_la_LDFLAGS = -no-undefined \ + -version-info $(CRYPTO_GNUTLS_LT_CURRENT):$(CRYPTO_GNUTLS_LT_REVISION):$(CRYPTO_GNUTLS_LT_AGE) \ + @JEMALLOC_LIBS@ @GNUTLS_LIBS@ +libngtcp2_crypto_gnutls_la_LIBADD = $(top_builddir)/lib/libngtcp2.la diff --git a/crypto/gnutls/gnutls.c b/crypto/gnutls/gnutls.c new file mode 100644 index 0000000000000000000000000000000000000000..d28191b7bc7b1b3cfd5474d01bbfc67bdd56a7ee --- /dev/null +++ b/crypto/gnutls/gnutls.c @@ -0,0 +1,316 @@ +/* + * 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. + */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <assert.h> + +#include <ngtcp2/ngtcp2_crypto.h> +#include <ngtcp2/ngtcp2_crypto_gnutls.h> + +#include <gnutls/gnutls.h> +#include <gnutls/crypto.h> +#include <string.h> + +ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_initial(ngtcp2_crypto_ctx *ctx) { + ctx->aead.native_handle = (void *)GNUTLS_CIPHER_AES_128_GCM; + ctx->md.native_handle = (void *)GNUTLS_DIG_SHA256; + ctx->hp.native_handle = (void *)GNUTLS_CIPHER_AES_128_CBC; + return ctx; +} + +ngtcp2_crypto_aead *ngtcp2_crypto_aead_retry(ngtcp2_crypto_aead *aead) { + aead->native_handle = (void *)GNUTLS_CIPHER_AES_128_GCM; + return aead; +} + +static gnutls_cipher_algorithm_t crypto_get_hp(gnutls_session_t session) { + switch (gnutls_cipher_get(session)) { + case GNUTLS_CIPHER_AES_128_GCM: + case GNUTLS_CIPHER_AES_128_CCM: + return GNUTLS_CIPHER_AES_128_CBC; + case GNUTLS_CIPHER_AES_256_GCM: + case GNUTLS_CIPHER_AES_256_CCM: + return GNUTLS_CIPHER_AES_256_CBC; + case GNUTLS_CIPHER_CHACHA20_POLY1305: + return GNUTLS_CIPHER_CHACHA20_32; + default: + return GNUTLS_CIPHER_UNKNOWN; + } +} + +ngtcp2_crypto_ctx *ngtcp2_crypto_ctx_tls(ngtcp2_crypto_ctx *ctx, + void *tls_native_handle) { + gnutls_session_t session = tls_native_handle; + gnutls_cipher_algorithm_t cipher; + gnutls_digest_algorithm_t hash; + gnutls_cipher_algorithm_t hp_cipher; + + cipher = gnutls_cipher_get(session); + if (cipher != GNUTLS_CIPHER_UNKNOWN || cipher != GNUTLS_CIPHER_NULL) { + ctx->aead.native_handle = (void *)cipher; + } + + hash = gnutls_prf_hash_get(session); + if (hash != GNUTLS_DIG_UNKNOWN || hash != GNUTLS_DIG_NULL) { + ctx->md.native_handle = (void *)hash; + } + + hp_cipher = crypto_get_hp(session); + if (hp_cipher != GNUTLS_CIPHER_UNKNOWN) { + ctx->hp.native_handle = (void *)hp_cipher; + } + + return ctx; +} + +size_t ngtcp2_crypto_md_hashlen(const ngtcp2_crypto_md *md) { + return gnutls_hash_get_len((gnutls_digest_algorithm_t)md->native_handle); +} + +size_t ngtcp2_crypto_aead_keylen(const ngtcp2_crypto_aead *aead) { + return gnutls_cipher_get_key_size((gnutls_cipher_algorithm_t)aead->native_handle); +} + +size_t ngtcp2_crypto_aead_noncelen(const ngtcp2_crypto_aead *aead) { + return gnutls_cipher_get_iv_size((gnutls_cipher_algorithm_t)aead->native_handle); +} + +size_t ngtcp2_crypto_aead_taglen(const ngtcp2_crypto_aead *aead) { + return gnutls_cipher_get_tag_size((gnutls_cipher_algorithm_t)aead->native_handle); +} + +int ngtcp2_crypto_hkdf_extract(uint8_t *dest, const ngtcp2_crypto_md *md, + const uint8_t *secret, size_t secretlen, + const uint8_t *salt, size_t saltlen) { + gnutls_mac_algorithm_t prf = (gnutls_mac_algorithm_t)md->native_handle; + gnutls_datum_t _secret = {(void*)secret, secretlen}; + gnutls_datum_t _salt = {(void*)salt, saltlen}; + + if (gnutls_hkdf_extract(prf, &_secret, &_salt, dest) != 0) { + return -1; + } + + return 0; +} + +int ngtcp2_crypto_hkdf_expand(uint8_t *dest, size_t destlen, + const ngtcp2_crypto_md *md, const uint8_t *secret, + size_t secretlen, const uint8_t *info, + size_t infolen) { + gnutls_mac_algorithm_t prf = (gnutls_mac_algorithm_t)md->native_handle; + gnutls_datum_t _secret = {(void*)secret, secretlen}; + gnutls_datum_t _info = {(void*)info, infolen}; + + if (gnutls_hkdf_expand(prf, &_secret, &_info, dest, destlen) != 0) { + return -1; + } + + return 0; +} + +int ngtcp2_crypto_encrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead, + 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) { + gnutls_cipher_algorithm_t cipher = (gnutls_cipher_algorithm_t)aead->native_handle; + gnutls_aead_cipher_hd_t hd = NULL; + gnutls_datum_t _key; + size_t taglen = ngtcp2_crypto_aead_taglen(aead); + size_t ciphertextlen = plaintextlen + taglen; + int rv = 0; + + _key.data = (void *)key; + _key.size = ngtcp2_crypto_aead_keylen(aead); + + if (gnutls_aead_cipher_init(&hd, cipher, &_key) != 0 || + gnutls_aead_cipher_encrypt(hd, + nonce, noncelen, + ad, adlen, taglen, + plaintext, plaintextlen, + dest, &ciphertextlen) != 0) { + rv = -1; + } + + gnutls_aead_cipher_deinit(hd); + + return rv; +} + +int ngtcp2_crypto_decrypt(uint8_t *dest, const ngtcp2_crypto_aead *aead, + 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) { + gnutls_cipher_algorithm_t cipher = + (gnutls_cipher_algorithm_t)aead->native_handle; + size_t taglen = gnutls_cipher_get_tag_size(cipher); + gnutls_aead_cipher_hd_t hd = NULL; + gnutls_datum_t _key; + int rv = 0; + size_t plaintextlen; + + if (taglen > ciphertextlen) { + return -1; + } + + plaintextlen = ciphertextlen - taglen; + + _key.data = (void *)key; + _key.size = ngtcp2_crypto_aead_keylen(aead); + + if (gnutls_aead_cipher_init(&hd, cipher, &_key) != 0 || + gnutls_aead_cipher_decrypt(hd, + nonce, noncelen, + ad, adlen, + taglen, + ciphertext, ciphertextlen, + dest, &plaintextlen) != 0) { + rv = -1; + } + + gnutls_aead_cipher_deinit(hd); + + return rv; +} + +int ngtcp2_crypto_hp_mask(uint8_t *dest, const ngtcp2_crypto_cipher *hp, + const uint8_t *hp_key, const uint8_t *sample) { + gnutls_cipher_algorithm_t cipher = (gnutls_cipher_algorithm_t)hp->native_handle; + int rv = 0; + + switch (cipher) { + case GNUTLS_CIPHER_AES_128_CBC: + case GNUTLS_CIPHER_AES_256_CBC: + { + gnutls_cipher_hd_t hd = NULL; + gnutls_datum_t _hp_key; + uint8_t iv[16]; + gnutls_datum_t _iv; + uint8_t buf[16]; + + _hp_key.data = (void *)hp_key; + _hp_key.size = gnutls_cipher_get_key_size(cipher); + + /* Emulate one block AES-ECB by invalidating the effect of IV */ + memset(iv, 0, sizeof(iv)); + _iv.data = iv; + _iv.size = 16; + + if (gnutls_cipher_init(&hd, cipher, &_hp_key, &_iv) != 0 || + gnutls_cipher_encrypt2(hd, sample, 16, buf, sizeof(buf)) != 0) { + rv = -1; + } + + memcpy(dest, buf, 5); + gnutls_cipher_deinit(hd); + } + break; + + case GNUTLS_CIPHER_CHACHA20_32: + { + gnutls_cipher_hd_t hd = NULL; + static const uint8_t PLAINTEXT[] = "\x00\x00\x00\x00\x00"; + gnutls_datum_t _hp_key; + gnutls_datum_t _iv; + uint8_t buf[5 + 16]; + size_t buflen = sizeof(buf); + + _hp_key.data = (void *)hp_key; + _hp_key.size = gnutls_cipher_get_key_size(cipher); + + _iv.data = (void *)sample; + _iv.size = 16; + + if (gnutls_cipher_init(&hd, cipher, &_hp_key, &_iv) != 0 || + gnutls_cipher_encrypt2(hd, + PLAINTEXT, sizeof(PLAINTEXT) - 1, + buf, buflen) != 0) { + rv = -1; + } + + memcpy(dest, buf, 5); + gnutls_cipher_deinit(hd); + } + break; + default: + assert(0); + } + + return rv; +} + +static gnutls_record_encryption_level_t +from_ngtcp2_level(ngtcp2_crypto_level crypto_level) { + switch (crypto_level) { + case NGTCP2_CRYPTO_LEVEL_INITIAL: + return GNUTLS_ENCRYPTION_LEVEL_INITIAL; + case NGTCP2_CRYPTO_LEVEL_HANDSHAKE: + return GNUTLS_ENCRYPTION_LEVEL_HANDSHAKE; + case NGTCP2_CRYPTO_LEVEL_APP: + return GNUTLS_ENCRYPTION_LEVEL_APPLICATION; + case NGTCP2_CRYPTO_LEVEL_EARLY: + return GNUTLS_ENCRYPTION_LEVEL_EARLY; + default: + assert(0); + } +} + +int ngtcp2_crypto_read_write_crypto_data(ngtcp2_conn *conn, void *tls, + ngtcp2_crypto_level crypto_level, + const uint8_t *data, size_t datalen) { + gnutls_session_t session = tls; + int rv; + + if (datalen > 0) { + if (gnutls_handshake_write(session, from_ngtcp2_level(crypto_level), data, + datalen) != 0) { + return -1; + } + } + + if (!ngtcp2_conn_get_handshake_completed(conn)) { + rv = gnutls_handshake(session); + if (rv < 0) { + if (!gnutls_error_is_fatal(rv)) { + return 0; + } + gnutls_alert_send_appropriate(session, rv); + return -1; + } + + ngtcp2_conn_handshake_completed(conn); + } + + return 0; +} + +int ngtcp2_crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls, + ngtcp2_crypto_side side) { + /* Nothing to do; GnuTLS applications are supposed to register the + quic_transport_parameters extension with + gnutls_session_ext_register. */ + return 0; +} diff --git a/crypto/gnutls/libngtcp2_crypto_gnutls.pc.in b/crypto/gnutls/libngtcp2_crypto_gnutls.pc.in new file mode 100644 index 0000000000000000000000000000000000000000..890e89d45f805ce44c96d4792b615a5f98928a97 --- /dev/null +++ b/crypto/gnutls/libngtcp2_crypto_gnutls.pc.in @@ -0,0 +1,33 @@ +# 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. +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libngtcp2_crypto_gnutls +Description: ngtcp2 GnuTLS crypto library +URL: https://github.com/ngtcp2/ngtcp2 +Version: @VERSION@ +Libs: -L${libdir} -lngtcp2_crypto_gnutls +Cflags: -I${includedir} diff --git a/crypto/includes/ngtcp2/ngtcp2_crypto_gnutls.h b/crypto/includes/ngtcp2/ngtcp2_crypto_gnutls.h new file mode 100644 index 0000000000000000000000000000000000000000..caf1a34895d704b1977c8bbe1ef5c03853fd6d14 --- /dev/null +++ b/crypto/includes/ngtcp2/ngtcp2_crypto_gnutls.h @@ -0,0 +1,30 @@ +/* + * 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. + */ +#ifndef NGTCP2_CRYPTO_GNUTLS_H +#define NGTCP2_CRYPTO_GNUTLS_H + +#include <ngtcp2/ngtcp2.h> + +#endif /* NGTCP2_CRYPTO_GNUTLS_H */