Loading Android.mk +1 −19 Original line number Diff line number Diff line Loading @@ -104,28 +104,10 @@ LOCAL_CLANG := true LOCAL_MODULE := libverifier LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := \ asn1_decoder.cpp include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_CLANG := true LOCAL_MODULE := verifier_test LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_MODULE_TAGS := tests LOCAL_CFLAGS += -Wno-unused-parameter LOCAL_SRC_FILES := \ verifier_test.cpp \ asn1_decoder.cpp \ verifier.cpp \ ui.cpp LOCAL_STATIC_LIBRARIES := \ libmincrypt \ libminui \ libminzip \ libcutils \ libc include $(BUILD_EXECUTABLE) include $(BUILD_STATIC_LIBRARY) include $(LOCAL_PATH)/minui/Android.mk \ $(LOCAL_PATH)/minzip/Android.mk \ Loading README.md +17 −0 Original line number Diff line number Diff line Loading @@ -10,3 +10,20 @@ Quick turn-around testing # without flashing the recovery partition: adb reboot bootloader fastboot boot $ANDROID_PRODUCT_OUT/recovery.img Running the tests ----------------- # After setting up environment and lunch. mmma -j bootable/recovery # Running the tests on device. adb root adb sync data # 32-bit device adb shell /data/nativetest/recovery_unit_test/recovery_unit_test adb shell /data/nativetest/recovery_component_test/recovery_component_test # Or 64-bit device adb shell /data/nativetest64/recovery_unit_test/recovery_unit_test adb shell /data/nativetest64/recovery_component_test/recovery_component_test tests/Android.mk +32 −3 Original line number Diff line number Diff line Loading @@ -16,11 +16,40 @@ LOCAL_PATH := $(call my-dir) # Unit tests include $(CLEAR_VARS) LOCAL_CLANG := true LOCAL_MODULE := recovery_unit_test LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_STATIC_LIBRARIES := libverifier LOCAL_SRC_FILES := asn1_decoder_test.cpp LOCAL_MODULE := asn1_decoder_test LOCAL_C_INCLUDES := $(LOCAL_PATH)/.. LOCAL_SRC_FILES := unit/asn1_decoder_test.cpp LOCAL_C_INCLUDES := bootable/recovery include $(BUILD_NATIVE_TEST) # Component tests include $(CLEAR_VARS) LOCAL_CLANG := true LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_MODULE := recovery_component_test LOCAL_C_INCLUDES := bootable/recovery LOCAL_SRC_FILES := component/verifier_test.cpp LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_STATIC_LIBRARIES := \ libbase \ libverifier \ libmincrypt \ libminui \ libminzip \ libcutils \ libc testdata_out_path := $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE) testdata_files := $(call find-subdir-files, testdata/*) GEN := $(addprefix $(testdata_out_path)/, $(testdata_files)) $(GEN): PRIVATE_PATH := $(LOCAL_PATH) $(GEN): PRIVATE_CUSTOM_TOOL = cp $< $@ $(GEN): $(testdata_out_path)/% : $(LOCAL_PATH)/% $(transform-generated-source) LOCAL_GENERATED_SOURCES += $(GEN) include $(BUILD_NATIVE_TEST) verifier_test.cpp→tests/component/verifier_test.cpp +95 −72 Original line number Diff line number Diff line /* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agree to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and Loading @@ -16,22 +16,33 @@ #include <errno.h> #include <fcntl.h> #include <stdarg.h> #include <gtest/gtest.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <memory> #include <string> #include <vector> #include <android-base/stringprintf.h> #include "common.h" #include "verifier.h" #include "ui.h" #include "mincrypt/sha.h" #include "mincrypt/sha256.h" #include "minzip/SysUtil.h" #include "ui.h" #include "verifier.h" #if defined(__LP64__) #define NATIVE_TEST_PATH "/nativetest64" #else #define NATIVE_TEST_PATH "/nativetest" #endif static const char* DATA_PATH = getenv("ANDROID_DATA"); static const char* TESTDATA_PATH = "/recovery_component_test/testdata/"; // This is build/target/product/security/testkey.x509.pem after being // dumped out by dumpkey.jar. Loading Loading @@ -123,9 +134,7 @@ ECPublicKey test_ec_key = RecoveryUI* ui = NULL; // verifier expects to find a UI object; we provide one that does // nothing but print. class FakeUI : public RecoveryUI { class MockUI : public RecoveryUI { void Init() { } void SetStage(int, int) { } void SetLocale(const char*) { } Loading Loading @@ -166,79 +175,93 @@ ui_print(const char* format, ...) { va_end(ap); } int main(int argc, char** argv) { if (argc < 2) { fprintf(stderr, "Usage: %s [-sha256] [-ec | -f4 | -file <keys>] <package>\n", argv[0]); return 2; } class VerifierTest : public testing::TestWithParam<std::vector<std::string>> { public: MemMapping memmap; std::vector<Certificate> certs; int argn = 1; while (argn < argc) { if (strcmp(argv[argn], "-sha256") == 0) { virtual void SetUp() { std::vector<std::string> args = GetParam(); std::string package = android::base::StringPrintf("%s%s%s%s", DATA_PATH, NATIVE_TEST_PATH, TESTDATA_PATH, args[0].c_str()); for (auto it = ++(args.cbegin()); it != args.cend(); ++it) { if (it->substr(it->length() - 3, it->length()) == "256") { if (certs.empty()) { fprintf(stderr, "May only specify -sha256 after key type\n"); return 2; FAIL() << "May only specify -sha256 after key type\n"; } ++argn; certs.back().hash_len = SHA256_DIGEST_SIZE; } else if (strcmp(argv[argn], "-ec") == 0) { ++argn; } else if (*it == "ec") { certs.emplace_back(SHA_DIGEST_SIZE, Certificate::EC, nullptr, std::unique_ptr<ECPublicKey>(new ECPublicKey(test_ec_key))); } else if (strcmp(argv[argn], "-e3") == 0) { ++argn; } else if (*it == "e3") { certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA, std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_key)), nullptr); } else if (strcmp(argv[argn], "-f4") == 0) { ++argn; } else if (*it == "f4") { certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA, std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_f4_key)), nullptr); } else if (strcmp(argv[argn], "-file") == 0) { if (!certs.empty()) { fprintf(stderr, "Cannot specify -file with other certs specified\n"); return 2; } ++argn; if (!load_keys(argv[argn], certs)) { fprintf(stderr, "Cannot load keys from %s\n", argv[argn]); } ++argn; } else if (argv[argn][0] == '-') { fprintf(stderr, "Unknown argument %s\n", argv[argn]); return 2; } else { break; if (certs.empty()) { certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA, std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_key)), nullptr); } if (sysMapFile(package.c_str(), &memmap) != 0) { FAIL() << "Failed to mmap " << package << ": " << strerror(errno) << "\n"; } if (argn == argc) { fprintf(stderr, "Must specify package to verify\n"); return 2; } if (certs.empty()) { certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA, std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_key)), nullptr); static void SetUpTestCase() { ui = new MockUI(); } }; ui = new FakeUI(); class VerifierSuccessTest : public VerifierTest { }; MemMapping map; if (sysMapFile(argv[argn], &map) != 0) { fprintf(stderr, "failed to mmap %s: %s\n", argv[argn], strerror(errno)); return 4; } class VerifierFailureTest : public VerifierTest { }; int result = verify_file(map.addr, map.length, certs); if (result == VERIFY_SUCCESS) { printf("VERIFIED\n"); return 0; } else if (result == VERIFY_FAILURE) { printf("NOT VERIFIED\n"); return 1; } else { printf("bad return value\n"); return 3; TEST_P(VerifierSuccessTest, VerifySucceed) { ASSERT_EQ(verify_file(memmap.addr, memmap.length, certs), VERIFY_SUCCESS); } TEST_P(VerifierFailureTest, VerifyFailure) { ASSERT_EQ(verify_file(memmap.addr, memmap.length, certs), VERIFY_FAILURE); } INSTANTIATE_TEST_CASE_P(SingleKeySuccess, VerifierSuccessTest, ::testing::Values( std::vector<std::string>({"otasigned.zip", "e3"}), std::vector<std::string>({"otasigned_f4.zip", "f4"}), std::vector<std::string>({"otasigned_sha256.zip", "e3", "sha256"}), std::vector<std::string>({"otasigned_f4_sha256.zip", "f4", "sha256"}), std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "ec", "sha256"}))); INSTANTIATE_TEST_CASE_P(MultiKeySuccess, VerifierSuccessTest, ::testing::Values( std::vector<std::string>({"otasigned.zip", "f4", "e3"}), std::vector<std::string>({"otasigned_f4.zip", "ec", "f4"}), std::vector<std::string>({"otasigned_sha256.zip", "ec", "e3", "e3", "sha256"}), std::vector<std::string>({"otasigned_f4_sha256.zip", "ec", "sha256", "e3", "f4", "sha256"}), std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "f4", "sha256", "e3", "ec", "sha256"}))); INSTANTIATE_TEST_CASE_P(WrongKey, VerifierFailureTest, ::testing::Values( std::vector<std::string>({"otasigned.zip", "f4"}), std::vector<std::string>({"otasigned_f4.zip", "e3"}), std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "e3", "sha256"}))); INSTANTIATE_TEST_CASE_P(WrongHash, VerifierFailureTest, ::testing::Values( std::vector<std::string>({"otasigned.zip", "e3", "sha256"}), std::vector<std::string>({"otasigned_f4.zip", "f4", "sha256"}), std::vector<std::string>({"otasigned_sha256.zip"}), std::vector<std::string>({"otasigned_f4_sha256.zip", "f4"}), std::vector<std::string>({"otasigned_ecdsa_sha256.zip"}))); INSTANTIATE_TEST_CASE_P(BadPackage, VerifierFailureTest, ::testing::Values( std::vector<std::string>({"random.zip"}), std::vector<std::string>({"fake-eocd.zip"}), std::vector<std::string>({"alter-metadata.zip"}), std::vector<std::string>({"alter-footer.zip"}))); testdata/alter-footer.zip→tests/testdata/alter-footer.zip (3.92 KiB) File moved. View file Loading
Android.mk +1 −19 Original line number Diff line number Diff line Loading @@ -104,28 +104,10 @@ LOCAL_CLANG := true LOCAL_MODULE := libverifier LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := \ asn1_decoder.cpp include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_CLANG := true LOCAL_MODULE := verifier_test LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_MODULE_TAGS := tests LOCAL_CFLAGS += -Wno-unused-parameter LOCAL_SRC_FILES := \ verifier_test.cpp \ asn1_decoder.cpp \ verifier.cpp \ ui.cpp LOCAL_STATIC_LIBRARIES := \ libmincrypt \ libminui \ libminzip \ libcutils \ libc include $(BUILD_EXECUTABLE) include $(BUILD_STATIC_LIBRARY) include $(LOCAL_PATH)/minui/Android.mk \ $(LOCAL_PATH)/minzip/Android.mk \ Loading
README.md +17 −0 Original line number Diff line number Diff line Loading @@ -10,3 +10,20 @@ Quick turn-around testing # without flashing the recovery partition: adb reboot bootloader fastboot boot $ANDROID_PRODUCT_OUT/recovery.img Running the tests ----------------- # After setting up environment and lunch. mmma -j bootable/recovery # Running the tests on device. adb root adb sync data # 32-bit device adb shell /data/nativetest/recovery_unit_test/recovery_unit_test adb shell /data/nativetest/recovery_component_test/recovery_component_test # Or 64-bit device adb shell /data/nativetest64/recovery_unit_test/recovery_unit_test adb shell /data/nativetest64/recovery_component_test/recovery_component_test
tests/Android.mk +32 −3 Original line number Diff line number Diff line Loading @@ -16,11 +16,40 @@ LOCAL_PATH := $(call my-dir) # Unit tests include $(CLEAR_VARS) LOCAL_CLANG := true LOCAL_MODULE := recovery_unit_test LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_STATIC_LIBRARIES := libverifier LOCAL_SRC_FILES := asn1_decoder_test.cpp LOCAL_MODULE := asn1_decoder_test LOCAL_C_INCLUDES := $(LOCAL_PATH)/.. LOCAL_SRC_FILES := unit/asn1_decoder_test.cpp LOCAL_C_INCLUDES := bootable/recovery include $(BUILD_NATIVE_TEST) # Component tests include $(CLEAR_VARS) LOCAL_CLANG := true LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_MODULE := recovery_component_test LOCAL_C_INCLUDES := bootable/recovery LOCAL_SRC_FILES := component/verifier_test.cpp LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_STATIC_LIBRARIES := \ libbase \ libverifier \ libmincrypt \ libminui \ libminzip \ libcutils \ libc testdata_out_path := $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE) testdata_files := $(call find-subdir-files, testdata/*) GEN := $(addprefix $(testdata_out_path)/, $(testdata_files)) $(GEN): PRIVATE_PATH := $(LOCAL_PATH) $(GEN): PRIVATE_CUSTOM_TOOL = cp $< $@ $(GEN): $(testdata_out_path)/% : $(LOCAL_PATH)/% $(transform-generated-source) LOCAL_GENERATED_SOURCES += $(GEN) include $(BUILD_NATIVE_TEST)
verifier_test.cpp→tests/component/verifier_test.cpp +95 −72 Original line number Diff line number Diff line /* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agree to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and Loading @@ -16,22 +16,33 @@ #include <errno.h> #include <fcntl.h> #include <stdarg.h> #include <gtest/gtest.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <memory> #include <string> #include <vector> #include <android-base/stringprintf.h> #include "common.h" #include "verifier.h" #include "ui.h" #include "mincrypt/sha.h" #include "mincrypt/sha256.h" #include "minzip/SysUtil.h" #include "ui.h" #include "verifier.h" #if defined(__LP64__) #define NATIVE_TEST_PATH "/nativetest64" #else #define NATIVE_TEST_PATH "/nativetest" #endif static const char* DATA_PATH = getenv("ANDROID_DATA"); static const char* TESTDATA_PATH = "/recovery_component_test/testdata/"; // This is build/target/product/security/testkey.x509.pem after being // dumped out by dumpkey.jar. Loading Loading @@ -123,9 +134,7 @@ ECPublicKey test_ec_key = RecoveryUI* ui = NULL; // verifier expects to find a UI object; we provide one that does // nothing but print. class FakeUI : public RecoveryUI { class MockUI : public RecoveryUI { void Init() { } void SetStage(int, int) { } void SetLocale(const char*) { } Loading Loading @@ -166,79 +175,93 @@ ui_print(const char* format, ...) { va_end(ap); } int main(int argc, char** argv) { if (argc < 2) { fprintf(stderr, "Usage: %s [-sha256] [-ec | -f4 | -file <keys>] <package>\n", argv[0]); return 2; } class VerifierTest : public testing::TestWithParam<std::vector<std::string>> { public: MemMapping memmap; std::vector<Certificate> certs; int argn = 1; while (argn < argc) { if (strcmp(argv[argn], "-sha256") == 0) { virtual void SetUp() { std::vector<std::string> args = GetParam(); std::string package = android::base::StringPrintf("%s%s%s%s", DATA_PATH, NATIVE_TEST_PATH, TESTDATA_PATH, args[0].c_str()); for (auto it = ++(args.cbegin()); it != args.cend(); ++it) { if (it->substr(it->length() - 3, it->length()) == "256") { if (certs.empty()) { fprintf(stderr, "May only specify -sha256 after key type\n"); return 2; FAIL() << "May only specify -sha256 after key type\n"; } ++argn; certs.back().hash_len = SHA256_DIGEST_SIZE; } else if (strcmp(argv[argn], "-ec") == 0) { ++argn; } else if (*it == "ec") { certs.emplace_back(SHA_DIGEST_SIZE, Certificate::EC, nullptr, std::unique_ptr<ECPublicKey>(new ECPublicKey(test_ec_key))); } else if (strcmp(argv[argn], "-e3") == 0) { ++argn; } else if (*it == "e3") { certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA, std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_key)), nullptr); } else if (strcmp(argv[argn], "-f4") == 0) { ++argn; } else if (*it == "f4") { certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA, std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_f4_key)), nullptr); } else if (strcmp(argv[argn], "-file") == 0) { if (!certs.empty()) { fprintf(stderr, "Cannot specify -file with other certs specified\n"); return 2; } ++argn; if (!load_keys(argv[argn], certs)) { fprintf(stderr, "Cannot load keys from %s\n", argv[argn]); } ++argn; } else if (argv[argn][0] == '-') { fprintf(stderr, "Unknown argument %s\n", argv[argn]); return 2; } else { break; if (certs.empty()) { certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA, std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_key)), nullptr); } if (sysMapFile(package.c_str(), &memmap) != 0) { FAIL() << "Failed to mmap " << package << ": " << strerror(errno) << "\n"; } if (argn == argc) { fprintf(stderr, "Must specify package to verify\n"); return 2; } if (certs.empty()) { certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA, std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_key)), nullptr); static void SetUpTestCase() { ui = new MockUI(); } }; ui = new FakeUI(); class VerifierSuccessTest : public VerifierTest { }; MemMapping map; if (sysMapFile(argv[argn], &map) != 0) { fprintf(stderr, "failed to mmap %s: %s\n", argv[argn], strerror(errno)); return 4; } class VerifierFailureTest : public VerifierTest { }; int result = verify_file(map.addr, map.length, certs); if (result == VERIFY_SUCCESS) { printf("VERIFIED\n"); return 0; } else if (result == VERIFY_FAILURE) { printf("NOT VERIFIED\n"); return 1; } else { printf("bad return value\n"); return 3; TEST_P(VerifierSuccessTest, VerifySucceed) { ASSERT_EQ(verify_file(memmap.addr, memmap.length, certs), VERIFY_SUCCESS); } TEST_P(VerifierFailureTest, VerifyFailure) { ASSERT_EQ(verify_file(memmap.addr, memmap.length, certs), VERIFY_FAILURE); } INSTANTIATE_TEST_CASE_P(SingleKeySuccess, VerifierSuccessTest, ::testing::Values( std::vector<std::string>({"otasigned.zip", "e3"}), std::vector<std::string>({"otasigned_f4.zip", "f4"}), std::vector<std::string>({"otasigned_sha256.zip", "e3", "sha256"}), std::vector<std::string>({"otasigned_f4_sha256.zip", "f4", "sha256"}), std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "ec", "sha256"}))); INSTANTIATE_TEST_CASE_P(MultiKeySuccess, VerifierSuccessTest, ::testing::Values( std::vector<std::string>({"otasigned.zip", "f4", "e3"}), std::vector<std::string>({"otasigned_f4.zip", "ec", "f4"}), std::vector<std::string>({"otasigned_sha256.zip", "ec", "e3", "e3", "sha256"}), std::vector<std::string>({"otasigned_f4_sha256.zip", "ec", "sha256", "e3", "f4", "sha256"}), std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "f4", "sha256", "e3", "ec", "sha256"}))); INSTANTIATE_TEST_CASE_P(WrongKey, VerifierFailureTest, ::testing::Values( std::vector<std::string>({"otasigned.zip", "f4"}), std::vector<std::string>({"otasigned_f4.zip", "e3"}), std::vector<std::string>({"otasigned_ecdsa_sha256.zip", "e3", "sha256"}))); INSTANTIATE_TEST_CASE_P(WrongHash, VerifierFailureTest, ::testing::Values( std::vector<std::string>({"otasigned.zip", "e3", "sha256"}), std::vector<std::string>({"otasigned_f4.zip", "f4", "sha256"}), std::vector<std::string>({"otasigned_sha256.zip"}), std::vector<std::string>({"otasigned_f4_sha256.zip", "f4"}), std::vector<std::string>({"otasigned_ecdsa_sha256.zip"}))); INSTANTIATE_TEST_CASE_P(BadPackage, VerifierFailureTest, ::testing::Values( std::vector<std::string>({"random.zip"}), std::vector<std::string>({"fake-eocd.zip"}), std::vector<std::string>({"alter-metadata.zip"}), std::vector<std::string>({"alter-footer.zip"})));