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