blob: 7122ca5122ab29bc8aaadb6a77744930b86d8384 [file] [log] [blame]
Janis Danisevskis13356b22021-10-20 09:44:12 -07001// 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
34use keystore2_crypto::{zvec, ZVec};
Janis Danisevskis2cef73f2021-11-03 15:02:48 -070035use open_dice_bcc_bindgen::BccMainFlow;
Janis Danisevskis13356b22021-10-20 09:44:12 -070036use 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};
43use 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};
Janis Danisevskis2cef73f2021-11-03 15:02:48 -070055use std::ffi::{c_void, NulError};
Janis Danisevskis13356b22021-10-20 09:44:12 -070056
57/// The size of a DICE hash.
58pub const HASH_SIZE: usize = DICE_HASH_SIZE as usize;
59/// The size of the DICE hidden value.
60pub const HIDDEN_SIZE: usize = DICE_HIDDEN_SIZE as usize;
61/// The size of a DICE inline config.
62pub const INLINE_CONFIG_SIZE: usize = DICE_INLINE_CONFIG_SIZE as usize;
63/// The size of a private key seed.
64pub const PRIVATE_KEY_SEED_SIZE: usize = DICE_PRIVATE_KEY_SEED_SIZE as usize;
65/// The size of a CDI.
66pub const CDI_SIZE: usize = DICE_CDI_SIZE as usize;
67/// The size of an ID.
68pub const ID_SIZE: usize = DICE_ID_SIZE as usize;
69/// The size of a private key.
70pub const PRIVATE_KEY_SIZE: usize = DICE_PRIVATE_KEY_SIZE as usize;
71/// The size of a public key.
72pub const PUBLIC_KEY_SIZE: usize = DICE_PUBLIC_KEY_SIZE as usize;
73/// The size of a signature.
74pub const SIGNATURE_SIZE: usize = DICE_SIGNATURE_SIZE as usize;
75
76/// Open dice wrapper error type.
77#[derive(Debug, thiserror::Error, PartialEq)]
78pub 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),
Janis Danisevskis2cef73f2021-11-03 15:02:48 -070096
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),
Janis Danisevskis13356b22021-10-20 09:44:12 -0700101}
102
103/// Open dice result type.
104pub type Result<T> = std::result::Result<T, Error>;
105
106impl From<DiceResult> for Error {
107 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
117fn 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)]
127pub 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
134enum ConfigOwned {
135 Inline([u8; INLINE_CONFIG_SIZE]),
136 Descriptor(Vec<u8>),
137}
138
139impl Config<'_> {
140 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
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
154 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
161 fn get_descriptor_size(&self) -> usize {
162 match self {
163 Self::Descriptor(descriptor) => descriptor.len(),
164 _ => 0,
165 }
166 }
167}
168
169impl From<Config<'_>> for ConfigOwned {
170 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)]
181pub 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
192impl Mode {
193 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.
204pub trait InputValues {
205 /// Returns the code hash.
206 fn code_hash(&self) -> &[u8; HASH_SIZE];
207 /// Returns the config.
208 fn config(&self) -> Config;
209 /// Returns the authority hash.
210 fn authority_hash(&self) -> &[u8; HASH_SIZE];
211 /// Returns the authority descriptor.
212 fn authority_descriptor(&self) -> Option<&[u8]>;
213 /// Returns the mode.
214 fn mode(&self) -> Mode;
215 /// Returns the hidden value.
216 fn hidden(&self) -> &[u8; HIDDEN_SIZE];
217}
218
219/// An owning convenience type implementing `InputValues`.
220pub 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
229impl InputValuesOwned {
230 /// Construct a new instance of InputValuesOwned.
231 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
250impl InputValues for InputValuesOwned {
251 fn code_hash(&self) -> &[u8; HASH_SIZE] {
252 &self.code_hash
253 }
254 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 }
260 fn authority_hash(&self) -> &[u8; HASH_SIZE] {
261 &self.authority_hash
262 }
263 fn authority_descriptor(&self) -> Option<&[u8]> {
264 self.authority_descriptor.as_deref()
265 }
266 fn mode(&self) -> Mode {
267 self.mode
268 }
269 fn hidden(&self) -> &[u8; HIDDEN_SIZE] {
270 &self.hidden
271 }
272}
273
274fn call_with_input_values<T: InputValues + ?Sized, F, R>(input_values: &T, f: F) -> Result<R>
275where
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.
310fn retry_while_adjusting_output_buffer<F>(mut f: F) -> Result<Vec<u8>>
311where
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.
353pub 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.
358 unsafe fn get_context(&mut self) -> *mut c_void;
359}
360
361impl<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)]
366pub struct OpenDiceCborContext();
367
368impl OpenDiceCborContext {
369 /// Construct a new instance of OpenDiceCborContext.
370 pub fn new() -> Self {
371 Default::default()
372 }
373}
374
375impl Context for OpenDiceCborContext {
376 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.
385pub type CdiAttest = ZVec;
386
387/// Type alias for ZVec indicating that it holds a CDI_SEAL secret.
388pub type CdiSeal = ZVec;
389
390/// Type alias for Vec<u8> indicating that it hold a DICE certificate.
391pub type Cert = Vec<u8>;
392
Janis Danisevskis2cef73f2021-11-03 15:02:48 -0700393/// Type alias for Vec<u8> indicating that it holds a BCC certificate chain.
394pub type Bcc = Vec<u8>;
395
Janis Danisevskis13356b22021-10-20 09:44:12 -0700396const 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.
401pub trait ContextImpl: Context + Send {
402 /// Safe wrapper around open-dice DiceDeriveCdiPrivateKeySeed, see open dice
403 /// documentation for details.
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.
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)`
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.
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.
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.
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.
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.
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.
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.
Janis Danisevskis2cef73f2021-11-03 15:02:48 -0700658 // * The seventh argument is a pointer to a mutable usize object. It is
Janis Danisevskis13356b22021-10-20 09:44:12 -0700659 // 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,
Janis Danisevskis2cef73f2021-11-03 15:02:48 -0700669 cert.len(),
Janis Danisevskis13356b22021-10-20 09:44:12 -0700670 cert.as_mut_ptr(),
671 actual_size as *mut _,
672 )
673 })
674 })?;
675 Ok(cert)
676 })
677 }
Janis Danisevskis2cef73f2021-11-03 15:02:48 -0700678
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)`
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
744pub 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.
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 }
Janis Danisevskis13356b22021-10-20 09:44:12 -0700792}
Janis Danisevskisdb78b772021-11-29 17:59:50 -0800793
794#[cfg(test)]
795mod 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]
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]
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]
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]
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}