Skip to content

feat: Support CAWG callback signing via c_ffi#2118

Merged
gpeacock merged 16 commits into
mainfrom
gpeacock/cawg_callback_signer
May 16, 2026
Merged

feat: Support CAWG callback signing via c_ffi#2118
gpeacock merged 16 commits into
mainfrom
gpeacock/cawg_callback_signer

Conversation

@gpeacock
Copy link
Copy Markdown
Member

@gpeacock gpeacock commented May 6, 2026

Replace AsyncRawSigner with AsyncSigner throughout AsyncX509CredentialHolder and AsyncIdentityAssertionSigner, using AsyncSignerWrapper from cose_sign.rs to bridge into the COSE signing path. Rename from_async_raw_signer to from_async_signer. Simplify test setup to use async_test_signer() directly.

Apply the same treatment to the sync side: replace hardcoded Box<dyn Signer + Send + Sync> with BoxedSigner in X509CredentialHolder, IdentityAssertionSigner, and IdentityAssertionBuilder, fixing WASM build failures. Add cfg-conditional Send/Sync handling to IdentityAssertionBuilder matching the pattern used by its async counterpart.

Add IdentityAssertionSigner::from_cawg_x509 as a convenience constructor for combining a C2PA signer with a CAWG X.509 identity assertion signer.

Add c2pa_create_cawg_signer(
takes C2paSigner pointers plus null-terminated arrays for referenced_assertions and roles, delegating to from_cawg_x509."

Expose SignerWrapper and
AsyncSignerWrapper as pub(crate) for use across the crate.

gpeacock added 2 commits May 1, 2026 00:22
Replace AsyncRawSigner with AsyncSigner throughout AsyncX509CredentialHolder
and AsyncIdentityAssertionSigner, using AsyncSignerWrapper from cose_sign.rs
to bridge into the COSE signing path. Rename from_async_raw_signer to
from_async_signer. Simplify test setup to use async_test_signer() directly.

Apply the same treatment to the sync side: replace hardcoded
Box<dyn Signer + Send + Sync> with BoxedSigner in X509CredentialHolder,
IdentityAssertionSigner, and IdentityAssertionBuilder, fixing WASM build
failures. Add cfg-conditional Send/Sync handling to IdentityAssertionBuilder
matching the pattern used by its async counterpart.

Add IdentityAssertionSigner::from_cawg_x509 as a convenience constructor
for combining a C2PA signer with a CAWG X.509 identity assertion signer.

Add c2pa_create_cawg_signer(
takes C2paSigner pointers plus null-terminated arrays for
referenced_assertions and roles, delegating to from_cawg_x509."

Expose SignerWrapper and
AsyncSignerWrapper as pub(crate) for use across the crate.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 6, 2026

Codecov Report

❌ Patch coverage is 57.63441% with 197 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.33%. Comparing base (87243f6) to head (6d5cf07).

Files with missing lines Patch % Lines
cli/src/main.rs 41.36% 129 Missing ⚠️
cli/src/signer.rs 2.27% 43 Missing ⚠️
sdk/src/settings/signer.rs 89.84% 13 Missing ⚠️
sdk/src/signer.rs 65.71% 12 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2118      +/-   ##
==========================================
- Coverage   78.44%   78.33%   -0.12%     
==========================================
  Files         177      176       -1     
  Lines       45503    45725     +222     
==========================================
+ Hits        35695    35818     +123     
- Misses       9808     9907      +99     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 6, 2026

Merging this PR will not alter performance

✅ 30 untouched benchmarks
⏩ 64 skipped benchmarks1


Comparing gpeacock/cawg_callback_signer (6d5cf07) with main (87243f6)

Open in CodSpeed

Footnotes

  1. 64 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@gpeacock gpeacock requested review from ok-nick, scouten-adobe and tmathern and removed request for scouten-adobe May 7, 2026 18:22
…_cawg_x509 → with_x509_identity

Remove CAWG-specific naming from the C and Rust identity signer APIs
Replace read_null_terminated_cstr_array with safer cstr_array_or_return_null! macro that enforces a max length and errors on invalid UTF-8
Add unit tests for with_x509_identity (Rust) and c2pa_identity_signer_create (C FFI)
@tmathern
Copy link
Copy Markdown
Contributor

tmathern commented May 8, 2026

This PR contains breaking changes. Are downstream SDKs affected by changes? Given it's the C FFI. I would think so?
Update: No effect detected.

Copy link
Copy Markdown
Contributor

@tmathern tmathern left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should likely prepare downstream fixes in branches as needed (before merging this).

Comment thread sdk/src/identity/builder/async_identity_assertion_signer.rs Outdated
Comment thread sdk/src/identity/builder/async_identity_assertion_signer.rs Outdated
Comment thread sdk/src/identity/x509/x509_credential_holder.rs Outdated
gpeacock added 10 commits May 8, 2026 11:41
Remove the CLI-local CallbackSigner, CallbackSignerConfig, and
ExternalProcessRunner in favour of c2pa::CallbackSigner from the SDK.
The subprocess invocation logic is now a closure inside make_subprocess_signer,
and the CAWG identity signer path now correctly reads the signing cert
from cawg_x509_signer settings rather than always falling back to the
C2PA manifest's sign_cert.
… signer tests

c2patool can now act as its own subprocess signer via C2PATOOL_SIGN_MODE
(set automatically by --signer-path/--identity-signer-path). Supports
c2pa, cawg, and fail modes; both signer paths fall back to baked-in test
certs when none are configured. Restores and adds integration tests for
subprocess signing, CAWG identity signing, not-found errors, and signer
failures using C2PATOOL_FORCE_SIGN_MODE.
…RawSigner-only

- Reverts changed to the Identity RawSigner
- Add OwnedSignerWrapper to signer.rs (BoxedSigner → RawSigner adapter,
  inverse of RawSignerWrapper)
- Make CawgX509IdentitySigner pub(crate) with two constructors:
  from_settings (builds RawSigner from cert/key bytes eagerly) and
  from_signer (wraps a BoxedSigner via OwnedSignerWrapper); both store
  the identity signer as Arc<dyn RawSigner + Send + Sync> so
  dynamic_assertions() clones the Arc instead of rebuilding each call
- Add ArcRawSigner adapter to delegate through the Arc
- Add public create_signer::from_x509_identity as the c2pa-layer entry
  point for combined C2PA + X.509 identity signing
- Update c2pa C FFI and c2patool CLI to use create_signer::from_x509_identity
Introduce a --signer-info protocol: before signing, c2patool calls the
subprocess with --signer-info and expects a JSON response containing alg,
sign_cert, and optionally tsa_url and reserve_size. The signer is the
only party that knows its maximum signature size, so reserve_size now
flows from the signer rather than from a --reserve-size CLI flag.

- Add reserve_size: Option<usize> to SignerInfo; signer declares it via
  --signer-info, c2patool sets it on CallbackSigner
- Hide --reserve-size (deprecated); signer-provided value takes precedence
- Add compat_mode: only pass --alg/--reserve-size to subprocess when
  cert/alg came from settings (legacy path); new --signer-info signers
  receive neither
- Add hidden test-signer subcommand as a test double (replaces
  C2PATOOL_SIGN_MODE env var); supports --signer-info and --fail
- Add cli/docs/signing.md covering the full signing protocol, both
  subprocess and settings-only paths, and how to write your own signer
- Fix Settings::from_file deprecation in signer.rs
- Update integration tests for new error messages and subcommand protocol
@scouten-adobe scouten-adobe changed the title feat: support cawg callback signing via c_ffi feat: Support CAWG callback signing via c_ffi May 15, 2026
@gpeacock gpeacock merged commit 5237f5b into main May 16, 2026
45 of 46 checks passed
@gpeacock gpeacock deleted the gpeacock/cawg_callback_signer branch May 16, 2026 17:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants