| 
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