-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathalg.rs
More file actions
94 lines (88 loc) · 3.07 KB
/
Copy pathalg.rs
File metadata and controls
94 lines (88 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// Unless explicitly stated otherwise all files in this repository are licensed under the MIT License.
//
// This product includes software developed at Datadog (https://www.datadoghq.com/)
// Copyright 2026 Datadog, Inc.
//! Algorithm provider initialization.
use once_cell::sync::OnceCell;
use rustls::Error;
#[cfg(feature = "tls12")]
use windows::Win32::Security::Cryptography::BCRYPT_TLS1_2_KDF_ALGORITHM;
use windows::Win32::Security::Cryptography::{
BCryptOpenAlgorithmProvider, BCryptSetProperty, BCRYPT_ECC_CURVE_25519, BCRYPT_ECC_CURVE_NAME,
BCRYPT_ECDH_ALGORITHM, BCRYPT_HANDLE,
};
use windows::{
core::PCWSTR,
Win32::Security::Cryptography::{BCRYPT_ALG_HANDLE, BCRYPT_OPEN_ALGORITHM_PROVIDER_FLAGS},
};
struct Handle(BCRYPT_ALG_HANDLE);
unsafe impl Send for Handle {}
unsafe impl Sync for Handle {}
pub(crate) fn ecdh_x25519() -> Result<BCRYPT_ALG_HANDLE, Error> {
static ALG_HANDLE: OnceCell<Option<Handle>> = OnceCell::new();
ALG_HANDLE
.get_or_init(|| {
load_algorithm(
BCRYPT_ECDH_ALGORITHM,
BCRYPT_OPEN_ALGORITHM_PROVIDER_FLAGS::default(),
Some((BCRYPT_ECC_CURVE_NAME, BCRYPT_ECC_CURVE_25519)),
)
.ok()
.map(Handle)
})
.as_ref()
.map(|handle| handle.0)
.ok_or_else(|| Error::General("CNG X25519 algorithm provider unavailable".into()))
}
#[cfg(feature = "tls12")]
pub(crate) fn tls12_kdf() -> Result<BCRYPT_ALG_HANDLE, Error> {
static ALG_HANDLE: OnceCell<Option<Handle>> = OnceCell::new();
ALG_HANDLE
.get_or_init(|| {
load_algorithm(
BCRYPT_TLS1_2_KDF_ALGORITHM,
BCRYPT_OPEN_ALGORITHM_PROVIDER_FLAGS::default(),
None,
)
.ok()
.map(Handle)
})
.as_ref()
.map(|handle| handle.0)
.ok_or_else(|| Error::General("CNG TLS 1.2 KDF algorithm provider unavailable".into()))
}
/// Load an algorithm provider with specified flags, and optional property.
fn load_algorithm(
id: PCWSTR,
flags: BCRYPT_OPEN_ALGORITHM_PROVIDER_FLAGS,
property: Option<(PCWSTR, PCWSTR)>,
) -> Result<BCRYPT_ALG_HANDLE, Error> {
let mut alg_handle = BCRYPT_ALG_HANDLE::default();
unsafe {
BCryptOpenAlgorithmProvider(&mut alg_handle, id, None, flags)
.ok()
.map_err(|e| Error::General(format!("BCryptOpenAlgorithmProvider error: {e}")))?;
if let Some((property, value)) = property {
let bcrypt_handle = BCRYPT_HANDLE(alg_handle.0);
BCryptSetProperty(
bcrypt_handle,
property,
&to_null_terminated_le_bytes(value),
0,
)
.ok()
.map_err(|e| Error::General(format!("BCryptSetProperty error: {e}")))?;
}
}
Ok(alg_handle)
}
fn to_null_terminated_le_bytes(str: PCWSTR) -> Vec<u8> {
unsafe {
str.as_wide()
.iter()
.copied()
.chain(Some(0))
.flat_map(u16::to_le_bytes)
.collect()
}
}