diff --git a/security-framework-sys/src/item.rs b/security-framework-sys/src/item.rs index 5faa121e..d7dcb67c 100644 --- a/security-framework-sys/src/item.rs +++ b/security-framework-sys/src/item.rs @@ -28,6 +28,7 @@ extern "C" { pub static kSecAttrLabel: CFStringRef; pub static kSecAttrIsPermanent: CFStringRef; pub static kSecAttrPublicKeyHash: CFStringRef; + pub static kSecAttrSerialNumber: CFStringRef; pub static kSecPrivateKeyAttrs: CFStringRef; pub static kSecPublicKeyAttrs: CFStringRef; diff --git a/security-framework-sys/src/key.rs b/security-framework-sys/src/key.rs index 6ccafcc8..d43a027f 100644 --- a/security-framework-sys/src/key.rs +++ b/security-framework-sys/src/key.rs @@ -60,6 +60,22 @@ extern "C" { error: *mut CFErrorRef, ) -> 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 SecKeyCreateEncryptedData( + key: SecKeyRef, + algorithm: SecKeyAlgorithm, + plaintext: CFDataRef, + error: *mut CFErrorRef, + ) -> CFDataRef; + + #[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))] + pub fn SecKeyCreateDecryptedData( + key: SecKeyRef, + algorithm: SecKeyAlgorithm, + ciphertext: CFDataRef, + error: *mut CFErrorRef, + ) -> CFDataRef; + #[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))] pub fn SecKeyIsAlgorithmSupported( key: SecKeyRef, diff --git a/security-framework/src/item.rs b/security-framework/src/item.rs index 383ebf21..1eca1447 100644 --- a/security-framework/src/item.rs +++ b/security-framework/src/item.rs @@ -137,6 +137,7 @@ pub struct ItemSearchOptions { account: Option, access_group: Option, pub_key_hash: Option, + serial_number: Option, app_label: Option, } @@ -272,6 +273,15 @@ impl ItemSearchOptions { self } + /// Search for a certificate with the given serial number. + /// + /// This is only compatible with [`ItemClass::certificate`]. + #[inline(always)] + pub fn serial_number(&mut self, serial_number: &[u8]) -> &mut Self { + self.serial_number = Some(CFData::from_buffer(serial_number)); + self + } + /// Search for a key with the given public key hash. /// /// This is only compatible with [`ItemClass::key`], to search for a @@ -399,6 +409,13 @@ impl ItemSearchOptions { ); } + if let Some(ref serial_number) = self.serial_number { + params.add( + &kSecAttrSerialNumber.to_void(), + &serial_number.to_void(), + ); + } + if let Some(ref app_label) = self.app_label { params.add( &kSecAttrApplicationLabel.to_void(), diff --git a/security-framework/src/key.rs b/security-framework/src/key.rs index 5b7fa372..322373bb 100644 --- a/security-framework/src/key.rs +++ b/security-framework/src/key.rs @@ -43,6 +43,7 @@ use security_framework_sys::key::{ SecKeyCopyAttributes, SecKeyCopyExternalRepresentation, SecKeyCreateSignature, SecKeyCreateRandomKey, SecKeyCopyPublicKey, + SecKeyCreateDecryptedData, SecKeyCreateEncryptedData, }; #[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))] use security_framework_sys::item::kSecAttrApplicationLabel; @@ -195,6 +196,40 @@ impl SecKey { Some(unsafe { SecKey::wrap_under_create_rule(pub_seckey) }) } + #[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))] + /// Encrypts a block of data using a public key and specified algorithm + pub fn encrypt_data(&self, algorithm: Algorithm, input: &[u8]) -> Result, CFError> { + let mut error: CFErrorRef = std::ptr::null_mut(); + + let output = unsafe { + SecKeyCreateEncryptedData(self.as_concrete_TypeRef(), algorithm.into(), CFData::from_buffer(input).as_concrete_TypeRef(), &mut error) + }; + + if !error.is_null() { + Err(unsafe { CFError::wrap_under_create_rule(error) }) + } else { + let output = unsafe { CFData::wrap_under_create_rule(output) }; + Ok(output.to_vec()) + } + } + + #[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))] + /// Decrypts a block of data using a private key and specified algorithm + pub fn decrypt_data(&self, algorithm: Algorithm, input: &[u8]) -> Result, CFError> { + let mut error: CFErrorRef = std::ptr::null_mut(); + + let output = unsafe { + SecKeyCreateDecryptedData(self.as_concrete_TypeRef(), algorithm.into(), CFData::from_buffer(input).as_concrete_TypeRef(), &mut error) + }; + + if !error.is_null() { + Err(unsafe { CFError::wrap_under_create_rule(error) }) + } else { + let output = unsafe { CFData::wrap_under_create_rule(output) }; + Ok(output.to_vec()) + } + } + #[cfg(any(feature = "OSX_10_12", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))] /// Creates the cryptographic signature for a block of data using a private /// key and specified algorithm.