Merge branch 'master' into no_wfr

This commit is contained in:
Julien Cretin
2020-05-28 19:33:33 +02:00
4 changed files with 99 additions and 56 deletions

View File

@@ -36,7 +36,7 @@ impl<'a> Writer<'a> {
return false; return false;
} }
match value { match value {
Value::KeyValue(KeyType::Unsigned(unsigned)) => self.start_item(0, unsigned as u64), Value::KeyValue(KeyType::Unsigned(unsigned)) => self.start_item(0, unsigned),
Value::KeyValue(KeyType::Negative(negative)) => { Value::KeyValue(KeyType::Negative(negative)) => {
self.start_item(1, -(negative + 1) as u64) self.start_item(1, -(negative + 1) as u64)
} }

View File

@@ -1,9 +1,9 @@
1003863864e06553e730eec6df4bf8d30c99f697ef9380efdc35eba679b4db78 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin b113945b033eb229e3821542f5889769e5fd2e2ae3cb85c6d13a4e05a44a9866 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin
b4d3b099ee30687cfa8f8705da9d70aa55a4c39f6ce97b7b16317bc18bbf5a96 target/nrf52840dk_merged.hex 13d923f9efad028c9fa5d14920f940ad0108b290088a84ca82f08a3e09a4e569 target/nrf52840dk_merged.hex
88f00a5e1dae6ab3f7571c254ac75f5f3e29ebea7f3ca46c16cfdc3708e804fc third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin 346016903ddf244a239162b7c703aafe7ec70a115175e2204892e874f930f6be third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin
a36027b1720ed5d451690c4bd3e5df2ab257618a8d94829a02cbceed316c3f02 target/nrf52840_dongle_merged.hex f1f0de2e54c0dc88fd503271322a985f9c769fc26a72e651f84b834cd623c09c target/nrf52840_dongle_merged.hex
1bc69b48a2c48da55db8b322902e1fe3f2e095c0dd8517db28837d86e0addc85 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin adcc4caaea86f7b0d54111d3080802e7389a4e69a8f17945d026ee732ea8daa4 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin
82abeb8001247dabbc864501ad1544c9ea859e891df04116ff0e9364a3af5f7e target/nrf52840_dongle_dfu_merged.hex d080c9267370b4a69e64e6098391cded7d3532feaa123c6331b12608aacd0112 target/nrf52840_dongle_dfu_merged.hex
f38ee31d3a09e7e11848e78b5318f95517b6dcd076afcb37e6e3d3e5e9995cc7 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin 97a7dbdb7c3caa345307d5ff7f7607dad5c2cdc523b43c68d3b741ddce318e92 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin
e9effd0350a80c53b6b5422cadd5d8120e1d5924b94c3086dfea09aef89d6466 target/nrf52840_mdk_dfu_merged.hex 5bdcfa69ff5e86cd8175e0d78912e54e803c284502e035416333a8da2eaa1616 target/nrf52840_mdk_dfu_merged.hex
5d081b56927e33c6369228e78a9c126ac55a27bf02397d42f29e2ecf9afa69f1 target/tab/ctap2.tab c68c723d21264b54a7167d999ad18294d10b05d48412595ccbe596865e166e5d target/tab/ctap2.tab

View File

@@ -1,9 +1,9 @@
c182bb4902fff51b2f56810fc2a27df3646cd66ba21359162354d53445623ab8 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin 921d6fc31f7235456dd41abc7e634a37ee87b5016b80c979d20ac5d3fcfc6b6b third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin
94cce0a02b2b44a1e4fd47a927455609890ff03e0574e2de99f355b732463af7 target/nrf52840dk_merged.hex e8e6b802722bf41eb5054ec94e87332fa996e954aad7d02db09beb798d7e381c target/nrf52840dk_merged.hex
0a9929ba8fa57e8a502a49fc7c53177397202e1b11f4c7c3cb6ed68b2b99dd46 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin aab5bdc406b1e874b83872c9358d310070b3ce948ec0e20c054fb923ec879249 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin
85464721e36e846262ce9e2147889ecadfb7e90ba2af4d791c7e4c920ad9809f target/nrf52840_dongle_merged.hex aab3193acc08bc38c4219968da5e9d99f6f73b78fe91d74e8cbc3b94166c7dd3 target/nrf52840_dongle_merged.hex
cca9086c9149c607589b23ffa599a5e4c26db7c20bd3700b79528bd3a5df991d third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin 26b8513e76058e86a01a4b408411ce429834eb2843993eb1671f2487b160bc9a third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin
be1e4f43dbb676e6963bb4d60a0a467d8213b5ebf764834a5dde0ff018bd2efc target/nrf52840_dongle_dfu_merged.hex 99a71cc0622f7cc0abdce686ff6581ec8b9fee6075b7cd771a68c08717e4198f target/nrf52840_dongle_dfu_merged.hex
8857488ba6a69e366f0da229bbfc012a2ad291d3a88d9494247d600c10bb19b7 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin 7cc558a66505e8cf8170aab50e6ddcb28f349fd7ced35ce841ccec33a533bea1 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin
e7736d57434121cf6c198417af0751bfbca100070042f0a28c659c1343f2669f target/nrf52840_mdk_dfu_merged.hex 810f3ef6353177742bba06618bdc865efd819e97cbed605769f12f9d66831671 target/nrf52840_mdk_dfu_merged.hex
ee1e1cd305b902631001fe977b7d692d54a8c2718de36406cf16d1b067ef0567 target/tab/ctap2.tab 54e05927ab650c2ccf10cde165e992e48869888609cc6e8b4429a5c7a420f145 target/tab/ctap2.tab

View File

@@ -433,6 +433,9 @@ impl TryFrom<&cbor::Value> for SignatureAlgorithm {
} }
// https://www.w3.org/TR/webauthn/#public-key-credential-source // https://www.w3.org/TR/webauthn/#public-key-credential-source
//
// Note that we only use the WebAuthn definition as an example. This data-structure is not specified
// by FIDO. In particular we may choose how we serialize and deserialize it.
#[derive(Clone)] #[derive(Clone)]
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]
#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug))] #[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug))]
@@ -447,25 +450,38 @@ pub struct PublicKeyCredentialSource {
pub cred_random: Option<Vec<u8>>, pub cred_random: Option<Vec<u8>>,
} }
// We serialize credentials for the persistent storage using CBOR maps. Each field of a credential
// is associated with a unique tag, implemented with a CBOR unsigned key.
enum PublicKeyCredentialSourceField {
CredentialId = 0,
PrivateKey = 1,
RpId = 2,
UserHandle = 3,
OtherUi = 4,
CredRandom = 5,
// When a field is removed, its tag should be reserved and not used for new fields. We document
// those reserved tags below.
// Reserved tags: none.
}
impl From<PublicKeyCredentialSourceField> for cbor::KeyType {
fn from(field: PublicKeyCredentialSourceField) -> cbor::KeyType {
(field as u64).into()
}
}
impl From<PublicKeyCredentialSource> for cbor::Value { impl From<PublicKeyCredentialSource> for cbor::Value {
fn from(credential: PublicKeyCredentialSource) -> cbor::Value { fn from(credential: PublicKeyCredentialSource) -> cbor::Value {
use PublicKeyCredentialSourceField::*;
let mut private_key = [0u8; 32]; let mut private_key = [0u8; 32];
credential.private_key.to_bytes(&mut private_key); credential.private_key.to_bytes(&mut private_key);
let other_ui = match credential.other_ui { cbor_map_options! {
None => cbor_null!(), CredentialId => Some(credential.credential_id),
Some(other_ui) => cbor_text!(other_ui), PrivateKey => Some(private_key.to_vec()),
}; RpId => Some(credential.rp_id),
let cred_random = match credential.cred_random { UserHandle => Some(credential.user_handle),
None => cbor_null!(), OtherUi => credential.other_ui,
Some(cred_random) => cbor_bytes!(cred_random), CredRandom => credential.cred_random
};
cbor_array! {
credential.credential_id,
private_key,
credential.rp_id,
credential.user_handle,
other_ui,
cred_random,
} }
} }
} }
@@ -473,30 +489,36 @@ impl From<PublicKeyCredentialSource> for cbor::Value {
impl TryFrom<cbor::Value> for PublicKeyCredentialSource { impl TryFrom<cbor::Value> for PublicKeyCredentialSource {
type Error = Ctap2StatusCode; type Error = Ctap2StatusCode;
fn try_from(cbor_value: cbor::Value) -> Result<PublicKeyCredentialSource, Ctap2StatusCode> { fn try_from(cbor_value: cbor::Value) -> Result<Self, Ctap2StatusCode> {
use cbor::{SimpleValue, Value}; use PublicKeyCredentialSourceField::*;
let mut map = extract_map(cbor_value)?;
let fields = read_array(&cbor_value)?; let credential_id = extract_byte_string(ok_or_missing(map.remove(&CredentialId.into()))?)?;
if fields.len() != 6 { let private_key = extract_byte_string(ok_or_missing(map.remove(&PrivateKey.into()))?)?;
return Err(Ctap2StatusCode::CTAP2_ERR_INVALID_CBOR);
}
let credential_id = read_byte_string(&fields[0])?;
let private_key = read_byte_string(&fields[1])?;
if private_key.len() != 32 { if private_key.len() != 32 {
return Err(Ctap2StatusCode::CTAP2_ERR_INVALID_CBOR); return Err(Ctap2StatusCode::CTAP2_ERR_INVALID_CBOR);
} }
let private_key = ecdsa::SecKey::from_bytes(array_ref!(private_key, 0, 32)) let private_key = ecdsa::SecKey::from_bytes(array_ref!(private_key, 0, 32))
.ok_or(Ctap2StatusCode::CTAP2_ERR_INVALID_CBOR)?; .ok_or(Ctap2StatusCode::CTAP2_ERR_INVALID_CBOR)?;
let rp_id = read_text_string(&fields[2])?; let rp_id = extract_text_string(ok_or_missing(map.remove(&RpId.into()))?)?;
let user_handle = read_byte_string(&fields[3])?; let user_handle = extract_byte_string(ok_or_missing(map.remove(&UserHandle.into()))?)?;
let other_ui = match &fields[4] { let other_ui = map
Value::Simple(SimpleValue::NullValue) => None, .remove(&OtherUi.into())
cbor_value => Some(read_text_string(cbor_value)?), .map(extract_text_string)
}; .transpose()?;
let cred_random = match &fields[5] { let cred_random = map
Value::Simple(SimpleValue::NullValue) => None, .remove(&CredRandom.into())
cbor_value => Some(read_byte_string(cbor_value)?), .map(extract_byte_string)
}; .transpose()?;
// We don't return whether there were unknown fields in the CBOR value. This means that
// deserialization is not injective. In particular deserialization is only an inverse of
// serialization at a given version of OpenSK. This is not a problem because:
// 1. When a field is deprecated, its tag is reserved and never reused in future versions,
// including to be reintroduced with the same semantics. In other words, removing a field
// is permanent.
// 2. OpenSK is never used with a more recent version of the storage. In particular, OpenSK
// is never rolled-back.
// As a consequence, the unknown fields are only reserved fields and don't need to be
// preserved.
Ok(PublicKeyCredentialSource { Ok(PublicKeyCredentialSource {
key_type: PublicKeyCredentialType::PublicKey, key_type: PublicKeyCredentialType::PublicKey,
credential_id, credential_id,
@@ -652,6 +674,13 @@ pub fn read_byte_string(cbor_value: &cbor::Value) -> Result<Vec<u8>, Ctap2Status
} }
} }
fn extract_byte_string(cbor_value: cbor::Value) -> Result<Vec<u8>, Ctap2StatusCode> {
match cbor_value {
cbor::Value::KeyValue(cbor::KeyType::ByteString(byte_string)) => Ok(byte_string),
_ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE),
}
}
pub(super) fn read_text_string(cbor_value: &cbor::Value) -> Result<String, Ctap2StatusCode> { pub(super) fn read_text_string(cbor_value: &cbor::Value) -> Result<String, Ctap2StatusCode> {
match cbor_value { match cbor_value {
cbor::Value::KeyValue(cbor::KeyType::TextString(text_string)) => { cbor::Value::KeyValue(cbor::KeyType::TextString(text_string)) => {
@@ -661,6 +690,13 @@ pub(super) fn read_text_string(cbor_value: &cbor::Value) -> Result<String, Ctap2
} }
} }
fn extract_text_string(cbor_value: cbor::Value) -> Result<String, Ctap2StatusCode> {
match cbor_value {
cbor::Value::KeyValue(cbor::KeyType::TextString(text_string)) => Ok(text_string),
_ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE),
}
}
pub(super) fn read_array(cbor_value: &cbor::Value) -> Result<&Vec<cbor::Value>, Ctap2StatusCode> { pub(super) fn read_array(cbor_value: &cbor::Value) -> Result<&Vec<cbor::Value>, Ctap2StatusCode> {
match cbor_value { match cbor_value {
cbor::Value::Array(array) => Ok(array), cbor::Value::Array(array) => Ok(array),
@@ -677,6 +713,15 @@ pub(super) fn read_map(
} }
} }
fn extract_map(
cbor_value: cbor::Value,
) -> Result<BTreeMap<cbor::KeyType, cbor::Value>, Ctap2StatusCode> {
match cbor_value {
cbor::Value::Map(map) => Ok(map),
_ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE),
}
}
pub(super) fn read_bool(cbor_value: &cbor::Value) -> Result<bool, Ctap2StatusCode> { pub(super) fn read_bool(cbor_value: &cbor::Value) -> Result<bool, Ctap2StatusCode> {
match cbor_value { match cbor_value {
cbor::Value::Simple(cbor::SimpleValue::FalseValue) => Ok(false), cbor::Value::Simple(cbor::SimpleValue::FalseValue) => Ok(false),
@@ -685,9 +730,7 @@ pub(super) fn read_bool(cbor_value: &cbor::Value) -> Result<bool, Ctap2StatusCod
} }
} }
pub(super) fn ok_or_missing( pub(super) fn ok_or_missing<T>(value_option: Option<T>) -> Result<T, Ctap2StatusCode> {
value_option: Option<&cbor::Value>,
) -> Result<&cbor::Value, Ctap2StatusCode> {
value_option.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER) value_option.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)
} }