Skip to content

Commit

Permalink
Update CCF to 4.0.12 and add support for OpenSSL 3.x (#173)
Browse files Browse the repository at this point in the history
  • Loading branch information
andpiccione authored Jan 9, 2024
1 parent 677ca57 commit d3b20b3
Show file tree
Hide file tree
Showing 16 changed files with 183 additions and 21 deletions.
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

0 comments on commit d3b20b3

Please sign in to comment.