Skip to content

Commit

Permalink
Flexible key manager policy signers
Browse files Browse the repository at this point in the history
  • Loading branch information
abukosek committed Jan 31, 2020
1 parent b3ee039 commit beca1ed
Show file tree
Hide file tree
Showing 18 changed files with 459 additions and 321 deletions.
5 changes: 5 additions & 0 deletions .changelog/2444.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Flexible key manager policy signers

The key manager runtime has been split into multiple crates to make its code
reusable. It is now possible for others to write their own key managers that
use a different set of trusted policy signers.
32 changes: 30 additions & 2 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ members = [
"runtime-loader",
"client",
"keymanager-client",
"keymanager-api-common",
"keymanager-lib",
"keymanager-runtime",
"tools",

Expand Down
16 changes: 16 additions & 0 deletions keymanager-api-common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "oasis-core-keymanager-api-common"
version = "0.3.0-alpha"
authors = ["Oasis Labs Inc. <[email protected]>"]

[dependencies]
base64 = "0.10.1"
oasis-core-runtime = { path = "../runtime" }
serde = "1.0.71"
serde_derive = "1.0"
serde_bytes = "~0.10"
rustc-hex = "2.0.1"
failure = "0.1.5"
lazy_static = "1.3.0"
x25519-dalek = "0.5.1"
rand = "0.6.5"
247 changes: 247 additions & 0 deletions keymanager-api-common/src/api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
use std::collections::{HashMap, HashSet};

use base64;
use failure::Fail;
use rand::{rngs::OsRng, Rng};
use serde_derive::{Deserialize, Serialize};
use x25519_dalek;

use oasis_core_runtime::{
common::{
crypto::signature::{PublicKey as OasisPublicKey, Signature, SignatureBundle},
runtime::RuntimeId,
sgx::avr::EnclaveIdentity,
},
impl_bytes,
};

impl_bytes!(ContractId, 32, "A 256-bit contract identifier.");
impl_bytes!(PrivateKey, 32, "A private key.");
impl_bytes!(PublicKey, 32, "A public key.");
impl_bytes!(StateKey, 32, "A state key.");
impl_bytes!(MasterSecret, 32, "A 256 bit master secret.");

/// Key manager initialization request.
#[derive(Clone, Serialize, Deserialize)]
pub struct InitRequest {
/// Checksum for validating replication.
#[serde(with = "serde_bytes")]
pub checksum: Vec<u8>,
/// Policy for queries/replication.
#[serde(with = "serde_bytes")]
pub policy: Vec<u8>,
/// True iff the enclave may generate a new master secret.
pub may_generate: bool,
}

/// Key manager initialization response.
#[derive(Clone, Serialize, Deserialize)]
pub struct InitResponse {
/// True iff the key manager thinks it's running in a secure mode.
pub is_secure: bool,
/// Checksum for validating replication.
#[serde(with = "serde_bytes")]
pub checksum: Vec<u8>,
/// Checksum for identifying policy.
#[serde(with = "serde_bytes")]
pub policy_checksum: Vec<u8>,
}

/// Context used for the init response signature.
pub const INIT_RESPONSE_CONTEXT: &'static [u8] = b"oasis-core/keymanager: init response";

/// Signed InitResponse.
#[derive(Clone, Serialize, Deserialize)]
pub struct SignedInitResponse {
/// InitResponse.
pub init_response: InitResponse,
/// Sign(init_response).
pub signature: Signature,
}

/// Key manager replication request.
#[derive(Clone, Serialize, Deserialize)]
pub struct ReplicateRequest {
// Empty.
}

/// Key manager replication response.
#[derive(Clone, Serialize, Deserialize)]
pub struct ReplicateResponse {
pub master_secret: MasterSecret,
}

/// Request runtime/contract id tuple.
#[derive(Clone, Serialize, Deserialize)]
pub struct RequestIds {
/// Runtime ID.
pub runtime_id: RuntimeId,
/// Contract ID.
pub contract_id: ContractId,
}

impl RequestIds {
pub fn new(runtime_id: RuntimeId, contract_id: ContractId) -> Self {
Self {
runtime_id,
contract_id,
}
}

pub fn to_cache_key(&self) -> Vec<u8> {
let mut k = self.runtime_id.as_ref().to_vec();
k.extend_from_slice(self.contract_id.as_ref());
k
}
}

/// Keys for a contract.
#[derive(Clone, Serialize, Deserialize)]
pub struct ContractKey {
/// Input key pair (pk, sk)
pub input_keypair: InputKeyPair,
/// State encryption key
pub state_key: StateKey,
/// Checksum of the key manager state.
#[serde(with = "serde_bytes")]
pub checksum: Vec<u8>,
}

impl ContractKey {
/// Generate a new random key (for testing).
pub fn generate_mock() -> Self {
let mut rng = OsRng::new().unwrap();
let sk = x25519_dalek::StaticSecret::new(&mut rng);
let pk = x25519_dalek::PublicKey::from(&sk);

let mut state_key = StateKey::default();
rng.fill(&mut state_key.0);

ContractKey::new(
PublicKey(*pk.as_bytes()),
PrivateKey(sk.to_bytes()),
state_key,
vec![],
)
}

/// Create a set of `ContractKey`.
pub fn new(pk: PublicKey, sk: PrivateKey, k: StateKey, sum: Vec<u8>) -> Self {
Self {
input_keypair: InputKeyPair::new(pk, sk),
state_key: k,
checksum: sum,
}
}

/// Create a set of `ContractKey` with only the public key.
pub fn from_public_key(k: PublicKey, sum: Vec<u8>) -> Self {
Self {
input_keypair: InputKeyPair::new(k, PrivateKey::default()),
state_key: StateKey::default(),
checksum: sum,
}
}
}

#[derive(Clone, Serialize, Deserialize)]
pub struct InputKeyPair {
/// Pk
pk: PublicKey,
/// sk
sk: PrivateKey,
}

impl InputKeyPair {
pub fn new(pk: PublicKey, sk: PrivateKey) -> Self {
Self { pk, sk }
}

pub fn get_pk(&self) -> PublicKey {
self.pk
}

pub fn get_sk(&self) -> PrivateKey {
self.sk
}
}

/// Context used for the public key signature.
pub const PUBLIC_KEY_CONTEXT: [u8; 8] = *b"EkKmPubK";

/// Signed public key.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SignedPublicKey {
/// Public key.
pub key: PublicKey,
/// Checksum of the key manager state.
#[serde(with = "serde_bytes")]
pub checksum: Vec<u8>,
/// Sign(sk, (key || checksum)) from the key manager.
pub signature: Signature,
}

/// Key manager error.
#[derive(Debug, Fail)]
pub enum KeyManagerError {
#[fail(display = "client session is not authenticated")]
NotAuthenticated,
#[fail(display = "client session authentication is invalid")]
InvalidAuthentication,
#[fail(display = "key manager is not initialized")]
NotInitialized,
#[fail(display = "key manager state corrupted")]
StateCorrupted,
#[fail(display = "key manager replication required")]
ReplicationRequired,
#[fail(display = "policy rollback")]
PolicyRollback,
#[fail(display = "policy alteration, without serial increment")]
PolicyChanged,
#[fail(display = "policy is malformed or invalid")]
PolicyInvalid,
#[fail(display = "policy failed signature verification")]
PolicyInvalidSignature,
#[fail(display = "policy has insufficient signatures")]
PolicyInsufficientSignatures,
}

/// Key manager access control policy.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PolicySGX {
pub serial: u32,
pub id: RuntimeId,
pub enclaves: HashMap<EnclaveIdentity, EnclavePolicySGX>,
}

/// Per enclave key manager access control policy.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct EnclavePolicySGX {
pub may_query: HashMap<RuntimeId, Vec<EnclaveIdentity>>,
pub may_replicate: Vec<EnclaveIdentity>,
}

/// Signed key manager access control policy.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SignedPolicySGX {
pub policy: PolicySGX,
pub signatures: Vec<SignatureBundle>,
}

/// Set of trusted key manager policy signing keys.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TrustedPolicySigners {
/// Set of trusted signers.
pub signers: HashSet<OasisPublicKey>,
/// Threshold for determining if enough valid signatures are present.
pub threshold: usize,
}

impl TrustedPolicySigners {
pub fn new() -> Self {
Self {
signers: HashSet::new(),
threshold: 9001,
}
}
}
Loading

0 comments on commit beca1ed

Please sign in to comment.