/rust/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-rs-1.15.4/src/evp_pkey.rs
Line | Count | Source |
1 | | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. |
2 | | // SPDX-License-Identifier: Apache-2.0 OR ISC |
3 | | |
4 | | use 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_derive, EVP_PKEY_derive_init, |
7 | | EVP_PKEY_derive_set_peer, EVP_PKEY_get0_EC_KEY, EVP_PKEY_get0_RSA, |
8 | | EVP_PKEY_get_raw_private_key, EVP_PKEY_get_raw_public_key, EVP_PKEY_id, EVP_PKEY_keygen, |
9 | | EVP_PKEY_keygen_init, EVP_PKEY_new_raw_private_key, EVP_PKEY_new_raw_public_key, EVP_PKEY_sign, |
10 | | EVP_PKEY_sign_init, EVP_PKEY_size, EVP_PKEY_up_ref, EVP_PKEY_verify, EVP_PKEY_verify_init, |
11 | | EVP_marshal_private_key, EVP_marshal_private_key_v2, EVP_marshal_public_key, |
12 | | EVP_parse_private_key, EVP_parse_public_key, EC_KEY, EVP_PKEY, EVP_PKEY_CTX, EVP_PKEY_ED25519, |
13 | | RSA, |
14 | | }; |
15 | | #[cfg(all(feature = "unstable", not(feature = "fips")))] |
16 | | use crate::aws_lc::{ |
17 | | EVP_PKEY_pqdsa_new_raw_private_key, EVP_PKEY_pqdsa_new_raw_public_key, EVP_PKEY_PQDSA, |
18 | | NID_MLDSA44, NID_MLDSA65, NID_MLDSA87, |
19 | | }; |
20 | | use crate::cbb::LcCBB; |
21 | | use crate::digest::digest_ctx::DigestContext; |
22 | | use crate::digest::Digest; |
23 | | use crate::error::{KeyRejected, Unspecified}; |
24 | | use crate::fips::indicator_check; |
25 | | use crate::pkcs8::Version; |
26 | | use crate::ptr::{ConstPointer, LcPtr}; |
27 | | use crate::{cbs, digest}; |
28 | | use core::ffi::c_int; |
29 | | use std::ptr::{null, null_mut}; |
30 | | |
31 | | impl PartialEq<Self> for LcPtr<EVP_PKEY> { |
32 | | /// Only compares params and public key |
33 | 0 | fn eq(&self, other: &Self) -> bool { |
34 | | // EVP_PKEY_cmp only compares params and public key |
35 | 0 | 1 == unsafe { EVP_PKEY_cmp(self.as_const_ptr(), other.as_const_ptr()) } |
36 | 0 | } |
37 | | } |
38 | | |
39 | | #[allow(non_camel_case_types)] |
40 | | pub(crate) trait EVP_PKEY_CTX_consumer: Fn(*mut EVP_PKEY_CTX) -> Result<(), ()> {} |
41 | | |
42 | | impl<T> EVP_PKEY_CTX_consumer for T where T: Fn(*mut EVP_PKEY_CTX) -> Result<(), ()> {} |
43 | | |
44 | | #[allow(non_upper_case_globals, clippy::type_complexity)] |
45 | | pub(crate) const No_EVP_PKEY_CTX_consumer: Option<fn(*mut EVP_PKEY_CTX) -> Result<(), ()>> = None; |
46 | | |
47 | | impl ConstPointer<'_, EVP_PKEY> { |
48 | 0 | pub(crate) fn validate_as_ed25519(&self) -> Result<(), KeyRejected> { |
49 | | const ED25519_KEY_TYPE: c_int = EVP_PKEY_ED25519; |
50 | | const ED25519_MIN_BITS: c_int = 253; |
51 | | const ED25519_MAX_BITS: c_int = 256; |
52 | | |
53 | 0 | let key_type = self.id(); |
54 | 0 | if key_type != ED25519_KEY_TYPE { |
55 | 0 | return Err(KeyRejected::wrong_algorithm()); |
56 | 0 | } |
57 | | |
58 | 0 | let bits: c_int = self.key_size_bits().try_into().unwrap(); |
59 | 0 | if bits < ED25519_MIN_BITS { |
60 | 0 | return Err(KeyRejected::too_small()); |
61 | 0 | } |
62 | | |
63 | 0 | if bits > ED25519_MAX_BITS { |
64 | 0 | return Err(KeyRejected::too_large()); |
65 | 0 | } |
66 | 0 | Ok(()) |
67 | 0 | } |
68 | | |
69 | | // EVP_PKEY_NONE = 0; |
70 | | // EVP_PKEY_RSA = 6; |
71 | | // EVP_PKEY_RSA_PSS = 912; |
72 | | // EVP_PKEY_DSA = 116; |
73 | | // EVP_PKEY_EC = 408; |
74 | | // EVP_PKEY_ED25519 = 949; |
75 | | // EVP_PKEY_X25519 = 948; |
76 | | // EVP_PKEY_KYBER512 = 970; |
77 | | // EVP_PKEY_HKDF = 969; |
78 | | // EVP_PKEY_DH = 28; |
79 | | // EVP_PKEY_RSA2 = 19; |
80 | | // EVP_PKEY_X448 = 961; |
81 | | // EVP_PKEY_ED448 = 960; |
82 | 0 | pub(crate) fn id(&self) -> i32 { |
83 | 0 | unsafe { EVP_PKEY_id(self.as_const_ptr()) } |
84 | 0 | } |
85 | | |
86 | 0 | pub(crate) fn key_size_bytes(&self) -> usize { |
87 | 0 | self.key_size_bits() / 8 |
88 | 0 | } |
89 | | |
90 | 0 | pub(crate) fn key_size_bits(&self) -> usize { |
91 | 0 | unsafe { EVP_PKEY_bits(self.as_const_ptr()) } |
92 | 0 | .try_into() |
93 | 0 | .unwrap() |
94 | 0 | } |
95 | | |
96 | 0 | pub(crate) fn signature_size_bytes(&self) -> usize { |
97 | 0 | unsafe { EVP_PKEY_size(self.as_const_ptr()) } |
98 | 0 | .try_into() |
99 | 0 | .unwrap() |
100 | 0 | } |
101 | | |
102 | | #[allow(dead_code)] |
103 | 0 | pub(crate) fn get_ec_key(&self) -> Result<ConstPointer<'_, EC_KEY>, KeyRejected> { |
104 | 0 | self.project_const_lifetime(unsafe { |
105 | 0 | |evp_pkey| EVP_PKEY_get0_EC_KEY(evp_pkey.as_const_ptr()) |
106 | | }) |
107 | 0 | .map_err(|()| KeyRejected::wrong_algorithm()) |
108 | 0 | } |
109 | | |
110 | 0 | pub(crate) fn get_rsa(&self) -> Result<ConstPointer<'_, RSA>, KeyRejected> { |
111 | 0 | self.project_const_lifetime(unsafe { |
112 | 0 | |evp_pkey| EVP_PKEY_get0_RSA(evp_pkey.as_const_ptr()) |
113 | | }) |
114 | 0 | .map_err(|()| KeyRejected::wrong_algorithm()) |
115 | 0 | } |
116 | | |
117 | 0 | pub(crate) fn marshal_rfc5280_public_key(&self) -> Result<Vec<u8>, Unspecified> { |
118 | | // Data shows that the SubjectPublicKeyInfo is roughly 356% to 375% increase in size compared to the RSA key |
119 | | // size in bytes for keys ranging from 2048-bit to 4096-bit. So size the initial capacity to be roughly |
120 | | // 500% as a conservative estimate to avoid needing to reallocate for any key in that range. |
121 | 0 | let mut cbb = LcCBB::new(self.key_size_bytes() * 5); |
122 | 0 | if 1 != unsafe { EVP_marshal_public_key(cbb.as_mut_ptr(), self.as_const_ptr()) } { |
123 | 0 | return Err(Unspecified); |
124 | 0 | } |
125 | 0 | cbb.into_vec() |
126 | 0 | } |
127 | | |
128 | 0 | pub(crate) fn marshal_rfc5208_private_key( |
129 | 0 | &self, |
130 | 0 | version: Version, |
131 | 0 | ) -> Result<Vec<u8>, Unspecified> { |
132 | 0 | let key_size_bytes = |
133 | 0 | TryInto::<usize>::try_into(unsafe { EVP_PKEY_bits(self.as_const_ptr()) }) |
134 | 0 | .expect("fit in usize") |
135 | 0 | / 8; |
136 | 0 | let mut cbb = LcCBB::new(key_size_bytes * 5); |
137 | 0 | match version { |
138 | | Version::V1 => { |
139 | 0 | if 1 != unsafe { EVP_marshal_private_key(cbb.as_mut_ptr(), self.as_const_ptr()) } { |
140 | 0 | return Err(Unspecified); |
141 | 0 | } |
142 | | } |
143 | | Version::V2 => { |
144 | 0 | if 1 != unsafe { EVP_marshal_private_key_v2(cbb.as_mut_ptr(), self.as_const_ptr()) } |
145 | | { |
146 | 0 | return Err(Unspecified); |
147 | 0 | } |
148 | | } |
149 | | } |
150 | 0 | cbb.into_vec() |
151 | 0 | } |
152 | | |
153 | 0 | pub(crate) fn marshal_raw_private_key(&self) -> Result<Vec<u8>, Unspecified> { |
154 | 0 | let mut size = 0; |
155 | 0 | if 1 != unsafe { EVP_PKEY_get_raw_private_key(self.as_const_ptr(), null_mut(), &mut size) } |
156 | | { |
157 | 0 | return Err(Unspecified); |
158 | 0 | } |
159 | 0 | let mut buffer = vec![0u8; size]; |
160 | 0 | let buffer_size = self.marshal_raw_private_to_buffer(&mut buffer)?; |
161 | 0 | debug_assert_eq!(buffer_size, size); |
162 | 0 | Ok(buffer) |
163 | 0 | } |
164 | | |
165 | 0 | pub(crate) fn marshal_raw_private_to_buffer( |
166 | 0 | &self, |
167 | 0 | buffer: &mut [u8], |
168 | 0 | ) -> Result<usize, Unspecified> { |
169 | 0 | let mut key_len = buffer.len(); |
170 | 0 | if 1 == unsafe { |
171 | 0 | EVP_PKEY_get_raw_private_key(self.as_const_ptr(), buffer.as_mut_ptr(), &mut key_len) |
172 | 0 | } { |
173 | 0 | Ok(key_len) |
174 | | } else { |
175 | 0 | Err(Unspecified) |
176 | | } |
177 | 0 | } |
178 | | |
179 | | #[allow(dead_code)] |
180 | 0 | pub(crate) fn marshal_raw_public_key(&self) -> Result<Vec<u8>, Unspecified> { |
181 | 0 | let mut size = 0; |
182 | 0 | if 1 != unsafe { EVP_PKEY_get_raw_public_key(self.as_const_ptr(), null_mut(), &mut size) } { |
183 | 0 | return Err(Unspecified); |
184 | 0 | } |
185 | 0 | let mut buffer = vec![0u8; size]; |
186 | 0 | let buffer_size = self.marshal_raw_public_to_buffer(&mut buffer)?; |
187 | 0 | debug_assert_eq!(buffer_size, size); |
188 | 0 | Ok(buffer) |
189 | 0 | } |
190 | | |
191 | 0 | pub(crate) fn marshal_raw_public_to_buffer( |
192 | 0 | &self, |
193 | 0 | buffer: &mut [u8], |
194 | 0 | ) -> Result<usize, Unspecified> { |
195 | 0 | let mut key_len = buffer.len(); |
196 | 0 | if 1 == unsafe { |
197 | 0 | // `EVP_PKEY_get_raw_public_key` writes the total length |
198 | 0 | // to `encapsulate_key_size` in the event that the buffer we provide is larger then |
199 | 0 | // required. |
200 | 0 | EVP_PKEY_get_raw_public_key(self.as_const_ptr(), buffer.as_mut_ptr(), &mut key_len) |
201 | 0 | } { |
202 | 0 | Ok(key_len) |
203 | | } else { |
204 | 0 | Err(Unspecified) |
205 | | } |
206 | 0 | } |
207 | | } |
208 | | |
209 | | impl LcPtr<EVP_PKEY> { |
210 | | #[inline] |
211 | 0 | pub unsafe fn as_mut_unsafe_ptr(&self) -> *mut EVP_PKEY { |
212 | 0 | self.as_const_ptr().cast_mut() |
213 | 0 | } Unexecuted instantiation: <aws_lc_rs::ptr::ManagedPointer<*mut aws_lc_sys::universal_crypto::evp_pkey_st>>::as_mut_unsafe_ptr Unexecuted instantiation: <aws_lc_rs::ptr::ManagedPointer<*mut aws_lc_sys::universal_crypto::evp_pkey_st>>::as_mut_unsafe_ptr |
214 | | |
215 | 0 | pub(crate) fn parse_rfc5280_public_key( |
216 | 0 | bytes: &[u8], |
217 | 0 | evp_pkey_type: c_int, |
218 | 0 | ) -> Result<Self, KeyRejected> { |
219 | 0 | let mut cbs = cbs::build_CBS(bytes); |
220 | | // Also checks the validity of the key |
221 | 0 | let evp_pkey = LcPtr::new(unsafe { EVP_parse_public_key(&mut cbs) }) |
222 | 0 | .map_err(|()| KeyRejected::invalid_encoding())?; |
223 | 0 | evp_pkey |
224 | 0 | .as_const() |
225 | 0 | .id() |
226 | 0 | .eq(&evp_pkey_type) |
227 | 0 | .then_some(evp_pkey) |
228 | 0 | .ok_or(KeyRejected::wrong_algorithm()) |
229 | 0 | } |
230 | | |
231 | 0 | pub(crate) fn parse_rfc5208_private_key( |
232 | 0 | bytes: &[u8], |
233 | 0 | evp_pkey_type: c_int, |
234 | 0 | ) -> Result<Self, KeyRejected> { |
235 | 0 | let mut cbs = cbs::build_CBS(bytes); |
236 | | // Also checks the validity of the key |
237 | 0 | let evp_pkey = LcPtr::new(unsafe { EVP_parse_private_key(&mut cbs) }) |
238 | 0 | .map_err(|()| KeyRejected::invalid_encoding())?; |
239 | 0 | evp_pkey |
240 | 0 | .as_const() |
241 | 0 | .id() |
242 | 0 | .eq(&evp_pkey_type) |
243 | 0 | .then_some(evp_pkey) |
244 | 0 | .ok_or(KeyRejected::wrong_algorithm()) |
245 | 0 | } |
246 | | |
247 | | #[allow(non_snake_case)] |
248 | 0 | pub(crate) fn create_EVP_PKEY_CTX(&self) -> Result<LcPtr<EVP_PKEY_CTX>, ()> { |
249 | | // The only modification made by EVP_PKEY_CTX_new to `priv_key` is to increment its |
250 | | // refcount. The modification is made while holding a global lock: |
251 | | // https://github.com/aws/aws-lc/blob/61503f7fe72457e12d3446853a5452d175560c49/crypto/refcount_lock.c#L29 |
252 | 0 | LcPtr::new(unsafe { EVP_PKEY_CTX_new(self.as_mut_unsafe_ptr(), null_mut()) }) |
253 | 0 | } |
254 | | |
255 | 0 | pub(crate) fn parse_raw_private_key( |
256 | 0 | bytes: &[u8], |
257 | 0 | evp_pkey_type: c_int, |
258 | 0 | ) -> Result<Self, KeyRejected> { |
259 | | #[cfg(all(feature = "unstable", not(feature = "fips")))] |
260 | | if evp_pkey_type == EVP_PKEY_PQDSA { |
261 | | return match bytes.len() { |
262 | | 2560 => Self::new(unsafe { |
263 | | EVP_PKEY_pqdsa_new_raw_private_key(NID_MLDSA44, bytes.as_ptr(), bytes.len()) |
264 | | }), |
265 | | 4032 => Self::new(unsafe { |
266 | | EVP_PKEY_pqdsa_new_raw_private_key(NID_MLDSA65, bytes.as_ptr(), bytes.len()) |
267 | | }), |
268 | | 4896 => Self::new(unsafe { |
269 | | EVP_PKEY_pqdsa_new_raw_private_key(NID_MLDSA87, bytes.as_ptr(), bytes.len()) |
270 | | }), |
271 | | _ => Err(()), |
272 | | } |
273 | | .map_err(|()| KeyRejected::invalid_encoding()); |
274 | | } |
275 | | |
276 | 0 | Self::new(unsafe { |
277 | 0 | EVP_PKEY_new_raw_private_key(evp_pkey_type, null_mut(), bytes.as_ptr(), bytes.len()) |
278 | | }) |
279 | 0 | .map_err(|()| KeyRejected::unspecified()) |
280 | 0 | } |
281 | | |
282 | 0 | pub(crate) fn parse_raw_public_key( |
283 | 0 | bytes: &[u8], |
284 | 0 | evp_pkey_type: c_int, |
285 | 0 | ) -> Result<Self, KeyRejected> { |
286 | | #[cfg(all(feature = "unstable", not(feature = "fips")))] |
287 | | if evp_pkey_type == EVP_PKEY_PQDSA { |
288 | | return match bytes.len() { |
289 | | 1312 => Self::new(unsafe { |
290 | | EVP_PKEY_pqdsa_new_raw_public_key(NID_MLDSA44, bytes.as_ptr(), bytes.len()) |
291 | | }), |
292 | | 1952 => Self::new(unsafe { |
293 | | EVP_PKEY_pqdsa_new_raw_public_key(NID_MLDSA65, bytes.as_ptr(), bytes.len()) |
294 | | }), |
295 | | 2592 => Self::new(unsafe { |
296 | | EVP_PKEY_pqdsa_new_raw_public_key(NID_MLDSA87, bytes.as_ptr(), bytes.len()) |
297 | | }), |
298 | | _ => Err(()), |
299 | | } |
300 | | .map_err(|()| KeyRejected::unspecified()); |
301 | | } |
302 | | |
303 | 0 | Self::new(unsafe { |
304 | 0 | EVP_PKEY_new_raw_public_key(evp_pkey_type, null_mut(), bytes.as_ptr(), bytes.len()) |
305 | | }) |
306 | 0 | .map_err(|()| KeyRejected::invalid_encoding()) |
307 | 0 | } |
308 | | |
309 | 0 | pub(crate) fn sign<F>( |
310 | 0 | &self, |
311 | 0 | message: &[u8], |
312 | 0 | digest: Option<&'static digest::Algorithm>, |
313 | 0 | padding_fn: Option<F>, |
314 | 0 | ) -> Result<Box<[u8]>, Unspecified> |
315 | 0 | where |
316 | 0 | F: EVP_PKEY_CTX_consumer, |
317 | | { |
318 | 0 | let mut md_ctx = DigestContext::new_uninit(); |
319 | 0 | let evp_md = if let Some(alg) = digest { |
320 | 0 | digest::match_digest_type(&alg.id).as_const_ptr() |
321 | | } else { |
322 | 0 | null() |
323 | | }; |
324 | 0 | let mut pctx = null_mut::<EVP_PKEY_CTX>(); |
325 | 0 | if 1 != unsafe { |
326 | 0 | // EVP_DigestSignInit does not mutate |pkey| for thread-safety purposes and may be |
327 | 0 | // used concurrently with other non-mutating functions on |pkey|. |
328 | 0 | // https://github.com/aws/aws-lc/blob/9b4b5a15a97618b5b826d742419ccd54c819fa42/include/openssl/evp.h#L297-L313 |
329 | 0 | EVP_DigestSignInit( |
330 | 0 | md_ctx.as_mut_ptr(), |
331 | 0 | &mut pctx, |
332 | 0 | evp_md, |
333 | 0 | null_mut(), |
334 | 0 | self.as_mut_unsafe_ptr(), |
335 | 0 | ) |
336 | 0 | } { |
337 | 0 | return Err(Unspecified); |
338 | 0 | } |
339 | | |
340 | 0 | if let Some(pad_fn) = padding_fn { |
341 | 0 | pad_fn(pctx)?; |
342 | 0 | } |
343 | | |
344 | | // Determine the maximum length of the signature. |
345 | 0 | let mut sig_len = 0; |
346 | 0 | if 1 != unsafe { |
347 | 0 | EVP_DigestSign( |
348 | 0 | md_ctx.as_mut_ptr(), |
349 | 0 | null_mut(), |
350 | 0 | &mut sig_len, |
351 | 0 | message.as_ptr(), |
352 | 0 | message.len(), |
353 | 0 | ) |
354 | 0 | } { |
355 | 0 | return Err(Unspecified); |
356 | 0 | } |
357 | 0 | if sig_len == 0 { |
358 | 0 | return Err(Unspecified); |
359 | 0 | } |
360 | | |
361 | 0 | let mut signature = vec![0u8; sig_len]; |
362 | 0 | if 1 != indicator_check!(unsafe { |
363 | 0 | EVP_DigestSign( |
364 | 0 | md_ctx.as_mut_ptr(), |
365 | 0 | signature.as_mut_ptr(), |
366 | 0 | &mut sig_len, |
367 | 0 | message.as_ptr(), |
368 | 0 | message.len(), |
369 | 0 | ) |
370 | 0 | }) { |
371 | 0 | return Err(Unspecified); |
372 | 0 | } |
373 | 0 | signature.truncate(sig_len); |
374 | 0 | Ok(signature.into_boxed_slice()) |
375 | 0 | } Unexecuted instantiation: <aws_lc_rs::ptr::ManagedPointer<*mut aws_lc_sys::universal_crypto::evp_pkey_st>>::sign::<fn(*mut aws_lc_sys::universal_crypto::evp_pkey_ctx_st) -> core::result::Result<(), ()>> Unexecuted instantiation: <aws_lc_rs::ptr::ManagedPointer<*mut aws_lc_sys::universal_crypto::evp_pkey_st>>::sign::<aws_lc_rs::rsa::signature::configure_rsa_pkcs1_pss_padding> |
376 | | |
377 | 0 | pub(crate) fn sign_digest<F>( |
378 | 0 | &self, |
379 | 0 | digest: &Digest, |
380 | 0 | padding_fn: Option<F>, |
381 | 0 | ) -> Result<Box<[u8]>, Unspecified> |
382 | 0 | where |
383 | 0 | F: EVP_PKEY_CTX_consumer, |
384 | | { |
385 | 0 | let mut pctx = self.create_EVP_PKEY_CTX()?; |
386 | | |
387 | 0 | if 1 != unsafe { EVP_PKEY_sign_init(pctx.as_mut_ptr()) } { |
388 | 0 | return Err(Unspecified); |
389 | 0 | } |
390 | | |
391 | 0 | if let Some(pad_fn) = padding_fn { |
392 | 0 | pad_fn(pctx.as_mut_ptr())?; |
393 | 0 | } |
394 | | |
395 | 0 | let msg_digest = digest.as_ref(); |
396 | 0 | let mut sig_len = 0; |
397 | 0 | if 1 != unsafe { |
398 | 0 | EVP_PKEY_sign( |
399 | 0 | pctx.as_mut_ptr(), |
400 | 0 | null_mut(), |
401 | 0 | &mut sig_len, |
402 | 0 | msg_digest.as_ptr(), |
403 | 0 | msg_digest.len(), |
404 | 0 | ) |
405 | 0 | } { |
406 | 0 | return Err(Unspecified); |
407 | 0 | } |
408 | | |
409 | 0 | let mut signature = vec![0u8; sig_len]; |
410 | 0 | if 1 != indicator_check!(unsafe { |
411 | 0 | EVP_PKEY_sign( |
412 | 0 | pctx.as_mut_ptr(), |
413 | 0 | signature.as_mut_ptr(), |
414 | 0 | &mut sig_len, |
415 | 0 | msg_digest.as_ptr(), |
416 | 0 | msg_digest.len(), |
417 | 0 | ) |
418 | 0 | }) { |
419 | 0 | return Err(Unspecified); |
420 | 0 | } |
421 | 0 | signature.truncate(sig_len); |
422 | | |
423 | 0 | Ok(signature.into_boxed_slice()) |
424 | 0 | } |
425 | | |
426 | 0 | pub(crate) fn verify<F>( |
427 | 0 | &self, |
428 | 0 | msg: &[u8], |
429 | 0 | digest: Option<&'static digest::Algorithm>, |
430 | 0 | padding_fn: Option<F>, |
431 | 0 | signature: &[u8], |
432 | 0 | ) -> Result<(), Unspecified> |
433 | 0 | where |
434 | 0 | F: EVP_PKEY_CTX_consumer, |
435 | | { |
436 | 0 | let mut md_ctx = DigestContext::new_uninit(); |
437 | | |
438 | 0 | let evp_md = if let Some(alg) = digest { |
439 | 0 | digest::match_digest_type(&alg.id).as_const_ptr() |
440 | | } else { |
441 | 0 | null() |
442 | | }; |
443 | | |
444 | 0 | let mut pctx = null_mut::<EVP_PKEY_CTX>(); |
445 | | |
446 | 0 | if 1 != unsafe { |
447 | 0 | EVP_DigestVerifyInit( |
448 | 0 | md_ctx.as_mut_ptr(), |
449 | 0 | &mut pctx, |
450 | 0 | evp_md, |
451 | 0 | null_mut(), |
452 | 0 | self.as_mut_unsafe_ptr(), |
453 | 0 | ) |
454 | 0 | } { |
455 | 0 | return Err(Unspecified); |
456 | 0 | } |
457 | 0 | if let Some(pad_fn) = padding_fn { |
458 | 0 | pad_fn(pctx)?; |
459 | 0 | } |
460 | | |
461 | 0 | if 1 != indicator_check!(unsafe { |
462 | 0 | EVP_DigestVerify( |
463 | 0 | md_ctx.as_mut_ptr(), |
464 | 0 | signature.as_ptr(), |
465 | 0 | signature.len(), |
466 | 0 | msg.as_ptr(), |
467 | 0 | msg.len(), |
468 | 0 | ) |
469 | 0 | }) { |
470 | 0 | return Err(Unspecified); |
471 | 0 | } |
472 | | |
473 | 0 | Ok(()) |
474 | 0 | } Unexecuted instantiation: <aws_lc_rs::ptr::ManagedPointer<*mut aws_lc_sys::universal_crypto::evp_pkey_st>>::verify::<fn(*mut aws_lc_sys::universal_crypto::evp_pkey_ctx_st) -> core::result::Result<(), ()>> Unexecuted instantiation: <aws_lc_rs::ptr::ManagedPointer<*mut aws_lc_sys::universal_crypto::evp_pkey_st>>::verify::<aws_lc_rs::rsa::signature::configure_rsa_pkcs1_pss_padding> |
475 | | |
476 | 0 | pub(crate) fn verify_digest_sig<F>( |
477 | 0 | &self, |
478 | 0 | digest: &Digest, |
479 | 0 | padding_fn: Option<F>, |
480 | 0 | signature: &[u8], |
481 | 0 | ) -> Result<(), Unspecified> |
482 | 0 | where |
483 | 0 | F: EVP_PKEY_CTX_consumer, |
484 | | { |
485 | 0 | let mut pctx = self.create_EVP_PKEY_CTX()?; |
486 | | |
487 | 0 | if 1 != unsafe { EVP_PKEY_verify_init(pctx.as_mut_ptr()) } { |
488 | 0 | return Err(Unspecified); |
489 | 0 | } |
490 | | |
491 | 0 | if let Some(pad_fn) = padding_fn { |
492 | 0 | pad_fn(pctx.as_mut_ptr())?; |
493 | 0 | } |
494 | | |
495 | 0 | let msg_digest = digest.as_ref(); |
496 | | |
497 | 0 | if 1 == unsafe { |
498 | 0 | indicator_check!(EVP_PKEY_verify( |
499 | 0 | pctx.as_mut_ptr(), |
500 | 0 | signature.as_ptr(), |
501 | 0 | signature.len(), |
502 | 0 | msg_digest.as_ptr(), |
503 | 0 | msg_digest.len(), |
504 | 0 | )) |
505 | 0 | } { |
506 | 0 | Ok(()) |
507 | | } else { |
508 | 0 | Err(Unspecified) |
509 | | } |
510 | 0 | } Unexecuted instantiation: <aws_lc_rs::ptr::ManagedPointer<*mut aws_lc_sys::universal_crypto::evp_pkey_st>>::verify_digest_sig::<fn(*mut aws_lc_sys::universal_crypto::evp_pkey_ctx_st) -> core::result::Result<(), ()>> Unexecuted instantiation: <aws_lc_rs::ptr::ManagedPointer<*mut aws_lc_sys::universal_crypto::evp_pkey_st>>::verify_digest_sig::<aws_lc_rs::rsa::signature::verify_rsa_digest_signature::{closure#0}> |
511 | | |
512 | 0 | pub(crate) fn agree(&self, peer_key: &mut Self) -> Result<Box<[u8]>, Unspecified> { |
513 | 0 | let mut pctx = self.create_EVP_PKEY_CTX()?; |
514 | | |
515 | 0 | if 1 != unsafe { EVP_PKEY_derive_init(pctx.as_mut_ptr()) } { |
516 | 0 | return Err(Unspecified); |
517 | 0 | } |
518 | | |
519 | 0 | let mut secret_len = 0; |
520 | 0 | if 1 != unsafe { EVP_PKEY_derive_set_peer(pctx.as_mut_ptr(), peer_key.as_mut_ptr()) } { |
521 | 0 | return Err(Unspecified); |
522 | 0 | } |
523 | | |
524 | 0 | if 1 != unsafe { EVP_PKEY_derive(pctx.as_mut_ptr(), null_mut(), &mut secret_len) } { |
525 | 0 | return Err(Unspecified); |
526 | 0 | } |
527 | | |
528 | 0 | let mut secret = vec![0u8; secret_len]; |
529 | 0 | if 1 != indicator_check!(unsafe { |
530 | 0 | EVP_PKEY_derive(pctx.as_mut_ptr(), secret.as_mut_ptr(), &mut secret_len) |
531 | 0 | }) { |
532 | 0 | return Err(Unspecified); |
533 | 0 | } |
534 | 0 | secret.truncate(secret_len); |
535 | | |
536 | 0 | Ok(secret.into_boxed_slice()) |
537 | 0 | } |
538 | | |
539 | 0 | pub(crate) fn generate<F>(pkey_type: c_int, params_fn: Option<F>) -> Result<Self, Unspecified> |
540 | 0 | where |
541 | 0 | F: EVP_PKEY_CTX_consumer, |
542 | | { |
543 | 0 | let mut pkey_ctx = LcPtr::new(unsafe { EVP_PKEY_CTX_new_id(pkey_type, null_mut()) })?; |
544 | | |
545 | 0 | if 1 != unsafe { EVP_PKEY_keygen_init(pkey_ctx.as_mut_ptr()) } { |
546 | 0 | return Err(Unspecified); |
547 | 0 | } |
548 | | |
549 | 0 | if let Some(pad_fn) = params_fn { |
550 | 0 | pad_fn(pkey_ctx.as_mut_ptr())?; |
551 | 0 | } |
552 | | |
553 | 0 | let mut pkey = null_mut::<EVP_PKEY>(); |
554 | | |
555 | 0 | if 1 != indicator_check!(unsafe { EVP_PKEY_keygen(pkey_ctx.as_mut_ptr(), &mut pkey) }) { |
556 | 0 | return Err(Unspecified); |
557 | 0 | } |
558 | | |
559 | 0 | Ok(LcPtr::new(pkey)?) |
560 | 0 | } Unexecuted instantiation: <aws_lc_rs::ptr::ManagedPointer<*mut aws_lc_sys::universal_crypto::evp_pkey_st>>::generate::<fn(*mut aws_lc_sys::universal_crypto::evp_pkey_ctx_st) -> core::result::Result<(), ()>> Unexecuted instantiation: <aws_lc_rs::ptr::ManagedPointer<*mut aws_lc_sys::universal_crypto::evp_pkey_st>>::generate::<aws_lc_rs::ec::evp_key_generate::{closure#0}>Unexecuted instantiation: <aws_lc_rs::ptr::ManagedPointer<*mut aws_lc_sys::universal_crypto::evp_pkey_st>>::generate::<aws_lc_rs::rsa::key::generate_rsa_key::{closure#0}> |
561 | | } |
562 | | |
563 | | impl Clone for LcPtr<EVP_PKEY> { |
564 | 0 | fn clone(&self) -> Self { |
565 | | // EVP_PKEY_up_ref increments the refcount while holding a global lock: |
566 | | // https://github.com/aws/aws-lc/blob/61503f7fe72457e12d3446853a5452d175560c49/crypto/refcount_lock.c#L29 |
567 | 0 | assert_eq!( |
568 | | 1, |
569 | 0 | unsafe { EVP_PKEY_up_ref(self.as_mut_unsafe_ptr()) }, |
570 | 0 | "infallible AWS-LC function" |
571 | | ); |
572 | 0 | Self::new(unsafe { self.as_mut_unsafe_ptr() }).expect("non-null AWS-LC EVP_PKEY pointer") |
573 | 0 | } |
574 | | } |