Home | History | Annotate | Download | only in component
      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