• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 //! Trusty implementation of RetrieveKeyMaterial.
17 
18 use alloc::vec::Vec;
19 use core::ffi::CStr;
20 use core::mem::size_of;
21 use hwkey::{Hwkey, KdfVersion, OsRollbackVersion, RollbackVersionSource};
22 use kmr_common::{crypto, km_err, vec_try_with_capacity, Error};
23 use kmr_wire::secureclock::{TimeStampToken, TIME_STAMP_MAC_LABEL};
24 
25 pub(crate) mod legacy;
26 
27 /// Size of a key agreement key in bytes.
28 const TRUSTY_KM_KAK_SIZE: usize = 32;
29 
30 /// Size of a key wrapping key in bytes.
31 const TRUSTY_KM_WRAPPING_KEY_SIZE: usize = 16;
32 
33 /// Key slot identification; matches the value used in
34 /// `OpenSSLKeymasterEnforcement::GetKeyAgreementKey` in `openssl_keymaster_enforcement.cpp` for
35 /// back-compatibility.
36 const KM_KAK_SLOT_ID: &[u8] = b"com.android.trusty.keymint.kak\0";
37 
38 /// Key derivation input data; matches `kMasterKeyDerivationData` in `trusty_keymaster_context.cpp`
39 /// for back-compatibility.
40 const KM_KEY_DERIVATION_DATA: &[u8] = b"KeymasterMaster\0";
41 
42 /// Size of a `u32` value in bytes.
43 const U32_SIZE: usize = core::mem::size_of::<u32>();
44 
45 /// Extract a (little-endian) serialized `u32`.
deserialize_u32(bytes: &[u8], error_message: &str) -> Result<u32, Error>46 fn deserialize_u32(bytes: &[u8], error_message: &str) -> Result<u32, Error> {
47     let u32_bytes: [u8; U32_SIZE] = match bytes.try_into() {
48         Ok(byte_array) => byte_array,
49         Err(_) => return Err(km_err!(InvalidArgument, "{}", error_message)),
50     };
51     Ok(u32::from_le_bytes(u32_bytes))
52 }
53 
54 /// Convert an [`OsRollbackVersion`] to an integer value, expanding `Current` along the way.
os_rollback_version_to_u32(os_rollback_version: OsRollbackVersion) -> Result<u32, Error>55 fn os_rollback_version_to_u32(os_rollback_version: OsRollbackVersion) -> Result<u32, Error> {
56     match os_rollback_version {
57         // If we get a `Current` version, we want to convert it to the specific version, so the
58         // context remains accurate if it is saved and used at a later time.
59         OsRollbackVersion::Current => {
60             let hwkey_session = match Hwkey::open() {
61                 Ok(connection) => connection,
62                 Err(_) => {
63                     return Err(km_err!(SecureHwCommunicationFailed, "hwkey connection error"))
64                 }
65             };
66             match hwkey_session.query_current_os_version(RollbackVersionSource::CommittedVersion) {
67                 Ok(OsRollbackVersion::Version(n)) => Ok(n),
68                 _ => Err(km_err!(
69                     SecureHwCommunicationFailed,
70                     "couldn't get current os rollback version"
71                 )),
72             }
73         }
74         OsRollbackVersion::Version(n) => Ok(n),
75     }
76 }
77 
78 /// Context information required for key derivation with versioned information.
79 #[derive(Clone, Debug, PartialEq, Eq)]
80 struct NonLegacyKeyContext {
81     kdf_version: KdfVersion,
82     os_rollback_version: OsRollbackVersion,
83 }
84 
85 /// KEK context that provides information to derive the same Key Encryption Key used to encrypt a
86 /// given key. To be able to do that we need to know if the key is a legacy one or not; and if it is
87 /// not a legacy key; we need to know the KDF method used (although currently there is only 1
88 /// method) and the Os Rollback version (more info on this parameters can be found on the trusty
89 /// hwkey crate).
90 #[derive(Clone, Debug, PartialEq, Eq)]
91 enum TrustyKekContext {
92     LegacyKey,
93     NonLegacyKey(NonLegacyKeyContext),
94 }
95 
96 impl TrustyKekContext {
97     /// Current version of the serialized format of [`TrustyKekContext`] data.  If the structure is
98     /// changed this number needs to be bumped and the serialize/deserialize functions updated.
99     const CONTEXT_VERSION: u32 = 1;
100 
101     /// Offset of version marker for serialized data.
102     const CONTEXT_VER_OFFSET: usize = 0;
103     /// Offset of non-legacy key indicator in serialized data.  Reserves 4 bytes in case we want to
104     /// replace it with the enum that represents the specific key format.  For kek derivation we
105     /// don't really use it; it is either a legacy key or not.
106     const NON_LEGACY_KEY_OFFSET: usize = Self::CONTEXT_VER_OFFSET + U32_SIZE;
107     /// Offset of KDF version in serialized data.
108     const KDF_VER_OFFSET: usize = Self::NON_LEGACY_KEY_OFFSET + U32_SIZE;
109     /// Offset of OS rollback version in serialized data.
110     const OS_ROLLBACK_VER_OFFSET: usize = Self::KDF_VER_OFFSET + U32_SIZE;
111 
112     /// Overall size of serialized form in bytes.
113     const SERIALIZED_SIZE: usize = Self::OS_ROLLBACK_VER_OFFSET + U32_SIZE;
114 
115     /// Build a new `TrustyKekContext` from constituent values.
new( non_legacy_key: bool, kdf_version: Option<KdfVersion>, os_rollback_version: Option<OsRollbackVersion>, ) -> Result<Self, Error>116     fn new(
117         non_legacy_key: bool,
118         kdf_version: Option<KdfVersion>,
119         os_rollback_version: Option<OsRollbackVersion>,
120     ) -> Result<Self, Error> {
121         if non_legacy_key {
122             if kdf_version.is_none() {
123                 return Err(km_err!(InvalidArgument, "non-legacy keys require a KDF version"));
124             }
125             if os_rollback_version.is_none() {
126                 return Err(km_err!(
127                     InvalidArgument,
128                     "non-legacy keys require an OS Rollback version"
129                 ));
130             }
131             // Directly unwrapping values because we checked that they were not None
132             let kdf_version = kdf_version.unwrap();
133             let os_rollback_version = os_rollback_version.unwrap();
134             Ok(TrustyKekContext::NonLegacyKey(NonLegacyKeyContext {
135                 kdf_version,
136                 os_rollback_version,
137             }))
138         } else {
139             if kdf_version.is_some() {
140                 return Err(km_err!(InvalidArgument, "legacy keys do not use a KDF version"));
141             }
142             if os_rollback_version.is_some() {
143                 return Err(km_err!(
144                     InvalidArgument,
145                     "legacy keys do not use a OS Rollback version"
146                 ));
147             }
148             Ok(TrustyKekContext::LegacyKey)
149         }
150     }
151 
152     /// Build a [`TrustyKekContext`] from its serialized form.
from_raw(raw_context: &[u8]) -> Result<Self, Error>153     fn from_raw(raw_context: &[u8]) -> Result<Self, Error> {
154         if raw_context.len() != Self::SERIALIZED_SIZE {
155             return Err(km_err!(
156                 InvalidArgument,
157                 "provided kek context had wrong size ({} not {} bytes)",
158                 raw_context.len(),
159                 Self::SERIALIZED_SIZE
160             ));
161         }
162         let context_version = deserialize_u32(
163             &raw_context[..Self::NON_LEGACY_KEY_OFFSET],
164             "couldn't deserialize context version",
165         )?;
166         if context_version != Self::CONTEXT_VERSION {
167             return Err(km_err!(InvalidArgument, "invalid context version {}", context_version));
168         }
169         let non_legacy_key = deserialize_u32(
170             &raw_context[Self::NON_LEGACY_KEY_OFFSET..Self::KDF_VER_OFFSET],
171             "couldn't deserialize kdf version",
172         )?;
173         match non_legacy_key {
174             0 => Ok(TrustyKekContext::LegacyKey),
175             1 => {
176                 let kdf_version = deserialize_u32(
177                     &raw_context[Self::KDF_VER_OFFSET..Self::OS_ROLLBACK_VER_OFFSET],
178                     "couldn't deserialize kdf version",
179                 )?;
180                 let kdf_version = KdfVersion::from(kdf_version);
181                 let os_rollback_version = deserialize_u32(
182                     &raw_context[Self::OS_ROLLBACK_VER_OFFSET..],
183                     "Couldn't deserialize os rolback version",
184                 )?;
185                 let os_rollback_version = OsRollbackVersion::Version(os_rollback_version);
186                 Ok(TrustyKekContext::NonLegacyKey(NonLegacyKeyContext {
187                     kdf_version,
188                     os_rollback_version,
189                 }))
190             }
191             v => Err(km_err!(InvalidArgument, "invalid non legacy key value {}", v)),
192         }
193     }
194 
195     /// Convert a [`TrustyKekContext`] into its serialized form, as 4 consecutive little-endian U32
196     /// values:
197     /// - context version
198     /// - non-legacy key indicator
199     /// - KDF version
200     /// - OS rollback version.
to_raw(&self) -> Result<Vec<u8>, Error>201     fn to_raw(&self) -> Result<Vec<u8>, Error> {
202         // For legacy keys giving 0 values for OS and KDF version. These values will be ignored on
203         // deserialization.
204         let (os_version, kdf_version, non_legacy_key) = match self {
205             TrustyKekContext::LegacyKey => (0, 0, 0u32),
206             TrustyKekContext::NonLegacyKey(ctx) => {
207                 let os_version = os_rollback_version_to_u32(ctx.os_rollback_version)?;
208                 let kdf_version: u32 = ctx.kdf_version.into();
209                 (os_version, kdf_version, 1u32)
210             }
211         };
212         let mut raw_vec = vec_try_with_capacity!(Self::SERIALIZED_SIZE)?;
213         raw_vec.extend_from_slice(&Self::CONTEXT_VERSION.to_le_bytes());
214         raw_vec.extend_from_slice(&non_legacy_key.to_le_bytes());
215         raw_vec.extend_from_slice(&kdf_version.to_le_bytes());
216         raw_vec.extend_from_slice(&os_version.to_le_bytes());
217         Ok(raw_vec)
218     }
219 }
220 
221 /// Key material retrieval implementation for Trusty.
222 pub struct TrustyKeys;
223 
224 // TODO: Change traits definitions to support kek and kak keys stored on hardware if needed.
225 //       RawKeyMaterial assume that the key will be passed in the clear, which won't be the case
226 //       if the IP block never releases the key. KeyMaterial type fixes that issue by including
227 //       Opaque keys, but RawKeys are not included in KeyMaterial.
228 impl kmr_ta::device::RetrieveKeyMaterial for TrustyKeys {
root_kek(&self, context: &[u8]) -> Result<crypto::OpaqueOr<crypto::hmac::Key>, Error>229     fn root_kek(&self, context: &[u8]) -> Result<crypto::OpaqueOr<crypto::hmac::Key>, Error> {
230         let context = TrustyKekContext::from_raw(context)?;
231         let hwkey_session = Hwkey::open().map_err(|e| {
232             km_err!(SecureHwCommunicationFailed, "failed to connect to hwkey: {:?}", e)
233         })?;
234 
235         let mut key_buffer = [0; TRUSTY_KM_WRAPPING_KEY_SIZE];
236 
237         match context {
238             TrustyKekContext::NonLegacyKey(context) => {
239                 let _ = hwkey_session
240                     .derive_key_req()
241                     .unique_key()
242                     .kdf(context.kdf_version)
243                     .os_rollback_version(context.os_rollback_version)
244                     .rollback_version_source(RollbackVersionSource::CommittedVersion)
245                     .derive(KM_KEY_DERIVATION_DATA, &mut key_buffer)
246                     .map_err(|e| {
247                         km_err!(SecureHwCommunicationFailed, "failed to derive key: {:?}", e)
248                     })?;
249             }
250             TrustyKekContext::LegacyKey => {
251                 let _ = hwkey_session
252                     .derive_key_req()
253                     .kdf(KdfVersion::Version(1))
254                     .derive(KM_KEY_DERIVATION_DATA, &mut key_buffer)
255                     .map_err(|e| {
256                         km_err!(SecureHwCommunicationFailed, "failed to derive legacy key: {:?}", e)
257                     })?;
258             }
259         }
260         Ok(crypto::hmac::Key::new(key_buffer.to_vec()).into())
261     }
262 
kek_context(&self) -> Result<Vec<u8>, Error>263     fn kek_context(&self) -> Result<Vec<u8>, Error> {
264         TrustyKekContext::new(true, Some(KdfVersion::Best), Some(OsRollbackVersion::Current))?
265             .to_raw()
266     }
267 
kak(&self) -> Result<crypto::OpaqueOr<crypto::aes::Key>, Error>268     fn kak(&self) -> Result<crypto::OpaqueOr<crypto::aes::Key>, Error> {
269         let hwkey_session = Hwkey::open().map_err(|e| {
270             km_err!(SecureHwCommunicationFailed, "failed to connect to HwKey: {:?}", e)
271         })?;
272         let mut key_buffer = [0; TRUSTY_KM_KAK_SIZE];
273         let keyslot = CStr::from_bytes_with_nul(KM_KAK_SLOT_ID)
274             .expect("should never happen, KM_KAK_SLOT_ID follows from_bytes_with_nul rules");
275         let _kak = hwkey_session
276             .get_keyslot_data(keyslot, &mut key_buffer)
277             .map_err(|e| km_err!(SecureHwCommunicationFailed, "failed to retrieve kak: {:?}", e))?;
278         // TODO: check whether `key_buffer` needs truncating to size of `_kak`.
279         Ok(crypto::aes::Key::Aes256(key_buffer).into())
280     }
281 
timestamp_token_mac_input(&self, token: &TimeStampToken) -> Result<Vec<u8>, Error>282     fn timestamp_token_mac_input(&self, token: &TimeStampToken) -> Result<Vec<u8>, Error> {
283         let mut result = vec_try_with_capacity!(
284             TIME_STAMP_MAC_LABEL.len() +
285         size_of::<i64>() + // challenge (host-endian)
286         size_of::<i64>() + // timestamp (host-endian)
287         size_of::<u32>() // 1u32 (host-endian)
288         )?;
289         // For compatibility with previous implementations, use native byte order for MAC inputs.
290         result.extend_from_slice(TIME_STAMP_MAC_LABEL);
291         result.extend_from_slice(&token.challenge.to_ne_bytes()[..]);
292         result.extend_from_slice(&token.timestamp.milliseconds.to_ne_bytes()[..]);
293         result.extend_from_slice(&1u32.to_ne_bytes()[..]);
294         Ok(result)
295     }
296 }
297 
298 #[cfg(test)]
299 mod tests {
300     use super::*;
301     use kmr_ta::device::RetrieveKeyMaterial;
302     use test::{expect, expect_eq, expect_ne, skip};
303 
304     #[test]
kak_call_returns_key()305     fn kak_call_returns_key() {
306         let trusty_keys = TrustyKeys;
307         let kak = trusty_keys.kak().expect("Couldn't retrieve kak");
308         let kak = kmr_common::explicit!(kak).expect("kak should be an explicit key");
309 
310         expect!(matches!(kak, crypto::aes::Key::Aes256(_)), "Should have received an AES 256 key");
311 
312         let key = match kak {
313             crypto::aes::Key::Aes256(key) => key,
314             _ => panic!("Wrong type of key received"),
315         };
316         // Getting an all 0 key agreement key by chance is not likely if we got a connection to
317         // HWKey
318         expect_ne!(key, [0; TRUSTY_KM_KAK_SIZE], "key agreement key should not be 0s");
319     }
320 
321     #[test]
kak_two_calls_returns_same_key()322     fn kak_two_calls_returns_same_key() {
323         let trusty_keys = TrustyKeys;
324 
325         let kak = trusty_keys.kak().expect("Couldn't retrieve kak");
326         let kak1 = match kmr_common::explicit!(kak).expect("kak should be an explicit key") {
327             crypto::aes::Key::Aes256(key) => key,
328             _ => panic!("Wrong type of key received"),
329         };
330         let kak = trusty_keys.kak().expect("Couldn't retrieve kak");
331         let kak2 = match kmr_common::explicit!(kak).expect("kak should be an explicit key") {
332             crypto::aes::Key::Aes256(key) => key,
333             _ => panic!("Wrong type of key received"),
334         };
335         expect_eq!(kak1, kak2, "Calls to kak should return the same key");
336     }
337 
338     #[test]
kek_call_returns_key()339     fn kek_call_returns_key() {
340         let trusty_keys = TrustyKeys;
341         let kek = trusty_keys
342             .root_kek(&trusty_keys.kek_context().expect("Couldn't get kek context"))
343             .expect("Couldn't get kek");
344         let kek = kmr_common::explicit!(kek).expect("kek should be an explicit key");
345 
346         // Getting an all 0 key encryption key by chance is not likely if we got a connection to
347         // HWKey
348         expect_ne!(
349             kek.0,
350             [0; TRUSTY_KM_WRAPPING_KEY_SIZE].to_vec(),
351             "Key encryption key should not be 0s"
352         );
353     }
354 
355     #[test]
kek_two_calls_returns_same_key()356     fn kek_two_calls_returns_same_key() {
357         let trusty_keys = TrustyKeys;
358         let kek1 = kmr_common::explicit!(trusty_keys
359             .root_kek(&trusty_keys.kek_context().expect("Couldn't get kek context"))
360             .expect("Couldn't get kek"))
361         .expect("kek should be an explicit key");
362         let kek2 = kmr_common::explicit!(trusty_keys
363             .root_kek(&trusty_keys.kek_context().expect("Couldn't get kek context"))
364             .expect("Couldn't get kek"))
365         .expect("kek should be an explicit key");
366 
367         expect_eq!(kek1.0, kek2.0, "Calls to root_kek should return the same key");
368     }
369 
370     #[test]
kek_with_different_context_return_different_keys()371     fn kek_with_different_context_return_different_keys() {
372         if true {
373             skip!("TODO: reinstate test");
374         }
375         let context1 =
376             TrustyKekContext::new(true, Some(KdfVersion::Best), Some(OsRollbackVersion::Current));
377         // Transforming back and forward to raw format to get specific versions
378         let context1 = TrustyKekContext::from_raw(&context1.unwrap().to_raw().unwrap()).unwrap();
379         let non_legacy_context1 = match context1.clone() {
380             TrustyKekContext::NonLegacyKey(context) => context,
381             _ => panic!("Didn't get back a non-legacy key"),
382         };
383         let context1_version = match non_legacy_context1.os_rollback_version {
384             OsRollbackVersion::Version(n) => n,
385             _ => panic!("Didn't get an specific version"),
386         };
387         // Specific running/committed versions are greater than 0.
388         let context2_version = context1_version - 1;
389         let context2 = TrustyKekContext::new(
390             true,
391             Some(KdfVersion::Best),
392             Some(OsRollbackVersion::Version(context2_version)),
393         )
394         .unwrap();
395         let trusty_keys = TrustyKeys;
396         let kek1 = kmr_common::explicit!(trusty_keys
397             .root_kek(&context1.to_raw().expect("Couldn't serialize kek1 context"))
398             .expect("Couldn't get kek"))
399         .expect("kek should be an explicit key");
400         let kek2 = kmr_common::explicit!(trusty_keys
401             .root_kek(&context2.to_raw().expect("Couldn't serialize kek2 context"))
402             .expect("Couldn't get kek"))
403         .expect("kek should be an explicit key");
404 
405         expect_ne!(kek1.0, kek2.0, "kek keys should be different");
406     }
407 
408     #[test]
legacy_kek_is_different_than_non_legacy()409     fn legacy_kek_is_different_than_non_legacy() {
410         if true {
411             skip!("TODO: reinstate test");
412         }
413         let context1 =
414             TrustyKekContext::new(true, Some(KdfVersion::Best), Some(OsRollbackVersion::Current))
415                 .unwrap();
416         let context2 = TrustyKekContext::new(false, None, None).unwrap();
417         let trusty_keys = TrustyKeys;
418         let kek1 = kmr_common::explicit!(trusty_keys
419             .root_kek(&context1.to_raw().expect("Couldn't serialize kek1 context"))
420             .expect("Couldn't get kek"))
421         .expect("kek should be an explicit key");
422         let kek2 = kmr_common::explicit!(trusty_keys
423             .root_kek(&context2.to_raw().expect("Couldn't serialize kek2 context"))
424             .expect("Couldn't get kek"))
425         .expect("kek should be an explicit key");
426 
427         expect_ne!(kek1.0, kek2.0, "kek keys should be different");
428     }
429 
430     #[test]
deserializing_u32s()431     fn deserializing_u32s() {
432         let num = deserialize_u32(&[0; 0], "");
433         expect!(num.is_err(), "We need an array of exactly 4 bytes for a u32");
434         let num = deserialize_u32(&[0; 3], "");
435         expect!(num.is_err(), "We need an array of exactly 4 bytes for a u32");
436         let num = deserialize_u32(&[0; 5], "");
437         expect!(num.is_err(), "We need an array of exactly 4 bytes for a u32");
438         let num = deserialize_u32(&[0; 4], "").unwrap();
439         expect_eq!(num, 0, "recovered number should be 0");
440         let num = deserialize_u32(&[0xff; 4], "").unwrap();
441         expect_eq!(num, 0xffffffff, "recovered number should be 0xffffffff");
442         let num = deserialize_u32(&[1, 0, 0, 0], "").unwrap();
443         expect_eq!(num, 1, "recovered number should be 1");
444         let num = deserialize_u32(&[0x78, 0x56, 0x34, 0x12], "").unwrap();
445         expect_eq!(num, 0x12345678, "recovered number should be 0x12345678");
446     }
447 
448     #[test]
os_version_to_u32()449     fn os_version_to_u32() {
450         for version in 0..20 {
451             let u32_version =
452                 os_rollback_version_to_u32(OsRollbackVersion::Version(version)).unwrap();
453             expect_eq!(version, u32_version, "Wriong version received");
454         }
455     }
456 
457     #[test]
current_version_to_u32()458     fn current_version_to_u32() {
459         if true {
460             skip!("TODO: reinstate test");
461         }
462         let curr_version = os_rollback_version_to_u32(OsRollbackVersion::Current).unwrap();
463         expect_ne!(curr_version, 0, "Current version should not be 0");
464     }
465 
466     #[test]
deserializing_bad_kek_context_fails()467     fn deserializing_bad_kek_context_fails() {
468         let ctx_1 = TrustyKekContext::from_raw(&[0; 0]);
469         expect!(ctx_1.is_err(), "deserializing an empty context should fail");
470         let good_ctx =
471             TrustyKekContext::new(true, Some(KdfVersion::Best), Some(OsRollbackVersion::Current))
472                 .unwrap();
473         let mut ctx_raw = good_ctx.to_raw().unwrap();
474         ctx_raw.push(0);
475         let ctx_2 = TrustyKekContext::from_raw(&ctx_raw);
476         expect!(ctx_2.is_err(), "deserializing a bigger than expected context should fail");
477         ctx_raw.pop();
478         let ctx_3 = TrustyKekContext::from_raw(&ctx_raw);
479         expect!(ctx_3.is_ok(), "checking that good context can be deserialized");
480         ctx_raw.pop();
481         let ctx_4 = TrustyKekContext::from_raw(&ctx_raw);
482         expect!(ctx_4.is_err(), "deserializing a smaller than expected context should fail");
483         let ctx_5 = TrustyKekContext::from_raw(&[0; TrustyKekContext::SERIALIZED_SIZE]);
484         expect!(ctx_5.is_err(), "deserializing a smaller than expected context should fail");
485     }
486 
487     #[test]
test_kek_context_serialization()488     fn test_kek_context_serialization() {
489         let original_ctx = TrustyKekContext::new(
490             true,
491             Some(KdfVersion::Best),
492             Some(OsRollbackVersion::Version(2)),
493         )
494         .unwrap();
495         let recovered_ctx = TrustyKekContext::from_raw(&original_ctx.to_raw().unwrap()).unwrap();
496         expect_eq!(original_ctx, recovered_ctx, "Didn't get back same context");
497         let original_ctx = TrustyKekContext::new(false, None, None).unwrap();
498         let recovered_ctx = TrustyKekContext::from_raw(&original_ctx.to_raw().unwrap()).unwrap();
499         expect_eq!(original_ctx, recovered_ctx, "Didn't get back same context");
500     }
501 
502     #[test]
test_kek_context_creation()503     fn test_kek_context_creation() {
504         // Testing that non legacy context requires all parameters to be present
505         let non_legacy_ctx = TrustyKekContext::new(true, None, Some(OsRollbackVersion::Version(2)));
506         expect!(
507             non_legacy_ctx.is_err(),
508             "We should not be able to create a non legacy context without KDF version"
509         );
510         let non_legacy_ctx = TrustyKekContext::new(true, Some(KdfVersion::Best), None);
511         expect!(
512             non_legacy_ctx.is_err(),
513             "We should not be able to create a non legacy context without OS rollback version"
514         );
515         let non_legacy_ctx = TrustyKekContext::new(
516             true,
517             Some(KdfVersion::Best),
518             Some(OsRollbackVersion::Version(2)),
519         );
520         expect!(non_legacy_ctx.is_ok(), "Couldn't create non legacy context");
521         // Testing that legacy context requires all optional parameters to be None
522         let legacy_ctx = TrustyKekContext::new(
523             false,
524             Some(KdfVersion::Best),
525             Some(OsRollbackVersion::Version(2)),
526         );
527         expect!(
528             legacy_ctx.is_err(),
529             "We should not be able to create a non legacy with optional parameters"
530         );
531         let legacy_ctx = TrustyKekContext::new(false, None, Some(OsRollbackVersion::Version(2)));
532         expect!(
533             legacy_ctx.is_err(),
534             "We should not be able to create a non legacy context with a OS Rollback version"
535         );
536         let legacy_ctx = TrustyKekContext::new(false, Some(KdfVersion::Best), None);
537         expect!(
538             legacy_ctx.is_err(),
539             "We should not be able to create a non legacy context without OS rollback version"
540         );
541         let legacy_ctx = TrustyKekContext::new(false, None, None);
542         expect!(legacy_ctx.is_ok(), "Couldn't create legacy context");
543     }
544 }
545