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