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