1 // Copyright 2022, 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 use super::*;
16 use crate::{
17 binder,
18 hal::keymint::{ErrorCode::ErrorCode, IKeyMintDevice::IKeyMintDevice},
19 keymint::MAX_CBOR_OVERHEAD,
20 };
21 use kmr_wire::{
22 keymint::{
23 HardwareAuthToken, HardwareAuthenticatorType, NEXT_MESSAGE_SIGNAL_FALSE,
24 NEXT_MESSAGE_SIGNAL_TRUE,
25 },
26 secureclock::{TimeStampToken, Timestamp},
27 FinishRequest, PerformOpReq,
28 };
29 use std::sync::{Arc, Mutex};
30
31 #[derive(Clone, Debug)]
32 struct TestChannel {
33 req: Arc<Mutex<Vec<u8>>>,
34 rsp: Vec<u8>,
35 }
36
37 impl TestChannel {
new(rsp: &str) -> Self38 fn new(rsp: &str) -> Self {
39 Self { req: Arc::new(Mutex::new(vec![])), rsp: hex::decode(rsp).unwrap() }
40 }
req_data(&self) -> Vec<u8>41 fn req_data(&self) -> Vec<u8> {
42 self.req.lock().unwrap().clone()
43 }
44 }
45
46 impl SerializedChannel for TestChannel {
47 const MAX_SIZE: usize = 4096;
execute(&mut self, serialized_req: &[u8]) -> binder::Result<Vec<u8>>48 fn execute(&mut self, serialized_req: &[u8]) -> binder::Result<Vec<u8>> {
49 *self.req.lock().unwrap() = serialized_req.to_vec();
50 Ok(self.rsp.clone())
51 }
52 }
53
54 #[test]
test_method_roundtrip()55 fn test_method_roundtrip() {
56 let channel = TestChannel::new(concat!(
57 "82", // 2-arr (PerformOpResponse)
58 "00", // int (PerformOpResponse.error_code == ErrorCode::Ok)
59 "81", // 1-arr (PerformOpResponse.rsp)
60 "82", // 2-arr (PerformOpResponse.rsp.0 : PerformOpRsp)
61 "13", // 0x13 = KeyMintOperation::DEVICE_GENERATE_KEY
62 "81", // 1-arr (GenerateKeyResponse)
63 "83", // 3-arr (ret: KeyCreationResult)
64 "41", "01", // 1-bstr (KeyCreationResult.keyBlob)
65 "80", // 0-arr (KeyCreationResult.keyCharacteristics)
66 "80", // 0-arr (KeyCreationResult.certificateChain)
67 ));
68 let imp = keymint::Device::new(Arc::new(Mutex::new(channel.clone())));
69
70 let result = imp.generateKey(&[], None).unwrap();
71
72 let want_req = concat!(
73 "82", // 2-arr (PerformOpReq)
74 "13", // 0x13 = DEVICE_GENERATE_KEY
75 "82", // 1-arr (GenerateKeyRequest)
76 "80", // 0-arr (* KeyParameter)
77 "80", // 0-arr (? AttestationKey)
78 );
79 assert_eq!(channel.req_data(), hex::decode(want_req).unwrap());
80
81 assert_eq!(result.keyBlob, vec![0x01]);
82 assert!(result.keyCharacteristics.is_empty());
83 assert!(result.certificateChain.is_empty());
84 }
85
86 #[test]
test_method_err_roundtrip()87 fn test_method_err_roundtrip() {
88 let channel = TestChannel::new(concat!(
89 "82", // 2-arr (PerformOpResponse)
90 "21", // (PerformOpResponse.error_code = ErrorCode::UNSUPPORTED_PURPOSE)
91 "80", // 0-arr (PerformOpResponse.rsp)
92 ));
93 let imp = keymint::Device::new(Arc::new(Mutex::new(channel.clone())));
94
95 let result = imp.generateKey(&[], None);
96
97 let want_req = concat!(
98 "82", // 2-arr (PerformOpReq)
99 "13", // 0x13 = DEVICE_GENERATE_KEY
100 "82", // 1-arr (GenerateKeyRequest)
101 "80", // 0-arr (* KeyParameter)
102 "80", // 0-arr (? AttestationKey)
103 );
104 assert_eq!(channel.req_data(), hex::decode(want_req).unwrap());
105
106 assert!(result.is_err());
107 let status = result.unwrap_err();
108 assert_eq!(status.exception_code(), binder::ExceptionCode::SERVICE_SPECIFIC);
109 assert_eq!(status.service_specific_error(), ErrorCode::UNSUPPORTED_PURPOSE.0);
110 }
111
112 #[test]
test_overhead_size()113 fn test_overhead_size() {
114 let largest_op_req = PerformOpReq::OperationFinish(FinishRequest {
115 op_handle: 0x7fffffff,
116 input: Some(Vec::new()),
117 signature: Some(vec![0; 132]),
118 auth_token: Some(HardwareAuthToken {
119 challenge: 0x7fffffff,
120 user_id: 0x7fffffff,
121 authenticator_id: 0x7fffffff,
122 authenticator_type: HardwareAuthenticatorType::Password,
123 timestamp: Timestamp { milliseconds: 0x7fffffff },
124 mac: vec![0; 32],
125 }),
126 timestamp_token: Some(TimeStampToken {
127 challenge: 0x7fffffff,
128 timestamp: Timestamp { milliseconds: 0x7fffffff },
129 mac: vec![0; 32],
130 }),
131 confirmation_token: Some(vec![0; 32]),
132 });
133 let data = largest_op_req.into_vec().unwrap();
134 assert!(
135 data.len() < MAX_CBOR_OVERHEAD,
136 "expect largest serialized empty message (size {}) to be smaller than {}",
137 data.len(),
138 MAX_CBOR_OVERHEAD
139 );
140 }
141
142 #[test]
test_extract_rsp_true_marker()143 fn test_extract_rsp_true_marker() {
144 let msg_content = vec![0x82, 0x21, 0x80];
145 // test true marker and message content
146 let mut resp = vec![NEXT_MESSAGE_SIGNAL_TRUE];
147 resp.extend_from_slice(&msg_content);
148 assert_eq!(Ok((true, msg_content.as_slice())), extract_rsp(&resp));
149 }
150
151 #[test]
test_extract_rsp_false_marker()152 fn test_extract_rsp_false_marker() {
153 let msg_content = vec![0x82, 0x21, 0x80];
154 // test false signal and message content
155 let mut resp = vec![NEXT_MESSAGE_SIGNAL_FALSE];
156 resp.extend_from_slice(&msg_content);
157 assert_eq!(Ok((false, msg_content.as_slice())), extract_rsp(&resp));
158 }
159
160 #[test]
test_extract_rsp_empty_input()161 fn test_extract_rsp_empty_input() {
162 // test invalid (empty) input
163 let resp3 = vec![];
164 let result = extract_rsp(&resp3);
165 assert!(result.is_err());
166 let status = result.unwrap_err();
167 assert_eq!(status.exception_code(), binder::ExceptionCode::ILLEGAL_ARGUMENT);
168 }
169
170 #[test]
test_extract_rsp_single_byte_input()171 fn test_extract_rsp_single_byte_input() {
172 // test invalid (single byte) input
173 let resp4 = vec![NEXT_MESSAGE_SIGNAL_FALSE];
174 let result = extract_rsp(&resp4);
175 assert!(result.is_err());
176 let status = result.unwrap_err();
177 assert_eq!(status.exception_code(), binder::ExceptionCode::ILLEGAL_ARGUMENT);
178 }
179