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