Skip to content

Commit

Permalink
feat(keybroker-server): the server learned to provide a random challenge
Browse files Browse the repository at this point in the history
as well as to optionnally provide a mock challenge, reusing the CCA
example token nonce. This can be useful during system bring-up for example.

Signed-off-by: Arnaud de Grandmaison <[email protected]>
  • Loading branch information
Arnaud-de-Grandmaison-ARM committed Sep 17, 2024
1 parent 2ad54f4 commit befccb3
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 8 deletions.
31 changes: 26 additions & 5 deletions rust-keybroker/keybroker-server/src/challenge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
//!
use crate::error::Result;
use keybroker_common::PublicWrappingKey;
use rand::{rngs::StdRng, Rng, SeedableRng};
use std::collections::HashMap;

/// Represents a single challenge, and provides the challenge value ("nonce") while also remembering the information
Expand All @@ -43,6 +44,8 @@ pub struct Challenge {
/// This structure provides a hash map of challenges, keyed on the integer challenge identifier.
pub struct Challenger {
challenge_table: HashMap<u32, Challenge>,
rng: StdRng,
pub verbose: bool,
}

// This is the challenge value from from https://git.trustedfirmware.org/TF-M/tf-m-tools/+/refs/heads/main/iat-verifier/tests/data/cca_example_token.cbor
Expand All @@ -59,6 +62,8 @@ impl Challenger {
pub fn new() -> Challenger {
Challenger {
challenge_table: HashMap::new(),
rng: StdRng::from_entropy(),
verbose: false,
}
}

Expand All @@ -70,27 +75,43 @@ impl Challenger {
&mut self,
key_id: &str,
wrapping_key: &PublicWrappingKey,
mock_challenge: bool,
) -> Challenge {
// All challenges are given random u32 identities
let mut challenge_id: u32 = rand::random();
let mut challenge_id: u32 = self.rng.gen();

// Simple lightweight collision avoidance - probably not needed given u32 distribution space,
// but it's easy to do. Also allows us to throw out zero if we get it.
while challenge_id == 0 || self.challenge_table.contains_key(&challenge_id) {
challenge_id = rand::random();
challenge_id = self.rng.gen();
}

let challenge = Challenge {
challenge_id,
key_id: key_id.to_owned(),
wrapping_key: wrapping_key.clone(),
// TODO: We should create a random nonce here. The use of this mock value allows the
// server to be tested with a hard-coded example attestation token during development.
challenge_value: CCA_EXAMPLE_TOKEN_NONCE.to_vec(),
challenge_value: if mock_challenge {
CCA_EXAMPLE_TOKEN_NONCE.to_vec()
} else {
let mut v: Vec<u8> = vec![0; 64];
self.rng.fill(&mut v[..]);
v
},
};

self.challenge_table.insert(challenge_id, challenge.clone());

if self.verbose {
println!("Created challenge:");
println!(" - challenge_id: {}", challenge_id);
println!(" - key_id: {}", challenge.key_id);
println!(
" - challenge value ({} bytes): {:02x?}",
challenge.challenge_value.len(),
challenge.challenge_value
);
}

challenge
}

Expand Down
12 changes: 9 additions & 3 deletions rust-keybroker/keybroker-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ async fn request_key(

// Get a new challenge from the challenger.
let mut challenger = data.challenger.lock().expect("Poisoned challenger lock.");
let challenge = challenger.create_challenge(&key_id, &key_request.pubkey);
let challenge =
challenger.create_challenge(&key_id, &key_request.pubkey, data.args.mock_challenge);

// TODO: The "accept" list is being hardcoded for Arm CCA here - it should come from the verifier.
let attestation_challenge = AttestationChallenge {
Expand Down Expand Up @@ -159,6 +160,10 @@ struct Args {
#[arg(long, default_value = "http://veraison.test.linaro.org:8080")]
verifier: String,

/// Use the static CCA example token nonce instead of a randomly generated one
#[arg(short, long, default_value_t = false)]
mock_challenge: bool,

/// Set the server verbosity
#[arg(short, long, default_value_t = false)]
verbose: bool,
Expand All @@ -176,7 +181,8 @@ async fn main() -> std::io::Result<()> {
let args = Args::parse();

let mut keystore = KeyStore::new();
let challenger = Challenger::new();
let mut challenger = Challenger::new();
challenger.verbose = args.verbose;

// TODO: Just storing one hard-coded item in the store. Would be better to read from an input file.
keystore.store_key(
Expand All @@ -186,7 +192,7 @@ async fn main() -> std::io::Result<()> {

let server_state = ServerState {
args: args.clone(),
base_url : match args.base_url {
base_url: match args.base_url {
Some(url) => format!("{}:{}", url, args.port),
None => format!("http://{}:{}", args.addr, args.port),
},
Expand Down

0 comments on commit befccb3

Please sign in to comment.