Skip to content

Commit

Permalink
Oak Standalone C++: Create standalone endorsed evidence
Browse files Browse the repository at this point in the history
We have a handy standalone EndorsedEvidence creator now in Rust. It does
some things that we don't have C++ implementations for yet, so this
change creates some very basic FFI wrappers around the standalone
orchestrator code to provide an EndorsedEvidence proto back to the C++
caller.

Bug: b/374848083

Change-Id: I15a75176ccfe992fe61820d26d6208a27701ebe6
  • Loading branch information
jblebrun committed Oct 23, 2024
1 parent 5a2af3d commit c4f5210
Show file tree
Hide file tree
Showing 10 changed files with 269 additions and 24 deletions.
45 changes: 45 additions & 0 deletions cc/containers/sdk/standalone/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#
# Copyright 2024 The Project Oak Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

package(
default_visibility = ["//:default_visibility"],
licenses = ["notice"],
)

cc_library(
name = "oak_standalone",
srcs = ["oak_standalone.cc"],
hdrs = ["oak_standalone.h"],
deps = [
"//oak_containers_sdk:ffi",
"//proto/session:messages_cc_proto",
"@com_google_absl//absl/log",
"@com_google_absl//absl/status:statusor",
],
)

cc_test(
name = "oak_standalone_test",
srcs = ["oak_standalone_test.cc"],
deps = [
":oak_standalone",
"//oak_containers_sdk:ffi",
"//proto/session:messages_cc_proto",
"@com_google_absl//absl/log",
"@com_google_absl//absl/status:statusor",
"@com_google_googletest//:gtest_main",
],
)
55 changes: 55 additions & 0 deletions cc/containers/sdk/standalone/oak_standalone.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2024 The Project Oak Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "cc/containers/sdk/standalone/oak_standalone.h"

#include "absl/log/log.h"
#include "absl/status/statusor.h"
#include "proto/session/messages.pb.h"

extern "C" {
extern bool standalone_endorsed_evidence(void*,
bool (*f)(void*, char*, uint32_t));
}

namespace oak::containers::sdk::standalone {

using oak::session::v1::EndorsedEvidence;

namespace {

/// This is the callback that we pass to the Rust code.
///
/// During the scope of this callback invocation, we can process the data
/// however we need, but anything we want to hold onto needs to be copied.
///
/// The context object is a pointer to the EndorsedEvidence to populate.
bool DeserializeEndorsedEvidence(void* evidence, char* data, uint32_t size) {
LOG(INFO) << "trying to interpret proto data of size " << size;
return (static_cast<EndorsedEvidence*>(evidence))->ParseFromArray(data, size);
}

} // namespace

absl::StatusOr<EndorsedEvidence> GetEndorsedEvidence() {
EndorsedEvidence evidence;
if (!standalone_endorsed_evidence(&evidence, DeserializeEndorsedEvidence)) {
return absl::InternalError("Failed to get endorsed evidence");
}
return evidence;
}

} // namespace oak::containers::sdk::standalone
31 changes: 31 additions & 0 deletions cc/containers/sdk/standalone/oak_standalone.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2024 The Project Oak Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "absl/status/statusor.h"
#include "proto/session/messages.pb.h"

#ifndef CC_CONTAINERS_SDK_STANDALONE_OAK_STANDALONE_H_
#define CC_CONTAINERS_SDK_STANDALONE_OAK_STANDALONE_H_

namespace oak::containers::sdk::standalone {

/// Get an instance of EndorsedEvidence that's valid to use in an Oak Standalone
/// application.
absl::StatusOr<session::v1::EndorsedEvidence> GetEndorsedEvidence();

} // namespace oak::containers::sdk::standalone

#endif // CC_CONTAINERS_SDK_STANDALONE_OAK_STANDALONE_H_
36 changes: 36 additions & 0 deletions cc/containers/sdk/standalone/oak_standalone_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2024 The Project Oak Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "cc/containers/sdk/standalone/oak_standalone.h"

#include <cstdint>

#include "absl/log/log.h"
#include "gtest/gtest.h"

namespace oak::containers::sdk::standalone {

using oak::session::v1::EndorsedEvidence;

namespace {
TEST(OakStandaloneTest, GetEndorsedEvidence) {
absl::StatusOr<EndorsedEvidence> endorsed_evidence = GetEndorsedEvidence();
ASSERT_TRUE(endorsed_evidence.ok());
LOG(INFO) << endorsed_evidence;
}
} // namespace

} // namespace oak::containers::sdk::standalone
6 changes: 3 additions & 3 deletions oak_attestation_integration_tests/src/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// limitations under the License.
//

use oak_containers_sdk::{standalone::StandaloneOrchestrator, OrchestratorInterface};
use oak_containers_sdk::standalone::StandaloneOrchestrator;
use oak_proto_rust::oak::{
attestation::v1::{
binary_reference_value, kernel_binary_reference_value, reference_values,
Expand Down Expand Up @@ -135,15 +135,15 @@ pub async fn oak_containers_standalone_endorsed_evidence_with_matching_reference
&application_config,
);
let endorsed_evidence = {
let mut orchestrator = StandaloneOrchestrator::builder()
let orchestrator = StandaloneOrchestrator::builder()
.stage0_measurements(stage0_measurements)
.stage1_system_image(stage1_system_image)
.application_image(application_image)
.application_config(application_config)
.build()
.expect("failed to create StandaloneOrchestrator");

orchestrator.get_endorsed_evidence().await.expect("failed to get endorsed evidence")
orchestrator.get_endorsed_evidence()
};

(endorsed_evidence, reference_values)
Expand Down
6 changes: 2 additions & 4 deletions oak_attestation_integration_tests/tests/verifier_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

use oak_attestation_integration_tests::{create, Snapshot, SnapshotPath};
use oak_attestation_verification::verifier::{to_attestation_results, verify, verify_dice_chain};
use oak_containers_sdk::OrchestratorInterface;
use oak_proto_rust::oak::attestation::{
self,
v1::{
Expand Down Expand Up @@ -217,9 +216,8 @@ fn oak_containers_skip_all_reference_values() -> ReferenceValues {
#[tokio::test]
async fn verify_mock_oak_containers_evidence() {
// Create a mock orchestrator and get endorsed evidence
let mut orchestrator = oak_containers_sdk::standalone::StandaloneOrchestrator::default();
let endorsed_evidence =
orchestrator.get_endorsed_evidence().await.expect("Failed to get endorsed evidence");
let orchestrator = oak_containers_sdk::standalone::StandaloneOrchestrator::default();
let endorsed_evidence = orchestrator.get_endorsed_evidence();

let evidence = endorsed_evidence.evidence.as_ref().expect("No evidence found");
let endorsements = endorsed_evidence.endorsements.as_ref().expect("No endorsements found");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ async fn start_server() -> Result<(SocketAddr, tokio::task::JoinHandle<Result<()
let mut orchestrator = StandaloneOrchestrator::default();
let encryption_key_handle = orchestrator.get_instance_encryption_key_handle();

let endorsed_evidence = orchestrator.get_endorsed_evidence().await?;
let endorsed_evidence = orchestrator.get_endorsed_evidence();
let application_config = orchestrator.get_application_config().await?;

Ok((
Expand Down
14 changes: 13 additions & 1 deletion oak_containers_sdk/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# limitations under the License.
#

load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test")
load("@rules_rust//rust:defs.bzl", "rust_library", "rust_static_library", "rust_test")

package(
default_visibility = ["//:internal"],
Expand Down Expand Up @@ -62,3 +62,15 @@ rust_test(
name = "oak_containers_sdk_test",
crate = ":oak_containers_sdk",
)

rust_static_library(
name = "ffi",
srcs = [
"src/ffi/standalone_c.rs",
],
deps = [
":oak_containers_sdk",
"//oak_proto_rust",
"@oak_crates_index//:prost",
],
)
64 changes: 64 additions & 0 deletions oak_containers_sdk/src/ffi/standalone_c.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//
// Copyright 2024 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! A few bindings to SDK-provided functionality for C++ callers.
//!
//! This is not a comprehensive set of SDK functionality; it's just to bridge
//! any gaps we have between our current C++ and Rust featureset.
use std::os::raw::c_void;

use oak_containers_sdk::standalone::StandaloneOrchestrator;
use prost::Message;

/// C bindings for generating standalone endorsed evidence.
/// Currently only supports the default configuration.
///
/// The provided callback will be called with the serialized EndorsedEvidence
/// proto generated by rust. Within the scope of the callback, you should
/// process the data however you'd like; but do not hold onto it, it will become
/// invalid when the callback scope is exited.
///
/// The callback also receive a caller-provided context object of the callers
/// choosing; this can contain the resources needed to properly handle the data.
///
/// # Safety
///
/// The semantics of `callback_context` are defined by the provided callback.
/// Ensure that the callback imlementation does not hold onto the memory pointed
/// to by `data` longer than the scope of the callback invocation.
#[no_mangle]
pub unsafe extern "C" fn standalone_endorsed_evidence(
callback_context: *mut c_void,
callback: unsafe extern "C" fn(
callback_context: *mut c_void,
data: *const u8,
data_length: usize,
),
) -> bool {
let orchestrator = StandaloneOrchestrator::default();
let endorsed_evidence = orchestrator.get_endorsed_evidence();
let serialized_endorsed_evidence = Message::encode_to_vec(&endorsed_evidence);

unsafe {
callback(
callback_context,
serialized_endorsed_evidence.as_ptr(),
serialized_endorsed_evidence.len(),
);
}

true
}
34 changes: 19 additions & 15 deletions oak_containers_sdk/src/standalone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,21 +173,9 @@ impl StandaloneOrchestrator {
pub fn get_instance_signer(&self) -> StandaloneInstanceSigner {
StandaloneInstanceSigner { signing_key: self.instance_private_keys.signing_key.clone() }
}
}

#[async_trait]
impl OrchestratorInterface for StandaloneOrchestrator {
async fn get_application_config(&mut self) -> Result<Vec<u8>> {
Ok(self.application_config.clone())
}

async fn notify_app_ready(&mut self) -> Result<()> {
// In standalone mode, we don't need to notify anyone
Ok(())
}

async fn get_endorsed_evidence(&mut self) -> Result<EndorsedEvidence> {
Ok(EndorsedEvidence {
pub fn get_endorsed_evidence(&self) -> EndorsedEvidence {
EndorsedEvidence {
evidence: Some(self.evidence.clone()),
endorsements: Some(Endorsements {
r#type: Some(endorsements::Type::OakContainers(
Expand All @@ -201,7 +189,23 @@ impl OrchestratorInterface for StandaloneOrchestrator {
// TODO: b/375137648 - Populate `event_endorsements` proto field.
event_endorsements: None,
}),
})
}
}
}

#[async_trait]
impl OrchestratorInterface for StandaloneOrchestrator {
async fn get_application_config(&mut self) -> Result<Vec<u8>> {
Ok(self.application_config.clone())
}

async fn notify_app_ready(&mut self) -> Result<()> {
// In standalone mode, we don't need to notify anyone
Ok(())
}

async fn get_endorsed_evidence(&mut self) -> Result<EndorsedEvidence> {
Ok(StandaloneOrchestrator::get_endorsed_evidence(self))
}
}

Expand Down

0 comments on commit c4f5210

Please sign in to comment.