• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021, 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 //! Implements safe wrappers around the public API of libopen-dice.
16 //! ## Example:
17 //! ```
18 //! use diced_open_dice_cbor as dice;
19 //!
20 //! let context = dice::dice::OpenDiceCborContext::new()
21 //! let parent_cdi_attest = [1u8, dice::CDI_SIZE];
22 //! let parent_cdi_seal = [2u8, dice::CDI_SIZE];
23 //! let input_values = dice::InputValuesOwned {
24 //!     code_hash: [3u8, dice::HASH_SIZE],
25 //!     config: dice::ConfigOwned::Descriptor("My descriptor".as_bytes().to_vec()),
26 //!     authority_hash: [0u8, dice::HASH_SIZE],
27 //!     mode: dice::Mode::Normal,
28 //!     hidden: [0u8, dice::HIDDEN_SIZE],
29 //! };
30 //! let (cdi_attest, cdi_seal, cert_chain) = context
31 //!     .main_flow(&parent_cdi_attest, &parent_cdi_seal, &input_values)?;
32 //! ```
33 
34 use keystore2_crypto::{zvec, ZVec};
35 use open_dice_bcc_bindgen::BccMainFlow;
36 use open_dice_cbor_bindgen::{
37     DiceConfigType, DiceDeriveCdiCertificateId, DiceDeriveCdiPrivateKeySeed,
38     DiceGenerateCertificate, DiceHash, DiceInputValues, DiceKdf, DiceKeypairFromSeed, DiceMainFlow,
39     DiceMode, DiceResult, DiceSign, DiceVerify, DICE_CDI_SIZE, DICE_HASH_SIZE, DICE_HIDDEN_SIZE,
40     DICE_ID_SIZE, DICE_INLINE_CONFIG_SIZE, DICE_PRIVATE_KEY_SEED_SIZE, DICE_PRIVATE_KEY_SIZE,
41     DICE_PUBLIC_KEY_SIZE, DICE_SIGNATURE_SIZE,
42 };
43 use open_dice_cbor_bindgen::{
44     DiceConfigType_kDiceConfigTypeDescriptor as DICE_CONFIG_TYPE_DESCRIPTOR,
45     DiceConfigType_kDiceConfigTypeInline as DICE_CONFIG_TYPE_INLINE,
46     DiceMode_kDiceModeDebug as DICE_MODE_DEBUG,
47     DiceMode_kDiceModeMaintenance as DICE_MODE_RECOVERY,
48     DiceMode_kDiceModeNormal as DICE_MODE_NORMAL,
49     DiceMode_kDiceModeNotInitialized as DICE_MODE_NOT_CONFIGURED,
50     DiceResult_kDiceResultBufferTooSmall as DICE_RESULT_BUFFER_TOO_SMALL,
51     DiceResult_kDiceResultInvalidInput as DICE_RESULT_INVALID_INPUT,
52     DiceResult_kDiceResultOk as DICE_RESULT_OK,
53     DiceResult_kDiceResultPlatformError as DICE_RESULT_PLATFORM_ERROR,
54 };
55 use std::ffi::{c_void, NulError};
56 
57 /// The size of a DICE hash.
58 pub const HASH_SIZE: usize = DICE_HASH_SIZE as usize;
59 /// The size of the DICE hidden value.
60 pub const HIDDEN_SIZE: usize = DICE_HIDDEN_SIZE as usize;
61 /// The size of a DICE inline config.
62 pub const INLINE_CONFIG_SIZE: usize = DICE_INLINE_CONFIG_SIZE as usize;
63 /// The size of a private key seed.
64 pub const PRIVATE_KEY_SEED_SIZE: usize = DICE_PRIVATE_KEY_SEED_SIZE as usize;
65 /// The size of a CDI.
66 pub const CDI_SIZE: usize = DICE_CDI_SIZE as usize;
67 /// The size of an ID.
68 pub const ID_SIZE: usize = DICE_ID_SIZE as usize;
69 /// The size of a private key.
70 pub const PRIVATE_KEY_SIZE: usize = DICE_PRIVATE_KEY_SIZE as usize;
71 /// The size of a public key.
72 pub const PUBLIC_KEY_SIZE: usize = DICE_PUBLIC_KEY_SIZE as usize;
73 /// The size of a signature.
74 pub const SIGNATURE_SIZE: usize = DICE_SIGNATURE_SIZE as usize;
75 
76 /// Open dice wrapper error type.
77 #[derive(Debug, thiserror::Error, PartialEq)]
78 pub enum Error {
79     /// The libopen-dice backend reported InvalidInput.
80     #[error("Open dice backend: Invalid input")]
81     InvalidInput,
82     /// The libopen-dice backend reported BufferTooSmall.
83     #[error("Open dice backend: Buffer too small")]
84     BufferTooSmall,
85     /// The libopen-dice backend reported PlatformError.
86     #[error("Open dice backend: Platform error")]
87     PlatformError,
88     /// The libopen-dice backend reported an error that is outside of the defined range of errors.
89     /// The returned error code is embedded in this value.
90     #[error("Open dice backend returned an unexpected error code: {0:?}")]
91     Unexpected(u32),
92 
93     /// The allocation of a ZVec failed. Most likely due to a failure during the call to mlock.
94     #[error("ZVec allocation failed")]
95     ZVec(#[from] zvec::Error),
96 
97     /// Functions that have to convert str to CString may fail if the string has an interior
98     /// nul byte.
99     #[error("Input string has an interior nul byte.")]
100     CStrNulError(#[from] NulError),
101 }
102 
103 /// Open dice result type.
104 pub type Result<T> = std::result::Result<T, Error>;
105 
106 impl From<DiceResult> for Error {
from(result: DiceResult) -> Self107     fn from(result: DiceResult) -> Self {
108         match result {
109             DICE_RESULT_INVALID_INPUT => Error::InvalidInput,
110             DICE_RESULT_BUFFER_TOO_SMALL => Error::BufferTooSmall,
111             DICE_RESULT_PLATFORM_ERROR => Error::PlatformError,
112             r => Error::Unexpected(r),
113         }
114     }
115 }
116 
check_result(result: DiceResult) -> Result<()>117 fn check_result(result: DiceResult) -> Result<()> {
118     if result == DICE_RESULT_OK {
119         Ok(())
120     } else {
121         Err(result.into())
122     }
123 }
124 
125 /// Configuration descriptor for dice input values.
126 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
127 pub enum Config<'a> {
128     /// A reference to an inline descriptor.
129     Inline(&'a [u8; INLINE_CONFIG_SIZE]),
130     /// A reference to a free form descriptor that will be hashed by the implementation.
131     Descriptor(&'a [u8]),
132 }
133 
134 enum ConfigOwned {
135     Inline([u8; INLINE_CONFIG_SIZE]),
136     Descriptor(Vec<u8>),
137 }
138 
139 impl Config<'_> {
get_type(&self) -> DiceConfigType140     fn get_type(&self) -> DiceConfigType {
141         match self {
142             Self::Inline(_) => DICE_CONFIG_TYPE_INLINE,
143             Self::Descriptor(_) => DICE_CONFIG_TYPE_DESCRIPTOR,
144         }
145     }
146 
get_inline(&self) -> [u8; INLINE_CONFIG_SIZE]147     fn get_inline(&self) -> [u8; INLINE_CONFIG_SIZE] {
148         match self {
149             Self::Inline(inline) => **inline,
150             _ => [0u8; INLINE_CONFIG_SIZE],
151         }
152     }
153 
get_descriptor_as_ptr(&self) -> *const u8154     fn get_descriptor_as_ptr(&self) -> *const u8 {
155         match self {
156             Self::Descriptor(descriptor) => descriptor.as_ptr(),
157             _ => std::ptr::null(),
158         }
159     }
160 
get_descriptor_size(&self) -> usize161     fn get_descriptor_size(&self) -> usize {
162         match self {
163             Self::Descriptor(descriptor) => descriptor.len(),
164             _ => 0,
165         }
166     }
167 }
168 
169 impl From<Config<'_>> for ConfigOwned {
from(config: Config) -> Self170     fn from(config: Config) -> Self {
171         match config {
172             Config::Inline(inline) => ConfigOwned::Inline(*inline),
173             Config::Descriptor(descriptor) => ConfigOwned::Descriptor(descriptor.to_owned()),
174         }
175     }
176 }
177 
178 /// DICE modes as defined here:
179 /// https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md#mode-value-details
180 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
181 pub enum Mode {
182     /// See documentation linked above.
183     NotConfigured = 0,
184     /// See documentation linked above.
185     Normal = 1,
186     /// See documentation linked above.
187     Debug = 2,
188     /// See documentation linked above.
189     Recovery = 3,
190 }
191 
192 impl Mode {
get_internal(&self) -> DiceMode193     fn get_internal(&self) -> DiceMode {
194         match self {
195             Self::NotConfigured => DICE_MODE_NOT_CONFIGURED,
196             Self::Normal => DICE_MODE_NORMAL,
197             Self::Debug => DICE_MODE_DEBUG,
198             Self::Recovery => DICE_MODE_RECOVERY,
199         }
200     }
201 }
202 
203 /// This trait allows API users to supply DICE input values without copying.
204 pub trait InputValues {
205     /// Returns the code hash.
code_hash(&self) -> &[u8; HASH_SIZE]206     fn code_hash(&self) -> &[u8; HASH_SIZE];
207     /// Returns the config.
config(&self) -> Config208     fn config(&self) -> Config;
209     /// Returns the authority hash.
authority_hash(&self) -> &[u8; HASH_SIZE]210     fn authority_hash(&self) -> &[u8; HASH_SIZE];
211     /// Returns the authority descriptor.
authority_descriptor(&self) -> Option<&[u8]>212     fn authority_descriptor(&self) -> Option<&[u8]>;
213     /// Returns the mode.
mode(&self) -> Mode214     fn mode(&self) -> Mode;
215     /// Returns the hidden value.
hidden(&self) -> &[u8; HIDDEN_SIZE]216     fn hidden(&self) -> &[u8; HIDDEN_SIZE];
217 }
218 
219 /// An owning convenience type implementing `InputValues`.
220 pub struct InputValuesOwned {
221     code_hash: [u8; HASH_SIZE],
222     config: ConfigOwned,
223     authority_hash: [u8; HASH_SIZE],
224     authority_descriptor: Option<Vec<u8>>,
225     mode: Mode,
226     hidden: [u8; HIDDEN_SIZE],
227 }
228 
229 impl InputValuesOwned {
230     /// Construct a new instance of InputValuesOwned.
new( code_hash: [u8; HASH_SIZE], config: Config, authority_hash: [u8; HASH_SIZE], authority_descriptor: Option<Vec<u8>>, mode: Mode, hidden: [u8; HIDDEN_SIZE], ) -> Self231     pub fn new(
232         code_hash: [u8; HASH_SIZE],
233         config: Config,
234         authority_hash: [u8; HASH_SIZE],
235         authority_descriptor: Option<Vec<u8>>,
236         mode: Mode,
237         hidden: [u8; HIDDEN_SIZE],
238     ) -> Self {
239         Self {
240             code_hash,
241             config: config.into(),
242             authority_hash,
243             authority_descriptor,
244             mode,
245             hidden,
246         }
247     }
248 }
249 
250 impl InputValues for InputValuesOwned {
code_hash(&self) -> &[u8; HASH_SIZE]251     fn code_hash(&self) -> &[u8; HASH_SIZE] {
252         &self.code_hash
253     }
config(&self) -> Config254     fn config(&self) -> Config {
255         match &self.config {
256             ConfigOwned::Inline(inline) => Config::Inline(inline),
257             ConfigOwned::Descriptor(descriptor) => Config::Descriptor(descriptor.as_slice()),
258         }
259     }
authority_hash(&self) -> &[u8; HASH_SIZE]260     fn authority_hash(&self) -> &[u8; HASH_SIZE] {
261         &self.authority_hash
262     }
authority_descriptor(&self) -> Option<&[u8]>263     fn authority_descriptor(&self) -> Option<&[u8]> {
264         self.authority_descriptor.as_deref()
265     }
mode(&self) -> Mode266     fn mode(&self) -> Mode {
267         self.mode
268     }
hidden(&self) -> &[u8; HIDDEN_SIZE]269     fn hidden(&self) -> &[u8; HIDDEN_SIZE] {
270         &self.hidden
271     }
272 }
273 
call_with_input_values<T: InputValues + ?Sized, F, R>(input_values: &T, f: F) -> Result<R> where F: FnOnce(*const DiceInputValues) -> Result<R>,274 fn call_with_input_values<T: InputValues + ?Sized, F, R>(input_values: &T, f: F) -> Result<R>
275 where
276     F: FnOnce(*const DiceInputValues) -> Result<R>,
277 {
278     let input_values = DiceInputValues {
279         code_hash: *input_values.code_hash(),
280         code_descriptor: std::ptr::null(),
281         code_descriptor_size: 0,
282         config_type: input_values.config().get_type(),
283         config_value: input_values.config().get_inline(),
284         config_descriptor: input_values.config().get_descriptor_as_ptr(),
285         config_descriptor_size: input_values.config().get_descriptor_size(),
286         authority_hash: *input_values.authority_hash(),
287         authority_descriptor: input_values
288             .authority_descriptor()
289             .map_or_else(std::ptr::null, <[u8]>::as_ptr),
290         authority_descriptor_size: input_values.authority_descriptor().map_or(0, <[u8]>::len),
291         mode: input_values.mode().get_internal(),
292         hidden: *input_values.hidden(),
293     };
294 
295     f(&input_values as *const DiceInputValues)
296 }
297 
298 /// Multiple of the open dice function required preallocated output buffer
299 /// which may be too small, this function implements the retry logic to handle
300 /// too small buffer allocations.
301 /// The callback `F` must expect a mutable reference to a buffer and a size hint
302 /// field. The callback is called repeatedly as long as it returns
303 /// `Err(Error::BufferTooSmall)`. If the size hint remains 0, the buffer size is
304 /// doubled with each iteration. If the size hint is set by the callback, the buffer
305 /// will be set to accommodate at least this many bytes.
306 /// If the callback returns `Ok(())`, the buffer is truncated to the size hint
307 /// exactly.
308 /// The function panics if the callback returns `Ok(())` and the size hint is
309 /// larger than the buffer size.
retry_while_adjusting_output_buffer<F>(mut f: F) -> Result<Vec<u8>> where F: FnMut(&mut Vec<u8>, &mut usize) -> Result<()>,310 fn retry_while_adjusting_output_buffer<F>(mut f: F) -> Result<Vec<u8>>
311 where
312     F: FnMut(&mut Vec<u8>, &mut usize) -> Result<()>,
313 {
314     let mut buffer = vec![0; INITIAL_OUT_BUFFER_SIZE];
315     let mut actual_size: usize = 0;
316     loop {
317         match f(&mut buffer, &mut actual_size) {
318             // If Error::BufferTooSmall was returned, the allocated certificate
319             // buffer was to small for the output. So the buffer is resized to the actual
320             // size, and a second attempt is made with the new buffer.
321             Err(Error::BufferTooSmall) => {
322                 let new_size = if actual_size == 0 {
323                     // Due to an off spec implementation of open dice cbor, actual size
324                     // does not return the required size if the buffer was too small. So
325                     // we have to try and approach it gradually.
326                     buffer.len() * 2
327                 } else {
328                     actual_size
329                 };
330                 buffer.resize(new_size, 0);
331                 continue;
332             }
333             Err(e) => return Err(e),
334             Ok(()) => {
335                 if actual_size > buffer.len() {
336                     panic!(
337                         "actual_size larger than buffer size: open-dice function
338                          may have written past the end of the buffer."
339                     );
340                 }
341                 // Truncate the certificate buffer to the actual size because it may be
342                 // smaller than the original allocation.
343                 buffer.truncate(actual_size);
344                 return Ok(buffer);
345             }
346         }
347     }
348 }
349 
350 /// Some libopen-dice variants use a context. Developers that want to customize these
351 /// bindings may want to implement their own Context factory that creates a context
352 /// useable by their preferred backend.
353 pub trait Context {
354     /// # Safety
355     /// The return value of get_context is passed to any open dice function.
356     /// Implementations must explain why the context pointer returned is safe
357     /// to be used by the open dice library.
get_context(&mut self) -> *mut c_void358     unsafe fn get_context(&mut self) -> *mut c_void;
359 }
360 
361 impl<T: Context + Send> ContextImpl for T {}
362 
363 /// This represents a context for the open dice library. The wrapped open dice instance, which
364 /// is based on boringssl and cbor, does not use a context, so that this type is empty.
365 #[derive(Default)]
366 pub struct OpenDiceCborContext();
367 
368 impl OpenDiceCborContext {
369     /// Construct a new instance of OpenDiceCborContext.
new() -> Self370     pub fn new() -> Self {
371         Default::default()
372     }
373 }
374 
375 impl Context for OpenDiceCborContext {
get_context(&mut self) -> *mut c_void376     unsafe fn get_context(&mut self) -> *mut c_void {
377         // # Safety
378         // The open dice cbor implementation does not use a context. It is safe
379         // to return NULL.
380         std::ptr::null_mut()
381     }
382 }
383 
384 /// Type alias for ZVec indicating that it holds a CDI_ATTEST secret.
385 pub type CdiAttest = ZVec;
386 
387 /// Type alias for ZVec indicating that it holds a CDI_SEAL secret.
388 pub type CdiSeal = ZVec;
389 
390 /// Type alias for Vec<u8> indicating that it hold a DICE certificate.
391 pub type Cert = Vec<u8>;
392 
393 /// Type alias for Vec<u8> indicating that it holds a BCC certificate chain.
394 pub type Bcc = Vec<u8>;
395 
396 const INITIAL_OUT_BUFFER_SIZE: usize = 1024;
397 
398 /// ContextImpl is a mixin trait that implements the safe wrappers around the open dice
399 /// library calls. Implementations must implement Context::get_context(). As of
400 /// this writing, the only implementation is OpenDiceCborContext, which returns NULL.
401 pub trait ContextImpl: Context + Send {
402     /// Safe wrapper around open-dice DiceDeriveCdiPrivateKeySeed, see open dice
403     /// documentation for details.
derive_cdi_private_key_seed(&mut self, cdi_attest: &[u8; CDI_SIZE]) -> Result<ZVec>404     fn derive_cdi_private_key_seed(&mut self, cdi_attest: &[u8; CDI_SIZE]) -> Result<ZVec> {
405         let mut seed = ZVec::new(PRIVATE_KEY_SEED_SIZE)?;
406         // SAFETY:
407         // * The first context argument may be NULL and is unused by the wrapped
408         //   implementation.
409         // * The second argument is expected to be a const array of size CDI_SIZE.
410         // * The third argument is expected to be a non const array of size
411         //   PRIVATE_KEY_SEED_SIZE which is fulfilled if the call to ZVec::new above
412         //   succeeds.
413         // * No pointers are expected to be valid beyond the scope of the function
414         //   call.
415         check_result(unsafe {
416             DiceDeriveCdiPrivateKeySeed(self.get_context(), cdi_attest.as_ptr(), seed.as_mut_ptr())
417         })?;
418         Ok(seed)
419     }
420 
421     /// Safe wrapper around open-dice DiceDeriveCdiCertificateId, see open dice
422     /// documentation for details.
derive_cdi_certificate_id(&mut self, cdi_public_key: &[u8]) -> Result<ZVec>423     fn derive_cdi_certificate_id(&mut self, cdi_public_key: &[u8]) -> Result<ZVec> {
424         let mut id = ZVec::new(ID_SIZE)?;
425         // SAFETY:
426         // * The first context argument may be NULL and is unused by the wrapped
427         //   implementation.
428         // * The second argument is expected to be a const array with a size given by the
429         //   third argument.
430         // * The fourth argument is expected to be a non const array of size
431         //   ID_SIZE which is fulfilled if the call to ZVec::new above succeeds.
432         // * No pointers are expected to be valid beyond the scope of the function
433         //   call.
434         check_result(unsafe {
435             DiceDeriveCdiCertificateId(
436                 self.get_context(),
437                 cdi_public_key.as_ptr(),
438                 cdi_public_key.len(),
439                 id.as_mut_ptr(),
440             )
441         })?;
442         Ok(id)
443     }
444 
445     /// Safe wrapper around open-dice DiceMainFlow, see open dice
446     /// documentation for details.
447     /// Returns a tuple of:
448     ///  * The next attestation CDI,
449     ///  * the next seal CDI, and
450     ///  * the next attestation certificate.
451     /// `(next_attest_cdi, next_seal_cdi, next_attestation_cert)`
main_flow<T: InputValues + ?Sized>( &mut self, current_cdi_attest: &[u8; CDI_SIZE], current_cdi_seal: &[u8; CDI_SIZE], input_values: &T, ) -> Result<(CdiAttest, CdiSeal, Cert)>452     fn main_flow<T: InputValues + ?Sized>(
453         &mut self,
454         current_cdi_attest: &[u8; CDI_SIZE],
455         current_cdi_seal: &[u8; CDI_SIZE],
456         input_values: &T,
457     ) -> Result<(CdiAttest, CdiSeal, Cert)> {
458         let mut next_attest = CdiAttest::new(CDI_SIZE)?;
459         let mut next_seal = CdiSeal::new(CDI_SIZE)?;
460 
461         // SAFETY (DiceMainFlow):
462         // * The first context argument may be NULL and is unused by the wrapped
463         //   implementation.
464         // * The second argument and the third argument are const arrays of size CDI_SIZE.
465         //   This is fulfilled as per the definition of the arguments `current_cdi_attest`
466         //   and `current_cdi_seal.
467         // * The fourth argument is a pointer to `DiceInputValues`. It, and its indirect
468         //   references must be valid for the duration of the function call which
469         //   is guaranteed by `call_with_input_values` which puts `DiceInputValues`
470         //   on the stack and initializes it from the `input_values` argument which
471         //   implements the `InputValues` trait.
472         // * The fifth and sixth argument are the length of and the pointer to the
473         //   allocated certificate buffer respectively. They are used to return
474         //   the generated certificate.
475         // * The seventh argument is a pointer to a mutable usize object. It is
476         //   used to return the actual size of the output certificate.
477         // * The eighth argument and the ninth argument are pointers to mutable buffers of size
478         //   CDI_SIZE. This is fulfilled if the allocation above succeeded.
479         // * No pointers are expected to be valid beyond the scope of the function
480         //   call.
481         call_with_input_values(input_values, |input_values| {
482             let cert = retry_while_adjusting_output_buffer(|cert, actual_size| {
483                 check_result(unsafe {
484                     DiceMainFlow(
485                         self.get_context(),
486                         current_cdi_attest.as_ptr(),
487                         current_cdi_seal.as_ptr(),
488                         input_values,
489                         cert.len(),
490                         cert.as_mut_ptr(),
491                         actual_size as *mut _,
492                         next_attest.as_mut_ptr(),
493                         next_seal.as_mut_ptr(),
494                     )
495                 })
496             })?;
497             Ok((next_attest, next_seal, cert))
498         })
499     }
500 
501     /// Safe wrapper around open-dice DiceHash, see open dice
502     /// documentation for details.
hash(&mut self, input: &[u8]) -> Result<Vec<u8>>503     fn hash(&mut self, input: &[u8]) -> Result<Vec<u8>> {
504         let mut output: Vec<u8> = vec![0; HASH_SIZE];
505 
506         // SAFETY:
507         // * The first context argument may be NULL and is unused by the wrapped
508         //   implementation.
509         // * The second argument and the third argument are the pointer to and length of the given
510         //   input buffer respectively.
511         // * The fourth argument must be a pointer to a mutable buffer of size HASH_SIZE
512         //   which is fulfilled by the allocation above.
513         check_result(unsafe {
514             DiceHash(self.get_context(), input.as_ptr(), input.len(), output.as_mut_ptr())
515         })?;
516         Ok(output)
517     }
518 
519     /// Safe wrapper around open-dice DiceKdf, see open dice
520     /// documentation for details.
kdf(&mut self, length: usize, input_key: &[u8], salt: &[u8], info: &[u8]) -> Result<ZVec>521     fn kdf(&mut self, length: usize, input_key: &[u8], salt: &[u8], info: &[u8]) -> Result<ZVec> {
522         let mut output = ZVec::new(length)?;
523 
524         // SAFETY:
525         // * The first context argument may be NULL and is unused by the wrapped
526         //   implementation.
527         // * The second argument is primitive.
528         // * The third argument and the fourth argument are the pointer to and length of the given
529         //   input key.
530         // * The fifth argument and the sixth argument are the pointer to and length of the given
531         //   salt.
532         // * The seventh argument and the eighth argument are the pointer to and length of the
533         //   given info field.
534         // * The ninth argument is a pointer to the output buffer which must have the
535         //   length given by the `length` argument (see second argument). This is
536         //   fulfilled if the allocation of `output` succeeds.
537         // * All pointers must be valid for the duration of the function call, but not
538         //   longer.
539         check_result(unsafe {
540             DiceKdf(
541                 self.get_context(),
542                 length,
543                 input_key.as_ptr(),
544                 input_key.len(),
545                 salt.as_ptr(),
546                 salt.len(),
547                 info.as_ptr(),
548                 info.len(),
549                 output.as_mut_ptr(),
550             )
551         })?;
552         Ok(output)
553     }
554 
555     /// Safe wrapper around open-dice DiceKeyPairFromSeed, see open dice
556     /// documentation for details.
keypair_from_seed(&mut self, seed: &[u8; PRIVATE_KEY_SEED_SIZE]) -> Result<(Vec<u8>, ZVec)>557     fn keypair_from_seed(&mut self, seed: &[u8; PRIVATE_KEY_SEED_SIZE]) -> Result<(Vec<u8>, ZVec)> {
558         let mut private_key = ZVec::new(PRIVATE_KEY_SIZE)?;
559         let mut public_key = vec![0u8; PUBLIC_KEY_SIZE];
560 
561         // SAFETY:
562         // * The first context argument may be NULL and is unused by the wrapped
563         //   implementation.
564         // * The second argument is a pointer to a const buffer of size `PRIVATE_KEY_SEED_SIZE`
565         //   fulfilled by the definition of the argument.
566         // * The third argument and the fourth argument are mutable buffers of size
567         //   `PRIVATE_KEY_SIZE` and `PUBLIC_KEY_SIZE` respectively. This is fulfilled by the
568         //   allocations above.
569         // * All pointers must be valid for the duration of the function call but not beyond.
570         check_result(unsafe {
571             DiceKeypairFromSeed(
572                 self.get_context(),
573                 seed.as_ptr(),
574                 public_key.as_mut_ptr(),
575                 private_key.as_mut_ptr(),
576             )
577         })?;
578         Ok((public_key, private_key))
579     }
580 
581     /// Safe wrapper around open-dice DiceSign, see open dice
582     /// documentation for details.
sign(&mut self, message: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE]) -> Result<Vec<u8>>583     fn sign(&mut self, message: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE]) -> Result<Vec<u8>> {
584         let mut signature = vec![0u8; SIGNATURE_SIZE];
585 
586         // SAFETY:
587         // * The first context argument may be NULL and is unused by the wrapped
588         //   implementation.
589         // * The second argument and the third argument are the pointer to and length of the given
590         //   message buffer.
591         // * The fourth argument is a const buffer of size `PRIVATE_KEY_SIZE`. This is fulfilled
592         //   by the definition of `private key`.
593         // * The fifth argument is mutable buffer of size `SIGNATURE_SIZE`. This is fulfilled
594         //   by the allocation above.
595         // * All pointers must be valid for the duration of the function call but not beyond.
596         check_result(unsafe {
597             DiceSign(
598                 self.get_context(),
599                 message.as_ptr(),
600                 message.len(),
601                 private_key.as_ptr(),
602                 signature.as_mut_ptr(),
603             )
604         })?;
605         Ok(signature)
606     }
607 
608     /// Safe wrapper around open-dice DiceVerify, see open dice
609     /// documentation for details.
verify( &mut self, message: &[u8], signature: &[u8; SIGNATURE_SIZE], public_key: &[u8; PUBLIC_KEY_SIZE], ) -> Result<()>610     fn verify(
611         &mut self,
612         message: &[u8],
613         signature: &[u8; SIGNATURE_SIZE],
614         public_key: &[u8; PUBLIC_KEY_SIZE],
615     ) -> Result<()> {
616         // SAFETY:
617         // * The first context argument may be NULL and is unused by the wrapped
618         //   implementation.
619         // * The second argument and the third argument are the pointer to and length of the given
620         //   message buffer.
621         // * The fourth argument is a const buffer of size `SIGNATURE_SIZE`. This is fulfilled
622         //   by the definition of `signature`.
623         // * The fifth argument is a const buffer of size `PUBLIC_KEY_SIZE`. This is fulfilled
624         //   by the definition of `public_key`.
625         // * All pointers must be valid for the duration of the function call but not beyond.
626         check_result(unsafe {
627             DiceVerify(
628                 self.get_context(),
629                 message.as_ptr(),
630                 message.len(),
631                 signature.as_ptr(),
632                 public_key.as_ptr(),
633             )
634         })
635     }
636 
637     /// Safe wrapper around open-dice DiceGenerateCertificate, see open dice
638     /// documentation for details.
generate_certificate<T: InputValues>( &mut self, subject_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE], authority_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE], input_values: &T, ) -> Result<Vec<u8>>639     fn generate_certificate<T: InputValues>(
640         &mut self,
641         subject_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
642         authority_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
643         input_values: &T,
644     ) -> Result<Vec<u8>> {
645         // SAFETY (DiceMainFlow):
646         // * The first context argument may be NULL and is unused by the wrapped
647         //   implementation.
648         // * The second argument and the third argument are const arrays of size
649         //   `PRIVATE_KEY_SEED_SIZE`. This is fulfilled as per the definition of the arguments.
650         // * The fourth argument is a pointer to `DiceInputValues` it, and its indirect
651         //   references must be valid for the duration of the function call which
652         //   is guaranteed by `call_with_input_values` which puts `DiceInputValues`
653         //   on the stack and initializes it from the `input_values` argument which
654         //   implements the `InputValues` trait.
655         // * The fifth argument and the sixth argument are the length of and the pointer to the
656         //   allocated certificate buffer respectively. They are used to return
657         //   the generated certificate.
658         // * The seventh argument is a pointer to a mutable usize object. It is
659         //   used to return the actual size of the output certificate.
660         // * All pointers must be valid for the duration of the function call but not beyond.
661         call_with_input_values(input_values, |input_values| {
662             let cert = retry_while_adjusting_output_buffer(|cert, actual_size| {
663                 check_result(unsafe {
664                     DiceGenerateCertificate(
665                         self.get_context(),
666                         subject_private_key_seed.as_ptr(),
667                         authority_private_key_seed.as_ptr(),
668                         input_values,
669                         cert.len(),
670                         cert.as_mut_ptr(),
671                         actual_size as *mut _,
672                     )
673                 })
674             })?;
675             Ok(cert)
676         })
677     }
678 
679     /// Safe wrapper around open-dice BccDiceMainFlow, see open dice
680     /// documentation for details.
681     /// Returns a tuple of:
682     ///  * The next attestation CDI,
683     ///  * the next seal CDI, and
684     ///  * the next bcc adding the new certificate to the given bcc.
685     /// `(next_attest_cdi, next_seal_cdi, next_bcc)`
bcc_main_flow<T: InputValues + ?Sized>( &mut self, current_cdi_attest: &[u8; CDI_SIZE], current_cdi_seal: &[u8; CDI_SIZE], bcc: &[u8], input_values: &T, ) -> Result<(CdiAttest, CdiSeal, Bcc)>686     fn bcc_main_flow<T: InputValues + ?Sized>(
687         &mut self,
688         current_cdi_attest: &[u8; CDI_SIZE],
689         current_cdi_seal: &[u8; CDI_SIZE],
690         bcc: &[u8],
691         input_values: &T,
692     ) -> Result<(CdiAttest, CdiSeal, Bcc)> {
693         let mut next_attest = CdiAttest::new(CDI_SIZE)?;
694         let mut next_seal = CdiSeal::new(CDI_SIZE)?;
695 
696         // SAFETY (BccMainFlow):
697         // * The first context argument may be NULL and is unused by the wrapped
698         //   implementation.
699         // * The second argument and the third argument are const arrays of size CDI_SIZE.
700         //   This is fulfilled as per the definition of the arguments `current_cdi_attest`
701         //   and `current_cdi_seal`.
702         // * The fourth argument and the fifth argument are the pointer to and size of the buffer
703         //   holding the current bcc.
704         // * The sixth argument is a pointer to `DiceInputValues` it, and its indirect
705         //   references must be valid for the duration of the function call which
706         //   is guaranteed by `call_with_input_values` which puts `DiceInputValues`
707         //   on the stack and initializes it from the `input_values` argument which
708         //   implements the `InputValues` trait.
709         // * The seventh argument and the eighth argument are the length of and the pointer to the
710         //   allocated certificate buffer respectively. They are used to return the generated
711         //   certificate.
712         // * The ninth argument is a pointer to a mutable usize object. It is
713         //   used to return the actual size of the output certificate.
714         // * The tenth argument and the eleventh argument are pointers to mutable buffers of
715         //   size CDI_SIZE. This is fulfilled if the allocation above succeeded.
716         // * No pointers are expected to be valid beyond the scope of the function
717         //   call.
718         call_with_input_values(input_values, |input_values| {
719             let next_bcc = retry_while_adjusting_output_buffer(|next_bcc, actual_size| {
720                 check_result(unsafe {
721                     BccMainFlow(
722                         self.get_context(),
723                         current_cdi_attest.as_ptr(),
724                         current_cdi_seal.as_ptr(),
725                         bcc.as_ptr(),
726                         bcc.len(),
727                         input_values,
728                         next_bcc.len(),
729                         next_bcc.as_mut_ptr(),
730                         actual_size as *mut _,
731                         next_attest.as_mut_ptr(),
732                         next_seal.as_mut_ptr(),
733                     )
734                 })
735             })?;
736             Ok((next_attest, next_seal, next_bcc))
737         })
738     }
739 }
740 
741 /// This submodule provides additional support for the Boot Certificate Chain (BCC)
742 /// specification.
743 /// See https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
744 pub mod bcc {
745     use super::{check_result, retry_while_adjusting_output_buffer, Result};
746     use open_dice_bcc_bindgen::{
747         BccConfigValues, BccFormatConfigDescriptor, BCC_INPUT_COMPONENT_NAME,
748         BCC_INPUT_COMPONENT_VERSION, BCC_INPUT_RESETTABLE,
749     };
750     use std::ffi::CString;
751 
752     /// Safe wrapper around BccFormatConfigDescriptor, see open dice documentation for details.
format_config_descriptor( component_name: Option<&str>, component_version: Option<u64>, resettable: bool, ) -> Result<Vec<u8>>753     pub fn format_config_descriptor(
754         component_name: Option<&str>,
755         component_version: Option<u64>,
756         resettable: bool,
757     ) -> Result<Vec<u8>> {
758         let component_name = match component_name {
759             Some(n) => Some(CString::new(n)?),
760             None => None,
761         };
762         let input = BccConfigValues {
763             inputs: if component_name.is_some() { BCC_INPUT_COMPONENT_NAME } else { 0 }
764                 | if component_version.is_some() { BCC_INPUT_COMPONENT_VERSION } else { 0 }
765                 | if resettable { BCC_INPUT_RESETTABLE } else { 0 },
766             // SAFETY: The as_ref() in the line below is vital to keep the component_name object
767             //         alive. Removing as_ref will move the component_name and the pointer will
768             //         become invalid after this statement.
769             component_name: component_name.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
770             component_version: component_version.unwrap_or(0),
771         };
772 
773         // SAFETY:
774         // * The first argument is a pointer to the BccConfigValues input assembled above.
775         //   It and its indirections must be valid for the duration of the function call.
776         // * The second argument and the third argument are the length of and the pointer to the
777         //   allocated output buffer respectively. The buffer must be at least as long
778         //   as indicated by the size argument.
779         // * The forth argument is a pointer to the actual size returned by the function.
780         // * All pointers must be valid for the duration of the function call but not beyond.
781         retry_while_adjusting_output_buffer(|config_descriptor, actual_size| {
782             check_result(unsafe {
783                 BccFormatConfigDescriptor(
784                     &input as *const BccConfigValues,
785                     config_descriptor.len(),
786                     config_descriptor.as_mut_ptr(),
787                     actual_size as *mut _,
788                 )
789             })
790         })
791     }
792 }
793 
794 #[cfg(test)]
795 mod test {
796     use super::*;
797     use diced_sample_inputs::make_sample_bcc_and_cdis;
798     use std::convert::TryInto;
799 
800     static SEED_TEST_VECTOR: &[u8] = &[
801         0xfa, 0x3c, 0x2f, 0x58, 0x37, 0xf5, 0x8e, 0x96, 0x16, 0x09, 0xf5, 0x22, 0xa1, 0xf1, 0xba,
802         0xaa, 0x19, 0x95, 0x01, 0x79, 0x2e, 0x60, 0x56, 0xaf, 0xf6, 0x41, 0xe7, 0xff, 0x48, 0xf5,
803         0x3a, 0x08, 0x84, 0x8a, 0x98, 0x85, 0x6d, 0xf5, 0x69, 0x21, 0x03, 0xcd, 0x09, 0xc3, 0x28,
804         0xd6, 0x06, 0xa7, 0x57, 0xbd, 0x48, 0x4b, 0x0f, 0x79, 0x0f, 0xf8, 0x2f, 0xf0, 0x0a, 0x41,
805         0x94, 0xd8, 0x8c, 0xa8,
806     ];
807 
808     static CDI_ATTEST_TEST_VECTOR: &[u8] = &[
809         0xfa, 0x3c, 0x2f, 0x58, 0x37, 0xf5, 0x8e, 0x96, 0x16, 0x09, 0xf5, 0x22, 0xa1, 0xf1, 0xba,
810         0xaa, 0x19, 0x95, 0x01, 0x79, 0x2e, 0x60, 0x56, 0xaf, 0xf6, 0x41, 0xe7, 0xff, 0x48, 0xf5,
811         0x3a, 0x08,
812     ];
813     static CDI_PRIVATE_KEY_SEED_TEST_VECTOR: &[u8] = &[
814         0x5f, 0xcc, 0x8e, 0x1a, 0xd1, 0xc2, 0xb3, 0xe9, 0xfb, 0xe1, 0x68, 0xf0, 0xf6, 0x98, 0xfe,
815         0x0d, 0xee, 0xd4, 0xb5, 0x18, 0xcb, 0x59, 0x70, 0x2d, 0xee, 0x06, 0xe5, 0x70, 0xf1, 0x72,
816         0x02, 0x6e,
817     ];
818 
819     static PUB_KEY_TEST_VECTOR: &[u8] = &[
820         0x47, 0x42, 0x4b, 0xbd, 0xd7, 0x23, 0xb4, 0xcd, 0xca, 0xe2, 0x8e, 0xdc, 0x6b, 0xfc, 0x23,
821         0xc9, 0x21, 0x5c, 0x48, 0x21, 0x47, 0xee, 0x5b, 0xfa, 0xaf, 0x88, 0x9a, 0x52, 0xf1, 0x61,
822         0x06, 0x37,
823     ];
824     static PRIV_KEY_TEST_VECTOR: &[u8] = &[
825         0x5f, 0xcc, 0x8e, 0x1a, 0xd1, 0xc2, 0xb3, 0xe9, 0xfb, 0xe1, 0x68, 0xf0, 0xf6, 0x98, 0xfe,
826         0x0d, 0xee, 0xd4, 0xb5, 0x18, 0xcb, 0x59, 0x70, 0x2d, 0xee, 0x06, 0xe5, 0x70, 0xf1, 0x72,
827         0x02, 0x6e, 0x47, 0x42, 0x4b, 0xbd, 0xd7, 0x23, 0xb4, 0xcd, 0xca, 0xe2, 0x8e, 0xdc, 0x6b,
828         0xfc, 0x23, 0xc9, 0x21, 0x5c, 0x48, 0x21, 0x47, 0xee, 0x5b, 0xfa, 0xaf, 0x88, 0x9a, 0x52,
829         0xf1, 0x61, 0x06, 0x37,
830     ];
831 
832     static SIGNATURE_TEST_VECTOR: &[u8] = &[
833         0x44, 0xae, 0xcc, 0xe2, 0xb9, 0x96, 0x18, 0x39, 0x0e, 0x61, 0x0f, 0x53, 0x07, 0xbf, 0xf2,
834         0x32, 0x3d, 0x44, 0xd4, 0xf2, 0x07, 0x23, 0x30, 0x85, 0x32, 0x18, 0xd2, 0x69, 0xb8, 0x29,
835         0x3c, 0x26, 0xe6, 0x0d, 0x9c, 0xa5, 0xc2, 0x73, 0xcd, 0x8c, 0xb8, 0x3c, 0x3e, 0x5b, 0xfd,
836         0x62, 0x8d, 0xf6, 0xc4, 0x27, 0xa6, 0xe9, 0x11, 0x06, 0x5a, 0xb2, 0x2b, 0x64, 0xf7, 0xfc,
837         0xbb, 0xab, 0x4a, 0x0e,
838     ];
839 
840     #[test]
hash_derive_sign_verify()841     fn hash_derive_sign_verify() {
842         let mut ctx = OpenDiceCborContext::new();
843         let seed = ctx.hash("MySeedString".as_bytes()).unwrap();
844         assert_eq!(seed, SEED_TEST_VECTOR);
845         let cdi_attest = &seed[..CDI_SIZE];
846         assert_eq!(cdi_attest, CDI_ATTEST_TEST_VECTOR);
847         let cdi_private_key_seed =
848             ctx.derive_cdi_private_key_seed(cdi_attest.try_into().unwrap()).unwrap();
849         assert_eq!(&cdi_private_key_seed[..], CDI_PRIVATE_KEY_SEED_TEST_VECTOR);
850         let (pub_key, priv_key) =
851             ctx.keypair_from_seed(cdi_private_key_seed[..].try_into().unwrap()).unwrap();
852         assert_eq!(&pub_key, PUB_KEY_TEST_VECTOR);
853         assert_eq!(&priv_key[..], PRIV_KEY_TEST_VECTOR);
854         let mut signature =
855             ctx.sign("MyMessage".as_bytes(), priv_key[..].try_into().unwrap()).unwrap();
856         assert_eq!(&signature, SIGNATURE_TEST_VECTOR);
857         assert!(ctx
858             .verify(
859                 "MyMessage".as_bytes(),
860                 signature[..].try_into().unwrap(),
861                 pub_key[..].try_into().unwrap()
862             )
863             .is_ok());
864         assert!(ctx
865             .verify(
866                 "MyMessage_fail".as_bytes(),
867                 signature[..].try_into().unwrap(),
868                 pub_key[..].try_into().unwrap()
869             )
870             .is_err());
871         signature[0] += 1;
872         assert!(ctx
873             .verify(
874                 "MyMessage".as_bytes(),
875                 signature[..].try_into().unwrap(),
876                 pub_key[..].try_into().unwrap()
877             )
878             .is_err());
879     }
880 
881     static SAMPLE_CDI_ATTEST_TEST_VECTOR: &[u8] = &[
882         0x3e, 0x57, 0x65, 0x5d, 0x48, 0x02, 0xbd, 0x5c, 0x66, 0xcc, 0x1f, 0x0f, 0xbe, 0x5e, 0x32,
883         0xb6, 0x9e, 0x3d, 0x04, 0xaf, 0x00, 0x15, 0xbc, 0xdd, 0x1f, 0xbc, 0x59, 0xe4, 0xc3, 0x87,
884         0x95, 0x5e,
885     ];
886 
887     static SAMPLE_CDI_SEAL_TEST_VECTOR: &[u8] = &[
888         0x36, 0x1b, 0xd2, 0xb3, 0xc4, 0xda, 0x77, 0xb2, 0x9c, 0xba, 0x39, 0x53, 0x82, 0x93, 0xd9,
889         0xb8, 0x9f, 0x73, 0x2d, 0x27, 0x06, 0x15, 0xa8, 0xcb, 0x6d, 0x1d, 0xf2, 0xb1, 0x54, 0xbb,
890         0x62, 0xf1,
891     ];
892 
893     static SAMPLE_BCC_TEST_VECTOR: &[u8] = &[
894         0x84, 0xa5, 0x01, 0x01, 0x03, 0x27, 0x04, 0x02, 0x20, 0x06, 0x21, 0x58, 0x20, 0x3e, 0x85,
895         0xe5, 0x72, 0x75, 0x55, 0xe5, 0x1e, 0xe7, 0xf3, 0x35, 0x94, 0x8e, 0xbb, 0xbd, 0x74, 0x1e,
896         0x1d, 0xca, 0x49, 0x9c, 0x97, 0x39, 0x77, 0x06, 0xd3, 0xc8, 0x6e, 0x8b, 0xd7, 0x33, 0xf9,
897         0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x59, 0x01, 0x8a, 0xa9, 0x01, 0x78, 0x28, 0x34, 0x32,
898         0x64, 0x38, 0x38, 0x36, 0x34, 0x66, 0x39, 0x37, 0x62, 0x36, 0x35, 0x34, 0x37, 0x61, 0x35,
899         0x30, 0x63, 0x31, 0x65, 0x30, 0x61, 0x37, 0x34, 0x39, 0x66, 0x38, 0x65, 0x66, 0x38, 0x62,
900         0x38, 0x31, 0x65, 0x63, 0x36, 0x32, 0x61, 0x66, 0x02, 0x78, 0x28, 0x31, 0x66, 0x36, 0x39,
901         0x36, 0x66, 0x30, 0x37, 0x32, 0x35, 0x32, 0x66, 0x32, 0x39, 0x65, 0x39, 0x33, 0x66, 0x65,
902         0x34, 0x64, 0x65, 0x31, 0x39, 0x65, 0x65, 0x33, 0x32, 0x63, 0x64, 0x38, 0x31, 0x64, 0x63,
903         0x34, 0x30, 0x34, 0x65, 0x37, 0x36, 0x3a, 0x00, 0x47, 0x44, 0x50, 0x58, 0x40, 0x16, 0x48,
904         0xf2, 0x55, 0x53, 0x23, 0xdd, 0x15, 0x2e, 0x83, 0x38, 0xc3, 0x64, 0x38, 0x63, 0x26, 0x0f,
905         0xcf, 0x5b, 0xd1, 0x3a, 0xd3, 0x40, 0x3e, 0x23, 0xf8, 0x34, 0x4c, 0x6d, 0xa2, 0xbe, 0x25,
906         0x1c, 0xb0, 0x29, 0xe8, 0xc3, 0xfb, 0xb8, 0x80, 0xdc, 0xb1, 0xd2, 0xb3, 0x91, 0x4d, 0xd3,
907         0xfb, 0x01, 0x0f, 0xe4, 0xe9, 0x46, 0xa2, 0xc0, 0x26, 0x57, 0x5a, 0xba, 0x30, 0xf7, 0x15,
908         0x98, 0x14, 0x3a, 0x00, 0x47, 0x44, 0x53, 0x56, 0xa3, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x63,
909         0x41, 0x42, 0x4c, 0x3a, 0x00, 0x01, 0x11, 0x72, 0x01, 0x3a, 0x00, 0x01, 0x11, 0x73, 0xf6,
910         0x3a, 0x00, 0x47, 0x44, 0x52, 0x58, 0x40, 0x47, 0xae, 0x42, 0x27, 0x4c, 0xcb, 0x65, 0x4d,
911         0xee, 0x74, 0x2d, 0x05, 0x78, 0x2a, 0x08, 0x2a, 0xa5, 0xf0, 0xcf, 0xea, 0x3e, 0x60, 0xee,
912         0x97, 0x11, 0x4b, 0x5b, 0xe6, 0x05, 0x0c, 0xe8, 0x90, 0xf5, 0x22, 0xc4, 0xc6, 0x67, 0x7a,
913         0x22, 0x27, 0x17, 0xb3, 0x79, 0xcc, 0x37, 0x64, 0x5e, 0x19, 0x4f, 0x96, 0x37, 0x67, 0x3c,
914         0xd0, 0xc5, 0xed, 0x0f, 0xdd, 0xe7, 0x2e, 0x4f, 0x70, 0x97, 0x30, 0x3a, 0x00, 0x47, 0x44,
915         0x54, 0x58, 0x40, 0xf9, 0x00, 0x9d, 0xc2, 0x59, 0x09, 0xe0, 0xb6, 0x98, 0xbd, 0xe3, 0x97,
916         0x4a, 0xcb, 0x3c, 0xe7, 0x6b, 0x24, 0xc3, 0xe4, 0x98, 0xdd, 0xa9, 0x6a, 0x41, 0x59, 0x15,
917         0xb1, 0x23, 0xe6, 0xc8, 0xdf, 0xfb, 0x52, 0xb4, 0x52, 0xc1, 0xb9, 0x61, 0xdd, 0xbc, 0x5b,
918         0x37, 0x0e, 0x12, 0x12, 0xb2, 0xfd, 0xc1, 0x09, 0xb0, 0xcf, 0x33, 0x81, 0x4c, 0xc6, 0x29,
919         0x1b, 0x99, 0xea, 0xae, 0xfd, 0xaa, 0x0d, 0x3a, 0x00, 0x47, 0x44, 0x56, 0x41, 0x01, 0x3a,
920         0x00, 0x47, 0x44, 0x57, 0x58, 0x2d, 0xa5, 0x01, 0x01, 0x03, 0x27, 0x04, 0x81, 0x02, 0x20,
921         0x06, 0x21, 0x58, 0x20, 0xb1, 0x02, 0xcc, 0x2c, 0xb2, 0x6a, 0x3b, 0xe9, 0xc1, 0xd3, 0x95,
922         0x10, 0xa0, 0xe1, 0xff, 0x51, 0xde, 0x57, 0xd5, 0x65, 0x28, 0xfd, 0x7f, 0xeb, 0xd4, 0xca,
923         0x15, 0xf3, 0xca, 0xdf, 0x37, 0x88, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20, 0x58, 0x40,
924         0x58, 0xd8, 0x03, 0x24, 0x53, 0x60, 0x57, 0xa9, 0x09, 0xfa, 0xab, 0xdc, 0x57, 0x1e, 0xf0,
925         0xe5, 0x1e, 0x51, 0x6f, 0x9e, 0xa3, 0x42, 0xe6, 0x6a, 0x8c, 0xaa, 0xad, 0x08, 0x48, 0xde,
926         0x7f, 0x4f, 0x6e, 0x2f, 0x7f, 0x39, 0x6c, 0xa1, 0xf8, 0x42, 0x71, 0xfe, 0x17, 0x3d, 0xca,
927         0x31, 0x83, 0x92, 0xed, 0xbb, 0x40, 0xb8, 0x10, 0xe0, 0xf2, 0x5a, 0x99, 0x53, 0x38, 0x46,
928         0x33, 0x97, 0x78, 0x05, 0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x59, 0x01, 0x8a, 0xa9, 0x01,
929         0x78, 0x28, 0x31, 0x66, 0x36, 0x39, 0x36, 0x66, 0x30, 0x37, 0x32, 0x35, 0x32, 0x66, 0x32,
930         0x39, 0x65, 0x39, 0x33, 0x66, 0x65, 0x34, 0x64, 0x65, 0x31, 0x39, 0x65, 0x65, 0x33, 0x32,
931         0x63, 0x64, 0x38, 0x31, 0x64, 0x63, 0x34, 0x30, 0x34, 0x65, 0x37, 0x36, 0x02, 0x78, 0x28,
932         0x32, 0x35, 0x39, 0x34, 0x38, 0x39, 0x65, 0x36, 0x39, 0x37, 0x34, 0x38, 0x37, 0x30, 0x35,
933         0x64, 0x65, 0x33, 0x65, 0x32, 0x66, 0x34, 0x34, 0x32, 0x36, 0x37, 0x65, 0x61, 0x34, 0x39,
934         0x33, 0x38, 0x66, 0x66, 0x36, 0x61, 0x35, 0x37, 0x32, 0x35, 0x3a, 0x00, 0x47, 0x44, 0x50,
935         0x58, 0x40, 0xa4, 0x0c, 0xcb, 0xc1, 0xbf, 0xfa, 0xcc, 0xfd, 0xeb, 0xf4, 0xfc, 0x43, 0x83,
936         0x7f, 0x46, 0x8d, 0xd8, 0xd8, 0x14, 0xc1, 0x96, 0x14, 0x1f, 0x6e, 0xb3, 0xa0, 0xd9, 0x56,
937         0xb3, 0xbf, 0x2f, 0xfa, 0x88, 0x70, 0x11, 0x07, 0x39, 0xa4, 0xd2, 0xa9, 0x6b, 0x18, 0x28,
938         0xe8, 0x29, 0x20, 0x49, 0x0f, 0xbb, 0x8d, 0x08, 0x8c, 0xc6, 0x54, 0xe9, 0x71, 0xd2, 0x7e,
939         0xa4, 0xfe, 0x58, 0x7f, 0xd3, 0xc7, 0x3a, 0x00, 0x47, 0x44, 0x53, 0x56, 0xa3, 0x3a, 0x00,
940         0x01, 0x11, 0x71, 0x63, 0x41, 0x56, 0x42, 0x3a, 0x00, 0x01, 0x11, 0x72, 0x01, 0x3a, 0x00,
941         0x01, 0x11, 0x73, 0xf6, 0x3a, 0x00, 0x47, 0x44, 0x52, 0x58, 0x40, 0x93, 0x17, 0xe1, 0x11,
942         0x27, 0x59, 0xd0, 0xef, 0x75, 0x0b, 0x2b, 0x1c, 0x0f, 0x5f, 0x52, 0xc3, 0x29, 0x23, 0xb5,
943         0x2a, 0xe6, 0x12, 0x72, 0x6f, 0x39, 0x86, 0x65, 0x2d, 0xf2, 0xe4, 0xe7, 0xd0, 0xaf, 0x0e,
944         0xa7, 0x99, 0x16, 0x89, 0x97, 0x21, 0xf7, 0xdc, 0x89, 0xdc, 0xde, 0xbb, 0x94, 0x88, 0x1f,
945         0xda, 0xe2, 0xf3, 0xe0, 0x54, 0xf9, 0x0e, 0x29, 0xb1, 0xbd, 0xe1, 0x0c, 0x0b, 0xd7, 0xf6,
946         0x3a, 0x00, 0x47, 0x44, 0x54, 0x58, 0x40, 0xb2, 0x69, 0x05, 0x48, 0x56, 0xb5, 0xfa, 0x55,
947         0x6f, 0xac, 0x56, 0xd9, 0x02, 0x35, 0x2b, 0xaa, 0x4c, 0xba, 0x28, 0xdd, 0x82, 0x3a, 0x86,
948         0xf5, 0xd4, 0xc2, 0xf1, 0xf9, 0x35, 0x7d, 0xe4, 0x43, 0x13, 0xbf, 0xfe, 0xd3, 0x36, 0xd8,
949         0x1c, 0x12, 0x78, 0x5c, 0x9c, 0x3e, 0xf6, 0x66, 0xef, 0xab, 0x3d, 0x0f, 0x89, 0xa4, 0x6f,
950         0xc9, 0x72, 0xee, 0x73, 0x43, 0x02, 0x8a, 0xef, 0xbc, 0x05, 0x98, 0x3a, 0x00, 0x47, 0x44,
951         0x56, 0x41, 0x01, 0x3a, 0x00, 0x47, 0x44, 0x57, 0x58, 0x2d, 0xa5, 0x01, 0x01, 0x03, 0x27,
952         0x04, 0x81, 0x02, 0x20, 0x06, 0x21, 0x58, 0x20, 0x96, 0x6d, 0x96, 0x42, 0xda, 0x64, 0x51,
953         0xad, 0xfa, 0x00, 0xbc, 0xbc, 0x95, 0x8a, 0xb0, 0xb9, 0x76, 0x01, 0xe6, 0xbd, 0xc0, 0x26,
954         0x79, 0x26, 0xfc, 0x0f, 0x1d, 0x87, 0x65, 0xf1, 0xf3, 0x99, 0x3a, 0x00, 0x47, 0x44, 0x58,
955         0x41, 0x20, 0x58, 0x40, 0x10, 0x7f, 0x77, 0xad, 0x70, 0xbd, 0x52, 0x81, 0x28, 0x8d, 0x24,
956         0x81, 0xb4, 0x3f, 0x21, 0x68, 0x9f, 0xc3, 0x80, 0x68, 0x86, 0x55, 0xfb, 0x2e, 0x6d, 0x96,
957         0xe1, 0xe1, 0xb7, 0x28, 0x8d, 0x63, 0x85, 0xba, 0x2a, 0x01, 0x33, 0x87, 0x60, 0x63, 0xbb,
958         0x16, 0x3f, 0x2f, 0x3d, 0xf4, 0x2d, 0x48, 0x5b, 0x87, 0xed, 0xda, 0x34, 0xeb, 0x9c, 0x4d,
959         0x14, 0xac, 0x65, 0xf4, 0xfa, 0xef, 0x45, 0x0b, 0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x59,
960         0x01, 0x8f, 0xa9, 0x01, 0x78, 0x28, 0x32, 0x35, 0x39, 0x34, 0x38, 0x39, 0x65, 0x36, 0x39,
961         0x37, 0x34, 0x38, 0x37, 0x30, 0x35, 0x64, 0x65, 0x33, 0x65, 0x32, 0x66, 0x34, 0x34, 0x32,
962         0x36, 0x37, 0x65, 0x61, 0x34, 0x39, 0x33, 0x38, 0x66, 0x66, 0x36, 0x61, 0x35, 0x37, 0x32,
963         0x35, 0x02, 0x78, 0x28, 0x35, 0x64, 0x34, 0x65, 0x64, 0x37, 0x66, 0x34, 0x31, 0x37, 0x61,
964         0x39, 0x35, 0x34, 0x61, 0x31, 0x38, 0x31, 0x34, 0x30, 0x37, 0x62, 0x35, 0x38, 0x38, 0x35,
965         0x61, 0x66, 0x64, 0x37, 0x32, 0x61, 0x35, 0x62, 0x66, 0x34, 0x30, 0x64, 0x61, 0x36, 0x3a,
966         0x00, 0x47, 0x44, 0x50, 0x58, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
967         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
968         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
969         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
970         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x47, 0x44, 0x53,
971         0x58, 0x1a, 0xa3, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x67, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
972         0x64, 0x3a, 0x00, 0x01, 0x11, 0x72, 0x0c, 0x3a, 0x00, 0x01, 0x11, 0x73, 0xf6, 0x3a, 0x00,
973         0x47, 0x44, 0x52, 0x58, 0x40, 0x26, 0x1a, 0xbd, 0x26, 0xd8, 0x37, 0x8f, 0x4a, 0xf2, 0x9e,
974         0x49, 0x4d, 0x93, 0x23, 0xc4, 0x6e, 0x02, 0xda, 0xe0, 0x00, 0x02, 0xe7, 0xed, 0x29, 0xdf,
975         0x2b, 0xb3, 0x69, 0xf3, 0x55, 0x0e, 0x4c, 0x22, 0xdc, 0xcf, 0xf5, 0x92, 0xc9, 0xfa, 0x78,
976         0x98, 0xf1, 0x0e, 0x55, 0x5f, 0xf4, 0x45, 0xed, 0xc0, 0x0a, 0x72, 0x2a, 0x7a, 0x3a, 0xd2,
977         0xb1, 0xf7, 0x76, 0xfe, 0x2a, 0x6b, 0x7b, 0x2a, 0x53, 0x3a, 0x00, 0x47, 0x44, 0x54, 0x58,
978         0x40, 0x04, 0x25, 0x5d, 0x60, 0x5f, 0x5c, 0x45, 0x0d, 0xf2, 0x9a, 0x6e, 0x99, 0x30, 0x03,
979         0xb8, 0xd6, 0xe1, 0x99, 0x71, 0x1b, 0xf8, 0x44, 0xfa, 0xb5, 0x31, 0x79, 0x1c, 0x37, 0x68,
980         0x4e, 0x1d, 0xc0, 0x24, 0x74, 0x68, 0xf8, 0x80, 0x20, 0x3e, 0x44, 0xb1, 0x43, 0xd2, 0x9c,
981         0xfc, 0x12, 0x9e, 0x77, 0x0a, 0xde, 0x29, 0x24, 0xff, 0x2e, 0xfa, 0xc7, 0x10, 0xd5, 0x73,
982         0xd4, 0xc6, 0xdf, 0x62, 0x9f, 0x3a, 0x00, 0x47, 0x44, 0x56, 0x41, 0x01, 0x3a, 0x00, 0x47,
983         0x44, 0x57, 0x58, 0x2d, 0xa5, 0x01, 0x01, 0x03, 0x27, 0x04, 0x81, 0x02, 0x20, 0x06, 0x21,
984         0x58, 0x20, 0xdb, 0xe7, 0x5b, 0x3f, 0xa3, 0x42, 0xb0, 0x9c, 0xf8, 0x40, 0x8c, 0xb0, 0x9c,
985         0xf0, 0x0a, 0xaf, 0xdf, 0x6f, 0xe5, 0x09, 0x21, 0x11, 0x92, 0xe1, 0xf8, 0xc5, 0x09, 0x02,
986         0x3d, 0x1f, 0xb7, 0xc5, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20, 0x58, 0x40, 0xc4, 0xc1,
987         0xd7, 0x1c, 0x2d, 0x26, 0x89, 0x22, 0xcf, 0xa6, 0x99, 0x77, 0x30, 0x84, 0x86, 0x27, 0x59,
988         0x8f, 0xd8, 0x08, 0x75, 0xe0, 0xb2, 0xef, 0xf9, 0xfa, 0xa5, 0x40, 0x8c, 0xd3, 0xeb, 0xbb,
989         0xda, 0xf2, 0xc8, 0xae, 0x41, 0x22, 0x50, 0x9c, 0xe8, 0xb2, 0x9c, 0x9b, 0x3f, 0x8a, 0x78,
990         0x76, 0xab, 0xd0, 0xbe, 0xfc, 0xe4, 0x79, 0xcb, 0x1b, 0x2b, 0xaa, 0x4d, 0xdd, 0x15, 0x61,
991         0x42, 0x06,
992     ];
993 
994     // This test invokes make_sample_bcc_and_cdis and compares the result bitwise to the target
995     // vectors. The function uses main_flow, bcc_main_flow, format_config_descriptor,
996     // derive_cdi_private_key_seed, and keypair_from_seed. This test is sensitive to errors
997     // and changes in any of those functions.
998     #[test]
main_flow_and_bcc_main_flow()999     fn main_flow_and_bcc_main_flow() {
1000         let (cdi_attest, cdi_seal, bcc) = make_sample_bcc_and_cdis().unwrap();
1001         assert_eq!(&cdi_attest[..], SAMPLE_CDI_ATTEST_TEST_VECTOR);
1002         assert_eq!(&cdi_seal[..], SAMPLE_CDI_SEAL_TEST_VECTOR);
1003         assert_eq!(&bcc[..], SAMPLE_BCC_TEST_VECTOR);
1004     }
1005 
1006     static DERIVED_KEY_TEST_VECTOR: &[u8] = &[
1007         0x0e, 0xd6, 0x07, 0x0e, 0x1c, 0x38, 0x2c, 0x76, 0x13, 0xc6, 0x76, 0x25, 0x7e, 0x07, 0x6f,
1008         0xdb, 0x1d, 0xb1, 0x0f, 0x3f, 0xed, 0xc5, 0x2b, 0x95, 0xd1, 0x32, 0xf1, 0x63, 0x2f, 0x2a,
1009         0x01, 0x5e,
1010     ];
1011 
1012     #[test]
kdf()1013     fn kdf() {
1014         let mut ctx = OpenDiceCborContext::new();
1015         let derived_key = ctx
1016             .kdf(
1017                 PRIVATE_KEY_SEED_SIZE,
1018                 "myKey".as_bytes(),
1019                 "mySalt".as_bytes(),
1020                 "myInfo".as_bytes(),
1021             )
1022             .unwrap();
1023         assert_eq!(&derived_key[..], DERIVED_KEY_TEST_VECTOR);
1024     }
1025 
1026     static CERT_ID_TEST_VECTOR: &[u8] = &[
1027         0x7a, 0x36, 0x45, 0x2c, 0x02, 0xf6, 0x2b, 0xec, 0xf9, 0x80, 0x06, 0x75, 0x87, 0xa5, 0xc1,
1028         0x44, 0x0c, 0xd3, 0xc0, 0x6d,
1029     ];
1030 
1031     #[test]
derive_cdi_certificate_id()1032     fn derive_cdi_certificate_id() {
1033         let mut ctx = OpenDiceCborContext::new();
1034         let cert_id = ctx.derive_cdi_certificate_id("MyPubKey".as_bytes()).unwrap();
1035         assert_eq!(&cert_id[..], CERT_ID_TEST_VECTOR);
1036     }
1037 }
1038