blob: e31d870eea1c6562e77a6f4bf403cd067a9e4610 [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::{
Andrew Walbran5b879eb2023-12-18 13:49:02 +000021 asn1::{BitString, ObjectIdentifier, OctetString, 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,
Andrew Walbran5b879eb2023-12-18 13:49:02 +000030 serial_number::SerialNumber,
Alice Wang20b8ebc2023-11-17 09:54:47 +000031 time::Validity,
32};
33
34/// OID value for ECDSA with SHA-256, see RFC 5912 s6.
35const 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.
40const 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
Alice Wang31302902024-03-25 10:47:53 +000046/// AttestationExtension ::= SEQUENCE {
Alice Wang20b8ebc2023-11-17 09:54:47 +000047/// attestationChallenge OCTET_STRING,
Alice Wang1cc13502023-12-05 11:05:34 +000048/// isVmSecure BOOLEAN,
49/// vmComponents SEQUENCE OF VmComponent,
Alice Wang20b8ebc2023-11-17 09:54:47 +000050/// }
51/// ```
Alice Wang20b8ebc2023-11-17 09:54:47 +000052#[derive(Debug, Clone, Sequence)]
53pub(crate) struct AttestationExtension<'a> {
54 #[asn1(type = "OCTET STRING")]
55 attestation_challenge: &'a [u8],
Alice Wangd3a96402023-11-24 15:37:39 +000056 /// Indicates whether the VM is operating under a secure configuration.
57 is_vm_secure: bool,
Alice Wang1cc13502023-12-05 11:05:34 +000058 vm_components: Vec<VmComponent<'a>>,
Alice Wang20b8ebc2023-11-17 09:54:47 +000059}
60
61impl<'a> AssociatedOid for AttestationExtension<'a> {
62 const OID: ObjectIdentifier = AVF_ATTESTATION_EXTENSION_V1;
63}
64
65impl<'a> AttestationExtension<'a> {
Alice Wang1cc13502023-12-05 11:05:34 +000066 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)]
86pub(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
95impl<'a> VmComponent<'a> {
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 })
Alice Wang20b8ebc2023-11-17 09:54:47 +0000103 }
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/// ```
Andrew Walbran5b879eb2023-12-18 13:49:02 +0000115pub(crate) fn build_certificate(
116 tbs_cert: TbsCertificate,
117 signature: &[u8],
118) -> der::Result<Certificate> {
Alice Wang20b8ebc2023-11-17 09:54:47 +0000119 Ok(Certificate {
Andrew Walbran5b879eb2023-12-18 13:49:02 +0000120 signature_algorithm: tbs_cert.signature.clone(),
Alice Wang20b8ebc2023-11-17 09:54:47 +0000121 tbs_certificate: tbs_cert,
Andrew Walbran5b879eb2023-12-18 13:49:02 +0000122 signature: BitString::new(0, signature)?,
Alice Wang20b8ebc2023-11-17 09:54:47 +0000123 })
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/// ```
Andrew Walbran5b879eb2023-12-18 13:49:02 +0000145pub(crate) fn build_tbs_certificate(
146 serial_number: &[u8],
147 issuer: Name,
148 subject: Name,
Alice Wang20b8ebc2023-11-17 09:54:47 +0000149 validity: Validity,
Andrew Walbran5b879eb2023-12-18 13:49:02 +0000150 subject_public_key_info: &[u8],
151 attestation_ext: &[u8],
152) -> der::Result<TbsCertificate> {
Alice Wang20b8ebc2023-11-17 09:54:47 +0000153 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,
Andrew Walbran5b879eb2023-12-18 13:49:02 +0000158 extn_value: OctetString::new(attestation_ext)?,
Alice Wang20b8ebc2023-11-17 09:54:47 +0000159 }];
160 Ok(TbsCertificate {
161 version: Version::V3,
Andrew Walbran5b879eb2023-12-18 13:49:02 +0000162 serial_number: SerialNumber::new(serial_number)?,
Alice Wang20b8ebc2023-11-17 09:54:47 +0000163 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}