Skip to content

Commit

Permalink
Trust support (#415)
Browse files Browse the repository at this point in the history
* Push to keep things moving

* Add ManifestStoreOptions to async bytes functions
ManifestStore::from_bytes_async()
ManifestStore::from_manifest_and_asset_bytes_async
Also some fmt/clippy fixes
Builds but unit tests do not run yet

* WASM build

* WASM fix

* Expose ManifestStoreOptions

* Fix missing anchors

* Fix misspelled var

* remove check that may be wrong

* remove issuer check

* switch to x509_parser because x509-certificate has issues

* Add support DER encoded EC signatures when validating trust lists

* Update Adobe trust root

* Small fixes for Wasm building (#354)

* Remove trust anchors from build, only leave the test certs

* Add ManifestStore::from_file_with_options

* Minor fixes

* Trust fixes

* Wasm compiler fixes

* Restored more tests

* EC sig fix

* Add ARW & NEF support

* Fix for wrong sig algoritm

* Support for allowed list

* Add Wasm compilation fixes for trust_support branch (#401)

* Fix wasm trust handler

* Fix reading lines inside PEM certificate blocks

* Wire in settings support
Remove feature flags covered by settings

* Build fixes
simplified check_trust

* Build fixes

* Test fixes

* Build fix

* another try to fix build issue

* Build fixes
Cleanup

* Fix preflight check

* Remove wrong cert from test anchors bundle

* Remove trust feature flag

* simplify manifest_store changes

* revert unintended change

* Remove ManifestStore changes
Update integration example to use loading settings from JSON

* Change feature flag setting

* Change more feature flags

* enhance trust pass through to support configuration of allowed_list and EKU config
Check signing cert before signing so that it gets checked independent of whether we validate after signing

* A little code cleanup

* Make sure ED25519 tests are disabled for WASM

* Remove Ed25519 from trust list until we can get it working in WASM

* Enable Ed25519 support

* Added debug logging for ed25519

* wasm build fix

* fix broken check

* Fixes for wasm

* Fix build failure

* Fix comment

* Code cleanup

* OCSP fix

---------

Co-authored-by: Gavin Peacock <gpeacock@adobe.com>
Co-authored-by: Dave Kozma <dkozma@adobe.com>
  • Loading branch information
3 people authored Mar 8, 2024
1 parent 9ccdb2b commit ca88432
Show file tree
Hide file tree
Showing 33 changed files with 2,462 additions and 400 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Cargo.lock

.DS_Store
.idea
.cargo/config.toml

.vscode

Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ The Rust library crate provides:
* `no_interleaved_io` forces fully-synchronous I/O; otherwise, the library uses threaded I/O for some operations to improve performance.
* `fetch_remote_manifests` enables the verification step to retrieve externally referenced manifest stores. External manifests are only fetched if there is no embedded manifest store and no locally adjacent .c2pa manifest store file of the same name.
* `json_schema` is used by `make schema` to produce a JSON schema document that represents the `ManifestStore` data structures.
* `fetch_ocsp_response` if the feature is enabled, during manifest validation if an OCSP response is not present in the manifest we will attempt a network call to fetch it. OCSP is used to check the revocation status of the manifest signing certificate.
* `psxxx_ocsp_stapling_experimental` this is an demonstration feature that will attempt to fetch the OCSP data from the OCSP responders listed in the manifest signing certificate. The response becomes part of the manifest and is used to prove the certificate was not revoked at the time of signing. This is only implemented for PS256, PS384 and PS512 signatures and is intended as a demonstration.


Expand Down
4 changes: 2 additions & 2 deletions sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ rustdoc-args = ["--cfg", "docsrs"]
[features]
default = []
add_thumbnails = ["image"]
fetch_ocsp_response = []
psxxx_ocsp_stapling_experimental = []
file_io = ["openssl_sign"]
serialize_thumbnails = []
Expand Down Expand Up @@ -110,7 +109,7 @@ thiserror = "1.0.40"
treeline = "0.1.0"
url = "2.2.2"
uuid = { version = "1.3.1", features = ["serde", "v4", "wasm-bindgen"] }
x509-parser = "0.15.0"
x509-parser = "0.15.1"
x509-certificate = "0.19.0"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
Expand All @@ -125,6 +124,7 @@ xmp_toolkit = { version = "1.7.1", optional = true }

[target.'cfg(target_arch = "wasm32")'.dependencies]
console_log = { version = "1.0.0", features = ["color"] }
ed25519-dalek = "2.1.1"
getrandom = { version = "0.2.7", features = ["js"] }
# We need to use the `inaccurate` flag here to ensure usage of the JavaScript Date API
# to handle certificate timestamp checking correctly.
Expand Down
17 changes: 14 additions & 3 deletions sdk/src/claim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ use crate::{
jumbf_io::{get_assetio_handler, get_assetio_handler_from_path},
salt::{DefaultSalt, SaltGenerator, NO_SALT},
status_tracker::{log_item, OneShotStatusTracker, StatusTracker},
trust_handler::TrustHandlerConfig,
utils::{
base64,
hash_utils::{hash_by_alg, vec_compare, verify_by_alg},
Expand Down Expand Up @@ -1018,10 +1019,11 @@ impl Claim {
/// Verify claim signature, assertion store and asset hashes
/// claim - claim to be verified
/// asset_bytes - reference to bytes of the asset
pub async fn verify_claim_async<'a>(
pub(crate) async fn verify_claim_async<'a>(
claim: &Claim,
asset_data: &mut ClaimAssetData<'_>,
is_provenance: bool,
th: &dyn TrustHandlerConfig,
validation_log: &mut impl StatusTracker,
) -> Result<()> {
// Parse COSE signed data (signature) and validate it.
Expand Down Expand Up @@ -1055,6 +1057,7 @@ impl Claim {
claim_data,
additional_bytes,
!is_provenance,
th,
validation_log,
)
.await;
Expand All @@ -1064,10 +1067,11 @@ impl Claim {
/// Verify claim signature, assertion store and asset hashes
/// claim - claim to be verified
/// asset_bytes - reference to bytes of the asset
pub fn verify_claim(
pub(crate) fn verify_claim(
claim: &Claim,
asset_data: &mut ClaimAssetData<'_>,
is_provenance: bool,
th: &dyn TrustHandlerConfig,
validation_log: &mut impl StatusTracker,
) -> Result<()> {
// Parse COSE signed data (signature) and validate it.
Expand Down Expand Up @@ -1096,7 +1100,14 @@ impl Claim {
return Err(Error::ClaimDecoding);
};

let verified = verify_cose(sig, data, &additional_bytes, !is_provenance, validation_log);
let verified = verify_cose(
sig,
data,
&additional_bytes,
!is_provenance,
th,
validation_log,
);

Claim::verify_internal(claim, asset_data, is_provenance, verified, validation_log)
}
Expand Down
40 changes: 37 additions & 3 deletions sdk/src/cose_sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

#![deny(missing_docs)]

use std::io::Cursor;

use async_generic::async_generic;
use ciborium::value::Value;
use coset::{
Expand All @@ -25,11 +27,13 @@ use coset::{

use crate::{
claim::Claim,
cose_validator::verify_cose,
cose_validator::{check_cert, verify_cose},
settings::get_settings_value,
status_tracker::OneShotStatusTracker,
time_stamp::{
cose_timestamp_countersign, cose_timestamp_countersign_async, make_cose_timestamp,
},
trust_handler::TrustHandlerConfig,
AsyncSigner, Error, Result, Signer, SigningAlg,
};

Expand Down Expand Up @@ -70,8 +74,16 @@ pub fn sign_claim(claim_bytes: &[u8], signer: &dyn Signer, box_size: usize) -> R
Ok(signed_bytes) => {
// Sanity check: Ensure that this signature is valid.
let mut cose_log = OneShotStatusTracker::new();

match verify_cose(&signed_bytes, claim_bytes, b"", false, &mut cose_log) {
let passthrough_tb = crate::trust_handler::TrustPassThrough::new();

match verify_cose(
&signed_bytes,
claim_bytes,
b"",
true,
&passthrough_tb,
&mut cose_log,
) {
Ok(r) => {
if !r.validated {
Err(Error::CoseSignature)
Expand All @@ -86,6 +98,20 @@ pub fn sign_claim(claim_bytes: &[u8], signer: &dyn Signer, box_size: usize) -> R
}
}

fn signing_cert_valid(signing_cert: &[u8]) -> Result<()> {
// make sure signer certs are valid
let mut cose_log = OneShotStatusTracker::default();
let mut passthrough_tb = crate::trust_handler::TrustPassThrough::new();

// allow user EKUs through this check if configured
if let Ok(Some(trust_config)) = get_settings_value::<Option<String>>("trust.trust_config") {
let mut reader = Cursor::new(trust_config.as_bytes());
passthrough_tb.load_configuration(&mut reader)?;
}

check_cert(signing_cert, &passthrough_tb, &mut cose_log, None)
}

/// Returns signed Cose_Sign1 bytes for `data`.
/// The Cose_Sign1 will be signed with the algorithm from [`Signer`].
#[async_generic(async_signature(
Expand Down Expand Up @@ -116,6 +142,14 @@ pub(crate) fn cose_sign(signer: &dyn Signer, data: &[u8], box_size: usize) -> Re
string.
*/

// make sure the signing cert is valid
let certs = signer.certs()?;
if let Some(signing_cert) = certs.first() {
signing_cert_valid(signing_cert)?;
} else {
return Err(Error::CoseNoCerts);
}

let alg = signer.alg();

// build complete header
Expand Down
Loading

0 comments on commit ca88432

Please sign in to comment.