Skip to content

Commit e4ae248

Browse files
authored
fix: Make openssl and rust_native_crypto features additive (#1379)
* fix: make `openssl` and `rust_native_crypto` features additive * style: alphabetize openssl feature * docs: document openssl and rust_native_crypto features * docs: fix typo
1 parent 74bb71d commit e4ae248

File tree

9 files changed

+81
-42
lines changed

9 files changed

+81
-42
lines changed

docs/usage.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ c2pa = { version = "0.45.2", features = ["file_io", "add_thumbnails"] }
3434

3535
The Rust library crate provides the following capabilities:
3636

37+
* `openssl` *(enabled by default)* - Enables the system `openssl` implementation for cryptography.
38+
* `rust_native_crypto` - Enables the Rust native implementation for cryptography.
3739
* `add_thumbnails` generates thumbnails automatically for JPEG and PNG files. (no longer included with `file_io`)
3840
* `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.
3941
* `file_io` enables manifest generation, signing via OpenSSL, and embedding manifests in [supported file formats](supported-formats.md).
@@ -43,6 +45,10 @@ The Rust library crate provides the following capabilities:
4345
* `v1_api` - Use the old API (which will soon be deprecated) instead of the [new API](release-notes.md#new-api).
4446
* `pdf` - Enable support for reading claims on PDF files.
4547

48+
> [!NOTE]
49+
> If both `rust_native_crypto` and `openssl` are enabled, it will default to `rust_native_crypto`.
50+
> It is recommended to disable default features when using `rust_native_crypto` as to avoid including `openssl` as a dependency.
51+
4652
### New API
4753

4854
The new API is now enabled by default. The `unstable_api` feature is no longer available.
@@ -78,7 +84,7 @@ When `file_io` is enabled, the lack of a scheme will be interpreted as a `file:/
7884

7985
### Source asset vs parent asset
8086

81-
The source asset isn't always the parent asset: The source asset is the asset that is hashed and signed. It can be the output from an editing application that has not preserved the manifest store from the parent. In that case, the application should have extracted a parent ingredient from the parent asset and added that to the manifest definition.
87+
The source asset isn't always the parent asset: The source asset is the asset that is hashed and signed. It can be the output from an editing application that has not preserved the manifest store from the parent. In that case, the application should have extracted a parent ingredient from the parent asset and added that to the manifest definition.
8288

8389
- Parent asset: with a manifest store.
8490
- Parent ingredient: generated from that parent asset (hashed and validated)
@@ -90,7 +96,7 @@ If there is no parent ingredient defined, and the source has a manifest store, t
9096
### Remote URLs and embedding
9197

9298
The default operation of C2PA signing is to embed a C2PA manifest store into an asset. The library also returns the C2PA manifest store so that it can be written to a sidecar or uploaded to a remote service.
93-
- The API supports embedding a remote URL reference into the asset.
99+
- The API supports embedding a remote URL reference into the asset.
94100
- The remote URL is stored in different ways depending on the asset, but is often stored in XMP data.
95101
- The remote URL must be added to the asset before signing so that it can be hashed along with the asset.
96102
- Not all file formats support embedding remote URLs or embedding manifests stores.

sdk/Cargo.toml

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,7 @@ rust-version = "1.86.0"
2424
exclude = ["tests/fixtures"]
2525

2626
[package.metadata.docs.rs]
27-
# Build with all features, but not with openssl and rust_native_crypto simulatenously.
28-
features = [
29-
"openssl",
30-
"add_thumbnails",
31-
"file_io",
32-
"serialize_thumbnails",
33-
"no_interleaved_io",
34-
"fetch_remote_manifests",
35-
"json_schema",
36-
"pdf",
37-
"v1_api",
38-
"diagnostics",
39-
]
27+
all-features = true
4028
rustdoc-args = ["--cfg", "docsrs"]
4129

4230
[features]
@@ -203,10 +191,19 @@ sha2 = { version = "0.10.6", features = ["asm"] }
203191
[target.'cfg(not(target_arch = "aarch64"))'.dependencies]
204192
sha2 = "0.10.6"
205193

194+
# This list matches the `rust_native_crypto` feature since they are not optional on WASM.
206195
[target.'cfg(target_arch = "wasm32")'.dependencies]
207196
const-oid = "0.9.6"
208197
der = "0.7.9"
198+
ecdsa = { version = "0.16.9", features = ["digest", "sha2"] }
209199
num-bigint-dig = "0.8.4"
200+
p256 = "0.13.2"
201+
p384 = "0.13.0"
202+
p521 = { version = "0.13.3", features = [
203+
"pkcs8",
204+
"digest",
205+
"ecdsa",
206+
] }
210207
pkcs1 = "0.7.5"
211208
rsa = { version = "0.9.6", features = ["sha2"] }
212209
spki = "0.7.3"
@@ -289,7 +286,7 @@ wasm-bindgen-test = "0.3.45"
289286
httpmock = "0.7.0"
290287
tokio = { version = "1.44.2", features = ["full"] }
291288
criterion = { package = "codspeed-criterion-compat", version = "3.0.5" }
292-
#
289+
293290
# WASM/WASI doesn't support default criterion features.
294291
# https://github.com/bheisler/criterion.rs/blob/4c19e913b84e6a7e4a8470cb0f766796886ed891/book/src/user_guide/wasi.md
295292
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]

sdk/src/crypto/cose/certificate_trust_policy.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ impl CertificateTrustPolicy {
141141
return Ok(TrustAnchorType::EndEntity);
142142
}
143143

144-
#[cfg(feature = "rust_native_crypto")]
144+
#[cfg(any(feature = "rust_native_crypto", target_arch = "wasm32"))]
145145
{
146146
return crate::crypto::raw_signature::rust_native::check_certificate_trust::check_certificate_trust(
147147
self,
@@ -151,7 +151,10 @@ impl CertificateTrustPolicy {
151151
);
152152
}
153153

154-
#[cfg(feature = "openssl")]
154+
#[cfg(all(
155+
feature = "openssl",
156+
not(all(feature = "rust_native_crypto", target_arch = "wasm32"))
157+
))]
155158
{
156159
return crate::crypto::raw_signature::openssl::check_certificate_trust::check_certificate_trust(
157160
self,
@@ -214,7 +217,7 @@ impl CertificateTrustPolicy {
214217

215218
/// Add user provided trust anchors that shall be accepted when verifying COSE signatures.
216219
/// These anchors are distinct from the C2PA trust anchors and are used to validate certificates
217-
/// that are not part of the C2PA trust anchors.
220+
/// that are not part of the C2PA trust anchors.
218221
pub fn add_user_trust_anchors(
219222
&mut self,
220223
trust_anchor_pems: &[u8],
@@ -430,14 +433,20 @@ pub enum CertificateTrustError {
430433
InternalError(String),
431434
}
432435

433-
#[cfg(feature = "openssl")]
436+
#[cfg(all(
437+
feature = "openssl",
438+
not(all(feature = "rust_native_crypto", target_arch = "wasm32"))
439+
))]
434440
impl From<openssl::error::ErrorStack> for CertificateTrustError {
435441
fn from(err: openssl::error::ErrorStack) -> Self {
436442
Self::CryptoLibraryError(err.to_string())
437443
}
438444
}
439445

440-
#[cfg(feature = "openssl")]
446+
#[cfg(all(
447+
feature = "openssl",
448+
not(all(feature = "rust_native_crypto", target_arch = "wasm32"))
449+
))]
441450
impl From<crate::crypto::raw_signature::openssl::OpenSslMutexUnavailable>
442451
for CertificateTrustError
443452
{

sdk/src/crypto/raw_signature/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@
1515
1616
pub(crate) mod oids;
1717

18-
#[cfg(feature = "openssl")]
18+
#[cfg(all(
19+
feature = "openssl",
20+
not(all(feature = "rust_native_crypto", target_arch = "wasm32"))
21+
))]
1922
pub(crate) mod openssl;
2023

21-
#[cfg(feature = "rust_native_crypto")]
24+
#[cfg(any(feature = "rust_native_crypto", target_arch = "wasm32"))]
2225
pub(crate) mod rust_native;
2326

2427
pub(crate) mod signer;

sdk/src/crypto/raw_signature/signer.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,20 @@ impl From<std::io::Error> for RawSignerError {
157157
}
158158
}
159159

160-
#[cfg(feature = "openssl")]
160+
#[cfg(all(
161+
feature = "openssl",
162+
not(all(feature = "rust_native_crypto", target_arch = "wasm32"))
163+
))]
161164
impl From<openssl::error::ErrorStack> for RawSignerError {
162165
fn from(err: openssl::error::ErrorStack) -> Self {
163166
Self::CryptoLibraryError(err.to_string())
164167
}
165168
}
166169

167-
#[cfg(feature = "openssl")]
170+
#[cfg(all(
171+
feature = "openssl",
172+
not(all(feature = "rust_native_crypto", target_arch = "wasm32"))
173+
))]
168174
impl From<crate::crypto::raw_signature::openssl::OpenSslMutexUnavailable> for RawSignerError {
169175
fn from(err: crate::crypto::raw_signature::openssl::OpenSslMutexUnavailable) -> Self {
170176
Self::InternalError(err.to_string())
@@ -187,7 +193,7 @@ pub fn signer_from_cert_chain_and_private_key(
187193
alg: SigningAlg,
188194
time_stamp_service_url: Option<String>,
189195
) -> Result<Box<dyn RawSigner + Send + Sync>, RawSignerError> {
190-
#[cfg(feature = "rust_native_crypto")]
196+
#[cfg(any(feature = "rust_native_crypto", target_arch = "wasm32"))]
191197
{
192198
match crate::crypto::raw_signature::rust_native::signers::signer_from_cert_chain_and_private_key(
193199
cert_chain,
@@ -201,7 +207,10 @@ pub fn signer_from_cert_chain_and_private_key(
201207
}
202208
}
203209

204-
#[cfg(feature = "openssl")]
210+
#[cfg(all(
211+
feature = "openssl",
212+
not(all(feature = "rust_native_crypto", target_arch = "wasm32"))
213+
))]
205214
{
206215
return crate::crypto::raw_signature::openssl::signers::signer_from_cert_chain_and_private_key(
207216
cert_chain,

sdk/src/crypto/raw_signature/tests/signers.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@ fn es384() {
6969
}
7070

7171
#[test]
72-
#[cfg(feature = "openssl")]
72+
#[cfg(all(
73+
feature = "openssl",
74+
not(all(feature = "rust_native_crypto", target_arch = "wasm32"))
75+
))]
7376
fn es512() {
7477
let cert_chain = include_bytes!("../../../../tests/fixtures/crypto/raw_signature/es512.pub");
7578
let private_key = include_bytes!("../../../../tests/fixtures/crypto/raw_signature/es512.priv");

sdk/src/crypto/raw_signature/tests/validators.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,10 @@ const SHA384_OID: Oid = bcder::Oid(OctetString::from_static(&[96, 134, 72, 1, 10
241241

242242
const SHA512_OID: Oid = bcder::Oid(OctetString::from_static(&[96, 134, 72, 1, 101, 3, 4, 2, 3]));
243243

244-
#[cfg_attr(feature = "rust_native_crypto", allow(unused))]
244+
#[cfg_attr(
245+
any(feature = "rust_native_crypto", target_arch = "wasm32"),
246+
allow(unused)
247+
)]
245248
const SHA1_OID: Oid = bcder::Oid(OctetString::from_static(&[43, 14, 3, 2, 26]));
246249

247250
#[test]
@@ -340,7 +343,10 @@ fn rs512() {
340343
}
341344

342345
#[test]
343-
#[cfg(feature = "openssl")]
346+
#[cfg(all(
347+
feature = "openssl",
348+
not(all(feature = "rust_native_crypto", target_arch = "wasm32"))
349+
))]
344350
fn sha1() {
345351
let signature =
346352
include_bytes!("../../../../tests/fixtures/crypto/raw_signature/legacy/sha1.raw_sig");

sdk/src/crypto/raw_signature/validator.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ pub trait AsyncRawSignatureValidator {
6565
/// Which validators are available may vary depending on the platform and
6666
/// which crate features were enabled.
6767
pub fn validator_for_signing_alg(alg: SigningAlg) -> Option<Box<dyn RawSignatureValidator>> {
68-
#[cfg(feature = "rust_native_crypto")]
68+
#[cfg(any(feature = "rust_native_crypto", target_arch = "wasm32"))]
6969
{
7070
if let Some(validator) =
7171
crate::crypto::raw_signature::rust_native::validators::validator_for_signing_alg(alg)
@@ -74,7 +74,10 @@ pub fn validator_for_signing_alg(alg: SigningAlg) -> Option<Box<dyn RawSignature
7474
}
7575
}
7676

77-
#[cfg(feature = "openssl")]
77+
#[cfg(all(
78+
feature = "openssl",
79+
not(all(feature = "rust_native_crypto", target_arch = "wasm32"))
80+
))]
7881
if let Some(validator) =
7982
crate::crypto::raw_signature::openssl::validators::validator_for_signing_alg(alg)
8083
{
@@ -95,7 +98,7 @@ pub(crate) fn validator_for_sig_and_hash_algs(
9598
hash_alg: &Oid,
9699
) -> Option<Box<dyn RawSignatureValidator>> {
97100
// TO REVIEW: Do we need any of the RSA-PSS algorithms for this use case?
98-
#[cfg(feature = "rust_native_crypto")]
101+
#[cfg(any(feature = "rust_native_crypto", target_arch = "wasm32"))]
99102
{
100103
if let Some(validator) =
101104
crate::crypto::raw_signature::rust_native::validators::validator_for_sig_and_hash_algs(
@@ -106,7 +109,10 @@ pub(crate) fn validator_for_sig_and_hash_algs(
106109
}
107110
}
108111

109-
#[cfg(feature = "openssl")]
112+
#[cfg(all(
113+
feature = "openssl",
114+
not(all(feature = "rust_native_crypto", target_arch = "wasm32"))
115+
))]
110116
if let Some(validator) =
111117
crate::crypto::raw_signature::openssl::validators::validator_for_sig_and_hash_algs(
112118
sig_alg, hash_alg,
@@ -175,14 +181,20 @@ pub enum RawSignatureValidationError {
175181
InternalError(String),
176182
}
177183

178-
#[cfg(feature = "openssl")]
184+
#[cfg(all(
185+
feature = "openssl",
186+
not(all(feature = "rust_native_crypto", target_arch = "wasm32"))
187+
))]
179188
impl From<openssl::error::ErrorStack> for RawSignatureValidationError {
180189
fn from(err: openssl::error::ErrorStack) -> Self {
181190
Self::CryptoLibraryError(err.to_string())
182191
}
183192
}
184193

185-
#[cfg(feature = "openssl")]
194+
#[cfg(all(
195+
feature = "openssl",
196+
not(all(feature = "rust_native_crypto", target_arch = "wasm32"))
197+
))]
186198
impl From<crate::crypto::raw_signature::openssl::OpenSslMutexUnavailable>
187199
for RawSignatureValidationError
188200
{

sdk/src/lib.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,5 @@ pub(crate) mod store;
203203
pub(crate) mod utils;
204204
pub(crate) use utils::{cbor_types, hash_utils};
205205

206-
#[cfg(all(feature = "openssl", feature = "rust_native_crypto"))]
207-
compile_error!("Features 'openssl' and 'rust_native_crypto' cannot be enabled at the same time.");
208-
209206
#[cfg(not(any(feature = "openssl", feature = "rust_native_crypto")))]
210207
compile_error!("Either 'openssl' or 'rust_native_crypto' feature must be enabled.");
211-
212-
#[cfg(all(feature = "openssl", target_arch = "wasm32"))]
213-
compile_error!("Feature 'openssl' is not available for wasm32.");

0 commit comments

Comments
 (0)