1 use std::{collections::HashMap, fmt}; 2 3 use openssl::x509::X509; 4 5 use crate::{dice::ChainForm, rkp::DeviceInfo}; 6 7 use super::ProtectedData; 8 9 /// Represents the payload of a Certificate Signing Request 10 #[derive(Clone, Eq, PartialEq)] 11 pub struct CsrPayload { 12 /// RKP VM or other? 13 pub certificate_type: String, 14 /// Describes the device that is requesting certificates. 15 pub device_info: DeviceInfo, 16 /// The keys to attest to when doing key attestation in one buffer 17 pub keys_to_sign: Vec<u8>, 18 } 19 20 /// Represents a Certificate Signing Request that is sent to an RKP backend to request 21 /// certificates to be signed for a set of public keys. The CSR is partially generated by an 22 /// IRemotelyProvisionedComponent HAL. The set of public keys to be signed is authenticated 23 /// (signed) with a device-unique key. 24 #[derive(Clone, Eq, PartialEq)] 25 pub enum Csr { 26 /// CSR V2 was introduced in Android T. In this version, the payload is encrypted using 27 /// an Endpoint Encryption Key (EEK). 28 V2 { 29 /// Describes the device that is requesting certificates. 30 device_info: DeviceInfo, 31 /// This is the challenge that is authenticated inside the protected data. 32 challenge: Vec<u8>, 33 /// Contains the plaintext of the payload that was encrypted to an EEK. 34 protected_data: ProtectedData, 35 }, 36 /// CSR V3 was introduced in Android T. This version drops encryption of the payload. 37 V3 { 38 /// The DICE chain for the device 39 dice_chain: ChainForm, 40 /// X.509 certificate chain that certifies the dice_chain root key (UDS_pub) 41 uds_certs: HashMap<String, Vec<X509>>, 42 /// This is the challenge that is authenticated inside the signed data. 43 /// The signed data is version (3), certificate type, device info, and keys to sign 44 challenge: Vec<u8>, 45 /// csr payload 46 csr_payload: CsrPayload, 47 }, 48 } 49 50 impl Csr { 51 /// copy the DICE chain and return it 52 #[allow(dead_code)] dice_chain(&self) -> ChainForm53 pub fn dice_chain(&self) -> ChainForm { 54 match self { 55 Csr::V2 { protected_data, .. } => protected_data.dice_chain(), 56 Csr::V3 { dice_chain, .. } => dice_chain.clone(), 57 } 58 } 59 } 60 61 impl fmt::Debug for Csr { fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result62 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 63 match self { 64 Csr::V2 { device_info, challenge, protected_data } => fmt 65 .debug_struct("CSR V2") 66 .field("DeviceInfo", &device_info) 67 .field("Challenge", &hex::encode(challenge)) 68 .field("ProtectedData", &protected_data) 69 .finish(), 70 Csr::V3 { dice_chain, uds_certs, csr_payload, .. } => fmt 71 .debug_struct("CSR V3") 72 .field("DeviceInfo", &csr_payload.device_info) 73 .field("DiceChain", &dice_chain) 74 .field("UdsCerts", &uds_certs) 75 .finish(), 76 } 77 } 78 } 79