diff --git a/src/api/src/attestation/mod.rs b/src/api/src/attestation/mod.rs index 03c8ce6d57..93740e195f 100644 --- a/src/api/src/attestation/mod.rs +++ b/src/api/src/attestation/mod.rs @@ -14,6 +14,10 @@ use kbs_types::Tee; use std::sync::Arc; use tokio::sync::Mutex; +use base64::engine::general_purpose::STANDARD; +use base64::Engine; +use rand::{thread_rng, Rng}; + #[cfg(feature = "coco-as")] #[allow(missing_docs)] pub mod coco; @@ -31,6 +35,17 @@ pub trait Attest: Send + Sync { Err(anyhow!("Set Policy API is unimplemented")) } + /// Get nonce from AS + async fn nonce(&mut self) -> Result { + let mut nonce: Vec = vec![0; 32]; + + thread_rng() + .try_fill(&mut nonce[..]) + .map_err(anyhow::Error::from)?; + + Ok(STANDARD.encode(&nonce)) + } + /// Verify Attestation Evidence /// Return Attestation Results Token async fn verify(&mut self, tee: Tee, nonce: &str, attestation: &str) -> Result; diff --git a/src/api/src/http/attest.rs b/src/api/src/http/attest.rs index f45ddfbd8c..a1405f9f32 100644 --- a/src/api/src/http/attest.rs +++ b/src/api/src/http/attest.rs @@ -17,11 +17,19 @@ pub(crate) async fn auth( request: web::Json, map: web::Data>, timeout: web::Data, - _attestation_service: web::Data, + attestation_service: web::Data, ) -> Result { info!("request: {:?}", &request); - let session = Session::from_request(&request, *timeout.into_inner()) + let nonce = attestation_service + .0 + .lock() + .await + .nonce() + .await + .map_err(|e| Error::FailedAuthentication(e.to_string()))?; + + let session = Session::from_request(&request, *timeout.into_inner(), nonce) .map_err(|e| Error::FailedAuthentication(format!("Session: {e}")))?; let response = HttpResponse::Ok().cookie(session.cookie()).json(Challenge { nonce: session.nonce().to_string(), diff --git a/src/api/src/http/resource.rs b/src/api/src/http/resource.rs index 26ac8474ca..eb102108fc 100644 --- a/src/api/src/http/resource.rs +++ b/src/api/src/http/resource.rs @@ -147,6 +147,8 @@ async fn get_attest_claims_from_session( "No attestation claims in the session".into(), ))?; + // TODO: also check claims expiration before Ok(): KBS user can configure + // the session length but AS may want short token expiration. Ok(claims) } diff --git a/src/api/src/session.rs b/src/api/src/session.rs index 4d33be6a65..95ead5b4c9 100644 --- a/src/api/src/session.rs +++ b/src/api/src/session.rs @@ -7,10 +7,7 @@ use actix_web::cookie::{ Cookie, Expiration, }; use anyhow::{anyhow, Result}; -use base64::engine::general_purpose::STANDARD; -use base64::Engine; use kbs_types::{Request, Tee, TeePubKey}; -use rand::{thread_rng, Rng}; use semver::Version; use std::collections::HashMap; use std::sync::Arc; @@ -19,16 +16,6 @@ use uuid::Uuid; pub(crate) static KBS_SESSION_ID: &str = "kbs-session-id"; -fn nonce() -> Result { - let mut nonce: Vec = vec![0; 32]; - - thread_rng() - .try_fill(&mut nonce[..]) - .map_err(anyhow::Error::from)?; - - Ok(STANDARD.encode(&nonce)) -} - #[allow(dead_code)] pub(crate) struct Session<'a> { cookie: Cookie<'a>, @@ -42,7 +29,7 @@ pub(crate) struct Session<'a> { #[allow(dead_code)] impl<'a> Session<'a> { - pub fn from_request(req: &Request, timeout: i64) -> Result { + pub fn from_request(req: &Request, timeout: i64, nonce: String) -> Result { let version = Version::parse(&req.version).map_err(anyhow::Error::from)?; if !crate::VERSION_REQ.matches(&version) { return Err(anyhow!("Invalid Request version {}", req.version)); @@ -54,13 +41,15 @@ impl<'a> Session<'a> { Some(req.extra_params.clone()) }; + // TODO: make session initially only valid for the nonce lifetime? let cookie = Cookie::build(KBS_SESSION_ID, id) .expires(OffsetDateTime::now_utc() + Duration::minutes(timeout)) .finish(); + // TODO: do not store nonce in the session at all? Ok(Session { cookie, - nonce: nonce()?, + nonce: nonce.clone(), tee: req.tee.clone(), tee_extra_params, tee_pub_key: None,