Skip to content

Commit 6318f52

Browse files
authored
Merge branch 'main' into test_endorsed_tcb
2 parents 9d56938 + 71c64f5 commit 6318f52

File tree

12 files changed

+220
-6
lines changed

12 files changed

+220
-6
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
99

1010
[7.0.0-dev12]: https://github.com/microsoft/CCF/releases/tag/ccf-7.0.0-dev12
1111

12+
### Added
13+
14+
- `NetworkIdentitySubsystemInterface` now exposes `get_trusted_keys()`, returning all trusted network identity keys as a `TrustedKeys` map (#7690).
15+
1216
### Changed
1317

1418
- Refactored the user facing surface of self-healing-open and local sealing. The whole feature is now `sealing-recovery` with `self-healing-open` now referred to as the `recovery-decision-protocol`. (#7679)

cmake/crypto.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ set(CCFCRYPTO_SRC
55
${CCF_DIR}/src/crypto/base64.cpp
66
${CCF_DIR}/src/crypto/entropy.cpp
77
${CCF_DIR}/src/crypto/hash.cpp
8+
${CCF_DIR}/src/crypto/public_key.cpp
89
${CCF_DIR}/src/crypto/sha256_hash.cpp
910
${CCF_DIR}/src/crypto/symmetric_key.cpp
1011
${CCF_DIR}/src/crypto/eddsa_key_pair.cpp

doc/build_apps/api.rst

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,4 +186,23 @@ COSE
186186
:project: CCF
187187

188188
.. doxygenfunction:: ccf::cose::edit::set_unprotected_header
189-
:project: CCF
189+
:project: CCF
190+
191+
Network Identity
192+
----------------
193+
194+
.. doxygentypedef:: ccf::RawCoseEndorsement
195+
:project: CCF
196+
197+
.. doxygentypedef:: ccf::CoseEndorsementsChain
198+
:project: CCF
199+
200+
.. doxygenenum:: ccf::FetchStatus
201+
:project: CCF
202+
203+
.. doxygentypedef:: ccf::TrustedKeys
204+
:project: CCF
205+
206+
.. doxygenclass:: ccf::NetworkIdentitySubsystemInterface
207+
:project: CCF
208+
:members:

doc/schemas/app_openapi.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,6 +1434,22 @@
14341434
}
14351435
}
14361436
},
1437+
"/app/log/public/trusted_keys": {
1438+
"get": {
1439+
"operationId": "GetAppLogPublicTrustedKeys",
1440+
"responses": {
1441+
"204": {
1442+
"description": "Default response description"
1443+
},
1444+
"default": {
1445+
"$ref": "#/components/responses/default"
1446+
}
1447+
},
1448+
"x-ccf-forwarding": {
1449+
"$ref": "#/components/x-ccf-forwarding/never"
1450+
}
1451+
}
1452+
},
14371453
"/app/log/public/verify_cose_receipt": {
14381454
"get": {
14391455
"operationId": "GetAppLogPublicVerifyCoseReceipt",

include/ccf/network_identity_interface.h

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "ccf/crypto/ec_public_key.h"
66
#include "ccf/node_subsystem_interface.h"
77

8+
#include <map>
89
#include <optional>
910
#include <string>
1011
#include <vector>
@@ -13,16 +14,25 @@ namespace ccf
1314
{
1415
struct NetworkIdentity;
1516

17+
/// A single raw COSE endorsement, stored as an opaque byte vector.
1618
using RawCoseEndorsement = std::vector<uint8_t>;
19+
/// An ordered chain of raw COSE endorsements.
1720
using CoseEndorsementsChain = std::vector<RawCoseEndorsement>;
1821

22+
/// Status of the network identity endorsement fetching process.
1923
enum class FetchStatus : uint8_t
2024
{
21-
Retry,
22-
Done,
23-
Failed
25+
Retry, ///< Fetching should be retried
26+
Done, ///< Fetching completed successfully
27+
Failed ///< Fetching failed
2428
};
2529

30+
/// Map from sequence number to EC public key, representing the trusted
31+
/// network identity keys over the history of the service.
32+
using TrustedKeys = std::map<ccf::SeqNo, ccf::crypto::ECPublicKeyPtr>;
33+
34+
/// Interface for accessing the network identity subsystem, which manages
35+
/// the service's cryptographic identity and its historical trusted keys.
2636
class NetworkIdentitySubsystemInterface : public ccf::AbstractNodeSubSystem
2737
{
2838
public:
@@ -33,14 +43,33 @@ namespace ccf
3343
return "NetworkIdentity";
3444
}
3545

46+
/// Returns a reference to the current network identity.
3647
virtual const std::unique_ptr<NetworkIdentity>& get() = 0;
3748

49+
/// Returns the current status of endorsement fetching.
3850
[[nodiscard]] virtual FetchStatus endorsements_fetching_status() const = 0;
3951

52+
/// Returns the COSE endorsements chain for the given sequence number,
53+
/// or std::nullopt if endorsement fetching has not completed or the
54+
/// chain is not available for the given sequence number.
4055
[[nodiscard]] virtual std::optional<CoseEndorsementsChain>
4156
get_cose_endorsements_chain(ccf::SeqNo seqno) const = 0;
4257

58+
/// Returns the trusted EC public key that was active at the given
59+
/// sequence number, or nullptr if the sequence number precedes the
60+
/// earliest known trusted key.
61+
///
62+
/// @throws std::logic_error if endorsement fetching has not completed
63+
/// (i.e. endorsements_fetching_status() != FetchStatus::Done), or if
64+
/// no trusted keys have been fetched.
4365
[[nodiscard]] virtual ccf::crypto::ECPublicKeyPtr get_trusted_identity_for(
4466
ccf::SeqNo seqno) const = 0;
67+
68+
/// Returns all trusted network identity keys as a map from sequence
69+
/// number to EC public key.
70+
///
71+
/// @throws std::logic_error if endorsement fetching has not completed
72+
/// (i.e. endorsements_fetching_status() != FetchStatus::Done).
73+
[[nodiscard]] virtual TrustedKeys get_trusted_keys() const = 0;
4574
};
4675
}

samples/apps/logging/logging.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "ccf/json_handler.h"
2222
#include "ccf/network_identity_interface.h"
2323
#include "ccf/version.h"
24+
#include "crypto/public_key.h"
2425

2526
#include <charconv>
2627
#define FMT_HEADER_ONLY
@@ -2109,6 +2110,40 @@ namespace loggingapp
21092110
.set_forwarding_required(ccf::endpoints::ForwardingRequired::Never)
21102111
.install();
21112112

2113+
auto get_trusted_keys = [&](
2114+
ccf::endpoints::ReadOnlyEndpointContext& ctx) {
2115+
auto network_identity_subsystem =
2116+
context.get_subsystem<ccf::NetworkIdentitySubsystemInterface>();
2117+
if (network_identity_subsystem == nullptr)
2118+
{
2119+
ctx.rpc_ctx->set_error(
2120+
HTTP_STATUS_INTERNAL_SERVER_ERROR,
2121+
ccf::errors::InternalError,
2122+
"Network identity subsystem not available");
2123+
return;
2124+
}
2125+
2126+
auto keys = network_identity_subsystem->get_trusted_keys();
2127+
nlohmann::json jwks = nlohmann::json::object();
2128+
auto keys_array = nlohmann::json::array();
2129+
for (const auto& [seqno, key_ptr] : keys)
2130+
{
2131+
const auto kid = ccf::crypto::kid_from_key(key_ptr->public_key_der());
2132+
keys_array.push_back(key_ptr->public_key_jwk(kid));
2133+
}
2134+
jwks["keys"] = keys_array;
2135+
2136+
ctx.rpc_ctx->set_response_json(jwks, HTTP_STATUS_OK);
2137+
};
2138+
make_read_only_endpoint(
2139+
"/log/public/trusted_keys",
2140+
HTTP_GET,
2141+
get_trusted_keys,
2142+
ccf::no_auth_required)
2143+
.set_auto_schema<void, void>()
2144+
.set_forwarding_required(ccf::endpoints::ForwardingRequired::Never)
2145+
.install();
2146+
21122147
auto get_cose_signature = [](
21132148
ccf::endpoints::ReadOnlyEndpointContext& ctx,
21142149
ccf::historical::StatePtr historical_state) {

src/crypto/public_key.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the Apache 2.0 License.
3+
4+
#include "crypto/public_key.h"
5+
6+
#include "ccf/crypto/sha256_hash.h"
7+
8+
namespace ccf::crypto
9+
{
10+
std::string kid_from_key(const std::vector<uint8_t>& public_key_der)
11+
{
12+
return Sha256Hash(public_key_der).hex_str();
13+
}
14+
}

src/crypto/public_key.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the Apache 2.0 License.
3+
#pragma once
4+
5+
#include <cstdint>
6+
#include <string>
7+
#include <vector>
8+
9+
namespace ccf::crypto
10+
{
11+
// Returns a hex-encoded SHA-256 hash of the DER-encoded public key,
12+
// suitable for use as a key identifier (kid).
13+
std::string kid_from_key(const std::vector<uint8_t>& public_key_der);
14+
}

src/node/history.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "crypto/openssl/cose_sign.h"
1111
#include "crypto/openssl/ec_key_pair.h"
1212
#include "crypto/openssl/hash.h"
13+
#include "crypto/public_key.h"
1314
#include "ds/internal_logger.h"
1415
#include "endian.h"
1516
#include "kv/kv_types.h"
@@ -356,8 +357,7 @@ namespace ccf
356357
primary_sig,
357358
endorsed_cert);
358359

359-
const auto& service_key_der = service_kp.public_key_der();
360-
auto kid = ccf::crypto::Sha256Hash(service_key_der).hex_str();
360+
auto kid = ccf::crypto::kid_from_key(service_kp.public_key_der());
361361
std::span<const uint8_t> kid_span{
362362
reinterpret_cast<const uint8_t*>(kid.data()), kid.size()};
363363

src/node/rpc/network_identity_subsystem.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,17 @@ namespace ccf
212212
return key_ptr;
213213
}
214214

215+
[[nodiscard]] TrustedKeys get_trusted_keys() const override
216+
{
217+
if (fetch_status.load() != FetchStatus::Done)
218+
{
219+
throw std::logic_error(
220+
"Trusted keys requested but endorsements/key fetching has not "
221+
"completed yet");
222+
}
223+
return trusted_keys;
224+
}
225+
215226
private:
216227
void retry_first_fetch()
217228
{

0 commit comments

Comments
 (0)