Skip to main content

security/
key.rs

1use serde_json::Value;
2
3use crate::bridge::{self, Handle};
4use crate::certificate::PublicKey;
5use crate::error::Result;
6
7#[repr(u32)]
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9/// Mirrors `SecExternalFormat`.
10pub enum ExternalFormat {
11    /// Mirrors a `SecExternalFormat` constant.
12    Unknown = 0,
13    /// Mirrors a `SecExternalFormat` constant.
14    OpenSsl = 1,
15    /// Mirrors a `SecExternalFormat` constant.
16    Ssh = 2,
17    /// Mirrors a `SecExternalFormat` constant.
18    Bsafe = 3,
19    /// Mirrors a `SecExternalFormat` constant.
20    RawKey = 4,
21    /// Mirrors a `SecExternalFormat` constant.
22    WrappedPkcs8 = 5,
23    /// Mirrors a `SecExternalFormat` constant.
24    WrappedOpenSsl = 6,
25    /// Mirrors a `SecExternalFormat` constant.
26    WrappedSsh = 7,
27    /// Mirrors a `SecExternalFormat` constant.
28    WrappedLsh = 8,
29    /// Mirrors a `SecExternalFormat` constant.
30    X509Certificate = 9,
31    /// Mirrors a `SecExternalFormat` constant.
32    PemSequence = 10,
33    /// Mirrors a `SecExternalFormat` constant.
34    Pkcs7 = 11,
35    /// Mirrors a `SecExternalFormat` constant.
36    Pkcs12 = 12,
37    /// Mirrors a `SecExternalFormat` constant.
38    NetscapeCertificateSequence = 13,
39    /// Mirrors a `SecExternalFormat` constant.
40    SshV2 = 14,
41}
42
43#[repr(u32)]
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
45/// Mirrors `SecExternalItemType`.
46pub enum ExternalItemType {
47    /// Mirrors a `SecExternalItemType` constant.
48    Unknown = 0,
49    /// Mirrors a `SecExternalItemType` constant.
50    PrivateKey = 1,
51    /// Mirrors a `SecExternalItemType` constant.
52    PublicKey = 2,
53    /// Mirrors a `SecExternalItemType` constant.
54    SessionKey = 3,
55    /// Mirrors a `SecExternalItemType` constant.
56    Certificate = 4,
57    /// Mirrors a `SecExternalItemType` constant.
58    Aggregate = 5,
59}
60
61#[repr(u32)]
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
63/// Mirrors key-type selectors used with `SecKeyCreateWithData`.
64pub enum KeyType {
65    /// Mirrors a Security.framework key-type selector.
66    Rsa = 0,
67    /// Mirrors a Security.framework key-type selector.
68    EcSecPrimeRandom = 1,
69}
70
71#[repr(u32)]
72#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
73/// Mirrors signing cases from `SecKeyAlgorithm`.
74pub enum SignatureAlgorithm {
75    /// Mirrors a `SecKeyAlgorithm` signing constant.
76    RsaSignatureMessagePkcs1v15Sha256 = 0,
77    /// Mirrors a `SecKeyAlgorithm` signing constant.
78    RsaSignatureDigestPkcs1v15Sha256 = 1,
79    /// Mirrors a `SecKeyAlgorithm` signing constant.
80    RsaSignatureMessagePssSha256 = 2,
81    /// Mirrors a `SecKeyAlgorithm` signing constant.
82    EcdsaSignatureMessageX962Sha256 = 3,
83    /// Mirrors a `SecKeyAlgorithm` signing constant.
84    EcdsaSignatureDigestX962Sha256 = 4,
85}
86
87#[repr(u32)]
88#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
89/// Mirrors encryption cases from `SecKeyAlgorithm`.
90pub enum EncryptionAlgorithm {
91    /// Mirrors a `SecKeyAlgorithm` encryption constant.
92    RsaEncryptionRaw = 0,
93    /// Mirrors a `SecKeyAlgorithm` encryption constant.
94    RsaEncryptionPkcs1 = 1,
95    /// Mirrors a `SecKeyAlgorithm` encryption constant.
96    RsaEncryptionOaepSha1 = 2,
97    /// Mirrors a `SecKeyAlgorithm` encryption constant.
98    RsaEncryptionOaepSha224 = 3,
99    /// Mirrors a `SecKeyAlgorithm` encryption constant.
100    RsaEncryptionOaepSha256 = 4,
101    /// Mirrors a `SecKeyAlgorithm` encryption constant.
102    RsaEncryptionOaepSha384 = 5,
103    /// Mirrors a `SecKeyAlgorithm` encryption constant.
104    RsaEncryptionOaepSha512 = 6,
105    /// Mirrors a `SecKeyAlgorithm` encryption constant.
106    RsaEncryptionOaepSha1AesGcm = 7,
107    /// Mirrors a `SecKeyAlgorithm` encryption constant.
108    RsaEncryptionOaepSha224AesGcm = 8,
109    /// Mirrors a `SecKeyAlgorithm` encryption constant.
110    RsaEncryptionOaepSha256AesGcm = 9,
111    /// Mirrors a `SecKeyAlgorithm` encryption constant.
112    RsaEncryptionOaepSha384AesGcm = 10,
113    /// Mirrors a `SecKeyAlgorithm` encryption constant.
114    RsaEncryptionOaepSha512AesGcm = 11,
115}
116
117pub(crate) fn key_type_id() -> usize {
118    unsafe { bridge::security_key_get_type_id() }
119}
120
121pub(crate) fn key_block_size(handle: &Handle) -> usize {
122    usize::try_from(unsafe { bridge::security_key_get_block_size(handle.as_ptr()) })
123        .unwrap_or_default()
124}
125
126pub(crate) fn key_external_representation(handle: &Handle) -> Result<Vec<u8>> {
127    let mut status = 0;
128    let mut error = std::ptr::null_mut();
129    let raw = unsafe {
130        bridge::security_key_copy_external_representation(handle.as_ptr(), &mut status, &mut error)
131    };
132    bridge::required_data(
133        "security_key_copy_external_representation",
134        raw,
135        status,
136        error,
137    )
138}
139
140pub(crate) fn encrypt_with_public_key(
141    handle: &Handle,
142    algorithm: EncryptionAlgorithm,
143    plaintext: &[u8],
144) -> Result<Vec<u8>> {
145    let mut status = 0;
146    let mut error = std::ptr::null_mut();
147    let raw = unsafe {
148        bridge::security_public_key_create_encrypted_data(
149            handle.as_ptr(),
150            algorithm as u32,
151            plaintext.as_ptr().cast(),
152            bridge::len_to_isize(plaintext.len())?,
153            &mut status,
154            &mut error,
155        )
156    };
157    bridge::required_data(
158        "security_public_key_create_encrypted_data",
159        raw,
160        status,
161        error,
162    )
163}
164
165pub(crate) fn decrypt_with_private_key(
166    handle: &Handle,
167    algorithm: EncryptionAlgorithm,
168    ciphertext: &[u8],
169) -> Result<Vec<u8>> {
170    let mut status = 0;
171    let mut error = std::ptr::null_mut();
172    let raw = unsafe {
173        bridge::security_private_key_create_decrypted_data(
174            handle.as_ptr(),
175            algorithm as u32,
176            ciphertext.as_ptr().cast(),
177            bridge::len_to_isize(ciphertext.len())?,
178            &mut status,
179            &mut error,
180        )
181    };
182    bridge::required_data(
183        "security_private_key_create_decrypted_data",
184        raw,
185        status,
186        error,
187    )
188}
189
190#[derive(Debug)]
191/// Wraps a private `SecKeyRef`.
192pub struct PrivateKey {
193    handle: Handle,
194}
195
196impl PrivateKey {
197    /// Wraps the corresponding private `SecKeyRef` operation.
198    pub fn type_id() -> usize {
199        key_type_id()
200    }
201
202    pub(crate) fn from_handle(handle: Handle) -> Self {
203        Self { handle }
204    }
205
206    pub(crate) fn handle(&self) -> &Handle {
207        &self.handle
208    }
209
210    /// Wraps the corresponding private `SecKeyRef` operation.
211    pub fn from_data(data: &[u8], key_type: KeyType, key_size_bits: usize) -> Result<Self> {
212        let mut status = 0;
213        let mut error = std::ptr::null_mut();
214        let raw = unsafe {
215            bridge::security_private_key_create_with_data(
216                data.as_ptr().cast(),
217                bridge::len_to_isize(data.len())?,
218                key_type as u32,
219                bridge::len_to_isize(key_size_bits)?,
220                &mut status,
221                &mut error,
222            )
223        };
224        bridge::required_handle("security_private_key_create_with_data", raw, status, error)
225            .map(Self::from_handle)
226    }
227
228    /// Wraps the corresponding private `SecKeyRef` operation.
229    pub fn import_item(
230        data: &[u8],
231        file_name_or_extension: Option<&str>,
232        format: ExternalFormat,
233        item_type: ExternalItemType,
234    ) -> Result<Self> {
235        let file_name_or_extension = file_name_or_extension.map(bridge::cstring).transpose()?;
236        let mut status = 0;
237        let mut error = std::ptr::null_mut();
238        let raw = unsafe {
239            bridge::security_private_key_import_item(
240                data.as_ptr().cast(),
241                bridge::len_to_isize(data.len())?,
242                file_name_or_extension
243                    .as_ref()
244                    .map_or(std::ptr::null(), |value| value.as_ptr()),
245                format as u32,
246                item_type as u32,
247                &mut status,
248                &mut error,
249            )
250        };
251        bridge::required_handle("security_private_key_import_item", raw, status, error)
252            .map(Self::from_handle)
253    }
254
255    /// Wraps the corresponding private `SecKeyRef` operation.
256    pub fn import_pem(pem: &[u8]) -> Result<Self> {
257        Self::import_item(
258            pem,
259            Some(".pem"),
260            ExternalFormat::Unknown,
261            ExternalItemType::PrivateKey,
262        )
263    }
264
265    /// Wraps the corresponding private `SecKeyRef` operation.
266    pub fn public_key(&self) -> Result<PublicKey> {
267        let mut status = 0;
268        let mut error = std::ptr::null_mut();
269        let raw = unsafe {
270            bridge::security_key_copy_public_key(self.handle.as_ptr(), &mut status, &mut error)
271        };
272        bridge::required_handle("security_key_copy_public_key", raw, status, error)
273            .map(PublicKey::from_handle)
274    }
275
276    /// Wraps the corresponding private `SecKeyRef` operation.
277    pub fn attributes(&self) -> Result<Value> {
278        let mut status = 0;
279        let mut error = std::ptr::null_mut();
280        let raw = unsafe {
281            bridge::security_key_copy_attributes(self.handle.as_ptr(), &mut status, &mut error)
282        };
283        bridge::required_json("security_key_copy_attributes", raw, status, error)
284    }
285
286    /// Wraps the corresponding private `SecKeyRef` operation.
287    pub fn block_size(&self) -> usize {
288        key_block_size(&self.handle)
289    }
290
291    /// Wraps the corresponding private `SecKeyRef` operation.
292    pub fn external_representation(&self) -> Result<Vec<u8>> {
293        key_external_representation(&self.handle)
294    }
295
296    /// Wraps the corresponding private `SecKeyRef` operation.
297    pub fn sign(&self, algorithm: SignatureAlgorithm, data: &[u8]) -> Result<Vec<u8>> {
298        let mut status = 0;
299        let mut error = std::ptr::null_mut();
300        let raw = unsafe {
301            bridge::security_private_key_create_signature(
302                self.handle.as_ptr(),
303                algorithm as u32,
304                data.as_ptr().cast(),
305                bridge::len_to_isize(data.len())?,
306                &mut status,
307                &mut error,
308            )
309        };
310        bridge::required_data("security_private_key_create_signature", raw, status, error)
311    }
312
313    /// Wraps the corresponding private `SecKeyRef` operation.
314    pub fn decrypt(&self, algorithm: EncryptionAlgorithm, ciphertext: &[u8]) -> Result<Vec<u8>> {
315        decrypt_with_private_key(&self.handle, algorithm, ciphertext)
316    }
317}