xref: /aosp_15_r20/system/keymint/hal/src/tests.rs (revision 9860b7637a5f185913c70aa0caabe3ecb78441e4)
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