1use crate::aws_lc::{EVP_PKEY, EVP_PKEY_EC};
5use crate::ec::encoding::sec1::parse_sec1_public_point;
6use crate::ec::validate_ec_evp_key;
7
8use crate::error::KeyRejected;
9use crate::ptr::LcPtr;
10
11pub(crate) mod sec1 {
15 use crate::aws_lc::{
16 point_conversion_form_t, BN_bn2cbb_padded, EC_GROUP_get_curve_name, EC_KEY_get0_group,
17 EC_KEY_get0_private_key, EC_KEY_get0_public_key, EC_KEY_new, EC_KEY_set_group,
18 EC_KEY_set_private_key, EC_KEY_set_public_key, EC_POINT_mul, EC_POINT_new,
19 EC_POINT_oct2point, EC_POINT_point2cbb, EVP_PKEY_assign_EC_KEY, EVP_PKEY_get0_EC_KEY,
20 EVP_PKEY_new, NID_X9_62_prime256v1, NID_secp256k1, NID_secp384r1, NID_secp521r1, BIGNUM,
21 EC_GROUP, EC_POINT, EVP_PKEY,
22 };
23 use crate::cbb::LcCBB;
24 use crate::ec::{
25 compressed_public_key_size_bytes, ec_group_from_nid, uncompressed_public_key_size_bytes,
26 validate_ec_evp_key, KeyRejected,
27 };
28 use crate::error::Unspecified;
29 use crate::ptr::{ConstPointer, DetachableLcPtr, LcPtr};
30 use std::ptr::{null, null_mut};
31
32 pub(crate) fn parse_sec1_public_point(
33 key_bytes: &[u8],
34 expected_curve_nid: i32,
35 ) -> Result<LcPtr<EVP_PKEY>, KeyRejected> {
36 let ec_group = ec_group_from_nid(expected_curve_nid)?;
37 let mut ec_point = LcPtr::new(unsafe { EC_POINT_new(ec_group.as_const_ptr()) })?;
38
39 if 1 != unsafe {
40 EC_POINT_oct2point(
41 ec_group.as_const_ptr(),
42 ec_point.as_mut_ptr(),
43 key_bytes.as_ptr(),
44 key_bytes.len(),
45 null_mut(),
46 )
47 } {
48 return Err(KeyRejected::invalid_encoding());
49 }
50 from_ec_public_point(&ec_group, &ec_point)
51 }
52
53 #[inline]
54 fn from_ec_public_point(
55 ec_group: &ConstPointer<EC_GROUP>,
56 public_ec_point: &LcPtr<EC_POINT>,
57 ) -> Result<LcPtr<EVP_PKEY>, KeyRejected> {
58 let nid = unsafe { EC_GROUP_get_curve_name(ec_group.as_const_ptr()) };
59 let mut ec_key = DetachableLcPtr::new(unsafe { EC_KEY_new() })?;
60 if 1 != unsafe { EC_KEY_set_group(ec_key.as_mut_ptr(), ec_group.as_const_ptr()) } {
61 return Err(KeyRejected::unexpected_error());
62 }
63 if 1 != unsafe {
64 EC_KEY_set_public_key(ec_key.as_mut_ptr(), public_ec_point.as_const_ptr())
65 } {
66 return Err(KeyRejected::inconsistent_components());
67 }
68
69 let mut pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?;
70
71 if 1 != unsafe { EVP_PKEY_assign_EC_KEY(pkey.as_mut_ptr(), ec_key.as_mut_ptr()) } {
72 return Err(KeyRejected::unexpected_error());
73 }
74
75 ec_key.detach();
76
77 validate_ec_evp_key(&pkey.as_const(), nid)?;
78
79 Ok(pkey)
80 }
81
82 pub(crate) fn parse_sec1_private_bn(
83 priv_key: &[u8],
84 nid: i32,
85 ) -> Result<LcPtr<EVP_PKEY>, KeyRejected> {
86 let ec_group = ec_group_from_nid(nid)?;
87 let priv_key = LcPtr::<BIGNUM>::try_from(priv_key)?;
88
89 let pkey = from_ec_private_bn(&ec_group, &priv_key.as_const())?;
90
91 Ok(pkey)
92 }
93
94 fn from_ec_private_bn(
95 ec_group: &ConstPointer<EC_GROUP>,
96 private_big_num: &ConstPointer<BIGNUM>,
97 ) -> Result<LcPtr<EVP_PKEY>, KeyRejected> {
98 let mut ec_key = DetachableLcPtr::new(unsafe { EC_KEY_new() })?;
99 if 1 != unsafe { EC_KEY_set_group(ec_key.as_mut_ptr(), ec_group.as_const_ptr()) } {
100 return Err(KeyRejected::unexpected_error());
101 }
102 if 1 != unsafe {
103 EC_KEY_set_private_key(ec_key.as_mut_ptr(), private_big_num.as_const_ptr())
104 } {
105 return Err(KeyRejected::invalid_encoding());
106 }
107 let mut pub_key = LcPtr::new(unsafe { EC_POINT_new(ec_group.as_const_ptr()) })?;
108 if 1 != unsafe {
109 EC_POINT_mul(
110 ec_group.as_const_ptr(),
111 pub_key.as_mut_ptr(),
112 private_big_num.as_const_ptr(),
113 null(),
114 null(),
115 null_mut(),
116 )
117 } {
118 return Err(KeyRejected::unexpected_error());
119 }
120 if 1 != unsafe { EC_KEY_set_public_key(ec_key.as_mut_ptr(), pub_key.as_const_ptr()) } {
121 return Err(KeyRejected::unexpected_error());
122 }
123 let expected_curve_nid = unsafe { EC_GROUP_get_curve_name(ec_group.as_const_ptr()) };
124
125 let mut pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?;
126
127 if 1 != unsafe { EVP_PKEY_assign_EC_KEY(pkey.as_mut_ptr(), ec_key.as_mut_ptr()) } {
128 return Err(KeyRejected::unexpected_error());
129 }
130 ec_key.detach();
131
132 validate_ec_evp_key(&pkey.as_const(), expected_curve_nid)?;
134
135 Ok(pkey)
136 }
137 pub(crate) fn marshal_sec1_public_point(
138 evp_pkey: &LcPtr<EVP_PKEY>,
139 compressed: bool,
140 ) -> Result<Vec<u8>, Unspecified> {
141 let pub_key_size = if compressed {
142 compressed_public_key_size_bytes(evp_pkey.as_const().key_size_bits())
143 } else {
144 uncompressed_public_key_size_bytes(evp_pkey.as_const().key_size_bits())
145 };
146 let mut cbb = LcCBB::new(pub_key_size);
147 marshal_sec1_public_point_into_cbb(&mut cbb, evp_pkey, compressed)?;
148 cbb.into_vec()
149 }
150
151 pub(crate) fn marshal_sec1_public_point_into_buffer(
152 buffer: &mut [u8],
153 evp_pkey: &LcPtr<EVP_PKEY>,
154 compressed: bool,
155 ) -> Result<usize, Unspecified> {
156 let mut cbb = LcCBB::new_from_slice(buffer);
157 marshal_sec1_public_point_into_cbb(&mut cbb, evp_pkey, compressed)?;
158 cbb.finish()
159 }
160
161 fn marshal_sec1_public_point_into_cbb(
162 cbb: &mut LcCBB,
163 evp_pkey: &LcPtr<EVP_PKEY>,
164 compressed: bool,
165 ) -> Result<(), Unspecified> {
166 let ec_key = evp_pkey.project_const_lifetime(unsafe {
167 |evp_pkey| EVP_PKEY_get0_EC_KEY(evp_pkey.as_const_ptr())
168 })?;
169 let ec_group = ec_key
170 .project_const_lifetime(unsafe { |ec_key| EC_KEY_get0_group(ec_key.as_const_ptr()) })?;
171 let ec_point = ec_key.project_const_lifetime(unsafe {
172 |ec_key| EC_KEY_get0_public_key(ec_key.as_const_ptr())
173 })?;
174
175 let point_conversion_form = if compressed {
176 point_conversion_form_t::POINT_CONVERSION_COMPRESSED
177 } else {
178 point_conversion_form_t::POINT_CONVERSION_UNCOMPRESSED
179 };
180
181 if 1 != unsafe {
182 EC_POINT_point2cbb(
183 cbb.as_mut_ptr(),
184 ec_group.as_const_ptr(),
185 ec_point.as_const_ptr(),
186 point_conversion_form,
187 null_mut(),
188 )
189 } {
190 return Err(Unspecified);
191 }
192 Ok(())
193 }
194
195 pub(crate) fn marshal_sec1_private_key(
196 evp_pkey: &LcPtr<EVP_PKEY>,
197 ) -> Result<Vec<u8>, Unspecified> {
198 let ec_key = evp_pkey.project_const_lifetime(unsafe {
199 |evp_pkey| EVP_PKEY_get0_EC_KEY(evp_pkey.as_const_ptr())
200 })?;
201 let ec_group = ec_key
202 .project_const_lifetime(unsafe { |ec_key| EC_KEY_get0_group(ec_key.as_const_ptr()) })?;
203 let nid = unsafe { EC_GROUP_get_curve_name(ec_group.as_const_ptr()) };
204 #[allow(non_upper_case_globals)]
205 let key_size: usize = match nid {
206 NID_X9_62_prime256v1 | NID_secp256k1 => Ok(32usize),
207 NID_secp384r1 => Ok(48usize),
208 NID_secp521r1 => Ok(66usize),
209 _ => Err(Unspecified),
210 }?;
211 let private_bn = ec_key.project_const_lifetime(unsafe {
212 |ec_key| EC_KEY_get0_private_key(ec_key.as_const_ptr())
213 })?;
214
215 let mut cbb = LcCBB::new(key_size);
216 if 1 != unsafe { BN_bn2cbb_padded(cbb.as_mut_ptr(), key_size, private_bn.as_const_ptr()) } {
217 return Err(Unspecified);
218 }
219 cbb.into_vec()
220 }
221}
222
223pub(crate) mod rfc5915 {
224 use crate::aws_lc::{
225 EC_KEY_get_enc_flags, EC_KEY_marshal_private_key, EC_KEY_parse_private_key,
226 EVP_PKEY_get0_EC_KEY, EVP_PKEY_new, EVP_PKEY_set1_EC_KEY, EVP_PKEY,
227 };
228 use crate::cbb::LcCBB;
229 use crate::cbs::build_CBS;
230 use crate::ec::ec_group_from_nid;
231 use crate::error::{KeyRejected, Unspecified};
232 use crate::ptr::LcPtr;
233
234 pub(crate) fn parse_rfc5915_private_key(
235 key_bytes: &[u8],
236 expected_curve_nid: i32,
237 ) -> Result<LcPtr<EVP_PKEY>, KeyRejected> {
238 let ec_group = ec_group_from_nid(expected_curve_nid)?;
239 let mut cbs = build_CBS(key_bytes);
240 let mut ec_key =
241 LcPtr::new(unsafe { EC_KEY_parse_private_key(&mut cbs, ec_group.as_const_ptr()) })?;
242 let mut evp_pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?;
243 if 1 != unsafe { EVP_PKEY_set1_EC_KEY(evp_pkey.as_mut_ptr(), ec_key.as_mut_ptr()) } {
244 return Err(KeyRejected::unexpected_error());
245 }
246 Ok(evp_pkey)
247 }
248
249 pub(crate) fn marshal_rfc5915_private_key(
250 evp_pkey: &LcPtr<EVP_PKEY>,
251 ) -> Result<Vec<u8>, Unspecified> {
252 let ec_key = evp_pkey.project_const_lifetime(unsafe {
253 |evp_pkey| EVP_PKEY_get0_EC_KEY(evp_pkey.as_const_ptr())
254 })?;
255 let mut cbb = LcCBB::new(evp_pkey.as_const().key_size_bytes());
256 let enc_flags = unsafe { EC_KEY_get_enc_flags(ec_key.as_const_ptr()) };
257 if 1 != unsafe {
258 EC_KEY_marshal_private_key(cbb.as_mut_ptr(), ec_key.as_const_ptr(), enc_flags)
259 } {
260 return Err(Unspecified);
261 }
262 cbb.into_vec()
263 }
264}
265
266pub(crate) fn parse_ec_public_key(
267 key_bytes: &[u8],
268 expected_curve_nid: i32,
269) -> Result<LcPtr<EVP_PKEY>, KeyRejected> {
270 LcPtr::<EVP_PKEY>::parse_rfc5280_public_key(key_bytes, EVP_PKEY_EC)
271 .or(parse_sec1_public_point(key_bytes, expected_curve_nid))
272 .and_then(|key| validate_ec_evp_key(&key.as_const(), expected_curve_nid).map(|()| key))
273}