Skip to content

Commit

Permalink
Merge branch 'main' into f/6594-conditional-plain-ecrypt-decrypt
Browse files Browse the repository at this point in the history
  • Loading branch information
maxtropets authored Nov 6, 2024
2 parents d20738f + 7573264 commit 013efc4
Show file tree
Hide file tree
Showing 31 changed files with 434 additions and 166 deletions.
31 changes: 30 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,43 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [6.0.0-dev6]

[6.0.0-dev6]: https://github.com/microsoft/CCF/releases/tag/6.0.0-dev6

### Added

- Added a `ccf::any_cert_auth_policy` (C++), or `any_cert` (JS/TS), implementing TLS client certificate authentication, but without checking for the presence of the certificate in the governance user or member tables. This enables applications wanting to do so to perform user management in application space, using application tables (#6608).

## [6.0.0-dev5]

[6.0.0-dev5]: https://github.com/microsoft/CCF/releases/tag/6.0.0-dev5

### Added

- Updated `ccf::cose::edit::set_unprotected_header()` API, to allow removing the unprotected header altogether (#6607).
- Updated `ccf.cose.verify_receipt()` to support checking the claim_digest against a reference value (#6607).

## [6.0.0-dev4]

[6.0.0-dev4]: https://github.com/microsoft/CCF/releases/tag/6.0.0-dev4

### Added

- `ccf.cose.verify_receipt()` to support verifiying [draft COSE receipts](https://datatracker.ietf.org/doc/draft-ietf-cose-merkle-tree-proofs/) (#6603).

### Removed

- Remove SECP256K1 support as a part of the migration to Azure Linux (#6592).

## [6.0.0-dev3]

[6.0.0-dev3]: https://github.com/microsoft/CCF/releases/tag/6.0.0-dev3

### Changed

- Set VMPL value when creating SNP attestations, and check VMPL value is in guest range when verifiying attestation, since recent [updates allow host-initiated attestations](https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/programmer-references/56860.pdf) (#6583).
- Added ccf::cose::edit::set_unprotected_header() API, to allow easy injection of proofs in signatures, and of receipts in signed statements (#6586).
- Added `ccf::cose::edit::set_unprotected_header()` API, to allow easy injection of proofs in signatures, and of receipts in signed statements (#6586).

## [6.0.0-dev2]

Expand Down
7 changes: 7 additions & 0 deletions doc/build_apps/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ Policies
.. doxygenvariable:: ccf::member_cert_auth_policy
:project: CCF

.. doxygenvariable:: ccf::any_cert_auth_policy
:project: CCF

.. doxygenvariable:: ccf::member_cose_sign1_auth_policy
:project: CCF

Expand All @@ -86,6 +89,10 @@ Identities
:project: CCF
:members:

.. doxygenstruct:: ccf::AnyCertAuthnIdentity
:project: CCF
:members:

.. doxygenstruct:: ccf::UserCOSESign1AuthnIdentity
:project: CCF
:members:
Expand Down
1 change: 1 addition & 0 deletions doc/build_apps/js_app_bundle.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ Each endpoint object contains the following information:

- ``"user_cert"``
- ``"member_cert"``
- ``"any_cert"``
- ``"jwt"``
- ``"user_cose_sign1"``
- ``"no_auth"``
Expand Down
5 changes: 5 additions & 0 deletions include/ccf/common_auth_policies.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ namespace ccf
static std::shared_ptr<MemberCertAuthnPolicy> member_cert_auth_policy =
std::make_shared<MemberCertAuthnPolicy>();

/** Authenticate using TLS session identity, but do not check
* the certificate against any table, and let the application decide */
static std::shared_ptr<AnyCertAuthnPolicy> any_cert_auth_policy =
std::make_shared<AnyCertAuthnPolicy>();

/** Authenticate using JWT, validating the token using the
* @c public:ccf.gov.jwt.public_signing_keys_metadata table */
static std::shared_ptr<JwtAuthnPolicy> jwt_auth_policy =
Expand Down
43 changes: 26 additions & 17 deletions include/ccf/crypto/cose.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,43 @@ namespace ccf::cose::edit

struct AtKey
{
/// @brief The key at which to insert the value.
/// @brief The sub-key at which to insert the value.
int64_t key;
};

using Type = std::variant<InArray, AtKey>;
}

namespace desc
{
struct Empty
{};

struct Value
{
/// @brief The type of position at which to insert the value.
pos::Type position;
/// @brief The top-level key at which to insert the value.
int64_t key;
/// @brief The value to insert in the unprotected header.
const std::vector<uint8_t>& value;
};

using Type = std::variant<Empty, Value>;
}

/**
* Set the unprotected header of a COSE_Sign1 message, to a map containing
* @p key and depending on the value of @p position, either an array
* containing
* @p value, or a map with key @p subkey and value @p value.
* Set the unprotected header of a COSE_Sign1 message, according to a
* descriptor.
*
* Useful to add a proof to a signature to turn it into a receipt, or to
* Useful to add a proof to a signature to turn it into a receipt, to
* add a receipt to a signed statement to turn it into a transparent
* statement.
* statement, or simply to strip the unprotected header from a COSE Sign1.
*
* @param cose_input The COSE_Sign1 message to edit.
* @param key The key at which to insert either an array or a map.
* @param position Either InArray or AtKey, to determine whether to insert an
* array or a map.
* @param value The value to insert either in the array or the map.
*
* @return The COSE_Sign1 message with the new unprotected header.
* @param descriptor An object describing whether and how to set the
* unprotected header.
*/
std::vector<uint8_t> set_unprotected_header(
const std::span<const uint8_t>& cose_input,
int64_t key,
pos::Type position,
const std::vector<uint8_t> value);
const std::span<const uint8_t>& cose_input, const desc::Type& descriptor);
}
5 changes: 0 additions & 5 deletions include/ccf/crypto/curve.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ namespace ccf::crypto
SECP384R1,
/// The SECP256R1 curve
SECP256R1,
/// The SECP256K1 curve
SECP256K1,
/// The CURVE25519 curve
CURVE25519,
X25519
Expand All @@ -34,7 +32,6 @@ namespace ccf::crypto
{{CurveID::NONE, "None"},
{CurveID::SECP384R1, "Secp384R1"},
{CurveID::SECP256R1, "Secp256R1"},
{CurveID::SECP256K1, "Secp256K1"},
{CurveID::CURVE25519, "Curve25519"},
{CurveID::X25519, "X25519"}});

Expand All @@ -50,8 +47,6 @@ namespace ccf::crypto
return MDType::SHA384;
case CurveID::SECP256R1:
return MDType::SHA256;
case CurveID::SECP256K1:
return MDType::SHA256;
default:
{
throw std::logic_error(fmt::format("Unhandled CurveID: {}", ec));
Expand Down
12 changes: 2 additions & 10 deletions include/ccf/crypto/jwk.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,12 @@ namespace ccf::crypto
enum class JsonWebKeyECCurve
{
P256 = 0,
P256K1 = 1,
P384 = 2,
P521 = 3
P384 = 1,
P521 = 2
};
DECLARE_JSON_ENUM(
JsonWebKeyECCurve,
{{JsonWebKeyECCurve::P256, "P-256"},
{JsonWebKeyECCurve::P256K1,
"secp256k1"}, // As per
// https://www.rfc-editor.org/rfc/rfc8812#name-jose-and-cose-secp256k1-cur
{JsonWebKeyECCurve::P384, "P-384"},
{JsonWebKeyECCurve::P521, "P-521"}});

Expand All @@ -59,8 +55,6 @@ namespace ccf::crypto
return JsonWebKeyECCurve::P384;
case CurveID::SECP256R1:
return JsonWebKeyECCurve::P256;
case CurveID::SECP256K1:
return JsonWebKeyECCurve::P256K1;
default:
throw std::logic_error(fmt::format("Unknown curve {}", curve_id));
}
Expand All @@ -74,8 +68,6 @@ namespace ccf::crypto
return CurveID::SECP384R1;
case JsonWebKeyECCurve::P256:
return CurveID::SECP256R1;
case JsonWebKeyECCurve::P256K1:
return CurveID::SECP256K1;
default:
throw std::logic_error(fmt::format("Unknown JWK curve {}", jwk_curve));
}
Expand Down
1 change: 1 addition & 0 deletions include/ccf/endpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ namespace ccf::endpoints
*
* @see ccf::empty_auth_policy
* @see ccf::user_cert_auth_policy
* @see ccf::any_cert_auth_policy
*/
AuthnPolicies authn_policies;
};
Expand Down
34 changes: 34 additions & 0 deletions include/ccf/endpoints/authentication/cert_auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,38 @@ namespace ccf
return SECURITY_SCHEME_NAME;
};
};

struct AnyCertAuthnIdentity : public AuthnIdentity
{
// Certificate as a vector of DER-encoded bytes
std::vector<uint8_t> cert;
};

class AnyCertAuthnPolicy : public AuthnPolicy
{
protected:
std::unique_ptr<ValidityPeriodsCache> validity_periods;

public:
static constexpr auto SECURITY_SCHEME_NAME = "any_cert";

AnyCertAuthnPolicy();
virtual ~AnyCertAuthnPolicy();

std::unique_ptr<AuthnIdentity> authenticate(
ccf::kv::ReadOnlyTx& tx,
const std::shared_ptr<ccf::RpcContext>& ctx,
std::string& error_reason) override;

std::optional<OpenAPISecuritySchema> get_openapi_security_schema()
const override
{
return get_cert_based_security_schema();
}

virtual std::string get_security_scheme_name() override
{
return SECURITY_SCHEME_NAME;
};
};
}
8 changes: 8 additions & 0 deletions include/ccf/endpoints/authentication/js.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ namespace ccf
ccf::MemberCertAuthnPolicy::SECURITY_SCHEME_NAME,
ccf::member_cert_auth_policy);

policies.emplace(
ccf::AnyCertAuthnPolicy::SECURITY_SCHEME_NAME,
ccf::any_cert_auth_policy);

policies.emplace(
ccf::JwtAuthnPolicy::SECURITY_SCHEME_NAME, ccf::jwt_auth_policy);

Expand Down Expand Up @@ -62,6 +66,10 @@ namespace ccf
{
return ccf::MemberCertAuthnPolicy::SECURITY_SCHEME_NAME;
}
else if constexpr (std::is_same_v<T, ccf::AnyCertAuthnIdentity>)
{
return ccf::AnyCertAuthnPolicy::SECURITY_SCHEME_NAME;
}
else if constexpr (std::is_same_v<T, ccf::JwtAuthnIdentity>)
{
return ccf::JwtAuthnPolicy::SECURITY_SCHEME_NAME;
Expand Down
20 changes: 14 additions & 6 deletions js/ccf-app/src/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,18 @@ export interface EmptyAuthnIdentity extends AuthnIdentityCommon {
policy: "no_auth";
}

interface UserMemberAuthnIdentityCommon extends AuthnIdentityCommon {
interface CertAuthnIdentityCommon extends AuthnIdentityCommon {
/**
* PEM-encoded certificate.
*/
cert: string;
}

export interface AnyCertAuthnIdentity extends CertAuthnIdentityCommon {
policy: "any_cert";
}

interface UserMemberAuthnIdentityCommon extends CertAuthnIdentityCommon {
/**
* User/member ID.
*/
Expand All @@ -127,11 +138,6 @@ interface UserMemberAuthnIdentityCommon extends AuthnIdentityCommon {
* User/member data object.
*/
data: any;

/**
* PEM-encoded user/member certificate.
*/
cert: string;
}

export interface UserCertAuthnIdentity extends UserMemberAuthnIdentityCommon {
Expand Down Expand Up @@ -193,6 +199,7 @@ export interface AllOfAuthnIdentity extends AuthnIdentityCommon {

user_cert?: UserCertAuthnIdentity;
member_cert?: MemberCertAuthnIdentity;
any_cert?: AnyCertAuthnIdentity;
user_cose_sign1?: UserCOSESign1AuthnIdentity;
member_cose_sign1?: MemberCOSESign1AuthnIdentity;
jwt?: JwtAuthnIdentity;
Expand All @@ -207,6 +214,7 @@ export type AuthnIdentity =
| EmptyAuthnIdentity
| UserCertAuthnIdentity
| MemberCertAuthnIdentity
| AnyCertAuthnIdentity
| JwtAuthnIdentity
| MemberCOSESign1AuthnIdentity
| UserCOSESign1AuthnIdentity
Expand Down
2 changes: 1 addition & 1 deletion js/ccf-app/src/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ export interface CCFCrypto {
/**
* Generate an ECDSA key pair.
*
* @param curve The name of the curve, one of "secp256r1", "secp256k1", "secp384r1".
* @param curve The name of the curve, one of "secp256r1", "secp384r1".
*/
generateEcdsaKeyPair(curve: string): CryptoKeyPair;

Expand Down
9 changes: 1 addition & 8 deletions js/ccf-app/test/polyfill.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,6 @@ describe("polyfill", function () {
assert.isTrue(pair.privateKey.startsWith("-----BEGIN PRIVATE KEY-----"));
});
});
describe("generateEcdsaKeyPair/secp256k1", function () {
it("generates a random ECDSA P256K1 key pair", function () {
const pair = ccf.crypto.generateEcdsaKeyPair("secp256k1");
assert.isTrue(pair.publicKey.startsWith("-----BEGIN PUBLIC KEY-----"));
assert.isTrue(pair.privateKey.startsWith("-----BEGIN PRIVATE KEY-----"));
});
});
describe("generateEcdsaKeyPair/secp384r1", function () {
it("generates a random ECDSA P384R1 key pair", function () {
const pair = ccf.crypto.generateEcdsaKeyPair("secp384r1");
Expand Down Expand Up @@ -586,7 +579,7 @@ describe("polyfill", function () {
describe("pemToJwk and jwkToPem", function () {
it("EC", function () {
const my_kid = "my_kid";
const curves = ["secp256r1", "secp256k1", "secp384r1"];
const curves = ["secp256r1", "secp384r1"];
for (const curve of curves) {
const pair = ccf.crypto.generateEcdsaKeyPair(curve);
{
Expand Down
2 changes: 1 addition & 1 deletion python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "ccf"
version = "6.0.0-dev3"
version = "6.0.0-dev6"
authors = [
{ name="CCF Team", email="[email protected]" },
]
Expand Down
Loading

0 comments on commit 013efc4

Please sign in to comment.