blob: 7f7b1b448b970b15fb8ddaa04f7b2e3cba482178 [file] [log] [blame]
Jed Estep43291862016-02-03 17:02:09 -08001/*
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/types.h>
23#include <sys/stat.h>
24
25#include <memory>
26#include <string>
27#include <vector>
28
29#include <android-base/stringprintf.h>
30
31#include "common.h"
32#include "mincrypt/sha.h"
33#include "mincrypt/sha256.h"
34#include "minzip/SysUtil.h"
35#include "ui.h"
36#include "verifier.h"
37
38#if defined(__LP64__)
39#define NATIVE_TEST_PATH "/nativetest64"
40#else
41#define NATIVE_TEST_PATH "/nativetest"
42#endif
43
44static const char* DATA_PATH = getenv("ANDROID_DATA");
45static const char* TESTDATA_PATH = "/recovery_component_test/testdata/";
46
47// This is build/target/product/security/testkey.x509.pem after being
48// dumped out by dumpkey.jar.
49RSAPublicKey test_key =
50 { 64, 0xc926ad21,
51 { 0x6afee91fu, 0x7fa31d5bu, 0x38a0b217u, 0x99df9baeu,
52 0xfe72991du, 0x727d3c04u, 0x20943f99u, 0xd08e7826u,
53 0x69e7c8a2u, 0xdeeccc8eu, 0x6b9af76fu, 0x553311c4u,
54 0x07b9e247u, 0x54c8bbcau, 0x6a540d81u, 0x48dbf567u,
55 0x98c92877u, 0x134fbfdeu, 0x01b32564u, 0x24581948u,
56 0x6cddc3b8u, 0x0cd444dau, 0xfe0381ccu, 0xf15818dfu,
57 0xc06e6d42u, 0x2e2f6412u, 0x093a6737u, 0x94d83b31u,
58 0xa466c87au, 0xb3f284a0u, 0xa694ec2cu, 0x053359e6u,
59 0x9717ee6au, 0x0732e080u, 0x220d5008u, 0xdc4af350u,
60 0x93d0a7c3u, 0xe330c9eau, 0xcac3da1eu, 0x8ebecf8fu,
61 0xc2be387fu, 0x38a14e89u, 0x211586f0u, 0x18b846f5u,
62 0x43be4c72u, 0xb578c204u, 0x1bbfb230u, 0xf1e267a8u,
63 0xa2d3e656u, 0x64b8e4feu, 0xe7e83d4bu, 0x3e77a943u,
64 0x3559ffd9u, 0x0ebb0f99u, 0x0aa76ce6u, 0xd3786ea7u,
65 0xbca8cd6bu, 0x068ca8e8u, 0xeb1de2ffu, 0x3e3ecd6cu,
66 0xe0d9d825u, 0xb1edc762u, 0xdec60b24u, 0xd6931904u},
67 { 0xccdcb989u, 0xe19281f9u, 0xa6e80accu, 0xb7f40560u,
68 0x0efb0bccu, 0x7f12b0bbu, 0x1e90531au, 0x136d95d0u,
69 0x9e660665u, 0x7d54918fu, 0xe3b93ea2u, 0x2f415d10u,
70 0x3d2df6e6u, 0x7a627ecfu, 0xa6f22d70u, 0xb995907au,
71 0x09de16b2u, 0xfeb8bd61u, 0xf24ec294u, 0x716a427fu,
72 0x2e12046fu, 0xeaf3d56au, 0xd9b873adu, 0x0ced340bu,
73 0xbc9cec09u, 0x73c65903u, 0xee39ce9bu, 0x3eede25au,
74 0x397633b7u, 0x2583c165u, 0x8514f97du, 0xe9166510u,
75 0x0b6fae99u, 0xa47139fdu, 0xdb8352f0u, 0xb2ad7f2cu,
76 0xa11552e2u, 0xd4d490a7u, 0xe11e8568u, 0xe9e484dau,
77 0xd3ef8449u, 0xa47055dau, 0x4edd9557u, 0x03a78ba1u,
78 0x770e130du, 0x16762facu, 0x0cbdfcc4u, 0xf3070540u,
79 0x008b6515u, 0x60e7e1b7u, 0xa72cf7f9u, 0xaff86e39u,
80 0x4296faadu, 0xfc90430eu, 0x6cc8f377u, 0xb398fd43u,
81 0x423c5997u, 0x991d59c4u, 0x6464bf73u, 0x96431575u,
82 0x15e3d207u, 0x30532a7au, 0x8c4be618u, 0x460a4d76u },
83 3
84 };
85
86RSAPublicKey test_f4_key =
87 { 64, 0xc9bd1f21,
88 { 0x1178db1fu, 0xbf5d0e55u, 0x3393a165u, 0x0ef4c287u,
89 0xbc472a4au, 0x383fc5a1u, 0x4a13b7d2u, 0xb1ff2ac3u,
90 0xaf66b4d9u, 0x9280acefu, 0xa2165bdbu, 0x6a4d6e5cu,
91 0x08ea676bu, 0xb7ac70c7u, 0xcd158139u, 0xa635ccfeu,
92 0xa46ab8a8u, 0x445a3e8bu, 0xdc81d9bbu, 0x91ce1a20u,
93 0x68021cdeu, 0x4516eda9u, 0x8d43c30cu, 0xed1eff14u,
94 0xca387e4cu, 0x58adc233u, 0x4657ab27u, 0xa95b521eu,
95 0xdfc0e30cu, 0x394d64a1u, 0xc6b321a1u, 0x2ca22cb8u,
96 0xb1892d5cu, 0x5d605f3eu, 0x6025483cu, 0x9afd5181u,
97 0x6e1a7105u, 0x03010593u, 0x70acd304u, 0xab957cbfu,
98 0x8844abbbu, 0x53846837u, 0x24e98a43u, 0x2ba060c1u,
99 0x8b88b88eu, 0x44eea405u, 0xb259fc41u, 0x0907ad9cu,
100 0x13003adau, 0xcf79634eu, 0x7d314ec9u, 0xfbbe4c2bu,
101 0xd84d0823u, 0xfd30fd88u, 0x68d8a909u, 0xfb4572d9u,
102 0xa21301c2u, 0xd00a4785u, 0x6862b50cu, 0xcfe49796u,
103 0xdaacbd83u, 0xfb620906u, 0xdf71e0ccu, 0xbbc5b030u },
104 { 0x69a82189u, 0x1a8b22f4u, 0xcf49207bu, 0x68cc056au,
105 0xb206b7d2u, 0x1d449bbdu, 0xe9d342f2u, 0x29daea58u,
106 0xb19d011au, 0xc62f15e4u, 0x9452697au, 0xb62bb87eu,
107 0x60f95cc2u, 0x279ebb2du, 0x17c1efd8u, 0xec47558bu,
108 0xc81334d1u, 0x88fe7601u, 0x79992eb1u, 0xb4555615u,
109 0x2022ac8cu, 0xc79a4b8cu, 0xb288b034u, 0xd6b942f0u,
110 0x0caa32fbu, 0xa065ba51u, 0x4de9f154u, 0x29f64f6cu,
111 0x7910af5eu, 0x3ed4636au, 0xe4c81911u, 0x9183f37du,
112 0x5811e1c4u, 0x29c7a58cu, 0x9715d4d3u, 0xc7e2dce3u,
113 0x140972ebu, 0xf4c8a69eu, 0xa104d424u, 0x5dabbdfbu,
114 0x41cb4c6bu, 0xd7f44717u, 0x61785ff7u, 0x5e0bc273u,
115 0x36426c70u, 0x2aa6f08eu, 0x083badbfu, 0x3cab941bu,
116 0x8871da23u, 0x1ab3dbaeu, 0x7115a21du, 0xf5aa0965u,
117 0xf766f562u, 0x7f110225u, 0x86d96a04u, 0xc50a120eu,
118 0x3a751ca3u, 0xc21aa186u, 0xba7359d0u, 0x3ff2b257u,
119 0xd116e8bbu, 0xfc1318c0u, 0x070e5b1du, 0x83b759a6u },
120 65537
121 };
122
123ECPublicKey test_ec_key =
124 {
125 {
126 {0xd656fa24u, 0x931416cau, 0x1c0278c6u, 0x174ebe4cu,
127 0x6018236au, 0x45ba1656u, 0xe8c05d84u, 0x670ed500u}
128 },
129 {
130 {0x0d179adeu, 0x4c16827du, 0x9f8cb992u, 0x8f69ff8au,
131 0x481b1020u, 0x798d91afu, 0x184db8e9u, 0xb5848dd9u}
132 }
133 };
134
135RecoveryUI* ui = NULL;
136
137class MockUI : public RecoveryUI {
138 void Init() { }
139 void SetStage(int, int) { }
140 void SetLocale(const char*) { }
141 void SetBackground(Icon icon) { }
142
143 void SetProgressType(ProgressType determinate) { }
144 void ShowProgress(float portion, float seconds) { }
145 void SetProgress(float fraction) { }
146
147 void ShowText(bool visible) { }
148 bool IsTextVisible() { return false; }
149 bool WasTextEverVisible() { return false; }
150 void Print(const char* fmt, ...) {
151 va_list ap;
152 va_start(ap, fmt);
153 vfprintf(stderr, fmt, ap);
154 va_end(ap);
155 }
156 void PrintOnScreenOnly(const char* fmt, ...) {
157 va_list ap;
158 va_start(ap, fmt);
159 vfprintf(stderr, fmt, ap);
160 va_end(ap);
161 }
162 void ShowFile(const char*) { }
163
164 void StartMenu(const char* const * headers, const char* const * items,
165 int initial_selection) { }
166 int SelectMenu(int sel) { return 0; }
167 void EndMenu() { }
168};
169
170void
171ui_print(const char* format, ...) {
172 va_list ap;
173 va_start(ap, format);
174 vfprintf(stdout, format, ap);
175 va_end(ap);
176}
177
178class VerifierTest : public testing::TestWithParam<std::vector<std::string>> {
179 public:
180 MemMapping memmap;
181 std::vector<Certificate> certs;
182
183 virtual void SetUp() {
184 std::vector<std::string> args = GetParam();
185 std::string package = android::base::StringPrintf("%s%s%s%s", DATA_PATH, NATIVE_TEST_PATH,
186 TESTDATA_PATH, args[0].c_str());
187 for (auto it = ++(args.cbegin()); it != args.cend(); ++it) {
188 if (it->substr(it->length() - 3, it->length()) == "256") {
189 if (certs.empty()) {
190 FAIL() << "May only specify -sha256 after key type\n";
191 }
192 certs.back().hash_len = SHA256_DIGEST_SIZE;
193 } else if (*it == "ec") {
194 certs.emplace_back(SHA_DIGEST_SIZE, Certificate::EC,
195 nullptr, std::unique_ptr<ECPublicKey>(new ECPublicKey(test_ec_key)));
196 } else if (*it == "e3") {
197 certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA,
198 std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_key)), nullptr);
199 } else if (*it == "f4") {
200 certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA,
201 std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_f4_key)), nullptr);
202 }
203 }
204 if (certs.empty()) {
205 certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA,
206 std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_key)), nullptr);
207 }
208 if (sysMapFile(package.c_str(), &memmap) != 0) {
209 FAIL() << "Failed to mmap " << package << ": " << strerror(errno) << "\n";
210 }
211 }
212
213 static void SetUpTestCase() {
214 ui = new MockUI();
215 }
216};
217
218class VerifierSuccessTest : public VerifierTest {
219};
220
221class VerifierFailureTest : public VerifierTest {
222};
223
224TEST_P(VerifierSuccessTest, VerifySucceed) {
225 ASSERT_EQ(verify_file(memmap.addr, memmap.length, certs), VERIFY_SUCCESS);
226}
227
228TEST_P(VerifierFailureTest, VerifyFailure) {
229 ASSERT_EQ(verify_file(memmap.addr, memmap.length, certs), VERIFY_FAILURE);
230}
231
232INSTANTIATE_TEST_CASE_P(SingleKeySuccess, VerifierSuccessTest,
233 ::testing::Values(
234 std::vector<std::string>({"otasigned.zip", "e3"}),
235 std::vector<std::string>({"otasigned_f4.zip", "f4"}),
236 std::vector<std::string>({"otasigned_sha256.zip", "e3", "sha256"}),
237 std::vector<std::string>({"otasigned_f4_sha256.zip", "f4", "sha256"}),
238 std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "ec", "sha256"})));
239
240INSTANTIATE_TEST_CASE_P(MultiKeySuccess, VerifierSuccessTest,
241 ::testing::Values(
242 std::vector<std::string>({"otasigned.zip", "f4", "e3"}),
243 std::vector<std::string>({"otasigned_f4.zip", "ec", "f4"}),
244 std::vector<std::string>({"otasigned_sha256.zip", "ec", "e3", "e3", "sha256"}),
245 std::vector<std::string>({"otasigned_f4_sha256.zip", "ec", "sha256", "e3", "f4", "sha256"}),
246 std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "f4", "sha256", "e3", "ec", "sha256"})));
247
248INSTANTIATE_TEST_CASE_P(WrongKey, VerifierFailureTest,
249 ::testing::Values(
250 std::vector<std::string>({"otasigned.zip", "f4"}),
251 std::vector<std::string>({"otasigned_f4.zip", "e3"}),
252 std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "e3", "sha256"})));
253
254INSTANTIATE_TEST_CASE_P(WrongHash, VerifierFailureTest,
255 ::testing::Values(
256 std::vector<std::string>({"otasigned.zip", "e3", "sha256"}),
257 std::vector<std::string>({"otasigned_f4.zip", "f4", "sha256"}),
258 std::vector<std::string>({"otasigned_sha256.zip"}),
259 std::vector<std::string>({"otasigned_f4_sha256.zip", "f4"}),
260 std::vector<std::string>({"otasigned_ecdsa_sha256.zip"})));
261
262INSTANTIATE_TEST_CASE_P(BadPackage, VerifierFailureTest,
263 ::testing::Values(
264 std::vector<std::string>({"random.zip"}),
265 std::vector<std::string>({"fake-eocd.zip"}),
266 std::vector<std::string>({"alter-metadata.zip"}),
267 std::vector<std::string>({"alter-footer.zip"})));