blob: 17868c093b4c6b87e89d2460361c51a8384709e4 [file] [log] [blame]
David Drysdale747e5932023-10-17 14:43:43 +01001// Copyright 2022, 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
David Drysdale64e07e32022-06-10 14:45:45 +010015//! Abstractions and related types for accessing cryptographic primitives
16//! and related functionality.
17
David Drysdale63e6ad62023-05-05 17:41:08 +010018// derive(N) generates a method that is missing a docstring.
19#![allow(missing_docs)]
20
David Drysdale0b3938d2022-09-28 16:49:16 +010021use crate::{km_err, vec_try, vec_try_with_capacity, Error, FallibleAllocExt};
David Drysdale9f27bc92022-06-10 15:53:32 +010022use alloc::{
23 format,
24 string::{String, ToString},
David Drysdale9f27bc92022-06-10 15:53:32 +010025 vec::Vec,
26};
27use core::convert::{From, TryInto};
David Drysdaleed33ed12022-08-23 10:01:39 +010028use enumn::N;
David Drysdale9f27bc92022-06-10 15:53:32 +010029use kmr_derive::AsCborValue;
David Drysdale0b3938d2022-09-28 16:49:16 +010030use kmr_wire::keymint::{Algorithm, Digest, EcCurve};
31use kmr_wire::{cbor, cbor_type_error, AsCborValue, CborError, KeySizeInBits, RsaExponent};
David Drysdaleed33ed12022-08-23 10:01:39 +010032use log::error;
Andrew Walbranc6dd88f2023-12-19 11:09:05 +000033use spki::SubjectPublicKeyInfoRef;
David Drysdale0b3938d2022-09-28 16:49:16 +010034use zeroize::ZeroizeOnDrop;
David Drysdale9f27bc92022-06-10 15:53:32 +010035
36pub mod aes;
37pub mod des;
38pub mod ec;
39pub mod hmac;
David Drysdale64e07e32022-06-10 14:45:45 +010040pub mod rsa;
David Drysdale9f27bc92022-06-10 15:53:32 +010041mod traits;
42pub use traits::*;
43
44/// Size of SHA-256 output in bytes.
45pub const SHA256_DIGEST_LEN: usize = 32;
David Drysdale64e07e32022-06-10 14:45:45 +010046
David Drysdale0b3938d2022-09-28 16:49:16 +010047/// Function that mimics `slice.to_vec()` but which detects allocation failures. This version emits
48/// `CborError` (instead of the `Error` that `crate::try_to_vec` emits).
49#[inline]
50pub fn try_to_vec<T: Clone>(s: &[T]) -> Result<Vec<T>, CborError> {
51 let mut v = vec_try_with_capacity!(s.len()).map_err(|_e| CborError::AllocationFailed)?;
52 v.extend_from_slice(s);
53 Ok(v)
54}
David Drysdale9f27bc92022-06-10 15:53:32 +010055
56/// Milliseconds since an arbitrary epoch.
57#[repr(transparent)]
58#[derive(Clone, Copy, Debug, PartialEq, Eq)]
59pub struct MillisecondsSinceEpoch(pub i64);
60
David Drysdale0b3938d2022-09-28 16:49:16 +010061impl From<MillisecondsSinceEpoch> for kmr_wire::secureclock::Timestamp {
David Drysdale9f27bc92022-06-10 15:53:32 +010062 fn from(value: MillisecondsSinceEpoch) -> Self {
David Drysdale0b3938d2022-09-28 16:49:16 +010063 kmr_wire::secureclock::Timestamp { milliseconds: value.0 }
David Drysdale9f27bc92022-06-10 15:53:32 +010064 }
65}
66
67/// Information for key generation.
68#[derive(Clone)]
69pub enum KeyGenInfo {
David Drysdale63e6ad62023-05-05 17:41:08 +010070 /// Generate an AES key of the given size.
David Drysdale9f27bc92022-06-10 15:53:32 +010071 Aes(aes::Variant),
David Drysdale63e6ad62023-05-05 17:41:08 +010072 /// Generate a 3-DES key.
David Drysdale9f27bc92022-06-10 15:53:32 +010073 TripleDes,
David Drysdale63e6ad62023-05-05 17:41:08 +010074 /// Generate an HMAC key of the given size.
David Drysdale9f27bc92022-06-10 15:53:32 +010075 Hmac(KeySizeInBits),
David Drysdale63e6ad62023-05-05 17:41:08 +010076 /// Generate an RSA keypair of the given size using the given exponent.
David Drysdale0b3938d2022-09-28 16:49:16 +010077 Rsa(KeySizeInBits, RsaExponent),
David Drysdale63e6ad62023-05-05 17:41:08 +010078 /// Generate a NIST EC keypair using the given curve.
David Drysdale9f27bc92022-06-10 15:53:32 +010079 NistEc(ec::NistCurve),
David Drysdale63e6ad62023-05-05 17:41:08 +010080 /// Generate an Ed25519 keypair.
David Drysdale9f27bc92022-06-10 15:53:32 +010081 Ed25519,
David Drysdale63e6ad62023-05-05 17:41:08 +010082 /// Generate an X25519 keypair.
David Drysdale9f27bc92022-06-10 15:53:32 +010083 X25519,
84}
85
David Drysdaleed33ed12022-08-23 10:01:39 +010086/// Type of elliptic curve.
87#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, AsCborValue, N)]
88#[repr(i32)]
89pub enum CurveType {
David Drysdale63e6ad62023-05-05 17:41:08 +010090 /// NIST curve.
David Drysdaleed33ed12022-08-23 10:01:39 +010091 Nist = 0,
David Drysdale63e6ad62023-05-05 17:41:08 +010092 /// EdDSA curve.
David Drysdaleed33ed12022-08-23 10:01:39 +010093 EdDsa = 1,
David Drysdale63e6ad62023-05-05 17:41:08 +010094 /// XDH curve.
David Drysdaleed33ed12022-08-23 10:01:39 +010095 Xdh = 2,
96}
97
98/// Raw key material used for deriving other keys.
David Drysdale3b3840d2022-10-30 17:28:14 +000099#[derive(PartialEq, Eq, ZeroizeOnDrop)]
David Drysdaleed33ed12022-08-23 10:01:39 +0100100pub struct RawKeyMaterial(pub Vec<u8>);
101
David Drysdale0b3938d2022-09-28 16:49:16 +0100102/// Opaque key material whose structure is only known/accessible to the crypto implementation.
103/// The contents of this are assumed to be encrypted (and so are not `ZeroizeOnDrop`).
David Drysdale9f27bc92022-06-10 15:53:32 +0100104#[derive(Clone, PartialEq, Eq)]
David Drysdale0b3938d2022-09-28 16:49:16 +0100105pub struct OpaqueKeyMaterial(pub Vec<u8>);
106
107/// Wrapper that holds either a key of explicit type `T`, or an opaque blob of key material.
108#[derive(Clone, PartialEq, Eq)]
109pub enum OpaqueOr<T> {
David Drysdale63e6ad62023-05-05 17:41:08 +0100110 /// Explicit key material of the given type, available in plaintext.
David Drysdale0b3938d2022-09-28 16:49:16 +0100111 Explicit(T),
David Drysdale63e6ad62023-05-05 17:41:08 +0100112 /// Opaque key material, either encrypted or an opaque key handle.
David Drysdale0b3938d2022-09-28 16:49:16 +0100113 Opaque(OpaqueKeyMaterial),
David Drysdale9f27bc92022-06-10 15:53:32 +0100114}
115
David Drysdale0b3938d2022-09-28 16:49:16 +0100116/// Macro to provide `impl From<SomeKey> for OpaqueOr<SomeKey>`, so that explicit key material
117/// automatically converts into the equivalent `OpaqueOr` variant.
118macro_rules! opaque_from_key {
119 { $t:ty } => {
120 impl From<$t> for OpaqueOr<$t> {
121 fn from(k: $t) -> Self {
122 Self::Explicit(k)
123 }
124 }
125 }
126}
127
128opaque_from_key!(aes::Key);
129opaque_from_key!(des::Key);
130opaque_from_key!(hmac::Key);
131opaque_from_key!(rsa::Key);
132opaque_from_key!(ec::Key);
133
134impl<T> From<OpaqueKeyMaterial> for OpaqueOr<T> {
135 fn from(k: OpaqueKeyMaterial) -> Self {
136 Self::Opaque(k)
137 }
138}
139
140/// Key material that is held in plaintext (or is alternatively an opaque blob that is only
141/// known/accessible to the crypto implementation, indicated by the `OpaqueOr::Opaque` variant).
142#[derive(Clone, PartialEq, Eq)]
143pub enum KeyMaterial {
David Drysdale63e6ad62023-05-05 17:41:08 +0100144 /// AES symmetric key.
David Drysdale0b3938d2022-09-28 16:49:16 +0100145 Aes(OpaqueOr<aes::Key>),
David Drysdale63e6ad62023-05-05 17:41:08 +0100146 /// 3-DES symmetric key.
David Drysdale0b3938d2022-09-28 16:49:16 +0100147 TripleDes(OpaqueOr<des::Key>),
David Drysdale63e6ad62023-05-05 17:41:08 +0100148 /// HMAC symmetric key.
David Drysdale0b3938d2022-09-28 16:49:16 +0100149 Hmac(OpaqueOr<hmac::Key>),
David Drysdale63e6ad62023-05-05 17:41:08 +0100150 /// RSA asymmetric key.
David Drysdale0b3938d2022-09-28 16:49:16 +0100151 Rsa(OpaqueOr<rsa::Key>),
David Drysdale63e6ad62023-05-05 17:41:08 +0100152 /// Elliptic curve asymmetric key.
David Drysdale0b3938d2022-09-28 16:49:16 +0100153 Ec(EcCurve, CurveType, OpaqueOr<ec::Key>),
154}
155
156/// Macro that extracts the explicit key from an [`OpaqueOr`] wrapper.
157#[macro_export]
158macro_rules! explicit {
159 { $key:expr } => {
160 if let $crate::crypto::OpaqueOr::Explicit(k) = $key {
161 Ok(k)
162 } else {
Tri Vo9e4b4472023-08-30 11:21:48 -0400163 Err($crate::km_err!(IncompatibleKeyFormat, "Expected explicit key but found opaque key!"))
David Drysdale0b3938d2022-09-28 16:49:16 +0100164 }
165 }
166}
167
168impl KeyMaterial {
David Drysdale9f27bc92022-06-10 15:53:32 +0100169 /// Indicate whether the key material is for an asymmetric key.
170 pub fn is_asymmetric(&self) -> bool {
171 match self {
172 Self::Aes(_) | Self::TripleDes(_) | Self::Hmac(_) => false,
David Drysdale0b3938d2022-09-28 16:49:16 +0100173 Self::Ec(_, _, _) | Self::Rsa(_) => true,
David Drysdale9f27bc92022-06-10 15:53:32 +0100174 }
175 }
176
177 /// Indicate whether the key material is for a symmetric key.
178 pub fn is_symmetric(&self) -> bool {
179 !self.is_asymmetric()
180 }
181
David Drysdale0b3938d2022-09-28 16:49:16 +0100182 /// Return the public key information as an ASN.1 DER encodable `SubjectPublicKeyInfo`, as
David Drysdale9f27bc92022-06-10 15:53:32 +0100183 /// described in RFC 5280 section 4.1.
184 ///
185 /// ```asn1
186 /// SubjectPublicKeyInfo ::= SEQUENCE {
187 /// algorithm AlgorithmIdentifier,
188 /// subjectPublicKey BIT STRING }
189 ///
190 /// AlgorithmIdentifier ::= SEQUENCE {
191 /// algorithm OBJECT IDENTIFIER,
192 /// parameters ANY DEFINED BY algorithm OPTIONAL }
193 /// ```
194 ///
195 /// Returns `None` for a symmetric key.
David Drysdale0b3938d2022-09-28 16:49:16 +0100196 pub fn subject_public_key_info<'a>(
197 &'a self,
198 buf: &'a mut Vec<u8>,
199 ec: &dyn Ec,
Hasini Gunasinghed8518eb2022-11-16 23:50:22 +0000200 rsa: &dyn Rsa,
Andrew Walbranc6dd88f2023-12-19 11:09:05 +0000201 ) -> Result<Option<SubjectPublicKeyInfoRef<'a>>, Error> {
David Drysdale0b3938d2022-09-28 16:49:16 +0100202 Ok(match self {
Hasini Gunasinghed8518eb2022-11-16 23:50:22 +0000203 Self::Rsa(key) => Some(key.subject_public_key_info(buf, rsa)?),
Hasini Gunasinghec939a9b2022-11-17 02:45:22 +0000204 Self::Ec(curve, curve_type, key) => {
205 Some(key.subject_public_key_info(buf, ec, curve, curve_type)?)
David Drysdale0b3938d2022-09-28 16:49:16 +0100206 }
David Drysdale9f27bc92022-06-10 15:53:32 +0100207 _ => None,
David Drysdale0b3938d2022-09-28 16:49:16 +0100208 })
David Drysdale9f27bc92022-06-10 15:53:32 +0100209 }
210}
211
212/// Manual implementation of [`Debug`] that skips emitting plaintext key material.
David Drysdale0b3938d2022-09-28 16:49:16 +0100213impl core::fmt::Debug for KeyMaterial {
David Drysdale9f27bc92022-06-10 15:53:32 +0100214 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
215 match self {
216 Self::Aes(k) => match k {
David Drysdale0b3938d2022-09-28 16:49:16 +0100217 OpaqueOr::Explicit(aes::Key::Aes128(_)) => f.write_str("Aes128(...)"),
218 OpaqueOr::Explicit(aes::Key::Aes192(_)) => f.write_str("Aes192(...)"),
219 OpaqueOr::Explicit(aes::Key::Aes256(_)) => f.write_str("Aes256(...)"),
220 OpaqueOr::Opaque(_) => f.write_str("Aes(opaque)"),
David Drysdale9f27bc92022-06-10 15:53:32 +0100221 },
222 Self::TripleDes(_) => f.write_str("TripleDes(...)"),
223 Self::Hmac(_) => f.write_str("Hmac(...)"),
224 Self::Rsa(_) => f.write_str("Rsa(...)"),
David Drysdale0b3938d2022-09-28 16:49:16 +0100225 Self::Ec(c, _, _) => f.write_fmt(format_args!("Ec({:?}, ...)", c)),
David Drysdale9f27bc92022-06-10 15:53:32 +0100226 }
227 }
228}
229
David Drysdale0b3938d2022-09-28 16:49:16 +0100230impl AsCborValue for KeyMaterial {
David Drysdale9f27bc92022-06-10 15:53:32 +0100231 fn from_cbor_value(value: cbor::value::Value) -> Result<Self, CborError> {
232 let mut a = match value {
David Drysdale0b3938d2022-09-28 16:49:16 +0100233 cbor::value::Value::Array(a) if a.len() == 3 => a,
234 _ => return cbor_type_error(&value, "arr len 3"),
David Drysdale9f27bc92022-06-10 15:53:32 +0100235 };
David Drysdale0b3938d2022-09-28 16:49:16 +0100236 let raw_key_value = a.remove(2);
237 let opaque = match a.remove(1) {
238 cbor::value::Value::Bool(b) => b,
239 v => return cbor_type_error(&v, "bool"),
240 };
David Drysdale9f27bc92022-06-10 15:53:32 +0100241 let algo: i32 = match a.remove(0) {
242 cbor::value::Value::Integer(i) => i.try_into()?,
David Drysdale0b3938d2022-09-28 16:49:16 +0100243 v => return cbor_type_error(&v, "uint"),
David Drysdale9f27bc92022-06-10 15:53:32 +0100244 };
245
246 match algo {
247 x if x == Algorithm::Aes as i32 => {
248 let raw_key = <Vec<u8>>::from_cbor_value(raw_key_value)?;
David Drysdale0b3938d2022-09-28 16:49:16 +0100249 if opaque {
250 Ok(Self::Aes(OpaqueKeyMaterial(raw_key).into()))
251 } else {
252 match aes::Key::new(raw_key) {
253 Ok(k) => Ok(Self::Aes(k.into())),
254 Err(_e) => Err(CborError::UnexpectedItem("bstr", "bstr len 16/24/32")),
255 }
David Drysdale9f27bc92022-06-10 15:53:32 +0100256 }
257 }
258 x if x == Algorithm::TripleDes as i32 => {
259 let raw_key = <Vec<u8>>::from_cbor_value(raw_key_value)?;
David Drysdale0b3938d2022-09-28 16:49:16 +0100260 if opaque {
261 Ok(Self::TripleDes(OpaqueKeyMaterial(raw_key).into()))
262 } else {
263 Ok(Self::TripleDes(
264 des::Key(
265 raw_key
266 .try_into()
267 .map_err(|_e| CborError::UnexpectedItem("bstr", "bstr len 24"))?,
268 )
269 .into(),
270 ))
271 }
David Drysdale9f27bc92022-06-10 15:53:32 +0100272 }
273 x if x == Algorithm::Hmac as i32 => {
274 let raw_key = <Vec<u8>>::from_cbor_value(raw_key_value)?;
David Drysdale0b3938d2022-09-28 16:49:16 +0100275 if opaque {
276 Ok(Self::Hmac(OpaqueKeyMaterial(raw_key).into()))
277 } else {
278 Ok(Self::Hmac(hmac::Key(raw_key).into()))
279 }
David Drysdale9f27bc92022-06-10 15:53:32 +0100280 }
281 x if x == Algorithm::Rsa as i32 => {
282 let raw_key = <Vec<u8>>::from_cbor_value(raw_key_value)?;
David Drysdale0b3938d2022-09-28 16:49:16 +0100283 if opaque {
284 Ok(Self::Rsa(OpaqueKeyMaterial(raw_key).into()))
285 } else {
286 Ok(Self::Rsa(rsa::Key(raw_key).into()))
287 }
David Drysdale9f27bc92022-06-10 15:53:32 +0100288 }
289 x if x == Algorithm::Ec as i32 => {
290 let mut a = match raw_key_value {
David Drysdaleed33ed12022-08-23 10:01:39 +0100291 cbor::value::Value::Array(a) if a.len() == 3 => a,
David Drysdale0b3938d2022-09-28 16:49:16 +0100292 _ => return cbor_type_error(&raw_key_value, "arr len 2"),
David Drysdale9f27bc92022-06-10 15:53:32 +0100293 };
David Drysdaleed33ed12022-08-23 10:01:39 +0100294 let raw_key_value = a.remove(2);
David Drysdale9f27bc92022-06-10 15:53:32 +0100295 let raw_key = <Vec<u8>>::from_cbor_value(raw_key_value)?;
David Drysdaleed33ed12022-08-23 10:01:39 +0100296 let curve_type = CurveType::from_cbor_value(a.remove(1))?;
David Drysdale9f27bc92022-06-10 15:53:32 +0100297 let curve = <EcCurve>::from_cbor_value(a.remove(0))?;
David Drysdale0b3938d2022-09-28 16:49:16 +0100298 if opaque {
299 Ok(Self::Ec(curve, curve_type, OpaqueKeyMaterial(raw_key).into()))
300 } else {
301 let key = match (curve, curve_type) {
302 (EcCurve::P224, CurveType::Nist) => ec::Key::P224(ec::NistKey(raw_key)),
303 (EcCurve::P256, CurveType::Nist) => ec::Key::P256(ec::NistKey(raw_key)),
304 (EcCurve::P384, CurveType::Nist) => ec::Key::P384(ec::NistKey(raw_key)),
305 (EcCurve::P521, CurveType::Nist) => ec::Key::P521(ec::NistKey(raw_key)),
306 (EcCurve::Curve25519, CurveType::EdDsa) => {
307 let key = raw_key.try_into().map_err(|_e| {
308 error!("decoding Ed25519 key of incorrect len");
309 CborError::OutOfRangeIntegerValue
310 })?;
311 ec::Key::Ed25519(ec::Ed25519Key(key))
312 }
313 (EcCurve::Curve25519, CurveType::Xdh) => {
314 let key = raw_key.try_into().map_err(|_e| {
315 error!("decoding X25519 key of incorrect len");
316 CborError::OutOfRangeIntegerValue
317 })?;
318 ec::Key::X25519(ec::X25519Key(key))
319 }
320 (_, _) => {
321 error!("Unexpected EC combination ({:?}, {:?})", curve, curve_type);
322 return Err(CborError::NonEnumValue);
323 }
324 };
325 Ok(Self::Ec(curve, curve_type, key.into()))
326 }
David Drysdale9f27bc92022-06-10 15:53:32 +0100327 }
328 _ => Err(CborError::UnexpectedItem("unknown enum", "algo enum")),
329 }
330 }
331
332 fn to_cbor_value(self) -> Result<cbor::value::Value, CborError> {
David Drysdale0b3938d2022-09-28 16:49:16 +0100333 let cbor_alloc_err = |_e| CborError::AllocationFailed;
David Drysdale9f27bc92022-06-10 15:53:32 +0100334 Ok(cbor::value::Value::Array(match self {
David Drysdale0b3938d2022-09-28 16:49:16 +0100335 Self::Aes(OpaqueOr::Opaque(OpaqueKeyMaterial(k))) => vec_try![
David Drysdale9f27bc92022-06-10 15:53:32 +0100336 cbor::value::Value::Integer((Algorithm::Aes as i32).into()),
David Drysdale0b3938d2022-09-28 16:49:16 +0100337 cbor::value::Value::Bool(true),
338 cbor::value::Value::Bytes(try_to_vec(&k)?),
339 ]
340 .map_err(cbor_alloc_err)?,
341 Self::TripleDes(OpaqueOr::Opaque(OpaqueKeyMaterial(k))) => vec_try![
David Drysdale9f27bc92022-06-10 15:53:32 +0100342 cbor::value::Value::Integer((Algorithm::TripleDes as i32).into()),
David Drysdale0b3938d2022-09-28 16:49:16 +0100343 cbor::value::Value::Bool(true),
344 cbor::value::Value::Bytes(try_to_vec(&k)?),
345 ]
346 .map_err(cbor_alloc_err)?,
347 Self::Hmac(OpaqueOr::Opaque(OpaqueKeyMaterial(k))) => vec_try![
David Drysdale9f27bc92022-06-10 15:53:32 +0100348 cbor::value::Value::Integer((Algorithm::Hmac as i32).into()),
David Drysdale0b3938d2022-09-28 16:49:16 +0100349 cbor::value::Value::Bool(true),
350 cbor::value::Value::Bytes(try_to_vec(&k)?),
351 ]
352 .map_err(cbor_alloc_err)?,
353 Self::Rsa(OpaqueOr::Opaque(OpaqueKeyMaterial(k))) => vec_try![
David Drysdale9f27bc92022-06-10 15:53:32 +0100354 cbor::value::Value::Integer((Algorithm::Rsa as i32).into()),
David Drysdale0b3938d2022-09-28 16:49:16 +0100355 cbor::value::Value::Bool(true),
356 cbor::value::Value::Bytes(try_to_vec(&k)?),
357 ]
358 .map_err(cbor_alloc_err)?,
359 Self::Ec(curve, curve_type, OpaqueOr::Opaque(OpaqueKeyMaterial(k))) => vec_try![
David Drysdale9f27bc92022-06-10 15:53:32 +0100360 cbor::value::Value::Integer((Algorithm::Ec as i32).into()),
David Drysdale0b3938d2022-09-28 16:49:16 +0100361 cbor::value::Value::Bool(true),
362 cbor::value::Value::Array(
363 vec_try![
364 cbor::value::Value::Integer((curve as i32).into()),
365 cbor::value::Value::Integer((curve_type as i32).into()),
366 cbor::value::Value::Bytes(try_to_vec(&k)?),
367 ]
368 .map_err(cbor_alloc_err)?
369 ),
370 ]
371 .map_err(cbor_alloc_err)?,
372
373 Self::Aes(OpaqueOr::Explicit(k)) => vec_try![
374 cbor::value::Value::Integer((Algorithm::Aes as i32).into()),
375 cbor::value::Value::Bool(false),
376 match k {
377 aes::Key::Aes128(k) => cbor::value::Value::Bytes(try_to_vec(&k)?),
378 aes::Key::Aes192(k) => cbor::value::Value::Bytes(try_to_vec(&k)?),
379 aes::Key::Aes256(k) => cbor::value::Value::Bytes(try_to_vec(&k)?),
380 },
381 ]
382 .map_err(cbor_alloc_err)?,
383
384 Self::TripleDes(OpaqueOr::Explicit(k)) => vec_try![
385 cbor::value::Value::Integer((Algorithm::TripleDes as i32).into()),
386 cbor::value::Value::Bool(false),
387 cbor::value::Value::Bytes(k.0.to_vec()),
388 ]
389 .map_err(cbor_alloc_err)?,
390 Self::Hmac(OpaqueOr::Explicit(k)) => vec_try![
391 cbor::value::Value::Integer((Algorithm::Hmac as i32).into()),
392 cbor::value::Value::Bool(false),
393 cbor::value::Value::Bytes(k.0.clone()),
394 ]
395 .map_err(cbor_alloc_err)?,
396 Self::Rsa(OpaqueOr::Explicit(k)) => vec_try![
397 cbor::value::Value::Integer((Algorithm::Rsa as i32).into()),
398 cbor::value::Value::Bool(false),
399 cbor::value::Value::Bytes(k.0.clone()),
400 ]
401 .map_err(cbor_alloc_err)?,
402 Self::Ec(curve, curve_type, OpaqueOr::Explicit(k)) => vec_try![
403 cbor::value::Value::Integer((Algorithm::Ec as i32).into()),
404 cbor::value::Value::Bool(false),
405 cbor::value::Value::Array(
406 vec_try![
407 cbor::value::Value::Integer((curve as i32).into()),
408 cbor::value::Value::Integer((curve_type as i32).into()),
409 cbor::value::Value::Bytes(k.private_key_bytes().to_vec()),
410 ]
411 .map_err(cbor_alloc_err)?,
412 ),
413 ]
414 .map_err(cbor_alloc_err)?,
David Drysdale9f27bc92022-06-10 15:53:32 +0100415 }))
416 }
417
418 fn cddl_typename() -> Option<String> {
David Drysdale0b3938d2022-09-28 16:49:16 +0100419 Some("KeyMaterial".to_string())
David Drysdale9f27bc92022-06-10 15:53:32 +0100420 }
421
422 fn cddl_schema() -> Option<String> {
423 Some(format!(
424 "&(
David Drysdale0b3938d2022-09-28 16:49:16 +0100425 ; For each variant the `bool` second entry indicates whether the bstr for the key material
426 ; is opaque (true), or explicit (false).
427 [{}, bool, bstr], ; {}
428 [{}, bool, bstr], ; {}
429 [{}, bool, bstr], ; {}
430 ; An explicit RSA key is in the form of an ASN.1 DER encoding of a PKCS#1 `RSAPrivateKey`
431 ; structure, as specified by RFC 3447 sections A.1.2 and 3.2.
432 [{}, bool, bstr], ; {}
433 ; An explicit EC key for a NIST curve is in the form of an ASN.1 DER encoding of a
434 ; `ECPrivateKey` structure, as specified by RFC 5915 section 3.
435 ; An explicit EC key for curve 25519 is the raw key bytes.
436 [{}, bool, [EcCurve, CurveType, bstr]], ; {}
David Drysdale9f27bc92022-06-10 15:53:32 +0100437)",
438 Algorithm::Aes as i32,
439 "Algorithm_Aes",
440 Algorithm::TripleDes as i32,
441 "Algorithm_TripleDes",
442 Algorithm::Hmac as i32,
443 "Algorithm_Hmac",
444 Algorithm::Rsa as i32,
445 "Algorithm_Rsa",
446 Algorithm::Ec as i32,
447 "Algorithm_Ec",
448 ))
449 }
450}
451
David Drysdale9f27bc92022-06-10 15:53:32 +0100452/// Direction of cipher operation.
453#[derive(Clone, Copy, Debug, PartialEq, Eq)]
454pub enum SymmetricOperation {
David Drysdale63e6ad62023-05-05 17:41:08 +0100455 /// Perform encryption.
David Drysdale9f27bc92022-06-10 15:53:32 +0100456 Encrypt,
David Drysdale63e6ad62023-05-05 17:41:08 +0100457 /// Perform decryption.
David Drysdale9f27bc92022-06-10 15:53:32 +0100458 Decrypt,
459}
460
461/// Extract or generate a nonce of the given size.
462pub fn nonce(
463 size: usize,
464 caller_nonce: Option<&Vec<u8>>,
465 rng: &mut dyn Rng,
466) -> Result<Vec<u8>, Error> {
467 match caller_nonce {
468 Some(n) => match n.len() {
469 l if l == size => Ok(n.clone()),
470 _ => Err(km_err!(InvalidNonce, "want {} byte nonce", size)),
471 },
472 None => {
David Drysdale0b3938d2022-09-28 16:49:16 +0100473 let mut n = vec_try![0; size]?;
David Drysdale9f27bc92022-06-10 15:53:32 +0100474 rng.fill_bytes(&mut n);
475 Ok(n)
476 }
477 }
478}
479
480/// Salt value used in HKDF if none provided.
481const HKDF_EMPTY_SALT: [u8; SHA256_DIGEST_LEN] = [0; SHA256_DIGEST_LEN];
482
483/// Convenience wrapper to perform one-shot HMAC-SHA256.
Hasini Gunasinghe11c29822022-11-14 02:24:54 +0000484pub fn hmac_sha256(hmac: &dyn Hmac, key: &[u8], data: &[u8]) -> Result<Vec<u8>, Error> {
David Drysdale0b3938d2022-09-28 16:49:16 +0100485 let mut op = hmac.begin(hmac::Key(crate::try_to_vec(key)?).into(), Digest::Sha256)?;
David Drysdale9f27bc92022-06-10 15:53:32 +0100486 op.update(data)?;
487 op.finish()
488}
489
David Drysdaleed33ed12022-08-23 10:01:39 +0100490/// Default implementation of [`Hkdf`] for any type implementing [`Hmac`].
491impl<T: Hmac> Hkdf for T {
Orlando Arbildo97ee0582023-01-13 17:05:26 +0000492 fn extract(&self, mut salt: &[u8], ikm: &[u8]) -> Result<OpaqueOr<hmac::Key>, Error> {
David Drysdaleed33ed12022-08-23 10:01:39 +0100493 if salt.is_empty() {
494 salt = &HKDF_EMPTY_SALT[..];
495 }
496 let prk = hmac_sha256(self, salt, ikm)?;
Orlando Arbildo97ee0582023-01-13 17:05:26 +0000497 Ok(OpaqueOr::Explicit(hmac::Key::new(prk)))
498 }
David Drysdale9f27bc92022-06-10 15:53:32 +0100499
Orlando Arbildo97ee0582023-01-13 17:05:26 +0000500 fn expand(
501 &self,
502 prk: &OpaqueOr<hmac::Key>,
503 info: &[u8],
504 out_len: usize,
505 ) -> Result<Vec<u8>, Error> {
506 let prk = &explicit!(prk)?.0;
David Drysdaleed33ed12022-08-23 10:01:39 +0100507 let n = (out_len + SHA256_DIGEST_LEN - 1) / SHA256_DIGEST_LEN;
508 if n > 256 {
Tri Vo9e4b4472023-08-30 11:21:48 -0400509 return Err(km_err!(InvalidArgument, "overflow in hkdf"));
David Drysdaleed33ed12022-08-23 10:01:39 +0100510 }
David Drysdale0b3938d2022-09-28 16:49:16 +0100511 let mut t = vec_try_with_capacity!(SHA256_DIGEST_LEN)?;
512 let mut okm = vec_try_with_capacity!(n * SHA256_DIGEST_LEN)?;
David Drysdaleed33ed12022-08-23 10:01:39 +0100513 let n = n as u8;
514 for idx in 0..n {
David Drysdale0b3938d2022-09-28 16:49:16 +0100515 let mut input = vec_try_with_capacity!(t.len() + info.len() + 1)?;
David Drysdaleed33ed12022-08-23 10:01:39 +0100516 input.extend_from_slice(&t);
517 input.extend_from_slice(info);
518 input.push(idx + 1);
David Drysdale0b3938d2022-09-28 16:49:16 +0100519
Orlando Arbildo97ee0582023-01-13 17:05:26 +0000520 t = hmac_sha256(self, prk, &input)?;
David Drysdale0b3938d2022-09-28 16:49:16 +0100521 okm.try_extend_from_slice(&t)?;
David Drysdaleed33ed12022-08-23 10:01:39 +0100522 }
523 okm.truncate(out_len);
524 Ok(okm)
David Drysdale9f27bc92022-06-10 15:53:32 +0100525 }
David Drysdale9f27bc92022-06-10 15:53:32 +0100526}
527
David Drysdaleed33ed12022-08-23 10:01:39 +0100528/// Default implementation of [`Ckdf`] for any type implementing [`AesCmac`].
529impl<T: AesCmac> Ckdf for T {
530 fn ckdf(
531 &self,
David Drysdale0b3938d2022-09-28 16:49:16 +0100532 key: &OpaqueOr<aes::Key>,
David Drysdaleed33ed12022-08-23 10:01:39 +0100533 label: &[u8],
534 chunks: &[&[u8]],
535 out_len: usize,
536 ) -> Result<Vec<u8>, Error> {
David Drysdale0b3938d2022-09-28 16:49:16 +0100537 let key = explicit!(key)?;
David Drysdaleed33ed12022-08-23 10:01:39 +0100538 // Note: the variables i and l correspond to i and L in the standard. See page 12 of
539 // http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-108.pdf.
David Drysdale9f27bc92022-06-10 15:53:32 +0100540
David Drysdaleed33ed12022-08-23 10:01:39 +0100541 let blocks: u32 = ((out_len + aes::BLOCK_SIZE - 1) / aes::BLOCK_SIZE) as u32;
542 let l = (out_len * 8) as u32; // in bits
543 let net_order_l = l.to_be_bytes();
544 let zero_byte: [u8; 1] = [0];
David Drysdale0b3938d2022-09-28 16:49:16 +0100545 let mut output = vec_try![0; out_len]?;
David Drysdaleed33ed12022-08-23 10:01:39 +0100546 let mut output_pos = 0;
David Drysdale9f27bc92022-06-10 15:53:32 +0100547
David Drysdaleed33ed12022-08-23 10:01:39 +0100548 for i in 1u32..=blocks {
549 // Data to mac is (i:u32 || label || 0x00:u8 || context || L:u32), with integers in
550 // network order.
David Drysdale0b3938d2022-09-28 16:49:16 +0100551 let mut op = self.begin(key.clone().into())?;
David Drysdaleed33ed12022-08-23 10:01:39 +0100552 let net_order_i = i.to_be_bytes();
553 op.update(&net_order_i[..])?;
554 op.update(label)?;
555 op.update(&zero_byte[..])?;
556 for chunk in chunks {
557 op.update(chunk)?;
558 }
559 op.update(&net_order_l[..])?;
560
561 let data = op.finish()?;
562 let copy_len = core::cmp::min(data.len(), output.len() - output_pos);
563 output[output_pos..output_pos + copy_len].clone_from_slice(&data[..copy_len]);
564 output_pos += copy_len;
David Drysdale9f27bc92022-06-10 15:53:32 +0100565 }
David Drysdaleed33ed12022-08-23 10:01:39 +0100566 if output_pos != output.len() {
567 return Err(km_err!(
Tri Vo9e4b4472023-08-30 11:21:48 -0400568 InvalidArgument,
David Drysdaleed33ed12022-08-23 10:01:39 +0100569 "finished at {} before end of output at {}",
570 output_pos,
571 output.len()
572 ));
573 }
574 Ok(output)
David Drysdale9f27bc92022-06-10 15:53:32 +0100575 }
David Drysdale9f27bc92022-06-10 15:53:32 +0100576}