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