Skip to content

Commit 0f0c5d3

Browse files
committed
Adding error handling and CDDL enforcement
- Adding custom errors. - Enforcing non-empty vectors (CDDL `[ + <TYPE>]`) via `NonEmptyVec` - Adding a Result type. Signed-off-by: Larry Dewey <[email protected]>
1 parent 1a10d5f commit 0f0c5d3

File tree

14 files changed

+695
-93
lines changed

14 files changed

+695
-93
lines changed

src/comid.rs

Lines changed: 140 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
//! // Create an empty triples map
4444
//! let triples = TriplesMap {
4545
//! reference_triples: None,
46-
//! endorse_triples: None,
46+
//! endorsed_triples: None,
4747
//! identity_triples: None,
4848
//! attest_key_triples: None,
4949
//! dependency_triples: None,
@@ -58,7 +58,7 @@
5858
//! let comid = ConciseMidTag {
5959
//! language: None,
6060
//! tag_identity,
61-
//! entities: vec![entity],
61+
//! entities: Some(vec![entity].into()),
6262
//! linked_tags: None,
6363
//! triples,
6464
//! extension: None,
@@ -85,13 +85,13 @@
8585
//! All components support optional extensions through [`ExtensionMap`] for future expandability.
8686
8787
use crate::{
88-
core::{RawValueType, TaggedBytes},
88+
core::{NonEmptyVec, RawValueType, TaggedBytes},
8989
generate_tagged,
9090
triples::{EnvironmentMap, MeasuredElementTypeChoice, MeasurementMap, MeasurementValuesMap},
91-
AttestKeyTripleRecord, ConditionalEndorsementSeriesTripleRecord,
91+
AttestKeyTripleRecord, ComidError, ConditionalEndorsementSeriesTripleRecord,
9292
ConditionalEndorsementTripleRecord, CoswidTripleRecord, DomainDependencyTripleRecord,
9393
DomainMembershipTripleRecord, EndorsedTripleRecord, ExtensionMap, IdentityTripleRecord,
94-
ReferenceTripleRecord, Text, Tstr, Uint, Uri, UuidType,
94+
ReferenceTripleRecord, Result, Text, Tstr, Uint, Uri, UuidType,
9595
};
9696
use derive_more::{Constructor, From, TryFrom};
9797
use serde::{Deserialize, Serialize};
@@ -120,12 +120,13 @@ pub struct ConciseMidTag<'a> {
120120
#[serde(rename = "1")]
121121
pub tag_identity: TagIdentityMap<'a>,
122122
/// List of entities associated with this tag
123+
#[serde(skip_serializing_if = "Option::is_none")]
123124
#[serde(rename = "2")]
124-
pub entities: Vec<ComidEntityMap<'a>>,
125+
pub entities: Option<NonEmptyVec<ComidEntityMap<'a>>>,
125126
/// Optional references to other related tags
126127
#[serde(skip_serializing_if = "Option::is_none")]
127128
#[serde(rename = "3")]
128-
pub linked_tags: Option<Vec<LinkedTagMap<'a>>>,
129+
pub linked_tags: Option<NonEmptyVec<LinkedTagMap<'a>>>,
129130
/// Collection of triples describing the module
130131
#[serde(rename = "4")]
131132
pub triples: TriplesMap<'a>,
@@ -198,7 +199,7 @@ impl<'a> ConciseMidTag<'a> {
198199
environment: &EnvironmentMap<'a>,
199200
mkey: MeasuredElementTypeChoice<'a>,
200201
value: &T,
201-
) -> Result<(), std::io::Error>
202+
) -> std::io::Result<()>
202203
where
203204
T: ?Sized + Serialize,
204205
{
@@ -223,17 +224,17 @@ impl<'a> ConciseMidTag<'a> {
223224
None => {
224225
let new_record = ReferenceTripleRecord {
225226
ref_env: environment.clone(),
226-
ref_claims: vec![measurement],
227+
ref_claims: vec![measurement].into(),
227228
};
228-
self.triples.reference_triples = Some(vec![new_record]);
229+
self.triples.reference_triples = Some(vec![new_record].into());
229230
}
230231
Some(vec) => {
231232
if let Some(record) = vec.iter_mut().find(|r| r.ref_env == *environment) {
232233
record.ref_claims.push(measurement);
233234
} else {
234235
let new_record = ReferenceTripleRecord {
235236
ref_env: environment.clone(),
236-
ref_claims: vec![measurement],
237+
ref_claims: vec![measurement].into(),
237238
};
238239
vec.push(new_record);
239240
}
@@ -246,7 +247,7 @@ impl<'a> ConciseMidTag<'a> {
246247
environment: &EnvironmentMap<'a>,
247248
mkey: MeasuredElementTypeChoice<'a>,
248249
value: &T,
249-
) -> Result<(), std::io::Error>
250+
) -> std::io::Result<()>
250251
where
251252
T: ?Sized + Serialize,
252253
{
@@ -267,13 +268,13 @@ impl<'a> ConciseMidTag<'a> {
267268
authorized_by: None,
268269
};
269270

270-
match &mut self.triples.endorse_triples {
271+
match &mut self.triples.endorsed_triples {
271272
None => {
272273
let new_record = EndorsedTripleRecord {
273274
condition: environment.clone(),
274-
endorsement: vec![measurement],
275+
endorsement: vec![measurement].into(),
275276
};
276-
self.triples.endorse_triples = Some(vec![new_record]);
277+
self.triples.endorsed_triples = Some(vec![new_record].into());
277278
}
278279

279280
Some(vec) => {
@@ -282,7 +283,7 @@ impl<'a> ConciseMidTag<'a> {
282283
} else {
283284
let new_record = EndorsedTripleRecord {
284285
condition: environment.clone(),
285-
endorsement: vec![measurement],
286+
endorsement: vec![measurement].into(),
286287
};
287288
vec.push(new_record);
288289
}
@@ -386,58 +387,171 @@ pub enum TagRelTypeChoice {
386387
Replaces,
387388
}
388389

389-
/// Collection of different types of triples describing the module characteristics
390+
/// Collection of different types of triples describing the module characteristics. It is
391+
/// **HIGHLY** recommended to use the TriplesMapBuilder, to ensure the CDDL enforcement of
392+
/// at least one field being present.
390393
#[derive(Default, Debug, Serialize, Deserialize, From, PartialEq, Eq, PartialOrd, Ord, Clone)]
391394
#[repr(C)]
392395
pub struct TriplesMap<'a> {
393396
/// Optional reference triples that link to external references
394397
#[serde(skip_serializing_if = "Option::is_none")]
395398
#[serde(rename = "0")]
396-
pub reference_triples: Option<Vec<ReferenceTripleRecord<'a>>>,
399+
pub reference_triples: Option<NonEmptyVec<ReferenceTripleRecord<'a>>>,
397400

398401
/// Optional endorsement triples that contain verification information
399402
#[serde(skip_serializing_if = "Option::is_none")]
400403
#[serde(rename = "1")]
401-
pub endorse_triples: Option<Vec<EndorsedTripleRecord<'a>>>,
404+
pub endorsed_triples: Option<NonEmptyVec<EndorsedTripleRecord<'a>>>,
402405

403406
/// Optional identity triples that provide identity information
404407
#[serde(skip_serializing_if = "Option::is_none")]
405408
#[serde(rename = "2")]
406-
pub identity_triples: Option<Vec<IdentityTripleRecord<'a>>>,
409+
pub identity_triples: Option<NonEmptyVec<IdentityTripleRecord<'a>>>,
407410

408411
/// Optional attestation key triples containing cryptographic keys
409412
#[serde(skip_serializing_if = "Option::is_none")]
410413
#[serde(rename = "3")]
411-
pub attest_key_triples: Option<Vec<AttestKeyTripleRecord<'a>>>,
414+
pub attest_key_triples: Option<NonEmptyVec<AttestKeyTripleRecord<'a>>>,
412415

413416
/// Optional domain dependency triples describing relationships between domains
414417
#[serde(skip_serializing_if = "Option::is_none")]
415418
#[serde(rename = "4")]
416-
pub dependency_triples: Option<Vec<DomainDependencyTripleRecord<'a>>>,
419+
pub dependency_triples: Option<NonEmptyVec<DomainDependencyTripleRecord<'a>>>,
417420

418421
/// Optional domain membership triples describing domain associations
419422
#[serde(skip_serializing_if = "Option::is_none")]
420423
#[serde(rename = "5")]
421-
pub membership_triples: Option<Vec<DomainMembershipTripleRecord<'a>>>,
424+
pub membership_triples: Option<NonEmptyVec<DomainMembershipTripleRecord<'a>>>,
422425

423426
/// Optional SWID triples containing software identification data
424427
#[serde(skip_serializing_if = "Option::is_none")]
425428
#[serde(rename = "6")]
426-
pub coswid_triples: Option<Vec<CoswidTripleRecord<'a>>>,
429+
pub coswid_triples: Option<NonEmptyVec<CoswidTripleRecord<'a>>>,
427430

428431
/// Optional conditional endorsement series triples for complex endorsement chains
429432
#[serde(skip_serializing_if = "Option::is_none")]
430433
#[serde(rename = "8")]
431434
pub conditional_endorsement_series_triples:
432-
Option<Vec<ConditionalEndorsementSeriesTripleRecord<'a>>>,
435+
Option<NonEmptyVec<ConditionalEndorsementSeriesTripleRecord<'a>>>,
433436

434437
/// Optional conditional endorsement triples for conditional verification
435438
#[serde(skip_serializing_if = "Option::is_none")]
436439
#[serde(rename = "10")]
437-
pub conditional_endorsement_triples: Option<Vec<ConditionalEndorsementTripleRecord<'a>>>,
440+
pub conditional_endorsement_triples:
441+
Option<NonEmptyVec<ConditionalEndorsementTripleRecord<'a>>>,
438442

439443
/// Optional extensible attributes for future expansion
440444
#[serde(skip_serializing_if = "Option::is_none")]
441445
#[serde(flatten)]
442446
pub extension: Option<ExtensionMap<'a>>,
443447
}
448+
449+
#[derive(Default)]
450+
pub struct TriplesMapBuilder<'a> {
451+
reference_triples: Option<NonEmptyVec<ReferenceTripleRecord<'a>>>,
452+
endorsed_triples: Option<NonEmptyVec<EndorsedTripleRecord<'a>>>,
453+
identity_triples: Option<NonEmptyVec<IdentityTripleRecord<'a>>>,
454+
attest_key_triples: Option<NonEmptyVec<AttestKeyTripleRecord<'a>>>,
455+
dependency_triples: Option<NonEmptyVec<DomainDependencyTripleRecord<'a>>>,
456+
membership_triples: Option<NonEmptyVec<DomainMembershipTripleRecord<'a>>>,
457+
coswid_triples: Option<NonEmptyVec<CoswidTripleRecord<'a>>>,
458+
conditional_endorsement_series_triples:
459+
Option<NonEmptyVec<ConditionalEndorsementSeriesTripleRecord<'a>>>,
460+
conditional_endorsement_triples: Option<NonEmptyVec<ConditionalEndorsementTripleRecord<'a>>>,
461+
extension: Option<ExtensionMap<'a>>,
462+
}
463+
464+
impl<'a> TriplesMapBuilder<'a> {
465+
// Setter methods for each field
466+
pub fn reference_triples(mut self, value: NonEmptyVec<ReferenceTripleRecord<'a>>) -> Self {
467+
self.reference_triples = Some(value);
468+
self
469+
}
470+
471+
pub fn endorsed_triples(mut self, value: NonEmptyVec<EndorsedTripleRecord<'a>>) -> Self {
472+
self.endorsed_triples = Some(value);
473+
self
474+
}
475+
476+
pub fn identity_triples(mut self, value: NonEmptyVec<IdentityTripleRecord<'a>>) -> Self {
477+
self.identity_triples = Some(value);
478+
self
479+
}
480+
481+
pub fn attest_key_triples(mut self, value: NonEmptyVec<AttestKeyTripleRecord<'a>>) -> Self {
482+
self.attest_key_triples = Some(value);
483+
self
484+
}
485+
486+
pub fn dependency_triples(
487+
mut self,
488+
value: NonEmptyVec<DomainDependencyTripleRecord<'a>>,
489+
) -> Self {
490+
self.dependency_triples = Some(value);
491+
self
492+
}
493+
494+
pub fn membership_triples(
495+
mut self,
496+
value: NonEmptyVec<DomainMembershipTripleRecord<'a>>,
497+
) -> Self {
498+
self.membership_triples = Some(value);
499+
self
500+
}
501+
502+
pub fn coswid_triples(mut self, value: NonEmptyVec<CoswidTripleRecord<'a>>) -> Self {
503+
self.coswid_triples = Some(value);
504+
self
505+
}
506+
507+
pub fn conditional_endorsement_series_triples(
508+
mut self,
509+
value: NonEmptyVec<ConditionalEndorsementSeriesTripleRecord<'a>>,
510+
) -> Self {
511+
self.conditional_endorsement_series_triples = Some(value);
512+
self
513+
}
514+
515+
pub fn conditional_endorsement_triples(
516+
mut self,
517+
value: NonEmptyVec<ConditionalEndorsementTripleRecord<'a>>,
518+
) -> Self {
519+
self.conditional_endorsement_triples = Some(value);
520+
self
521+
}
522+
523+
pub fn extension(mut self, value: ExtensionMap<'a>) -> Self {
524+
self.extension = Some(value);
525+
self
526+
}
527+
528+
/// Builds the TriplesMap, returning an error if no fields are set
529+
pub fn build(self) -> Result<TriplesMap<'a>> {
530+
if self.reference_triples.is_none()
531+
&& self.endorsed_triples.is_none()
532+
&& self.identity_triples.is_none()
533+
&& self.attest_key_triples.is_none()
534+
&& self.dependency_triples.is_none()
535+
&& self.membership_triples.is_none()
536+
&& self.coswid_triples.is_none()
537+
&& self.conditional_endorsement_series_triples.is_none()
538+
&& self.conditional_endorsement_triples.is_none()
539+
&& self.extension.is_none()
540+
{
541+
return Err(ComidError::EmptyTriplesMap)?;
542+
}
543+
544+
Ok(TriplesMap {
545+
reference_triples: self.reference_triples,
546+
endorsed_triples: self.endorsed_triples,
547+
identity_triples: self.identity_triples,
548+
attest_key_triples: self.attest_key_triples,
549+
dependency_triples: self.dependency_triples,
550+
membership_triples: self.membership_triples,
551+
coswid_triples: self.coswid_triples,
552+
conditional_endorsement_series_triples: self.conditional_endorsement_series_triples,
553+
conditional_endorsement_triples: self.conditional_endorsement_triples,
554+
extension: self.extension,
555+
})
556+
}
557+
}

0 commit comments

Comments
 (0)