Coverage Report

Created: 2026-02-14 06:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}