1 //! PKCS #12 archives. 2 3 use foreign_types::{ForeignType, ForeignTypeRef}; 4 use libc::c_int; 5 use std::ffi::CString; 6 use std::ptr; 7 8 use crate::error::ErrorStack; 9 #[cfg(not(boringssl))] 10 use crate::hash::MessageDigest; 11 use crate::nid::Nid; 12 use crate::pkey::{HasPrivate, PKey, PKeyRef, Private}; 13 use crate::stack::Stack; 14 use crate::util::ForeignTypeExt; 15 use crate::x509::{X509Ref, X509}; 16 use crate::{cvt, cvt_p}; 17 use openssl_macros::corresponds; 18 19 foreign_type_and_impl_send_sync! { 20 type CType = ffi::PKCS12; 21 fn drop = ffi::PKCS12_free; 22 23 pub struct Pkcs12; 24 pub struct Pkcs12Ref; 25 } 26 27 impl Pkcs12Ref { 28 to_der! { 29 /// Serializes the `Pkcs12` to its standard DER encoding. 30 #[corresponds(i2d_PKCS12)] 31 to_der, 32 ffi::i2d_PKCS12 33 } 34 35 /// Deprecated. 36 #[deprecated(note = "Use parse2 instead", since = "0.10.46")] 37 #[allow(deprecated)] parse(&self, pass: &str) -> Result<ParsedPkcs12, ErrorStack>38 pub fn parse(&self, pass: &str) -> Result<ParsedPkcs12, ErrorStack> { 39 let parsed = self.parse2(pass)?; 40 41 Ok(ParsedPkcs12 { 42 pkey: parsed.pkey.unwrap(), 43 cert: parsed.cert.unwrap(), 44 chain: parsed.ca, 45 }) 46 } 47 48 /// Extracts the contents of the `Pkcs12`. 49 #[corresponds(PKCS12_parse)] parse2(&self, pass: &str) -> Result<ParsedPkcs12_2, ErrorStack>50 pub fn parse2(&self, pass: &str) -> Result<ParsedPkcs12_2, ErrorStack> { 51 unsafe { 52 let pass = CString::new(pass.as_bytes()).unwrap(); 53 54 let mut pkey = ptr::null_mut(); 55 let mut cert = ptr::null_mut(); 56 let mut ca = ptr::null_mut(); 57 58 cvt(ffi::PKCS12_parse( 59 self.as_ptr(), 60 pass.as_ptr(), 61 &mut pkey, 62 &mut cert, 63 &mut ca, 64 ))?; 65 66 let pkey = PKey::from_ptr_opt(pkey); 67 let cert = X509::from_ptr_opt(cert); 68 let ca = Stack::from_ptr_opt(ca); 69 70 Ok(ParsedPkcs12_2 { pkey, cert, ca }) 71 } 72 } 73 } 74 75 impl Pkcs12 { 76 from_der! { 77 /// Deserializes a DER-encoded PKCS#12 archive. 78 #[corresponds(d2i_PKCS12)] 79 from_der, 80 Pkcs12, 81 ffi::d2i_PKCS12 82 } 83 84 /// Creates a new builder for a protected pkcs12 certificate. 85 /// 86 /// This uses the defaults from the OpenSSL library: 87 /// 88 /// * `nid_key` - `AES_256_CBC` (3.0.0+) or `PBE_WITHSHA1AND3_KEY_TRIPLEDES_CBC` 89 /// * `nid_cert` - `AES_256_CBC` (3.0.0+) or `PBE_WITHSHA1AND40BITRC2_CBC` 90 /// * `iter` - `2048` 91 /// * `mac_iter` - `2048` 92 /// * `mac_md` - `SHA-256` (3.0.0+) or `SHA-1` (`SHA-1` only for BoringSSL) builder() -> Pkcs12Builder93 pub fn builder() -> Pkcs12Builder { 94 ffi::init(); 95 96 Pkcs12Builder { 97 name: None, 98 pkey: None, 99 cert: None, 100 ca: None, 101 nid_key: Nid::UNDEF, 102 nid_cert: Nid::UNDEF, 103 iter: ffi::PKCS12_DEFAULT_ITER, 104 mac_iter: ffi::PKCS12_DEFAULT_ITER, 105 #[cfg(not(boringssl))] 106 mac_md: None, 107 } 108 } 109 } 110 111 #[deprecated(note = "Use ParsedPkcs12_2 instead", since = "0.10.46")] 112 pub struct ParsedPkcs12 { 113 pub pkey: PKey<Private>, 114 pub cert: X509, 115 pub chain: Option<Stack<X509>>, 116 } 117 118 pub struct ParsedPkcs12_2 { 119 pub pkey: Option<PKey<Private>>, 120 pub cert: Option<X509>, 121 pub ca: Option<Stack<X509>>, 122 } 123 124 pub struct Pkcs12Builder { 125 // FIXME borrow 126 name: Option<CString>, 127 pkey: Option<PKey<Private>>, 128 cert: Option<X509>, 129 ca: Option<Stack<X509>>, 130 nid_key: Nid, 131 nid_cert: Nid, 132 iter: c_int, 133 mac_iter: c_int, 134 // FIXME remove 135 #[cfg(not(boringssl))] 136 mac_md: Option<MessageDigest>, 137 } 138 139 impl Pkcs12Builder { 140 /// The `friendlyName` used for the certificate and private key. name(&mut self, name: &str) -> &mut Self141 pub fn name(&mut self, name: &str) -> &mut Self { 142 self.name = Some(CString::new(name).unwrap()); 143 self 144 } 145 146 /// The private key. pkey<T>(&mut self, pkey: &PKeyRef<T>) -> &mut Self where T: HasPrivate,147 pub fn pkey<T>(&mut self, pkey: &PKeyRef<T>) -> &mut Self 148 where 149 T: HasPrivate, 150 { 151 let new_pkey = unsafe { PKeyRef::from_ptr(pkey.as_ptr()) }; 152 self.pkey = Some(new_pkey.to_owned()); 153 self 154 } 155 156 /// The certificate. cert(&mut self, cert: &X509Ref) -> &mut Self157 pub fn cert(&mut self, cert: &X509Ref) -> &mut Self { 158 self.cert = Some(cert.to_owned()); 159 self 160 } 161 162 /// An additional set of certificates to include in the archive beyond the one provided to 163 /// `build`. ca(&mut self, ca: Stack<X509>) -> &mut Self164 pub fn ca(&mut self, ca: Stack<X509>) -> &mut Self { 165 self.ca = Some(ca); 166 self 167 } 168 169 /// The encryption algorithm that should be used for the key key_algorithm(&mut self, nid: Nid) -> &mut Self170 pub fn key_algorithm(&mut self, nid: Nid) -> &mut Self { 171 self.nid_key = nid; 172 self 173 } 174 175 /// The encryption algorithm that should be used for the cert cert_algorithm(&mut self, nid: Nid) -> &mut Self176 pub fn cert_algorithm(&mut self, nid: Nid) -> &mut Self { 177 self.nid_cert = nid; 178 self 179 } 180 181 /// Key iteration count, default is 2048 as of this writing key_iter(&mut self, iter: u32) -> &mut Self182 pub fn key_iter(&mut self, iter: u32) -> &mut Self { 183 self.iter = iter as c_int; 184 self 185 } 186 187 /// MAC iteration count, default is the same as key_iter. 188 /// 189 /// Old implementations don't understand MAC iterations greater than 1, (pre 1.0.1?), if such 190 /// compatibility is required this should be set to 1. mac_iter(&mut self, mac_iter: u32) -> &mut Self191 pub fn mac_iter(&mut self, mac_iter: u32) -> &mut Self { 192 self.mac_iter = mac_iter as c_int; 193 self 194 } 195 196 /// MAC message digest type 197 #[cfg(not(boringssl))] mac_md(&mut self, md: MessageDigest) -> &mut Self198 pub fn mac_md(&mut self, md: MessageDigest) -> &mut Self { 199 self.mac_md = Some(md); 200 self 201 } 202 203 /// Deprecated. 204 #[deprecated( 205 note = "Use Self::{name, pkey, cert, build2} instead.", 206 since = "0.10.46" 207 )] build<T>( mut self, password: &str, friendly_name: &str, pkey: &PKeyRef<T>, cert: &X509Ref, ) -> Result<Pkcs12, ErrorStack> where T: HasPrivate,208 pub fn build<T>( 209 mut self, 210 password: &str, 211 friendly_name: &str, 212 pkey: &PKeyRef<T>, 213 cert: &X509Ref, 214 ) -> Result<Pkcs12, ErrorStack> 215 where 216 T: HasPrivate, 217 { 218 self.name(friendly_name) 219 .pkey(pkey) 220 .cert(cert) 221 .build2(password) 222 } 223 224 /// Builds the PKCS#12 object. 225 #[corresponds(PKCS12_create)] build2(&self, password: &str) -> Result<Pkcs12, ErrorStack>226 pub fn build2(&self, password: &str) -> Result<Pkcs12, ErrorStack> { 227 unsafe { 228 let pass = CString::new(password).unwrap(); 229 let pass = pass.as_ptr(); 230 let friendly_name = self.name.as_ref().map_or(ptr::null(), |p| p.as_ptr()); 231 let pkey = self.pkey.as_ref().map_or(ptr::null(), |p| p.as_ptr()); 232 let cert = self.cert.as_ref().map_or(ptr::null(), |p| p.as_ptr()); 233 let ca = self 234 .ca 235 .as_ref() 236 .map(|ca| ca.as_ptr()) 237 .unwrap_or(ptr::null_mut()); 238 let nid_key = self.nid_key.as_raw(); 239 let nid_cert = self.nid_cert.as_raw(); 240 241 // According to the OpenSSL docs, keytype is a non-standard extension for MSIE, 242 // It's values are KEY_SIG or KEY_EX, see the OpenSSL docs for more information: 243 // https://www.openssl.org/docs/manmaster/crypto/PKCS12_create.html 244 let keytype = 0; 245 246 let pkcs12 = cvt_p(ffi::PKCS12_create( 247 pass as *mut _, 248 friendly_name as *mut _, 249 pkey as *mut _, 250 cert as *mut _, 251 ca, 252 nid_key, 253 nid_cert, 254 self.iter, 255 self.mac_iter, 256 keytype, 257 )) 258 .map(Pkcs12)?; 259 260 #[cfg(not(boringssl))] 261 // BoringSSL does not support overriding the MAC and will always 262 // use SHA-1 263 { 264 let md_type = self 265 .mac_md 266 .map(|md_type| md_type.as_ptr()) 267 .unwrap_or(ptr::null()); 268 269 cvt(ffi::PKCS12_set_mac( 270 pkcs12.as_ptr(), 271 pass, 272 -1, 273 ptr::null_mut(), 274 0, 275 self.mac_iter, 276 md_type, 277 ))?; 278 } 279 280 Ok(pkcs12) 281 } 282 } 283 } 284 285 #[cfg(test)] 286 mod test { 287 use crate::asn1::Asn1Time; 288 use crate::hash::MessageDigest; 289 use crate::nid::Nid; 290 use crate::pkey::PKey; 291 use crate::rsa::Rsa; 292 use crate::x509::extension::KeyUsage; 293 use crate::x509::{X509Name, X509}; 294 295 use super::*; 296 297 #[test] parse()298 fn parse() { 299 #[cfg(ossl300)] 300 let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); 301 302 let der = include_bytes!("../test/identity.p12"); 303 let pkcs12 = Pkcs12::from_der(der).unwrap(); 304 let parsed = pkcs12.parse2("mypass").unwrap(); 305 306 assert_eq!( 307 hex::encode( 308 parsed 309 .cert 310 .as_ref() 311 .unwrap() 312 .digest(MessageDigest::sha1()) 313 .unwrap() 314 ), 315 "59172d9313e84459bcff27f967e79e6e9217e584" 316 ); 317 assert_eq!( 318 parsed.cert.as_ref().unwrap().alias(), 319 Some(b"foobar.com" as &[u8]) 320 ); 321 322 let chain = parsed.ca.unwrap(); 323 assert_eq!(chain.len(), 1); 324 assert_eq!( 325 hex::encode(chain[0].digest(MessageDigest::sha1()).unwrap()), 326 "c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875" 327 ); 328 } 329 330 #[test] parse_empty_chain()331 fn parse_empty_chain() { 332 #[cfg(ossl300)] 333 let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); 334 335 let der = include_bytes!("../test/keystore-empty-chain.p12"); 336 let pkcs12 = Pkcs12::from_der(der).unwrap(); 337 let parsed = pkcs12.parse2("cassandra").unwrap(); 338 if let Some(stack) = parsed.ca { 339 assert_eq!(stack.len(), 0); 340 } 341 } 342 343 #[test] create()344 fn create() { 345 let subject_name = "ns.example.com"; 346 let rsa = Rsa::generate(2048).unwrap(); 347 let pkey = PKey::from_rsa(rsa).unwrap(); 348 349 let mut name = X509Name::builder().unwrap(); 350 name.append_entry_by_nid(Nid::COMMONNAME, subject_name) 351 .unwrap(); 352 let name = name.build(); 353 354 let key_usage = KeyUsage::new().digital_signature().build().unwrap(); 355 356 let mut builder = X509::builder().unwrap(); 357 builder.set_version(2).unwrap(); 358 builder 359 .set_not_before(&Asn1Time::days_from_now(0).unwrap()) 360 .unwrap(); 361 builder 362 .set_not_after(&Asn1Time::days_from_now(365).unwrap()) 363 .unwrap(); 364 builder.set_subject_name(&name).unwrap(); 365 builder.set_issuer_name(&name).unwrap(); 366 builder.append_extension(key_usage).unwrap(); 367 builder.set_pubkey(&pkey).unwrap(); 368 builder.sign(&pkey, MessageDigest::sha256()).unwrap(); 369 let cert = builder.build(); 370 371 let pkcs12 = Pkcs12::builder() 372 .name(subject_name) 373 .pkey(&pkey) 374 .cert(&cert) 375 .build2("mypass") 376 .unwrap(); 377 let der = pkcs12.to_der().unwrap(); 378 379 let pkcs12 = Pkcs12::from_der(&der).unwrap(); 380 let parsed = pkcs12.parse2("mypass").unwrap(); 381 382 assert_eq!( 383 &*parsed.cert.unwrap().digest(MessageDigest::sha1()).unwrap(), 384 &*cert.digest(MessageDigest::sha1()).unwrap() 385 ); 386 assert!(parsed.pkey.unwrap().public_eq(&pkey)); 387 } 388 389 #[test] create_only_ca()390 fn create_only_ca() { 391 let ca = include_bytes!("../test/root-ca.pem"); 392 let ca = X509::from_pem(ca).unwrap(); 393 let mut chain = Stack::new().unwrap(); 394 chain.push(ca).unwrap(); 395 396 let pkcs12 = Pkcs12::builder().ca(chain).build2("hunter2").unwrap(); 397 let parsed = pkcs12.parse2("hunter2").unwrap(); 398 399 assert!(parsed.cert.is_none()); 400 assert!(parsed.pkey.is_none()); 401 assert_eq!(parsed.ca.unwrap().len(), 1); 402 } 403 } 404