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