blob: 30bfc217e814b70c59c71b3f27de6abe2ed25360 [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;
18use crate::ec_key::EcKey;
19use crate::util::{check_int_result, to_call_failed_error};
20use alloc::vec::Vec;
21use bssl_avf_error::{ApiName, Result};
22use bssl_ffi::{
23 CBB_flush, CBB_len, EVP_PKEY_free, EVP_PKEY_new, EVP_PKEY_set1_EC_KEY, EVP_marshal_public_key,
24 EVP_PKEY,
25};
26use core::ptr::NonNull;
27
28/// Wrapper of an `EVP_PKEY` object, representing a public or private key.
29pub struct EvpPKey {
30 pkey: NonNull<EVP_PKEY>,
31 /// Since this struct owns the inner key, the inner key remains valid as
32 /// long as the pointer to `EVP_PKEY` is valid.
33 _inner_key: EcKey,
34}
35
36impl Drop for EvpPKey {
37 fn drop(&mut self) {
38 // SAFETY: It is safe because `EVP_PKEY` has been allocated by BoringSSL and isn't
39 // used after this.
40 unsafe { EVP_PKEY_free(self.pkey.as_ptr()) }
41 }
42}
43
44/// Creates a new empty `EVP_PKEY`.
45fn new_pkey() -> Result<NonNull<EVP_PKEY>> {
46 // SAFETY: The returned pointer is checked below.
47 let key = unsafe { EVP_PKEY_new() };
48 NonNull::new(key).ok_or(to_call_failed_error(ApiName::EVP_PKEY_new))
49}
50
51impl TryFrom<EcKey> for EvpPKey {
52 type Error = bssl_avf_error::Error;
53
54 fn try_from(key: EcKey) -> Result<Self> {
55 let pkey = new_pkey()?;
56 // SAFETY: The function only sets the inner key of the initialized and
57 // non-null `EVP_PKEY` to point to the given `EC_KEY`. It only reads from
58 // and writes to the initialized `EVP_PKEY`.
59 // Since this struct owns the inner key, the inner key remains valid as
60 // long as `EVP_PKEY` is valid.
61 let ret = unsafe { EVP_PKEY_set1_EC_KEY(pkey.as_ptr(), key.0.as_ptr()) };
62 check_int_result(ret, ApiName::EVP_PKEY_set1_EC_KEY)?;
63 Ok(Self { pkey, _inner_key: key })
64 }
65}
66
67impl EvpPKey {
68 /// Returns a DER-encoded SubjectPublicKeyInfo structure as specified
69 /// in RFC 5280 s4.1.2.7:
70 ///
71 /// https://www.rfc-editor.org/rfc/rfc5280.html#section-4.1.2.7
72 pub fn subject_public_key_info(&self) -> Result<Vec<u8>> {
73 const CAPACITY: usize = 256;
74 let mut buf = [0u8; CAPACITY];
75 let mut cbb = CbbFixed::new(buf.as_mut());
76 // SAFETY: The function only write bytes to the buffer managed by the valid `CBB`.
77 // The inner key in `EVP_PKEY` was set to a valid key when the object was created.
78 // As this struct owns the inner key, the inner key is guaranteed to be valid
79 // throughout the execution of the function.
80 let ret = unsafe { EVP_marshal_public_key(cbb.as_mut(), self.pkey.as_ptr()) };
81 check_int_result(ret, ApiName::EVP_marshal_public_key)?;
82 // SAFETY: This is safe because the CBB pointer is a valid pointer initialized with
83 // `CBB_init_fixed()`.
84 check_int_result(unsafe { CBB_flush(cbb.as_mut()) }, ApiName::CBB_flush)?;
85 // SAFETY: This is safe because the CBB pointer is initialized with `CBB_init_fixed()`,
86 // and it has been flushed, thus it has no active children.
87 let len = unsafe { CBB_len(cbb.as_ref()) };
88 Ok(buf.get(0..len).ok_or(to_call_failed_error(ApiName::CBB_len))?.to_vec())
89 }
90}