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