blob: 2baca2a64d2752d02e852a3d3450b207920691f5 [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
17use alloc::vec;
18use der::{
19 asn1::{BitStringRef, ObjectIdentifier, UIntRef},
20 oid::AssociatedOid,
21 Decode, Sequence,
22};
23use spki::{AlgorithmIdentifier, SubjectPublicKeyInfo};
24use x509_cert::{
25 certificate::{Certificate, TbsCertificate, Version},
26 ext::Extension,
27 name::Name,
28 time::Validity,
29};
30
31/// OID value for ECDSA with SHA-256, see RFC 5912 s6.
32const ECDSA_WITH_SHA_256: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10045.4.3.2");
33
34/// OID value for the protected VM remote attestation extension.
35///
36/// This OID value was added at cl/584542390.
37const AVF_ATTESTATION_EXTENSION_V1: ObjectIdentifier =
38 ObjectIdentifier::new_unwrap("1.3.6.1.4.1.11129.2.1.29.1");
39
40/// Attestation extension contents
41///
42/// ```asn1
43/// AttestationDescription ::= SEQUENCE {
44/// attestationChallenge OCTET_STRING,
45/// }
46/// ```
47/// TODO(b/312448064): Add VM root of trust and payload information to the extension.
48#[derive(Debug, Clone, Sequence)]
49pub(crate) struct AttestationExtension<'a> {
50 #[asn1(type = "OCTET STRING")]
51 attestation_challenge: &'a [u8],
Alice Wangd3a96402023-11-24 15:37:39 +000052 /// Indicates whether the VM is operating under a secure configuration.
53 is_vm_secure: bool,
Alice Wang20b8ebc2023-11-17 09:54:47 +000054}
55
56impl<'a> AssociatedOid for AttestationExtension<'a> {
57 const OID: ObjectIdentifier = AVF_ATTESTATION_EXTENSION_V1;
58}
59
60impl<'a> AttestationExtension<'a> {
Alice Wangd3a96402023-11-24 15:37:39 +000061 pub(crate) fn new(attestation_challenge: &'a [u8], is_vm_secure: bool) -> Self {
62 Self { attestation_challenge, is_vm_secure }
Alice Wang20b8ebc2023-11-17 09:54:47 +000063 }
64}
65
66/// Builds an X.509 `Certificate` as defined in RFC 5280 Section 4.1:
67///
68/// ```asn1
69/// Certificate ::= SEQUENCE {
70/// tbsCertificate TBSCertificate,
71/// signatureAlgorithm AlgorithmIdentifier,
72/// signature BIT STRING
73/// }
74/// ```
75pub(crate) fn build_certificate<'a>(
76 tbs_cert: TbsCertificate<'a>,
77 signature: &'a [u8],
78) -> der::Result<Certificate<'a>> {
79 Ok(Certificate {
80 signature_algorithm: tbs_cert.signature,
81 tbs_certificate: tbs_cert,
82 signature: BitStringRef::new(0, signature)?,
83 })
84}
85
86/// Builds an X.509 `TbsCertificate` as defined in RFC 5280 Section 4.1:
87///
88/// ```asn1
89/// TBSCertificate ::= SEQUENCE {
90/// version [0] EXPLICIT Version DEFAULT v1,
91/// serialNumber CertificateSerialNumber,
92/// signature AlgorithmIdentifier,
93/// issuer Name,
94/// validity Validity,
95/// subject Name,
96/// subjectPublicKeyInfo SubjectPublicKeyInfo,
97/// issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
98/// -- If present, version MUST be v2 or v3
99/// subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
100/// -- If present, version MUST be v2 or v3
101/// extensions [3] Extensions OPTIONAL
102/// -- If present, version MUST be v3 --
103/// }
104/// ```
105pub(crate) fn build_tbs_certificate<'a>(
106 serial_number: &'a [u8],
107 issuer: Name<'a>,
108 subject: Name<'a>,
109 validity: Validity,
110 subject_public_key_info: &'a [u8],
111 attestation_ext: &'a [u8],
112) -> der::Result<TbsCertificate<'a>> {
113 let signature = AlgorithmIdentifier { oid: ECDSA_WITH_SHA_256, parameters: None };
114 let subject_public_key_info = SubjectPublicKeyInfo::from_der(subject_public_key_info)?;
115 let extensions = vec![Extension {
116 extn_id: AttestationExtension::OID,
117 critical: false,
118 extn_value: attestation_ext,
119 }];
120 Ok(TbsCertificate {
121 version: Version::V3,
122 serial_number: UIntRef::new(serial_number)?,
123 signature,
124 issuer,
125 validity,
126 subject,
127 subject_public_key_info,
128 issuer_unique_id: None,
129 subject_unique_id: None,
130 extensions: Some(extensions),
131 })
132}