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 the structs related to the CSR (Certificate Signing Request) 16 //! sent from the client VM to the service VM for attestation. 17 18 use alloc::vec; 19 use alloc::vec::Vec; 20 use cbor_util::{cbor_value_type, value_to_bytes}; 21 use ciborium::Value; 22 use coset::{self, CborSerializable, CoseError}; 23 24 /// Represents a CSR sent from the client VM to the service VM for attestation. 25 /// 26 /// See client_vm_csr.cddl for the definition of the CSR. 27 #[derive(Clone, Debug, Eq, PartialEq)] 28 pub struct Csr { 29 /// The DICE certificate chain of the client VM. 30 pub dice_cert_chain: Vec<u8>, 31 32 /// The signed CSR payload in COSE_Sign structure, which includes two signatures: 33 /// - one by CDI_Leaf_Priv of the client VM's DICE chain, 34 /// - another by the private key corresponding to the public key. 35 pub signed_csr_payload: Vec<u8>, 36 } 37 38 impl Csr { 39 /// Serializes this object to a CBOR-encoded vector. into_cbor_vec(self) -> coset::Result<Vec<u8>>40 pub fn into_cbor_vec(self) -> coset::Result<Vec<u8>> { 41 let value = Value::Array(vec![ 42 Value::Bytes(self.dice_cert_chain), 43 Value::Bytes(self.signed_csr_payload), 44 ]); 45 value.to_vec() 46 } 47 48 /// Creates an object instance from the provided CBOR-encoded slice. from_cbor_slice(data: &[u8]) -> coset::Result<Self>49 pub fn from_cbor_slice(data: &[u8]) -> coset::Result<Self> { 50 let value = Value::from_slice(data)?; 51 let Value::Array(mut arr) = value else { 52 return Err(CoseError::UnexpectedItem(cbor_value_type(&value), "array")); 53 }; 54 if arr.len() != 2 { 55 return Err(CoseError::UnexpectedItem("array", "array with 2 items")); 56 } 57 Ok(Self { 58 signed_csr_payload: value_to_bytes(arr.remove(1), "signed_csr_payload")?, 59 dice_cert_chain: value_to_bytes(arr.remove(0), "dice_cert_chain")?, 60 }) 61 } 62 } 63 64 /// Represents the data to be signed and sent from the client VM to the service VM 65 /// for attestation. 66 /// 67 /// It will be signed by both CDI_Leaf_Priv of the client VM's DICE chain and 68 /// the private key corresponding to the public key to be attested. 69 #[derive(Clone, Debug, Eq, PartialEq)] 70 pub struct CsrPayload { 71 /// COSE_Key encoded EC P-256 public key to be attested. 72 pub public_key: Vec<u8>, 73 74 /// A random array with a length between 0 and 64. 75 /// It will be included in the certificate chain in the attestation result, 76 /// serving as proof of the freshness of the result. 77 pub challenge: Vec<u8>, 78 } 79 80 impl CsrPayload { 81 /// Serializes this object to a CBOR-encoded vector. into_cbor_vec(self) -> coset::Result<Vec<u8>>82 pub fn into_cbor_vec(self) -> coset::Result<Vec<u8>> { 83 let value = Value::Array(vec![Value::Bytes(self.public_key), Value::Bytes(self.challenge)]); 84 value.to_vec() 85 } 86 87 /// Creates an object instance from the provided CBOR-encoded slice. from_cbor_slice(data: &[u8]) -> coset::Result<Self>88 pub fn from_cbor_slice(data: &[u8]) -> coset::Result<Self> { 89 let value = Value::from_slice(data)?; 90 let Value::Array(mut arr) = value else { 91 return Err(CoseError::UnexpectedItem(cbor_value_type(&value), "array")); 92 }; 93 if arr.len() != 2 { 94 return Err(CoseError::UnexpectedItem("array", "array with 2 items")); 95 } 96 Ok(Self { 97 challenge: value_to_bytes(arr.remove(1), "challenge")?, 98 public_key: value_to_bytes(arr.remove(0), "public_key")?, 99 }) 100 } 101 } 102