1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <errno.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 21 #include <memory> 22 #include <string> 23 24 #include <android-base/file.h> 25 #include <android-base/test_utils.h> 26 #include <android-base/unique_fd.h> 27 #include <crypto_utils/android_pubkey.h> 28 #include <fec/io.h> 29 #include <openssl/obj_mac.h> 30 #include <openssl/rsa.h> 31 #include <openssl/sha.h> 32 #include <sparse/sparse.h> 33 34 static RSA* load_key(const char* path) { 35 std::string content; 36 if (!android::base::ReadFileToString(path, &content) || 37 content.size() < ANDROID_PUBKEY_ENCODED_SIZE) { 38 fprintf(stderr, "Failed to load key from %s\n", path); 39 return nullptr; 40 } 41 42 RSA* key = nullptr; 43 if (!android_pubkey_decode(reinterpret_cast<const uint8_t*>(content.c_str()), 44 ANDROID_PUBKEY_ENCODED_SIZE, &key)) { 45 fprintf(stderr, "Failed to parse key!\n"); 46 return nullptr; 47 } 48 49 return key; 50 } 51 52 static int verify_table(const char* key_path, const uint8_t* signature, size_t signature_size, 53 const char* table, uint32_t table_length) { 54 // Hash the table 55 uint8_t hash_buf[SHA256_DIGEST_LENGTH]; 56 SHA256(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(table)), table_length, hash_buf); 57 58 // Now get the public key from the keyfile 59 std::unique_ptr<RSA, decltype(&RSA_free)> key(load_key(key_path), RSA_free); 60 if (!key) { 61 fprintf(stderr, "Couldn't load verity keys\n"); 62 return -1; 63 } 64 65 // Verify the result 66 if (!RSA_verify(NID_sha256, hash_buf, sizeof(hash_buf), signature, signature_size, key.get())) { 67 fprintf(stderr, "Couldn't verify table\n"); 68 return -1; 69 } 70 71 return 0; 72 } 73 74 int main(int argc, char* argv[]) { 75 if (argc != 4 || strcmp(argv[2], "-mincrypt") != 0) { 76 printf("Usage: %s <image> -mincrypt <verity_key>\n" 77 " image the image file (raw or sparse image) to be verified\n" 78 " verity_key the verity key in mincrypt format (/verity_key on device)\n", argv[0]); 79 return 2; 80 } 81 82 // Get the raw image. 83 android::base::unique_fd fd(open(argv[1], O_RDONLY)); 84 if (!fd) { 85 fprintf(stderr, "failed to open %s: %s\n", argv[1], strerror(errno)); 86 return 1; 87 } 88 89 struct sparse_file* file = sparse_file_import_auto(fd, false, false); 90 if (file == nullptr) { 91 fprintf(stderr, "failed to read file %s\n", argv[1]); 92 return 1; 93 } 94 95 TemporaryFile tf; 96 if (sparse_file_write(file, tf.fd, false, false, false) < 0) { 97 fprintf(stderr, "failed to write output file\n"); 98 return 1; 99 } 100 sparse_file_destroy(file); 101 102 // Verify. 103 fec::io input(tf.path); 104 if (!input) { 105 return 1; 106 } 107 108 fec_verity_metadata verity; 109 if (!input.get_verity_metadata(verity)) { 110 fprintf(stderr, "failed to get verity metadata\n"); 111 return 1; 112 } 113 114 int ret = verify_table(argv[3], verity.signature, sizeof(verity.signature), 115 verity.table, verity.table_length); 116 printf("%s\n", ret == 0 ? "VERIFIED" : "FAILED"); 117 return ret; 118 } 119