Skip to content

Commit

Permalink
Merge pull request #218 from crashdump/key-exchange
Browse files Browse the repository at this point in the history
  • Loading branch information
kornelski authored Dec 16, 2024
2 parents 9f00f41 + 5956011 commit b2189b2
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 1 deletion.
5 changes: 5 additions & 0 deletions security-framework-sys/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ extern "C" {
pub static kSecAttrAccessGroup: CFStringRef;
pub static kSecAttrAccessGroupToken: CFStringRef;

#[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))]
pub static kSecKeyKeyExchangeParameterRequestedSize: CFStringRef;
#[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))]
pub static kSecKeyKeyExchangeParameterSharedInfo: CFStringRef;

pub static kSecAttrAuthenticationType: CFStringRef;
pub static kSecAttrComment: CFStringRef;
pub static kSecAttrDescription: CFStringRef;
Expand Down
16 changes: 16 additions & 0 deletions security-framework-sys/src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ extern "C" {
#[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))]
pub fn SecKeyCreateRandomKey(parameters: CFDictionaryRef, error: *mut CFErrorRef) -> SecKeyRef;

#[cfg(any(feature = "OSX_10_13", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))]
pub fn SecKeyCreateWithData(
keyData: CFDataRef,
attributes: CFDictionaryRef,
error: *mut CFErrorRef,
) -> SecKeyRef;

#[cfg(target_os = "macos")]
pub fn SecKeyCreateFromData(
parameters: CFDictionaryRef,
Expand Down Expand Up @@ -82,6 +89,15 @@ extern "C" {
operation: SecKeyOperationType,
algorithm: SecKeyAlgorithm,
) -> core_foundation_sys::base::Boolean;

#[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))]
pub fn SecKeyCopyKeyExchangeResult(
privateKey: SecKeyRef,
algorithm: SecKeyAlgorithm,
publicKey: SecKeyRef,
parameters: CFDictionaryRef,
error: *mut CFErrorRef,
) -> CFDataRef;
}

#[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))]
Expand Down
58 changes: 57 additions & 1 deletion security-framework/src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ use core_foundation::error::{CFError, CFErrorRef};

use security_framework_sys::{
item::{kSecAttrKeyTypeRSA, kSecValueRef},
keychain_item::SecItemDelete
keychain_item::SecItemDelete,
key::SecKeyCopyKeyExchangeResult
};
#[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))]
use security_framework_sys::{item::{
Expand Down Expand Up @@ -117,6 +118,15 @@ impl KeyType {
unsafe { Self(kSecAttrKeyTypeEC) }
}

#[inline(always)]
#[must_use]
pub fn ec_sec_prime_random() -> Self {
use security_framework_sys::item::kSecAttrKeyTypeECSECPrimeRandom;

unsafe { Self(kSecAttrKeyTypeECSECPrimeRandom) }
}


pub(crate) fn to_str(self) -> CFString {
unsafe { CFString::wrap_under_get_rule(self.0) }
}
Expand Down Expand Up @@ -276,6 +286,52 @@ impl SecKey {
Ok(valid != 0)
}

/// Performs the Diffie-Hellman style of key exchange.
#[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))]
pub fn key_exchange(
&self,
algorithm: Algorithm,
public_key: &SecKey,
requested_size: usize,
shared_info: Option<&[u8]>,
) -> Result<Vec<u8>, CFError> {
use core_foundation::data::CFData;
use security_framework_sys::item::{kSecKeyKeyExchangeParameterRequestedSize, kSecKeyKeyExchangeParameterSharedInfo};

unsafe {
let mut params = vec![(
CFString::wrap_under_get_rule(kSecKeyKeyExchangeParameterRequestedSize),
CFNumber::from(requested_size as i64).into_CFType(),
)];

if let Some(shared_info) = shared_info {
params.push((
CFString::wrap_under_get_rule(kSecKeyKeyExchangeParameterSharedInfo),
CFData::from_buffer(shared_info).as_CFType(),
))
};

let parameters = CFDictionary::from_CFType_pairs(&params);

let mut error: CFErrorRef = std::ptr::null_mut();

let output = SecKeyCopyKeyExchangeResult(
self.as_concrete_TypeRef(),
algorithm.into(),
public_key.as_concrete_TypeRef(),
parameters.as_concrete_TypeRef(),
&mut error,
);

if !error.is_null() {
Err(CFError::wrap_under_create_rule(error))
} else {
let output = CFData::wrap_under_create_rule(output);
Ok(output.to_vec())
}
}
}

/// Translates to `SecItemDelete`, passing in the `SecKeyRef`
pub fn delete(&self) -> Result<(), Error> {
let query = CFMutableDictionary::from_CFType_pairs(&[(
Expand Down

0 comments on commit b2189b2

Please sign in to comment.