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