xref: /aosp_15_r20/system/keymint/boringssl/src/lib.rs (revision 9860b7637a5f185913c70aa0caabe3ecb78441e4)
1*9860b763SAndroid Build Coastguard Worker // Copyright 2022, The Android Open Source Project
2*9860b763SAndroid Build Coastguard Worker //
3*9860b763SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9860b763SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9860b763SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9860b763SAndroid Build Coastguard Worker //
7*9860b763SAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*9860b763SAndroid Build Coastguard Worker //
9*9860b763SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9860b763SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9860b763SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9860b763SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9860b763SAndroid Build Coastguard Worker // limitations under the License.
14*9860b763SAndroid Build Coastguard Worker 
15*9860b763SAndroid Build Coastguard Worker //! Implementations of [`kmr_common::crypto`] traits based on BoringSSL.
16*9860b763SAndroid Build Coastguard Worker #![no_std]
17*9860b763SAndroid Build Coastguard Worker 
18*9860b763SAndroid Build Coastguard Worker extern crate alloc;
19*9860b763SAndroid Build Coastguard Worker 
20*9860b763SAndroid Build Coastguard Worker use alloc::string::ToString;
21*9860b763SAndroid Build Coastguard Worker use kmr_common::Error;
22*9860b763SAndroid Build Coastguard Worker use kmr_wire::keymint::{Digest, ErrorCode};
23*9860b763SAndroid Build Coastguard Worker use log::error;
24*9860b763SAndroid Build Coastguard Worker use openssl::hash::MessageDigest;
25*9860b763SAndroid Build Coastguard Worker 
26*9860b763SAndroid Build Coastguard Worker #[cfg(soong)]
27*9860b763SAndroid Build Coastguard Worker // There is no OpenSSL CMAC API that is available in both BoringSSL for Android (which has `cmac.h`
28*9860b763SAndroid Build Coastguard Worker // functions but not `EVP_PKEY_CMAC` functionality) and in tip OpenSSL (which has `EVP_PKEY_CMAC`
29*9860b763SAndroid Build Coastguard Worker // functionality but which has removed `cmac.h`).  So only build AES-CMAC for Android.
30*9860b763SAndroid Build Coastguard Worker pub mod aes_cmac;
31*9860b763SAndroid Build Coastguard Worker 
32*9860b763SAndroid Build Coastguard Worker pub mod aes;
33*9860b763SAndroid Build Coastguard Worker pub mod des;
34*9860b763SAndroid Build Coastguard Worker pub mod ec;
35*9860b763SAndroid Build Coastguard Worker pub mod eq;
36*9860b763SAndroid Build Coastguard Worker pub mod hmac;
37*9860b763SAndroid Build Coastguard Worker pub mod rng;
38*9860b763SAndroid Build Coastguard Worker pub mod rsa;
39*9860b763SAndroid Build Coastguard Worker pub mod sha256;
40*9860b763SAndroid Build Coastguard Worker 
41*9860b763SAndroid Build Coastguard Worker #[cfg(soong)]
42*9860b763SAndroid Build Coastguard Worker mod err;
43*9860b763SAndroid Build Coastguard Worker #[cfg(soong)]
44*9860b763SAndroid Build Coastguard Worker use err::*;
45*9860b763SAndroid Build Coastguard Worker 
46*9860b763SAndroid Build Coastguard Worker #[cfg(test)]
47*9860b763SAndroid Build Coastguard Worker mod tests;
48*9860b763SAndroid Build Coastguard Worker 
49*9860b763SAndroid Build Coastguard Worker mod types;
50*9860b763SAndroid Build Coastguard Worker 
51*9860b763SAndroid Build Coastguard Worker /// Map an OpenSSL `ErrorStack` into a KeyMint [`ErrorCode`] value.
map_openssl_errstack(errs: &openssl::error::ErrorStack) -> ErrorCode52*9860b763SAndroid Build Coastguard Worker pub(crate) fn map_openssl_errstack(errs: &openssl::error::ErrorStack) -> ErrorCode {
53*9860b763SAndroid Build Coastguard Worker     let errors = errs.errors();
54*9860b763SAndroid Build Coastguard Worker     if errors.is_empty() {
55*9860b763SAndroid Build Coastguard Worker         error!("BoringSSL error requested but none available!");
56*9860b763SAndroid Build Coastguard Worker         return ErrorCode::BoringSslError;
57*9860b763SAndroid Build Coastguard Worker     }
58*9860b763SAndroid Build Coastguard Worker     let err = &errors[0]; // safe: length checked above
59*9860b763SAndroid Build Coastguard Worker     map_openssl_err(err)
60*9860b763SAndroid Build Coastguard Worker }
61*9860b763SAndroid Build Coastguard Worker 
62*9860b763SAndroid Build Coastguard Worker /// Stub function for mapping an OpenSSL `ErrorStack` into a KeyMint [`ErrorCode`] value.
63*9860b763SAndroid Build Coastguard Worker #[cfg(not(soong))]
map_openssl_err(_err: &openssl::error::Error) -> ErrorCode64*9860b763SAndroid Build Coastguard Worker fn map_openssl_err(_err: &openssl::error::Error) -> ErrorCode {
65*9860b763SAndroid Build Coastguard Worker     ErrorCode::BoringSslError
66*9860b763SAndroid Build Coastguard Worker }
67*9860b763SAndroid Build Coastguard Worker 
68*9860b763SAndroid Build Coastguard Worker /// Macro to auto-generate error mapping around invocations of `openssl` methods.
69*9860b763SAndroid Build Coastguard Worker /// An invocation like:
70*9860b763SAndroid Build Coastguard Worker ///
71*9860b763SAndroid Build Coastguard Worker /// ```ignore
72*9860b763SAndroid Build Coastguard Worker /// let x = ossl!(y.func(a, b))?;
73*9860b763SAndroid Build Coastguard Worker /// ```
74*9860b763SAndroid Build Coastguard Worker ///
75*9860b763SAndroid Build Coastguard Worker /// will map to:
76*9860b763SAndroid Build Coastguard Worker ///
77*9860b763SAndroid Build Coastguard Worker /// ```ignore
78*9860b763SAndroid Build Coastguard Worker /// let x = y.func(a, b).map_err(openssl_err!("failed to perform: y.func(a, b)"))?;
79*9860b763SAndroid Build Coastguard Worker /// ```
80*9860b763SAndroid Build Coastguard Worker #[macro_export]
81*9860b763SAndroid Build Coastguard Worker macro_rules! ossl {
82*9860b763SAndroid Build Coastguard Worker     { $e:expr } => {
83*9860b763SAndroid Build Coastguard Worker         $e.map_err(openssl_err!(concat!("failed to perform: ", stringify!($e))))
84*9860b763SAndroid Build Coastguard Worker     }
85*9860b763SAndroid Build Coastguard Worker }
86*9860b763SAndroid Build Coastguard Worker 
87*9860b763SAndroid Build Coastguard Worker /// Macro to emit a closure that builds an [`Error::Hal`] instance, based on an
88*9860b763SAndroid Build Coastguard Worker /// openssl `ErrorStack` together with a format-like message.
89*9860b763SAndroid Build Coastguard Worker #[macro_export]
90*9860b763SAndroid Build Coastguard Worker macro_rules! openssl_err {
91*9860b763SAndroid Build Coastguard Worker     { $($arg:tt)+ } => {
92*9860b763SAndroid Build Coastguard Worker         |e| kmr_common::Error::Hal(
93*9860b763SAndroid Build Coastguard Worker             $crate::map_openssl_errstack(&e),
94*9860b763SAndroid Build Coastguard Worker             alloc::format!("{}:{}: {}: {:?}", file!(), line!(), format_args!($($arg)+), e)
95*9860b763SAndroid Build Coastguard Worker         )
96*9860b763SAndroid Build Coastguard Worker     };
97*9860b763SAndroid Build Coastguard Worker }
98*9860b763SAndroid Build Coastguard Worker 
99*9860b763SAndroid Build Coastguard Worker /// Macro to emit a closure that builds an [`Error::Hal`] instance, based on an openssl `ErrorStack`
100*9860b763SAndroid Build Coastguard Worker /// together with a format-like message, plus default `ErrorCode` to be used if no OpenSSL error is
101*9860b763SAndroid Build Coastguard Worker /// available.
102*9860b763SAndroid Build Coastguard Worker #[macro_export]
103*9860b763SAndroid Build Coastguard Worker macro_rules! openssl_err_or {
104*9860b763SAndroid Build Coastguard Worker     { $default:ident, $($arg:tt)+ } => {
105*9860b763SAndroid Build Coastguard Worker         |e| {
106*9860b763SAndroid Build Coastguard Worker             let errors = e.errors();
107*9860b763SAndroid Build Coastguard Worker             let errcode = if errors.is_empty() {
108*9860b763SAndroid Build Coastguard Worker                 kmr_wire::keymint::ErrorCode::$default
109*9860b763SAndroid Build Coastguard Worker             } else {
110*9860b763SAndroid Build Coastguard Worker                 $crate::map_openssl_err(&errors[0]) // safe: length checked above
111*9860b763SAndroid Build Coastguard Worker             };
112*9860b763SAndroid Build Coastguard Worker             kmr_common::Error::Hal(
113*9860b763SAndroid Build Coastguard Worker                 errcode,
114*9860b763SAndroid Build Coastguard Worker                 alloc::format!("{}:{}: {}: {:?}", file!(), line!(), format_args!($($arg)+), e)
115*9860b763SAndroid Build Coastguard Worker             )
116*9860b763SAndroid Build Coastguard Worker         }
117*9860b763SAndroid Build Coastguard Worker     };
118*9860b763SAndroid Build Coastguard Worker }
119*9860b763SAndroid Build Coastguard Worker 
120*9860b763SAndroid Build Coastguard Worker /// Macro to emit an [`Error`] indicating allocation failure at the current location.
121*9860b763SAndroid Build Coastguard Worker #[macro_export]
122*9860b763SAndroid Build Coastguard Worker macro_rules! malloc_err {
123*9860b763SAndroid Build Coastguard Worker     {} => {
124*9860b763SAndroid Build Coastguard Worker         kmr_common::Error::Alloc(concat!(file!(), ":", line!(), ": BoringSSL allocation failed"))
125*9860b763SAndroid Build Coastguard Worker     };
126*9860b763SAndroid Build Coastguard Worker }
127*9860b763SAndroid Build Coastguard Worker 
128*9860b763SAndroid Build Coastguard Worker /// Translate the most recent OpenSSL error into [`Error`].
openssl_last_err() -> Error129*9860b763SAndroid Build Coastguard Worker fn openssl_last_err() -> Error {
130*9860b763SAndroid Build Coastguard Worker     from_openssl_err(openssl::error::ErrorStack::get())
131*9860b763SAndroid Build Coastguard Worker }
132*9860b763SAndroid Build Coastguard Worker 
133*9860b763SAndroid Build Coastguard Worker /// Translate a returned `openssl` error into [`Error`].
from_openssl_err(errs: openssl::error::ErrorStack) -> Error134*9860b763SAndroid Build Coastguard Worker fn from_openssl_err(errs: openssl::error::ErrorStack) -> Error {
135*9860b763SAndroid Build Coastguard Worker     Error::Hal(map_openssl_errstack(&errs), "OpenSSL failure".to_string())
136*9860b763SAndroid Build Coastguard Worker }
137*9860b763SAndroid Build Coastguard Worker 
138*9860b763SAndroid Build Coastguard Worker /// Translate a [`keymint::Digest`] into an OpenSSL [`MessageDigest`].
digest_into_openssl(digest: Digest) -> Option<MessageDigest>139*9860b763SAndroid Build Coastguard Worker fn digest_into_openssl(digest: Digest) -> Option<MessageDigest> {
140*9860b763SAndroid Build Coastguard Worker     match digest {
141*9860b763SAndroid Build Coastguard Worker         Digest::None => None,
142*9860b763SAndroid Build Coastguard Worker         Digest::Md5 => Some(MessageDigest::md5()),
143*9860b763SAndroid Build Coastguard Worker         Digest::Sha1 => Some(MessageDigest::sha1()),
144*9860b763SAndroid Build Coastguard Worker         Digest::Sha224 => Some(MessageDigest::sha224()),
145*9860b763SAndroid Build Coastguard Worker         Digest::Sha256 => Some(MessageDigest::sha256()),
146*9860b763SAndroid Build Coastguard Worker         Digest::Sha384 => Some(MessageDigest::sha384()),
147*9860b763SAndroid Build Coastguard Worker         Digest::Sha512 => Some(MessageDigest::sha512()),
148*9860b763SAndroid Build Coastguard Worker     }
149*9860b763SAndroid Build Coastguard Worker }
150*9860b763SAndroid Build Coastguard Worker 
151*9860b763SAndroid Build Coastguard Worker #[inline]
cvt_p<T>(r: *mut T) -> Result<*mut T, Error>152*9860b763SAndroid Build Coastguard Worker fn cvt_p<T>(r: *mut T) -> Result<*mut T, Error> {
153*9860b763SAndroid Build Coastguard Worker     if r.is_null() {
154*9860b763SAndroid Build Coastguard Worker         Err(openssl_last_err())
155*9860b763SAndroid Build Coastguard Worker     } else {
156*9860b763SAndroid Build Coastguard Worker         Ok(r)
157*9860b763SAndroid Build Coastguard Worker     }
158*9860b763SAndroid Build Coastguard Worker }
159*9860b763SAndroid Build Coastguard Worker 
160*9860b763SAndroid Build Coastguard Worker #[inline]
cvt(r: libc::c_int) -> Result<libc::c_int, Error>161*9860b763SAndroid Build Coastguard Worker fn cvt(r: libc::c_int) -> Result<libc::c_int, Error> {
162*9860b763SAndroid Build Coastguard Worker     if r <= 0 {
163*9860b763SAndroid Build Coastguard Worker         Err(openssl_last_err())
164*9860b763SAndroid Build Coastguard Worker     } else {
165*9860b763SAndroid Build Coastguard Worker         Ok(r)
166*9860b763SAndroid Build Coastguard Worker     }
167*9860b763SAndroid Build Coastguard Worker }
168