1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright (C) 2016 The Android Open Source Project
4  */
5 
6 #include "avb_vbmeta_image.h"
7 #include "avb_crypto.h"
8 #include "avb_rsa.h"
9 #include "avb_sha.h"
10 #include "avb_util.h"
11 #include "avb_version.h"
12 
avb_vbmeta_image_verify(const uint8_t * data,size_t length,const uint8_t ** out_public_key_data,size_t * out_public_key_length)13 AvbVBMetaVerifyResult avb_vbmeta_image_verify(
14     const uint8_t* data,
15     size_t length,
16     const uint8_t** out_public_key_data,
17     size_t* out_public_key_length) {
18   AvbVBMetaVerifyResult ret;
19   AvbVBMetaImageHeader h;
20   uint8_t* computed_hash;
21   const AvbAlgorithmData* algorithm;
22   AvbSHA256Ctx sha256_ctx;
23   AvbSHA512Ctx sha512_ctx;
24   const uint8_t* header_block;
25   const uint8_t* authentication_block;
26   const uint8_t* auxiliary_block;
27   int verification_result;
28 
29   ret = AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER;
30 
31   if (out_public_key_data != NULL) {
32     *out_public_key_data = NULL;
33   }
34   if (out_public_key_length != NULL) {
35     *out_public_key_length = 0;
36   }
37 
38   /* Before we byteswap or compare Magic, ensure length is long enough. */
39   if (length < sizeof(AvbVBMetaImageHeader)) {
40     avb_error("Length is smaller than header.\n");
41     goto out;
42   }
43 
44   /* Ensure magic is correct. */
45   if (avb_safe_memcmp(data, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
46     avb_error("Magic is incorrect.\n");
47     goto out;
48   }
49 
50   avb_vbmeta_image_header_to_host_byte_order((const AvbVBMetaImageHeader*)data,
51                                              &h);
52 
53   /* Ensure we don't attempt to access any fields if we do not meet
54    * the specified minimum version of libavb.
55    */
56   if ((h.required_libavb_version_major != AVB_VERSION_MAJOR) ||
57       (h.required_libavb_version_minor > AVB_VERSION_MINOR)) {
58     avb_error("Mismatch between image version and libavb version.\n");
59     ret = AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION;
60     goto out;
61   }
62 
63   /* Ensure |release_string| ends with a NUL byte. */
64   if (h.release_string[AVB_RELEASE_STRING_SIZE - 1] != '\0') {
65     avb_error("Release string does not end with a NUL byte.\n");
66     goto out;
67   }
68 
69   /* Ensure inner block sizes are multiple of 64. */
70   if ((h.authentication_data_block_size & 0x3f) != 0 ||
71       (h.auxiliary_data_block_size & 0x3f) != 0) {
72     avb_error("Block size is not a multiple of 64.\n");
73     goto out;
74   }
75 
76   /* Ensure block sizes all add up to at most |length|. */
77   uint64_t block_total = sizeof(AvbVBMetaImageHeader);
78   if (!avb_safe_add_to(&block_total, h.authentication_data_block_size) ||
79       !avb_safe_add_to(&block_total, h.auxiliary_data_block_size)) {
80     avb_error("Overflow while computing size of boot image.\n");
81     goto out;
82   }
83   if (block_total > length) {
84     avb_error("Block sizes add up to more than given length.\n");
85     goto out;
86   }
87 
88   uintptr_t data_ptr = (uintptr_t)data;
89   /* Ensure passed in memory doesn't wrap. */
90   if (!avb_safe_add(NULL, (uint64_t)data_ptr, length)) {
91     avb_error("Boot image location and length mismatch.\n");
92     goto out;
93   }
94 
95   /* Ensure hash and signature are entirely in the Authentication data block. */
96   uint64_t hash_end;
97   if (!avb_safe_add(&hash_end, h.hash_offset, h.hash_size) ||
98       hash_end > h.authentication_data_block_size) {
99     avb_error("Hash is not entirely in its block.\n");
100     goto out;
101   }
102   uint64_t signature_end;
103   if (!avb_safe_add(&signature_end, h.signature_offset, h.signature_size) ||
104       signature_end > h.authentication_data_block_size) {
105     avb_error("Signature is not entirely in its block.\n");
106     goto out;
107   }
108 
109   /* Ensure public key is entirely in the Auxiliary data block. */
110   uint64_t pubkey_end;
111   if (!avb_safe_add(&pubkey_end, h.public_key_offset, h.public_key_size) ||
112       pubkey_end > h.auxiliary_data_block_size) {
113     avb_error("Public key is not entirely in its block.\n");
114     goto out;
115   }
116 
117   /* Ensure public key metadata (if set) is entirely in the Auxiliary
118    * data block. */
119   if (h.public_key_metadata_size > 0) {
120     uint64_t pubkey_md_end;
121     if (!avb_safe_add(&pubkey_md_end,
122                       h.public_key_metadata_offset,
123                       h.public_key_metadata_size) ||
124         pubkey_md_end > h.auxiliary_data_block_size) {
125       avb_error("Public key metadata is not entirely in its block.\n");
126       goto out;
127     }
128   }
129 
130   /* Bail early if there's no hash or signature. */
131   if (h.algorithm_type == AVB_ALGORITHM_TYPE_NONE) {
132     ret = AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED;
133     goto out;
134   }
135 
136   /* Ensure algorithm field is supported. */
137   algorithm = avb_get_algorithm_data(h.algorithm_type);
138   if (!algorithm) {
139     avb_error("Invalid or unknown algorithm.\n");
140     goto out;
141   }
142 
143   /* Bail if the embedded hash size doesn't match the chosen algorithm. */
144   if (h.hash_size != algorithm->hash_len) {
145     avb_error("Embedded hash has wrong size.\n");
146     goto out;
147   }
148 
149   /* No overflow checks needed from here-on after since all block
150    * sizes and offsets have been verified above.
151    */
152 
153   header_block = data;
154   authentication_block = header_block + sizeof(AvbVBMetaImageHeader);
155   auxiliary_block = authentication_block + h.authentication_data_block_size;
156 
157   switch (h.algorithm_type) {
158     /* Explicit fall-through: */
159     case AVB_ALGORITHM_TYPE_SHA256_RSA2048:
160     case AVB_ALGORITHM_TYPE_SHA256_RSA4096:
161     case AVB_ALGORITHM_TYPE_SHA256_RSA8192:
162       avb_sha256_init(&sha256_ctx);
163       avb_sha256_update(
164           &sha256_ctx, header_block, sizeof(AvbVBMetaImageHeader));
165       avb_sha256_update(
166           &sha256_ctx, auxiliary_block, h.auxiliary_data_block_size);
167       computed_hash = avb_sha256_final(&sha256_ctx);
168       break;
169     /* Explicit fall-through: */
170     case AVB_ALGORITHM_TYPE_SHA512_RSA2048:
171     case AVB_ALGORITHM_TYPE_SHA512_RSA4096:
172     case AVB_ALGORITHM_TYPE_SHA512_RSA8192:
173       avb_sha512_init(&sha512_ctx);
174       avb_sha512_update(
175           &sha512_ctx, header_block, sizeof(AvbVBMetaImageHeader));
176       avb_sha512_update(
177           &sha512_ctx, auxiliary_block, h.auxiliary_data_block_size);
178       computed_hash = avb_sha512_final(&sha512_ctx);
179       break;
180     default:
181       avb_error("Unknown algorithm.\n");
182       goto out;
183   }
184 
185   if (avb_safe_memcmp(authentication_block + h.hash_offset,
186                       computed_hash,
187                       h.hash_size) != 0) {
188     avb_error("Hash does not match!\n");
189     ret = AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH;
190     goto out;
191   }
192 
193   verification_result =
194       avb_rsa_verify(auxiliary_block + h.public_key_offset,
195                      h.public_key_size,
196                      authentication_block + h.signature_offset,
197                      h.signature_size,
198                      authentication_block + h.hash_offset,
199                      h.hash_size,
200                      algorithm->padding,
201                      algorithm->padding_len);
202 
203   if (verification_result == 0) {
204     ret = AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH;
205     goto out;
206   }
207 
208   if (h.public_key_size > 0) {
209     if (out_public_key_data != NULL) {
210       *out_public_key_data = auxiliary_block + h.public_key_offset;
211     }
212     if (out_public_key_length != NULL) {
213       *out_public_key_length = h.public_key_size;
214     }
215   }
216 
217   ret = AVB_VBMETA_VERIFY_RESULT_OK;
218 
219 out:
220   return ret;
221 }
222 
avb_vbmeta_image_header_to_host_byte_order(const AvbVBMetaImageHeader * src,AvbVBMetaImageHeader * dest)223 void avb_vbmeta_image_header_to_host_byte_order(const AvbVBMetaImageHeader* src,
224                                                 AvbVBMetaImageHeader* dest) {
225   avb_memcpy(dest, src, sizeof(AvbVBMetaImageHeader));
226 
227   dest->required_libavb_version_major =
228       avb_be32toh(dest->required_libavb_version_major);
229   dest->required_libavb_version_minor =
230       avb_be32toh(dest->required_libavb_version_minor);
231 
232   dest->authentication_data_block_size =
233       avb_be64toh(dest->authentication_data_block_size);
234   dest->auxiliary_data_block_size =
235       avb_be64toh(dest->auxiliary_data_block_size);
236 
237   dest->algorithm_type = avb_be32toh(dest->algorithm_type);
238 
239   dest->hash_offset = avb_be64toh(dest->hash_offset);
240   dest->hash_size = avb_be64toh(dest->hash_size);
241 
242   dest->signature_offset = avb_be64toh(dest->signature_offset);
243   dest->signature_size = avb_be64toh(dest->signature_size);
244 
245   dest->public_key_offset = avb_be64toh(dest->public_key_offset);
246   dest->public_key_size = avb_be64toh(dest->public_key_size);
247 
248   dest->public_key_metadata_offset =
249       avb_be64toh(dest->public_key_metadata_offset);
250   dest->public_key_metadata_size = avb_be64toh(dest->public_key_metadata_size);
251 
252   dest->descriptors_offset = avb_be64toh(dest->descriptors_offset);
253   dest->descriptors_size = avb_be64toh(dest->descriptors_size);
254 
255   dest->rollback_index = avb_be64toh(dest->rollback_index);
256   dest->flags = avb_be32toh(dest->flags);
257 }
258 
avb_vbmeta_verify_result_to_string(AvbVBMetaVerifyResult result)259 const char* avb_vbmeta_verify_result_to_string(AvbVBMetaVerifyResult result) {
260   const char* ret = NULL;
261 
262   switch (result) {
263     case AVB_VBMETA_VERIFY_RESULT_OK:
264       ret = "OK";
265       break;
266     case AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED:
267       ret = "OK_NOT_SIGNED";
268       break;
269     case AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER:
270       ret = "INVALID_VBMETA_HEADER";
271       break;
272     case AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION:
273       ret = "UNSUPPORTED_VERSION";
274       break;
275     case AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH:
276       ret = "HASH_MISMATCH";
277       break;
278     case AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH:
279       ret = "SIGNATURE_MISMATCH";
280       break;
281       /* Do not add a 'default:' case here because of -Wswitch. */
282   }
283 
284   if (ret == NULL) {
285     avb_error("Unknown AvbVBMetaVerifyResult value.\n");
286     ret = "(unknown)";
287   }
288 
289   return ret;
290 }
291