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