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)]
9pub enum ExternalFormat {
10 Unknown = 0,
11 OpenSsl = 1,
12 Ssh = 2,
13 Bsafe = 3,
14 RawKey = 4,
15 WrappedPkcs8 = 5,
16 WrappedOpenSsl = 6,
17 WrappedSsh = 7,
18 WrappedLsh = 8,
19 X509Certificate = 9,
20 PemSequence = 10,
21 Pkcs7 = 11,
22 Pkcs12 = 12,
23 NetscapeCertificateSequence = 13,
24 SshV2 = 14,
25}
26
27#[repr(u32)]
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
29pub enum ExternalItemType {
30 Unknown = 0,
31 PrivateKey = 1,
32 PublicKey = 2,
33 SessionKey = 3,
34 Certificate = 4,
35 Aggregate = 5,
36}
37
38#[repr(u32)]
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
40pub enum KeyType {
41 Rsa = 0,
42 EcSecPrimeRandom = 1,
43}
44
45#[repr(u32)]
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
47pub enum SignatureAlgorithm {
48 RsaSignatureMessagePkcs1v15Sha256 = 0,
49 RsaSignatureDigestPkcs1v15Sha256 = 1,
50 RsaSignatureMessagePssSha256 = 2,
51 EcdsaSignatureMessageX962Sha256 = 3,
52 EcdsaSignatureDigestX962Sha256 = 4,
53}
54
55#[derive(Debug)]
56pub struct PrivateKey {
57 handle: Handle,
58}
59
60impl PrivateKey {
61 pub(crate) fn from_handle(handle: Handle) -> Self {
62 Self { handle }
63 }
64
65 pub fn from_data(data: &[u8], key_type: KeyType, key_size_bits: usize) -> Result<Self> {
66 let mut status = 0;
67 let mut error = std::ptr::null_mut();
68 let raw = unsafe {
69 bridge::security_private_key_create_with_data(
70 data.as_ptr().cast(),
71 bridge::len_to_isize(data.len())?,
72 key_type as u32,
73 bridge::len_to_isize(key_size_bits)?,
74 &mut status,
75 &mut error,
76 )
77 };
78 bridge::required_handle("security_private_key_create_with_data", raw, status, error)
79 .map(Self::from_handle)
80 }
81
82 pub fn import_item(
83 data: &[u8],
84 file_name_or_extension: Option<&str>,
85 format: ExternalFormat,
86 item_type: ExternalItemType,
87 ) -> Result<Self> {
88 let file_name_or_extension = file_name_or_extension.map(bridge::cstring).transpose()?;
89 let mut status = 0;
90 let mut error = std::ptr::null_mut();
91 let raw = unsafe {
92 bridge::security_private_key_import_item(
93 data.as_ptr().cast(),
94 bridge::len_to_isize(data.len())?,
95 file_name_or_extension
96 .as_ref()
97 .map_or(std::ptr::null(), |value| value.as_ptr()),
98 format as u32,
99 item_type as u32,
100 &mut status,
101 &mut error,
102 )
103 };
104 bridge::required_handle("security_private_key_import_item", raw, status, error)
105 .map(Self::from_handle)
106 }
107
108 pub fn import_pem(pem: &[u8]) -> Result<Self> {
109 Self::import_item(
110 pem,
111 Some(".pem"),
112 ExternalFormat::Unknown,
113 ExternalItemType::PrivateKey,
114 )
115 }
116
117 pub fn public_key(&self) -> Result<PublicKey> {
118 let mut status = 0;
119 let mut error = std::ptr::null_mut();
120 let raw = unsafe {
121 bridge::security_key_copy_public_key(self.handle.as_ptr(), &mut status, &mut error)
122 };
123 bridge::required_handle("security_key_copy_public_key", raw, status, error)
124 .map(PublicKey::from_handle)
125 }
126
127 pub fn attributes(&self) -> Result<Value> {
128 let mut status = 0;
129 let mut error = std::ptr::null_mut();
130 let raw = unsafe {
131 bridge::security_key_copy_attributes(self.handle.as_ptr(), &mut status, &mut error)
132 };
133 bridge::required_json("security_key_copy_attributes", raw, status, error)
134 }
135
136 pub fn sign(&self, algorithm: SignatureAlgorithm, data: &[u8]) -> Result<Vec<u8>> {
137 let mut status = 0;
138 let mut error = std::ptr::null_mut();
139 let raw = unsafe {
140 bridge::security_private_key_create_signature(
141 self.handle.as_ptr(),
142 algorithm as u32,
143 data.as_ptr().cast(),
144 bridge::len_to_isize(data.len())?,
145 &mut status,
146 &mut error,
147 )
148 };
149 bridge::required_data("security_private_key_create_signature", raw, status, error)
150 }
151}