• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
Init()45     void Init() { }
SetStage(int,int)46     void SetStage(int, int) { }
SetLocale(const char *)47     void SetLocale(const char*) { }
SetBackground(Icon icon)48     void SetBackground(Icon icon) { }
SetSystemUpdateText(bool security_update)49     void SetSystemUpdateText(bool security_update) { }
50 
SetProgressType(ProgressType determinate)51     void SetProgressType(ProgressType determinate) { }
ShowProgress(float portion,float seconds)52     void ShowProgress(float portion, float seconds) { }
SetProgress(float fraction)53     void SetProgress(float fraction) { }
54 
ShowText(bool visible)55     void ShowText(bool visible) { }
IsTextVisible()56     bool IsTextVisible() { return false; }
WasTextEverVisible()57     bool WasTextEverVisible() { return false; }
Print(const char * fmt,...)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     }
PrintOnScreenOnly(const char * fmt,...)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     }
ShowFile(const char *)70     void ShowFile(const char*) { }
71 
StartMenu(const char * const * headers,const char * const * items,int initial_selection)72     void StartMenu(const char* const * headers, const char* const * items,
73                            int initial_selection) { }
SelectMenu(int sel)74     int SelectMenu(int sel) { return 0; }
EndMenu()75     void EndMenu() { }
76 };
77 
78 void
ui_print(const char * format,...)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 
SetUp()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 
SetUpTestCase()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 
TEST_P(VerifierSuccessTest,VerifySucceed)135 TEST_P(VerifierSuccessTest, VerifySucceed) {
136     ASSERT_EQ(verify_file(memmap.addr, memmap.length, certs), VERIFY_SUCCESS);
137 }
138 
TEST_P(VerifierFailureTest,VerifyFailure)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