blob: 384aff1f2996fa62a3bd8be003375c378ed045f2 [file] [log] [blame]
Janis Danisevskis13356b22021-10-20 09:44:12 -07001// Copyright 2021, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Implements safe wrappers around the public API of libopen-dice.
16//! ## Example:
17//! ```
18//! use diced_open_dice_cbor as dice;
19//!
20//! let context = dice::dice::OpenDiceCborContext::new()
21//! let parent_cdi_attest = [1u8, dice::CDI_SIZE];
22//! let parent_cdi_seal = [2u8, dice::CDI_SIZE];
23//! let input_values = dice::InputValuesOwned {
24//! code_hash: [3u8, dice::HASH_SIZE],
25//! config: dice::ConfigOwned::Descriptor("My descriptor".as_bytes().to_vec()),
26//! authority_hash: [0u8, dice::HASH_SIZE],
27//! mode: dice::Mode::Normal,
28//! hidden: [0u8, dice::HIDDEN_SIZE],
29//! };
30//! let (cdi_attest, cdi_seal, cert_chain) = context
31//! .main_flow(&parent_cdi_attest, &parent_cdi_seal, &input_values)?;
32//! ```
33
34use keystore2_crypto::{zvec, ZVec};
35use open_dice_cbor_bindgen::{
36 DiceConfigType, DiceDeriveCdiCertificateId, DiceDeriveCdiPrivateKeySeed,
37 DiceGenerateCertificate, DiceHash, DiceInputValues, DiceKdf, DiceKeypairFromSeed, DiceMainFlow,
38 DiceMode, DiceResult, DiceSign, DiceVerify, DICE_CDI_SIZE, DICE_HASH_SIZE, DICE_HIDDEN_SIZE,
39 DICE_ID_SIZE, DICE_INLINE_CONFIG_SIZE, DICE_PRIVATE_KEY_SEED_SIZE, DICE_PRIVATE_KEY_SIZE,
40 DICE_PUBLIC_KEY_SIZE, DICE_SIGNATURE_SIZE,
41};
42use open_dice_cbor_bindgen::{
43 DiceConfigType_kDiceConfigTypeDescriptor as DICE_CONFIG_TYPE_DESCRIPTOR,
44 DiceConfigType_kDiceConfigTypeInline as DICE_CONFIG_TYPE_INLINE,
45 DiceMode_kDiceModeDebug as DICE_MODE_DEBUG,
46 DiceMode_kDiceModeMaintenance as DICE_MODE_RECOVERY,
47 DiceMode_kDiceModeNormal as DICE_MODE_NORMAL,
48 DiceMode_kDiceModeNotInitialized as DICE_MODE_NOT_CONFIGURED,
49 DiceResult_kDiceResultBufferTooSmall as DICE_RESULT_BUFFER_TOO_SMALL,
50 DiceResult_kDiceResultInvalidInput as DICE_RESULT_INVALID_INPUT,
51 DiceResult_kDiceResultOk as DICE_RESULT_OK,
52 DiceResult_kDiceResultPlatformError as DICE_RESULT_PLATFORM_ERROR,
53};
54use std::ffi::c_void;
55
56/// The size of a DICE hash.
57pub const HASH_SIZE: usize = DICE_HASH_SIZE as usize;
58/// The size of the DICE hidden value.
59pub const HIDDEN_SIZE: usize = DICE_HIDDEN_SIZE as usize;
60/// The size of a DICE inline config.
61pub const INLINE_CONFIG_SIZE: usize = DICE_INLINE_CONFIG_SIZE as usize;
62/// The size of a private key seed.
63pub const PRIVATE_KEY_SEED_SIZE: usize = DICE_PRIVATE_KEY_SEED_SIZE as usize;
64/// The size of a CDI.
65pub const CDI_SIZE: usize = DICE_CDI_SIZE as usize;
66/// The size of an ID.
67pub const ID_SIZE: usize = DICE_ID_SIZE as usize;
68/// The size of a private key.
69pub const PRIVATE_KEY_SIZE: usize = DICE_PRIVATE_KEY_SIZE as usize;
70/// The size of a public key.
71pub const PUBLIC_KEY_SIZE: usize = DICE_PUBLIC_KEY_SIZE as usize;
72/// The size of a signature.
73pub const SIGNATURE_SIZE: usize = DICE_SIGNATURE_SIZE as usize;
74
75/// Open dice wrapper error type.
76#[derive(Debug, thiserror::Error, PartialEq)]
77pub enum Error {
78 /// The libopen-dice backend reported InvalidInput.
79 #[error("Open dice backend: Invalid input")]
80 InvalidInput,
81 /// The libopen-dice backend reported BufferTooSmall.
82 #[error("Open dice backend: Buffer too small")]
83 BufferTooSmall,
84 /// The libopen-dice backend reported PlatformError.
85 #[error("Open dice backend: Platform error")]
86 PlatformError,
87 /// The libopen-dice backend reported an error that is outside of the defined range of errors.
88 /// The returned error code is embedded in this value.
89 #[error("Open dice backend returned an unexpected error code: {0:?}")]
90 Unexpected(u32),
91
92 /// The allocation of a ZVec failed. Most likely due to a failure during the call to mlock.
93 #[error("ZVec allocation failed")]
94 ZVec(#[from] zvec::Error),
95}
96
97/// Open dice result type.
98pub type Result<T> = std::result::Result<T, Error>;
99
100impl From<DiceResult> for Error {
101 fn from(result: DiceResult) -> Self {
102 match result {
103 DICE_RESULT_INVALID_INPUT => Error::InvalidInput,
104 DICE_RESULT_BUFFER_TOO_SMALL => Error::BufferTooSmall,
105 DICE_RESULT_PLATFORM_ERROR => Error::PlatformError,
106 r => Error::Unexpected(r),
107 }
108 }
109}
110
111fn check_result(result: DiceResult) -> Result<()> {
112 if result == DICE_RESULT_OK {
113 Ok(())
114 } else {
115 Err(result.into())
116 }
117}
118
119/// Configuration descriptor for dice input values.
120#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
121pub enum Config<'a> {
122 /// A reference to an inline descriptor.
123 Inline(&'a [u8; INLINE_CONFIG_SIZE]),
124 /// A reference to a free form descriptor that will be hashed by the implementation.
125 Descriptor(&'a [u8]),
126}
127
128enum ConfigOwned {
129 Inline([u8; INLINE_CONFIG_SIZE]),
130 Descriptor(Vec<u8>),
131}
132
133impl Config<'_> {
134 fn get_type(&self) -> DiceConfigType {
135 match self {
136 Self::Inline(_) => DICE_CONFIG_TYPE_INLINE,
137 Self::Descriptor(_) => DICE_CONFIG_TYPE_DESCRIPTOR,
138 }
139 }
140
141 fn get_inline(&self) -> [u8; INLINE_CONFIG_SIZE] {
142 match self {
143 Self::Inline(inline) => **inline,
144 _ => [0u8; INLINE_CONFIG_SIZE],
145 }
146 }
147
148 fn get_descriptor_as_ptr(&self) -> *const u8 {
149 match self {
150 Self::Descriptor(descriptor) => descriptor.as_ptr(),
151 _ => std::ptr::null(),
152 }
153 }
154
155 fn get_descriptor_size(&self) -> usize {
156 match self {
157 Self::Descriptor(descriptor) => descriptor.len(),
158 _ => 0,
159 }
160 }
161}
162
163impl From<Config<'_>> for ConfigOwned {
164 fn from(config: Config) -> Self {
165 match config {
166 Config::Inline(inline) => ConfigOwned::Inline(*inline),
167 Config::Descriptor(descriptor) => ConfigOwned::Descriptor(descriptor.to_owned()),
168 }
169 }
170}
171
172/// DICE modes as defined here:
173/// https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md#mode-value-details
174#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
175pub enum Mode {
176 /// See documentation linked above.
177 NotConfigured = 0,
178 /// See documentation linked above.
179 Normal = 1,
180 /// See documentation linked above.
181 Debug = 2,
182 /// See documentation linked above.
183 Recovery = 3,
184}
185
186impl Mode {
187 fn get_internal(&self) -> DiceMode {
188 match self {
189 Self::NotConfigured => DICE_MODE_NOT_CONFIGURED,
190 Self::Normal => DICE_MODE_NORMAL,
191 Self::Debug => DICE_MODE_DEBUG,
192 Self::Recovery => DICE_MODE_RECOVERY,
193 }
194 }
195}
196
197/// This trait allows API users to supply DICE input values without copying.
198pub trait InputValues {
199 /// Returns the code hash.
200 fn code_hash(&self) -> &[u8; HASH_SIZE];
201 /// Returns the config.
202 fn config(&self) -> Config;
203 /// Returns the authority hash.
204 fn authority_hash(&self) -> &[u8; HASH_SIZE];
205 /// Returns the authority descriptor.
206 fn authority_descriptor(&self) -> Option<&[u8]>;
207 /// Returns the mode.
208 fn mode(&self) -> Mode;
209 /// Returns the hidden value.
210 fn hidden(&self) -> &[u8; HIDDEN_SIZE];
211}
212
213/// An owning convenience type implementing `InputValues`.
214pub struct InputValuesOwned {
215 code_hash: [u8; HASH_SIZE],
216 config: ConfigOwned,
217 authority_hash: [u8; HASH_SIZE],
218 authority_descriptor: Option<Vec<u8>>,
219 mode: Mode,
220 hidden: [u8; HIDDEN_SIZE],
221}
222
223impl InputValuesOwned {
224 /// Construct a new instance of InputValuesOwned.
225 pub fn new(
226 code_hash: [u8; HASH_SIZE],
227 config: Config,
228 authority_hash: [u8; HASH_SIZE],
229 authority_descriptor: Option<Vec<u8>>,
230 mode: Mode,
231 hidden: [u8; HIDDEN_SIZE],
232 ) -> Self {
233 Self {
234 code_hash,
235 config: config.into(),
236 authority_hash,
237 authority_descriptor,
238 mode,
239 hidden,
240 }
241 }
242}
243
244impl InputValues for InputValuesOwned {
245 fn code_hash(&self) -> &[u8; HASH_SIZE] {
246 &self.code_hash
247 }
248 fn config(&self) -> Config {
249 match &self.config {
250 ConfigOwned::Inline(inline) => Config::Inline(inline),
251 ConfigOwned::Descriptor(descriptor) => Config::Descriptor(descriptor.as_slice()),
252 }
253 }
254 fn authority_hash(&self) -> &[u8; HASH_SIZE] {
255 &self.authority_hash
256 }
257 fn authority_descriptor(&self) -> Option<&[u8]> {
258 self.authority_descriptor.as_deref()
259 }
260 fn mode(&self) -> Mode {
261 self.mode
262 }
263 fn hidden(&self) -> &[u8; HIDDEN_SIZE] {
264 &self.hidden
265 }
266}
267
268fn call_with_input_values<T: InputValues + ?Sized, F, R>(input_values: &T, f: F) -> Result<R>
269where
270 F: FnOnce(*const DiceInputValues) -> Result<R>,
271{
272 let input_values = DiceInputValues {
273 code_hash: *input_values.code_hash(),
274 code_descriptor: std::ptr::null(),
275 code_descriptor_size: 0,
276 config_type: input_values.config().get_type(),
277 config_value: input_values.config().get_inline(),
278 config_descriptor: input_values.config().get_descriptor_as_ptr(),
279 config_descriptor_size: input_values.config().get_descriptor_size(),
280 authority_hash: *input_values.authority_hash(),
281 authority_descriptor: input_values
282 .authority_descriptor()
283 .map_or_else(std::ptr::null, <[u8]>::as_ptr),
284 authority_descriptor_size: input_values.authority_descriptor().map_or(0, <[u8]>::len),
285 mode: input_values.mode().get_internal(),
286 hidden: *input_values.hidden(),
287 };
288
289 f(&input_values as *const DiceInputValues)
290}
291
292/// Multiple of the open dice function required preallocated output buffer
293/// which may be too small, this function implements the retry logic to handle
294/// too small buffer allocations.
295/// The callback `F` must expect a mutable reference to a buffer and a size hint
296/// field. The callback is called repeatedly as long as it returns
297/// `Err(Error::BufferTooSmall)`. If the size hint remains 0, the buffer size is
298/// doubled with each iteration. If the size hint is set by the callback, the buffer
299/// will be set to accommodate at least this many bytes.
300/// If the callback returns `Ok(())`, the buffer is truncated to the size hint
301/// exactly.
302/// The function panics if the callback returns `Ok(())` and the size hint is
303/// larger than the buffer size.
304fn retry_while_adjusting_output_buffer<F>(mut f: F) -> Result<Vec<u8>>
305where
306 F: FnMut(&mut Vec<u8>, &mut usize) -> Result<()>,
307{
308 let mut buffer = vec![0; INITIAL_OUT_BUFFER_SIZE];
309 let mut actual_size: usize = 0;
310 loop {
311 match f(&mut buffer, &mut actual_size) {
312 // If Error::BufferTooSmall was returned, the allocated certificate
313 // buffer was to small for the output. So the buffer is resized to the actual
314 // size, and a second attempt is made with the new buffer.
315 Err(Error::BufferTooSmall) => {
316 let new_size = if actual_size == 0 {
317 // Due to an off spec implementation of open dice cbor, actual size
318 // does not return the required size if the buffer was too small. So
319 // we have to try and approach it gradually.
320 buffer.len() * 2
321 } else {
322 actual_size
323 };
324 buffer.resize(new_size, 0);
325 continue;
326 }
327 Err(e) => return Err(e),
328 Ok(()) => {
329 if actual_size > buffer.len() {
330 panic!(
331 "actual_size larger than buffer size: open-dice function
332 may have written past the end of the buffer."
333 );
334 }
335 // Truncate the certificate buffer to the actual size because it may be
336 // smaller than the original allocation.
337 buffer.truncate(actual_size);
338 return Ok(buffer);
339 }
340 }
341 }
342}
343
344/// Some libopen-dice variants use a context. Developers that want to customize these
345/// bindings may want to implement their own Context factory that creates a context
346/// useable by their preferred backend.
347pub trait Context {
348 /// # Safety
349 /// The return value of get_context is passed to any open dice function.
350 /// Implementations must explain why the context pointer returned is safe
351 /// to be used by the open dice library.
352 unsafe fn get_context(&mut self) -> *mut c_void;
353}
354
355impl<T: Context + Send> ContextImpl for T {}
356
357/// This represents a context for the open dice library. The wrapped open dice instance, which
358/// is based on boringssl and cbor, does not use a context, so that this type is empty.
359#[derive(Default)]
360pub struct OpenDiceCborContext();
361
362impl OpenDiceCborContext {
363 /// Construct a new instance of OpenDiceCborContext.
364 pub fn new() -> Self {
365 Default::default()
366 }
367}
368
369impl Context for OpenDiceCborContext {
370 unsafe fn get_context(&mut self) -> *mut c_void {
371 // # Safety
372 // The open dice cbor implementation does not use a context. It is safe
373 // to return NULL.
374 std::ptr::null_mut()
375 }
376}
377
378/// Type alias for ZVec indicating that it holds a CDI_ATTEST secret.
379pub type CdiAttest = ZVec;
380
381/// Type alias for ZVec indicating that it holds a CDI_SEAL secret.
382pub type CdiSeal = ZVec;
383
384/// Type alias for Vec<u8> indicating that it hold a DICE certificate.
385pub type Cert = Vec<u8>;
386
387const INITIAL_OUT_BUFFER_SIZE: usize = 1024;
388
389/// ContextImpl is a mixin trait that implements the safe wrappers around the open dice
390/// library calls. Implementations must implement Context::get_context(). As of
391/// this writing, the only implementation is OpenDiceCborContext, which returns NULL.
392pub trait ContextImpl: Context + Send {
393 /// Safe wrapper around open-dice DiceDeriveCdiPrivateKeySeed, see open dice
394 /// documentation for details.
395 fn derive_cdi_private_key_seed(&mut self, cdi_attest: &[u8; CDI_SIZE]) -> Result<ZVec> {
396 let mut seed = ZVec::new(PRIVATE_KEY_SEED_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 of size CDI_SIZE.
401 // * The third argument is expected to be a non const array of size
402 // PRIVATE_KEY_SEED_SIZE which is fulfilled if the call to ZVec::new above
403 // succeeds.
404 // * No pointers are expected to be valid beyond the scope of the function
405 // call.
406 check_result(unsafe {
407 DiceDeriveCdiPrivateKeySeed(self.get_context(), cdi_attest.as_ptr(), seed.as_mut_ptr())
408 })?;
409 Ok(seed)
410 }
411
412 /// Safe wrapper around open-dice DiceDeriveCdiCertificateId, see open dice
413 /// documentation for details.
414 fn derive_cdi_certificate_id(&mut self, cdi_public_key: &[u8]) -> Result<ZVec> {
415 let mut id = ZVec::new(ID_SIZE)?;
416 // SAFETY:
417 // * The first context argument may be NULL and is unused by the wrapped
418 // implementation.
419 // * The second argument is expected to be a const array with a size given by the
420 // third argument.
421 // * The fourth argument is expected to be a non const array of size
422 // ID_SIZE which is fulfilled if the call to ZVec::new above succeeds.
423 // * No pointers are expected to be valid beyond the scope of the function
424 // call.
425 check_result(unsafe {
426 DiceDeriveCdiCertificateId(
427 self.get_context(),
428 cdi_public_key.as_ptr(),
429 cdi_public_key.len(),
430 id.as_mut_ptr(),
431 )
432 })?;
433 Ok(id)
434 }
435
436 /// Safe wrapper around open-dice DiceMainFlow, see open dice
437 /// documentation for details.
438 /// Returns a tuple of:
439 /// * The next attestation CDI,
440 /// * the next seal CDI, and
441 /// * the next attestation certificate.
442 /// `(next_attest_cdi, next_seal_cdi, next_attestation_cert)`
443 fn main_flow<T: InputValues + ?Sized>(
444 &mut self,
445 current_cdi_attest: &[u8; CDI_SIZE],
446 current_cdi_seal: &[u8; CDI_SIZE],
447 input_values: &T,
448 ) -> Result<(CdiAttest, CdiSeal, Cert)> {
449 let mut next_attest = CdiAttest::new(CDI_SIZE)?;
450 let mut next_seal = CdiSeal::new(CDI_SIZE)?;
451
452 // SAFETY (DiceMainFlow):
453 // * The first context argument may be NULL and is unused by the wrapped
454 // implementation.
455 // * The second argument and the third argument are const arrays of size CDI_SIZE.
456 // This is fulfilled as per the definition of the arguments `current_cdi_attest`
457 // and `current_cdi_seal.
458 // * The fourth argument is a pointer to `DiceInputValues`. It, and its indirect
459 // references must be valid for the duration of the function call which
460 // is guaranteed by `call_with_input_values` which puts `DiceInputValues`
461 // on the stack and initializes it from the `input_values` argument which
462 // implements the `InputValues` trait.
463 // * The fifth and sixth argument are the length of and the pointer to the
464 // allocated certificate buffer respectively. They are used to return
465 // the generated certificate.
466 // * The seventh argument is a pointer to a mutable usize object. It is
467 // used to return the actual size of the output certificate.
468 // * The eighth argument and the ninth argument are pointers to mutable buffers of size
469 // CDI_SIZE. This is fulfilled if the allocation above succeeded.
470 // * No pointers are expected to be valid beyond the scope of the function
471 // call.
472 call_with_input_values(input_values, |input_values| {
473 let cert = retry_while_adjusting_output_buffer(|cert, actual_size| {
474 check_result(unsafe {
475 DiceMainFlow(
476 self.get_context(),
477 current_cdi_attest.as_ptr(),
478 current_cdi_seal.as_ptr(),
479 input_values,
480 cert.len(),
481 cert.as_mut_ptr(),
482 actual_size as *mut _,
483 next_attest.as_mut_ptr(),
484 next_seal.as_mut_ptr(),
485 )
486 })
487 })?;
488 Ok((next_attest, next_seal, cert))
489 })
490 }
491
492 /// Safe wrapper around open-dice DiceHash, see open dice
493 /// documentation for details.
494 fn hash(&mut self, input: &[u8]) -> Result<Vec<u8>> {
495 let mut output: Vec<u8> = vec![0; HASH_SIZE];
496
497 // SAFETY:
498 // * The first context argument may be NULL and is unused by the wrapped
499 // implementation.
500 // * The second argument and the third argument are the pointer to and length of the given
501 // input buffer respectively.
502 // * The fourth argument must be a pointer to a mutable buffer of size HASH_SIZE
503 // which is fulfilled by the allocation above.
504 check_result(unsafe {
505 DiceHash(self.get_context(), input.as_ptr(), input.len(), output.as_mut_ptr())
506 })?;
507 Ok(output)
508 }
509
510 /// Safe wrapper around open-dice DiceKdf, see open dice
511 /// documentation for details.
512 fn kdf(&mut self, length: usize, input_key: &[u8], salt: &[u8], info: &[u8]) -> Result<ZVec> {
513 let mut output = ZVec::new(length)?;
514
515 // SAFETY:
516 // * The first context argument may be NULL and is unused by the wrapped
517 // implementation.
518 // * The second argument is primitive.
519 // * The third argument and the fourth argument are the pointer to and length of the given
520 // input key.
521 // * The fifth argument and the sixth argument are the pointer to and length of the given
522 // salt.
523 // * The seventh argument and the eighth argument are the pointer to and length of the
524 // given info field.
525 // * The ninth argument is a pointer to the output buffer which must have the
526 // length given by the `length` argument (see second argument). This is
527 // fulfilled if the allocation of `output` succeeds.
528 // * All pointers must be valid for the duration of the function call, but not
529 // longer.
530 check_result(unsafe {
531 DiceKdf(
532 self.get_context(),
533 length,
534 input_key.as_ptr(),
535 input_key.len(),
536 salt.as_ptr(),
537 salt.len(),
538 info.as_ptr(),
539 info.len(),
540 output.as_mut_ptr(),
541 )
542 })?;
543 Ok(output)
544 }
545
546 /// Safe wrapper around open-dice DiceKeyPairFromSeed, see open dice
547 /// documentation for details.
548 fn keypair_from_seed(&mut self, seed: &[u8; PRIVATE_KEY_SEED_SIZE]) -> Result<(Vec<u8>, ZVec)> {
549 let mut private_key = ZVec::new(PRIVATE_KEY_SIZE)?;
550 let mut public_key = vec![0u8; PUBLIC_KEY_SIZE];
551
552 // SAFETY:
553 // * The first context argument may be NULL and is unused by the wrapped
554 // implementation.
555 // * The second argument is a pointer to a const buffer of size `PRIVATE_KEY_SEED_SIZE`
556 // fulfilled by the definition of the argument.
557 // * The third argument and the fourth argument are mutable buffers of size
558 // `PRIVATE_KEY_SIZE` and `PUBLIC_KEY_SIZE` respectively. This is fulfilled by the
559 // allocations above.
560 // * All pointers must be valid for the duration of the function call but not beyond.
561 check_result(unsafe {
562 DiceKeypairFromSeed(
563 self.get_context(),
564 seed.as_ptr(),
565 public_key.as_mut_ptr(),
566 private_key.as_mut_ptr(),
567 )
568 })?;
569 Ok((public_key, private_key))
570 }
571
572 /// Safe wrapper around open-dice DiceSign, see open dice
573 /// documentation for details.
574 fn sign(&mut self, message: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE]) -> Result<Vec<u8>> {
575 let mut signature = vec![0u8; SIGNATURE_SIZE];
576
577 // SAFETY:
578 // * The first context argument may be NULL and is unused by the wrapped
579 // implementation.
580 // * The second argument and the third argument are the pointer to and length of the given
581 // message buffer.
582 // * The fourth argument is a const buffer of size `PRIVATE_KEY_SIZE`. This is fulfilled
583 // by the definition of `private key`.
584 // * The fifth argument is mutable buffer of size `SIGNATURE_SIZE`. This is fulfilled
585 // by the allocation above.
586 // * All pointers must be valid for the duration of the function call but not beyond.
587 check_result(unsafe {
588 DiceSign(
589 self.get_context(),
590 message.as_ptr(),
591 message.len(),
592 private_key.as_ptr(),
593 signature.as_mut_ptr(),
594 )
595 })?;
596 Ok(signature)
597 }
598
599 /// Safe wrapper around open-dice DiceVerify, see open dice
600 /// documentation for details.
601 fn verify(
602 &mut self,
603 message: &[u8],
604 signature: &[u8; SIGNATURE_SIZE],
605 public_key: &[u8; PUBLIC_KEY_SIZE],
606 ) -> Result<()> {
607 // SAFETY:
608 // * The first context argument may be NULL and is unused by the wrapped
609 // implementation.
610 // * The second argument and the third argument are the pointer to and length of the given
611 // message buffer.
612 // * The fourth argument is a const buffer of size `SIGNATURE_SIZE`. This is fulfilled
613 // by the definition of `signature`.
614 // * The fifth argument is a const buffer of size `PUBLIC_KEY_SIZE`. This is fulfilled
615 // by the definition of `public_key`.
616 // * All pointers must be valid for the duration of the function call but not beyond.
617 check_result(unsafe {
618 DiceVerify(
619 self.get_context(),
620 message.as_ptr(),
621 message.len(),
622 signature.as_ptr(),
623 public_key.as_ptr(),
624 )
625 })
626 }
627
628 /// Safe wrapper around open-dice DiceGenerateCertificate, see open dice
629 /// documentation for details.
630 fn generate_certificate<T: InputValues>(
631 &mut self,
632 subject_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
633 authority_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
634 input_values: &T,
635 ) -> Result<Vec<u8>> {
636 // SAFETY (DiceMainFlow):
637 // * The first context argument may be NULL and is unused by the wrapped
638 // implementation.
639 // * The second argument and the third argument are const arrays of size
640 // `PRIVATE_KEY_SEED_SIZE`. This is fulfilled as per the definition of the arguments.
641 // * The fourth argument is a pointer to `DiceInputValues` it, and its indirect
642 // references must be valid for the duration of the function call which
643 // is guaranteed by `call_with_input_values` which puts `DiceInputValues`
644 // on the stack and initializes it from the `input_values` argument which
645 // implements the `InputValues` trait.
646 // * The fifth argument and the sixth argument are the length of and the pointer to the
647 // allocated certificate buffer respectively. They are used to return
648 // the generated certificate.
649 // * The seventh argument is a pointer to a mutable size_t object. It is
650 // used to return the actual size of the output certificate.
651 // * All pointers must be valid for the duration of the function call but not beyond.
652 call_with_input_values(input_values, |input_values| {
653 let cert = retry_while_adjusting_output_buffer(|cert, actual_size| {
654 check_result(unsafe {
655 DiceGenerateCertificate(
656 self.get_context(),
657 subject_private_key_seed.as_ptr(),
658 authority_private_key_seed.as_ptr(),
659 input_values,
660 cert.len().try_into()?,
661 cert.as_mut_ptr(),
662 actual_size as *mut _,
663 )
664 })
665 })?;
666 Ok(cert)
667 })
668 }
669}