1 //! Bindings to winapi's `PCCERT_CONTEXT` APIs. 2 3 use std::ffi::{CStr, OsString}; 4 use std::io; 5 use std::mem; 6 use std::os::windows::prelude::*; 7 use std::ptr; 8 use std::slice; 9 use winapi::shared::minwindef as winapi; 10 use winapi::shared::ntdef; 11 use winapi::shared::winerror; 12 use winapi::um::wincrypt; 13 14 use crate::Inner; 15 use crate::ncrypt_key::NcryptKey; 16 use crate::crypt_prov::{CryptProv, ProviderType}; 17 use crate::cert_store::CertStore; 18 19 /// A supported hashing algorithm 20 pub struct HashAlgorithm(winapi::DWORD, usize); 21 22 #[allow(missing_docs)] 23 impl HashAlgorithm { md5() -> HashAlgorithm24 pub fn md5() -> HashAlgorithm { 25 HashAlgorithm(wincrypt::CALG_MD5, 16) 26 } 27 sha1() -> HashAlgorithm28 pub fn sha1() -> HashAlgorithm{ 29 HashAlgorithm(wincrypt::CALG_SHA1, 20) 30 } 31 sha256() -> HashAlgorithm32 pub fn sha256() -> HashAlgorithm { 33 HashAlgorithm(wincrypt::CALG_SHA_256, 32) 34 } 35 sha384() -> HashAlgorithm36 pub fn sha384() -> HashAlgorithm { 37 HashAlgorithm(wincrypt::CALG_SHA_384, 48) 38 } 39 sha512() -> HashAlgorithm40 pub fn sha512() -> HashAlgorithm { 41 HashAlgorithm(wincrypt::CALG_SHA_512, 64) 42 } 43 } 44 45 /// Wrapper of a winapi certificate, or a `PCCERT_CONTEXT`. 46 #[derive(Debug)] 47 pub struct CertContext(wincrypt::PCCERT_CONTEXT); 48 49 unsafe impl Sync for CertContext {} 50 unsafe impl Send for CertContext {} 51 52 impl Drop for CertContext { drop(&mut self)53 fn drop(&mut self) { 54 unsafe { 55 wincrypt::CertFreeCertificateContext(self.0); 56 } 57 } 58 } 59 60 impl Clone for CertContext { clone(&self) -> CertContext61 fn clone(&self) -> CertContext { 62 unsafe { CertContext(wincrypt::CertDuplicateCertificateContext(self.0)) } 63 } 64 } 65 66 inner!(CertContext, wincrypt::PCCERT_CONTEXT); 67 68 impl CertContext { 69 /// Decodes a DER-formatted X509 certificate. new(data: &[u8]) -> io::Result<CertContext>70 pub fn new(data: &[u8]) -> io::Result<CertContext> { 71 let ret = unsafe { 72 wincrypt::CertCreateCertificateContext(wincrypt::X509_ASN_ENCODING | 73 wincrypt::PKCS_7_ASN_ENCODING, 74 data.as_ptr(), 75 data.len() as winapi::DWORD) 76 }; 77 if ret.is_null() { 78 Err(io::Error::last_os_error()) 79 } else { 80 Ok(CertContext(ret)) 81 } 82 } 83 84 /// Get certificate in binary DER form to_der<'a>(&'a self) -> &'a [u8]85 pub fn to_der<'a>(&'a self) -> &'a [u8] { 86 self.get_encoded_bytes() 87 } 88 89 /// Certificate subject public key info subject_public_key_info_der(&self) -> io::Result<Vec<u8>>90 pub fn subject_public_key_info_der(&self) -> io::Result<Vec<u8>> { 91 unsafe { 92 let mut len:u32 = 0; 93 let ok = wincrypt::CryptEncodeObjectEx(wincrypt::X509_ASN_ENCODING, 94 wincrypt::CERT_INFO_SUBJECT_PUBLIC_KEY_INFO_FLAG as *const u32 as *const _, 95 &(*(*self.0).pCertInfo).SubjectPublicKeyInfo as *const wincrypt::CERT_PUBLIC_KEY_INFO as _, 96 0, 97 ptr::null_mut(), 98 ptr::null_mut(), 99 &mut len as *mut _); 100 if ok != winapi::TRUE { 101 return Err(io::Error::last_os_error()); 102 } 103 if len > 0 { 104 let mut buf = vec![0; len as usize]; 105 let ok = wincrypt::CryptEncodeObjectEx(wincrypt::X509_ASN_ENCODING, 106 wincrypt::CERT_INFO_SUBJECT_PUBLIC_KEY_INFO_FLAG as *const u32 as *const _, 107 &(*(*self.0).pCertInfo).SubjectPublicKeyInfo as *const wincrypt::CERT_PUBLIC_KEY_INFO as _, 108 0, 109 ptr::null_mut(), 110 buf.as_mut_ptr() as _, 111 &mut len as *mut _); 112 if ok != winapi::TRUE { 113 return Err(io::Error::last_os_error()); 114 } 115 return Ok(buf); 116 } 117 } 118 Err(io::Error::last_os_error()) 119 } 120 121 /// Decodes a PEM-formatted X509 certificate. from_pem(pem: &str) -> io::Result<CertContext>122 pub fn from_pem(pem: &str) -> io::Result<CertContext> { 123 unsafe { 124 assert!(pem.len() <= winapi::DWORD::max_value() as usize); 125 126 let mut len = 0; 127 let ok = wincrypt::CryptStringToBinaryA(pem.as_ptr() as ntdef::LPCSTR, 128 pem.len() as winapi::DWORD, 129 wincrypt::CRYPT_STRING_BASE64HEADER, 130 ptr::null_mut(), 131 &mut len, 132 ptr::null_mut(), 133 ptr::null_mut()); 134 if ok != winapi::TRUE { 135 return Err(io::Error::last_os_error()); 136 } 137 138 let mut buf = vec![0; len as usize]; 139 let ok = wincrypt::CryptStringToBinaryA(pem.as_ptr() as ntdef::LPCSTR, 140 pem.len() as winapi::DWORD, 141 wincrypt::CRYPT_STRING_BASE64HEADER, 142 buf.as_mut_ptr(), 143 &mut len, 144 ptr::null_mut(), 145 ptr::null_mut()); 146 if ok != winapi::TRUE { 147 return Err(io::Error::last_os_error()); 148 } 149 150 CertContext::new(&buf) 151 } 152 } 153 154 /// Get certificate as PEM-formatted X509 certificate. to_pem(&self) -> io::Result<String>155 pub fn to_pem(&self) -> io::Result<String> { 156 unsafe { 157 let mut len = 0; 158 let ok = wincrypt::CryptBinaryToStringA( 159 (*self.0).pbCertEncoded, 160 (*self.0).cbCertEncoded, 161 wincrypt::CRYPT_STRING_BASE64HEADER, 162 ptr::null_mut(), 163 &mut len, 164 ); 165 if ok != winapi::TRUE { 166 return Err(io::Error::last_os_error()); 167 } 168 169 let mut buf = vec![0; len as usize]; 170 let ok = wincrypt::CryptBinaryToStringA( 171 (*self.0).pbCertEncoded, 172 (*self.0).cbCertEncoded, 173 wincrypt::CRYPT_STRING_BASE64HEADER, 174 buf.as_mut_ptr(), 175 &mut len, 176 ); 177 if ok != winapi::TRUE { 178 return Err(io::Error::last_os_error()); 179 } 180 181 Ok(CStr::from_ptr(buf.as_ptr()).to_string_lossy().into_owned()) 182 } 183 } 184 185 /// Returns a hash of this certificate fingerprint(&self, alg: HashAlgorithm) -> io::Result<Vec<u8>>186 pub fn fingerprint(&self, alg: HashAlgorithm) -> io::Result<Vec<u8>> { 187 unsafe { 188 let mut buf = vec![0u8; alg.1]; 189 let mut len = buf.len() as winapi::DWORD; 190 191 let ret = wincrypt::CryptHashCertificate(0, 192 alg.0, 193 0, 194 (*self.0).pbCertEncoded, 195 (*self.0).cbCertEncoded, 196 buf.as_mut_ptr(), 197 &mut len); 198 199 if ret != winapi::TRUE { 200 return Err(io::Error::last_os_error()); 201 } 202 Ok(buf) 203 } 204 } 205 206 /// Returns the sha1 hash of this certificate 207 /// 208 /// The sha1 is returned as a 20-byte array representing the bits of the 209 /// sha1 hash. 210 #[deprecated(note = "please use fingerprint instead")] sha1(&self) -> io::Result<[u8; 20]>211 pub fn sha1(&self) -> io::Result<[u8; 20]> { 212 let mut out = [0u8; 20]; 213 out.copy_from_slice(&self.fingerprint(HashAlgorithm::sha1())?); 214 Ok(out) 215 } 216 217 /// Returns the `<SIGNATURE>/<HASH>` string representing the certificate 218 /// signature. 219 /// 220 /// The `<SIGNATURE>` value identifies the CNG public key 221 /// algorithm. The `<HASH>` value identifies the CNG hash algorithm. 222 /// 223 /// Common examples are: 224 /// 225 /// * `RSA/SHA1` 226 /// * `RSA/SHA256` 227 /// * `ECDSA/SHA256` sign_hash_algorithms(&self) -> io::Result<String>228 pub fn sign_hash_algorithms(&self) -> io::Result<String> { 229 self.get_string(wincrypt::CERT_SIGN_HASH_CNG_ALG_PROP_ID) 230 } 231 232 /// Returns the signature hash. signature_hash(&self) -> io::Result<Vec<u8>>233 pub fn signature_hash(&self) -> io::Result<Vec<u8>> { 234 self.get_bytes(wincrypt::CERT_SIGNATURE_HASH_PROP_ID) 235 } 236 237 /// Returns the property displayed by the certificate UI. This property 238 /// allows the user to describe the certificate's use. description(&self) -> io::Result<Vec<u8>>239 pub fn description(&self) -> io::Result<Vec<u8>> { 240 self.get_bytes(wincrypt::CERT_DESCRIPTION_PROP_ID) 241 } 242 243 /// Returns a string that contains the display name for the certificate. friendly_name(&self) -> io::Result<String>244 pub fn friendly_name(&self) -> io::Result<String> { 245 self.get_string(wincrypt::CERT_FRIENDLY_NAME_PROP_ID) 246 } 247 248 /// Configures the string that contains the display name for this 249 /// certificate. set_friendly_name(&self, name: &str) -> io::Result<()>250 pub fn set_friendly_name(&self, name: &str) -> io::Result<()> { 251 self.set_string(wincrypt::CERT_FRIENDLY_NAME_PROP_ID, name) 252 } 253 254 /// Verifies the time validity of this certificate relative to the system's 255 /// current time. is_time_valid(&self) -> io::Result<bool>256 pub fn is_time_valid(&self) -> io::Result<bool> { 257 let ret = unsafe { wincrypt::CertVerifyTimeValidity(ptr::null_mut(), (*self.0).pCertInfo) }; 258 Ok(ret == 0) 259 } 260 261 /// Returns a builder used to acquire the private key corresponding to this certificate. private_key<'a>(&'a self) -> AcquirePrivateKeyOptions<'a>262 pub fn private_key<'a>(&'a self) -> AcquirePrivateKeyOptions<'a> { 263 AcquirePrivateKeyOptions { 264 cert: self, 265 flags: 0, 266 } 267 } 268 269 /// Deletes this certificate from its certificate store. delete(self) -> io::Result<()>270 pub fn delete(self) -> io::Result<()> { 271 unsafe { 272 let ret = wincrypt::CertDeleteCertificateFromStore(self.0); 273 mem::forget(self); 274 if ret == winapi::TRUE { 275 Ok(()) 276 } else { 277 Err(io::Error::last_os_error()) 278 } 279 } 280 } 281 282 /// Returns a builder used to set the private key associated with this certificate. set_key_prov_info<'a>(&'a self) -> SetKeyProvInfo<'a>283 pub fn set_key_prov_info<'a>(&'a self) -> SetKeyProvInfo<'a> { 284 SetKeyProvInfo { 285 cert: self, 286 container: None, 287 provider: None, 288 type_: 0, 289 flags: 0, 290 key_spec: 0, 291 } 292 } 293 294 /// Returns the valid uses for this certificate valid_uses(&self) -> io::Result<ValidUses>295 pub fn valid_uses(&self) -> io::Result<ValidUses> { 296 unsafe { 297 let mut buf_len = 0; 298 let ok = wincrypt::CertGetEnhancedKeyUsage(self.0, 0, ptr::null_mut(), &mut buf_len); 299 300 if ok != winapi::TRUE { 301 return Err(io::Error::last_os_error()); 302 } 303 304 let mut buf = vec![0u8; buf_len as usize]; 305 let cert_enhkey_usage = buf.as_mut_ptr() as *mut wincrypt::CERT_ENHKEY_USAGE; 306 307 let ok = wincrypt::CertGetEnhancedKeyUsage(self.0, 0, cert_enhkey_usage, &mut buf_len); 308 if ok != winapi::TRUE { 309 return Err(io::Error::last_os_error()); 310 } 311 312 let use_cnt = (*cert_enhkey_usage).cUsageIdentifier; 313 if use_cnt == 0 { 314 let last_error = io::Error::last_os_error(); 315 match last_error.raw_os_error() { 316 Some(winerror::CRYPT_E_NOT_FOUND) => return Ok(ValidUses::All), 317 Some(0) => (), 318 _ => return Err(last_error), 319 }; 320 } 321 322 let mut oids: Vec<String> = Vec::with_capacity(use_cnt as usize); 323 for i in 0..use_cnt { 324 let oid_ptr = (*cert_enhkey_usage).rgpszUsageIdentifier; 325 oids.push( 326 CStr::from_ptr(*(oid_ptr.offset(i as isize))) 327 .to_string_lossy() 328 .into_owned(), 329 ); 330 } 331 Ok(ValidUses::Oids(oids)) 332 } 333 } 334 335 /// For a remote certificate, returns a certificate store containing any intermediate 336 /// certificates provided by the remote sender. cert_store(&self) -> Option<CertStore>337 pub fn cert_store(&self) -> Option<CertStore> { 338 unsafe { 339 let chain = (*self.0).hCertStore; 340 if chain.is_null() { 341 None 342 } else { 343 Some(CertStore::from_inner(wincrypt::CertDuplicateStore(chain))) 344 } 345 } 346 } 347 get_encoded_bytes<'a>(&'a self) -> &'a [u8]348 fn get_encoded_bytes<'a>(&'a self) -> &'a [u8] { 349 unsafe { 350 let cert_ctx = *self.0; 351 slice::from_raw_parts(cert_ctx.pbCertEncoded, cert_ctx.cbCertEncoded as usize) 352 } 353 } 354 get_bytes(&self, prop: winapi::DWORD) -> io::Result<Vec<u8>>355 fn get_bytes(&self, prop: winapi::DWORD) -> io::Result<Vec<u8>> { 356 unsafe { 357 let mut len = 0; 358 let ret = 359 wincrypt::CertGetCertificateContextProperty(self.0, prop, ptr::null_mut(), &mut len); 360 if ret != winapi::TRUE { 361 return Err(io::Error::last_os_error()); 362 } 363 364 let mut buf = vec![0u8; len as usize]; 365 let ret = wincrypt::CertGetCertificateContextProperty(self.0, 366 prop, 367 buf.as_mut_ptr() as winapi::LPVOID, 368 &mut len); 369 if ret != winapi::TRUE { 370 return Err(io::Error::last_os_error()); 371 } 372 Ok(buf) 373 } 374 } 375 get_string(&self, prop: winapi::DWORD) -> io::Result<String>376 fn get_string(&self, prop: winapi::DWORD) -> io::Result<String> { 377 unsafe { 378 let mut len = 0; 379 let ret = 380 wincrypt::CertGetCertificateContextProperty(self.0, prop, ptr::null_mut(), &mut len); 381 if ret != winapi::TRUE { 382 return Err(io::Error::last_os_error()); 383 } 384 385 // Divide by 2 b/c `len` is the byte length, but we're allocating 386 // u16 pairs which are 2 bytes each. 387 let amt = (len / 2) as usize; 388 let mut buf = vec![0u16; amt]; 389 let ret = wincrypt::CertGetCertificateContextProperty(self.0, 390 prop, 391 buf.as_mut_ptr() as winapi::LPVOID, 392 &mut len); 393 if ret != winapi::TRUE { 394 return Err(io::Error::last_os_error()); 395 } 396 397 // Chop off the trailing nul byte 398 Ok(OsString::from_wide(&buf[..amt - 1]).into_string().unwrap()) 399 } 400 } 401 set_string(&self, prop: winapi::DWORD, s: &str) -> io::Result<()>402 fn set_string(&self, prop: winapi::DWORD, s: &str) -> io::Result<()> { 403 unsafe { 404 let data = s.encode_utf16().chain(Some(0)).collect::<Vec<_>>(); 405 let data = wincrypt::CRYPT_DATA_BLOB { 406 cbData: (data.len() * 2) as winapi::DWORD, 407 pbData: data.as_ptr() as *mut _, 408 }; 409 let ret = wincrypt::CertSetCertificateContextProperty(self.0, 410 prop, 411 0, 412 &data as *const _ as *const _); 413 if ret != winapi::TRUE { 414 Err(io::Error::last_os_error()) 415 } else { 416 Ok(()) 417 } 418 } 419 } 420 } 421 422 impl PartialEq for CertContext { eq(&self, other: &CertContext) -> bool423 fn eq(&self, other: &CertContext) -> bool { 424 self.get_encoded_bytes() == other.get_encoded_bytes() 425 } 426 } 427 428 /// A builder type for certificate private key lookup. 429 pub struct AcquirePrivateKeyOptions<'a> { 430 cert: &'a CertContext, 431 flags: winapi::DWORD, 432 } 433 434 impl<'a> AcquirePrivateKeyOptions<'a> { 435 /// If set, the certificate's public key will be compared with the private key to ensure a 436 /// match. compare_key(&mut self, compare_key: bool) -> &mut AcquirePrivateKeyOptions<'a>437 pub fn compare_key(&mut self, compare_key: bool) -> &mut AcquirePrivateKeyOptions<'a> { 438 self.flag(wincrypt::CRYPT_ACQUIRE_COMPARE_KEY_FLAG, compare_key) 439 } 440 441 /// If set, the lookup will not display any user interface, even if that causes the lookup to 442 /// fail. silent(&mut self, silent: bool) -> &mut AcquirePrivateKeyOptions<'a>443 pub fn silent(&mut self, silent: bool) -> &mut AcquirePrivateKeyOptions<'a> { 444 self.flag(wincrypt::CRYPT_ACQUIRE_SILENT_FLAG, silent) 445 } 446 flag(&mut self, flag: winapi::DWORD, set: bool) -> &mut AcquirePrivateKeyOptions<'a>447 fn flag(&mut self, flag: winapi::DWORD, set: bool) -> &mut AcquirePrivateKeyOptions<'a> { 448 if set { 449 self.flags |= flag; 450 } else { 451 self.flags &= !flag; 452 } 453 self 454 } 455 456 /// Acquires the private key handle. acquire(&self) -> io::Result<PrivateKey>457 pub fn acquire(&self) -> io::Result<PrivateKey> { 458 unsafe { 459 let flags = self.flags | wincrypt::CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG; 460 let mut handle = 0; 461 let mut spec = 0; 462 let mut free = winapi::FALSE; 463 let res = wincrypt::CryptAcquireCertificatePrivateKey(self.cert.0, 464 flags, 465 ptr::null_mut(), 466 &mut handle, 467 &mut spec, 468 &mut free); 469 if res != winapi::TRUE { 470 return Err(io::Error::last_os_error()); 471 } 472 assert!(free == winapi::TRUE); 473 if spec & wincrypt::CERT_NCRYPT_KEY_SPEC != 0 { 474 Ok(PrivateKey::NcryptKey(NcryptKey::from_inner(handle))) 475 } else { 476 Ok(PrivateKey::CryptProv(CryptProv::from_inner(handle))) 477 } 478 } 479 } 480 } 481 482 /// The private key associated with a certificate context. 483 pub enum PrivateKey { 484 /// A CryptoAPI provider. 485 CryptProv(CryptProv), 486 /// A CNG provider. 487 NcryptKey(NcryptKey), 488 } 489 490 /// A builder used to set the private key associated with a certificate. 491 pub struct SetKeyProvInfo<'a> { 492 cert: &'a CertContext, 493 container: Option<Vec<u16>>, 494 provider: Option<Vec<u16>>, 495 type_: winapi::DWORD, 496 flags: winapi::DWORD, 497 key_spec: winapi::DWORD, 498 } 499 500 impl<'a> SetKeyProvInfo<'a> { 501 /// The name of the key container. 502 /// 503 /// If `type_` is not provided, this specifies the name of the key withing 504 /// the CNG key storage provider. container(&mut self, container: &str) -> &mut SetKeyProvInfo<'a>505 pub fn container(&mut self, container: &str) -> &mut SetKeyProvInfo<'a> { 506 self.container = Some(container.encode_utf16().chain(Some(0)).collect()); 507 self 508 } 509 510 /// The name of the CSP. 511 /// 512 /// If `type_` is not provided, this contains the name of the CNG key 513 /// storage provider. provider(&mut self, provider: &str) -> &mut SetKeyProvInfo<'a>514 pub fn provider(&mut self, provider: &str) -> &mut SetKeyProvInfo<'a> { 515 self.provider = Some(provider.encode_utf16().chain(Some(0)).collect()); 516 self 517 } 518 519 /// Sets the CSP type. 520 /// 521 /// If not provided, the key container is one of the CNG key storage 522 /// providers. type_(&mut self, type_: ProviderType) -> &mut SetKeyProvInfo<'a>523 pub fn type_(&mut self, type_: ProviderType) -> &mut SetKeyProvInfo<'a> { 524 self.type_ = type_.as_raw(); 525 self 526 } 527 528 /// If set, the handle to the key provider can be kept open for subsequent 529 /// calls to cryptographic functions. keep_open(&mut self, keep_open: bool) -> &mut SetKeyProvInfo<'a>530 pub fn keep_open(&mut self, keep_open: bool) -> &mut SetKeyProvInfo<'a> { 531 self.flag(wincrypt::CERT_SET_KEY_PROV_HANDLE_PROP_ID, keep_open) 532 } 533 534 /// If set, the key container contains machine keys. machine_keyset(&mut self, machine_keyset: bool) -> &mut SetKeyProvInfo<'a>535 pub fn machine_keyset(&mut self, machine_keyset: bool) -> &mut SetKeyProvInfo<'a> { 536 self.flag(wincrypt::CRYPT_MACHINE_KEYSET, machine_keyset) 537 } 538 539 /// If set, the key container will attempt to open keys without any user 540 /// interface prompts. silent(&mut self, silent: bool) -> &mut SetKeyProvInfo<'a>541 pub fn silent(&mut self, silent: bool) -> &mut SetKeyProvInfo<'a> { 542 self.flag(wincrypt::CRYPT_SILENT, silent) 543 } 544 flag(&mut self, flag: winapi::DWORD, on: bool) -> &mut SetKeyProvInfo<'a>545 fn flag(&mut self, flag: winapi::DWORD, on: bool) -> &mut SetKeyProvInfo<'a> { 546 if on { 547 self.flags |= flag; 548 } else { 549 self.flags &= !flag; 550 } 551 self 552 } 553 554 /// The specification of the private key to retrieve. key_spec(&mut self, key_spec: KeySpec) -> &mut SetKeyProvInfo<'a>555 pub fn key_spec(&mut self, key_spec: KeySpec) -> &mut SetKeyProvInfo<'a> { 556 self.key_spec = key_spec.0; 557 self 558 } 559 560 /// Sets the private key for this certificate. set(&mut self) -> io::Result<()>561 pub fn set(&mut self) -> io::Result<()> { 562 unsafe { 563 let container = self.container.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null()); 564 let provider = self.provider.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null()); 565 566 let info = wincrypt::CRYPT_KEY_PROV_INFO { 567 pwszContainerName: container as *mut _, 568 pwszProvName: provider as *mut _, 569 dwProvType: self.type_, 570 dwFlags: self.flags, 571 cProvParam: 0, 572 rgProvParam: ptr::null_mut(), 573 dwKeySpec: self.key_spec, 574 }; 575 576 let res = 577 wincrypt::CertSetCertificateContextProperty(self.cert.0, 578 wincrypt::CERT_KEY_PROV_INFO_PROP_ID, 579 0, 580 &info as *const _ as *const _); 581 if res == winapi::TRUE { 582 Ok(()) 583 } else { 584 Err(io::Error::last_os_error()) 585 } 586 } 587 } 588 } 589 590 /// The specification of a private key. 591 #[derive(Copy, Clone)] 592 pub struct KeySpec(winapi::DWORD); 593 594 impl KeySpec { 595 /// A key used to encrypt/decrypt session keys. key_exchange() -> KeySpec596 pub fn key_exchange() -> KeySpec { 597 KeySpec(wincrypt::AT_KEYEXCHANGE) 598 } 599 600 /// A key used to create and verify digital signatures. signature() -> KeySpec601 pub fn signature() -> KeySpec { 602 KeySpec(wincrypt::AT_SIGNATURE) 603 } 604 } 605 606 /// Valid uses of a Certificate - All, or specific OIDs 607 pub enum ValidUses { 608 /// Certificate is valid for all uses 609 All, 610 611 /// Certificate is valid for uses specified. No entries means that the certificate 612 /// has no valid uses. 613 Oids(Vec<String>), 614 } 615 616 #[cfg(test)] 617 mod test { 618 use super::*; 619 620 #[test] decode()621 fn decode() { 622 let der = include_bytes!("../test/cert.der"); 623 let pem = include_str!("../test/cert.pem"); 624 625 let der = CertContext::new(der).unwrap(); 626 let pem = CertContext::from_pem(pem).unwrap(); 627 assert_eq!(der, pem); 628 } 629 630 #[test] certcontext_to_der()631 fn certcontext_to_der() { 632 let der = include_bytes!("../test/cert.der"); 633 let cert = CertContext::new(der).unwrap(); 634 let der2 = CertContext::to_der(&cert); 635 assert_eq!(der as &[u8], der2); 636 } 637 638 #[test] certcontext_to_pem()639 fn certcontext_to_pem() { 640 let der = include_bytes!("../test/cert.der"); 641 let pem1 = include_str!("../test/cert.pem").replace("\r", ""); 642 643 let der = CertContext::new(der).unwrap(); 644 let pem2 = CertContext::to_pem(&der).unwrap().replace("\r", ""); 645 assert_eq!(pem1, pem2); 646 } 647 648 #[test] fingerprint()649 fn fingerprint() { 650 let der = include_bytes!("../test/cert.der"); 651 let pem = include_str!("../test/cert.pem"); 652 653 let der = CertContext::new(der).unwrap(); 654 let pem = CertContext::from_pem(pem).unwrap(); 655 656 let hash = der.fingerprint(HashAlgorithm::sha1()).unwrap(); 657 assert_eq!(hash, vec![ 658 0x59, 0x17, 0x2D, 0x93, 0x13, 0xE8, 0x44, 0x59, 0xBC, 0xFF, 659 0x27, 0xF9, 0x67, 0xE7, 0x9E, 0x6E, 0x92, 0x17, 0xE5, 0x84 660 ]); 661 assert_eq!(hash, pem.fingerprint(HashAlgorithm::sha1()).unwrap()); 662 663 let hash = der.fingerprint(HashAlgorithm::sha256()).unwrap(); 664 assert_eq!(hash, vec![ 665 0x47, 0x12, 0xB9, 0x39, 0xFB, 0xCB, 0x42, 0xA6, 0xB5, 0x10, 666 0x1B, 0x42, 0x13, 0x9A, 0x25, 0xB1, 0x4F, 0x81, 0xB4, 0x18, 667 0xFA, 0xCA, 0xBD, 0x37, 0x87, 0x46, 0xF1, 0x2F, 0x85, 0xCC, 668 0x65, 0x44 669 ]); 670 assert_eq!(hash, pem.fingerprint(HashAlgorithm::sha256()).unwrap()); 671 } 672 } 673