1use crate::aws_lc::{
5 EVP_DigestSign, EVP_DigestSignInit, EVP_DigestVerify, EVP_DigestVerifyInit, EVP_PKEY_CTX_new,
6 EVP_PKEY_CTX_new_id, EVP_PKEY_bits, EVP_PKEY_cmp, EVP_PKEY_get0_EC_KEY, EVP_PKEY_get0_RSA,
7 EVP_PKEY_get_raw_private_key, EVP_PKEY_get_raw_public_key, EVP_PKEY_id, EVP_PKEY_keygen,
8 EVP_PKEY_keygen_init, EVP_PKEY_new_raw_private_key, EVP_PKEY_new_raw_public_key, EVP_PKEY_size,
9 EVP_PKEY_up_ref, EVP_marshal_private_key, EVP_marshal_private_key_v2, EVP_marshal_public_key,
10 EVP_parse_private_key, EVP_parse_public_key, EC_KEY, EVP_PKEY, EVP_PKEY_CTX, EVP_PKEY_ED25519,
11 RSA,
12};
13#[cfg(all(feature = "unstable", not(feature = "fips")))]
14use crate::aws_lc::{
15 EVP_PKEY_pqdsa_new_raw_private_key, EVP_PKEY_pqdsa_new_raw_public_key, EVP_PKEY_PQDSA,
16 NID_MLDSA44, NID_MLDSA65, NID_MLDSA87,
17};
18use crate::cbb::LcCBB;
19use crate::error::{KeyRejected, Unspecified};
20use crate::pkcs8::Version;
21use crate::ptr::{ConstPointer, LcPtr};
22use crate::{cbs, digest};
23use crate::digest::digest_ctx::DigestContext;
26use crate::fips::indicator_check;
27use std::os::raw::c_int;
28use std::ptr::{null, null_mut};
29
30impl PartialEq<Self> for LcPtr<EVP_PKEY> {
31 fn eq(&self, other: &Self) -> bool {
33 1 == unsafe { EVP_PKEY_cmp(*self.as_const(), *other.as_const()) }
35 }
36}
37
38#[allow(non_camel_case_types)]
39pub(crate) trait EVP_PKEY_CTX_consumer: Fn(*mut EVP_PKEY_CTX) -> Result<(), ()> {}
40
41impl<T> EVP_PKEY_CTX_consumer for T where T: Fn(*mut EVP_PKEY_CTX) -> Result<(), ()> {}
42
43#[allow(non_upper_case_globals, clippy::type_complexity)]
44pub(crate) const No_EVP_PKEY_CTX_consumer: Option<fn(*mut EVP_PKEY_CTX) -> Result<(), ()>> = None;
45
46impl ConstPointer<'_, EVP_PKEY> {
47 pub(crate) fn validate_as_ed25519(&self) -> Result<(), KeyRejected> {
48 const ED25519_KEY_TYPE: c_int = EVP_PKEY_ED25519;
49 const ED25519_MIN_BITS: c_int = 253;
50 const ED25519_MAX_BITS: c_int = 256;
51
52 let key_type = self.id();
53 if key_type != ED25519_KEY_TYPE {
54 return Err(KeyRejected::wrong_algorithm());
55 }
56
57 let bits: c_int = self.key_size_bits().try_into().unwrap();
58 if bits < ED25519_MIN_BITS {
59 return Err(KeyRejected::too_small());
60 }
61
62 if bits > ED25519_MAX_BITS {
63 return Err(KeyRejected::too_large());
64 }
65 Ok(())
66 }
67
68 pub(crate) fn id(&self) -> i32 {
82 unsafe { EVP_PKEY_id(**self) }
83 }
84
85 pub(crate) fn key_size_bytes(&self) -> usize {
86 self.key_size_bits() / 8
87 }
88
89 pub(crate) fn key_size_bits(&self) -> usize {
90 unsafe { EVP_PKEY_bits(**self) }.try_into().unwrap()
91 }
92
93 pub(crate) fn signature_size_bytes(&self) -> usize {
94 unsafe { EVP_PKEY_size(**self) }.try_into().unwrap()
95 }
96
97 #[allow(dead_code)]
98 pub(crate) fn get_ec_key(&self) -> Result<ConstPointer<'_, EC_KEY>, KeyRejected> {
99 self.project_const_lifetime(unsafe { |evp_pkey| EVP_PKEY_get0_EC_KEY(**evp_pkey) })
100 .map_err(|()| KeyRejected::wrong_algorithm())
101 }
102
103 pub(crate) fn get_rsa(&self) -> Result<ConstPointer<'_, RSA>, KeyRejected> {
104 self.project_const_lifetime(unsafe { |evp_pkey| EVP_PKEY_get0_RSA(**evp_pkey) })
105 .map_err(|()| KeyRejected::wrong_algorithm())
106 }
107
108 pub(crate) fn marshal_rfc5280_public_key(&self) -> Result<Vec<u8>, Unspecified> {
109 let mut cbb = LcCBB::new(self.key_size_bytes() * 5);
113 if 1 != unsafe { EVP_marshal_public_key(cbb.as_mut_ptr(), **self) } {
114 return Err(Unspecified);
115 }
116 cbb.into_vec()
117 }
118
119 pub(crate) fn marshal_rfc5208_private_key(
120 &self,
121 version: Version,
122 ) -> Result<Vec<u8>, Unspecified> {
123 let key_size_bytes =
124 TryInto::<usize>::try_into(unsafe { EVP_PKEY_bits(**self) }).expect("fit in usize") / 8;
125 let mut cbb = LcCBB::new(key_size_bytes * 5);
126 match version {
127 Version::V1 => {
128 if 1 != unsafe { EVP_marshal_private_key(cbb.as_mut_ptr(), **self) } {
129 return Err(Unspecified);
130 }
131 }
132 Version::V2 => {
133 if 1 != unsafe { EVP_marshal_private_key_v2(cbb.as_mut_ptr(), **self) } {
134 return Err(Unspecified);
135 }
136 }
137 }
138 cbb.into_vec()
139 }
140
141 pub(crate) fn marshal_raw_private_key(&self) -> Result<Vec<u8>, Unspecified> {
142 let mut size = 0;
143 if 1 != unsafe { EVP_PKEY_get_raw_private_key(**self, null_mut(), &mut size) } {
144 return Err(Unspecified);
145 }
146 let mut buffer = vec![0u8; size];
147 let buffer_size = self.marshal_raw_private_to_buffer(&mut buffer)?;
148 debug_assert_eq!(buffer_size, size);
149 Ok(buffer)
150 }
151
152 pub(crate) fn marshal_raw_private_to_buffer(
153 &self,
154 buffer: &mut [u8],
155 ) -> Result<usize, Unspecified> {
156 let mut key_len = buffer.len();
157 if 1 == unsafe { EVP_PKEY_get_raw_private_key(**self, buffer.as_mut_ptr(), &mut key_len) } {
158 Ok(key_len)
159 } else {
160 Err(Unspecified)
161 }
162 }
163
164 #[allow(dead_code)]
165 pub(crate) fn marshal_raw_public_key(&self) -> Result<Vec<u8>, Unspecified> {
166 let mut size = 0;
167 if 1 != unsafe { EVP_PKEY_get_raw_public_key(**self, null_mut(), &mut size) } {
168 return Err(Unspecified);
169 }
170 let mut buffer = vec![0u8; size];
171 let buffer_size = self.marshal_raw_public_to_buffer(&mut buffer)?;
172 debug_assert_eq!(buffer_size, size);
173 Ok(buffer)
174 }
175
176 pub(crate) fn marshal_raw_public_to_buffer(
177 &self,
178 buffer: &mut [u8],
179 ) -> Result<usize, Unspecified> {
180 let mut key_len = buffer.len();
181 if 1 == unsafe {
182 EVP_PKEY_get_raw_public_key(**self, buffer.as_mut_ptr(), &mut key_len)
186 } {
187 Ok(key_len)
188 } else {
189 Err(Unspecified)
190 }
191 }
192}
193
194impl LcPtr<EVP_PKEY> {
195 pub(crate) fn parse_rfc5280_public_key(
196 bytes: &[u8],
197 evp_pkey_type: c_int,
198 ) -> Result<Self, KeyRejected> {
199 let mut cbs = cbs::build_CBS(bytes);
200 let evp_pkey = LcPtr::new(unsafe { EVP_parse_public_key(&mut cbs) })
202 .map_err(|()| KeyRejected::invalid_encoding())?;
203 evp_pkey
204 .as_const()
205 .id()
206 .eq(&evp_pkey_type)
207 .then_some(evp_pkey)
208 .ok_or(KeyRejected::wrong_algorithm())
209 }
210
211 pub(crate) fn parse_rfc5208_private_key(
212 bytes: &[u8],
213 evp_pkey_type: c_int,
214 ) -> Result<Self, KeyRejected> {
215 let mut cbs = cbs::build_CBS(bytes);
216 let evp_pkey = LcPtr::new(unsafe { EVP_parse_private_key(&mut cbs) })
218 .map_err(|()| KeyRejected::invalid_encoding())?;
219 evp_pkey
220 .as_const()
221 .id()
222 .eq(&evp_pkey_type)
223 .then_some(evp_pkey)
224 .ok_or(KeyRejected::wrong_algorithm())
225 }
226
227 #[allow(non_snake_case)]
228 pub(crate) fn create_EVP_PKEY_CTX(&self) -> Result<LcPtr<EVP_PKEY_CTX>, ()> {
229 LcPtr::new(unsafe { EVP_PKEY_CTX_new(*self.as_mut_unsafe(), null_mut()) })
233 }
234
235 pub(crate) fn parse_raw_private_key(
236 bytes: &[u8],
237 evp_pkey_type: c_int,
238 ) -> Result<Self, KeyRejected> {
239 #[cfg(all(feature = "unstable", not(feature = "fips")))]
240 if evp_pkey_type == EVP_PKEY_PQDSA {
241 return match bytes.len() {
242 2560 => Self::new(unsafe {
243 EVP_PKEY_pqdsa_new_raw_private_key(NID_MLDSA44, bytes.as_ptr(), bytes.len())
244 }),
245 4032 => Self::new(unsafe {
246 EVP_PKEY_pqdsa_new_raw_private_key(NID_MLDSA65, bytes.as_ptr(), bytes.len())
247 }),
248 4896 => Self::new(unsafe {
249 EVP_PKEY_pqdsa_new_raw_private_key(NID_MLDSA87, bytes.as_ptr(), bytes.len())
250 }),
251 _ => Err(()),
252 }
253 .map_err(|()| KeyRejected::invalid_encoding());
254 }
255
256 Self::new(unsafe {
257 EVP_PKEY_new_raw_private_key(evp_pkey_type, null_mut(), bytes.as_ptr(), bytes.len())
258 })
259 .map_err(|()| KeyRejected::unspecified())
260 }
261
262 pub(crate) fn parse_raw_public_key(
263 bytes: &[u8],
264 evp_pkey_type: c_int,
265 ) -> Result<Self, KeyRejected> {
266 #[cfg(all(feature = "unstable", not(feature = "fips")))]
267 if evp_pkey_type == EVP_PKEY_PQDSA {
268 return match bytes.len() {
269 1312 => Self::new(unsafe {
270 EVP_PKEY_pqdsa_new_raw_public_key(NID_MLDSA44, bytes.as_ptr(), bytes.len())
271 }),
272 1952 => Self::new(unsafe {
273 EVP_PKEY_pqdsa_new_raw_public_key(NID_MLDSA65, bytes.as_ptr(), bytes.len())
274 }),
275 2592 => Self::new(unsafe {
276 EVP_PKEY_pqdsa_new_raw_public_key(NID_MLDSA87, bytes.as_ptr(), bytes.len())
277 }),
278 _ => Err(()),
279 }
280 .map_err(|()| KeyRejected::unspecified());
281 }
282
283 Self::new(unsafe {
284 EVP_PKEY_new_raw_public_key(evp_pkey_type, null_mut(), bytes.as_ptr(), bytes.len())
285 })
286 .map_err(|()| KeyRejected::invalid_encoding())
287 }
288
289 pub(crate) fn sign<F>(
290 &self,
291 message: &[u8],
292 digest: Option<&'static digest::Algorithm>,
293 padding_fn: Option<F>,
294 ) -> Result<Box<[u8]>, Unspecified>
295 where
296 F: EVP_PKEY_CTX_consumer,
297 {
298 let mut md_ctx = DigestContext::new_uninit();
299 let evp_md = if let Some(alg) = digest {
300 *digest::match_digest_type(&alg.id)
301 } else {
302 null()
303 };
304 let mut pctx = null_mut::<EVP_PKEY_CTX>();
305 if 1 != unsafe {
306 EVP_DigestSignInit(
310 md_ctx.as_mut_ptr(),
311 &mut pctx,
312 evp_md,
313 null_mut(),
314 *self.as_mut_unsafe(),
315 )
316 } {
317 return Err(Unspecified);
318 }
319
320 if let Some(pad_fn) = padding_fn {
321 pad_fn(pctx)?;
322 }
323
324 let mut sig_len = 0;
326 if 1 != unsafe {
327 EVP_DigestSign(
328 md_ctx.as_mut_ptr(),
329 null_mut(),
330 &mut sig_len,
331 message.as_ptr(),
332 message.len(),
333 )
334 } {
335 return Err(Unspecified);
336 }
337 if sig_len == 0 {
338 return Err(Unspecified);
339 }
340
341 let mut signature = vec![0u8; sig_len];
342 if 1 != indicator_check!(unsafe {
343 EVP_DigestSign(
344 md_ctx.as_mut_ptr(),
345 signature.as_mut_ptr(),
346 &mut sig_len,
347 message.as_ptr(),
348 message.len(),
349 )
350 }) {
351 return Err(Unspecified);
352 }
353 signature.truncate(sig_len);
354 Ok(signature.into_boxed_slice())
355 }
356
357 pub(crate) fn verify<F>(
358 &self,
359 msg: &[u8],
360 digest: Option<&'static digest::Algorithm>,
361 padding_fn: Option<F>,
362 signature: &[u8],
363 ) -> Result<(), Unspecified>
364 where
365 F: EVP_PKEY_CTX_consumer,
366 {
367 let mut md_ctx = DigestContext::new_uninit();
368
369 let evp_md = if let Some(alg) = digest {
370 *digest::match_digest_type(&alg.id)
371 } else {
372 null()
373 };
374
375 let mut pctx = null_mut::<EVP_PKEY_CTX>();
376
377 if 1 != unsafe {
378 EVP_DigestVerifyInit(
379 md_ctx.as_mut_ptr(),
380 &mut pctx,
381 evp_md,
382 null_mut(),
383 *self.as_mut_unsafe(),
384 )
385 } {
386 return Err(Unspecified);
387 }
388 if let Some(pad_fn) = padding_fn {
389 pad_fn(pctx)?;
390 }
391
392 if 1 != indicator_check!(unsafe {
393 EVP_DigestVerify(
394 md_ctx.as_mut_ptr(),
395 signature.as_ptr(),
396 signature.len(),
397 msg.as_ptr(),
398 msg.len(),
399 )
400 }) {
401 return Err(Unspecified);
402 }
403
404 Ok(())
405 }
406
407 pub(crate) fn generate<F>(pkey_type: c_int, params_fn: Option<F>) -> Result<Self, Unspecified>
408 where
409 F: EVP_PKEY_CTX_consumer,
410 {
411 let mut pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new_id(pkey_type, null_mut()) })?;
412
413 if 1 != unsafe { EVP_PKEY_keygen_init(*pkey_ctx.as_mut()) } {
414 return Err(Unspecified);
415 }
416
417 if let Some(pad_fn) = params_fn {
418 pad_fn(*pkey_ctx.as_mut())?;
419 }
420
421 let mut pkey = null_mut::<EVP_PKEY>();
422
423 if 1 != indicator_check!(unsafe { EVP_PKEY_keygen(*pkey_ctx.as_mut(), &mut pkey) }) {
424 return Err(Unspecified);
425 }
426
427 Ok(LcPtr::new(pkey)?)
428 }
429}
430
431impl Clone for LcPtr<EVP_PKEY> {
432 fn clone(&self) -> Self {
433 assert_eq!(
436 1,
437 unsafe { EVP_PKEY_up_ref(*self.as_mut_unsafe()) },
438 "infallible AWS-LC function"
439 );
440 Self::new(unsafe { *self.as_mut_unsafe() }).expect("non-null AWS-LC EVP_PKEY pointer")
441 }
442}