Skip to content

Commit

Permalink
added sha256 support
Browse files Browse the repository at this point in the history
  • Loading branch information
MS-megliu committed Dec 10, 2024
1 parent 7766c76 commit 40cf451
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
53 changes: 53 additions & 0 deletions src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,26 @@ impl CertStore {
unsafe { self.do_find(CERT_FIND_HASH, &hash_blob as *const _ as _) }
}


/// On later OS releases, we added CERT_FIND_SHA256_HASH.
/// However, rustls-cng could be installed on earlier OS release where this FIND_SHA256 isn't present.
/// But the CERT_SHA256_HASH_PROP_ID is present.
/// So will need to add a new internal find function that gets and compares the SHA256 property.
/// Also, since SHA1 is being deprecated, Windows components should not use.
/// Therefore, the need to find via SHA256 instead of SHA1.
/// Find list of certificates matching the SHA256 hash
pub fn find_by_sha256<D>(&self, hash: D) -> Result<Vec<CertContext>>
where
D: AsRef<[u8]>,
{
let hash_blob = CRYPT_INTEGER_BLOB {
cbData: hash.as_ref().len() as u32,
pbData: hash.as_ref().as_ptr() as _,
};
unsafe { self.do_find_by_sha256_property(&hash_blob as *const _ as _) }
}

/// Find list of certificates matching the key identifier
pub fn find_by_key_id<D>(&self, key_id: D) -> Result<Vec<CertContext>>
where
Expand Down Expand Up @@ -180,6 +200,39 @@ impl CertStore {
Ok(certs)
}

unsafe fn do_find_by_sha256_property(
&self,
find_param: *const c_void,
) -> Result<Vec<CertContext>> {
let mut certs = Vec::new();
let mut cert: *mut CERT_CONTEXT = ptr::null_mut();
let hash_blob = &*(find_param as *const CRYPT_INTEGER_BLOB);
let sha256_hash = std::slice::from_raw_parts(hash_blob.pbData, hash_blob.cbData as usize);
loop {
cert = CertFindCertificateInStore(self.0, MY_ENCODING_TYPE, 0, CERT_FIND_ANY, find_param, cert);
if cert.is_null() {
break;
} else {
let mut prop_data = [0u8; 32];
let mut prop_data_len = prop_data.len() as u32;

if CertGetCertificateContextProperty(
cert,
CERT_SHA256_HASH_PROP_ID,
prop_data.as_mut_ptr() as *mut c_void,
&mut prop_data_len,
) != 0
{
if prop_data[..prop_data_len as usize] == sha256_hash[..] {
let cert = CertDuplicateCertificateContext(cert);
certs.push(CertContext::new_owned(cert))
}
}
}
}
Ok(certs)
}

fn find_by_str(&self, pattern: &str, flags: CERT_FIND_FLAGS) -> Result<Vec<CertContext>> {
let u16pattern = utf16z!(pattern);
unsafe { self.do_find(flags, u16pattern.as_ptr() as _) }
Expand Down
15 changes: 15 additions & 0 deletions tests/test_find.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,21 @@ fn test_find_by_hash() {
assert!(context.is_some());
}

#[test]
fn test_find_by_hash256() {
let store = CertStore::from_pkcs12(PFX, PASSWORD).expect("Cannot open cert store");

let sha256 = [
0xC9, 0x7C, 0xD6, 0xA1, 0x3F, 0xF6, 0xBD, 0xF6,
0xD4, 0xE2, 0xFB, 0x0E, 0xCD, 0x74, 0x2F, 0x14,
0x30, 0x53, 0xB0, 0x89, 0xFA, 0x4D, 0xA5, 0xE5,
0x8B, 0xA3, 0x9F, 0x72, 0xED, 0x2F, 0x9F, 0xB6
];

let context = store.find_by_sha256(sha256).unwrap().into_iter().next();
assert!(context.is_some());
}

#[test]
fn test_find_all() {
let store = CertStore::from_pkcs12(PFX, PASSWORD).expect("Cannot open cert store");
Expand Down

0 comments on commit 40cf451

Please sign in to comment.