diff --git a/src/cose.rs b/src/cose.rs index da9d9852..990fa28b 100644 --- a/src/cose.rs +++ b/src/cose.rs @@ -1,5 +1,6 @@ pub mod key; pub mod mac0; +mod serialize; pub mod sign1; use coset::iana; diff --git a/src/cose/key.rs b/src/cose/key.rs index 9767d3eb..7b18f5c5 100644 --- a/src/cose/key.rs +++ b/src/cose/key.rs @@ -160,12 +160,14 @@ impl<'de> Deserialize<'de> for CoseKey { impl TryFrom for EncodedPoint { type Error = Error; fn try_from(value: CoseKey) -> Result { - let x = get_x(&value)?.as_bytes().ok_or(Error::EC2MissingX)?; + let x = get_coord(&value, Element::X)? + .as_bytes() + .ok_or(Error::EC2MissingX)?; match value.0.kty { KeyType::Assigned(kty) => match kty { iana::KeyType::EC2 => { let x_generic_array = GenericArray::from_slice(x.as_ref()); - match get_y(&value)? { + match get_coord(&value, Element::Y)? { Value::Bytes(y) => { let y_generic_array = GenericArray::from_slice(y.as_ref()); Ok(EncodedPoint::from_affine_coordinates( @@ -208,13 +210,13 @@ impl From for CborValue { /// If X or Y is missing. fn from(key: CoseKey) -> CborValue { let mut map = BTreeMap::new(); - let x = get_x(&key) + let x = get_coord(&key, Element::X) .unwrap() .as_bytes() .ok_or(Error::EC2MissingX) .unwrap() .clone(); - let y = get_y(&key) + let y = get_coord(&key, Element::Y) .unwrap() .as_bytes() .ok_or(Error::EC2MissingY) @@ -366,24 +368,26 @@ fn into_curve(str: String) -> Result { }) } -fn get_x(key: &CoseKey) -> Result<&Value, Error> { - for (key, value) in &key.0.params { - match key { - Label::Int(p) if *p == iana::Ec2KeyParameter::X as i64 => return Ok(value), - _ => continue, - } - } - Err(Error::EC2MissingX) +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +enum Element { + X, + Y, } -fn get_y(key: &CoseKey) -> Result<&Value, Error> { +fn get_coord(key: &CoseKey, element: Element) -> Result<&Value, Error> { for (key, value) in &key.0.params { - match key { - Label::Int(p) if *p == iana::Ec2KeyParameter::Y as i64 => return Ok(value), - _ => continue, + match element { + Element::X => match key { + Label::Int(p) if *p == iana::Ec2KeyParameter::X as i64 => return Ok(value), + _ => continue, + }, + Element::Y => match key { + Label::Int(p) if *p == iana::Ec2KeyParameter::Y as i64 => return Ok(value), + _ => continue, + }, } } - Err(Error::EC2MissingY) + Err(Error::EC2MissingX) } fn get_crv(key: &CoseKey) -> Result { diff --git a/src/cose/mac0.rs b/src/cose/mac0.rs index b865a0c3..d3d3fbc0 100644 --- a/src/cose/mac0.rs +++ b/src/cose/mac0.rs @@ -1,4 +1,4 @@ -use crate::cose::SignatureAlgorithm; +use crate::cose::{serialize, SignatureAlgorithm}; use ::hmac::Hmac; use coset::cbor::Value; use coset::cwt::ClaimsSet; @@ -7,9 +7,7 @@ use coset::{ RegisteredLabelWithPrivate, }; use digest::{Mac, MacError}; -use serde::ser::{SerializeMap, SerializeSeq}; use serde::{ser, Deserialize, Deserializer, Serialize}; -use serde_cbor::tags::Tagged; use sha2::Sha256; /// Prepared `COSE_Mac0` for remote signing. @@ -254,74 +252,15 @@ impl ser::Serialize for CoseMac0 { .clone() .to_cbor_value() .map_err(ser::Error::custom)?; - if self.tagged { - return Tagged::new(Some(iana::CborTag::CoseMac0 as u64), value).serialize(serializer); - } - match value { - Value::Bytes(x) => serializer.serialize_bytes(&x), - Value::Bool(x) => serializer.serialize_bool(x), - Value::Text(x) => serializer.serialize_str(x.as_str()), - Value::Null => serializer.serialize_unit(), - - Value::Tag(tag, ref v) => Tagged::new(Some(tag), v).serialize(serializer), - - Value::Float(x) => { - let y = x as f32; - if (y as f64).to_bits() == x.to_bits() { - serializer.serialize_f32(y) - } else { - serializer.serialize_f64(x) - } - } - - #[allow(clippy::unnecessary_fallible_conversions)] - Value::Integer(x) => { - if let Ok(x) = u8::try_from(x) { - serializer.serialize_u8(x) - } else if let Ok(x) = i8::try_from(x) { - serializer.serialize_i8(x) - } else if let Ok(x) = u16::try_from(x) { - serializer.serialize_u16(x) - } else if let Ok(x) = i16::try_from(x) { - serializer.serialize_i16(x) - } else if let Ok(x) = u32::try_from(x) { - serializer.serialize_u32(x) - } else if let Ok(x) = i32::try_from(x) { - serializer.serialize_i32(x) - } else if let Ok(x) = u64::try_from(x) { - serializer.serialize_u64(x) - } else if let Ok(x) = i64::try_from(x) { - serializer.serialize_i64(x) - } else if let Ok(x) = u128::try_from(x) { - serializer.serialize_u128(x) - } else if let Ok(x) = i128::try_from(x) { - serializer.serialize_i128(x) - } else { - unreachable!() - } - } - - Value::Array(x) => { - let mut map = serializer.serialize_seq(Some(x.len()))?; - - for v in x { - map.serialize_element(&v)?; - } - - map.end() - } - - Value::Map(x) => { - let mut map = serializer.serialize_map(Some(x.len()))?; - - for (k, v) in x { - map.serialize_entry(&k, &v)?; - } - - map.end() - } - _ => unimplemented!(), - } + serialize::serialize( + value, + if self.tagged { + Some(iana::CborTag::CoseMac0 as u64) + } else { + None + }, + serializer, + ) } } diff --git a/src/cose/sign1.rs b/src/cose/sign1.rs index 3490b0bc..36da7da3 100644 --- a/src/cose/sign1.rs +++ b/src/cose/sign1.rs @@ -4,12 +4,10 @@ use coset::{ iana, sig_structure_data, AsCborValue, CborSerializable, CoseError, RegisteredLabelWithPrivate, SignatureContext, }; -use serde::ser::{SerializeMap, SerializeSeq}; use serde::{ser, Deserialize, Deserializer, Serialize}; -use serde_cbor::tags::Tagged; use signature::Verifier; -use crate::cose::SignatureAlgorithm; +use crate::cose::{serialize, SignatureAlgorithm}; /// Prepared `COSE_Sign1` for remote signing. /// @@ -268,74 +266,15 @@ impl ser::Serialize for CoseSign1 { .clone() .to_cbor_value() .map_err(ser::Error::custom)?; - if self.tagged { - return Tagged::new(Some(iana::CborTag::CoseSign1 as u64), value).serialize(serializer); - } - match value { - Value::Bytes(x) => serializer.serialize_bytes(&x), - Value::Bool(x) => serializer.serialize_bool(x), - Value::Text(x) => serializer.serialize_str(x.as_str()), - Value::Null => serializer.serialize_unit(), - - Value::Tag(tag, ref v) => Tagged::new(Some(tag), v).serialize(serializer), - - Value::Float(x) => { - let y = x as f32; - if (y as f64).to_bits() == x.to_bits() { - serializer.serialize_f32(y) - } else { - serializer.serialize_f64(x) - } - } - - #[allow(clippy::unnecessary_fallible_conversions)] - Value::Integer(x) => { - if let Ok(x) = u8::try_from(x) { - serializer.serialize_u8(x) - } else if let Ok(x) = i8::try_from(x) { - serializer.serialize_i8(x) - } else if let Ok(x) = u16::try_from(x) { - serializer.serialize_u16(x) - } else if let Ok(x) = i16::try_from(x) { - serializer.serialize_i16(x) - } else if let Ok(x) = u32::try_from(x) { - serializer.serialize_u32(x) - } else if let Ok(x) = i32::try_from(x) { - serializer.serialize_i32(x) - } else if let Ok(x) = u64::try_from(x) { - serializer.serialize_u64(x) - } else if let Ok(x) = i64::try_from(x) { - serializer.serialize_i64(x) - } else if let Ok(x) = u128::try_from(x) { - serializer.serialize_u128(x) - } else if let Ok(x) = i128::try_from(x) { - serializer.serialize_i128(x) - } else { - unreachable!() - } - } - - Value::Array(x) => { - let mut map = serializer.serialize_seq(Some(x.len()))?; - - for v in x { - map.serialize_element(&v)?; - } - - map.end() - } - - Value::Map(x) => { - let mut map = serializer.serialize_map(Some(x.len()))?; - - for (k, v) in x { - map.serialize_entry(&k, &v)?; - } - - map.end() - } - _ => unimplemented!(), - } + serialize::serialize( + value, + if self.tagged { + Some(iana::CborTag::CoseSign1 as u64) + } else { + None + }, + serializer, + ) } }