blob: c533b03f6587bf681dfc5c4e91dee9745755eebd [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 Estepd5a14c62016-02-05 11:24:27 -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*) { }
Tao Baoe1a16af2016-02-04 11:30:42 -0800136 void SetBackground(Icon /*icon*/) { }
Jed Estep43291862016-02-03 17:02:09 -0800137
Tao Baoe1a16af2016-02-04 11:30:42 -0800138 void SetProgressType(ProgressType /*determinate*/) { }
139 void ShowProgress(float /*portion*/, float /*seconds*/) { }
140 void SetProgress(float /*fraction*/) { }
Jed Estep43291862016-02-03 17:02:09 -0800141
Tao Baoe1a16af2016-02-04 11:30:42 -0800142 void ShowText(bool /*visible*/) { }
Jed Estep43291862016-02-03 17:02:09 -0800143 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
Tao Baoe1a16af2016-02-04 11:30:42 -0800159 void StartMenu(const char* const* /*headers*/,
160 const char* const* /*items*/,
161 int /*initial_selection*/) { }
162 int SelectMenu(int /*sel*/) { return 0; }
Jed Estep43291862016-02-03 17:02:09 -0800163 void EndMenu() { }
164};
165
166void
167ui_print(const char* format, ...) {
168 va_list ap;
169 va_start(ap, format);
170 vfprintf(stdout, format, ap);
171 va_end(ap);
172}
173
174class VerifierTest : public testing::TestWithParam<std::vector<std::string>> {
175 public:
176 MemMapping memmap;
177 std::vector<Certificate> certs;
178
179 virtual void SetUp() {
180 std::vector<std::string> args = GetParam();
181 std::string package = android::base::StringPrintf("%s%s%s%s", DATA_PATH, NATIVE_TEST_PATH,
182 TESTDATA_PATH, args[0].c_str());
183 for (auto it = ++(args.cbegin()); it != args.cend(); ++it) {
184 if (it->substr(it->length() - 3, it->length()) == "256") {
185 if (certs.empty()) {
186 FAIL() << "May only specify -sha256 after key type\n";
187 }
188 certs.back().hash_len = SHA256_DIGEST_SIZE;
189 } else if (*it == "ec") {
190 certs.emplace_back(SHA_DIGEST_SIZE, Certificate::EC,
191 nullptr, std::unique_ptr<ECPublicKey>(new ECPublicKey(test_ec_key)));
192 } else if (*it == "e3") {
193 certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA,
194 std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_key)), nullptr);
195 } else if (*it == "f4") {
196 certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA,
197 std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_f4_key)), nullptr);
198 }
199 }
200 if (certs.empty()) {
201 certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA,
202 std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_key)), nullptr);
203 }
204 if (sysMapFile(package.c_str(), &memmap) != 0) {
205 FAIL() << "Failed to mmap " << package << ": " << strerror(errno) << "\n";
206 }
207 }
208
209 static void SetUpTestCase() {
210 ui = new MockUI();
211 }
212};
213
214class VerifierSuccessTest : public VerifierTest {
215};
216
217class VerifierFailureTest : public VerifierTest {
218};
219
220TEST_P(VerifierSuccessTest, VerifySucceed) {
221 ASSERT_EQ(verify_file(memmap.addr, memmap.length, certs), VERIFY_SUCCESS);
222}
223
224TEST_P(VerifierFailureTest, VerifyFailure) {
225 ASSERT_EQ(verify_file(memmap.addr, memmap.length, certs), VERIFY_FAILURE);
226}
227
228INSTANTIATE_TEST_CASE_P(SingleKeySuccess, VerifierSuccessTest,
229 ::testing::Values(
230 std::vector<std::string>({"otasigned.zip", "e3"}),
231 std::vector<std::string>({"otasigned_f4.zip", "f4"}),
232 std::vector<std::string>({"otasigned_sha256.zip", "e3", "sha256"}),
233 std::vector<std::string>({"otasigned_f4_sha256.zip", "f4", "sha256"}),
234 std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "ec", "sha256"})));
235
236INSTANTIATE_TEST_CASE_P(MultiKeySuccess, VerifierSuccessTest,
237 ::testing::Values(
238 std::vector<std::string>({"otasigned.zip", "f4", "e3"}),
239 std::vector<std::string>({"otasigned_f4.zip", "ec", "f4"}),
240 std::vector<std::string>({"otasigned_sha256.zip", "ec", "e3", "e3", "sha256"}),
241 std::vector<std::string>({"otasigned_f4_sha256.zip", "ec", "sha256", "e3", "f4", "sha256"}),
242 std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "f4", "sha256", "e3", "ec", "sha256"})));
243
244INSTANTIATE_TEST_CASE_P(WrongKey, VerifierFailureTest,
245 ::testing::Values(
246 std::vector<std::string>({"otasigned.zip", "f4"}),
247 std::vector<std::string>({"otasigned_f4.zip", "e3"}),
248 std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "e3", "sha256"})));
249
250INSTANTIATE_TEST_CASE_P(WrongHash, VerifierFailureTest,
251 ::testing::Values(
252 std::vector<std::string>({"otasigned.zip", "e3", "sha256"}),
253 std::vector<std::string>({"otasigned_f4.zip", "f4", "sha256"}),
254 std::vector<std::string>({"otasigned_sha256.zip"}),
255 std::vector<std::string>({"otasigned_f4_sha256.zip", "f4"}),
256 std::vector<std::string>({"otasigned_ecdsa_sha256.zip"})));
257
258INSTANTIATE_TEST_CASE_P(BadPackage, VerifierFailureTest,
259 ::testing::Values(
260 std::vector<std::string>({"random.zip"}),
261 std::vector<std::string>({"fake-eocd.zip"}),
262 std::vector<std::string>({"alter-metadata.zip"}),
263 std::vector<std::string>({"alter-footer.zip"})));