diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/cose/src | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/cose/src')
-rw-r--r-- | third_party/rust/cose/src/cose.rs | 72 | ||||
-rw-r--r-- | third_party/rust/cose/src/decoder.rs | 235 | ||||
-rw-r--r-- | third_party/rust/cose/src/test_cose.rs | 496 | ||||
-rw-r--r-- | third_party/rust/cose/src/test_setup.rs | 169 | ||||
-rw-r--r-- | third_party/rust/cose/src/util.rs | 27 |
5 files changed, 999 insertions, 0 deletions
diff --git a/third_party/rust/cose/src/cose.rs b/third_party/rust/cose/src/cose.rs new file mode 100644 index 0000000000..d55dda8d16 --- /dev/null +++ b/third_party/rust/cose/src/cose.rs @@ -0,0 +1,72 @@ +//! This crate implements [COSE](https://tools.ietf.org/html/rfc8152) signature +//! parsing. Verification has to be performed by the caller. +//! +//! Example usage: Let `payload` and `cose_signature` be variables holding the +//! signed payload and the COSE signature bytes respectively. +//! Let further `verify_callback` be a function callback that implements +//! signature verification. +//! +//!```rust,ignore +//! use cose::decoder::decode_signature; +//! +//! // Parse the incoming signature. +//! let cose_signatures = decode_signature(cose_signature, &payload); +//! let cose_signatures = match cose_signatures { +//! Ok(signature) => signature, +//! Err(_) => Vec::new(), +//! }; +//! if cose_signatures.len() < 1 { +//! return false; +//! } +//! +//! let mut result = true; +//! for cose_signature in cose_signatures { +//! // Call callback to verify the parsed signatures. +//! result &= verify_callback(cose_signature); +//! +//! // We can stop early. The cose_signature is not valid. +//! if !result { +//! return result; +//! } +//! } +//!``` +extern crate moz_cbor as cbor; + +pub mod decoder; +pub mod util; + +/// Errors that can be returned from COSE functions. +#[derive(Debug, PartialEq)] +pub enum CoseError { + DecodingFailure, + LibraryFailure, + MalformedInput, + MissingHeader, + UnexpectedHeaderValue, + UnexpectedTag, + UnexpectedType, + Unimplemented, + VerificationFailed, + UnknownSignatureScheme, + SigningFailed, + InvalidArgument, +} + +/// An enum identifying supported signature algorithms. +/// Currently ES256 (ECDSA with P256 and SHA256), ES384 (ECDSA with P384 and SHA384) +/// ES512 (ECDSA with P521 and SHA512), and PS256 (RSASSA-PSS with SHA256) +/// are supported. Note that with PS256, the salt length is defined +/// to be 32 bytes. +#[derive(Debug)] +#[derive(PartialEq)] +pub enum SignatureAlgorithm { + ES256, + ES384, + ES512, + PS256, +} + +#[cfg(test)] +mod test_setup; +#[cfg(test)] +mod test_cose; diff --git a/third_party/rust/cose/src/decoder.rs b/third_party/rust/cose/src/decoder.rs new file mode 100644 index 0000000000..90463d5dd2 --- /dev/null +++ b/third_party/rust/cose/src/decoder.rs @@ -0,0 +1,235 @@ +//! Parse and decode COSE signatures. + +use cbor::CborType; +use cbor::decoder::decode; +use {CoseError, SignatureAlgorithm}; +use util::get_sig_struct_bytes; +use std::collections::BTreeMap; + +pub const COSE_SIGN_TAG: u64 = 98; + +/// The result of `decode_signature` holding a decoded COSE signature. +#[derive(Debug)] +pub struct CoseSignature { + pub signature_type: SignatureAlgorithm, + pub signature: Vec<u8>, + pub signer_cert: Vec<u8>, + pub certs: Vec<Vec<u8>>, + pub to_verify: Vec<u8>, +} + +pub const COSE_TYPE_ES256: i64 = -7; +pub const COSE_TYPE_ES384: i64 = -35; +pub const COSE_TYPE_ES512: i64 = -36; +pub const COSE_TYPE_PS256: i64 = -37; + +pub const COSE_HEADER_ALG: u64 = 1; +pub const COSE_HEADER_KID: u64 = 4; + +macro_rules! unpack { + ($to:tt, $var:ident) => ( + match *$var { + CborType::$to(ref cbor_object) => { + cbor_object + } + _ => return Err(CoseError::UnexpectedType), + }; + ) +} + +fn get_map_value( + map: &BTreeMap<CborType, CborType>, + key: &CborType, +) -> Result<CborType, CoseError> { + match map.get(key) { + Some(x) => Ok(x.clone()), + _ => Err(CoseError::MissingHeader), + } +} + +/// Ensure that the referenced `CborType` is an empty map. +fn ensure_empty_map(map: &CborType) -> Result<(), CoseError> { + let unpacked = unpack!(Map, map); + if !unpacked.is_empty() { + return Err(CoseError::MalformedInput); + } + Ok(()) +} + +// This syntax is a little unintuitive. Taken together, the two previous definitions essentially +// mean: +// +// COSE_Sign = [ +// protected : empty_or_serialized_map, +// unprotected : header_map +// payload : bstr / nil, +// signatures : [+ COSE_Signature] +// ] +// +// (COSE_Sign is an array. The first element is an empty or serialized map (in our case, it is +// never expected to be empty). The second element is a map (it is expected to be empty. The third +// element is a bstr or nil (it is expected to be nil). The fourth element is an array of +// COSE_Signature.) +// +// COSE_Signature = [ +// Headers, +// signature : bstr +// ] +// +// but again, unpacking this: +// +// COSE_Signature = [ +// protected : empty_or_serialized_map, +// unprotected : header_map +// signature : bstr +// ] +fn decode_signature_struct( + cose_signature: &CborType, + payload: &[u8], + protected_body_head: &CborType, +) -> Result<CoseSignature, CoseError> { + let cose_signature = unpack!(Array, cose_signature); + if cose_signature.len() != 3 { + return Err(CoseError::MalformedInput); + } + let protected_signature_header_serialized = &cose_signature[0]; + let protected_signature_header_bytes = unpack!(Bytes, protected_signature_header_serialized); + + // Parse the protected signature header. + let protected_signature_header = &match decode(protected_signature_header_bytes) { + Err(_) => return Err(CoseError::DecodingFailure), + Ok(value) => value, + }; + let protected_signature_header = unpack!(Map, protected_signature_header); + if protected_signature_header.len() != 2 { + return Err(CoseError::MalformedInput); + } + let signature_algorithm = get_map_value( + protected_signature_header, + &CborType::Integer(COSE_HEADER_ALG), + )?; + let signature_algorithm = match signature_algorithm { + CborType::SignedInteger(val) => { + match val { + COSE_TYPE_ES256 => SignatureAlgorithm::ES256, + COSE_TYPE_ES384 => SignatureAlgorithm::ES384, + COSE_TYPE_ES512 => SignatureAlgorithm::ES512, + COSE_TYPE_PS256 => SignatureAlgorithm::PS256, + _ => return Err(CoseError::UnexpectedHeaderValue), + } + } + _ => return Err(CoseError::UnexpectedType), + }; + + let ee_cert = &get_map_value( + protected_signature_header, + &CborType::Integer(COSE_HEADER_KID), + )?; + let ee_cert = unpack!(Bytes, ee_cert).clone(); + + // The unprotected header section is expected to be an empty map. + ensure_empty_map(&cose_signature[1])?; + + // Build signature structure to verify. + let signature_bytes = &cose_signature[2]; + let signature_bytes = unpack!(Bytes, signature_bytes).clone(); + let sig_structure_bytes = get_sig_struct_bytes( + protected_body_head.clone(), + protected_signature_header_serialized.clone(), + payload, + ); + + // Read intermediate certificates from protected_body_head. + // Any tampering of the protected header during transport will be detected + // because it is input to the signature verification. + // Note that a protected header has to be present and hold a kid with an + // empty list of intermediate certificates. + let protected_body_head_bytes = unpack!(Bytes, protected_body_head); + let protected_body_head_map = &match decode(protected_body_head_bytes) { + Ok(value) => value, + Err(_) => return Err(CoseError::DecodingFailure), + }; + let protected_body_head_map = unpack!(Map, protected_body_head_map); + if protected_body_head_map.len() != 1 { + return Err(CoseError::MalformedInput); + } + let intermediate_certs_array = + &get_map_value(protected_body_head_map, &CborType::Integer(COSE_HEADER_KID))?; + let intermediate_certs = unpack!(Array, intermediate_certs_array); + let mut certs: Vec<Vec<u8>> = Vec::new(); + for cert in intermediate_certs { + let cert = unpack!(Bytes, cert); + certs.push(cert.clone()); + } + + Ok(CoseSignature { + signature_type: signature_algorithm, + signature: signature_bytes, + signer_cert: ee_cert, + certs: certs, + to_verify: sig_structure_bytes, + }) +} + +/// Decode COSE signature bytes and return a vector of `CoseSignature`. +/// +///```rust,ignore +/// COSE_Sign = [ +/// Headers, +/// payload : bstr / nil, +/// signatures : [+ COSE_Signature] +/// ] +/// +/// Headers = ( +/// protected : empty_or_serialized_map, +/// unprotected : header_map +/// ) +///``` +pub fn decode_signature(bytes: &[u8], payload: &[u8]) -> Result<Vec<CoseSignature>, CoseError> { + // This has to be a COSE_Sign object, which is a tagged array. + let tagged_cose_sign = match decode(bytes) { + Err(_) => return Err(CoseError::DecodingFailure), + Ok(value) => value, + }; + let cose_sign_array = match tagged_cose_sign { + CborType::Tag(tag, cose_sign) => { + if tag != COSE_SIGN_TAG { + return Err(CoseError::UnexpectedTag); + } + match *cose_sign { + CborType::Array(values) => values, + _ => return Err(CoseError::UnexpectedType), + } + } + _ => return Err(CoseError::UnexpectedType), + }; + if cose_sign_array.len() != 4 { + return Err(CoseError::MalformedInput); + } + + // The unprotected header section is expected to be an empty map. + ensure_empty_map(&cose_sign_array[1])?; + + // The payload is expected to be Null (i.e. this is a detached signature). + match cose_sign_array[2] { + CborType::Null => {} + _ => return Err(CoseError::UnexpectedType), + }; + + let signatures = &cose_sign_array[3]; + let signatures = unpack!(Array, signatures); + + // Decode COSE_Signatures. + // There has to be at least one signature to make this a valid COSE signature. + if signatures.len() < 1 { + return Err(CoseError::MalformedInput); + } + let mut result = Vec::new(); + for cose_signature in signatures { + // cose_sign_array[0] holds the protected body header. + let signature = decode_signature_struct(cose_signature, payload, &cose_sign_array[0])?; + result.push(signature); + } + + Ok(result) +} diff --git a/third_party/rust/cose/src/test_cose.rs b/third_party/rust/cose/src/test_cose.rs new file mode 100644 index 0000000000..7c680a879c --- /dev/null +++ b/third_party/rust/cose/src/test_cose.rs @@ -0,0 +1,496 @@ +use test_setup as test; +use {CoseError, SignatureAlgorithm}; +use decoder::{COSE_HEADER_ALG, COSE_HEADER_KID, COSE_SIGN_TAG, COSE_TYPE_ES256, decode_signature}; +use cbor::CborType; +use std::collections::BTreeMap; + +#[test] +fn test_cose_decode() { + let payload = b"This is the content."; + let cose_signatures = decode_signature(&test::COSE_SIGNATURE_BYTES, payload).unwrap(); + assert_eq!(cose_signatures.len(), 1); + assert_eq!(cose_signatures[0].signature_type, SignatureAlgorithm::ES256); + assert_eq!(cose_signatures[0].signature, test::SIGNATURE_BYTES.to_vec()); + assert_eq!(cose_signatures[0].certs[0], test::P256_ROOT.to_vec()); + assert_eq!(cose_signatures[0].certs[1], test::P256_INT.to_vec()); +} + +fn test_cose_format_error(bytes: &[u8], expected_error: CoseError) { + let payload = vec![0]; + let result = decode_signature(bytes, &payload); + assert!(result.is_err()); + assert_eq!(result.err(), Some(expected_error)); +} + +// Helper function to take a `Vec<CborType>`, wrap it in a `CborType::Array`, tag it with the +// COSE_Sign tag (COSE_SIGN_TAG = 98), and serialize it to a `Vec<u8>`. +fn wrap_tag_and_encode_array(array: Vec<CborType>) -> Vec<u8> { + CborType::Tag(COSE_SIGN_TAG, Box::new(CborType::Array(array))).serialize() +} + +// Helper function to create an encoded protected header for a COSE_Sign or COSE_Signature +// structure. +fn encode_test_protected_header(keys: Vec<CborType>, values: Vec<CborType>) -> Vec<u8> { + assert_eq!(keys.len(), values.len()); + let mut map: BTreeMap<CborType, CborType> = BTreeMap::new(); + for (key, value) in keys.iter().zip(values) { + map.insert(key.clone(), value.clone()); + } + CborType::Map(map).serialize() +} + +// Helper function to create a test COSE_Signature structure with the given protected header. +fn build_test_cose_signature(protected_header: Vec<u8>) -> CborType { + CborType::Array(vec![CborType::Bytes(protected_header), + CborType::Map(BTreeMap::new()), + CborType::Bytes(Vec::new())]) +} + +// Helper function to create the minimally-valid COSE_Sign (i.e. "body") protected header. +fn make_minimally_valid_cose_sign_protected_header() -> Vec<u8> { + encode_test_protected_header( + vec![CborType::Integer(COSE_HEADER_KID)], + vec![CborType::Array(Vec::new())], + ) +} + +// Helper function to create a minimally-valid COSE_Signature (i.e. "body"). +fn make_minimally_valid_cose_signature_protected_header() -> Vec<u8> { + encode_test_protected_header( + vec![CborType::Integer(COSE_HEADER_ALG), + CborType::Integer(COSE_HEADER_KID)], + vec![CborType::SignedInteger(COSE_TYPE_ES256), + CborType::Bytes(Vec::new())], + ) +} + +// This tests the minimally-valid COSE_Sign structure according to this implementation. +// The structure must be a CBOR array of length 4 tagged with the integer 98. +// The COSE_Sign protected header must have the `kid` integer key and no others. The value for `kid` +// must be an array (although it may be empty). Each element of the array must be of type bytes. +// The COSE_Sign unprotected header must be an empty map. +// The COSE_Sign payload must be nil. +// The COSE_Sign signatures must be an array with at least one COSE_Signature. +// Each COSE_Signature must be an array of length 3. +// Each COSE_Signature protected header must have the `alg` and `kid` integer keys and no others. +// The value for `alg` must be a valid algorithm identifier. The value for `kid` must be bytes, +// although it may be empty. +// Each COSE_Signature unprotected header must be an empty map. +// Each COSE_Signature signature must be of type bytes (although it may be empty). +#[test] +fn test_cose_sign_minimally_valid() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature_protected_header = make_minimally_valid_cose_signature_protected_header(); + let signature = build_test_cose_signature(signature_protected_header); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + let payload = vec![0]; + let result = decode_signature(&bytes, &payload); + assert!(result.is_ok()); + let decoded = result.unwrap(); + assert_eq!(decoded.len(), 1); + assert_eq!(decoded[0].signer_cert.len(), 0); + assert_eq!(decoded[0].certs.len(), 0); +} + +#[test] +fn test_cose_sign_not_tagged() { + let bytes = CborType::Array(vec![CborType::Integer(0)]).serialize(); + test_cose_format_error(&bytes, CoseError::UnexpectedType); +} + +#[test] +fn test_cose_sign_wrong_tag() { + // The expected COSE_Sign tag is 98. + let bytes = CborType::Tag(99, Box::new(CborType::Integer(0))).serialize(); + test_cose_format_error(&bytes, CoseError::UnexpectedTag); +} + +#[test] +fn test_cose_sign_right_tag_wrong_contents() { + // The COSE_Sign tag is 98, but the contents should be an array. + let bytes = CborType::Tag(98, Box::new(CborType::Integer(0))).serialize(); + test_cose_format_error(&bytes, CoseError::UnexpectedType); +} + +#[test] +fn test_cose_sign_too_small() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::MalformedInput); +} + +#[test] +fn test_cose_sign_too_large() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(Vec::new()), + CborType::Array(Vec::new())]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::MalformedInput); +} + +#[test] +fn test_cose_sign_protected_header_empty() { + let body_protected_header = encode_test_protected_header(Vec::new(), Vec::new()); + let signature_protected_header = make_minimally_valid_cose_signature_protected_header(); + let signature = build_test_cose_signature(signature_protected_header); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::MalformedInput); +} + +#[test] +fn test_cose_sign_protected_header_missing_kid() { + let body_protected_header = + encode_test_protected_header(vec![CborType::Integer(2)], vec![CborType::Integer(2)]); + let signature_protected_header = make_minimally_valid_cose_signature_protected_header(); + let signature = build_test_cose_signature(signature_protected_header); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::MissingHeader); +} + +#[test] +fn test_cose_sign_protected_header_kid_wrong_type() { + let body_protected_header = encode_test_protected_header( + vec![CborType::Integer(COSE_HEADER_KID)], + vec![CborType::Integer(2)], + ); + let signature_protected_header = make_minimally_valid_cose_signature_protected_header(); + let signature = build_test_cose_signature(signature_protected_header); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::UnexpectedType); +} + +#[test] +fn test_cose_sign_protected_header_extra_header_key() { + let body_protected_header = encode_test_protected_header( + vec![CborType::Integer(COSE_HEADER_KID), + CborType::Integer(2)], + vec![CborType::Bytes(Vec::new()), + CborType::Integer(2)], + ); + let signature_protected_header = make_minimally_valid_cose_signature_protected_header(); + let signature = build_test_cose_signature(signature_protected_header); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::MalformedInput); +} + +#[test] +fn test_cose_sign_unprotected_header_wrong_type() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature_protected_header = make_minimally_valid_cose_signature_protected_header(); + let signature = build_test_cose_signature(signature_protected_header); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Integer(1), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::UnexpectedType); +} + +#[test] +fn test_cose_sign_unprotected_header_not_empty() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature_protected_header = make_minimally_valid_cose_signature_protected_header(); + let signature = build_test_cose_signature(signature_protected_header); + let mut unprotected_header_map: BTreeMap<CborType, CborType> = BTreeMap::new(); + unprotected_header_map.insert(CborType::Integer(0), CborType::SignedInteger(-1)); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(unprotected_header_map), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::MalformedInput); +} + +#[test] +fn test_cose_sign_payload_not_null() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature_protected_header = make_minimally_valid_cose_signature_protected_header(); + let signature = build_test_cose_signature(signature_protected_header); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Integer(0), + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::UnexpectedType); +} + +#[test] +fn test_cose_signatures_not_array() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Integer(0)]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::UnexpectedType); +} + +#[test] +fn test_cose_signatures_empty() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(Vec::new())]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::MalformedInput); +} + +#[test] +fn test_cose_signature_protected_header_wrong_type() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature = CborType::Array(vec![CborType::Null, + CborType::Map(BTreeMap::new()), + CborType::SignedInteger(-1)]); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::UnexpectedType); +} + +#[test] +fn test_cose_signature_protected_header_empty() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature_protected_header = encode_test_protected_header(Vec::new(), Vec::new()); + let signature = build_test_cose_signature(signature_protected_header); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::MalformedInput); +} + +#[test] +fn test_cose_signature_protected_header_too_large() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature_protected_header = make_minimally_valid_cose_signature_protected_header(); + let signature = CborType::Array(vec![CborType::Bytes(signature_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Bytes(Vec::new()), + CborType::Null]); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::MalformedInput); +} + +#[test] +fn test_cose_signature_protected_header_bad_encoding() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + // The bytes here are a truncated integer encoding. + let signature = CborType::Array(vec![CborType::Bytes(vec![0x1a, 0x00, 0x00]), + CborType::Map(BTreeMap::new()), + CborType::Bytes(Vec::new())]); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::DecodingFailure); +} + +#[test] +fn test_cose_signature_protected_header_missing_alg() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature_protected_header = encode_test_protected_header( + vec![CborType::Integer(2), + CborType::Integer(COSE_HEADER_KID)], + vec![CborType::SignedInteger(COSE_TYPE_ES256), + CborType::Bytes(Vec::new())], + ); + let signature = build_test_cose_signature(signature_protected_header); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::MissingHeader); +} + +#[test] +fn test_cose_signature_protected_header_missing_kid() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature_protected_header = encode_test_protected_header( + vec![CborType::Integer(COSE_HEADER_ALG), + CborType::Integer(3)], + vec![CborType::SignedInteger(COSE_TYPE_ES256), + CborType::Bytes(Vec::new())], + ); + let signature = build_test_cose_signature(signature_protected_header); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::MissingHeader); +} + +#[test] +fn test_cose_signature_protected_header_wrong_key_types() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature_protected_header = encode_test_protected_header( + vec![CborType::SignedInteger(-1), + CborType::Bytes(vec![0])], + vec![CborType::SignedInteger(COSE_TYPE_ES256), + CborType::Bytes(Vec::new())], + ); + let signature = build_test_cose_signature(signature_protected_header); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::MissingHeader); +} + +#[test] +fn test_cose_signature_protected_header_unexpected_alg_type() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature_protected_header = encode_test_protected_header( + vec![CborType::Integer(COSE_HEADER_ALG), + CborType::Integer(COSE_HEADER_KID)], + vec![CborType::Integer(10), + CborType::Integer(4)], + ); + let signature = build_test_cose_signature(signature_protected_header); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::UnexpectedType); +} + +#[test] +fn test_cose_signature_protected_header_unsupported_alg() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature_protected_header = encode_test_protected_header( + vec![CborType::Integer(COSE_HEADER_ALG), + CborType::Integer(COSE_HEADER_KID)], + vec![CborType::SignedInteger(-10), + CborType::Bytes(Vec::new())], + ); + let signature = build_test_cose_signature(signature_protected_header); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::UnexpectedHeaderValue); +} + +#[test] +fn test_cose_signature_protected_header_unexpected_kid_type() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature_protected_header = encode_test_protected_header( + vec![CborType::Integer(COSE_HEADER_ALG), + CborType::Integer(COSE_HEADER_KID)], + vec![CborType::SignedInteger(COSE_TYPE_ES256), + CborType::Integer(0)], + ); + let signature = build_test_cose_signature(signature_protected_header); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::UnexpectedType); +} + +#[test] +fn test_cose_signature_protected_header_extra_key() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature_protected_header = encode_test_protected_header( + vec![CborType::Integer(COSE_HEADER_ALG), + CborType::Integer(COSE_HEADER_KID), + CborType::Integer(5)], + vec![CborType::SignedInteger(COSE_TYPE_ES256), + CborType::Bytes(Vec::new()), + CborType::Integer(5)], + ); + let signature = build_test_cose_signature(signature_protected_header); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::MalformedInput); +} + +#[test] +fn test_cose_signature_unprotected_header_wrong_type() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature_protected_header = make_minimally_valid_cose_signature_protected_header(); + let signature = CborType::Array(vec![CborType::Bytes(signature_protected_header), + CborType::Integer(1), + CborType::Bytes(Vec::new())]); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::UnexpectedType); +} + +#[test] +fn test_cose_signature_unprotected_header_not_empty() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature_protected_header = make_minimally_valid_cose_signature_protected_header(); + let mut unprotected_header_map: BTreeMap<CborType, CborType> = BTreeMap::new(); + unprotected_header_map.insert(CborType::Integer(0), CborType::SignedInteger(-1)); + let signature = CborType::Array(vec![CborType::Bytes(signature_protected_header), + CborType::Map(unprotected_header_map), + CborType::Bytes(Vec::new())]); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::MalformedInput); +} + +#[test] +fn test_cose_signature_signature_wrong_type() { + let body_protected_header = make_minimally_valid_cose_sign_protected_header(); + let signature_protected_header = make_minimally_valid_cose_signature_protected_header(); + let signature = CborType::Array(vec![CborType::Bytes(signature_protected_header), + CborType::Map(BTreeMap::new()), + CborType::SignedInteger(-1)]); + let values = vec![CborType::Bytes(body_protected_header), + CborType::Map(BTreeMap::new()), + CborType::Null, + CborType::Array(vec![signature])]; + let bytes = wrap_tag_and_encode_array(values); + test_cose_format_error(&bytes, CoseError::UnexpectedType); +} diff --git a/third_party/rust/cose/src/test_setup.rs b/third_party/rust/cose/src/test_setup.rs new file mode 100644 index 0000000000..fce0676a66 --- /dev/null +++ b/third_party/rust/cose/src/test_setup.rs @@ -0,0 +1,169 @@ +#[cfg_attr(rustfmt, rustfmt_skip)] +pub const P256_INT: [u8; 332] = [ + 0x30, 0x82, 0x01, 0x48, 0x30, 0x81, 0xf0, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x14, 0x43, 0x63, 0x59, 0xad, 0x04, 0x34, 0x56, 0x80, + 0x43, 0xec, 0x90, 0x6a, 0xd4, 0x10, 0x64, 0x7c, 0x7f, 0x38, 0x32, + 0xe2, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, + 0x03, 0x02, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x32, + 0x35, 0x36, 0x30, 0x22, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, + 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, + 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33, 0x31, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x13, 0x31, 0x11, 0x30, 0x0f, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x69, 0x6e, 0x74, 0x2d, + 0x70, 0x32, 0x35, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, + 0xbb, 0xbb, 0x61, 0xe0, 0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, + 0x87, 0x04, 0xe2, 0xec, 0x05, 0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e, + 0x92, 0x3f, 0x2c, 0x4f, 0x79, 0x4b, 0x45, 0x5c, 0x2a, 0x69, 0xd2, + 0x33, 0x45, 0x6c, 0x36, 0xc4, 0x11, 0x9d, 0x07, 0x06, 0xe0, 0x0e, + 0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99, 0x1b, 0x7b, 0x2d, 0x07, + 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0xa3, 0x1d, 0x30, 0x1b, + 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, + 0x01, 0x01, 0xff, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, + 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, + 0x02, 0x20, 0x63, 0x59, 0x02, 0x01, 0x89, 0xd7, 0x3e, 0x5b, 0xff, + 0xd1, 0x16, 0x4e, 0xe3, 0xe2, 0x0a, 0xe0, 0x4a, 0xd8, 0x75, 0xaf, + 0x77, 0x5c, 0x93, 0x60, 0xba, 0x10, 0x1f, 0x97, 0xdd, 0x27, 0x2d, + 0x24, 0x02, 0x20, 0x3d, 0x87, 0x0f, 0xac, 0x22, 0x4d, 0x16, 0xd9, + 0xa1, 0x95, 0xbb, 0x56, 0xe0, 0x21, 0x05, 0x93, 0xd1, 0x07, 0xb5, + 0x25, 0x3b, 0xf4, 0x57, 0x20, 0x87, 0x13, 0xa2, 0xf7, 0x78, 0x15, + 0x30, 0xa7 +]; + +#[cfg_attr(rustfmt, rustfmt_skip)] +pub const P256_ROOT: [u8; 334] = [ + 0x30, 0x82, 0x01, 0x4a, 0x30, 0x81, 0xf1, 0xa0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x14, 0x5f, 0x3f, 0xae, 0x90, 0x49, 0x30, 0x2f, 0x33, 0x6e, 0x95, + 0x23, 0xa7, 0xcb, 0x23, 0xd7, 0x65, 0x4f, 0xea, 0x3c, 0xf7, 0x30, 0x0a, + 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x14, + 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x72, + 0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x22, 0x18, 0x0f, + 0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33, + 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x14, 0x31, 0x12, + 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x72, 0x6f, 0x6f, + 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, 0xbb, + 0xbb, 0x61, 0xe0, 0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87, 0x04, + 0xe2, 0xec, 0x05, 0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92, 0x3f, 0x2c, + 0x4f, 0x79, 0x4b, 0x45, 0x5c, 0x2a, 0x69, 0xd2, 0x33, 0x45, 0x6c, 0x36, + 0xc4, 0x11, 0x9d, 0x07, 0x06, 0xe0, 0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, + 0xd7, 0x99, 0x1b, 0x7b, 0x2d, 0x07, 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, + 0xc0, 0xa3, 0x1d, 0x30, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0b, 0x06, 0x03, 0x55, + 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, + 0x45, 0x02, 0x20, 0x5c, 0x75, 0x51, 0x9f, 0x13, 0x11, 0x50, 0xcd, 0x5d, + 0x8a, 0xde, 0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff, 0xb2, 0x73, 0x75, + 0x5f, 0x31, 0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a, 0x70, 0xe6, 0x02, + 0x21, 0x00, 0xc2, 0xe4, 0xc1, 0xa8, 0xe2, 0x89, 0xdc, 0xa1, 0xbb, 0xe7, + 0xd5, 0x4f, 0x5c, 0x88, 0xad, 0xeb, 0xa4, 0x78, 0xa1, 0x19, 0xbe, 0x22, + 0x54, 0xc8, 0x9f, 0xef, 0xb8, 0x5d, 0xa2, 0x40, 0xd9, 0x8b +]; + +#[cfg_attr(rustfmt, rustfmt_skip)] +pub const COSE_SIGNATURE_BYTES: [u8; 1062] = [ + 0xd8, 0x62, 0x84, 0x59, 0x02, 0xa3, 0xa1, 0x04, 0x82, 0x59, 0x01, 0x4e, + 0x30, 0x82, 0x01, 0x4a, 0x30, 0x81, 0xf1, 0xa0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x14, 0x5f, 0x3f, 0xae, 0x90, 0x49, 0x30, 0x2f, 0x33, 0x6e, 0x95, + 0x23, 0xa7, 0xcb, 0x23, 0xd7, 0x65, 0x4f, 0xea, 0x3c, 0xf7, 0x30, 0x0a, + 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x14, + 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x72, + 0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x22, 0x18, 0x0f, + 0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33, + 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x14, 0x31, 0x12, + 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x72, 0x6f, 0x6f, + 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, 0xbb, + 0xbb, 0x61, 0xe0, 0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87, 0x04, + 0xe2, 0xec, 0x05, 0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92, 0x3f, 0x2c, + 0x4f, 0x79, 0x4b, 0x45, 0x5c, 0x2a, 0x69, 0xd2, 0x33, 0x45, 0x6c, 0x36, + 0xc4, 0x11, 0x9d, 0x07, 0x06, 0xe0, 0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, + 0xd7, 0x99, 0x1b, 0x7b, 0x2d, 0x07, 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, + 0xc0, 0xa3, 0x1d, 0x30, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0b, 0x06, 0x03, 0x55, + 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, + 0x45, 0x02, 0x20, 0x5c, 0x75, 0x51, 0x9f, 0x13, 0x11, 0x50, 0xcd, 0x5d, + 0x8a, 0xde, 0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff, 0xb2, 0x73, 0x75, + 0x5f, 0x31, 0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a, 0x70, 0xe6, 0x02, + 0x21, 0x00, 0xc2, 0xe4, 0xc1, 0xa8, 0xe2, 0x89, 0xdc, 0xa1, 0xbb, 0xe7, + 0xd5, 0x4f, 0x5c, 0x88, 0xad, 0xeb, 0xa4, 0x78, 0xa1, 0x19, 0xbe, 0x22, + 0x54, 0xc8, 0x9f, 0xef, 0xb8, 0x5d, 0xa2, 0x40, 0xd9, 0x8b, 0x59, 0x01, + 0x4c, 0x30, 0x82, 0x01, 0x48, 0x30, 0x81, 0xf0, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x14, 0x43, 0x63, 0x59, 0xad, 0x04, 0x34, 0x56, 0x80, 0x43, + 0xec, 0x90, 0x6a, 0xd4, 0x10, 0x64, 0x7c, 0x7f, 0x38, 0x32, 0xe2, 0x30, + 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, + 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, + 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x22, 0x18, + 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, + 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x13, 0x31, + 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x69, 0x6e, + 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, 0xbb, + 0xbb, 0x61, 0xe0, 0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87, 0x04, + 0xe2, 0xec, 0x05, 0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92, 0x3f, 0x2c, + 0x4f, 0x79, 0x4b, 0x45, 0x5c, 0x2a, 0x69, 0xd2, 0x33, 0x45, 0x6c, 0x36, + 0xc4, 0x11, 0x9d, 0x07, 0x06, 0xe0, 0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, + 0xd7, 0x99, 0x1b, 0x7b, 0x2d, 0x07, 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, + 0xc0, 0xa3, 0x1d, 0x30, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0b, 0x06, 0x03, 0x55, + 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, + 0x44, 0x02, 0x20, 0x63, 0x59, 0x02, 0x01, 0x89, 0xd7, 0x3e, 0x5b, 0xff, + 0xd1, 0x16, 0x4e, 0xe3, 0xe2, 0x0a, 0xe0, 0x4a, 0xd8, 0x75, 0xaf, 0x77, + 0x5c, 0x93, 0x60, 0xba, 0x10, 0x1f, 0x97, 0xdd, 0x27, 0x2d, 0x24, 0x02, + 0x20, 0x3d, 0x87, 0x0f, 0xac, 0x22, 0x4d, 0x16, 0xd9, 0xa1, 0x95, 0xbb, + 0x56, 0xe0, 0x21, 0x05, 0x93, 0xd1, 0x07, 0xb5, 0x25, 0x3b, 0xf4, 0x57, + 0x20, 0x87, 0x13, 0xa2, 0xf7, 0x78, 0x15, 0x30, 0xa7, 0xa0, 0xf6, 0x81, + 0x83, 0x59, 0x01, 0x33, 0xa2, 0x01, 0x26, 0x04, 0x59, 0x01, 0x2c, 0x30, + 0x82, 0x01, 0x28, 0x30, 0x81, 0xcf, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, + 0x14, 0x2f, 0xc3, 0x5f, 0x05, 0x80, 0xb4, 0x49, 0x45, 0x13, 0x92, 0xd6, + 0x93, 0xb7, 0x2d, 0x71, 0x19, 0xc5, 0x8c, 0x40, 0x39, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x13, 0x31, + 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x69, 0x6e, + 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x22, 0x18, 0x0f, 0x32, 0x30, + 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33, 0x31, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x12, 0x31, 0x10, 0x30, 0x0e, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x07, 0x65, 0x65, 0x2d, 0x70, 0x32, + 0x35, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, + 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, 0xbb, 0xbb, 0x61, 0xe0, 0xf8, + 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87, 0x04, 0xe2, 0xec, 0x05, 0x0b, + 0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92, 0x3f, 0x2c, 0x4f, 0x79, 0x4b, 0x45, + 0x5c, 0x2a, 0x69, 0xd2, 0x33, 0x45, 0x6c, 0x36, 0xc4, 0x11, 0x9d, 0x07, + 0x06, 0xe0, 0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99, 0x1b, 0x7b, + 0x2d, 0x07, 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0x30, 0x0a, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, + 0x30, 0x45, 0x02, 0x20, 0x5c, 0x75, 0x51, 0x9f, 0x13, 0x11, 0x50, 0xcd, + 0x5d, 0x8a, 0xde, 0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff, 0xb2, 0x73, + 0x75, 0x5f, 0x31, 0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a, 0x70, 0xe6, + 0x02, 0x21, 0x00, 0xff, 0x81, 0xbe, 0xa8, 0x0d, 0x03, 0x36, 0x6b, 0x75, + 0xe2, 0x70, 0x6a, 0xac, 0x07, 0x2e, 0x4c, 0xdc, 0xf9, 0xc5, 0x89, 0xc1, + 0xcf, 0x88, 0xc2, 0xc8, 0x2a, 0x32, 0xf5, 0x42, 0x0c, 0xfa, 0x0b, 0xa0, + 0x58, 0x40, 0x11, 0xe5, 0x73, 0x2c, 0x23, 0x31, 0x6f, 0xb4, 0x17, 0xcf, + 0xa9, 0xee, 0xc5, 0xe3, 0x57, 0xcc, 0x77, 0x82, 0x29, 0x1f, 0xba, 0x97, + 0xbf, 0x32, 0xaf, 0x8d, 0x88, 0x27, 0xde, 0x69, 0xd2, 0xdf, 0xd6, 0xec, + 0x9e, 0x5b, 0xd3, 0x9d, 0xf8, 0x9d, 0x68, 0xc6, 0xce, 0x91, 0x32, 0x41, + 0x50, 0x5f, 0xd8, 0x72, 0xb0, 0x41, 0xb9, 0x39, 0x3d, 0xdf, 0x44, 0xee, + 0x89, 0x74, 0x4d, 0x9e, 0xb4, 0xd7 +]; + +#[cfg_attr(rustfmt, rustfmt_skip)] +pub const SIGNATURE_BYTES: [u8; 64] = [ + 0x11, 0xe5, 0x73, 0x2c, 0x23, 0x31, 0x6f, 0xb4, 0x17, 0xcf, + 0xa9, 0xee, 0xc5, 0xe3, 0x57, 0xcc, 0x77, 0x82, 0x29, 0x1f, 0xba, 0x97, + 0xbf, 0x32, 0xaf, 0x8d, 0x88, 0x27, 0xde, 0x69, 0xd2, 0xdf, 0xd6, 0xec, + 0x9e, 0x5b, 0xd3, 0x9d, 0xf8, 0x9d, 0x68, 0xc6, 0xce, 0x91, 0x32, 0x41, + 0x50, 0x5f, 0xd8, 0x72, 0xb0, 0x41, 0xb9, 0x39, 0x3d, 0xdf, 0x44, 0xee, + 0x89, 0x74, 0x4d, 0x9e, 0xb4, 0xd7 +]; diff --git a/third_party/rust/cose/src/util.rs b/third_party/rust/cose/src/util.rs new file mode 100644 index 0000000000..8f1cf7e954 --- /dev/null +++ b/third_party/rust/cose/src/util.rs @@ -0,0 +1,27 @@ +use cbor::CborType; + +/// Sig_structure is a CBOR array: +/// +/// Sig_structure = [ +/// context : "Signature" / "Signature1" / "CounterSignature", +/// body_protected : empty_or_serialized_map, +/// ? sign_protected : empty_or_serialized_map, +/// external_aad : bstr, +/// payload : bstr +/// ] +/// +/// In this case, the context is "Signature". There is no external_aad, so this defaults to a +/// zero-length bstr. +pub fn get_sig_struct_bytes( + protected_body_header_serialized: CborType, + protected_signature_header_serialized: CborType, + payload: &[u8], +) -> Vec<u8> { + let sig_structure_array: Vec<CborType> = vec![CborType::String(String::from("Signature")), + protected_body_header_serialized, + protected_signature_header_serialized, + CborType::Null, + CborType::Bytes(payload.to_vec())]; + + CborType::Array(sig_structure_array).serialize() +} |