blob: 3f5b68f636bf86955032619ea11c1af7377b828b [file] [log] [blame]
Janis Danisevskisda092a12021-11-17 22:58:16 -08001// Copyright 2021, 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
15use android_hardware_security_dice::aidl::android::hardware::security::dice::{
16 Config::Config as BinderConfig, InputValues::InputValues as BinderInputValues,
17 Mode::Mode as BinderMode,
18};
19use android_security_dice::aidl::android::security::dice::IDiceMaintenance::IDiceMaintenance;
20use android_security_dice::aidl::android::security::dice::IDiceNode::IDiceNode;
21use anyhow::Result;
22use binder::Strong;
23use diced_open_dice_cbor as dice;
24use nix::libc::uid_t;
25use std::convert::TryInto;
26
27static DICE_NODE_SERVICE_NAME: &str = "android.security.dice.IDiceNode";
28static DICE_MAINTENANCE_SERVICE_NAME: &str = "android.security.dice.IDiceMaintenance";
29
30fn get_dice_node() -> Strong<dyn IDiceNode> {
31 binder::get_interface(DICE_NODE_SERVICE_NAME).unwrap()
32}
33
34fn get_dice_maintenance() -> Strong<dyn IDiceMaintenance> {
35 binder::get_interface(DICE_MAINTENANCE_SERVICE_NAME).unwrap()
36}
37
38static TEST_MESSAGE: &[u8] = &[
39 // "My test message!"
40 0x4d, 0x79, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x21,
41 0x0a,
42];
43
44// This test calls derive with an empty argument vector and with a set of three input values.
45// It then performs the same three derivation steps on the result of the former and compares
46// the result to the result of the latter.
47fn equivalence_test() {
48 let node = get_dice_node();
49 let input_values = diced_sample_inputs::get_input_values_vector();
50 let former = node.derive(&[]).expect("Trying to call derive.");
51 let latter = node.derive(&input_values).expect("Trying to call derive with input values.");
52 let artifacts = diced_utils::ResidentArtifacts::new(
53 former.cdiAttest[..].try_into().unwrap(),
54 former.cdiSeal[..].try_into().unwrap(),
55 &former.bcc.data,
56 )
57 .unwrap();
58
59 let input_values: Vec<diced_utils::InputValues> =
60 input_values.iter().map(|v| v.try_into()).collect::<Result<_>>().unwrap();
61
62 let artifacts =
63 artifacts.execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues)).unwrap();
64 let (cdi_attest, cdi_seal, bcc) = artifacts.into_tuple();
65 let from_former = diced_utils::make_bcc_handover(
66 cdi_attest[..].try_into().unwrap(),
67 cdi_seal[..].try_into().unwrap(),
68 &bcc,
69 )
70 .unwrap();
71 // TODO when we have a parser/verifier, check equivalence rather
72 // than bit by bit equality.
73 assert_eq!(latter, from_former);
74}
75
76fn sign_and_verify() {
77 let node = get_dice_node();
78 let _signature = node.sign(&[], TEST_MESSAGE).expect("Trying to call sign.");
79
80 let _bcc = node.getAttestationChain(&[]).expect("Trying to call getAttestationChain.");
81 // TODO b/204938506 check the signature with the bcc when the verifier is available.
82}
83
84// This test calls derive with an empty argument vector, then demotes the itself using
85// a set of three input values, and then calls derive with empty argument vector again.
86// It then performs the same three derivation steps on the result of the former and compares
87// the result to the result of the latter.
88fn demote_test() {
89 let node = get_dice_node();
90 let input_values = diced_sample_inputs::get_input_values_vector();
91 let former = node.derive(&[]).expect("Trying to call derive.");
92 node.demote(&input_values).expect("Trying to call demote with input values.");
93
94 let latter = node.derive(&[]).expect("Trying to call derive after demote.");
95
96 let artifacts = diced_utils::ResidentArtifacts::new(
97 former.cdiAttest[..].try_into().unwrap(),
98 former.cdiSeal[..].try_into().unwrap(),
99 &former.bcc.data,
100 )
101 .unwrap();
102
103 let input_values: Vec<diced_utils::InputValues> =
104 input_values.iter().map(|v| v.try_into()).collect::<Result<_>>().unwrap();
105
106 let artifacts =
107 artifacts.execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues)).unwrap();
108 let (cdi_attest, cdi_seal, bcc) = artifacts.into_tuple();
109 let from_former = diced_utils::make_bcc_handover(
110 cdi_attest[..].try_into().unwrap(),
111 cdi_seal[..].try_into().unwrap(),
112 &bcc,
113 )
114 .unwrap();
115 // TODO b/204938506 when we have a parser/verifier, check equivalence rather
116 // than bit by bit equality.
117 assert_eq!(latter, from_former);
118}
119
120fn client_input_values(uid: uid_t) -> BinderInputValues {
121 BinderInputValues {
122 codeHash: vec![0; dice::HASH_SIZE],
123 config: BinderConfig {
124 desc: dice::bcc::format_config_descriptor(Some(&format!("{}", uid)), None, true)
125 .unwrap(),
126 },
127 authorityHash: vec![0; dice::HASH_SIZE],
128 authorityDescriptor: None,
129 mode: BinderMode::NORMAL,
130 hidden: vec![0; dice::HIDDEN_SIZE],
131 }
132}
133
134// This test calls derive with an empty argument vector `former` which look like this:
135// <common root> | <caller>
136// It then demotes diced using a set of three input values prefixed with the uid based input
137// values that diced would add to any call. It then calls derive with empty argument vector
138// again which will add another step using the identity of the caller. If diced was demoted
139// correctly the chain of `latter` will
140// look as follows:
141// <common root> | <caller> | <the three sample inputs> | <caller>
142//
143// It then performs the same three derivation steps followed by a set of caller input values
144// on `former` and compares it to `latter`.
145fn demote_self_test() {
146 let maintenance = get_dice_maintenance();
147 let node = get_dice_node();
148 let input_values = diced_sample_inputs::get_input_values_vector();
149 let former = node.derive(&[]).expect("Trying to call derive.");
150
151 let client = client_input_values(nix::unistd::getuid().into());
152
153 let mut demote_vector = vec![client.clone()];
154 demote_vector.append(&mut input_values.clone());
155 maintenance.demoteSelf(&demote_vector).expect("Trying to call demote_self with input values.");
156
157 let latter = node.derive(&[]).expect("Trying to call derive after demote.");
158
159 let artifacts = diced_utils::ResidentArtifacts::new(
160 former.cdiAttest[..].try_into().unwrap(),
161 former.cdiSeal[..].try_into().unwrap(),
162 &former.bcc.data,
163 )
164 .unwrap();
165
166 let client = [client];
167 let input_values: Vec<diced_utils::InputValues> = input_values
168 .iter()
169 .chain(client.iter())
170 .map(|v| v.try_into())
171 .collect::<Result<_>>()
172 .unwrap();
173
174 let artifacts =
175 artifacts.execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues)).unwrap();
176 let (cdi_attest, cdi_seal, bcc) = artifacts.into_tuple();
177 let from_former = diced_utils::make_bcc_handover(
178 cdi_attest[..].try_into().unwrap(),
179 cdi_seal[..].try_into().unwrap(),
180 &bcc,
181 )
182 .unwrap();
183 // TODO b/204938506 when we have a parser/verifier, check equivalence rather
184 // than bit by bit equality.
185 assert_eq!(latter, from_former);
186}
187
188#[test]
189fn run_serialized_test() {
190 equivalence_test();
191 sign_and_verify();
192 // The demote self test must run before the demote test or the test fails.
193 // And since demotion is not reversible the test can only pass once per boot.
194 demote_self_test();
195 demote_test();
196}