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