1 /*
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 //! Unit tests for testing serialization & deserialization of exported data_types.
18
19 use ciborium::Value;
20 use coset::CborSerializable;
21 use rdroidtest::rdroidtest;
22 use secretkeeper_comm::data_types::error::{Error, SecretkeeperError, ERROR_OK};
23 use secretkeeper_comm::data_types::packet::{RequestPacket, ResponsePacket, ResponseType};
24 use secretkeeper_comm::data_types::request::Request;
25 use secretkeeper_comm::data_types::request_response_impl::Opcode;
26 use secretkeeper_comm::data_types::request_response_impl::{
27 GetSecretRequest, GetSecretResponse, GetVersionRequest, GetVersionResponse, StoreSecretRequest,
28 StoreSecretResponse,
29 };
30 use secretkeeper_comm::data_types::response::Response;
31 use secretkeeper_comm::data_types::{Id, Secret, SeqNum};
32
33 #[rdroidtest]
request_serialization_deserialization_get_version()34 fn request_serialization_deserialization_get_version() {
35 verify_request_structure(GetVersionRequest {}, Opcode::GetVersion);
36 }
37
38 #[rdroidtest]
request_serialization_deserialization_store_secret()39 fn request_serialization_deserialization_store_secret() {
40 let req =
41 StoreSecretRequest { id: ex_id(), secret: ex_secret(), sealing_policy: ex_dice_policy() };
42 verify_request_structure(req, Opcode::StoreSecret);
43 }
44
45 #[rdroidtest]
request_serialization_deserialization_get_secret()46 fn request_serialization_deserialization_get_secret() {
47 let req = GetSecretRequest { id: ex_id(), updated_sealing_policy: Some(ex_dice_policy()) };
48 verify_request_structure(req, Opcode::GetSecret);
49
50 let req = GetSecretRequest { id: ex_id(), updated_sealing_policy: None };
51 verify_request_structure(req, Opcode::GetSecret);
52 }
53
54 #[rdroidtest]
success_response_serialization_deserialization_get_version()55 fn success_response_serialization_deserialization_get_version() {
56 let response = GetVersionResponse { version: 1 };
57 verify_response_structure(response, ResponseType::Success);
58 }
59
60 #[rdroidtest]
success_response_serialization_deserialization_store_secret()61 fn success_response_serialization_deserialization_store_secret() {
62 let response = StoreSecretResponse {};
63 verify_response_structure(response, ResponseType::Success);
64 }
65
66 #[rdroidtest]
success_response_serialization_deserialization_get_secret()67 fn success_response_serialization_deserialization_get_secret() {
68 let response = GetSecretResponse { secret: ex_secret() };
69 verify_response_structure(response, ResponseType::Success);
70 }
71
72 #[rdroidtest]
error_response_serialization_deserialization()73 fn error_response_serialization_deserialization() {
74 let response = SecretkeeperError::RequestMalformed;
75 verify_response_structure(response, ResponseType::Error);
76 }
77
verify_request_structure<R: Request + core::fmt::Debug + core::cmp::PartialEq>( req: R, expected_opcode: Opcode, )78 fn verify_request_structure<R: Request + core::fmt::Debug + core::cmp::PartialEq>(
79 req: R,
80 expected_opcode: Opcode,
81 ) {
82 let packet = req.serialize_to_packet();
83 assert_eq!(packet.opcode().unwrap(), expected_opcode);
84 let packet = packet.to_vec().unwrap();
85 let packet = RequestPacket::from_slice(&packet).unwrap();
86 let req_other_end = *R::deserialize_from_packet(packet).unwrap();
87 assert_eq!(req, req_other_end);
88 }
89
verify_response_structure<R: Response + core::fmt::Debug + core::cmp::PartialEq>( response: R, expected_response_type: ResponseType, )90 fn verify_response_structure<R: Response + core::fmt::Debug + core::cmp::PartialEq>(
91 response: R,
92 expected_response_type: ResponseType,
93 ) {
94 let packet = response.serialize_to_packet();
95 assert_eq!(packet.response_type().unwrap(), expected_response_type);
96 let packet_bytes = packet.to_vec().unwrap();
97 let packet = ResponsePacket::from_slice(&packet_bytes).unwrap();
98 let response_other_end = *R::deserialize_from_packet(packet).unwrap();
99 assert_eq!(response, response_other_end);
100 }
101
102 #[rdroidtest]
request_creation()103 fn request_creation() {
104 // GetVersionRequest
105 let _: GetVersionRequest = *Request::new(vec![]).unwrap();
106
107 // StoreSecretRequest
108 let req: StoreSecretRequest = *Request::new(vec![
109 Value::Bytes(ex_id_bytes()),
110 Value::Bytes(ex_secret_bytes()),
111 Value::Bytes(ex_dice_policy()),
112 ])
113 .unwrap();
114 assert_eq!(req.id.0, ex_id().0);
115 assert_eq!(req.secret.0, ex_secret().0);
116 assert_eq!(req.sealing_policy, ex_dice_policy());
117
118 // GetSecretRequest with an updated_sealing_policy
119 let req: GetSecretRequest =
120 *Request::new(vec![Value::Bytes(ex_id_bytes()), Value::Bytes(ex_dice_policy())]).unwrap();
121 assert_eq!(req.id.0, ex_id().0);
122 assert_eq!(req.updated_sealing_policy, Some(ex_dice_policy()));
123
124 // GetSecretRequest with no updated_sealing_policy
125 let req: GetSecretRequest =
126 *Request::new(vec![Value::Bytes(ex_id_bytes()), Value::Null]).unwrap();
127 assert_eq!(req.id.0, ex_id().0);
128 assert_eq!(req.updated_sealing_policy, None);
129 }
130
131 #[rdroidtest]
response_creation()132 fn response_creation() {
133 // GetVersionResponse
134 let res: GetVersionResponse =
135 *Response::new(vec![Value::from(ERROR_OK), Value::from(5)]).unwrap();
136 assert_eq!(res.version, 5);
137
138 // StoreSecretResponse
139 let _ = *<StoreSecretResponse as Response>::new(vec![Value::from(ERROR_OK)]).unwrap();
140
141 // GetSecretResponse
142 let res = *<GetSecretResponse as Response>::new(vec![
143 Value::from(ERROR_OK),
144 Value::Bytes(ex_secret_bytes()),
145 ])
146 .unwrap();
147 assert_eq!(res.secret.0, ex_secret().0);
148 }
149
150 #[rdroidtest]
invalid_request_creation()151 fn invalid_request_creation() {
152 // A GetVersionRequest with non-zero arg is invalid.
153 assert!(<GetVersionRequest as Request>::new(vec![Value::Null]).is_err());
154
155 // StoreSecretRequest
156 // Incorrect number of arg is invalid.
157 assert!(<StoreSecretRequest as Request>::new(vec![]).is_err(),);
158 // Incorrect arg type is invalid.
159 assert!(<StoreSecretRequest as Request>::new(vec![
160 Value::Bytes(ex_id_bytes()),
161 Value::Integer(22.into()),
162 Value::Bytes(ex_dice_policy()),
163 ])
164 .is_err());
165
166 // A GetSecretRequest
167 // Incorrect number of arg is invalid.
168 assert!(<GetSecretRequest as Request>::new(vec![]).is_err());
169 // Incorrect arg type is invalid.
170 assert!(<GetSecretRequest as Request>::new(vec![
171 Value::Integer(22.into()),
172 Value::Bytes(ex_dice_policy()),
173 ])
174 .is_err());
175 }
176
177 #[rdroidtest]
invalid_response_creation_get_version()178 fn invalid_response_creation_get_version() {
179 // A response with non-zero error_code is an invalid success response.
180 assert!(<GetVersionResponse as Response>::new(vec![
181 Value::from(SecretkeeperError::RequestMalformed as u16),
182 Value::from(5)
183 ])
184 .is_err());
185
186 // A response with incorrect size of array is invalid.
187 assert!(<GetVersionResponse as Response>::new(vec![
188 Value::from(ERROR_OK),
189 Value::from(5),
190 Value::from(7)
191 ])
192 .is_err());
193
194 // A response with incorrect type is invalid.
195 assert!(<GetVersionResponse as Response>::new(vec![
196 Value::from(ERROR_OK),
197 Value::from("a tstr")
198 ])
199 .is_err());
200 }
201
202 #[rdroidtest]
invalid_store_secret_response_creation()203 fn invalid_store_secret_response_creation() {
204 // A response with non-zero error_code is an invalid success response.
205 assert!(<StoreSecretResponse as Response>::new(vec![Value::from(
206 SecretkeeperError::RequestMalformed as u16
207 ),])
208 .is_err());
209
210 // A response with incorrect type or size of array is invalid.
211 assert!(<StoreSecretResponse as Response>::new(vec![Value::from(ERROR_OK), Value::from(7)])
212 .is_err());
213 }
214
215 #[rdroidtest]
invalid_get_secret_response_creation()216 fn invalid_get_secret_response_creation() {
217 // A response with non-zero error_code is an invalid success response.
218 assert!(<GetSecretResponse as Response>::new(vec![
219 Value::from(SecretkeeperError::RequestMalformed as u16),
220 Value::Bytes(ex_secret_bytes()),
221 ])
222 .is_err());
223
224 // A response with incorrect type or size of array is invalid.
225 assert!(
226 <GetSecretResponse as Response>::new(vec![Value::from(ERROR_OK), Value::from(7)]).is_err()
227 );
228 }
229
230 #[rdroidtest]
invalid_error_response_creation()231 fn invalid_error_response_creation() {
232 // A response with ERROR_OK(0) as the error_code is an invalid error response.
233 assert_eq!(
234 <SecretkeeperError as Response>::new(vec![Value::from(ERROR_OK)]).unwrap_err(),
235 Error::ResponseMalformed
236 );
237 }
238
239 #[rdroidtest]
seq_num_test()240 fn seq_num_test() {
241 let mut seq_b = SeqNum::new();
242 let mut seq_a = SeqNum::new();
243 assert_eq!(seq_a.get_then_increment().unwrap(), seq_b.get_then_increment().unwrap());
244 let _ = seq_a.get_then_increment().unwrap();
245 assert_ne!(seq_a.get_then_increment().unwrap(), seq_b.get_then_increment().unwrap());
246 let _ = seq_b.get_then_increment().unwrap();
247 assert_eq!(seq_a.get_then_increment().unwrap(), seq_b.get_then_increment().unwrap());
248 }
249
ex_id_bytes() -> Vec<u8>250 fn ex_id_bytes() -> Vec<u8> {
251 (b"sixty_four_bytes_in_a_sentences_can_make_it_really_really_longer").to_vec()
252 }
253
ex_secret_bytes() -> Vec<u8>254 fn ex_secret_bytes() -> Vec<u8> {
255 (*b"thirty_two_bytes_long_sentences_").to_vec()
256 }
257
ex_id() -> Id258 fn ex_id() -> Id {
259 Id(ex_id_bytes().try_into().unwrap())
260 }
261
ex_secret() -> Secret262 fn ex_secret() -> Secret {
263 Secret(ex_secret_bytes().try_into().unwrap())
264 }
265
ex_dice_policy() -> Vec<u8>266 fn ex_dice_policy() -> Vec<u8> {
267 (*b"example_dice_policy").to_vec()
268 }
269