blob: 657e4828308889c697c8186d93f0cbced740a867 [file] [log] [blame]
Alice Wangd3a96402023-11-24 15:37:39 +00001// Copyright 2023, 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//! This module contains functions related to DICE.
16
Alice Wang1cc13502023-12-05 11:05:34 +000017use alloc::string::String;
Alice Wangd3a96402023-11-24 15:37:39 +000018use alloc::vec::Vec;
Alice Wang3397b362023-12-01 13:57:10 +000019use bssl_avf::{ed25519_verify, Digester, EcKey};
Alice Wangdd29c5d2023-12-07 09:56:23 +000020use cbor_util::{
Alice Wang3397b362023-12-01 13:57:10 +000021 cbor_value_type, get_label_value, get_label_value_as_bytes, value_to_array,
22 value_to_byte_array, value_to_bytes, value_to_map, value_to_num, value_to_text,
Alice Wangdd29c5d2023-12-07 09:56:23 +000023};
24use ciborium::value::Value;
Alice Wangd3a96402023-11-24 15:37:39 +000025use core::cell::OnceCell;
26use core::result;
27use coset::{
Alice Wang3397b362023-12-01 13:57:10 +000028 self,
29 iana::{self, EnumI64},
30 Algorithm, AsCborValue, CborSerializable, CoseError, CoseKey, CoseSign1, KeyOperation, KeyType,
31 Label,
Alice Wangd3a96402023-11-24 15:37:39 +000032};
33use diced_open_dice::{DiceMode, HASH_SIZE};
34use log::error;
Alice Wangdd29c5d2023-12-07 09:56:23 +000035use service_vm_comm::RequestProcessingError;
Alice Wangd3a96402023-11-24 15:37:39 +000036
37type Result<T> = result::Result<T, RequestProcessingError>;
38
39const CODE_HASH: i64 = -4670545;
40const CONFIG_DESC: i64 = -4670548;
41const AUTHORITY_HASH: i64 = -4670549;
42const MODE: i64 = -4670551;
43const SUBJECT_PUBLIC_KEY: i64 = -4670552;
44
Alice Wang1cc13502023-12-05 11:05:34 +000045const CONFIG_DESC_COMPONENT_NAME: i64 = -70002;
46const CONFIG_DESC_SUB_COMPONENTS: i64 = -71002;
47
48const SUB_COMPONENT_NAME: i64 = 1;
49const SUB_COMPONENT_VERSION: i64 = 2;
50const SUB_COMPONENT_CODE_HASH: i64 = 3;
51const SUB_COMPONENT_AUTHORITY_HASH: i64 = 4;
52
53const MICRODROID_KERNEL_COMPONENT_NAME: &str = "vm_entry";
54const MICRODROID_PAYLOAD_COMPONENT_NAME: &str = "Microdroid payload";
55
Alice Wangd3a96402023-11-24 15:37:39 +000056/// Represents a partially decoded `DiceCertChain` from the client VM.
57/// The whole chain is defined as following:
58///
59/// DiceCertChain = [
60/// PubKeyEd25519 / PubKeyECDSA256 / PubKeyECDSA384, ; UDS_Pub
61/// + DiceChainEntry, ; First CDI_Certificate -> Last CDI_Certificate
62/// ]
63#[derive(Debug, Clone)]
64pub(crate) struct ClientVmDiceChain {
Alice Wang3397b362023-12-01 13:57:10 +000065 payloads: Vec<DiceChainEntryPayload>,
Alice Wangd3a96402023-11-24 15:37:39 +000066}
67
68impl ClientVmDiceChain {
69 /// Validates the signatures of the entries in the `client_vm_dice_chain` as following:
70 ///
71 /// - The first entry of the `client_vm_dice_chain` must be signed with the root public key.
72 /// - After the first entry, each entry of the `client_vm_dice_chain` must be signed with the
73 /// subject public key of the previous entry.
74 ///
75 /// Returns a partially decoded client VM's DICE chain if the verification succeeds.
76 pub(crate) fn validate_signatures_and_parse_dice_chain(
77 mut client_vm_dice_chain: Vec<Value>,
78 ) -> Result<Self> {
79 let root_public_key =
80 CoseKey::from_cbor_value(client_vm_dice_chain.remove(0))?.try_into()?;
81
82 let mut payloads = Vec::with_capacity(client_vm_dice_chain.len());
83 let mut previous_public_key = &root_public_key;
84 for (i, value) in client_vm_dice_chain.into_iter().enumerate() {
85 let payload = DiceChainEntryPayload::validate_cose_signature_and_extract_payload(
86 value,
87 previous_public_key,
88 )
89 .map_err(|e| {
90 error!("Failed to verify the DICE chain entry {}: {:?}", i, e);
91 e
92 })?;
93 payloads.push(payload);
94 previous_public_key = &payloads.last().unwrap().subject_public_key;
95 }
96 // After successfully calling `validate_client_vm_dice_chain_prefix_match`, we can be
97 // certain that the client VM's DICE chain must contain at least three entries that
98 // describe:
99 // - pvmfw
100 // - Microdroid kernel
101 // - Apk/Apexes
102 assert!(
103 payloads.len() >= 3,
104 "The client VM DICE chain must contain at least three DiceChainEntryPayloads"
105 );
Alice Wang1cc13502023-12-05 11:05:34 +0000106 let chain = Self { payloads };
107 chain.validate_microdroid_components_names()?;
108 Ok(chain)
109 }
110
111 fn validate_microdroid_components_names(&self) -> Result<()> {
112 let microdroid_kernel_name = &self.microdroid_kernel().config_descriptor.component_name;
113 if MICRODROID_KERNEL_COMPONENT_NAME != microdroid_kernel_name {
114 error!(
115 "The second to last entry in the client VM DICE chain must describe the \
116 Microdroid kernel. Got {}",
117 microdroid_kernel_name
118 );
119 return Err(RequestProcessingError::InvalidDiceChain);
120 }
121 let microdroid_payload_name = &self.microdroid_payload().config_descriptor.component_name;
122 if MICRODROID_PAYLOAD_COMPONENT_NAME != microdroid_payload_name {
123 error!(
124 "The last entry in the client VM DICE chain must describe the Microdroid \
125 payload. Got {}",
126 microdroid_payload_name
127 );
128 return Err(RequestProcessingError::InvalidDiceChain);
129 }
130 Ok(())
131 }
132
Alice Wang4e093102023-12-13 09:16:29 +0000133 pub(crate) fn microdroid_kernel(&self) -> &DiceChainEntryPayload {
Alice Wang1cc13502023-12-05 11:05:34 +0000134 &self.payloads[self.payloads.len() - 2]
135 }
136
Alice Wang3397b362023-12-01 13:57:10 +0000137 pub(crate) fn microdroid_payload(&self) -> &DiceChainEntryPayload {
Alice Wang1cc13502023-12-05 11:05:34 +0000138 &self.payloads[self.payloads.len() - 1]
139 }
140
141 pub(crate) fn microdroid_payload_components(&self) -> Option<&Vec<SubComponent>> {
142 self.microdroid_payload().config_descriptor.sub_components.as_ref()
Alice Wangd3a96402023-11-24 15:37:39 +0000143 }
144
145 /// Returns true if all payloads in the DICE chain are in normal mode.
146 pub(crate) fn all_entries_are_secure(&self) -> bool {
147 self.payloads.iter().all(|p| p.mode == DiceMode::kDiceModeNormal)
148 }
149}
150
151/// Validates that the `client_vm_dice_chain` matches the `service_vm_dice_chain` up to the pvmfw
152/// entry.
153///
Alice Wang4e093102023-12-13 09:16:29 +0000154/// Returns `Ok(())` if the verification succeeds.
Alice Wangd3a96402023-11-24 15:37:39 +0000155pub(crate) fn validate_client_vm_dice_chain_prefix_match(
Alice Wang4e093102023-12-13 09:16:29 +0000156 client_vm_dice_chain: &[Value],
157 service_vm_dice_chain: &[Value],
158) -> Result<()> {
Alice Wangd3a96402023-11-24 15:37:39 +0000159 if service_vm_dice_chain.len() < 3 {
160 // The service VM's DICE chain must contain the root key and at least two other entries
161 // that describe:
162 // - pvmfw
163 // - Service VM kernel
164 error!("The service VM DICE chain must contain at least three entries");
165 return Err(RequestProcessingError::InternalError);
166 }
167 // Ignores the last entry that describes service VM
168 let entries_up_to_pvmfw = &service_vm_dice_chain[0..(service_vm_dice_chain.len() - 1)];
169 if entries_up_to_pvmfw.len() + 2 != client_vm_dice_chain.len() {
170 // Client VM DICE chain = entries_up_to_pvmfw
171 // + Microdroid kernel entry (added in pvmfw)
172 // + Apk/Apexes entry (added in microdroid)
173 error!("The client VM's DICE chain must contain exactly two extra entries");
174 return Err(RequestProcessingError::InvalidDiceChain);
175 }
176 if entries_up_to_pvmfw != &client_vm_dice_chain[0..entries_up_to_pvmfw.len()] {
177 error!(
178 "The client VM's DICE chain does not match service VM's DICE chain up to \
179 the pvmfw entry"
180 );
181 return Err(RequestProcessingError::InvalidDiceChain);
182 }
Alice Wang4e093102023-12-13 09:16:29 +0000183 Ok(())
Alice Wangd3a96402023-11-24 15:37:39 +0000184}
185
186#[derive(Debug, Clone)]
187pub(crate) struct PublicKey(CoseKey);
188
189impl TryFrom<CoseKey> for PublicKey {
190 type Error = RequestProcessingError;
191
192 fn try_from(key: CoseKey) -> Result<Self> {
193 if !key.key_ops.contains(&KeyOperation::Assigned(iana::KeyOperation::Verify)) {
194 error!("Public key does not support verification");
195 return Err(RequestProcessingError::InvalidDiceChain);
196 }
197 Ok(Self(key))
198 }
199}
200
Alice Wang3397b362023-12-01 13:57:10 +0000201impl PublicKey {
202 /// Verifies the signature of the provided message with the public key.
203 ///
204 /// This function supports the following key/algorithm types as specified in
205 /// hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/
206 /// generateCertificateRequestV2.cddl:
207 ///
208 /// PubKeyEd25519 / PubKeyECDSA256 / PubKeyECDSA384
209 pub(crate) fn verify(&self, signature: &[u8], message: &[u8]) -> Result<()> {
210 match &self.0.kty {
211 KeyType::Assigned(iana::KeyType::EC2) => {
212 let public_key = EcKey::from_cose_public_key(&self.0)?;
213 let Some(Algorithm::Assigned(alg)) = self.0.alg else {
214 error!("Invalid algorithm in COSE key {:?}", self.0.alg);
215 return Err(RequestProcessingError::InvalidDiceChain);
216 };
217 let digester = match alg {
218 iana::Algorithm::ES256 => Digester::sha256(),
219 iana::Algorithm::ES384 => Digester::sha384(),
220 _ => {
221 error!("Unsupported algorithm in EC2 key: {:?}", alg);
222 return Err(RequestProcessingError::InvalidDiceChain);
223 }
224 };
225 let digest = digester.digest(message)?;
226 Ok(public_key.ecdsa_verify(signature, &digest)?)
227 }
228 KeyType::Assigned(iana::KeyType::OKP) => {
229 let curve_type =
230 get_label_value(&self.0, Label::Int(iana::OkpKeyParameter::Crv.to_i64()))?;
231 if curve_type != &Value::from(iana::EllipticCurve::Ed25519.to_i64()) {
232 error!("Unsupported curve type in OKP COSE key: {:?}", curve_type);
233 return Err(RequestProcessingError::OperationUnimplemented);
234 }
235 let x = get_label_value_as_bytes(
236 &self.0,
237 Label::Int(iana::OkpKeyParameter::X.to_i64()),
238 )?;
239 let public_key = x.try_into().map_err(|_| {
240 error!("Invalid ED25519 public key size: {}", x.len());
241 RequestProcessingError::InvalidDiceChain
242 })?;
243 let signature = signature.try_into().map_err(|_| {
244 error!("Invalid ED25519 signature size: {}", signature.len());
245 RequestProcessingError::InvalidDiceChain
246 })?;
247 Ok(ed25519_verify(message, signature, public_key)?)
248 }
249 kty => {
250 error!("Unsupported key type in COSE key: {:?}", kty);
251 Err(RequestProcessingError::OperationUnimplemented)
252 }
253 }
254 }
255}
256
Alice Wangd3a96402023-11-24 15:37:39 +0000257/// Represents a partially decoded `DiceChainEntryPayload`. The whole payload is defined in:
258///
259/// hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/
260/// generateCertificateRequestV2.cddl
261#[derive(Debug, Clone)]
262pub(crate) struct DiceChainEntryPayload {
Alice Wang3397b362023-12-01 13:57:10 +0000263 pub(crate) subject_public_key: PublicKey,
Alice Wangd3a96402023-11-24 15:37:39 +0000264 mode: DiceMode,
Alice Wang4e093102023-12-13 09:16:29 +0000265 pub(crate) code_hash: [u8; HASH_SIZE],
266 pub(crate) authority_hash: [u8; HASH_SIZE],
Alice Wang1cc13502023-12-05 11:05:34 +0000267 config_descriptor: ConfigDescriptor,
Alice Wangd3a96402023-11-24 15:37:39 +0000268}
269
270impl DiceChainEntryPayload {
271 /// Validates the signature of the provided CBOR value with the provided public key and
272 /// extracts payload from the value.
273 fn validate_cose_signature_and_extract_payload(
274 value: Value,
Alice Wang3397b362023-12-01 13:57:10 +0000275 authority_public_key: &PublicKey,
Alice Wangd3a96402023-11-24 15:37:39 +0000276 ) -> Result<Self> {
277 let cose_sign1 = CoseSign1::from_cbor_value(value)?;
Alice Wang3397b362023-12-01 13:57:10 +0000278 let aad = &[]; // AAD is not used in DICE chain entry.
279 cose_sign1.verify_signature(aad, |signature, message| {
280 authority_public_key.verify(signature, message)
281 })?;
Alice Wangd3a96402023-11-24 15:37:39 +0000282
283 let payload = cose_sign1.payload.ok_or_else(|| {
284 error!("No payload found in the DICE chain entry");
285 RequestProcessingError::InvalidDiceChain
286 })?;
Alice Wang4e093102023-12-13 09:16:29 +0000287 Self::from_slice(&payload)
Alice Wangd3a96402023-11-24 15:37:39 +0000288 }
Ajinkya Chalkebd511762023-12-12 11:57:03 +0000289
Alice Wang4e093102023-12-13 09:16:29 +0000290 pub(crate) fn from_slice(data: &[u8]) -> Result<Self> {
291 let entries = value_to_map(Value::from_slice(data)?, "DiceChainEntryPayload")?;
292 let mut builder = PayloadBuilder::default();
293 for (key, value) in entries.into_iter() {
294 let key: i64 = value_to_num(key, "DiceChainEntryPayload key")?;
295 match key {
296 SUBJECT_PUBLIC_KEY => {
297 let subject_public_key = value_to_bytes(value, "subject_public_key")?;
298 let subject_public_key =
299 CoseKey::from_slice(&subject_public_key)?.try_into()?;
300 builder.subject_public_key(subject_public_key)?;
301 }
302 MODE => builder.mode(to_mode(value)?)?,
303 CODE_HASH => {
304 let code_hash = value_to_byte_array(value, "DiceChainEntryPayload code_hash")?;
305 builder.code_hash(code_hash)?;
306 }
307 AUTHORITY_HASH => {
308 let authority_hash =
309 value_to_byte_array(value, "DiceChainEntryPayload authority_hash")?;
310 builder.authority_hash(authority_hash)?;
311 }
312 CONFIG_DESC => {
313 let config_descriptor = value_to_bytes(value, "config_descriptor")?;
314 let config_descriptor = ConfigDescriptor::from_slice(&config_descriptor)?;
315 builder.config_descriptor(config_descriptor)?;
316 }
317 _ => {}
Ajinkya Chalkebd511762023-12-12 11:57:03 +0000318 }
Ajinkya Chalkebd511762023-12-12 11:57:03 +0000319 }
Alice Wang4e093102023-12-13 09:16:29 +0000320 builder.build()
Ajinkya Chalkebd511762023-12-12 11:57:03 +0000321 }
Ajinkya Chalkebd511762023-12-12 11:57:03 +0000322}
Alice Wang1cc13502023-12-05 11:05:34 +0000323/// Represents a partially decoded `ConfigurationDescriptor`.
324///
325/// The whole `ConfigurationDescriptor` is defined in:
326///
327/// hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/
328/// generateCertificateRequestV2.cddl
329#[derive(Debug, Clone)]
330pub(crate) struct ConfigDescriptor {
331 component_name: String,
332 sub_components: Option<Vec<SubComponent>>,
333}
334
335impl ConfigDescriptor {
336 fn from_slice(data: &[u8]) -> Result<Self> {
337 let value = Value::from_slice(data)?;
338 let entries = value_to_map(value, "ConfigDescriptor")?;
339 let mut builder = ConfigDescriptorBuilder::default();
340 for (key, value) in entries.into_iter() {
341 let key: i64 = value_to_num(key, "ConfigDescriptor key")?;
342 match key {
343 CONFIG_DESC_COMPONENT_NAME => {
344 let name = value_to_text(value, "ConfigDescriptor component_name")?;
345 builder.component_name(name)?;
346 }
347 CONFIG_DESC_SUB_COMPONENTS => {
348 let sub_components = value_to_array(value, "ConfigDescriptor sub_components")?;
349 let sub_components = sub_components
350 .into_iter()
351 .map(SubComponent::try_from)
352 .collect::<Result<Vec<_>>>()?;
353 builder.sub_components(sub_components)?
354 }
355 _ => {}
356 }
357 }
358 builder.build()
359 }
360}
361
362#[derive(Debug, Clone, Default)]
363struct ConfigDescriptorBuilder {
364 component_name: OnceCell<String>,
365 sub_components: OnceCell<Vec<SubComponent>>,
366}
367
368impl ConfigDescriptorBuilder {
369 fn component_name(&mut self, component_name: String) -> Result<()> {
370 set_once(&self.component_name, component_name, "ConfigDescriptor component_name")
371 }
372
373 fn sub_components(&mut self, sub_components: Vec<SubComponent>) -> Result<()> {
374 set_once(&self.sub_components, sub_components, "ConfigDescriptor sub_components")
375 }
376
377 fn build(mut self) -> Result<ConfigDescriptor> {
378 let component_name =
379 take_value(&mut self.component_name, "ConfigDescriptor component_name")?;
380 let sub_components = self.sub_components.take();
381 Ok(ConfigDescriptor { component_name, sub_components })
382 }
383}
384
385#[derive(Debug, Clone)]
386pub(crate) struct SubComponent {
387 pub(crate) name: String,
388 pub(crate) version: u64,
389 pub(crate) code_hash: Vec<u8>,
390 pub(crate) authority_hash: Vec<u8>,
391}
392
393impl TryFrom<Value> for SubComponent {
394 type Error = RequestProcessingError;
395
396 fn try_from(value: Value) -> Result<Self> {
397 let entries = value_to_map(value, "SubComponent")?;
398 let mut builder = SubComponentBuilder::default();
399 for (key, value) in entries.into_iter() {
400 let key: i64 = value_to_num(key, "SubComponent key")?;
401 match key {
402 SUB_COMPONENT_NAME => {
403 builder.name(value_to_text(value, "SubComponent component_name")?)?
404 }
405 SUB_COMPONENT_VERSION => {
406 builder.version(value_to_num(value, "SubComponent version")?)?
407 }
408 SUB_COMPONENT_CODE_HASH => {
409 builder.code_hash(value_to_bytes(value, "SubComponent code_hash")?)?
410 }
411 SUB_COMPONENT_AUTHORITY_HASH => {
412 builder.authority_hash(value_to_bytes(value, "SubComponent authority_hash")?)?
413 }
414 k => {
415 error!("Unknown key in SubComponent: {}", k);
416 return Err(RequestProcessingError::InvalidDiceChain);
417 }
418 }
419 }
420 builder.build()
421 }
422}
423
424#[derive(Debug, Clone, Default)]
425struct SubComponentBuilder {
426 name: OnceCell<String>,
427 version: OnceCell<u64>,
428 code_hash: OnceCell<Vec<u8>>,
429 authority_hash: OnceCell<Vec<u8>>,
430}
431
432impl SubComponentBuilder {
433 fn name(&mut self, name: String) -> Result<()> {
434 set_once(&self.name, name, "SubComponent name")
435 }
436
437 fn version(&mut self, version: u64) -> Result<()> {
438 set_once(&self.version, version, "SubComponent version")
439 }
440
441 fn code_hash(&mut self, code_hash: Vec<u8>) -> Result<()> {
442 set_once(&self.code_hash, code_hash, "SubComponent code_hash")
443 }
444
445 fn authority_hash(&mut self, authority_hash: Vec<u8>) -> Result<()> {
446 set_once(&self.authority_hash, authority_hash, "SubComponent authority_hash")
447 }
448
449 fn build(mut self) -> Result<SubComponent> {
450 let name = take_value(&mut self.name, "SubComponent name")?;
451 let version = take_value(&mut self.version, "SubComponent version")?;
452 let code_hash = take_value(&mut self.code_hash, "SubComponent code_hash")?;
453 let authority_hash = take_value(&mut self.authority_hash, "SubComponent authority_hash")?;
454 Ok(SubComponent { name, version, code_hash, authority_hash })
455 }
456}
457
Alice Wangd3a96402023-11-24 15:37:39 +0000458fn to_mode(value: Value) -> Result<DiceMode> {
459 let mode = match value {
460 // Mode is supposed to be encoded as a 1-byte bstr, but some implementations instead
461 // encode it as an integer. Accept either. See b/273552826.
462 // If Mode is omitted, it should be treated as if it was NotConfigured, according to
463 // the Open Profile for DICE spec.
464 Value::Bytes(bytes) => {
465 if bytes.len() != 1 {
466 error!("Bytes array with invalid length for mode: {:?}", bytes.len());
467 return Err(RequestProcessingError::InvalidDiceChain);
468 }
469 bytes[0].into()
470 }
471 Value::Integer(i) => i,
472 v => return Err(CoseError::UnexpectedItem(cbor_value_type(&v), "bstr or int").into()),
473 };
474 let mode = match mode {
475 x if x == (DiceMode::kDiceModeNormal as i64).into() => DiceMode::kDiceModeNormal,
476 x if x == (DiceMode::kDiceModeDebug as i64).into() => DiceMode::kDiceModeDebug,
477 x if x == (DiceMode::kDiceModeMaintenance as i64).into() => DiceMode::kDiceModeMaintenance,
478 // If Mode is invalid, it should be treated as if it was NotConfigured, according to
479 // the Open Profile for DICE spec.
480 _ => DiceMode::kDiceModeNotInitialized,
481 };
482 Ok(mode)
483}
484
485#[derive(Default, Debug, Clone)]
486struct PayloadBuilder {
487 subject_public_key: OnceCell<PublicKey>,
488 mode: OnceCell<DiceMode>,
489 code_hash: OnceCell<[u8; HASH_SIZE]>,
490 authority_hash: OnceCell<[u8; HASH_SIZE]>,
Alice Wang1cc13502023-12-05 11:05:34 +0000491 config_descriptor: OnceCell<ConfigDescriptor>,
Alice Wangd3a96402023-11-24 15:37:39 +0000492}
493
494fn set_once<T>(field: &OnceCell<T>, value: T, field_name: &str) -> Result<()> {
495 field.set(value).map_err(|_| {
496 error!("Field '{field_name}' is duplicated in the Payload");
497 RequestProcessingError::InvalidDiceChain
498 })
499}
500
501fn take_value<T>(field: &mut OnceCell<T>, field_name: &str) -> Result<T> {
502 field.take().ok_or_else(|| {
503 error!("Field '{field_name}' is missing in the Payload");
504 RequestProcessingError::InvalidDiceChain
505 })
506}
507
508impl PayloadBuilder {
509 fn subject_public_key(&mut self, key: PublicKey) -> Result<()> {
510 set_once(&self.subject_public_key, key, "subject_public_key")
511 }
512
513 fn mode(&mut self, mode: DiceMode) -> Result<()> {
514 set_once(&self.mode, mode, "mode")
515 }
516
517 fn code_hash(&mut self, code_hash: [u8; HASH_SIZE]) -> Result<()> {
518 set_once(&self.code_hash, code_hash, "code_hash")
519 }
520
521 fn authority_hash(&mut self, authority_hash: [u8; HASH_SIZE]) -> Result<()> {
522 set_once(&self.authority_hash, authority_hash, "authority_hash")
523 }
524
Alice Wang1cc13502023-12-05 11:05:34 +0000525 fn config_descriptor(&mut self, config_descriptor: ConfigDescriptor) -> Result<()> {
Alice Wangd3a96402023-11-24 15:37:39 +0000526 set_once(&self.config_descriptor, config_descriptor, "config_descriptor")
527 }
528
529 fn build(mut self) -> Result<DiceChainEntryPayload> {
530 let subject_public_key = take_value(&mut self.subject_public_key, "subject_public_key")?;
531 // If Mode is omitted, it should be treated as if it was NotConfigured, according to
532 // the Open Profile for DICE spec.
533 let mode = self.mode.take().unwrap_or(DiceMode::kDiceModeNotInitialized);
534 let code_hash = take_value(&mut self.code_hash, "code_hash")?;
535 let authority_hash = take_value(&mut self.authority_hash, "authority_hash")?;
536 let config_descriptor = take_value(&mut self.config_descriptor, "config_descriptor")?;
537 Ok(DiceChainEntryPayload {
538 subject_public_key,
539 mode,
540 code_hash,
541 authority_hash,
542 config_descriptor,
543 })
544 }
545}