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 #if defined(HAS_GTEST)
18 #include <gtest/gtest.h>
19 #else
20 #include "gtest_stubs.h"
21 #endif
22 
23 #include <string.h>
24 
25 #include <nvram/core/nvram_manager.h>
26 #include <nvram/core/persistence.h>
27 
28 #include "fake_storage.h"
29 
30 namespace nvram {
31 namespace {
32 
33 class NvramManagerTest : public testing::Test {
34  protected:
NvramManagerTest()35   NvramManagerTest() {
36     storage::Clear();
37   }
38 
SetupHeader(uint32_t header_version,uint32_t index)39   static void SetupHeader(uint32_t header_version, uint32_t index) {
40     NvramHeader header;
41     header.version = header_version;
42     ASSERT_TRUE(header.allocated_indices.Resize(1));
43     header.allocated_indices[0] = index;
44     ASSERT_EQ(storage::Status::kSuccess, persistence::StoreHeader(header));
45   }
46 
ReadAndCompareSpaceData(NvramManager * nvram,uint32_t index,const void * expected_contents,size_t expected_size)47   static void ReadAndCompareSpaceData(NvramManager* nvram,
48                                       uint32_t index,
49                                       const void* expected_contents,
50                                       size_t expected_size) {
51     ReadSpaceRequest read_space_request;
52     read_space_request.index = index;
53     ReadSpaceResponse read_space_response;
54     EXPECT_EQ(NV_RESULT_SUCCESS,
55               nvram->ReadSpace(read_space_request, &read_space_response));
56     ASSERT_EQ(expected_size, read_space_response.buffer.size());
57     EXPECT_EQ(0, memcmp(read_space_response.buffer.data(), expected_contents,
58                         expected_size));
59   }
60 
GetControlsMask(const Vector<nvram_control_t> & controls)61   static uint32_t GetControlsMask(const Vector<nvram_control_t>& controls) {
62     uint32_t mask = 0;
63     for (nvram_control_t control : controls) {
64       mask |= (1 << control);
65     }
66     return mask;
67   }
68 };
69 
TEST_F(NvramManagerTest,Init_FromScratch)70 TEST_F(NvramManagerTest, Init_FromScratch) {
71   NvramManager nvram;
72 
73   GetSpaceInfoRequest get_space_info_request;
74   get_space_info_request.index = 1;
75   GetSpaceInfoResponse get_space_info_response;
76   EXPECT_EQ(
77       NV_RESULT_SPACE_DOES_NOT_EXIST,
78       nvram.GetSpaceInfo(get_space_info_request, &get_space_info_response));
79 }
80 
TEST_F(NvramManagerTest,Init_TrailingStorageBytes)81 TEST_F(NvramManagerTest, Init_TrailingStorageBytes) {
82   // Set up a pre-existing space and add some trailing bytes.
83   NvramSpace space;
84   ASSERT_TRUE(space.contents.Resize(10));
85   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(1, space));
86   Blob space_blob;
87   ASSERT_EQ(storage::Status::kSuccess, storage::LoadSpace(1, &space_blob));
88   ASSERT_TRUE(space_blob.Resize(space_blob.size() + 10));
89   ASSERT_EQ(storage::Status::kSuccess, storage::StoreSpace(1, space_blob));
90 
91   // Produce a matching header and append some trailing bytes.
92   NvramHeader header;
93   header.version = NvramHeader::kVersion;
94   ASSERT_TRUE(header.allocated_indices.Resize(1));
95   header.allocated_indices[0] = 1;
96   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreHeader(header));
97   Blob header_blob;
98   ASSERT_EQ(storage::Status::kSuccess, storage::LoadHeader(&header_blob));
99   ASSERT_TRUE(header_blob.Resize(header_blob.size() + 10));
100   ASSERT_EQ(storage::Status::kSuccess, storage::StoreHeader(header_blob));
101 
102   // Initialize the |NvramManager| and check that the header and space blobs get
103   // loaded successfully.
104   NvramManager nvram;
105 
106   GetInfoRequest get_info_request;
107   GetInfoResponse get_info_response;
108   EXPECT_EQ(NV_RESULT_SUCCESS,
109             nvram.GetInfo(get_info_request, &get_info_response));
110   ASSERT_EQ(1U, get_info_response.space_list.size());
111   EXPECT_EQ(1U, get_info_response.space_list[0]);
112 
113   GetSpaceInfoRequest get_space_info_request;
114   get_space_info_request.index = 1;
115   GetSpaceInfoResponse get_space_info_response;
116   EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
117                                                   &get_space_info_response));
118   EXPECT_EQ(10U, get_space_info_response.size);
119 }
120 
TEST_F(NvramManagerTest,Init_SpacesPresent)121 TEST_F(NvramManagerTest, Init_SpacesPresent) {
122   // Set up two pre-existing spaces.
123   NvramSpace space;
124   ASSERT_TRUE(space.contents.Resize(10));
125   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(1, space));
126   ASSERT_TRUE(space.contents.Resize(20));
127   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(2, space));
128 
129   // Indicate 3 present spaces in the header, including one that doesn't have
130   // space data in storage.
131   NvramHeader header;
132   header.version = NvramHeader::kVersion;
133   ASSERT_TRUE(header.allocated_indices.Resize(3));
134   header.allocated_indices[0] = 1;
135   header.allocated_indices[1] = 2;
136   header.allocated_indices[2] = 3;
137   header.provisional_index.Activate() = 4;
138   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreHeader(header));
139 
140   NvramManager nvram;
141 
142   // Check that the spaces are correctly recovered.
143   GetSpaceInfoRequest get_space_info_request;
144   get_space_info_request.index = 1;
145   GetSpaceInfoResponse get_space_info_response;
146   EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
147                                                   &get_space_info_response));
148   EXPECT_EQ(10u, get_space_info_response.size);
149 
150   get_space_info_request.index = 2;
151   EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
152                                                   &get_space_info_response));
153   EXPECT_EQ(20u, get_space_info_response.size);
154 
155   get_space_info_request.index = 3;
156   EXPECT_EQ(
157       NV_RESULT_INTERNAL_ERROR,
158       nvram.GetSpaceInfo(get_space_info_request, &get_space_info_response));
159 
160   get_space_info_request.index = 4;
161   EXPECT_EQ(
162       NV_RESULT_SPACE_DOES_NOT_EXIST,
163       nvram.GetSpaceInfo(get_space_info_request, &get_space_info_response));
164 }
165 
TEST_F(NvramManagerTest,Init_BadSpacePresent)166 TEST_F(NvramManagerTest, Init_BadSpacePresent) {
167   // Set up a good and a bad NVRAM space.
168   NvramSpace space;
169   ASSERT_TRUE(space.contents.Resize(10));
170   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(1, space));
171   const uint8_t kBadSpaceData[] = {0xba, 0xad};
172   Blob bad_space_blob;
173   ASSERT_TRUE(bad_space_blob.Assign(kBadSpaceData, sizeof(kBadSpaceData)));
174   ASSERT_EQ(storage::Status::kSuccess,
175             storage::StoreSpace(2, bad_space_blob));
176 
177   NvramHeader header;
178   header.version = NvramHeader::kVersion;
179   ASSERT_TRUE(header.allocated_indices.Resize(2));
180   header.allocated_indices[0] = 1;
181   header.allocated_indices[1] = 2;
182   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreHeader(header));
183 
184   NvramManager nvram;
185 
186   // The bad index will fail requests.
187   GetSpaceInfoRequest get_space_info_request;
188   get_space_info_request.index = 2;
189   GetSpaceInfoResponse get_space_info_response;
190   nvram_result_t result =
191       nvram.GetSpaceInfo(get_space_info_request, &get_space_info_response);
192   EXPECT_NE(NV_RESULT_SUCCESS, result);
193   EXPECT_NE(NV_RESULT_SPACE_DOES_NOT_EXIST, result);
194 
195   // A request to get info for the good index should succeed.
196   get_space_info_request.index = 1;
197   EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
198                                                   &get_space_info_response));
199   EXPECT_EQ(10u, get_space_info_response.size);
200 }
201 
TEST_F(NvramManagerTest,Init_NewerStorageVersion)202 TEST_F(NvramManagerTest, Init_NewerStorageVersion) {
203   // Set up an NVRAM space.
204   NvramSpace space;
205   ASSERT_TRUE(space.contents.Resize(10));
206   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(1, space));
207 
208   SetupHeader(NvramHeader::kVersion + 1, 1);
209 
210   NvramManager nvram;
211 
212   // Requests should fail due to version mismatch.
213   GetSpaceInfoRequest get_space_info_request;
214   get_space_info_request.index = 1;
215   GetSpaceInfoResponse get_space_info_response;
216   EXPECT_EQ(
217       NV_RESULT_INTERNAL_ERROR,
218       nvram.GetSpaceInfo(get_space_info_request, &get_space_info_response));
219 }
220 
TEST_F(NvramManagerTest,Init_StorageObjectTypeMismatch)221 TEST_F(NvramManagerTest, Init_StorageObjectTypeMismatch) {
222   // Set up an NVRAM space.
223   NvramSpace space;
224   ASSERT_TRUE(space.contents.Resize(10));
225   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(1, space));
226 
227   // Copy the space blob to the header storage.
228   Blob space_blob;
229   ASSERT_EQ(storage::Status::kSuccess, storage::LoadSpace(1, &space_blob));
230   ASSERT_EQ(storage::Status::kSuccess, storage::StoreHeader(space_blob));
231 
232   NvramManager nvram;
233 
234   // Initialization should detect that the header storage object doesn't look
235   // like a header, so initialization should fail.
236   GetInfoRequest get_info_request;
237   GetInfoResponse get_info_response;
238   EXPECT_EQ(NV_RESULT_INTERNAL_ERROR,
239             nvram.GetInfo(get_info_request, &get_info_response));
240 }
241 
TEST_F(NvramManagerTest,CreateSpace_Success)242 TEST_F(NvramManagerTest, CreateSpace_Success) {
243   NvramManager nvram;
244 
245   // Make a call to CreateSpace, which should succeed.
246   CreateSpaceRequest create_space_request;
247   create_space_request.index = 1;
248   create_space_request.size = 32;
249   ASSERT_TRUE(create_space_request.controls.Resize(5));
250   create_space_request.controls[0] = NV_CONTROL_BOOT_WRITE_LOCK;
251   create_space_request.controls[1] = NV_CONTROL_BOOT_READ_LOCK;
252   create_space_request.controls[2] = NV_CONTROL_WRITE_AUTHORIZATION;
253   create_space_request.controls[3] = NV_CONTROL_READ_AUTHORIZATION;
254   create_space_request.controls[4] = NV_CONTROL_WRITE_EXTEND;
255 
256   CreateSpaceResponse create_space_response;
257   EXPECT_EQ(NV_RESULT_SUCCESS,
258             nvram.CreateSpace(create_space_request, &create_space_response));
259 
260   // GetSpaceInfo should reflect the space parameters set during creation.
261   GetSpaceInfoRequest get_space_info_request;
262   get_space_info_request.index = 1;
263   GetSpaceInfoResponse get_space_info_response;
264   EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
265                                                   &get_space_info_response));
266 
267   EXPECT_EQ(32u, get_space_info_response.size);
268   EXPECT_EQ(GetControlsMask(create_space_request.controls),
269             GetControlsMask(get_space_info_response.controls));
270   EXPECT_EQ(false, get_space_info_response.read_locked);
271   EXPECT_EQ(false, get_space_info_response.write_locked);
272 }
273 
TEST_F(NvramManagerTest,CreateSpace_Existing)274 TEST_F(NvramManagerTest, CreateSpace_Existing) {
275   // Set up an NVRAM space.
276   NvramSpace space;
277   ASSERT_TRUE(space.contents.Resize(10));
278   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(1, space));
279 
280   SetupHeader(NvramHeader::kVersion, 1);
281 
282   NvramManager nvram;
283 
284   // A request to create another space with the same index should fail.
285   CreateSpaceRequest create_space_request;
286   create_space_request.index = 1;
287   create_space_request.size = 16;
288 
289   CreateSpaceResponse create_space_response;
290   EXPECT_EQ(NV_RESULT_SPACE_ALREADY_EXISTS,
291             nvram.CreateSpace(create_space_request, &create_space_response));
292 }
293 
TEST_F(NvramManagerTest,CreateSpace_TooLarge)294 TEST_F(NvramManagerTest, CreateSpace_TooLarge) {
295   NvramManager nvram;
296 
297   // A request to create a space with a too large content size should fail.
298   CreateSpaceRequest create_space_request;
299   create_space_request.index = 1;
300   create_space_request.size = 16384;
301 
302   CreateSpaceResponse create_space_response;
303   EXPECT_EQ(NV_RESULT_INVALID_PARAMETER,
304             nvram.CreateSpace(create_space_request, &create_space_response));
305 }
306 
TEST_F(NvramManagerTest,CreateSpace_AuthTooLarge)307 TEST_F(NvramManagerTest, CreateSpace_AuthTooLarge) {
308   NvramManager nvram;
309 
310   // A request to create a space with a too large authorization value size
311   // should fail.
312   CreateSpaceRequest create_space_request;
313   create_space_request.index = 1;
314   ASSERT_TRUE(create_space_request.authorization_value.Resize(256));
315 
316   CreateSpaceResponse create_space_response;
317   EXPECT_EQ(NV_RESULT_INVALID_PARAMETER,
318             nvram.CreateSpace(create_space_request, &create_space_response));
319 }
320 
TEST_F(NvramManagerTest,CreateSpace_BadControl)321 TEST_F(NvramManagerTest, CreateSpace_BadControl) {
322   NvramManager nvram;
323 
324   // A request to create a space with an unknown control value should fail.
325   CreateSpaceRequest create_space_request;
326   create_space_request.index = 1;
327   create_space_request.size = 16;
328   ASSERT_TRUE(create_space_request.controls.Resize(2));
329   create_space_request.controls[0] = NV_CONTROL_BOOT_WRITE_LOCK;
330   create_space_request.controls[1] = 17;
331 
332   CreateSpaceResponse create_space_response;
333   EXPECT_EQ(NV_RESULT_INVALID_PARAMETER,
334             nvram.CreateSpace(create_space_request, &create_space_response));
335 }
336 
TEST_F(NvramManagerTest,CreateSpace_ControlWriteLockExclusive)337 TEST_F(NvramManagerTest, CreateSpace_ControlWriteLockExclusive) {
338   NvramManager nvram;
339 
340   // Spaces may not be created with conflicting write lock modes.
341   CreateSpaceRequest create_space_request;
342   create_space_request.index = 1;
343   create_space_request.size = 16;
344   ASSERT_TRUE(create_space_request.controls.Resize(2));
345   create_space_request.controls[0] = NV_CONTROL_BOOT_WRITE_LOCK;
346   create_space_request.controls[1] = NV_CONTROL_PERSISTENT_WRITE_LOCK;
347 
348   CreateSpaceResponse create_space_response;
349   EXPECT_EQ(NV_RESULT_INVALID_PARAMETER,
350             nvram.CreateSpace(create_space_request, &create_space_response));
351 }
352 
TEST_F(NvramManagerTest,CreateSpace_WriteExtendSpaceSize)353 TEST_F(NvramManagerTest, CreateSpace_WriteExtendSpaceSize) {
354   NvramManager nvram;
355 
356   // Write-extend spaces must match SHA256 hash size, i.e. 32 bytes.
357   CreateSpaceRequest create_space_request;
358   create_space_request.index = 1;
359   create_space_request.size = 16;
360   ASSERT_TRUE(create_space_request.controls.Resize(1));
361   create_space_request.controls[0] = NV_CONTROL_WRITE_EXTEND;
362 
363   CreateSpaceResponse create_space_response;
364   EXPECT_EQ(NV_RESULT_INVALID_PARAMETER,
365             nvram.CreateSpace(create_space_request, &create_space_response));
366 }
367 
TEST_F(NvramManagerTest,CreateSpace_HeaderWriteError)368 TEST_F(NvramManagerTest, CreateSpace_HeaderWriteError) {
369   // If the header fails to get written to storage, the creation request should
370   // fail.
371   storage::SetHeaderWriteError(true);
372 
373   NvramManager nvram;
374 
375   CreateSpaceRequest create_space_request;
376   create_space_request.index = 1;
377   create_space_request.size = 16;
378 
379   CreateSpaceResponse create_space_response;
380   EXPECT_EQ(NV_RESULT_INTERNAL_ERROR,
381             nvram.CreateSpace(create_space_request, &create_space_response));
382 
383   // The space shouldn't be present.
384   GetInfoRequest get_info_request;
385   GetInfoResponse get_info_response;
386   EXPECT_EQ(NV_RESULT_SUCCESS,
387             nvram.GetInfo(get_info_request, &get_info_response));
388   EXPECT_EQ(0U, get_info_response.space_list.size());
389 
390   // Creation of the space after clearing the error should work.
391   storage::SetHeaderWriteError(false);
392   EXPECT_EQ(NV_RESULT_SUCCESS,
393             nvram.CreateSpace(create_space_request, &create_space_response));
394 
395   // The space should be reported as allocated now.
396   EXPECT_EQ(NV_RESULT_SUCCESS,
397             nvram.GetInfo(get_info_request, &get_info_response));
398   ASSERT_EQ(1U, get_info_response.space_list.size());
399   EXPECT_EQ(1U, get_info_response.space_list[0]);
400 }
401 
TEST_F(NvramManagerTest,CreateSpace_SpaceWriteError)402 TEST_F(NvramManagerTest, CreateSpace_SpaceWriteError) {
403   storage::SetSpaceWriteError(1, true);
404   NvramManager nvram;
405 
406   // A request to create another space with the same index should fail.
407   CreateSpaceRequest create_space_request;
408   create_space_request.index = 1;
409   create_space_request.size = 16;
410 
411   CreateSpaceResponse create_space_response;
412   EXPECT_EQ(NV_RESULT_INTERNAL_ERROR,
413             nvram.CreateSpace(create_space_request, &create_space_response));
414 
415   // Reloading the state after a crash should not show any traces of the space.
416   storage::SetSpaceWriteError(1, false);
417   NvramManager nvram2;
418 
419   // The space shouldn't exist in the space list.
420   GetInfoRequest get_info_request;
421   GetInfoResponse get_info_response;
422   EXPECT_EQ(NV_RESULT_SUCCESS,
423             nvram2.GetInfo(get_info_request, &get_info_response));
424 
425   EXPECT_EQ(0U, get_info_response.space_list.size());
426 
427   // The space info request should indicate the space doesn't exist.
428   GetSpaceInfoRequest get_space_info_request;
429   get_space_info_request.index = 1;
430   GetSpaceInfoResponse get_space_info_response;
431   EXPECT_EQ(
432       NV_RESULT_SPACE_DOES_NOT_EXIST,
433       nvram2.GetSpaceInfo(get_space_info_request, &get_space_info_response));
434 }
435 
TEST_F(NvramManagerTest,DeleteSpace_SpaceAbsent)436 TEST_F(NvramManagerTest, DeleteSpace_SpaceAbsent) {
437   NvramManager nvram;
438 
439   // Attempt to delete a non-existing space.
440   DeleteSpaceRequest delete_space_request;
441   delete_space_request.index = 42;
442   DeleteSpaceResponse delete_space_response;
443   EXPECT_EQ(NV_RESULT_SPACE_DOES_NOT_EXIST,
444             nvram.DeleteSpace(delete_space_request, &delete_space_response));
445 }
446 
TEST_F(NvramManagerTest,DeleteSpace_Success)447 TEST_F(NvramManagerTest, DeleteSpace_Success) {
448   // Set up an NVRAM space.
449   NvramSpace space;
450   ASSERT_TRUE(space.contents.Resize(10));
451   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(42, space));
452   SetupHeader(NvramHeader::kVersion, 42);
453 
454   NvramManager nvram;
455 
456   // Successful deletion.
457   DeleteSpaceRequest delete_space_request;
458   delete_space_request.index = 42;
459   DeleteSpaceResponse delete_space_response;
460   EXPECT_EQ(NV_RESULT_SUCCESS,
461             nvram.DeleteSpace(delete_space_request, &delete_space_response));
462 }
463 
TEST_F(NvramManagerTest,DeleteSpace_AuthorizationFailure)464 TEST_F(NvramManagerTest, DeleteSpace_AuthorizationFailure) {
465   // Set up an NVRAM space.
466   NvramSpace space;
467   space.controls = (1 << NV_CONTROL_WRITE_AUTHORIZATION);
468   const char kAuthorizationValue[] = "secret";
469   ASSERT_TRUE(space.authorization_value.Assign(kAuthorizationValue,
470                                                sizeof(kAuthorizationValue)));
471   ASSERT_TRUE(space.contents.Resize(10));
472   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(42, space));
473   SetupHeader(NvramHeader::kVersion, 42);
474 
475   NvramManager nvram;
476 
477   // Deletion should fail if correct secret is not provided.
478   DeleteSpaceRequest delete_space_request;
479   delete_space_request.index = 42;
480   DeleteSpaceResponse delete_space_response;
481   EXPECT_EQ(NV_RESULT_ACCESS_DENIED,
482             nvram.DeleteSpace(delete_space_request, &delete_space_response));
483 }
484 
TEST_F(NvramManagerTest,DeleteSpace_HalfDeleted)485 TEST_F(NvramManagerTest, DeleteSpace_HalfDeleted) {
486   // Set up an NVRAM space.
487   NvramSpace space;
488   ASSERT_TRUE(space.contents.Resize(10));
489   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(42, space));
490   SetupHeader(NvramHeader::kVersion, 42);
491 
492   // Hold on to the space data.
493   Blob space_data;
494   ASSERT_EQ(storage::Status::kSuccess, storage::LoadSpace(42, &space_data));
495 
496   NvramManager nvram;
497 
498   // Delete the space.
499   DeleteSpaceRequest delete_space_request;
500   delete_space_request.index = 42;
501   DeleteSpaceResponse delete_space_response;
502   EXPECT_EQ(NV_RESULT_SUCCESS,
503             nvram.DeleteSpace(delete_space_request, &delete_space_response));
504 
505   // Put the space data back into place to simulate a half-completed deletion.
506   ASSERT_EQ(storage::Status::kSuccess, storage::StoreSpace(42, space_data));
507 
508   // The space should remain deleted after re-initialization.
509   NvramManager nvram2;
510 
511   GetSpaceInfoRequest get_space_info_request;
512   get_space_info_request.index = 42;
513   GetSpaceInfoResponse get_space_info_response;
514   EXPECT_EQ(
515       NV_RESULT_SPACE_DOES_NOT_EXIST,
516       nvram2.GetSpaceInfo(get_space_info_request, &get_space_info_response));
517 
518   // Re-creation of a space with the same index should work.
519   CreateSpaceRequest create_space_request;
520   create_space_request.index = 42;
521   create_space_request.size = 32;
522   ASSERT_TRUE(create_space_request.controls.Resize(1));
523   create_space_request.controls[0] = NV_CONTROL_BOOT_WRITE_LOCK;
524   CreateSpaceResponse create_space_response;
525   EXPECT_EQ(NV_RESULT_SUCCESS,
526             nvram2.CreateSpace(create_space_request, &create_space_response));
527 }
528 
TEST_F(NvramManagerTest,DeleteSpace_SpaceDeleteError)529 TEST_F(NvramManagerTest, DeleteSpace_SpaceDeleteError) {
530   // Set up an NVRAM space.
531   NvramSpace space;
532   ASSERT_TRUE(space.contents.Resize(10));
533   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(42, space));
534   SetupHeader(NvramHeader::kVersion, 42);
535 
536   // Make space deletion fail.
537   storage::SetSpaceWriteError(42, true);
538 
539   NvramManager nvram;
540 
541   // Attempt to delete the space.
542   DeleteSpaceRequest delete_space_request;
543   delete_space_request.index = 42;
544   DeleteSpaceResponse delete_space_response;
545   EXPECT_EQ(NV_RESULT_INTERNAL_ERROR,
546             nvram.DeleteSpace(delete_space_request, &delete_space_response));
547 
548   // The space should remain present.
549   GetSpaceInfoRequest get_space_info_request;
550   get_space_info_request.index = 42;
551   GetSpaceInfoResponse get_space_info_response;
552   EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
553                                                   &get_space_info_response));
554   EXPECT_EQ(10U, get_space_info_response.size);
555 
556   // Starting up from scratch shouldn't destroy the space either.
557   storage::SetSpaceWriteError(42, false);
558 
559   NvramManager nvram2;
560 
561   GetSpaceInfoResponse get_space_info_response_2;
562   EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
563                                                   &get_space_info_response_2));
564   EXPECT_EQ(10U, get_space_info_response_2.size);
565 }
566 
TEST_F(NvramManagerTest,DeleteSpace_HeaderWriteError)567 TEST_F(NvramManagerTest, DeleteSpace_HeaderWriteError) {
568   // Set up an NVRAM space.
569   NvramSpace space;
570   ASSERT_TRUE(space.contents.Resize(10));
571   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(42, space));
572   SetupHeader(NvramHeader::kVersion, 42);
573 
574   // Header write on deletion will fail.
575   storage::SetHeaderWriteError(true);
576 
577   NvramManager nvram;
578 
579   // Attempt to delete the space.
580   DeleteSpaceRequest delete_space_request;
581   delete_space_request.index = 42;
582   DeleteSpaceResponse delete_space_response;
583   EXPECT_EQ(NV_RESULT_INTERNAL_ERROR,
584             nvram.DeleteSpace(delete_space_request, &delete_space_response));
585 
586   // The space should remain present.
587   GetSpaceInfoRequest get_space_info_request;
588   get_space_info_request.index = 42;
589   GetSpaceInfoResponse get_space_info_response;
590   EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
591                                                   &get_space_info_response));
592   EXPECT_EQ(10U, get_space_info_response.size);
593 
594   // Starting up from scratch shouldn't destroy the space either.
595   storage::SetSpaceWriteError(42, false);
596 
597   NvramManager nvram2;
598 
599   GetSpaceInfoResponse get_space_info_response_2;
600   EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
601                                                   &get_space_info_response_2));
602   EXPECT_EQ(10U, get_space_info_response_2.size);
603 }
604 
TEST_F(NvramManagerTest,DisableCreate_Success)605 TEST_F(NvramManagerTest, DisableCreate_Success) {
606   NvramManager nvram;
607 
608   // Issue a successful disable create request.
609   DisableCreateRequest disable_create_request;
610   DisableCreateResponse disable_create_response;
611   EXPECT_EQ(NV_RESULT_SUCCESS, nvram.DisableCreate(disable_create_request,
612                                                    &disable_create_response));
613 
614   // Make sure space creation request fail afterwards.
615   CreateSpaceRequest create_space_request;
616   create_space_request.index = 1;
617   create_space_request.size = 32;
618   ASSERT_TRUE(create_space_request.controls.Resize(1));
619   create_space_request.controls[0] = NV_CONTROL_BOOT_WRITE_LOCK;
620   CreateSpaceResponse create_space_response;
621   EXPECT_EQ(NV_RESULT_OPERATION_DISABLED,
622             nvram.CreateSpace(create_space_request, &create_space_response));
623 
624   // Redundant requests to disable creation are OK.
625   EXPECT_EQ(NV_RESULT_SUCCESS, nvram.DisableCreate(disable_create_request,
626                                                    &disable_create_response));
627 
628   // Space creation should remain disabled even after a reboot.
629   NvramManager nvram2;
630   EXPECT_EQ(NV_RESULT_OPERATION_DISABLED,
631             nvram2.CreateSpace(create_space_request, &create_space_response));
632 }
633 
TEST_F(NvramManagerTest,DisableCreate_WriteError)634 TEST_F(NvramManagerTest, DisableCreate_WriteError) {
635   // Make header writes fail.
636   storage::SetHeaderWriteError(true);
637 
638   NvramManager nvram;
639 
640   // The disable request should fail.
641   DisableCreateRequest disable_create_request;
642   DisableCreateResponse disable_create_response;
643   EXPECT_EQ(
644       NV_RESULT_INTERNAL_ERROR,
645       nvram.DisableCreate(disable_create_request, &disable_create_response));
646 
647   // We should still be able to create spaces after clearing the error.
648   storage::SetHeaderWriteError(false);
649 
650   CreateSpaceRequest create_space_request;
651   create_space_request.index = 1;
652   create_space_request.size = 32;
653   ASSERT_TRUE(create_space_request.controls.Resize(1));
654   create_space_request.controls[0] = NV_CONTROL_BOOT_WRITE_LOCK;
655   CreateSpaceResponse create_space_response;
656   EXPECT_EQ(NV_RESULT_SUCCESS,
657             nvram.CreateSpace(create_space_request, &create_space_response));
658 }
659 
TEST_F(NvramManagerTest,WriteSpace_SpaceAbsent)660 TEST_F(NvramManagerTest, WriteSpace_SpaceAbsent) {
661   NvramManager nvram;
662 
663   // Attempt to write a non-existing space.
664   WriteSpaceRequest write_space_request;
665   write_space_request.index = 17;
666   ASSERT_TRUE(write_space_request.buffer.Assign("0123456789", 10));
667   WriteSpaceResponse write_space_response;
668   EXPECT_EQ(NV_RESULT_SPACE_DOES_NOT_EXIST,
669             nvram.WriteSpace(write_space_request, &write_space_response));
670 }
671 
TEST_F(NvramManagerTest,WriteSpace_Success)672 TEST_F(NvramManagerTest, WriteSpace_Success) {
673   // Set up an NVRAM space.
674   NvramSpace space;
675   ASSERT_TRUE(space.contents.Resize(10));
676   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
677   SetupHeader(NvramHeader::kVersion, 17);
678 
679   NvramManager nvram;
680 
681   // Write the space.
682   WriteSpaceRequest write_space_request;
683   write_space_request.index = 17;
684   ASSERT_TRUE(write_space_request.buffer.Assign("0123456789", 10));
685   WriteSpaceResponse write_space_response;
686   EXPECT_EQ(NV_RESULT_SUCCESS, nvram.WriteSpace(write_space_request,
687                                                 &write_space_response));
688 
689   // Read back the space and compare contents.
690   ReadAndCompareSpaceData(&nvram, 17, "0123456789", 10);
691 
692   // The data should persist even after a reboot.
693   NvramManager nvram2;
694 
695   ReadAndCompareSpaceData(&nvram2, 17, "0123456789", 10);
696 }
697 
TEST_F(NvramManagerTest,WriteSpace_ExcessData)698 TEST_F(NvramManagerTest, WriteSpace_ExcessData) {
699   // Set up an NVRAM space.
700   NvramSpace space;
701   ASSERT_TRUE(space.contents.Resize(10));
702   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
703   SetupHeader(NvramHeader::kVersion, 17);
704 
705   NvramManager nvram;
706 
707   // Write the space.
708   WriteSpaceRequest write_space_request;
709   write_space_request.index = 17;
710   ASSERT_TRUE(write_space_request.buffer.Assign("0123456789abcdef", 16));
711   WriteSpaceResponse write_space_response;
712   EXPECT_EQ(NV_RESULT_INVALID_PARAMETER,
713             nvram.WriteSpace(write_space_request, &write_space_response));
714 }
715 
TEST_F(NvramManagerTest,WriteSpace_ShortData)716 TEST_F(NvramManagerTest, WriteSpace_ShortData) {
717   // Set up an NVRAM space.
718   NvramSpace space;
719   ASSERT_TRUE(space.contents.Resize(10));
720   memset(space.contents.data(), 'X', space.contents.size());
721   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
722   SetupHeader(NvramHeader::kVersion, 17);
723 
724   NvramManager nvram;
725 
726   // Write the space.
727   WriteSpaceRequest write_space_request;
728   write_space_request.index = 17;
729   ASSERT_TRUE(write_space_request.buffer.Assign("01234", 5));
730   WriteSpaceResponse write_space_response;
731   EXPECT_EQ(NV_RESULT_SUCCESS,
732             nvram.WriteSpace(write_space_request, &write_space_response));
733 
734   // Read back the space data and verify that the missing content bytes have
735   // been set to 0.
736   const uint8_t kExpectedContents[] = {'0', '1', '2', '3', '4', 0, 0, 0, 0, 0};
737   ReadAndCompareSpaceData(&nvram, 17, kExpectedContents, 10);
738 }
739 
TEST_F(NvramManagerTest,WriteSpace_WriteExtend)740 TEST_F(NvramManagerTest, WriteSpace_WriteExtend) {
741   // Set up an NVRAM space.
742   NvramSpace space;
743   space.controls = (1 << NV_CONTROL_WRITE_EXTEND);
744   ASSERT_TRUE(space.contents.Resize(32));
745   memset(space.contents.data(), 0, space.contents.size());
746   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
747   SetupHeader(NvramHeader::kVersion, 17);
748 
749   NvramManager nvram;
750 
751   // Write the space.
752   WriteSpaceRequest write_space_request;
753   write_space_request.index = 17;
754   ASSERT_TRUE(write_space_request.buffer.Assign("data", 4));
755   WriteSpaceResponse write_space_response;
756   EXPECT_EQ(NV_RESULT_SUCCESS,
757             nvram.WriteSpace(write_space_request, &write_space_response));
758 
759   // Read back the space data and verify the hash.
760   const uint8_t kExpectedContents[] = {
761       0xee, 0x84, 0x52, 0x88, 0xbb, 0x60, 0x7e, 0x02, 0xfd, 0xfb, 0x31,
762       0x95, 0x3a, 0x77, 0x23, 0xcf, 0x67, 0xea, 0x6e, 0x2d, 0xd7, 0xdb,
763       0x8c, 0xb4, 0xe4, 0xd2, 0xfd, 0xb4, 0x76, 0x7a, 0x67, 0x89,
764   };
765   ReadAndCompareSpaceData(&nvram, 17, kExpectedContents, 32);
766 }
767 
TEST_F(NvramManagerTest,WriteSpace_WriteExtendShortSpace)768 TEST_F(NvramManagerTest, WriteSpace_WriteExtendShortSpace) {
769   // Set up an NVRAM space.
770   NvramSpace space;
771   space.controls = (1 << NV_CONTROL_WRITE_EXTEND);
772   ASSERT_TRUE(space.contents.Resize(16));
773   memset(space.contents.data(), 0, space.contents.size());
774   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
775   SetupHeader(NvramHeader::kVersion, 17);
776 
777   NvramManager nvram;
778 
779   // Write the space.
780   WriteSpaceRequest write_space_request;
781   write_space_request.index = 17;
782   ASSERT_TRUE(write_space_request.buffer.Assign("data", 4));
783   WriteSpaceResponse write_space_response;
784   EXPECT_EQ(NV_RESULT_SUCCESS,
785             nvram.WriteSpace(write_space_request, &write_space_response));
786 
787   // Read back the space data and verify the truncated hash.
788   const uint8_t kExpectedContents[] = {
789       0x24, 0x2a, 0xbb, 0x36, 0x10, 0x37, 0x92, 0x3f,
790       0x7d, 0x7d, 0x92, 0x3a, 0x16, 0x65, 0xd2, 0xa2,
791   };
792   ReadAndCompareSpaceData(&nvram, 17, kExpectedContents, 16);
793 }
794 
TEST_F(NvramManagerTest,WriteSpace_WriteExtendLongSpace)795 TEST_F(NvramManagerTest, WriteSpace_WriteExtendLongSpace) {
796   // Set up an NVRAM space.
797   NvramSpace space;
798   space.controls = (1 << NV_CONTROL_WRITE_EXTEND);
799   ASSERT_TRUE(space.contents.Resize(33));
800   memset(space.contents.data(), 'X', space.contents.size());
801   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
802   SetupHeader(NvramHeader::kVersion, 17);
803 
804   NvramManager nvram;
805 
806   // Write the space.
807   WriteSpaceRequest write_space_request;
808   write_space_request.index = 17;
809   ASSERT_TRUE(write_space_request.buffer.Assign("data", 4));
810   WriteSpaceResponse write_space_response;
811   EXPECT_EQ(NV_RESULT_SUCCESS,
812             nvram.WriteSpace(write_space_request, &write_space_response));
813 
814   // Read back the space data and verify the hash and trailing 0 bytes.
815   const uint8_t kExpectedContents[] = {
816       0x99, 0xb8, 0x5f, 0xd0, 0xf7, 0x9b, 0x17, 0x2e, 0x0e, 0x58, 0x3d,
817       0x3c, 0x9a, 0x29, 0xa3, 0xaf, 0x0a, 0x4c, 0x68, 0x97, 0x72, 0x8c,
818       0x0c, 0xa4, 0x37, 0xad, 0x39, 0xf3, 0x8c, 0x6e, 0x64, 0xd7, 0x00,
819   };
820   ReadAndCompareSpaceData(&nvram, 17, kExpectedContents, 33);
821 }
822 
TEST_F(NvramManagerTest,WriteSpace_AuthorizationFailure)823 TEST_F(NvramManagerTest, WriteSpace_AuthorizationFailure) {
824   // Set up an NVRAM space.
825   NvramSpace space;
826   space.controls = (1 << NV_CONTROL_WRITE_AUTHORIZATION);
827   ASSERT_TRUE(space.contents.Resize(10));
828   const char kAuthorizationValue[] = "secret";
829   ASSERT_TRUE(space.authorization_value.Assign(kAuthorizationValue,
830                                                sizeof(kAuthorizationValue)));
831   ASSERT_TRUE(space.contents.Assign("0123456789", 10));
832   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
833   SetupHeader(NvramHeader::kVersion, 17);
834 
835   NvramManager nvram;
836 
837   // Attempt a write with the wrong authorization value.
838   WriteSpaceRequest write_space_request;
839   write_space_request.index = 17;
840   ASSERT_TRUE(write_space_request.buffer.Assign("data", 4));
841   WriteSpaceResponse write_space_response;
842   EXPECT_EQ(NV_RESULT_ACCESS_DENIED,
843             nvram.WriteSpace(write_space_request, &write_space_response));
844 
845   // The previous data should remain effective.
846   ReadAndCompareSpaceData(&nvram, 17, "0123456789", 10);
847 }
848 
TEST_F(NvramManagerTest,WriteSpace_WriteError)849 TEST_F(NvramManagerTest, WriteSpace_WriteError) {
850   // Set up an NVRAM space.
851   NvramSpace space;
852   ASSERT_TRUE(space.contents.Assign("0123456789", 10));
853   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
854   SetupHeader(NvramHeader::kVersion, 17);
855 
856   NvramManager nvram;
857 
858   storage::SetSpaceWriteError(17, true);
859 
860   // Attempt a write, which should fail.
861   WriteSpaceRequest write_space_request;
862   write_space_request.index = 17;
863   ASSERT_TRUE(write_space_request.buffer.Assign("data", 4));
864   WriteSpaceResponse write_space_response;
865   EXPECT_EQ(NV_RESULT_INTERNAL_ERROR,
866             nvram.WriteSpace(write_space_request, &write_space_response));
867 
868   // The previous data should remain effective.
869   ReadAndCompareSpaceData(&nvram, 17, "0123456789", 10);
870 }
871 
TEST_F(NvramManagerTest,ReadSpace_SpaceAbsent)872 TEST_F(NvramManagerTest, ReadSpace_SpaceAbsent) {
873   NvramManager nvram;
874 
875   // Attempt a read from a space that doesn't exist.
876   ReadSpaceRequest read_space_request;
877   read_space_request.index = 17;
878   ReadSpaceResponse read_space_response;
879   EXPECT_EQ(NV_RESULT_SPACE_DOES_NOT_EXIST,
880             nvram.ReadSpace(read_space_request, &read_space_response));
881 }
882 
TEST_F(NvramManagerTest,ReadSpace_AuthorizationFailure)883 TEST_F(NvramManagerTest, ReadSpace_AuthorizationFailure) {
884   // Set up an NVRAM space.
885   NvramSpace space;
886   space.controls = (1 << NV_CONTROL_READ_AUTHORIZATION);
887   ASSERT_TRUE(space.contents.Resize(10));
888   const char kAuthorizationValue[] = "secret";
889   ASSERT_TRUE(space.authorization_value.Assign(kAuthorizationValue,
890                                                sizeof(kAuthorizationValue)));
891   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
892   SetupHeader(NvramHeader::kVersion, 17);
893 
894   NvramManager nvram;
895 
896   // Attempt a read from the space.
897   ReadSpaceRequest read_space_request;
898   read_space_request.index = 17;
899   ReadSpaceResponse read_space_response;
900   EXPECT_EQ(NV_RESULT_ACCESS_DENIED,
901             nvram.ReadSpace(read_space_request, &read_space_response));
902   EXPECT_EQ(0U, read_space_response.buffer.size());
903 }
904 
TEST_F(NvramManagerTest,LockSpaceWrite_SpaceAbsent)905 TEST_F(NvramManagerTest, LockSpaceWrite_SpaceAbsent) {
906   NvramManager nvram;
907 
908   // Attempt to lock a space that doesn't exist.
909   LockSpaceWriteRequest lock_space_write_request;
910   lock_space_write_request.index = 17;
911   LockSpaceWriteResponse lock_space_write_response;
912   EXPECT_EQ(NV_RESULT_SPACE_DOES_NOT_EXIST,
913             nvram.LockSpaceWrite(lock_space_write_request,
914                                  &lock_space_write_response));
915 }
916 
TEST_F(NvramManagerTest,LockSpaceWrite_AuthorizationFailure)917 TEST_F(NvramManagerTest, LockSpaceWrite_AuthorizationFailure) {
918   // Set up an NVRAM space.
919   NvramSpace space;
920   space.controls = (1 << NV_CONTROL_PERSISTENT_WRITE_LOCK) |
921                    (1 << NV_CONTROL_WRITE_AUTHORIZATION);
922   ASSERT_TRUE(space.contents.Resize(10));
923   const char kAuthorizationValue[] = "secret";
924   ASSERT_TRUE(space.authorization_value.Assign(kAuthorizationValue,
925                                                sizeof(kAuthorizationValue)));
926   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
927   SetupHeader(NvramHeader::kVersion, 17);
928 
929   NvramManager nvram;
930 
931   // Attempt to lock a space without valid authentication.
932   LockSpaceWriteRequest lock_space_write_request;
933   lock_space_write_request.index = 17;
934   LockSpaceWriteResponse lock_space_write_response;
935   EXPECT_EQ(NV_RESULT_ACCESS_DENIED,
936             nvram.LockSpaceWrite(lock_space_write_request,
937                                  &lock_space_write_response));
938 }
939 
TEST_F(NvramManagerTest,LockSpaceWrite_SuccessPersistent)940 TEST_F(NvramManagerTest, LockSpaceWrite_SuccessPersistent) {
941   // Set up an NVRAM space.
942   NvramSpace space;
943   space.controls = (1 << NV_CONTROL_PERSISTENT_WRITE_LOCK);
944   ASSERT_TRUE(space.contents.Resize(10));
945   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
946   SetupHeader(NvramHeader::kVersion, 17);
947 
948   NvramManager nvram;
949 
950   // Lock the space.
951   LockSpaceWriteRequest lock_space_write_request;
952   lock_space_write_request.index = 17;
953   LockSpaceWriteResponse lock_space_write_response;
954   EXPECT_EQ(NV_RESULT_SUCCESS,
955             nvram.LockSpaceWrite(lock_space_write_request,
956                                  &lock_space_write_response));
957 
958   // Writing should fail now.
959   WriteSpaceRequest write_space_request;
960   write_space_request.index = 17;
961   ASSERT_TRUE(write_space_request.buffer.Assign("data", 4));
962   WriteSpaceResponse write_space_response;
963   EXPECT_EQ(NV_RESULT_OPERATION_DISABLED,
964             nvram.WriteSpace(write_space_request, &write_space_response));
965 
966   // The lock should be persistent, so writing should fail after reboot.
967   NvramManager nvram2;
968 
969   EXPECT_EQ(NV_RESULT_OPERATION_DISABLED,
970             nvram2.WriteSpace(write_space_request, &write_space_response));
971 }
972 
TEST_F(NvramManagerTest,LockSpaceWrite_SuccessBoot)973 TEST_F(NvramManagerTest, LockSpaceWrite_SuccessBoot) {
974   // Set up an NVRAM space.
975   NvramSpace space;
976   space.controls = (1 << NV_CONTROL_BOOT_WRITE_LOCK);
977   ASSERT_TRUE(space.contents.Assign("01234567890", 10));
978   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
979   SetupHeader(NvramHeader::kVersion, 17);
980 
981   NvramManager nvram;
982 
983   // Lock the space.
984   LockSpaceWriteRequest lock_space_write_request;
985   lock_space_write_request.index = 17;
986   LockSpaceWriteResponse lock_space_write_response;
987   EXPECT_EQ(NV_RESULT_SUCCESS,
988             nvram.LockSpaceWrite(lock_space_write_request,
989                                  &lock_space_write_response));
990 
991   // Writing should fail now.
992   WriteSpaceRequest write_space_request;
993   write_space_request.index = 17;
994   ASSERT_TRUE(write_space_request.buffer.Assign("newcontent", 10));
995   WriteSpaceResponse write_space_response;
996   EXPECT_EQ(NV_RESULT_OPERATION_DISABLED,
997             nvram.WriteSpace(write_space_request, &write_space_response));
998 
999   // We configured a per-boot lock, so writing should succeed after reboot.
1000   NvramManager nvram2;
1001 
1002   EXPECT_EQ(NV_RESULT_SUCCESS,
1003             nvram2.WriteSpace(write_space_request, &write_space_response));
1004   ReadAndCompareSpaceData(&nvram2, 17, "newcontent", 10);
1005 }
1006 
TEST_F(NvramManagerTest,LockSpaceWrite_NotLockable)1007 TEST_F(NvramManagerTest, LockSpaceWrite_NotLockable) {
1008   // Set up an NVRAM space.
1009   NvramSpace space;
1010   ASSERT_TRUE(space.contents.Resize(10));
1011   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
1012   SetupHeader(NvramHeader::kVersion, 17);
1013 
1014   NvramManager nvram;
1015 
1016   // Attempt to lock a space without valid authentication.
1017   LockSpaceWriteRequest lock_space_write_request;
1018   lock_space_write_request.index = 17;
1019   LockSpaceWriteResponse lock_space_write_response;
1020   EXPECT_EQ(NV_RESULT_INVALID_PARAMETER,
1021             nvram.LockSpaceWrite(lock_space_write_request,
1022                                  &lock_space_write_response));
1023 }
1024 
TEST_F(NvramManagerTest,LockSpaceRead_SpaceAbsent)1025 TEST_F(NvramManagerTest, LockSpaceRead_SpaceAbsent) {
1026   NvramManager nvram;
1027 
1028   // Attempt to lock a non-existing space.
1029   LockSpaceReadRequest lock_space_read_request;
1030   lock_space_read_request.index = 17;
1031   LockSpaceReadResponse lock_space_read_response;
1032   EXPECT_EQ(
1033       NV_RESULT_SPACE_DOES_NOT_EXIST,
1034       nvram.LockSpaceRead(lock_space_read_request, &lock_space_read_response));
1035 }
1036 
TEST_F(NvramManagerTest,LockSpaceRead_AuthorizationFailure)1037 TEST_F(NvramManagerTest, LockSpaceRead_AuthorizationFailure) {
1038   // Set up an NVRAM space.
1039   NvramSpace space;
1040   space.controls =
1041       (1 << NV_CONTROL_BOOT_READ_LOCK) | (1 << NV_CONTROL_READ_AUTHORIZATION);
1042   ASSERT_TRUE(space.contents.Resize(10));
1043   const char kAuthorizationValue[] = "secret";
1044   ASSERT_TRUE(space.authorization_value.Assign(kAuthorizationValue,
1045                                                sizeof(kAuthorizationValue)));
1046   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
1047   SetupHeader(NvramHeader::kVersion, 17);
1048 
1049   NvramManager nvram;
1050 
1051   // Attempt to lock a space without valid authorization.
1052   LockSpaceReadRequest lock_space_read_request;
1053   lock_space_read_request.index = 17;
1054   LockSpaceReadResponse lock_space_read_response;
1055   EXPECT_EQ(
1056       NV_RESULT_ACCESS_DENIED,
1057       nvram.LockSpaceRead(lock_space_read_request, &lock_space_read_response));
1058 }
1059 
TEST_F(NvramManagerTest,LockSpaceRead_Success)1060 TEST_F(NvramManagerTest, LockSpaceRead_Success) {
1061   // Set up an NVRAM space.
1062   NvramSpace space;
1063   space.controls = (1 << NV_CONTROL_BOOT_READ_LOCK);
1064   ASSERT_TRUE(space.contents.Assign("0123456789", 10));
1065   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
1066   SetupHeader(NvramHeader::kVersion, 17);
1067 
1068   NvramManager nvram;
1069 
1070   // Lock the space.
1071   LockSpaceReadRequest lock_space_read_request;
1072   lock_space_read_request.index = 17;
1073   LockSpaceReadResponse lock_space_read_response;
1074   EXPECT_EQ(NV_RESULT_SUCCESS, nvram.LockSpaceRead(lock_space_read_request,
1075                                                    &lock_space_read_response));
1076 
1077   // Read requests should fail now.
1078   ReadSpaceRequest read_space_request;
1079   read_space_request.index = 17;
1080   ReadSpaceResponse read_space_response;
1081   EXPECT_EQ(NV_RESULT_OPERATION_DISABLED,
1082             nvram.ReadSpace(read_space_request, &read_space_response));
1083   EXPECT_EQ(0U, read_space_response.buffer.size());
1084 
1085   // This is a non-persistent lock, so reads should work again after a reboot.
1086   NvramManager nvram2;
1087 
1088   ReadAndCompareSpaceData(&nvram2, 17, "0123456789", 10);
1089 }
1090 
TEST_F(NvramManagerTest,LockSpaceRead_NotLockable)1091 TEST_F(NvramManagerTest, LockSpaceRead_NotLockable) {
1092   // Set up an NVRAM space.
1093   NvramSpace space;
1094   ASSERT_TRUE(space.contents.Resize(10));
1095   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
1096   SetupHeader(NvramHeader::kVersion, 17);
1097 
1098   NvramManager nvram;
1099 
1100   // Attempt to lock a space without valid authorization.
1101   LockSpaceReadRequest lock_space_read_request;
1102   lock_space_read_request.index = 17;
1103   LockSpaceReadResponse lock_space_read_response;
1104   EXPECT_EQ(
1105       NV_RESULT_INVALID_PARAMETER,
1106       nvram.LockSpaceRead(lock_space_read_request, &lock_space_read_response));
1107 }
1108 
TEST_F(NvramManagerTest,WipeStorage_Success)1109 TEST_F(NvramManagerTest, WipeStorage_Success) {
1110   // Set up an NVRAM space.
1111   NvramSpace space;
1112   ASSERT_TRUE(space.contents.Resize(10));
1113   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
1114   SetupHeader(NvramHeader::kVersion, 17);
1115 
1116   // Check that the space is visible.
1117   NvramManager nvram;
1118   GetSpaceInfoRequest get_space_info_request;
1119   get_space_info_request.index = 17;
1120   GetSpaceInfoResponse get_space_info_response;
1121   EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
1122                                                   &get_space_info_response));
1123   EXPECT_EQ(10U, get_space_info_response.size);
1124 
1125   // Request a wipe.
1126   WipeStorageRequest wipe_storage_request;
1127   WipeStorageResponse wipe_storage_response;
1128   EXPECT_EQ(NV_RESULT_SUCCESS,
1129             nvram.WipeStorage(wipe_storage_request, &wipe_storage_response));
1130 
1131   // The space should no longer be declared.
1132   GetInfoRequest get_info_request;
1133   GetInfoResponse get_info_response;
1134   EXPECT_EQ(NV_RESULT_SUCCESS,
1135             nvram.GetInfo(get_info_request, &get_info_response));
1136   EXPECT_EQ(0U, get_info_response.space_list.size());
1137 
1138   // Accessing the space should fail.
1139   EXPECT_EQ(
1140       NV_RESULT_SPACE_DOES_NOT_EXIST,
1141       nvram.GetSpaceInfo(get_space_info_request, &get_space_info_response));
1142 }
1143 
TEST_F(NvramManagerTest,WipeStorage_Abort)1144 TEST_F(NvramManagerTest, WipeStorage_Abort) {
1145   // Set up two pre-existing spaces and a matching header.
1146   NvramSpace space;
1147   ASSERT_TRUE(space.contents.Resize(10));
1148   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(1, space));
1149   ASSERT_TRUE(space.contents.Resize(20));
1150   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(2, space));
1151   NvramHeader header;
1152   header.version = NvramHeader::kVersion;
1153   ASSERT_TRUE(header.allocated_indices.Resize(2));
1154   header.allocated_indices[0] = 1;
1155   header.allocated_indices[1] = 2;
1156   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreHeader(header));
1157 
1158   // Check that the spaces are visible.
1159   NvramManager nvram;
1160   GetInfoRequest get_info_request;
1161   GetInfoResponse get_info_response;
1162   EXPECT_EQ(NV_RESULT_SUCCESS,
1163             nvram.GetInfo(get_info_request, &get_info_response));
1164   EXPECT_EQ(2U, get_info_response.space_list.size());
1165   int space_mask = 0;
1166   for (size_t i = 0; i < get_info_response.space_list.size(); ++i) {
1167     space_mask |= (1 << get_info_response.space_list[i]);
1168   }
1169   EXPECT_EQ(0x6, space_mask);
1170 
1171   // Set things up so the deletion request for the second space fails.
1172   storage::SetSpaceWriteError(2, true);
1173 
1174   // The wipe request should fail now.
1175   WipeStorageRequest wipe_storage_request;
1176   WipeStorageResponse wipe_storage_response;
1177   EXPECT_EQ(NV_RESULT_INTERNAL_ERROR,
1178             nvram.WipeStorage(wipe_storage_request, &wipe_storage_response));
1179 
1180   // New wipe attempt with a fresh instance after clearing the error.
1181   storage::SetSpaceWriteError(2, false);
1182   NvramManager nvram2;
1183   EXPECT_EQ(NV_RESULT_SUCCESS,
1184             nvram2.WipeStorage(wipe_storage_request, &wipe_storage_response));
1185 
1186   // No spaces should remain.
1187   EXPECT_EQ(NV_RESULT_SUCCESS,
1188             nvram2.GetInfo(get_info_request, &get_info_response));
1189   EXPECT_EQ(0U, get_info_response.space_list.size());
1190 }
1191 
TEST_F(NvramManagerTest,WipeStorage_Disable)1192 TEST_F(NvramManagerTest, WipeStorage_Disable) {
1193   // Set up an NVRAM space.
1194   NvramSpace space;
1195   ASSERT_TRUE(space.contents.Resize(10));
1196   ASSERT_EQ(storage::Status::kSuccess, persistence::StoreSpace(17, space));
1197   SetupHeader(NvramHeader::kVersion, 17);
1198 
1199   NvramManager nvram;
1200 
1201   // Disable wiping.
1202   DisableWipeRequest disable_wipe_request;
1203   DisableWipeResponse disable_wipe_response;
1204   EXPECT_EQ(NV_RESULT_SUCCESS,
1205             nvram.DisableWipe(disable_wipe_request, &disable_wipe_response));
1206 
1207   // A wipe request should fail.
1208   WipeStorageRequest wipe_storage_request;
1209   WipeStorageResponse wipe_storage_response;
1210   EXPECT_EQ(NV_RESULT_OPERATION_DISABLED,
1211             nvram.WipeStorage(wipe_storage_request, &wipe_storage_response));
1212 
1213   // The space should remain declared.
1214   GetInfoRequest get_info_request;
1215   GetInfoResponse get_info_response;
1216   EXPECT_EQ(NV_RESULT_SUCCESS,
1217             nvram.GetInfo(get_info_request, &get_info_response));
1218   ASSERT_EQ(1U, get_info_response.space_list.size());
1219   EXPECT_EQ(17U, get_info_response.space_list[0]);
1220 
1221   // The space data should remain present.
1222   GetSpaceInfoRequest get_space_info_request;
1223   get_space_info_request.index = 17;
1224   GetSpaceInfoResponse get_space_info_response;
1225   EXPECT_EQ(NV_RESULT_SUCCESS, nvram.GetSpaceInfo(get_space_info_request,
1226                                                   &get_space_info_response));
1227   EXPECT_EQ(10U, get_space_info_response.size);
1228 }
1229 
1230 }  // namespace
1231 }  // namespace nvram
1232