Skip to content

Commit

Permalink
Make session transcript more flexible (#74)
Browse files Browse the repository at this point in the history
* Make SessionTranscript more flexible.

Makes SessionTranscript more flexible so that other transport
protocols can reuse the core components of this library.

Also remove the old OpenID4VP code.

* Use generics

* Remove oid4vp-specific definitions
  • Loading branch information
cobward authored Nov 20, 2023
1 parent 8fe7226 commit 3183341
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 306 deletions.
27 changes: 15 additions & 12 deletions src/definitions/device_signed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::definitions::{
};
use cose_rs::sign1::CoseSign1;
use serde::{Deserialize, Serialize};
use serde_cbor::Value as CborValue;
use serde_cbor::{Error as CborError, Value as CborValue};
use std::collections::BTreeMap;

#[derive(Clone, Debug, Deserialize, Serialize)]
Expand All @@ -28,22 +28,19 @@ pub enum DeviceAuth {
Mac { device_mac: CborValue },
}

pub type DeviceAuthenticationBytes = Tag24<DeviceAuthentication>;
pub type DeviceAuthenticationBytes<S> = Tag24<DeviceAuthentication<S>>;

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DeviceAuthentication(
pub struct DeviceAuthentication<S: SessionTranscript>(
&'static str,
pub SessionTranscript,
pub String,
pub DeviceNamespacesBytes,
// See https://github.com/serde-rs/serde/issues/1296.
#[serde(bound = "")] S,
String,
DeviceNamespacesBytes,
);

impl DeviceAuthentication {
pub fn new(
transcript: SessionTranscript,
doc_type: String,
namespaces_bytes: DeviceNamespacesBytes,
) -> Self {
impl<S: SessionTranscript> DeviceAuthentication<S> {
pub fn new(transcript: S, doc_type: String, namespaces_bytes: DeviceNamespacesBytes) -> Self {
Self(
"DeviceAuthentication",
transcript,
Expand All @@ -52,3 +49,9 @@ impl DeviceAuthentication {
)
}
}

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Unable to encode value as CBOR: {0}")]
UnableToEncode(CborError),
}
3 changes: 1 addition & 2 deletions src/definitions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ pub mod helpers;
pub mod issuer_signed;
pub mod mso;
pub mod namespaces;
pub mod oid4vp;
pub mod session;
pub mod traits;
pub mod validity_info;
Expand All @@ -22,5 +21,5 @@ pub use device_response::{DeviceResponse, Document};
pub use device_signed::{DeviceAuth, DeviceSigned};
pub use issuer_signed::{IssuerSigned, IssuerSignedItem};
pub use mso::{DigestAlgorithm, DigestId, DigestIds, Mso};
pub use session::{SessionData, SessionEstablishment, SessionTranscript};
pub use session::{SessionData, SessionEstablishment, SessionTranscript180135};
pub use validity_info::ValidityInfo;
42 changes: 0 additions & 42 deletions src/definitions/oid4vp.rs

This file was deleted.

14 changes: 9 additions & 5 deletions src/definitions/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use sha2::{Digest, Sha256};
pub type EReaderKey = CoseKey;
pub type EDeviceKey = CoseKey;
pub type DeviceEngagementBytes = Tag24<DeviceEngagement>;
pub type SessionTranscriptBytes = Tag24<SessionTranscript>;
pub type SessionTranscriptBytes = Tag24<SessionTranscript180135>;
pub type NfcHandover = (ByteStr, Option<ByteStr>);

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down Expand Up @@ -78,13 +78,17 @@ impl TryFrom<u64> for Status {
}
}

pub trait SessionTranscript: Serialize + for<'a> Deserialize<'a> {}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SessionTranscript(
pub struct SessionTranscript180135(
pub DeviceEngagementBytes,
pub Tag24<EReaderKey>,
pub Handover,
);

impl SessionTranscript for SessionTranscript180135 {}

#[derive(Debug, Clone, thiserror::Error)]
pub enum Error {
#[error("Curve not supported for DH exchange")]
Expand Down Expand Up @@ -164,7 +168,7 @@ pub fn get_shared_secret(

pub fn derive_session_key(
shared_secret: &SharedSecret<NistP256>,
session_transcript: &Tag24<SessionTranscript>,
session_transcript: &SessionTranscriptBytes,
reader: bool,
) -> Result<GenericArray<u8, U32>> {
let salt = Sha256::digest(serde_cbor::to_vec(session_transcript)?);
Expand Down Expand Up @@ -400,7 +404,7 @@ mod test {
};

let device_engagement_bytes = Tag24::new(device_engagement).unwrap();
let session_transcript = Tag24::new(SessionTranscript(
let session_transcript = Tag24::new(SessionTranscript180135(
device_engagement_bytes,
reader_key_bytes,
Handover::QR,
Expand Down Expand Up @@ -456,7 +460,7 @@ mod test {
assert_eq!(shared_secret_hex, SHARED_SECRET);

let session_transcript_bytes = hex::decode(SESSION_TRANSCRIPT).unwrap();
let session_transcript: Tag24<SessionTranscript> =
let session_transcript: SessionTranscriptBytes =
serde_cbor::from_slice(&session_transcript_bytes).unwrap();

let session_key = derive_session_key(&shared_secret, &session_transcript, true).unwrap();
Expand Down
38 changes: 21 additions & 17 deletions src/presentation/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,22 @@ use crate::{
device_signed::{DeviceAuth, DeviceAuthentication, DeviceNamespacesBytes, DeviceSigned},
helpers::{tag24, NonEmptyMap, NonEmptyVec, Tag24},
issuer_signed::{IssuerSigned, IssuerSignedItemBytes},
session::{self, derive_session_key, get_shared_secret, Handover, SessionData},
CoseKey, DeviceEngagement, DeviceResponse, Mso, SessionEstablishment, SessionTranscript,
session::{
self, derive_session_key, get_shared_secret, Handover, SessionData, SessionTranscript,
},
CoseKey, DeviceEngagement, DeviceResponse, Mso, SessionEstablishment,
},
issuance::Mdoc,
};
use cose_rs::sign1::{CoseSign1, PreparedCoseSign1};
use p256::FieldBytes;
use serde::{Deserialize, Serialize};
use serde_cbor::Value as CborValue;
use session::SessionTranscript180135;
use std::collections::BTreeMap;
use std::num::ParseIntError;
use uuid::Uuid;

pub mod oid4vp;

#[derive(Serialize, Deserialize)]
pub struct SessionManagerInit {
documents: Documents,
Expand All @@ -43,7 +44,7 @@ pub struct SessionManagerEngaged {
#[derive(Serialize, Deserialize)]
pub struct SessionManager {
documents: Documents,
session_transcript: Tag24<SessionTranscript>,
session_transcript: SessionTranscript180135,
sk_device: [u8; 32],
device_message_counter: u32,
sk_reader: [u8; 32],
Expand Down Expand Up @@ -168,20 +169,19 @@ impl SessionManagerEngaged {
session_establishment: SessionEstablishment,
) -> anyhow::Result<(SessionManager, RequestedItems)> {
let e_reader_key = session_establishment.e_reader_key;
let session_transcript = Tag24::new(SessionTranscript(
self.device_engagement,
e_reader_key.clone(),
self.handover,
))
.map_err(Error::Tag24CborEncoding)?;
let session_transcript =
SessionTranscript180135(self.device_engagement, e_reader_key.clone(), self.handover);
let session_transcript_bytes =
Tag24::new(session_transcript.clone()).map_err(Error::Tag24CborEncoding)?;

let e_device_key = p256::SecretKey::from_bytes(FieldBytes::from_slice(&self.e_device_key))?;

let shared_secret = get_shared_secret(e_reader_key.into_inner(), &e_device_key.into())
.map_err(Error::SharedSecretGeneration)?;

let sk_reader = derive_session_key(&shared_secret, &session_transcript, true)?.into();
let sk_device = derive_session_key(&shared_secret, &session_transcript, false)?.into();
let sk_reader = derive_session_key(&shared_secret, &session_transcript_bytes, true)?.into();
let sk_device =
derive_session_key(&shared_secret, &session_transcript_bytes, false)?.into();

let mut sm = SessionManager {
documents: self.documents,
Expand Down Expand Up @@ -418,8 +418,10 @@ impl PreparedDocument {
}

pub trait DeviceSession {
type ST: SessionTranscript;

fn documents(&self) -> &Documents;
fn session_transcript(&self) -> &Tag24<SessionTranscript>;
fn session_transcript(&self) -> Self::ST;
fn prepare_response(
&self,
requests: &RequestedItems,
Expand Down Expand Up @@ -516,7 +518,7 @@ pub trait DeviceSession {
}
};
let device_auth = DeviceAuthentication::new(
self.session_transcript().as_ref().clone(),
self.session_transcript(),
doc_type.clone(),
device_namespaces.clone(),
);
Expand Down Expand Up @@ -579,12 +581,14 @@ pub trait DeviceSession {
}

impl DeviceSession for SessionManager {
type ST = SessionTranscript180135;

fn documents(&self) -> &Documents {
&self.documents
}

fn session_transcript(&self) -> &Tag24<SessionTranscript> {
&self.session_transcript
fn session_transcript(&self) -> SessionTranscript180135 {
self.session_transcript.clone()
}
}

Expand Down
Loading

0 comments on commit 3183341

Please sign in to comment.