summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk20
-rw-r--r--README.md17
-rw-r--r--applypatch/Android.mk10
-rw-r--r--applypatch/applypatch.cpp226
-rw-r--r--applypatch/applypatch.h17
-rw-r--r--applypatch/bspatch.cpp39
-rw-r--r--applypatch/freecache.cpp141
-rw-r--r--applypatch/imgpatch.cpp60
-rw-r--r--applypatch/main.cpp83
-rw-r--r--print_sha1.h10
-rw-r--r--tests/Android.mk35
-rw-r--r--tests/component/verifier_test.cpp (renamed from verifier_test.cpp)167
-rw-r--r--tests/testdata/alter-footer.zip (renamed from testdata/alter-footer.zip)bin4009 -> 4009 bytes
-rw-r--r--tests/testdata/alter-metadata.zip (renamed from testdata/alter-metadata.zip)bin4009 -> 4009 bytes
-rw-r--r--tests/testdata/fake-eocd.zip (renamed from testdata/fake-eocd.zip)bin4313 -> 4313 bytes
-rw-r--r--tests/testdata/jarsigned.zip (renamed from testdata/jarsigned.zip)bin2271 -> 2271 bytes
-rw-r--r--tests/testdata/otasigned.zip (renamed from testdata/otasigned.zip)bin4009 -> 4009 bytes
-rw-r--r--tests/testdata/otasigned_ecdsa_sha256.zip (renamed from testdata/otasigned_ecdsa_sha256.zip)bin3085 -> 3085 bytes
-rw-r--r--tests/testdata/otasigned_f4.zip (renamed from testdata/otasigned_f4.zip)bin5195 -> 5195 bytes
-rw-r--r--tests/testdata/otasigned_f4_sha256.zip (renamed from testdata/otasigned_f4_sha256.zip)bin5319 -> 5319 bytes
-rw-r--r--tests/testdata/otasigned_sha256.zip (renamed from testdata/otasigned_sha256.zip)bin5326 -> 5326 bytes
-rw-r--r--tests/testdata/random.zip (renamed from testdata/random.zip)bin1024 -> 1024 bytes
-rw-r--r--tests/testdata/test_f4.pk8 (renamed from testdata/test_f4.pk8)bin1217 -> 1217 bytes
-rw-r--r--tests/testdata/test_f4.x509.pem (renamed from testdata/test_f4.x509.pem)0
-rw-r--r--tests/testdata/test_f4_sha256.x509.pem (renamed from testdata/test_f4_sha256.x509.pem)0
-rw-r--r--tests/testdata/testkey.pk8 (renamed from testdata/testkey.pk8)bin1217 -> 1217 bytes
-rw-r--r--tests/testdata/testkey.x509.pem (renamed from testdata/testkey.x509.pem)0
-rw-r--r--tests/testdata/testkey_ecdsa.pk8 (renamed from testdata/testkey_ecdsa.pk8)bin138 -> 138 bytes
-rw-r--r--tests/testdata/testkey_ecdsa.x509.pem (renamed from testdata/testkey_ecdsa.x509.pem)0
-rw-r--r--tests/testdata/testkey_sha256.x509.pem (renamed from testdata/testkey_sha256.x509.pem)0
-rw-r--r--tests/testdata/unsigned.zip (renamed from testdata/unsigned.zip)bin376 -> 376 bytes
-rw-r--r--tests/unit/asn1_decoder_test.cpp (renamed from tests/asn1_decoder_test.cpp)0
-rw-r--r--updater/Android.mk2
-rw-r--r--updater/blockimg.cpp19
-rw-r--r--updater/install.cpp95
-rwxr-xr-xverifier_test.sh121
36 files changed, 443 insertions, 619 deletions
diff --git a/Android.mk b/Android.mk
index 13fc04bcc..4da34eef5 100644
--- a/Android.mk
+++ b/Android.mk
@@ -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 \
diff --git a/README.md b/README.md
index bab7e87cd..01fab9465 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/applypatch/Android.mk b/applypatch/Android.mk
index bc2e69e62..887a570db 100644
--- a/applypatch/Android.mk
+++ b/applypatch/Android.mk
@@ -21,7 +21,7 @@ LOCAL_SRC_FILES := applypatch.cpp bspatch.cpp freecache.cpp imgpatch.cpp utils.c
LOCAL_MODULE := libapplypatch
LOCAL_MODULE_TAGS := eng
LOCAL_C_INCLUDES += bootable/recovery
-LOCAL_STATIC_LIBRARIES += libbase libotafault libmtdutils libmincrypt libbz libz
+LOCAL_STATIC_LIBRARIES += libbase libotafault libmtdutils libcrypto_static libbz libz
include $(BUILD_STATIC_LIBRARY)
@@ -32,7 +32,7 @@ LOCAL_SRC_FILES := bspatch.cpp imgpatch.cpp utils.cpp
LOCAL_MODULE := libimgpatch
LOCAL_C_INCLUDES += bootable/recovery
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES += libmincrypt libbz libz
+LOCAL_STATIC_LIBRARIES += libcrypto_static libbz libz
include $(BUILD_STATIC_LIBRARY)
@@ -44,7 +44,7 @@ LOCAL_SRC_FILES := bspatch.cpp imgpatch.cpp utils.cpp
LOCAL_MODULE := libimgpatch
LOCAL_C_INCLUDES += bootable/recovery
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES += libmincrypt libbz libz
+LOCAL_STATIC_LIBRARIES += libcrypto_static libbz libz
include $(BUILD_HOST_STATIC_LIBRARY)
endif # HOST_OS == linux
@@ -55,7 +55,9 @@ LOCAL_CLANG := true
LOCAL_SRC_FILES := main.cpp
LOCAL_MODULE := applypatch
LOCAL_C_INCLUDES += bootable/recovery
-LOCAL_STATIC_LIBRARIES += libapplypatch libbase libotafault libmtdutils libmincrypt libbz
+LOCAL_STATIC_LIBRARIES += libapplypatch libbase libotafault libmtdutils libcrypto_static libbz \
+ libedify \
+
LOCAL_SHARED_LIBRARIES += libz libcutils libc
include $(BUILD_EXECUTABLE)
diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp
index 93e6b25ac..9f5e2f200 100644
--- a/applypatch/applypatch.cpp
+++ b/applypatch/applypatch.cpp
@@ -25,9 +25,12 @@
#include <sys/types.h>
#include <unistd.h>
+#include <memory>
+#include <string>
+
#include <android-base/strings.h>
-#include "mincrypt/sha.h"
+#include "openssl/sha.h"
#include "applypatch.h"
#include "mtdutils/mtdutils.h"
#include "edify/expr.h"
@@ -42,7 +45,7 @@ static int GenerateTarget(FileContents* source_file,
const Value* copy_patch_value,
const char* source_filename,
const char* target_filename,
- const uint8_t target_sha1[SHA_DIGEST_SIZE],
+ const uint8_t target_sha1[SHA_DIGEST_LENGTH],
size_t target_size,
const Value* bonus_data);
@@ -68,26 +71,30 @@ int LoadFileContents(const char* filename, FileContents* file) {
}
file->size = file->st.st_size;
- file->data = reinterpret_cast<unsigned char*>(malloc(file->size));
+ file->data = nullptr;
+
+ std::unique_ptr<unsigned char, decltype(&free)> data(
+ static_cast<unsigned char*>(malloc(file->size)), free);
+ if (data == nullptr) {
+ printf("failed to allocate memory: %s\n", strerror(errno));
+ return -1;
+ }
FILE* f = ota_fopen(filename, "rb");
if (f == NULL) {
printf("failed to open \"%s\": %s\n", filename, strerror(errno));
- free(file->data);
- file->data = NULL;
return -1;
}
- size_t bytes_read = ota_fread(file->data, 1, file->size, f);
+ size_t bytes_read = ota_fread(data.get(), 1, file->size, f);
if (bytes_read != static_cast<size_t>(file->size)) {
printf("short read of \"%s\" (%zu bytes of %zd)\n", filename, bytes_read, file->size);
- free(file->data);
- file->data = NULL;
+ fclose(f);
return -1;
}
ota_fclose(f);
-
- SHA_hash(file->data, file->size, file->sha1);
+ file->data = data.release();
+ SHA1(file->data, file->size, file->sha1);
return 0;
}
@@ -182,11 +189,11 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
}
SHA_CTX sha_ctx;
- SHA_init(&sha_ctx);
- uint8_t parsed_sha[SHA_DIGEST_SIZE];
+ SHA1_Init(&sha_ctx);
+ uint8_t parsed_sha[SHA_DIGEST_LENGTH];
// Allocate enough memory to hold the largest size.
- file->data = reinterpret_cast<unsigned char*>(malloc(size[index[pairs-1]]));
+ file->data = static_cast<unsigned char*>(malloc(size[index[pairs-1]]));
char* p = (char*)file->data;
file->size = 0; // # bytes read so far
bool found = false;
@@ -213,7 +220,7 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
file->data = NULL;
return -1;
}
- SHA_update(&sha_ctx, p, read);
+ SHA1_Update(&sha_ctx, p, read);
file->size += read;
}
@@ -221,7 +228,8 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
// check it against this pair's expected hash.
SHA_CTX temp_ctx;
memcpy(&temp_ctx, &sha_ctx, sizeof(SHA_CTX));
- const uint8_t* sha_so_far = SHA_final(&temp_ctx);
+ uint8_t sha_so_far[SHA_DIGEST_LENGTH];
+ SHA1_Final(sha_so_far, &temp_ctx);
if (ParseSha1(sha1sum[index[i]].c_str(), parsed_sha) != 0) {
printf("failed to parse sha1 %s in %s\n", sha1sum[index[i]].c_str(), filename);
@@ -230,7 +238,7 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
return -1;
}
- if (memcmp(sha_so_far, parsed_sha, SHA_DIGEST_SIZE) == 0) {
+ if (memcmp(sha_so_far, parsed_sha, SHA_DIGEST_LENGTH) == 0) {
// we have a match. stop reading the partition; we'll return
// the data we've read so far.
printf("partition read matched size %zu sha %s\n",
@@ -261,10 +269,7 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
return -1;
}
- const uint8_t* sha_final = SHA_final(&sha_ctx);
- for (size_t i = 0; i < SHA_DIGEST_SIZE; ++i) {
- file->sha1[i] = sha_final[i];
- }
+ SHA1_Final(file->sha1, &sha_ctx);
// Fake some stat() info.
file->st.st_mode = 0644;
@@ -316,7 +321,7 @@ int SaveFileContents(const char* filename, const FileContents* file) {
// "MTD:<partition>[:...]" or "EMMC:<partition_device>[:...]". The target name
// might contain multiple colons, but WriteToPartition() only uses the first
// two and ignores the rest. Return 0 on success.
-int WriteToPartition(unsigned char* data, size_t len, const char* target) {
+int WriteToPartition(const unsigned char* data, size_t len, const char* target) {
std::string copy(target);
std::vector<std::string> pieces = android::base::Split(copy, ":");
@@ -355,7 +360,7 @@ int WriteToPartition(unsigned char* data, size_t len, const char* target) {
return -1;
}
- size_t written = mtd_write_data(ctx, reinterpret_cast<char*>(data), len);
+ size_t written = mtd_write_data(ctx, reinterpret_cast<const char*>(data), len);
if (written != len) {
printf("only wrote %zu of %zu bytes to MTD %s\n", written, len, partition);
mtd_write_close(ctx);
@@ -495,7 +500,7 @@ int WriteToPartition(unsigned char* data, size_t len, const char* target) {
int ParseSha1(const char* str, uint8_t* digest) {
const char* ps = str;
uint8_t* pd = digest;
- for (int i = 0; i < SHA_DIGEST_SIZE * 2; ++i, ++ps) {
+ for (int i = 0; i < SHA_DIGEST_LENGTH * 2; ++i, ++ps) {
int digit;
if (*ps >= '0' && *ps <= '9') {
digit = *ps - '0';
@@ -522,10 +527,10 @@ int ParseSha1(const char* str, uint8_t* digest) {
// found.
int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str,
int num_patches) {
- uint8_t patch_sha1[SHA_DIGEST_SIZE];
+ uint8_t patch_sha1[SHA_DIGEST_LENGTH];
for (int i = 0; i < num_patches; ++i) {
if (ParseSha1(patch_sha1_str[i], patch_sha1) == 0 &&
- memcmp(patch_sha1, sha1, SHA_DIGEST_SIZE) == 0) {
+ memcmp(patch_sha1, sha1, SHA_DIGEST_LENGTH) == 0) {
return i;
}
}
@@ -581,7 +586,7 @@ int ShowLicenses() {
}
ssize_t FileSink(const unsigned char* data, ssize_t len, void* token) {
- int fd = *reinterpret_cast<int *>(token);
+ int fd = *static_cast<int*>(token);
ssize_t done = 0;
ssize_t wrote;
while (done < len) {
@@ -595,19 +600,9 @@ ssize_t FileSink(const unsigned char* data, ssize_t len, void* token) {
return done;
}
-typedef struct {
- unsigned char* buffer;
- ssize_t size;
- ssize_t pos;
-} MemorySinkInfo;
-
ssize_t MemorySink(const unsigned char* data, ssize_t len, void* token) {
- MemorySinkInfo* msi = reinterpret_cast<MemorySinkInfo*>(token);
- if (msi->size - msi->pos < len) {
- return -1;
- }
- memcpy(msi->buffer + msi->pos, data, len);
- msi->pos += len;
+ std::string* s = static_cast<std::string*>(token);
+ s->append(reinterpret_cast<const char*>(data), len);
return len;
}
@@ -671,7 +666,7 @@ int applypatch(const char* source_filename,
target_filename = source_filename;
}
- uint8_t target_sha1[SHA_DIGEST_SIZE];
+ uint8_t target_sha1[SHA_DIGEST_LENGTH];
if (ParseSha1(target_sha1_str, target_sha1) != 0) {
printf("failed to parse tgt-sha1 \"%s\"\n", target_sha1_str);
return 1;
@@ -686,7 +681,7 @@ int applypatch(const char* source_filename,
// We try to load the target file into the source_file object.
if (LoadFileContents(target_filename, &source_file) == 0) {
- if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
+ if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_LENGTH) == 0) {
// The early-exit case: the patch was already applied, this file
// has the desired hash, nothing for us to do.
printf("already %s\n", short_sha1(target_sha1).c_str());
@@ -757,7 +752,7 @@ int applypatch_flash(const char* source_filename, const char* target_filename,
const char* target_sha1_str, size_t target_size) {
printf("flash %s: ", target_filename);
- uint8_t target_sha1[SHA_DIGEST_SIZE];
+ uint8_t target_sha1[SHA_DIGEST_LENGTH];
if (ParseSha1(target_sha1_str, target_sha1) != 0) {
printf("failed to parse tgt-sha1 \"%s\"\n", target_sha1_str);
return 1;
@@ -778,7 +773,7 @@ int applypatch_flash(const char* source_filename, const char* target_filename,
pieces.push_back(target_sha1_str);
std::string fullname = android::base::Join(pieces, ':');
if (LoadPartitionContents(fullname.c_str(), &source_file) == 0 &&
- memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
+ memcmp(source_file.sha1, target_sha1, SHA_DIGEST_LENGTH) == 0) {
// The early-exit case: the image was already applied, this partition
// has the desired hash, nothing for us to do.
printf("already %s\n", short_sha1(target_sha1).c_str());
@@ -787,7 +782,7 @@ int applypatch_flash(const char* source_filename, const char* target_filename,
}
if (LoadFileContents(source_filename, &source_file) == 0) {
- if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) != 0) {
+ if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_LENGTH) != 0) {
// The source doesn't have desired checksum.
printf("source \"%s\" doesn't have expected sha1 sum\n", source_filename);
printf("expected: %s, found: %s\n", short_sha1(target_sha1).c_str(),
@@ -813,36 +808,57 @@ static int GenerateTarget(FileContents* source_file,
const Value* copy_patch_value,
const char* source_filename,
const char* target_filename,
- const uint8_t target_sha1[SHA_DIGEST_SIZE],
+ const uint8_t target_sha1[SHA_DIGEST_LENGTH],
size_t target_size,
const Value* bonus_data) {
int retry = 1;
SHA_CTX ctx;
- int output;
- MemorySinkInfo msi;
+ std::string memory_sink_str;
FileContents* source_to_use;
- char* outname;
int made_copy = 0;
+ bool target_is_partition = (strncmp(target_filename, "MTD:", 4) == 0 ||
+ strncmp(target_filename, "EMMC:", 5) == 0);
+ const std::string tmp_target_filename = std::string(target_filename) + ".patch";
+
// assume that target_filename (eg "/system/app/Foo.apk") is located
// on the same filesystem as its top-level directory ("/system").
// We need something that exists for calling statfs().
- char target_fs[strlen(target_filename)+1];
- char* slash = strchr(target_filename+1, '/');
- if (slash != NULL) {
- int count = slash - target_filename;
- strncpy(target_fs, target_filename, count);
- target_fs[count] = '\0';
+ std::string target_fs = target_filename;
+ auto slash_pos = target_fs.find('/', 1);
+ if (slash_pos != std::string::npos) {
+ target_fs.resize(slash_pos);
+ }
+
+ const Value* patch;
+ if (source_patch_value != NULL) {
+ source_to_use = source_file;
+ patch = source_patch_value;
} else {
- strcpy(target_fs, target_filename);
+ source_to_use = copy_file;
+ patch = copy_patch_value;
+ }
+ if (patch->type != VAL_BLOB) {
+ printf("patch is not a blob\n");
+ return 1;
+ }
+ char* header = patch->data;
+ ssize_t header_bytes_read = patch->size;
+ bool use_bsdiff = false;
+ if (header_bytes_read >= 8 && memcmp(header, "BSDIFF40", 8) == 0) {
+ use_bsdiff = true;
+ } else if (header_bytes_read >= 8 && memcmp(header, "IMGDIFF2", 8) == 0) {
+ use_bsdiff = false;
+ } else {
+ printf("Unknown patch file format\n");
+ return 1;
}
do {
// Is there enough room in the target filesystem to hold the patched
// file?
- if (strncmp(target_filename, "MTD:", 4) == 0 ||
- strncmp(target_filename, "EMMC:", 5) == 0) {
+ if (target_is_partition) {
// If the target is a partition, we're actually going to
// write the output to /tmp and then copy it to the
// partition. statfs() always returns 0 blocks free for
@@ -864,7 +880,7 @@ static int GenerateTarget(FileContents* source_file,
} else {
int enough_space = 0;
if (retry > 0) {
- size_t free_space = FreeSpaceForFile(target_fs);
+ size_t free_space = FreeSpaceForFile(target_fs.c_str());
enough_space =
(free_space > (256 << 10)) && // 256k (two-block) minimum
(free_space > (target_size * 3 / 2)); // 50% margin of error
@@ -904,84 +920,53 @@ static int GenerateTarget(FileContents* source_file,
made_copy = 1;
unlink(source_filename);
- size_t free_space = FreeSpaceForFile(target_fs);
+ size_t free_space = FreeSpaceForFile(target_fs.c_str());
printf("(now %zu bytes free for target) ", free_space);
}
}
- const Value* patch;
- if (source_patch_value != NULL) {
- source_to_use = source_file;
- patch = source_patch_value;
- } else {
- source_to_use = copy_file;
- patch = copy_patch_value;
- }
-
- if (patch->type != VAL_BLOB) {
- printf("patch is not a blob\n");
- return 1;
- }
SinkFn sink = NULL;
void* token = NULL;
- output = -1;
- outname = NULL;
- if (strncmp(target_filename, "MTD:", 4) == 0 ||
- strncmp(target_filename, "EMMC:", 5) == 0) {
+ int output_fd = -1;
+ if (target_is_partition) {
// We store the decoded output in memory.
- msi.buffer = reinterpret_cast<unsigned char*>(malloc(target_size));
- if (msi.buffer == NULL) {
- printf("failed to alloc %zu bytes for output\n", target_size);
- return 1;
- }
- msi.pos = 0;
- msi.size = target_size;
sink = MemorySink;
- token = &msi;
+ token = &memory_sink_str;
} else {
// We write the decoded output to "<tgt-file>.patch".
- outname = reinterpret_cast<char*>(malloc(strlen(target_filename) + 10));
- strcpy(outname, target_filename);
- strcat(outname, ".patch");
-
- output = ota_open(outname, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR);
- if (output < 0) {
- printf("failed to open output file %s: %s\n",
- outname, strerror(errno));
+ output_fd = ota_open(tmp_target_filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_SYNC,
+ S_IRUSR | S_IWUSR);
+ if (output_fd < 0) {
+ printf("failed to open output file %s: %s\n", tmp_target_filename.c_str(),
+ strerror(errno));
return 1;
}
sink = FileSink;
- token = &output;
+ token = &output_fd;
}
- char* header = patch->data;
- ssize_t header_bytes_read = patch->size;
- SHA_init(&ctx);
+ SHA1_Init(&ctx);
int result;
-
- if (header_bytes_read >= 8 &&
- memcmp(header, "BSDIFF40", 8) == 0) {
+ if (use_bsdiff) {
result = ApplyBSDiffPatch(source_to_use->data, source_to_use->size,
patch, 0, sink, token, &ctx);
- } else if (header_bytes_read >= 8 &&
- memcmp(header, "IMGDIFF2", 8) == 0) {
+ } else {
result = ApplyImagePatch(source_to_use->data, source_to_use->size,
patch, sink, token, &ctx, bonus_data);
- } else {
- printf("Unknown patch file format\n");
- return 1;
}
- if (output >= 0) {
- if (ota_fsync(output) != 0) {
- printf("failed to fsync file \"%s\" (%s)\n", outname, strerror(errno));
+ if (!target_is_partition) {
+ if (ota_fsync(output_fd) != 0) {
+ printf("failed to fsync file \"%s\" (%s)\n", tmp_target_filename.c_str(),
+ strerror(errno));
result = 1;
}
- if (ota_close(output) != 0) {
- printf("failed to close file \"%s\" (%s)\n", outname, strerror(errno));
+ if (ota_close(output_fd) != 0) {
+ printf("failed to close file \"%s\" (%s)\n", tmp_target_filename.c_str(),
+ strerror(errno));
result = 1;
}
}
@@ -993,8 +978,8 @@ static int GenerateTarget(FileContents* source_file,
} else {
printf("applying patch failed; retrying\n");
}
- if (outname != NULL) {
- unlink(outname);
+ if (!target_is_partition) {
+ unlink(tmp_target_filename.c_str());
}
} else {
// succeeded; no need to retry
@@ -1002,35 +987,36 @@ static int GenerateTarget(FileContents* source_file,
}
} while (retry-- > 0);
- const uint8_t* current_target_sha1 = SHA_final(&ctx);
- if (memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE) != 0) {
+ uint8_t current_target_sha1[SHA_DIGEST_LENGTH];
+ SHA1_Final(current_target_sha1, &ctx);
+ if (memcmp(current_target_sha1, target_sha1, SHA_DIGEST_LENGTH) != 0) {
printf("patch did not produce expected sha1\n");
return 1;
} else {
printf("now %s\n", short_sha1(target_sha1).c_str());
}
- if (output < 0) {
+ if (target_is_partition) {
// Copy the temp file to the partition.
- if (WriteToPartition(msi.buffer, msi.pos, target_filename) != 0) {
+ if (WriteToPartition(reinterpret_cast<const unsigned char*>(memory_sink_str.c_str()),
+ memory_sink_str.size(), target_filename) != 0) {
printf("write of patched data to %s failed\n", target_filename);
return 1;
}
- free(msi.buffer);
} else {
// Give the .patch file the same owner, group, and mode of the
// original source file.
- if (chmod(outname, source_to_use->st.st_mode) != 0) {
- printf("chmod of \"%s\" failed: %s\n", outname, strerror(errno));
+ if (chmod(tmp_target_filename.c_str(), source_to_use->st.st_mode) != 0) {
+ printf("chmod of \"%s\" failed: %s\n", tmp_target_filename.c_str(), strerror(errno));
return 1;
}
- if (chown(outname, source_to_use->st.st_uid, source_to_use->st.st_gid) != 0) {
- printf("chown of \"%s\" failed: %s\n", outname, strerror(errno));
+ if (chown(tmp_target_filename.c_str(), source_to_use->st.st_uid, source_to_use->st.st_gid) != 0) {
+ printf("chown of \"%s\" failed: %s\n", tmp_target_filename.c_str(), strerror(errno));
return 1;
}
// Finally, rename the .patch file to replace the target file.
- if (rename(outname, target_filename) != 0) {
+ if (rename(tmp_target_filename.c_str(), target_filename) != 0) {
printf("rename of .patch to \"%s\" failed: %s\n", target_filename, strerror(errno));
return 1;
}
diff --git a/applypatch/applypatch.h b/applypatch/applypatch.h
index 415bc1b3c..14fb490ba 100644
--- a/applypatch/applypatch.h
+++ b/applypatch/applypatch.h
@@ -18,16 +18,19 @@
#define _APPLYPATCH_H
#include <sys/stat.h>
-#include "mincrypt/sha.h"
+
+#include <vector>
+
+#include "openssl/sha.h"
#include "edify/expr.h"
typedef struct _Patch {
- uint8_t sha1[SHA_DIGEST_SIZE];
+ uint8_t sha1[SHA_DIGEST_LENGTH];
const char* patch_filename;
} Patch;
typedef struct _FileContents {
- uint8_t sha1[SHA_DIGEST_SIZE];
+ uint8_t sha1[SHA_DIGEST_LENGTH];
unsigned char* data;
ssize_t size;
struct stat st;
@@ -68,22 +71,22 @@ void FreeFileContents(FileContents* file);
int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str,
int num_patches);
-// bsdiff.c
+// bsdiff.cpp
void ShowBSDiffLicense();
int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size,
const Value* patch, ssize_t patch_offset,
SinkFn sink, void* token, SHA_CTX* ctx);
int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
const Value* patch, ssize_t patch_offset,
- unsigned char** new_data, ssize_t* new_size);
+ std::vector<unsigned char>* new_data);
-// imgpatch.c
+// imgpatch.cpp
int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
const Value* patch,
SinkFn sink, void* token, SHA_CTX* ctx,
const Value* bonus_data);
-// freecache.c
+// freecache.cpp
int MakeFreeSpaceOnCache(size_t bytes_needed);
#endif
diff --git a/applypatch/bspatch.cpp b/applypatch/bspatch.cpp
index 75975ad6d..ebb55f1d1 100644
--- a/applypatch/bspatch.cpp
+++ b/applypatch/bspatch.cpp
@@ -24,13 +24,12 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
-#include <malloc.h>
#include <unistd.h>
#include <string.h>
#include <bzlib.h>
-#include "mincrypt/sha.h"
+#include "openssl/sha.h"
#include "applypatch.h"
void ShowBSDiffLicense() {
@@ -103,26 +102,22 @@ int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size,
const Value* patch, ssize_t patch_offset,
SinkFn sink, void* token, SHA_CTX* ctx) {
- unsigned char* new_data;
- ssize_t new_size;
- if (ApplyBSDiffPatchMem(old_data, old_size, patch, patch_offset,
- &new_data, &new_size) != 0) {
+ std::vector<unsigned char> new_data;
+ if (ApplyBSDiffPatchMem(old_data, old_size, patch, patch_offset, &new_data) != 0) {
return -1;
}
- if (sink(new_data, new_size, token) < new_size) {
+ if (sink(new_data.data(), new_data.size(), token) < static_cast<ssize_t>(new_data.size())) {
printf("short write of output: %d (%s)\n", errno, strerror(errno));
return 1;
}
- if (ctx) SHA_update(ctx, new_data, new_size);
- free(new_data);
-
+ if (ctx) SHA1_Update(ctx, new_data.data(), new_data.size());
return 0;
}
int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
const Value* patch, ssize_t patch_offset,
- unsigned char** new_data, ssize_t* new_size) {
+ std::vector<unsigned char>* new_data) {
// Patch data format:
// 0 8 "BSDIFF40"
// 8 8 X
@@ -141,12 +136,12 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
return 1;
}
- ssize_t ctrl_len, data_len;
+ ssize_t ctrl_len, data_len, new_size;
ctrl_len = offtin(header+8);
data_len = offtin(header+16);
- *new_size = offtin(header+24);
+ new_size = offtin(header+24);
- if (ctrl_len < 0 || data_len < 0 || *new_size < 0) {
+ if (ctrl_len < 0 || data_len < 0 || new_size < 0) {
printf("corrupt patch file header (data lengths)\n");
return 1;
}
@@ -183,18 +178,14 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
printf("failed to bzinit extra stream (%d)\n", bzerr);
}
- *new_data = reinterpret_cast<unsigned char*>(malloc(*new_size));
- if (*new_data == NULL) {
- printf("failed to allocate %zd bytes of memory for output file\n", *new_size);
- return 1;
- }
+ new_data->resize(new_size);
off_t oldpos = 0, newpos = 0;
off_t ctrl[3];
off_t len_read;
int i;
unsigned char buf[24];
- while (newpos < *new_size) {
+ while (newpos < new_size) {
// Read control data
if (FillBuffer(buf, 24, &cstream) != 0) {
printf("error while reading control stream\n");
@@ -210,13 +201,13 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
}
// Sanity check
- if (newpos + ctrl[0] > *new_size) {
+ if (newpos + ctrl[0] > new_size) {
printf("corrupt patch (new file overrun)\n");
return 1;
}
// Read diff string
- if (FillBuffer(*new_data + newpos, ctrl[0], &dstream) != 0) {
+ if (FillBuffer(new_data->data() + newpos, ctrl[0], &dstream) != 0) {
printf("error while reading diff stream\n");
return 1;
}
@@ -233,13 +224,13 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
oldpos += ctrl[0];
// Sanity check
- if (newpos + ctrl[1] > *new_size) {
+ if (newpos + ctrl[1] > new_size) {
printf("corrupt patch (new file overrun)\n");
return 1;
}
// Read extra string
- if (FillBuffer(*new_data + newpos, ctrl[1], &estream) != 0) {
+ if (FillBuffer(new_data->data() + newpos, ctrl[1], &estream) != 0) {
printf("error while reading extra stream\n");
return 1;
}
diff --git a/applypatch/freecache.cpp b/applypatch/freecache.cpp
index 2eb2f55ef..c84f42797 100644
--- a/applypatch/freecache.cpp
+++ b/applypatch/freecache.cpp
@@ -25,119 +25,90 @@
#include <dirent.h>
#include <ctype.h>
+#include <memory>
+#include <set>
+#include <string>
+
+#include <android-base/parseint.h>
+#include <android-base/stringprintf.h>
+
#include "applypatch.h"
-static int EliminateOpenFiles(char** files, int file_count) {
- DIR* d;
- struct dirent* de;
- d = opendir("/proc");
- if (d == NULL) {
+static int EliminateOpenFiles(std::set<std::string>* files) {
+ std::unique_ptr<DIR, decltype(&closedir)> d(opendir("/proc"), closedir);
+ if (!d) {
printf("error opening /proc: %s\n", strerror(errno));
return -1;
}
- while ((de = readdir(d)) != 0) {
- int i;
- for (i = 0; de->d_name[i] != '\0' && isdigit(de->d_name[i]); ++i);
- if (de->d_name[i]) continue;
-
- // de->d_name[i] is numeric
-
- char path[FILENAME_MAX];
- strcpy(path, "/proc/");
- strcat(path, de->d_name);
- strcat(path, "/fd/");
+ struct dirent* de;
+ while ((de = readdir(d.get())) != 0) {
+ unsigned int pid;
+ if (!android::base::ParseUint(de->d_name, &pid)) {
+ continue;
+ }
+ std::string path = android::base::StringPrintf("/proc/%s/fd/", de->d_name);
- DIR* fdd;
struct dirent* fdde;
- fdd = opendir(path);
- if (fdd == NULL) {
- printf("error opening %s: %s\n", path, strerror(errno));
+ std::unique_ptr<DIR, decltype(&closedir)> fdd(opendir(path.c_str()), closedir);
+ if (!fdd) {
+ printf("error opening %s: %s\n", path.c_str(), strerror(errno));
continue;
}
- while ((fdde = readdir(fdd)) != 0) {
- char fd_path[FILENAME_MAX];
+ while ((fdde = readdir(fdd.get())) != 0) {
+ std::string fd_path = path + fdde->d_name;
char link[FILENAME_MAX];
- strcpy(fd_path, path);
- strcat(fd_path, fdde->d_name);
- int count;
- count = readlink(fd_path, link, sizeof(link)-1);
+ int count = readlink(fd_path.c_str(), link, sizeof(link)-1);
if (count >= 0) {
link[count] = '\0';
-
- // This is inefficient, but it should only matter if there are
- // lots of files in /cache, and lots of them are open (neither
- // of which should be true, especially in recovery).
if (strncmp(link, "/cache/", 7) == 0) {
- int j;
- for (j = 0; j < file_count; ++j) {
- if (files[j] && strcmp(files[j], link) == 0) {
- printf("%s is open by %s\n", link, de->d_name);
- free(files[j]);
- files[j] = NULL;
- }
+ if (files->erase(link) > 0) {
+ printf("%s is open by %s\n", link, de->d_name);
}
}
}
}
- closedir(fdd);
}
- closedir(d);
-
return 0;
}
-int FindExpendableFiles(char*** names, int* entries) {
- DIR* d;
- struct dirent* de;
- int size = 32;
- *entries = 0;
- *names = reinterpret_cast<char**>(malloc(size * sizeof(char*)));
-
- char path[FILENAME_MAX];
-
+static std::set<std::string> FindExpendableFiles() {
+ std::set<std::string> files;
// We're allowed to delete unopened regular files in any of these
// directories.
const char* dirs[2] = {"/cache", "/cache/recovery/otatest"};
for (size_t i = 0; i < sizeof(dirs)/sizeof(dirs[0]); ++i) {
- d = opendir(dirs[i]);
- if (d == NULL) {
+ std::unique_ptr<DIR, decltype(&closedir)> d(opendir(dirs[i]), closedir);
+ if (!d) {
printf("error opening %s: %s\n", dirs[i], strerror(errno));
continue;
}
// Look for regular files in the directory (not in any subdirectories).
- while ((de = readdir(d)) != 0) {
- strcpy(path, dirs[i]);
- strcat(path, "/");
- strcat(path, de->d_name);
+ struct dirent* de;
+ while ((de = readdir(d.get())) != 0) {
+ std::string path = std::string(dirs[i]) + "/" + de->d_name;
// We can't delete CACHE_TEMP_SOURCE; if it's there we might have
// restarted during installation and could be depending on it to
// be there.
- if (strcmp(path, CACHE_TEMP_SOURCE) == 0) continue;
+ if (path == CACHE_TEMP_SOURCE) {
+ continue;
+ }
struct stat st;
- if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) {
- if (*entries >= size) {
- size *= 2;
- *names = reinterpret_cast<char**>(realloc(*names, size * sizeof(char*)));
- }
- (*names)[(*entries)++] = strdup(path);
+ if (stat(path.c_str(), &st) == 0 && S_ISREG(st.st_mode)) {
+ files.insert(path);
}
}
-
- closedir(d);
}
- printf("%d regular files in deletable directories\n", *entries);
-
- if (EliminateOpenFiles(*names, *entries) < 0) {
- return -1;
+ printf("%zu regular files in deletable directories\n", files.size());
+ if (EliminateOpenFiles(&files) < 0) {
+ return std::set<std::string>();
}
-
- return 0;
+ return files;
}
int MakeFreeSpaceOnCache(size_t bytes_needed) {
@@ -147,15 +118,8 @@ int MakeFreeSpaceOnCache(size_t bytes_needed) {
if (free_now >= bytes_needed) {
return 0;
}
-
- char** names;
- int entries;
-
- if (FindExpendableFiles(&names, &entries) < 0) {
- return -1;
- }
-
- if (entries == 0) {
+ std::set<std::string> files = FindExpendableFiles();
+ if (files.empty()) {
// nothing we can delete to free up space!
printf("no files can be deleted to free space on /cache\n");
return -1;
@@ -167,20 +131,13 @@ int MakeFreeSpaceOnCache(size_t bytes_needed) {
//
// Instead, we'll be dumb.
- int i;
- for (i = 0; i < entries && free_now < bytes_needed; ++i) {
- if (names[i]) {
- unlink(names[i]);
- free_now = FreeSpaceForFile("/cache");
- printf("deleted %s; now %zu bytes free\n", names[i], free_now);
- free(names[i]);
+ for (const auto& file : files) {
+ unlink(file.c_str());
+ free_now = FreeSpaceForFile("/cache");
+ printf("deleted %s; now %zu bytes free\n", file.c_str(), free_now);
+ if (free_now < bytes_needed) {
+ break;
}
}
-
- for (; i < entries; ++i) {
- free(names[i]);
- }
- free(names);
-
return (free_now >= bytes_needed) ? 0 : -1;
}
diff --git a/applypatch/imgpatch.cpp b/applypatch/imgpatch.cpp
index 3e72b2cb5..8824038ea 100644
--- a/applypatch/imgpatch.cpp
+++ b/applypatch/imgpatch.cpp
@@ -21,12 +21,13 @@
#include <sys/cdefs.h>
#include <sys/stat.h>
#include <errno.h>
-#include <malloc.h>
#include <unistd.h>
#include <string.h>
+#include <vector>
+
#include "zlib.h"
-#include "mincrypt/sha.h"
+#include "openssl/sha.h"
#include "applypatch.h"
#include "imgdiff.h"
#include "utils.h"
@@ -109,7 +110,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
printf("failed to read chunk %d raw data\n", i);
return -1;
}
- if (ctx) SHA_update(ctx, patch->data + pos, data_len);
+ if (ctx) SHA1_Update(ctx, patch->data + pos, data_len);
if (sink((unsigned char*)patch->data + pos,
data_len, token) != data_len) {
printf("failed to write chunk %d raw data\n", i);
@@ -129,7 +130,6 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
size_t src_len = Read8(deflate_header+8);
size_t patch_offset = Read8(deflate_header+16);
size_t expanded_len = Read8(deflate_header+24);
- size_t target_len = Read8(deflate_header+32);
int level = Read4(deflate_header+40);
int method = Read4(deflate_header+44);
int windowBits = Read4(deflate_header+48);
@@ -150,13 +150,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
// must be appended from the bonus_data value.
size_t bonus_size = (i == 1 && bonus_data != NULL) ? bonus_data->size : 0;
- unsigned char* expanded_source = reinterpret_cast<unsigned char*>(malloc(expanded_len));
- if (expanded_source == NULL) {
- printf("failed to allocate %zu bytes for expanded_source\n",
- expanded_len);
- return -1;
- }
-
+ std::vector<unsigned char> expanded_source(expanded_len);
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
@@ -164,7 +158,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
strm.avail_in = src_len;
strm.next_in = (unsigned char*)(old_data + src_start);
strm.avail_out = expanded_len;
- strm.next_out = expanded_source;
+ strm.next_out = expanded_source.data();
int ret;
ret = inflateInit2(&strm, -15);
@@ -189,18 +183,16 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
inflateEnd(&strm);
if (bonus_size) {
- memcpy(expanded_source + (expanded_len - bonus_size),
+ memcpy(expanded_source.data() + (expanded_len - bonus_size),
bonus_data->data, bonus_size);
}
// Next, apply the bsdiff patch (in memory) to the uncompressed
// data.
- unsigned char* uncompressed_target_data;
- ssize_t uncompressed_target_size;
- if (ApplyBSDiffPatchMem(expanded_source, expanded_len,
+ std::vector<unsigned char> uncompressed_target_data;
+ if (ApplyBSDiffPatchMem(expanded_source.data(), expanded_len,
patch, patch_offset,
- &uncompressed_target_data,
- &uncompressed_target_size) != 0) {
+ &uncompressed_target_data) != 0) {
return -1;
}
@@ -208,40 +200,36 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
// we're done with the expanded_source data buffer, so we'll
// reuse that memory to receive the output of deflate.
- unsigned char* temp_data = expanded_source;
- ssize_t temp_size = expanded_len;
- if (temp_size < 32768) {
- // ... unless the buffer is too small, in which case we'll
- // allocate a fresh one.
- free(temp_data);
- temp_data = reinterpret_cast<unsigned char*>(malloc(32768));
- temp_size = 32768;
+ if (expanded_source.size() < 32768U) {
+ expanded_source.resize(32768U);
}
+ std::vector<unsigned char>& temp_data = expanded_source;
// now the deflate stream
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
- strm.avail_in = uncompressed_target_size;
- strm.next_in = uncompressed_target_data;
+ strm.avail_in = uncompressed_target_data.size();
+ strm.next_in = uncompressed_target_data.data();
ret = deflateInit2(&strm, level, method, windowBits, memLevel, strategy);
+ if (ret != Z_OK) {
+ printf("failed to init uncompressed data deflation: %d\n", ret);
+ return -1;
+ }
do {
- strm.avail_out = temp_size;
- strm.next_out = temp_data;
+ strm.avail_out = temp_data.size();
+ strm.next_out = temp_data.data();
ret = deflate(&strm, Z_FINISH);
- ssize_t have = temp_size - strm.avail_out;
+ ssize_t have = temp_data.size() - strm.avail_out;
- if (sink(temp_data, have, token) != have) {
+ if (sink(temp_data.data(), have, token) != have) {
printf("failed to write %ld compressed bytes to output\n",
(long)have);
return -1;
}
- if (ctx) SHA_update(ctx, temp_data, have);
+ if (ctx) SHA1_Update(ctx, temp_data.data(), have);
} while (ret != Z_STREAM_END);
deflateEnd(&strm);
-
- free(temp_data);
- free(uncompressed_target_data);
} else {
printf("patch chunk %d is unknown type %d\n", i, type);
return -1;
diff --git a/applypatch/main.cpp b/applypatch/main.cpp
index 966d8b91f..7606d5d3c 100644
--- a/applypatch/main.cpp
+++ b/applypatch/main.cpp
@@ -19,9 +19,12 @@
#include <string.h>
#include <unistd.h>
+#include <memory>
+#include <vector>
+
#include "applypatch.h"
#include "edify/expr.h"
-#include "mincrypt/sha.h"
+#include "openssl/sha.h"
static int CheckMode(int argc, char** argv) {
if (argc < 3) {
@@ -47,16 +50,11 @@ static int SpaceMode(int argc, char** argv) {
// "<sha1>:<filename>" into the new parallel arrays *sha1s and
// *patches (loading file contents into the patches). Returns true on
// success.
-static bool ParsePatchArgs(int argc, char** argv, char*** sha1s,
- Value*** patches, int* num_patches) {
- *num_patches = argc;
- *sha1s = reinterpret_cast<char**>(malloc(*num_patches * sizeof(char*)));
- *patches = reinterpret_cast<Value**>(malloc(*num_patches * sizeof(Value*)));
- memset(*patches, 0, *num_patches * sizeof(Value*));
-
- uint8_t digest[SHA_DIGEST_SIZE];
+static bool ParsePatchArgs(int argc, char** argv, std::vector<char*>* sha1s,
+ std::vector<std::unique_ptr<Value, decltype(&FreeValue)>>* patches) {
+ uint8_t digest[SHA_DIGEST_LENGTH];
- for (int i = 0; i < *num_patches; ++i) {
+ for (int i = 0; i < argc; ++i) {
char* colon = strchr(argv[i], ':');
if (colon != NULL) {
*colon = '\0';
@@ -68,34 +66,22 @@ static bool ParsePatchArgs(int argc, char** argv, char*** sha1s,
return false;
}
- (*sha1s)[i] = argv[i];
+ sha1s->push_back(argv[i]);
if (colon == NULL) {
- (*patches)[i] = NULL;
+ patches->emplace_back(nullptr, FreeValue);
} else {
FileContents fc;
if (LoadFileContents(colon, &fc) != 0) {
- goto abort;
+ return false;
}
- (*patches)[i] = reinterpret_cast<Value*>(malloc(sizeof(Value)));
- (*patches)[i]->type = VAL_BLOB;
- (*patches)[i]->size = fc.size;
- (*patches)[i]->data = reinterpret_cast<char*>(fc.data);
+ std::unique_ptr<Value, decltype(&FreeValue)> value(new Value, FreeValue);
+ value->type = VAL_BLOB;
+ value->size = fc.size;
+ value->data = reinterpret_cast<char*>(fc.data);
+ patches->push_back(std::move(value));
}
}
-
return true;
-
- abort:
- for (int i = 0; i < *num_patches; ++i) {
- Value* p = (*patches)[i];
- if (p != NULL) {
- free(p->data);
- free(p);
- }
- }
- free(*sha1s);
- free(*patches);
- return false;
}
static int FlashMode(const char* src_filename, const char* tgt_filename,
@@ -104,17 +90,17 @@ static int FlashMode(const char* src_filename, const char* tgt_filename,
}
static int PatchMode(int argc, char** argv) {
- Value* bonus = NULL;
+ std::unique_ptr<Value, decltype(&FreeValue)> bonus(nullptr, FreeValue);
if (argc >= 3 && strcmp(argv[1], "-b") == 0) {
FileContents fc;
if (LoadFileContents(argv[2], &fc) != 0) {
printf("failed to load bonus file %s\n", argv[2]);
return 1;
}
- bonus = reinterpret_cast<Value*>(malloc(sizeof(Value)));
+ bonus.reset(new Value);
bonus->type = VAL_BLOB;
bonus->size = fc.size;
- bonus->data = (char*)fc.data;
+ bonus->data = reinterpret_cast<char*>(fc.data);
argc -= 2;
argv += 2;
}
@@ -140,33 +126,20 @@ static int PatchMode(int argc, char** argv) {
}
- char** sha1s;
- Value** patches;
- int num_patches;
- if (!ParsePatchArgs(argc-5, argv+5, &sha1s, &patches, &num_patches)) {
+ std::vector<char*> sha1s;
+ std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> patches;
+ if (!ParsePatchArgs(argc-5, argv+5, &sha1s, &patches)) {
printf("failed to parse patch args\n");
return 1;
}
- int result = applypatch(argv[1], argv[2], argv[3], target_size,
- num_patches, sha1s, patches, bonus);
-
- int i;
- for (i = 0; i < num_patches; ++i) {
- Value* p = patches[i];
- if (p != NULL) {
- free(p->data);
- free(p);
- }
- }
- if (bonus) {
- free(bonus->data);
- free(bonus);
+ std::vector<Value*> patch_ptrs;
+ for (const auto& p : patches) {
+ patch_ptrs.push_back(p.get());
}
- free(sha1s);
- free(patches);
-
- return result;
+ return applypatch(argv[1], argv[2], argv[3], target_size,
+ patch_ptrs.size(), sha1s.data(),
+ patch_ptrs.data(), bonus.get());
}
// This program applies binary patches to files in a way that is safe
diff --git a/print_sha1.h b/print_sha1.h
index 9e37c5fe3..fa3d7e009 100644
--- a/print_sha1.h
+++ b/print_sha1.h
@@ -20,9 +20,9 @@
#include <stdint.h>
#include <string>
-#include "mincrypt/sha.h"
+#include "openssl/sha.h"
-static std::string print_sha1(const uint8_t sha1[SHA_DIGEST_SIZE], size_t len) {
+static std::string print_sha1(const uint8_t sha1[SHA_DIGEST_LENGTH], size_t len) {
const char* hex = "0123456789abcdef";
std::string result = "";
for (size_t i = 0; i < len; ++i) {
@@ -32,11 +32,11 @@ static std::string print_sha1(const uint8_t sha1[SHA_DIGEST_SIZE], size_t len) {
return result;
}
-static std::string print_sha1(const uint8_t sha1[SHA_DIGEST_SIZE]) {
- return print_sha1(sha1, SHA_DIGEST_SIZE);
+static std::string print_sha1(const uint8_t sha1[SHA_DIGEST_LENGTH]) {
+ return print_sha1(sha1, SHA_DIGEST_LENGTH);
}
-static std::string short_sha1(const uint8_t sha1[SHA_DIGEST_SIZE]) {
+static std::string short_sha1(const uint8_t sha1[SHA_DIGEST_LENGTH]) {
return print_sha1(sha1, 4);
}
diff --git a/tests/Android.mk b/tests/Android.mk
index 4ce00b457..3f3c433eb 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -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)
diff --git a/verifier_test.cpp b/tests/component/verifier_test.cpp
index 2367e0052..7f7b1b448 100644
--- a/verifier_test.cpp
+++ b/tests/component/verifier_test.cpp
@@ -1,13 +1,13 @@
/*
* 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
@@ -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.
@@ -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*) { }
@@ -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) {
- if (certs.empty()) {
- fprintf(stderr, "May only specify -sha256 after key type\n");
- return 2;
+
+ 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()) {
+ FAIL() << "May only specify -sha256 after key type\n";
+ }
+ certs.back().hash_len = SHA256_DIGEST_SIZE;
+ } else if (*it == "ec") {
+ certs.emplace_back(SHA_DIGEST_SIZE, Certificate::EC,
+ nullptr, std::unique_ptr<ECPublicKey>(new ECPublicKey(test_ec_key)));
+ } else if (*it == "e3") {
+ certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA,
+ std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_key)), nullptr);
+ } else if (*it == "f4") {
+ certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA,
+ std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_f4_key)), nullptr);
}
- ++argn;
- certs.back().hash_len = SHA256_DIGEST_SIZE;
- } else if (strcmp(argv[argn], "-ec") == 0) {
- ++argn;
- 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;
+ }
+ if (certs.empty()) {
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;
- 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 (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;
+ static void SetUpTestCase() {
+ ui = new MockUI();
}
+};
- if (certs.empty()) {
- certs.emplace_back(SHA_DIGEST_SIZE, Certificate::RSA,
- std::unique_ptr<RSAPublicKey>(new RSAPublicKey(test_key)), nullptr);
- }
+class VerifierSuccessTest : public VerifierTest {
+};
- ui = new FakeUI();
+class VerifierFailureTest : public VerifierTest {
+};
- MemMapping map;
- if (sysMapFile(argv[argn], &map) != 0) {
- fprintf(stderr, "failed to mmap %s: %s\n", argv[argn], strerror(errno));
- return 4;
- }
+TEST_P(VerifierSuccessTest, VerifySucceed) {
+ ASSERT_EQ(verify_file(memmap.addr, memmap.length, certs), VERIFY_SUCCESS);
+}
- 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(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"})));
diff --git a/testdata/alter-footer.zip b/tests/testdata/alter-footer.zip
index f497ec000..f497ec000 100644
--- a/testdata/alter-footer.zip
+++ b/tests/testdata/alter-footer.zip
Binary files differ
diff --git a/testdata/alter-metadata.zip b/tests/testdata/alter-metadata.zip
index 1c71fbc49..1c71fbc49 100644
--- a/testdata/alter-metadata.zip
+++ b/tests/testdata/alter-metadata.zip
Binary files differ
diff --git a/testdata/fake-eocd.zip b/tests/testdata/fake-eocd.zip
index 15dc0a946..15dc0a946 100644
--- a/testdata/fake-eocd.zip
+++ b/tests/testdata/fake-eocd.zip
Binary files differ
diff --git a/testdata/jarsigned.zip b/tests/testdata/jarsigned.zip
index 8b1ef8bdd..8b1ef8bdd 100644
--- a/testdata/jarsigned.zip
+++ b/tests/testdata/jarsigned.zip
Binary files differ
diff --git a/testdata/otasigned.zip b/tests/testdata/otasigned.zip
index a6bc53e41..a6bc53e41 100644
--- a/testdata/otasigned.zip
+++ b/tests/testdata/otasigned.zip
Binary files differ
diff --git a/testdata/otasigned_ecdsa_sha256.zip b/tests/testdata/otasigned_ecdsa_sha256.zip
index 999fcdd0f..999fcdd0f 100644
--- a/testdata/otasigned_ecdsa_sha256.zip
+++ b/tests/testdata/otasigned_ecdsa_sha256.zip
Binary files differ
diff --git a/testdata/otasigned_f4.zip b/tests/testdata/otasigned_f4.zip
index dd1e4dd40..dd1e4dd40 100644
--- a/testdata/otasigned_f4.zip
+++ b/tests/testdata/otasigned_f4.zip
Binary files differ
diff --git a/testdata/otasigned_f4_sha256.zip b/tests/testdata/otasigned_f4_sha256.zip
index 3af408c40..3af408c40 100644
--- a/testdata/otasigned_f4_sha256.zip
+++ b/tests/testdata/otasigned_f4_sha256.zip
Binary files differ
diff --git a/testdata/otasigned_sha256.zip b/tests/testdata/otasigned_sha256.zip
index 0ed4409b3..0ed4409b3 100644
--- a/testdata/otasigned_sha256.zip
+++ b/tests/testdata/otasigned_sha256.zip
Binary files differ
diff --git a/testdata/random.zip b/tests/testdata/random.zip
index 18c0b3b9f..18c0b3b9f 100644
--- a/testdata/random.zip
+++ b/tests/testdata/random.zip
Binary files differ
diff --git a/testdata/test_f4.pk8 b/tests/testdata/test_f4.pk8
index 3052613c5..3052613c5 100644
--- a/testdata/test_f4.pk8
+++ b/tests/testdata/test_f4.pk8
Binary files differ
diff --git a/testdata/test_f4.x509.pem b/tests/testdata/test_f4.x509.pem
index 814abcf99..814abcf99 100644
--- a/testdata/test_f4.x509.pem
+++ b/tests/testdata/test_f4.x509.pem
diff --git a/testdata/test_f4_sha256.x509.pem b/tests/testdata/test_f4_sha256.x509.pem
index 9d5376b45..9d5376b45 100644
--- a/testdata/test_f4_sha256.x509.pem
+++ b/tests/testdata/test_f4_sha256.x509.pem
diff --git a/testdata/testkey.pk8 b/tests/testdata/testkey.pk8
index 586c1bd5c..586c1bd5c 100644
--- a/testdata/testkey.pk8
+++ b/tests/testdata/testkey.pk8
Binary files differ
diff --git a/testdata/testkey.x509.pem b/tests/testdata/testkey.x509.pem
index e242d83e2..e242d83e2 100644
--- a/testdata/testkey.x509.pem
+++ b/tests/testdata/testkey.x509.pem
diff --git a/testdata/testkey_ecdsa.pk8 b/tests/testdata/testkey_ecdsa.pk8
index 9a521c8cf..9a521c8cf 100644
--- a/testdata/testkey_ecdsa.pk8
+++ b/tests/testdata/testkey_ecdsa.pk8
Binary files differ
diff --git a/testdata/testkey_ecdsa.x509.pem b/tests/testdata/testkey_ecdsa.x509.pem
index b12283645..b12283645 100644
--- a/testdata/testkey_ecdsa.x509.pem
+++ b/tests/testdata/testkey_ecdsa.x509.pem
diff --git a/testdata/testkey_sha256.x509.pem b/tests/testdata/testkey_sha256.x509.pem
index 002ce8968..002ce8968 100644
--- a/testdata/testkey_sha256.x509.pem
+++ b/tests/testdata/testkey_sha256.x509.pem
diff --git a/testdata/unsigned.zip b/tests/testdata/unsigned.zip
index 24e3eadac..24e3eadac 100644
--- a/testdata/unsigned.zip
+++ b/tests/testdata/unsigned.zip
Binary files differ
diff --git a/tests/asn1_decoder_test.cpp b/tests/unit/asn1_decoder_test.cpp
index af96d87d2..af96d87d2 100644
--- a/tests/asn1_decoder_test.cpp
+++ b/tests/unit/asn1_decoder_test.cpp
diff --git a/updater/Android.mk b/updater/Android.mk
index d74dffc0c..d7aa613e9 100644
--- a/updater/Android.mk
+++ b/updater/Android.mk
@@ -46,7 +46,7 @@ endif
LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UPDATER_LIBS) $(TARGET_RECOVERY_UPDATER_EXTRA_LIBS)
LOCAL_STATIC_LIBRARIES += libapplypatch libbase libotafault libedify libmtdutils libminzip libz
-LOCAL_STATIC_LIBRARIES += libmincrypt libbz
+LOCAL_STATIC_LIBRARIES += libbz
LOCAL_STATIC_LIBRARIES += libcutils liblog libc
LOCAL_STATIC_LIBRARIES += libselinux
tune2fs_static_libraries := \
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index c898ac6f6..e9c8ddbc0 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -43,7 +43,7 @@
#include "applypatch/applypatch.h"
#include "edify/expr.h"
#include "install.h"
-#include "mincrypt/sha.h"
+#include "openssl/sha.h"
#include "minzip/Hash.h"
#include "otafault/ota_io.h"
#include "print_sha1.h"
@@ -408,10 +408,10 @@ static int LoadSrcTgtVersion1(CommandParameters& params, RangeSet& tgt, size_t&
static int VerifyBlocks(const std::string& expected, const std::vector<uint8_t>& buffer,
const size_t blocks, bool printerror) {
- uint8_t digest[SHA_DIGEST_SIZE];
+ uint8_t digest[SHA_DIGEST_LENGTH];
const uint8_t* data = buffer.data();
- SHA_hash(data, blocks * BLOCKSIZE, digest);
+ SHA1(data, blocks * BLOCKSIZE, digest);
std::string hexdigest = print_sha1(digest);
@@ -663,10 +663,8 @@ static int CreateStash(State* state, int maxblocks, const char* blockdev, std::s
// Stash directory should be different for each partition to avoid conflicts
// when updating multiple partitions at the same time, so we use the hash of
// the block device name as the base directory
- SHA_CTX ctx;
- SHA_init(&ctx);
- SHA_update(&ctx, blockdev, strlen(blockdev));
- const uint8_t* digest = SHA_final(&ctx);
+ uint8_t digest[SHA_DIGEST_LENGTH];
+ SHA1(reinterpret_cast<const uint8_t*>(blockdev), strlen(blockdev), digest);
base = print_sha1(digest);
std::string dirname = GetStashFileName(base, "", "");
@@ -1628,7 +1626,7 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[])
parse_range(ranges->data, rs);
SHA_CTX ctx;
- SHA_init(&ctx);
+ SHA1_Init(&ctx);
std::vector<uint8_t> buffer(BLOCKSIZE);
for (size_t i = 0; i < rs.count; ++i) {
@@ -1644,10 +1642,11 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[])
return StringValue(strdup(""));
}
- SHA_update(&ctx, buffer.data(), BLOCKSIZE);
+ SHA1_Update(&ctx, buffer.data(), BLOCKSIZE);
}
}
- const uint8_t* digest = SHA_final(&ctx);
+ uint8_t digest[SHA_DIGEST_LENGTH];
+ SHA1_Final(digest, &ctx);
return StringValue(strdup(print_sha1(digest).c_str()));
}
diff --git a/updater/install.cpp b/updater/install.cpp
index be9735595..a2efc0b97 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -34,6 +34,9 @@
#include <linux/xattr.h>
#include <inttypes.h>
+#include <memory>
+#include <vector>
+
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <android-base/stringprintf.h>
@@ -44,7 +47,7 @@
#include "cutils/misc.h"
#include "cutils/properties.h"
#include "edify/expr.h"
-#include "mincrypt/sha.h"
+#include "openssl/sha.h"
#include "minzip/DirUtil.h"
#include "mtdutils/mounts.h"
#include "mtdutils/mtdutils.h"
@@ -92,10 +95,10 @@ void uiPrintf(State* state, const char* format, ...) {
// Take a sha-1 digest and return it as a newly-allocated hex string.
char* PrintSha1(const uint8_t* digest) {
- char* buffer = reinterpret_cast<char*>(malloc(SHA_DIGEST_SIZE*2 + 1));
+ char* buffer = reinterpret_cast<char*>(malloc(SHA_DIGEST_LENGTH*2 + 1));
const char* alphabet = "0123456789abcdef";
size_t i;
- for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
+ for (i = 0; i < SHA_DIGEST_LENGTH; ++i) {
buffer[i*2] = alphabet[(digest[i] >> 4) & 0xf];
buffer[i*2+1] = alphabet[digest[i] & 0xf];
}
@@ -440,8 +443,7 @@ Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) {
for (int i = 0; i < argc; ++i) {
paths[i] = Evaluate(state, argv[i]);
if (paths[i] == NULL) {
- int j;
- for (j = 0; j < i; ++i) {
+ for (int j = 0; j < i; ++j) {
free(paths[j]);
}
free(paths);
@@ -582,13 +584,13 @@ Value* PackageExtractFileFn(const char* name, State* state,
// as the result.
char* zip_path;
+ if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL;
+
Value* v = reinterpret_cast<Value*>(malloc(sizeof(Value)));
v->type = VAL_BLOB;
v->size = -1;
v->data = NULL;
- if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL;
-
ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip;
const ZipEntry* entry = mzFindZipEntry(za, zip_path);
if (entry == NULL) {
@@ -1194,44 +1196,40 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
}
int patchcount = (argc-4) / 2;
- Value** patches = ReadValueVarArgs(state, argc-4, argv+4);
+ std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc-4, argv+4),
+ free);
+ if (!arg_values) {
+ return nullptr;
+ }
+ std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> patch_shas;
+ std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> patches;
+ // Protect values by unique_ptrs first to get rid of memory leak.
+ for (int i = 0; i < patchcount * 2; i += 2) {
+ patch_shas.emplace_back(arg_values.get()[i], FreeValue);
+ patches.emplace_back(arg_values.get()[i+1], FreeValue);
+ }
- int i;
- for (i = 0; i < patchcount; ++i) {
- if (patches[i*2]->type != VAL_STRING) {
+ for (int i = 0; i < patchcount; ++i) {
+ if (patch_shas[i]->type != VAL_STRING) {
ErrorAbort(state, "%s(): sha-1 #%d is not string", name, i);
- break;
+ return nullptr;
}
- if (patches[i*2+1]->type != VAL_BLOB) {
+ if (patches[i]->type != VAL_BLOB) {
ErrorAbort(state, "%s(): patch #%d is not blob", name, i);
- break;
+ return nullptr;
}
}
- if (i != patchcount) {
- for (i = 0; i < patchcount*2; ++i) {
- FreeValue(patches[i]);
- }
- free(patches);
- return NULL;
- }
- char** patch_sha_str = reinterpret_cast<char**>(malloc(patchcount * sizeof(char*)));
- for (i = 0; i < patchcount; ++i) {
- patch_sha_str[i] = patches[i*2]->data;
- patches[i*2]->data = NULL;
- FreeValue(patches[i*2]);
- patches[i] = patches[i*2+1];
+ std::vector<char*> patch_sha_str;
+ std::vector<Value*> patch_ptrs;
+ for (int i = 0; i < patchcount; ++i) {
+ patch_sha_str.push_back(patch_shas[i]->data);
+ patch_ptrs.push_back(patches[i].get());
}
int result = applypatch(source_filename, target_filename,
target_sha1, target_size,
- patchcount, patch_sha_str, patches, NULL);
-
- for (i = 0; i < patchcount; ++i) {
- FreeValue(patches[i]);
- }
- free(patch_sha_str);
- free(patches);
+ patchcount, patch_sha_str.data(), patch_ptrs.data(), NULL);
return StringValue(strdup(result == 0 ? "t" : ""));
}
@@ -1350,24 +1348,27 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
return ErrorAbort(state, "%s() expects at least 1 arg", name);
}
- Value** args = ReadValueVarArgs(state, argc, argv);
- if (args == NULL) {
- return NULL;
+ std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc, argv), free);
+ if (arg_values == nullptr) {
+ return nullptr;
+ }
+ std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> args;
+ for (int i = 0; i < argc; ++i) {
+ args.emplace_back(arg_values.get()[i], FreeValue);
}
if (args[0]->size < 0) {
return StringValue(strdup(""));
}
- uint8_t digest[SHA_DIGEST_SIZE];
- SHA_hash(args[0]->data, args[0]->size, digest);
- FreeValue(args[0]);
+ uint8_t digest[SHA_DIGEST_LENGTH];
+ SHA1(reinterpret_cast<uint8_t*>(args[0]->data), args[0]->size, digest);
if (argc == 1) {
return StringValue(PrintSha1(digest));
}
int i;
- uint8_t* arg_digest = reinterpret_cast<uint8_t*>(malloc(SHA_DIGEST_SIZE));
+ uint8_t arg_digest[SHA_DIGEST_LENGTH];
for (i = 1; i < argc; ++i) {
if (args[i]->type != VAL_STRING) {
printf("%s(): arg %d is not a string; skipping",
@@ -1376,22 +1377,16 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
// Warn about bad args and skip them.
printf("%s(): error parsing \"%s\" as sha-1; skipping",
name, args[i]->data);
- } else if (memcmp(digest, arg_digest, SHA_DIGEST_SIZE) == 0) {
+ } else if (memcmp(digest, arg_digest, SHA_DIGEST_LENGTH) == 0) {
break;
}
- FreeValue(args[i]);
}
if (i >= argc) {
// Didn't match any of the hex strings; return false.
return StringValue(strdup(""));
}
- // Found a match; free all the remaining arguments and return the
- // matched one.
- int j;
- for (j = i+1; j < argc; ++j) {
- FreeValue(args[j]);
- }
- return args[i];
+ // Found a match.
+ return args[i].release();
}
// Read a local file and return its contents (the Value* returned
diff --git a/verifier_test.sh b/verifier_test.sh
deleted file mode 100755
index 4761cef4a..000000000
--- a/verifier_test.sh
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/bin/bash
-#
-# A test suite for recovery's package signature verifier. Run in a
-# client where you have done envsetup, lunch, etc.
-#
-# TODO: find some way to get this run regularly along with the rest of
-# the tests.
-
-EMULATOR_PORT=5580
-DATA_DIR=$ANDROID_BUILD_TOP/bootable/recovery/testdata
-
-WORK_DIR=/data/local/tmp
-
-# set to 0 to use a device instead
-USE_EMULATOR=0
-
-# ------------------------
-
-if [ "$USE_EMULATOR" == 1 ]; then
- emulator -wipe-data -noaudio -no-window -port $EMULATOR_PORT &
- pid_emulator=$!
- ADB="adb -s emulator-$EMULATOR_PORT "
-else
- ADB="adb -d "
-fi
-
-echo "waiting to connect to device"
-$ADB wait-for-device
-
-# run a command on the device; exit with the exit status of the device
-# command.
-run_command() {
- $ADB shell "$@" \; echo \$? | awk '{if (b) {print a}; a=$0; b=1} END {exit a}'
-}
-
-testname() {
- echo
- echo "::: testing $1 :::"
- testname="$1"
-}
-
-fail() {
- echo
- echo FAIL: $testname
- echo
- [ "$open_pid" == "" ] || kill $open_pid
- [ "$pid_emulator" == "" ] || kill $pid_emulator
- exit 1
-}
-
-
-cleanup() {
- # not necessary if we're about to kill the emulator, but nice for
- # running on real devices or already-running emulators.
- run_command rm $WORK_DIR/verifier_test
- run_command rm $WORK_DIR/package.zip
-
- [ "$pid_emulator" == "" ] || kill $pid_emulator
-}
-
-$ADB push $ANDROID_PRODUCT_OUT/system/bin/verifier_test \
- $WORK_DIR/verifier_test
-
-expect_succeed() {
- testname "$1 (should succeed)"
- $ADB push $DATA_DIR/$1 $WORK_DIR/package.zip
- shift
- run_command $WORK_DIR/verifier_test "$@" $WORK_DIR/package.zip || fail
-}
-
-expect_fail() {
- testname "$1 (should fail)"
- $ADB push $DATA_DIR/$1 $WORK_DIR/package.zip
- shift
- run_command $WORK_DIR/verifier_test "$@" $WORK_DIR/package.zip && fail
-}
-
-# not signed at all
-expect_fail unsigned.zip
-# signed in the pre-donut way
-expect_fail jarsigned.zip
-
-# success cases
-expect_succeed otasigned.zip -e3
-expect_succeed otasigned_f4.zip -f4
-expect_succeed otasigned_sha256.zip -e3 -sha256
-expect_succeed otasigned_f4_sha256.zip -f4 -sha256
-expect_succeed otasigned_ecdsa_sha256.zip -ec -sha256
-
-# success with multiple keys
-expect_succeed otasigned.zip -f4 -e3
-expect_succeed otasigned_f4.zip -ec -f4
-expect_succeed otasigned_sha256.zip -ec -e3 -e3 -sha256
-expect_succeed otasigned_f4_sha256.zip -ec -sha256 -e3 -f4 -sha256
-expect_succeed otasigned_ecdsa_sha256.zip -f4 -sha256 -e3 -ec -sha256
-
-# verified against different key
-expect_fail otasigned.zip -f4
-expect_fail otasigned_f4.zip -e3
-expect_fail otasigned_ecdsa_sha256.zip -e3 -sha256
-
-# verified against right key but wrong hash algorithm
-expect_fail otasigned.zip -e3 -sha256
-expect_fail otasigned_f4.zip -f4 -sha256
-expect_fail otasigned_sha256.zip
-expect_fail otasigned_f4_sha256.zip -f4
-expect_fail otasigned_ecdsa_sha256.zip
-
-# various other cases
-expect_fail random.zip
-expect_fail fake-eocd.zip
-expect_fail alter-metadata.zip
-expect_fail alter-footer.zip
-
-# --------------- cleanup ----------------------
-
-cleanup
-
-echo
-echo PASS
-echo