|
4 | 4 | use anyhow::{anyhow, Result}; |
5 | 5 | use const_oid::ObjectIdentifier; |
6 | 6 | use der::{asn1::AnyRef, Sequence}; |
| 7 | + |
7 | 8 | use rsa::pkcs1::DecodeRsaPublicKey; |
| 9 | +#[cfg(all(target_os = "wasi", feature = "wasi-crypto"))] |
| 10 | +use spki::EncodePublicKey; |
8 | 11 | use spki::{AlgorithmIdentifier, SubjectPublicKeyInfo}; |
9 | 12 |
|
10 | 13 | use const_oid::db::rfc5912::{ |
11 | 14 | ECDSA_WITH_SHA_256, ECDSA_WITH_SHA_384, ID_EC_PUBLIC_KEY as ECPK, ID_MGF_1, ID_RSASSA_PSS, |
12 | 15 | ID_SHA_256 as SHA256, ID_SHA_384 as SHA384, ID_SHA_512 as SHA512, RSA_ENCRYPTION as RSA, |
13 | 16 | SECP_256_R_1 as P256, SECP_384_R_1 as P384, |
14 | 17 | }; |
| 18 | +#[cfg(all(target_os = "wasi", feature = "wasi-crypto"))] |
| 19 | +use der::pem::LineEnding; |
| 20 | + |
| 21 | +#[cfg(all(target_os = "wasi", feature = "wasi-crypto"))] |
| 22 | +use wasi_crypto_guest::signatures::{Signature, SignaturePublicKey}; |
15 | 23 |
|
16 | 24 | const ES256: (ObjectIdentifier, Option<AnyRef<'static>>) = (ECDSA_WITH_SHA_256, None); |
17 | 25 | const ES384: (ObjectIdentifier, Option<AnyRef<'static>>) = (ECDSA_WITH_SHA_384, None); |
@@ -43,6 +51,108 @@ pub trait SubjectPublicKeyInfoExt { |
43 | 51 | } |
44 | 52 |
|
45 | 53 | impl<'a> SubjectPublicKeyInfoExt for SubjectPublicKeyInfo<'a> { |
| 54 | + #[cfg(all(target_os = "wasi", feature = "wasi-crypto"))] |
| 55 | + fn verify(&self, body: &[u8], algo: AlgorithmIdentifier<'_>, sign: &[u8]) -> Result<()> { |
| 56 | + let algo_name = match (self.algorithm.oids()?, (algo.oid, algo.parameters)) { |
| 57 | + ((ECPK, Some(P256)), ES256) => "ECDSA_P256_SHA256", |
| 58 | + ((ECPK, Some(P384)), ES384) => "ECDSA_P384_SHA384", |
| 59 | + ((RSA, None), (ID_RSASSA_PSS, Some(p))) => { |
| 60 | + // Decompose the RSA PSS parameters. |
| 61 | + let RsaSsaPssParams { |
| 62 | + hash_algorithm: hash, |
| 63 | + mask_algorithm: mask, |
| 64 | + salt_length: salt, |
| 65 | + trailer_field: tfld, |
| 66 | + } = p.decode_into().unwrap(); |
| 67 | + |
| 68 | + // Validate the sanity of the mask algorithm. |
| 69 | + let algo = match (mask.oid, mask.parameters) { |
| 70 | + (ID_MGF_1, Some(p)) => { |
| 71 | + let p = p.decode_into::<AlgorithmIdentifier<'_>>()?; |
| 72 | + match (p.oids()?, salt, tfld) { |
| 73 | + ((SHA256, None), 32, 1) => Ok(SHA256), |
| 74 | + ((SHA384, None), 48, 1) => Ok(SHA384), |
| 75 | + ((SHA512, None), 64, 1) => Ok(SHA512), |
| 76 | + ((x, y), s, t) => { |
| 77 | + eprint!( |
| 78 | + "Unknown RSA hash and components: {:?}, {:?}, salt {}, tfld {}", |
| 79 | + x, y, s, t |
| 80 | + ); |
| 81 | + Err(anyhow!("unsupported")) |
| 82 | + } |
| 83 | + } |
| 84 | + } |
| 85 | + (x, _) => { |
| 86 | + eprintln!("Unknown RSA OID {:?}", x); |
| 87 | + Err(anyhow!("unsupported")) |
| 88 | + } |
| 89 | + } |
| 90 | + .map_err(|e| { |
| 91 | + eprintln!("Some algo error {:?}", e); |
| 92 | + anyhow!("{:?}", e) |
| 93 | + }) |
| 94 | + .unwrap(); |
| 95 | + |
| 96 | + match (hash.oids()?, algo) { |
| 97 | + ((SHA256, None), SHA256) => "RSA_PSS_2048_SHA256", |
| 98 | + ((SHA384, None), SHA384) => "RSA_PSS_3072_SHA384", |
| 99 | + ((SHA512, None), SHA512) => "RSA_PSS_4096_SHA512", |
| 100 | + _ => { |
| 101 | + eprintln!("Error unknown hash.oids"); |
| 102 | + bail!("unsupported") |
| 103 | + } |
| 104 | + } |
| 105 | + } |
| 106 | + _ => { |
| 107 | + eprintln!("Unknown algorithm, should not be here!"); |
| 108 | + bail!("unsupported") |
| 109 | + } |
| 110 | + }; |
| 111 | + |
| 112 | + let public_key = match algo_name { |
| 113 | + "RSA_PSS_2048_SHA256" | "RSA_PSS_3072_SHA384" | "RSA_PSS_4096_SHA512" => { |
| 114 | + let pkey = rsa::RsaPublicKey::from_pkcs1_der(self.subject_public_key)?; |
| 115 | + SignaturePublicKey::from_pem( |
| 116 | + algo_name, |
| 117 | + pkey.to_public_key_pem(LineEnding::LF).unwrap().as_bytes(), |
| 118 | + ) |
| 119 | + .map_err(|e| anyhow!("{:?}", e)) |
| 120 | + .unwrap() |
| 121 | + } |
| 122 | + _ => SignaturePublicKey::from_raw(algo_name, self.subject_public_key) |
| 123 | + .map_err(|e| anyhow!("{:?}", e)) |
| 124 | + .unwrap(), |
| 125 | + }; |
| 126 | + |
| 127 | + let signature = match algo_name { |
| 128 | + "ECDSA_P256_SHA256" => { |
| 129 | + let temp = p256::ecdsa::Signature::from_der(sign)?; |
| 130 | + temp.to_vec() |
| 131 | + } |
| 132 | + "ECDSA_P384_SHA384" => { |
| 133 | + let temp = p384::ecdsa::Signature::from_der(sign)?; |
| 134 | + temp.to_vec() |
| 135 | + } |
| 136 | + "RSA_PSS_2048_SHA256" | "RSA_PSS_3072_SHA384" | "RSA_PSS_4096_SHA512" => { |
| 137 | + use signature::Signature; |
| 138 | + let s = rsa::pss::Signature::from_bytes(sign)?; |
| 139 | + eprintln!("Made RSA signature"); |
| 140 | + s.to_vec() |
| 141 | + } |
| 142 | + _ => sign.to_vec(), |
| 143 | + }; |
| 144 | + |
| 145 | + let signature = Signature::from_raw(algo_name, &signature) |
| 146 | + .map_err(|e| anyhow!("{:?}", e)) |
| 147 | + .unwrap(); |
| 148 | + |
| 149 | + Ok(public_key |
| 150 | + .signature_verify(body, &signature) |
| 151 | + .map_err(|e| anyhow!("{:?}", e)) |
| 152 | + .unwrap()) |
| 153 | + } |
| 154 | + |
| 155 | + #[cfg(any(not(target_os = "wasi"), not(feature = "wasi-crypto")))] |
46 | 156 | fn verify(&self, body: &[u8], algo: AlgorithmIdentifier<'_>, sign: &[u8]) -> Result<()> { |
47 | 157 | match (self.algorithm.oids()?, (algo.oid, algo.parameters)) { |
48 | 158 | ((ECPK, Some(P256)), ES256) => { |
|
0 commit comments