Skip to content

Commit b2189b2

Browse files
authored
Merge pull request #218 from crashdump/key-exchange
2 parents 9f00f41 + 5956011 commit b2189b2

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

security-framework-sys/src/item.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ extern "C" {
6868
pub static kSecAttrAccessGroup: CFStringRef;
6969
pub static kSecAttrAccessGroupToken: CFStringRef;
7070

71+
#[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))]
72+
pub static kSecKeyKeyExchangeParameterRequestedSize: CFStringRef;
73+
#[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))]
74+
pub static kSecKeyKeyExchangeParameterSharedInfo: CFStringRef;
75+
7176
pub static kSecAttrAuthenticationType: CFStringRef;
7277
pub static kSecAttrComment: CFStringRef;
7378
pub static kSecAttrDescription: CFStringRef;

security-framework-sys/src/key.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ extern "C" {
2929
#[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))]
3030
pub fn SecKeyCreateRandomKey(parameters: CFDictionaryRef, error: *mut CFErrorRef) -> SecKeyRef;
3131

32+
#[cfg(any(feature = "OSX_10_13", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))]
33+
pub fn SecKeyCreateWithData(
34+
keyData: CFDataRef,
35+
attributes: CFDictionaryRef,
36+
error: *mut CFErrorRef,
37+
) -> SecKeyRef;
38+
3239
#[cfg(target_os = "macos")]
3340
pub fn SecKeyCreateFromData(
3441
parameters: CFDictionaryRef,
@@ -82,6 +89,15 @@ extern "C" {
8289
operation: SecKeyOperationType,
8390
algorithm: SecKeyAlgorithm,
8491
) -> core_foundation_sys::base::Boolean;
92+
93+
#[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))]
94+
pub fn SecKeyCopyKeyExchangeResult(
95+
privateKey: SecKeyRef,
96+
algorithm: SecKeyAlgorithm,
97+
publicKey: SecKeyRef,
98+
parameters: CFDictionaryRef,
99+
error: *mut CFErrorRef,
100+
) -> CFDataRef;
85101
}
86102

87103
#[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))]

security-framework/src/key.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ use core_foundation::error::{CFError, CFErrorRef};
1919

2020
use security_framework_sys::{
2121
item::{kSecAttrKeyTypeRSA, kSecValueRef},
22-
keychain_item::SecItemDelete
22+
keychain_item::SecItemDelete,
23+
key::SecKeyCopyKeyExchangeResult
2324
};
2425
#[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))]
2526
use security_framework_sys::{item::{
@@ -117,6 +118,15 @@ impl KeyType {
117118
unsafe { Self(kSecAttrKeyTypeEC) }
118119
}
119120

121+
#[inline(always)]
122+
#[must_use]
123+
pub fn ec_sec_prime_random() -> Self {
124+
use security_framework_sys::item::kSecAttrKeyTypeECSECPrimeRandom;
125+
126+
unsafe { Self(kSecAttrKeyTypeECSECPrimeRandom) }
127+
}
128+
129+
120130
pub(crate) fn to_str(self) -> CFString {
121131
unsafe { CFString::wrap_under_get_rule(self.0) }
122132
}
@@ -276,6 +286,52 @@ impl SecKey {
276286
Ok(valid != 0)
277287
}
278288

289+
/// Performs the Diffie-Hellman style of key exchange.
290+
#[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))]
291+
pub fn key_exchange(
292+
&self,
293+
algorithm: Algorithm,
294+
public_key: &SecKey,
295+
requested_size: usize,
296+
shared_info: Option<&[u8]>,
297+
) -> Result<Vec<u8>, CFError> {
298+
use core_foundation::data::CFData;
299+
use security_framework_sys::item::{kSecKeyKeyExchangeParameterRequestedSize, kSecKeyKeyExchangeParameterSharedInfo};
300+
301+
unsafe {
302+
let mut params = vec![(
303+
CFString::wrap_under_get_rule(kSecKeyKeyExchangeParameterRequestedSize),
304+
CFNumber::from(requested_size as i64).into_CFType(),
305+
)];
306+
307+
if let Some(shared_info) = shared_info {
308+
params.push((
309+
CFString::wrap_under_get_rule(kSecKeyKeyExchangeParameterSharedInfo),
310+
CFData::from_buffer(shared_info).as_CFType(),
311+
))
312+
};
313+
314+
let parameters = CFDictionary::from_CFType_pairs(&params);
315+
316+
let mut error: CFErrorRef = std::ptr::null_mut();
317+
318+
let output = SecKeyCopyKeyExchangeResult(
319+
self.as_concrete_TypeRef(),
320+
algorithm.into(),
321+
public_key.as_concrete_TypeRef(),
322+
parameters.as_concrete_TypeRef(),
323+
&mut error,
324+
);
325+
326+
if !error.is_null() {
327+
Err(CFError::wrap_under_create_rule(error))
328+
} else {
329+
let output = CFData::wrap_under_create_rule(output);
330+
Ok(output.to_vec())
331+
}
332+
}
333+
}
334+
279335
/// Translates to `SecItemDelete`, passing in the `SecKeyRef`
280336
pub fn delete(&self) -> Result<(), Error> {
281337
let query = CFMutableDictionary::from_CFType_pairs(&[(

0 commit comments

Comments
 (0)