1 // Copyright 2024, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 //! Gbl AVB operations.
16
17 use crate::{
18 gbl_avb::state::{BootStateColor, KeyValidationStatus},
19 gbl_print, gbl_println, GblOps,
20 };
21 use avb::{
22 cert_validate_vbmeta_public_key, CertOps, CertPermanentAttributes, IoError, IoResult,
23 Ops as AvbOps, PublicKeyForPartitionInfo, SlotVerifyData, SHA256_DIGEST_SIZE,
24 };
25 use core::{
26 cmp::{max, min},
27 ffi::CStr,
28 };
29 use liberror::Error;
30 use safemath::SafeNum;
31 use uuid::Uuid;
32
33 // AVB cert tracks versions for the PIK and PSK; PRK cannot be changed so has no version info.
34 const AVB_CERT_NUM_KEY_VERSIONS: usize = 2;
35
36 /// Implements avb ops callbacks for [GblOps].
37 pub struct GblAvbOps<'a, T> {
38 /// The underlying [GblOps].
39 pub gbl_ops: &'a mut T,
40 preloaded_partitions: &'a [(&'a str, &'a [u8])],
41 /// Used for storing key versions to be set (location, version).
42 ///
43 /// These will initially be `None`, but if using the cert extensions they will be updated during
44 /// verification. These values will not be automatically persisted to disk because whether to do
45 /// so depends on other factors such as slot success state; it's up to the user to persist them
46 /// post-verification if needed.
47 // If `array_map` is imported in the future, consider switching to it.
48 pub key_versions: [Option<(usize, u64)>; AVB_CERT_NUM_KEY_VERSIONS],
49 /// True to use the AVB cert extensions.
50 use_cert: bool,
51 /// Avb public key validation status reported by validate_vbmeta_public_key.
52 /// https://source.android.com/docs/security/features/verifiedboot/boot-flow#locked-devices-with-custom-root-of-trust
53 key_validation_status: Option<KeyValidationStatus>,
54 }
55
56 impl<'a, 'p, 'q, T: GblOps<'p, 'q>> GblAvbOps<'a, T> {
57 /// Creates a new [GblAvbOps].
new( gbl_ops: &'a mut T, preloaded_partitions: &'a [(&'a str, &'a [u8])], use_cert: bool, ) -> Self58 pub fn new(
59 gbl_ops: &'a mut T,
60 preloaded_partitions: &'a [(&'a str, &'a [u8])],
61 use_cert: bool,
62 ) -> Self {
63 Self {
64 gbl_ops,
65 preloaded_partitions,
66 key_versions: [None; AVB_CERT_NUM_KEY_VERSIONS],
67 use_cert,
68 key_validation_status: None,
69 }
70 }
71
72 /// Returns the size of a partition.
73 ///
74 /// This will only consider the [GblOps] partitions. To include preloaded partitions as well,
75 /// use [AvbOps::get_size_of_partition].
partition_size(&mut self, partition: &str) -> IoResult<u64>76 fn partition_size(&mut self, partition: &str) -> IoResult<u64> {
77 self.gbl_ops.partition_size(partition).or(Err(IoError::Io))?.ok_or(IoError::NoSuchPartition)
78 }
79
80 /// Allowes implementation side to handle verification result.
handle_verification_result( &mut self, slot_verify: &SlotVerifyData, color: BootStateColor, ) -> IoResult<()>81 pub fn handle_verification_result(
82 &mut self,
83 slot_verify: &SlotVerifyData,
84 color: BootStateColor,
85 ) -> IoResult<()> {
86 let mut vbmeta = None;
87 let mut vbmeta_boot = None;
88 let mut vbmeta_system = None;
89 let mut vbmeta_vendor = None;
90
91 // The Android build system automatically generates only the main vbmeta, but also allows
92 // to have separate chained partitions like vbmeta_system (for system, product, system_ext,
93 // etc.) or vbmeta_vendor (for vendor).
94 // https://android.googlesource.com/platform/external/avb/+/master/README.md#build-system-integration
95 //
96 // It may also integrate chained vbmeta into system level metadata partitions such as boot
97 // or init_boot, so they can be updated separately.
98 // https://android.googlesource.com/platform/external/avb/+/master/README.md#gki-2_0-integration
99 //
100 // Custom chained partitions are also supported by the Android build system, but we expect
101 // OEMs to follow about the same pattern.
102 // https://android-review.googlesource.com/q/Id671e2c3aee9ada90256381cce432927df03169b
103 for data in slot_verify.vbmeta_data() {
104 match data.partition_name().to_str().unwrap_or_default() {
105 "vbmeta" => vbmeta = Some(data),
106 "boot" => vbmeta_boot = Some(data),
107 "vbmeta_system" => vbmeta_system = Some(data),
108 "vbmeta_vendor" => vbmeta_vendor = Some(data),
109 _ => {}
110 }
111 }
112
113 let data = vbmeta.ok_or(IoError::NoSuchPartition)?;
114 let boot_data = vbmeta_boot.unwrap_or(data);
115 let system_data = vbmeta_system.unwrap_or(data);
116 let vendor_data = vbmeta_vendor.unwrap_or(data);
117
118 let boot_os_version = boot_data.get_property_value("com.android.build.boot.os_version");
119 let boot_security_patch =
120 boot_data.get_property_value("com.android.build.boot.security_patch");
121
122 let system_os_version =
123 system_data.get_property_value("com.android.build.system.os_version");
124 let system_security_patch =
125 system_data.get_property_value("com.android.build.system.security_patch");
126
127 let vendor_os_version =
128 vendor_data.get_property_value("com.android.build.vendor.os_version");
129 let vendor_security_patch =
130 vendor_data.get_property_value("com.android.build.vendor.security_patch");
131
132 self.gbl_ops.avb_handle_verification_result(
133 color,
134 // TODO(b/337846185): extract VBH from the command line provided by libavb.
135 None,
136 boot_os_version,
137 boot_security_patch,
138 system_os_version,
139 system_security_patch,
140 vendor_os_version,
141 vendor_security_patch,
142 )
143 }
144
145 /// Get vbmeta public key validation status reported by validate_vbmeta_public_key.
key_validation_status(&self) -> IoResult<KeyValidationStatus>146 pub fn key_validation_status(&self) -> IoResult<KeyValidationStatus> {
147 self.key_validation_status.ok_or(IoError::NotImplemented)
148 }
149 }
150
151 /// A helper function for converting `CStr` to `str`
cstr_to_str<E>(s: &CStr, err: E) -> Result<&str, E>152 fn cstr_to_str<E>(s: &CStr, err: E) -> Result<&str, E> {
153 Ok(s.to_str().or(Err(err))?)
154 }
155
156 /// # Lifetimes
157 /// * `'a`: preloaded data lifetime
158 /// * `'b`: [GblOps] partition lifetime
159 impl<'a, 'b, 'c, T: GblOps<'b, 'c>> AvbOps<'a> for GblAvbOps<'a, T> {
read_from_partition( &mut self, partition: &CStr, offset: i64, buffer: &mut [u8], ) -> IoResult<usize>160 fn read_from_partition(
161 &mut self,
162 partition: &CStr,
163 offset: i64,
164 buffer: &mut [u8],
165 ) -> IoResult<usize> {
166 let part_str = cstr_to_str(partition, IoError::NoSuchPartition)?;
167 let partition_size = SafeNum::from(self.partition_size(part_str)?);
168 let read_off = match offset < 0 {
169 true => partition_size - offset.abs(),
170 _ => SafeNum::from(offset),
171 };
172 let read_sz = partition_size - read_off;
173 let read_off = read_off.try_into().or(Err(IoError::RangeOutsidePartition))?;
174 let read_sz =
175 min(buffer.len(), read_sz.try_into().or(Err(IoError::RangeOutsidePartition))?);
176 self.gbl_ops.read_from_partition_sync(part_str, read_off, &mut buffer[..read_sz]).map_err(
177 |e| match e {
178 Error::NotFound => IoError::NoSuchPartition,
179 Error::ArithmeticOverflow(_) => IoError::RangeOutsidePartition,
180 _ => IoError::Io,
181 },
182 )?;
183 Ok(read_sz)
184 }
185
get_preloaded_partition(&mut self, partition: &CStr) -> IoResult<&'a [u8]>186 fn get_preloaded_partition(&mut self, partition: &CStr) -> IoResult<&'a [u8]> {
187 let part_str = cstr_to_str(partition, IoError::NotImplemented)?;
188 Ok(self
189 .preloaded_partitions
190 .iter()
191 .find(|(name, _)| *name == part_str)
192 .ok_or(IoError::NotImplemented)?
193 .1)
194 }
195
validate_vbmeta_public_key( &mut self, public_key: &[u8], public_key_metadata: Option<&[u8]>, ) -> IoResult<bool>196 fn validate_vbmeta_public_key(
197 &mut self,
198 public_key: &[u8],
199 public_key_metadata: Option<&[u8]>,
200 ) -> IoResult<bool> {
201 let status = if self.use_cert {
202 match cert_validate_vbmeta_public_key(self, public_key, public_key_metadata)? {
203 true => KeyValidationStatus::Valid,
204 false => KeyValidationStatus::Invalid,
205 }
206 } else {
207 self.gbl_ops.avb_validate_vbmeta_public_key(public_key, public_key_metadata).or_else(
208 |err| {
209 // TODO(b/337846185): Remove fallback once AVB protocol implementation is
210 // forced.
211 fallback_not_implemented(
212 self.gbl_ops,
213 err,
214 "validate_vbmeta_public_key",
215 KeyValidationStatus::ValidCustomKey,
216 )
217 },
218 )?
219 };
220
221 self.key_validation_status = Some(status);
222
223 Ok(matches!(status, KeyValidationStatus::Valid | KeyValidationStatus::ValidCustomKey))
224 }
225
read_rollback_index(&mut self, rollback_index_location: usize) -> IoResult<u64>226 fn read_rollback_index(&mut self, rollback_index_location: usize) -> IoResult<u64> {
227 self.gbl_ops.avb_read_rollback_index(rollback_index_location).or_else(|err| {
228 // TODO(b/337846185): Remove fallback once AVB protocol implementation is
229 // forced.
230 fallback_not_implemented(self.gbl_ops, err, "read_rollback_index", 0)
231 })
232 }
233
write_rollback_index(&mut self, rollback_index_location: usize, index: u64) -> IoResult<()>234 fn write_rollback_index(&mut self, rollback_index_location: usize, index: u64) -> IoResult<()> {
235 self.gbl_ops.avb_write_rollback_index(rollback_index_location, index).or_else(|err| {
236 // TODO(b/337846185): Remove fallback once AVB protocol implementation is
237 // forced.
238 fallback_not_implemented(self.gbl_ops, err, "write_rollback_index", ())
239 })
240 }
241
read_is_device_unlocked(&mut self) -> IoResult<bool>242 fn read_is_device_unlocked(&mut self) -> IoResult<bool> {
243 self.gbl_ops.avb_read_is_device_unlocked().or_else(|err| {
244 // TODO(b/337846185): Remove fallback once AVB protocol implementation is
245 // forced.
246 fallback_not_implemented(self.gbl_ops, err, "read_is_device_unlocked", true)
247 })
248 }
249
get_unique_guid_for_partition(&mut self, partition: &CStr) -> IoResult<Uuid>250 fn get_unique_guid_for_partition(&mut self, partition: &CStr) -> IoResult<Uuid> {
251 // The ops is only used to check that a partition exists. GUID is not used.
252 self.partition_size(cstr_to_str(partition, IoError::NoSuchPartition)?)?;
253 Ok(Uuid::nil())
254 }
255
get_size_of_partition(&mut self, partition: &CStr) -> IoResult<u64>256 fn get_size_of_partition(&mut self, partition: &CStr) -> IoResult<u64> {
257 match self.get_preloaded_partition(partition) {
258 Ok(img) => Ok(img.len().try_into().unwrap()),
259 _ => {
260 let part_str = cstr_to_str(partition, IoError::NoSuchPartition)?;
261 self.partition_size(part_str)
262 }
263 }
264 }
265
read_persistent_value(&mut self, name: &CStr, value: &mut [u8]) -> IoResult<usize>266 fn read_persistent_value(&mut self, name: &CStr, value: &mut [u8]) -> IoResult<usize> {
267 self.gbl_ops.avb_read_persistent_value(name, value).or_else(|err| {
268 // TODO(b/337846185): Remove fallback once AVB protocol implementation is
269 // forced.
270 fallback_not_implemented(self.gbl_ops, err, "read_persistent_value", 0)
271 })
272 }
273
write_persistent_value(&mut self, name: &CStr, value: &[u8]) -> IoResult<()>274 fn write_persistent_value(&mut self, name: &CStr, value: &[u8]) -> IoResult<()> {
275 self.gbl_ops.avb_write_persistent_value(name, value).or_else(|err| {
276 // TODO(b/337846185): Remove fallback once AVB protocol implementation is
277 // forced.
278 fallback_not_implemented(self.gbl_ops, err, "write_persistent_value", ())
279 })
280 }
281
erase_persistent_value(&mut self, name: &CStr) -> IoResult<()>282 fn erase_persistent_value(&mut self, name: &CStr) -> IoResult<()> {
283 self.gbl_ops.avb_erase_persistent_value(name).or_else(|err| {
284 // TODO(b/337846185): Remove fallback once AVB protocol implementation is
285 // forced.
286 fallback_not_implemented(self.gbl_ops, err, "erase_persistent_value", ())
287 })
288 }
289
validate_public_key_for_partition( &mut self, _partition: &CStr, _public_key: &[u8], _public_key_metadata: Option<&[u8]>, ) -> IoResult<PublicKeyForPartitionInfo>290 fn validate_public_key_for_partition(
291 &mut self,
292 _partition: &CStr,
293 _public_key: &[u8],
294 _public_key_metadata: Option<&[u8]>,
295 ) -> IoResult<PublicKeyForPartitionInfo> {
296 // Not needed yet; eventually we will plumb this through [GblOps].
297 unreachable!();
298 }
299
cert_ops(&mut self) -> Option<&mut dyn CertOps>300 fn cert_ops(&mut self) -> Option<&mut dyn CertOps> {
301 match self.use_cert {
302 true => Some(self),
303 false => None,
304 }
305 }
306 }
307
308 /// [GblAvbOps] always implements [CertOps], but it's only used if `use_cert` is set.
309 impl<'a, 'b, T: GblOps<'a, 'b>> CertOps for GblAvbOps<'_, T> {
read_permanent_attributes( &mut self, attributes: &mut CertPermanentAttributes, ) -> IoResult<()>310 fn read_permanent_attributes(
311 &mut self,
312 attributes: &mut CertPermanentAttributes,
313 ) -> IoResult<()> {
314 self.gbl_ops.avb_cert_read_permanent_attributes(attributes)
315 }
316
read_permanent_attributes_hash(&mut self) -> IoResult<[u8; SHA256_DIGEST_SIZE]>317 fn read_permanent_attributes_hash(&mut self) -> IoResult<[u8; SHA256_DIGEST_SIZE]> {
318 self.gbl_ops.avb_cert_read_permanent_attributes_hash()
319 }
320
set_key_version(&mut self, rollback_index_location: usize, key_version: u64)321 fn set_key_version(&mut self, rollback_index_location: usize, key_version: u64) {
322 // Checks if there is already an allocated slot for this location.
323 let existing = self
324 .key_versions
325 .iter_mut()
326 .find_map(|v| v.as_mut().filter(|(loc, _)| *loc == rollback_index_location));
327 match existing {
328 Some((_, val)) => *val = max(*val, key_version),
329 _ => {
330 // Finds an empty slot and stores the rollback index.
331 *self
332 .key_versions
333 .iter_mut()
334 .find(|v| v.is_none())
335 .expect("Ran out of key version slots") =
336 Some((rollback_index_location, key_version))
337 }
338 }
339 }
340
get_random(&mut self, _: &mut [u8]) -> IoResult<()>341 fn get_random(&mut self, _: &mut [u8]) -> IoResult<()> {
342 // Not needed yet; eventually we will plumb this through [GblOps].
343 unimplemented!()
344 }
345 }
346
fallback_not_implemented<'a, 'b, T>( ops: &mut impl GblOps<'a, 'b>, error: IoError, method_name: &str, value: T, ) -> IoResult<T>347 fn fallback_not_implemented<'a, 'b, T>(
348 ops: &mut impl GblOps<'a, 'b>,
349 error: IoError,
350 method_name: &str,
351 value: T,
352 ) -> IoResult<T> {
353 match error {
354 IoError::NotImplemented => {
355 gbl_println!(
356 ops,
357 "WARNING: UEFI GblEfiAvbProtocol.{} implementation is missing. This will not be \
358 permitted in the future.",
359 method_name,
360 );
361 Ok(value)
362 }
363 err => Err(err),
364 }
365 }
366
367 #[cfg(test)]
368 mod test {
369 use super::*;
370 use crate::ops::test::{FakeGblOps, FakeGblOpsStorage};
371
372 // Returns test data consisting of `size` incrementing bytes (0-255 repeating).
test_data(size: usize) -> Vec<u8>373 fn test_data(size: usize) -> Vec<u8> {
374 let mut data = vec![0u8; size];
375 for index in 0..data.len() {
376 data[index] = index as u8;
377 }
378 data
379 }
380
381 #[test]
read_from_partition_positive_off()382 fn read_from_partition_positive_off() {
383 let mut storage = FakeGblOpsStorage::default();
384 storage.add_raw_device(c"test_part", test_data(512));
385
386 let mut gbl_ops = FakeGblOps::new(&storage);
387 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
388
389 // Positive offset.
390 let mut out = [0u8; 4];
391 assert_eq!(avb_ops.read_from_partition(c"test_part", 1, &mut out[..]), Ok(4));
392 assert_eq!(out, [1, 2, 3, 4]);
393 }
394
395 #[test]
read_from_partition_negative_off()396 fn read_from_partition_negative_off() {
397 let mut storage = FakeGblOpsStorage::default();
398 storage.add_raw_device(c"test_part", test_data(512));
399
400 let mut gbl_ops = FakeGblOps::new(&storage);
401 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
402
403 // Negative offset should wrap from the end
404 let mut out = [0u8; 6];
405 assert_eq!(avb_ops.read_from_partition(c"test_part", -6, &mut out[..]), Ok(6));
406 assert_eq!(out, [0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF]);
407 }
408
409 #[test]
read_from_partition_partial_read()410 fn read_from_partition_partial_read() {
411 let mut storage = FakeGblOpsStorage::default();
412 storage.add_raw_device(c"test_part", test_data(512));
413
414 let mut gbl_ops = FakeGblOps::new(&storage);
415 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
416
417 // Reading past the end of the partition should truncate.
418 let mut out = [0u8; 6];
419 assert_eq!(avb_ops.read_from_partition(c"test_part", -3, &mut out[..]), Ok(3));
420 assert_eq!(out, [0xFD, 0xFE, 0xFF, 0, 0, 0]);
421 }
422
423 #[test]
read_from_partition_out_of_bounds()424 fn read_from_partition_out_of_bounds() {
425 let mut storage = FakeGblOpsStorage::default();
426 storage.add_raw_device(c"test_part", test_data(512));
427
428 let mut gbl_ops = FakeGblOps::new(&storage);
429 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
430
431 // Reads starting out of bounds should fail.
432 let mut out = [0u8; 4];
433 assert_eq!(
434 avb_ops.read_from_partition(c"test_part", 513, &mut out[..]),
435 Err(IoError::RangeOutsidePartition)
436 );
437 assert_eq!(
438 avb_ops.read_from_partition(c"test_part", -513, &mut out[..]),
439 Err(IoError::RangeOutsidePartition)
440 );
441 }
442
443 #[test]
read_from_partition_unknown_part()444 fn read_from_partition_unknown_part() {
445 let mut gbl_ops = FakeGblOps::new(&[]);
446 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
447
448 let mut out = [0u8; 4];
449 assert_eq!(
450 avb_ops.read_from_partition(c"unknown_part", 0, &mut out[..]),
451 Err(IoError::NoSuchPartition)
452 );
453 }
454
455 #[test]
set_key_version_default()456 fn set_key_version_default() {
457 let mut gbl_ops = FakeGblOps::new(&[]);
458 let avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
459
460 assert_eq!(avb_ops.key_versions, [None, None]);
461 }
462
463 #[test]
set_key_version_once()464 fn set_key_version_once() {
465 let mut gbl_ops = FakeGblOps::new(&[]);
466 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
467
468 avb_ops.set_key_version(5, 10);
469 assert_eq!(avb_ops.key_versions, [Some((5, 10)), None]);
470 }
471
472 #[test]
set_key_version_twice()473 fn set_key_version_twice() {
474 let mut gbl_ops = FakeGblOps::new(&[]);
475 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
476
477 avb_ops.set_key_version(5, 10);
478 avb_ops.set_key_version(20, 40);
479 assert_eq!(avb_ops.key_versions, [Some((5, 10)), Some((20, 40))]);
480 }
481
482 #[test]
set_key_version_overwrite()483 fn set_key_version_overwrite() {
484 let mut gbl_ops = FakeGblOps::new(&[]);
485 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
486
487 avb_ops.set_key_version(5, 10);
488 avb_ops.set_key_version(20, 40);
489 avb_ops.set_key_version(5, 100);
490 assert_eq!(avb_ops.key_versions, [Some((5, 100)), Some((20, 40))]);
491 }
492
493 // AVB's key version callback cannot return an error, so if it fails we panic.
494 //
495 // It's possible we could stash the failure somewhere and check it later, but we'd have to be
496 // very careful, as failing to check the status would be a security vulnerability. For now it's
497 // safer to panic, and we only ever expect the PSK and PIK to have key versions.
498 #[test]
499 #[should_panic(expected = "Ran out of key version slots")]
set_key_version_overflow()500 fn set_key_version_overflow() {
501 let mut gbl_ops = FakeGblOps::new(&[]);
502 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
503
504 avb_ops.set_key_version(5, 10);
505 avb_ops.set_key_version(20, 40);
506 avb_ops.set_key_version(40, 100);
507 }
508
509 #[test]
validate_vbmeta_public_key_valid()510 fn validate_vbmeta_public_key_valid() {
511 let mut gbl_ops = FakeGblOps::new(&[]);
512 gbl_ops.avb_key_validation_status = Some(Ok(KeyValidationStatus::Valid));
513
514 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
515 assert_eq!(avb_ops.validate_vbmeta_public_key(&[], None), Ok(true));
516 assert_eq!(avb_ops.key_validation_status(), Ok(KeyValidationStatus::Valid));
517 }
518
519 #[test]
validate_vbmeta_public_key_valid_custom_key()520 fn validate_vbmeta_public_key_valid_custom_key() {
521 let mut gbl_ops = FakeGblOps::new(&[]);
522 gbl_ops.avb_key_validation_status = Some(Ok(KeyValidationStatus::ValidCustomKey));
523
524 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
525 assert_eq!(avb_ops.validate_vbmeta_public_key(&[], None), Ok(true));
526 assert_eq!(avb_ops.key_validation_status(), Ok(KeyValidationStatus::ValidCustomKey));
527 }
528
529 #[test]
validate_vbmeta_public_key_invalid()530 fn validate_vbmeta_public_key_invalid() {
531 let mut gbl_ops = FakeGblOps::new(&[]);
532 gbl_ops.avb_key_validation_status = Some(Ok(KeyValidationStatus::Invalid));
533
534 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
535 assert_eq!(avb_ops.validate_vbmeta_public_key(&[], None), Ok(false));
536 assert_eq!(avb_ops.key_validation_status(), Ok(KeyValidationStatus::Invalid));
537 }
538
539 #[test]
validate_vbmeta_public_key_failed()540 fn validate_vbmeta_public_key_failed() {
541 let mut gbl_ops = FakeGblOps::new(&[]);
542 gbl_ops.avb_key_validation_status = Some(Err(IoError::Io));
543
544 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
545 assert_eq!(avb_ops.validate_vbmeta_public_key(&[], None), Err(IoError::Io));
546 assert!(avb_ops.key_validation_status().is_err());
547 }
548
549 // TODO(b/337846185): Remove test once AVB protocol implementation is forced.
550 #[test]
validate_vbmeta_public_key_not_implemented()551 fn validate_vbmeta_public_key_not_implemented() {
552 let mut gbl_ops = FakeGblOps::new(&[]);
553 gbl_ops.avb_key_validation_status = Some(Err(IoError::NotImplemented));
554
555 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
556
557 assert_eq!(avb_ops.validate_vbmeta_public_key(&[], None), Ok(true));
558 assert_eq!(avb_ops.key_validation_status(), Ok(KeyValidationStatus::ValidCustomKey));
559 }
560
561 #[test]
read_rollback_index_read_value()562 fn read_rollback_index_read_value() {
563 const EXPECTED_INDEX: usize = 1;
564 const EXPECTED_VALUE: u64 = 100;
565
566 let mut gbl_ops = FakeGblOps::new(&[]);
567 gbl_ops.avb_ops.rollbacks.insert(EXPECTED_INDEX, Ok(EXPECTED_VALUE));
568
569 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
570 assert_eq!(avb_ops.read_rollback_index(EXPECTED_INDEX), Ok(EXPECTED_VALUE));
571 }
572
573 #[test]
read_rollback_index_error_handled()574 fn read_rollback_index_error_handled() {
575 let mut gbl_ops = FakeGblOps::new(&[]);
576
577 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
578 assert_eq!(avb_ops.read_rollback_index(0), Err(IoError::Io));
579 }
580
581 // TODO(b/337846185): Remove test once AVB protocol implementation is forced.
582 #[test]
read_rollback_index_not_implemented()583 fn read_rollback_index_not_implemented() {
584 let mut gbl_ops = FakeGblOps::new(&[]);
585 gbl_ops.avb_ops.rollbacks.insert(0, Err(IoError::NotImplemented));
586
587 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
588 assert_eq!(avb_ops.read_rollback_index(0), Ok(0));
589 }
590
591 #[test]
write_rollback_index_write_value()592 fn write_rollback_index_write_value() {
593 const EXPECTED_INDEX: usize = 1;
594 const EXPECTED_VALUE: u64 = 100;
595
596 let mut gbl_ops = FakeGblOps::new(&[]);
597
598 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
599 assert_eq!(avb_ops.write_rollback_index(EXPECTED_INDEX, EXPECTED_VALUE), Ok(()));
600 assert_eq!(
601 gbl_ops.avb_ops.rollbacks.get(&EXPECTED_INDEX),
602 Some(Ok(EXPECTED_VALUE)).as_ref()
603 );
604 }
605
606 #[test]
write_rollback_index_error_handled()607 fn write_rollback_index_error_handled() {
608 let mut gbl_ops = FakeGblOps::new(&[]);
609 gbl_ops.avb_ops.rollbacks.insert(0, Err(IoError::Io));
610
611 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
612 assert_eq!(avb_ops.write_rollback_index(0, 0), Err(IoError::Io));
613 }
614
615 // TODO(b/337846185): Remove test once AVB protocol implementation is forced.
616 #[test]
write_rollback_index_not_implemented()617 fn write_rollback_index_not_implemented() {
618 let mut gbl_ops = FakeGblOps::new(&[]);
619 gbl_ops.avb_ops.rollbacks.insert(0, Err(IoError::NotImplemented));
620
621 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
622 assert_eq!(avb_ops.write_rollback_index(0, 0), Ok(()));
623 }
624
625 #[test]
read_is_device_unlocked_value_obtained()626 fn read_is_device_unlocked_value_obtained() {
627 let mut gbl_ops = FakeGblOps::new(&[]);
628 gbl_ops.avb_ops.unlock_state = Ok(true);
629
630 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
631
632 assert_eq!(avb_ops.read_is_device_unlocked(), Ok(true));
633 }
634
635 #[test]
read_is_device_unlocked_error_handled()636 fn read_is_device_unlocked_error_handled() {
637 let mut gbl_ops = FakeGblOps::new(&[]);
638 gbl_ops.avb_ops.unlock_state = Err(IoError::Io);
639
640 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
641 assert_eq!(avb_ops.read_is_device_unlocked(), Err(IoError::Io));
642 }
643
644 // TODO(b/337846185): Remove test once AVB protocol implementation is forced.
645 #[test]
read_is_device_unlocked_not_implemented()646 fn read_is_device_unlocked_not_implemented() {
647 let mut gbl_ops = FakeGblOps::new(&[]);
648 gbl_ops.avb_ops.unlock_state = Err(IoError::NotImplemented);
649
650 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
651 assert_eq!(avb_ops.read_is_device_unlocked(), Ok(true));
652 }
653
654 #[test]
read_persistent_value_success()655 fn read_persistent_value_success() {
656 const EXPECTED_NAME: &CStr = c"test";
657 const EXPECTED_VALUE: &[u8] = b"test";
658
659 let mut gbl_ops = FakeGblOps::new(&[]);
660 gbl_ops.avb_ops.add_persistent_value(EXPECTED_NAME.to_str().unwrap(), Ok(EXPECTED_VALUE));
661
662 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
663 let mut buffer = [0u8; EXPECTED_VALUE.len()];
664 assert_eq!(
665 avb_ops.read_persistent_value(EXPECTED_NAME, &mut buffer),
666 Ok(EXPECTED_VALUE.len())
667 );
668 assert_eq!(buffer, EXPECTED_VALUE);
669 }
670
671 #[test]
read_persistent_value_error()672 fn read_persistent_value_error() {
673 const EXPECTED_NAME: &CStr = c"test";
674
675 let mut gbl_ops = FakeGblOps::new(&[]);
676 gbl_ops.avb_ops.add_persistent_value(EXPECTED_NAME.to_str().unwrap(), Err(IoError::Io));
677
678 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
679 let mut buffer = [0u8; 4];
680 assert_eq!(avb_ops.read_persistent_value(EXPECTED_NAME, &mut buffer), Err(IoError::Io));
681 }
682
683 // TODO(b/337846185): Remove test once AVB protocol implementation is forced.
684 #[test]
read_persistent_value_not_implemented()685 fn read_persistent_value_not_implemented() {
686 const EXPECTED_NAME: &CStr = c"test";
687
688 let mut gbl_ops = FakeGblOps::new(&[]);
689 gbl_ops
690 .avb_ops
691 .add_persistent_value(EXPECTED_NAME.to_str().unwrap(), Err(IoError::NotImplemented));
692
693 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
694 let mut buffer = [0u8; 0];
695 assert_eq!(avb_ops.read_persistent_value(EXPECTED_NAME, &mut buffer), Ok(0));
696 }
697
698 #[test]
write_persistent_value_success()699 fn write_persistent_value_success() {
700 const EXPECTED_NAME: &CStr = c"test";
701 const EXPECTED_VALUE: &[u8] = b"test";
702
703 let mut gbl_ops = FakeGblOps::new(&[]);
704
705 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
706 assert_eq!(avb_ops.write_persistent_value(EXPECTED_NAME, EXPECTED_VALUE), Ok(()));
707
708 assert_eq!(
709 gbl_ops.avb_ops.persistent_values.get(EXPECTED_NAME.to_str().unwrap()),
710 Some(Ok(EXPECTED_VALUE.to_vec())).as_ref()
711 );
712 }
713
714 #[test]
write_persistent_value_error()715 fn write_persistent_value_error() {
716 const EXPECTED_NAME: &CStr = c"test";
717 const EXPECTED_VALUE: &[u8] = b"test";
718
719 let mut gbl_ops = FakeGblOps::new(&[]);
720 gbl_ops.avb_ops.add_persistent_value(EXPECTED_NAME.to_str().unwrap(), Err(IoError::Io));
721
722 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
723 assert_eq!(avb_ops.write_persistent_value(EXPECTED_NAME, EXPECTED_VALUE), Err(IoError::Io));
724 }
725
726 // TODO(b/337846185): Remove test once AVB protocol implementation is forced.
727 #[test]
write_persistent_value_not_implemented()728 fn write_persistent_value_not_implemented() {
729 const EXPECTED_NAME: &CStr = c"test";
730 const EXPECTED_VALUE: &[u8] = b"test";
731
732 let mut gbl_ops = FakeGblOps::new(&[]);
733 gbl_ops
734 .avb_ops
735 .add_persistent_value(EXPECTED_NAME.to_str().unwrap(), Err(IoError::NotImplemented));
736
737 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
738 assert_eq!(avb_ops.write_persistent_value(EXPECTED_NAME, EXPECTED_VALUE), Ok(()));
739 }
740
741 #[test]
erase_persistent_value_success()742 fn erase_persistent_value_success() {
743 const EXPECTED_NAME: &CStr = c"test";
744
745 let mut gbl_ops = FakeGblOps::new(&[]);
746 gbl_ops.avb_ops.add_persistent_value(EXPECTED_NAME.to_str().unwrap(), Ok(b"test"));
747
748 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
749 assert_eq!(avb_ops.erase_persistent_value(EXPECTED_NAME), Ok(()));
750
751 assert!(!gbl_ops.avb_ops.persistent_values.contains_key(EXPECTED_NAME.to_str().unwrap()));
752 }
753
754 #[test]
erase_persistent_value_error()755 fn erase_persistent_value_error() {
756 const EXPECTED_NAME: &CStr = c"test";
757
758 let mut gbl_ops = FakeGblOps::new(&[]);
759 gbl_ops.avb_ops.add_persistent_value(EXPECTED_NAME.to_str().unwrap(), Err(IoError::Io));
760
761 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
762 assert_eq!(avb_ops.erase_persistent_value(EXPECTED_NAME), Err(IoError::Io));
763 }
764
765 // TODO(b/337846185): Remove test once AVB protocol implementation is forced.
766 #[test]
erase_persistent_value_not_implemented()767 fn erase_persistent_value_not_implemented() {
768 const EXPECTED_NAME: &CStr = c"test";
769
770 let mut gbl_ops = FakeGblOps::new(&[]);
771 gbl_ops
772 .avb_ops
773 .add_persistent_value(EXPECTED_NAME.to_str().unwrap(), Err(IoError::NotImplemented));
774
775 let mut avb_ops = GblAvbOps::new(&mut gbl_ops, &[], false);
776 assert_eq!(avb_ops.erase_persistent_value(EXPECTED_NAME), Ok(()));
777 }
778 }
779