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 //! Generation of certificates and attestation extensions.
16 
17 use crate::dice::SubComponent;
18 use alloc::vec;
19 use alloc::vec::Vec;
20 use der::{
21     asn1::{BitString, ObjectIdentifier, OctetString, Utf8StringRef},
22     oid::AssociatedOid,
23     Decode, Sequence,
24 };
25 use spki::{AlgorithmIdentifier, SubjectPublicKeyInfo};
26 use x509_cert::{
27     certificate::{Certificate, TbsCertificate, Version},
28     ext::Extension,
29     name::Name,
30     serial_number::SerialNumber,
31     time::Validity,
32 };
33 
34 /// OID value for ECDSA with SHA-256, see RFC 5912 s6.
35 const ECDSA_WITH_SHA_256: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10045.4.3.2");
36 
37 /// OID value for the protected VM remote attestation extension.
38 ///
39 /// This OID value was added at cl/584542390.
40 const AVF_ATTESTATION_EXTENSION_V1: ObjectIdentifier =
41     ObjectIdentifier::new_unwrap("1.3.6.1.4.1.11129.2.1.29.1");
42 
43 /// Attestation extension contents
44 ///
45 /// ```asn1
46 /// AttestationExtension ::= SEQUENCE {
47 ///     attestationChallenge       OCTET_STRING,
48 ///     isVmSecure                 BOOLEAN,
49 ///     vmComponents               SEQUENCE OF VmComponent,
50 /// }
51 /// ```
52 #[derive(Debug, Clone, Sequence)]
53 pub(crate) struct AttestationExtension<'a> {
54     #[asn1(type = "OCTET STRING")]
55     attestation_challenge: &'a [u8],
56     /// Indicates whether the VM is operating under a secure configuration.
57     is_vm_secure: bool,
58     vm_components: Vec<VmComponent<'a>>,
59 }
60 
61 impl<'a> AssociatedOid for AttestationExtension<'a> {
62     const OID: ObjectIdentifier = AVF_ATTESTATION_EXTENSION_V1;
63 }
64 
65 impl<'a> AttestationExtension<'a> {
new( attestation_challenge: &'a [u8], is_vm_secure: bool, vm_components: Vec<VmComponent<'a>>, ) -> Self66     pub(crate) fn new(
67         attestation_challenge: &'a [u8],
68         is_vm_secure: bool,
69         vm_components: Vec<VmComponent<'a>>,
70     ) -> Self {
71         Self { attestation_challenge, is_vm_secure, vm_components }
72     }
73 }
74 
75 /// VM component information
76 ///
77 /// ```asn1
78 /// VmComponent ::= SEQUENCE {
79 ///    name               UTF8String,
80 ///    securityVersion    INTEGER,
81 ///    codeHash           OCTET STRING,
82 ///    authorityHash      OCTET STRING,
83 /// }
84 /// ```
85 #[derive(Debug, Clone, Sequence)]
86 pub(crate) struct VmComponent<'a> {
87     name: Utf8StringRef<'a>,
88     version: u64,
89     #[asn1(type = "OCTET STRING")]
90     code_hash: &'a [u8],
91     #[asn1(type = "OCTET STRING")]
92     authority_hash: &'a [u8],
93 }
94 
95 impl<'a> VmComponent<'a> {
new(sub_component: &'a SubComponent) -> der::Result<Self>96     pub(crate) fn new(sub_component: &'a SubComponent) -> der::Result<Self> {
97         Ok(Self {
98             name: Utf8StringRef::new(&sub_component.name)?,
99             version: sub_component.version,
100             code_hash: &sub_component.code_hash,
101             authority_hash: &sub_component.authority_hash,
102         })
103     }
104 }
105 
106 /// Builds an X.509 `Certificate` as defined in RFC 5280 Section 4.1:
107 ///
108 /// ```asn1
109 /// Certificate  ::=  SEQUENCE  {
110 ///   tbsCertificate       TBSCertificate,
111 ///   signatureAlgorithm   AlgorithmIdentifier,
112 ///   signature            BIT STRING
113 /// }
114 /// ```
build_certificate( tbs_cert: TbsCertificate, signature: &[u8], ) -> der::Result<Certificate>115 pub(crate) fn build_certificate(
116     tbs_cert: TbsCertificate,
117     signature: &[u8],
118 ) -> der::Result<Certificate> {
119     Ok(Certificate {
120         signature_algorithm: tbs_cert.signature.clone(),
121         tbs_certificate: tbs_cert,
122         signature: BitString::new(0, signature)?,
123     })
124 }
125 
126 /// Builds an X.509 `TbsCertificate` as defined in RFC 5280 Section 4.1:
127 ///
128 /// ```asn1
129 /// TBSCertificate  ::=  SEQUENCE  {
130 ///   version         [0]  EXPLICIT Version DEFAULT v1,
131 ///   serialNumber         CertificateSerialNumber,
132 ///   signature            AlgorithmIdentifier,
133 ///   issuer               Name,
134 ///   validity             Validity,
135 ///   subject              Name,
136 ///   subjectPublicKeyInfo SubjectPublicKeyInfo,
137 ///   issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
138 ///                        -- If present, version MUST be v2 or v3
139 ///   subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
140 ///                        -- If present, version MUST be v2 or v3
141 ///   extensions      [3]  Extensions OPTIONAL
142 ///                        -- If present, version MUST be v3 --
143 /// }
144 /// ```
build_tbs_certificate( serial_number: &[u8], issuer: Name, subject: Name, validity: Validity, subject_public_key_info: &[u8], attestation_ext: &[u8], ) -> der::Result<TbsCertificate>145 pub(crate) fn build_tbs_certificate(
146     serial_number: &[u8],
147     issuer: Name,
148     subject: Name,
149     validity: Validity,
150     subject_public_key_info: &[u8],
151     attestation_ext: &[u8],
152 ) -> der::Result<TbsCertificate> {
153     let signature = AlgorithmIdentifier { oid: ECDSA_WITH_SHA_256, parameters: None };
154     let subject_public_key_info = SubjectPublicKeyInfo::from_der(subject_public_key_info)?;
155     let extensions = vec![Extension {
156         extn_id: AttestationExtension::OID,
157         critical: false,
158         extn_value: OctetString::new(attestation_ext)?,
159     }];
160     Ok(TbsCertificate {
161         version: Version::V3,
162         serial_number: SerialNumber::new(serial_number)?,
163         signature,
164         issuer,
165         validity,
166         subject,
167         subject_public_key_info,
168         issuer_unique_id: None,
169         subject_unique_id: None,
170         extensions: Some(extensions),
171     })
172 }
173