• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2023, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14  */
15 
16 //! `Pkey` and `PkeyCtx` classes for holding asymmetric keys. This module is intended for internal
17 //! use within this crate only, to create higher-level abstractions suitable to be exposed
18 //! externally.
19 
20 use crate::{ec::EcKey, CSliceMut, ForeignType};
21 use alloc::borrow::ToOwned;
22 use alloc::string::String;
23 
24 pub(crate) struct Pkey {
25     ptr: *mut bssl_sys::EVP_PKEY,
26 }
27 
28 // Safety: Implementation ensures `from_ptr(x).as_ptr == x`
29 unsafe impl ForeignType for Pkey {
30     type CType = bssl_sys::EVP_PKEY;
31 
from_ptr(ptr: *mut Self::CType) -> Self32     unsafe fn from_ptr(ptr: *mut Self::CType) -> Self {
33         Self { ptr }
34     }
35 
as_ptr(&self) -> *mut Self::CType36     fn as_ptr(&self) -> *mut Self::CType {
37         self.ptr
38     }
39 }
40 
41 impl From<&EcKey> for Pkey {
from(eckey: &EcKey) -> Self42     fn from(eckey: &EcKey) -> Self {
43         // Safety: EVP_PKEY_new does not have any preconditions
44         let pkey = unsafe { bssl_sys::EVP_PKEY_new() };
45         assert!(!pkey.is_null());
46         // Safety:
47         // - pkey is just allocated and is null-checked
48         // - EcKey ensures eckey.ptr is valid during its lifetime
49         // - EVP_PKEY_set1_EC_KEY doesn't take ownership
50         let result = unsafe { bssl_sys::EVP_PKEY_set1_EC_KEY(pkey, eckey.as_ptr()) };
51         assert_eq!(result, 1, "bssl_sys::EVP_PKEY_set1_EC_KEY failed");
52         Self { ptr: pkey }
53     }
54 }
55 
56 impl Drop for Pkey {
drop(&mut self)57     fn drop(&mut self) {
58         // Safety: `self.ptr` is owned by this struct
59         unsafe { bssl_sys::EVP_PKEY_free(self.ptr) }
60     }
61 }
62 
63 pub(crate) struct PkeyCtx {
64     ptr: *mut bssl_sys::EVP_PKEY_CTX,
65 }
66 
67 impl PkeyCtx {
new(pkey: &Pkey) -> Self68     pub fn new(pkey: &Pkey) -> Self {
69         // Safety:
70         // - `Pkey` ensures `pkey.ptr` is valid, and EVP_PKEY_CTX_new does not take ownership.
71         let pkeyctx = unsafe { bssl_sys::EVP_PKEY_CTX_new(pkey.ptr, core::ptr::null_mut()) };
72         assert!(!pkeyctx.is_null());
73         Self { ptr: pkeyctx }
74     }
75 
76     #[allow(clippy::panic)]
diffie_hellman( self, other_public_key: &Pkey, mut output: CSliceMut, ) -> Result<(), String>77     pub(crate) fn diffie_hellman(
78         self,
79         other_public_key: &Pkey,
80         mut output: CSliceMut,
81     ) -> Result<(), String> {
82         let result = unsafe { bssl_sys::EVP_PKEY_derive_init(self.ptr) };
83         assert_eq!(result, 1, "bssl_sys::EVP_PKEY_derive_init failed");
84 
85         let result = unsafe { bssl_sys::EVP_PKEY_derive_set_peer(self.ptr, other_public_key.ptr) };
86         assert_eq!(result, 1, "bssl_sys::EVP_PKEY_derive_set_peer failed");
87 
88         let result =
89             unsafe { bssl_sys::EVP_PKEY_derive(self.ptr, output.as_mut_ptr(), &mut output.len()) };
90         match result {
91             0 => Err("bssl_sys::EVP_PKEY_derive failed".to_owned()),
92             1 => Ok(()),
93             _ => panic!("Unexpected result {result:?} from bssl_sys::EVP_PKEY_derive"),
94         }
95     }
96 }
97 
98 impl Drop for PkeyCtx {
drop(&mut self)99     fn drop(&mut self) {
100         // Safety: self.ptr is owned by this struct
101         unsafe { bssl_sys::EVP_PKEY_CTX_free(self.ptr) }
102     }
103 }
104