blob: 900e15209f0a98231df02e25bd087df8923c6c13 [file] [log] [blame]
Alice Wang28cbcf12022-12-01 07:58:28 +00001// Copyright 2022, 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//! This module regroups methods related to AvbOps.
16
17#![warn(unsafe_op_in_unsafe_fn)]
18// TODO(b/256148034): Remove this when the feature is code complete.
19#![allow(dead_code)]
20#![allow(unused_imports)]
21
22extern crate alloc;
23
24use alloc::ffi::CString;
25use avb_bindgen::{
26 avb_slot_verify, AvbHashtreeErrorMode_AVB_HASHTREE_ERROR_MODE_EIO,
27 AvbSlotVerifyFlags_AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION,
28 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT,
29 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA,
30 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_IO,
31 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_OOM,
32 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED,
33 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX,
34 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION,
35 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
36 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_OK,
37};
38use core::fmt;
39use log::debug;
40
41/// Error code from AVB image verification.
42#[derive(Clone, Copy, Debug)]
43pub enum AvbImageVerifyError {
44 /// AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
45 InvalidArgument,
46 /// AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA
47 InvalidMetadata,
48 /// AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_IO
49 Io,
50 /// AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_OOM
51 Oom,
52 /// AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED
53 PublicKeyRejected,
54 /// AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX
55 RollbackIndex,
56 /// AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION
57 UnsupportedVersion,
58 /// AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION
59 Verification,
60 /// Unknown error.
61 Unknown(u32),
62}
63
64fn to_avb_verify_result(result: u32) -> Result<(), AvbImageVerifyError> {
65 #[allow(non_upper_case_globals)]
66 match result {
67 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_OK => Ok(()),
68 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT => {
69 Err(AvbImageVerifyError::InvalidArgument)
70 }
71 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA => {
72 Err(AvbImageVerifyError::InvalidMetadata)
73 }
74 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_IO => Err(AvbImageVerifyError::Io),
75 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_OOM => Err(AvbImageVerifyError::Oom),
76 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED => {
77 Err(AvbImageVerifyError::PublicKeyRejected)
78 }
79 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX => {
80 Err(AvbImageVerifyError::RollbackIndex)
81 }
82 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION => {
83 Err(AvbImageVerifyError::UnsupportedVersion)
84 }
85 AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION => {
86 Err(AvbImageVerifyError::Verification)
87 }
88 _ => Err(AvbImageVerifyError::Unknown(result)),
89 }
90}
91
92impl fmt::Display for AvbImageVerifyError {
93 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94 match self {
95 Self::InvalidArgument => write!(f, "Invalid parameters."),
96 Self::InvalidMetadata => write!(f, "Invalid metadata."),
97 Self::Io => write!(f, "I/O error while trying to load data or get a rollback index."),
98 Self::Oom => write!(f, "Unable to allocate memory."),
99 Self::PublicKeyRejected => write!(
100 f,
101 "Everything is verified correctly out but the public key is not accepted. \
102 This includes the case where integrity data is not signed."
103 ),
104 Self::RollbackIndex => write!(f, "Rollback index is less than its stored value."),
105 Self::UnsupportedVersion => write!(
106 f,
107 "Some of the metadata requires a newer version of libavb than what is in use."
108 ),
109 Self::Verification => write!(f, "Data does not verify."),
110 Self::Unknown(e) => write!(f, "Unknown avb_slot_verify error '{e}'"),
111 }
112 }
113}
114
115/// Verifies that for the given image:
116/// - The given public key is acceptable.
117/// - The VBMeta struct is valid.
118/// - The partitions of the image match the descriptors of the verified VBMeta struct.
119/// Returns Ok if everything is verified correctly and the public key is accepted.
120pub fn verify_image(image: &[u8], public_key: &[u8]) -> Result<(), AvbImageVerifyError> {
121 AvbOps::new().verify_image(image, public_key)
122}
123
124/// TODO(b/256148034): Make AvbOps a rust wrapper of avb_bindgen::AvbOps using foreign_types.
125struct AvbOps {}
126
127impl AvbOps {
128 fn new() -> Self {
129 AvbOps {}
130 }
131
132 fn verify_image(&self, image: &[u8], public_key: &[u8]) -> Result<(), AvbImageVerifyError> {
133 debug!("AVB image: addr={:?}, size={:#x} ({1})", image.as_ptr(), image.len());
134 debug!(
135 "AVB public key: addr={:?}, size={:#x} ({1})",
136 public_key.as_ptr(),
137 public_key.len()
138 );
139 // TODO(b/256148034): Verify the kernel image with avb_slot_verify()
140 // let result = unsafe {
141 // avb_slot_verify(
142 // self.as_ptr(),
143 // requested_partitions.as_ptr(),
144 // ab_suffix.as_ptr(),
145 // AvbSlotVerifyFlags_AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION,
146 // AvbHashtreeErrorMode_AVB_HASHTREE_ERROR_MODE_EIO,
147 // &image.as_ptr(),
148 // )
149 // };
150 let result = AvbSlotVerifyResult_AVB_SLOT_VERIFY_RESULT_OK;
151 to_avb_verify_result(result)
152 }
153}