Skip to content

Commit

Permalink
Update mdoc and certs and fix response handling
Browse files Browse the repository at this point in the history
Also re-add e2e test which had disappeared
  • Loading branch information
sbihel committed Aug 30, 2024
1 parent 6143b7c commit bff7167
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 85 deletions.
37 changes: 10 additions & 27 deletions MobileSdkRs/Sources/MobileSdkRs/mobile_sdk_rs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -959,11 +959,17 @@ public func FfiConverterTypeMDLReaderRequest_lower(_ value: MdlReaderRequest) ->

public struct MdlReaderResponseData {
public var state: MdlSessionManager
public var verifiedResponse: [String: [String: [String: MDocItem]]]
/**
* Contains the namespaces for the mDL directly, without top-level doc types
*/
public var verifiedResponse: [String: [String: MDocItem]]

// Default memberwise initializers are never public by default, so we
// declare one manually.
public init(state: MdlSessionManager, verifiedResponse: [String: [String: [String: MDocItem]]]) {
public init(state: MdlSessionManager,
/**
* Contains the namespaces for the mDL directly, without top-level doc types
*/verifiedResponse: [String: [String: MDocItem]]) {
self.state = state
self.verifiedResponse = verifiedResponse
}
Expand All @@ -976,13 +982,13 @@ public struct FfiConverterTypeMDLReaderResponseData: FfiConverterRustBuffer {
return
try MdlReaderResponseData(
state: FfiConverterTypeMDLSessionManager.read(from: &buf),
verifiedResponse: FfiConverterDictionaryStringDictionaryStringDictionaryStringTypeMDocItem.read(from: &buf)
verifiedResponse: FfiConverterDictionaryStringDictionaryStringTypeMDocItem.read(from: &buf)
)
}

public static func write(_ value: MdlReaderResponseData, into buf: inout [UInt8]) {
FfiConverterTypeMDLSessionManager.write(value.state, into: &buf)
FfiConverterDictionaryStringDictionaryStringDictionaryStringTypeMDocItem.write(value.verifiedResponse, into: &buf)
FfiConverterDictionaryStringDictionaryStringTypeMDocItem.write(value.verifiedResponse, into: &buf)
}
}

Expand Down Expand Up @@ -2666,29 +2672,6 @@ fileprivate struct FfiConverterDictionaryStringDictionaryStringSequenceString: F
}
}

fileprivate struct FfiConverterDictionaryStringDictionaryStringDictionaryStringTypeMDocItem: FfiConverterRustBuffer {
public static func write(_ value: [String: [String: [String: MDocItem]]], into buf: inout [UInt8]) {
let len = Int32(value.count)
writeInt(&buf, len)
for (key, value) in value {
FfiConverterString.write(key, into: &buf)
FfiConverterDictionaryStringDictionaryStringTypeMDocItem.write(value, into: &buf)
}
}

public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> [String: [String: [String: MDocItem]]] {
let len: Int32 = try readInt(&buf)
var dict = [String: [String: [String: MDocItem]]]()
dict.reserveCapacity(Int(len))
for _ in 0..<len {
let key = try FfiConverterString.read(from: &buf)
let value = try FfiConverterDictionaryStringDictionaryStringTypeMDocItem.read(from: &buf)
dict[key] = value
}
return dict
}
}


/**
* Typealias from the type name used in the UDL file to the builtin type. This
Expand Down
63 changes: 55 additions & 8 deletions src/mdl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ mod tests {
}

#[test]
fn end_to_end_ble_presentment() {
fn end_to_end_ble_presentment_holder() {
let mdoc_b64 = include_str!("../../tests/res/mdoc.b64");
let mdoc_bytes = BASE64_STANDARD.decode(mdoc_b64).unwrap();
let mdoc = MDoc::from_cbor(mdoc_bytes).unwrap();
Expand All @@ -399,7 +399,7 @@ mod tests {
.try_into()
.unwrap();
let trust_anchor = TrustAnchorRegistry::iaca_registry_from_str(vec![include_str!(
"../../tests/res/issuer-cert.pem"
"../../tests/res/root-cert.pem"
)
.to_string()])
.unwrap();
Expand Down Expand Up @@ -428,11 +428,58 @@ mod tests {
let signature: p256::ecdsa::Signature = key.sign(&signing_payload);
let response =
submit_signature(request_data.session_manager, signature.to_der().to_vec()).unwrap();
// Root cert is expired
let mut errors = reader_session_manager.handle_response(&response).errors;
let (k, v) = errors.pop_first().unwrap();
assert_eq!(k, "certificate_errors");
assert_eq!(v.as_array().unwrap().len(), 1);
assert_eq!(errors, BTreeMap::default());
let res = reader_session_manager.handle_response(&response);
assert_eq!(res.errors, BTreeMap::new());
}

#[test]
fn end_to_end_ble_presentment_holder_reader() {
let mdoc_b64 = include_str!("../../tests/res/mdoc.b64");
let mdoc_bytes = BASE64_STANDARD.decode(mdoc_b64).unwrap();
let mdoc = MDoc::from_cbor(mdoc_bytes).unwrap();
let key: p256::ecdsa::SigningKey =
p256::SecretKey::from_sec1_pem(include_str!("../../tests/res/sec1.pem"))
.unwrap()
.into();
let holder_session_data = initialise_session(mdoc, Uuid::new_v4()).unwrap();
let namespaces = [(
"org.iso.18013.5.1".to_string(),
[
("given_name".to_string(), true),
("family_name".to_string(), false),
]
.into_iter()
.collect(),
)]
.into_iter()
.collect();
let reader_session_data = super::reader::establish_session(
holder_session_data.qr_code_uri,
namespaces,
Some(vec![
include_str!("../../tests/res/root-cert.pem").to_string()
]),
)
.unwrap();
// let request = reader_session_manager.new_request(namespaces).unwrap();
let request_data =
handle_request(holder_session_data.state, reader_session_data.request).unwrap();
let permitted_items = [(
"org.iso.18013.5.1.mDL".to_string(),
[(
"org.iso.18013.5.1".to_string(),
vec!["given_name".to_string()],
)]
.into_iter()
.collect(),
)]
.into_iter()
.collect();
let signing_payload =
submit_response(request_data.session_manager.clone(), permitted_items).unwrap();
let signature: p256::ecdsa::Signature = key.sign(&signing_payload);
let response =
submit_signature(request_data.session_manager, signature.to_der().to_vec()).unwrap();
let _ = super::reader::handle_response(reader_session_data.state, response).unwrap();
}
}
52 changes: 20 additions & 32 deletions src/mdl/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,8 @@ impl From<serde_json::Value> for MDocItem {
#[derive(uniffi::Record, Debug)]
pub struct MDLReaderResponseData {
state: Arc<MDLSessionManager>,
verified_response: HashMap<String, HashMap<String, HashMap<String, MDocItem>>>,
/// Contains the namespaces for the mDL directly, without top-level doc types
verified_response: HashMap<String, HashMap<String, MDocItem>>,
}

#[uniffi::export]
Expand All @@ -234,6 +235,16 @@ pub fn handle_response(
) -> Result<MDLReaderResponseData, MDLReaderResponseError> {
let mut state = state.0.clone();
let validated_response = state.handle_response(&response);
if !validated_response.errors.is_empty() {
return Err(MDLReaderResponseError::Generic {
value: serde_json::to_string(&validated_response.errors).map_err(|e| {
MDLReaderResponseError::Generic {
value: format!("Could not serialze errors: {e:?}"),
}
})?,
});
}
// These checks should be unreachable as they always have a corresponding entry in `errors`
if let validated_response::Status::Invalid = validated_response.decryption {
return Err(MDLReaderResponseError::InvalidDecryption);
}
Expand All @@ -246,43 +257,20 @@ pub fn handle_response(
if let validated_response::Status::Invalid = validated_response.device_authentication {
return Err(MDLReaderResponseError::InvalidDeviceAuthentication);
}
if !validated_response.errors.is_empty() {
return Err(MDLReaderResponseError::Generic {
value: serde_json::to_string(&validated_response.errors).map_err(|e| {
MDLReaderResponseError::Generic {
value: format!("Could not serialze errors: {e:?}"),
}
})?,
});
}
// We get the namespaces directly without the top-level doc types
let verified_response: Result<_, _> = validated_response
.response
.into_iter()
.map(|(doc_type, namespaces)| {
if let Some(namespaces) = namespaces.as_object() {
let namespaces: Result<_, _> = namespaces
.into_iter()
.map(|(namespace, items)| {
if let Some(items) = items.as_object() {
let items = items
.iter()
.map(|(item, value)| (item.clone(), value.clone().into()))
.collect();
Ok((namespace.to_string(), items))
} else {
Err(MDLReaderResponseError::Generic {
value: "Items not array".to_string(),
})
}
})
.map(|(namespace, items)| {
if let Some(items) = items.as_object() {
let items = items
.iter()
.map(|(item, value)| (item.clone(), value.clone().into()))
.collect();
let namespaces = namespaces.map_err(|e| MDLReaderResponseError::Generic {
value: format!("Unable to parse response: {e:?}"),
})?;
Ok((doc_type, namespaces))
Ok((namespace.to_string(), items))
} else {
Err(MDLReaderResponseError::Generic {
value: "Non-hashmap namespaces".to_string(),
value: format!("Items not object, instead: {items:#?}"),
})
}
})
Expand Down
33 changes: 16 additions & 17 deletions tests/res/issuer-cert.pem
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIDEzCCArqgAwIBAgIUcNjfsRctLizp55XN8+FWBSLE0uYwCgYIKoZIzj0EAwIw
ajELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMRswGQYDVQQKDBJTcHJ1Y2VJRCBU
ZXN0IFJvb3QxMTAvBgNVBAMMKFNwcnVjZUlEIFRlc3QgQ2VydGlmaWNhdGUgUm9v
dCBQYXJpczIwMjMwHhcNMjMxMjAxMTUxMjA4WhcNMjMxMjMxMTUxMjA4WjBqMQsw
CQYDVQQGEwJVUzELMAkGA1UECAwCTlkxGzAZBgNVBAoMElNwcnVjZUlEIFRlc3Qg
Um9vdDExMC8GA1UEAwwoU3BydWNlSUQgVGVzdCBDZXJ0aWZpY2F0ZSBSb290IFBh
cmlzMjAyMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD1/+ffmDpngHzroJ1Kn
0YvEwhw9Rgv0dl4qfN2jXZjPQ1T+zRYlEacSIATQ5o+FWaHQ6Is/wRkjvZeksqb9
YWCjggE8MIIBODAdBgNVHQ4EFgQU5xn7tyLS9unEonXA5D2Jm/9ERcAwgZEGA1Ud
IwSBiTCBhqFupGwwajELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMRswGQYDVQQK
DBJTcHJ1Y2VJRCBUZXN0IFJvb3QxMTAvBgNVBAMMKFNwcnVjZUlEIFRlc3QgQ2Vy
dGlmaWNhdGUgUm9vdCBQYXJpczIwMjOCFHDY37EXLS4s6eeVzfPhVgUixNLmMBIG
A1UdEwEB/wQIMAYBAf8CAQAwPgYDVR0fBDcwNTAzoDGgL4YtaHR0cHM6Ly9pbnRl
cm9wZXZlbnQuc3BydWNlaWQuY29tL2ludGVyb3AuY3JsMA4GA1UdDwEB/wQEAwIB
BjAfBgNVHRIEGDAWgRRpbnRlcm9wQHNwcnVjZWlkLmNvbTAKBggqhkjOPQQDAgNH
ADBEAiBCZjl9NAeNpBQ0hL5ksB1ucQtrdUwY5DzFcqMOQ7XRYgIgZ/WmmOLwOY0f
MvZZ/8dp0GjqlOqLvSMSW4sFzH1qw1M=
MIIC6DCCAo6gAwIBAgIUDWOcz9+mmi6u1douWkiurrDNPlwwCgYIKoZIzj0EAwIw
bjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMRswGQYDVQQKDBJTcHJ1Y2VJRCBU
ZXN0IFJvb3QxNTAzBgNVBAMMLFNwcnVjZUlEIFRlc3QgQ2VydGlmaWNhdGUgUm9v
dCBPSUQ0VkNJV2FsbGV0MB4XDTI0MDgzMDE0MzcxN1oXDTM0MDgyNzE0MzcxN1ow
eTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMSQwIgYDVQQKDBtTcHJ1Y2VJRCBU
ZXN0IElzc3VlciBTaWduZXIxNzA1BgNVBAMMLlNwcnVjZUlEIFRlc3QgQ2VydGlm
aWNhdGUgU2lnbmVyIE9JRDRWQ0lXYWxsZXQwWTATBgcqhkjOPQIBBggqhkjOPQMB
BwNCAARVTxu0PaRPB0CPl+y2Z/ME00uj6fPLxq9y5iFD+ezl7/5wtQX/DuN5IcBn
eQFmFVb2q84KAO0CzirwxE+zgf3To4H+MIH7MB0GA1UdDgQWBBQqeDmZwK83yCWC
c6JX+jl4xap4/DAfBgNVHSMEGDAWgBTnGfu3ItL26cSidcDkPYmb/0RFwDAxBglg
hkgBhvhCAQ0EJBYiSVNPMTgwMTMtNSBUZXN0IFNpZ25lciBDZXJ0aWZpY2F0ZTAO
BgNVHQ8BAf8EBAMCB4AwFQYDVR0lAQH/BAswCQYHKIGMXQUBAjAfBgNVHRIEGDAW
gRRpbnRlcm9wQHNwcnVjZWlkLmNvbTA+BgNVHR8ENzA1MDOgMaAvhi1odHRwczov
L2ludGVyb3BldmVudC5zcHJ1Y2VpZC5jb20vaW50ZXJvcC5jcmwwCgYIKoZIzj0E
AwIDSAAwRQIhAPqmf0Ef7xwrZaAOJlf7kVrFskrB/pwKJ/yz4E3k+jXXAiBQymuA
d1vN8x7LrFih3h0Zg6zhf0XyVDHw5Ey1721vng==
-----END CERTIFICATE-----
2 changes: 1 addition & 1 deletion tests/res/mdoc.b64

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions tests/res/root-cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIIChjCCAiygAwIBAgIUPgwgeCSsRYiU8iN6KHqKED3w/AAwCgYIKoZIzj0EAwIw
bjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMRswGQYDVQQKDBJTcHJ1Y2VJRCBU
ZXN0IFJvb3QxNTAzBgNVBAMMLFNwcnVjZUlEIFRlc3QgQ2VydGlmaWNhdGUgUm9v
dCBPSUQ0VkNJV2FsbGV0MB4XDTI0MDgzMDE0MzQyM1oXDTM0MDgyODE0MzQyM1ow
bjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5ZMRswGQYDVQQKDBJTcHJ1Y2VJRCBU
ZXN0IFJvb3QxNTAzBgNVBAMMLFNwcnVjZUlEIFRlc3QgQ2VydGlmaWNhdGUgUm9v
dCBPSUQ0VkNJV2FsbGV0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPX/59+YO
meAfOugnUqfRi8TCHD1GC/R2Xip83aNdmM9DVP7NFiURpxIgBNDmj4VZodDoiz/B
GSO9l6Sypv1hYKOBpzCBpDAdBgNVHQ4EFgQU5xn7tyLS9unEonXA5D2Jm/9ERcAw
EgYDVR0TAQH/BAgwBgEB/wIBADA+BgNVHR8ENzA1MDOgMaAvhi1odHRwczovL2lu
dGVyb3BldmVudC5zcHJ1Y2VpZC5jb20vaW50ZXJvcC5jcmwwDgYDVR0PAQH/BAQD
AgEGMB8GA1UdEgQYMBaBFGludGVyb3BAc3BydWNlaWQuY29tMAoGCCqGSM49BAMC
A0gAMEUCIQCqFHqCM5NTgkiSJbOeFvGKJKBbordnzOVzb7UrFGQL5gIgKgh9gMKh
VixVit4VpJnYkcJXhQpTba/kWPCCfJh06kU=
-----END CERTIFICATE-----

0 comments on commit bff7167

Please sign in to comment.