From bb7ae5352e71750692a64b0f5a492530cef4f1b8 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 10 Jul 2023 10:50:05 +0000 Subject: [PATCH 01/57] Compiles --- CHANGELOG.md | 1 + cmake/ccf_app.cmake | 2 +- cmake/cpack_settings.cmake | 2 +- cmake/open_enclave.cmake | 4 ++-- cmake/t_cose.cmake | 4 ++-- getting_started/setup_vm/roles/openenclave/vars/common.yml | 4 ++-- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f98360181f51..b68ac9718542 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. [4.0.5]: https://github.com/microsoft/CCF/releases/tag/ccf-4.0.5 - Debug logging is now available in non-SGX builds by default, and controlled by a run-time CLI argument (`--enclave-log-level`). On SGX this remains a build-time decision (#5375). +- Updated Open Enclave to [0.19.2](https://github.com/openenclave/openenclave/releases/tag/v0.19.2). ## [4.0.4] diff --git a/cmake/ccf_app.cmake b/cmake/ccf_app.cmake index 71fcba0e40e6..7cbf26c5376f 100644 --- a/cmake/ccf_app.cmake +++ b/cmake/ccf_app.cmake @@ -225,7 +225,7 @@ if(COMPILE_TARGET STREQUAL "sgx") cmake_parse_arguments(PARSE_ARGV 1 PARSED_ARGS "" "" "") set(files ${PARSED_ARGS_UNPARSED_ARGUMENTS}) add_library(${name} ${files}) - target_compile_options(${name} PUBLIC -nostdinc -nostdinc++) + target_compile_options(${name} PUBLIC -nostdinc -nostdinc++ "-Wno-deprecated-declarations") target_compile_definitions( ${name} PUBLIC INSIDE_ENCLAVE _LIBCPP_HAS_THREAD_API_PTHREAD ) diff --git a/cmake/cpack_settings.cmake b/cmake/cpack_settings.cmake index 0d9d58972aaf..84bfa525da99 100644 --- a/cmake/cpack_settings.cmake +++ b/cmake/cpack_settings.cmake @@ -24,7 +24,7 @@ message(STATUS "Debian package version: ${CPACK_DEBIAN_PACKAGE_VERSION}") set(CCF_DEB_BASE_DEPENDENCIES "libuv1 (>= 1.34.2);openssl (>=1.1.1f)") set(CCF_DEB_DEPENDENCIES ${CCF_DEB_BASE_DEPENDENCIES}) -set(OE_VERSION "0.19.0") +set(OE_VERSION "0.19.2") if(COMPILE_TARGET STREQUAL "sgx") list(APPEND CCF_DEB_DEPENDENCIES "libc++1-11;libc++abi1-11;open-enclave (>=${OE_VERSION})" diff --git a/cmake/open_enclave.cmake b/cmake/open_enclave.cmake index 0970ef68cdb9..a6b4fae1aafa 100644 --- a/cmake/open_enclave.cmake +++ b/cmake/open_enclave.cmake @@ -13,7 +13,7 @@ if(REQUIRE_OPENENCLAVE) endif() # Find OpenEnclave package - find_package(OpenEnclave 0.19.0 CONFIG REQUIRED) + find_package(OpenEnclave 0.19.2 CONFIG REQUIRED) # As well as pulling in openenclave:: targets, this sets variables which can # be used for our edge cases (eg - for virtual libraries). These do not follow @@ -23,7 +23,7 @@ if(REQUIRE_OPENENCLAVE) set(OE_TARGET_LIBC openenclave::oelibc) set(OE_TARGET_ENCLAVE_AND_STD openenclave::oeenclave openenclave::oelibcxx openenclave::oelibc - openenclave::oecryptoopenssl + openenclave::oecryptoopenssl_3 ) # These oe libraries must be linked in specific order diff --git a/cmake/t_cose.cmake b/cmake/t_cose.cmake index 18dfc2a94c30..5ce75ac007dc 100644 --- a/cmake/t_cose.cmake +++ b/cmake/t_cose.cmake @@ -15,7 +15,7 @@ set(T_COSE_SRCS if(COMPILE_TARGET STREQUAL "sgx") add_enclave_library_c(t_cose.enclave ${T_COSE_SRCS}) target_compile_definitions(t_cose.enclave PRIVATE ${T_COSE_DEFS}) - target_compile_options(t_cose.enclave INTERFACE ${T_COSE_OPTS_INTERFACE}) + target_compile_options(t_cose.enclave INTERFACE ${T_COSE_OPTS_INTERFACE} "-Wno-deprecated-declarations") target_include_directories(t_cose.enclave PRIVATE "${T_COSE_SRC}") target_include_directories( @@ -26,7 +26,7 @@ if(COMPILE_TARGET STREQUAL "sgx") target_link_libraries(t_cose.enclave PUBLIC qcbor.enclave) # This is needed to get the OpenSSL includes from Open Enclave - target_link_libraries(t_cose.enclave PRIVATE openenclave::oecryptoopenssl) + target_link_libraries(t_cose.enclave PRIVATE openenclave::oecryptoopenssl_3) install( TARGETS t_cose.enclave diff --git a/getting_started/setup_vm/roles/openenclave/vars/common.yml b/getting_started/setup_vm/roles/openenclave/vars/common.yml index b8aaec7a5a92..41bc87272daf 100644 --- a/getting_started/setup_vm/roles/openenclave/vars/common.yml +++ b/getting_started/setup_vm/roles/openenclave/vars/common.yml @@ -1,6 +1,6 @@ -oe_ver: "0.19.0" +oe_ver: "0.19.2" # Usually the same, except for rc, where ver is -rc and ver_ is _rc -oe_ver_: "0.19.0" +oe_ver_: "0.19.2" # Source install workspace: "/tmp/" From e2c7be83cf0c43414f02e90b2723fd8ab6d07215 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 10 Jul 2023 13:29:00 +0000 Subject: [PATCH 02/57] Better macros --- cmake/ccf_app.cmake | 4 ++-- cmake/t_cose.cmake | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/ccf_app.cmake b/cmake/ccf_app.cmake index 7cbf26c5376f..ed49ec64e3b6 100644 --- a/cmake/ccf_app.cmake +++ b/cmake/ccf_app.cmake @@ -225,9 +225,9 @@ if(COMPILE_TARGET STREQUAL "sgx") cmake_parse_arguments(PARSE_ARGV 1 PARSED_ARGS "" "" "") set(files ${PARSED_ARGS_UNPARSED_ARGUMENTS}) add_library(${name} ${files}) - target_compile_options(${name} PUBLIC -nostdinc -nostdinc++ "-Wno-deprecated-declarations") + target_compile_options(${name} PUBLIC -nostdinc -nostdinc++) target_compile_definitions( - ${name} PUBLIC INSIDE_ENCLAVE _LIBCPP_HAS_THREAD_API_PTHREAD + ${name} PUBLIC INSIDE_ENCLAVE _LIBCPP_HAS_THREAD_API_PTHREAD OPENSSL_API_COMPAT=0x10101000L ) target_link_libraries(${name} PUBLIC ${OE_TARGET_ENCLAVE_AND_STD} -lgcc) set_property(TARGET ${name} PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/cmake/t_cose.cmake b/cmake/t_cose.cmake index 5ce75ac007dc..11a252e53e16 100644 --- a/cmake/t_cose.cmake +++ b/cmake/t_cose.cmake @@ -14,8 +14,8 @@ set(T_COSE_SRCS ) if(COMPILE_TARGET STREQUAL "sgx") add_enclave_library_c(t_cose.enclave ${T_COSE_SRCS}) - target_compile_definitions(t_cose.enclave PRIVATE ${T_COSE_DEFS}) - target_compile_options(t_cose.enclave INTERFACE ${T_COSE_OPTS_INTERFACE} "-Wno-deprecated-declarations") + target_compile_definitions(t_cose.enclave PRIVATE ${T_COSE_DEFS} OPENSSL_API_COMPAT=0x10101000L) + target_compile_options(t_cose.enclave INTERFACE ${T_COSE_OPTS_INTERFACE}) target_include_directories(t_cose.enclave PRIVATE "${T_COSE_SRC}") target_include_directories( From 3b1a0703f8156ce354baa742d18364f5733fb010 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 10 Jul 2023 13:35:08 +0000 Subject: [PATCH 03/57] CI image --- .azure-pipelines-gh-pages.yml | 2 +- .azure-pipelines-quictls.yml | 2 +- .azure-pipelines.yml | 6 +++--- .daily.yml | 6 +++--- .devcontainer/devcontainer.json | 4 ++-- .github/workflows/build-ci-container.yml | 4 ++-- .github/workflows/ci-checks.yml | 2 +- .multi-thread.yml | 2 +- .stress.yml | 2 +- docker/ccf_ci_built | 2 +- scripts/azure_deployment/arm_aci.py | 2 +- 11 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.azure-pipelines-gh-pages.yml b/.azure-pipelines-gh-pages.yml index 620d39407585..8364788a9c25 100644 --- a/.azure-pipelines-gh-pages.yml +++ b/.azure-pipelines-gh-pages.yml @@ -11,7 +11,7 @@ jobs: variables: Codeql.SkipTaskAutoInjection: true skipComponentGovernanceDetection: true - container: ccfmsrc.azurecr.io/ccf/ci:27-04-2023-virtual-clang15 + container: ccfmsrc.azurecr.io/ccf/ci:10-07-2023-virtual-clang15 pool: vmImage: ubuntu-20.04 diff --git a/.azure-pipelines-quictls.yml b/.azure-pipelines-quictls.yml index abe469be4e5e..461df3c06b4c 100644 --- a/.azure-pipelines-quictls.yml +++ b/.azure-pipelines-quictls.yml @@ -17,7 +17,7 @@ parameters: jobs: - job: build_quictls - container: ccfmsrc.azurecr.io/ccf/ci:27-04-2023-clang15 + container: ccfmsrc.azurecr.io/ccf/ci:10-07-2023-clang15 pool: ado-virtual-ccf-sub strategy: diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 22d862812472..8400569e2988 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -29,15 +29,15 @@ schedules: resources: containers: - container: virtual - image: ccfmsrc.azurecr.io/ccf/ci:27-04-2023-virtual-clang15 + image: ccfmsrc.azurecr.io/ccf/ci:10-07-2023-virtual-clang15 options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --cap-add SYS_PTRACE -v /lib/modules:/lib/modules:ro - container: snp - image: ccfmsrc.azurecr.io/ccf/ci:27-04-2023-snp-clang15 + image: ccfmsrc.azurecr.io/ccf/ci:10-07-2023-snp-clang15 options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --cap-add SYS_PTRACE -v /lib/modules:/lib/modules:ro - container: sgx - image: ccfmsrc.azurecr.io/ccf/ci:27-04-2023-sgx + image: ccfmsrc.azurecr.io/ccf/ci:10-07-2023-sgx options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --device /dev/sgx_enclave:/dev/sgx_enclave --device /dev/sgx_provision:/dev/sgx_provision -v /dev/sgx:/dev/sgx -v /lib/modules:/lib/modules:ro variables: diff --git a/.daily.yml b/.daily.yml index eda51342667f..972b443bf9ab 100644 --- a/.daily.yml +++ b/.daily.yml @@ -25,15 +25,15 @@ schedules: resources: containers: - container: virtual - image: ccfmsrc.azurecr.io/ccf/ci:27-04-2023-virtual-clang15 + image: ccfmsrc.azurecr.io/ccf/ci:10-07-2023-virtual-clang15 options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --cap-add SYS_PTRACE - container: snp - image: ccfmsrc.azurecr.io/ccf/ci:27-04-2023-snp-clang15 + image: ccfmsrc.azurecr.io/ccf/ci:10-07-2023-snp-clang15 options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --cap-add SYS_PTRACE -v /lib/modules:/lib/modules:ro - container: sgx - image: ccfmsrc.azurecr.io/ccf/ci:27-04-2023-sgx + image: ccfmsrc.azurecr.io/ccf/ci:10-07-2023-sgx options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --device /dev/sgx_enclave:/dev/sgx_enclave --device /dev/sgx_provision:/dev/sgx_provision -v /dev/sgx:/dev/sgx jobs: diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c66fdb3cc242..61ed75adbe74 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,6 @@ { "name": "CCF Development Environment", - "image": "ccfmsrc.azurecr.io/ccf/ci:27-04-2023-virtual-clang15", + "image": "ccfmsrc.azurecr.io/ccf/ci:10-07-2023-virtual-clang15", "runArgs": [], "extensions": [ "eamodio.gitlens", @@ -28,4 +28,4 @@ "version": "latest" } } -} +} \ No newline at end of file diff --git a/.github/workflows/build-ci-container.yml b/.github/workflows/build-ci-container.yml index b0e7c5d0213c..d7320a15c4b7 100644 --- a/.github/workflows/build-ci-container.yml +++ b/.github/workflows/build-ci-container.yml @@ -45,10 +45,10 @@ jobs: run: docker login -u $ACR_TOKEN_NAME -p ${{ secrets.ACR_CI_PUSH_TOKEN_PASSWORD }} $ACR_REGISTRY - name: Pull CI container - run: docker pull $ACR_REGISTRY/ccf/ci:27-04-2023-snp-clang15 + run: docker pull $ACR_REGISTRY/ccf/ci:10-07-2023-snp-clang15 - name: Build CCF CI SNP container - run: docker build -f docker/ccf_ci_built . --build-arg="base=ccfmsrc.azurecr.io/ccf/ci:27-04-2023-snp-clang15" --build-arg="platform=snp" -t $ACR_REGISTRY/ccf/ci:pr-`git rev-parse HEAD` + run: docker build -f docker/ccf_ci_built . --build-arg="base=ccfmsrc.azurecr.io/ccf/ci:10-07-2023-snp-clang15" --build-arg="platform=snp" -t $ACR_REGISTRY/ccf/ci:pr-`git rev-parse HEAD` - name: Push CI container run: docker push $ACR_REGISTRY/ccf/ci:pr-`git rev-parse HEAD` diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml index 58def75f64e0..cbc7766568c6 100644 --- a/.github/workflows/ci-checks.yml +++ b/.github/workflows/ci-checks.yml @@ -9,7 +9,7 @@ on: jobs: checks: runs-on: ubuntu-latest - container: ccfmsrc.azurecr.io/ccf/ci:27-04-2023-virtual-clang15 + container: ccfmsrc.azurecr.io/ccf/ci:10-07-2023-virtual-clang15 steps: - run: git config --global --add safe.directory "$GITHUB_WORKSPACE" diff --git a/.multi-thread.yml b/.multi-thread.yml index 19d96e67c6f9..d477ee9bcfd4 100644 --- a/.multi-thread.yml +++ b/.multi-thread.yml @@ -16,7 +16,7 @@ pr: resources: containers: - container: virtual - image: ccfmsrc.azurecr.io/ccf/ci:27-04-2023-virtual-clang15 + image: ccfmsrc.azurecr.io/ccf/ci:10-07-2023-virtual-clang15 options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --cap-add SYS_PTRACE -v /lib/modules:/lib/modules:ro jobs: diff --git a/.stress.yml b/.stress.yml index 7aa671ef8b53..b27b4e93b3f6 100644 --- a/.stress.yml +++ b/.stress.yml @@ -20,7 +20,7 @@ schedules: resources: containers: - container: sgx - image: ccfmsrc.azurecr.io/ccf/ci:27-04-2023-sgx + image: ccfmsrc.azurecr.io/ccf/ci:10-07-2023-sgx options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --device /dev/sgx_enclave:/dev/sgx_enclave --device /dev/sgx_provision:/dev/sgx_provision -v /dev/sgx:/dev/sgx jobs: diff --git a/docker/ccf_ci_built b/docker/ccf_ci_built index 99115ff6e145..8f9771b9cd08 100644 --- a/docker/ccf_ci_built +++ b/docker/ccf_ci_built @@ -4,7 +4,7 @@ # Latest image as of this change ARG platform=sgx -ARG base=ccfmsrc.azurecr.io/ccf/ci:27-04-2023-snp-clang-15 +ARG base=ccfmsrc.azurecr.io/ccf/ci:10-07-2023-snp-clang-15 FROM ${base} # SSH. Note that this could (should) be done in the base ccf_ci image instead diff --git a/scripts/azure_deployment/arm_aci.py b/scripts/azure_deployment/arm_aci.py index eff9e5351ed2..a7f8b8b633e0 100644 --- a/scripts/azure_deployment/arm_aci.py +++ b/scripts/azure_deployment/arm_aci.py @@ -178,7 +178,7 @@ def parse_aci_args(parser: ArgumentParser) -> Namespace: "--aci-image", help="The name of the image to deploy in the ACI", type=str, - default="ccfmsrc.azurecr.io/ccf/ci:27-04-2023-snp", + default="ccfmsrc.azurecr.io/ccf/ci:10-07-2023-snp", ) parser.add_argument( "--aci-type", From 980d07cdd316b1dafb3caa7b4e2342827f778d23 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 10 Jul 2023 15:38:40 +0000 Subject: [PATCH 04/57] Fix snapshot verification --- src/node/snapshot_serdes.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/node/snapshot_serdes.h b/src/node/snapshot_serdes.h index 24238d5bd0c6..1e9cb706a4f2 100644 --- a/src/node/snapshot_serdes.h +++ b/src/node/snapshot_serdes.h @@ -85,7 +85,8 @@ namespace ccf root.h.data(), root.h.size(), receipt->signature.data(), - receipt->signature.size())) + receipt->signature.size(), + crypto::MDType::SHA256)) { throw std::logic_error( "Signature verification failed for snapshot receipt"); From da67c3f270e0bf41aed694581238596dc5461184 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 11 Jul 2023 12:41:44 +0000 Subject: [PATCH 05/57] Unit test works --- .devcontainer/devcontainer.json | 2 +- CMakeLists.txt | 3 -- cmake/ccf_app.cmake | 28 +++++++------ cmake/common.cmake | 2 +- cmake/crypto.cmake | 59 ++++++++++++++++----------- cmake/t_cose.cmake | 8 ++-- src/crypto/openssl/openssl_wrappers.h | 2 + 7 files changed, 59 insertions(+), 45 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 61ed75adbe74..6e674719a528 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -28,4 +28,4 @@ "version": "latest" } } -} \ No newline at end of file +} diff --git a/CMakeLists.txt b/CMakeLists.txt index e84d994839ac..574b9ee72cb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -247,9 +247,6 @@ set(CCF_ENDPOINTS_SOURCES ${CCF_DIR}/src/node/receipt.cpp ) -find_library(CRYPTO_LIBRARY crypto) -find_library(TLS_LIBRARY ssl) - include(${CCF_DIR}/cmake/crypto.cmake) include(${CCF_DIR}/cmake/quickjs.cmake) include(${CCF_DIR}/cmake/sss.cmake) diff --git a/cmake/ccf_app.cmake b/cmake/ccf_app.cmake index ed49ec64e3b6..b871002d919e 100644 --- a/cmake/ccf_app.cmake +++ b/cmake/ccf_app.cmake @@ -5,16 +5,16 @@ set(ALLOWED_TARGETS "sgx;snp;virtual") if(NOT DEFINED COMPILE_TARGET) set(COMPILE_TARGET - "sgx" - CACHE STRING - "Target compilation platforms, Choose from: ${ALLOWED_TARGETS}" + "sgx" + CACHE STRING + "Target compilation platforms, Choose from: ${ALLOWED_TARGETS}" ) endif() if(NOT COMPILE_TARGET IN_LIST ALLOWED_TARGETS) message( FATAL_ERROR - "${REQUESTED_TARGET} is not a valid target. Choose from: ${ALLOWED_TARGETS}" + "${REQUESTED_TARGET} is not a valid target. Choose from: ${ALLOWED_TARGETS}" ) endif() message(STATUS "Compile target platform: ${COMPILE_TARGET}") @@ -42,9 +42,9 @@ function(sign_app_library name app_oe_conf_path enclave_sign_key_path) # Add Debug=1 line COMMAND echo "Debug=1" >> ${DEBUG_CONF_NAME} COMMAND - openenclave::oesign sign -e ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so -c - ${DEBUG_CONF_NAME} -k ${enclave_sign_key_path} -o - ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so.debuggable + openenclave::oesign sign -e ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so -c + ${DEBUG_CONF_NAME} -k ${enclave_sign_key_path} -o + ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so.debuggable DEPENDS ${name} ${app_oe_conf_path} ${enclave_sign_key_path} ) @@ -65,8 +65,8 @@ function(sign_app_library name app_oe_conf_path enclave_sign_key_path) # Add Debug=0 line COMMAND echo "Debug=0" >> ${SIGNED_CONF_NAME} COMMAND - openenclave::oesign sign -e ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so -c - ${SIGNED_CONF_NAME} -k ${enclave_sign_key_path} + openenclave::oesign sign -e ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so -c + ${SIGNED_CONF_NAME} -k ${enclave_sign_key_path} DEPENDS ${name} ${app_oe_conf_path} ${enclave_sign_key_path} ) @@ -77,10 +77,10 @@ function(sign_app_library name app_oe_conf_path enclave_sign_key_path) if(${PARSED_ARGS_INSTALL_LIBS}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so.debuggable - DESTINATION lib + DESTINATION lib ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so.signed - DESTINATION lib + DESTINATION lib ) endif() endif() @@ -113,7 +113,7 @@ function(add_ccf_app name) add_warning_checks(${enc_name}) target_link_libraries( ${enc_name} PRIVATE ${PARSED_ARGS_LINK_LIBS_ENCLAVE} - ${OE_TARGET_ENCLAVE_CORE_LIBS} ccf.enclave + ${OE_TARGET_ENCLAVE_CORE_LIBS} ccf.enclave ) set_property(TARGET ${enc_name} PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -227,7 +227,9 @@ if(COMPILE_TARGET STREQUAL "sgx") add_library(${name} ${files}) target_compile_options(${name} PUBLIC -nostdinc -nostdinc++) target_compile_definitions( - ${name} PUBLIC INSIDE_ENCLAVE _LIBCPP_HAS_THREAD_API_PTHREAD OPENSSL_API_COMPAT=0x10101000L + ${name} PUBLIC INSIDE_ENCLAVE _LIBCPP_HAS_THREAD_API_PTHREAD + + # OPENSSL_API_COMPAT=0x10101000L ) target_link_libraries(${name} PUBLIC ${OE_TARGET_ENCLAVE_AND_STD} -lgcc) set_property(TARGET ${name} PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/cmake/common.cmake b/cmake/common.cmake index 148c9560fb00..2921a974db4f 100644 --- a/cmake/common.cmake +++ b/cmake/common.cmake @@ -10,7 +10,7 @@ function(add_unit_test name) ) enable_coverage(${name}) target_link_libraries(${name} PRIVATE ${LINK_LIBCXX} ccfcrypto.host -pthread) - link_openenclave_host(${name}) + # link_openenclave_host(${name}) add_san(${name}) add_test(NAME ${name} COMMAND ${name}) diff --git a/cmake/crypto.cmake b/cmake/crypto.cmake index b3a6409f7fde..0ef271bcbdf6 100644 --- a/cmake/crypto.cmake +++ b/cmake/crypto.cmake @@ -2,28 +2,28 @@ # Licensed under the Apache 2.0 License. set(CCFCRYPTO_SRC - ${CCF_DIR}/src/crypto/base64.cpp - ${CCF_DIR}/src/crypto/entropy.cpp - ${CCF_DIR}/src/crypto/hash.cpp - ${CCF_DIR}/src/crypto/sha256_hash.cpp - ${CCF_DIR}/src/crypto/symmetric_key.cpp - ${CCF_DIR}/src/crypto/key_pair.cpp - ${CCF_DIR}/src/crypto/eddsa_key_pair.cpp - ${CCF_DIR}/src/crypto/rsa_key_pair.cpp - ${CCF_DIR}/src/crypto/verifier.cpp - ${CCF_DIR}/src/crypto/key_wrap.cpp - ${CCF_DIR}/src/crypto/hmac.cpp - ${CCF_DIR}/src/crypto/ecdsa.cpp - ${CCF_DIR}/src/crypto/openssl/symmetric_key.cpp - ${CCF_DIR}/src/crypto/openssl/public_key.cpp - ${CCF_DIR}/src/crypto/openssl/key_pair.cpp - ${CCF_DIR}/src/crypto/openssl/eddsa_public_key.cpp - ${CCF_DIR}/src/crypto/openssl/eddsa_key_pair.cpp - ${CCF_DIR}/src/crypto/openssl/hash.cpp - ${CCF_DIR}/src/crypto/openssl/rsa_public_key.cpp - ${CCF_DIR}/src/crypto/openssl/rsa_key_pair.cpp - ${CCF_DIR}/src/crypto/openssl/verifier.cpp - ${CCF_DIR}/src/crypto/openssl/cose_verifier.cpp + ${CCF_DIR}/src/crypto/base64.cpp + ${CCF_DIR}/src/crypto/entropy.cpp + ${CCF_DIR}/src/crypto/hash.cpp + ${CCF_DIR}/src/crypto/sha256_hash.cpp + ${CCF_DIR}/src/crypto/symmetric_key.cpp + ${CCF_DIR}/src/crypto/key_pair.cpp + ${CCF_DIR}/src/crypto/eddsa_key_pair.cpp + ${CCF_DIR}/src/crypto/rsa_key_pair.cpp + ${CCF_DIR}/src/crypto/verifier.cpp + ${CCF_DIR}/src/crypto/key_wrap.cpp + ${CCF_DIR}/src/crypto/hmac.cpp + ${CCF_DIR}/src/crypto/ecdsa.cpp + ${CCF_DIR}/src/crypto/openssl/symmetric_key.cpp + ${CCF_DIR}/src/crypto/openssl/public_key.cpp + ${CCF_DIR}/src/crypto/openssl/key_pair.cpp + ${CCF_DIR}/src/crypto/openssl/eddsa_public_key.cpp + ${CCF_DIR}/src/crypto/openssl/eddsa_key_pair.cpp + ${CCF_DIR}/src/crypto/openssl/hash.cpp + ${CCF_DIR}/src/crypto/openssl/rsa_public_key.cpp + ${CCF_DIR}/src/crypto/openssl/rsa_key_pair.cpp + ${CCF_DIR}/src/crypto/openssl/verifier.cpp + ${CCF_DIR}/src/crypto/openssl/cose_verifier.cpp ) if(COMPILE_TARGET STREQUAL "sgx") @@ -54,14 +54,25 @@ elseif(COMPILE_TARGET STREQUAL "snp") ) endif() +set(OPENSSL_INSTALL_PATH "/opt/openssl") + +find_library(CRYPTO_LIBRARY crypto HINTS "${OPENSSL_INSTALL_PATH}/lib64") +find_library(TLS_LIBRARY ssl HINTS "${OPENSSL_INSTALL_PATH}/lib64") + add_library(ccfcrypto.host STATIC ${CCFCRYPTO_SRC}) add_san(ccfcrypto.host) target_compile_options(ccfcrypto.host PUBLIC ${COMPILE_LIBCXX}) +target_compile_definitions(ccfcrypto.host PUBLIC OPENSSL_API_COMPAT=0x10101000L) target_link_options(ccfcrypto.host PUBLIC ${LINK_LIBCXX}) +target_include_directories(ccfcrypto.host PRIVATE "${OPENSSL_INSTALL_PATH}/include") + target_link_libraries(ccfcrypto.host PUBLIC qcbor.host) target_link_libraries(ccfcrypto.host PUBLIC t_cose.host) -target_link_libraries(ccfcrypto.host PUBLIC crypto) -target_link_libraries(ccfcrypto.host PUBLIC ssl) + +# target_link_libraries(ccfcrypto.host PUBLIC crypto) +# target_link_libraries(ccfcrypto.host PUBLIC ssl) +target_link_libraries(ccfcrypto.host PUBLIC "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") +target_link_libraries(ccfcrypto.host PUBLIC "${OPENSSL_INSTALL_PATH}/lib64/libssl.so") set_property(TARGET ccfcrypto.host PROPERTY POSITION_INDEPENDENT_CODE ON) if(INSTALL_VIRTUAL_LIBRARIES) diff --git a/cmake/t_cose.cmake b/cmake/t_cose.cmake index 11a252e53e16..636cde35d230 100644 --- a/cmake/t_cose.cmake +++ b/cmake/t_cose.cmake @@ -14,7 +14,9 @@ set(T_COSE_SRCS ) if(COMPILE_TARGET STREQUAL "sgx") add_enclave_library_c(t_cose.enclave ${T_COSE_SRCS}) - target_compile_definitions(t_cose.enclave PRIVATE ${T_COSE_DEFS} OPENSSL_API_COMPAT=0x10101000L) + target_compile_definitions( + t_cose.enclave PRIVATE ${T_COSE_DEFS} OPENSSL_API_COMPAT=0x10101000L + ) target_compile_options(t_cose.enclave INTERFACE ${T_COSE_OPTS_INTERFACE}) target_include_directories(t_cose.enclave PRIVATE "${T_COSE_SRC}") @@ -47,7 +49,7 @@ elseif(COMPILE_TARGET STREQUAL "snp") $ ) - target_link_libraries(t_cose.snp PUBLIC qcbor.snp crypto) + target_link_libraries(t_cose.snp PUBLIC qcbor.snp "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") set_property(TARGET t_cose.snp PROPERTY POSITION_INDEPENDENT_CODE ON) add_san(t_cose.snp) @@ -70,7 +72,7 @@ target_include_directories( $ ) -target_link_libraries(t_cose.host PUBLIC qcbor.host crypto) +target_link_libraries(t_cose.host PUBLIC qcbor.host "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") set_property(TARGET t_cose.host PROPERTY POSITION_INDEPENDENT_CODE ON) add_san(t_cose.host) diff --git a/src/crypto/openssl/openssl_wrappers.h b/src/crypto/openssl/openssl_wrappers.h index c6bcbbb9adb7..53d9a9eb7da0 100644 --- a/src/crypto/openssl/openssl_wrappers.h +++ b/src/crypto/openssl/openssl_wrappers.h @@ -10,11 +10,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include From 27d0e7daf32891b3c67fddc8a2bce3897c258451 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Wed, 12 Jul 2023 08:11:41 +0000 Subject: [PATCH 06/57] . --- src/crypto/openssl/public_key.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crypto/openssl/public_key.cpp b/src/crypto/openssl/public_key.cpp index 265eae3d8144..204b1a0ef598 100644 --- a/src/crypto/openssl/public_key.cpp +++ b/src/crypto/openssl/public_key.cpp @@ -82,8 +82,7 @@ namespace crypto CurveID PublicKey_OpenSSL::get_curve_id() const { - int nid = - EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(key))); + int nid = get_openssl_group_id(); switch (nid) { case NID_secp384r1: @@ -100,6 +99,7 @@ namespace crypto int PublicKey_OpenSSL::get_openssl_group_id() const { + // return EVP_PKEY_get_id(key); return EC_GROUP_get_curve_name( EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(key))); } From b3870eca67ffe1c0ecd512aae12ae23a54769652 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Wed, 12 Jul 2023 13:27:57 +0000 Subject: [PATCH 07/57] Remove use of `EVP_PKEY_get0_RSA` --- cmake/crypto.cmake | 2 +- src/crypto/openssl/cose_verifier.cpp | 2 +- src/crypto/openssl/public_key.cpp | 26 +++++++++++++++++++++++++- src/crypto/openssl/verifier.cpp | 5 +++-- 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/cmake/crypto.cmake b/cmake/crypto.cmake index 0ef271bcbdf6..3cde83a5fee7 100644 --- a/cmake/crypto.cmake +++ b/cmake/crypto.cmake @@ -62,7 +62,7 @@ find_library(TLS_LIBRARY ssl HINTS "${OPENSSL_INSTALL_PATH}/lib64") add_library(ccfcrypto.host STATIC ${CCFCRYPTO_SRC}) add_san(ccfcrypto.host) target_compile_options(ccfcrypto.host PUBLIC ${COMPILE_LIBCXX}) -target_compile_definitions(ccfcrypto.host PUBLIC OPENSSL_API_COMPAT=0x10101000L) +# target_compile_definitions(ccfcrypto.host PUBLIC OPENSSL_API_COMPAT=0x10101000L) target_link_options(ccfcrypto.host PUBLIC ${LINK_LIBCXX}) target_include_directories(ccfcrypto.host PRIVATE "${OPENSSL_INSTALL_PATH}/include") diff --git a/src/crypto/openssl/cose_verifier.cpp b/src/crypto/openssl/cose_verifier.cpp index 662295544929..cd664be67be8 100644 --- a/src/crypto/openssl/cose_verifier.cpp +++ b/src/crypto/openssl/cose_verifier.cpp @@ -39,7 +39,7 @@ namespace crypto EVP_PKEY* pk = X509_get_pubkey(cert); - if (EVP_PKEY_get0_EC_KEY(pk)) + if (EVP_PKEY_get_base_id(pk) == EVP_PKEY_EC) { public_key = std::make_shared(pk); } diff --git a/src/crypto/openssl/public_key.cpp b/src/crypto/openssl/public_key.cpp index 204b1a0ef598..a28e86b68add 100644 --- a/src/crypto/openssl/public_key.cpp +++ b/src/crypto/openssl/public_key.cpp @@ -99,9 +99,33 @@ namespace crypto int PublicKey_OpenSSL::get_openssl_group_id() const { - // return EVP_PKEY_get_id(key); +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + size_t gname_len = 0; + CHECK1(EVP_PKEY_get_group_name(key, nullptr, 0, &gname_len)); + std::string gname(gname_len + 1, 0); + CHECK1(EVP_PKEY_get_group_name( + key, (char*)gname.data(), gname.size(), &gname_len)); + gname.resize(gname_len); + if (gname == SN_secp384r1) + { + return NID_secp384r1; + } + else if (gname == SN_X9_62_prime256v1) + { + return NID_X9_62_prime256v1; + } + else if (gname == SN_secp256k1) + { + return NID_secp256k1; + } + else + { + throw std::runtime_error(fmt::format("Unknown OpenSSL group {}", gname)); + } +#else return EC_GROUP_get_curve_name( EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(key))); +#endif } int PublicKey_OpenSSL::get_openssl_group_id(CurveID gid) diff --git a/src/crypto/openssl/verifier.cpp b/src/crypto/openssl/verifier.cpp index acc9ca88db43..4af7090bbaf8 100644 --- a/src/crypto/openssl/verifier.cpp +++ b/src/crypto/openssl/verifier.cpp @@ -56,11 +56,12 @@ namespace crypto EVP_PKEY* pk = X509_get_pubkey(cert); - if (EVP_PKEY_get0_EC_KEY(pk)) + auto base_id = EVP_PKEY_get_base_id(pk); + if (base_id == EVP_PKEY_EC) { public_key = std::make_unique(pk); } - else if (EVP_PKEY_get0_RSA(pk)) + else if (base_id == EVP_PKEY_RSA) { public_key = std::make_unique(pk); } From 790d2c2aea7863ac5ecd58dcbed2f2d5ee0107c9 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Wed, 12 Jul 2023 15:51:23 +0000 Subject: [PATCH 08/57] JWK conversions --- cmake/ccf_app.cmake | 2 +- cmake/crypto.cmake | 16 +- cmake/t_cose.cmake | 4 +- src/crypto/openssl/cose_verifier.cpp | 5 + src/crypto/openssl/openssl_wrappers.h | 2 + src/crypto/openssl/rsa_key_pair.cpp | 41 +- src/crypto/openssl/rsa_public_key.cpp | 35 +- src/crypto/openssl/rsa_public_key.h | 1 + src/crypto/openssl/verifier.cpp | 4 + src/crypto/test/crypto.cpp | 9 + tests/js-modules/modules.py | 918 +++++++++++++------------- 11 files changed, 552 insertions(+), 485 deletions(-) diff --git a/cmake/ccf_app.cmake b/cmake/ccf_app.cmake index b871002d919e..6ac62cacf3b9 100644 --- a/cmake/ccf_app.cmake +++ b/cmake/ccf_app.cmake @@ -229,7 +229,7 @@ if(COMPILE_TARGET STREQUAL "sgx") target_compile_definitions( ${name} PUBLIC INSIDE_ENCLAVE _LIBCPP_HAS_THREAD_API_PTHREAD - # OPENSSL_API_COMPAT=0x10101000L + OPENSSL_API_COMPAT=0x10101000L ) target_link_libraries(${name} PUBLIC ${OE_TARGET_ENCLAVE_AND_STD} -lgcc) set_property(TARGET ${name} PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/cmake/crypto.cmake b/cmake/crypto.cmake index 3cde83a5fee7..ec67d9dc9b64 100644 --- a/cmake/crypto.cmake +++ b/cmake/crypto.cmake @@ -54,25 +54,25 @@ elseif(COMPILE_TARGET STREQUAL "snp") ) endif() -set(OPENSSL_INSTALL_PATH "/opt/openssl") +# set(OPENSSL_INSTALL_PATH "/opt/openssl") -find_library(CRYPTO_LIBRARY crypto HINTS "${OPENSSL_INSTALL_PATH}/lib64") -find_library(TLS_LIBRARY ssl HINTS "${OPENSSL_INSTALL_PATH}/lib64") +find_library(CRYPTO_LIBRARY crypto)# HINTS "${OPENSSL_INSTALL_PATH}/lib64") +find_library(TLS_LIBRARY ssl)#HINTS "${OPENSSL_INSTALL_PATH}/lib64") add_library(ccfcrypto.host STATIC ${CCFCRYPTO_SRC}) add_san(ccfcrypto.host) target_compile_options(ccfcrypto.host PUBLIC ${COMPILE_LIBCXX}) # target_compile_definitions(ccfcrypto.host PUBLIC OPENSSL_API_COMPAT=0x10101000L) target_link_options(ccfcrypto.host PUBLIC ${LINK_LIBCXX}) -target_include_directories(ccfcrypto.host PRIVATE "${OPENSSL_INSTALL_PATH}/include") +# target_include_directories(ccfcrypto.host PRIVATE "${OPENSSL_INSTALL_PATH}/include") target_link_libraries(ccfcrypto.host PUBLIC qcbor.host) target_link_libraries(ccfcrypto.host PUBLIC t_cose.host) -# target_link_libraries(ccfcrypto.host PUBLIC crypto) -# target_link_libraries(ccfcrypto.host PUBLIC ssl) -target_link_libraries(ccfcrypto.host PUBLIC "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") -target_link_libraries(ccfcrypto.host PUBLIC "${OPENSSL_INSTALL_PATH}/lib64/libssl.so") +target_link_libraries(ccfcrypto.host PUBLIC crypto) +target_link_libraries(ccfcrypto.host PUBLIC ssl) +# target_link_libraries(ccfcrypto.host PUBLIC "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") +# target_link_libraries(ccfcrypto.host PUBLIC "${OPENSSL_INSTALL_PATH}/lib64/libssl.so") set_property(TARGET ccfcrypto.host PROPERTY POSITION_INDEPENDENT_CODE ON) if(INSTALL_VIRTUAL_LIBRARIES) diff --git a/cmake/t_cose.cmake b/cmake/t_cose.cmake index 636cde35d230..057c8d21f5cc 100644 --- a/cmake/t_cose.cmake +++ b/cmake/t_cose.cmake @@ -49,7 +49,7 @@ elseif(COMPILE_TARGET STREQUAL "snp") $ ) - target_link_libraries(t_cose.snp PUBLIC qcbor.snp "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") + target_link_libraries(t_cose.snp PUBLIC qcbor.snp)# "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") set_property(TARGET t_cose.snp PROPERTY POSITION_INDEPENDENT_CODE ON) add_san(t_cose.snp) @@ -72,7 +72,7 @@ target_include_directories( $ ) -target_link_libraries(t_cose.host PUBLIC qcbor.host "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") +target_link_libraries(t_cose.host PUBLIC qcbor.host)# "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") set_property(TARGET t_cose.host PROPERTY POSITION_INDEPENDENT_CODE ON) add_san(t_cose.host) diff --git a/src/crypto/openssl/cose_verifier.cpp b/src/crypto/openssl/cose_verifier.cpp index cd664be67be8..3d4c2d57df00 100644 --- a/src/crypto/openssl/cose_verifier.cpp +++ b/src/crypto/openssl/cose_verifier.cpp @@ -39,6 +39,8 @@ namespace crypto EVP_PKEY* pk = X509_get_pubkey(cert); + // TODO: Get it working with OpenSSL 1.x +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 if (EVP_PKEY_get_base_id(pk) == EVP_PKEY_EC) { public_key = std::make_shared(pk); @@ -47,6 +49,9 @@ namespace crypto { throw std::logic_error("unsupported public key type"); } +#else + +#endif } COSEVerifier_OpenSSL::COSEVerifier_OpenSSL(const RSAPublicKeyPtr& pubk_ptr) diff --git a/src/crypto/openssl/openssl_wrappers.h b/src/crypto/openssl/openssl_wrappers.h index 53d9a9eb7da0..1276f8b7cb55 100644 --- a/src/crypto/openssl/openssl_wrappers.h +++ b/src/crypto/openssl/openssl_wrappers.h @@ -311,6 +311,8 @@ namespace crypto struct Unique_BIGNUM : public Unique_SSL_OBJECT { using Unique_SSL_OBJECT::Unique_SSL_OBJECT; + + Unique_BIGNUM(const BIGNUM* n) : Unique_BIGNUM(BN_dup(n), BN_free) {} }; struct Unique_X509_TIME diff --git a/src/crypto/openssl/rsa_key_pair.cpp b/src/crypto/openssl/rsa_key_pair.cpp index 903115d53788..9cfbf0662a79 100644 --- a/src/crypto/openssl/rsa_key_pair.cpp +++ b/src/crypto/openssl/rsa_key_pair.cpp @@ -6,6 +6,10 @@ #include "crypto/openssl/hash.h" #include "openssl_wrappers.h" +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 +# include +#endif + namespace crypto { using namespace OpenSSL; @@ -177,24 +181,37 @@ namespace crypto { JsonWebKeyRSAPrivate jwk = {RSAPublicKey_OpenSSL::public_key_jwk_rsa(kid)}; + Unique_BIGNUM d, p, q, dp, dq, qi; + +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + d = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_D); + p = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_FACTOR1); + q = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_FACTOR2); + dp = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_EXPONENT1); + dq = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_EXPONENT2); + qi = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_COEFFICIENT1); + +#else const RSA* rsa = EVP_PKEY_get0_RSA(key); if (!rsa) { throw std::logic_error("invalid RSA key"); } - jwk.d = - b64url_from_raw(RSAPublicKey_OpenSSL::bn_bytes(RSA_get0_d(rsa)), false); - jwk.p = - b64url_from_raw(RSAPublicKey_OpenSSL::bn_bytes(RSA_get0_p(rsa)), false); - jwk.q = - b64url_from_raw(RSAPublicKey_OpenSSL::bn_bytes(RSA_get0_q(rsa)), false); - jwk.dp = b64url_from_raw( - RSAPublicKey_OpenSSL::bn_bytes(RSA_get0_dmp1(rsa)), false); - jwk.dq = b64url_from_raw( - RSAPublicKey_OpenSSL::bn_bytes(RSA_get0_dmq1(rsa)), false); - jwk.qi = b64url_from_raw( - RSAPublicKey_OpenSSL::bn_bytes(RSA_get0_iqmp(rsa)), false); + d = RSA_get0_d(rsa); + p = RSA_get0_p(rsa); + q = RSA_get0_q(rsa); + dp = RSA_get0_dmp1(rsa); + dq = RSA_get0_dmq1(rsa); + qi = RSA_get0_iqmp(rsa); +#endif + + jwk.d = b64url_from_raw(RSAPublicKey_OpenSSL::bn_bytes(d), false); + jwk.p = b64url_from_raw(RSAPublicKey_OpenSSL::bn_bytes(p), false); + jwk.q = b64url_from_raw(RSAPublicKey_OpenSSL::bn_bytes(q), false); + jwk.dp = b64url_from_raw(RSAPublicKey_OpenSSL::bn_bytes(dp), false); + jwk.dq = b64url_from_raw(RSAPublicKey_OpenSSL::bn_bytes(dq), false); + jwk.qi = b64url_from_raw(RSAPublicKey_OpenSSL::bn_bytes(qi), false); return jwk; } diff --git a/src/crypto/openssl/rsa_public_key.cpp b/src/crypto/openssl/rsa_public_key.cpp index 926986bdab41..9d48f200db09 100644 --- a/src/crypto/openssl/rsa_public_key.cpp +++ b/src/crypto/openssl/rsa_public_key.cpp @@ -5,26 +5,37 @@ #include "crypto/openssl/rsa_key_pair.h" #include "openssl_wrappers.h" +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 +# include +#endif + namespace crypto { using namespace OpenSSL; RSAPublicKey_OpenSSL::RSAPublicKey_OpenSSL(EVP_PKEY* c) : PublicKey_OpenSSL(c) { - if (!EVP_PKEY_get0_RSA(key)) +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + if (EVP_PKEY_get_base_id(key) != EVP_PKEY_RSA) { throw std::logic_error("invalid RSA key"); } +#else + +#endif } RSAPublicKey_OpenSSL::RSAPublicKey_OpenSSL(const Pem& pem) { Unique_BIO mem(pem); key = PEM_read_bio_PUBKEY(mem, NULL, NULL, NULL); - if (!key || !EVP_PKEY_get0_RSA(key)) +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + if (!key || EVP_PKEY_get_base_id(key) != EVP_PKEY_RSA) { throw std::logic_error("invalid RSA key"); } +#else +#endif } RSAPublicKey_OpenSSL::RSAPublicKey_OpenSSL(const std::vector& der) @@ -166,17 +177,35 @@ namespace crypto return r; } +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + Unique_BIGNUM RSAPublicKey_OpenSSL::get_bn_param(const char* key_name) const + { + BIGNUM* bn = NULL; + CHECK1(EVP_PKEY_get_bn_param(key, key_name, &bn)); + Unique_BIGNUM r(bn); + BN_free(bn); + LOG_FAIL_FMT("get_bn_param: {}", key_name); + return r; + } +#endif + RSAPublicKey::Components RSAPublicKey_OpenSSL::components() const { + Components r; +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + r.n = bn_bytes(get_bn_param(OSSL_PKEY_PARAM_RSA_N)); + r.e = bn_bytes(get_bn_param(OSSL_PKEY_PARAM_RSA_E)); + +#else const RSA* rsa = EVP_PKEY_get0_RSA(key); if (!rsa) { throw std::logic_error("invalid RSA key"); } - Components r; r.n = bn_bytes(RSA_get0_n(rsa)); r.e = bn_bytes(RSA_get0_e(rsa)); +#endif return r; } diff --git a/src/crypto/openssl/rsa_public_key.h b/src/crypto/openssl/rsa_public_key.h index 063a5725bd94..06405296d257 100644 --- a/src/crypto/openssl/rsa_public_key.h +++ b/src/crypto/openssl/rsa_public_key.h @@ -52,6 +52,7 @@ namespace crypto virtual Components components() const override; static std::vector bn_bytes(const BIGNUM* bn); + OpenSSL::Unique_BIGNUM get_bn_param(const char* key_name) const; virtual JsonWebKeyRSAPublic public_key_jwk_rsa( const std::optional& kid = std::nullopt) const override; diff --git a/src/crypto/openssl/verifier.cpp b/src/crypto/openssl/verifier.cpp index 4af7090bbaf8..b2dfa4763c0a 100644 --- a/src/crypto/openssl/verifier.cpp +++ b/src/crypto/openssl/verifier.cpp @@ -56,6 +56,7 @@ namespace crypto EVP_PKEY* pk = X509_get_pubkey(cert); +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 auto base_id = EVP_PKEY_get_base_id(pk); if (base_id == EVP_PKEY_EC) { @@ -69,6 +70,9 @@ namespace crypto { throw std::logic_error("unsupported public key type"); } +#else + +#endif } Verifier_OpenSSL::~Verifier_OpenSSL() {} diff --git a/src/crypto/test/crypto.cpp b/src/crypto/test/crypto.cpp index edf346aeca34..e35b6e58e2a7 100644 --- a/src/crypto/test/crypto.cpp +++ b/src/crypto/test/crypto.cpp @@ -783,6 +783,8 @@ TEST_CASE("PEM to JWK and back") // to compare with JWK reference implementation. auto kid = "my_kid"; + logger::config::default_init(); + INFO("EC"); { auto curves = {CurveID::SECP384R1, CurveID::SECP256R1, CurveID::SECP256K1}; @@ -823,6 +825,9 @@ TEST_CASE("PEM to JWK and back") auto kp = make_rsa_key_pair(); auto pubk = make_rsa_public_key(kp->public_key_pem()); + LOG_FAIL_FMT("PEM: {}", kp->public_key_pem().str()); + LOG_FAIL_FMT("PEM (priv): {}", kp->private_key_pem().str()); + INFO("Public"); { auto jwk = pubk->public_key_jwk_rsa(); @@ -833,6 +838,8 @@ TEST_CASE("PEM to JWK and back") auto pubk2 = make_rsa_public_key(jwk); auto jwk2 = pubk2->public_key_jwk_rsa(kid); REQUIRE(jwk == jwk2); + + LOG_FAIL_FMT("JWK: {}", nlohmann::json(jwk).dump()); } INFO("Private"); @@ -845,6 +852,8 @@ TEST_CASE("PEM to JWK and back") auto kp2 = make_rsa_key_pair(jwk); auto jwk2 = kp2->private_key_jwk_rsa(kid); REQUIRE(jwk == jwk2); + + LOG_FAIL_FMT("JWK: {}", nlohmann::json(jwk).dump()); } } diff --git a/tests/js-modules/modules.py b/tests/js-modules/modules.py index b945956e8d05..f72b6a6cafe0 100644 --- a/tests/js-modules/modules.py +++ b/tests/js-modules/modules.py @@ -481,461 +481,461 @@ def test_npm_app(network, args): LOG.info("Calling npm app endpoints") with primary.client("user0") as c: - body = [1, 2, 3, 4] - r = c.post("/app/partition", body) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert r.body.json() == [[1, 3], [2, 4]], r.body - - r = c.post("/app/proto", body) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert r.headers["content-type"] == "application/x-protobuf" - # We could now decode the protobuf message but given all the machinery - # involved to make it happen (code generation with protoc) we'll leave it at that. - assert len(r.body) == 14, len(r.body) - - r = c.get("/app/crypto") - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert r.body.json()["available"], r.body - - key_size = 256 - r = c.post("/app/generateAesKey", {"size": key_size}) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert len(r.body.data()) == key_size // 8 - assert r.body.data() != b"\x00" * (key_size // 8) - - r = c.post("/app/generateRsaKeyPair", {"size": 2048}) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert infra.crypto.check_key_pair_pem( - r.body.json()["privateKey"], r.body.json()["publicKey"] - ) - - r = c.post("/app/generateEcdsaKeyPair", {"curve": "secp256r1"}) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert infra.crypto.check_key_pair_pem( - r.body.json()["privateKey"], r.body.json()["publicKey"] - ) - - r = c.post("/app/generateEcdsaKeyPair", {"curve": "secp256k1"}) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert infra.crypto.check_key_pair_pem( - r.body.json()["privateKey"], r.body.json()["publicKey"] - ) - - r = c.post("/app/generateEcdsaKeyPair", {"curve": "secp384r1"}) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert infra.crypto.check_key_pair_pem( - r.body.json()["privateKey"], r.body.json()["publicKey"] - ) - - r = c.post("/app/generateEddsaKeyPair", {"curve": "curve25519"}) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert infra.crypto.check_key_pair_pem( - r.body.json()["privateKey"], r.body.json()["publicKey"] - ) - - aes_key_to_wrap = infra.crypto.generate_aes_key(256) - wrapping_key_priv_pem, wrapping_key_pub_pem = infra.crypto.generate_rsa_keypair( - 2048 - ) - label = "label42" - r = c.post( - "/app/wrapKey", - { - "key": b64encode(aes_key_to_wrap).decode(), - "wrappingKey": b64encode(bytes(wrapping_key_pub_pem, "ascii")).decode(), - "wrapAlgo": { - "name": "RSA-OAEP", - "label": b64encode(bytes(label, "ascii")).decode(), - }, - }, - ) - assert r.status_code == http.HTTPStatus.OK, r.status_code - unwrapped = infra.crypto.unwrap_key_rsa_oaep( - r.body.data(), wrapping_key_priv_pem, label.encode("ascii") - ) - assert unwrapped == aes_key_to_wrap - - aes_wrapping_key = infra.crypto.generate_aes_key(256) - r = c.post( - "/app/wrapKey", - { - "key": b64encode(aes_key_to_wrap).decode(), - "wrappingKey": b64encode(aes_wrapping_key).decode(), - "wrapAlgo": {"name": "AES-KWP"}, - }, - ) - assert r.status_code == http.HTTPStatus.OK, r.status_code - unwrapped = infra.crypto.unwrap_key_aes_pad(r.body.data(), aes_wrapping_key) - assert unwrapped == aes_key_to_wrap - - wrapping_key_priv_pem, wrapping_key_pub_pem = infra.crypto.generate_rsa_keypair( - 2048 - ) - label = "label44" - r = c.post( - "/app/wrapKey", - { - "key": b64encode(aes_key_to_wrap).decode(), - "wrappingKey": b64encode(bytes(wrapping_key_pub_pem, "ascii")).decode(), - "wrapAlgo": { - "name": "RSA-OAEP-AES-KWP", - "aesKeySize": 256, - "label": b64encode(bytes(label, "ascii")).decode(), - }, - }, - ) - assert r.status_code == http.HTTPStatus.OK, r.status_code - unwrapped = infra.crypto.unwrap_key_rsa_oaep_aes_pad( - r.body.data(), wrapping_key_priv_pem, label.encode("ascii") - ) - assert unwrapped == aes_key_to_wrap - - key_priv_pem, key_pub_pem = infra.crypto.generate_rsa_keypair(2048) - algorithm = {"name": "RSASSA-PKCS1-v1_5", "hash": "SHA-256"} - data = "foo".encode() - r = c.post( - "/app/sign", - { - "algorithm": algorithm, - "key": key_priv_pem, - "data": b64encode(data).decode(), - }, - ) - assert r.status_code == http.HTTPStatus.OK, r.status_code - - signature = r.body.data() - infra.crypto.verify_signature(algorithm, signature, data, key_pub_pem) - - # Also verify with the JS API - r = c.post( - "/app/verifySignature", - { - "algorithm": algorithm, - "key": key_pub_pem, - "signature": b64encode(signature).decode(), - "data": b64encode(data).decode(), - }, - ) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert r.body.json() is True, r.body - - try: - infra.crypto.verify_signature( - algorithm, signature, "bar".encode(), key_pub_pem - ) - assert False, "verify_signature() should throw" - except InvalidSignature: - pass - - curves = [ec.SECP256R1, ec.SECP256K1, ec.SECP384R1] - for curve in curves: - key_priv_pem, key_pub_pem = infra.crypto.generate_ec_keypair(curve) - algorithm = {"name": "ECDSA", "hash": "SHA-256"} - data = "foo".encode() - r = c.post( - "/app/sign", - { - "algorithm": algorithm, - "key": key_priv_pem, - "data": b64encode(data).decode(), - }, - ) - assert r.status_code == http.HTTPStatus.OK, r.status_code - - signature = r.body.data() - infra.crypto.verify_signature(algorithm, signature, data, key_pub_pem) - - # Also verify with the JS API - r = c.post( - "/app/verifySignature", - { - "algorithm": algorithm, - "key": key_pub_pem, - "signature": b64encode(signature).decode(), - "data": b64encode(data).decode(), - }, - ) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert r.body.json() is True, r.body - - try: - infra.crypto.verify_signature( - algorithm, signature, "bar".encode(), key_pub_pem - ) - assert False, "verify_signature() should throw" - except InvalidSignature: - pass - - key_priv_pem, key_pub_pem = infra.crypto.generate_eddsa_keypair() - algorithm = {"name": "EdDSA"} - data = "foo".encode() - r = c.post( - "/app/sign", - { - "algorithm": algorithm, - "key": key_priv_pem, - "data": b64encode(data).decode(), - }, - ) - assert r.status_code == http.HTTPStatus.OK, r.status_code - - signature = r.body.data() - infra.crypto.verify_signature(algorithm, signature, data, key_pub_pem) - - # Also verify with the JS API - r = c.post( - "/app/verifySignature", - { - "algorithm": algorithm, - "key": key_pub_pem, - "signature": b64encode(signature).decode(), - "data": b64encode(data).decode(), - }, - ) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert r.body.json() is True, r.body - - try: - infra.crypto.verify_signature( - algorithm, signature, "bar".encode(), key_pub_pem - ) - assert False, "verify_signature() should throw" - except InvalidSignature: - pass - - key_priv_pem, key_pub_pem = infra.crypto.generate_rsa_keypair(2048) - algorithm = {"name": "RSASSA-PKCS1-v1_5", "hash": "SHA-256"} - data = "foo".encode() - signature = infra.crypto.sign(algorithm, key_priv_pem, data) - r = c.post( - "/app/verifySignature", - { - "algorithm": algorithm, - "key": key_pub_pem, - "signature": b64encode(signature).decode(), - "data": b64encode(data).decode(), - }, - ) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert r.body.json() is True, r.body - - r = c.post( - "/app/verifySignature", - { - "algorithm": algorithm, - "key": key_pub_pem, - "signature": b64encode(signature).decode(), - "data": b64encode("bar".encode()).decode(), - }, - ) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert r.body.json() is False, r.body - - curves = [ec.SECP256R1, ec.SECP256K1, ec.SECP384R1] - for curve in curves: - key_priv_pem, key_pub_pem = infra.crypto.generate_ec_keypair(curve) - algorithm = {"name": "ECDSA", "hash": "SHA-256"} - data = "foo".encode() - signature = infra.crypto.sign(algorithm, key_priv_pem, data) - r = c.post( - "/app/verifySignature", - { - "algorithm": algorithm, - "key": key_pub_pem, - "signature": b64encode(signature).decode(), - "data": b64encode(data).decode(), - }, - ) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert r.body.json() is True, r.body - - key_priv_pem, key_pub_pem = infra.crypto.generate_eddsa_keypair() - algorithm = {"name": "EdDSA"} - data = "foo".encode() - signature = infra.crypto.sign(algorithm, key_priv_pem, data) - r = c.post( - "/app/verifySignature", - { - "algorithm": algorithm, - "key": key_pub_pem, - "signature": b64encode(signature).decode(), - "data": b64encode(data).decode(), - }, - ) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert r.body.json() is True, r.body - - r = c.post( - "/app/digest", - { - "algorithm": "SHA-256", - "data": b64encode(bytes("Hello world!", "ascii")).decode(), - }, - ) - assert r.status_code == http.HTTPStatus.OK, r.status_code - assert ( - r.body.text() - == "c0535e4be2b79ffd93291305436bf889314e4a3faec05ecffcbb7df31ad9e51a" - ), r.body - - r = c.get("/app/log?id=42") - assert r.status_code == http.HTTPStatus.NOT_FOUND, r.status_code - - r = c.post("/app/log?id=42", {"msg": "Hello!"}) - assert r.status_code == http.HTTPStatus.OK, r.status_code - - r = c.get("/app/log?id=42") - assert r.status_code == http.HTTPStatus.OK, r.status_code - body = r.body.json() - assert body["msg"] == "Hello!", r.body - - r = c.post("/app/log?id=42", {"msg": "Saluton!"}) - assert r.status_code == http.HTTPStatus.OK, r.status_code - r = c.post("/app/log?id=43", {"msg": "Bonjour!"}) - assert r.status_code == http.HTTPStatus.OK, r.status_code - - r = c.get("/app/log/all") - assert r.status_code == http.HTTPStatus.OK, r.status_code - body = r.body.json() - # Response is list in undefined order - assert len(body) == 2, body - assert {"id": 42, "msg": "Saluton!"} in body, body - assert {"id": 43, "msg": "Bonjour!"} in body, body - - test_apply_writes(c) - - r = c.get("/app/jwt") - assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code - body = r.body.json() - assert body["msg"] == "authorization header missing", r.body - - r = c.get("/app/jwt", headers={"authorization": "Bearer not-a-jwt"}) - assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code - body = r.body.json() - assert body["msg"].startswith("malformed jwt:"), r.body - - jwt_key_priv_pem, _ = infra.crypto.generate_rsa_keypair(2048) - jwt_cert_pem = infra.crypto.generate_cert(jwt_key_priv_pem) - - jwt_kid = "my_key_id" - jwt = infra.crypto.create_jwt({}, jwt_key_priv_pem, jwt_kid) - r = c.get("/app/jwt", headers={"authorization": "Bearer " + jwt}) - assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code - body = r.body.json() - assert body["msg"].startswith("token signing key not found"), r.body - - priv_key_pem, _ = infra.crypto.generate_rsa_keypair(2048) - pem = infra.crypto.generate_cert(priv_key_pem) - r = c.post("/app/isValidX509CertBundle", pem) - assert r.body.json(), r.body - r = c.post("/app/isValidX509CertBundle", pem + "\n" + pem) - assert r.body.json(), r.body - r = c.post("/app/isValidX509CertBundle", "garbage") - assert not r.body.json(), r.body - - priv_key_pem1, _ = infra.crypto.generate_rsa_keypair(2048) - pem1 = infra.crypto.generate_cert(priv_key_pem1, cn="1", ca=True) - priv_key_pem2, _ = infra.crypto.generate_rsa_keypair(2048) - pem2 = infra.crypto.generate_cert( - priv_key_pem2, - cn="2", - ca=True, - issuer_priv_key_pem=priv_key_pem1, - issuer_cn="1", - ) - priv_key_pem3, _ = infra.crypto.generate_rsa_keypair(2048) - pem3 = infra.crypto.generate_cert( - priv_key_pem3, cn="3", issuer_priv_key_pem=priv_key_pem2, issuer_cn="2" - ) - # validates chains with target being trusted directly - r = c.post("/app/isValidX509CertChain", {"chain": pem3, "trusted": pem3}) - assert r.body.json(), r.body - # validates chains without intermediates - r = c.post("/app/isValidX509CertChain", {"chain": pem2, "trusted": pem1}) - assert r.body.json(), r.body - # validates chains with intermediates - r = c.post( - "/app/isValidX509CertChain", {"chain": pem3 + "\n" + pem2, "trusted": pem1} - ) - assert r.body.json(), r.body - # validates partial chains (pem2 is an intermediate) - r = c.post("/app/isValidX509CertChain", {"chain": pem3, "trusted": pem2}) - assert r.body.json(), r.body - # fails to reach trust anchor - r = c.post("/app/isValidX509CertChain", {"chain": pem3, "trusted": pem1}) - assert not r.body.json(), r.body - - r = c.get("/node/quotes/self") - primary_quote_info = r.body.json() - if args.enclave_platform != "sgx": - LOG.info("Skipping /app/verifyOpenEnclaveEvidence test, non-sgx node") - else: - # See /opt/openenclave/include/openenclave/attestation/sgx/evidence.h - OE_FORMAT_UUID_SGX_ECDSA = "a3a21e87-1b4d-4014-b70a-a125d2fbcd8c" - r = c.post( - "/app/verifyOpenEnclaveEvidence", - { - "format": OE_FORMAT_UUID_SGX_ECDSA, - "evidence": primary_quote_info["raw"], - "endorsements": primary_quote_info["endorsements"], - }, - ) - assert r.status_code == http.HTTPStatus.OK, r.status_code - body = r.body.json() - assert body["claims"]["unique_id"] == primary_quote_info["mrenclave"], body - assert "sgx_report_data" in body["customClaims"], body - - # again but without endorsements - r = c.post( - "/app/verifyOpenEnclaveEvidence", - { - "format": OE_FORMAT_UUID_SGX_ECDSA, - "evidence": primary_quote_info["raw"], - }, - ) - assert r.status_code == http.HTTPStatus.OK, r.status_code - body = r.body.json() - assert body["claims"]["unique_id"] == primary_quote_info["mrenclave"], body - assert "sgx_report_data" in body["customClaims"], body - - validate_openapi(c) + # body = [1, 2, 3, 4] + # r = c.post("/app/partition", body) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert r.body.json() == [[1, 3], [2, 4]], r.body + + # r = c.post("/app/proto", body) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert r.headers["content-type"] == "application/x-protobuf" + # # We could now decode the protobuf message but given all the machinery + # # involved to make it happen (code generation with protoc) we'll leave it at that. + # assert len(r.body) == 14, len(r.body) + + # r = c.get("/app/crypto") + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert r.body.json()["available"], r.body + + # key_size = 256 + # r = c.post("/app/generateAesKey", {"size": key_size}) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert len(r.body.data()) == key_size // 8 + # assert r.body.data() != b"\x00" * (key_size // 8) + + # r = c.post("/app/generateRsaKeyPair", {"size": 2048}) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert infra.crypto.check_key_pair_pem( + # r.body.json()["privateKey"], r.body.json()["publicKey"] + # ) + + # r = c.post("/app/generateEcdsaKeyPair", {"curve": "secp256r1"}) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert infra.crypto.check_key_pair_pem( + # r.body.json()["privateKey"], r.body.json()["publicKey"] + # ) + + # r = c.post("/app/generateEcdsaKeyPair", {"curve": "secp256k1"}) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert infra.crypto.check_key_pair_pem( + # r.body.json()["privateKey"], r.body.json()["publicKey"] + # ) + + # r = c.post("/app/generateEcdsaKeyPair", {"curve": "secp384r1"}) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert infra.crypto.check_key_pair_pem( + # r.body.json()["privateKey"], r.body.json()["publicKey"] + # ) + + # r = c.post("/app/generateEddsaKeyPair", {"curve": "curve25519"}) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert infra.crypto.check_key_pair_pem( + # r.body.json()["privateKey"], r.body.json()["publicKey"] + # ) + + # aes_key_to_wrap = infra.crypto.generate_aes_key(256) + # wrapping_key_priv_pem, wrapping_key_pub_pem = infra.crypto.generate_rsa_keypair( + # 2048 + # ) + # label = "label42" + # r = c.post( + # "/app/wrapKey", + # { + # "key": b64encode(aes_key_to_wrap).decode(), + # "wrappingKey": b64encode(bytes(wrapping_key_pub_pem, "ascii")).decode(), + # "wrapAlgo": { + # "name": "RSA-OAEP", + # "label": b64encode(bytes(label, "ascii")).decode(), + # }, + # }, + # ) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # unwrapped = infra.crypto.unwrap_key_rsa_oaep( + # r.body.data(), wrapping_key_priv_pem, label.encode("ascii") + # ) + # assert unwrapped == aes_key_to_wrap + + # aes_wrapping_key = infra.crypto.generate_aes_key(256) + # r = c.post( + # "/app/wrapKey", + # { + # "key": b64encode(aes_key_to_wrap).decode(), + # "wrappingKey": b64encode(aes_wrapping_key).decode(), + # "wrapAlgo": {"name": "AES-KWP"}, + # }, + # ) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # unwrapped = infra.crypto.unwrap_key_aes_pad(r.body.data(), aes_wrapping_key) + # assert unwrapped == aes_key_to_wrap + + # wrapping_key_priv_pem, wrapping_key_pub_pem = infra.crypto.generate_rsa_keypair( + # 2048 + # ) + # label = "label44" + # r = c.post( + # "/app/wrapKey", + # { + # "key": b64encode(aes_key_to_wrap).decode(), + # "wrappingKey": b64encode(bytes(wrapping_key_pub_pem, "ascii")).decode(), + # "wrapAlgo": { + # "name": "RSA-OAEP-AES-KWP", + # "aesKeySize": 256, + # "label": b64encode(bytes(label, "ascii")).decode(), + # }, + # }, + # ) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # unwrapped = infra.crypto.unwrap_key_rsa_oaep_aes_pad( + # r.body.data(), wrapping_key_priv_pem, label.encode("ascii") + # ) + # assert unwrapped == aes_key_to_wrap + + # key_priv_pem, key_pub_pem = infra.crypto.generate_rsa_keypair(2048) + # algorithm = {"name": "RSASSA-PKCS1-v1_5", "hash": "SHA-256"} + # data = "foo".encode() + # r = c.post( + # "/app/sign", + # { + # "algorithm": algorithm, + # "key": key_priv_pem, + # "data": b64encode(data).decode(), + # }, + # ) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + + # signature = r.body.data() + # infra.crypto.verify_signature(algorithm, signature, data, key_pub_pem) + + # # Also verify with the JS API + # r = c.post( + # "/app/verifySignature", + # { + # "algorithm": algorithm, + # "key": key_pub_pem, + # "signature": b64encode(signature).decode(), + # "data": b64encode(data).decode(), + # }, + # ) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert r.body.json() is True, r.body + + # try: + # infra.crypto.verify_signature( + # algorithm, signature, "bar".encode(), key_pub_pem + # ) + # assert False, "verify_signature() should throw" + # except InvalidSignature: + # pass + + # curves = [ec.SECP256R1, ec.SECP256K1, ec.SECP384R1] + # for curve in curves: + # key_priv_pem, key_pub_pem = infra.crypto.generate_ec_keypair(curve) + # algorithm = {"name": "ECDSA", "hash": "SHA-256"} + # data = "foo".encode() + # r = c.post( + # "/app/sign", + # { + # "algorithm": algorithm, + # "key": key_priv_pem, + # "data": b64encode(data).decode(), + # }, + # ) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + + # signature = r.body.data() + # infra.crypto.verify_signature(algorithm, signature, data, key_pub_pem) + + # # Also verify with the JS API + # r = c.post( + # "/app/verifySignature", + # { + # "algorithm": algorithm, + # "key": key_pub_pem, + # "signature": b64encode(signature).decode(), + # "data": b64encode(data).decode(), + # }, + # ) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert r.body.json() is True, r.body + + # try: + # infra.crypto.verify_signature( + # algorithm, signature, "bar".encode(), key_pub_pem + # ) + # assert False, "verify_signature() should throw" + # except InvalidSignature: + # pass + + # key_priv_pem, key_pub_pem = infra.crypto.generate_eddsa_keypair() + # algorithm = {"name": "EdDSA"} + # data = "foo".encode() + # r = c.post( + # "/app/sign", + # { + # "algorithm": algorithm, + # "key": key_priv_pem, + # "data": b64encode(data).decode(), + # }, + # ) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + + # signature = r.body.data() + # infra.crypto.verify_signature(algorithm, signature, data, key_pub_pem) + + # # Also verify with the JS API + # r = c.post( + # "/app/verifySignature", + # { + # "algorithm": algorithm, + # "key": key_pub_pem, + # "signature": b64encode(signature).decode(), + # "data": b64encode(data).decode(), + # }, + # ) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert r.body.json() is True, r.body + + # try: + # infra.crypto.verify_signature( + # algorithm, signature, "bar".encode(), key_pub_pem + # ) + # assert False, "verify_signature() should throw" + # except InvalidSignature: + # pass + + # key_priv_pem, key_pub_pem = infra.crypto.generate_rsa_keypair(2048) + # algorithm = {"name": "RSASSA-PKCS1-v1_5", "hash": "SHA-256"} + # data = "foo".encode() + # signature = infra.crypto.sign(algorithm, key_priv_pem, data) + # r = c.post( + # "/app/verifySignature", + # { + # "algorithm": algorithm, + # "key": key_pub_pem, + # "signature": b64encode(signature).decode(), + # "data": b64encode(data).decode(), + # }, + # ) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert r.body.json() is True, r.body + + # r = c.post( + # "/app/verifySignature", + # { + # "algorithm": algorithm, + # "key": key_pub_pem, + # "signature": b64encode(signature).decode(), + # "data": b64encode("bar".encode()).decode(), + # }, + # ) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert r.body.json() is False, r.body + + # curves = [ec.SECP256R1, ec.SECP256K1, ec.SECP384R1] + # for curve in curves: + # key_priv_pem, key_pub_pem = infra.crypto.generate_ec_keypair(curve) + # algorithm = {"name": "ECDSA", "hash": "SHA-256"} + # data = "foo".encode() + # signature = infra.crypto.sign(algorithm, key_priv_pem, data) + # r = c.post( + # "/app/verifySignature", + # { + # "algorithm": algorithm, + # "key": key_pub_pem, + # "signature": b64encode(signature).decode(), + # "data": b64encode(data).decode(), + # }, + # ) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert r.body.json() is True, r.body + + # key_priv_pem, key_pub_pem = infra.crypto.generate_eddsa_keypair() + # algorithm = {"name": "EdDSA"} + # data = "foo".encode() + # signature = infra.crypto.sign(algorithm, key_priv_pem, data) + # r = c.post( + # "/app/verifySignature", + # { + # "algorithm": algorithm, + # "key": key_pub_pem, + # "signature": b64encode(signature).decode(), + # "data": b64encode(data).decode(), + # }, + # ) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert r.body.json() is True, r.body + + # r = c.post( + # "/app/digest", + # { + # "algorithm": "SHA-256", + # "data": b64encode(bytes("Hello world!", "ascii")).decode(), + # }, + # ) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # assert ( + # r.body.text() + # == "c0535e4be2b79ffd93291305436bf889314e4a3faec05ecffcbb7df31ad9e51a" + # ), r.body + + # r = c.get("/app/log?id=42") + # assert r.status_code == http.HTTPStatus.NOT_FOUND, r.status_code + + # r = c.post("/app/log?id=42", {"msg": "Hello!"}) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + + # r = c.get("/app/log?id=42") + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # body = r.body.json() + # assert body["msg"] == "Hello!", r.body + + # r = c.post("/app/log?id=42", {"msg": "Saluton!"}) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # r = c.post("/app/log?id=43", {"msg": "Bonjour!"}) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + + # r = c.get("/app/log/all") + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # body = r.body.json() + # # Response is list in undefined order + # assert len(body) == 2, body + # assert {"id": 42, "msg": "Saluton!"} in body, body + # assert {"id": 43, "msg": "Bonjour!"} in body, body + + # test_apply_writes(c) + + # r = c.get("/app/jwt") + # assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code + # body = r.body.json() + # assert body["msg"] == "authorization header missing", r.body + + # r = c.get("/app/jwt", headers={"authorization": "Bearer not-a-jwt"}) + # assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code + # body = r.body.json() + # assert body["msg"].startswith("malformed jwt:"), r.body + + # jwt_key_priv_pem, _ = infra.crypto.generate_rsa_keypair(2048) + # jwt_cert_pem = infra.crypto.generate_cert(jwt_key_priv_pem) + + # jwt_kid = "my_key_id" + # jwt = infra.crypto.create_jwt({}, jwt_key_priv_pem, jwt_kid) + # r = c.get("/app/jwt", headers={"authorization": "Bearer " + jwt}) + # assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code + # body = r.body.json() + # assert body["msg"].startswith("token signing key not found"), r.body + + # priv_key_pem, _ = infra.crypto.generate_rsa_keypair(2048) + # pem = infra.crypto.generate_cert(priv_key_pem) + # r = c.post("/app/isValidX509CertBundle", pem) + # assert r.body.json(), r.body + # r = c.post("/app/isValidX509CertBundle", pem + "\n" + pem) + # assert r.body.json(), r.body + # r = c.post("/app/isValidX509CertBundle", "garbage") + # assert not r.body.json(), r.body + + # priv_key_pem1, _ = infra.crypto.generate_rsa_keypair(2048) + # pem1 = infra.crypto.generate_cert(priv_key_pem1, cn="1", ca=True) + # priv_key_pem2, _ = infra.crypto.generate_rsa_keypair(2048) + # pem2 = infra.crypto.generate_cert( + # priv_key_pem2, + # cn="2", + # ca=True, + # issuer_priv_key_pem=priv_key_pem1, + # issuer_cn="1", + # ) + # priv_key_pem3, _ = infra.crypto.generate_rsa_keypair(2048) + # pem3 = infra.crypto.generate_cert( + # priv_key_pem3, cn="3", issuer_priv_key_pem=priv_key_pem2, issuer_cn="2" + # ) + # # validates chains with target being trusted directly + # r = c.post("/app/isValidX509CertChain", {"chain": pem3, "trusted": pem3}) + # assert r.body.json(), r.body + # # validates chains without intermediates + # r = c.post("/app/isValidX509CertChain", {"chain": pem2, "trusted": pem1}) + # assert r.body.json(), r.body + # # validates chains with intermediates + # r = c.post( + # "/app/isValidX509CertChain", {"chain": pem3 + "\n" + pem2, "trusted": pem1} + # ) + # assert r.body.json(), r.body + # # validates partial chains (pem2 is an intermediate) + # r = c.post("/app/isValidX509CertChain", {"chain": pem3, "trusted": pem2}) + # assert r.body.json(), r.body + # # fails to reach trust anchor + # r = c.post("/app/isValidX509CertChain", {"chain": pem3, "trusted": pem1}) + # assert not r.body.json(), r.body + + # r = c.get("/node/quotes/self") + # primary_quote_info = r.body.json() + # if args.enclave_platform != "sgx": + # LOG.info("Skipping /app/verifyOpenEnclaveEvidence test, non-sgx node") + # else: + # # See /opt/openenclave/include/openenclave/attestation/sgx/evidence.h + # OE_FORMAT_UUID_SGX_ECDSA = "a3a21e87-1b4d-4014-b70a-a125d2fbcd8c" + # r = c.post( + # "/app/verifyOpenEnclaveEvidence", + # { + # "format": OE_FORMAT_UUID_SGX_ECDSA, + # "evidence": primary_quote_info["raw"], + # "endorsements": primary_quote_info["endorsements"], + # }, + # ) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # body = r.body.json() + # assert body["claims"]["unique_id"] == primary_quote_info["mrenclave"], body + # assert "sgx_report_data" in body["customClaims"], body + + # # again but without endorsements + # r = c.post( + # "/app/verifyOpenEnclaveEvidence", + # { + # "format": OE_FORMAT_UUID_SGX_ECDSA, + # "evidence": primary_quote_info["raw"], + # }, + # ) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # body = r.body.json() + # assert body["claims"]["unique_id"] == primary_quote_info["mrenclave"], body + # assert "sgx_report_data" in body["customClaims"], body + + # validate_openapi(c) generate_and_verify_jwk(c) LOG.info("Store JWT signing keys") - issuer = "https://example.issuer" - with tempfile.NamedTemporaryFile(prefix="ccf", mode="w+") as metadata_fp: - jwt_cert_der = infra.crypto.cert_pem_to_der(jwt_cert_pem) - der_b64 = base64.b64encode(jwt_cert_der).decode("ascii") - data = { - "issuer": issuer, - "jwks": {"keys": [{"kty": "RSA", "kid": jwt_kid, "x5c": [der_b64]}]}, - } - json.dump(data, metadata_fp) - metadata_fp.flush() - network.consortium.set_jwt_issuer(primary, metadata_fp.name) - - LOG.info("Calling jwt endpoint after storing keys") - with primary.client("user0") as c: - jwt_mismatching_key_priv_pem, _ = infra.crypto.generate_rsa_keypair(2048) - jwt = infra.crypto.create_jwt({}, jwt_mismatching_key_priv_pem, jwt_kid) - r = c.get("/app/jwt", headers={"authorization": "Bearer " + jwt}) - assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code - body = r.body.json() - assert body["msg"] == "jwt validation failed", r.body - - jwt = infra.crypto.create_jwt({}, jwt_key_priv_pem, jwt_kid) - r = c.get("/app/jwt", headers={"authorization": "Bearer " + jwt}) - assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code - body = r.body.json() - assert body["msg"] == "jwt invalid, sub claim missing", r.body - - user_id = "user0" - jwt = infra.crypto.create_jwt({"sub": user_id}, jwt_key_priv_pem, jwt_kid) - r = c.get("/app/jwt", headers={"authorization": "Bearer " + jwt}) - assert r.status_code == http.HTTPStatus.OK, r.status_code - body = r.body.json() - assert body["userId"] == user_id, r.body + # issuer = "https://example.issuer" + # with tempfile.NamedTemporaryFile(prefix="ccf", mode="w+") as metadata_fp: + # jwt_cert_der = infra.crypto.cert_pem_to_der(jwt_cert_pem) + # der_b64 = base64.b64encode(jwt_cert_der).decode("ascii") + # data = { + # "issuer": issuer, + # "jwks": {"keys": [{"kty": "RSA", "kid": jwt_kid, "x5c": [der_b64]}]}, + # } + # json.dump(data, metadata_fp) + # metadata_fp.flush() + # network.consortium.set_jwt_issuer(primary, metadata_fp.name) + + # LOG.info("Calling jwt endpoint after storing keys") + # with primary.client("user0") as c: + # jwt_mismatching_key_priv_pem, _ = infra.crypto.generate_rsa_keypair(2048) + # jwt = infra.crypto.create_jwt({}, jwt_mismatching_key_priv_pem, jwt_kid) + # r = c.get("/app/jwt", headers={"authorization": "Bearer " + jwt}) + # assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code + # body = r.body.json() + # assert body["msg"] == "jwt validation failed", r.body + + # jwt = infra.crypto.create_jwt({}, jwt_key_priv_pem, jwt_kid) + # r = c.get("/app/jwt", headers={"authorization": "Bearer " + jwt}) + # assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code + # body = r.body.json() + # assert body["msg"] == "jwt invalid, sub claim missing", r.body + + # user_id = "user0" + # jwt = infra.crypto.create_jwt({"sub": user_id}, jwt_key_priv_pem, jwt_kid) + # r = c.get("/app/jwt", headers={"authorization": "Bearer " + jwt}) + # assert r.status_code == http.HTTPStatus.OK, r.status_code + # body = r.body.json() + # assert body["userId"] == user_id, r.body return network @@ -1105,15 +1105,15 @@ def run(args): args.nodes, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb ) as network: network.start_and_open(args) - network = test_module_import(network, args) - network = test_bytecode_cache(network, args) - network = test_app_bundle(network, args) - network = test_dynamic_endpoints(network, args) - network = test_set_js_runtime(network, args) + # network = test_module_import(network, args) + # network = test_bytecode_cache(network, args) + # network = test_app_bundle(network, args) + # network = test_dynamic_endpoints(network, args) + # network = test_set_js_runtime(network, args) network = test_npm_app(network, args) - network = test_js_execution_time(network, args) - network = test_js_exception_output(network, args) - network = test_user_cose_authentication(network, args) + # network = test_js_execution_time(network, args) + # network = test_js_exception_output(network, args) + # network = test_user_cose_authentication(network, args) if __name__ == "__main__": From cb9f5ee473c0de6926b02994276e3cbb22b476fa Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Thu, 13 Jul 2023 10:44:33 +0000 Subject: [PATCH 09/57] Fixes --- cmake/ccf_app.cmake | 2 +- cmake/open_enclave.cmake | 9 ++++++++- cmake/t_cose.cmake | 6 +++--- src/crypto/key_wrap.cpp | 1 + src/crypto/openssl/cose_verifier.cpp | 7 +++---- src/crypto/openssl/key_pair.cpp | 1 + src/crypto/openssl/rsa_public_key.cpp | 13 ++++++------- src/crypto/openssl/rsa_public_key.h | 3 +++ src/crypto/openssl/verifier.cpp | 13 ++++++++++--- 9 files changed, 36 insertions(+), 19 deletions(-) diff --git a/cmake/ccf_app.cmake b/cmake/ccf_app.cmake index 6ac62cacf3b9..b871002d919e 100644 --- a/cmake/ccf_app.cmake +++ b/cmake/ccf_app.cmake @@ -229,7 +229,7 @@ if(COMPILE_TARGET STREQUAL "sgx") target_compile_definitions( ${name} PUBLIC INSIDE_ENCLAVE _LIBCPP_HAS_THREAD_API_PTHREAD - OPENSSL_API_COMPAT=0x10101000L + # OPENSSL_API_COMPAT=0x10101000L ) target_link_libraries(${name} PUBLIC ${OE_TARGET_ENCLAVE_AND_STD} -lgcc) set_property(TARGET ${name} PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/cmake/open_enclave.cmake b/cmake/open_enclave.cmake index a6b4fae1aafa..f4a795bd1739 100644 --- a/cmake/open_enclave.cmake +++ b/cmake/open_enclave.cmake @@ -15,6 +15,13 @@ if(REQUIRE_OPENENCLAVE) # Find OpenEnclave package find_package(OpenEnclave 0.19.2 CONFIG REQUIRED) + option(USE_OPENSSL_3 "Use OpenSSL 3.x for Open Enclave builds" ON) + if(USE_OPENSSL_3) + set(OE_OPENSSL_LIBRARY openenclave::oecryptoopenssl_3) + else() + set(OE_OPENSSL_LIBRARY openenclave::oecryptoopenssl) + endif() + # As well as pulling in openenclave:: targets, this sets variables which can # be used for our edge cases (eg - for virtual libraries). These do not follow # the standard naming patterns, for example use OE_INCLUDEDIR rather than @@ -23,7 +30,7 @@ if(REQUIRE_OPENENCLAVE) set(OE_TARGET_LIBC openenclave::oelibc) set(OE_TARGET_ENCLAVE_AND_STD openenclave::oeenclave openenclave::oelibcxx openenclave::oelibc - openenclave::oecryptoopenssl_3 + ${OE_OPENSSL_LIBRARY} ) # These oe libraries must be linked in specific order diff --git a/cmake/t_cose.cmake b/cmake/t_cose.cmake index 057c8d21f5cc..0c11782bd63e 100644 --- a/cmake/t_cose.cmake +++ b/cmake/t_cose.cmake @@ -15,8 +15,8 @@ set(T_COSE_SRCS if(COMPILE_TARGET STREQUAL "sgx") add_enclave_library_c(t_cose.enclave ${T_COSE_SRCS}) target_compile_definitions( - t_cose.enclave PRIVATE ${T_COSE_DEFS} OPENSSL_API_COMPAT=0x10101000L - ) + t_cose.enclave PRIVATE ${T_COSE_DEFS})# OPENSSL_API_COMPAT=0x10101000L + #) target_compile_options(t_cose.enclave INTERFACE ${T_COSE_OPTS_INTERFACE}) target_include_directories(t_cose.enclave PRIVATE "${T_COSE_SRC}") @@ -28,7 +28,7 @@ if(COMPILE_TARGET STREQUAL "sgx") target_link_libraries(t_cose.enclave PUBLIC qcbor.enclave) # This is needed to get the OpenSSL includes from Open Enclave - target_link_libraries(t_cose.enclave PRIVATE openenclave::oecryptoopenssl_3) + target_link_libraries(t_cose.enclave PRIVATE ${OE_OPENSSL_LIBRARY}) install( TARGETS t_cose.enclave diff --git a/src/crypto/key_wrap.cpp b/src/crypto/key_wrap.cpp index b7c7b9963238..9868a96308ac 100644 --- a/src/crypto/key_wrap.cpp +++ b/src/crypto/key_wrap.cpp @@ -9,6 +9,7 @@ #include "openssl/symmetric_key.h" #include +#include #include #include diff --git a/src/crypto/openssl/cose_verifier.cpp b/src/crypto/openssl/cose_verifier.cpp index 3d4c2d57df00..5c5666655f3e 100644 --- a/src/crypto/openssl/cose_verifier.cpp +++ b/src/crypto/openssl/cose_verifier.cpp @@ -39,9 +39,11 @@ namespace crypto EVP_PKEY* pk = X509_get_pubkey(cert); - // TODO: Get it working with OpenSSL 1.x #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 if (EVP_PKEY_get_base_id(pk) == EVP_PKEY_EC) +#else + if (EVP_PKEY_get0_EC_KEY(pk)) +#endif { public_key = std::make_shared(pk); } @@ -49,9 +51,6 @@ namespace crypto { throw std::logic_error("unsupported public key type"); } -#else - -#endif } COSEVerifier_OpenSSL::COSEVerifier_OpenSSL(const RSAPublicKeyPtr& pubk_ptr) diff --git a/src/crypto/openssl/key_pair.cpp b/src/crypto/openssl/key_pair.cpp index fd509540927c..6ae6dfdeb58d 100644 --- a/src/crypto/openssl/key_pair.cpp +++ b/src/crypto/openssl/key_pair.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/src/crypto/openssl/rsa_public_key.cpp b/src/crypto/openssl/rsa_public_key.cpp index 9d48f200db09..3f8b42a7a65c 100644 --- a/src/crypto/openssl/rsa_public_key.cpp +++ b/src/crypto/openssl/rsa_public_key.cpp @@ -17,12 +17,12 @@ namespace crypto { #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 if (EVP_PKEY_get_base_id(key) != EVP_PKEY_RSA) +#else + if (!EVP_PKEY_get0_RSA(key)) +#endif { throw std::logic_error("invalid RSA key"); } -#else - -#endif } RSAPublicKey_OpenSSL::RSAPublicKey_OpenSSL(const Pem& pem) @@ -31,11 +31,12 @@ namespace crypto key = PEM_read_bio_PUBKEY(mem, NULL, NULL, NULL); #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 if (!key || EVP_PKEY_get_base_id(key) != EVP_PKEY_RSA) +#else + if (!key || !EVP_PKEY_get0_RSA(key)) +#endif { throw std::logic_error("invalid RSA key"); } -#else -#endif } RSAPublicKey_OpenSSL::RSAPublicKey_OpenSSL(const std::vector& der) @@ -184,7 +185,6 @@ namespace crypto CHECK1(EVP_PKEY_get_bn_param(key, key_name, &bn)); Unique_BIGNUM r(bn); BN_free(bn); - LOG_FAIL_FMT("get_bn_param: {}", key_name); return r; } #endif @@ -195,7 +195,6 @@ namespace crypto #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 r.n = bn_bytes(get_bn_param(OSSL_PKEY_PARAM_RSA_N)); r.e = bn_bytes(get_bn_param(OSSL_PKEY_PARAM_RSA_E)); - #else const RSA* rsa = EVP_PKEY_get0_RSA(key); if (!rsa) diff --git a/src/crypto/openssl/rsa_public_key.h b/src/crypto/openssl/rsa_public_key.h index 06405296d257..5db482c5ec06 100644 --- a/src/crypto/openssl/rsa_public_key.h +++ b/src/crypto/openssl/rsa_public_key.h @@ -52,7 +52,10 @@ namespace crypto virtual Components components() const override; static std::vector bn_bytes(const BIGNUM* bn); + +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 OpenSSL::Unique_BIGNUM get_bn_param(const char* key_name) const; +#endif virtual JsonWebKeyRSAPublic public_key_jwk_rsa( const std::optional& kid = std::nullopt) const override; diff --git a/src/crypto/openssl/verifier.cpp b/src/crypto/openssl/verifier.cpp index b2dfa4763c0a..b11a42d12455 100644 --- a/src/crypto/openssl/verifier.cpp +++ b/src/crypto/openssl/verifier.cpp @@ -66,13 +66,20 @@ namespace crypto { public_key = std::make_unique(pk); } +#else + if (EVP_PKEY_get0_EC_KEY(pk)) + { + public_key = std::make_unique(pk); + } + else if (EVP_PKEY_get0_RSA(pk)) + { + public_key = std::make_unique(pk); + } +#endif else { throw std::logic_error("unsupported public key type"); } -#else - -#endif } Verifier_OpenSSL::~Verifier_OpenSSL() {} From 8dc725586c2a4a2d5fbdfac5580c2997ee2bd8b0 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Thu, 13 Jul 2023 14:29:16 +0000 Subject: [PATCH 10/57] WIP --- cmake/crypto.cmake | 18 +++++++++--------- cmake/t_cose.cmake | 4 ++-- src/crypto/openssl/public_key.cpp | 28 ++++++++++++++++++++++++++-- src/crypto/openssl/rsa_key_pair.cpp | 1 - 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/cmake/crypto.cmake b/cmake/crypto.cmake index ec67d9dc9b64..562ac0d00c30 100644 --- a/cmake/crypto.cmake +++ b/cmake/crypto.cmake @@ -54,25 +54,25 @@ elseif(COMPILE_TARGET STREQUAL "snp") ) endif() -# set(OPENSSL_INSTALL_PATH "/opt/openssl") +set(OPENSSL_INSTALL_PATH "/opt/openssl") -find_library(CRYPTO_LIBRARY crypto)# HINTS "${OPENSSL_INSTALL_PATH}/lib64") -find_library(TLS_LIBRARY ssl)#HINTS "${OPENSSL_INSTALL_PATH}/lib64") +find_library(CRYPTO_LIBRARY crypto HINTS "${OPENSSL_INSTALL_PATH}/lib64") +find_library(TLS_LIBRARY ssl "${OPENSSL_INSTALL_PATH}/lib64") add_library(ccfcrypto.host STATIC ${CCFCRYPTO_SRC}) add_san(ccfcrypto.host) -target_compile_options(ccfcrypto.host PUBLIC ${COMPILE_LIBCXX}) +target_compile_options(ccfcrypto.host PUBLIC ${COMPILE_LIBCXX} "-Wno-deprecated-declarations") # target_compile_definitions(ccfcrypto.host PUBLIC OPENSSL_API_COMPAT=0x10101000L) target_link_options(ccfcrypto.host PUBLIC ${LINK_LIBCXX}) -# target_include_directories(ccfcrypto.host PRIVATE "${OPENSSL_INSTALL_PATH}/include") +target_include_directories(ccfcrypto.host PRIVATE "${OPENSSL_INSTALL_PATH}/include") target_link_libraries(ccfcrypto.host PUBLIC qcbor.host) target_link_libraries(ccfcrypto.host PUBLIC t_cose.host) -target_link_libraries(ccfcrypto.host PUBLIC crypto) -target_link_libraries(ccfcrypto.host PUBLIC ssl) -# target_link_libraries(ccfcrypto.host PUBLIC "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") -# target_link_libraries(ccfcrypto.host PUBLIC "${OPENSSL_INSTALL_PATH}/lib64/libssl.so") +# target_link_libraries(ccfcrypto.host PUBLIC crypto) +# target_link_libraries(ccfcrypto.host PUBLIC ssl) +target_link_libraries(ccfcrypto.host PUBLIC "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") +target_link_libraries(ccfcrypto.host PUBLIC "${OPENSSL_INSTALL_PATH}/lib64/libssl.so") set_property(TARGET ccfcrypto.host PROPERTY POSITION_INDEPENDENT_CODE ON) if(INSTALL_VIRTUAL_LIBRARIES) diff --git a/cmake/t_cose.cmake b/cmake/t_cose.cmake index 0c11782bd63e..b1fdcb4c1a7e 100644 --- a/cmake/t_cose.cmake +++ b/cmake/t_cose.cmake @@ -49,7 +49,7 @@ elseif(COMPILE_TARGET STREQUAL "snp") $ ) - target_link_libraries(t_cose.snp PUBLIC qcbor.snp)# "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") + target_link_libraries(t_cose.snp PUBLIC qcbor.snp "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") set_property(TARGET t_cose.snp PROPERTY POSITION_INDEPENDENT_CODE ON) add_san(t_cose.snp) @@ -72,7 +72,7 @@ target_include_directories( $ ) -target_link_libraries(t_cose.host PUBLIC qcbor.host)# "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") +target_link_libraries(t_cose.host PUBLIC qcbor.host "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") set_property(TARGET t_cose.host PROPERTY POSITION_INDEPENDENT_CODE ON) add_san(t_cose.host) diff --git a/src/crypto/openssl/public_key.cpp b/src/crypto/openssl/public_key.cpp index a28e86b68add..189024f3883e 100644 --- a/src/crypto/openssl/public_key.cpp +++ b/src/crypto/openssl/public_key.cpp @@ -18,6 +18,10 @@ #include #include +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 +# include +#endif + namespace crypto { using namespace OpenSSL; @@ -247,10 +251,30 @@ namespace crypto Unique_EC_POINT p(group); CHECK1(EC_POINT_oct2point(group, p, raw.data(), raw.size(), bn_ctx)); Unique_EC_KEY ec_key(nid); - CHECK1(EC_KEY_set_public_key(ec_key, p)); + +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + Unique_EVP_PKEY_CTX pkctx; + EVP_PKEY* pkey; + + OSSL_PARAM* params = nullptr; // TODO: Fill with public key + OSSL_PARAM_BLD* param_bld = nullptr; + param_bld = OSSL_PARAM_BLD_new(); + + // TODO: Also push group! + CHECK1(OSSL_PARAM_BLD_push_octet_string( + param_bld, "pub", raw.data(), raw.size())); + + params = OSSL_PARAM_BLD_to_param(param_bld); + + CHECK1(EVP_PKEY_fromdata_init(pkctx)); + CHECK1(EVP_PKEY_fromdata(pkctx, &pkey, EVP_PKEY_PUBLIC_KEY, params)); + Unique_PKEY pk; // TODO: Remove +#else Unique_PKEY pk; - CHECK1(EVP_PKEY_set1_EC_KEY(pk, ec_key)); + CHECK1(EC_KEY_set_public_key(ec_key, p)); // TODO: Deprecated + CHECK1(EVP_PKEY_set1_EC_KEY(pk, ec_key)); // TODO: Deprecated EVP_PKEY_up_ref(pk); +#endif return pk; } diff --git a/src/crypto/openssl/rsa_key_pair.cpp b/src/crypto/openssl/rsa_key_pair.cpp index 9cfbf0662a79..be0fcdd15759 100644 --- a/src/crypto/openssl/rsa_key_pair.cpp +++ b/src/crypto/openssl/rsa_key_pair.cpp @@ -190,7 +190,6 @@ namespace crypto dp = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_EXPONENT1); dq = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_EXPONENT2); qi = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_COEFFICIENT1); - #else const RSA* rsa = EVP_PKEY_get0_RSA(key); if (!rsa) From 4b8a7e6c5f17566fd7769d8ec2d7400c647a0296 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 14 Jul 2023 08:39:54 +0000 Subject: [PATCH 11/57] Very much WIP --- src/crypto/openssl/openssl_wrappers.h | 11 +++++++++++ src/crypto/openssl/public_key.cpp | 12 ++++++++++-- src/node/test/channels.cpp | 2 ++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/crypto/openssl/openssl_wrappers.h b/src/crypto/openssl/openssl_wrappers.h index 1276f8b7cb55..9ab690412e0c 100644 --- a/src/crypto/openssl/openssl_wrappers.h +++ b/src/crypto/openssl/openssl_wrappers.h @@ -5,6 +5,8 @@ #include "ccf/crypto/pem.h" #define FMT_HEADER_ONLY +#include "ccf/ds/logger.h" // TODO: Remove + #include #include #include @@ -55,6 +57,7 @@ namespace crypto unsigned long ec = ERR_get_error(); if (rc != 1 && ec != 0) { + LOG_FAIL_FMT("OpenSSL error: {}", error_string(ec)); throw std::runtime_error( fmt::format("OpenSSL error: {}", error_string(ec))); } @@ -195,6 +198,14 @@ namespace crypto Unique_SSL_OBJECT( PEM_read_bio_PUBKEY(mem, NULL, NULL, NULL), EVP_PKEY_free) {} + +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + Unique_PKEY(EVP_PKEY* pkey) : + Unique_SSL_OBJECT(EVP_PKEY_dup(pkey), EVP_PKEY_free) + { + LOG_FAIL_FMT("dup"); + } +#endif }; struct Unique_EVP_PKEY_CTX diff --git a/src/crypto/openssl/public_key.cpp b/src/crypto/openssl/public_key.cpp index 189024f3883e..9e7ebe7aba5c 100644 --- a/src/crypto/openssl/public_key.cpp +++ b/src/crypto/openssl/public_key.cpp @@ -253,6 +253,11 @@ namespace crypto Unique_EC_KEY ec_key(nid); #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + + // EVP_PKEY* pkey; + // d2i_PublicKey( + // EVP_PKEY_EC, pkey, const unsigned char** pp, long length); + LOG_FAIL_FMT("here"); Unique_EVP_PKEY_CTX pkctx; EVP_PKEY* pkey; @@ -260,15 +265,18 @@ namespace crypto OSSL_PARAM_BLD* param_bld = nullptr; param_bld = OSSL_PARAM_BLD_new(); - // TODO: Also push group! + CHECK1( + OSSL_PARAM_BLD_push_utf8_string(param_bld, "group", SN_secp384r1, 0)); CHECK1(OSSL_PARAM_BLD_push_octet_string( param_bld, "pub", raw.data(), raw.size())); params = OSSL_PARAM_BLD_to_param(param_bld); + // pkctx = EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr); CHECK1(EVP_PKEY_fromdata_init(pkctx)); CHECK1(EVP_PKEY_fromdata(pkctx, &pkey, EVP_PKEY_PUBLIC_KEY, params)); - Unique_PKEY pk; // TODO: Remove + Unique_PKEY pk(pkey); + EVP_PKEY_free(pkey); #else Unique_PKEY pk; CHECK1(EC_KEY_set_public_key(ec_key, p)); // TODO: Deprecated diff --git a/src/node/test/channels.cpp b/src/node/test/channels.cpp index cba3ee51004c..ffc8cc5256c6 100644 --- a/src/node/test/channels.cpp +++ b/src/node/test/channels.cpp @@ -233,6 +233,8 @@ NodeOutboundMsg get_first( TEST_CASE_FIXTURE(IORingbuffersFixture, "Client/Server key exchange") { + logger::config::default_init(); + auto network_kp = crypto::make_key_pair(default_curve); auto service_cert = generate_self_signed_cert(network_kp, "CN=Network"); From 6b4388c226b31c377422fda931143144e318ada3 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 14 Jul 2023 11:15:01 +0000 Subject: [PATCH 12/57] Seems to be working --- src/crypto/openssl/public_key.cpp | 99 ++++++++++++++++++++++++------- 1 file changed, 78 insertions(+), 21 deletions(-) diff --git a/src/crypto/openssl/public_key.cpp b/src/crypto/openssl/public_key.cpp index 9e7ebe7aba5c..e0b86c969af8 100644 --- a/src/crypto/openssl/public_key.cpp +++ b/src/crypto/openssl/public_key.cpp @@ -19,6 +19,7 @@ #include #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 +# include # include #endif @@ -228,8 +229,39 @@ namespace crypto Unique_BIO buf; unsigned char* p = NULL; + LOG_FAIL_FMT(">>> i2d_PublicKey"); size_t n = i2d_PublicKey(key, &p); + { + const unsigned char* pp = p; + EVP_PKEY* pkey = nullptr; + + // TODO: Init pkey + OSSL_PARAM params[2]; + params[0] = OSSL_PARAM_construct_utf8_string( + OSSL_PKEY_PARAM_GROUP_NAME, SN_secp384r1, 0); + params[1] = OSSL_PARAM_construct_end(); + + EVP_PKEY_CTX* pctx = NULL; + pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + EVP_PKEY_fromdata_init(pctx); + EVP_PKEY_fromdata( + pctx, &pkey, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, params); + + pkey = d2i_PublicKey(EVP_PKEY_EC, &pkey, &pp, n); + if (pkey == nullptr) + { + LOG_FAIL_FMT("Error loading public key"); + throw std::logic_error("Error loading public key"); + } + + if (!EVP_PKEY_eq(pkey, key)) + { + LOG_FAIL_FMT("Not the same key!"); + throw std::logic_error("Not the same key :("); + } + } + std::vector r; if (p) { @@ -254,29 +286,54 @@ namespace crypto #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 - // EVP_PKEY* pkey; - // d2i_PublicKey( - // EVP_PKEY_EC, pkey, const unsigned char** pp, long length); - LOG_FAIL_FMT("here"); - Unique_EVP_PKEY_CTX pkctx; - EVP_PKEY* pkey; - - OSSL_PARAM* params = nullptr; // TODO: Fill with public key - OSSL_PARAM_BLD* param_bld = nullptr; - param_bld = OSSL_PARAM_BLD_new(); - - CHECK1( - OSSL_PARAM_BLD_push_utf8_string(param_bld, "group", SN_secp384r1, 0)); - CHECK1(OSSL_PARAM_BLD_push_octet_string( - param_bld, "pub", raw.data(), raw.size())); - - params = OSSL_PARAM_BLD_to_param(param_bld); - - // pkctx = EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr); - CHECK1(EVP_PKEY_fromdata_init(pkctx)); - CHECK1(EVP_PKEY_fromdata(pkctx, &pkey, EVP_PKEY_PUBLIC_KEY, params)); + const unsigned char* pp = raw.data(); + EVP_PKEY* pkey = nullptr; + + // TODO: Get group name from nid! + OSSL_PARAM params[2]; + params[0] = OSSL_PARAM_construct_utf8_string( + OSSL_PKEY_PARAM_GROUP_NAME, SN_secp384r1, 0); + params[1] = OSSL_PARAM_construct_end(); + + EVP_PKEY_CTX* pctx = NULL; + pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + EVP_PKEY_fromdata_init(pctx); + EVP_PKEY_fromdata( + pctx, &pkey, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, params); + + pkey = d2i_PublicKey(EVP_PKEY_EC, &pkey, &pp, raw.size()); + if (pkey == nullptr) + { + LOG_FAIL_FMT("Error loading public key"); + throw std::logic_error("Error loading public key"); + } + Unique_PKEY pk(pkey); + EVP_PKEY_up_ref(pk); EVP_PKEY_free(pkey); + + LOG_FAIL_FMT(">>>> SUCCESS!!!"); + // LOG_FAIL_FMT("here"); + // Unique_EVP_PKEY_CTX pkctx; + // EVP_PKEY* pkey; + + // OSSL_PARAM* params = nullptr; // TODO: Fill with public key + // OSSL_PARAM_BLD* param_bld = nullptr; + // param_bld = OSSL_PARAM_BLD_new(); + + // CHECK1( + // OSSL_PARAM_BLD_push_utf8_string(param_bld, "group", SN_secp384r1, 0)); + // CHECK1(OSSL_PARAM_BLD_push_octet_string( + // param_bld, "pub", raw.data(), raw.size())); + + // params = OSSL_PARAM_BLD_to_param(param_bld); + + // // pkctx = EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr); + // CHECK1(EVP_PKEY_fromdata_init(pkctx)); + // CHECK1(EVP_PKEY_fromdata(pkctx, &pkey, EVP_PKEY_PUBLIC_KEY, params)); + // LOG_FAIL_FMT("success"); + // Unique_PKEY pk(pkey); + // EVP_PKEY_free(pkey); #else Unique_PKEY pk; CHECK1(EC_KEY_set_public_key(ec_key, p)); // TODO: Deprecated From c5ed719f807588eb9eccb3c13355db1112f2bc9d Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 14 Jul 2023 14:17:31 +0000 Subject: [PATCH 13/57] Cleanup --- src/crypto/openssl/openssl_wrappers.h | 6 +- src/crypto/openssl/public_key.cpp | 88 ++++----------------------- src/node/test/channels.cpp | 2 - 3 files changed, 14 insertions(+), 82 deletions(-) diff --git a/src/crypto/openssl/openssl_wrappers.h b/src/crypto/openssl/openssl_wrappers.h index 9ab690412e0c..2d99766296f7 100644 --- a/src/crypto/openssl/openssl_wrappers.h +++ b/src/crypto/openssl/openssl_wrappers.h @@ -5,7 +5,6 @@ #include "ccf/crypto/pem.h" #define FMT_HEADER_ONLY -#include "ccf/ds/logger.h" // TODO: Remove #include #include @@ -57,7 +56,6 @@ namespace crypto unsigned long ec = ERR_get_error(); if (rc != 1 && ec != 0) { - LOG_FAIL_FMT("OpenSSL error: {}", error_string(ec)); throw std::runtime_error( fmt::format("OpenSSL error: {}", error_string(ec))); } @@ -202,9 +200,7 @@ namespace crypto #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 Unique_PKEY(EVP_PKEY* pkey) : Unique_SSL_OBJECT(EVP_PKEY_dup(pkey), EVP_PKEY_free) - { - LOG_FAIL_FMT("dup"); - } + {} #endif }; diff --git a/src/crypto/openssl/public_key.cpp b/src/crypto/openssl/public_key.cpp index e0b86c969af8..ab9b6b972adc 100644 --- a/src/crypto/openssl/public_key.cpp +++ b/src/crypto/openssl/public_key.cpp @@ -106,7 +106,7 @@ namespace crypto { #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 size_t gname_len = 0; - CHECK1(EVP_PKEY_get_group_name(key, nullptr, 0, &gname_len)); + CHECK1(EVP_PKEY_get_group_name(key, NULL, 0, &gname_len)); std::string gname(gname_len + 1, 0); CHECK1(EVP_PKEY_get_group_name( key, (char*)gname.data(), gname.size(), &gname_len)); @@ -229,39 +229,8 @@ namespace crypto Unique_BIO buf; unsigned char* p = NULL; - LOG_FAIL_FMT(">>> i2d_PublicKey"); size_t n = i2d_PublicKey(key, &p); - { - const unsigned char* pp = p; - EVP_PKEY* pkey = nullptr; - - // TODO: Init pkey - OSSL_PARAM params[2]; - params[0] = OSSL_PARAM_construct_utf8_string( - OSSL_PKEY_PARAM_GROUP_NAME, SN_secp384r1, 0); - params[1] = OSSL_PARAM_construct_end(); - - EVP_PKEY_CTX* pctx = NULL; - pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); - EVP_PKEY_fromdata_init(pctx); - EVP_PKEY_fromdata( - pctx, &pkey, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, params); - - pkey = d2i_PublicKey(EVP_PKEY_EC, &pkey, &pp, n); - if (pkey == nullptr) - { - LOG_FAIL_FMT("Error loading public key"); - throw std::logic_error("Error loading public key"); - } - - if (!EVP_PKEY_eq(pkey, key)) - { - LOG_FAIL_FMT("Not the same key!"); - throw std::logic_error("Not the same key :("); - } - } - std::vector r; if (p) { @@ -273,26 +242,12 @@ namespace crypto Unique_PKEY key_from_raw_ec_point(const std::vector& raw, int nid) { - // To extract a raw encoding of the EC point, OpenSSL has i2d_PublicKey, - // but the converse in d2i_PublicKey is useless until we switch to 3.0 - // (see also https://github.com/openssl/openssl/issues/16989). - // So, instead we reconstruct the key the long way round. - - Unique_BN_CTX bn_ctx; - Unique_EC_GROUP group(nid); - Unique_EC_POINT p(group); - CHECK1(EC_POINT_oct2point(group, p, raw.data(), raw.size(), bn_ctx)); - Unique_EC_KEY ec_key(nid); - #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 - const unsigned char* pp = raw.data(); - EVP_PKEY* pkey = nullptr; - - // TODO: Get group name from nid! + EVP_PKEY* pkey = NULL; OSSL_PARAM params[2]; params[0] = OSSL_PARAM_construct_utf8_string( - OSSL_PKEY_PARAM_GROUP_NAME, SN_secp384r1, 0); + OSSL_PKEY_PARAM_GROUP_NAME, (char*)OSSL_EC_curve_nid2name(nid), 0); params[1] = OSSL_PARAM_construct_end(); EVP_PKEY_CTX* pctx = NULL; @@ -302,42 +257,25 @@ namespace crypto pctx, &pkey, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, params); pkey = d2i_PublicKey(EVP_PKEY_EC, &pkey, &pp, raw.size()); - if (pkey == nullptr) + if (pkey == NULL) { - LOG_FAIL_FMT("Error loading public key"); throw std::logic_error("Error loading public key"); } Unique_PKEY pk(pkey); EVP_PKEY_up_ref(pk); EVP_PKEY_free(pkey); - - LOG_FAIL_FMT(">>>> SUCCESS!!!"); - // LOG_FAIL_FMT("here"); - // Unique_EVP_PKEY_CTX pkctx; - // EVP_PKEY* pkey; - - // OSSL_PARAM* params = nullptr; // TODO: Fill with public key - // OSSL_PARAM_BLD* param_bld = nullptr; - // param_bld = OSSL_PARAM_BLD_new(); - - // CHECK1( - // OSSL_PARAM_BLD_push_utf8_string(param_bld, "group", SN_secp384r1, 0)); - // CHECK1(OSSL_PARAM_BLD_push_octet_string( - // param_bld, "pub", raw.data(), raw.size())); - - // params = OSSL_PARAM_BLD_to_param(param_bld); - - // // pkctx = EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr); - // CHECK1(EVP_PKEY_fromdata_init(pkctx)); - // CHECK1(EVP_PKEY_fromdata(pkctx, &pkey, EVP_PKEY_PUBLIC_KEY, params)); - // LOG_FAIL_FMT("success"); - // Unique_PKEY pk(pkey); - // EVP_PKEY_free(pkey); + return pk; #else + Unique_BN_CTX bn_ctx; + Unique_EC_GROUP group(nid); + Unique_EC_POINT p(group); + CHECK1(EC_POINT_oct2point(group, p, raw.data(), raw.size(), bn_ctx)); + Unique_EC_KEY ec_key(nid); + Unique_PKEY pk; - CHECK1(EC_KEY_set_public_key(ec_key, p)); // TODO: Deprecated - CHECK1(EVP_PKEY_set1_EC_KEY(pk, ec_key)); // TODO: Deprecated + CHECK1(EC_KEY_set_public_key(ec_key, p)); + CHECK1(EVP_PKEY_set1_EC_KEY(pk, ec_key)); EVP_PKEY_up_ref(pk); #endif return pk; diff --git a/src/node/test/channels.cpp b/src/node/test/channels.cpp index 343d959d0f62..b42e3fd51f41 100644 --- a/src/node/test/channels.cpp +++ b/src/node/test/channels.cpp @@ -233,8 +233,6 @@ NodeOutboundMsg get_first( TEST_CASE_FIXTURE(IORingbuffersFixture, "Client/Server key exchange") { - logger::config::default_init(); - auto network_kp = crypto::make_key_pair(default_curve); auto service_cert = generate_self_signed_cert(network_kp, "CN=Network"); From f13c9cafe264347ff7276a3a2e907a989ca2740b Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 17 Jul 2023 14:21:33 +0000 Subject: [PATCH 14/57] WIP --- src/crypto/openssl/key_pair.cpp | 2 +- src/crypto/openssl/public_key.cpp | 37 ++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/crypto/openssl/key_pair.cpp b/src/crypto/openssl/key_pair.cpp index 6ae6dfdeb58d..b843c57c1323 100644 --- a/src/crypto/openssl/key_pair.cpp +++ b/src/crypto/openssl/key_pair.cpp @@ -77,7 +77,7 @@ namespace crypto CHECK1(EC_KEY_set_private_key(ec_key, d)); key = EVP_PKEY_new(); - CHECK1(EVP_PKEY_set1_EC_KEY(key, ec_key)); + CHECK1(EVP_PKEY_set1_EC_KEY(key, ec_key)); // TODO: Fix } Pem KeyPair_OpenSSL::private_key_pem() const diff --git a/src/crypto/openssl/public_key.cpp b/src/crypto/openssl/public_key.cpp index ab9b6b972adc..25eea45d69a8 100644 --- a/src/crypto/openssl/public_key.cpp +++ b/src/crypto/openssl/public_key.cpp @@ -73,8 +73,43 @@ namespace crypto PublicKey_OpenSSL::PublicKey_OpenSSL(const JsonWebKeyECPublic& jwk) { key = EVP_PKEY_new(); - CHECK1(EVP_PKEY_set1_EC_KEY(key, ec_key_public_from_jwk(jwk))); +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + if (jwk.kty != JsonWebKeyType::EC) + { + throw std::logic_error("Cannot construct public key from non-EC JWK"); + } + + auto nid = get_openssl_group_id(jwk_curve_to_curve_id(jwk.crv)); + Unique_BIGNUM x, y; + auto x_raw = raw_from_b64url(jwk.x); + auto y_raw = raw_from_b64url(jwk.y); + OpenSSL::CHECKNULL(BN_bin2bn(x_raw.data(), x_raw.size(), x)); + OpenSSL::CHECKNULL(BN_bin2bn(y_raw.data(), y_raw.size(), y)); + + // TODO: Set group + OSSL_PARAM params[4]; + params[0] = OSSL_PARAM_construct_utf8_string( + OSSL_PKEY_PARAM_GROUP_NAME, (char*)OSSL_EC_curve_nid2name(nid), 0); + params[1] = + OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_X, x_raw.data(), x_raw.size()); + params[2] = + OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_Y, x_raw.data(), x_raw.size()); + params[3] = OSSL_PARAM_construct_end(); + + LOG_FAIL_FMT("EVP_PKEY_set_params"); + + CHECK1(EVP_PKEY_set_params(key, params)); + + LOG_FAIL_FMT("Success"); + // CHECK1(EVP_PKEY_set_bn_param(key, OSSL_PKEY_PARAM_EC_PUB_X, x)); + // CHECK1(EVP_PKEY_set_bn_param(key, OSSL_PKEY_PARAM_EC_PUB_Y, y)); + +#else + + CHECK1(EVP_PKEY_set1_EC_KEY(key, ec_key_public_from_jwk(jwk))); // TODO: Fix +#endif } + PublicKey_OpenSSL::PublicKey_OpenSSL(EVP_PKEY* key) : key(key) {} PublicKey_OpenSSL::~PublicKey_OpenSSL() From c36ee2fb16dd62348942ac4a6aa9487992fa10d7 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 24 Jul 2023 14:45:03 +0000 Subject: [PATCH 15/57] Finally works --- src/crypto/openssl/public_key.cpp | 35 ++++++++++++++++++------------- src/crypto/test/crypto.cpp | 10 +++++++++ 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/crypto/openssl/public_key.cpp b/src/crypto/openssl/public_key.cpp index 25eea45d69a8..ea7bbd20321b 100644 --- a/src/crypto/openssl/public_key.cpp +++ b/src/crypto/openssl/public_key.cpp @@ -74,7 +74,7 @@ namespace crypto { key = EVP_PKEY_new(); #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 - if (jwk.kty != JsonWebKeyType::EC) + if (jwk.kty != JsonWebKeyType::EC) // TODO: Deduplicate { throw std::logic_error("Cannot construct public key from non-EC JWK"); } @@ -86,23 +86,30 @@ namespace crypto OpenSSL::CHECKNULL(BN_bin2bn(x_raw.data(), x_raw.size(), x)); OpenSSL::CHECKNULL(BN_bin2bn(y_raw.data(), y_raw.size(), y)); - // TODO: Set group - OSSL_PARAM params[4]; + Unique_BN_CTX bn_ctx; + Unique_EC_GROUP group(nid); + Unique_EC_POINT p(group); + + CHECK1(EC_POINT_set_affine_coordinates(group, p, x, y, bn_ctx)); + + // 2. EC_POINT_point2oct into buffer + size_t buf_size = EC_POINT_point2oct( + group, p, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, bn_ctx); + std::vector buf(buf_size); + CHECKPOSITIVE(EC_POINT_point2oct( + group, p, POINT_CONVERSION_UNCOMPRESSED, buf.data(), buf.size(), bn_ctx)); + + OSSL_PARAM params[3]; params[0] = OSSL_PARAM_construct_utf8_string( OSSL_PKEY_PARAM_GROUP_NAME, (char*)OSSL_EC_curve_nid2name(nid), 0); - params[1] = - OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_X, x_raw.data(), x_raw.size()); - params[2] = - OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_Y, x_raw.data(), x_raw.size()); - params[3] = OSSL_PARAM_construct_end(); - - LOG_FAIL_FMT("EVP_PKEY_set_params"); + params[1] = OSSL_PARAM_construct_octet_string( + OSSL_PKEY_PARAM_PUB_KEY, buf.data(), buf.size()); + params[2] = OSSL_PARAM_construct_end(); - CHECK1(EVP_PKEY_set_params(key, params)); + EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + CHECK1(EVP_PKEY_fromdata_init(ctx)); - LOG_FAIL_FMT("Success"); - // CHECK1(EVP_PKEY_set_bn_param(key, OSSL_PKEY_PARAM_EC_PUB_X, x)); - // CHECK1(EVP_PKEY_set_bn_param(key, OSSL_PKEY_PARAM_EC_PUB_Y, y)); + CHECK1(EVP_PKEY_fromdata(ctx, &key, EVP_PKEY_PUBLIC_KEY, params)); #else diff --git a/src/crypto/test/crypto.cpp b/src/crypto/test/crypto.cpp index e35b6e58e2a7..efb32b888564 100644 --- a/src/crypto/test/crypto.cpp +++ b/src/crypto/test/crypto.cpp @@ -794,6 +794,9 @@ TEST_CASE("PEM to JWK and back") auto kp = make_key_pair(curve); auto pubk = make_public_key(kp->public_key_pem()); + LOG_FAIL_FMT("PEM: {}", kp->public_key_pem().str()); + LOG_FAIL_FMT("PEM (priv): {}", kp->private_key_pem().str()); + INFO("Public"); { auto jwk = pubk->public_key_jwk(); @@ -801,8 +804,15 @@ TEST_CASE("PEM to JWK and back") jwk = pubk->public_key_jwk(kid); REQUIRE(jwk.kid.value() == kid); + LOG_FAIL_FMT("make_public_key"); auto pubk2 = make_public_key(jwk); + LOG_FAIL_FMT("make_public_key done"); + auto jwk2 = pubk2->public_key_jwk(kid); + + LOG_FAIL_FMT("JWK: {}", nlohmann::json(jwk).dump()); + LOG_FAIL_FMT("JWK2: {}", nlohmann::json(jwk2).dump()); + REQUIRE(jwk == jwk2); } From a34619e3ca4a87a51bf4e8d6a27001711c516512 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 24 Jul 2023 14:53:40 +0000 Subject: [PATCH 16/57] . --- cmake/crypto.cmake | 1 + src/crypto/openssl/key_pair.cpp | 5 +++++ src/crypto/openssl/public_key.cpp | 14 +++++--------- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/cmake/crypto.cmake b/cmake/crypto.cmake index 562ac0d00c30..794a58f7c818 100644 --- a/cmake/crypto.cmake +++ b/cmake/crypto.cmake @@ -62,6 +62,7 @@ find_library(TLS_LIBRARY ssl "${OPENSSL_INSTALL_PATH}/lib64") add_library(ccfcrypto.host STATIC ${CCFCRYPTO_SRC}) add_san(ccfcrypto.host) target_compile_options(ccfcrypto.host PUBLIC ${COMPILE_LIBCXX} "-Wno-deprecated-declarations") + # target_compile_definitions(ccfcrypto.host PUBLIC OPENSSL_API_COMPAT=0x10101000L) target_link_options(ccfcrypto.host PUBLIC ${LINK_LIBCXX}) target_include_directories(ccfcrypto.host PRIVATE "${OPENSSL_INSTALL_PATH}/include") diff --git a/src/crypto/openssl/key_pair.cpp b/src/crypto/openssl/key_pair.cpp index b843c57c1323..0a5bde35a315 100644 --- a/src/crypto/openssl/key_pair.cpp +++ b/src/crypto/openssl/key_pair.cpp @@ -68,6 +68,10 @@ namespace crypto KeyPair_OpenSSL::KeyPair_OpenSSL(const JsonWebKeyECPrivate& jwk) { + // #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + + // #else + auto ec_key = PublicKey_OpenSSL::ec_key_public_from_jwk(jwk); Unique_BIGNUM d; @@ -78,6 +82,7 @@ namespace crypto key = EVP_PKEY_new(); CHECK1(EVP_PKEY_set1_EC_KEY(key, ec_key)); // TODO: Fix + // #endif } Pem KeyPair_OpenSSL::private_key_pem() const diff --git a/src/crypto/openssl/public_key.cpp b/src/crypto/openssl/public_key.cpp index ea7bbd20321b..207ecfb54291 100644 --- a/src/crypto/openssl/public_key.cpp +++ b/src/crypto/openssl/public_key.cpp @@ -92,7 +92,6 @@ namespace crypto CHECK1(EC_POINT_set_affine_coordinates(group, p, x, y, bn_ctx)); - // 2. EC_POINT_point2oct into buffer size_t buf_size = EC_POINT_point2oct( group, p, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, bn_ctx); std::vector buf(buf_size); @@ -106,14 +105,12 @@ namespace crypto OSSL_PKEY_PARAM_PUB_KEY, buf.data(), buf.size()); params[2] = OSSL_PARAM_construct_end(); - EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); - CHECK1(EVP_PKEY_fromdata_init(ctx)); - - CHECK1(EVP_PKEY_fromdata(ctx, &key, EVP_PKEY_PUBLIC_KEY, params)); + EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + CHECK1(EVP_PKEY_fromdata_init(pctx)); + CHECK1(EVP_PKEY_fromdata(pctx, &key, EVP_PKEY_PUBLIC_KEY, params)); #else - - CHECK1(EVP_PKEY_set1_EC_KEY(key, ec_key_public_from_jwk(jwk))); // TODO: Fix + CHECK1(EVP_PKEY_set1_EC_KEY(key, ec_key_public_from_jwk(jwk))); #endif } @@ -292,8 +289,7 @@ namespace crypto OSSL_PKEY_PARAM_GROUP_NAME, (char*)OSSL_EC_curve_nid2name(nid), 0); params[1] = OSSL_PARAM_construct_end(); - EVP_PKEY_CTX* pctx = NULL; - pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); EVP_PKEY_fromdata_init(pctx); EVP_PKEY_fromdata( pctx, &pkey, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, params); From 6963358cbe0c9f5cacccb038a8d8822e8aa7a10f Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 24 Jul 2023 16:43:05 +0000 Subject: [PATCH 17/57] Private too --- src/crypto/openssl/key_pair.cpp | 50 +++++++++++++++++++++++++++---- src/crypto/openssl/public_key.cpp | 2 -- src/crypto/test/crypto.cpp | 10 +++---- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/crypto/openssl/key_pair.cpp b/src/crypto/openssl/key_pair.cpp index 0a5bde35a315..ca42c7811c63 100644 --- a/src/crypto/openssl/key_pair.cpp +++ b/src/crypto/openssl/key_pair.cpp @@ -22,6 +22,10 @@ #include #include +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 +# include +#endif + namespace crypto { using namespace OpenSSL; @@ -68,9 +72,46 @@ namespace crypto KeyPair_OpenSSL::KeyPair_OpenSSL(const JsonWebKeyECPrivate& jwk) { - // #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + key = EVP_PKEY_new(); +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 - // #else + auto nid = get_openssl_group_id(jwk_curve_to_curve_id(jwk.crv)); + Unique_BIGNUM x, y, d; + auto x_raw = raw_from_b64url(jwk.x); + auto y_raw = raw_from_b64url(jwk.y); + auto d_raw = raw_from_b64url(jwk.d); + OpenSSL::CHECKNULL(BN_bin2bn(x_raw.data(), x_raw.size(), x)); + OpenSSL::CHECKNULL(BN_bin2bn(y_raw.data(), y_raw.size(), y)); + // Note: d_raw is big endian while OSSL_PARAM_construct_BN expects native + // endianness + std::vector d_raw_native(d_raw.size()); + CHECKPOSITIVE(BN_bn2nativepad(d, d_raw_native.data(), d_raw_native.size())); + + // Public + Unique_BN_CTX bn_ctx; + Unique_EC_GROUP group(nid); + Unique_EC_POINT p(group); + CHECK1(EC_POINT_set_affine_coordinates(group, p, x, y, bn_ctx)); + size_t buf_size = EC_POINT_point2oct( + group, p, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, bn_ctx); + std::vector buf(buf_size); + CHECKPOSITIVE(EC_POINT_point2oct( + group, p, POINT_CONVERSION_UNCOMPRESSED, buf.data(), buf.size(), bn_ctx)); + + OSSL_PARAM params[4]; + params[0] = OSSL_PARAM_construct_utf8_string( + OSSL_PKEY_PARAM_GROUP_NAME, (char*)OSSL_EC_curve_nid2name(nid), 0); + params[1] = OSSL_PARAM_construct_octet_string( + OSSL_PKEY_PARAM_PUB_KEY, buf.data(), buf.size()); + params[2] = OSSL_PARAM_construct_BN( + OSSL_PKEY_PARAM_PRIV_KEY, d_raw_native.data(), d_raw_native.size()); + params[3] = OSSL_PARAM_construct_end(); + + EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + CHECK1(EVP_PKEY_fromdata_init(pctx)); + CHECK1(EVP_PKEY_fromdata(pctx, &key, EVP_PKEY_KEYPAIR, params)); + +#else auto ec_key = PublicKey_OpenSSL::ec_key_public_from_jwk(jwk); @@ -80,9 +121,8 @@ namespace crypto CHECK1(EC_KEY_set_private_key(ec_key, d)); - key = EVP_PKEY_new(); - CHECK1(EVP_PKEY_set1_EC_KEY(key, ec_key)); // TODO: Fix - // #endif + CHECK1(EVP_PKEY_set1_EC_KEY(key, ec_key)); +#endif } Pem KeyPair_OpenSSL::private_key_pem() const diff --git a/src/crypto/openssl/public_key.cpp b/src/crypto/openssl/public_key.cpp index 207ecfb54291..377d45f25f0c 100644 --- a/src/crypto/openssl/public_key.cpp +++ b/src/crypto/openssl/public_key.cpp @@ -89,9 +89,7 @@ namespace crypto Unique_BN_CTX bn_ctx; Unique_EC_GROUP group(nid); Unique_EC_POINT p(group); - CHECK1(EC_POINT_set_affine_coordinates(group, p, x, y, bn_ctx)); - size_t buf_size = EC_POINT_point2oct( group, p, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, bn_ctx); std::vector buf(buf_size); diff --git a/src/crypto/test/crypto.cpp b/src/crypto/test/crypto.cpp index efb32b888564..48e34043ac3b 100644 --- a/src/crypto/test/crypto.cpp +++ b/src/crypto/test/crypto.cpp @@ -794,7 +794,6 @@ TEST_CASE("PEM to JWK and back") auto kp = make_key_pair(curve); auto pubk = make_public_key(kp->public_key_pem()); - LOG_FAIL_FMT("PEM: {}", kp->public_key_pem().str()); LOG_FAIL_FMT("PEM (priv): {}", kp->private_key_pem().str()); INFO("Public"); @@ -804,15 +803,10 @@ TEST_CASE("PEM to JWK and back") jwk = pubk->public_key_jwk(kid); REQUIRE(jwk.kid.value() == kid); - LOG_FAIL_FMT("make_public_key"); auto pubk2 = make_public_key(jwk); - LOG_FAIL_FMT("make_public_key done"); auto jwk2 = pubk2->public_key_jwk(kid); - LOG_FAIL_FMT("JWK: {}", nlohmann::json(jwk).dump()); - LOG_FAIL_FMT("JWK2: {}", nlohmann::json(jwk2).dump()); - REQUIRE(jwk == jwk2); } @@ -825,6 +819,10 @@ TEST_CASE("PEM to JWK and back") auto kp2 = make_key_pair(jwk); auto jwk2 = kp2->private_key_jwk(kid); + + LOG_FAIL_FMT("JWK: {}", nlohmann::json(jwk).dump()); + LOG_FAIL_FMT("JWK2: {}", nlohmann::json(jwk2).dump()); + REQUIRE(jwk == jwk2); } } From 88350c34ae7b18535d0397b396a06621761a9642 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 24 Jul 2023 16:45:54 +0000 Subject: [PATCH 18/57] Oops --- src/crypto/openssl/key_pair.cpp | 2 +- src/crypto/test/crypto.cpp | 15 --------------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/src/crypto/openssl/key_pair.cpp b/src/crypto/openssl/key_pair.cpp index ca42c7811c63..13b49a8970c1 100644 --- a/src/crypto/openssl/key_pair.cpp +++ b/src/crypto/openssl/key_pair.cpp @@ -82,12 +82,12 @@ namespace crypto auto d_raw = raw_from_b64url(jwk.d); OpenSSL::CHECKNULL(BN_bin2bn(x_raw.data(), x_raw.size(), x)); OpenSSL::CHECKNULL(BN_bin2bn(y_raw.data(), y_raw.size(), y)); + OpenSSL::CHECKNULL(BN_bin2bn(d_raw.data(), d_raw.size(), d)); // Note: d_raw is big endian while OSSL_PARAM_construct_BN expects native // endianness std::vector d_raw_native(d_raw.size()); CHECKPOSITIVE(BN_bn2nativepad(d, d_raw_native.data(), d_raw_native.size())); - // Public Unique_BN_CTX bn_ctx; Unique_EC_GROUP group(nid); Unique_EC_POINT p(group); diff --git a/src/crypto/test/crypto.cpp b/src/crypto/test/crypto.cpp index 48e34043ac3b..a07ac5c04b97 100644 --- a/src/crypto/test/crypto.cpp +++ b/src/crypto/test/crypto.cpp @@ -794,8 +794,6 @@ TEST_CASE("PEM to JWK and back") auto kp = make_key_pair(curve); auto pubk = make_public_key(kp->public_key_pem()); - LOG_FAIL_FMT("PEM (priv): {}", kp->private_key_pem().str()); - INFO("Public"); { auto jwk = pubk->public_key_jwk(); @@ -804,9 +802,7 @@ TEST_CASE("PEM to JWK and back") REQUIRE(jwk.kid.value() == kid); auto pubk2 = make_public_key(jwk); - auto jwk2 = pubk2->public_key_jwk(kid); - REQUIRE(jwk == jwk2); } @@ -819,10 +815,6 @@ TEST_CASE("PEM to JWK and back") auto kp2 = make_key_pair(jwk); auto jwk2 = kp2->private_key_jwk(kid); - - LOG_FAIL_FMT("JWK: {}", nlohmann::json(jwk).dump()); - LOG_FAIL_FMT("JWK2: {}", nlohmann::json(jwk2).dump()); - REQUIRE(jwk == jwk2); } } @@ -833,9 +825,6 @@ TEST_CASE("PEM to JWK and back") auto kp = make_rsa_key_pair(); auto pubk = make_rsa_public_key(kp->public_key_pem()); - LOG_FAIL_FMT("PEM: {}", kp->public_key_pem().str()); - LOG_FAIL_FMT("PEM (priv): {}", kp->private_key_pem().str()); - INFO("Public"); { auto jwk = pubk->public_key_jwk_rsa(); @@ -846,8 +835,6 @@ TEST_CASE("PEM to JWK and back") auto pubk2 = make_rsa_public_key(jwk); auto jwk2 = pubk2->public_key_jwk_rsa(kid); REQUIRE(jwk == jwk2); - - LOG_FAIL_FMT("JWK: {}", nlohmann::json(jwk).dump()); } INFO("Private"); @@ -860,8 +847,6 @@ TEST_CASE("PEM to JWK and back") auto kp2 = make_rsa_key_pair(jwk); auto jwk2 = kp2->private_key_jwk_rsa(kid); REQUIRE(jwk == jwk2); - - LOG_FAIL_FMT("JWK: {}", nlohmann::json(jwk).dump()); } } From c6f2184ea0c582322a6708ac8a8a19283f730908 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 24 Jul 2023 17:12:17 +0000 Subject: [PATCH 19/57] cleanup --- src/crypto/openssl/key_pair.cpp | 31 +++--------------- src/crypto/openssl/public_key.cpp | 53 +++++++++++++++++-------------- src/crypto/openssl/public_key.h | 5 +++ 3 files changed, 40 insertions(+), 49 deletions(-) diff --git a/src/crypto/openssl/key_pair.cpp b/src/crypto/openssl/key_pair.cpp index 13b49a8970c1..e4878edcdde9 100644 --- a/src/crypto/openssl/key_pair.cpp +++ b/src/crypto/openssl/key_pair.cpp @@ -73,36 +73,23 @@ namespace crypto KeyPair_OpenSSL::KeyPair_OpenSSL(const JsonWebKeyECPrivate& jwk) { key = EVP_PKEY_new(); -#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 - - auto nid = get_openssl_group_id(jwk_curve_to_curve_id(jwk.crv)); - Unique_BIGNUM x, y, d; - auto x_raw = raw_from_b64url(jwk.x); - auto y_raw = raw_from_b64url(jwk.y); + Unique_BIGNUM d; auto d_raw = raw_from_b64url(jwk.d); - OpenSSL::CHECKNULL(BN_bin2bn(x_raw.data(), x_raw.size(), x)); - OpenSSL::CHECKNULL(BN_bin2bn(y_raw.data(), y_raw.size(), y)); OpenSSL::CHECKNULL(BN_bin2bn(d_raw.data(), d_raw.size(), d)); +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + auto nid = get_openssl_group_id(jwk_curve_to_curve_id(jwk.crv)); // Note: d_raw is big endian while OSSL_PARAM_construct_BN expects native // endianness std::vector d_raw_native(d_raw.size()); CHECKPOSITIVE(BN_bn2nativepad(d, d_raw_native.data(), d_raw_native.size())); - Unique_BN_CTX bn_ctx; - Unique_EC_GROUP group(nid); - Unique_EC_POINT p(group); - CHECK1(EC_POINT_set_affine_coordinates(group, p, x, y, bn_ctx)); - size_t buf_size = EC_POINT_point2oct( - group, p, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, bn_ctx); - std::vector buf(buf_size); - CHECKPOSITIVE(EC_POINT_point2oct( - group, p, POINT_CONVERSION_UNCOMPRESSED, buf.data(), buf.size(), bn_ctx)); + auto pub_buf = PublicKey_OpenSSL::ec_point_public_from_jwk(jwk); OSSL_PARAM params[4]; params[0] = OSSL_PARAM_construct_utf8_string( OSSL_PKEY_PARAM_GROUP_NAME, (char*)OSSL_EC_curve_nid2name(nid), 0); params[1] = OSSL_PARAM_construct_octet_string( - OSSL_PKEY_PARAM_PUB_KEY, buf.data(), buf.size()); + OSSL_PKEY_PARAM_PUB_KEY, pub_buf.data(), pub_buf.size()); params[2] = OSSL_PARAM_construct_BN( OSSL_PKEY_PARAM_PRIV_KEY, d_raw_native.data(), d_raw_native.size()); params[3] = OSSL_PARAM_construct_end(); @@ -110,17 +97,9 @@ namespace crypto EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); CHECK1(EVP_PKEY_fromdata_init(pctx)); CHECK1(EVP_PKEY_fromdata(pctx, &key, EVP_PKEY_KEYPAIR, params)); - #else - auto ec_key = PublicKey_OpenSSL::ec_key_public_from_jwk(jwk); - - Unique_BIGNUM d; - auto d_raw = raw_from_b64url(jwk.d); - OpenSSL::CHECKNULL(BN_bin2bn(d_raw.data(), d_raw.size(), d)); - CHECK1(EC_KEY_set_private_key(ec_key, d)); - CHECK1(EVP_PKEY_set1_EC_KEY(key, ec_key)); #endif } diff --git a/src/crypto/openssl/public_key.cpp b/src/crypto/openssl/public_key.cpp index 377d45f25f0c..db35e379d1fe 100644 --- a/src/crypto/openssl/public_key.cpp +++ b/src/crypto/openssl/public_key.cpp @@ -49,7 +49,7 @@ namespace crypto } } - Unique_EC_KEY PublicKey_OpenSSL::ec_key_public_from_jwk( + std::pair get_components( const JsonWebKeyECPublic& jwk) { if (jwk.kty != JsonWebKeyType::EC) @@ -57,34 +57,21 @@ namespace crypto throw std::logic_error("Cannot construct public key from non-EC JWK"); } - auto nid = get_openssl_group_id(jwk_curve_to_curve_id(jwk.crv)); - - Unique_BIGNUM x, y; + std::pair xy; auto x_raw = raw_from_b64url(jwk.x); auto y_raw = raw_from_b64url(jwk.y); - OpenSSL::CHECKNULL(BN_bin2bn(x_raw.data(), x_raw.size(), x)); - OpenSSL::CHECKNULL(BN_bin2bn(y_raw.data(), y_raw.size(), y)); + OpenSSL::CHECKNULL(BN_bin2bn(x_raw.data(), x_raw.size(), xy.first)); + OpenSSL::CHECKNULL(BN_bin2bn(y_raw.data(), y_raw.size(), xy.second)); - Unique_EC_KEY ec_key(nid); - CHECK1(EC_KEY_set_public_key_affine_coordinates(ec_key, x, y)); - return ec_key; + return xy; } - PublicKey_OpenSSL::PublicKey_OpenSSL(const JsonWebKeyECPublic& jwk) - { - key = EVP_PKEY_new(); #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 - if (jwk.kty != JsonWebKeyType::EC) // TODO: Deduplicate - { - throw std::logic_error("Cannot construct public key from non-EC JWK"); - } - + std::vector PublicKey_OpenSSL::ec_point_public_from_jwk( + const JsonWebKeyECPublic& jwk) + { auto nid = get_openssl_group_id(jwk_curve_to_curve_id(jwk.crv)); - Unique_BIGNUM x, y; - auto x_raw = raw_from_b64url(jwk.x); - auto y_raw = raw_from_b64url(jwk.y); - OpenSSL::CHECKNULL(BN_bin2bn(x_raw.data(), x_raw.size(), x)); - OpenSSL::CHECKNULL(BN_bin2bn(y_raw.data(), y_raw.size(), y)); + auto [x, y] = get_components(jwk); Unique_BN_CTX bn_ctx; Unique_EC_GROUP group(nid); @@ -95,6 +82,27 @@ namespace crypto std::vector buf(buf_size); CHECKPOSITIVE(EC_POINT_point2oct( group, p, POINT_CONVERSION_UNCOMPRESSED, buf.data(), buf.size(), bn_ctx)); + return buf; + } +#else + Unique_EC_KEY PublicKey_OpenSSL::ec_key_public_from_jwk( + const JsonWebKeyECPublic& jwk) + { + auto nid = get_openssl_group_id(jwk_curve_to_curve_id(jwk.crv)); + auto [x, y] = get_components(jwk); + + Unique_EC_KEY ec_key(nid); + CHECK1(EC_KEY_set_public_key_affine_coordinates(ec_key, x, y)); + return ec_key; + } +#endif + + PublicKey_OpenSSL::PublicKey_OpenSSL(const JsonWebKeyECPublic& jwk) + { + key = EVP_PKEY_new(); +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + auto nid = get_openssl_group_id(jwk_curve_to_curve_id(jwk.crv)); + auto buf = ec_point_public_from_jwk(jwk); OSSL_PARAM params[3]; params[0] = OSSL_PARAM_construct_utf8_string( @@ -106,7 +114,6 @@ namespace crypto EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); CHECK1(EVP_PKEY_fromdata_init(pctx)); CHECK1(EVP_PKEY_fromdata(pctx, &key, EVP_PKEY_PUBLIC_KEY, params)); - #else CHECK1(EVP_PKEY_set1_EC_KEY(key, ec_key_public_from_jwk(jwk))); #endif diff --git a/src/crypto/openssl/public_key.h b/src/crypto/openssl/public_key.h index a42dbf86b078..bc77b80f2f6f 100644 --- a/src/crypto/openssl/public_key.h +++ b/src/crypto/openssl/public_key.h @@ -18,8 +18,13 @@ namespace crypto EVP_PKEY* key = nullptr; PublicKey_OpenSSL(); +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + std::vector ec_point_public_from_jwk( + const JsonWebKeyECPublic& jwk); +#else OpenSSL::Unique_EC_KEY ec_key_public_from_jwk( const JsonWebKeyECPublic& jwk); +#endif public: PublicKey_OpenSSL(PublicKey_OpenSSL&& key) = default; From aed42e5a5c14d66214b1268e7d989ef65c789166 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 25 Jul 2023 09:27:36 +0000 Subject: [PATCH 20/57] WIP --- src/crypto/openssl/rsa_key_pair.cpp | 4 ++-- src/crypto/openssl/rsa_public_key.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/crypto/openssl/rsa_key_pair.cpp b/src/crypto/openssl/rsa_key_pair.cpp index be0fcdd15759..b6a451a0521d 100644 --- a/src/crypto/openssl/rsa_key_pair.cpp +++ b/src/crypto/openssl/rsa_key_pair.cpp @@ -24,7 +24,7 @@ namespace crypto OpenSSL::CHECKNULL(rsa = RSA_new()); OpenSSL::CHECK1(RSA_generate_key_ex(rsa, public_key_size, big_exp, NULL)); OpenSSL::CHECKNULL(key = EVP_PKEY_new()); - OpenSSL::CHECK1(EVP_PKEY_set1_RSA(key, rsa)); + OpenSSL::CHECK1(EVP_PKEY_set1_RSA(key, rsa)); // TODO: Next BN_free(big_exp); RSA_free(rsa); } @@ -75,7 +75,7 @@ namespace crypto qi.release(); key = EVP_PKEY_new(); - CHECK1(EVP_PKEY_set1_RSA(key, rsa)); + CHECK1(EVP_PKEY_set1_RSA(key, rsa)); // TODO: Next } size_t RSAKeyPair_OpenSSL::key_size() const diff --git a/src/crypto/openssl/rsa_public_key.cpp b/src/crypto/openssl/rsa_public_key.cpp index 3f8b42a7a65c..f69d196c52ff 100644 --- a/src/crypto/openssl/rsa_public_key.cpp +++ b/src/crypto/openssl/rsa_public_key.cpp @@ -55,7 +55,7 @@ namespace crypto } key = EVP_PKEY_new(); - OpenSSL::CHECK1(EVP_PKEY_set1_RSA(key, rsa)); + OpenSSL::CHECK1(EVP_PKEY_set1_RSA(key, rsa)); // TODO: Next RSA_free(rsa); } @@ -85,7 +85,7 @@ namespace crypto RSAPublicKey_OpenSSL::RSAPublicKey_OpenSSL(const JsonWebKeyRSAPublic& jwk) { key = EVP_PKEY_new(); - CHECK1(EVP_PKEY_set1_RSA(key, rsa_public_from_jwk(jwk))); + CHECK1(EVP_PKEY_set1_RSA(key, rsa_public_from_jwk(jwk))); // TODO: Next } size_t RSAPublicKey_OpenSSL::key_size() const From 2d44d8f03ebcccdb9fe21eaad703d399bb53b0c3 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 25 Jul 2023 15:30:04 +0000 Subject: [PATCH 21/57] WIP --- src/crypto/openssl/rsa_key_pair.cpp | 28 +++++++++-- src/crypto/test/crypto.cpp | 75 +++++++++++++++-------------- 2 files changed, 64 insertions(+), 39 deletions(-) diff --git a/src/crypto/openssl/rsa_key_pair.cpp b/src/crypto/openssl/rsa_key_pair.cpp index b6a451a0521d..369592019304 100644 --- a/src/crypto/openssl/rsa_key_pair.cpp +++ b/src/crypto/openssl/rsa_key_pair.cpp @@ -21,12 +21,32 @@ namespace crypto BIGNUM* big_exp = NULL; OpenSSL::CHECKNULL(big_exp = BN_new()); OpenSSL::CHECK1(BN_set_word(big_exp, public_exponent)); - OpenSSL::CHECKNULL(rsa = RSA_new()); - OpenSSL::CHECK1(RSA_generate_key_ex(rsa, public_key_size, big_exp, NULL)); + std::vector r(BN_num_bytes(big_exp)); + BN_bn2bin(big_exp, r.data()); + OpenSSL::CHECKNULL(key = EVP_PKEY_new()); - OpenSSL::CHECK1(EVP_PKEY_set1_RSA(key, rsa)); // TODO: Next + + LOG_FAIL_FMT("RSAKeyPair_OpenSSL"); + + OSSL_PARAM params[3]; + params[0] = + OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_BITS, &public_key_size); + params[1] = + OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_N, r.data(), r.size()); + params[2] = OSSL_PARAM_construct_end(); + + EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + CHECK1(EVP_PKEY_fromdata_init(pctx)); + CHECK1(EVP_PKEY_fromdata(pctx, &key, EVP_PKEY_KEYPAIR, params)); + + LOG_FAIL_FMT("success"); + + // OpenSSL::CHECKNULL(rsa = RSA_new()); // TODO: Next + // OpenSSL::CHECK1(RSA_generate_key_ex(rsa, public_key_size, big_exp, + // NULL)); // TODO: Next OpenSSL::CHECKNULL(key = EVP_PKEY_new()); + // OpenSSL::CHECK1(EVP_PKEY_set1_RSA(key, rsa)); // TODO: Next BN_free(big_exp); - RSA_free(rsa); + // RSA_free(rsa); } RSAKeyPair_OpenSSL::RSAKeyPair_OpenSSL(EVP_PKEY* k) : diff --git a/src/crypto/test/crypto.cpp b/src/crypto/test/crypto.cpp index a07ac5c04b97..799dccd59407 100644 --- a/src/crypto/test/crypto.cpp +++ b/src/crypto/test/crypto.cpp @@ -784,45 +784,50 @@ TEST_CASE("PEM to JWK and back") auto kid = "my_kid"; logger::config::default_init(); - - INFO("EC"); - { - auto curves = {CurveID::SECP384R1, CurveID::SECP256R1, CurveID::SECP256K1}; - - for (auto const& curve : curves) - { - auto kp = make_key_pair(curve); - auto pubk = make_public_key(kp->public_key_pem()); - - INFO("Public"); - { - auto jwk = pubk->public_key_jwk(); - REQUIRE_FALSE(jwk.kid.has_value()); - jwk = pubk->public_key_jwk(kid); - REQUIRE(jwk.kid.value() == kid); - - auto pubk2 = make_public_key(jwk); - auto jwk2 = pubk2->public_key_jwk(kid); - REQUIRE(jwk == jwk2); - } - - INFO("Private"); - { - auto jwk = kp->private_key_jwk(); - REQUIRE_FALSE(jwk.kid.has_value()); - jwk = kp->private_key_jwk(kid); - REQUIRE(jwk.kid.value() == kid); - - auto kp2 = make_key_pair(jwk); - auto jwk2 = kp2->private_key_jwk(kid); - REQUIRE(jwk == jwk2); - } - } - } + LOG_FAIL_FMT("here"); + + // INFO("EC"); + // { + // auto curves = {CurveID::SECP384R1, CurveID::SECP256R1, + // CurveID::SECP256K1}; + + // for (auto const& curve : curves) + // { + // auto kp = make_key_pair(curve); + // auto pubk = make_public_key(kp->public_key_pem()); + + // INFO("Public"); + // { + // auto jwk = pubk->public_key_jwk(); + // REQUIRE_FALSE(jwk.kid.has_value()); + // jwk = pubk->public_key_jwk(kid); + // REQUIRE(jwk.kid.value() == kid); + + // auto pubk2 = make_public_key(jwk); + // auto jwk2 = pubk2->public_key_jwk(kid); + // REQUIRE(jwk == jwk2); + // } + + // INFO("Private"); + // { + // auto jwk = kp->private_key_jwk(); + // REQUIRE_FALSE(jwk.kid.has_value()); + // jwk = kp->private_key_jwk(kid); + // REQUIRE(jwk.kid.value() == kid); + + // auto kp2 = make_key_pair(jwk); + // auto jwk2 = kp2->private_key_jwk(kid); + // REQUIRE(jwk == jwk2); + // } + // } + // } INFO("RSA"); { + LOG_FAIL_FMT("*****"); auto kp = make_rsa_key_pair(); + LOG_FAIL_FMT("*****"); + auto pubk = make_rsa_public_key(kp->public_key_pem()); INFO("Public"); From 132d3f4b7fd63b4ffbee50d20c3b0e746c104cd2 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Wed, 26 Jul 2023 10:25:15 +0000 Subject: [PATCH 22/57] Works --- src/crypto/openssl/rsa_key_pair.cpp | 72 +++++++++++------------------ src/crypto/test/crypto.cpp | 2 - 2 files changed, 28 insertions(+), 46 deletions(-) diff --git a/src/crypto/openssl/rsa_key_pair.cpp b/src/crypto/openssl/rsa_key_pair.cpp index 369592019304..1ccb9280c207 100644 --- a/src/crypto/openssl/rsa_key_pair.cpp +++ b/src/crypto/openssl/rsa_key_pair.cpp @@ -17,36 +17,23 @@ namespace crypto RSAKeyPair_OpenSSL::RSAKeyPair_OpenSSL( size_t public_key_size, size_t public_exponent) { - RSA* rsa; - BIGNUM* big_exp = NULL; - OpenSSL::CHECKNULL(big_exp = BN_new()); - OpenSSL::CHECK1(BN_set_word(big_exp, public_exponent)); - std::vector r(BN_num_bytes(big_exp)); - BN_bn2bin(big_exp, r.data()); - - OpenSSL::CHECKNULL(key = EVP_PKEY_new()); - - LOG_FAIL_FMT("RSAKeyPair_OpenSSL"); - - OSSL_PARAM params[3]; - params[0] = - OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_BITS, &public_key_size); - params[1] = - OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_N, r.data(), r.size()); - params[2] = OSSL_PARAM_construct_end(); + CHECKNULL(key = EVP_PKEY_new()); + Unique_BIGNUM big_exp; + CHECK1(BN_set_word(big_exp, public_exponent)); +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); - CHECK1(EVP_PKEY_fromdata_init(pctx)); - CHECK1(EVP_PKEY_fromdata(pctx, &key, EVP_PKEY_KEYPAIR, params)); - - LOG_FAIL_FMT("success"); - - // OpenSSL::CHECKNULL(rsa = RSA_new()); // TODO: Next - // OpenSSL::CHECK1(RSA_generate_key_ex(rsa, public_key_size, big_exp, - // NULL)); // TODO: Next OpenSSL::CHECKNULL(key = EVP_PKEY_new()); - // OpenSSL::CHECK1(EVP_PKEY_set1_RSA(key, rsa)); // TODO: Next - BN_free(big_exp); - // RSA_free(rsa); + CHECK1(EVP_PKEY_keygen_init(pctx)); + CHECKPOSITIVE(EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, public_key_size)); + CHECKPOSITIVE(EVP_PKEY_CTX_set1_rsa_keygen_pubexp(pctx, big_exp)); + CHECK1(EVP_PKEY_generate(pctx, &key)); +#else + RSA* rsa; + CHECKNULL(rsa = RSA_new()); + CHECK1(RSA_generate_key_ex(rsa, public_key_size, big_exp, NULL)); + CHECK1(EVP_PKEY_set1_RSA(key, rsa)); + RSA_free(rsa); +#endif } RSAKeyPair_OpenSSL::RSAKeyPair_OpenSSL(EVP_PKEY* k) : @@ -75,12 +62,12 @@ namespace crypto auto dq_raw = raw_from_b64url(jwk.dq); auto qi_raw = raw_from_b64url(jwk.qi); - OpenSSL::CHECKNULL(BN_bin2bn(d_raw.data(), d_raw.size(), d)); - OpenSSL::CHECKNULL(BN_bin2bn(p_raw.data(), p_raw.size(), p)); - OpenSSL::CHECKNULL(BN_bin2bn(q_raw.data(), q_raw.size(), q)); - OpenSSL::CHECKNULL(BN_bin2bn(dp_raw.data(), dp_raw.size(), dp)); - OpenSSL::CHECKNULL(BN_bin2bn(dq_raw.data(), dq_raw.size(), dq)); - OpenSSL::CHECKNULL(BN_bin2bn(qi_raw.data(), qi_raw.size(), qi)); + CHECKNULL(BN_bin2bn(d_raw.data(), d_raw.size(), d)); + CHECKNULL(BN_bin2bn(p_raw.data(), p_raw.size(), p)); + CHECKNULL(BN_bin2bn(q_raw.data(), q_raw.size(), q)); + CHECKNULL(BN_bin2bn(dp_raw.data(), dp_raw.size(), dp)); + CHECKNULL(BN_bin2bn(dq_raw.data(), dq_raw.size(), dq)); + CHECKNULL(BN_bin2bn(qi_raw.data(), qi_raw.size(), qi)); CHECK1(RSA_set0_key(rsa, nullptr, nullptr, d)); d.release(); @@ -120,7 +107,7 @@ namespace crypto } Unique_EVP_PKEY_CTX ctx(key); - OpenSSL::CHECK1(EVP_PKEY_decrypt_init(ctx)); + CHECK1(EVP_PKEY_decrypt_init(ctx)); EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING); EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha256()); EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha256()); @@ -137,11 +124,10 @@ namespace crypto } size_t olen; - OpenSSL::CHECK1( - EVP_PKEY_decrypt(ctx, NULL, &olen, input.data(), input.size())); + CHECK1(EVP_PKEY_decrypt(ctx, NULL, &olen, input.data(), input.size())); std::vector output(olen); - OpenSSL::CHECK1( + CHECK1( EVP_PKEY_decrypt(ctx, output.data(), &olen, input.data(), input.size())); output.resize(olen); @@ -152,8 +138,7 @@ namespace crypto { Unique_BIO buf; - OpenSSL::CHECK1( - PEM_write_bio_PrivateKey(buf, key, NULL, NULL, 0, NULL, NULL)); + CHECK1(PEM_write_bio_PrivateKey(buf, key, NULL, NULL, 0, NULL, NULL)); BUF_MEM* bptr; BIO_get_mem_ptr(buf, &bptr); @@ -176,11 +161,10 @@ namespace crypto std::vector r(2048); auto hash = OpenSSLHashProvider().Hash(d.data(), d.size(), md_type); Unique_EVP_PKEY_CTX pctx(key); - OpenSSL::CHECK1(EVP_PKEY_sign_init(pctx)); - OpenSSL::CHECK1(EVP_PKEY_CTX_set_signature_md(pctx, get_md_type(md_type))); + CHECK1(EVP_PKEY_sign_init(pctx)); + CHECK1(EVP_PKEY_CTX_set_signature_md(pctx, get_md_type(md_type))); size_t olen = r.size(); - OpenSSL::CHECK1( - EVP_PKEY_sign(pctx, r.data(), &olen, hash.data(), hash.size())); + CHECK1(EVP_PKEY_sign(pctx, r.data(), &olen, hash.data(), hash.size())); r.resize(olen); return r; } diff --git a/src/crypto/test/crypto.cpp b/src/crypto/test/crypto.cpp index 799dccd59407..593a2be162d3 100644 --- a/src/crypto/test/crypto.cpp +++ b/src/crypto/test/crypto.cpp @@ -824,9 +824,7 @@ TEST_CASE("PEM to JWK and back") INFO("RSA"); { - LOG_FAIL_FMT("*****"); auto kp = make_rsa_key_pair(); - LOG_FAIL_FMT("*****"); auto pubk = make_rsa_public_key(kp->public_key_pem()); From ba9a214fe096df80ccb29226f4c8635381210992 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Wed, 26 Jul 2023 13:31:46 +0000 Subject: [PATCH 23/57] JWK to RSA --- src/crypto/openssl/rsa_key_pair.cpp | 90 ++++++++++++++++++++++++++- src/crypto/openssl/rsa_public_key.cpp | 2 +- src/crypto/test/crypto.cpp | 4 ++ 3 files changed, 92 insertions(+), 4 deletions(-) diff --git a/src/crypto/openssl/rsa_key_pair.cpp b/src/crypto/openssl/rsa_key_pair.cpp index 1ccb9280c207..de8700b3bbe7 100644 --- a/src/crypto/openssl/rsa_key_pair.cpp +++ b/src/crypto/openssl/rsa_key_pair.cpp @@ -52,7 +52,7 @@ namespace crypto RSAKeyPair_OpenSSL::RSAKeyPair_OpenSSL(const JsonWebKeyRSAPrivate& jwk) { - auto rsa = RSAPublicKey_OpenSSL::rsa_public_from_jwk(jwk); + key = EVP_PKEY_new(); Unique_BIGNUM d, p, q, dp, dq, qi; auto d_raw = raw_from_b64url(jwk.d); @@ -69,6 +69,90 @@ namespace crypto CHECKNULL(BN_bin2bn(dq_raw.data(), dq_raw.size(), dq)); CHECKNULL(BN_bin2bn(qi_raw.data(), qi_raw.size(), qi)); + // Note: raw vectors are big endians while OSSL_PARAM_construct_BN expects + // native endianness + std::vector d_raw_native(d_raw.size()); + CHECKPOSITIVE(BN_bn2nativepad(d, d_raw_native.data(), d_raw_native.size())); + + std::vector p_raw_native(p_raw.size()); + CHECKPOSITIVE(BN_bn2nativepad(p, p_raw_native.data(), p_raw_native.size())); + + std::vector q_raw_native(q_raw.size()); + CHECKPOSITIVE(BN_bn2nativepad(q, q_raw_native.data(), q_raw_native.size())); + + std::vector dp_raw_native(dp_raw.size()); + CHECKPOSITIVE( + BN_bn2nativepad(dp, dp_raw_native.data(), dp_raw_native.size())); + + std::vector dq_raw_native(dq_raw.size()); + CHECKPOSITIVE( + BN_bn2nativepad(dq, dq_raw_native.data(), dq_raw_native.size())); + + std::vector qi_raw_native(qi_raw.size()); + CHECKPOSITIVE( + BN_bn2nativepad(qi, qi_raw_native.data(), qi_raw_native.size())); + +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + Unique_BIGNUM n, e; + auto n_raw = raw_from_b64url(jwk.n); + auto e_raw = raw_from_b64url(jwk.e); + CHECKNULL(BN_bin2bn(n_raw.data(), n_raw.size(), n)); + CHECKNULL(BN_bin2bn(e_raw.data(), e_raw.size(), e)); + + std::vector n_raw_native(n_raw.size()); + CHECKPOSITIVE(BN_bn2nativepad(n, n_raw_native.data(), n_raw_native.size())); + + std::vector e_raw_native(e_raw.size()); + CHECKPOSITIVE(BN_bn2nativepad(e, e_raw_native.data(), e_raw_native.size())); + + OSSL_PARAM params[9]; + params[0] = OSSL_PARAM_construct_BN( + OSSL_PKEY_PARAM_RSA_N, n_raw_native.data(), n_raw_native.size()); + params[1] = OSSL_PARAM_construct_BN( + OSSL_PKEY_PARAM_RSA_E, e_raw_native.data(), e_raw_native.size()); + params[2] = OSSL_PARAM_construct_BN( + OSSL_PKEY_PARAM_RSA_D, d_raw_native.data(), d_raw_native.size()); + params[3] = OSSL_PARAM_construct_BN( + OSSL_PKEY_PARAM_RSA_FACTOR1, p_raw_native.data(), p_raw_native.size()); + params[4] = OSSL_PARAM_construct_BN( + OSSL_PKEY_PARAM_RSA_FACTOR2, q_raw_native.data(), q_raw_native.size()); + params[5] = OSSL_PARAM_construct_BN( + OSSL_PKEY_PARAM_RSA_EXPONENT1, + dp_raw_native.data(), + dp_raw_native.size()); + params[6] = OSSL_PARAM_construct_BN( + OSSL_PKEY_PARAM_RSA_EXPONENT2, + dq_raw_native.data(), + dq_raw_native.size()); + params[7] = OSSL_PARAM_construct_BN( + OSSL_PKEY_PARAM_RSA_COEFFICIENT1, + qi_raw_native.data(), + qi_raw_native.size()); + // params[1] = OSSL_PARAM_construct_octet_string( + // OSSL_PKEY_PARAM_PUB_KEY, pub_buf.data(), pub_buf.size()); + // params[2] = OSSL_PARAM_construct_BN( + // OSSL_PKEY_PARAM_PRIV_KEY, d_raw_native.data(), d_raw_native.size()); + params[8] = OSSL_PARAM_construct_end(); + + EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + CHECK1(EVP_PKEY_fromdata_init(pctx)); + CHECK1(EVP_PKEY_fromdata(pctx, &key, EVP_PKEY_KEYPAIR, params)); + + LOG_FAIL_FMT("success"); + + // r.n = bn_bytes(get_bn_param(OSSL_PKEY_PARAM_RSA_N)); + // r.e = bn_bytes(get_bn_param(OSSL_PKEY_PARAM_RSA_E)); + + // d = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_D); + // p = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_FACTOR1); + // q = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_FACTOR2); + // dp = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_EXPONENT1); + // dq = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_EXPONENT2); + // qi = + // RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_COEFFICIENT1); + +#else + auto rsa = RSAPublicKey_OpenSSL::rsa_public_from_jwk(jwk); CHECK1(RSA_set0_key(rsa, nullptr, nullptr, d)); d.release(); @@ -81,8 +165,8 @@ namespace crypto dq.release(); qi.release(); - key = EVP_PKEY_new(); - CHECK1(EVP_PKEY_set1_RSA(key, rsa)); // TODO: Next + CHECK1(EVP_PKEY_set1_RSA(key, rsa)); +#endif } size_t RSAKeyPair_OpenSSL::key_size() const diff --git a/src/crypto/openssl/rsa_public_key.cpp b/src/crypto/openssl/rsa_public_key.cpp index f69d196c52ff..1026023379c6 100644 --- a/src/crypto/openssl/rsa_public_key.cpp +++ b/src/crypto/openssl/rsa_public_key.cpp @@ -75,7 +75,7 @@ namespace crypto OpenSSL::CHECKNULL(BN_bin2bn(n_raw.data(), n_raw.size(), n)); Unique_RSA rsa; - CHECK1(RSA_set0_key(rsa, n, e, nullptr)); + CHECK1(RSA_set0_key(rsa, n, e, nullptr)); // TODO: Next n.release(); e.release(); diff --git a/src/crypto/test/crypto.cpp b/src/crypto/test/crypto.cpp index 593a2be162d3..db26e9b1254f 100644 --- a/src/crypto/test/crypto.cpp +++ b/src/crypto/test/crypto.cpp @@ -849,6 +849,10 @@ TEST_CASE("PEM to JWK and back") auto kp2 = make_rsa_key_pair(jwk); auto jwk2 = kp2->private_key_jwk_rsa(kid); + + LOG_FAIL_FMT("jwk: {}", nlohmann::json(jwk).dump()); + LOG_FAIL_FMT("jwk2: {}", nlohmann::json(jwk2).dump()); + REQUIRE(jwk == jwk2); } } From 9e2459e3dfbf39da2714d16e8b64586090e9a3b1 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Wed, 26 Jul 2023 13:46:32 +0000 Subject: [PATCH 24/57] Almost there! --- src/crypto/openssl/rsa_key_pair.cpp | 34 ++------------------- src/crypto/openssl/rsa_public_key.cpp | 43 ++++++++++++++++++++++++++- src/crypto/openssl/rsa_public_key.h | 5 ++++ 3 files changed, 50 insertions(+), 32 deletions(-) diff --git a/src/crypto/openssl/rsa_key_pair.cpp b/src/crypto/openssl/rsa_key_pair.cpp index de8700b3bbe7..039af2326973 100644 --- a/src/crypto/openssl/rsa_key_pair.cpp +++ b/src/crypto/openssl/rsa_key_pair.cpp @@ -93,23 +93,13 @@ namespace crypto BN_bn2nativepad(qi, qi_raw_native.data(), qi_raw_native.size())); #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 - Unique_BIGNUM n, e; - auto n_raw = raw_from_b64url(jwk.n); - auto e_raw = raw_from_b64url(jwk.e); - CHECKNULL(BN_bin2bn(n_raw.data(), n_raw.size(), n)); - CHECKNULL(BN_bin2bn(e_raw.data(), e_raw.size(), e)); - - std::vector n_raw_native(n_raw.size()); - CHECKPOSITIVE(BN_bn2nativepad(n, n_raw_native.data(), n_raw_native.size())); - - std::vector e_raw_native(e_raw.size()); - CHECKPOSITIVE(BN_bn2nativepad(e, e_raw_native.data(), e_raw_native.size())); + auto [n_raw, e_raw] = RSAPublicKey_OpenSSL::rsa_public_raw_from_jwk(jwk); OSSL_PARAM params[9]; params[0] = OSSL_PARAM_construct_BN( - OSSL_PKEY_PARAM_RSA_N, n_raw_native.data(), n_raw_native.size()); + OSSL_PKEY_PARAM_RSA_N, n_raw.data(), n_raw.size()); params[1] = OSSL_PARAM_construct_BN( - OSSL_PKEY_PARAM_RSA_E, e_raw_native.data(), e_raw_native.size()); + OSSL_PKEY_PARAM_RSA_E, e_raw.data(), e_raw.size()); params[2] = OSSL_PARAM_construct_BN( OSSL_PKEY_PARAM_RSA_D, d_raw_native.data(), d_raw_native.size()); params[3] = OSSL_PARAM_construct_BN( @@ -128,29 +118,11 @@ namespace crypto OSSL_PKEY_PARAM_RSA_COEFFICIENT1, qi_raw_native.data(), qi_raw_native.size()); - // params[1] = OSSL_PARAM_construct_octet_string( - // OSSL_PKEY_PARAM_PUB_KEY, pub_buf.data(), pub_buf.size()); - // params[2] = OSSL_PARAM_construct_BN( - // OSSL_PKEY_PARAM_PRIV_KEY, d_raw_native.data(), d_raw_native.size()); params[8] = OSSL_PARAM_construct_end(); EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); CHECK1(EVP_PKEY_fromdata_init(pctx)); CHECK1(EVP_PKEY_fromdata(pctx, &key, EVP_PKEY_KEYPAIR, params)); - - LOG_FAIL_FMT("success"); - - // r.n = bn_bytes(get_bn_param(OSSL_PKEY_PARAM_RSA_N)); - // r.e = bn_bytes(get_bn_param(OSSL_PKEY_PARAM_RSA_E)); - - // d = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_D); - // p = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_FACTOR1); - // q = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_FACTOR2); - // dp = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_EXPONENT1); - // dq = RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_EXPONENT2); - // qi = - // RSAPublicKey_OpenSSL::get_bn_param(OSSL_PKEY_PARAM_RSA_COEFFICIENT1); - #else auto rsa = RSAPublicKey_OpenSSL::rsa_public_from_jwk(jwk); CHECK1(RSA_set0_key(rsa, nullptr, nullptr, d)); diff --git a/src/crypto/openssl/rsa_public_key.cpp b/src/crypto/openssl/rsa_public_key.cpp index 1026023379c6..179518622275 100644 --- a/src/crypto/openssl/rsa_public_key.cpp +++ b/src/crypto/openssl/rsa_public_key.cpp @@ -59,6 +59,31 @@ namespace crypto RSA_free(rsa); } +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + std::pair, std::vector> RSAPublicKey_OpenSSL:: + rsa_public_raw_from_jwk(const JsonWebKeyRSAPublic& jwk) + { + if (jwk.kty != JsonWebKeyType::RSA) + { + throw std::logic_error( + "Cannot construct RSA public key from non-RSA JWK"); + } + + Unique_BIGNUM n, e; + auto n_raw = raw_from_b64url(jwk.n); + auto e_raw = raw_from_b64url(jwk.e); + CHECKNULL(BN_bin2bn(n_raw.data(), n_raw.size(), n)); + CHECKNULL(BN_bin2bn(e_raw.data(), e_raw.size(), e)); + + std::pair, std::vector> r( + n_raw.size(), e_raw.size()); + + CHECKPOSITIVE(BN_bn2nativepad(n, r.first.data(), r.first.size())); + CHECKPOSITIVE(BN_bn2nativepad(e, r.second.data(), r.second.size())); + + return r; + } +#else OpenSSL::Unique_RSA RSAPublicKey_OpenSSL::rsa_public_from_jwk( const JsonWebKeyRSAPublic& jwk) { @@ -81,11 +106,27 @@ namespace crypto return rsa; } +#endif RSAPublicKey_OpenSSL::RSAPublicKey_OpenSSL(const JsonWebKeyRSAPublic& jwk) { key = EVP_PKEY_new(); - CHECK1(EVP_PKEY_set1_RSA(key, rsa_public_from_jwk(jwk))); // TODO: Next +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + auto [n_raw, e_raw] = rsa_public_raw_from_jwk(jwk); + + OSSL_PARAM params[3]; + params[0] = OSSL_PARAM_construct_BN( + OSSL_PKEY_PARAM_RSA_N, n_raw.data(), n_raw.size()); + params[1] = OSSL_PARAM_construct_BN( + OSSL_PKEY_PARAM_RSA_E, e_raw.data(), e_raw.size()); + params[2] = OSSL_PARAM_construct_end(); + + EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + CHECK1(EVP_PKEY_fromdata_init(pctx)); + CHECK1(EVP_PKEY_fromdata(pctx, &key, EVP_PKEY_PUBLIC_KEY, params)); +#else + CHECK1(EVP_PKEY_set1_RSA(key, rsa_public_from_jwk(jwk))); +#endif } size_t RSAPublicKey_OpenSSL::key_size() const diff --git a/src/crypto/openssl/rsa_public_key.h b/src/crypto/openssl/rsa_public_key.h index 5db482c5ec06..afe3164fa8aa 100644 --- a/src/crypto/openssl/rsa_public_key.h +++ b/src/crypto/openssl/rsa_public_key.h @@ -16,7 +16,12 @@ namespace crypto class RSAPublicKey_OpenSSL : public PublicKey_OpenSSL, public RSAPublicKey { protected: +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + std::pair, std::vector> + rsa_public_raw_from_jwk(const JsonWebKeyRSAPublic& jwk); +#else OpenSSL::Unique_RSA rsa_public_from_jwk(const JsonWebKeyRSAPublic& jwk); +#endif public: RSAPublicKey_OpenSSL() = default; From b8e0e3212bf4081c1404b5cca9da126508f95409 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Wed, 26 Jul 2023 13:57:23 +0000 Subject: [PATCH 25/57] Cleanup --- src/crypto/openssl/rsa_public_key.cpp | 38 ++++++++++++--------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/src/crypto/openssl/rsa_public_key.cpp b/src/crypto/openssl/rsa_public_key.cpp index 179518622275..77c95c59c308 100644 --- a/src/crypto/openssl/rsa_public_key.cpp +++ b/src/crypto/openssl/rsa_public_key.cpp @@ -59,24 +59,30 @@ namespace crypto RSA_free(rsa); } -#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 - std::pair, std::vector> RSAPublicKey_OpenSSL:: - rsa_public_raw_from_jwk(const JsonWebKeyRSAPublic& jwk) + std::pair get_modulus_and_exponent( + const JsonWebKeyRSAPublic& jwk) { if (jwk.kty != JsonWebKeyType::RSA) { - throw std::logic_error( - "Cannot construct RSA public key from non-RSA JWK"); + throw std::logic_error("Cannot construct public key from non-RSA JWK"); } - Unique_BIGNUM n, e; + std::pair ne; auto n_raw = raw_from_b64url(jwk.n); auto e_raw = raw_from_b64url(jwk.e); - CHECKNULL(BN_bin2bn(n_raw.data(), n_raw.size(), n)); - CHECKNULL(BN_bin2bn(e_raw.data(), e_raw.size(), e)); + OpenSSL::CHECKNULL(BN_bin2bn(n_raw.data(), n_raw.size(), ne.first)); + OpenSSL::CHECKNULL(BN_bin2bn(e_raw.data(), e_raw.size(), ne.second)); + return ne; + } + +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + std::pair, std::vector> RSAPublicKey_OpenSSL:: + rsa_public_raw_from_jwk(const JsonWebKeyRSAPublic& jwk) + { + auto [n, e] = get_modulus_and_exponent(jwk); std::pair, std::vector> r( - n_raw.size(), e_raw.size()); + BN_num_bytes(n), BN_num_bytes(e)); CHECKPOSITIVE(BN_bn2nativepad(n, r.first.data(), r.first.size())); CHECKPOSITIVE(BN_bn2nativepad(e, r.second.data(), r.second.size())); @@ -87,20 +93,10 @@ namespace crypto OpenSSL::Unique_RSA RSAPublicKey_OpenSSL::rsa_public_from_jwk( const JsonWebKeyRSAPublic& jwk) { - if (jwk.kty != JsonWebKeyType::RSA) - { - throw std::logic_error( - "Cannot construct RSA public key from non-RSA JWK"); - } - - Unique_BIGNUM e, n; - auto e_raw = raw_from_b64url(jwk.e); - auto n_raw = raw_from_b64url(jwk.n); - OpenSSL::CHECKNULL(BN_bin2bn(e_raw.data(), e_raw.size(), e)); - OpenSSL::CHECKNULL(BN_bin2bn(n_raw.data(), n_raw.size(), n)); + auto [n, e] = get_modulus_and_exponent(jwk); Unique_RSA rsa; - CHECK1(RSA_set0_key(rsa, n, e, nullptr)); // TODO: Next + CHECK1(RSA_set0_key(rsa, n, e, nullptr)); n.release(); e.release(); From 484b6a54e83b06809d91bd170be7f22eca52a4da Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Thu, 27 Jul 2023 16:45:47 +0000 Subject: [PATCH 26/57] WIP --- src/crypto/openssl/rsa_public_key.cpp | 43 +++++++++++++-- src/crypto/test/crypto.cpp | 78 ++++++++++++++------------- 2 files changed, 81 insertions(+), 40 deletions(-) diff --git a/src/crypto/openssl/rsa_public_key.cpp b/src/crypto/openssl/rsa_public_key.cpp index 77c95c59c308..185bb90d805c 100644 --- a/src/crypto/openssl/rsa_public_key.cpp +++ b/src/crypto/openssl/rsa_public_key.cpp @@ -7,6 +7,7 @@ #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 # include +# include #endif namespace crypto @@ -41,7 +42,42 @@ namespace crypto RSAPublicKey_OpenSSL::RSAPublicKey_OpenSSL(const std::vector& der) { - const unsigned char* pp = der.data(); + LOG_FAIL_FMT("RSAPublicKey_OpenSSL from DER"); + unsigned char* pp = (unsigned char*)der.data(); + size_t s = der.size(); + key = EVP_PKEY_new(); +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + // // TODO: Use this for 1.1.1 too? + + OSSL_DECODER_CTX* ctx = OSSL_DECODER_CTX_new_for_pkey( + key, EVP_PKEY_PUBLIC_KEY, "DER", "SubjectPublicKeyInfo", NULL); + + if (ctx == NULL) + { + /* fatal error handling */ + LOG_FAIL_FMT("ctx is null"); + } + if (OSSL_ENCODER_CTX_get_num_encoders(ctx) == 0) + { + OSSL_ENCODER_CTX_free(ctx); + /* non-fatal error handling */ + LOG_FAIL_FMT("ctx num"); + } + if (!OSSL_ENCODER_to_data(ctx, &pp, &s)) + { + OSSL_ENCODER_CTX_free(ctx); + /* error handling */ + } + OSSL_ENCODER_CTX_free(ctx); + + // key = d2i_PublicKey(EVP_PKEY_RSA, &key, &pp, der.size()); + // if (key == nullptr) + // { + // unsigned long ec = ERR_get_error(); + // auto msg = OpenSSL::error_string(ec); + // throw std::runtime_error(fmt::format("OpenSSL error: {}", msg)); + // } +#else RSA* rsa = nullptr; if ( ((rsa = d2i_RSA_PUBKEY(NULL, &pp, der.size())) == @@ -54,9 +90,10 @@ namespace crypto throw std::runtime_error(fmt::format("OpenSSL error: {}", msg)); } - key = EVP_PKEY_new(); - OpenSSL::CHECK1(EVP_PKEY_set1_RSA(key, rsa)); // TODO: Next + OpenSSL::CHECK1(EVP_PKEY_set1_RSA(key, rsa)); RSA_free(rsa); +#endif + LOG_FAIL_FMT("success"); } std::pair get_modulus_and_exponent( diff --git a/src/crypto/test/crypto.cpp b/src/crypto/test/crypto.cpp index db26e9b1254f..b43075c257c0 100644 --- a/src/crypto/test/crypto.cpp +++ b/src/crypto/test/crypto.cpp @@ -784,43 +784,41 @@ TEST_CASE("PEM to JWK and back") auto kid = "my_kid"; logger::config::default_init(); - LOG_FAIL_FMT("here"); - - // INFO("EC"); - // { - // auto curves = {CurveID::SECP384R1, CurveID::SECP256R1, - // CurveID::SECP256K1}; - - // for (auto const& curve : curves) - // { - // auto kp = make_key_pair(curve); - // auto pubk = make_public_key(kp->public_key_pem()); - - // INFO("Public"); - // { - // auto jwk = pubk->public_key_jwk(); - // REQUIRE_FALSE(jwk.kid.has_value()); - // jwk = pubk->public_key_jwk(kid); - // REQUIRE(jwk.kid.value() == kid); - - // auto pubk2 = make_public_key(jwk); - // auto jwk2 = pubk2->public_key_jwk(kid); - // REQUIRE(jwk == jwk2); - // } - - // INFO("Private"); - // { - // auto jwk = kp->private_key_jwk(); - // REQUIRE_FALSE(jwk.kid.has_value()); - // jwk = kp->private_key_jwk(kid); - // REQUIRE(jwk.kid.value() == kid); - - // auto kp2 = make_key_pair(jwk); - // auto jwk2 = kp2->private_key_jwk(kid); - // REQUIRE(jwk == jwk2); - // } - // } - // } + + INFO("EC"); + { + auto curves = {CurveID::SECP384R1, CurveID::SECP256R1, CurveID::SECP256K1}; + + for (auto const& curve : curves) + { + auto kp = make_key_pair(curve); + auto pubk = make_public_key(kp->public_key_pem()); + + INFO("Public"); + { + auto jwk = pubk->public_key_jwk(); + REQUIRE_FALSE(jwk.kid.has_value()); + jwk = pubk->public_key_jwk(kid); + REQUIRE(jwk.kid.value() == kid); + + auto pubk2 = make_public_key(jwk); + auto jwk2 = pubk2->public_key_jwk(kid); + REQUIRE(jwk == jwk2); + } + + INFO("Private"); + { + auto jwk = kp->private_key_jwk(); + REQUIRE_FALSE(jwk.kid.has_value()); + jwk = kp->private_key_jwk(kid); + REQUIRE(jwk.kid.value() == kid); + + auto kp2 = make_key_pair(jwk); + auto jwk2 = kp2->private_key_jwk(kid); + REQUIRE(jwk == jwk2); + } + } + } INFO("RSA"); { @@ -828,6 +826,12 @@ TEST_CASE("PEM to JWK and back") auto pubk = make_rsa_public_key(kp->public_key_pem()); + INFO("DER"); + { + auto pubk_der = make_rsa_public_key(kp->public_key_der()); + REQUIRE(pubk_der->public_key_pem() == kp->public_key_pem()); + } + INFO("Public"); { auto jwk = pubk->public_key_jwk_rsa(); From c2dbe894fe074a99966d4008270f99f7dd2b3428 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 28 Jul 2023 09:45:46 +0000 Subject: [PATCH 27/57] Last fix --- src/crypto/openssl/rsa_public_key.cpp | 46 ++------------------------- 1 file changed, 3 insertions(+), 43 deletions(-) diff --git a/src/crypto/openssl/rsa_public_key.cpp b/src/crypto/openssl/rsa_public_key.cpp index 185bb90d805c..4497f9de77c4 100644 --- a/src/crypto/openssl/rsa_public_key.cpp +++ b/src/crypto/openssl/rsa_public_key.cpp @@ -42,58 +42,18 @@ namespace crypto RSAPublicKey_OpenSSL::RSAPublicKey_OpenSSL(const std::vector& der) { - LOG_FAIL_FMT("RSAPublicKey_OpenSSL from DER"); - unsigned char* pp = (unsigned char*)der.data(); - size_t s = der.size(); + const unsigned char* pp = der.data(); key = EVP_PKEY_new(); -#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 - // // TODO: Use this for 1.1.1 too? - - OSSL_DECODER_CTX* ctx = OSSL_DECODER_CTX_new_for_pkey( - key, EVP_PKEY_PUBLIC_KEY, "DER", "SubjectPublicKeyInfo", NULL); - - if (ctx == NULL) - { - /* fatal error handling */ - LOG_FAIL_FMT("ctx is null"); - } - if (OSSL_ENCODER_CTX_get_num_encoders(ctx) == 0) - { - OSSL_ENCODER_CTX_free(ctx); - /* non-fatal error handling */ - LOG_FAIL_FMT("ctx num"); - } - if (!OSSL_ENCODER_to_data(ctx, &pp, &s)) - { - OSSL_ENCODER_CTX_free(ctx); - /* error handling */ - } - OSSL_ENCODER_CTX_free(ctx); - - // key = d2i_PublicKey(EVP_PKEY_RSA, &key, &pp, der.size()); - // if (key == nullptr) - // { - // unsigned long ec = ERR_get_error(); - // auto msg = OpenSSL::error_string(ec); - // throw std::runtime_error(fmt::format("OpenSSL error: {}", msg)); - // } -#else - RSA* rsa = nullptr; if ( - ((rsa = d2i_RSA_PUBKEY(NULL, &pp, der.size())) == + ((key = d2i_PUBKEY(&key, &pp, der.size())) == NULL) && // "SubjectPublicKeyInfo structure" format - ((rsa = d2i_RSAPublicKey(NULL, &pp, der.size())) == + ((key = d2i_PublicKey(EVP_PKEY_RSA, &key, &pp, der.size())) == NULL)) // PKCS#1 structure format { unsigned long ec = ERR_get_error(); auto msg = OpenSSL::error_string(ec); throw std::runtime_error(fmt::format("OpenSSL error: {}", msg)); } - - OpenSSL::CHECK1(EVP_PKEY_set1_RSA(key, rsa)); - RSA_free(rsa); -#endif - LOG_FAIL_FMT("success"); } std::pair get_modulus_and_exponent( From 6c557b07cb36d0c1baab7d8a756ff85a03a70f14 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 28 Jul 2023 09:54:02 +0000 Subject: [PATCH 28/57] fmt --- CHANGELOG.md | 1 - cmake/ccf_app.cmake | 25 ++++++++-------- cmake/crypto.cmake | 62 +++++++++++++++++++++++----------------- cmake/open_enclave.cmake | 5 ++-- cmake/t_cose.cmake | 14 +++++---- 5 files changed, 58 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 294ffc6cd4fd..74fc13f58e1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. [4.0.5]: https://github.com/microsoft/CCF/releases/tag/ccf-4.0.5 - Debug logging is now available in non-SGX builds by default, and controlled by a run-time CLI argument (`--enclave-log-level`). On SGX this remains a build-time decision (#5375). -- Updated Open Enclave to [0.19.2](https://github.com/openenclave/openenclave/releases/tag/v0.19.2). - Supporting intermediate cert chain included in TLS handshake, where previously only server leaf certificate was present (#5453). - Added `getVersionOfPreviousWrite` to TypeScript `TypedKvMap` interface (#5451). diff --git a/cmake/ccf_app.cmake b/cmake/ccf_app.cmake index b871002d919e..e46c71699023 100644 --- a/cmake/ccf_app.cmake +++ b/cmake/ccf_app.cmake @@ -5,16 +5,16 @@ set(ALLOWED_TARGETS "sgx;snp;virtual") if(NOT DEFINED COMPILE_TARGET) set(COMPILE_TARGET - "sgx" - CACHE STRING - "Target compilation platforms, Choose from: ${ALLOWED_TARGETS}" + "sgx" + CACHE STRING + "Target compilation platforms, Choose from: ${ALLOWED_TARGETS}" ) endif() if(NOT COMPILE_TARGET IN_LIST ALLOWED_TARGETS) message( FATAL_ERROR - "${REQUESTED_TARGET} is not a valid target. Choose from: ${ALLOWED_TARGETS}" + "${REQUESTED_TARGET} is not a valid target. Choose from: ${ALLOWED_TARGETS}" ) endif() message(STATUS "Compile target platform: ${COMPILE_TARGET}") @@ -42,9 +42,9 @@ function(sign_app_library name app_oe_conf_path enclave_sign_key_path) # Add Debug=1 line COMMAND echo "Debug=1" >> ${DEBUG_CONF_NAME} COMMAND - openenclave::oesign sign -e ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so -c - ${DEBUG_CONF_NAME} -k ${enclave_sign_key_path} -o - ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so.debuggable + openenclave::oesign sign -e ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so -c + ${DEBUG_CONF_NAME} -k ${enclave_sign_key_path} -o + ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so.debuggable DEPENDS ${name} ${app_oe_conf_path} ${enclave_sign_key_path} ) @@ -65,8 +65,8 @@ function(sign_app_library name app_oe_conf_path enclave_sign_key_path) # Add Debug=0 line COMMAND echo "Debug=0" >> ${SIGNED_CONF_NAME} COMMAND - openenclave::oesign sign -e ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so -c - ${SIGNED_CONF_NAME} -k ${enclave_sign_key_path} + openenclave::oesign sign -e ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so -c + ${SIGNED_CONF_NAME} -k ${enclave_sign_key_path} DEPENDS ${name} ${app_oe_conf_path} ${enclave_sign_key_path} ) @@ -77,10 +77,10 @@ function(sign_app_library name app_oe_conf_path enclave_sign_key_path) if(${PARSED_ARGS_INSTALL_LIBS}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so.debuggable - DESTINATION lib + DESTINATION lib ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lib${name}.so.signed - DESTINATION lib + DESTINATION lib ) endif() endif() @@ -113,7 +113,7 @@ function(add_ccf_app name) add_warning_checks(${enc_name}) target_link_libraries( ${enc_name} PRIVATE ${PARSED_ARGS_LINK_LIBS_ENCLAVE} - ${OE_TARGET_ENCLAVE_CORE_LIBS} ccf.enclave + ${OE_TARGET_ENCLAVE_CORE_LIBS} ccf.enclave ) set_property(TARGET ${enc_name} PROPERTY POSITION_INDEPENDENT_CODE ON) @@ -228,7 +228,6 @@ if(COMPILE_TARGET STREQUAL "sgx") target_compile_options(${name} PUBLIC -nostdinc -nostdinc++) target_compile_definitions( ${name} PUBLIC INSIDE_ENCLAVE _LIBCPP_HAS_THREAD_API_PTHREAD - # OPENSSL_API_COMPAT=0x10101000L ) target_link_libraries(${name} PUBLIC ${OE_TARGET_ENCLAVE_AND_STD} -lgcc) diff --git a/cmake/crypto.cmake b/cmake/crypto.cmake index 794a58f7c818..dfe0279c9892 100644 --- a/cmake/crypto.cmake +++ b/cmake/crypto.cmake @@ -2,28 +2,28 @@ # Licensed under the Apache 2.0 License. set(CCFCRYPTO_SRC - ${CCF_DIR}/src/crypto/base64.cpp - ${CCF_DIR}/src/crypto/entropy.cpp - ${CCF_DIR}/src/crypto/hash.cpp - ${CCF_DIR}/src/crypto/sha256_hash.cpp - ${CCF_DIR}/src/crypto/symmetric_key.cpp - ${CCF_DIR}/src/crypto/key_pair.cpp - ${CCF_DIR}/src/crypto/eddsa_key_pair.cpp - ${CCF_DIR}/src/crypto/rsa_key_pair.cpp - ${CCF_DIR}/src/crypto/verifier.cpp - ${CCF_DIR}/src/crypto/key_wrap.cpp - ${CCF_DIR}/src/crypto/hmac.cpp - ${CCF_DIR}/src/crypto/ecdsa.cpp - ${CCF_DIR}/src/crypto/openssl/symmetric_key.cpp - ${CCF_DIR}/src/crypto/openssl/public_key.cpp - ${CCF_DIR}/src/crypto/openssl/key_pair.cpp - ${CCF_DIR}/src/crypto/openssl/eddsa_public_key.cpp - ${CCF_DIR}/src/crypto/openssl/eddsa_key_pair.cpp - ${CCF_DIR}/src/crypto/openssl/hash.cpp - ${CCF_DIR}/src/crypto/openssl/rsa_public_key.cpp - ${CCF_DIR}/src/crypto/openssl/rsa_key_pair.cpp - ${CCF_DIR}/src/crypto/openssl/verifier.cpp - ${CCF_DIR}/src/crypto/openssl/cose_verifier.cpp + ${CCF_DIR}/src/crypto/base64.cpp + ${CCF_DIR}/src/crypto/entropy.cpp + ${CCF_DIR}/src/crypto/hash.cpp + ${CCF_DIR}/src/crypto/sha256_hash.cpp + ${CCF_DIR}/src/crypto/symmetric_key.cpp + ${CCF_DIR}/src/crypto/key_pair.cpp + ${CCF_DIR}/src/crypto/eddsa_key_pair.cpp + ${CCF_DIR}/src/crypto/rsa_key_pair.cpp + ${CCF_DIR}/src/crypto/verifier.cpp + ${CCF_DIR}/src/crypto/key_wrap.cpp + ${CCF_DIR}/src/crypto/hmac.cpp + ${CCF_DIR}/src/crypto/ecdsa.cpp + ${CCF_DIR}/src/crypto/openssl/symmetric_key.cpp + ${CCF_DIR}/src/crypto/openssl/public_key.cpp + ${CCF_DIR}/src/crypto/openssl/key_pair.cpp + ${CCF_DIR}/src/crypto/openssl/eddsa_public_key.cpp + ${CCF_DIR}/src/crypto/openssl/eddsa_key_pair.cpp + ${CCF_DIR}/src/crypto/openssl/hash.cpp + ${CCF_DIR}/src/crypto/openssl/rsa_public_key.cpp + ${CCF_DIR}/src/crypto/openssl/rsa_key_pair.cpp + ${CCF_DIR}/src/crypto/openssl/verifier.cpp + ${CCF_DIR}/src/crypto/openssl/cose_verifier.cpp ) if(COMPILE_TARGET STREQUAL "sgx") @@ -61,19 +61,27 @@ find_library(TLS_LIBRARY ssl "${OPENSSL_INSTALL_PATH}/lib64") add_library(ccfcrypto.host STATIC ${CCFCRYPTO_SRC}) add_san(ccfcrypto.host) -target_compile_options(ccfcrypto.host PUBLIC ${COMPILE_LIBCXX} "-Wno-deprecated-declarations") +target_compile_options(ccfcrypto.host PUBLIC ${COMPILE_LIBCXX} +)# "-Wno-deprecated-declarations") -# target_compile_definitions(ccfcrypto.host PUBLIC OPENSSL_API_COMPAT=0x10101000L) +# target_compile_definitions(ccfcrypto.host PUBLIC +# OPENSSL_API_COMPAT=0x10101000L) target_link_options(ccfcrypto.host PUBLIC ${LINK_LIBCXX}) -target_include_directories(ccfcrypto.host PRIVATE "${OPENSSL_INSTALL_PATH}/include") +target_include_directories( + ccfcrypto.host PRIVATE "${OPENSSL_INSTALL_PATH}/include" +) target_link_libraries(ccfcrypto.host PUBLIC qcbor.host) target_link_libraries(ccfcrypto.host PUBLIC t_cose.host) # target_link_libraries(ccfcrypto.host PUBLIC crypto) # target_link_libraries(ccfcrypto.host PUBLIC ssl) -target_link_libraries(ccfcrypto.host PUBLIC "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") -target_link_libraries(ccfcrypto.host PUBLIC "${OPENSSL_INSTALL_PATH}/lib64/libssl.so") +target_link_libraries( + ccfcrypto.host PUBLIC "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so" +) +target_link_libraries( + ccfcrypto.host PUBLIC "${OPENSSL_INSTALL_PATH}/lib64/libssl.so" +) set_property(TARGET ccfcrypto.host PROPERTY POSITION_INDEPENDENT_CODE ON) if(INSTALL_VIRTUAL_LIBRARIES) diff --git a/cmake/open_enclave.cmake b/cmake/open_enclave.cmake index 320b90c89537..c98bd15c1987 100644 --- a/cmake/open_enclave.cmake +++ b/cmake/open_enclave.cmake @@ -27,9 +27,8 @@ if(REQUIRE_OPENENCLAVE) # OpenEnclave_INCLUDE_DIRS if(COMPILE_TARGET STREQUAL "sgx") set(OE_TARGET_LIBC openenclave::oelibc) - set(OE_TARGET_ENCLAVE_AND_STD - openenclave::oeenclave openenclave::oelibcxx openenclave::oelibc - ${OE_OPENSSL_LIBRARY} + set(OE_TARGET_ENCLAVE_AND_STD openenclave::oeenclave openenclave::oelibcxx + openenclave::oelibc ${OE_OPENSSL_LIBRARY} ) # These oe libraries must be linked in specific order diff --git a/cmake/t_cose.cmake b/cmake/t_cose.cmake index b1fdcb4c1a7e..6b86644eebcb 100644 --- a/cmake/t_cose.cmake +++ b/cmake/t_cose.cmake @@ -14,9 +14,9 @@ set(T_COSE_SRCS ) if(COMPILE_TARGET STREQUAL "sgx") add_enclave_library_c(t_cose.enclave ${T_COSE_SRCS}) - target_compile_definitions( - t_cose.enclave PRIVATE ${T_COSE_DEFS})# OPENSSL_API_COMPAT=0x10101000L - #) + target_compile_definitions(t_cose.enclave PRIVATE ${T_COSE_DEFS} + )# OPENSSL_API_COMPAT=0x10101000L + # ) target_compile_options(t_cose.enclave INTERFACE ${T_COSE_OPTS_INTERFACE}) target_include_directories(t_cose.enclave PRIVATE "${T_COSE_SRC}") @@ -49,7 +49,9 @@ elseif(COMPILE_TARGET STREQUAL "snp") $ ) - target_link_libraries(t_cose.snp PUBLIC qcbor.snp "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") + target_link_libraries( + t_cose.snp PUBLIC qcbor.snp "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so" + ) set_property(TARGET t_cose.snp PROPERTY POSITION_INDEPENDENT_CODE ON) add_san(t_cose.snp) @@ -72,7 +74,9 @@ target_include_directories( $ ) -target_link_libraries(t_cose.host PUBLIC qcbor.host "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so") +target_link_libraries( + t_cose.host PUBLIC qcbor.host "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so" +) set_property(TARGET t_cose.host PROPERTY POSITION_INDEPENDENT_CODE ON) add_san(t_cose.host) From 40e452851db3a0c2f961c1b00096e47e76f1a021 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 28 Jul 2023 09:57:59 +0000 Subject: [PATCH 29/57] More cleanup before PR --- cmake/ccf_app.cmake | 1 - cmake/common.cmake | 2 +- cmake/t_cose.cmake | 11 +- src/crypto/test/crypto.cpp | 5 - tests/js-modules/modules.py | 918 ++++++++++++++++++------------------ 5 files changed, 463 insertions(+), 474 deletions(-) diff --git a/cmake/ccf_app.cmake b/cmake/ccf_app.cmake index e46c71699023..71fcba0e40e6 100644 --- a/cmake/ccf_app.cmake +++ b/cmake/ccf_app.cmake @@ -228,7 +228,6 @@ if(COMPILE_TARGET STREQUAL "sgx") target_compile_options(${name} PUBLIC -nostdinc -nostdinc++) target_compile_definitions( ${name} PUBLIC INSIDE_ENCLAVE _LIBCPP_HAS_THREAD_API_PTHREAD - # OPENSSL_API_COMPAT=0x10101000L ) target_link_libraries(${name} PUBLIC ${OE_TARGET_ENCLAVE_AND_STD} -lgcc) set_property(TARGET ${name} PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/cmake/common.cmake b/cmake/common.cmake index 2921a974db4f..148c9560fb00 100644 --- a/cmake/common.cmake +++ b/cmake/common.cmake @@ -10,7 +10,7 @@ function(add_unit_test name) ) enable_coverage(${name}) target_link_libraries(${name} PRIVATE ${LINK_LIBCXX} ccfcrypto.host -pthread) - # link_openenclave_host(${name}) + link_openenclave_host(${name}) add_san(${name}) add_test(NAME ${name} COMMAND ${name}) diff --git a/cmake/t_cose.cmake b/cmake/t_cose.cmake index 6b86644eebcb..9405e646f1df 100644 --- a/cmake/t_cose.cmake +++ b/cmake/t_cose.cmake @@ -15,8 +15,7 @@ set(T_COSE_SRCS if(COMPILE_TARGET STREQUAL "sgx") add_enclave_library_c(t_cose.enclave ${T_COSE_SRCS}) target_compile_definitions(t_cose.enclave PRIVATE ${T_COSE_DEFS} - )# OPENSSL_API_COMPAT=0x10101000L - # ) + ) target_compile_options(t_cose.enclave INTERFACE ${T_COSE_OPTS_INTERFACE}) target_include_directories(t_cose.enclave PRIVATE "${T_COSE_SRC}") @@ -49,9 +48,7 @@ elseif(COMPILE_TARGET STREQUAL "snp") $ ) - target_link_libraries( - t_cose.snp PUBLIC qcbor.snp "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so" - ) + target_link_libraries(t_cose.snp PUBLIC qcbor.snp crypto) set_property(TARGET t_cose.snp PROPERTY POSITION_INDEPENDENT_CODE ON) add_san(t_cose.snp) @@ -74,9 +71,7 @@ target_include_directories( $ ) -target_link_libraries( - t_cose.host PUBLIC qcbor.host "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so" -) +target_link_libraries(t_cose.host PUBLIC qcbor.host crypto) set_property(TARGET t_cose.host PROPERTY POSITION_INDEPENDENT_CODE ON) add_san(t_cose.host) diff --git a/src/crypto/test/crypto.cpp b/src/crypto/test/crypto.cpp index b43075c257c0..d2f80311511c 100644 --- a/src/crypto/test/crypto.cpp +++ b/src/crypto/test/crypto.cpp @@ -783,8 +783,6 @@ TEST_CASE("PEM to JWK and back") // to compare with JWK reference implementation. auto kid = "my_kid"; - logger::config::default_init(); - INFO("EC"); { auto curves = {CurveID::SECP384R1, CurveID::SECP256R1, CurveID::SECP256K1}; @@ -854,9 +852,6 @@ TEST_CASE("PEM to JWK and back") auto kp2 = make_rsa_key_pair(jwk); auto jwk2 = kp2->private_key_jwk_rsa(kid); - LOG_FAIL_FMT("jwk: {}", nlohmann::json(jwk).dump()); - LOG_FAIL_FMT("jwk2: {}", nlohmann::json(jwk2).dump()); - REQUIRE(jwk == jwk2); } } diff --git a/tests/js-modules/modules.py b/tests/js-modules/modules.py index f72b6a6cafe0..b945956e8d05 100644 --- a/tests/js-modules/modules.py +++ b/tests/js-modules/modules.py @@ -481,461 +481,461 @@ def test_npm_app(network, args): LOG.info("Calling npm app endpoints") with primary.client("user0") as c: - # body = [1, 2, 3, 4] - # r = c.post("/app/partition", body) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert r.body.json() == [[1, 3], [2, 4]], r.body - - # r = c.post("/app/proto", body) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert r.headers["content-type"] == "application/x-protobuf" - # # We could now decode the protobuf message but given all the machinery - # # involved to make it happen (code generation with protoc) we'll leave it at that. - # assert len(r.body) == 14, len(r.body) - - # r = c.get("/app/crypto") - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert r.body.json()["available"], r.body - - # key_size = 256 - # r = c.post("/app/generateAesKey", {"size": key_size}) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert len(r.body.data()) == key_size // 8 - # assert r.body.data() != b"\x00" * (key_size // 8) - - # r = c.post("/app/generateRsaKeyPair", {"size": 2048}) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert infra.crypto.check_key_pair_pem( - # r.body.json()["privateKey"], r.body.json()["publicKey"] - # ) - - # r = c.post("/app/generateEcdsaKeyPair", {"curve": "secp256r1"}) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert infra.crypto.check_key_pair_pem( - # r.body.json()["privateKey"], r.body.json()["publicKey"] - # ) - - # r = c.post("/app/generateEcdsaKeyPair", {"curve": "secp256k1"}) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert infra.crypto.check_key_pair_pem( - # r.body.json()["privateKey"], r.body.json()["publicKey"] - # ) - - # r = c.post("/app/generateEcdsaKeyPair", {"curve": "secp384r1"}) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert infra.crypto.check_key_pair_pem( - # r.body.json()["privateKey"], r.body.json()["publicKey"] - # ) - - # r = c.post("/app/generateEddsaKeyPair", {"curve": "curve25519"}) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert infra.crypto.check_key_pair_pem( - # r.body.json()["privateKey"], r.body.json()["publicKey"] - # ) - - # aes_key_to_wrap = infra.crypto.generate_aes_key(256) - # wrapping_key_priv_pem, wrapping_key_pub_pem = infra.crypto.generate_rsa_keypair( - # 2048 - # ) - # label = "label42" - # r = c.post( - # "/app/wrapKey", - # { - # "key": b64encode(aes_key_to_wrap).decode(), - # "wrappingKey": b64encode(bytes(wrapping_key_pub_pem, "ascii")).decode(), - # "wrapAlgo": { - # "name": "RSA-OAEP", - # "label": b64encode(bytes(label, "ascii")).decode(), - # }, - # }, - # ) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # unwrapped = infra.crypto.unwrap_key_rsa_oaep( - # r.body.data(), wrapping_key_priv_pem, label.encode("ascii") - # ) - # assert unwrapped == aes_key_to_wrap - - # aes_wrapping_key = infra.crypto.generate_aes_key(256) - # r = c.post( - # "/app/wrapKey", - # { - # "key": b64encode(aes_key_to_wrap).decode(), - # "wrappingKey": b64encode(aes_wrapping_key).decode(), - # "wrapAlgo": {"name": "AES-KWP"}, - # }, - # ) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # unwrapped = infra.crypto.unwrap_key_aes_pad(r.body.data(), aes_wrapping_key) - # assert unwrapped == aes_key_to_wrap - - # wrapping_key_priv_pem, wrapping_key_pub_pem = infra.crypto.generate_rsa_keypair( - # 2048 - # ) - # label = "label44" - # r = c.post( - # "/app/wrapKey", - # { - # "key": b64encode(aes_key_to_wrap).decode(), - # "wrappingKey": b64encode(bytes(wrapping_key_pub_pem, "ascii")).decode(), - # "wrapAlgo": { - # "name": "RSA-OAEP-AES-KWP", - # "aesKeySize": 256, - # "label": b64encode(bytes(label, "ascii")).decode(), - # }, - # }, - # ) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # unwrapped = infra.crypto.unwrap_key_rsa_oaep_aes_pad( - # r.body.data(), wrapping_key_priv_pem, label.encode("ascii") - # ) - # assert unwrapped == aes_key_to_wrap - - # key_priv_pem, key_pub_pem = infra.crypto.generate_rsa_keypair(2048) - # algorithm = {"name": "RSASSA-PKCS1-v1_5", "hash": "SHA-256"} - # data = "foo".encode() - # r = c.post( - # "/app/sign", - # { - # "algorithm": algorithm, - # "key": key_priv_pem, - # "data": b64encode(data).decode(), - # }, - # ) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - - # signature = r.body.data() - # infra.crypto.verify_signature(algorithm, signature, data, key_pub_pem) - - # # Also verify with the JS API - # r = c.post( - # "/app/verifySignature", - # { - # "algorithm": algorithm, - # "key": key_pub_pem, - # "signature": b64encode(signature).decode(), - # "data": b64encode(data).decode(), - # }, - # ) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert r.body.json() is True, r.body - - # try: - # infra.crypto.verify_signature( - # algorithm, signature, "bar".encode(), key_pub_pem - # ) - # assert False, "verify_signature() should throw" - # except InvalidSignature: - # pass - - # curves = [ec.SECP256R1, ec.SECP256K1, ec.SECP384R1] - # for curve in curves: - # key_priv_pem, key_pub_pem = infra.crypto.generate_ec_keypair(curve) - # algorithm = {"name": "ECDSA", "hash": "SHA-256"} - # data = "foo".encode() - # r = c.post( - # "/app/sign", - # { - # "algorithm": algorithm, - # "key": key_priv_pem, - # "data": b64encode(data).decode(), - # }, - # ) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - - # signature = r.body.data() - # infra.crypto.verify_signature(algorithm, signature, data, key_pub_pem) - - # # Also verify with the JS API - # r = c.post( - # "/app/verifySignature", - # { - # "algorithm": algorithm, - # "key": key_pub_pem, - # "signature": b64encode(signature).decode(), - # "data": b64encode(data).decode(), - # }, - # ) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert r.body.json() is True, r.body - - # try: - # infra.crypto.verify_signature( - # algorithm, signature, "bar".encode(), key_pub_pem - # ) - # assert False, "verify_signature() should throw" - # except InvalidSignature: - # pass - - # key_priv_pem, key_pub_pem = infra.crypto.generate_eddsa_keypair() - # algorithm = {"name": "EdDSA"} - # data = "foo".encode() - # r = c.post( - # "/app/sign", - # { - # "algorithm": algorithm, - # "key": key_priv_pem, - # "data": b64encode(data).decode(), - # }, - # ) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - - # signature = r.body.data() - # infra.crypto.verify_signature(algorithm, signature, data, key_pub_pem) - - # # Also verify with the JS API - # r = c.post( - # "/app/verifySignature", - # { - # "algorithm": algorithm, - # "key": key_pub_pem, - # "signature": b64encode(signature).decode(), - # "data": b64encode(data).decode(), - # }, - # ) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert r.body.json() is True, r.body - - # try: - # infra.crypto.verify_signature( - # algorithm, signature, "bar".encode(), key_pub_pem - # ) - # assert False, "verify_signature() should throw" - # except InvalidSignature: - # pass - - # key_priv_pem, key_pub_pem = infra.crypto.generate_rsa_keypair(2048) - # algorithm = {"name": "RSASSA-PKCS1-v1_5", "hash": "SHA-256"} - # data = "foo".encode() - # signature = infra.crypto.sign(algorithm, key_priv_pem, data) - # r = c.post( - # "/app/verifySignature", - # { - # "algorithm": algorithm, - # "key": key_pub_pem, - # "signature": b64encode(signature).decode(), - # "data": b64encode(data).decode(), - # }, - # ) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert r.body.json() is True, r.body - - # r = c.post( - # "/app/verifySignature", - # { - # "algorithm": algorithm, - # "key": key_pub_pem, - # "signature": b64encode(signature).decode(), - # "data": b64encode("bar".encode()).decode(), - # }, - # ) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert r.body.json() is False, r.body - - # curves = [ec.SECP256R1, ec.SECP256K1, ec.SECP384R1] - # for curve in curves: - # key_priv_pem, key_pub_pem = infra.crypto.generate_ec_keypair(curve) - # algorithm = {"name": "ECDSA", "hash": "SHA-256"} - # data = "foo".encode() - # signature = infra.crypto.sign(algorithm, key_priv_pem, data) - # r = c.post( - # "/app/verifySignature", - # { - # "algorithm": algorithm, - # "key": key_pub_pem, - # "signature": b64encode(signature).decode(), - # "data": b64encode(data).decode(), - # }, - # ) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert r.body.json() is True, r.body - - # key_priv_pem, key_pub_pem = infra.crypto.generate_eddsa_keypair() - # algorithm = {"name": "EdDSA"} - # data = "foo".encode() - # signature = infra.crypto.sign(algorithm, key_priv_pem, data) - # r = c.post( - # "/app/verifySignature", - # { - # "algorithm": algorithm, - # "key": key_pub_pem, - # "signature": b64encode(signature).decode(), - # "data": b64encode(data).decode(), - # }, - # ) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert r.body.json() is True, r.body - - # r = c.post( - # "/app/digest", - # { - # "algorithm": "SHA-256", - # "data": b64encode(bytes("Hello world!", "ascii")).decode(), - # }, - # ) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # assert ( - # r.body.text() - # == "c0535e4be2b79ffd93291305436bf889314e4a3faec05ecffcbb7df31ad9e51a" - # ), r.body - - # r = c.get("/app/log?id=42") - # assert r.status_code == http.HTTPStatus.NOT_FOUND, r.status_code - - # r = c.post("/app/log?id=42", {"msg": "Hello!"}) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - - # r = c.get("/app/log?id=42") - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # body = r.body.json() - # assert body["msg"] == "Hello!", r.body - - # r = c.post("/app/log?id=42", {"msg": "Saluton!"}) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # r = c.post("/app/log?id=43", {"msg": "Bonjour!"}) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - - # r = c.get("/app/log/all") - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # body = r.body.json() - # # Response is list in undefined order - # assert len(body) == 2, body - # assert {"id": 42, "msg": "Saluton!"} in body, body - # assert {"id": 43, "msg": "Bonjour!"} in body, body - - # test_apply_writes(c) - - # r = c.get("/app/jwt") - # assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code - # body = r.body.json() - # assert body["msg"] == "authorization header missing", r.body - - # r = c.get("/app/jwt", headers={"authorization": "Bearer not-a-jwt"}) - # assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code - # body = r.body.json() - # assert body["msg"].startswith("malformed jwt:"), r.body - - # jwt_key_priv_pem, _ = infra.crypto.generate_rsa_keypair(2048) - # jwt_cert_pem = infra.crypto.generate_cert(jwt_key_priv_pem) - - # jwt_kid = "my_key_id" - # jwt = infra.crypto.create_jwt({}, jwt_key_priv_pem, jwt_kid) - # r = c.get("/app/jwt", headers={"authorization": "Bearer " + jwt}) - # assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code - # body = r.body.json() - # assert body["msg"].startswith("token signing key not found"), r.body - - # priv_key_pem, _ = infra.crypto.generate_rsa_keypair(2048) - # pem = infra.crypto.generate_cert(priv_key_pem) - # r = c.post("/app/isValidX509CertBundle", pem) - # assert r.body.json(), r.body - # r = c.post("/app/isValidX509CertBundle", pem + "\n" + pem) - # assert r.body.json(), r.body - # r = c.post("/app/isValidX509CertBundle", "garbage") - # assert not r.body.json(), r.body - - # priv_key_pem1, _ = infra.crypto.generate_rsa_keypair(2048) - # pem1 = infra.crypto.generate_cert(priv_key_pem1, cn="1", ca=True) - # priv_key_pem2, _ = infra.crypto.generate_rsa_keypair(2048) - # pem2 = infra.crypto.generate_cert( - # priv_key_pem2, - # cn="2", - # ca=True, - # issuer_priv_key_pem=priv_key_pem1, - # issuer_cn="1", - # ) - # priv_key_pem3, _ = infra.crypto.generate_rsa_keypair(2048) - # pem3 = infra.crypto.generate_cert( - # priv_key_pem3, cn="3", issuer_priv_key_pem=priv_key_pem2, issuer_cn="2" - # ) - # # validates chains with target being trusted directly - # r = c.post("/app/isValidX509CertChain", {"chain": pem3, "trusted": pem3}) - # assert r.body.json(), r.body - # # validates chains without intermediates - # r = c.post("/app/isValidX509CertChain", {"chain": pem2, "trusted": pem1}) - # assert r.body.json(), r.body - # # validates chains with intermediates - # r = c.post( - # "/app/isValidX509CertChain", {"chain": pem3 + "\n" + pem2, "trusted": pem1} - # ) - # assert r.body.json(), r.body - # # validates partial chains (pem2 is an intermediate) - # r = c.post("/app/isValidX509CertChain", {"chain": pem3, "trusted": pem2}) - # assert r.body.json(), r.body - # # fails to reach trust anchor - # r = c.post("/app/isValidX509CertChain", {"chain": pem3, "trusted": pem1}) - # assert not r.body.json(), r.body - - # r = c.get("/node/quotes/self") - # primary_quote_info = r.body.json() - # if args.enclave_platform != "sgx": - # LOG.info("Skipping /app/verifyOpenEnclaveEvidence test, non-sgx node") - # else: - # # See /opt/openenclave/include/openenclave/attestation/sgx/evidence.h - # OE_FORMAT_UUID_SGX_ECDSA = "a3a21e87-1b4d-4014-b70a-a125d2fbcd8c" - # r = c.post( - # "/app/verifyOpenEnclaveEvidence", - # { - # "format": OE_FORMAT_UUID_SGX_ECDSA, - # "evidence": primary_quote_info["raw"], - # "endorsements": primary_quote_info["endorsements"], - # }, - # ) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # body = r.body.json() - # assert body["claims"]["unique_id"] == primary_quote_info["mrenclave"], body - # assert "sgx_report_data" in body["customClaims"], body - - # # again but without endorsements - # r = c.post( - # "/app/verifyOpenEnclaveEvidence", - # { - # "format": OE_FORMAT_UUID_SGX_ECDSA, - # "evidence": primary_quote_info["raw"], - # }, - # ) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # body = r.body.json() - # assert body["claims"]["unique_id"] == primary_quote_info["mrenclave"], body - # assert "sgx_report_data" in body["customClaims"], body - - # validate_openapi(c) + body = [1, 2, 3, 4] + r = c.post("/app/partition", body) + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert r.body.json() == [[1, 3], [2, 4]], r.body + + r = c.post("/app/proto", body) + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert r.headers["content-type"] == "application/x-protobuf" + # We could now decode the protobuf message but given all the machinery + # involved to make it happen (code generation with protoc) we'll leave it at that. + assert len(r.body) == 14, len(r.body) + + r = c.get("/app/crypto") + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert r.body.json()["available"], r.body + + key_size = 256 + r = c.post("/app/generateAesKey", {"size": key_size}) + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert len(r.body.data()) == key_size // 8 + assert r.body.data() != b"\x00" * (key_size // 8) + + r = c.post("/app/generateRsaKeyPair", {"size": 2048}) + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert infra.crypto.check_key_pair_pem( + r.body.json()["privateKey"], r.body.json()["publicKey"] + ) + + r = c.post("/app/generateEcdsaKeyPair", {"curve": "secp256r1"}) + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert infra.crypto.check_key_pair_pem( + r.body.json()["privateKey"], r.body.json()["publicKey"] + ) + + r = c.post("/app/generateEcdsaKeyPair", {"curve": "secp256k1"}) + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert infra.crypto.check_key_pair_pem( + r.body.json()["privateKey"], r.body.json()["publicKey"] + ) + + r = c.post("/app/generateEcdsaKeyPair", {"curve": "secp384r1"}) + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert infra.crypto.check_key_pair_pem( + r.body.json()["privateKey"], r.body.json()["publicKey"] + ) + + r = c.post("/app/generateEddsaKeyPair", {"curve": "curve25519"}) + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert infra.crypto.check_key_pair_pem( + r.body.json()["privateKey"], r.body.json()["publicKey"] + ) + + aes_key_to_wrap = infra.crypto.generate_aes_key(256) + wrapping_key_priv_pem, wrapping_key_pub_pem = infra.crypto.generate_rsa_keypair( + 2048 + ) + label = "label42" + r = c.post( + "/app/wrapKey", + { + "key": b64encode(aes_key_to_wrap).decode(), + "wrappingKey": b64encode(bytes(wrapping_key_pub_pem, "ascii")).decode(), + "wrapAlgo": { + "name": "RSA-OAEP", + "label": b64encode(bytes(label, "ascii")).decode(), + }, + }, + ) + assert r.status_code == http.HTTPStatus.OK, r.status_code + unwrapped = infra.crypto.unwrap_key_rsa_oaep( + r.body.data(), wrapping_key_priv_pem, label.encode("ascii") + ) + assert unwrapped == aes_key_to_wrap + + aes_wrapping_key = infra.crypto.generate_aes_key(256) + r = c.post( + "/app/wrapKey", + { + "key": b64encode(aes_key_to_wrap).decode(), + "wrappingKey": b64encode(aes_wrapping_key).decode(), + "wrapAlgo": {"name": "AES-KWP"}, + }, + ) + assert r.status_code == http.HTTPStatus.OK, r.status_code + unwrapped = infra.crypto.unwrap_key_aes_pad(r.body.data(), aes_wrapping_key) + assert unwrapped == aes_key_to_wrap + + wrapping_key_priv_pem, wrapping_key_pub_pem = infra.crypto.generate_rsa_keypair( + 2048 + ) + label = "label44" + r = c.post( + "/app/wrapKey", + { + "key": b64encode(aes_key_to_wrap).decode(), + "wrappingKey": b64encode(bytes(wrapping_key_pub_pem, "ascii")).decode(), + "wrapAlgo": { + "name": "RSA-OAEP-AES-KWP", + "aesKeySize": 256, + "label": b64encode(bytes(label, "ascii")).decode(), + }, + }, + ) + assert r.status_code == http.HTTPStatus.OK, r.status_code + unwrapped = infra.crypto.unwrap_key_rsa_oaep_aes_pad( + r.body.data(), wrapping_key_priv_pem, label.encode("ascii") + ) + assert unwrapped == aes_key_to_wrap + + key_priv_pem, key_pub_pem = infra.crypto.generate_rsa_keypair(2048) + algorithm = {"name": "RSASSA-PKCS1-v1_5", "hash": "SHA-256"} + data = "foo".encode() + r = c.post( + "/app/sign", + { + "algorithm": algorithm, + "key": key_priv_pem, + "data": b64encode(data).decode(), + }, + ) + assert r.status_code == http.HTTPStatus.OK, r.status_code + + signature = r.body.data() + infra.crypto.verify_signature(algorithm, signature, data, key_pub_pem) + + # Also verify with the JS API + r = c.post( + "/app/verifySignature", + { + "algorithm": algorithm, + "key": key_pub_pem, + "signature": b64encode(signature).decode(), + "data": b64encode(data).decode(), + }, + ) + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert r.body.json() is True, r.body + + try: + infra.crypto.verify_signature( + algorithm, signature, "bar".encode(), key_pub_pem + ) + assert False, "verify_signature() should throw" + except InvalidSignature: + pass + + curves = [ec.SECP256R1, ec.SECP256K1, ec.SECP384R1] + for curve in curves: + key_priv_pem, key_pub_pem = infra.crypto.generate_ec_keypair(curve) + algorithm = {"name": "ECDSA", "hash": "SHA-256"} + data = "foo".encode() + r = c.post( + "/app/sign", + { + "algorithm": algorithm, + "key": key_priv_pem, + "data": b64encode(data).decode(), + }, + ) + assert r.status_code == http.HTTPStatus.OK, r.status_code + + signature = r.body.data() + infra.crypto.verify_signature(algorithm, signature, data, key_pub_pem) + + # Also verify with the JS API + r = c.post( + "/app/verifySignature", + { + "algorithm": algorithm, + "key": key_pub_pem, + "signature": b64encode(signature).decode(), + "data": b64encode(data).decode(), + }, + ) + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert r.body.json() is True, r.body + + try: + infra.crypto.verify_signature( + algorithm, signature, "bar".encode(), key_pub_pem + ) + assert False, "verify_signature() should throw" + except InvalidSignature: + pass + + key_priv_pem, key_pub_pem = infra.crypto.generate_eddsa_keypair() + algorithm = {"name": "EdDSA"} + data = "foo".encode() + r = c.post( + "/app/sign", + { + "algorithm": algorithm, + "key": key_priv_pem, + "data": b64encode(data).decode(), + }, + ) + assert r.status_code == http.HTTPStatus.OK, r.status_code + + signature = r.body.data() + infra.crypto.verify_signature(algorithm, signature, data, key_pub_pem) + + # Also verify with the JS API + r = c.post( + "/app/verifySignature", + { + "algorithm": algorithm, + "key": key_pub_pem, + "signature": b64encode(signature).decode(), + "data": b64encode(data).decode(), + }, + ) + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert r.body.json() is True, r.body + + try: + infra.crypto.verify_signature( + algorithm, signature, "bar".encode(), key_pub_pem + ) + assert False, "verify_signature() should throw" + except InvalidSignature: + pass + + key_priv_pem, key_pub_pem = infra.crypto.generate_rsa_keypair(2048) + algorithm = {"name": "RSASSA-PKCS1-v1_5", "hash": "SHA-256"} + data = "foo".encode() + signature = infra.crypto.sign(algorithm, key_priv_pem, data) + r = c.post( + "/app/verifySignature", + { + "algorithm": algorithm, + "key": key_pub_pem, + "signature": b64encode(signature).decode(), + "data": b64encode(data).decode(), + }, + ) + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert r.body.json() is True, r.body + + r = c.post( + "/app/verifySignature", + { + "algorithm": algorithm, + "key": key_pub_pem, + "signature": b64encode(signature).decode(), + "data": b64encode("bar".encode()).decode(), + }, + ) + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert r.body.json() is False, r.body + + curves = [ec.SECP256R1, ec.SECP256K1, ec.SECP384R1] + for curve in curves: + key_priv_pem, key_pub_pem = infra.crypto.generate_ec_keypair(curve) + algorithm = {"name": "ECDSA", "hash": "SHA-256"} + data = "foo".encode() + signature = infra.crypto.sign(algorithm, key_priv_pem, data) + r = c.post( + "/app/verifySignature", + { + "algorithm": algorithm, + "key": key_pub_pem, + "signature": b64encode(signature).decode(), + "data": b64encode(data).decode(), + }, + ) + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert r.body.json() is True, r.body + + key_priv_pem, key_pub_pem = infra.crypto.generate_eddsa_keypair() + algorithm = {"name": "EdDSA"} + data = "foo".encode() + signature = infra.crypto.sign(algorithm, key_priv_pem, data) + r = c.post( + "/app/verifySignature", + { + "algorithm": algorithm, + "key": key_pub_pem, + "signature": b64encode(signature).decode(), + "data": b64encode(data).decode(), + }, + ) + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert r.body.json() is True, r.body + + r = c.post( + "/app/digest", + { + "algorithm": "SHA-256", + "data": b64encode(bytes("Hello world!", "ascii")).decode(), + }, + ) + assert r.status_code == http.HTTPStatus.OK, r.status_code + assert ( + r.body.text() + == "c0535e4be2b79ffd93291305436bf889314e4a3faec05ecffcbb7df31ad9e51a" + ), r.body + + r = c.get("/app/log?id=42") + assert r.status_code == http.HTTPStatus.NOT_FOUND, r.status_code + + r = c.post("/app/log?id=42", {"msg": "Hello!"}) + assert r.status_code == http.HTTPStatus.OK, r.status_code + + r = c.get("/app/log?id=42") + assert r.status_code == http.HTTPStatus.OK, r.status_code + body = r.body.json() + assert body["msg"] == "Hello!", r.body + + r = c.post("/app/log?id=42", {"msg": "Saluton!"}) + assert r.status_code == http.HTTPStatus.OK, r.status_code + r = c.post("/app/log?id=43", {"msg": "Bonjour!"}) + assert r.status_code == http.HTTPStatus.OK, r.status_code + + r = c.get("/app/log/all") + assert r.status_code == http.HTTPStatus.OK, r.status_code + body = r.body.json() + # Response is list in undefined order + assert len(body) == 2, body + assert {"id": 42, "msg": "Saluton!"} in body, body + assert {"id": 43, "msg": "Bonjour!"} in body, body + + test_apply_writes(c) + + r = c.get("/app/jwt") + assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code + body = r.body.json() + assert body["msg"] == "authorization header missing", r.body + + r = c.get("/app/jwt", headers={"authorization": "Bearer not-a-jwt"}) + assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code + body = r.body.json() + assert body["msg"].startswith("malformed jwt:"), r.body + + jwt_key_priv_pem, _ = infra.crypto.generate_rsa_keypair(2048) + jwt_cert_pem = infra.crypto.generate_cert(jwt_key_priv_pem) + + jwt_kid = "my_key_id" + jwt = infra.crypto.create_jwt({}, jwt_key_priv_pem, jwt_kid) + r = c.get("/app/jwt", headers={"authorization": "Bearer " + jwt}) + assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code + body = r.body.json() + assert body["msg"].startswith("token signing key not found"), r.body + + priv_key_pem, _ = infra.crypto.generate_rsa_keypair(2048) + pem = infra.crypto.generate_cert(priv_key_pem) + r = c.post("/app/isValidX509CertBundle", pem) + assert r.body.json(), r.body + r = c.post("/app/isValidX509CertBundle", pem + "\n" + pem) + assert r.body.json(), r.body + r = c.post("/app/isValidX509CertBundle", "garbage") + assert not r.body.json(), r.body + + priv_key_pem1, _ = infra.crypto.generate_rsa_keypair(2048) + pem1 = infra.crypto.generate_cert(priv_key_pem1, cn="1", ca=True) + priv_key_pem2, _ = infra.crypto.generate_rsa_keypair(2048) + pem2 = infra.crypto.generate_cert( + priv_key_pem2, + cn="2", + ca=True, + issuer_priv_key_pem=priv_key_pem1, + issuer_cn="1", + ) + priv_key_pem3, _ = infra.crypto.generate_rsa_keypair(2048) + pem3 = infra.crypto.generate_cert( + priv_key_pem3, cn="3", issuer_priv_key_pem=priv_key_pem2, issuer_cn="2" + ) + # validates chains with target being trusted directly + r = c.post("/app/isValidX509CertChain", {"chain": pem3, "trusted": pem3}) + assert r.body.json(), r.body + # validates chains without intermediates + r = c.post("/app/isValidX509CertChain", {"chain": pem2, "trusted": pem1}) + assert r.body.json(), r.body + # validates chains with intermediates + r = c.post( + "/app/isValidX509CertChain", {"chain": pem3 + "\n" + pem2, "trusted": pem1} + ) + assert r.body.json(), r.body + # validates partial chains (pem2 is an intermediate) + r = c.post("/app/isValidX509CertChain", {"chain": pem3, "trusted": pem2}) + assert r.body.json(), r.body + # fails to reach trust anchor + r = c.post("/app/isValidX509CertChain", {"chain": pem3, "trusted": pem1}) + assert not r.body.json(), r.body + + r = c.get("/node/quotes/self") + primary_quote_info = r.body.json() + if args.enclave_platform != "sgx": + LOG.info("Skipping /app/verifyOpenEnclaveEvidence test, non-sgx node") + else: + # See /opt/openenclave/include/openenclave/attestation/sgx/evidence.h + OE_FORMAT_UUID_SGX_ECDSA = "a3a21e87-1b4d-4014-b70a-a125d2fbcd8c" + r = c.post( + "/app/verifyOpenEnclaveEvidence", + { + "format": OE_FORMAT_UUID_SGX_ECDSA, + "evidence": primary_quote_info["raw"], + "endorsements": primary_quote_info["endorsements"], + }, + ) + assert r.status_code == http.HTTPStatus.OK, r.status_code + body = r.body.json() + assert body["claims"]["unique_id"] == primary_quote_info["mrenclave"], body + assert "sgx_report_data" in body["customClaims"], body + + # again but without endorsements + r = c.post( + "/app/verifyOpenEnclaveEvidence", + { + "format": OE_FORMAT_UUID_SGX_ECDSA, + "evidence": primary_quote_info["raw"], + }, + ) + assert r.status_code == http.HTTPStatus.OK, r.status_code + body = r.body.json() + assert body["claims"]["unique_id"] == primary_quote_info["mrenclave"], body + assert "sgx_report_data" in body["customClaims"], body + + validate_openapi(c) generate_and_verify_jwk(c) LOG.info("Store JWT signing keys") - # issuer = "https://example.issuer" - # with tempfile.NamedTemporaryFile(prefix="ccf", mode="w+") as metadata_fp: - # jwt_cert_der = infra.crypto.cert_pem_to_der(jwt_cert_pem) - # der_b64 = base64.b64encode(jwt_cert_der).decode("ascii") - # data = { - # "issuer": issuer, - # "jwks": {"keys": [{"kty": "RSA", "kid": jwt_kid, "x5c": [der_b64]}]}, - # } - # json.dump(data, metadata_fp) - # metadata_fp.flush() - # network.consortium.set_jwt_issuer(primary, metadata_fp.name) - - # LOG.info("Calling jwt endpoint after storing keys") - # with primary.client("user0") as c: - # jwt_mismatching_key_priv_pem, _ = infra.crypto.generate_rsa_keypair(2048) - # jwt = infra.crypto.create_jwt({}, jwt_mismatching_key_priv_pem, jwt_kid) - # r = c.get("/app/jwt", headers={"authorization": "Bearer " + jwt}) - # assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code - # body = r.body.json() - # assert body["msg"] == "jwt validation failed", r.body - - # jwt = infra.crypto.create_jwt({}, jwt_key_priv_pem, jwt_kid) - # r = c.get("/app/jwt", headers={"authorization": "Bearer " + jwt}) - # assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code - # body = r.body.json() - # assert body["msg"] == "jwt invalid, sub claim missing", r.body - - # user_id = "user0" - # jwt = infra.crypto.create_jwt({"sub": user_id}, jwt_key_priv_pem, jwt_kid) - # r = c.get("/app/jwt", headers={"authorization": "Bearer " + jwt}) - # assert r.status_code == http.HTTPStatus.OK, r.status_code - # body = r.body.json() - # assert body["userId"] == user_id, r.body + issuer = "https://example.issuer" + with tempfile.NamedTemporaryFile(prefix="ccf", mode="w+") as metadata_fp: + jwt_cert_der = infra.crypto.cert_pem_to_der(jwt_cert_pem) + der_b64 = base64.b64encode(jwt_cert_der).decode("ascii") + data = { + "issuer": issuer, + "jwks": {"keys": [{"kty": "RSA", "kid": jwt_kid, "x5c": [der_b64]}]}, + } + json.dump(data, metadata_fp) + metadata_fp.flush() + network.consortium.set_jwt_issuer(primary, metadata_fp.name) + + LOG.info("Calling jwt endpoint after storing keys") + with primary.client("user0") as c: + jwt_mismatching_key_priv_pem, _ = infra.crypto.generate_rsa_keypair(2048) + jwt = infra.crypto.create_jwt({}, jwt_mismatching_key_priv_pem, jwt_kid) + r = c.get("/app/jwt", headers={"authorization": "Bearer " + jwt}) + assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code + body = r.body.json() + assert body["msg"] == "jwt validation failed", r.body + + jwt = infra.crypto.create_jwt({}, jwt_key_priv_pem, jwt_kid) + r = c.get("/app/jwt", headers={"authorization": "Bearer " + jwt}) + assert r.status_code == http.HTTPStatus.UNAUTHORIZED, r.status_code + body = r.body.json() + assert body["msg"] == "jwt invalid, sub claim missing", r.body + + user_id = "user0" + jwt = infra.crypto.create_jwt({"sub": user_id}, jwt_key_priv_pem, jwt_kid) + r = c.get("/app/jwt", headers={"authorization": "Bearer " + jwt}) + assert r.status_code == http.HTTPStatus.OK, r.status_code + body = r.body.json() + assert body["userId"] == user_id, r.body return network @@ -1105,15 +1105,15 @@ def run(args): args.nodes, args.binary_dir, args.debug_nodes, args.perf_nodes, pdb=args.pdb ) as network: network.start_and_open(args) - # network = test_module_import(network, args) - # network = test_bytecode_cache(network, args) - # network = test_app_bundle(network, args) - # network = test_dynamic_endpoints(network, args) - # network = test_set_js_runtime(network, args) + network = test_module_import(network, args) + network = test_bytecode_cache(network, args) + network = test_app_bundle(network, args) + network = test_dynamic_endpoints(network, args) + network = test_set_js_runtime(network, args) network = test_npm_app(network, args) - # network = test_js_execution_time(network, args) - # network = test_js_exception_output(network, args) - # network = test_user_cose_authentication(network, args) + network = test_js_execution_time(network, args) + network = test_js_exception_output(network, args) + network = test_user_cose_authentication(network, args) if __name__ == "__main__": From 04582be74f6713ce2f0c311ea643da9a17c6d566 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 28 Jul 2023 10:00:19 +0000 Subject: [PATCH 30/57] . --- cmake/t_cose.cmake | 3 +-- tests/js-modules/modules.py | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/cmake/t_cose.cmake b/cmake/t_cose.cmake index 9405e646f1df..b103164388fb 100644 --- a/cmake/t_cose.cmake +++ b/cmake/t_cose.cmake @@ -14,8 +14,7 @@ set(T_COSE_SRCS ) if(COMPILE_TARGET STREQUAL "sgx") add_enclave_library_c(t_cose.enclave ${T_COSE_SRCS}) - target_compile_definitions(t_cose.enclave PRIVATE ${T_COSE_DEFS} - ) + target_compile_definitions(t_cose.enclave PRIVATE ${T_COSE_DEFS}) target_compile_options(t_cose.enclave INTERFACE ${T_COSE_OPTS_INTERFACE}) target_include_directories(t_cose.enclave PRIVATE "${T_COSE_SRC}") diff --git a/tests/js-modules/modules.py b/tests/js-modules/modules.py index b945956e8d05..cf30b4d49973 100644 --- a/tests/js-modules/modules.py +++ b/tests/js-modules/modules.py @@ -784,16 +784,38 @@ def test_npm_app(network, args): r = c.post("/app/log?id=42", {"msg": "Hello!"}) assert r.status_code == http.HTTPStatus.OK, r.status_code + r = c.get("/app/log/version?id=42") + assert r.status_code == http.HTTPStatus.NOT_FOUND, r.status_code + r = c.get("/app/log?id=42") assert r.status_code == http.HTTPStatus.OK, r.status_code body = r.body.json() + assert body["id"] == 42, r.body assert body["msg"] == "Hello!", r.body + r = c.get("/app/log/version?id=42") + assert r.status_code == http.HTTPStatus.OK, r.status_code + v0 = r.body.json()["version"] + r = c.post("/app/log?id=42", {"msg": "Saluton!"}) assert r.status_code == http.HTTPStatus.OK, r.status_code + + r = c.get("/app/log/version?id=42") + assert r.status_code == http.HTTPStatus.OK, r.status_code + v1 = r.body.json()["version"] + assert v1 > v0 + + r = c.get("/app/log/version?id=43") + assert r.status_code == http.HTTPStatus.NOT_FOUND, r.status_code + r = c.post("/app/log?id=43", {"msg": "Bonjour!"}) assert r.status_code == http.HTTPStatus.OK, r.status_code + r = c.get("/app/log/version?id=43") + assert r.status_code == http.HTTPStatus.OK, r.status_code + v2 = r.body.json()["version"] + assert v2 > v1 + r = c.get("/app/log/all") assert r.status_code == http.HTTPStatus.OK, r.status_code body = r.body.json() @@ -802,6 +824,11 @@ def test_npm_app(network, args): assert {"id": 42, "msg": "Saluton!"} in body, body assert {"id": 43, "msg": "Bonjour!"} in body, body + r = c.get("/app/log/version?id=42") + assert r.status_code == http.HTTPStatus.OK, r.status_code + v3 = r.body.json()["version"] + assert v3 == v1 + test_apply_writes(c) r = c.get("/app/jwt") From d613ecc7bab49973b0d2fda4f24252a160be0094 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 28 Jul 2023 10:02:21 +0000 Subject: [PATCH 31/57] Almost there --- cmake/crypto.cmake | 22 +++++----------------- tests/js-modules/modules.py | 6 +++--- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/cmake/crypto.cmake b/cmake/crypto.cmake index dfe0279c9892..dc361f6feb1e 100644 --- a/cmake/crypto.cmake +++ b/cmake/crypto.cmake @@ -54,18 +54,13 @@ elseif(COMPILE_TARGET STREQUAL "snp") ) endif() -set(OPENSSL_INSTALL_PATH "/opt/openssl") - -find_library(CRYPTO_LIBRARY crypto HINTS "${OPENSSL_INSTALL_PATH}/lib64") -find_library(TLS_LIBRARY ssl "${OPENSSL_INSTALL_PATH}/lib64") +find_library(CRYPTO_LIBRARY crypto) +find_library(TLS_LIBRARY ssl) add_library(ccfcrypto.host STATIC ${CCFCRYPTO_SRC}) add_san(ccfcrypto.host) -target_compile_options(ccfcrypto.host PUBLIC ${COMPILE_LIBCXX} -)# "-Wno-deprecated-declarations") +target_compile_options(ccfcrypto.host PUBLIC ${COMPILE_LIBCXX}) -# target_compile_definitions(ccfcrypto.host PUBLIC -# OPENSSL_API_COMPAT=0x10101000L) target_link_options(ccfcrypto.host PUBLIC ${LINK_LIBCXX}) target_include_directories( ccfcrypto.host PRIVATE "${OPENSSL_INSTALL_PATH}/include" @@ -73,15 +68,8 @@ target_include_directories( target_link_libraries(ccfcrypto.host PUBLIC qcbor.host) target_link_libraries(ccfcrypto.host PUBLIC t_cose.host) - -# target_link_libraries(ccfcrypto.host PUBLIC crypto) -# target_link_libraries(ccfcrypto.host PUBLIC ssl) -target_link_libraries( - ccfcrypto.host PUBLIC "${OPENSSL_INSTALL_PATH}/lib64/libcrypto.so" -) -target_link_libraries( - ccfcrypto.host PUBLIC "${OPENSSL_INSTALL_PATH}/lib64/libssl.so" -) +target_link_libraries(ccfcrypto.host PUBLIC crypto) +target_link_libraries(ccfcrypto.host PUBLIC ssl) set_property(TARGET ccfcrypto.host PROPERTY POSITION_INDEPENDENT_CODE ON) if(INSTALL_VIRTUAL_LIBRARIES) diff --git a/tests/js-modules/modules.py b/tests/js-modules/modules.py index cf30b4d49973..d9ec9e082cfd 100644 --- a/tests/js-modules/modules.py +++ b/tests/js-modules/modules.py @@ -781,12 +781,12 @@ def test_npm_app(network, args): r = c.get("/app/log?id=42") assert r.status_code == http.HTTPStatus.NOT_FOUND, r.status_code + r = c.get("/app/log/version?id=42") + assert r.status_code == http.HTTPStatus.NOT_FOUND, r.status_code + r = c.post("/app/log?id=42", {"msg": "Hello!"}) assert r.status_code == http.HTTPStatus.OK, r.status_code - r = c.get("/app/log/version?id=42") - assert r.status_code == http.HTTPStatus.NOT_FOUND, r.status_code - r = c.get("/app/log?id=42") assert r.status_code == http.HTTPStatus.OK, r.status_code body = r.body.json() From 394c4ba8b21b337ac803b3935f27f20f5b2188ba Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 28 Jul 2023 10:03:02 +0000 Subject: [PATCH 32/57] . --- cmake/crypto.cmake | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cmake/crypto.cmake b/cmake/crypto.cmake index dc361f6feb1e..35f0f21b7541 100644 --- a/cmake/crypto.cmake +++ b/cmake/crypto.cmake @@ -60,11 +60,7 @@ find_library(TLS_LIBRARY ssl) add_library(ccfcrypto.host STATIC ${CCFCRYPTO_SRC}) add_san(ccfcrypto.host) target_compile_options(ccfcrypto.host PUBLIC ${COMPILE_LIBCXX}) - target_link_options(ccfcrypto.host PUBLIC ${LINK_LIBCXX}) -target_include_directories( - ccfcrypto.host PRIVATE "${OPENSSL_INSTALL_PATH}/include" -) target_link_libraries(ccfcrypto.host PUBLIC qcbor.host) target_link_libraries(ccfcrypto.host PUBLIC t_cose.host) From 73098b52368c276d44f41b9b06111bd0a14c0435 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 28 Jul 2023 10:14:31 +0000 Subject: [PATCH 33/57] Fix 1.1.1 build --- src/crypto/openssl/rsa_key_pair.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/crypto/openssl/rsa_key_pair.cpp b/src/crypto/openssl/rsa_key_pair.cpp index 039af2326973..6cf80aee243f 100644 --- a/src/crypto/openssl/rsa_key_pair.cpp +++ b/src/crypto/openssl/rsa_key_pair.cpp @@ -69,30 +69,25 @@ namespace crypto CHECKNULL(BN_bin2bn(dq_raw.data(), dq_raw.size(), dq)); CHECKNULL(BN_bin2bn(qi_raw.data(), qi_raw.size(), qi)); +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 // Note: raw vectors are big endians while OSSL_PARAM_construct_BN expects // native endianness std::vector d_raw_native(d_raw.size()); - CHECKPOSITIVE(BN_bn2nativepad(d, d_raw_native.data(), d_raw_native.size())); - std::vector p_raw_native(p_raw.size()); - CHECKPOSITIVE(BN_bn2nativepad(p, p_raw_native.data(), p_raw_native.size())); - std::vector q_raw_native(q_raw.size()); - CHECKPOSITIVE(BN_bn2nativepad(q, q_raw_native.data(), q_raw_native.size())); - std::vector dp_raw_native(dp_raw.size()); + std::vector dq_raw_native(dq_raw.size()); + std::vector qi_raw_native(qi_raw.size()); + CHECKPOSITIVE(BN_bn2nativepad(d, d_raw_native.data(), d_raw_native.size())); + CHECKPOSITIVE(BN_bn2nativepad(p, p_raw_native.data(), p_raw_native.size())); + CHECKPOSITIVE(BN_bn2nativepad(q, q_raw_native.data(), q_raw_native.size())); CHECKPOSITIVE( BN_bn2nativepad(dp, dp_raw_native.data(), dp_raw_native.size())); - - std::vector dq_raw_native(dq_raw.size()); CHECKPOSITIVE( BN_bn2nativepad(dq, dq_raw_native.data(), dq_raw_native.size())); - - std::vector qi_raw_native(qi_raw.size()); CHECKPOSITIVE( BN_bn2nativepad(qi, qi_raw_native.data(), qi_raw_native.size())); -#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 auto [n_raw, e_raw] = RSAPublicKey_OpenSSL::rsa_public_raw_from_jwk(jwk); OSSL_PARAM params[9]; From f37bb9df91c0193d18ee8a06abade12b40744610 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 28 Jul 2023 10:21:52 +0000 Subject: [PATCH 34/57] Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74fc13f58e1c..c497d61ca9c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## Unreleased - Updated Open Enclave to [0.19.2](https://github.com/openenclave/openenclave/releases/tag/v0.19.2). +- SGX builds now use OpenSSL 3.1.1 by default (#5481). ## [4.0.5] From 8f31850742618c9e793ef9463c86fd41d011548f Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 28 Jul 2023 10:23:11 +0000 Subject: [PATCH 35/57] . --- .daily_canary | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.daily_canary b/.daily_canary index fff5ef29a821..e2179308991e 100644 --- a/.daily_canary +++ b/.daily_canary @@ -1,4 +1,4 @@ --- ___ ___ (- -) (= =) | Y & +--? - ( V ) z . z O +---=---' + ( V ) > . < O +---=---' /--x-m- /--n-n---xXx--/--yY-----. From 587c981aa3b87f42db4d03ad2933564034870abc Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 28 Jul 2023 13:04:08 +0000 Subject: [PATCH 36/57] Compat flag --- CHANGELOG.md | 2 +- cmake/crypto.cmake | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c497d61ca9c8..3a37e039e953 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## Unreleased - Updated Open Enclave to [0.19.2](https://github.com/openenclave/openenclave/releases/tag/v0.19.2). -- SGX builds now use OpenSSL 3.1.1 by default (#5481). +- SGX builds now use OpenSSL 3.1.1 by default (#5481). ## [4.0.5] diff --git a/cmake/crypto.cmake b/cmake/crypto.cmake index 35f0f21b7541..019d92af76ed 100644 --- a/cmake/crypto.cmake +++ b/cmake/crypto.cmake @@ -31,6 +31,11 @@ if(COMPILE_TARGET STREQUAL "sgx") target_link_libraries(ccfcrypto.enclave PUBLIC qcbor.enclave) target_link_libraries(ccfcrypto.enclave PUBLIC t_cose.enclave) + # To be removed once https://github.com/microsoft/CCF/issues/5291 is complete + if (USE_OPENSSL_3) + target_compile_definitions(ccfcrypto.enclave PUBLIC OPENSSL_API_COMPAT=0x10101000L) + endif() + install( TARGETS ccfcrypto.enclave EXPORT ccf From 349f81314ba09d1bb9271aec2754b1294b08198e Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 28 Jul 2023 13:04:15 +0000 Subject: [PATCH 37/57] . --- cmake/crypto.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/crypto.cmake b/cmake/crypto.cmake index 019d92af76ed..a37213a68e8a 100644 --- a/cmake/crypto.cmake +++ b/cmake/crypto.cmake @@ -32,8 +32,10 @@ if(COMPILE_TARGET STREQUAL "sgx") target_link_libraries(ccfcrypto.enclave PUBLIC t_cose.enclave) # To be removed once https://github.com/microsoft/CCF/issues/5291 is complete - if (USE_OPENSSL_3) - target_compile_definitions(ccfcrypto.enclave PUBLIC OPENSSL_API_COMPAT=0x10101000L) + if(USE_OPENSSL_3) + target_compile_definitions( + ccfcrypto.enclave PUBLIC OPENSSL_API_COMPAT=0x10101000L + ) endif() install( From 2ed84a726e74a80012a2430f7fee87a8e51bd5cc Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 28 Jul 2023 13:09:20 +0000 Subject: [PATCH 38/57] . --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d659bb60502b..e7dc2e7762f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Updated Open Enclave to [0.19.2](https://github.com/openenclave/openenclave/releases/tag/v0.19.2). - Updated Open Enclave to [0.19.3](https://github.com/openenclave/openenclave/releases/tag/v0.19.3). - Expose COSESign1 `content` for `user_cose_sign1` authenticated endpoints in JavaScript/TypeScript apps (#5465). -- SGX builds now use OpenSSL 3.1.1 by default (#5481). +- SGX builds now use OpenSSL 3.1.1 by default (#5481). ## [4.0.5] From bbee61caecd42d62fe27170bb1d1110a13d11805 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Wed, 9 Aug 2023 15:56:26 +0000 Subject: [PATCH 39/57] Add client shutdown --- src/clients/tls_client.h | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/src/clients/tls_client.h b/src/clients/tls_client.h index 19dbf12daa50..2972b25dcc9b 100644 --- a/src/clients/tls_client.h +++ b/src/clients/tls_client.h @@ -142,7 +142,12 @@ namespace client init(); } - virtual ~TlsClient() {} + virtual ~TlsClient() + { + SSL* ssl; + BIO_get_ssl(bio, &ssl); + SSL_shutdown(ssl); + } auto get_ciphersuite_name() { @@ -207,28 +212,7 @@ namespace client std::vector read_all() { constexpr auto read_size = 4096; - std::vector buf(read_size); - auto ret = 0; - do - { - ret = BIO_read(bio, buf.data(), buf.size()); - } while (ret < 0 && BIO_should_retry(bio)); - - if (ret > 0) - { - buf.resize(ret); - } - else if (ret == 0) - { - connected = false; - throw std::logic_error("Underlying transport closed"); - } - else - { - throw std::logic_error(error_string(ERR_get_error())); - } - - return buf; + return read(read_size); } void set_tcp_nodelay(bool on) From b12690062d8c094aec41788fb81a30b6258c99a5 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Wed, 9 Aug 2023 15:57:05 +0000 Subject: [PATCH 40/57] Perf test fix: ignore (BIO_CB_CTRL | BIO_CB_RETURN) --- src/enclave/tls_session.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/enclave/tls_session.h b/src/enclave/tls_session.h index 58b502e66f1f..b4250631e556 100644 --- a/src/enclave/tls_session.h +++ b/src/enclave/tls_session.h @@ -673,7 +673,15 @@ namespace ccf (void)argi; (void)argl; - if (ret && oper == (BIO_CB_READ | BIO_CB_RETURN)) + if (ret == 1 && oper == (BIO_CB_CTRL | BIO_CB_RETURN)) + { + // This callback may be fired at the end of large batches of TLS frames + // on OpenSSL 3.x. Note that processed == nullptr in this case, hence + // the early exit. + return 0; + } + + if (ret && (oper == (BIO_CB_READ | BIO_CB_RETURN))) { // Pipe object void* ctx = (BIO_get_callback_arg(b)); From 6821652508c68ac2cc70b9a6d43cd3d027c7b68c Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 15 Aug 2023 13:00:39 +0000 Subject: [PATCH 41/57] Faster hashing --- src/clients/perf/scenario_perf_client.cpp | 2 + src/crypto/openssl/hash.cpp | 61 +++++++++++++++++++++-- src/crypto/openssl/hash.h | 2 + src/crypto/test/bench.cpp | 39 +++++++++------ src/enclave/enclave.h | 11 ++++ 5 files changed, 96 insertions(+), 19 deletions(-) diff --git a/src/clients/perf/scenario_perf_client.cpp b/src/clients/perf/scenario_perf_client.cpp index 33a22eb3e923..9b463ef9f19f 100644 --- a/src/clients/perf/scenario_perf_client.cpp +++ b/src/clients/perf/scenario_perf_client.cpp @@ -1,5 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the Apache 2.0 License. +#include "crypto/openssl/hash.h" #include "ds/files.h" #include "perf_client.h" @@ -132,6 +133,7 @@ int main(int argc, char** argv) { logger::config::default_init(); logger::config::level() = LoggerLevel::INFO; + crypto::openssl_sha256_init(); CLI::App cli_app{"Scenario Perf Client"}; ScenarioPerfClientOptions options(cli_app, argv[0]); diff --git a/src/crypto/openssl/hash.cpp b/src/crypto/openssl/hash.cpp index ae93518385f6..dcd29ca78aff 100644 --- a/src/crypto/openssl/hash.cpp +++ b/src/crypto/openssl/hash.cpp @@ -37,13 +37,68 @@ namespace crypto using namespace OpenSSL; + static thread_local EVP_MD_CTX* mdctx = nullptr; + static thread_local EVP_MD_CTX* basectx = nullptr; + + void openssl_sha256_init() + { + if (mdctx || basectx) + { + return; // Already initialised + } + + mdctx = EVP_MD_CTX_new(); + if (mdctx == nullptr) + { + throw std::logic_error("openssl_sha256_init: failed to create mdctx"); + } + basectx = EVP_MD_CTX_new(); + if (basectx == nullptr) + { + throw std::logic_error("openssl_sha256_init: failed to create basectx"); + } + if (EVP_DigestInit_ex(basectx, EVP_sha256(), nullptr) != 1) + { + throw std::logic_error("EVP_DigestInit_ex failed"); + } + } + + void openssl_sha256_shutdown() + { + if (mdctx) + { + EVP_MD_CTX_free(mdctx); + mdctx = nullptr; + } + if (basectx) + { + EVP_MD_CTX_free(basectx); + basectx = nullptr; + } + } + void openssl_sha256(const std::span& data, uint8_t* h) { - const EVP_MD* md = EVP_sha256(); - int rc = EVP_Digest(data.data(), data.size(), h, nullptr, md, nullptr); + // EVP_Digest calls are notoriously slow with OpenSSL 3.x (see + // https://github.com/openssl/openssl/issues/19612). Instead, we skip the + // calls to EVP_DigestInit_ex() by keeping 2 static thread-local contexts + // and reusing them between calls. This is about 2x faster than EVP_Digest + // for 128-byte buffers. + + int rc = EVP_MD_CTX_copy_ex(mdctx, basectx); + if (rc != 1) + { + throw std::logic_error(fmt::format("EVP_MD_CTX_copy_ex failed: {}", rc)); + } + rc = EVP_DigestUpdate(mdctx, data.data(), data.size()); + if (rc != 1) + { + throw std::logic_error(fmt::format("EVP_DigestUpdate failed: {}", rc)); + } + rc = EVP_DigestFinal_ex(mdctx, h, nullptr); if (rc != 1) { - throw std::logic_error(fmt::format("EVP_Digest failed: {}", rc)); + throw std::logic_error(fmt::format("EVP_DigestFinal_ex failed: {}", rc)); } } diff --git a/src/crypto/openssl/hash.h b/src/crypto/openssl/hash.h index c02ea7112462..606c4fdde17e 100644 --- a/src/crypto/openssl/hash.h +++ b/src/crypto/openssl/hash.h @@ -78,4 +78,6 @@ namespace crypto }; void openssl_sha256(const std::span& data, uint8_t* h); + void openssl_sha256_init(); + void openssl_sha256_shutdown(); } diff --git a/src/crypto/test/bench.cpp b/src/crypto/test/bench.cpp index bca3aff0a13f..e2f8ea37d486 100644 --- a/src/crypto/test/bench.cpp +++ b/src/crypto/test/bench.cpp @@ -113,6 +113,9 @@ static void benchmark_hmac(picobench::state& s) template static void benchmark_hash(picobench::state& s) { + logger::config::default_init(); + OpenSSLHashProvider::init(); + const auto contents = make_contents(); s.start_timer(); @@ -351,28 +354,32 @@ namespace Hashes PICOBENCH(sha_512_ossl_100k).PICO_HASH_SUFFIX(); } -PICOBENCH_SUITE("digest sha256"); -namespace SHA256_bench +template +static void sha256_bench(picobench::state& s) { - template - static void sha256_bench(picobench::state& s) + logger::config::default_init(); + crypto::openssl_sha256_init(); + + std::vector v(size); + for (size_t i = 0; i < size; ++i) { - std::vector v(size); - for (size_t i = 0; i < size; ++i) - { - v[i] = rand(); - } + v[i] = rand(); + } - crypto::Sha256Hash h; + crypto::Sha256Hash h; - s.start_timer(); - for (size_t i = 0; i < 10; ++i) - { - crypto::openssl_sha256(v, h.h.data()); - } - s.stop_timer(); + s.start_timer(); + for (size_t i = 0; i < 10; ++i) + { + crypto::openssl_sha256(v, h.h.data()); } + s.stop_timer(); + crypto::openssl_sha256_shutdown(); +} +PICOBENCH_SUITE("digest sha256"); +namespace SHA256_bench +{ auto openssl_sha256_base = sha256_bench<2 << 6>; PICOBENCH(openssl_sha256_base).PICO_HASH_SUFFIX(); diff --git a/src/enclave/enclave.h b/src/enclave/enclave.h index 0cf81059d52d..82d18206dd37 100644 --- a/src/enclave/enclave.h +++ b/src/enclave/enclave.h @@ -7,6 +7,7 @@ #include "ccf/node_subsystem_interface.h" #include "ccf/pal/enclave.h" #include "ccf/pal/mem.h" +#include "crypto/openssl/hash.h" #include "ds/oversized.h" #include "enclave_time.h" #include "indexing/enclave_lfs_access.h" @@ -94,6 +95,7 @@ namespace ccf { ccf::pal::initialize_enclave(); ccf::initialize_verifiers(); + crypto::openssl_sha256_init(); // From // https://software.intel.com/content/www/us/en/develop/articles/how-to-use-the-rdrand-engine-in-openssl-for-random-number-generation.html @@ -195,6 +197,7 @@ namespace ccf LOG_TRACE_FMT("Shutting down enclave"); ccf::shutdown_verifiers(); ccf::pal::shutdown_enclave(); + crypto::openssl_sha256_shutdown(); } CreateNodeStatus create_new_node( @@ -275,6 +278,7 @@ namespace ccf bool run_main() { + crypto::openssl_sha256_init(); LOG_DEBUG_FMT("Running main thread"); #ifndef VIRTUAL_ENCLAVE try @@ -473,6 +477,8 @@ namespace ccf LOG_INFO_FMT("Enclave stopped successfully. Stopping host..."); RINGBUFFER_WRITE_MESSAGE(AdminMessage::stopped, to_host); + crypto::openssl_sha256_shutdown(); + return true; } #ifndef VIRTUAL_ENCLAVE @@ -483,6 +489,7 @@ namespace ccf // exceptions bubble up to here and cause the node to shutdown. RINGBUFFER_WRITE_MESSAGE( AdminMessage::fatal_error_msg, to_host, std::string(e.what())); + crypto::openssl_sha256_shutdown(); return false; } #endif @@ -500,6 +507,8 @@ namespace ccf bool run_worker() { + crypto::openssl_sha256_init(); + LOG_DEBUG_FMT("Running worker thread"); #ifndef VIRTUAL_ENCLAVE try @@ -511,12 +520,14 @@ namespace ccf msg->data.tid, std::move(msg)); threading::ThreadMessaging::instance().run(); + crypto::openssl_sha256_shutdown(); } #ifndef VIRTUAL_ENCLAVE catch (const std::exception& e) { RINGBUFFER_WRITE_MESSAGE( AdminMessage::fatal_error_msg, to_host, std::string(e.what())); + crypto::openssl_sha256_shutdown(); return false; } #endif From 3526d301ea09318aabff3bd17da3dd66029bc1ea Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 15 Aug 2023 13:00:39 +0000 Subject: [PATCH 42/57] Faster SHA256 OpenSSL hashing --- src/clients/perf/scenario_perf_client.cpp | 3 ++ src/crypto/openssl/hash.cpp | 61 +++++++++++++++++++++-- src/crypto/openssl/hash.h | 2 + src/crypto/test/bench.cpp | 39 +++++++++------ src/enclave/enclave.h | 11 ++++ 5 files changed, 97 insertions(+), 19 deletions(-) diff --git a/src/clients/perf/scenario_perf_client.cpp b/src/clients/perf/scenario_perf_client.cpp index e97e7effd862..9b463ef9f19f 100644 --- a/src/clients/perf/scenario_perf_client.cpp +++ b/src/clients/perf/scenario_perf_client.cpp @@ -1,5 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the Apache 2.0 License. +#include "crypto/openssl/hash.h" #include "ds/files.h" #include "perf_client.h" @@ -131,6 +132,8 @@ class ScenarioPerfClient : public Base int main(int argc, char** argv) { logger::config::default_init(); + logger::config::level() = LoggerLevel::INFO; + crypto::openssl_sha256_init(); CLI::App cli_app{"Scenario Perf Client"}; ScenarioPerfClientOptions options(cli_app, argv[0]); diff --git a/src/crypto/openssl/hash.cpp b/src/crypto/openssl/hash.cpp index ae93518385f6..dcd29ca78aff 100644 --- a/src/crypto/openssl/hash.cpp +++ b/src/crypto/openssl/hash.cpp @@ -37,13 +37,68 @@ namespace crypto using namespace OpenSSL; + static thread_local EVP_MD_CTX* mdctx = nullptr; + static thread_local EVP_MD_CTX* basectx = nullptr; + + void openssl_sha256_init() + { + if (mdctx || basectx) + { + return; // Already initialised + } + + mdctx = EVP_MD_CTX_new(); + if (mdctx == nullptr) + { + throw std::logic_error("openssl_sha256_init: failed to create mdctx"); + } + basectx = EVP_MD_CTX_new(); + if (basectx == nullptr) + { + throw std::logic_error("openssl_sha256_init: failed to create basectx"); + } + if (EVP_DigestInit_ex(basectx, EVP_sha256(), nullptr) != 1) + { + throw std::logic_error("EVP_DigestInit_ex failed"); + } + } + + void openssl_sha256_shutdown() + { + if (mdctx) + { + EVP_MD_CTX_free(mdctx); + mdctx = nullptr; + } + if (basectx) + { + EVP_MD_CTX_free(basectx); + basectx = nullptr; + } + } + void openssl_sha256(const std::span& data, uint8_t* h) { - const EVP_MD* md = EVP_sha256(); - int rc = EVP_Digest(data.data(), data.size(), h, nullptr, md, nullptr); + // EVP_Digest calls are notoriously slow with OpenSSL 3.x (see + // https://github.com/openssl/openssl/issues/19612). Instead, we skip the + // calls to EVP_DigestInit_ex() by keeping 2 static thread-local contexts + // and reusing them between calls. This is about 2x faster than EVP_Digest + // for 128-byte buffers. + + int rc = EVP_MD_CTX_copy_ex(mdctx, basectx); + if (rc != 1) + { + throw std::logic_error(fmt::format("EVP_MD_CTX_copy_ex failed: {}", rc)); + } + rc = EVP_DigestUpdate(mdctx, data.data(), data.size()); + if (rc != 1) + { + throw std::logic_error(fmt::format("EVP_DigestUpdate failed: {}", rc)); + } + rc = EVP_DigestFinal_ex(mdctx, h, nullptr); if (rc != 1) { - throw std::logic_error(fmt::format("EVP_Digest failed: {}", rc)); + throw std::logic_error(fmt::format("EVP_DigestFinal_ex failed: {}", rc)); } } diff --git a/src/crypto/openssl/hash.h b/src/crypto/openssl/hash.h index c02ea7112462..606c4fdde17e 100644 --- a/src/crypto/openssl/hash.h +++ b/src/crypto/openssl/hash.h @@ -78,4 +78,6 @@ namespace crypto }; void openssl_sha256(const std::span& data, uint8_t* h); + void openssl_sha256_init(); + void openssl_sha256_shutdown(); } diff --git a/src/crypto/test/bench.cpp b/src/crypto/test/bench.cpp index bca3aff0a13f..e2f8ea37d486 100644 --- a/src/crypto/test/bench.cpp +++ b/src/crypto/test/bench.cpp @@ -113,6 +113,9 @@ static void benchmark_hmac(picobench::state& s) template static void benchmark_hash(picobench::state& s) { + logger::config::default_init(); + OpenSSLHashProvider::init(); + const auto contents = make_contents(); s.start_timer(); @@ -351,28 +354,32 @@ namespace Hashes PICOBENCH(sha_512_ossl_100k).PICO_HASH_SUFFIX(); } -PICOBENCH_SUITE("digest sha256"); -namespace SHA256_bench +template +static void sha256_bench(picobench::state& s) { - template - static void sha256_bench(picobench::state& s) + logger::config::default_init(); + crypto::openssl_sha256_init(); + + std::vector v(size); + for (size_t i = 0; i < size; ++i) { - std::vector v(size); - for (size_t i = 0; i < size; ++i) - { - v[i] = rand(); - } + v[i] = rand(); + } - crypto::Sha256Hash h; + crypto::Sha256Hash h; - s.start_timer(); - for (size_t i = 0; i < 10; ++i) - { - crypto::openssl_sha256(v, h.h.data()); - } - s.stop_timer(); + s.start_timer(); + for (size_t i = 0; i < 10; ++i) + { + crypto::openssl_sha256(v, h.h.data()); } + s.stop_timer(); + crypto::openssl_sha256_shutdown(); +} +PICOBENCH_SUITE("digest sha256"); +namespace SHA256_bench +{ auto openssl_sha256_base = sha256_bench<2 << 6>; PICOBENCH(openssl_sha256_base).PICO_HASH_SUFFIX(); diff --git a/src/enclave/enclave.h b/src/enclave/enclave.h index 0cf81059d52d..82d18206dd37 100644 --- a/src/enclave/enclave.h +++ b/src/enclave/enclave.h @@ -7,6 +7,7 @@ #include "ccf/node_subsystem_interface.h" #include "ccf/pal/enclave.h" #include "ccf/pal/mem.h" +#include "crypto/openssl/hash.h" #include "ds/oversized.h" #include "enclave_time.h" #include "indexing/enclave_lfs_access.h" @@ -94,6 +95,7 @@ namespace ccf { ccf::pal::initialize_enclave(); ccf::initialize_verifiers(); + crypto::openssl_sha256_init(); // From // https://software.intel.com/content/www/us/en/develop/articles/how-to-use-the-rdrand-engine-in-openssl-for-random-number-generation.html @@ -195,6 +197,7 @@ namespace ccf LOG_TRACE_FMT("Shutting down enclave"); ccf::shutdown_verifiers(); ccf::pal::shutdown_enclave(); + crypto::openssl_sha256_shutdown(); } CreateNodeStatus create_new_node( @@ -275,6 +278,7 @@ namespace ccf bool run_main() { + crypto::openssl_sha256_init(); LOG_DEBUG_FMT("Running main thread"); #ifndef VIRTUAL_ENCLAVE try @@ -473,6 +477,8 @@ namespace ccf LOG_INFO_FMT("Enclave stopped successfully. Stopping host..."); RINGBUFFER_WRITE_MESSAGE(AdminMessage::stopped, to_host); + crypto::openssl_sha256_shutdown(); + return true; } #ifndef VIRTUAL_ENCLAVE @@ -483,6 +489,7 @@ namespace ccf // exceptions bubble up to here and cause the node to shutdown. RINGBUFFER_WRITE_MESSAGE( AdminMessage::fatal_error_msg, to_host, std::string(e.what())); + crypto::openssl_sha256_shutdown(); return false; } #endif @@ -500,6 +507,8 @@ namespace ccf bool run_worker() { + crypto::openssl_sha256_init(); + LOG_DEBUG_FMT("Running worker thread"); #ifndef VIRTUAL_ENCLAVE try @@ -511,12 +520,14 @@ namespace ccf msg->data.tid, std::move(msg)); threading::ThreadMessaging::instance().run(); + crypto::openssl_sha256_shutdown(); } #ifndef VIRTUAL_ENCLAVE catch (const std::exception& e) { RINGBUFFER_WRITE_MESSAGE( AdminMessage::fatal_error_msg, to_host, std::string(e.what())); + crypto::openssl_sha256_shutdown(); return false; } #endif From a5f3ee4f9e4fa0b92203409e90a89eb587b724fa Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 15 Aug 2023 13:08:45 +0000 Subject: [PATCH 43/57] Fix --- src/crypto/test/bench.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/crypto/test/bench.cpp b/src/crypto/test/bench.cpp index e2f8ea37d486..d5f590717b1a 100644 --- a/src/crypto/test/bench.cpp +++ b/src/crypto/test/bench.cpp @@ -114,7 +114,6 @@ template static void benchmark_hash(picobench::state& s) { logger::config::default_init(); - OpenSSLHashProvider::init(); const auto contents = make_contents(); From 25fc715769324de696d70ef6c8a7452f4585a980 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 15 Aug 2023 13:11:58 +0000 Subject: [PATCH 44/57] Canaries --- .daily_canary | 4 ++-- .threading_canary | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.daily_canary b/.daily_canary index 5a59cd564060..21f88a729b7e 100644 --- a/.daily_canary +++ b/.daily_canary @@ -1,4 +1,4 @@ --- ___ ___ (- -) (= =) | Y & +--? - ( V ) z . z O +---=---' -/--x-m- /--n-n---xXx--/--yY-----..... \ No newline at end of file + ( V ) \ . \ O +---=---' +/--x-m- /--n-n---xXx--/--yY-----. diff --git a/.threading_canary b/.threading_canary index ff262be76437..40d41071089a 100644 --- a/.threading_canary +++ b/.threading_canary @@ -1 +1 @@ -THIS looks like a job for Threading Canar!y!1!.. +THIS looks like a job for Threading Canard!y!1!.. From 0a212253837ec3b2e09a0263b3f767b8df1ad7c1 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 15 Aug 2023 13:20:23 +0000 Subject: [PATCH 45/57] Fix build --- src/crypto/test/bench.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/crypto/test/bench.cpp b/src/crypto/test/bench.cpp index e2f8ea37d486..d5f590717b1a 100644 --- a/src/crypto/test/bench.cpp +++ b/src/crypto/test/bench.cpp @@ -114,7 +114,6 @@ template static void benchmark_hash(picobench::state& s) { logger::config::default_init(); - OpenSSLHashProvider::init(); const auto contents = make_contents(); From a13c26867639f2d7f221814164a5a14f08fdc824 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 15 Aug 2023 14:50:11 +0000 Subject: [PATCH 46/57] . --- src/crypto/openssl/hash.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/crypto/openssl/hash.cpp b/src/crypto/openssl/hash.cpp index dcd29ca78aff..5900ce4963b0 100644 --- a/src/crypto/openssl/hash.cpp +++ b/src/crypto/openssl/hash.cpp @@ -85,6 +85,11 @@ namespace crypto // and reusing them between calls. This is about 2x faster than EVP_Digest // for 128-byte buffers. + if (mdctx == nullptr || basectx == nullptr) + { + openssl_sha256_init(); + } + int rc = EVP_MD_CTX_copy_ex(mdctx, basectx); if (rc != 1) { From bc1f31ef8e24bea800e98ce5d7888fec9be806c6 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 15 Aug 2023 14:51:49 +0000 Subject: [PATCH 47/57] Simplify --- src/clients/perf/scenario_perf_client.cpp | 1 - src/enclave/enclave.h | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/clients/perf/scenario_perf_client.cpp b/src/clients/perf/scenario_perf_client.cpp index 9b463ef9f19f..734501eb6563 100644 --- a/src/clients/perf/scenario_perf_client.cpp +++ b/src/clients/perf/scenario_perf_client.cpp @@ -133,7 +133,6 @@ int main(int argc, char** argv) { logger::config::default_init(); logger::config::level() = LoggerLevel::INFO; - crypto::openssl_sha256_init(); CLI::App cli_app{"Scenario Perf Client"}; ScenarioPerfClientOptions options(cli_app, argv[0]); diff --git a/src/enclave/enclave.h b/src/enclave/enclave.h index 82d18206dd37..7d7f149fd0cf 100644 --- a/src/enclave/enclave.h +++ b/src/enclave/enclave.h @@ -95,7 +95,6 @@ namespace ccf { ccf::pal::initialize_enclave(); ccf::initialize_verifiers(); - crypto::openssl_sha256_init(); // From // https://software.intel.com/content/www/us/en/develop/articles/how-to-use-the-rdrand-engine-in-openssl-for-random-number-generation.html @@ -278,7 +277,6 @@ namespace ccf bool run_main() { - crypto::openssl_sha256_init(); LOG_DEBUG_FMT("Running main thread"); #ifndef VIRTUAL_ENCLAVE try @@ -507,8 +505,6 @@ namespace ccf bool run_worker() { - crypto::openssl_sha256_init(); - LOG_DEBUG_FMT("Running worker thread"); #ifndef VIRTUAL_ENCLAVE try From 9a12d2666aa9994ecc84c7e416b5a33fe227eef6 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Tue, 15 Aug 2023 14:59:14 +0000 Subject: [PATCH 48/57] Cleanup --- src/clients/perf/scenario_perf_client.cpp | 1 - src/crypto/test/bench.cpp | 3 --- 2 files changed, 4 deletions(-) diff --git a/src/clients/perf/scenario_perf_client.cpp b/src/clients/perf/scenario_perf_client.cpp index 734501eb6563..33a22eb3e923 100644 --- a/src/clients/perf/scenario_perf_client.cpp +++ b/src/clients/perf/scenario_perf_client.cpp @@ -1,6 +1,5 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the Apache 2.0 License. -#include "crypto/openssl/hash.h" #include "ds/files.h" #include "perf_client.h" diff --git a/src/crypto/test/bench.cpp b/src/crypto/test/bench.cpp index d5f590717b1a..98a8cc2e0fb0 100644 --- a/src/crypto/test/bench.cpp +++ b/src/crypto/test/bench.cpp @@ -113,8 +113,6 @@ static void benchmark_hmac(picobench::state& s) template static void benchmark_hash(picobench::state& s) { - logger::config::default_init(); - const auto contents = make_contents(); s.start_timer(); @@ -356,7 +354,6 @@ namespace Hashes template static void sha256_bench(picobench::state& s) { - logger::config::default_init(); crypto::openssl_sha256_init(); std::vector v(size); From 48cb0fe9bd4a0da0053d426816abe43013ed10fb Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Wed, 16 Aug 2023 08:17:43 +0000 Subject: [PATCH 49/57] PR comments --- src/crypto/openssl/hash.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/crypto/openssl/hash.cpp b/src/crypto/openssl/hash.cpp index 5900ce4963b0..e9d7fb13d1cd 100644 --- a/src/crypto/openssl/hash.cpp +++ b/src/crypto/openssl/hash.cpp @@ -55,10 +55,13 @@ namespace crypto basectx = EVP_MD_CTX_new(); if (basectx == nullptr) { + mdctx = nullptr; throw std::logic_error("openssl_sha256_init: failed to create basectx"); } if (EVP_DigestInit_ex(basectx, EVP_sha256(), nullptr) != 1) { + mdctx = nullptr; + basectx = nullptr; throw std::logic_error("EVP_DigestInit_ex failed"); } } @@ -87,7 +90,8 @@ namespace crypto if (mdctx == nullptr || basectx == nullptr) { - openssl_sha256_init(); + throw std::logic_error( + "openssl_sha256 failed: openssl_sha256_init should be called first"); } int rc = EVP_MD_CTX_copy_ex(mdctx, basectx); From 6f3ff4dd1951e94c6a7bff3d10e108bcd616b034 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Wed, 16 Aug 2023 09:03:49 +0000 Subject: [PATCH 50/57] Fix tests --- src/clients/perf/scenario_perf_client.cpp | 2 ++ src/crypto/test/crypto.cpp | 2 ++ src/enclave/enclave.h | 2 ++ src/host/test/ledger.cpp | 3 +++ src/kv/test/kv_contention.cpp | 5 +++++ src/kv/test/kv_test.cpp | 3 +++ src/node/rpc/test/frontend_test.cpp | 13 +++++++++++++ src/node/rpc/test/node_frontend_test.cpp | 3 +++ src/node/test/encryptor.cpp | 16 +++++++++++++++- src/node/test/historical_queries.cpp | 5 +++++ src/node/test/history.cpp | 3 +++ src/node/test/snapshot.cpp | 3 +++ src/node/test/snapshotter.cpp | 3 +++ 13 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/clients/perf/scenario_perf_client.cpp b/src/clients/perf/scenario_perf_client.cpp index 33a22eb3e923..9b463ef9f19f 100644 --- a/src/clients/perf/scenario_perf_client.cpp +++ b/src/clients/perf/scenario_perf_client.cpp @@ -1,5 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the Apache 2.0 License. +#include "crypto/openssl/hash.h" #include "ds/files.h" #include "perf_client.h" @@ -132,6 +133,7 @@ int main(int argc, char** argv) { logger::config::default_init(); logger::config::level() = LoggerLevel::INFO; + crypto::openssl_sha256_init(); CLI::App cli_app{"Scenario Perf Client"}; ScenarioPerfClientOptions options(cli_app, argv[0]); diff --git a/src/crypto/test/crypto.cpp b/src/crypto/test/crypto.cpp index edf346aeca34..296357ea44f9 100644 --- a/src/crypto/test/crypto.cpp +++ b/src/crypto/test/crypto.cpp @@ -881,6 +881,7 @@ TEST_CASE("PEM to JWK and back") TEST_CASE("Incremental hash") { + crypto::openssl_sha256_init(); auto simple_hash = crypto::Sha256Hash(contents); INFO("Incremental hash"); @@ -921,4 +922,5 @@ TEST_CASE("Incremental hash") REQUIRE_THROWS_AS(ihash->finalise(), std::logic_error); } } + crypto::openssl_sha256_shutdown(); } \ No newline at end of file diff --git a/src/enclave/enclave.h b/src/enclave/enclave.h index 7d7f149fd0cf..1123759d099c 100644 --- a/src/enclave/enclave.h +++ b/src/enclave/enclave.h @@ -277,6 +277,7 @@ namespace ccf bool run_main() { + crypto::openssl_sha256_init(); LOG_DEBUG_FMT("Running main thread"); #ifndef VIRTUAL_ENCLAVE try @@ -505,6 +506,7 @@ namespace ccf bool run_worker() { + crypto::openssl_sha256_init(); LOG_DEBUG_FMT("Running worker thread"); #ifndef VIRTUAL_ENCLAVE try diff --git a/src/host/test/ledger.cpp b/src/host/test/ledger.cpp index f362d1047113..8f066b2d244f 100644 --- a/src/host/test/ledger.cpp +++ b/src/host/test/ledger.cpp @@ -4,6 +4,7 @@ #include "ccf/crypto/sha256_hash.h" #include "ccf/ds/logger.h" +#include "crypto/openssl/hash.h" #include "ds/files.h" #include "ds/serialized.h" #include "host/snapshots.h" @@ -1725,9 +1726,11 @@ TEST_CASE("Ledger init with existing files") int main(int argc, char** argv) { logger::config::default_init(); + crypto::openssl_sha256_init(); doctest::Context context; context.applyCommandLine(argc, argv); int res = context.run(); + crypto::openssl_sha256_shutdown(); if (context.shouldExit()) return res; return res; diff --git a/src/kv/test/kv_contention.cpp b/src/kv/test/kv_contention.cpp index 167b8c4667ae..65d74c68603b 100644 --- a/src/kv/test/kv_contention.cpp +++ b/src/kv/test/kv_contention.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the Apache 2.0 License. #include "ccf/ds/logger.h" +#include "crypto/openssl/hash.h" #include "kv/compacted_version_conflict.h" #include "kv/kv_serialiser.h" #include "kv/store.h" @@ -79,6 +80,7 @@ DOCTEST_TEST_CASE("Concurrent kv access" * doctest::test_suite("concurrency")) } auto thread_fn = [](void* a) { + crypto::openssl_sha256_init(); auto args = static_cast(a); for (size_t i = 0u; i < tx_count; ++i) @@ -137,6 +139,7 @@ DOCTEST_TEST_CASE("Concurrent kv access" * doctest::test_suite("concurrency")) // Notify that this thread has finished --*args->counter; + crypto::openssl_sha256_shutdown(); }; // Start a thread which continually compacts at the latest version, until all @@ -265,6 +268,7 @@ DOCTEST_TEST_CASE( std::atomic conflict_count = 0; auto point_at_previous_write = [&]() { + crypto::openssl_sha256_init(); auto sleep_time = std::chrono::microseconds(5); while (true) { @@ -306,6 +310,7 @@ DOCTEST_TEST_CASE( sleep_time = std::chrono::microseconds((size_t)(sleep_time.count() * factor)); } + crypto::openssl_sha256_shutdown(); }; std::vector threads; diff --git a/src/kv/test/kv_test.cpp b/src/kv/test/kv_test.cpp index 96359f99a2b2..77fbc1ecced8 100644 --- a/src/kv/test/kv_test.cpp +++ b/src/kv/test/kv_test.cpp @@ -5,6 +5,7 @@ #include "ccf/kv/map.h" #include "ccf/kv/set.h" #include "ccf/kv/value.h" +#include "crypto/openssl/hash.h" #include "kv/compacted_version_conflict.h" #include "kv/kv_serialiser.h" #include "kv/store.h" @@ -3255,9 +3256,11 @@ TEST_CASE("Ledger entry chunk request") int main(int argc, char** argv) { logger::config::default_init(); + crypto::openssl_sha256_init(); doctest::Context context; context.applyCommandLine(argc, argv); int res = context.run(); + crypto::openssl_sha256_shutdown(); if (context.shouldExit()) return res; return res; diff --git a/src/node/rpc/test/frontend_test.cpp b/src/node/rpc/test/frontend_test.cpp index 86e5d8ac9821..643577a7093b 100644 --- a/src/node/rpc/test/frontend_test.cpp +++ b/src/node/rpc/test/frontend_test.cpp @@ -9,6 +9,7 @@ #include "ccf/json_handler.h" #include "ccf/kv/map.h" #include "ccf/serdes.h" +#include "crypto/openssl/hash.h" #include "ds/files.h" #include "enclave/enclave_time.h" #include "frontend_test_infra.h" @@ -1488,15 +1489,18 @@ TEST_CASE("Manual conflicts") auto call_pausable = [&]( std::shared_ptr session, http_status expected_status) { + crypto::openssl_sha256_init(); auto req = create_simple_request("/pausable"); auto serialized_call = req.build_request(); auto rpc_ctx = ccf::make_rpc_context(session, serialized_call); frontend.process(rpc_ctx); auto response = parse_response(rpc_ctx->serialise_response()); CHECK(response.status == expected_status); + crypto::openssl_sha256_shutdown(); }; auto get_metrics = [&]() { + crypto::openssl_sha256_init(); auto req = create_simple_request("/api/metrics"); req.set_method(HTTP_GET); auto serialized_call = req.build_request(); @@ -1516,30 +1520,36 @@ TEST_CASE("Manual conflicts") } } + crypto::openssl_sha256_shutdown(); return ret; }; auto get_value = [&](const std::string& table = TF::DST) { + crypto::openssl_sha256_init(); auto tx = network.tables->create_tx(); auto handle = tx.ro(table); auto ret = handle->get(TF::KEY); REQUIRE(tx.commit() == kv::CommitResult::SUCCESS); + crypto::openssl_sha256_shutdown(); return ret; }; auto update_value = [&](size_t n, const std::string& table = TF::SRC, size_t key = TF::KEY) { + crypto::openssl_sha256_init(); auto tx = network.tables->create_tx(); using TF = TestManualConflictsFrontend; auto handle = tx.wo(table); handle->put(key, n); REQUIRE(tx.commit() == kv::CommitResult::SUCCESS); + crypto::openssl_sha256_shutdown(); }; auto run_test = [&]( std::function&& read_write_op, std::shared_ptr session = user_session, http_status expected_status = HTTP_STATUS_OK) { + crypto::openssl_sha256_init(); frontend.before_read.ready = false; frontend.after_read.ready = false; frontend.before_write.ready = false; @@ -1556,6 +1566,7 @@ TEST_CASE("Manual conflicts") frontend.after_write.wait(); worker.join(); + crypto::openssl_sha256_shutdown(); }; { @@ -1720,9 +1731,11 @@ int main(int argc, char** argv) std::chrono::system_clock::now().time_since_epoch()); threading::ThreadMessaging::init(1); + crypto::openssl_sha256_init(); doctest::Context context; context.applyCommandLine(argc, argv); int res = context.run(); + crypto::openssl_sha256_shutdown(); if (context.shouldExit()) return res; return res; diff --git a/src/node/rpc/test/node_frontend_test.cpp b/src/node/rpc/test/node_frontend_test.cpp index c7e124595a7d..f912ea1f903e 100644 --- a/src/node/rpc/test/node_frontend_test.cpp +++ b/src/node/rpc/test/node_frontend_test.cpp @@ -5,6 +5,7 @@ #include "ccf/crypto/verifier.h" #include "ccf/ds/logger.h" #include "ccf/serdes.h" +#include "crypto/openssl/hash.h" #include "frontend_test_infra.h" #include "kv/test/null_encryptor.h" #include "nlohmann/json.hpp" @@ -317,9 +318,11 @@ TEST_CASE("Add a node to an open service") int main(int argc, char** argv) { + crypto::openssl_sha256_init(); doctest::Context context; context.applyCommandLine(argc, argv); int res = context.run(); + crypto::openssl_sha256_shutdown(); if (context.shouldExit()) return res; return res; diff --git a/src/node/test/encryptor.cpp b/src/node/test/encryptor.cpp index fdb902adbc13..b247e39ae5d0 100644 --- a/src/node/test/encryptor.cpp +++ b/src/node/test/encryptor.cpp @@ -1,9 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the Apache 2.0 License. -#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#define DOCTEST_CONFIG_IMPLEMENT #include "kv/encryptor.h" +#include "crypto/openssl/hash.h" #include "kv/kv_types.h" #include "kv/store.h" #include "kv/test/stub_consensus.h" @@ -442,3 +443,16 @@ TEST_CASE("Encryptor rollback") commit_one(store, map); commit_one(store, map); } + +int main(int argc, char** argv) +{ + logger::config::default_init(); + crypto::openssl_sha256_init(); + doctest::Context context; + context.applyCommandLine(argc, argv); + int res = context.run(); + crypto::openssl_sha256_shutdown(); + if (context.shouldExit()) + return res; + return res; +} diff --git a/src/node/test/historical_queries.cpp b/src/node/test/historical_queries.cpp index 0536a851aa28..59c90b9b8e4e 100644 --- a/src/node/test/historical_queries.cpp +++ b/src/node/test/historical_queries.cpp @@ -9,6 +9,7 @@ #include "ccf/crypto/rsa_key_pair.h" #include "ccf/pal/locking.h" +#include "crypto/openssl/hash.h" #include "ds/messaging.h" #include "ds/test/stub_writer.h" #include "kv/test/null_encryptor.h" @@ -1109,6 +1110,7 @@ TEST_CASE("StateCache concurrent access") std::atomic finished = false; std::thread host_thread([&]() { + crypto::openssl_sha256_init(); auto ledger = construct_host_ledger(state.kv_store->get_consensus()); size_t last_handled_write = 0; @@ -1158,6 +1160,7 @@ TEST_CASE("StateCache concurrent access") cache.tick(std::chrono::milliseconds(100)); std::this_thread::sleep_for(std::chrono::milliseconds(1)); } + crypto::openssl_sha256_shutdown(); }); constexpr auto per_thread_queries = 30; @@ -1702,9 +1705,11 @@ TEST_CASE("Recover historical ledger secrets") int main(int argc, char** argv) { threading::ThreadMessaging::init(1); + crypto::openssl_sha256_init(); doctest::Context context; context.applyCommandLine(argc, argv); int res = context.run(); + crypto::openssl_sha256_shutdown(); if (context.shouldExit()) return res; return res; diff --git a/src/node/test/history.cpp b/src/node/test/history.cpp index 9ffce5d61320..c2d62534f410 100644 --- a/src/node/test/history.cpp +++ b/src/node/test/history.cpp @@ -6,6 +6,7 @@ #include "ccf/ds/logger.h" #include "ccf/service/tables/nodes.h" #include "crypto/certs.h" +#include "crypto/openssl/hash.h" #include "ds/x509_time_fmt.h" #include "kv/kv_types.h" #include "kv/store.h" @@ -474,9 +475,11 @@ TEST_CASE( int main(int argc, char** argv) { threading::ThreadMessaging::init(1); + crypto::openssl_sha256_init(); doctest::Context context; context.applyCommandLine(argc, argv); int res = context.run(); + crypto::openssl_sha256_shutdown(); if (context.shouldExit()) return res; return res; diff --git a/src/node/test/snapshot.cpp b/src/node/test/snapshot.cpp index 139c8365004c..46a798648476 100644 --- a/src/node/test/snapshot.cpp +++ b/src/node/test/snapshot.cpp @@ -3,6 +3,7 @@ #include "ccf/crypto/key_pair.h" #include "ccf/service/tables/nodes.h" +#include "crypto/openssl/hash.h" #include "kv/test/null_encryptor.h" #include "kv/test/stub_consensus.h" #include "node/history.h" @@ -172,9 +173,11 @@ TEST_CASE("Snapshot with merkle tree" * doctest::test_suite("snapshot")) int main(int argc, char** argv) { threading::ThreadMessaging::init(1); + crypto::openssl_sha256_init(); doctest::Context context; context.applyCommandLine(argc, argv); int res = context.run(); + crypto::openssl_sha256_shutdown(); if (context.shouldExit()) return res; return res; diff --git a/src/node/test/snapshotter.cpp b/src/node/test/snapshotter.cpp index 5ea06f53ddff..c5985ffbd81e 100644 --- a/src/node/test/snapshotter.cpp +++ b/src/node/test/snapshotter.cpp @@ -4,6 +4,7 @@ #include "node/snapshotter.h" #include "ccf/ds/logger.h" +#include "crypto/openssl/hash.h" #include "ds/ring_buffer.h" #include "kv/test/null_encryptor.h" #include "kv/test/stub_consensus.h" @@ -522,9 +523,11 @@ TEST_CASE("Rekey ledger while snapshot is in progress") int main(int argc, char** argv) { threading::ThreadMessaging::init(1); + crypto::openssl_sha256_init(); doctest::Context context; context.applyCommandLine(argc, argv); int res = context.run(); + crypto::openssl_sha256_shutdown(); if (context.shouldExit()) return res; return res; From 5ba93c284a4c65a8940e97028faf9630042bb425 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Wed, 16 Aug 2023 09:53:04 +0000 Subject: [PATCH 51/57] Fix e2e test --- src/enclave/enclave.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/enclave/enclave.h b/src/enclave/enclave.h index 1123759d099c..ad1bea2ec0c4 100644 --- a/src/enclave/enclave.h +++ b/src/enclave/enclave.h @@ -95,6 +95,7 @@ namespace ccf { ccf::pal::initialize_enclave(); ccf::initialize_verifiers(); + crypto::openssl_sha256_init(); // From // https://software.intel.com/content/www/us/en/develop/articles/how-to-use-the-rdrand-engine-in-openssl-for-random-number-generation.html From 0800e978a64afabdf2ee3064809f69ef9e70b660 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Wed, 16 Aug 2023 10:21:45 +0000 Subject: [PATCH 52/57] Fix perf tests --- src/node/test/history_bench.cpp | 6 +++++- tests/perf-system/submitter/submit.cpp | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/node/test/history_bench.cpp b/src/node/test/history_bench.cpp index 69e4d2ff1736..a7f30eb1efb1 100644 --- a/src/node/test/history_bench.cpp +++ b/src/node/test/history_bench.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the Apache 2.0 License. +#include "crypto/openssl/hash.h" #include "kv/test/stub_consensus.h" #include "node/history.h" @@ -162,8 +163,11 @@ int main(int argc, char* argv[]) { logger::config::level() = LoggerLevel::FATAL; threading::ThreadMessaging::init(1); + crypto::openssl_sha256_init(); picobench::runner runner; runner.parse_cmd_line(argc, argv); - return runner.run(); + auto ret = runner.run(); + crypto::openssl_sha256_init(); + return ret; } diff --git a/tests/perf-system/submitter/submit.cpp b/tests/perf-system/submitter/submit.cpp index 78d1b3dc10d8..d750c82100f0 100644 --- a/tests/perf-system/submitter/submit.cpp +++ b/tests/perf-system/submitter/submit.cpp @@ -6,6 +6,7 @@ #include "ccf/service/node_info_network.h" #include "clients/perf/perf_client.h" #include "clients/rpc_tls_client.h" +#include "crypto/openssl/hash.h" #include "ds/files.h" #include "handle_arguments.h" #include "parquet_data.h" @@ -266,6 +267,7 @@ int main(int argc, char** argv) logger::config::default_init(); logger::config::level() = LoggerLevel::INFO; + crypto::openssl_sha256_init(); CLI::App cli_app{"Perf Tool"}; ArgumentParser args("Perf Tool", cli_app); CLI11_PARSE(cli_app, argc, argv); @@ -379,6 +381,7 @@ int main(int argc, char** argv) } store_parquet_results(args, data_handler); + crypto::openssl_sha256_shutdown(); return 0; } From 971b4f668cae4b886a65cdbdb841807a38787fa9 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Thu, 17 Aug 2023 13:55:26 +0000 Subject: [PATCH 53/57] `EC_` --- src/crypto/openssl/key_pair.cpp | 13 ++++++++++--- src/crypto/openssl/openssl_wrappers.h | 2 ++ src/crypto/openssl/public_key.cpp | 17 ++++++++++++++--- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/crypto/openssl/key_pair.cpp b/src/crypto/openssl/key_pair.cpp index e4878edcdde9..23658daf7815 100644 --- a/src/crypto/openssl/key_pair.cpp +++ b/src/crypto/openssl/key_pair.cpp @@ -483,10 +483,17 @@ namespace crypto // As per https://www.openssl.org/docs/man1.0.2/man3/BN_num_bytes.html, size // should not be calculated with BN_num_bytes(d)! size_t size = EVP_PKEY_bits(key) / 8; - Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(key)); - const BIGNUM* d = EC_KEY_get0_private_key(eckey); - std::vector bytes(size); + Unique_BIGNUM d; +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + BIGNUM* bn_d = NULL; + CHECK1(EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_PRIV_KEY, &bn_d)); + d = bn_d; + BN_free(bn_d); +#else + Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(key)); + d = EC_KEY_get0_private_key(eckey); +#endif auto rc = BN_bn2binpad(d, bytes.data(), size); if (rc != size) { diff --git a/src/crypto/openssl/openssl_wrappers.h b/src/crypto/openssl/openssl_wrappers.h index 2d99766296f7..5fbf0e51b078 100644 --- a/src/crypto/openssl/openssl_wrappers.h +++ b/src/crypto/openssl/openssl_wrappers.h @@ -368,6 +368,7 @@ namespace crypto {} }; +#if !(defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3) struct Unique_EC_KEY : public Unique_SSL_OBJECT { Unique_EC_KEY(int nid) : @@ -383,6 +384,7 @@ namespace crypto { using Unique_SSL_OBJECT::Unique_SSL_OBJECT; }; +#endif struct Unique_EVP_ENCODE_CTX : public Unique_SSL_OBJECT< EVP_ENCODE_CTX, diff --git a/src/crypto/openssl/public_key.cpp b/src/crypto/openssl/public_key.cpp index db35e379d1fe..e0efa1f339d3 100644 --- a/src/crypto/openssl/public_key.cpp +++ b/src/crypto/openssl/public_key.cpp @@ -326,13 +326,24 @@ namespace crypto PublicKey::Coordinates PublicKey_OpenSSL::coordinates() const { + Coordinates r; + Unique_BIGNUM x, y; + Unique_EC_GROUP group(get_openssl_group_id()); +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + BIGNUM* bn_x = NULL; + BIGNUM* bn_y = NULL; + CHECK1(EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_EC_PUB_X, &bn_x)); + CHECK1(EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_EC_PUB_Y, &bn_y)); + x = bn_x; + y = bn_y; + BN_free(bn_x); + BN_free(bn_y); +#else Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(key)); const EC_POINT* p = EC_KEY_get0_public_key(eckey); - Unique_EC_GROUP group(get_openssl_group_id()); Unique_BN_CTX bn_ctx; - Unique_BIGNUM x, y; CHECK1(EC_POINT_get_affine_coordinates(group, p, x, y, bn_ctx)); - Coordinates r; +#endif int sz = EC_GROUP_get_degree(group) / 8; r.x.resize(sz); r.y.resize(sz); From 38ff2c2678b1a55f13cd35c7f7312029dc250534 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 21 Aug 2023 10:45:58 +0000 Subject: [PATCH 54/57] ENGINE --- cmake/crypto.cmake | 7 ------- src/enclave/enclave.h | 10 ++++++++++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/cmake/crypto.cmake b/cmake/crypto.cmake index a37213a68e8a..35f0f21b7541 100644 --- a/cmake/crypto.cmake +++ b/cmake/crypto.cmake @@ -31,13 +31,6 @@ if(COMPILE_TARGET STREQUAL "sgx") target_link_libraries(ccfcrypto.enclave PUBLIC qcbor.enclave) target_link_libraries(ccfcrypto.enclave PUBLIC t_cose.enclave) - # To be removed once https://github.com/microsoft/CCF/issues/5291 is complete - if(USE_OPENSSL_3) - target_compile_definitions( - ccfcrypto.enclave PUBLIC OPENSSL_API_COMPAT=0x10101000L - ) - endif() - install( TARGETS ccfcrypto.enclave EXPORT ccf diff --git a/src/enclave/enclave.h b/src/enclave/enclave.h index ad1bea2ec0c4..370af53dabb8 100644 --- a/src/enclave/enclave.h +++ b/src/enclave/enclave.h @@ -51,7 +51,9 @@ namespace ccf std::unique_ptr node; ringbuffer::WriterPtr to_host = nullptr; std::chrono::microseconds last_tick_time; +#if !(defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3) ENGINE* rdrand_engine = nullptr; +#endif StartType start_type; @@ -97,6 +99,11 @@ namespace ccf ccf::initialize_verifiers(); crypto::openssl_sha256_init(); + // https://github.com/microsoft/CCF/issues/5569 + // Open Enclave with OpenSSL 3.x (default for SGX) is built with RDCPU + // (https://github.com/openenclave/openenclave/blob/master/docs/OpenSSLSupport.md#how-to-use-rand-apis) + // and so does not need to make use of the (deprecated) ENGINE_x API. +#if !(defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3) // From // https://software.intel.com/content/www/us/en/develop/articles/how-to-use-the-rdrand-engine-in-openssl-for-random-number-generation.html if ( @@ -110,6 +117,7 @@ namespace ccf throw ccf::ccf_openssl_rdrand_init_error( "could not initialize RDRAND engine for OpenSSL"); } +#endif to_host = writer_factory->create_writer_to_outside(); @@ -188,12 +196,14 @@ namespace ccf ~Enclave() { +#if !(defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3) if (rdrand_engine) { LOG_TRACE_FMT("Finishing RDRAND engine"); ENGINE_finish(rdrand_engine); ENGINE_free(rdrand_engine); } +#endif LOG_TRACE_FMT("Shutting down enclave"); ccf::shutdown_verifiers(); ccf::pal::shutdown_enclave(); From b8936942237d4f1a4cbe941a56305c9895d301ab Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 21 Aug 2023 14:05:41 +0000 Subject: [PATCH 55/57] Unique EVP_PKEY_CTX --- src/crypto/openssl/key_pair.cpp | 2 +- src/crypto/openssl/openssl_wrappers.h | 5 +++++ src/crypto/openssl/public_key.cpp | 4 ++-- src/crypto/openssl/rsa_key_pair.cpp | 4 ++-- src/crypto/openssl/rsa_public_key.cpp | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/crypto/openssl/key_pair.cpp b/src/crypto/openssl/key_pair.cpp index 23658daf7815..92c058db793a 100644 --- a/src/crypto/openssl/key_pair.cpp +++ b/src/crypto/openssl/key_pair.cpp @@ -94,7 +94,7 @@ namespace crypto OSSL_PKEY_PARAM_PRIV_KEY, d_raw_native.data(), d_raw_native.size()); params[3] = OSSL_PARAM_construct_end(); - EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + Unique_EVP_PKEY_CTX pctx("EC"); CHECK1(EVP_PKEY_fromdata_init(pctx)); CHECK1(EVP_PKEY_fromdata(pctx, &key, EVP_PKEY_KEYPAIR, params)); #else diff --git a/src/crypto/openssl/openssl_wrappers.h b/src/crypto/openssl/openssl_wrappers.h index 5fbf0e51b078..f4f8bc0606fb 100644 --- a/src/crypto/openssl/openssl_wrappers.h +++ b/src/crypto/openssl/openssl_wrappers.h @@ -214,6 +214,11 @@ namespace crypto Unique_SSL_OBJECT( EVP_PKEY_CTX_new_id(key_type, NULL), EVP_PKEY_CTX_free) {} + Unique_EVP_PKEY_CTX(const std::string& name) : + Unique_SSL_OBJECT( + EVP_PKEY_CTX_new_from_name(NULL, name.c_str(), NULL), + EVP_PKEY_CTX_free) + {} }; struct Unique_EVP_MD_CTX diff --git a/src/crypto/openssl/public_key.cpp b/src/crypto/openssl/public_key.cpp index e0efa1f339d3..c4a1204d53e6 100644 --- a/src/crypto/openssl/public_key.cpp +++ b/src/crypto/openssl/public_key.cpp @@ -111,7 +111,7 @@ namespace crypto OSSL_PKEY_PARAM_PUB_KEY, buf.data(), buf.size()); params[2] = OSSL_PARAM_construct_end(); - EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + Unique_EVP_PKEY_CTX pctx("EC"); CHECK1(EVP_PKEY_fromdata_init(pctx)); CHECK1(EVP_PKEY_fromdata(pctx, &key, EVP_PKEY_PUBLIC_KEY, params)); #else @@ -294,7 +294,7 @@ namespace crypto OSSL_PKEY_PARAM_GROUP_NAME, (char*)OSSL_EC_curve_nid2name(nid), 0); params[1] = OSSL_PARAM_construct_end(); - EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + Unique_EVP_PKEY_CTX pctx("EC"); EVP_PKEY_fromdata_init(pctx); EVP_PKEY_fromdata( pctx, &pkey, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, params); diff --git a/src/crypto/openssl/rsa_key_pair.cpp b/src/crypto/openssl/rsa_key_pair.cpp index 6cf80aee243f..d8e4fbe6f90d 100644 --- a/src/crypto/openssl/rsa_key_pair.cpp +++ b/src/crypto/openssl/rsa_key_pair.cpp @@ -22,7 +22,7 @@ namespace crypto CHECK1(BN_set_word(big_exp, public_exponent)); #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 - EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + Unique_EVP_PKEY_CTX pctx("RSA"); CHECK1(EVP_PKEY_keygen_init(pctx)); CHECKPOSITIVE(EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, public_key_size)); CHECKPOSITIVE(EVP_PKEY_CTX_set1_rsa_keygen_pubexp(pctx, big_exp)); @@ -115,7 +115,7 @@ namespace crypto qi_raw_native.size()); params[8] = OSSL_PARAM_construct_end(); - EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + Unique_EVP_PKEY_CTX pctx("RSA"); CHECK1(EVP_PKEY_fromdata_init(pctx)); CHECK1(EVP_PKEY_fromdata(pctx, &key, EVP_PKEY_KEYPAIR, params)); #else diff --git a/src/crypto/openssl/rsa_public_key.cpp b/src/crypto/openssl/rsa_public_key.cpp index 4497f9de77c4..67f332c7f2dc 100644 --- a/src/crypto/openssl/rsa_public_key.cpp +++ b/src/crypto/openssl/rsa_public_key.cpp @@ -114,7 +114,7 @@ namespace crypto OSSL_PKEY_PARAM_RSA_E, e_raw.data(), e_raw.size()); params[2] = OSSL_PARAM_construct_end(); - EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + Unique_EVP_PKEY_CTX pctx("RSA"); CHECK1(EVP_PKEY_fromdata_init(pctx)); CHECK1(EVP_PKEY_fromdata(pctx, &key, EVP_PKEY_PUBLIC_KEY, params)); #else From 1a5c482cd3460f7e3ef1224f3471b04b7369acb7 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 21 Aug 2023 14:54:30 +0000 Subject: [PATCH 56/57] Last of memory leaks --- src/crypto/openssl/key_pair.cpp | 3 +-- src/crypto/openssl/openssl_wrappers.h | 7 +++++++ src/crypto/openssl/public_key.cpp | 9 ++++----- src/crypto/openssl/rsa_key_pair.cpp | 4 +--- src/crypto/openssl/rsa_public_key.cpp | 4 ++-- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/crypto/openssl/key_pair.cpp b/src/crypto/openssl/key_pair.cpp index 92c058db793a..371da7ae17f3 100644 --- a/src/crypto/openssl/key_pair.cpp +++ b/src/crypto/openssl/key_pair.cpp @@ -488,8 +488,7 @@ namespace crypto #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 BIGNUM* bn_d = NULL; CHECK1(EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_PRIV_KEY, &bn_d)); - d = bn_d; - BN_free(bn_d); + d.reset(bn_d); #else Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(key)); d = EC_KEY_get0_private_key(eckey); diff --git a/src/crypto/openssl/openssl_wrappers.h b/src/crypto/openssl/openssl_wrappers.h index f4f8bc0606fb..54b21e31d3f3 100644 --- a/src/crypto/openssl/openssl_wrappers.h +++ b/src/crypto/openssl/openssl_wrappers.h @@ -22,6 +22,10 @@ #include #include +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 +# include +#endif + namespace crypto { namespace OpenSSL @@ -214,11 +218,14 @@ namespace crypto Unique_SSL_OBJECT( EVP_PKEY_CTX_new_id(key_type, NULL), EVP_PKEY_CTX_free) {} + +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 Unique_EVP_PKEY_CTX(const std::string& name) : Unique_SSL_OBJECT( EVP_PKEY_CTX_new_from_name(NULL, name.c_str(), NULL), EVP_PKEY_CTX_free) {} +#endif }; struct Unique_EVP_MD_CTX diff --git a/src/crypto/openssl/public_key.cpp b/src/crypto/openssl/public_key.cpp index c4a1204d53e6..20fb5d0db89e 100644 --- a/src/crypto/openssl/public_key.cpp +++ b/src/crypto/openssl/public_key.cpp @@ -302,6 +302,7 @@ namespace crypto pkey = d2i_PublicKey(EVP_PKEY_EC, &pkey, &pp, raw.size()); if (pkey == NULL) { + EVP_PKEY_free(pkey); throw std::logic_error("Error loading public key"); } @@ -320,8 +321,8 @@ namespace crypto CHECK1(EC_KEY_set_public_key(ec_key, p)); CHECK1(EVP_PKEY_set1_EC_KEY(pk, ec_key)); EVP_PKEY_up_ref(pk); -#endif return pk; +#endif } PublicKey::Coordinates PublicKey_OpenSSL::coordinates() const @@ -333,11 +334,9 @@ namespace crypto BIGNUM* bn_x = NULL; BIGNUM* bn_y = NULL; CHECK1(EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_EC_PUB_X, &bn_x)); + x.reset(bn_x); CHECK1(EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_EC_PUB_Y, &bn_y)); - x = bn_x; - y = bn_y; - BN_free(bn_x); - BN_free(bn_y); + y.reset(bn_y); #else Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(key)); const EC_POINT* p = EC_KEY_get0_public_key(eckey); diff --git a/src/crypto/openssl/rsa_key_pair.cpp b/src/crypto/openssl/rsa_key_pair.cpp index d8e4fbe6f90d..affb5f1056de 100644 --- a/src/crypto/openssl/rsa_key_pair.cpp +++ b/src/crypto/openssl/rsa_key_pair.cpp @@ -28,11 +28,9 @@ namespace crypto CHECKPOSITIVE(EVP_PKEY_CTX_set1_rsa_keygen_pubexp(pctx, big_exp)); CHECK1(EVP_PKEY_generate(pctx, &key)); #else - RSA* rsa; - CHECKNULL(rsa = RSA_new()); + Unique_RSA rsa; CHECK1(RSA_generate_key_ex(rsa, public_key_size, big_exp, NULL)); CHECK1(EVP_PKEY_set1_RSA(key, rsa)); - RSA_free(rsa); #endif } diff --git a/src/crypto/openssl/rsa_public_key.cpp b/src/crypto/openssl/rsa_public_key.cpp index 67f332c7f2dc..ca5d1bc5ab72 100644 --- a/src/crypto/openssl/rsa_public_key.cpp +++ b/src/crypto/openssl/rsa_public_key.cpp @@ -215,10 +215,10 @@ namespace crypto #if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 Unique_BIGNUM RSAPublicKey_OpenSSL::get_bn_param(const char* key_name) const { + Unique_BIGNUM r; BIGNUM* bn = NULL; CHECK1(EVP_PKEY_get_bn_param(key, key_name, &bn)); - Unique_BIGNUM r(bn); - BN_free(bn); + r.reset(bn); return r; } #endif From 86523f6c68e57b477fe0a79c1ab8f58e0f5f154c Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Mon, 21 Aug 2023 15:14:13 +0000 Subject: [PATCH 57/57] Remove log --- src/crypto/test/bench.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/crypto/test/bench.cpp b/src/crypto/test/bench.cpp index 6294458ac836..98a8cc2e0fb0 100644 --- a/src/crypto/test/bench.cpp +++ b/src/crypto/test/bench.cpp @@ -113,8 +113,6 @@ static void benchmark_hmac(picobench::state& s) template static void benchmark_hash(picobench::state& s) { - logger::config::default_init(); - const auto contents = make_contents(); s.start_timer();