diff --git a/cli/tests/fixtures/trust/cawg_sign_settings.toml b/cli/tests/fixtures/trust/cawg_sign_settings.toml index c76cf6a32..b567cb5ba 100644 --- a/cli/tests/fixtures/trust/cawg_sign_settings.toml +++ b/cli/tests/fixtures/trust/cawg_sign_settings.toml @@ -1,8 +1,7 @@ # c2pa-rs Configuration File # Version information. -version_major = 1 -version_minor = 0 +version = 1 # Trust settings for certificate validation. # [trust] @@ -220,13 +219,13 @@ xPd7wFhjRZHfuWb2cs63xjAGjQ== """ # String to trust configuration. trust_config = """ -//id-kp-emailProtection +//id-kp-emailProtection 1.3.6.1.5.5.7.3.4 -//id-kp-documentSigning +//id-kp-documentSigning 1.3.6.1.5.5.7.3.36 -//id-kp-timeStamping +//id-kp-timeStamping 1.3.6.1.5.5.7.3.8 -//id-kp-OCSPSigning +//id-kp-OCSPSigning 1.3.6.1.5.5.7.3.9 // MS C2PA Signing 1.3.6.1.4.1.311.76.59.1.9 @@ -418,8 +417,8 @@ name = "c2pa-rs testing" version = "1.0.0" # The operating system the claim generator is running on. #operating_system.name = "macOS" -# Or if the name isn't specified, it can be inferred automatically. -operating_system.infer = true +# Or specify "auto" to infer the operating system automatically. +operating_system = "auto" # Arbitrary fields can also be defined. # # By default, the SDK adds a field "org.cai.c2pa_rs" with the value diff --git a/cli/tests/fixtures/trust/cawg_test_settings.toml b/cli/tests/fixtures/trust/cawg_test_settings.toml index 7eeccc45b..3d7000704 100644 --- a/cli/tests/fixtures/trust/cawg_test_settings.toml +++ b/cli/tests/fixtures/trust/cawg_test_settings.toml @@ -3,16 +3,18 @@ trusted = true [trust] trust_config = """ -//id-kp-emailProtection +//id-kp-emailProtection 1.3.6.1.5.5.7.3.4 -//id-kp-documentSigning +//id-kp-documentSigning 1.3.6.1.5.5.7.3.36 -//id-kp-timeStamping +//id-kp-timeStamping 1.3.6.1.5.5.7.3.8 -//id-kp-OCSPSigning +//id-kp-OCSPSigning 1.3.6.1.5.5.7.3.9 // MS C2PA Signing 1.3.6.1.4.1.311.76.59.1.9 +// c2pa-kp-claimSigning +1.3.6.1.4.1.62558.2.1 """ trust_anchors = """ -----BEGIN CERTIFICATE----- @@ -227,9 +229,9 @@ xPd7wFhjRZHfuWb2cs63xjAGjQ== [cawg_trust] trust_config = """ -//id-kp-emailProtection +//id-kp-emailProtection 1.3.6.1.5.5.7.3.4 -//id-kp-documentSigning +//id-kp-documentSigning 1.3.6.1.5.5.7.3.36 """ trust_anchors = """ diff --git a/sdk/examples/c2pa.toml b/sdk/examples/c2pa.toml index 34a98b68d..8636388fa 100644 --- a/sdk/examples/c2pa.toml +++ b/sdk/examples/c2pa.toml @@ -1,8 +1,7 @@ # c2pa-rs Configuration File # Version information. -version_major = 1 -version_minor = 0 +version = 1 # # Trust settings for certificate validation. # [trust] @@ -66,9 +65,8 @@ name = "My Service" # A human readable string of the product's version. version = "1.0.0" # The operating system the claim generator is running on. -operating_system.name = "macOS" -# Or if the name isn't specified, it can be inferred automatically. -operating_system.infer = true +# Or specify "auto" to infer the operating system automatically. +operating_system = "macOS" # Arbitrary fields can also be defined. # # By default, the SDK adds a field "org.cai.c2pa_rs" with the value diff --git a/sdk/src/settings/builder.rs b/sdk/src/settings/builder.rs index 0c582d284..60c7d2da9 100644 --- a/sdk/src/settings/builder.rs +++ b/sdk/src/settings/builder.rs @@ -31,9 +31,10 @@ use crate::{ /// /// These formats are a combination of types supported in [image-rs](https://docs.rs/image/latest/image/enum.ImageFormat.html) /// and types defined by the [IANA registry media type](https://www.iana.org/assignments/media-types/media-types.xhtml) (as defined in the spec). +#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))] #[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize)] #[serde(rename_all = "lowercase")] -pub(crate) enum ThumbnailFormat { +pub enum ThumbnailFormat { /// An image in PNG format. Png, /// An image in JPEG format. @@ -46,9 +47,10 @@ pub(crate) enum ThumbnailFormat { Tiff, } /// Quality of the thumbnail. +#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))] #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] #[serde(rename_all = "lowercase")] -pub(crate) enum ThumbnailQuality { +pub enum ThumbnailQuality { /// Low quality. Low, /// Medium quality. @@ -58,23 +60,36 @@ pub(crate) enum ThumbnailQuality { } /// Settings for controlling automatic thumbnail generation. +#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -pub(crate) struct ThumbnailSettings { +pub struct ThumbnailSettings { /// Whether or not to automatically generate thumbnails. + /// + /// The default value is true. + /// + ///
+ /// This setting is only applicable if the crate is compiled with the `add_thumbnails` feature. + ///
pub enabled: bool, /// Whether to ignore thumbnail generation errors. /// /// This may occur, for instance, if the thumbnail media type or color layout isn't /// supported. + /// + /// The default value is true. pub ignore_errors: bool, /// The size of the longest edge of the thumbnail. /// /// This function will resize the input to preserve aspect ratio. + /// + /// The default value is 1024. pub long_edge: u32, /// Format of the thumbnail. /// /// If this field isn't specified, the thumbnail format will correspond to the /// input format. + /// + /// The default value is None. #[serde(skip_serializing_if = "Option::is_none")] pub format: Option, /// Whether or not to prefer a smaller sized media format for the thumbnail. @@ -85,11 +100,15 @@ pub(crate) struct ThumbnailSettings { /// /// For instance, if the source input type is a PNG, but it doesn't have an alpha channel, /// the image will be converted to a JPEG of smaller size. + /// + /// The default value is true. pub prefer_smallest_format: bool, /// The output quality of the thumbnail. /// /// This setting contains sensible defaults for things like quality, compression, and /// algorithms for various formats. + /// + /// The default value is [`ThumbnailQuality::Medium`]. pub quality: ThumbnailQuality, } @@ -118,9 +137,9 @@ impl SettingsValidate for ThumbnailSettings { } /// Settings for the auto actions (e.g. created, opened, placed). -#[allow(unused)] +#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -pub(crate) struct AutoActionSettings { +pub struct AutoActionSettings { /// Whether to enable this auto action or not. pub enabled: bool, /// The default source type for the auto action. @@ -128,31 +147,33 @@ pub(crate) struct AutoActionSettings { pub source_type: Option, } -/// Settings for how to specify the claim generator info's operating system. -#[allow(unused)] +#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -pub(crate) struct ClaimGeneratorInfoOSSettings { - /// Whether or not to infer the operating system. - pub infer: bool, +#[serde(untagged, rename_all = "lowercase")] +pub enum ClaimGeneratorInfoOperatingSystem { + /// Whether or not to automatically infer the operating system. + /// + /// This option will attempt to following the [LLVM "triples"] conventions. For more information, + /// see [`ClaimGeneratorInfoOperatingSystem::Other`]. + /// + /// [LLVM "triples"]: https://clang.llvm.org/docs/CrossCompilation.html#target-triple + Auto, /// The name of the operating system. /// - /// Note this field overrides [ClaimGeneratorInfoOSSettings::infer]. - pub name: Option, -} - -impl Default for ClaimGeneratorInfoOSSettings { - fn default() -> Self { - Self { - infer: true, - name: None, - } - } + /// It is recommended to follow the [LLVM "triples"] conventions to define the operating system, + /// with the format `---`. For instance: + /// - `x86_64-unknown-linux-gnu` + /// - `x86_64-pc-windows-msvc` + /// - `arm64-apple-darwin` + /// + /// [LLVM "triples"]: https://clang.llvm.org/docs/CrossCompilation.html#target-triple + Other(String), } /// Settings for the claim generator info. -#[allow(unused)] +#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -pub(crate) struct ClaimGeneratorInfoSettings { +pub struct ClaimGeneratorInfoSettings { /// A human readable string naming the claim_generator. pub name: String, /// A human readable string of the product's version. @@ -160,13 +181,13 @@ pub(crate) struct ClaimGeneratorInfoSettings { pub version: Option, /// Reference to an icon. #[serde(skip_serializing_if = "Option::is_none")] - pub icon: Option, + pub(crate) icon: Option, /// Settings for the claim generator info's operating system field. #[serde(skip_serializing_if = "Option::is_none")] - pub operating_system: Option, + pub operating_system: Option, /// Any other values that are not part of the standard. #[serde(flatten)] - pub other: HashMap, + pub other: HashMap, } impl TryFrom for ClaimGeneratorInfo { @@ -178,11 +199,12 @@ impl TryFrom for ClaimGeneratorInfo { version: value.version, icon: value.icon.map(UriOrResource::ResourceRef), operating_system: { - let os = value.operating_system.unwrap_or_default(); - match os.infer { - true => Some(consts::OS.to_owned()), - false => os.name, - } + value.operating_system.map(|os| match os { + ClaimGeneratorInfoOperatingSystem::Auto => { + format!("{}-unknown-{}", consts::ARCH, consts::OS) + } + ClaimGeneratorInfoOperatingSystem::Other(name) => name, + }) }, other: value .other @@ -198,6 +220,7 @@ impl TryFrom for ClaimGeneratorInfo { } /// Settings for an action template. +#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] pub(crate) struct ActionTemplateSettings { /// The label associated with this action. See ([c2pa_action][crate::assertions::actions::c2pa_action]). @@ -221,7 +244,7 @@ pub(crate) struct ActionTemplateSettings { pub description: Option, /// Additional parameters for the template #[serde(skip_serializing_if = "Option::is_none")] - pub template_parameters: Option>, + pub template_parameters: Option>, } impl TryFrom for ActionTemplate { @@ -256,7 +279,6 @@ impl TryFrom for ActionTemplate { } /// Settings for an action. -#[allow(unused)] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] pub(crate) struct ActionSettings { /// The label associated with this action. See ([`c2pa_action`]). @@ -323,34 +345,33 @@ impl TryFrom for Action { /// /// The reason this setting exists only for an [Actions][crate::assertions::Actions] assertion /// is because of its mandations and reusable fields. -#[allow(unused)] +#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -pub(crate) struct ActionsSettings { +pub struct ActionsSettings { /// Whether or not to set the [Actions::all_actions_included][crate::assertions::Actions::all_actions_included] /// field. #[serde(skip_serializing_if = "Option::is_none")] pub all_actions_included: Option, /// Templates to be added to the [Actions::templates][crate::assertions::Actions::templates] field. #[serde(skip_serializing_if = "Option::is_none")] - pub templates: Option>, - // TODO: should we define a new struct for "Action" too, like ActionTemplateSettings? + pub(crate) templates: Option>, /// Actions to be added to the [Actions::actions][crate::assertions::Actions::actions] field. - #[serde(skip_serializing_if = "Option::is_none")] - pub actions: Option>, - /// Whether to automatically generate a c2pa.created [Action][crate::assertions::Action] - /// assertion or error that it doesn't already exist. + // TODO: ActionSettings indirectly depends on ActionParameters which contains a serde_cbor::Value and + // schemars can't generate a schema for cbor values. It also doesn't feel right to change our API for + // the sake of json schemas. + #[cfg_attr(feature = "json_schema", schemars(skip))] + pub(crate) actions: Option>, + /// Whether to automatically generate a c2pa.created [Action] assertion or error that it doesn't already exist. /// /// For more information about the mandatory conditions for a c2pa.created action assertion, see here: /// pub auto_created_action: AutoActionSettings, - /// Whether to automatically generate a c2pa.opened [Action][crate::assertions::Action] - /// assertion or error that it doesn't already exist. + /// Whether to automatically generate a c2pa.opened [Action] assertion or error that it doesn't already exist. /// /// For more information about the mandatory conditions for a c2pa.opened action assertion, see here: /// pub auto_opened_action: AutoActionSettings, - /// Whether to automatically generate a c2pa.placed [Action][crate::assertions::Action] - /// assertion or error that it doesn't already exist. + /// Whether to automatically generate a c2pa.placed [Action] assertion or error that it doesn't already exist. /// /// For more information about the mandatory conditions for a c2pa.placed action assertion, see: /// @@ -390,9 +411,9 @@ impl SettingsValidate for ActionsSettings { // TODO: do more validation on URL fields, cert fields, etc. /// Settings for the [Builder][crate::Builder]. -#[allow(unused)] +#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Default)] -pub(crate) struct BuilderSettings { +pub struct BuilderSettings { /// Claim generator info that is automatically added to the builder. /// /// Note that this information will prepend any claim generator info @@ -405,18 +426,38 @@ pub(crate) struct BuilderSettings { /// /// For more information on the reasoning behind this field see [ActionsSettings]. pub actions: ActionsSettings, - - // Certificate statuses will be fetched for either all the manifest labels, or just the active manifest. - pub certificate_status_fetch: Option, - - // Whether or not existing OCSP responses should be overridden by new values. - pub certificate_status_should_override: Option, + // TODO: this setting affects fetching and generation of the assertion; needs clarification + /// Whether to create [`CertificateStatus`] assertions for manifests to store certificate revocation + /// status. The assertion can be fetched for the active manifest or for all manifests (including + /// ingredients). + /// + /// The default is to not fetch them at all. + /// + /// See more information in the spec here: + /// + /// + /// [`CertificateStatus`]: crate::assertions::CertificateStatus + pub(crate) certificate_status_fetch: Option, + // TODO: this setting affects fetching and generation of the assertion; needs clarification + /// Whether to only use [`CertificateStatus`] assertions to check certificate revocation status. If there + /// is a stapled OCSP in the COSE claim of the manifest, it will be ignored. If [`Verify::ocsp_fetch`] is + /// enabled, it will also be ignored. + /// + /// The default value is false. + /// + /// [`CertificateStatus`]: crate::assertions::CertificateStatus + /// [`Verify::ocsp_fetch`]: crate::settings::Verify::ocsp_fetch + pub(crate) certificate_status_should_override: Option, } +/// The scope of which manifests to fetch for OCSP. +#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))] #[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize)] #[serde(rename_all = "lowercase")] -pub(crate) enum OcspFetch { +pub(crate) enum OcspFetchScope { + /// Fetch OCSP for all manifests. All, + /// Fetch OCSP for the active manifest only. Active, } diff --git a/sdk/src/settings/mod.rs b/sdk/src/settings/mod.rs index 5c605675c..7d664b60c 100644 --- a/sdk/src/settings/mod.rs +++ b/sdk/src/settings/mod.rs @@ -11,8 +11,10 @@ // specific language governing permissions and limitations under // each license. -pub(crate) mod builder; -pub(crate) mod signer; +/// Settings for configuring the [`Builder`][crate::Builder]. +pub mod builder; +/// Settings for configuring the [`Settings::signer`]. +pub mod signer; #[cfg(feature = "file_io")] use std::path::Path; @@ -27,6 +29,8 @@ use signer::SignerSettings; use crate::{crypto::base64, settings::builder::BuilderSettings, Error, Result, Signer}; +const VERSION: u32 = 1; + thread_local!( static SETTINGS: RefCell = RefCell::new(Config::try_from(&Settings::default()).unwrap_or_default()); @@ -40,15 +44,24 @@ pub(crate) trait SettingsValidate { } } -// Settings for trust list feature +/// Settings to configure the trust list. +#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -#[allow(unused)] -pub(crate) struct Trust { - pub(crate) verify_trust_list: bool, - pub(crate) user_anchors: Option, - pub(crate) trust_anchors: Option, - pub(crate) trust_config: Option, - pub(crate) allowed_list: Option, +pub struct Trust { + /// The default value is true. + pub verify_trust_list: bool, + /// List of additional user-provided trust anchor root certificates as a PEM bundle. + pub user_anchors: Option, + /// List of default trust anchor root certificates as a PEM bundle. + /// + /// Normally this option contains the official C2PA-recognized trust anchors found here: + /// + pub trust_anchors: Option, + /// List of allowed extended key usage (EKU) object identifiers (OID) that + /// certificates must have. + pub trust_config: Option, + /// List of explicitly allowed certificates as a PEM bundle. + pub allowed_list: Option, } impl Trust { @@ -160,42 +173,49 @@ impl SettingsValidate for Trust { } } -// TODO: all of these settings aren't implemented -// Settings for core C2PA-RS functionality +/// Settings to configure core features. +#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -#[allow(unused)] -pub(crate) struct Core { - debug: bool, - hash_alg: String, - #[serde(skip_serializing_if = "Option::is_none")] - soft_hash_alg: Option, - salt_jumbf_boxes: bool, - prefer_box_hash: bool, - pub(crate) merkle_tree_chunk_size_in_kb: Option, - pub(crate) merkle_tree_max_proofs: usize, - compress_manifests: bool, - #[serde(skip_serializing_if = "Option::is_none")] - max_memory_usage: Option, - pub(crate) backing_store_memory_threshold_in_mb: usize, - // TODO: pending https://github.com/contentauth/c2pa-rs/pull/1180 - // prefer_update_manifests: bool, - pub(crate) decode_identity_assertions: bool, +pub struct Core { + /// Size of the [`BmffHash`] merkle tree chunks in kilobytes. + /// + /// This option is associated with the [`MerkleMap::fixed_block_size`] field. + /// + /// See more information in the spec here: + /// + /// + /// [`MerkleMap::fixed_block_size`]: crate::assertions::MerkleMap::fixed_block_size + /// [`BmffHash`]: crate::assertions::BmffHash + pub merkle_tree_chunk_size_in_kb: Option, + /// Maximum number of proofs when validating or writing a [`BmffHash`] merkle tree. + /// + /// This option defaults to 5. + /// + /// See more information in the spec here: + /// + /// + /// [`BmffHash`]: crate::assertions::BmffHash + pub merkle_tree_max_proofs: usize, + /// Maximum amount of data in megabytes that will be loaded into memory before + /// being stored in temporary files on the disk. + /// + /// This option defaults to 512MB and can result in noticeable performance improvements. + pub backing_store_memory_threshold_in_mb: usize, + /// Whether to decode CAWG [`IdentityAssertion`]s during reading in the [`Reader`]. + /// + /// This option defaults to true. + /// + /// [`IdentityAssertion`]: crate::identity::IdentityAssertion + /// [`Reader`]: crate::Reader + pub decode_identity_assertions: bool, } impl Default for Core { fn default() -> Self { Self { - debug: false, - hash_alg: "sha256".into(), - soft_hash_alg: None, - salt_jumbf_boxes: true, - prefer_box_hash: false, merkle_tree_chunk_size_in_kb: None, merkle_tree_max_proofs: 5, - compress_manifests: true, - max_memory_usage: None, backing_store_memory_threshold_in_mb: 512, - // prefer_update_manifests: true, decode_identity_assertions: true, } } @@ -203,26 +223,95 @@ impl Default for Core { impl SettingsValidate for Core { fn validate(&self) -> Result<()> { - match self.hash_alg.as_str() { - "sha256" | "sha384" | "sha512" => Ok(()), - _ => Err(Error::UnsupportedType), - } + Ok(()) } } -// Settings for verification options +/// Settings to configure the verification process. +#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] -#[allow(unused)] -pub(crate) struct Verify { - pub(crate) verify_after_reading: bool, - pub(crate) verify_after_sign: bool, - pub(crate) verify_trust: bool, - pub(crate) verify_timestamp_trust: bool, - pub(crate) ocsp_fetch: bool, - pub(crate) remote_manifest_fetch: bool, +pub struct Verify { + /// Whether to verify the manifest after reading in the [`Reader`]. + /// + /// The default value is true. + /// + ///
+ /// Disabling validation can improve reading performance, BUT it carries the risk of reading an invalid + /// manifest. + ///
+ /// + /// [`Reader`]: crate::Reader + pub verify_after_reading: bool, + /// Whether to verify the manifest after signing in the [`Builder`]. + /// + /// The default value is true. + /// + ///
+ /// Disabling validation can improve signing performance, BUT it carries the risk of signing an invalid + /// manifest. + ///
+ /// + /// [`Builder`]: crate::Builder + pub verify_after_sign: bool, + /// Whether to verify certificates against the trust lists specified in [`Trust`]. To configure + /// timestamp certificate verification, see [`Verify::verify_timestamp_trust`]. + /// + /// The default value is true. + /// + ///
+ /// Verifying trust is REQUIRED by the C2PA spec. This option should only be used for development or testing. + ///
+ pub verify_trust: bool, + /// Whether to verify the timestamp certificates against the trust lists specified in [`Trust`]. + /// + /// The default value is true. + /// + ///
+ /// Verifying timestamp trust is REQUIRED by the C2PA spec. This option should only be used for development or testing. + ///
+ pub verify_timestamp_trust: bool, + /// Whether to fetch the certificates OCSP status during validation. + /// + /// Revocation status is checked in the following order: + /// 1. The OCSP staple stored in the COSE claim of the manifest + /// 2. Otherwise if `ocsp_fetch` is enabled, it fetches a new OCSP status + /// 3. Otherwise if `ocsp_fetch` is disabled, it checks [`CertificateStatus`] assertions + /// + /// The default value is false. + /// + /// [`CertificateStatus`]: crate::assertions::CertificateStatus + pub ocsp_fetch: bool, + /// Whether to fetch remote manifests in the following scenarios: + /// - Constructing a [`Reader`] + /// - Constructing an [`Ingredient`] + /// - Adding an [`Ingredient`] to the [`Builder`] + /// + /// The default value is true. + /// + ///
+ /// This setting is only applicable if the crate is compiled with the `fetch_remote_manifests` feature. + ///
+ /// + /// [`Reader`]: crate::Reader + /// [`Ingredient`]: crate::Ingredient + /// [`Builder`]: crate::Builder + pub remote_manifest_fetch: bool, + /// Whether to verify ingredient certificates against the trust lists specific in [`Trust`]. + /// + /// The default value is true. pub(crate) check_ingredient_trust: bool, + /// Whether to skip ingredient conflict resolution when multiple ingredients have the same + /// manifest identifier. This settings is only applicable for C2PA v2 validation. + /// + /// The default value is false. + /// + /// See more information in the spec here: + /// pub(crate) skip_ingredient_conflict_resolution: bool, - pub(crate) strict_v1_validation: bool, + /// Whether to do strictly C2PA v1 validation or otherwise the latest validation. + /// + /// The default value is false. + pub strict_v1_validation: bool, } impl Default for Verify { @@ -243,29 +332,35 @@ impl Default for Verify { impl SettingsValidate for Verify {} -const MAJOR_VERSION: usize = 1; -const MINOR_VERSION: usize = 0; - /// Settings for configuring all aspects of c2pa-rs. /// /// [Settings::default] will be set thread-locally by default. Any settings set via /// [Settings::from_toml] or [Settings::from_file] will also be thread-local. +#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))] #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] -#[allow(unused)] pub struct Settings { - version_major: usize, - version_minor: usize, + /// Version of the configuration. + pub version: u32, // TODO (https://github.com/contentauth/c2pa-rs/issues/1314): // Rename to c2pa_trust? Discuss possibly breaking change. - pub(crate) trust: Trust, - pub(crate) cawg_trust: Trust, - pub(crate) core: Core, - pub(crate) verify: Verify, - pub(crate) builder: BuilderSettings, + /// Settings for configuring the C2PA trust lists. + pub trust: Trust, + /// Settings for configuring the CAWG trust lists. + pub cawg_trust: Trust, + /// Settings for configuring core features. + pub core: Core, + /// Settings for configuring verification. + pub verify: Verify, + /// Settings for configuring the [`Builder`]. + /// + /// [`Builder`]: crate::Builder + pub builder: BuilderSettings, + /// Settings for configuring the base C2PA signer, accessible via [`Settings::signer`]. #[serde(skip_serializing_if = "Option::is_none")] - signer: Option, + pub signer: Option, + /// Settings for configuring the CAWG x509 signer, accessible via [`Settings::signer`]. #[serde(skip_serializing_if = "Option::is_none")] - cawg_x509_signer: Option, + pub cawg_x509_signer: Option, } impl Settings { @@ -431,8 +526,7 @@ impl Settings { impl Default for Settings { fn default() -> Self { Settings { - version_major: MAJOR_VERSION, - version_minor: MINOR_VERSION, + version: VERSION, trust: Default::default(), cawg_trust: Default::default(), core: Default::default(), @@ -446,7 +540,7 @@ impl Default for Settings { impl SettingsValidate for Settings { fn validate(&self) -> Result<()> { - if self.version_major > MAJOR_VERSION { + if self.version > VERSION { return Err(Error::VersionCompatibility( "settings version too new".into(), )); @@ -544,10 +638,6 @@ pub mod tests { #[test] fn test_get_val_by_direct_path() { // you can do this for all values but if these sanity checks pass they all should if the path is correct - assert_eq!( - get_settings_value::("core.hash_alg").unwrap(), - Core::default().hash_alg - ); assert_eq!( get_settings_value::("builder.thumbnail.enabled").unwrap(), BuilderSettings::default().thumbnail.enabled @@ -573,13 +663,11 @@ pub mod tests { ); // test implicit deserialization - let hash_alg: String = get_settings_value("core.hash_alg").unwrap(); let remote_manifest_fetch: bool = get_settings_value("verify.remote_manifest_fetch").unwrap(); let auto_thumbnail: bool = get_settings_value("builder.thumbnail.enabled").unwrap(); let user_anchors: Option = get_settings_value("trust.user_anchors").unwrap(); - assert_eq!(hash_alg, Core::default().hash_alg); assert_eq!( remote_manifest_fetch, Verify::default().remote_manifest_fetch @@ -606,7 +694,7 @@ pub mod tests { let ts = include_bytes!("../../tests/fixtures/certs/trust/test_cert_root_bundle.pem"); // test updating values - Settings::set_value("core.hash_alg", "sha512").unwrap(); + Settings::set_value("core.merkle_tree_chunk_size_in_kb", 10).unwrap(); Settings::set_value("verify.remote_manifest_fetch", false).unwrap(); Settings::set_value("builder.thumbnail.enabled", false).unwrap(); Settings::set_value( @@ -616,8 +704,8 @@ pub mod tests { .unwrap(); assert_eq!( - get_settings_value::("core.hash_alg").unwrap(), - "sha512" + get_settings_value::("core.merkle_tree_chunk_size_in_kb").unwrap(), + 10 ); assert!(!get_settings_value::("verify.remote_manifest_fetch").unwrap()); assert!(!get_settings_value::("builder.thumbnail.enabled").unwrap()); @@ -713,11 +801,6 @@ pub mod tests { BuilderSettings::default().thumbnail.enabled ); - assert_eq!( - get_settings_value::("core.salt_jumbf_boxes").unwrap(), - Core::default().salt_jumbf_boxes - ); - reset_default_settings().unwrap(); } @@ -725,9 +808,9 @@ pub mod tests { fn test_bad_setting() { let modified_core = toml::toml! { [core] - debug = true - hash_alg = "sha1000000" - max_memory_usage = 123456 + merkle_tree_chunk_size_in_kb = true + merkle_tree_max_proofs = "sha1000000" + backing_store_memory_threshold_in_mb = -123456 } .to_string(); @@ -763,8 +846,7 @@ pub mod tests { #[test] fn test_all_setting() { let all_settings = toml::toml! { - version_major = 1 - version_minor = 0 + version = 1 [trust] diff --git a/sdk/src/settings/signer.rs b/sdk/src/settings/signer.rs index 9857130e4..4a83059bf 100644 --- a/sdk/src/settings/signer.rs +++ b/sdk/src/settings/signer.rs @@ -27,11 +27,11 @@ use crate::{ /// A [`Signer`] can be obtained by calling the [`signer()`] function. /// /// [`Signer`]: crate::Signer -/// [`signer()`]: Builder::signer -#[allow(unused)] +/// [`signer()`]: crate::settings::Settings::signer +#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))] #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] #[serde(rename_all = "lowercase")] -pub(crate) enum SignerSettings { +pub enum SignerSettings { /// A signer configured locally. Local { // Algorithm to use for signing. @@ -60,9 +60,9 @@ pub(crate) enum SignerSettings { impl SignerSettings { // TODO: add async signer - /// Returns the constructed signer from the [BuilderSettings::signer] field. + /// Returns the constructed signer from the [Settings::signer] field. /// - /// If the signer settings aren't specified, this function will return [Error::MissingSignerSettings][crate::Error::MissingSignerSettings]. + /// If the signer settings aren't specified, this function will return [Error::MissingSignerSettings]. pub fn signer() -> Result> { let c2pa_signer = Self::c2pa_signer()?; diff --git a/sdk/src/store.rs b/sdk/src/store.rs index c4d8489ba..5ad0128ec 100644 --- a/sdk/src/store.rs +++ b/sdk/src/store.rs @@ -72,7 +72,7 @@ use crate::{ log_item, manifest_store_report::ManifestStoreReport, salt::DefaultSalt, - settings::{builder::OcspFetch, Settings}, + settings::{builder::OcspFetchScope, Settings}, status_tracker::{ErrorBehavior, StatusTracker}, utils::{ hash_utils::HashRange, @@ -648,8 +648,8 @@ impl Store { pub fn get_manifest_labels_for_ocsp(&self, settings: &Settings) -> Vec { let labels = match settings.builder.certificate_status_fetch { Some(ocsp_fetch) => match ocsp_fetch { - OcspFetch::All => self.claims.clone(), - OcspFetch::Active => { + OcspFetchScope::All => self.claims.clone(), + OcspFetchScope::Active => { if let Some(active_label) = self.provenance_label() { vec![active_label] } else { diff --git a/sdk/tests/fixtures/certs/trust/test_settings.toml b/sdk/tests/fixtures/certs/trust/test_settings.toml index a666c4db7..8b1607092 100644 --- a/sdk/tests/fixtures/certs/trust/test_settings.toml +++ b/sdk/tests/fixtures/certs/trust/test_settings.toml @@ -3,16 +3,18 @@ trusted = true [trust] trust_config = """ -//id-kp-emailProtection +//id-kp-emailProtection 1.3.6.1.5.5.7.3.4 -//id-kp-documentSigning +//id-kp-documentSigning 1.3.6.1.5.5.7.3.36 -//id-kp-timeStamping +//id-kp-timeStamping 1.3.6.1.5.5.7.3.8 -//id-kp-OCSPSigning +//id-kp-OCSPSigning 1.3.6.1.5.5.7.3.9 // MS C2PA Signing 1.3.6.1.4.1.311.76.59.1.9 +// c2pa-kp-claimSigning +1.3.6.1.4.1.62558.2.1 """ trust_anchors = """ -----BEGIN CERTIFICATE----- diff --git a/sdk/tests/fixtures/test_settings.toml b/sdk/tests/fixtures/test_settings.toml index 9d987d66c..373abfad2 100644 --- a/sdk/tests/fixtures/test_settings.toml +++ b/sdk/tests/fixtures/test_settings.toml @@ -1,8 +1,7 @@ # c2pa-rs Configuration File # Version information. -version_major = 1 -version_minor = 0 +version = 1 # Trust settings for certificate validation. # [trust] @@ -222,16 +221,18 @@ xPd7wFhjRZHfuWb2cs63xjAGjQ== """ # String to trust configuration. trust_config = """ -//id-kp-emailProtection +//id-kp-emailProtection 1.3.6.1.5.5.7.3.4 -//id-kp-documentSigning +//id-kp-documentSigning 1.3.6.1.5.5.7.3.36 -//id-kp-timeStamping +//id-kp-timeStamping 1.3.6.1.5.5.7.3.8 -//id-kp-OCSPSigning +//id-kp-OCSPSigning 1.3.6.1.5.5.7.3.9 // MS C2PA Signing 1.3.6.1.4.1.311.76.59.1.9 +// c2pa-kp-claimSigning +1.3.6.1.4.1.62558.2.1 """ # # Path to allowed certificate list (PEM format). @@ -420,8 +421,8 @@ name = "c2pa-rs testing" version = "1.0.0" # The operating system the claim generator is running on. #operating_system.name = "macOS" -# Or if the name isn't specified, it can be inferred automatically. -operating_system.infer = true +# Or specify "auto" to infer the operating system automatically. +operating_system = "auto" # Arbitrary fields can also be defined. # # By default, the SDK adds a field "org.cai.c2pa_rs" with the value diff --git a/sdk/tests/fixtures/test_settings_with_cawg_signing.toml b/sdk/tests/fixtures/test_settings_with_cawg_signing.toml index c77950e02..02e1c0e2b 100644 --- a/sdk/tests/fixtures/test_settings_with_cawg_signing.toml +++ b/sdk/tests/fixtures/test_settings_with_cawg_signing.toml @@ -1,8 +1,7 @@ # c2pa-rs Configuration File # Version information. -version_major = 1 -version_minor = 0 +version = 1 # Trust settings for certificate validation. # [trust] @@ -220,16 +219,18 @@ xPd7wFhjRZHfuWb2cs63xjAGjQ== """ # String to trust configuration. trust_config = """ -//id-kp-emailProtection +//id-kp-emailProtection 1.3.6.1.5.5.7.3.4 -//id-kp-documentSigning +//id-kp-documentSigning 1.3.6.1.5.5.7.3.36 -//id-kp-timeStamping +//id-kp-timeStamping 1.3.6.1.5.5.7.3.8 -//id-kp-OCSPSigning +//id-kp-OCSPSigning 1.3.6.1.5.5.7.3.9 // MS C2PA Signing 1.3.6.1.4.1.311.76.59.1.9 +// c2pa-kp-claimSigning +1.3.6.1.4.1.62558.2.1 """ # # Path to allowed certificate list (PEM format). @@ -418,8 +419,8 @@ name = "c2pa-rs testing" version = "1.0.0" # The operating system the claim generator is running on. #operating_system.name = "macOS" -# Or if the name isn't specified, it can be inferred automatically. -operating_system.infer = true +# Or specify "auto" to infer the operating system automatically. +operating_system = "auto" # Arbitrary fields can also be defined. # # By default, the SDK adds a field "org.cai.c2pa_rs" with the value