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 <fec/io.h> 28#include <mincrypt/rsa.h> 29#include <mincrypt/sha.h> 30#include <mincrypt/sha256.h> 31#include <sparse/sparse.h> 32 33static RSAPublicKey* load_key(const char* path) { 34 std::string content; 35 if (!android::base::ReadFileToString(path, &content)) { 36 fprintf(stderr, "Failed to load key from %s\n", path); 37 return nullptr; 38 } 39 40 std::unique_ptr<RSAPublicKey> key(new RSAPublicKey); 41 if (!key) { 42 fprintf(stderr, "Failed to malloc key\n"); 43 return nullptr; 44 } 45 46 memcpy(key.get(), content.data(), sizeof(RSAPublicKey)); 47 48 if (key->len != RSANUMWORDS) { 49 fprintf(stderr, "Invalid key length %d\n", key->len); 50 return nullptr; 51 } 52 53 return key.release(); 54} 55 56static int verify_table(const char* key_path, const uint8_t* signature, 57 const char* table, uint32_t table_length) { 58 // Hash the table 59 uint8_t hash_buf[SHA256_DIGEST_LENGTH]; 60 SHA256_hash(reinterpret_cast<const void*>(table), table_length, hash_buf); 61 62 // Now get the public key from the keyfile 63 std::unique_ptr<RSAPublicKey> key(load_key(key_path)); 64 if (!key) { 65 fprintf(stderr, "Couldn't load verity keys\n"); 66 return -1; 67 } 68 69 // Verify the result 70 if (!RSA_verify(key.get(), signature, RSANUMBYTES, hash_buf, SHA256_DIGEST_SIZE)) { 71 fprintf(stderr, "Couldn't verify table\n"); 72 return -1; 73 } 74 75 return 0; 76} 77 78int main(int argc, char* argv[]) { 79 if (argc != 4 || strcmp(argv[2], "-mincrypt") != 0) { 80 printf("Usage: %s <image> -mincrypt <verity_key>\n" 81 " image the image file (raw or sparse image) to be verified\n" 82 " verity_key the verity key in mincrypt format (/verity_key on device)\n", argv[0]); 83 return 2; 84 } 85 86 // Get the raw image. 87 android::base::unique_fd fd(open(argv[1], O_RDONLY)); 88 if (!fd) { 89 fprintf(stderr, "failed to open %s: %s\n", argv[1], strerror(errno)); 90 return 1; 91 } 92 93 struct sparse_file* file = sparse_file_import_auto(fd, false, false); 94 if (file == nullptr) { 95 fprintf(stderr, "failed to read file %s\n", argv[1]); 96 return 1; 97 } 98 99 TemporaryFile tf; 100 if (sparse_file_write(file, tf.fd, false, false, false) < 0) { 101 fprintf(stderr, "failed to write output file\n"); 102 return 1; 103 } 104 sparse_file_destroy(file); 105 106 // Verify. 107 fec::io input(tf.path); 108 if (!input) { 109 return 1; 110 } 111 112 fec_verity_metadata verity; 113 if (!input.get_verity_metadata(verity)) { 114 fprintf(stderr, "failed to get verity metadata\n"); 115 return 1; 116 } 117 118 int ret = verify_table(argv[3], verity.signature, verity.table, verity.table_length); 119 printf("%s\n", ret == 0 ? "VERIFIED" : "FAILED"); 120 return ret; 121} 122