Skip to content

Commit

Permalink
Add Oak Session High-Level SDK stub
Browse files Browse the repository at this point in the history
Bug: 341242090

Change-Id: I65fd086e8a9c2631e54bf8d7b34b5e703b58c0f1
  • Loading branch information
ipetr0v committed May 23, 2024
1 parent dbd014f commit ecaad4c
Show file tree
Hide file tree
Showing 6 changed files with 266 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions oak_session/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ edition = "2021"
license = "Apache-2.0"

[dependencies]
anyhow = { version = "*", default-features = false }
oak_proto_rust = { workspace = true }
32 changes: 32 additions & 0 deletions oak_session/src/attestation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// 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.
//

use oak_proto_rust::oak::{
attestation::v1::{AttestationResults, Endorsements, Evidence},
session::v1::EndorsedEvidence,
};

pub trait Attester {
fn get_endorsed_evidence(&self) -> anyhow::Result<EndorsedEvidence>;
}

pub trait AttestationVerifier {
fn verify(
&self,
evidence: &Evidence,
endorsements: &Endorsements,
) -> anyhow::Result<AttestationResults>;
}
58 changes: 58 additions & 0 deletions oak_session/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//
// 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.
//

use crate::attestation::{AttestationVerifier, Attester};

#[derive(Default)]
pub struct SessionConfig<'a> {
self_attester: Option<&'a dyn Attester>,
peer_verifier: Option<&'a dyn AttestationVerifier>,
}

impl<'a> SessionConfig<'a> {
pub fn builder() -> SessionConfigBuilder<'a> {
SessionConfigBuilder::default()
}
}

#[derive(Default)]
pub struct SessionConfigBuilder<'a> {
config: SessionConfig<'a>,
}

impl<'a> SessionConfigBuilder<'a> {
pub fn set_self_attester(mut self, self_attester: &'a dyn Attester) -> Self {
if self.config.self_attester.is_none() {
self.config.self_attester = Some(self_attester);
} else {
panic!("self attester has already been set");
}
self
}

pub fn set_peer_verifier(mut self, peer_verifier: &'a dyn AttestationVerifier) -> Self {
if self.config.peer_verifier.is_none() {
self.config.peer_verifier = Some(peer_verifier);
} else {
panic!("peer verifier has already been set");
}
self
}

pub fn build(self) -> SessionConfig<'a> {
self.config
}
}
36 changes: 36 additions & 0 deletions oak_session/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,39 @@ extern crate alloc;

#[cfg(test)]
extern crate std;

pub mod attestation;
pub mod config;
mod session;

pub use session::{ClientSession, ServerSession, Session};

/// Trait that represents a state-machine for protocol message generation.
/// Incoming and outgoing messages are represented as generic arguments `I` and
/// `O`.
///
/// This trait can be used to implement bidirectional streams, meaning that
/// there doesn't have to be a one-to-one correspondence between incoming and
/// outgoing messages.
///
/// If one of the methods returns an error, it means that there was a protocol
/// error and the session needs to be restarted (because the state-machine is in
/// an incorrect state).
pub trait ProtocolEngine<I, O> {
/// Puts a message received from the peer into the state-machine changing
/// its state.
///
/// Method returns `Result<Option<()>>` with the corresponding outcomes:
/// - `Ok(None)`: No incoming messages were expected
/// - `Ok(Some(()))`: An incoming message was accepted by the state-machine
/// - `Err`: Protocol error
fn put_incoming_message(&mut self, incoming_message: &I) -> anyhow::Result<Option<()>>;

/// Creates a next message that needs to be sent to the peer.
///
/// Method returns `Result<Option<()>>` with the corresponding outcomes:
/// - `Ok(None)`: No outgoing messages
/// - `Ok(Some(O))`: An outgoing message that needs to be sent to the peer
/// - `Err`: Protocol error
fn get_outgoing_message(&mut self) -> anyhow::Result<Option<O>>;
}
134 changes: 134 additions & 0 deletions oak_session/src/session.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
//
// 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.
//

//! This module provides an SDK for creating secure attested sessions between
//! two parties.
use alloc::vec::Vec;

use oak_proto_rust::oak::session::v1::{SessionRequest, SessionResponse};

use crate::{config::SessionConfig, ProtocolEngine};

/// Trait that represents an end-to-end encrypted bidirectional streaming
/// session between two peers.
///
/// If one of the methods returns an error, it means that there was a protocol
/// error and the session needs to be restarted (because the state-machine is in
/// an incorrect state).
pub trait Session {
/// Checks whether session is ready to send and receive encrypted messages.
/// Session becomes ready once remote attestation and crypto handshake have
/// been successfully finished.
fn is_open(&self) -> bool;

/// Encrypts `plaintext` and send it to the peer.
///
/// This function can be called multiple times in a row, which will result
/// in multiple outgoing protocol messages being created.
fn write(&mut self, plaintext: &[u8]) -> anyhow::Result<()>;

/// Reads an encrypted message from the peer and decrypt it.
///
/// This function can be called multiple times in a row, if the peer sent
/// multiple protocol messages that need to be decrypted.
///
/// Method returns `Result<Option<()>>` with the corresponding outcomes:
/// - `Ok(None)`: Nothing to read
/// - `Ok(Some(Vec<u8>))`: Successfully read plaintext bytes
/// - `Err`: Protocol error
fn read(&mut self) -> anyhow::Result<Option<Vec<u8>>>;
}

// Client-side secure attested session entrypoint.
#[allow(dead_code)]
pub struct ClientSession<'a> {
config: &'a SessionConfig<'a>,
}

#[allow(dead_code)]
impl<'a> ClientSession<'a> {
pub fn new(config: &'a SessionConfig<'a>) -> Self {
Self { config }
}
}

impl<'a> Session for ClientSession<'a> {
fn is_open(&self) -> bool {
core::unimplemented!();
}

fn write(&mut self, _plaintext: &[u8]) -> anyhow::Result<()> {
core::unimplemented!();
}

fn read(&mut self) -> anyhow::Result<Option<Vec<u8>>> {
core::unimplemented!();
}
}

impl<'a> ProtocolEngine<SessionResponse, SessionRequest> for ClientSession<'a> {
fn get_outgoing_message(&mut self) -> anyhow::Result<Option<SessionRequest>> {
core::unimplemented!();
}

fn put_incoming_message(
&mut self,
_incoming_message: &SessionResponse,
) -> anyhow::Result<Option<()>> {
core::unimplemented!();
}
}

// Server-side secure attested session entrypoint.
#[allow(dead_code)]
pub struct ServerSession<'a> {
config: &'a SessionConfig<'a>,
}

#[allow(dead_code)]
impl<'a> ServerSession<'a> {
pub fn new(config: &'a SessionConfig<'a>) -> Self {
Self { config }
}
}

impl<'a> Session for ServerSession<'a> {
fn is_open(&self) -> bool {
core::unimplemented!();
}

fn write(&mut self, _plaintext: &[u8]) -> anyhow::Result<()> {
core::unimplemented!();
}

fn read(&mut self) -> anyhow::Result<Option<Vec<u8>>> {
core::unimplemented!();
}
}

impl<'a> ProtocolEngine<SessionRequest, SessionResponse> for ClientSession<'a> {
fn get_outgoing_message(&mut self) -> anyhow::Result<Option<SessionResponse>> {
core::unimplemented!();
}

fn put_incoming_message(
&mut self,
_incoming_message: &SessionRequest,
) -> anyhow::Result<Option<()>> {
core::unimplemented!();
}
}

0 comments on commit ecaad4c

Please sign in to comment.