blob: 97b4789985cd667c924cca30090b1b61b03b5410 [file] [log] [blame]
Shikha Panwar7c53bb32024-01-03 17:58:11 +00001/*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//! This module provides a set of sample DICE chains for testing purpose only. Note that this
18//! module duplicates a large chunk of code in libdiced_sample_inputs. We avoid modifying the
19//! latter for testing purposes because it is installed on device.
20
Shikha Panwar9e15e5e2024-01-25 11:16:28 +000021use crate::{
22 COMPONENT_NAME, COMPONENT_RESETTABLE, COMPONENT_VERSION, SUBCOMPONENT_AUTHORITY_HASH,
23 SUBCOMPONENT_CODE_HASH, SUBCOMPONENT_DESCRIPTORS, SUBCOMPONENT_NAME,
24 SUBCOMPONENT_SECURITY_VERSION,
25};
26use ciborium::{cbor, de, ser, value::Value};
Shikha Panwar7c53bb32024-01-03 17:58:11 +000027use core::ffi::CStr;
Shikha Panwar9e15e5e2024-01-25 11:16:28 +000028use coset::{
29 iana, Algorithm, AsCborValue, CborSerializable, CoseKey, KeyOperation, KeyType, Label,
30};
Shikha Panwar7c53bb32024-01-03 17:58:11 +000031use diced_open_dice::{
32 derive_cdi_private_key_seed, keypair_from_seed, retry_bcc_format_config_descriptor,
33 retry_bcc_main_flow, retry_dice_main_flow, Config, DiceArtifacts, DiceConfigValues, DiceError,
34 DiceMode, InputValues, OwnedDiceArtifacts, CDI_SIZE, HASH_SIZE, HIDDEN_SIZE,
35};
36use log::error;
37use secretkeeper_client::dice::OwnedDiceArtifactsWithExplicitKey;
38
39/// Sample UDS used to perform the root DICE flow by `make_sample_bcc_and_cdis`.
40const UDS: &[u8; CDI_SIZE] = &[
41 0x65, 0x4f, 0xab, 0xa9, 0xa5, 0xad, 0x0f, 0x5e, 0x15, 0xc3, 0x12, 0xf7, 0x77, 0x45, 0xfa, 0x55,
42 0x18, 0x6a, 0xa6, 0x34, 0xb6, 0x7c, 0x82, 0x7b, 0x89, 0x4c, 0xc5, 0x52, 0xd3, 0x27, 0x35, 0x8e,
43];
44
45const CODE_HASH_ABL: [u8; HASH_SIZE] = [
46 0x16, 0x48, 0xf2, 0x55, 0x53, 0x23, 0xdd, 0x15, 0x2e, 0x83, 0x38, 0xc3, 0x64, 0x38, 0x63, 0x26,
47 0x0f, 0xcf, 0x5b, 0xd1, 0x3a, 0xd3, 0x40, 0x3e, 0x23, 0xf8, 0x34, 0x4c, 0x6d, 0xa2, 0xbe, 0x25,
48 0x1c, 0xb0, 0x29, 0xe8, 0xc3, 0xfb, 0xb8, 0x80, 0xdc, 0xb1, 0xd2, 0xb3, 0x91, 0x4d, 0xd3, 0xfb,
49 0x01, 0x0f, 0xe4, 0xe9, 0x46, 0xa2, 0xc0, 0x26, 0x57, 0x5a, 0xba, 0x30, 0xf7, 0x15, 0x98, 0x14,
50];
51const AUTHORITY_HASH_ABL: [u8; HASH_SIZE] = [
52 0xf9, 0x00, 0x9d, 0xc2, 0x59, 0x09, 0xe0, 0xb6, 0x98, 0xbd, 0xe3, 0x97, 0x4a, 0xcb, 0x3c, 0xe7,
53 0x6b, 0x24, 0xc3, 0xe4, 0x98, 0xdd, 0xa9, 0x6a, 0x41, 0x59, 0x15, 0xb1, 0x23, 0xe6, 0xc8, 0xdf,
54 0xfb, 0x52, 0xb4, 0x52, 0xc1, 0xb9, 0x61, 0xdd, 0xbc, 0x5b, 0x37, 0x0e, 0x12, 0x12, 0xb2, 0xfd,
55 0xc1, 0x09, 0xb0, 0xcf, 0x33, 0x81, 0x4c, 0xc6, 0x29, 0x1b, 0x99, 0xea, 0xae, 0xfd, 0xaa, 0x0d,
56];
57const HIDDEN_ABL: [u8; HIDDEN_SIZE] = [
58 0xa2, 0x01, 0xd0, 0xc0, 0xaa, 0x75, 0x3c, 0x06, 0x43, 0x98, 0x6c, 0xc3, 0x5a, 0xb5, 0x5f, 0x1f,
59 0x0f, 0x92, 0x44, 0x3b, 0x0e, 0xd4, 0x29, 0x75, 0xe3, 0xdb, 0x36, 0xda, 0xc8, 0x07, 0x97, 0x4d,
60 0xff, 0xbc, 0x6a, 0xa4, 0x8a, 0xef, 0xc4, 0x7f, 0xf8, 0x61, 0x7d, 0x51, 0x4d, 0x2f, 0xdf, 0x7e,
61 0x8c, 0x3d, 0xa3, 0xfc, 0x63, 0xd4, 0xd4, 0x74, 0x8a, 0xc4, 0x14, 0x45, 0x83, 0x6b, 0x12, 0x7e,
62];
63const CODE_HASH_AVB: [u8; HASH_SIZE] = [
64 0xa4, 0x0c, 0xcb, 0xc1, 0xbf, 0xfa, 0xcc, 0xfd, 0xeb, 0xf4, 0xfc, 0x43, 0x83, 0x7f, 0x46, 0x8d,
65 0xd8, 0xd8, 0x14, 0xc1, 0x96, 0x14, 0x1f, 0x6e, 0xb3, 0xa0, 0xd9, 0x56, 0xb3, 0xbf, 0x2f, 0xfa,
66 0x88, 0x70, 0x11, 0x07, 0x39, 0xa4, 0xd2, 0xa9, 0x6b, 0x18, 0x28, 0xe8, 0x29, 0x20, 0x49, 0x0f,
67 0xbb, 0x8d, 0x08, 0x8c, 0xc6, 0x54, 0xe9, 0x71, 0xd2, 0x7e, 0xa4, 0xfe, 0x58, 0x7f, 0xd3, 0xc7,
68];
69const AUTHORITY_HASH_AVB: [u8; HASH_SIZE] = [
70 0xb2, 0x69, 0x05, 0x48, 0x56, 0xb5, 0xfa, 0x55, 0x6f, 0xac, 0x56, 0xd9, 0x02, 0x35, 0x2b, 0xaa,
71 0x4c, 0xba, 0x28, 0xdd, 0x82, 0x3a, 0x86, 0xf5, 0xd4, 0xc2, 0xf1, 0xf9, 0x35, 0x7d, 0xe4, 0x43,
72 0x13, 0xbf, 0xfe, 0xd3, 0x36, 0xd8, 0x1c, 0x12, 0x78, 0x5c, 0x9c, 0x3e, 0xf6, 0x66, 0xef, 0xab,
73 0x3d, 0x0f, 0x89, 0xa4, 0x6f, 0xc9, 0x72, 0xee, 0x73, 0x43, 0x02, 0x8a, 0xef, 0xbc, 0x05, 0x98,
74];
75const HIDDEN_AVB: [u8; HIDDEN_SIZE] = [
76 0x5b, 0x3f, 0xc9, 0x6b, 0xe3, 0x95, 0x59, 0x40, 0x5e, 0x64, 0xe5, 0x64, 0x3f, 0xfd, 0x21, 0x09,
77 0x9d, 0xf3, 0xcd, 0xc7, 0xa4, 0x2a, 0xe2, 0x97, 0xdd, 0xe2, 0x4f, 0xb0, 0x7d, 0x7e, 0xf5, 0x8e,
78 0xd6, 0x4d, 0x84, 0x25, 0x54, 0x41, 0x3f, 0x8f, 0x78, 0x64, 0x1a, 0x51, 0x27, 0x9d, 0x55, 0x8a,
79 0xe9, 0x90, 0x35, 0xab, 0x39, 0x80, 0x4b, 0x94, 0x40, 0x84, 0xa2, 0xfd, 0x73, 0xeb, 0x35, 0x7a,
80];
81const AUTHORITY_HASH_ANDROID: [u8; HASH_SIZE] = [
82 0x04, 0x25, 0x5d, 0x60, 0x5f, 0x5c, 0x45, 0x0d, 0xf2, 0x9a, 0x6e, 0x99, 0x30, 0x03, 0xb8, 0xd6,
83 0xe1, 0x99, 0x71, 0x1b, 0xf8, 0x44, 0xfa, 0xb5, 0x31, 0x79, 0x1c, 0x37, 0x68, 0x4e, 0x1d, 0xc0,
84 0x24, 0x74, 0x68, 0xf8, 0x80, 0x20, 0x3e, 0x44, 0xb1, 0x43, 0xd2, 0x9c, 0xfc, 0x12, 0x9e, 0x77,
85 0x0a, 0xde, 0x29, 0x24, 0xff, 0x2e, 0xfa, 0xc7, 0x10, 0xd5, 0x73, 0xd4, 0xc6, 0xdf, 0x62, 0x9f,
86];
87
88/// Encode the public key to CBOR Value. The input (raw 32 bytes) is wrapped into CoseKey.
89fn ed25519_public_key_to_cbor_value(public_key: &[u8]) -> Value {
90 let key = CoseKey {
91 kty: KeyType::Assigned(iana::KeyType::OKP),
92 alg: Some(Algorithm::Assigned(iana::Algorithm::EdDSA)),
93 key_ops: vec![KeyOperation::Assigned(iana::KeyOperation::Verify)].into_iter().collect(),
94 params: vec![
95 (
96 Label::Int(iana::Ec2KeyParameter::Crv as i64),
97 Value::from(iana::EllipticCurve::Ed25519 as u64),
98 ),
99 (Label::Int(iana::Ec2KeyParameter::X as i64), Value::Bytes(public_key.to_vec())),
100 ],
101 ..Default::default()
102 };
103 key.to_cbor_value().unwrap()
104}
105
106/// Makes a DICE chain (BCC) from the sample input.
107///
108/// The DICE chain is of the following format:
109/// public key derived from UDS -> ABL certificate -> AVB certificate -> Android certificate
Shikha Panwar9e15e5e2024-01-25 11:16:28 +0000110/// The `security_version` is included in the Android certificate as well as each subcomponent
111/// of AVB certificate.
Shikha Panwar7c53bb32024-01-03 17:58:11 +0000112pub fn make_explicit_owned_dice(security_version: u64) -> OwnedDiceArtifactsWithExplicitKey {
113 let dice = make_sample_bcc_and_cdis(security_version);
114 OwnedDiceArtifactsWithExplicitKey::from_owned_artifacts(dice).unwrap()
115}
116
117fn make_sample_bcc_and_cdis(security_version: u64) -> OwnedDiceArtifacts {
118 let private_key_seed = derive_cdi_private_key_seed(UDS).unwrap();
119
120 // Gets the root public key in DICE chain (BCC).
121 let (public_key, _) = keypair_from_seed(private_key_seed.as_array()).unwrap();
122 let ed25519_public_key_value = ed25519_public_key_to_cbor_value(&public_key);
123
124 // Gets the ABL certificate to as the root certificate of DICE chain.
125 let config_values = DiceConfigValues {
126 component_name: Some(CStr::from_bytes_with_nul(b"ABL\0").unwrap()),
127 component_version: Some(1),
128 resettable: true,
129 ..Default::default()
130 };
131 let config_descriptor = retry_bcc_format_config_descriptor(&config_values).unwrap();
132 let input_values = InputValues::new(
133 CODE_HASH_ABL,
134 Config::Descriptor(config_descriptor.as_slice()),
135 AUTHORITY_HASH_ABL,
136 DiceMode::kDiceModeNormal,
137 HIDDEN_ABL,
138 );
139 let (cdi_values, cert) = retry_dice_main_flow(UDS, UDS, &input_values).unwrap();
140 let bcc_value =
141 Value::Array(vec![ed25519_public_key_value, de::from_reader(&cert[..]).unwrap()]);
142 let mut bcc: Vec<u8> = vec![];
143 ser::into_writer(&bcc_value, &mut bcc).unwrap();
144
145 // Appends AVB certificate to DICE chain.
Shikha Panwar9e15e5e2024-01-25 11:16:28 +0000146 let config_desc = cbor!({
147 COMPONENT_NAME => "AVB",
148 COMPONENT_VERSION => 1,
149 COMPONENT_RESETTABLE => null,
150 SUBCOMPONENT_DESCRIPTORS => [
151 {
152 SUBCOMPONENT_NAME => "sub_1",
153 SUBCOMPONENT_SECURITY_VERSION => security_version,
154 SUBCOMPONENT_CODE_HASH=> b"xoxo",
155 SUBCOMPONENT_AUTHORITY_HASH => b"oxox"
156 },
157 {
158 SUBCOMPONENT_NAME => "sub_2",
159 SUBCOMPONENT_SECURITY_VERSION => security_version,
160 SUBCOMPONENT_CODE_HASH => b"xoxo",
161 SUBCOMPONENT_AUTHORITY_HASH => b"oxox",
162 }
163 ]
164 })
165 .unwrap()
166 .to_vec()
167 .unwrap();
Shikha Panwar7c53bb32024-01-03 17:58:11 +0000168 let input_values = InputValues::new(
169 CODE_HASH_AVB,
Shikha Panwar9e15e5e2024-01-25 11:16:28 +0000170 Config::Descriptor(&config_desc),
Shikha Panwar7c53bb32024-01-03 17:58:11 +0000171 AUTHORITY_HASH_AVB,
172 DiceMode::kDiceModeNormal,
173 HIDDEN_AVB,
174 );
175 let dice_artifacts =
176 retry_bcc_main_flow(&cdi_values.cdi_attest, &cdi_values.cdi_seal, &bcc, &input_values)
177 .unwrap();
178
179 // Appends Android certificate to DICE chain.
180 let config_values = DiceConfigValues {
181 component_name: Some(CStr::from_bytes_with_nul(b"Android\0").unwrap()),
182 component_version: Some(12),
183 security_version: Some(security_version),
184 resettable: true,
185 ..Default::default()
186 };
187 let config_descriptor = retry_bcc_format_config_descriptor(&config_values).unwrap();
188 let input_values = InputValues::new(
189 [0u8; HASH_SIZE], // code_hash
190 Config::Descriptor(config_descriptor.as_slice()),
191 AUTHORITY_HASH_ANDROID,
192 DiceMode::kDiceModeNormal,
193 [0u8; HIDDEN_SIZE], // hidden
194 );
195 retry_bcc_main_flow(
196 dice_artifacts.cdi_attest(),
197 dice_artifacts.cdi_seal(),
198 dice_artifacts
199 .bcc()
200 .ok_or_else(|| {
201 error!("bcc is none");
202 DiceError::InvalidInput
203 })
204 .unwrap(),
205 &input_values,
206 )
207 .unwrap()
208}