1/*
2 * Copyright (C) 2016 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#include <stdlib.h>
18#include <string.h>
19
20#include <gtest/gtest.h>
21
22#include <nvram/messages/nvram_messages.h>
23
24namespace nvram {
25
26namespace {
27
28template <typename Message>
29void EncodeAndDecode(const Message& in, Message* out) {
30  Blob blob;
31  ASSERT_TRUE(Encode(in, &blob));
32  ASSERT_TRUE(Decode(blob.data(), blob.size(), out));
33}
34
35}  // namespace
36
37TEST(NvramMessagesTest, GetInfoRequest) {
38  Request request;
39  request.payload.Activate<COMMAND_GET_INFO>();
40
41  Request decoded;
42  EncodeAndDecode(request, &decoded);
43
44  EXPECT_EQ(COMMAND_GET_INFO, decoded.payload.which());
45  EXPECT_TRUE(decoded.payload.get<COMMAND_GET_INFO>());
46}
47
48TEST(NvramMessagesTest, GetInfoResponse) {
49  Response response;
50  response.result = NV_RESULT_SUCCESS;
51  response.payload.Activate<COMMAND_GET_INFO>();
52
53  GetInfoResponse& response_payload =
54      response.payload.Activate<COMMAND_GET_INFO>();
55  response_payload.total_size = 32768;
56  response_payload.available_size = 4096;
57  response_payload.max_space_size = 512;
58  response_payload.max_spaces = 32;
59  ASSERT_TRUE(response_payload.space_list.Append(0x1234));
60  ASSERT_TRUE(response_payload.space_list.Append(0xffffffff));
61  ASSERT_TRUE(response_payload.space_list.Append(0x32));
62  ASSERT_TRUE(response_payload.space_list.Append(0x0));
63  ASSERT_TRUE(response_payload.space_list.Append(0x1));
64
65  Response decoded;
66  EncodeAndDecode(response, &decoded);
67
68  EXPECT_EQ(NV_RESULT_SUCCESS, response.result);
69  EXPECT_EQ(COMMAND_GET_INFO, decoded.payload.which());
70  const GetInfoResponse* decoded_payload =
71      decoded.payload.get<COMMAND_GET_INFO>();
72  ASSERT_TRUE(decoded_payload);
73
74  EXPECT_EQ(32768ULL, decoded_payload->total_size);
75  EXPECT_EQ(4096ULL, decoded_payload->available_size);
76  EXPECT_EQ(512ULL, decoded_payload->max_space_size);
77  EXPECT_EQ(32U, decoded_payload->max_spaces);
78  ASSERT_EQ(5U, decoded_payload->space_list.size());
79  EXPECT_EQ(0x1234U, decoded_payload->space_list[0]);
80  EXPECT_EQ(0xffffffffU, decoded_payload->space_list[1]);
81  EXPECT_EQ(0x32U, decoded_payload->space_list[2]);
82  EXPECT_EQ(0x0U, decoded_payload->space_list[3]);
83  EXPECT_EQ(0x1U, decoded_payload->space_list[4]);
84}
85
86TEST(NvramMessagesTest, CreateSpaceRequest) {
87  Request request;
88  CreateSpaceRequest& request_payload =
89      request.payload.Activate<COMMAND_CREATE_SPACE>();
90  request_payload.index = 0x12345678;
91  request_payload.size = 8;
92  ASSERT_TRUE(request_payload.controls.Append(NV_CONTROL_BOOT_WRITE_LOCK));
93  ASSERT_TRUE(request_payload.controls.Append(NV_CONTROL_WRITE_EXTEND));
94  const uint8_t kAuthValue[] = {1, 2, 3, 4, 5};
95  ASSERT_TRUE(request_payload.authorization_value.Assign(kAuthValue,
96                                                         sizeof(kAuthValue)));
97
98  Request decoded;
99  EncodeAndDecode(request, &decoded);
100
101  EXPECT_EQ(COMMAND_CREATE_SPACE, decoded.payload.which());
102  const CreateSpaceRequest* decoded_payload =
103      decoded.payload.get<COMMAND_CREATE_SPACE>();
104  ASSERT_TRUE(decoded_payload);
105
106  EXPECT_EQ(0x12345678U, decoded_payload->index);
107  EXPECT_EQ(8ULL, decoded_payload->size);
108  ASSERT_EQ(2UL, decoded_payload->controls.size());
109  EXPECT_EQ(NV_CONTROL_BOOT_WRITE_LOCK, decoded_payload->controls[0]);
110  EXPECT_EQ(NV_CONTROL_WRITE_EXTEND, decoded_payload->controls[1]);
111  const Blob& decoded_auth_value = decoded_payload->authorization_value;
112  ASSERT_EQ(sizeof(kAuthValue), decoded_auth_value.size());
113  EXPECT_EQ(0,
114            memcmp(kAuthValue, decoded_auth_value.data(), sizeof(kAuthValue)));
115}
116
117TEST(NvramMessagesTest, CreateSpaceResponse) {
118  Response response;
119  response.result = NV_RESULT_SPACE_ALREADY_EXISTS;
120  response.payload.Activate<COMMAND_CREATE_SPACE>();
121
122  Response decoded;
123  EncodeAndDecode(response, &decoded);
124
125  EXPECT_EQ(NV_RESULT_SPACE_ALREADY_EXISTS, response.result);
126  EXPECT_EQ(COMMAND_CREATE_SPACE, decoded.payload.which());
127  EXPECT_TRUE(decoded.payload.get<COMMAND_CREATE_SPACE>());
128}
129
130TEST(NvramMessagesTest, GetSpaceInfoRequest) {
131  Request request;
132  GetSpaceInfoRequest& request_payload =
133      request.payload.Activate<COMMAND_GET_SPACE_INFO>();
134  request_payload.index = 0x1234;
135
136  Request decoded;
137  EncodeAndDecode(request, &decoded);
138
139  EXPECT_EQ(COMMAND_GET_SPACE_INFO, decoded.payload.which());
140  const GetSpaceInfoRequest* decoded_payload =
141      decoded.payload.get<COMMAND_GET_SPACE_INFO>();
142  ASSERT_TRUE(decoded_payload);
143
144  EXPECT_EQ(0x1234U, decoded_payload->index);
145}
146
147TEST(NvramMessagesTest, GetSpaceInfoResponse) {
148  Response response;
149  response.result = NV_RESULT_SPACE_DOES_NOT_EXIST;
150  GetSpaceInfoResponse& response_payload =
151      response.payload.Activate<COMMAND_GET_SPACE_INFO>();
152  response_payload.size = 256;
153  ASSERT_TRUE(response_payload.controls.Append(NV_CONTROL_BOOT_WRITE_LOCK));
154  ASSERT_TRUE(response_payload.controls.Append(NV_CONTROL_BOOT_READ_LOCK));
155  ASSERT_TRUE(response_payload.controls.Append(NV_CONTROL_WRITE_EXTEND));
156  response_payload.read_locked = false;
157  response_payload.write_locked = true;
158
159  Response decoded;
160  EncodeAndDecode(response, &decoded);
161
162  EXPECT_EQ(NV_RESULT_SPACE_DOES_NOT_EXIST, response.result);
163  EXPECT_EQ(COMMAND_GET_SPACE_INFO, decoded.payload.which());
164  const GetSpaceInfoResponse* decoded_payload =
165      decoded.payload.get<COMMAND_GET_SPACE_INFO>();
166  ASSERT_TRUE(decoded_payload);
167
168  EXPECT_EQ(256ULL, decoded_payload->size);
169  ASSERT_EQ(3U, decoded_payload->controls.size());
170  EXPECT_EQ(NV_CONTROL_BOOT_WRITE_LOCK, decoded_payload->controls[0]);
171  EXPECT_EQ(NV_CONTROL_BOOT_READ_LOCK, decoded_payload->controls[1]);
172  EXPECT_EQ(NV_CONTROL_WRITE_EXTEND, decoded_payload->controls[2]);
173  EXPECT_FALSE(decoded_payload->read_locked);
174  EXPECT_TRUE(decoded_payload->write_locked);
175}
176
177TEST(NvramMessagesTest, DeleteSpaceRequest) {
178  Request request;
179  DeleteSpaceRequest& request_payload =
180      request.payload.Activate<COMMAND_DELETE_SPACE>();
181  request_payload.index = 0x1234;
182  const uint8_t kAuthValue[] = {1, 2, 3};
183  ASSERT_TRUE(request_payload.authorization_value.Assign(kAuthValue,
184                                                         sizeof(kAuthValue)));
185
186  Request decoded;
187  EncodeAndDecode(request, &decoded);
188
189  EXPECT_EQ(COMMAND_DELETE_SPACE, decoded.payload.which());
190  const DeleteSpaceRequest* decoded_payload =
191      decoded.payload.get<COMMAND_DELETE_SPACE>();
192  ASSERT_TRUE(decoded_payload);
193
194  EXPECT_EQ(0x1234U, decoded_payload->index);
195  const Blob& decoded_auth_value = decoded_payload->authorization_value;
196  ASSERT_EQ(sizeof(kAuthValue), decoded_auth_value.size());
197  EXPECT_EQ(0,
198            memcmp(kAuthValue, decoded_auth_value.data(), sizeof(kAuthValue)));
199}
200
201TEST(NvramMessagesTest, DeleteSpaceResponse) {
202  Response response;
203  response.result = NV_RESULT_ACCESS_DENIED;
204  response.payload.Activate<COMMAND_DELETE_SPACE>();
205
206  Response decoded;
207  EncodeAndDecode(response, &decoded);
208
209  EXPECT_EQ(NV_RESULT_ACCESS_DENIED, response.result);
210  EXPECT_EQ(COMMAND_DELETE_SPACE, decoded.payload.which());
211  EXPECT_TRUE(decoded.payload.get<COMMAND_DELETE_SPACE>());
212}
213
214TEST(NvramMessagesTest, DisableCreateRequest) {
215  Request request;
216  request.payload.Activate<COMMAND_DISABLE_CREATE>();
217
218  Request decoded;
219  EncodeAndDecode(request, &decoded);
220
221  EXPECT_EQ(COMMAND_DISABLE_CREATE, decoded.payload.which());
222  EXPECT_TRUE(decoded.payload.get<COMMAND_DISABLE_CREATE>());
223}
224
225TEST(NvramMessagesTest, DisableCreateResponse) {
226  Response response;
227  response.result = NV_RESULT_INTERNAL_ERROR;
228  response.payload.Activate<COMMAND_DISABLE_CREATE>();
229
230  Response decoded;
231  EncodeAndDecode(response, &decoded);
232
233  EXPECT_EQ(NV_RESULT_INTERNAL_ERROR, response.result);
234  EXPECT_EQ(COMMAND_DISABLE_CREATE, decoded.payload.which());
235  EXPECT_TRUE(decoded.payload.get<COMMAND_DISABLE_CREATE>());
236}
237
238TEST(NvramMessagesTest, WriteSpaceRequest) {
239  Request request;
240  WriteSpaceRequest& request_payload =
241      request.payload.Activate<COMMAND_WRITE_SPACE>();
242  request_payload.index = 0x1234;
243  const uint8_t kData[] = {17, 29, 33};
244  ASSERT_TRUE(request_payload.buffer.Assign(kData, sizeof(kData)));
245  const uint8_t kAuthValue[] = {1, 2, 3};
246  ASSERT_TRUE(request_payload.authorization_value.Assign(kAuthValue,
247                                                         sizeof(kAuthValue)));
248
249  Request decoded;
250  EncodeAndDecode(request, &decoded);
251
252  EXPECT_EQ(COMMAND_WRITE_SPACE, decoded.payload.which());
253  const WriteSpaceRequest* decoded_payload =
254      decoded.payload.get<COMMAND_WRITE_SPACE>();
255  ASSERT_TRUE(decoded_payload);
256
257  EXPECT_EQ(0x1234U, decoded_payload->index);
258  const Blob& decoded_buffer = decoded_payload->buffer;
259  ASSERT_EQ(sizeof(kData), decoded_buffer.size());
260  EXPECT_EQ(0, memcmp(kData, decoded_buffer.data(), sizeof(kData)));
261  const Blob& decoded_auth_value = decoded_payload->authorization_value;
262  ASSERT_EQ(sizeof(kAuthValue), decoded_auth_value.size());
263  EXPECT_EQ(0,
264            memcmp(kAuthValue, decoded_auth_value.data(), sizeof(kAuthValue)));
265}
266
267TEST(NvramMessagesTest, WriteSpaceResponse) {
268  Response response;
269  response.result = NV_RESULT_OPERATION_DISABLED;
270  response.payload.Activate<COMMAND_WRITE_SPACE>();
271
272  Response decoded;
273  EncodeAndDecode(response, &decoded);
274
275  EXPECT_EQ(NV_RESULT_OPERATION_DISABLED, response.result);
276  EXPECT_EQ(COMMAND_WRITE_SPACE, decoded.payload.which());
277  EXPECT_TRUE(decoded.payload.get<COMMAND_WRITE_SPACE>());
278}
279
280TEST(NvramMessagesTest, ReadSpaceRequest) {
281  Request request;
282  ReadSpaceRequest& request_payload =
283      request.payload.Activate<COMMAND_READ_SPACE>();
284  request_payload.index = 0x1234;
285  const uint8_t kAuthValue[] = {1, 2, 3};
286  ASSERT_TRUE(request_payload.authorization_value.Assign(kAuthValue,
287                                                         sizeof(kAuthValue)));
288
289  Request decoded;
290  EncodeAndDecode(request, &decoded);
291
292  EXPECT_EQ(COMMAND_READ_SPACE, decoded.payload.which());
293  const ReadSpaceRequest* decoded_payload =
294      decoded.payload.get<COMMAND_READ_SPACE>();
295  ASSERT_TRUE(decoded_payload);
296
297  EXPECT_EQ(0x1234U, decoded_payload->index);
298  const Blob& decoded_auth_value = decoded_payload->authorization_value;
299  ASSERT_EQ(sizeof(kAuthValue), decoded_auth_value.size());
300  EXPECT_EQ(0,
301            memcmp(kAuthValue, decoded_auth_value.data(), sizeof(kAuthValue)));
302}
303
304TEST(NvramMessagesTest, ReadSpaceResponse) {
305  Response response;
306  response.result = NV_RESULT_SUCCESS;
307  ReadSpaceResponse& response_payload =
308      response.payload.Activate<COMMAND_READ_SPACE>();
309  const uint8_t kData[] = {48, 0, 32, 1, 255};
310  ASSERT_TRUE(response_payload.buffer.Assign(kData, sizeof(kData)));
311
312  Response decoded;
313  EncodeAndDecode(response, &decoded);
314
315  EXPECT_EQ(NV_RESULT_SUCCESS, response.result);
316  EXPECT_EQ(COMMAND_READ_SPACE, decoded.payload.which());
317  const ReadSpaceResponse* decoded_payload =
318      decoded.payload.get<COMMAND_READ_SPACE>();
319  ASSERT_TRUE(decoded_payload);
320  const Blob& decoded_buffer = decoded_payload->buffer;
321  ASSERT_EQ(sizeof(kData), decoded_buffer.size());
322  EXPECT_EQ(0, memcmp(kData, decoded_buffer.data(), sizeof(kData)));
323}
324
325TEST(NvramMessagesTest, LockSpaceWriteRequest) {
326  Request request;
327  LockSpaceWriteRequest& request_payload =
328      request.payload.Activate<COMMAND_LOCK_SPACE_WRITE>();
329  request_payload.index = 0x1234;
330  const uint8_t kAuthValue[] = {1, 2, 3};
331  ASSERT_TRUE(request_payload.authorization_value.Assign(kAuthValue,
332                                                         sizeof(kAuthValue)));
333
334  Request decoded;
335  EncodeAndDecode(request, &decoded);
336
337  EXPECT_EQ(COMMAND_LOCK_SPACE_WRITE, decoded.payload.which());
338  const LockSpaceWriteRequest* decoded_payload =
339      decoded.payload.get<COMMAND_LOCK_SPACE_WRITE>();
340  ASSERT_TRUE(decoded_payload);
341
342  EXPECT_EQ(0x1234U, decoded_payload->index);
343  const Blob& decoded_auth_value = decoded_payload->authorization_value;
344  ASSERT_EQ(sizeof(kAuthValue), decoded_auth_value.size());
345  EXPECT_EQ(0,
346            memcmp(kAuthValue, decoded_auth_value.data(), sizeof(kAuthValue)));
347}
348
349TEST(NvramMessagesTest, LockSpaceWriteResponse) {
350  Response response;
351  response.result = NV_RESULT_SUCCESS;
352  response.payload.Activate<COMMAND_LOCK_SPACE_WRITE>();
353
354  Response decoded;
355  EncodeAndDecode(response, &decoded);
356
357  EXPECT_EQ(NV_RESULT_SUCCESS, response.result);
358  EXPECT_EQ(COMMAND_LOCK_SPACE_WRITE, decoded.payload.which());
359  EXPECT_TRUE(decoded.payload.get<COMMAND_LOCK_SPACE_WRITE>());
360}
361
362TEST(NvramMessagesTest, LockSpaceReadRequest) {
363  Request request;
364  LockSpaceReadRequest& request_payload =
365      request.payload.Activate<COMMAND_LOCK_SPACE_READ>();
366  request_payload.index = 0x1234;
367  const uint8_t kAuthValue[] = {1, 2, 3};
368  ASSERT_TRUE(request_payload.authorization_value.Assign(kAuthValue,
369                                                         sizeof(kAuthValue)));
370
371  Request decoded;
372  EncodeAndDecode(request, &decoded);
373
374  EXPECT_EQ(COMMAND_LOCK_SPACE_READ, decoded.payload.which());
375  const LockSpaceReadRequest* decoded_payload =
376      decoded.payload.get<COMMAND_LOCK_SPACE_READ>();
377  ASSERT_TRUE(decoded_payload);
378
379  EXPECT_EQ(0x1234U, decoded_payload->index);
380  const Blob& decoded_auth_value = decoded_payload->authorization_value;
381  ASSERT_EQ(sizeof(kAuthValue), decoded_auth_value.size());
382  EXPECT_EQ(0,
383            memcmp(kAuthValue, decoded_auth_value.data(), sizeof(kAuthValue)));
384}
385
386TEST(NvramMessagesTest, LockSpaceReadResponse) {
387  Response response;
388  response.result = NV_RESULT_SUCCESS;
389  response.payload.Activate<COMMAND_LOCK_SPACE_READ>();
390
391  Response decoded;
392  EncodeAndDecode(response, &decoded);
393
394  EXPECT_EQ(NV_RESULT_SUCCESS, response.result);
395  EXPECT_EQ(COMMAND_LOCK_SPACE_READ, decoded.payload.which());
396  EXPECT_TRUE(decoded.payload.get<COMMAND_LOCK_SPACE_READ>());
397}
398
399TEST(NvramMessagesTest, GarbageDecode) {
400  srand(0);
401  uint8_t random_data[1024];
402  for (size_t i = 0; i < sizeof(random_data); ++i) {
403    random_data[i] = rand() & 0xff;
404  }
405
406  // Feed the data to the decoder. The test succeeds if we don't crash.
407  for (size_t pos = 0; pos < sizeof(random_data); ++pos) {
408    for (size_t end = pos; end < sizeof(random_data); ++end) {
409      Request request;
410      Decode(random_data + pos, end - pos, &request);
411
412      Response response;
413      Decode(random_data + pos, end - pos, &response);
414    }
415  }
416}
417
418}  // namespace nvram
419