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