1 // 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 
17 use alloc::string::String;
18 use alloc::vec;
19 use alloc::vec::Vec;
20 use bssl_avf::{ed25519_verify, Digester, EcKey};
21 use cbor_util::{
22     cbor_value_type, get_label_value, get_label_value_as_bytes, value_to_array,
23     value_to_byte_array, value_to_bytes, value_to_map, value_to_num, value_to_text,
24 };
25 use ciborium::value::Value;
26 use core::cell::OnceCell;
27 use core::result;
28 use coset::{
29     self,
30     iana::{self, EnumI64},
31     Algorithm, AsCborValue, CborSerializable, CoseError, CoseKey, CoseSign1, KeyOperation, KeyType,
32     Label,
33 };
34 use diced_open_dice::{DiceMode, HASH_SIZE};
35 use log::{debug, error, info};
36 use service_vm_comm::RequestProcessingError;
37 
38 type Result<T> = result::Result<T, RequestProcessingError>;
39 
40 const CODE_HASH: i64 = -4670545;
41 const CONFIG_DESC: i64 = -4670548;
42 const AUTHORITY_HASH: i64 = -4670549;
43 const MODE: i64 = -4670551;
44 const SUBJECT_PUBLIC_KEY: i64 = -4670552;
45 
46 const CONFIG_DESC_COMPONENT_NAME: i64 = -70002;
47 const CONFIG_DESC_SUB_COMPONENTS: i64 = -71002;
48 
49 const SUB_COMPONENT_NAME: i64 = 1;
50 const SUB_COMPONENT_VERSION: i64 = 2;
51 const SUB_COMPONENT_CODE_HASH: i64 = 3;
52 const SUB_COMPONENT_AUTHORITY_HASH: i64 = 4;
53 
54 const KERNEL_COMPONENT_NAME: &str = "vm_entry";
55 const VENDOR_PARTITION_COMPONENT_NAME: &str = "Microdroid vendor";
56 const MICRODROID_PAYLOAD_COMPONENT_NAME: &str = "Microdroid payload";
57 
58 /// Represents a partially decoded `DiceCertChain` from the client VM.
59 /// The whole chain is defined as following:
60 ///
61 /// DiceCertChain = [
62 ///     PubKeyEd25519 / PubKeyECDSA256 / PubKeyECDSA384,  ; UDS_Pub
63 ///     + DiceChainEntry,               ; First CDI_Certificate -> Last CDI_Certificate
64 /// ]
65 #[derive(Debug, Clone)]
66 pub(crate) struct ClientVmDiceChain {
67     payloads: Vec<DiceChainEntryPayload>,
68     /// The index of the vendor partition entry in the DICE chain if it exists.
69     vendor_partition_index: Option<usize>,
70     /// The index of the kernel entry in the DICE chain.
71     kernel_index: usize,
72 }
73 
74 impl ClientVmDiceChain {
75     /// Validates the signatures of the entries in the `client_vm_dice_chain` as following:
76     ///
77     /// - The first entry of the `client_vm_dice_chain` must be signed with the root public key.
78     /// - After the first entry, each entry of the `client_vm_dice_chain` must be signed with the
79     ///   subject public key of the previous entry.
80     ///
81     /// Returns a partially decoded client VM's DICE chain if the verification succeeds.
validate_signatures_and_parse_dice_chain( mut client_vm_dice_chain: Vec<Value>, service_vm_dice_chain_len: usize, ) -> Result<Self>82     pub(crate) fn validate_signatures_and_parse_dice_chain(
83         mut client_vm_dice_chain: Vec<Value>,
84         service_vm_dice_chain_len: usize,
85     ) -> Result<Self> {
86         let has_vendor_partition =
87             vendor_partition_exists(client_vm_dice_chain.len(), service_vm_dice_chain_len)?;
88 
89         let root_public_key =
90             CoseKey::from_cbor_value(client_vm_dice_chain.remove(0))?.try_into()?;
91 
92         let mut payloads = Vec::with_capacity(client_vm_dice_chain.len());
93         let mut previous_public_key = &root_public_key;
94         for (i, value) in client_vm_dice_chain.into_iter().enumerate() {
95             let payload = DiceChainEntryPayload::validate_cose_signature_and_extract_payload(
96                 value,
97                 previous_public_key,
98             )
99             .map_err(|e| {
100                 error!("Failed to verify the DICE chain entry {}: {:?}", i, e);
101                 e
102             })?;
103             payloads.push(payload);
104             previous_public_key = &payloads.last().unwrap().subject_public_key;
105         }
106 
107         Self::build(payloads, has_vendor_partition)
108     }
109 
build( dice_entry_payloads: Vec<DiceChainEntryPayload>, has_vendor_partition: bool, ) -> Result<Self>110     fn build(
111         dice_entry_payloads: Vec<DiceChainEntryPayload>,
112         has_vendor_partition: bool,
113     ) -> Result<Self> {
114         let microdroid_payload_name =
115             &dice_entry_payloads[dice_entry_payloads.len() - 1].config_descriptor.component_name;
116         if Some(MICRODROID_PAYLOAD_COMPONENT_NAME) != microdroid_payload_name.as_deref() {
117             error!(
118                 "The last entry in the client VM DICE chain must describe the Microdroid \
119                  payload. Got '{microdroid_payload_name:?}'"
120             );
121             return Err(RequestProcessingError::InvalidDiceChain);
122         }
123 
124         let (vendor_partition_index, kernel_index) = if has_vendor_partition {
125             let index = dice_entry_payloads.len() - 2;
126             let vendor_partition_name =
127                 &dice_entry_payloads[index].config_descriptor.component_name;
128             if Some(VENDOR_PARTITION_COMPONENT_NAME) != vendor_partition_name.as_deref() {
129                 error!(
130                     "The vendor partition entry in the client VM DICE chain must describe the \
131                     vendor partition. Got '{vendor_partition_name:?}'"
132                 );
133                 return Err(RequestProcessingError::InvalidDiceChain);
134             }
135             (Some(index), index - 1)
136         } else {
137             (None, dice_entry_payloads.len() - 2)
138         };
139 
140         let kernel_name = &dice_entry_payloads[kernel_index].config_descriptor.component_name;
141         if Some(KERNEL_COMPONENT_NAME) != kernel_name.as_deref() {
142             error!(
143                 "The microdroid kernel entry in the client VM DICE chain must describe the \
144                  Microdroid kernel. Got '{kernel_name:?}'"
145             );
146             return Err(RequestProcessingError::InvalidDiceChain);
147         }
148 
149         debug!("All entries in the client VM DICE chain have correct component names");
150         Ok(Self { payloads: dice_entry_payloads, vendor_partition_index, kernel_index })
151     }
152 
microdroid_kernel(&self) -> &DiceChainEntryPayload153     pub(crate) fn microdroid_kernel(&self) -> &DiceChainEntryPayload {
154         &self.payloads[self.kernel_index]
155     }
156 
vendor_partition(&self) -> Option<&DiceChainEntryPayload>157     pub(crate) fn vendor_partition(&self) -> Option<&DiceChainEntryPayload> {
158         self.vendor_partition_index.map(|i| &self.payloads[i])
159     }
160 
microdroid_payload(&self) -> &DiceChainEntryPayload161     pub(crate) fn microdroid_payload(&self) -> &DiceChainEntryPayload {
162         &self.payloads[self.payloads.len() - 1]
163     }
164 
microdroid_payload_components(&self) -> Result<Vec<SubComponent>>165     pub(crate) fn microdroid_payload_components(&self) -> Result<Vec<SubComponent>> {
166         self.microdroid_payload().config_descriptor.sub_components()
167     }
168 
169     /// Returns true if all payloads in the DICE chain are in normal mode.
all_entries_are_secure(&self) -> bool170     pub(crate) fn all_entries_are_secure(&self) -> bool {
171         self.payloads.iter().all(|p| p.mode == DiceMode::kDiceModeNormal)
172     }
173 }
174 
vendor_partition_exists( client_vm_dice_chain_len: usize, service_vm_dice_chain_len: usize, ) -> Result<bool>175 fn vendor_partition_exists(
176     client_vm_dice_chain_len: usize,
177     service_vm_dice_chain_len: usize,
178 ) -> Result<bool> {
179     let entries_up_to_pvmfw_len = service_vm_dice_chain_len - 1;
180     // Client VM DICE chain = entries_up_to_pvmfw
181     //    + Vendor module entry (exists only when the vendor partition is present)
182     //    + Microdroid kernel entry (added in pvmfw)
183     //    + Apk/Apexes entry (added in microdroid)
184     match client_vm_dice_chain_len.checked_sub(entries_up_to_pvmfw_len) {
185         Some(2) => {
186             debug!("The vendor partition entry is not present in the client VM's DICE chain");
187             Ok(false)
188         }
189         Some(3) => {
190             info!("The vendor partition entry is present in the client VM's DICE chain");
191             Ok(true)
192         }
193         _ => {
194             error!(
195                 "The client VM's DICE chain must contain two or three extra entries. \
196             Service VM DICE chain: {} entries, client VM DICE chain: {} entries",
197                 service_vm_dice_chain_len, client_vm_dice_chain_len
198             );
199             Err(RequestProcessingError::InvalidDiceChain)
200         }
201     }
202 }
203 
204 #[derive(Debug, Clone)]
205 pub(crate) struct PublicKey(CoseKey);
206 
207 impl TryFrom<CoseKey> for PublicKey {
208     type Error = RequestProcessingError;
209 
try_from(key: CoseKey) -> Result<Self>210     fn try_from(key: CoseKey) -> Result<Self> {
211         // The public key must allow use for verification.
212         // Note that an empty key_ops set implicitly allows everything.
213         let key_ops = &key.key_ops;
214         if !key_ops.is_empty()
215             && !key_ops.contains(&KeyOperation::Assigned(iana::KeyOperation::Verify))
216         {
217             error!("Public key does not support verification - key_ops: {key_ops:?}");
218             return Err(RequestProcessingError::InvalidDiceChain);
219         }
220         Ok(Self(key))
221     }
222 }
223 
224 impl PublicKey {
225     /// Verifies the signature of the provided message with the public key.
226     ///
227     /// This function supports the following key/algorithm types as specified in
228     /// hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/
229     /// generateCertificateRequestV2.cddl:
230     ///
231     /// PubKeyEd25519 / PubKeyECDSA256 / PubKeyECDSA384
232     ///
233     /// The signature should be in the format defined by COSE in RFC 9053 section 2 for the
234     /// specific algorithm.
verify(&self, signature: &[u8], message: &[u8]) -> Result<()>235     pub(crate) fn verify(&self, signature: &[u8], message: &[u8]) -> Result<()> {
236         match &self.0.kty {
237             KeyType::Assigned(iana::KeyType::EC2) => {
238                 let public_key = EcKey::from_cose_public_key(&self.0)?;
239                 let Some(Algorithm::Assigned(alg)) = self.0.alg else {
240                     error!("Invalid algorithm in COSE key {:?}", self.0.alg);
241                     return Err(RequestProcessingError::InvalidDiceChain);
242                 };
243                 let digester = match alg {
244                     iana::Algorithm::ES256 => Digester::sha256(),
245                     iana::Algorithm::ES384 => Digester::sha384(),
246                     _ => {
247                         error!("Unsupported algorithm in EC2 key: {:?}", alg);
248                         return Err(RequestProcessingError::InvalidDiceChain);
249                     }
250                 };
251                 let digest = digester.digest(message)?;
252                 Ok(public_key.ecdsa_verify_cose(signature, &digest)?)
253             }
254             KeyType::Assigned(iana::KeyType::OKP) => {
255                 let curve_type =
256                     get_label_value(&self.0, Label::Int(iana::OkpKeyParameter::Crv.to_i64()))?;
257                 if curve_type != &Value::from(iana::EllipticCurve::Ed25519.to_i64()) {
258                     error!("Unsupported curve type in OKP COSE key: {:?}", curve_type);
259                     return Err(RequestProcessingError::OperationUnimplemented);
260                 }
261                 let x = get_label_value_as_bytes(
262                     &self.0,
263                     Label::Int(iana::OkpKeyParameter::X.to_i64()),
264                 )?;
265                 let public_key = x.try_into().map_err(|_| {
266                     error!("Invalid ED25519 public key size: {}", x.len());
267                     RequestProcessingError::InvalidDiceChain
268                 })?;
269                 let signature = signature.try_into().map_err(|_| {
270                     error!("Invalid ED25519 signature size: {}", signature.len());
271                     RequestProcessingError::InvalidDiceChain
272                 })?;
273                 Ok(ed25519_verify(message, signature, public_key)?)
274             }
275             kty => {
276                 error!("Unsupported key type in COSE key: {:?}", kty);
277                 Err(RequestProcessingError::OperationUnimplemented)
278             }
279         }
280     }
281 }
282 
283 /// Represents a partially decoded `DiceChainEntryPayload`. The whole payload is defined in:
284 ///
285 /// hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/
286 /// generateCertificateRequestV2.cddl
287 #[derive(Debug, Clone)]
288 pub(crate) struct DiceChainEntryPayload {
289     pub(crate) subject_public_key: PublicKey,
290     mode: DiceMode,
291     pub(crate) code_hash: [u8; HASH_SIZE],
292     pub(crate) authority_hash: [u8; HASH_SIZE],
293     config_descriptor: ConfigDescriptor,
294 }
295 
296 impl DiceChainEntryPayload {
297     /// Validates the signature of the provided CBOR value with the provided public key and
298     /// extracts payload from the value.
validate_cose_signature_and_extract_payload( value: Value, authority_public_key: &PublicKey, ) -> Result<Self>299     fn validate_cose_signature_and_extract_payload(
300         value: Value,
301         authority_public_key: &PublicKey,
302     ) -> Result<Self> {
303         let cose_sign1 = CoseSign1::from_cbor_value(value)?;
304         let aad = &[]; // AAD is not used in DICE chain entry.
305         cose_sign1.verify_signature(aad, |signature, message| {
306             authority_public_key.verify(signature, message)
307         })?;
308 
309         let payload = cose_sign1.payload.ok_or_else(|| {
310             error!("No payload found in the DICE chain entry");
311             RequestProcessingError::InvalidDiceChain
312         })?;
313         Self::from_slice(&payload)
314     }
315 
from_slice(data: &[u8]) -> Result<Self>316     pub(crate) fn from_slice(data: &[u8]) -> Result<Self> {
317         let entries = value_to_map(Value::from_slice(data)?, "DiceChainEntryPayload")?;
318         let mut builder = PayloadBuilder::default();
319         for (key, value) in entries.into_iter() {
320             let key: i64 = value_to_num(key, "DiceChainEntryPayload key")?;
321             match key {
322                 SUBJECT_PUBLIC_KEY => {
323                     let subject_public_key = value_to_bytes(value, "subject_public_key")?;
324                     let subject_public_key =
325                         CoseKey::from_slice(&subject_public_key)?.try_into()?;
326                     builder.subject_public_key(subject_public_key)?;
327                 }
328                 MODE => builder.mode(to_mode(value)?)?,
329                 CODE_HASH => {
330                     let code_hash = value_to_byte_array(value, "DiceChainEntryPayload code_hash")?;
331                     builder.code_hash(code_hash)?;
332                 }
333                 AUTHORITY_HASH => {
334                     let authority_hash =
335                         value_to_byte_array(value, "DiceChainEntryPayload authority_hash")?;
336                     builder.authority_hash(authority_hash)?;
337                 }
338                 CONFIG_DESC => {
339                     let config_descriptor = value_to_bytes(value, "config_descriptor")?;
340                     let config_descriptor = ConfigDescriptor::from_slice(&config_descriptor)?;
341                     builder.config_descriptor(config_descriptor)?;
342                 }
343                 _ => {}
344             }
345         }
346         builder.build()
347     }
348 }
349 /// Represents a partially decoded `ConfigurationDescriptor`.
350 ///
351 /// The whole `ConfigurationDescriptor` is defined in:
352 ///
353 /// hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/
354 /// generateCertificateRequestV2.cddl
355 #[derive(Debug, Clone, Default)]
356 pub(crate) struct ConfigDescriptor {
357     component_name: Option<String>,
358     sub_components: Option<Value>,
359 }
360 
361 impl ConfigDescriptor {
from_slice(data: &[u8]) -> Result<Self>362     fn from_slice(data: &[u8]) -> Result<Self> {
363         let value = Value::from_slice(data);
364         let Ok(value) = value else {
365             // Some DICE implementations store a hash in the config descriptor. So we just
366             // skip anything that doesn't parse correctly.
367             info!("Ignoring malformed config descriptor");
368             return Ok(Default::default());
369         };
370         let entries = value_to_map(value, "ConfigDescriptor")?;
371         let mut builder = ConfigDescriptorBuilder::default();
372         for (key, value) in entries.into_iter() {
373             let key: i64 = value_to_num(key, "ConfigDescriptor key")?;
374             match key {
375                 CONFIG_DESC_COMPONENT_NAME => {
376                     let name = value_to_text(value, "ConfigDescriptor component_name")?;
377                     builder.component_name(name)?;
378                 }
379                 CONFIG_DESC_SUB_COMPONENTS => {
380                     // If this is the Microdroid payload node then these are the subcomponents. But
381                     // for any other node it could be anything - this isn't a reserved key. So defer
382                     // decoding until we know which node is which.
383                     builder.sub_components(value)?
384                 }
385                 _ => {}
386             }
387         }
388         builder.build()
389     }
390 
391     /// Attempt to decode any Microdroid sub-components that were present in this config descriptor.
sub_components(&self) -> Result<Vec<SubComponent>>392     fn sub_components(&self) -> Result<Vec<SubComponent>> {
393         let Some(value) = &self.sub_components else {
394             return Ok(vec![]);
395         };
396         let sub_components = value_to_array(value.clone(), "ConfigDescriptor sub_components")?;
397         sub_components.into_iter().map(SubComponent::try_from).collect()
398     }
399 }
400 
401 #[derive(Debug, Clone, Default)]
402 struct ConfigDescriptorBuilder {
403     component_name: OnceCell<String>,
404     sub_components: OnceCell<Value>,
405 }
406 
407 impl ConfigDescriptorBuilder {
component_name(&mut self, component_name: String) -> Result<()>408     fn component_name(&mut self, component_name: String) -> Result<()> {
409         set_once(&self.component_name, component_name, "ConfigDescriptor component_name")
410     }
411 
sub_components(&mut self, sub_components: Value) -> Result<()>412     fn sub_components(&mut self, sub_components: Value) -> Result<()> {
413         set_once(&self.sub_components, sub_components, "ConfigDescriptor sub_components")
414     }
415 
build(mut self) -> Result<ConfigDescriptor>416     fn build(mut self) -> Result<ConfigDescriptor> {
417         let component_name = self.component_name.take();
418         let sub_components = self.sub_components.take();
419         Ok(ConfigDescriptor { component_name, sub_components })
420     }
421 }
422 
423 #[derive(Debug, Clone)]
424 pub(crate) struct SubComponent {
425     pub(crate) name: String,
426     pub(crate) version: u64,
427     pub(crate) code_hash: Vec<u8>,
428     pub(crate) authority_hash: Vec<u8>,
429 }
430 
431 impl TryFrom<Value> for SubComponent {
432     type Error = RequestProcessingError;
433 
try_from(value: Value) -> Result<Self>434     fn try_from(value: Value) -> Result<Self> {
435         let entries = value_to_map(value, "SubComponent")?;
436         let mut builder = SubComponentBuilder::default();
437         for (key, value) in entries.into_iter() {
438             let key: i64 = value_to_num(key, "SubComponent key")?;
439             match key {
440                 SUB_COMPONENT_NAME => {
441                     builder.name(value_to_text(value, "SubComponent component_name")?)?
442                 }
443                 SUB_COMPONENT_VERSION => {
444                     builder.version(value_to_num(value, "SubComponent version")?)?
445                 }
446                 SUB_COMPONENT_CODE_HASH => {
447                     builder.code_hash(value_to_bytes(value, "SubComponent code_hash")?)?
448                 }
449                 SUB_COMPONENT_AUTHORITY_HASH => {
450                     builder.authority_hash(value_to_bytes(value, "SubComponent authority_hash")?)?
451                 }
452                 k => {
453                     error!("Unknown key in SubComponent: {}", k);
454                     return Err(RequestProcessingError::InvalidDiceChain);
455                 }
456             }
457         }
458         builder.build()
459     }
460 }
461 
462 #[derive(Debug, Clone, Default)]
463 struct SubComponentBuilder {
464     name: OnceCell<String>,
465     version: OnceCell<u64>,
466     code_hash: OnceCell<Vec<u8>>,
467     authority_hash: OnceCell<Vec<u8>>,
468 }
469 
470 impl SubComponentBuilder {
name(&mut self, name: String) -> Result<()>471     fn name(&mut self, name: String) -> Result<()> {
472         set_once(&self.name, name, "SubComponent name")
473     }
474 
version(&mut self, version: u64) -> Result<()>475     fn version(&mut self, version: u64) -> Result<()> {
476         set_once(&self.version, version, "SubComponent version")
477     }
478 
code_hash(&mut self, code_hash: Vec<u8>) -> Result<()>479     fn code_hash(&mut self, code_hash: Vec<u8>) -> Result<()> {
480         set_once(&self.code_hash, code_hash, "SubComponent code_hash")
481     }
482 
authority_hash(&mut self, authority_hash: Vec<u8>) -> Result<()>483     fn authority_hash(&mut self, authority_hash: Vec<u8>) -> Result<()> {
484         set_once(&self.authority_hash, authority_hash, "SubComponent authority_hash")
485     }
486 
build(mut self) -> Result<SubComponent>487     fn build(mut self) -> Result<SubComponent> {
488         let name = take_value(&mut self.name, "SubComponent name")?;
489         let version = take_value(&mut self.version, "SubComponent version")?;
490         let code_hash = take_value(&mut self.code_hash, "SubComponent code_hash")?;
491         let authority_hash = take_value(&mut self.authority_hash, "SubComponent authority_hash")?;
492         Ok(SubComponent { name, version, code_hash, authority_hash })
493     }
494 }
495 
to_mode(value: Value) -> Result<DiceMode>496 fn to_mode(value: Value) -> Result<DiceMode> {
497     let mode = match value {
498         // Mode is supposed to be encoded as a 1-byte bstr, but some implementations instead
499         // encode it as an integer. Accept either. See b/273552826.
500         // If Mode is omitted, it should be treated as if it was NotConfigured, according to
501         // the Open Profile for DICE spec.
502         Value::Bytes(bytes) => {
503             if bytes.len() != 1 {
504                 error!("Bytes array with invalid length for mode: {:?}", bytes.len());
505                 return Err(RequestProcessingError::InvalidDiceChain);
506             }
507             bytes[0].into()
508         }
509         Value::Integer(i) => i,
510         v => return Err(CoseError::UnexpectedItem(cbor_value_type(&v), "bstr or int").into()),
511     };
512     let mode = match mode {
513         x if x == (DiceMode::kDiceModeNormal as i64).into() => DiceMode::kDiceModeNormal,
514         x if x == (DiceMode::kDiceModeDebug as i64).into() => DiceMode::kDiceModeDebug,
515         x if x == (DiceMode::kDiceModeMaintenance as i64).into() => DiceMode::kDiceModeMaintenance,
516         // If Mode is invalid, it should be treated as if it was NotConfigured, according to
517         // the Open Profile for DICE spec.
518         _ => DiceMode::kDiceModeNotInitialized,
519     };
520     Ok(mode)
521 }
522 
523 #[derive(Default, Debug, Clone)]
524 struct PayloadBuilder {
525     subject_public_key: OnceCell<PublicKey>,
526     mode: OnceCell<DiceMode>,
527     code_hash: OnceCell<[u8; HASH_SIZE]>,
528     authority_hash: OnceCell<[u8; HASH_SIZE]>,
529     config_descriptor: OnceCell<ConfigDescriptor>,
530 }
531 
set_once<T>(field: &OnceCell<T>, value: T, field_name: &str) -> Result<()>532 fn set_once<T>(field: &OnceCell<T>, value: T, field_name: &str) -> Result<()> {
533     field.set(value).map_err(|_| {
534         error!("Field '{field_name}' is duplicated in the Payload");
535         RequestProcessingError::InvalidDiceChain
536     })
537 }
538 
take_value<T>(field: &mut OnceCell<T>, field_name: &str) -> Result<T>539 fn take_value<T>(field: &mut OnceCell<T>, field_name: &str) -> Result<T> {
540     field.take().ok_or_else(|| {
541         error!("Field '{field_name}' is missing in the Payload");
542         RequestProcessingError::InvalidDiceChain
543     })
544 }
545 
546 impl PayloadBuilder {
subject_public_key(&mut self, key: PublicKey) -> Result<()>547     fn subject_public_key(&mut self, key: PublicKey) -> Result<()> {
548         set_once(&self.subject_public_key, key, "subject_public_key")
549     }
550 
mode(&mut self, mode: DiceMode) -> Result<()>551     fn mode(&mut self, mode: DiceMode) -> Result<()> {
552         set_once(&self.mode, mode, "mode")
553     }
554 
code_hash(&mut self, code_hash: [u8; HASH_SIZE]) -> Result<()>555     fn code_hash(&mut self, code_hash: [u8; HASH_SIZE]) -> Result<()> {
556         set_once(&self.code_hash, code_hash, "code_hash")
557     }
558 
authority_hash(&mut self, authority_hash: [u8; HASH_SIZE]) -> Result<()>559     fn authority_hash(&mut self, authority_hash: [u8; HASH_SIZE]) -> Result<()> {
560         set_once(&self.authority_hash, authority_hash, "authority_hash")
561     }
562 
config_descriptor(&mut self, config_descriptor: ConfigDescriptor) -> Result<()>563     fn config_descriptor(&mut self, config_descriptor: ConfigDescriptor) -> Result<()> {
564         set_once(&self.config_descriptor, config_descriptor, "config_descriptor")
565     }
566 
build(mut self) -> Result<DiceChainEntryPayload>567     fn build(mut self) -> Result<DiceChainEntryPayload> {
568         let subject_public_key = take_value(&mut self.subject_public_key, "subject_public_key")?;
569         // If Mode is omitted, it should be treated as if it was NotConfigured, according to
570         // the Open Profile for DICE spec.
571         let mode = self.mode.take().unwrap_or(DiceMode::kDiceModeNotInitialized);
572         let code_hash = take_value(&mut self.code_hash, "code_hash")?;
573         let authority_hash = take_value(&mut self.authority_hash, "authority_hash")?;
574         let config_descriptor = take_value(&mut self.config_descriptor, "config_descriptor")?;
575         Ok(DiceChainEntryPayload {
576             subject_public_key,
577             mode,
578             code_hash,
579             authority_hash,
580             config_descriptor,
581         })
582     }
583 }
584