diff --git a/.github/workflows/boring.yml b/.github/workflows/boring.yml new file mode 100644 index 00000000..7988d58f --- /dev/null +++ b/.github/workflows/boring.yml @@ -0,0 +1,90 @@ +name: MLSPP CI (BoringSSL Test) + +on: + push: + branches: + - main + pull_request: + branches: + - main + +env: + CTEST_OUTPUT_ON_FAILURE: 1 + CMAKE_BUILD_BORINGSSL_DIR: ${{ github.workspace }}/build_boringssl + CMAKE_TEST_BORINGSSL_DIR: ${{ github.workspace }}/build_boringssl/test + VCPKG_BINARY_SOURCES: files,${{ github.workspace }}/build/cache,readwrite + +jobs: + formatting-check: + name: Formatting Check + runs-on: ubuntu-latest + strategy: + matrix: + path: + - 'include' + - 'src' + - 'test' + - 'cmd' + - 'lib' + steps: + - uses: actions/checkout@v3 + + - name: Run clang-format style check for C/C++ programs + uses: jidicula/clang-format-action@v4.11.0 + with: + clang-format-version: '16' + check-path: ${{ matrix.path }} + fallback-style: 'Mozilla' + + platform-sanitizer-tests: + name: Build and test with BoringSSL + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [windows-latest, ubuntu-latest, macos-latest] + include: + - os: windows-latest + vcpkg-cmake-file: "$env:VCPKG_INSTALLATION_ROOT\\scripts\\buildsystems\\vcpkg.cmake" + boring-vcpkg-dir: "alternatives\\boringssl_1.1" + ctest-target: RUN_TESTS + - os: ubuntu-latest + vcpkg-cmake-file: "$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" + boring-vcpkg-dir: "alternatives/boringssl_1.1" + ctest-target: test + - os: macos-latest + vcpkg-cmake-file: "$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" + boring-vcpkg-dir: "alternatives/boringssl_1.1" + ctest-target: test + + steps: + - uses: actions/checkout@v3 + + - name: Dependencies (macOs) + if: ${{ matrix.os == 'macos-latest' }} + run: | + brew install llvm pkg-config + ln -s "/usr/local/opt/llvm/bin/clang-format" "/usr/local/bin/clang-format" + ln -s "/usr/local/opt/llvm/bin/clang-tidy" "/usr/local/bin/clang-tidy" + + - name: Dependencies (Ubuntu) + if: ${{ matrix.os == 'ubuntu-latest' }} + run: | + sudo apt-get install -y linux-headers-$(uname -r) nasm + + - name: Restore cache + uses: actions/cache@v3 + with: + path: ${{ github.workspace }}/build/cache + key: VCPKG-BinaryCache-${{ runner.os }} + + - name: Build (BoringSSL 1.1) + run: | + cmake -B "${{ env.CMAKE_BUILD_BORINGSSL_DIR }}" -DTESTING=ON -DCLANG_TIDY=ON -DSANITIZERS=ON -DVCPKG_MANIFEST_DIR="${{ matrix.ossl3-vcpkg-dir }}" -DCMAKE_TOOLCHAIN_FILE="${{ matrix.vcpkg-cmake-file}}" -DREQUIRE_BORINGSSL=1 + cmake --build "${{ env.CMAKE_BUILD_BORINGSSL_DIR }}" + + - name: Unit Test (BoringSSL 1.1) + run: | + cmake --build "${{ env.CMAKE_BUILD_BORINGSSL_DIR }}" --target "${{ matrix.ctest-target}}" + + diff --git a/CMakeLists.txt b/CMakeLists.txt index 28e8efd1..9125d1c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ option(TESTING "Build tests" OFF) option(CLANG_TIDY "Perform linting with clang-tidy" OFF) option(SANITIZERS "Enable sanitizers" OFF) option(MLS_NAMESPACE_SUFFIX "Namespace Suffix for CXX and CMake Export") +option(REQUIRE_BORINGSSL "Require BoringSSL instead of OpenSSL" OFF) if(MLS_NAMESPACE_SUFFIX) set(MLS_CXX_NAMESPACE "mls_${MLS_NAMESPACE_SUFFIX}" CACHE STRING "Top-level Namespace for CXX") @@ -93,16 +94,34 @@ endif() # External libraries find_package(OpenSSL REQUIRED) if ( OPENSSL_FOUND ) + find_path(BORINGSSL_INCLUDE_DIR openssl/is_boringssl.h HINTS ${OPENSSL_INCLUDE_DIR} NO_DEFAULT_PATH) + + if (BORINGSSL_INCLUDE_DIR) + message(STATUS "Found OpenSSL includes are for BoringSSL") + + add_compile_definitions(WITH_BORINGSSL) + add_compile_options(-Wno-gnu-anonymous-struct -Wno-nested-anon-types) + + file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/crypto.h" boringssl_version_str + REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_TEXT[\t ]+\"OpenSSL ([0-9])+\\.([0-9])+\\.([0-9])+ .+") + + string(REGEX REPLACE "^.*OPENSSL_VERSION_TEXT[\t ]+\"OpenSSL ([0-9]+\\.[0-9]+\\.[0-9])+ .+$" + "\\1" OPENSSL_VERSION "${boringssl_version_str}") + + elseif (REQUIRE_BORINGSSL) + message(FATAL_ERROR "BoringSSL required but not found") + endif () + if (${OPENSSL_VERSION} VERSION_GREATER_EQUAL 3) - add_compile_definitions(WITH_OPENSSL3) + add_compile_definitions(WITH_OPENSSL3) elseif(${OPENSSL_VERSION} VERSION_LESS 1.1.1) - message(FATAL_ERROR "OpenSSL 1.1.1 or greater is required") + message(FATAL_ERROR "OpenSSL 1.1.1 or greater is required") endif() message(STATUS "OpenSSL Found: ${OPENSSL_VERSION}") message(STATUS "OpenSSL Include: ${OPENSSL_INCLUDE_DIR}") message(STATUS "OpenSSL Libraries: ${OPENSSL_LIBRARIES}") else() - message(FATAL_ERROR "No OpenSSL library found") + message(FATAL_ERROR "No OpenSSL library found") endif() # Internal libraries diff --git a/README.md b/README.md index c3089d27..9daff2c0 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ MLS++ Implementation of the proposed [Messaging Layer Security](https://github.com/mlswg/mls-protocol/blob/master/draft-ietf-mls-protocol.md) protocol in C++. Depends on C++17, STL for data structures, and -OpenSSL for crypto. +OpenSSL or BoringSSL for crypto. Quickstart ---------- @@ -31,3 +31,11 @@ Conventions * Snake case for variables, functions, members (`derive_epoch_keys`) * Private member variables start with underscore (`_`) * In general, prefer descriptive names + + +OpenSSL / BoringSSL +------------------- + +MLS++ requires OpenSSL of at least version 1.1.1, or BoringSSL compatible with the same requirement. MLS++ is compatible with OpenSSL >= 3.0. + +Pass `OPENSSL_ROOT_DIR` to guide CMake to select a specific OpenSSL/BoringSSL installation. You may also need to specify `OPENSSL_INCLUDE_DIR`, `OPENSSL_CRYPTO_LIBRARY`, and `OPENSSL_SSL_LIBRARY` depending on the file and folder structure of your installation. When manually passing `OPENSSL_*` options one should carefully verify that both the includes and libraries match the expected installation. diff --git a/alternatives/boringssl_1.1/vcpkg.json b/alternatives/boringssl_1.1/vcpkg.json new file mode 100644 index 00000000..1a726f6d --- /dev/null +++ b/alternatives/boringssl_1.1/vcpkg.json @@ -0,0 +1,21 @@ +{ + "name": "mlspp", + "version-string": "0.1", + "description": "Cisco MLS C++ library (BoringSSL 1.1)", + "dependencies": [ + { + "name": "boringssl", + "version>=": "2023-09-25" + }, + "doctest", + "nlohmann-json" + ], + "builtin-baseline": "5908d702d61cea1429b223a0b7a10ab86bad4c78", + "overrides": [ + { + "name": "boringssl", + "version": "2023-09-25" + } + ] +} + \ No newline at end of file diff --git a/include/mls/crypto.h b/include/mls/crypto.h index dc467c0d..16aefaab 100644 --- a/include/mls/crypto.h +++ b/include/mls/crypto.h @@ -133,7 +133,11 @@ struct CipherSuite static const bytes& reference_label(); }; +#if WITH_BORINGSSL +extern const std::array all_supported_suites; +#else extern const std::array all_supported_suites; +#endif // Utilities using MLS_NAMESPACE::hpke::random_bytes; diff --git a/lib/hpke/CMakeLists.txt b/lib/hpke/CMakeLists.txt index d57afed0..ecc0409f 100644 --- a/lib/hpke/CMakeLists.txt +++ b/lib/hpke/CMakeLists.txt @@ -4,7 +4,6 @@ set(CURRENT_LIB_NAME hpke) ### Dependencies ### find_package(nlohmann_json REQUIRED) -find_package(OpenSSL 1.1 REQUIRED) ### ### Library Config @@ -17,14 +16,16 @@ add_library(${CURRENT_LIB_NAME} ${LIB_HEADERS} ${LIB_SOURCES}) add_dependencies(${CURRENT_LIB_NAME} bytes tls_syntax) target_link_libraries(${CURRENT_LIB_NAME} PRIVATE - nlohmann_json::nlohmann_json OpenSSL::Crypto + OpenSSL::Crypto PUBLIC - bytes tls_syntax) + nlohmann_json::nlohmann_json bytes tls_syntax) target_include_directories(${CURRENT_LIB_NAME} PUBLIC $ $ $ + PRIVATE + ${OPENSSL_INCLUDE_DIR} ) ### diff --git a/lib/hpke/include/hpke/hpke.h b/lib/hpke/include/hpke/hpke.h index 74ff9384..0c64fb91 100644 --- a/lib/hpke/include/hpke/hpke.h +++ b/lib/hpke/include/hpke/hpke.h @@ -17,7 +17,9 @@ struct KEM DHKEM_P384_SHA384 = 0x0011, DHKEM_P521_SHA512 = 0x0012, DHKEM_X25519_SHA256 = 0x0020, +#if !defined(WITH_BORINGSSL) DHKEM_X448_SHA512 = 0x0021, +#endif }; template diff --git a/lib/hpke/include/hpke/signature.h b/lib/hpke/include/hpke/signature.h index 311baa18..19e66b06 100644 --- a/lib/hpke/include/hpke/signature.h +++ b/lib/hpke/include/hpke/signature.h @@ -16,7 +16,9 @@ struct Signature P384_SHA384, P521_SHA512, Ed25519, +#if !defined(WITH_BORINGSSL) Ed448, +#endif RSA_SHA256, RSA_SHA384, RSA_SHA512, diff --git a/lib/hpke/src/aead_cipher.cpp b/lib/hpke/src/aead_cipher.cpp index 43a4f073..8f04d733 100644 --- a/lib/hpke/src/aead_cipher.cpp +++ b/lib/hpke/src/aead_cipher.cpp @@ -4,6 +4,10 @@ #include #include +#if WITH_BORINGSSL +#include +#endif + namespace MLS_NAMESPACE::hpke { /// @@ -109,6 +113,25 @@ cipher_tag_size(AEAD::ID cipher) } } +#if WITH_BORINGSSL +static const EVP_AEAD* +boringssl_cipher(AEAD::ID cipher) +{ + switch (cipher) { + case AEAD::ID::AES_128_GCM: + return EVP_aead_aes_128_gcm(); + + case AEAD::ID::AES_256_GCM: + return EVP_aead_aes_256_gcm(); + + case AEAD::ID::CHACHA20_POLY1305: + return EVP_aead_chacha20_poly1305(); + + default: + throw std::runtime_error("Unsupported algorithm"); + } +} +#else static const EVP_CIPHER* openssl_cipher(AEAD::ID cipher) { @@ -126,6 +149,7 @@ openssl_cipher(AEAD::ID cipher) throw std::runtime_error("Unsupported algorithm"); } } +#endif // WITH_BORINGSSL AEADCipher::AEADCipher(AEAD::ID id_in) : AEAD(id_in, cipher_key_size(id_in), cipher_nonce_size(id_in)) @@ -139,6 +163,30 @@ AEADCipher::seal(const bytes& key, const bytes& aad, const bytes& pt) const { +#if WITH_BORINGSSL + auto ctx = make_typed_unique( + EVP_AEAD_CTX_new(boringssl_cipher(id), key.data(), key.size(), tag_size)); + if (ctx == nullptr) { + throw openssl_error(); + } + + auto ct = bytes(pt.size() + tag_size); + auto out_len = ct.size(); + if (1 != EVP_AEAD_CTX_seal(ctx.get(), + ct.data(), + &out_len, + ct.size(), + nonce.data(), + nonce.size(), + pt.data(), + pt.size(), + aad.data(), + aad.size())) { + throw openssl_error(); + } + + return ct; +#else auto ctx = make_typed_unique(EVP_CIPHER_CTX_new()); if (ctx == nullptr) { throw openssl_error(); @@ -185,6 +233,7 @@ AEADCipher::seal(const bytes& key, ct += tag; return ct; +#endif // WITH_BORINGSSL } std::optional @@ -197,6 +246,30 @@ AEADCipher::open(const bytes& key, throw std::runtime_error("AEAD ciphertext smaller than tag size"); } +#if WITH_BORINGSSL + auto ctx = make_typed_unique(EVP_AEAD_CTX_new( + boringssl_cipher(id), key.data(), key.size(), cipher_tag_size(id))); + if (ctx == nullptr) { + throw openssl_error(); + } + + auto pt = bytes(ct.size() - tag_size); + auto out_len = pt.size(); + if (1 != EVP_AEAD_CTX_open(ctx.get(), + pt.data(), + &out_len, + pt.size(), + nonce.data(), + nonce.size(), + ct.data(), + ct.size(), + aad.data(), + aad.size())) { + throw openssl_error(); + } + + return pt; +#else auto ctx = make_typed_unique(EVP_CIPHER_CTX_new()); if (ctx == nullptr) { throw openssl_error(); @@ -243,6 +316,7 @@ AEADCipher::open(const bytes& key, } return pt; +#endif // WITH_BORINGSSL } } // namespace MLS_NAMESPACE::hpke diff --git a/lib/hpke/src/base64.cpp b/lib/hpke/src/base64.cpp index 476ea997..1b28cd02 100644 --- a/lib/hpke/src/base64.cpp +++ b/lib/hpke/src/base64.cpp @@ -15,7 +15,11 @@ to_base64(const bytes& data) return ""; } +#if WITH_BORINGSSL + const auto data_size = data.size(); +#else const auto data_size = static_cast(data.size()); +#endif // base64 encoding produces 4 characters for every 3 input bytes (rounded up) const auto out_size = (data_size + 2) / 3 * 4; diff --git a/lib/hpke/src/certificate.cpp b/lib/hpke/src/certificate.cpp index 1ce97e64..14254c69 100644 --- a/lib/hpke/src/certificate.cpp +++ b/lib/hpke/src/certificate.cpp @@ -228,13 +228,22 @@ struct Certificate::ParsedCertificate static Signature::ID public_key_algorithm(X509* x509) { - switch (EVP_PKEY_base_id(X509_get0_pubkey(x509))) { +#if WITH_BORINGSSL + const auto pub = make_typed_unique(X509_get_pubkey(x509)); + const auto* pub_ptr = pub.get(); +#else + const auto* pub_ptr = X509_get0_pubkey(x509); +#endif + + switch (EVP_PKEY_base_id(pub_ptr)) { case EVP_PKEY_ED25519: return Signature::ID::Ed25519; +#if !defined(WITH_BORINGSSL) case EVP_PKEY_ED448: return Signature::ID::Ed448; +#endif case EVP_PKEY_EC: { - auto key_size = EVP_PKEY_bits(X509_get0_pubkey(x509)); + auto key_size = EVP_PKEY_bits(pub_ptr); switch (key_size) { case 256: return Signature::ID::P256_SHA256; @@ -261,8 +270,10 @@ struct Certificate::ParsedCertificate switch (nid) { case EVP_PKEY_ED25519: return Signature::ID::Ed25519; +#if !defined(WITH_BORINGSSL) case EVP_PKEY_ED448: return Signature::ID::Ed448; +#endif case NID_ecdsa_with_SHA256: return Signature::ID::P256_SHA256; case NID_ecdsa_with_SHA384: diff --git a/lib/hpke/src/dhkem.cpp b/lib/hpke/src/dhkem.cpp index d145be50..28562f64 100644 --- a/lib/hpke/src/dhkem.cpp +++ b/lib/hpke/src/dhkem.cpp @@ -62,6 +62,7 @@ DHKEM::get() return instance; } +#if !defined(WITH_BORINGSSL) template<> const DHKEM& DHKEM::get() @@ -71,6 +72,7 @@ DHKEM::get() KDF::get()); return instance; } +#endif DHKEM::DHKEM(KEM::ID kem_id_in, const Group& group_in, const KDF& kdf_in) : KEM(kem_id_in, diff --git a/lib/hpke/src/digest.cpp b/lib/hpke/src/digest.cpp index 2284f771..053fd2cd 100644 --- a/lib/hpke/src/digest.cpp +++ b/lib/hpke/src/digest.cpp @@ -143,7 +143,7 @@ Digest::hmac_for_hkdf_extract(const bytes& key, const bytes& data) const // OpenSSL 3 does not support the flag EVP_MD_CTX_FLAG_NON_FIPS_ALLOW anymore. // However, OpenSSL 3 in FIPS mode doesn't seem to check the HMAC key size // constraint. -#if !defined(WITH_OPENSSL3) +#if !defined(WITH_OPENSSL3) && !defined(WITH_BORINGSSL) static const auto fips_min_hmac_key_len = 14; if (FIPS_mode() != 0 && key_size < fips_min_hmac_key_len) { HMAC_CTX_set_flags(ctx.get(), EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); diff --git a/lib/hpke/src/group.cpp b/lib/hpke/src/group.cpp index cf02b1e0..2d60dd33 100644 --- a/lib/hpke/src/group.cpp +++ b/lib/hpke/src/group.cpp @@ -6,6 +6,7 @@ #include "common.h" #include "openssl_common.h" +#include "openssl/bn.h" #include "openssl/ec.h" #include "openssl/evp.h" #include "openssl/obj_mac.h" @@ -494,7 +495,14 @@ struct ECKeyGroup : public EVPGroup #endif auto out = bytes(BN_num_bytes(d)); - if (BN_bn2bin(d, out.data()) != int(out.size())) { +#if WITH_BORINGSSL + // In BoringSSL, BN_bn2bin returns size_t + const auto out_size = out.size(); +#else + // In OpenSSL, BN_bn2bin returns int + const auto out_size = static_cast(out.size()); +#endif + if (BN_bn2bin(d, out.data()) != out_size) { throw openssl_error(); } @@ -923,6 +931,8 @@ Group::get() return instance; } +// BoringSSL doesn't support X448 / Ed448 +#if !defined(WITH_BORINGSSL) template<> const Group& Group::get() @@ -931,6 +941,7 @@ Group::get() KDF::get()); return instance; } +#endif template<> const Group& diff --git a/lib/hpke/src/hpke.cpp b/lib/hpke/src/hpke.cpp index 19a37fa2..51100c08 100644 --- a/lib/hpke/src/hpke.cpp +++ b/lib/hpke/src/hpke.cpp @@ -125,12 +125,14 @@ KEM::get() return DHKEM::get(); } +#if !defined(WITH_BORINGSSL) template<> const KEM& KEM::get() { return DHKEM::get(); } +#endif bytes KEM::serialize_private(const KEM::PrivateKey& /* unused */) const @@ -353,8 +355,10 @@ select_kem(KEM::ID id) return KEM::get(); case KEM::ID::DHKEM_X25519_SHA256: return KEM::get(); +#if !defined(WITH_BORINGSSL) case KEM::ID::DHKEM_X448_SHA512: return KEM::get(); +#endif default: throw std::runtime_error("Unsupported algorithm"); } diff --git a/lib/hpke/src/openssl_common.cpp b/lib/hpke/src/openssl_common.cpp index e1714d81..33f62f2d 100644 --- a/lib/hpke/src/openssl_common.cpp +++ b/lib/hpke/src/openssl_common.cpp @@ -20,6 +20,15 @@ typed_delete(EVP_CIPHER_CTX* ptr) EVP_CIPHER_CTX_free(ptr); } +#if WITH_BORINGSSL +template<> +void +typed_delete(EVP_AEAD_CTX* ptr) +{ + EVP_AEAD_CTX_free(ptr); +} +#endif + template<> void typed_delete(EVP_PKEY_CTX* ptr) diff --git a/lib/hpke/src/signature.cpp b/lib/hpke/src/signature.cpp index 16cfe117..8860c18a 100644 --- a/lib/hpke/src/signature.cpp +++ b/lib/hpke/src/signature.cpp @@ -46,8 +46,10 @@ struct GroupSignature : public Signature return Signature::ID::P521_SHA512; case Group::ID::Ed25519: return Signature::ID::Ed25519; +#if !defined(WITH_BORINGSSL) case Group::ID::Ed448: return Signature::ID::Ed448; +#endif default: throw std::runtime_error("Unsupported group"); } @@ -234,6 +236,7 @@ Signature::get() return instance; } +#if !defined(WITH_BORINGSSL) template<> const Signature& Signature::get() @@ -241,6 +244,7 @@ Signature::get() static const auto instance = GroupSignature(Group::get()); return instance; } +#endif template<> const Signature& @@ -281,12 +285,15 @@ static const Signature& sig_from_jwk(const std::string& jwk_json) { using KeyTypeAndCurve = std::tuple; - static const auto alg_sig_map = std::map{ + static const auto alg_sig_map = std::map + { { { "EC", "P-256" }, Signature::get() }, - { { "EC", "P-384" }, Signature::get() }, - { { "EC", "P-512" }, Signature::get() }, - { { "OKP", "Ed25519" }, Signature::get() }, - { { "OKP", "Ed448" }, Signature::get() }, + { { "EC", "P-384" }, Signature::get() }, + { { "EC", "P-512" }, Signature::get() }, + { { "OKP", "Ed25519" }, Signature::get() }, +#if !defined(WITH_BORINGSSL) + { { "OKP", "Ed448" }, Signature::get() }, +#endif // TODO(RLB): RSA }; diff --git a/lib/hpke/src/userinfo_vc.cpp b/lib/hpke/src/userinfo_vc.cpp index 65cbe5d9..e8ba105e 100644 --- a/lib/hpke/src/userinfo_vc.cpp +++ b/lib/hpke/src/userinfo_vc.cpp @@ -52,15 +52,18 @@ get_optional(const json& json_object, const std::string& field_name) static const Signature& signature_from_alg(const std::string& alg) { - static const auto alg_sig_map = std::map{ + static const auto alg_sig_map = std::map + { { "ES256", Signature::get() }, - { "ES384", Signature::get() }, - { "ES512", Signature::get() }, - { "Ed25519", Signature::get() }, - { "Ed448", Signature::get() }, - { "RS256", Signature::get() }, - { "RS384", Signature::get() }, - { "RS512", Signature::get() }, + { "ES384", Signature::get() }, + { "ES512", Signature::get() }, + { "Ed25519", Signature::get() }, +#if !defined(WITH_BORINGSSL) + { "Ed448", Signature::get() }, +#endif + { "RS256", Signature::get() }, + { "RS384", Signature::get() }, + { "RS512", Signature::get() }, }; return alg_sig_map.at(alg); diff --git a/lib/hpke/test/CMakeLists.txt b/lib/hpke/test/CMakeLists.txt index 26b1de2b..9e640b88 100644 --- a/lib/hpke/test/CMakeLists.txt +++ b/lib/hpke/test/CMakeLists.txt @@ -8,7 +8,7 @@ file(GLOB TEST_SOURCES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) add_executable(${TEST_APP_NAME} ${TEST_SOURCES}) add_dependencies(${TEST_APP_NAME} ${CURRENT_LIB_NAME} bytes tls_syntax) -target_link_libraries(${TEST_APP_NAME} ${CURRENT_LIB_NAME} bytes tls_syntax doctest::doctest OpenSSL::Crypto) +target_link_libraries(${TEST_APP_NAME} ${CURRENT_LIB_NAME} bytes tls_syntax doctest::doctest ${OPENSSL_CRYPTO_LIBRARY}) # Enable CTest include(doctest) diff --git a/lib/hpke/test/common.cpp b/lib/hpke/test/common.cpp index cfd0d930..2065ec10 100644 --- a/lib/hpke/test/common.cpp +++ b/lib/hpke/test/common.cpp @@ -49,8 +49,11 @@ fips_disable(AEAD::ID id) bool fips_disable(Signature::ID id) { - static const auto disabled = std::set{ + static const auto disabled = std::set + { +#if !defined(WITH_BORINGSSL) Signature::ID::Ed448, +#endif }; return disabled.count(id) > 0; } @@ -71,8 +74,10 @@ select_signature(Signature::ID id) case Signature::ID::Ed25519: return Signature::get(); +#if !defined(WITH_BORINGSSL) case Signature::ID::Ed448: return Signature::get(); +#endif case Signature::ID::RSA_SHA256: return Signature::get(); @@ -88,6 +93,24 @@ select_signature(Signature::ID id) } } +bool +supported_kem(KEM::ID id) +{ + switch (id) { + case KEM::ID::DHKEM_P256_SHA256: + case KEM::ID::DHKEM_P384_SHA384: + case KEM::ID::DHKEM_P521_SHA512: + case KEM::ID::DHKEM_X25519_SHA256: +#if !defined(WITH_BORINGSSL) + case KEM::ID::DHKEM_X448_SHA512: +#endif + return true; + + default: + return false; + } +} + const KEM& select_kem(KEM::ID id) { @@ -104,8 +127,10 @@ select_kem(KEM::ID id) case KEM::ID::DHKEM_X25519_SHA256: return KEM::get(); +#if !defined(WITH_BORINGSSL) case KEM::ID::DHKEM_X448_SHA512: return KEM::get(); +#endif default: throw std::runtime_error("Unknown algorithm"); diff --git a/lib/hpke/test/common.h b/lib/hpke/test/common.h index 0ef60053..b26f0bfd 100644 --- a/lib/hpke/test/common.h +++ b/lib/hpke/test/common.h @@ -18,6 +18,9 @@ fips_disable(Signature::ID id); const Signature& select_signature(Signature::ID id); +bool +supported_kem(KEM::ID id); + const KEM& select_kem(KEM::ID id); diff --git a/lib/hpke/test/hpke.cpp b/lib/hpke/test/hpke.cpp index 78cd5ab2..93c63645 100644 --- a/lib/hpke/test/hpke.cpp +++ b/lib/hpke/test/hpke.cpp @@ -45,6 +45,10 @@ test_context(ReceiverContext& ctxR, const HPKETestVector& tv) static void test_base_vector(const HPKETestVector& tv) { + if (!supported_kem(tv.kem_id)) { + return; + } + const auto& kem = select_kem(tv.kem_id); auto hpke = HPKE(tv.kem_id, tv.kdf_id, tv.aead_id); @@ -63,6 +67,10 @@ test_base_vector(const HPKETestVector& tv) static void test_psk_vector(const HPKETestVector& tv) { + if (!supported_kem(tv.kem_id)) { + return; + } + const auto& kem = select_kem(tv.kem_id); auto hpke = HPKE(tv.kem_id, tv.kdf_id, tv.aead_id); @@ -81,6 +89,10 @@ test_psk_vector(const HPKETestVector& tv) static void test_auth_vector(const HPKETestVector& tv) { + if (!supported_kem(tv.kem_id)) { + return; + } + const auto& kem = select_kem(tv.kem_id); auto hpke = HPKE(tv.kem_id, tv.kdf_id, tv.aead_id); @@ -107,6 +119,10 @@ test_auth_vector(const HPKETestVector& tv) static void test_auth_psk_vector(const HPKETestVector& tv) { + if (!supported_kem(tv.kem_id)) { + return; + } + const auto& kem = select_kem(tv.kem_id); auto hpke = HPKE(tv.kem_id, tv.kdf_id, tv.aead_id); @@ -168,11 +184,14 @@ TEST_CASE("HPKE Round-Trip") { ensure_fips_if_required(); - const std::vector kems{ KEM::ID::DHKEM_P256_SHA256, - KEM::ID::DHKEM_P384_SHA384, - KEM::ID::DHKEM_P384_SHA384, - KEM::ID::DHKEM_P521_SHA512, - KEM::ID::DHKEM_X448_SHA512 }; + const std::vector kems + { + KEM::ID::DHKEM_P256_SHA256, KEM::ID::DHKEM_P384_SHA384, + KEM::ID::DHKEM_P384_SHA384, KEM::ID::DHKEM_P521_SHA512, +#if !defined(WITH_BORINGSSL) + KEM::ID::DHKEM_X448_SHA512 +#endif + }; const std::vector kdfs{ KDF::ID::HKDF_SHA256, KDF::ID::HKDF_SHA384, KDF::ID::HKDF_SHA512 }; diff --git a/lib/hpke/test/kem.cpp b/lib/hpke/test/kem.cpp index a62d509f..90a6d4bc 100644 --- a/lib/hpke/test/kem.cpp +++ b/lib/hpke/test/kem.cpp @@ -9,11 +9,14 @@ TEST_CASE("KEM round-trip") { ensure_fips_if_required(); - const std::vector ids{ KEM::ID::DHKEM_P256_SHA256, - KEM::ID::DHKEM_P384_SHA384, - KEM::ID::DHKEM_P384_SHA384, - KEM::ID::DHKEM_P521_SHA512, - KEM::ID::DHKEM_X448_SHA512 }; + const std::vector ids + { + KEM::ID::DHKEM_P256_SHA256, KEM::ID::DHKEM_P384_SHA384, + KEM::ID::DHKEM_P384_SHA384, KEM::ID::DHKEM_P521_SHA512, +#if !defined(WITH_BORINGSSL) + KEM::ID::DHKEM_X448_SHA512, +#endif + }; const auto plaintext = from_hex("00010203"); const auto seedS = from_hex("A0A0A0A0"); diff --git a/lib/hpke/test/signature.cpp b/lib/hpke/test/signature.cpp index c8f8a149..dd8782e3 100644 --- a/lib/hpke/test/signature.cpp +++ b/lib/hpke/test/signature.cpp @@ -22,7 +22,8 @@ TEST_CASE("Signature Known-Answer") bytes signature; }; - const std::vector cases{ + const std::vector cases + { // TODO(RLB): Add ECDSA known-answer tests { // https://tools.ietf.org/html/rfc8032#section-7.1 @@ -41,31 +42,33 @@ TEST_CASE("Signature Known-Answer") "09351fc9ac90b3ecfdfbc7c66431e030" "3dca179c138ac17ad9bef1177331a704"), }, - { - // https://tools.ietf.org/html/rfc8032#section-7.2 - Signature::ID::Ed448, - true, - from_hex("d65df341ad13e008567688baedda8e9d" - "cdc17dc024974ea5b4227b6530e339bf" - "f21f99e68ca6968f3cca6dfe0fb9f4fa" - "b4fa135d5542ea3f01"), - from_hex("df9705f58edbab802c7f8363cfe5560a" - "b1c6132c20a9f1dd163483a26f8ac53a" - "39d6808bf4a1dfbd261b099bb03b3fb5" - "0906cb28bd8a081f00"), - from_hex("bd0f6a3747cd561bdddf4640a332461a" - "4a30a12a434cd0bf40d766d9c6d458e5" - "512204a30c17d1f50b5079631f64eb31" - "12182da3005835461113718d1a5ef944"), - from_hex("554bc2480860b49eab8532d2a533b7d5" - "78ef473eeb58c98bb2d0e1ce488a98b1" - "8dfde9b9b90775e67f47d4a1c3482058" - "efc9f40d2ca033a0801b63d45b3b722e" - "f552bad3b4ccb667da350192b61c508c" - "f7b6b5adadc2c8d9a446ef003fb05cba" - "5f30e88e36ec2703b349ca229c267083" - "3900"), - }, +#if !defined(WITH_BORINGSSL) + { + // https://tools.ietf.org/html/rfc8032#section-7.2 + Signature::ID::Ed448, + true, + from_hex("d65df341ad13e008567688baedda8e9d" + "cdc17dc024974ea5b4227b6530e339bf" + "f21f99e68ca6968f3cca6dfe0fb9f4fa" + "b4fa135d5542ea3f01"), + from_hex("df9705f58edbab802c7f8363cfe5560a" + "b1c6132c20a9f1dd163483a26f8ac53a" + "39d6808bf4a1dfbd261b099bb03b3fb5" + "0906cb28bd8a081f00"), + from_hex("bd0f6a3747cd561bdddf4640a332461a" + "4a30a12a434cd0bf40d766d9c6d458e5" + "512204a30c17d1f50b5079631f64eb31" + "12182da3005835461113718d1a5ef944"), + from_hex("554bc2480860b49eab8532d2a533b7d5" + "78ef473eeb58c98bb2d0e1ce488a98b1" + "8dfde9b9b90775e67f47d4a1c3482058" + "efc9f40d2ca033a0801b63d45b3b722e" + "f552bad3b4ccb667da350192b61c508c" + "f7b6b5adadc2c8d9a446ef003fb05cba" + "5f30e88e36ec2703b349ca229c267083" + "3900"), + }, +#endif }; for (const auto& tc : cases) { @@ -101,7 +104,8 @@ TEST_CASE("Signature Verify Known-Answer") bytes signature; }; - const std::vector cases{ + const std::vector cases + { { Signature::ID::P256_SHA256, from_hex( @@ -116,67 +120,87 @@ TEST_CASE("Signature Verify Known-Answer") "86f94b88c02203b6a5e140d2d13ebec80636bfb1e32d17fe3d7f2983a53104e" "101e766830453a"), }, - { - Signature::ID::P384_SHA384, - from_hex( - "04d5a2abcb844865a479af773f9db66f5b8994710e2617e8b3c7ab4555f023f8e71a42" - "291416cdf9ea288874c5cc9f38a49b6e7cc96a3a65f60a42a05e233af26c94e0cc23c8" - "ee60177f1e1e3b52514a8de018addcc97245c2bef6bdd9ea7149da"), - from_hex( - "4be880bc0ccc92f79ed58b2c78268e28610719fb654b7d8b8aceae09e9e9ec3115de63" - "3d5dbeb36762a67d48b0fd1c74cd499058557638372bb5d76f88a5ea00194f9c0b1578" - "a9b5833d8d001ce847d4a55212601d514d6134f581f4c9a1f7bc5564ceaf28169c7fff" - "70fbc67087da868826913dab1f1dcfdf045d027e7460b7"), - from_hex( - "3064023036da67b80ca54e25cffd8c7992d406118de661c9ff40ed0468938b04d71009" - "7a3f5a947d2cb5420a5af6ca9b7a8684cb023042950fa4859def74cee5066f974b7a49" - "cd43899468831970b736b7bbb95338d1dd0c9e9034c9801f414982580fe9e590"), - }, - { - Signature::ID::P521_SHA512, - from_hex( - "0400a659dcddfafe88ebbba8c04155870e0315794c7bd5a0c53ed9b57bcfaa36d79743" - "5b40a74d62ba4104d62e166538e6f88d832aa047b6ed3cd119a477000f3362df01855f" - "4e61ed4be7e81ed5f566ef6455a4fb588db6e6e44f57dc4271ac3d22cdba16d361db47" - "8fa4fb233fd71179633e722615c33cfbd1d556cc29a839121c37b982"), - from_hex( - "6abe2712353e03ef03571a9679a3f1e889937d5ffc0df431fab44a408ce8cc37449f94" - "28aae783a2ce200bb7ed546a1a92ea3555b45552844d15d6d86b662778e33124304691" - "16615523990495dd3352b374792d591384123c3c7ca81ad42b9f6e856426a82dddd284" - "d2f447df243067af6fe7f73cc4a368cb7cd53240af21d6"), - from_hex( - "3081880242015a033045a1bf86b3e1017826dd226604d78d129dcfca84f4020063beec" - "03e0b4bedbedacbf1b0d1285ddbd0c7107078ac200be9876577025ffdd898e97f648f7" - "80024201afcf701a73ab224ea5a0b6399fc231da0e7f1a8649df17ef2d5171fc4dc278" - "6923727c2edc4f0ad9e98825750596be312d0109d47888ab6481c688a287b0aac6b0"), - }, - { - Signature::ID::Ed25519, - from_hex( - "923654bbdbacc72ab6c568208719c7cb866c3f89c366914ae90d604ef360c5c8"), - from_hex( - "dab12589702ff146b4e83b808da4007ff4ea4a358af2f7baa6861f08fb11ed71e338b2" - "fa01c7a68f86daaed5c1f00683bd5a2e511f773ac3e664222692297d7b469fcae561e6" - "1a8127bef87978449ec640883c0ba17d4f1741ed4ec94443b0fa0db1a139ad219ff7a4" - "ac34ced9c7d74e4bf608a1d8f792c0bf28eedbf2536af7"), - from_hex( - "460396e559547d5faa532503b9a15bdd4d9b7415f3e71327adb1dd1cc21eb905dd9654" - "136772745f5cc9d9ffdf6bed05b9b17491a2ae8309e847bc1c7f4d6e0c"), - }, - { - Signature::ID::Ed448, - from_hex("7d60a1da10701ca4579de441643a545e334fddf18f6159ad2e8d2d914877a82" - "ea95f0b1bdac911dfb2499d3ccf814ebe69b09f9914c6aca000"), - from_hex( - "074f95d4f746a270af113b5650da98dcb247ef9839e480e99961a2cc998058e2b98be3" - "f949ceb7b000973127c0f79e54644f3b750763c2e904ac2179aa0a7e03da4e6d848f50" - "8323ff81e4a6d20b4eb89fed06a9117383daa50e13d25e6e1c740691021379005d140a" - "8e2157744cf7717f95a503d8e3740a081efa27146974c6"), - from_hex("902aa0a168a9e7a547a1736fb52b491f857fe8984b9a5a5b2ae50b3c2c3b232" - "894ae055013b256218cea79c4b4055719de3a6fbb2b0be0470062bc9e76f89e" - "4ffc4c08cbd8ce50de80bae8029b78ced07cce09bc75c9b2eedcf402ed0e74c" - "8078326f8ab69960d8062d2294ad1ff63901b00"), - }, + { + Signature::ID::P384_SHA384, + from_hex("04d5a2abcb844865a479af773f9db66f5b8994710e2617e8b3c7ab4555f02" + "3f8e71a42" + "291416cdf9ea288874c5cc9f38a49b6e7cc96a3a65f60a42a05e233af26c9" + "4e0cc23c8" + "ee60177f1e1e3b52514a8de018addcc97245c2bef6bdd9ea7149da"), + from_hex("4be880bc0ccc92f79ed58b2c78268e28610719fb654b7d8b8aceae09e9e9e" + "c3115de63" + "3d5dbeb36762a67d48b0fd1c74cd499058557638372bb5d76f88a5ea00194" + "f9c0b1578" + "a9b5833d8d001ce847d4a55212601d514d6134f581f4c9a1f7bc5564ceaf2" + "8169c7fff" + "70fbc67087da868826913dab1f1dcfdf045d027e7460b7"), + from_hex( + "3064023036da67b80ca54e25cffd8c7992d406118de661c9ff40ed0468938b04d710" + "09" + "7a3f5a947d2cb5420a5af6ca9b7a8684cb023042950fa4859def74cee5066f974b7a" + "49" + "cd43899468831970b736b7bbb95338d1dd0c9e9034c9801f414982580fe9e590"), + }, + { + Signature::ID::P521_SHA512, + from_hex("0400a659dcddfafe88ebbba8c04155870e0315794c7bd5a0c53ed9b57bcfa" + "a36d79743" + "5b40a74d62ba4104d62e166538e6f88d832aa047b6ed3cd119a477000f336" + "2df01855f" + "4e61ed4be7e81ed5f566ef6455a4fb588db6e6e44f57dc4271ac3d22cdba1" + "6d361db47" + "8fa4fb233fd71179633e722615c33cfbd1d556cc29a839121c37b982"), + from_hex("6abe2712353e03ef03571a9679a3f1e889937d5ffc0df431fab44a408ce8c" + "c37449f94" + "28aae783a2ce200bb7ed546a1a92ea3555b45552844d15d6d86b662778e33" + "124304691" + "16615523990495dd3352b374792d591384123c3c7ca81ad42b9f6e856426a" + "82dddd284" + "d2f447df243067af6fe7f73cc4a368cb7cd53240af21d6"), + from_hex("3081880242015a033045a1bf86b3e1017826dd226604d78d129dcfca84f40" + "20063beec" + "03e0b4bedbedacbf1b0d1285ddbd0c7107078ac200be9876577025ffdd898" + "e97f648f7" + "80024201afcf701a73ab224ea5a0b6399fc231da0e7f1a8649df17ef2d517" + "1fc4dc278" + "6923727c2edc4f0ad9e98825750596be312d0109d47888ab6481c688a287b" + "0aac6b0"), + }, + { + Signature::ID::Ed25519, + from_hex( + "923654bbdbacc72ab6c568208719c7cb866c3f89c366914ae90d604ef360c5c8"), + from_hex("dab12589702ff146b4e83b808da4007ff4ea4a358af2f7baa6861f08fb11e" + "d71e338b2" + "fa01c7a68f86daaed5c1f00683bd5a2e511f773ac3e664222692297d7b469" + "fcae561e6" + "1a8127bef87978449ec640883c0ba17d4f1741ed4ec94443b0fa0db1a139a" + "d219ff7a4" + "ac34ced9c7d74e4bf608a1d8f792c0bf28eedbf2536af7"), + from_hex("460396e559547d5faa532503b9a15bdd4d9b7415f3e71327adb1dd1cc21eb" + "905dd9654" + "136772745f5cc9d9ffdf6bed05b9b17491a2ae8309e847bc1c7f4d6e0c"), + }, +#if !defined(WITH_BORINGSSL) + { + Signature::ID::Ed448, + from_hex( + "7d60a1da10701ca4579de441643a545e334fddf18f6159ad2e8d2d914877a82" + "ea95f0b1bdac911dfb2499d3ccf814ebe69b09f9914c6aca000"), + from_hex("074f95d4f746a270af113b5650da98dcb247ef9839e480e99961a2cc99805" + "8e2b98be3" + "f949ceb7b000973127c0f79e54644f3b750763c2e904ac2179aa0a7e03da4" + "e6d848f50" + "8323ff81e4a6d20b4eb89fed06a9117383daa50e13d25e6e1c74069102137" + "9005d140a" + "8e2157744cf7717f95a503d8e3740a081efa27146974c6"), + from_hex( + "902aa0a168a9e7a547a1736fb52b491f857fe8984b9a5a5b2ae50b3c2c3b232" + "894ae055013b256218cea79c4b4055719de3a6fbb2b0be0470062bc9e76f89e" + "4ffc4c08cbd8ce50de80bae8029b78ced07cce09bc75c9b2eedcf402ed0e74c" + "8078326f8ab69960d8062d2294ad1ff63901b00"), + }, +#endif }; for (const auto& tc : cases) { @@ -198,11 +222,15 @@ TEST_CASE("Signature Round-Trip") { ensure_fips_if_required(); - const std::vector ids{ + const std::vector ids + { Signature::ID::P256_SHA256, Signature::ID::P384_SHA384, - Signature::ID::P521_SHA512, Signature::ID::Ed25519, - Signature::ID::Ed448, Signature::ID::RSA_SHA256, - Signature::ID::RSA_SHA384, Signature::ID::RSA_SHA512, + Signature::ID::P521_SHA512, Signature::ID::Ed25519, +#if !defined(WITH_BORINGSSL) + Signature::ID::Ed448, +#endif + Signature::ID::RSA_SHA256, Signature::ID::RSA_SHA384, + Signature::ID::RSA_SHA512, }; const auto data = from_hex("00010203"); @@ -245,10 +273,13 @@ TEST_CASE("Signature Round-Trip") TEST_CASE("Signature Key JWK Round-Trip") { ensure_fips_if_required(); - const std::vector ids{ + const std::vector ids + { Signature::ID::P256_SHA256, Signature::ID::P384_SHA384, - Signature::ID::P521_SHA512, Signature::ID::Ed25519, - Signature::ID::Ed448, + Signature::ID::P521_SHA512, Signature::ID::Ed25519, +#if !defined(WITH_BORINGSSL) + Signature::ID::Ed448, +#endif }; for (const auto& id : ids) { @@ -346,6 +377,7 @@ TEST_CASE("Signature Key JWK Known-Answer") "x": "Rv-rXr1oUaa29TdaXzIhJEOV3eJYzMqy_luvV0T80no" })", }, +#if !defined(WITH_BORINGSSL) { Signature::ID::Ed448, R"({ @@ -360,6 +392,7 @@ TEST_CASE("Signature Key JWK Known-Answer") "x":"0P_035gQbBr8mHe_4uLu8wUI22JiSBYWq9Yzb3Tr3C4ksfv85Xo5OIRrWzE-L0QFRez78nrNA4wA" })", }, +#endif }; // clang-format on diff --git a/lib/mls_vectors/test/CMakeLists.txt b/lib/mls_vectors/test/CMakeLists.txt index 360f03aa..9e640b88 100644 --- a/lib/mls_vectors/test/CMakeLists.txt +++ b/lib/mls_vectors/test/CMakeLists.txt @@ -8,7 +8,7 @@ file(GLOB TEST_SOURCES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) add_executable(${TEST_APP_NAME} ${TEST_SOURCES}) add_dependencies(${TEST_APP_NAME} ${CURRENT_LIB_NAME} bytes tls_syntax) -target_link_libraries(${TEST_APP_NAME} ${CURRENT_LIB_NAME} bytes tls_syntax doctest::doctest) +target_link_libraries(${TEST_APP_NAME} ${CURRENT_LIB_NAME} bytes tls_syntax doctest::doctest ${OPENSSL_CRYPTO_LIBRARY}) # Enable CTest include(doctest) diff --git a/lib/mls_vectors/test/mls_vectors.cpp b/lib/mls_vectors/test/mls_vectors.cpp index f50f96b0..7ff741b6 100644 --- a/lib/mls_vectors/test/mls_vectors.cpp +++ b/lib/mls_vectors/test/mls_vectors.cpp @@ -4,13 +4,16 @@ using namespace mls_vectors; -static const std::vector supported_suites{ +static const std::vector supported_suites +{ { MLS_NAMESPACE::CipherSuite::ID::X25519_AES128GCM_SHA256_Ed25519 }, - { MLS_NAMESPACE::CipherSuite::ID::P256_AES128GCM_SHA256_P256 }, - { MLS_NAMESPACE::CipherSuite::ID::X25519_CHACHA20POLY1305_SHA256_Ed25519 }, - { MLS_NAMESPACE::CipherSuite::ID::X448_AES256GCM_SHA512_Ed448 }, - { MLS_NAMESPACE::CipherSuite::ID::P521_AES256GCM_SHA512_P521 }, - { MLS_NAMESPACE::CipherSuite::ID::X448_CHACHA20POLY1305_SHA512_Ed448 }, + { MLS_NAMESPACE::CipherSuite::ID::P256_AES128GCM_SHA256_P256 }, + { MLS_NAMESPACE::CipherSuite::ID::X25519_CHACHA20POLY1305_SHA256_Ed25519 }, + { MLS_NAMESPACE::CipherSuite::ID::P521_AES256GCM_SHA512_P521 }, +#if !defined(WITH_BORINGSSL) + { MLS_NAMESPACE::CipherSuite::ID::X448_AES256GCM_SHA512_Ed448 }, + { MLS_NAMESPACE::CipherSuite::ID::X448_CHACHA20POLY1305_SHA512_Ed448 }, +#endif }; TEST_CASE("Tree Math") diff --git a/src/credential.cpp b/src/credential.cpp index 36b10629..cc5178c5 100644 --- a/src/credential.cpp +++ b/src/credential.cpp @@ -26,8 +26,10 @@ find_signature(Signature::ID id) return Signature::get(); case Signature::ID::Ed25519: return Signature::get(); +#if !defined(WITH_BORINGSSL) case Signature::ID::Ed448: return Signature::get(); +#endif case Signature::ID::RSA_SHA256: return Signature::get(); default: diff --git a/src/crypto.cpp b/src/crypto.cpp index 1986659c..8d859c0e 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -26,8 +26,10 @@ tls_signature_scheme(Signature::ID id) return SignatureScheme::ecdsa_secp521r1_sha512; case Signature::ID::Ed25519: return SignatureScheme::ed25519; +#if !defined(WITH_BORINGSSL) case Signature::ID::Ed448: return SignatureScheme::ed448; +#endif case Signature::ID::RSA_SHA256: return SignatureScheme::rsa_pkcs1_sha256; default: @@ -98,18 +100,26 @@ CipherSuite::get() const Signature::get(), }; - static const auto ciphers_X448_AES256GCM_SHA512_Ed448 = CipherSuite::Ciphers{ + static const auto ciphers_P521_AES256GCM_SHA512_P521 = CipherSuite::Ciphers{ HPKE( - KEM::ID::DHKEM_X448_SHA512, KDF::ID::HKDF_SHA512, AEAD::ID::AES_256_GCM), + KEM::ID::DHKEM_P521_SHA512, KDF::ID::HKDF_SHA512, AEAD::ID::AES_256_GCM), Digest::get(), - Signature::get(), + Signature::get(), }; - static const auto ciphers_P521_AES256GCM_SHA512_P521 = CipherSuite::Ciphers{ + static const auto ciphers_P384_AES256GCM_SHA384_P384 = CipherSuite::Ciphers{ HPKE( - KEM::ID::DHKEM_P521_SHA512, KDF::ID::HKDF_SHA512, AEAD::ID::AES_256_GCM), + KEM::ID::DHKEM_P384_SHA384, KDF::ID::HKDF_SHA384, AEAD::ID::AES_256_GCM), + Digest::get(), + Signature::get(), + }; + +#if !defined(WITH_BORINGSSL) + static const auto ciphers_X448_AES256GCM_SHA512_Ed448 = CipherSuite::Ciphers{ + HPKE( + KEM::ID::DHKEM_X448_SHA512, KDF::ID::HKDF_SHA512, AEAD::ID::AES_256_GCM), Digest::get(), - Signature::get(), + Signature::get(), }; static const auto ciphers_X448_CHACHA20POLY1305_SHA512_Ed448 = @@ -120,13 +130,7 @@ CipherSuite::get() const Digest::get(), Signature::get(), }; - - static const auto ciphers_P384_AES256GCM_SHA384_P384 = CipherSuite::Ciphers{ - HPKE( - KEM::ID::DHKEM_P384_SHA384, KDF::ID::HKDF_SHA384, AEAD::ID::AES_256_GCM), - Digest::get(), - Signature::get(), - }; +#endif switch (id) { case ID::unknown: @@ -141,18 +145,20 @@ CipherSuite::get() const case ID::X25519_CHACHA20POLY1305_SHA256_Ed25519: return ciphers_X25519_CHACHA20POLY1305_SHA256_Ed25519; - case ID::X448_AES256GCM_SHA512_Ed448: - return ciphers_X448_AES256GCM_SHA512_Ed448; - case ID::P521_AES256GCM_SHA512_P521: return ciphers_P521_AES256GCM_SHA512_P521; - case ID::X448_CHACHA20POLY1305_SHA512_Ed448: - return ciphers_X448_CHACHA20POLY1305_SHA512_Ed448; - case ID::P384_AES256GCM_SHA384_P384: return ciphers_P384_AES256GCM_SHA384_P384; +#if !defined(WITH_BORINGSSL) + case ID::X448_AES256GCM_SHA512_Ed448: + return ciphers_X448_AES256GCM_SHA512_Ed448; + + case ID::X448_CHACHA20POLY1305_SHA512_Ed448: + return ciphers_X448_CHACHA20POLY1305_SHA512_Ed448; +#endif + default: throw InvalidParameterError("Unsupported ciphersuite"); } @@ -194,15 +200,25 @@ CipherSuite::derive_tree_secret(const bytes& secret, return expand_with_label(secret, label, tls::marshal(generation), length); } +#if WITH_BORINGSSL +const std::array all_supported_suites = { + CipherSuite::ID::X25519_AES128GCM_SHA256_Ed25519, + CipherSuite::ID::P256_AES128GCM_SHA256_P256, + CipherSuite::ID::X25519_CHACHA20POLY1305_SHA256_Ed25519, + CipherSuite::ID::P521_AES256GCM_SHA512_P521, + CipherSuite::ID::P384_AES256GCM_SHA384_P384, +}; +#else const std::array all_supported_suites = { CipherSuite::ID::X25519_AES128GCM_SHA256_Ed25519, CipherSuite::ID::P256_AES128GCM_SHA256_P256, CipherSuite::ID::X25519_CHACHA20POLY1305_SHA256_Ed25519, - CipherSuite::ID::X448_AES256GCM_SHA512_Ed448, CipherSuite::ID::P521_AES256GCM_SHA512_P521, - CipherSuite::ID::X448_CHACHA20POLY1305_SHA512_Ed448, CipherSuite::ID::P384_AES256GCM_SHA384_P384, + CipherSuite::ID::X448_CHACHA20POLY1305_SHA512_Ed448, + CipherSuite::ID::X448_AES256GCM_SHA512_Ed448, }; +#endif // MakeKeyPackageRef(value) = KDF.expand( // KDF.extract("", value), "MLS 1.0 KeyPackage Reference", 16) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 87af1c49..182e2cfc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -11,7 +11,7 @@ add_dependencies(${TEST_APP_NAME} ${LIB_NAME} bytes tls_syntax mls_vectors) target_include_directories(${TEST_APP_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/src) target_link_libraries(${TEST_APP_NAME} ${LIB_NAME} bytes tls_syntax mls_vectors - doctest::doctest OpenSSL::Crypto) + doctest::doctest ${OPENSSL_CRYPTO_LIBRARY}) # Enable CTest include(doctest) diff --git a/test/session.cpp b/test/session.cpp index 894f2654..da5df003 100644 --- a/test/session.cpp +++ b/test/session.cpp @@ -221,6 +221,26 @@ TEST_CASE_FIXTURE(RunningSessionTest, "Full Session Life-Cycle") } } +// XXX(RLB) BoringSSL rejects the leaf certificate here with the following error +// code: +// +// error:0b00008b:X.509 certificate +// routines:OPENSSL_internal:INVALID_FIELD_FOR_VERSION +// +// I have disabled the test for now, but given that the BoringSSL maintainers +// know what they're doing, there's probably a legitimate issue here and we +// should regenerate the test certificates. +// +// On a quick look, it appears that INVALID_FIELD_FOR_VERSION is returned when +// a field is present in the certificate that requires v2 or v3 according to RFC +// 5280 [1]. And in the decoding of these certificates, it looks like the +// version field is missing, thus v1 by default. (Interesting, given that +// I think we generated these with Go!) So the solution appears to be +// regenerating with an explicit version field set to v3. +// +// [1] +// https://boringssl.googlesource.com/boringssl.git/+/dd86e75b24dcfd47d4ee6b3e4cdce907389335b2%5E%21/ +#if !defined(WITH_BORINGSSL) TEST_CASE("Session with X509 Credential") { // leaf_cert with p-256 public key @@ -298,3 +318,4 @@ TEST_CASE("Session with X509 Credential") REQUIRE(alice_session.epoch_authenticator() == bob_session.epoch_authenticator()); } +#endif