Skip to content

Commit

Permalink
chore: Move WASM asynchronous raw signature mechanism into c2pa-crypto (
Browse files Browse the repository at this point in the history
  • Loading branch information
scouten-adobe authored Nov 21, 2024
1 parent 738fb61 commit 2df2f1d
Show file tree
Hide file tree
Showing 16 changed files with 816 additions and 672 deletions.
1 change: 1 addition & 0 deletions internal/crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ default-features = false
features = ["now", "wasmbind"]

[target.'cfg(target_arch = "wasm32")'.dependencies]
async-trait = { version = "0.1.77" }
ecdsa = "0.16.9"
ed25519-dalek = "2.1.1"
p256 = "0.13.2"
Expand Down
23 changes: 23 additions & 0 deletions internal/crypto/src/raw_signature/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,15 @@ pub enum RawSignatureValidationError {
/// An invalid signature value was provided.
#[error("invalid signature value")]
InvalidSignature,

/// The time stamp uses an unsupported signing or hash algorithm.
#[error("signature uses an unsupported algorithm")]
UnsupportedAlgorithm,

/// An unexpected internal error occured while requesting the time stamp
/// response.
#[error("internal error ({0})")]
InternalError(&'static str),
}

#[cfg(feature = "openssl")]
Expand All @@ -141,3 +150,17 @@ impl From<openssl::error::ErrorStack> for RawSignatureValidationError {
Self::OpenSslError(err.to_string())
}
}

#[cfg(target_arch = "wasm32")]
impl From<crate::webcrypto::WasmCryptoError> for RawSignatureValidationError {
fn from(err: crate::webcrypto::WasmCryptoError) -> Self {
match err {
crate::webcrypto::WasmCryptoError::UnknownContext => {
Self::InternalError("unknown WASM context")
}
crate::webcrypto::WasmCryptoError::NoCryptoAvailable => {
Self::InternalError("WASM crypto unavailable")
}
}
}
}
303 changes: 303 additions & 0 deletions internal/crypto/src/tests/webcrypto/validators/async_validators.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,303 @@
// Copyright 2024 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 bcder::Oid;
use rasn::types::OctetString;
use wasm_bindgen_test::wasm_bindgen_test;

use crate::{
raw_signature::RawSignatureValidationError,
webcrypto::{
async_validator_for_sig_and_hash_algs, async_validators::async_validator_for_signing_alg,
},
SigningAlg,
};

const SAMPLE_DATA: &[u8] = b"some sample content to sign";

#[wasm_bindgen_test]
async fn es256() {
let signature = include_bytes!("../../fixtures/raw_signature/es256.raw_sig");
let pub_key = include_bytes!("../../fixtures/raw_signature/es256.pub_key");

let validator = async_validator_for_signing_alg(SigningAlg::Es256).unwrap();

validator
.validate_async(signature, SAMPLE_DATA, pub_key)
.await
.unwrap();
}

#[wasm_bindgen_test]
async fn es256_bad_signature() {
let mut signature = include_bytes!("../../fixtures/raw_signature/es256.raw_sig").to_vec();
assert_ne!(signature[10], 10);
signature[10] = 10;

let pub_key = include_bytes!("../../fixtures/raw_signature/es256.pub_key");

let validator = async_validator_for_signing_alg(SigningAlg::Es256).unwrap();

assert_eq!(
validator
.validate_async(&signature, SAMPLE_DATA, pub_key)
.await
.unwrap_err(),
RawSignatureValidationError::SignatureMismatch
);
}

#[wasm_bindgen_test]
async fn es256_bad_data() {
let signature = include_bytes!("../../fixtures/raw_signature/es256.raw_sig");
let pub_key = include_bytes!("../../fixtures/raw_signature/es256.pub_key");

let mut data = SAMPLE_DATA.to_vec();
data[10] = 0;

let validator = async_validator_for_signing_alg(SigningAlg::Es256).unwrap();

assert_eq!(
validator
.validate_async(signature, &data, pub_key)
.await
.unwrap_err(),
RawSignatureValidationError::SignatureMismatch
);
}

#[wasm_bindgen_test]
async fn es384() {
let signature = include_bytes!("../../fixtures/raw_signature/es384.raw_sig");
let pub_key = include_bytes!("../../fixtures/raw_signature/es384.pub_key");

let validator = async_validator_for_signing_alg(SigningAlg::Es384).unwrap();

validator
.validate_async(signature, SAMPLE_DATA, pub_key)
.await
.unwrap();
}

#[wasm_bindgen_test]
async fn es512() {
let signature = include_bytes!("../../fixtures/raw_signature/es512.raw_sig");
let pub_key = include_bytes!("../../fixtures/raw_signature/es512.pub_key");

let validator = async_validator_for_signing_alg(SigningAlg::Es512).unwrap();

validator
.validate_async(signature, SAMPLE_DATA, pub_key)
.await
.unwrap();
}

#[wasm_bindgen_test]
async fn ed25519() {
let signature = include_bytes!("../../fixtures/raw_signature/ed25519.raw_sig");
let pub_key = include_bytes!("../../fixtures/raw_signature/ed25519.pub_key");

let validator = async_validator_for_signing_alg(SigningAlg::Ed25519).unwrap();

validator
.validate_async(signature, SAMPLE_DATA, pub_key)
.await
.unwrap();
}

#[wasm_bindgen_test]
async fn ed25519_bad_data() {
let signature = include_bytes!("../../fixtures/raw_signature/ed25519.raw_sig");
let pub_key = include_bytes!("../../fixtures/raw_signature/ed25519.pub_key");

let mut data = SAMPLE_DATA.to_vec();
data[5] = 10;
data[6] = 11;

let validator = async_validator_for_signing_alg(SigningAlg::Ed25519).unwrap();

assert_eq!(
validator
.validate_async(signature, &data, pub_key)
.await
.unwrap_err(),
RawSignatureValidationError::SignatureMismatch
);
}

#[wasm_bindgen_test]
async fn ps256() {
let signature = include_bytes!("../../fixtures/raw_signature/ps256.raw_sig");
let pub_key = include_bytes!("../../fixtures/raw_signature/ps256.pub_key");

let validator = async_validator_for_signing_alg(SigningAlg::Ps256).unwrap();

validator
.validate_async(signature, SAMPLE_DATA, pub_key)
.await
.unwrap();
}

#[wasm_bindgen_test]
async fn ps256_bad_signature() {
let mut signature = include_bytes!("../../fixtures/raw_signature/ps256.raw_sig").to_vec();
assert_ne!(signature[10], 10);
signature[10] = 10;

let pub_key = include_bytes!("../../fixtures/raw_signature/ps256.pub_key");

let validator = async_validator_for_signing_alg(SigningAlg::Ps256).unwrap();

assert_eq!(
validator
.validate_async(&signature, SAMPLE_DATA, pub_key)
.await
.unwrap_err(),
RawSignatureValidationError::SignatureMismatch
);
}

#[wasm_bindgen_test]
async fn ps256_bad_data() {
let signature = include_bytes!("../../fixtures/raw_signature/ps256.raw_sig");
let pub_key = include_bytes!("../../fixtures/raw_signature/ps256.pub_key");

let mut data = SAMPLE_DATA.to_vec();
data[10] = 0;

let validator = async_validator_for_signing_alg(SigningAlg::Ps256).unwrap();

assert_eq!(
validator
.validate_async(signature, &data, pub_key)
.await
.unwrap_err(),
RawSignatureValidationError::SignatureMismatch
);
}

#[wasm_bindgen_test]
async fn ps384() {
let signature = include_bytes!("../../fixtures/raw_signature/ps384.raw_sig");
let pub_key = include_bytes!("../../fixtures/raw_signature/ps384.pub_key");

let validator = async_validator_for_signing_alg(SigningAlg::Ps384).unwrap();

validator
.validate_async(signature, SAMPLE_DATA, pub_key)
.await
.unwrap();
}

#[wasm_bindgen_test]
async fn ps512() {
let signature = include_bytes!("../../fixtures/raw_signature/ps512.raw_sig");
let pub_key = include_bytes!("../../fixtures/raw_signature/ps512.pub_key");

let validator = async_validator_for_signing_alg(SigningAlg::Ps512).unwrap();

validator
.validate_async(signature, SAMPLE_DATA, pub_key)
.await
.unwrap();
}

// Argh. Different Oid types across different crates, so we have to construct
// our own constants here.
const RSA_OID: Oid = bcder::Oid(OctetString::from_static(&[
42, 134, 72, 134, 247, 13, 1, 1, 1,
]));

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

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

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

#[wasm_bindgen_test]
async fn legacy_rs256() {
let signature = include_bytes!("../../fixtures/raw_signature/legacy/rs256.raw_sig");
let pub_key = include_bytes!("../../fixtures/raw_signature/legacy/rs256.pub_key");

let validator = async_validator_for_sig_and_hash_algs(&RSA_OID, &SHA256_OID).unwrap();

validator
.validate_async(signature, SAMPLE_DATA, pub_key)
.await
.unwrap();
}

#[wasm_bindgen_test]
async fn legacy_rs256_bad_signature() {
let mut signature =
include_bytes!("../../fixtures/raw_signature/legacy/rs256.raw_sig").to_vec();
assert_ne!(signature[10], 10);
signature[10] = 10;

let pub_key = include_bytes!("../../fixtures/raw_signature/legacy/rs256.pub_key");

let validator = async_validator_for_sig_and_hash_algs(&RSA_OID, &SHA256_OID).unwrap();

assert_eq!(
validator
.validate_async(&signature, SAMPLE_DATA, pub_key)
.await
.unwrap_err(),
RawSignatureValidationError::SignatureMismatch
);
}

#[wasm_bindgen_test]
async fn legacy_rs256_bad_data() {
let signature = include_bytes!("../../fixtures/raw_signature/legacy/rs256.raw_sig");
let pub_key = include_bytes!("../../fixtures/raw_signature/legacy/rs256.pub_key");

let mut data = SAMPLE_DATA.to_vec();
data[10] = 0;

let validator = async_validator_for_sig_and_hash_algs(&RSA_OID, &SHA256_OID).unwrap();

assert_eq!(
validator
.validate_async(signature, &data, pub_key)
.await
.unwrap_err(),
RawSignatureValidationError::SignatureMismatch
);
}

#[wasm_bindgen_test]
async fn legacy_rs384() {
let signature = include_bytes!("../../fixtures/raw_signature/legacy/rs384.raw_sig");
let pub_key = include_bytes!("../../fixtures/raw_signature/legacy/rs384.pub_key");

let validator = async_validator_for_sig_and_hash_algs(&RSA_OID, &SHA384_OID).unwrap();

validator
.validate_async(signature, SAMPLE_DATA, pub_key)
.await
.unwrap();
}

#[wasm_bindgen_test]
async fn legacy_rs512() {
let signature = include_bytes!("../../fixtures/raw_signature/legacy/rs512.raw_sig");
let pub_key = include_bytes!("../../fixtures/raw_signature/legacy/rs512.pub_key");

let validator = async_validator_for_sig_and_hash_algs(&RSA_OID, &SHA512_OID).unwrap();

validator
.validate_async(signature, SAMPLE_DATA, pub_key)
.await
.unwrap();
}
1 change: 1 addition & 0 deletions internal/crypto/src/tests/webcrypto/validators/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// specific language governing permissions and limitations under
// each license.

mod async_validators;
mod ecdsa_validator;
mod ed25519_validator;
mod rsa_legacy_validator;
Expand Down
Loading

0 comments on commit 2df2f1d

Please sign in to comment.