blob: 330f317f340d8e1ccd4e7692d670429a906f5ae9 [file] [log] [blame]
Alice Wang600ea5b2023-11-17 15:12:16 +00001// Copyright 2023, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Wrappers of the EVP functions in BoringSSL evp.h.
16
17use crate::cbb::CbbFixed;
Alice Wang7468ae42023-11-30 10:20:36 +000018use crate::digest::{Digester, DigesterContext};
Alice Wang600ea5b2023-11-17 15:12:16 +000019use crate::ec_key::EcKey;
20use crate::util::{check_int_result, to_call_failed_error};
21use alloc::vec::Vec;
22use bssl_avf_error::{ApiName, Result};
23use bssl_ffi::{
Alice Wang7468ae42023-11-30 10:20:36 +000024 CBB_flush, CBB_len, EVP_DigestVerify, EVP_DigestVerifyInit, EVP_PKEY_free, EVP_PKEY_new,
25 EVP_PKEY_new_raw_public_key, EVP_PKEY_set1_EC_KEY, EVP_marshal_public_key, EVP_PKEY,
26 EVP_PKEY_ED25519, EVP_PKEY_X25519,
Alice Wang600ea5b2023-11-17 15:12:16 +000027};
Alice Wang7468ae42023-11-30 10:20:36 +000028use core::ptr::{self, NonNull};
Alice Wang600ea5b2023-11-17 15:12:16 +000029
30/// Wrapper of an `EVP_PKEY` object, representing a public or private key.
Alice Wangeb77f7d2023-12-01 09:13:58 +000031pub struct PKey {
Alice Wang600ea5b2023-11-17 15:12:16 +000032 pkey: NonNull<EVP_PKEY>,
Alice Wang7468ae42023-11-30 10:20:36 +000033 /// If this struct owns the inner EC key, the inner EC key should remain valid as
Alice Wang600ea5b2023-11-17 15:12:16 +000034 /// long as the pointer to `EVP_PKEY` is valid.
Alice Wang7468ae42023-11-30 10:20:36 +000035 _inner_ec_key: Option<EcKey>,
Alice Wang600ea5b2023-11-17 15:12:16 +000036}
37
Alice Wangeb77f7d2023-12-01 09:13:58 +000038impl Drop for PKey {
Alice Wang600ea5b2023-11-17 15:12:16 +000039 fn drop(&mut self) {
40 // SAFETY: It is safe because `EVP_PKEY` has been allocated by BoringSSL and isn't
41 // used after this.
42 unsafe { EVP_PKEY_free(self.pkey.as_ptr()) }
43 }
44}
45
46/// Creates a new empty `EVP_PKEY`.
47fn new_pkey() -> Result<NonNull<EVP_PKEY>> {
48 // SAFETY: The returned pointer is checked below.
49 let key = unsafe { EVP_PKEY_new() };
50 NonNull::new(key).ok_or(to_call_failed_error(ApiName::EVP_PKEY_new))
51}
52
Alice Wangeb77f7d2023-12-01 09:13:58 +000053impl TryFrom<EcKey> for PKey {
Alice Wang600ea5b2023-11-17 15:12:16 +000054 type Error = bssl_avf_error::Error;
55
56 fn try_from(key: EcKey) -> Result<Self> {
57 let pkey = new_pkey()?;
Alice Wang7468ae42023-11-30 10:20:36 +000058 // SAFETY: The function only sets the inner EC key of the initialized and
Alice Wang600ea5b2023-11-17 15:12:16 +000059 // non-null `EVP_PKEY` to point to the given `EC_KEY`. It only reads from
60 // and writes to the initialized `EVP_PKEY`.
61 // Since this struct owns the inner key, the inner key remains valid as
62 // long as `EVP_PKEY` is valid.
63 let ret = unsafe { EVP_PKEY_set1_EC_KEY(pkey.as_ptr(), key.0.as_ptr()) };
64 check_int_result(ret, ApiName::EVP_PKEY_set1_EC_KEY)?;
Alice Wang7468ae42023-11-30 10:20:36 +000065 Ok(Self { pkey, _inner_ec_key: Some(key) })
Alice Wang600ea5b2023-11-17 15:12:16 +000066 }
67}
68
Alice Wangeb77f7d2023-12-01 09:13:58 +000069impl PKey {
Alice Wang600ea5b2023-11-17 15:12:16 +000070 /// Returns a DER-encoded SubjectPublicKeyInfo structure as specified
71 /// in RFC 5280 s4.1.2.7:
72 ///
73 /// https://www.rfc-editor.org/rfc/rfc5280.html#section-4.1.2.7
74 pub fn subject_public_key_info(&self) -> Result<Vec<u8>> {
75 const CAPACITY: usize = 256;
76 let mut buf = [0u8; CAPACITY];
77 let mut cbb = CbbFixed::new(buf.as_mut());
78 // SAFETY: The function only write bytes to the buffer managed by the valid `CBB`.
79 // The inner key in `EVP_PKEY` was set to a valid key when the object was created.
80 // As this struct owns the inner key, the inner key is guaranteed to be valid
81 // throughout the execution of the function.
82 let ret = unsafe { EVP_marshal_public_key(cbb.as_mut(), self.pkey.as_ptr()) };
83 check_int_result(ret, ApiName::EVP_marshal_public_key)?;
84 // SAFETY: This is safe because the CBB pointer is a valid pointer initialized with
85 // `CBB_init_fixed()`.
86 check_int_result(unsafe { CBB_flush(cbb.as_mut()) }, ApiName::CBB_flush)?;
87 // SAFETY: This is safe because the CBB pointer is initialized with `CBB_init_fixed()`,
88 // and it has been flushed, thus it has no active children.
89 let len = unsafe { CBB_len(cbb.as_ref()) };
90 Ok(buf.get(0..len).ok_or(to_call_failed_error(ApiName::CBB_len))?.to_vec())
91 }
Alice Wang7468ae42023-11-30 10:20:36 +000092
93 /// This function takes a raw public key data slice and creates a `PKey` instance wrapping
94 /// a freshly allocated `EVP_PKEY` object from it.
95 ///
96 /// The lifetime of the returned instance is not tied to the lifetime of the raw public
97 /// key slice because the raw data is copied into the `EVP_PKEY` object.
98 ///
99 /// Currently the only supported raw formats are X25519 and Ed25519, where the formats
100 /// are specified in RFC 7748 and RFC 8032 respectively.
101 pub fn new_raw_public_key(raw_public_key: &[u8], type_: PKeyType) -> Result<Self> {
102 let engine = ptr::null_mut(); // Engine is not used.
103 let pkey =
104 // SAFETY: The function only reads from the given raw public key within its bounds.
105 // The returned pointer is checked below.
106 unsafe {
107 EVP_PKEY_new_raw_public_key(
108 type_.0,
109 engine,
110 raw_public_key.as_ptr(),
111 raw_public_key.len(),
112 )
113 };
114 let pkey =
115 NonNull::new(pkey).ok_or(to_call_failed_error(ApiName::EVP_PKEY_new_raw_public_key))?;
116 Ok(Self { pkey, _inner_ec_key: None })
117 }
118
119 /// Verifies the given `signature` of the `message` using the current public key.
120 ///
121 /// The `message` will be hashed using the given `digester` before verification.
122 ///
123 /// For algorithms like Ed25519 that do not use pre-hashed inputs, the `digester` should
124 /// be `None`.
125 pub fn verify(
126 &self,
127 signature: &[u8],
128 message: &[u8],
129 digester: Option<Digester>,
130 ) -> Result<()> {
131 let mut digester_context = DigesterContext::new()?;
132 // The `EVP_PKEY_CTX` is set to null as this function does not collect the context
133 // during the verification.
134 let pkey_context = ptr::null_mut();
135 let engine = ptr::null_mut(); // Use the default engine.
136 let ret =
137 // SAFETY: All the non-null parameters passed to this function have been properly
138 // initialized as required in the BoringSSL spec.
139 unsafe {
140 EVP_DigestVerifyInit(
141 digester_context.as_mut_ptr(),
142 pkey_context,
143 digester.map_or(ptr::null(), |d| d.0),
144 engine,
145 self.pkey.as_ptr(),
146 )
147 };
148 check_int_result(ret, ApiName::EVP_DigestVerifyInit)?;
149
150 // SAFETY: The function only reads from the given slices within their bounds.
151 // The `EVP_MD_CTX` is successfully initialized before this call.
152 let ret = unsafe {
153 EVP_DigestVerify(
154 digester_context.as_mut_ptr(),
155 signature.as_ptr(),
156 signature.len(),
157 message.as_ptr(),
158 message.len(),
159 )
160 };
161 check_int_result(ret, ApiName::EVP_DigestVerify)
162 }
163}
164
165/// Type of the keys supported by `PKey`.
166///
167/// It is a wrapper of the `EVP_PKEY_*` macros defined BoringSSL evp.h, which are the
168/// NID values of the corresponding keys.
169#[derive(Debug, Copy, Clone, PartialEq, Eq)]
170pub struct PKeyType(i32);
171
172impl PKeyType {
173 /// EVP_PKEY_X25519 / NID_X25519
174 pub const X25519: PKeyType = PKeyType(EVP_PKEY_X25519);
175 /// EVP_PKEY_ED25519 / NID_ED25519
176 pub const ED25519: PKeyType = PKeyType(EVP_PKEY_ED25519);
Alice Wang600ea5b2023-11-17 15:12:16 +0000177}