ec_validator.rs (7184B)
1 // Copyright 2022 Adobe. All rights reserved. 2 // This file is licensed to you under the Apache License, 3 // Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) 4 // or the MIT license (http://opensource.org/licenses/MIT), 5 // at your option. 6 7 // Unless required by applicable law or agreed to in writing, 8 // this software is distributed on an "AS IS" BASIS, WITHOUT 9 // WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or 10 // implied. See the LICENSE-MIT and LICENSE-APACHE files for the 11 // specific language governing permissions and limitations under 12 // each license. 13 14 use openssl::{ec::EcKey, hash::MessageDigest, pkey::PKey}; 15 16 use crate::{validator::CoseValidator, Error, Result, SigningAlg}; 17 18 pub struct EcValidator { 19 alg: SigningAlg, 20 } 21 22 impl EcValidator { 23 pub const fn new(alg: SigningAlg) -> Self { 24 EcValidator { alg } 25 } 26 } 27 28 impl CoseValidator for EcValidator { 29 fn validate(&self, sig: &[u8], data: &[u8], pkey: &[u8]) -> Result<bool> { 30 let public_key = EcKey::public_key_from_der(pkey).map_err(|_err| Error::CoseSignature)?; 31 let key = PKey::from_ec_key(public_key).map_err(wrap_openssl_err)?; 32 33 let mut verifier = match self.alg { 34 SigningAlg::Es256 => openssl::sign::Verifier::new(MessageDigest::sha256(), &key)?, 35 SigningAlg::Es384 => openssl::sign::Verifier::new(MessageDigest::sha384(), &key)?, 36 SigningAlg::Es512 => openssl::sign::Verifier::new(MessageDigest::sha512(), &key)?, 37 _ => return Err(Error::UnsupportedType), 38 }; 39 40 // is this an expected P1363 sig size 41 let sig_der = if sig.len() == 64 || sig.len() == 96 || sig.len() == 132 { 42 if sig.len() 43 != match self.alg { 44 SigningAlg::Es256 => 64, 45 SigningAlg::Es384 => 96, 46 SigningAlg::Es512 => 132, 47 _ => return Err(Error::UnsupportedType), 48 } 49 { 50 return Err(Error::CoseSignature); 51 } 52 53 // convert P1363 sig to DER sig 54 let sig_len = sig.len() / 2; 55 let r = openssl::bn::BigNum::from_slice(&sig[0..sig_len]) 56 .map_err(|_err| Error::CoseSignature)?; 57 let s = openssl::bn::BigNum::from_slice(&sig[sig_len..]) 58 .map_err(|_err| Error::CoseSignature)?; 59 60 let ecdsa_sig = openssl::ecdsa::EcdsaSig::from_private_components(r, s) 61 .map_err(|_err| Error::CoseSignature)?; 62 63 ecdsa_sig.to_der().map_err(|_err| Error::CoseSignature)? 64 } else { 65 sig.to_vec() 66 }; 67 68 verifier.update(data).map_err(wrap_openssl_err)?; 69 verifier 70 .verify(&sig_der) 71 .map_err(|_err| Error::CoseSignature) 72 } 73 } 74 75 const fn wrap_openssl_err(err: openssl::error::ErrorStack) -> Error { 76 Error::OpenSslError(err) 77 } 78 79 #[cfg(test)] 80 #[cfg(feature = "file_io")] 81 mod tests { 82 #![allow(clippy::unwrap_used)] 83 use super::*; 84 use crate::{openssl::temp_signer, utils::test::fixture_path, Signer}; 85 86 #[test] 87 fn sign_and_validate_es256() { 88 let cert_dir = fixture_path("certs"); 89 90 let (signer, cert_path) = temp_signer::get_ec_signer(cert_dir, SigningAlg::Es256, None); 91 92 let data = b"some sample content to sign"; 93 println!("data len = {}", data.len()); 94 95 let signature = signer.sign(data).unwrap(); 96 println!("signature.len = {}", signature.len()); 97 assert!(signature.len() >= 64); 98 assert!(signature.len() <= signer.reserve_size()); 99 100 let cert_bytes = std::fs::read(cert_path).unwrap(); 101 102 let signcert = openssl::x509::X509::from_pem(&cert_bytes).unwrap(); 103 let pub_key = signcert.public_key().unwrap().public_key_to_der().unwrap(); 104 105 let validator = EcValidator::new(SigningAlg::Es256); 106 assert!(validator.validate(&signature, data, &pub_key).unwrap()); 107 } 108 109 #[test] 110 fn sign_and_validate_es384() { 111 let cert_dir = fixture_path("certs"); 112 113 let (signer, cert_path) = temp_signer::get_ec_signer(cert_dir, SigningAlg::Es384, None); 114 115 let data = b"some sample content to sign"; 116 println!("data len = {}", data.len()); 117 118 let signature = signer.sign(data).unwrap(); 119 println!("signature.len = {}", signature.len()); 120 assert!(signature.len() >= 64); 121 assert!(signature.len() <= signer.reserve_size()); 122 123 let cert_bytes = std::fs::read(cert_path).unwrap(); 124 125 let signcert = openssl::x509::X509::from_pem(&cert_bytes).unwrap(); 126 let pub_key = signcert.public_key().unwrap().public_key_to_der().unwrap(); 127 128 let validator = EcValidator::new(SigningAlg::Es384); 129 assert!(validator.validate(&signature, data, &pub_key).unwrap()); 130 } 131 132 #[test] 133 fn sign_and_validate_es512() { 134 let cert_dir = fixture_path("certs"); 135 136 let (signer, cert_path) = temp_signer::get_ec_signer(cert_dir, SigningAlg::Es512, None); 137 138 let data = b"some sample content to sign"; 139 println!("data len = {}", data.len()); 140 141 let signature = signer.sign(data).unwrap(); 142 println!("signature.len = {}", signature.len()); 143 assert!(signature.len() >= 64); 144 assert!(signature.len() <= signer.reserve_size()); 145 146 let cert_bytes = std::fs::read(cert_path).unwrap(); 147 148 let signcert = openssl::x509::X509::from_pem(&cert_bytes).unwrap(); 149 let pub_key = signcert.public_key().unwrap().public_key_to_der().unwrap(); 150 151 let validator = EcValidator::new(SigningAlg::Es512); 152 assert!(validator.validate(&signature, data, &pub_key).unwrap()); 153 } 154 155 #[test] 156 fn bad_sig_es256() { 157 let cert_dir = fixture_path("certs"); 158 159 let (signer, cert_path) = temp_signer::get_ec_signer(cert_dir, SigningAlg::Es256, None); 160 161 let data = b"some sample content to sign"; 162 println!("data len = {}", data.len()); 163 let mut signature = signer.sign(data).unwrap(); 164 165 signature.push(10); 166 167 let cert_bytes = std::fs::read(cert_path).unwrap(); 168 let signcert = openssl::x509::X509::from_pem(&cert_bytes).unwrap(); 169 let pub_key = signcert.public_key().unwrap().public_key_to_der().unwrap(); 170 171 let validator = EcValidator::new(SigningAlg::Es256); 172 let validated = validator.validate(&signature, data, &pub_key); 173 assert!(validated.is_err()); 174 } 175 176 #[test] 177 fn bad_data_es256() { 178 let cert_dir = fixture_path("certs"); 179 180 let (signer, cert_path) = temp_signer::get_ec_signer(cert_dir, SigningAlg::Es256, None); 181 182 let mut data = b"some sample content to sign".to_vec(); 183 println!("data len = {}", data.len()); 184 let signature = signer.sign(&data).unwrap(); 185 186 data[5] = 10; 187 data[6] = 11; 188 189 let cert_bytes = std::fs::read(cert_path).unwrap(); 190 let signcert = openssl::x509::X509::from_pem(&cert_bytes).unwrap(); 191 let pub_key = signcert.public_key().unwrap().public_key_to_der().unwrap(); 192 193 let validator = EcValidator::new(SigningAlg::Es256); 194 assert!(!validator.validate(&signature, &data, &pub_key).unwrap()); 195 } 196 }