diff --git a/security-framework-sys/src/item.rs b/security-framework-sys/src/item.rs index d7dcb67c..afdbdfce 100644 --- a/security-framework-sys/src/item.rs +++ b/security-framework-sys/src/item.rs @@ -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; diff --git a/security-framework-sys/src/key.rs b/security-framework-sys/src/key.rs index d43a027f..a40a3036 100644 --- a/security-framework-sys/src/key.rs +++ b/security-framework-sys/src/key.rs @@ -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, @@ -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"))] diff --git a/security-framework/src/key.rs b/security-framework/src/key.rs index 322373bb..1c1575d8 100644 --- a/security-framework/src/key.rs +++ b/security-framework/src/key.rs @@ -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::{ @@ -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) } } @@ -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, 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(¶ms); + + 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(&[(