Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update CCF to 4.0.12 and add support for OpenSSL 3.x #173

Merged
merged 9 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/ccf/app/dev:4.0.7-virtual
FROM mcr.microsoft.com/ccf/app/dev:4.0.12-virtual

# Dependency of the virtual build of attested-fetch.
RUN apt-get update && apt-get install -y libcurl4-openssl-dev
2 changes: 1 addition & 1 deletion .github/workflows/build-test-virtual.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
run:
shell: bash
container:
image: mcr.microsoft.com/ccf/app/dev:4.0.7-virtual
image: mcr.microsoft.com/ccf/app/dev:4.0.12-virtual
env:
# Helps to distinguish between CI and local builds.
SCITT_CI: 1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
name: Analyze

runs-on: ubuntu-latest
container: mcr.microsoft.com/ccf/app/dev:4.0.7-virtual
container: mcr.microsoft.com/ccf/app/dev:4.0.12-virtual

permissions:
actions: read
Expand Down
2 changes: 1 addition & 1 deletion .pipelines/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ trigger:
parameters:
- name: CCF_VERSION
type: string
default: 4.0.7
default: 4.0.12

resources:
containers:
Expand Down
8 changes: 4 additions & 4 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ Follow the steps below to setup your development environment, replacing `<sgx|vi

2. Install dependencies:
```sh
wget https://github.com/microsoft/CCF/archive/refs/tags/ccf-4.0.7.tar.gz
tar xvzf ccf-4.0.7.tar.gz
cd CCF-ccf-4.0.7/getting_started/setup_vm/
./run.sh app-dev.yml -e ccf_ver=4.0.7 -e platform=<sgx|virtual> -e clang_version=<11|15>
wget https://github.com/microsoft/CCF/archive/refs/tags/ccf-4.0.12.tar.gz
tar xvzf ccf-4.0.12.tar.gz
cd CCF-ccf-4.0.12/getting_started/setup_vm/
./run.sh app-dev.yml -e ccf_ver=4.0.12 -e platform=<sgx|virtual> -e clang_version=<11|15>
```

## Building
Expand Down
4 changes: 2 additions & 2 deletions app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ if (CCF_UNSAFE)
message(FATAL_ERROR "The unsafe CCF variant is only available on SGX builds.")
endif()

find_package(ccf_sgx_unsafe 4.0.7 REQUIRED)
find_package(ccf_sgx_unsafe 4.0.12 REQUIRED)
else()
find_package(ccf_${COMPILE_TARGET} 4.0.7 REQUIRED)
find_package(ccf_${COMPILE_TARGET} 4.0.12 REQUIRED)
endif()

if (ENABLE_PREFIX_TREE)
Expand Down
62 changes: 56 additions & 6 deletions app/src/openssl_wrappers.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,24 @@
#include <fmt/format.h>
#include <memory>
#include <openssl/asn1.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/engine.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>

// Note: This file was extended from:
// https://github.com/microsoft/CCF/blob/main/src/crypto/openssl/openssl_wrappers.h

#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
# include <openssl/evp.h>
#endif

namespace scitt
{
namespace OpenSSL
Expand Down Expand Up @@ -49,7 +55,7 @@ namespace scitt
}
}

/// Throws if rc is 1 and has error
/// Throws if rc is not 1 and has error
inline void CHECK1(int rc)
{
unsigned long ec = ERR_get_error();
Expand Down Expand Up @@ -80,6 +86,26 @@ namespace scitt
}
}

// Throws if values are not equal
inline void CHECKEQUAL(int expect, int actual)
{
if (expect != actual)
{
unsigned long ec = ERR_get_error();
throw std::runtime_error(
fmt::format("OpenSSL error: {}", error_string(ec)));
}
}

// Throws if value is not positive
inline void CHECKPOSITIVE(int val)
{
if (val <= 0)
{
throw std::runtime_error("OpenSSL error: expected positive value");
}
}

/*
* Unique pointer wrappers for SSL objects, with SSL' specific constructors
* and destructors. Some objects need special functionality, others are just
Expand Down Expand Up @@ -177,6 +203,12 @@ namespace scitt
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)
{}
#endif
};

struct Unique_EVP_PKEY_CTX
Expand All @@ -189,6 +221,14 @@ namespace scitt
Unique_SSL_OBJECT(
EVP_PKEY_CTX_new_id(EVP_PKEY_EC, 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_X509_REQ
Expand Down Expand Up @@ -287,6 +327,8 @@ namespace scitt
struct Unique_BIGNUM : public Unique_SSL_OBJECT<BIGNUM, BN_new, BN_free>
{
using Unique_SSL_OBJECT::Unique_SSL_OBJECT;

Unique_BIGNUM(const BIGNUM* n) : Unique_BIGNUM(BN_dup(n), BN_free) {}
};

struct Unique_X509_TIME
Expand Down Expand Up @@ -330,25 +372,33 @@ namespace scitt
Unique_SSL_OBJECT(
EC_POINT_new(group), EC_POINT_free, /*check_null=*/true)
{}
Unique_EC_POINT(EC_POINT* point) :
Unique_SSL_OBJECT(point, EC_POINT_free, /*check_null=*/true)
{}
};

#if !(defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3)
struct Unique_EC_KEY : public Unique_SSL_OBJECT<EC_KEY, nullptr, nullptr>
{
Unique_EC_KEY(int nid) :
Unique_SSL_OBJECT(
EC_KEY_new_by_curve_name(nid), EC_KEY_free, /*check_null=*/true)
{}
Unique_EC_KEY(EC_KEY* key) :
Unique_SSL_OBJECT(key, EC_KEY_free, /*check_null=*/true)
{}
};

struct Unique_EVP_ENCODE_CTX : public Unique_SSL_OBJECT<
EVP_ENCODE_CTX,
EVP_ENCODE_CTX_new,
EVP_ENCODE_CTX_free>
struct Unique_RSA : public Unique_SSL_OBJECT<RSA, RSA_new, RSA_free>
{
using Unique_SSL_OBJECT::Unique_SSL_OBJECT;
};
#endif

struct Unique_RSA : public Unique_SSL_OBJECT<RSA, RSA_new, RSA_free>
struct Unique_EVP_ENCODE_CTX : public Unique_SSL_OBJECT<
EVP_ENCODE_CTX,
EVP_ENCODE_CTX_new,
EVP_ENCODE_CTX_free>
{
using Unique_SSL_OBJECT::Unique_SSL_OBJECT;
};
Expand Down
44 changes: 44 additions & 0 deletions app/src/public_key.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@

#include <optional>

#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
# include <openssl/core_names.h>
# include <openssl/encoder.h>
# include <openssl/evp.h>
#endif

namespace scitt
{
class PublicKey
Expand All @@ -20,6 +26,43 @@ namespace scitt
cose_alg(cose_alg)
{}

#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
PublicKey(
std::vector<uint8_t>& n_raw,
std::vector<uint8_t>& e_raw,
std::optional<int64_t> cose_alg) :
cose_alg(cose_alg)
{
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();

OpenSSL::Unique_EVP_PKEY_CTX pctx("RSA");
OpenSSL::CHECK1(EVP_PKEY_fromdata_init(pctx));
OpenSSL::CHECK1(
EVP_PKEY_fromdata(pctx, (EVP_PKEY**)&key, EVP_PKEY_PUBLIC_KEY, params));
}

PublicKey(
std::vector<uint8_t>& buf, int nid, std::optional<int64_t> cose_alg) :
cose_alg(cose_alg)
{
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_construct_octet_string(
OSSL_PKEY_PARAM_PUB_KEY, buf.data(), buf.size());
params[2] = OSSL_PARAM_construct_end();

OpenSSL::Unique_EVP_PKEY_CTX pctx("EC");
OpenSSL::CHECK1(EVP_PKEY_fromdata_init(pctx));
OpenSSL::CHECK1(
EVP_PKEY_fromdata(pctx, (EVP_PKEY**)&key, EVP_PKEY_PUBLIC_KEY, params));
}
#else
PublicKey(
const OpenSSL::Unique_RSA& rsa_key, std::optional<int64_t> cose_alg) :
cose_alg(cose_alg)
Expand All @@ -39,6 +82,7 @@ namespace scitt
throw std::runtime_error("EC key could not be set");
}
}
#endif

PublicKey(
int ossl_type,
Expand Down
39 changes: 39 additions & 0 deletions app/src/verifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@
#include <ccf/service/tables/cert_bundles.h>
#include <fmt/format.h>

#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
# include <openssl/core_names.h>
# include <openssl/encoder.h>
# include <openssl/param_build.h>
#endif

namespace scitt::verifier
{
struct VerificationError : public std::runtime_error
Expand Down Expand Up @@ -538,6 +544,17 @@ namespace scitt::verifier
throw VerificationError("JWK e could not be parsed");
}

#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
std::pair<std::vector<uint8_t>, std::vector<uint8_t>> r(
BN_num_bytes(n_bn), BN_num_bytes(e_bn));

OpenSSL::CHECKPOSITIVE(
BN_bn2nativepad(n_bn, r.first.data(), r.first.size()));
OpenSSL::CHECKPOSITIVE(
BN_bn2nativepad(e_bn, r.second.data(), r.second.size()));

return PublicKey(r.first, r.second, cose_alg);
#else
OpenSSL::Unique_RSA rsa;
if (!RSA_set0_key(rsa, n_bn, e_bn, nullptr))
{
Expand All @@ -548,6 +565,7 @@ namespace scitt::verifier
(void)e_bn.release();

return PublicKey(rsa, cose_alg);
#endif
}

if (jwk.kty == "OKP" && jwk.crv == "Ed25519" && jwk.x.has_value())
Expand Down Expand Up @@ -590,13 +608,34 @@ namespace scitt::verifier
{
throw VerificationError("JWK EC Key has no valid supported curve");
}

#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
OpenSSL::Unique_BN_CTX bn_ctx;
OpenSSL::Unique_EC_GROUP group(nid);
OpenSSL::Unique_EC_POINT p(group);
OpenSSL::CHECK1(
EC_POINT_set_affine_coordinates(group, p, x_bn, y_bn, bn_ctx));
size_t buf_size = EC_POINT_point2oct(
group, p, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, bn_ctx);
std::vector<uint8_t> buf(buf_size);
OpenSSL::CHECKPOSITIVE(EC_POINT_point2oct(
group,
p,
POINT_CONVERSION_UNCOMPRESSED,
buf.data(),
buf.size(),
bn_ctx));

return PublicKey(buf, nid, cose_alg);
#else
auto ec_key = OpenSSL::Unique_EC_KEY(nid);
if (!EC_KEY_set_public_key_affine_coordinates(ec_key, x_bn, y_bn))
{
throw std::runtime_error("EC key could not be set");
}

return PublicKey(ec_key, cose_alg);
#endif
}

throw VerificationError("JWK has no valid supported key");
Expand Down
8 changes: 8 additions & 0 deletions app/unit-tests/cbor_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include "cbor.h"

#include "cbor_test_utils.h"

#include <gtest/gtest.h>
#include <rapidcheck.h>
#include <rapidcheck/gtest.h>
Expand All @@ -13,6 +15,7 @@ namespace
{
RC_GTEST_PROP(CborHasher, hash_text, ())
{
crypto::openssl_sha256_init();
auto text = *rc::gen::arbitrary<std::string>();

cbor::hasher hasher;
Expand All @@ -24,10 +27,12 @@ namespace
auto h2 = crypto::Sha256Hash(encoder.finish());

RC_ASSERT(h1 == h2);
crypto::openssl_sha256_shutdown();
}

RC_GTEST_PROP(Cbor, hash_bytes, ())
{
crypto::openssl_sha256_init();
auto bytes = *rc::gen::arbitrary<std::vector<uint8_t>>();

cbor::hasher hasher;
Expand All @@ -39,10 +44,12 @@ namespace
auto h2 = crypto::Sha256Hash(encoder.finish());

RC_ASSERT(h1 == h2);
crypto::openssl_sha256_shutdown();
}

RC_GTEST_PROP(Cbor, hash_array, ())
{
crypto::openssl_sha256_init();
auto fields = *rc::gen::arbitrary<std::vector<std::vector<uint8_t>>>();

cbor::hasher hasher;
Expand All @@ -63,5 +70,6 @@ namespace
auto h2 = crypto::Sha256Hash(encoder.finish());

RC_ASSERT(h1 == h2);
crypto::openssl_sha256_shutdown();
}
}
Loading
Loading