1 //! Implementations of [`kmr_common::crypto`] traits based on BoringSSL.
2
3 #![no_std]
4
5 extern crate alloc;
6
7 use alloc::string::ToString;
8 use kmr_common::Error;
9 use kmr_wire::keymint::{Digest, ErrorCode};
10 use log::error;
11 use openssl::hash::MessageDigest;
12
13 #[cfg(soong)]
14 // There is no OpenSSL CMAC API that is available in both BoringSSL for Android (which has `cmac.h`
15 // functions but not `EVP_PKEY_CMAC` functionality) and in tip OpenSSL (which has `EVP_PKEY_CMAC`
16 // functionality but which has removed `cmac.h`). So only build AES-CMAC for Android.
17 pub mod aes_cmac;
18
19 pub mod aes;
20 pub mod des;
21 pub mod ec;
22 pub mod eq;
23 pub mod hmac;
24 pub mod rng;
25 pub mod rsa;
26
27 #[cfg(soong)]
28 mod err;
29 #[cfg(soong)]
30 use err::*;
31
32 #[cfg(test)]
33 mod tests;
34
35 /// Map an OpenSSL `ErrorStack` into a KeyMint [`ErrorCode`] value.
map_openssl_errstack(errs: &openssl::error::ErrorStack) -> ErrorCode36 pub(crate) fn map_openssl_errstack(errs: &openssl::error::ErrorStack) -> ErrorCode {
37 let errors = errs.errors();
38 if errors.is_empty() {
39 error!("BoringSSL error requested but none available!");
40 return ErrorCode::UnknownError;
41 }
42 let err = &errors[0]; // safe: length checked above
43 map_openssl_err(err)
44 }
45
46 /// Stub function for mapping an OpenSSL `ErrorStack` into a KeyMint [`ErrorCode`] value.
47 #[cfg(not(soong))]
map_openssl_err(_err: &openssl::error::Error) -> ErrorCode48 fn map_openssl_err(_err: &openssl::error::Error) -> ErrorCode {
49 ErrorCode::UnknownError
50 }
51
52 /// Macro to auto-generate error mapping around invocations of `openssl` methods.
53 /// An invocation like:
54 ///
55 /// ```ignore
56 /// let x = ossl!(y.func(a, b))?;
57 /// ```
58 ///
59 /// will map to:
60 ///
61 /// ```ignore
62 /// let x = y.func(a, b).map_err(openssl_err!("failed to perform: y.func(a, b)"))?;
63 /// ```
64 #[macro_export]
65 macro_rules! ossl {
66 { $e:expr } => {
67 $e.map_err(openssl_err!(concat!("failed to perform: ", stringify!($e))))
68 }
69 }
70
71 /// Macro to emit a closure that builds an [`Error::Hal`] instance, based on an
72 /// openssl `ErrorStack` together with a format-like message.
73 #[macro_export]
74 macro_rules! openssl_err {
75 { $($arg:tt)+ } => {
76 |e| kmr_common::Error::Hal(
77 $crate::map_openssl_errstack(&e),
78 alloc::format!("{}:{}: {}: {:?}", file!(), line!(), format_args!($($arg)+), e)
79 )
80 };
81 }
82
83 /// Macro to emit a closure that builds an [`Error::Hal`] instance, based on an openssl `ErrorStack`
84 /// together with a format-like message, plus default `ErrorCode` to be used if no OpenSSL error is
85 /// available.
86 #[macro_export]
87 macro_rules! openssl_err_or {
88 { $default:ident, $($arg:tt)+ } => {
89 |e| {
90 let errors = e.errors();
91 let errcode = if errors.is_empty() {
92 kmr_wire::keymint::ErrorCode::$default
93 } else {
94 $crate::map_openssl_err(&errors[0]) // safe: length checked above
95 };
96 kmr_common::Error::Hal(
97 errcode,
98 alloc::format!("{}:{}: {}: {:?}", file!(), line!(), format_args!($($arg)+), e)
99 )
100 }
101 };
102 }
103
104 /// Macro to emit an [`Error`] indicating allocation failure at the current location.
105 #[macro_export]
106 macro_rules! malloc_err {
107 {} => {
108 kmr_common::Error::Alloc(concat!(file!(), ":", line!(), ": BoringSSL allocation failed"))
109 };
110 }
111
112 /// Translate the most recent OpenSSL error into [`Error`].
openssl_last_err() -> Error113 fn openssl_last_err() -> Error {
114 from_openssl_err(openssl::error::ErrorStack::get())
115 }
116
117 /// Translate a returned `openssl` error into [`Error`].
from_openssl_err(errs: openssl::error::ErrorStack) -> Error118 fn from_openssl_err(errs: openssl::error::ErrorStack) -> Error {
119 Error::Hal(map_openssl_errstack(&errs), "OpenSSL failure".to_string())
120 }
121
122 /// Translate a [`keymint::Digest`] into an OpenSSL [`MessageDigest`].
digest_into_openssl(digest: Digest) -> Option<MessageDigest>123 fn digest_into_openssl(digest: Digest) -> Option<MessageDigest> {
124 match digest {
125 Digest::None => None,
126 Digest::Md5 => Some(MessageDigest::md5()),
127 Digest::Sha1 => Some(MessageDigest::sha1()),
128 Digest::Sha224 => Some(MessageDigest::sha224()),
129 Digest::Sha256 => Some(MessageDigest::sha256()),
130 Digest::Sha384 => Some(MessageDigest::sha384()),
131 Digest::Sha512 => Some(MessageDigest::sha512()),
132 }
133 }
134
135 #[inline]
cvt_p<T>(r: *mut T) -> Result<*mut T, Error>136 fn cvt_p<T>(r: *mut T) -> Result<*mut T, Error> {
137 if r.is_null() {
138 Err(openssl_last_err())
139 } else {
140 Ok(r)
141 }
142 }
143
144 #[inline]
cvt(r: libc::c_int) -> Result<libc::c_int, Error>145 fn cvt(r: libc::c_int) -> Result<libc::c_int, Error> {
146 if r <= 0 {
147 Err(openssl_last_err())
148 } else {
149 Ok(r)
150 }
151 }
152