rsa_signer.rs (9768B)
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 std::cell::Cell; 15 16 //use extfmt::Hexlify; 17 use openssl::{ 18 hash::MessageDigest, 19 pkey::{PKey, Private}, 20 rsa::{Rsa, RsaPrivateKeyBuilder}, 21 x509::X509, 22 }; 23 24 use super::check_chain_order; 25 use crate::{ocsp_utils::OcspData, signer::ConfigurableSigner, Error, Result, Signer, SigningAlg}; 26 27 /// Implements `Signer` trait using OpenSSL's implementation of 28 /// SHA256 + RSA encryption. 29 pub struct RsaSigner { 30 signcerts: Vec<X509>, 31 pkey: PKey<Private>, 32 33 certs_size: usize, 34 timestamp_size: usize, 35 ocsp_size: Cell<usize>, 36 37 alg: SigningAlg, 38 tsa_url: Option<String>, 39 ocsp_rsp: Cell<OcspData>, 40 } 41 42 impl RsaSigner { 43 // Sample of OCSP stapling while signing. This code is only for demo purposes and not for 44 // production use since there is no caching in the SDK and fetching is expensive. This is behind the 45 // feature flag 'psxxx_ocsp_stapling_experimental' 46 fn update_ocsp(&self) { 47 // do we need an update 48 let now = chrono::offset::Utc::now(); 49 50 // is it time for an OCSP update 51 let ocsp_data = self.ocsp_rsp.take(); 52 let next_update = ocsp_data.next_update; 53 self.ocsp_rsp.set(ocsp_data); 54 if now > next_update { 55 #[cfg(feature = "psxxx_ocsp_stapling_experimental")] 56 { 57 if let Ok(certs) = self.certs() { 58 if let Some(ocsp_rsp) = crate::ocsp_utils::fetch_ocsp_response(&certs) { 59 self.ocsp_size.set(ocsp_rsp.len()); 60 let mut validation_log = 61 crate::status_tracker::DetailedStatusTracker::default(); 62 if let Ok(ocsp_data) = crate::ocsp_utils::check_ocsp_response( 63 &ocsp_rsp, 64 None, 65 &mut validation_log, 66 ) { 67 self.ocsp_rsp.set(ocsp_data); 68 } 69 } 70 } 71 } 72 } 73 } 74 } 75 76 impl ConfigurableSigner for RsaSigner { 77 fn from_signcert_and_pkey( 78 signcert: &[u8], 79 pkey: &[u8], 80 alg: SigningAlg, 81 tsa_url: Option<String>, 82 ) -> Result<Self> { 83 let signcerts = X509::stack_from_pem(signcert).map_err(wrap_openssl_err)?; 84 let rsa = Rsa::private_key_from_pem(pkey).map_err(wrap_openssl_err)?; 85 86 // rebuild RSA keys to eliminate incompatible values 87 let n = rsa.n().to_owned().map_err(wrap_openssl_err)?; 88 let e = rsa.e().to_owned().map_err(wrap_openssl_err)?; 89 let d = rsa.d().to_owned().map_err(wrap_openssl_err)?; 90 let po = rsa.p(); 91 let qo = rsa.q(); 92 let dmp1o = rsa.dmp1(); 93 let dmq1o = rsa.dmq1(); 94 let iqmpo = rsa.iqmp(); 95 let mut builder = RsaPrivateKeyBuilder::new(n, e, d).map_err(wrap_openssl_err)?; 96 97 if let Some(p) = po { 98 if let Some(q) = qo { 99 builder = builder 100 .set_factors(p.to_owned()?, q.to_owned()?) 101 .map_err(wrap_openssl_err)?; 102 } 103 } 104 105 if let Some(dmp1) = dmp1o { 106 if let Some(dmq1) = dmq1o { 107 if let Some(iqmp) = iqmpo { 108 builder = builder 109 .set_crt_params(dmp1.to_owned()?, dmq1.to_owned()?, iqmp.to_owned()?) 110 .map_err(wrap_openssl_err)?; 111 } 112 } 113 } 114 115 let new_rsa = builder.build(); 116 117 let pkey = PKey::from_rsa(new_rsa).map_err(wrap_openssl_err)?; 118 119 // make sure cert chains are in order 120 if !check_chain_order(&signcerts) { 121 return Err(Error::BadParam( 122 "certificate chain is not in correct order".to_string(), 123 )); 124 } 125 126 let signer = RsaSigner { 127 signcerts, 128 pkey, 129 certs_size: signcert.len(), 130 timestamp_size: 10000, /* todo: call out to TSA to get actual timestamp and use that size */ 131 ocsp_size: Cell::new(0), 132 alg, 133 tsa_url, 134 ocsp_rsp: Cell::new(OcspData::new()), 135 }; 136 137 // get OCSP if possible 138 signer.update_ocsp(); 139 140 Ok(signer) 141 } 142 } 143 144 impl Signer for RsaSigner { 145 fn sign(&self, data: &[u8]) -> Result<Vec<u8>> { 146 let mut signer = match self.alg { 147 SigningAlg::Ps256 => { 148 let mut signer = openssl::sign::Signer::new(MessageDigest::sha256(), &self.pkey) 149 .map_err(wrap_openssl_err)?; 150 151 signer.set_rsa_padding(openssl::rsa::Padding::PKCS1_PSS)?; // use C2PA recommended padding 152 signer.set_rsa_mgf1_md(MessageDigest::sha256())?; 153 signer.set_rsa_pss_saltlen(openssl::sign::RsaPssSaltlen::DIGEST_LENGTH)?; 154 signer 155 } 156 SigningAlg::Ps384 => { 157 let mut signer = openssl::sign::Signer::new(MessageDigest::sha384(), &self.pkey) 158 .map_err(wrap_openssl_err)?; 159 160 signer.set_rsa_padding(openssl::rsa::Padding::PKCS1_PSS)?; // use C2PA recommended padding 161 signer.set_rsa_mgf1_md(MessageDigest::sha384())?; 162 signer.set_rsa_pss_saltlen(openssl::sign::RsaPssSaltlen::DIGEST_LENGTH)?; 163 signer 164 } 165 SigningAlg::Ps512 => { 166 let mut signer = openssl::sign::Signer::new(MessageDigest::sha512(), &self.pkey) 167 .map_err(wrap_openssl_err)?; 168 169 signer.set_rsa_padding(openssl::rsa::Padding::PKCS1_PSS)?; // use C2PA recommended padding 170 signer.set_rsa_mgf1_md(MessageDigest::sha512())?; 171 signer.set_rsa_pss_saltlen(openssl::sign::RsaPssSaltlen::DIGEST_LENGTH)?; 172 signer 173 } 174 // "rs256" => openssl::sign::Signer::new(MessageDigest::sha256(), &self.pkey) 175 // .map_err(wrap_openssl_err)?, 176 // "rs384" => openssl::sign::Signer::new(MessageDigest::sha384(), &self.pkey) 177 // .map_err(wrap_openssl_err)?, 178 // "rs512" => openssl::sign::Signer::new(MessageDigest::sha512(), &self.pkey) 179 // .map_err(wrap_openssl_err)?, 180 _ => return Err(Error::UnsupportedType), 181 }; 182 183 let signed_data = signer.sign_oneshot_to_vec(data)?; 184 185 // println!("sig: {}", Hexlify(&signed_data)); 186 187 Ok(signed_data) 188 } 189 190 fn reserve_size(&self) -> usize { 191 1024 + self.certs_size + self.timestamp_size + self.ocsp_size.get() // the Cose_Sign1 contains complete certs, timestamps and ocsp so account for size 192 } 193 194 fn certs(&self) -> Result<Vec<Vec<u8>>> { 195 let mut certs: Vec<Vec<u8>> = Vec::new(); 196 197 for c in &self.signcerts { 198 let cert = c.to_der().map_err(wrap_openssl_err)?; 199 certs.push(cert); 200 } 201 202 Ok(certs) 203 } 204 205 fn alg(&self) -> SigningAlg { 206 self.alg 207 } 208 209 fn time_authority_url(&self) -> Option<String> { 210 self.tsa_url.clone() 211 } 212 213 fn ocsp_val(&self) -> Option<Vec<u8>> { 214 // update OCSP if needed 215 self.update_ocsp(); 216 217 let ocsp_data = self.ocsp_rsp.take(); 218 let ocsp_rsp = ocsp_data.ocsp_der.clone(); 219 self.ocsp_rsp.set(ocsp_data); 220 if !ocsp_rsp.is_empty() { 221 Some(ocsp_rsp) 222 } else { 223 None 224 } 225 } 226 } 227 228 const fn wrap_openssl_err(err: openssl::error::ErrorStack) -> Error { 229 Error::OpenSslError(err) 230 } 231 232 #[allow(unused_imports)] 233 #[allow(clippy::unwrap_used)] 234 #[cfg(test)] 235 mod tests { 236 237 use super::*; 238 use crate::{ 239 utils::test::{fixture_path, temp_signer}, 240 Signer, SigningAlg, 241 }; 242 243 #[test] 244 fn signer_from_files() { 245 let signer = temp_signer(); 246 let data = b"some sample content to sign"; 247 248 let signature = signer.sign(data).unwrap(); 249 println!("signature len = {}", signature.len()); 250 assert!(signature.len() <= signer.reserve_size()); 251 } 252 253 #[test] 254 fn sign_ps256() { 255 let cert_bytes = include_bytes!("../../tests/fixtures/temp_cert.data"); 256 let key_bytes = include_bytes!("../../tests/fixtures/temp_priv_key.data"); 257 258 let signer = 259 RsaSigner::from_signcert_and_pkey(cert_bytes, key_bytes, SigningAlg::Ps256, None) 260 .unwrap(); 261 262 let data = b"some sample content to sign"; 263 264 let signature = signer.sign(data).unwrap(); 265 println!("signature len = {}", signature.len()); 266 assert!(signature.len() <= signer.reserve_size()); 267 } 268 269 // #[test] 270 // fn sign_rs256() { 271 // let cert_bytes = include_bytes!("../../tests/fixtures/temp_cert.data"); 272 // let key_bytes = include_bytes!("../../tests/fixtures/temp_priv_key.data"); 273 274 // let signer = 275 // RsaSigner::from_signcert_and_pkey(cert_bytes, key_bytes, "rs256".to_string(), None) 276 // .unwrap(); 277 278 // let data = b"some sample content to sign"; 279 280 // let signature = signer.sign(data).unwrap(); 281 // println!("signature len = {}", signature.len()); 282 // assert!(signature.len() <= signer.reserve_size()); 283 // } 284 }