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