1 /*
2  * Copyright 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 "avb_manager.h"
18 
19 #include <string.h>
20 #include <uapi/err.h>
21 
22 #include "secure_storage_interface.h"
23 
24 #define DEBUG 0
25 
26 const unsigned int kRollbackSlotMax = 32;
27 
28 static const uint32_t kAvbVersion = 1;
29 static const char* kAvbRollbackFilename = "avb.rollback";
30 static const unsigned int kPermanentAttributesLengthMax = 2048;
31 static const char* kPermanentAttributesFilename = "avb.ppa";
32 static const char* kLockStateFile = "avb.lock_state";
33 static const unsigned int kStorageIdLengthMax = 64;
34 
35 static const uint32_t kTypeMask = 0xF000;
36 static const unsigned int kTypeShift = 12;
37 
38 // Helper function to get |filename| and |slot| and based on type flag
39 // in |raw_slot|. |filename| is assumed to be allocated with
40 // kStorageIdLengthMax bytes.
GetFilenameAndSlot(uint32_t raw_slot,char filename[kStorageIdLengthMax],uint32_t * slot)41 static int GetFilenameAndSlot(uint32_t raw_slot,
42                               char filename[kStorageIdLengthMax],
43                               uint32_t* slot) {
44     // Upper 16 bits should not be set
45     if (raw_slot & 0xFFFF0000) {
46         TLOGE("Error: Slot value %u invalid\n", raw_slot);
47         return ERR_NOT_VALID;
48     }
49     // Mask type flag from raw slot to get index
50     *slot = raw_slot & ~kTypeMask;
51     if (*slot >= kRollbackSlotMax) {
52         TLOGE("Error: Slot value %u larger than supported %u\n", *slot,
53               kRollbackSlotMax);
54         return ERR_NOT_VALID;
55     }
56     // Choose correct file for rollback index type
57     strcpy(filename, kAvbRollbackFilename);
58     int index_type = (raw_slot & kTypeMask) >> kTypeShift;
59     char postfix[4];
60     snprintf(postfix, 4, ".%01X", index_type);
61     strcat(filename, postfix);
62     return NO_ERROR;
63 }
64 
65 namespace avb {
66 
ReadRollbackIndex(const RollbackIndexRequest & request,RollbackIndexResponse * response)67 void AvbManager::ReadRollbackIndex(const RollbackIndexRequest& request,
68                                    RollbackIndexResponse* response) {
69     uint32_t slot;
70     char filename[kStorageIdLengthMax];
71     if (GetFilenameAndSlot(request.get_slot(), filename, &slot) < 0) {
72         response->set_error(AvbError::kInvalid);
73         TLOGE("Error: Invalid slot value: %u\n", request.get_slot());
74         return;
75     }
76 
77     int rc = storage_->open(filename);
78     if (rc < 0) {
79         response->set_error(AvbError::kInternal);
80         TLOGE("Error: failed to open file %s: %d\n", filename, rc);
81         return;
82     }
83     uint64_t size;
84     rc = storage_->get_file_size(&size);
85     if (rc < 0) {
86         response->set_error(AvbError::kInternal);
87         TLOGE("Error: failed to get size of file %s: %d\n", filename, rc);
88         return;
89     }
90 
91     // If no valid rollback counter file is found, initialize to 0
92     uint64_t rollback_counter;
93     if (size < kRollbackSlotMax * sizeof(uint64_t)) {
94         TLOGD("No valid rollback index file found. Initializing to 0\n");
95         uint64_t write_buf[kRollbackSlotMax] = {0};
96         rc = storage_->write(0, write_buf, sizeof(write_buf));
97         rollback_counter = 0;
98     } else {
99         TLOGD("Rollback index file found\n");
100         rc = storage_->read(sizeof(rollback_counter) * slot, &rollback_counter,
101                             sizeof(rollback_counter));
102     }
103 
104     if (rc < 0) {
105         response->set_error(AvbError::kInternal);
106         TLOGE("Error: reading storage object: %d\n", rc);
107         return;
108     }
109 
110     if (static_cast<size_t>(rc) < sizeof(rollback_counter)) {
111         response->set_error(AvbError::kInternal);
112         TLOGE("Error: invalid object size: %d\n", rc);
113         return;
114     }
115 
116     response->set_value(rollback_counter);
117 }
118 
WriteRollbackIndex(const RollbackIndexRequest & request,RollbackIndexResponse * response)119 void AvbManager::WriteRollbackIndex(const RollbackIndexRequest& request,
120                                     RollbackIndexResponse* response) {
121     uint32_t slot;
122     char filename[kStorageIdLengthMax];
123     if (GetFilenameAndSlot(request.get_slot(), filename, &slot) < 0) {
124         response->set_error(AvbError::kInvalid);
125         TLOGE("Error: Invalid slot value: %u\n", request.get_slot());
126         return;
127     }
128 
129     int rc = storage_->open(filename);
130     if (rc < 0) {
131         response->set_error(AvbError::kInternal);
132         TLOGE("Error: failed to open file %s: %d\n", filename, rc);
133         return;
134     }
135     uint64_t size;
136     rc = storage_->get_file_size(&size);
137     if (rc < 0) {
138         response->set_error(AvbError::kInternal);
139         TLOGE("Error: failed to get size of file %s: %d\n", filename, rc);
140         return;
141     }
142 
143     // If no valid rollback counter file is found, initialize to 0
144     uint64_t request_value = request.get_value();
145     if (static_cast<size_t>(size) < kRollbackSlotMax * sizeof(uint64_t)) {
146         TLOGD("No valid rollback index file found. Initializing to 0\n");
147         uint64_t write_buf[kRollbackSlotMax] = {0};
148         write_buf[slot] = request_value;
149         rc = storage_->write(0, write_buf, sizeof(write_buf));
150     } else {
151         uint64_t rollback_counter;
152         TLOGD("Found a rollback index file\n");
153         rc = storage_->read(sizeof(rollback_counter) * slot, &rollback_counter,
154                             sizeof(rollback_counter));
155 
156         // Write value to specified slot in file
157         if (request_value < rollback_counter) {
158             response->set_error(AvbError::kInvalid);
159             TLOGE("Error: Requested write [%lu] is less than existing counter value "
160                   "[%lu]\n",
161                   static_cast<long unsigned>(request_value),
162                   static_cast<long unsigned>(rollback_counter));
163             response->set_value(rollback_counter);
164             return;
165         }
166         rc = storage_->write(sizeof(request_value) * slot, &request_value,
167                              sizeof(request_value));
168     }
169 
170     if (rc < 0) {
171         response->set_error(AvbError::kInternal);
172         TLOGE("Error: accessing storage object [%d]\n", rc);
173         return;
174     }
175 
176     if (static_cast<size_t>(rc) < sizeof(request_value)) {
177         response->set_error(AvbError::kInternal);
178         TLOGE("Error: invalid object size [%d]\n", rc);
179         return;
180     }
181 
182     response->set_value(request_value);
183 }
184 
GetVersion(const GetVersionRequest & request,GetVersionResponse * response)185 void AvbManager::GetVersion(const GetVersionRequest& request,
186                             GetVersionResponse* response) {
187     response->set_version(kAvbVersion);
188 }
189 
ReadPermanentAttributes(const ReadPermanentAttributesRequest & request,ReadPermanentAttributesResponse * response)190 void AvbManager::ReadPermanentAttributes(
191         const ReadPermanentAttributesRequest& request,
192         ReadPermanentAttributesResponse* response) {
193     int rc = storage_->open(kPermanentAttributesFilename);
194     if (rc < 0) {
195         response->set_error(AvbError::kInternal);
196         TLOGE("Error: failed to open attributes file: %d\n", rc);
197         return;
198     }
199 
200     // Read permanent product attributes
201     UniquePtr<uint8_t[]> attributes(new uint8_t[kPermanentAttributesLengthMax]);
202     rc = storage_->read(0, attributes.get(), kPermanentAttributesLengthMax);
203     if (rc <= 0) {
204         response->set_error(AvbError::kInternal);
205         TLOGE("Error: %s attributes file [%d]\n",
206               rc == 0 ? "missing" : "accessing", rc);
207         return;
208     }
209     uint32_t attributes_size = static_cast<uint32_t>(rc);
210     response->set_attributes_buf(attributes.get(), attributes_size);
211 }
212 
WritePermanentAttributes(const WritePermanentAttributesRequest & request,WritePermanentAttributesResponse * response)213 void AvbManager::WritePermanentAttributes(
214         const WritePermanentAttributesRequest& request,
215         WritePermanentAttributesResponse* response) {
216     int rc = storage_->open(kPermanentAttributesFilename);
217     if (rc < 0) {
218         response->set_error(AvbError::kInternal);
219         TLOGE("Error: failed to open attributes file: %d\n", rc);
220         return;
221     }
222     uint64_t size;
223     rc = storage_->get_file_size(&size);
224     if (rc < 0) {
225         response->set_error(AvbError::kInternal);
226         TLOGE("Error: failed to get size of attributes file: %d\n", rc);
227         return;
228     }
229 
230     if (size) {
231         response->set_error(AvbError::kInvalid);
232         TLOGE("Error: Permanent attributes already set!\n");
233         return;
234     }
235     // New file, write serialized permanent product attributes to storage
236     uint32_t attributes_size = request.get_attributes_size();
237     uint8_t* attributes = request.get_attributes_buf();
238     rc = storage_->write(0, attributes, attributes_size);
239 
240     if (rc < 0 || static_cast<size_t>(rc) < attributes_size) {
241         response->set_error(AvbError::kInternal);
242         TLOGE("Error: accessing storage object [%d]\n", rc);
243         return;
244     }
245 }
246 
ReadLockState(const ReadLockStateRequest & request,ReadLockStateResponse * response)247 void AvbManager::ReadLockState(const ReadLockStateRequest& request,
248                                ReadLockStateResponse* response) {
249     int rc = storage_->open(kLockStateFile);
250     if (rc < 0) {
251         response->set_error(AvbError::kInternal);
252         TLOGE("Error: failed to open lock state file: %d\n", rc);
253         return;
254     }
255     uint64_t size;
256     rc = storage_->get_file_size(&size);
257     if (rc < 0) {
258         response->set_error(AvbError::kInternal);
259         TLOGE("Error: failed to get size of lock state file: %d\n", rc);
260         return;
261     }
262 
263     uint8_t lock_state = 1;
264     if (size == 0) {
265         // No lock state found, assume initial state is locked and write it
266         rc = storage_->write(0, &lock_state, sizeof(lock_state));
267     } else {
268         rc = storage_->read(0, &lock_state, sizeof(lock_state));
269     }
270     if (rc < 0 || static_cast<size_t>(rc) < sizeof(lock_state)) {
271         response->set_error(AvbError::kInternal);
272         TLOGE("Error: accessing storage object [%d]\n", rc);
273         return;
274     }
275     response->set_lock_state(lock_state);
276 }
277 
WriteLockState(const WriteLockStateRequest & request,WriteLockStateResponse * response)278 void AvbManager::WriteLockState(const WriteLockStateRequest& request,
279                                 WriteLockStateResponse* response) {
280     // Only 0 and 1 are valid lock states
281     uint8_t request_lock_state = request.get_lock_state();
282     if (request_lock_state != 0 && request_lock_state != 1) {
283         response->set_error(AvbError::kInvalid);
284         TLOGE("Error: invalid lock state requested: %d\n", request_lock_state);
285         return;
286     }
287 
288     int rc = storage_->open(kLockStateFile);
289     if (rc < 0) {
290         response->set_error(AvbError::kInternal);
291         TLOGE("Error: failed to open lock state file: %d\n", rc);
292         return;
293     }
294 
295     // Try to read existing lock state
296     uint8_t stored_lock_state = 0xFF;
297     storage_->read(0, &stored_lock_state, sizeof(stored_lock_state));
298 
299     // If no lock state file was found, or the device is changing lock state,
300     // clear rollback index data
301     if (stored_lock_state != request_lock_state) {
302         if (DeleteRollbackIndexFiles() < 0) {
303             response->set_error(AvbError::kInternal);
304             TLOGE("Error: clearing rollback index data\n");
305             return;
306         }
307     }
308 
309     // Write new lock state
310     rc = storage_->write(0, &request_lock_state, sizeof(request_lock_state));
311     if (rc < 0 || static_cast<size_t>(rc) < sizeof(request_lock_state)) {
312         response->set_error(AvbError::kInternal);
313         TLOGE("Error: accessing storage object [%d]\n", rc);
314         return;
315     }
316 }
317 
318 // Rollback counters are stored in files avb.rollback.{0..F}. When a device
319 // changes lock state, data in rollback index files must be deleted.
DeleteRollbackIndexFiles()320 int AvbManager::DeleteRollbackIndexFiles() {
321     char filename[kStorageIdLengthMax];
322     char postfix[4];
323     int rc = NO_ERROR;
324 
325     for (unsigned int i = 0x0; i <= 0xF; ++i) {
326         strcpy(filename, kAvbRollbackFilename);
327         snprintf(postfix, 4, ".%01X", i);
328         strcat(filename, postfix);
329         int storage_rc = storage_->delete_file(filename);
330         if (storage_rc < 0 && storage_rc != ERR_NOT_FOUND) {
331             rc = storage_rc;
332             TLOGE("Error: deleting file %s: %d\n", filename, rc);
333             continue;
334         }
335     }
336     return rc;
337 }
338 
339 };  // namespace avb
340