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