1 /* 2 * Copyright (C) 2009 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 agree 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 <fcntl.h> 19 #include <gtest/gtest.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <sys/stat.h> 23 #include <sys/types.h> 24 25 #include <memory> 26 #include <string> 27 #include <vector> 28 29 #include <openssl/sha.h> 30 31 #include <android-base/stringprintf.h> 32 33 #include "common.h" 34 #include "common/test_constants.h" 35 #include "minzip/SysUtil.h" 36 #include "ui.h" 37 #include "verifier.h" 38 39 static const char* DATA_PATH = getenv("ANDROID_DATA"); 40 static const char* TESTDATA_PATH = "/recovery/testdata/"; 41 42 RecoveryUI* ui = NULL; 43 44 class MockUI : public RecoveryUI { 45 void Init() { } 46 void SetStage(int, int) { } 47 void SetLocale(const char*) { } 48 void SetBackground(Icon icon) { } 49 void SetSystemUpdateText(bool security_update) { } 50 51 void SetProgressType(ProgressType determinate) { } 52 void ShowProgress(float portion, float seconds) { } 53 void SetProgress(float fraction) { } 54 55 void ShowText(bool visible) { } 56 bool IsTextVisible() { return false; } 57 bool WasTextEverVisible() { return false; } 58 void Print(const char* fmt, ...) { 59 va_list ap; 60 va_start(ap, fmt); 61 vfprintf(stderr, fmt, ap); 62 va_end(ap); 63 } 64 void PrintOnScreenOnly(const char* fmt, ...) { 65 va_list ap; 66 va_start(ap, fmt); 67 vfprintf(stderr, fmt, ap); 68 va_end(ap); 69 } 70 void ShowFile(const char*) { } 71 72 void StartMenu(const char* const * headers, const char* const * items, 73 int initial_selection) { } 74 int SelectMenu(int sel) { return 0; } 75 void EndMenu() { } 76 }; 77 78 void 79 ui_print(const char* format, ...) { 80 va_list ap; 81 va_start(ap, format); 82 vfprintf(stdout, format, ap); 83 va_end(ap); 84 } 85 86 class VerifierTest : public testing::TestWithParam<std::vector<std::string>> { 87 public: 88 MemMapping memmap; 89 std::vector<Certificate> certs; 90 91 virtual void SetUp() { 92 std::vector<std::string> args = GetParam(); 93 std::string package = 94 android::base::StringPrintf("%s%s%s%s", DATA_PATH, NATIVE_TEST_PATH, 95 TESTDATA_PATH, args[0].c_str()); 96 if (sysMapFile(package.c_str(), &memmap) != 0) { 97 FAIL() << "Failed to mmap " << package << ": " << strerror(errno) 98 << "\n"; 99 } 100 101 for (auto it = ++(args.cbegin()); it != args.cend(); ++it) { 102 if (it->substr(it->length() - 3, it->length()) == "256") { 103 if (certs.empty()) { 104 FAIL() << "May only specify -sha256 after key type\n"; 105 } 106 certs.back().hash_len = SHA256_DIGEST_LENGTH; 107 } else { 108 std::string public_key_file = android::base::StringPrintf( 109 "%s%s%stest_key_%s.txt", DATA_PATH, NATIVE_TEST_PATH, 110 TESTDATA_PATH, it->c_str()); 111 ASSERT_TRUE(load_keys(public_key_file.c_str(), certs)); 112 certs.back().hash_len = SHA_DIGEST_LENGTH; 113 } 114 } 115 if (certs.empty()) { 116 std::string public_key_file = android::base::StringPrintf( 117 "%s%s%stest_key_e3.txt", DATA_PATH, NATIVE_TEST_PATH, 118 TESTDATA_PATH); 119 ASSERT_TRUE(load_keys(public_key_file.c_str(), certs)); 120 certs.back().hash_len = SHA_DIGEST_LENGTH; 121 } 122 } 123 124 static void SetUpTestCase() { 125 ui = new MockUI(); 126 } 127 }; 128 129 class VerifierSuccessTest : public VerifierTest { 130 }; 131 132 class VerifierFailureTest : public VerifierTest { 133 }; 134 135 TEST_P(VerifierSuccessTest, VerifySucceed) { 136 ASSERT_EQ(verify_file(memmap.addr, memmap.length, certs), VERIFY_SUCCESS); 137 } 138 139 TEST_P(VerifierFailureTest, VerifyFailure) { 140 ASSERT_EQ(verify_file(memmap.addr, memmap.length, certs), VERIFY_FAILURE); 141 } 142 143 INSTANTIATE_TEST_CASE_P(SingleKeySuccess, VerifierSuccessTest, 144 ::testing::Values( 145 std::vector<std::string>({"otasigned.zip", "e3"}), 146 std::vector<std::string>({"otasigned_f4.zip", "f4"}), 147 std::vector<std::string>({"otasigned_sha256.zip", "e3", "sha256"}), 148 std::vector<std::string>({"otasigned_f4_sha256.zip", "f4", "sha256"}), 149 std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "ec", "sha256"}))); 150 151 INSTANTIATE_TEST_CASE_P(MultiKeySuccess, VerifierSuccessTest, 152 ::testing::Values( 153 std::vector<std::string>({"otasigned.zip", "f4", "e3"}), 154 std::vector<std::string>({"otasigned_f4.zip", "ec", "f4"}), 155 std::vector<std::string>({"otasigned_sha256.zip", "ec", "e3", "e3", "sha256"}), 156 std::vector<std::string>({"otasigned_f4_sha256.zip", "ec", "sha256", "e3", "f4", "sha256"}), 157 std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "f4", "sha256", "e3", "ec", "sha256"}))); 158 159 INSTANTIATE_TEST_CASE_P(WrongKey, VerifierFailureTest, 160 ::testing::Values( 161 std::vector<std::string>({"otasigned.zip", "f4"}), 162 std::vector<std::string>({"otasigned_f4.zip", "e3"}), 163 std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "e3", "sha256"}))); 164 165 INSTANTIATE_TEST_CASE_P(WrongHash, VerifierFailureTest, 166 ::testing::Values( 167 std::vector<std::string>({"otasigned.zip", "e3", "sha256"}), 168 std::vector<std::string>({"otasigned_f4.zip", "f4", "sha256"}), 169 std::vector<std::string>({"otasigned_sha256.zip"}), 170 std::vector<std::string>({"otasigned_f4_sha256.zip", "f4"}), 171 std::vector<std::string>({"otasigned_ecdsa_sha256.zip"}))); 172 173 INSTANTIATE_TEST_CASE_P(BadPackage, VerifierFailureTest, 174 ::testing::Values( 175 std::vector<std::string>({"random.zip"}), 176 std::vector<std::string>({"fake-eocd.zip"}), 177 std::vector<std::string>({"alter-metadata.zip"}), 178 std::vector<std::string>({"alter-footer.zip"}))); 179