From 950e61c47e10f201d066a4298bca141d9b7d865e Mon Sep 17 00:00:00 2001 From: Thomas Fossati Date: Tue, 24 Mar 2026 08:44:11 +0100 Subject: [PATCH 1/7] test Signed-off-by: Thomas Fossati --- .github/workflows/ci.yml | 11 ++- Cargo.toml | 8 +-- src/store/memo_refvaluestore.rs | 14 ++-- src/token/base64.rs | 98 ------------------------- src/token/evidence.rs | 15 ++-- src/token/mod.rs | 1 - src/token/platform.rs | 124 ++++++++++++++++---------------- src/token/realm.rs | 72 +++++++++---------- 8 files changed, 128 insertions(+), 215 deletions(-) delete mode 100644 src/token/base64.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 17ea25c..e3aeabe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,11 @@ jobs: build: runs-on: ubuntu-latest - + - name: Install latest stable Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + components: rustfmt, clippy steps: - uses: actions/checkout@v3 - name: Formatting checks @@ -40,6 +44,11 @@ jobs: steps: - uses: actions/checkout@v3 + - name: Install latest stable Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true - uses: EmbarkStudios/cargo-deny-action@v1 with: command: check ${{ matrix.checks }} diff --git a/Cargo.toml b/Cargo.toml index 7fd269a..09b6fd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" repository = "https://github.com/veraison/rust-ccatoken" license = "Apache-2.0" description = "CCA attestation token decoding, verification, and appraisal" -keywords = [ "Arm", "CCA", "attestation" ] -categories = [ "cryptography", "parser implementations" ] +keywords = ["Arm", "CCA", "attestation"] +categories = ["cryptography", "parser implementations"] readme = "README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -20,9 +20,9 @@ serde_json = { version = "1.0", features = ["raw_value"] } hex = { version = "0.4", features = ["serde"] } thiserror = "1" hex-literal = "0.4.1" -bitmask = "0.5.0" +bitflags = "2.11.0" serde_with = { version = "3.14.0", features = ["hex"] } -jsonwebtoken = "9.1.0" +jsonwebtoken = "10.3.0" cose-rust = "0.1.7" ear = "0.4.0" clap = { version = "4.4.10", features = ["derive"] } diff --git a/src/store/memo_refvaluestore.rs b/src/store/memo_refvaluestore.rs index 44a852e..ad3a1e3 100644 --- a/src/store/memo_refvaluestore.rs +++ b/src/store/memo_refvaluestore.rs @@ -32,19 +32,15 @@ impl MemoRefValueStore { pub fn load_json(&mut self, j: &str) -> Result<(), Error> { let v = RefValues::parse(j)?; - if v.platform.is_some() { - let p = v.platform.as_ref().unwrap(); - - for prv in p.iter() { + if let Some(platform) = v.platform { + for prv in platform.iter() { self.p.write().unwrap().insert(prv.impl_id, prv.clone()); } } - if v.realm.is_some() { - let p = v.realm.as_ref().unwrap(); - - for prv in p.iter() { - self.r.write().unwrap().insert(prv.rim.clone(), prv.clone()); + if let Some(realm) = v.realm { + for rrv in realm.iter() { + self.r.write().unwrap().insert(rrv.rim.clone(), rrv.clone()); } } diff --git a/src/token/base64.rs b/src/token/base64.rs deleted file mode 100644 index 360bfe0..0000000 --- a/src/token/base64.rs +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -use base64::{self, engine::general_purpose, Engine as _}; -use serde::{ - de::{self, Deserialize, Visitor}, - ser::{Serialize, Serializer}, -}; - -use super::errors::Error; - -/// decodes bytes from a base64-encoded string -pub fn decode_str(v: &str) -> Result, Error> { - general_purpose::URL_SAFE_NO_PAD - .decode(v) - .map_err(|e| Error::Parse(e.to_string())) -} - -/// a `Vec` encoded as base64 in human readable serialization -#[derive(Debug, PartialEq)] -pub struct Bytes(Vec); - -impl Bytes { - pub fn new() -> Self { - Bytes(Vec::new()) - } -} - -impl Default for Bytes { - fn default() -> Self { - Self::new() - } -} - -impl From<&[u8]> for Bytes { - fn from(v: &[u8]) -> Self { - Self(v.to_owned()) - } -} - -impl TryFrom<&str> for Bytes { - type Error = Error; - - fn try_from(v: &str) -> Result { - general_purpose::URL_SAFE_NO_PAD - .decode(v) - .map(Bytes) - .map_err(|e| Error::Parse(e.to_string())) - } -} - -impl Serialize for Bytes { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - if serializer.is_human_readable() { - serializer.collect_str(&base64::display::Base64Display::new( - &self.0, - &general_purpose::URL_SAFE_NO_PAD, - )) - } else { - serializer.serialize_bytes(&self.0) - } - } -} - -impl<'de> Deserialize<'de> for Bytes { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_any(BytesVisitor {}) - } -} - -struct BytesVisitor; - -impl Visitor<'_> for BytesVisitor { - type Value = Bytes; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a text string or a byte string") - } - - fn visit_str(self, v: &str) -> Result - where - E: de::Error, - { - Bytes::try_from(v).map_err(de::Error::custom) - } - - fn visit_bytes(self, v: &[u8]) -> Result - where - E: de::Error, - { - Ok(Bytes::from(v)) - } -} diff --git a/src/token/evidence.rs b/src/token/evidence.rs index 5c82010..e9d1337 100644 --- a/src/token/evidence.rs +++ b/src/token/evidence.rs @@ -1,7 +1,6 @@ // Copyright 2023-2025 Contributors to the Veraison project. // SPDX-License-Identifier: Apache-2.0 -use super::base64; use super::common::*; use super::errors::Error; use super::platform::Platform; @@ -10,6 +9,8 @@ use super::realm::REALM_PROFILE; use crate::store::PlatformRefValue; use crate::store::RealmRefValue; use crate::store::{Cpak, IRefValueStore, ITrustAnchorStore}; +use base64::engine::general_purpose; +use base64::Engine; use ciborium::de::from_reader; use ciborium::Value; use cose::keys::CoseKey; @@ -596,8 +597,12 @@ fn make_cose_key(cose_message: &CoseMessage, pkey: jwk::Jwk) -> Result cose::keys::P_521, c => return Err(Error::Key(format!("invalid EC2 curve {c:?}"))), }); - cose_key.x(base64::decode_str(ec_params.x.as_str())?); - cose_key.y(base64::decode_str(ec_params.y.as_str())?); + cose_key.x(general_purpose::URL_SAFE_NO_PAD + .decode(ec_params.x.as_str()) + .map_err(|e| Error::Key(format!("decoding EC2 x parameter failed: {e:?}")))?); + cose_key.y(general_purpose::URL_SAFE_NO_PAD + .decode(ec_params.y.as_str()) + .map_err(|e| Error::Key(format!("decoding EC2 y parameter failed: {e:?}")))?); } jwk::AlgorithmParameters::OctetKeyPair(okp_params) => { cose_key.kty(cose::keys::OKP); @@ -605,7 +610,9 @@ fn make_cose_key(cose_message: &CoseMessage, pkey: jwk::Jwk) -> Result cose::keys::ED25519, c => return Err(Error::Key(format!("invalid OKP curve {c:?}"))), }); - cose_key.x(base64::decode_str(okp_params.x.as_str())?); + cose_key.x(general_purpose::URL_SAFE_NO_PAD + .decode(okp_params.x.as_str()) + .map_err(|e| Error::Key(format!("decoding OKP x parameter failed: {e:?}")))?); } a => return Err(Error::Key(format!("unsupported algorithm params {a:?}"))), } diff --git a/src/token/mod.rs b/src/token/mod.rs index 2bad32f..d621e0c 100644 --- a/src/token/mod.rs +++ b/src/token/mod.rs @@ -53,7 +53,6 @@ pub use self::platform::Platform; pub use self::platform::SwComponent; pub use self::realm::Realm; -mod base64; mod common; mod errors; mod evidence; diff --git a/src/token/platform.rs b/src/token/platform.rs index 640ece7..1540920 100644 --- a/src/token/platform.rs +++ b/src/token/platform.rs @@ -4,7 +4,7 @@ use super::common::*; use super::errors::Error; -use bitmask::*; +use bitflags::bitflags; use ciborium::de::from_reader; use ciborium::Value; @@ -14,15 +14,15 @@ const SW_COMPONENT_VERSION: i128 = 4; const SW_COMPONENT_SIGNER_ID: i128 = 5; const SW_COMPONENT_HASH_ALGO: i128 = 6; -bitmask! { - #[derive(Debug)] - mask SwClaimsSet: u8 where flags SwClaims { - MTyp = 0x01, - MVal = 0x02, - Version = 0x04, - SignerID = 0x08, - Config = 0x10, - HashAlg = 0x20, +bitflags! { + #[derive(Debug, PartialEq, Copy, Clone)] + struct SwClaimsSet: u8 { + const MTYP = 0x01; + const MVAL = 0x02; + const VERSION = 0x04; + const SIGNER_ID = 0x08; + const CONFIG = 0x10; + const HASH_ALG = 0x20; } } @@ -53,12 +53,12 @@ impl SwComponent { signer_id: Default::default(), hash_alg: None, - claims_set: SwClaimsSet::none(), + claims_set: SwClaimsSet::empty(), } } fn set_hash_alg(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(SwClaims::HashAlg) { + if self.claims_set.contains(SwClaimsSet::HASH_ALG) { return Err(Error::DuplicatedClaim("hash-algo-id".to_string())); } @@ -66,25 +66,25 @@ impl SwComponent { self.hash_alg = Some(x); - self.claims_set.set(SwClaims::HashAlg); + self.claims_set.set(SwClaimsSet::HASH_ALG, true); Ok(()) } fn set_signer_id(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(SwClaims::SignerID) { + if self.claims_set.contains(SwClaimsSet::SIGNER_ID) { return Err(Error::DuplicatedClaim("signer-id".to_string())); } self.signer_id = to_bstr(v, "signer-id")?; - self.claims_set.set(SwClaims::SignerID); + self.claims_set.set(SwClaimsSet::SIGNER_ID, true); Ok(()) } fn set_version(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(SwClaims::Version) { + if self.claims_set.contains(SwClaimsSet::VERSION) { return Err(Error::DuplicatedClaim("version".to_string())); } @@ -92,13 +92,13 @@ impl SwComponent { self.version = Some(x); - self.claims_set.set(SwClaims::Version); + self.claims_set.set(SwClaimsSet::VERSION, true); Ok(()) } fn set_mtyp(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(SwClaims::MTyp) { + if self.claims_set.contains(SwClaimsSet::MTYP) { return Err(Error::DuplicatedClaim("measurement-type".to_string())); } @@ -106,19 +106,19 @@ impl SwComponent { self.mtyp = Some(x); - self.claims_set.set(SwClaims::MTyp); + self.claims_set.set(SwClaimsSet::MTYP, true); Ok(()) } fn set_mval(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(SwClaims::MVal) { + if self.claims_set.contains(SwClaimsSet::MVAL) { return Err(Error::DuplicatedClaim("measurement-value".to_string())); } self.mval = to_measurement(v, "measurement-value")?; - self.claims_set.set(SwClaims::MVal); + self.claims_set.set(SwClaimsSet::MVAL, true); Ok(()) } @@ -150,8 +150,8 @@ impl SwComponent { fn validate(&self) -> Result<(), Error> { // only mval and signer-id are mandatory let mandatory_claims = [ - (SwClaims::MVal, "measurement-value"), - (SwClaims::SignerID, "signer-id"), + (SwClaimsSet::MVAL, "measurement-value"), + (SwClaimsSet::SIGNER_ID, "signer-id"), ]; for (c, n) in mandatory_claims.iter() { @@ -179,18 +179,18 @@ const PLATFORM_SW_COMPONENTS: i128 = 2399; const PLATFORM_VERIFICATION_SERVICE: i128 = 2400; const PLATFORM_HASH_ALG: i128 = 2402; // XXX not requested, unassigned -bitmask! { - #[derive(Debug)] - mask ClaimsSet: u16 where flags Claims { - Profile = 0x01, - Challenge = 0x02, - ImplID = 0x04, - InstID = 0x08, - Config = 0x10, - Lifecycle = 0x20, - SwComponents = 0x40, - Vsi = 0x80, - HashAlg = 0x100, +bitflags! { + #[derive(Debug, PartialEq, Copy, Clone)] + struct ClaimsSet: u16 { + const PROFILE = 0x01; + const CHALLENGE = 0x02; + const IMPL_ID = 0x04; + const INST_ID = 0x08; + const CONFIG = 0x10; + const LIFECYCLE = 0x20; + const SW_COMPONENTS = 0x40; + const VSI = 0x80; + const HASH_ALG = 0x100; } } @@ -229,7 +229,7 @@ impl Platform { sw_components: Default::default(), verification_service: None, hash_alg: String::from(""), - claims_set: ClaimsSet::none(), + claims_set: ClaimsSet::empty(), } } @@ -276,14 +276,14 @@ impl Platform { fn validate(&self) -> Result<(), Error> { // all platform claims are mandatory except vsi let mandatory_claims = [ - (Claims::Profile, "profile"), - (Claims::Challenge, "challenge"), - (Claims::ImplID, "implementation-id"), - (Claims::InstID, "instance-id"), - (Claims::Config, "config"), - (Claims::Lifecycle, "lifecycle"), - (Claims::SwComponents, "sw-components"), - (Claims::HashAlg, "hash-algo"), + (ClaimsSet::PROFILE, "profile"), + (ClaimsSet::CHALLENGE, "challenge"), + (ClaimsSet::IMPL_ID, "implementation-id"), + (ClaimsSet::INST_ID, "instance-id"), + (ClaimsSet::CONFIG, "config"), + (ClaimsSet::LIFECYCLE, "lifecycle"), + (ClaimsSet::SW_COMPONENTS, "sw-components"), + (ClaimsSet::HASH_ALG, "hash-algo"), ]; for (c, n) in mandatory_claims.iter() { @@ -298,7 +298,7 @@ impl Platform { } fn set_profile(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::Profile) { + if self.claims_set.contains(ClaimsSet::PROFILE) { return Err(Error::DuplicatedClaim("profile".to_string())); } @@ -314,25 +314,25 @@ impl Platform { self.profile = p; - self.claims_set.set(Claims::Profile); + self.claims_set.set(ClaimsSet::PROFILE, true); Ok(()) } fn set_challenge(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::Challenge) { + if self.claims_set.contains(ClaimsSet::CHALLENGE) { return Err(Error::DuplicatedClaim("challenge".to_string())); } self.challenge = to_measurement(v, "challenge")?; - self.claims_set.set(Claims::Challenge); + self.claims_set.set(ClaimsSet::CHALLENGE, true); Ok(()) } fn set_impl_id(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::ImplID) { + if self.claims_set.contains(ClaimsSet::IMPL_ID) { return Err(Error::DuplicatedClaim("implementation-id".to_string())); } @@ -347,13 +347,13 @@ impl Platform { self.impl_id[..].clone_from_slice(&x); - self.claims_set.set(Claims::ImplID); + self.claims_set.set(ClaimsSet::IMPL_ID, true); Ok(()) } fn set_inst_id(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::InstID) { + if self.claims_set.contains(ClaimsSet::INST_ID) { return Err(Error::DuplicatedClaim("instance-id".to_string())); } @@ -368,25 +368,25 @@ impl Platform { self.inst_id[..].clone_from_slice(&x); - self.claims_set.set(Claims::InstID); + self.claims_set.set(ClaimsSet::INST_ID, true); Ok(()) } fn set_config(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::Config) { + if self.claims_set.contains(ClaimsSet::CONFIG) { return Err(Error::DuplicatedClaim("config".to_string())); } self.config = to_bstr(v, "config")?; - self.claims_set.set(Claims::Config); + self.claims_set.set(ClaimsSet::CONFIG, true); Ok(()) } fn set_lifecycle(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::Lifecycle) { + if self.claims_set.contains(ClaimsSet::LIFECYCLE) { return Err(Error::DuplicatedClaim("lifecycle".to_string())); } @@ -398,13 +398,13 @@ impl Platform { self.lifecycle = lc as u16; - self.claims_set.set(Claims::Lifecycle); + self.claims_set.set(ClaimsSet::LIFECYCLE, true); Ok(()) } fn set_vsi(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::Vsi) { + if self.claims_set.contains(ClaimsSet::VSI) { return Err(Error::DuplicatedClaim("verification-service".to_string())); } @@ -416,20 +416,20 @@ impl Platform { self.verification_service = Some(_x); - self.claims_set.set(Claims::Vsi); + self.claims_set.set(ClaimsSet::VSI, true); Ok(()) } // XXX this is exactly the same as realm's fn set_hash_alg(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::HashAlg) { + if self.claims_set.contains(ClaimsSet::HASH_ALG) { return Err(Error::DuplicatedClaim("hash-algo-id".to_string())); } self.hash_alg = to_hash_alg(v, "hash-algo-id")?; - self.claims_set.set(Claims::HashAlg); + self.claims_set.set(ClaimsSet::HASH_ALG, true); Ok(()) } @@ -449,7 +449,7 @@ impl Platform { } fn set_sw_components(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::SwComponents) { + if self.claims_set.contains(ClaimsSet::SW_COMPONENTS) { return Err(Error::DuplicatedClaim("software-components".to_string())); } @@ -482,7 +482,7 @@ impl Platform { self.set_sw_component(xi)?; } - self.claims_set.set(Claims::SwComponents); + self.claims_set.set(ClaimsSet::SW_COMPONENTS, true); Ok(()) } diff --git a/src/token/realm.rs b/src/token/realm.rs index 7014a33..473054c 100644 --- a/src/token/realm.rs +++ b/src/token/realm.rs @@ -4,7 +4,7 @@ use super::common::*; use super::errors::Error; -use bitmask::*; +use bitflags::bitflags; use ciborium::de::from_reader; use ciborium::Value; @@ -19,17 +19,17 @@ const REALM_HASH_ALG_LABEL: i128 = 44236; const REALM_RAK_LABEL: i128 = 44237; const REALM_RAK_HASH_ALG_LABEL: i128 = 44240; -bitmask! { - #[derive(Debug)] - mask ClaimsSet: u8 where flags Claims { - Challenge = 0x01, - Perso = 0x02, - Rim = 0x04, - Rem = 0x08, - HashAlg = 0x10, - Rak = 0x20, - RakHashAlg = 0x40, - Profile = 0x80, +bitflags! { + #[derive(Debug, PartialEq, Copy, Clone)] + struct ClaimsSet: u8 { + const CHALLENGE = 0x01; + const PERSO = 0x02; + const RIM = 0x04; + const REM = 0x08; + const HASH_ALG = 0x10; + const RAK = 0x20; + const RAK_HASH_ALG = 0x40; + const PROFILE = 0x80; } } @@ -68,7 +68,7 @@ impl Realm { raw_rak: [0; 97], cose_rak: Default::default(), rak_hash_alg: String::from(""), - claims_set: ClaimsSet::none(), + claims_set: ClaimsSet::empty(), } } @@ -125,13 +125,13 @@ impl Realm { fn validate(&self) -> Result<(), Error> { // all realm claims are mandatory let mandatory_claims = [ - (Claims::Challenge, "challenge"), - (Claims::Perso, "personalization-value"), - (Claims::Rim, "initial-measurement"), - (Claims::Rem, "extensible-measurements"), - (Claims::HashAlg, "hash-algo-id"), - (Claims::Rak, "public-key"), - (Claims::RakHashAlg, "public-key-hash-algo-id"), + (ClaimsSet::CHALLENGE, "challenge"), + (ClaimsSet::PERSO, "personalization-value"), + (ClaimsSet::RIM, "initial-measurement"), + (ClaimsSet::REM, "extensible-measurements"), + (ClaimsSet::HASH_ALG, "hash-algo-id"), + (ClaimsSet::RAK, "public-key"), + (ClaimsSet::RAK_HASH_ALG, "public-key-hash-algo-id"), ]; for (c, n) in mandatory_claims.iter() { @@ -155,7 +155,7 @@ impl Realm { } fn set_profile(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::Profile) { + if self.claims_set.contains(ClaimsSet::PROFILE) { return Err(Error::DuplicatedClaim("profile".to_string())); } @@ -167,13 +167,13 @@ impl Realm { self.profile = p; - self.claims_set.set(Claims::Profile); + self.claims_set.set(ClaimsSet::PROFILE, true); Ok(()) } fn set_challenge(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::Challenge) { + if self.claims_set.contains(ClaimsSet::CHALLENGE) { return Err(Error::DuplicatedClaim("challenge".to_string())); } @@ -194,13 +194,13 @@ impl Realm { self.challenge[..].clone_from_slice(&x); - self.claims_set.set(Claims::Challenge); + self.claims_set.set(ClaimsSet::CHALLENGE, true); Ok(()) } fn set_rak_hash_alg(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::RakHashAlg) { + if self.claims_set.contains(ClaimsSet::RAK_HASH_ALG) { return Err(Error::DuplicatedClaim( "public-key-hash-algo-id".to_string(), )); @@ -208,37 +208,37 @@ impl Realm { self.rak_hash_alg = to_hash_alg(v, "public-key-hash-algo-id")?; - self.claims_set.set(Claims::RakHashAlg); + self.claims_set.set(ClaimsSet::RAK_HASH_ALG, true); Ok(()) } fn set_hash_alg(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::HashAlg) { + if self.claims_set.contains(ClaimsSet::HASH_ALG) { return Err(Error::DuplicatedClaim("hash-algo-id".to_string())); } self.hash_alg = to_hash_alg(v, "hash-algo-id")?; - self.claims_set.set(Claims::HashAlg); + self.claims_set.set(ClaimsSet::HASH_ALG, true); Ok(()) } fn set_rim(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::Rim) { + if self.claims_set.contains(ClaimsSet::RIM) { return Err(Error::DuplicatedClaim("initial-measurement".to_string())); } self.rim = to_measurement(v, "initial-measurement")?; - self.claims_set.set(Claims::Rim); + self.claims_set.set(ClaimsSet::RIM, true); Ok(()) } fn set_rak(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::Rak) { + if self.claims_set.contains(ClaimsSet::RAK) { return Err(Error::DuplicatedClaim("public-key".to_string())); } @@ -263,13 +263,13 @@ impl Realm { self.cose_rak = x } - self.claims_set.set(Claims::Rak); + self.claims_set.set(ClaimsSet::RAK, true); Ok(()) } fn set_rem(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::Rem) { + if self.claims_set.contains(ClaimsSet::REM) { return Err(Error::DuplicatedClaim( "extensible-measurements".to_string(), )); @@ -296,13 +296,13 @@ impl Realm { self.rem[i] = to_measurement(xi, format!("extensible-measurement[{i}]").as_str())?; } - self.claims_set.set(Claims::Rem); + self.claims_set.set(ClaimsSet::REM, true); Ok(()) } fn set_perso(&mut self, v: &Value) -> Result<(), Error> { - if self.claims_set.contains(Claims::Perso) { + if self.claims_set.contains(ClaimsSet::PERSO) { return Err(Error::DuplicatedClaim("personalization-value".to_string())); } @@ -324,7 +324,7 @@ impl Realm { } self.perso[..].clone_from_slice(&x); - self.claims_set.set(Claims::Perso); + self.claims_set.set(ClaimsSet::PERSO, true); Ok(()) } From ec9e607ebae1748aa96e957b3fba6269ccc0c599 Mon Sep 17 00:00:00 2001 From: Thomas Fossati Date: Tue, 24 Mar 2026 08:48:40 +0100 Subject: [PATCH 2/7] remove nl Signed-off-by: Thomas Fossati --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3aeabe..b541af8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,6 @@ env: jobs: build: - runs-on: ubuntu-latest - name: Install latest stable Rust uses: actions-rs/toolchain@v1 From 4048d364346b98ed38c9d8878e648603f8ea3c8d Mon Sep 17 00:00:00 2001 From: Thomas Fossati Date: Tue, 24 Mar 2026 08:51:18 +0100 Subject: [PATCH 3/7] reorder Signed-off-by: Thomas Fossati --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b541af8..6a660b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,12 +12,12 @@ env: jobs: build: runs-on: ubuntu-latest + steps: - name: Install latest stable Rust uses: actions-rs/toolchain@v1 with: toolchain: stable components: rustfmt, clippy - steps: - uses: actions/checkout@v3 - name: Formatting checks run: cargo fmt --all -- --check From a4472bcb0ce358ada2d4239e6bdb11aaf84db199 Mon Sep 17 00:00:00 2001 From: Thomas Fossati Date: Tue, 24 Mar 2026 08:57:57 +0100 Subject: [PATCH 4/7] override Signed-off-by: Thomas Fossati --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a660b5..729e849 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,7 @@ jobs: uses: actions-rs/toolchain@v1 with: toolchain: stable + override: true components: rustfmt, clippy - uses: actions/checkout@v3 - name: Formatting checks @@ -48,6 +49,7 @@ jobs: with: toolchain: stable override: true + components: rustfmt, clippy - uses: EmbarkStudios/cargo-deny-action@v1 with: command: check ${{ matrix.checks }} From bc4b5b206bca6dad6a409dc9baace0161c63ba78 Mon Sep 17 00:00:00 2001 From: Thomas Fossati Date: Tue, 24 Mar 2026 09:00:43 +0100 Subject: [PATCH 5/7] rustup Signed-off-by: Thomas Fossati --- .github/workflows/ci.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 729e849..86aa1c1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,11 +45,8 @@ jobs: steps: - uses: actions/checkout@v3 - name: Install latest stable Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - components: rustfmt, clippy + - name: Install latest Rust + run: rustup update stable - uses: EmbarkStudios/cargo-deny-action@v1 with: command: check ${{ matrix.checks }} From ac60f44856e08e8aa0bcf16975593da485d043cc Mon Sep 17 00:00:00 2001 From: Thomas Fossati Date: Tue, 24 Mar 2026 09:01:25 +0100 Subject: [PATCH 6/7] remove empty Signed-off-by: Thomas Fossati --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 86aa1c1..85f87f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,7 +44,6 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Install latest stable Rust - name: Install latest Rust run: rustup update stable - uses: EmbarkStudios/cargo-deny-action@v1 From 1ee22dab2b9eb4b37c8b2a05ac4a9e6fc089226d Mon Sep 17 00:00:00 2001 From: Thomas Fossati Date: Tue, 24 Mar 2026 09:55:25 +0100 Subject: [PATCH 7/7] deny update Signed-off-by: Thomas Fossati --- .github/workflows/ci.yml | 15 ++---- Cargo.toml | 2 +- deny.toml | 111 +++++++++++++++------------------------ 3 files changed, 47 insertions(+), 81 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85f87f4..7dadea7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,13 +13,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - name: Install latest stable Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - components: rustfmt, clippy - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - name: Formatting checks run: cargo fmt --all -- --check - name: Clippy checks @@ -43,9 +37,8 @@ jobs: continue-on-error: ${{ matrix.checks == 'advisories' }} steps: - - uses: actions/checkout@v3 - - name: Install latest Rust - run: rustup update stable - - uses: EmbarkStudios/cargo-deny-action@v1 + - uses: actions/checkout@v4 + - uses: EmbarkStudios/cargo-deny-action@v2 with: command: check ${{ matrix.checks }} + rust-version: "1.85.0" diff --git a/Cargo.toml b/Cargo.toml index 09b6fd0..9257ca1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,4 +26,4 @@ jsonwebtoken = "10.3.0" cose-rust = "0.1.7" ear = "0.4.0" clap = { version = "4.4.10", features = ["derive"] } -openssl = "0.10.34" +openssl = "0.10.72" diff --git a/deny.toml b/deny.toml index 6d6b0ba..ddc170a 100644 --- a/deny.toml +++ b/deny.toml @@ -11,6 +11,9 @@ # Root options +# The graph table configures how the dependency graph is constructed and thus +# which crates the checks are performed against +[graph] # If 1 or more target triples (and optionally, target_features) are specified, # only the specified targets will be checked when running `cargo deny check`. # This means, if a particular package is only ever used as a target specific @@ -22,7 +25,7 @@ targets = [ # The triple can be any string, but only the target triples built in to # rustc (as of 1.40) can be checked against actual config expressions - #{ triple = "x86_64-unknown-linux-musl" }, + #"x86_64-unknown-linux-musl", # You can also specify which target_features you promise are enabled for a # particular target. target_features are currently not validated against # the actual valid features supported by the target architecture. @@ -46,6 +49,9 @@ no-default-features = false # If set, these feature will be enabled when collecting metadata. If `--features` # is specified on the cmd line they will take precedence over this option. #features = [] + +# The output table provides options for how/if diagnostics are outputted +[output] # When outputting inclusion graphs in diagnostics that include features, this # option can be used to specify the depth at which feature edges will be added. # This option is included since the graphs can be quite large and the addition @@ -57,37 +63,22 @@ feature-depth = 1 # More documentation for the advisories section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html [advisories] -# The path where the advisory database is cloned/fetched into -db-path = "~/.cargo/advisory-db" +# The path where the advisory databases are cloned/fetched into +db-path = "$CARGO_HOME/advisory-dbs" # The url(s) of the advisory databases to use db-urls = ["https://github.com/rustsec/advisory-db"] -# The lint level for security vulnerabilities -vulnerability = "deny" # The lint level for unmaintained crates -unmaintained = "warn" +unmaintained = "workspace" # The lint level for crates that have been yanked from their source registry yanked = "warn" -# The lint level for crates with security notices. Note that as of -# 2019-12-17 there are no security notice advisories in -# https://github.com/rustsec/advisory-db -notice = "warn" # A list of advisory IDs to ignore. Note that ignored advisories will still # output a note when they are encountered. ignore = [ -# NOTE: This is a TEMPORARY recognition of the cbindgen use of clap+atty that -# requires clap to update its dependencies - #"RUSTSEC-2021-0145", + #"RUSTSEC-0000-0000", + #{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" }, + #"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish + #{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" }, ] -# Threshold for security vulnerabilities, any vulnerability with a CVSS score -# lower than the range specified will be ignored. Note that ignored advisories -# will still output a note when they are encountered. -# * None - CVSS Score 0.0 -# * Low - CVSS Score 0.1 - 3.9 -# * Medium - CVSS Score 4.0 - 6.9 -# * High - CVSS Score 7.0 - 8.9 -# * Critical - CVSS Score 9.0 - 10.0 -#severity-threshold = - # If this is true, then cargo deny will use the git executable to fetch advisory database. # If this is false, then it uses a built-in git library. # Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support. @@ -98,8 +89,6 @@ ignore = [ # More documentation for the licenses section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html [licenses] -# The lint level for crates which do not have a detectable license -unlicensed = "deny" # List of explicitly allowed licenses # See https://spdx.org/licenses/ for list of possible licenses # [possible values: any SPDX 3.11 short identifier (+ optional exception)]. @@ -116,26 +105,7 @@ allow = [ "MPL-2.0", "Unicode-3.0", ] -# List of explicitly disallowed licenses -# See https://spdx.org/licenses/ for list of possible licenses -# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. -deny = [ - #"Nokia", -] -# Lint level for licenses considered copyleft -copyleft = "warn" -# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses -# * both - The license will be approved if it is both OSI-approved *AND* FSF -# * either - The license will be approved if it is either OSI-approved *OR* FSF -# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF -# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved -# * neither - This predicate is ignored and the default lint level is used -allow-osi-fsf-free = "neither" -# Lint level used when no other predicates are matched -# 1. License isn't in the allow or deny lists -# 2. License isn't copyleft -# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither" -default = "deny" + # The confidence threshold for detecting a license from license text. # The higher the value, the more closely the license text must be to the # canonical license text of a valid SPDX license file. @@ -146,17 +116,15 @@ confidence-threshold = 0.8 exceptions = [ # Each entry is the crate and version constraint, and its specific allow # list - #{ allow = ["Zlib"], name = "adler32", version = "*" }, + #{ allow = ["Zlib"], crate = "adler32" }, ] # Some crates don't have (easily) machine readable licensing information, # adding a clarification entry for it allows you to manually specify the # licensing information [[licenses.clarify]] -# The name of the crate the clarification applies to -name = "ring" -# The optional version constraint for the crate -version = "*" +# The package spec the clarification applies to +crate = "ring" # The SPDX expression for the license requirements of the crate expression = "MIT AND ISC AND OpenSSL" # One or more files in the crate's source used as the "source of truth" for @@ -165,8 +133,8 @@ expression = "MIT AND ISC AND OpenSSL" # and the crate will be checked normally, which may produce warnings or errors # depending on the rest of your configuration license-files = [ - # Each entry is a crate relative path, and the (opaque) hash of its contents - { path = "LICENSE", hash = 0xbd0eed23 } + # Each entry is a crate relative path, and the (opaque) hash of its contents + { path = "LICENSE", hash = 0xbd0eed23 } ] [licenses.private] @@ -199,33 +167,36 @@ wildcards = "allow" # * all - Both lowest-version and simplest-path are used highlight = "all" # The default lint level for `default` features for crates that are members of -# the workspace that is being checked. This can be overriden by allowing/denying +# the workspace that is being checked. This can be overridden by allowing/denying # `default` on a crate-by-crate basis if desired. workspace-default-features = "allow" # The default lint level for `default` features for external crates that are not -# members of the workspace. This can be overriden by allowing/denying `default` +# members of the workspace. This can be overridden by allowing/denying `default` # on a crate-by-crate basis if desired. external-default-features = "allow" # List of crates that are allowed. Use with care! allow = [ - #{ name = "ansi_term", version = "=0.11.0" }, + #"ansi_term@0.11.0", + #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is allowed" }, ] +# If true, workspace members are automatically allowed even when using deny-by-default +# This is useful for organizations that want to deny all external dependencies by default +# but allow their own workspace crates without having to explicitly list them +allow-workspace = false # List of crates to deny deny = [ - # Each entry the name of a crate and a version range. If version is - # not specified, all versions will be matched. - #{ name = "ansi_term", version = "=0.11.0" }, - # + #"ansi_term@0.11.0", + #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is banned" }, # Wrapper crates can optionally be specified to allow the crate when it # is a direct dependency of the otherwise banned crate - #{ name = "ansi_term", version = "=0.11.0", wrappers = [] }, + #{ crate = "ansi_term@0.11.0", wrappers = ["this-crate-directly-depends-on-ansi_term"] }, ] # List of features to allow/deny # Each entry the name of a crate and a version range. If version is # not specified, all versions will be matched. #[[bans.features]] -#name = "reqwest" +#crate = "reqwest" # Features to not allow #deny = ["json"] # Features to allow @@ -246,14 +217,16 @@ deny = [ # Certain crates/versions that will be skipped when doing duplicate detection. skip = [ - #{ name = "ansi_term", version = "=0.11.0" }, + #"ansi_term@0.11.0", + #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason why it can't be updated/removed" }, ] # Similarly to `skip` allows you to skip certain crates during duplicate # detection. Unlike skip, it also includes the entire tree of transitive # dependencies starting at the specified crate, up to a certain depth, which is # by default infinite. skip-tree = [ - #{ name = "ansi_term", version = "=0.11.0", depth = 20 }, + #"ansi_term@0.11.0", # will be skipped along with _all_ of its direct and transitive dependencies + #{ crate = "ansi_term@0.11.0", depth = 20 }, ] # This section is considered when running `cargo deny check sources`. @@ -273,9 +246,9 @@ allow-registry = ["https://github.com/rust-lang/crates.io-index"] allow-git = [] [sources.allow-org] -# 1 or more github.com organizations to allow git sources for -# github = [""] -# 1 or more gitlab.com organizations to allow git sources for -# gitlab = [""] -# 1 or more bitbucket.org organizations to allow git sources for -# bitbucket = [""] +# github.com organizations to allow git sources for +github = [] +# gitlab.com organizations to allow git sources for +gitlab = [] +# bitbucket.org organizations to allow git sources for +bitbucket = []