impl make credential
This commit is contained in:
parent
9737a006e7
commit
33229a0b3c
@ -8,6 +8,8 @@ use std::collections::{BTreeMap, HashMap};
|
||||
use std::fmt;
|
||||
use std::fmt::Debug;
|
||||
use std::io::{Read, Write};
|
||||
use std::borrow::Cow;
|
||||
use failure::_core::marker::PhantomData;
|
||||
|
||||
#[deny(missing_debug_implementations)]
|
||||
|
||||
@ -41,7 +43,7 @@ pub enum CborRequests {
|
||||
// 0x05
|
||||
____Unused,
|
||||
// 0x06
|
||||
ClientPin,
|
||||
ClientPin(GetClientPinRequest),
|
||||
// 0x07
|
||||
Reset,
|
||||
// 0x08
|
||||
@ -58,7 +60,7 @@ pub enum CborRequests {
|
||||
|
||||
pub type GetInfoRequest = ();
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize,Eq, PartialEq )]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
pub struct GetInfoResponse {
|
||||
/// Not used in protocol but required to bump the packed index to 0x01
|
||||
// 0x00
|
||||
@ -100,7 +102,7 @@ pub struct GetInfoResponse {
|
||||
default_cred_protect: CredProtect,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
pub struct GetInfoOptions {
|
||||
#[serde(default)]
|
||||
plat: bool,
|
||||
@ -118,7 +120,7 @@ pub struct GetInfoOptions {
|
||||
config: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
pub struct PublicKeyCredentialParameters {
|
||||
/// Not used in protocol but required to bump the packed index to 0x01
|
||||
// 0x00
|
||||
@ -131,10 +133,13 @@ pub struct PublicKeyCredentialParameters {
|
||||
alg: PublicKeyCredentialAlgorithm,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
pub enum PublicKeyCredentialType {
|
||||
#[serde(rename = "public-key")]
|
||||
PublicKey = 0,
|
||||
NoTwo = 2,
|
||||
#[serde(other)]
|
||||
Other,
|
||||
}
|
||||
|
||||
impl Default for PublicKeyCredentialType {
|
||||
@ -143,11 +148,13 @@ impl Default for PublicKeyCredentialType {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, FromPrimitive, ToPrimitive, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, FromPrimitive, ToPrimitive, Eq, PartialEq)]
|
||||
pub enum PublicKeyCredentialAlgorithm {
|
||||
ES256 = -7,
|
||||
// Unsupported
|
||||
EdDSA = -8,
|
||||
// Compatibility reasons
|
||||
ECDH_ES_HKDF_256 = -25,
|
||||
// Unsupported
|
||||
ES384 = -35,
|
||||
// Unsupported
|
||||
@ -214,7 +221,7 @@ impl<'de> Deserialize<'de> for PublicKeyCredentialAlgorithm {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
pub enum CredProtect {
|
||||
VerificationOptional,
|
||||
VerificationOptionalWithCredentialIDList,
|
||||
@ -227,7 +234,7 @@ impl Default for CredProtect {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
pub struct GetClientPinRequest {
|
||||
/// Not used in protocol but required to bump the packed index to 0x01
|
||||
// 0x00
|
||||
@ -252,7 +259,7 @@ pub struct GetClientPinRequest {
|
||||
#[serde(rename = "pinHashEnc", with = "serde_bytes", default)]
|
||||
pin_hash_enc: Vec<u8>,
|
||||
}
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
pub enum GetClientPinSubommand {
|
||||
/// Not used in protocol but required to bump the packed index to 0x01
|
||||
// 0x00
|
||||
@ -280,7 +287,7 @@ pub enum GetClientPinSubommand {
|
||||
GetUVRetries,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
pub struct GetClientPinResponse {
|
||||
/// Not used in protocol but required to bump the packed index to 0x01
|
||||
// 0x00
|
||||
@ -312,32 +319,13 @@ pub struct GetClientPinResponse {
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct CoseKey {
|
||||
/// Not used in protocol but required to bump the packed index to 0x01
|
||||
// 0x00
|
||||
// #[serde(default)]
|
||||
//__bump: (),
|
||||
// 0x01
|
||||
//#[serde(rename = "type", default)]
|
||||
type_: PublicKeyCredentialType,
|
||||
// 0x02
|
||||
//#[serde(with = "serde_bytes", default)]
|
||||
id: Vec<u8>,
|
||||
// 0x03
|
||||
alg: PublicKeyCredentialAlgorithm,
|
||||
parameters: BTreeMap<i32, serde_cbor::value::Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CoseKeyDescriptor {
|
||||
/// Not used in protocol but required to bump the packed index to 0x01
|
||||
// 0x00
|
||||
#[serde(default)]
|
||||
__bump: (),
|
||||
#[serde(rename = "type")]
|
||||
type_: PublicKeyCredentialType,
|
||||
#[serde(with = "serde_bytes", default)]
|
||||
id: Vec<u8>,
|
||||
alg: PublicKeyCredentialAlgorithm,
|
||||
// remainder
|
||||
parameters: BTreeMap<i32, serde_cbor::value::Value>,
|
||||
}
|
||||
|
||||
@ -346,7 +334,9 @@ impl Serialize for CoseKey {
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut s = serializer.serialize_map(Some(self.parameters.len() + 2 + (!self.id.is_empty()) as usize))?;
|
||||
let mut s = serializer.serialize_map(Some(
|
||||
self.parameters.len() + 2 + (!self.id.is_empty()) as usize,
|
||||
))?;
|
||||
s.serialize_entry(&0x01, &self.type_);
|
||||
if !self.id.is_empty() {
|
||||
s.serialize_entry(&0x02, &self.id);
|
||||
@ -364,15 +354,17 @@ impl<'de> Deserialize<'de> for CoseKey {
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
|
||||
enum Field {
|
||||
Type, Alg, Id, Other(i32)
|
||||
Type,
|
||||
Alg,
|
||||
Id,
|
||||
Other(i32),
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Field {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct FieldVisitor;
|
||||
|
||||
@ -384,8 +376,8 @@ impl<'de> Deserialize<'de> for CoseKey {
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Field, E>
|
||||
where
|
||||
E: de::Error,
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
match value {
|
||||
"alg" => Ok(Field::Alg),
|
||||
@ -394,24 +386,38 @@ impl<'de> Deserialize<'de> for CoseKey {
|
||||
_ => Err(de::Error::unknown_field(value, &["type", "alg", "id"])),
|
||||
}
|
||||
}
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
match value {
|
||||
b"alg" => Ok(Field::Alg),
|
||||
b"type" => Ok(Field::Type),
|
||||
b"id" => Ok(Field::Id),
|
||||
_ => Err(de::Error::unknown_field(
|
||||
&format!("{:?}", value),
|
||||
&["type", "alg", "id"],
|
||||
)),
|
||||
}
|
||||
}
|
||||
fn visit_i64<E>(self, value: i64) -> Result<Field, E>
|
||||
where
|
||||
E: de::Error,
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
match value {
|
||||
0x01 => Ok(Field::Type),
|
||||
0x02 => Ok(Field::Id),
|
||||
0x03=> Ok(Field::Alg),
|
||||
0x03 => Ok(Field::Alg),
|
||||
other => Ok(Field::Other(other as i32)),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_u64<E>(self, value: u64) -> Result<Field, E>
|
||||
where
|
||||
E: de::Error,
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
let signed: i64 = value as i64;
|
||||
self.visit_i64(signed)
|
||||
self.visit_i64(signed)
|
||||
}
|
||||
}
|
||||
|
||||
@ -438,16 +444,18 @@ impl<'de> Deserialize<'de> for CoseKey {
|
||||
let mut parameters: BTreeMap<i32, serde_cbor::value::Value> = BTreeMap::new();
|
||||
while let Some(k) = map.next_key()? {
|
||||
match k {
|
||||
Field::Type => type_ = Some(map.next_value()?),
|
||||
Field::Type => type_ = Some(map.next_value()?),
|
||||
Field::Id => id = Some(map.next_value()?),
|
||||
Field::Alg => alg = Some(map.next_value()?),
|
||||
Field::Other(i) => {parameters.insert(i, map.next_value()?);}
|
||||
Field::Other(i) => {
|
||||
parameters.insert(i, map.next_value()?);
|
||||
}
|
||||
};
|
||||
}
|
||||
let type_ = type_.ok_or_else(|| serde::de::Error::missing_field("type"))?;
|
||||
let id = id.map(|id| id.into_vec()).unwrap_or_else(|| vec![]);
|
||||
let alg = alg.ok_or_else(|| serde::de::Error::missing_field("alg"))?;
|
||||
Ok(CoseKey{
|
||||
Ok(CoseKey {
|
||||
type_,
|
||||
id,
|
||||
alg,
|
||||
@ -460,13 +468,246 @@ impl<'de> Deserialize<'de> for CoseKey {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone,Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct MakeCredentialRequest<'a> {
|
||||
/// Not used in protocol but required to bump the packed index to 0x01
|
||||
// 0x00
|
||||
#[serde(default)]
|
||||
__bump: (),
|
||||
// 0x01
|
||||
#[serde(rename = "clientDataHash")]
|
||||
client_data_hash: Cow<'a, serde_bytes::Bytes>,
|
||||
// 0x02
|
||||
rp: PublicKeyCredentialRpEntity<'a>,
|
||||
// 0x03
|
||||
user: PublicKeyCredentialUserEntity<'a>,
|
||||
// 0x04
|
||||
#[serde(rename = "pubKeyCredParams")]
|
||||
pubkey_cred_params: Cow<'a, [PublicKeyCredentialParameters]>,
|
||||
// 0x05
|
||||
#[serde(rename = "excludeList", default)]
|
||||
exclude_list: Cow<'a, [PublicKeyCredentialDescriptor<'a>]>,
|
||||
// 0x06
|
||||
#[serde(default)]
|
||||
extensions: BTreeMap<Cow<'a ,str>, Cow<'a ,serde_cbor::value::Value>>,
|
||||
#[serde(default)]
|
||||
options: AuthenticatorOptions<'a>,
|
||||
#[serde(rename = "pinUvAuthParam", default)]
|
||||
pin_auth_param: Option<Cow<'a,serde_bytes::Bytes>>,
|
||||
#[serde(rename = "pinUvAuthProtocol", default)]
|
||||
pin_auth_protocol: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq)]
|
||||
pub struct PublicKeyCredentialRpEntity<'a> {
|
||||
id: Cow<'a ,str>,
|
||||
#[serde(default)]
|
||||
name: Option<Cow<'a ,str>>,
|
||||
#[serde(default)]
|
||||
icon: Option<Cow<'a ,str>>,
|
||||
}
|
||||
|
||||
// Ensure keys aren't packed but instead serialized as string
|
||||
impl<'a> Serialize for PublicKeyCredentialRpEntity<'a> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut s = serializer.serialize_map(Some(1 + self.name.is_some() as usize + self.icon.is_some() as usize))?;
|
||||
for (k, v) in &[("id", Some(&self.id)), ("name", self.name.as_ref()), ("icon", self.icon.as_ref())] {
|
||||
s.serialize_entry(k, v)?;
|
||||
}
|
||||
s.end()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq)]
|
||||
pub struct PublicKeyCredentialUserEntity<'a> {
|
||||
id: Cow<'a ,[u8]>,
|
||||
#[serde(default)]
|
||||
name: Option<Cow<'a ,str>>,
|
||||
#[serde(default)]
|
||||
icon: Option<Cow<'a ,str>>,
|
||||
}
|
||||
|
||||
// Ensure keys aren't packed but instead serialized as string
|
||||
impl<'a> Serialize for PublicKeyCredentialUserEntity<'a> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut s = serializer.serialize_map(Some(1 + self.name.is_some() as usize + self.icon.is_some() as usize))?;
|
||||
s.serialize_entry("id", &self.id)?;
|
||||
for (k, v) in &[("name", self.name.as_ref()), ("icon", self.icon.as_ref())] {
|
||||
s.serialize_entry(k, v)?;
|
||||
}
|
||||
s.end()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq)]
|
||||
pub struct PublicKeyCredentialDescriptor<'a> {
|
||||
#[serde(rename = "type")]
|
||||
type_: PublicKeyCredentialType,
|
||||
id: Cow<'a ,[u8]>,
|
||||
}
|
||||
|
||||
// Ensure keys aren't packed but instead serialized as string
|
||||
impl<'a> Serialize for PublicKeyCredentialDescriptor<'a> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut s = serializer.serialize_map(Some(2))?;
|
||||
s.serialize_entry("type", &self.type_)?;
|
||||
s.serialize_entry("id", &self.id)?;
|
||||
s.end()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
pub struct AuthenticatorOptions<'a> {
|
||||
rk: bool,
|
||||
uv: bool,
|
||||
other: BTreeMap<Cow<'a, str>, bool>,
|
||||
}
|
||||
|
||||
impl<'a> Serialize for AuthenticatorOptions<'a> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut s = serializer.serialize_map(Some(
|
||||
self.other.len() + [self.rk, self.uv].iter().filter(|o| **o).count(),
|
||||
))?;
|
||||
for (k, v) in &[("rk", self.rk), ("uv", self.uv)] {
|
||||
if *v {
|
||||
s.serialize_entry(k, v)?;
|
||||
}
|
||||
}
|
||||
for (k, v) in &self.other {
|
||||
s.serialize_entry(k, v)?;
|
||||
}
|
||||
s.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'de> Deserialize<'de> for AuthenticatorOptions<'a> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
enum Field {
|
||||
RK,
|
||||
UV,
|
||||
Other(String),
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Field {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct FieldVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for FieldVisitor {
|
||||
type Value = Field;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("type, alg, id or other")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Field, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
match value {
|
||||
"rk" => Ok(Field::RK),
|
||||
"uv" => Ok(Field::UV),
|
||||
other => Ok(Field::Other(other.into())),
|
||||
}
|
||||
}
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
match value {
|
||||
b"rk" => Ok(Field::RK),
|
||||
b"uv" => Ok(Field::UV),
|
||||
_ => Err(de::Error::unknown_field(
|
||||
&format!("{:?}", value),
|
||||
&["rk", "uv"],
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_identifier(FieldVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
struct AuthenticatorOptionsVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for AuthenticatorOptionsVisitor {
|
||||
type Value = AuthenticatorOptions<'static>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("struct AuthenticatorOptions")
|
||||
}
|
||||
|
||||
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
|
||||
where
|
||||
V: MapAccess<'de>,
|
||||
{
|
||||
let mut options = AuthenticatorOptions::default();
|
||||
while let Some(k) = map.next_key()? {
|
||||
match k {
|
||||
Field::RK => options.rk = map.next_value()?,
|
||||
Field::UV => options.uv = map.next_value()?,
|
||||
Field::Other(i) => {
|
||||
options.other.insert(Cow::Owned(i), map.next_value()?);
|
||||
}
|
||||
};
|
||||
}
|
||||
Ok(options)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_map(AuthenticatorOptionsVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone,Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct MakeCredentialResponse {
|
||||
/// Not used in protocol but required to bump the packed index to 0x01
|
||||
// 0x00
|
||||
#[serde(default)]
|
||||
__bump: (),
|
||||
// 0x01
|
||||
fmt: String,
|
||||
// 0x02
|
||||
#[serde(rename = "authData", with = "serde_bytes")]
|
||||
auth_data: Vec<u8>,
|
||||
// 0x03
|
||||
#[serde(rename = "attStmt")]
|
||||
attestation_statement: BTreeMap<serde_cbor::value::Value, serde_cbor::value::Value>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use super::*;
|
||||
|
||||
fn assert_ok<O: Debug, E: Debug>(res: Result<O, E>) {
|
||||
assert!(dbg!(res).is_ok())
|
||||
assert!(dbg!(res).is_ok());
|
||||
}
|
||||
|
||||
fn encode_round<'a, T: Serialize + Deserialize<'a> + Debug + Eq>(val: T) {
|
||||
let mut buf = Vec::new();
|
||||
val.serialize_cbor(&mut buf).unwrap();
|
||||
let mut buf_slice = &buf[..];
|
||||
let val2 = T::deserialize_cbor(&mut buf_slice).unwrap();
|
||||
assert_eq!(val, val2);
|
||||
}
|
||||
|
||||
mod info {
|
||||
@ -477,7 +718,6 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn response_yubikey() {
|
||||
test_response(&[
|
||||
170, 1, 131, 102, 85, 50, 70, 95, 86, 50, 104, 70, 73, 68, 79, 95, 50, 95, 48, 108,
|
||||
@ -495,7 +735,6 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn response_solokey() {
|
||||
test_response(&[
|
||||
168, 1, 131, 102, 85, 50, 70, 95, 86, 50, 104, 70, 73, 68, 79, 95, 50, 95, 48, 108,
|
||||
@ -520,8 +759,8 @@ mod test {
|
||||
|
||||
fn test_response(mut resp: &[u8]) {
|
||||
let res = GetClientPinResponse::deserialize_cbor(&mut resp).unwrap();
|
||||
let cose = res.key_agreement.unwrap();
|
||||
dbg!(cose.alg);
|
||||
//let cose = res.key_agreement;
|
||||
//dbg!(cose.alg);
|
||||
//assert_ne!(cose.alg, PublicKeyCredentialAlgorithm::Unknown);
|
||||
/*let mut buf = Vec::new();
|
||||
cose.serialize_cbor(&mut buf).unwrap();
|
||||
@ -534,23 +773,41 @@ mod test {
|
||||
test_request(&[162, 1, 1, 2, 2])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cose_key_round() {
|
||||
let key = CoseKey{
|
||||
fn cose_key() -> CoseKey {
|
||||
CoseKey {
|
||||
type_: PublicKeyCredentialType::PublicKey,
|
||||
id: vec![1u8, 3 ,4, 5],
|
||||
id: vec![8, 3, 4, 5],
|
||||
alg: PublicKeyCredentialAlgorithm::PS512,
|
||||
parameters: vec![(-3, serde_cbor::value::Value::Text("test".into()))].into_iter().collect()
|
||||
};
|
||||
let mut buf = Vec::new();
|
||||
key.serialize_cbor(&mut buf).unwrap();
|
||||
let mut buf_slice = &buf[..];
|
||||
let key2 = CoseKey::deserialize_cbor(&mut buf_slice).unwrap();
|
||||
assert_eq!(key, key2);
|
||||
parameters: vec![
|
||||
(-3, serde_cbor::value::Value::Text("test".into())),
|
||||
(
|
||||
-42,
|
||||
serde_cbor::value::Value::Bytes("test".as_bytes().to_vec()),
|
||||
),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cose_key_round() {
|
||||
encode_round(cose_key());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn client_pin_resp_round() {
|
||||
encode_round(GetClientPinResponse {
|
||||
__bump: (),
|
||||
key_agreement: Some(cose_key()),
|
||||
pin_auth_token: vec![1, 2, 3, 4],
|
||||
pin_retries: 3,
|
||||
requires_power_cycle: true,
|
||||
uv_retries: 1,
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn resp_key_agreement_yubikey() {
|
||||
test_response(&[
|
||||
161, 1, 165, 1, 2, 3, 56, 24, 32, 1, 33, 88, 32, 225, 230, 133, 231, 92, 119, 250,
|
||||
@ -563,7 +820,6 @@ mod test {
|
||||
|
||||
// SoloKey v1 fw 4.0.0
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn resp_key_agreement_solokey() {
|
||||
test_response(&[
|
||||
161, 1, 165, 1, 2, 3, 56, 24, 32, 1, 33, 88, 32, 9, 161, 111, 235, 155, 109, 166,
|
||||
@ -576,7 +832,6 @@ mod test {
|
||||
|
||||
// Trezor Model T fw 2.3.0
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn resp_key_agreement_trezor() {
|
||||
test_response(&[
|
||||
161, 1, 165, 1, 2, 3, 56, 24, 32, 1, 33, 88, 32, 164, 211, 77, 255, 139, 183, 45,
|
||||
@ -588,6 +843,81 @@ mod test {
|
||||
}
|
||||
}
|
||||
|
||||
mod make_credential {
|
||||
use super::*;
|
||||
|
||||
fn rp_entity<'a>() -> PublicKeyCredentialRpEntity<'a> {
|
||||
PublicKeyCredentialRpEntity {
|
||||
id: Cow::Borrowed("test"),
|
||||
name: Some("Test".into()),
|
||||
icon: None
|
||||
}
|
||||
}
|
||||
|
||||
fn user_entity<'a>() -> PublicKeyCredentialUserEntity<'a> {
|
||||
PublicKeyCredentialUserEntity {
|
||||
id: Cow::Borrowed(&[0u8]),
|
||||
name: Some("Tester".into()),
|
||||
icon: None
|
||||
}
|
||||
}
|
||||
|
||||
fn pubkey_cred_desc<'a>() -> PublicKeyCredentialDescriptor<'a> {
|
||||
PublicKeyCredentialDescriptor{
|
||||
type_: Default::default(),
|
||||
id: Cow::Owned(vec![1, 2, 3, 4])
|
||||
}
|
||||
}
|
||||
|
||||
fn authenticator_options<'a>() -> AuthenticatorOptions<'a> {
|
||||
AuthenticatorOptions{
|
||||
rk: false,
|
||||
uv: true,
|
||||
other: vec![(Cow::Borrowed("whatever the future may bring"), true)].into_iter().collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn make_credential_request<'a>() -> MakeCredentialRequest<'a> {
|
||||
MakeCredentialRequest{
|
||||
__bump: (),
|
||||
client_data_hash: Cow::Owned(serde_bytes::ByteBuf::from(vec![0u8; 32].into_boxed_slice())),
|
||||
rp: rp_entity(),
|
||||
user: user_entity(),
|
||||
pubkey_cred_params: Cow::Owned(vec![PublicKeyCredentialParameters{
|
||||
__bump: (),
|
||||
type_: Default::default(),
|
||||
alg: PublicKeyCredentialAlgorithm::EdDSA
|
||||
}]) ,
|
||||
exclude_list: Cow::Borrowed(&[]),
|
||||
extensions: Default::default(),
|
||||
options: authenticator_options(),
|
||||
pin_auth_param: None,
|
||||
pin_auth_protocol: None
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rp_entity_round() {
|
||||
encode_round(rp_entity());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn user_entity_round() {
|
||||
encode_round(user_entity());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pubkey_cred_desc_round() {
|
||||
encode_round(pubkey_cred_desc());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn authenticator_options_round() {
|
||||
encode_round(authenticator_options());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//#[test]
|
||||
fn vec_layout() {
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
Loading…
x
Reference in New Issue
Block a user