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