Skip to content

Commit

Permalink
Signal invalid CBOR through new status tracking path
Browse files Browse the repository at this point in the history
  • Loading branch information
scouten-adobe committed Feb 27, 2025
1 parent 6a4a7cc commit ef95c5f
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 55 deletions.
22 changes: 19 additions & 3 deletions cawg_identity/src/identity_assertion/assertion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use std::{
};

use c2pa::{Manifest, Reader};
use c2pa_status_tracker::StatusTracker;
use c2pa_status_tracker::{log_item, StatusTracker};
use serde::{Deserialize, Serialize};
use serde_bytes::ByteBuf;

Expand Down Expand Up @@ -66,13 +66,29 @@ impl IdentityAssertion {
/// Aside from CBOR parsing, no further validation is performed.
pub fn from_manifest<'a>(
manifest: &'a Manifest,
_status_tracker: &'a mut StatusTracker,
status_tracker: &'a mut StatusTracker,
) -> impl Iterator<Item = Result<Self, c2pa::Error>> + use<'a> {
manifest
.assertions()
.iter()
.filter(|a| a.label().starts_with("cawg.identity"))
.map(|a| a.to_assertion())
.map(|a| (a.label().to_owned(), a.to_assertion()))
.inspect(|(label, r)| {
if let Err(err) = r {
// TO DO: a.label() is probably wrong (not a full JUMBF URI)
log_item!(
label.clone(),
"invalid CBOR",
"IdentityAssertion::from_manifest"
)
.validation_status("cawg.identity.cbor.invalid")
.failure_no_throw(
status_tracker,
c2pa::Error::AssertionSpecificError(err.to_string()),
);
}
})
.map(move |(_label, r)| r)
}

/// Create a summary report from this `IdentityAssertion`.
Expand Down
56 changes: 4 additions & 52 deletions cawg_identity/src/tests/builder/simple_case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use std::io::{Cursor, Seek};

use c2pa::{Builder, Reader, SigningAlg};
use c2pa_status_tracker::StatusTracker;
use serde_json::json;
#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
use wasm_bindgen_test::wasm_bindgen_test;

Expand All @@ -24,7 +23,10 @@ use crate::{
AsyncIdentityAssertionBuilder, AsyncIdentityAssertionSigner, IdentityAssertionBuilder,
IdentityAssertionSigner,
},
tests::fixtures::{NaiveAsyncCredentialHolder, NaiveCredentialHolder, NaiveSignatureVerifier},
tests::fixtures::{
manifest_json, parent_json, NaiveAsyncCredentialHolder, NaiveCredentialHolder,
NaiveSignatureVerifier,
},
IdentityAssertion, ToCredentialSummary,
};

Expand Down Expand Up @@ -142,53 +144,3 @@ async fn simple_case_async() {
let nc_json = serde_json::to_string(&nc_summary).unwrap();
assert_eq!(nc_json, "{}");
}

fn manifest_json() -> String {
json!({
"vendor": "test",
"claim_generator_info": [
{
"name": "c2pa_test",
"version": "1.0.0"
}
],
"metadata": [
{
"dateTime": "1985-04-12T23:20:50.52Z",
"my_custom_metadata": "my custom metatdata value"
}
],
"title": "Test_Manifest",
"format": "image/tiff",
"instance_id": "1234",
"thumbnail": {
"format": "image/jpeg",
"identifier": "thumbnail.jpg"
},
"ingredients": [
{
"title": "Test",
"format": "image/jpeg",
"instance_id": "12345",
"relationship": "componentOf"
}
],
"assertions": [
{
"label": "org.test.assertion",
"data": "assertion"
}
]
})
.to_string()
}

fn parent_json() -> String {
json!({
"title": "Parent Test",
"format": "image/jpeg",
"instance_id": "12345",
"relationship": "parentOf"
})
.to_string()
}
65 changes: 65 additions & 0 deletions cawg_identity/src/tests/fixtures/manifest_json.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2025 Adobe. All rights reserved.
// This file is licensed to you under the Apache License,
// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
// or the MIT license (http://opensource.org/licenses/MIT),
// at your option.

// Unless required by applicable law or agreed to in writing,
// this software is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
// specific language governing permissions and limitations under
// each license.

use serde_json::json;

/// Boilerplate JSON to use when building manifests for test cases.
pub(crate) fn manifest_json() -> String {
json!({
"vendor": "test",
"claim_generator_info": [
{
"name": "c2pa_test",
"version": "1.0.0"
}
],
"metadata": [
{
"dateTime": "1985-04-12T23:20:50.52Z",
"my_custom_metadata": "my custom metatdata value"
}
],
"title": "Test_Manifest",
"format": "image/tiff",
"instance_id": "1234",
"thumbnail": {
"format": "image/jpeg",
"identifier": "thumbnail.jpg"
},
"ingredients": [
{
"title": "Test",
"format": "image/jpeg",
"instance_id": "12345",
"relationship": "componentOf"
}
],
"assertions": [
{
"label": "org.test.assertion",
"data": "assertion"
}
]
})
.to_string()
}

pub(crate) fn parent_json() -> String {
json!({
"title": "Parent Test",
"format": "image/jpeg",
"instance_id": "12345",
"relationship": "parentOf"
})
.to_string()
}
3 changes: 3 additions & 0 deletions cawg_identity/src/tests/fixtures/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@

#![allow(unused)]

mod manifest_json;
pub(crate) use manifest_json::{manifest_json, parent_json};

mod naive_credential_holder;
pub(crate) use naive_credential_holder::{
NaiveAsyncCredentialHolder, NaiveCredentialHolder, NaiveSignatureVerifier,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions cawg_identity/src/tests/identity_assertion/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
// each license.

mod signer_payload;
mod validation_errors;
61 changes: 61 additions & 0 deletions cawg_identity/src/tests/identity_assertion/validation_errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2025 Adobe. All rights reserved.
// This file is licensed to you under the Apache License,
// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
// or the MIT license (http://opensource.org/licenses/MIT),
// at your option.

// Unless required by applicable law or agreed to in writing,
// this software is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
// implied. See the LICENSE-MIT and LICENSE-APACHE files for the
// specific language governing permissions and limitations under
// each license.

use std::io::Cursor;

use c2pa::Reader;
use c2pa_status_tracker::{LogKind, StatusTracker};
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test;

use crate::IdentityAssertion;

#[cfg_attr(not(target_arch = "wasm32"), tokio::test)]
#[cfg_attr(
all(target_arch = "wasm32", not(target_os = "wasi")),
wasm_bindgen_test
)]
#[cfg_attr(target_os = "wasi", wstd::test)]
async fn malformed_cbor() {
let format = "image/jpeg";
let test_image = include_bytes!("../fixtures/validation_errors/malformed_cbor.jpg");

let mut test_image = Cursor::new(test_image);

// Initial read with default `Reader` should pass without issues.
let reader = Reader::from_stream(format, &mut test_image).unwrap();
assert_eq!(reader.validation_status(), None);

// Re-parse with identity assertion code should find malformed CBOR error.
let mut status_tracker = StatusTracker::default();

let active_manifest = reader.active_manifest().unwrap();
let ia_results: Vec<Result<IdentityAssertion, c2pa::Error>> =
IdentityAssertion::from_manifest(active_manifest, &mut status_tracker).collect();

assert_eq!(ia_results.len(), 1);

let ia_err = ia_results[0].as_ref().unwrap_err();
assert_eq!(ia_err.to_string(), "could not decode assertion cawg.identity (version (no version), content type application/json): missing field `signer_payload`");

assert_eq!(status_tracker.logged_items().len(), 1);

let log = &status_tracker.logged_items()[0];
assert_eq!(log.kind, LogKind::Failure);
assert_eq!(log.label, "cawg.identity");
assert_eq!(log.description, "invalid CBOR");
assert_eq!(
log.validation_status.as_ref().unwrap().as_ref(),
"cawg.identity.cbor.invalid"
);
}
3 changes: 3 additions & 0 deletions sdk/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ pub enum Error {
#[error("could not find the assertion to redact")]
AssertionRedactionNotFound,

#[error("assertion-specific error: {0}")]
AssertionSpecificError(String),

#[error("bad parameter: {0}")]
BadParam(String),

Expand Down

0 comments on commit ef95c5f

Please sign in to comment.