From 3f3568d8af52c844945c43eca782d8b6a36ffac9 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Fri, 10 Mar 2017 04:08:17 +0800 Subject: [PATCH] More cpio features --- jni/magiskboot/Android.mk | 2 +- jni/magiskboot/compress.c | 4 +- jni/magiskboot/cpio.c | 188 ++++++++++++++++++++++- jni/magiskboot/cpio.h | 2 +- jni/magiskboot/magiskboot.h | 17 +-- jni/magiskboot/main.c | 92 +++++------ jni/magiskboot/repack.c | 4 +- jni/magiskboot/sha1.c | 295 ++++++++++++++++++++++++++++++++++++ jni/magiskboot/sha1.h | 44 ++++++ jni/magiskboot/unpack.c | 2 +- jni/magiskboot/utils.c | 5 + 11 files changed, 578 insertions(+), 77 deletions(-) create mode 100644 jni/magiskboot/sha1.c create mode 100644 jni/magiskboot/sha1.h diff --git a/jni/magiskboot/Android.mk b/jni/magiskboot/Android.mk index 6e32b577e..dd18769ea 100644 --- a/jni/magiskboot/Android.mk +++ b/jni/magiskboot/Android.mk @@ -9,7 +9,7 @@ LOCAL_C_INCLUDES := \ jni/ndk-compression/lz4/lib/ \ jni/ndk-compression/bzip2/ -LOCAL_SRC_FILES := main.c unpack.c repack.c hexpatch.c parseimg.c compress.c utils.c cpio.c +LOCAL_SRC_FILES := main.c unpack.c repack.c hexpatch.c parseimg.c compress.c utils.c cpio.c sha1.c LOCAL_CFLAGS += -DZLIB_CONST include $(BUILD_EXECUTABLE) diff --git a/jni/magiskboot/compress.c b/jni/magiskboot/compress.c index b71dfe1de..89c8eaa75 100644 --- a/jni/magiskboot/compress.c +++ b/jni/magiskboot/compress.c @@ -13,10 +13,10 @@ static void write_file(const int fd, const void *buf, const size_t size, const c static void report(const int mode, const char* filename) { switch(mode) { case 0: - printf("Decompressing to %s\n", filename); + printf("Decompressing to [%s]\n\n", filename); break; default: - printf("Compressing to %s\n", filename); + printf("Compressing to [%s]\n\n", filename); break; } } diff --git a/jni/magiskboot/cpio.c b/jni/magiskboot/cpio.c index 343d72b76..5d678dfe2 100644 --- a/jni/magiskboot/cpio.c +++ b/jni/magiskboot/cpio.c @@ -30,6 +30,9 @@ static void cpio_vec_insert(vector *v, cpio_file *n) { t = f; if (strcmp(f->filename, n->filename) == 0) { // Replace, then all is done + free(f->filename); + free(f->data); + free(f); vec_entry(v)[_i] = n; return; } else if (strcmp(f->filename, n->filename) > 0) { @@ -42,9 +45,13 @@ static void cpio_vec_insert(vector *v, cpio_file *n) { vec_push_back(v, t); } +static int cpio_compare(const void *a, const void *b) { + return strcmp((*(cpio_file **) a)->filename, (*(cpio_file **) b)->filename); +} + // Parse cpio file to a vector of cpio_file -void parse_cpio(const char *filename, vector *v) { - printf("\nLoading cpio: [%s]\n\n", filename); +static void parse_cpio(const char *filename, vector *v) { + printf("Loading cpio: [%s]\n\n", filename); int fd = open(filename, O_RDONLY); if (fd < 0) error(1, "Cannot open %s", filename); @@ -68,6 +75,11 @@ void parse_cpio(const char *filename, vector *v) { f->filename = malloc(f->namesize); read(fd, f->filename, f->namesize); file_align(fd, 4, 0); + if (strcmp(f->filename, "TRAILER!!!") == 0 || strcmp(f->filename, ".") == 0) { + free(f->filename); + free(f); + break; + } if (f->filesize) { f->data = malloc(f->filesize); read(fd, f->data, f->filesize); @@ -76,10 +88,12 @@ void parse_cpio(const char *filename, vector *v) { vec_push_back(v, f); } close(fd); + // Sort by name + vec_sort(v, cpio_compare); } -void dump_cpio(const char *filename, vector *v) { - printf("\nDump cpio: [%s]\n\n", filename); +static void dump_cpio(const char *filename, vector *v) { + printf("Dump cpio: [%s]\n\n", filename); int fd = open_new(filename); unsigned inode = 300000; char header[111]; @@ -109,9 +123,14 @@ void dump_cpio(const char *filename, vector *v) { file_align(fd, 4, 1); } } + // Write trailer + sprintf(header, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", inode++, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 11, 0); + write(fd, header, 110); + write(fd, "TRAILER!!!\0", 11); + file_align(fd, 4, 1); } -void cpio_vec_destroy(vector *v) { +static void cpio_vec_destroy(vector *v) { // Free each cpio_file cpio_file *f; vec_for_each(v, f) { @@ -122,7 +141,7 @@ void cpio_vec_destroy(vector *v) { vec_destroy(v); } -void cpio_rm(int recursive, const char *entry, vector *v) { +static void cpio_rm(int recursive, const char *entry, vector *v) { cpio_file *f; vec_for_each(v, f) { if ((recursive && strncmp(f->filename, entry, strlen(entry)) == 0) @@ -132,7 +151,7 @@ void cpio_rm(int recursive, const char *entry, vector *v) { } } -void cpio_mkdir(mode_t mode, const char *entry, vector *v) { +static void cpio_mkdir(mode_t mode, const char *entry, vector *v) { cpio_file *f = calloc(sizeof(*f), 1); f->mode = S_IFDIR | mode; f->namesize = strlen(entry) + 1; @@ -141,7 +160,7 @@ void cpio_mkdir(mode_t mode, const char *entry, vector *v) { cpio_vec_insert(v, f); } -void cpio_add(mode_t mode, const char *entry, const char *filename, vector *v) { +static void cpio_add(mode_t mode, const char *entry, const char *filename, vector *v) { int fd = open(filename, O_RDONLY); if (fd < 0) error(1, "Cannot open %s", filename); @@ -156,3 +175,156 @@ void cpio_add(mode_t mode, const char *entry, const char *filename, vector *v) { read(fd, f->data, f->filesize); cpio_vec_insert(v, f); } + +static void cpio_test(vector *v) { + int ret = 0; + cpio_file *f; + vec_for_each(v, f) { + if (strcmp(f->filename, "sbin/launch_daemonsu.sh") == 0) { + if (!ret) ret = 2; + } else if (strcmp(f->filename, "magisk") == 0) { + ret = 1; + break; + } + } + cpio_vec_destroy(v); + exit(ret); +} + +static int check_verity_pattern(const char *s) { + int pos = 0; + if (s[0] == ',') ++pos; + if (strncmp(s + pos, "verify", 6) != 0) return -1; + pos += 6; + if (s[pos] == '=') { + while (s[pos] != ' ' && s[pos] != '\n' && s[pos] != ',') ++pos; + } + return pos; +} + +static void cpio_dmverity(vector *v) { + cpio_file *f; + size_t read, write; + int skip; + vec_for_each(v, f) { + if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) { + for (read = 0, write = 0; read < f->filesize; ++read, ++write) { + skip = check_verity_pattern(f->data + read); + if (skip > 0) { + printf("Remove pattern [%.*s] in [%s]\n", (int) skip, f->data + read, f->filename); + read += skip; + } + f->data[write] = f->data[read]; + } + f->filesize = write; + } else if (strcmp(f->filename, "verity_key") == 0) { + f->remove = 1; + break; + } + } + printf("\n"); +} + +static void cpio_forceencrypt(vector *v) { + cpio_file *f; + size_t read, write; + #define ENCRYPT_LIST_SIZE 2 + const char *ENCRYPT_LIST[ENCRYPT_LIST_SIZE] = { "forceencrypt", "forcefdeorfbe" }; + vec_for_each(v, f) { + if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) { + for (read = 0, write = 0; read < f->filesize; ++read, ++write) { + for (int i = 0 ; i < ENCRYPT_LIST_SIZE; ++i) { + if (strncmp(f->data + read, ENCRYPT_LIST[i], strlen(ENCRYPT_LIST[i])) == 0) { + memcpy(f->data + write, "encryptable", 11); + printf("Replace [%s] with [%s] in [%s]\n", ENCRYPT_LIST[i], "encryptable", f->filename); + write += 11; + read += strlen(ENCRYPT_LIST[i]); + break; + } + } + f->data[write] = f->data[read]; + } + f->filesize = write; + } + } + printf("\n"); +} + +static void cpio_extract(const char *entry, const char *filename, vector *v) { + cpio_file *f; + vec_for_each(v, f) { + if (strcmp(f->filename, entry) == 0 && S_ISREG(f->mode)) { + printf("Extracting [%s] to [%s]\n\n", entry, filename); + int fd = open_new(filename); + write(fd, f->data, f->filesize); + fchmod(fd, f->mode); + fchown(fd, f->uid, f->gid); + close(fd); + return; + } + } + error(1, "Cannot find the file entry [%s]", entry); +} + +int cpio_commands(const char *command, int argc, char *argv[]) { + int recursive = 0; + command_t cmd; + char *incpio = argv[0]; + ++argv; + --argc; + if (strcmp(command, "test") == 0) { + cmd = TEST; + } else if (strcmp(command, "patch-dmverity") == 0) { + cmd = DMVERITY; + } else if (strcmp(command, "patch-forceencrypt") == 0) { + cmd = FORCEENCRYPT; + } else if (argc == 2 && strcmp(command, "extract") == 0) { + cmd = EXTRACT; + } else if (argc > 0 && strcmp(command, "rm") == 0) { + cmd = RM; + if (argc == 2 && strcmp(argv[0], "-r") == 0) { + recursive = 1; + ++argv; + --argc; + } + } else if (argc == 2 && strcmp(command, "mkdir") == 0) { + cmd = MKDIR; + } else if (argc == 3 && strcmp(command, "add") == 0) { + cmd = ADD; + } else { + cmd = NONE; + return 1; + } + vector v; + vec_init(&v); + parse_cpio(incpio, &v); + switch(cmd) { + case TEST: + cpio_test(&v); + break; + case DMVERITY: + cpio_dmverity(&v); + break; + case FORCEENCRYPT: + cpio_forceencrypt(&v); + break; + case EXTRACT: + cpio_extract(argv[0], argv[1], &v); + break; + case RM: + cpio_rm(recursive, argv[0], &v); + break; + case MKDIR: + cpio_mkdir(strtoul(argv[0], NULL, 8), argv[1], &v); + break; + case ADD: + cpio_add(strtoul(argv[0], NULL, 8), argv[1], argv[2], &v); + break; + default: + // Never happen + break; + } + dump_cpio(incpio, &v); + cpio_vec_destroy(&v); + return 0; +} diff --git a/jni/magiskboot/cpio.h b/jni/magiskboot/cpio.h index 32a6935f0..6f8cda49b 100644 --- a/jni/magiskboot/cpio.h +++ b/jni/magiskboot/cpio.h @@ -18,7 +18,7 @@ typedef struct cpio_file { uint32_t namesize; // uint32_t check; char *filename; - void *data; + char *data; int remove; } cpio_file; diff --git a/jni/magiskboot/magiskboot.h b/jni/magiskboot/magiskboot.h index 81ee859ee..18f9572db 100644 --- a/jni/magiskboot/magiskboot.h +++ b/jni/magiskboot/magiskboot.h @@ -14,6 +14,7 @@ #include #include "bootimg.h" +#include "sha1.h" #define windowBits 15 #define ZLIB_GZIP 16 @@ -54,7 +55,11 @@ typedef enum { NONE, RM, MKDIR, - ADD + ADD, + EXTRACT, + TEST, + DMVERITY, + FORCEENCRYPT } command_t; extern char *SUP_EXT_LIST[SUP_NUM]; @@ -71,6 +76,7 @@ typedef struct vector { } vector; void vec_init(vector *v); void vec_push_back(vector *v, void *p); +void vec_sort(vector *v, int (*compar)(const void *, const void *)); void vec_destroy(vector *v); #define vec_size(v) (v)->size @@ -93,6 +99,7 @@ void repack(const char* orig_image, const char* out_image); void hexpatch(const char *image, const char *from, const char *to); void error(int rc, const char *msg, ...); void parse_img(unsigned char *orig, size_t size); +int cpio_commands(const char *command, int argc, char *argv[]); void cleanup(); // Compressions @@ -105,14 +112,6 @@ void comp_file(const char *method, const char *from); int decomp(file_t type, const char *to, const unsigned char *from, size_t size); void decomp_file(char *from); -// CPIO -void parse_cpio(const char *filename, vector *v); -void dump_cpio(const char *filename, vector *v); -void cpio_vec_destroy(vector *v); -void cpio_rm(int recursive, const char *entry, vector *v); -void cpio_mkdir(mode_t mode, const char *entry, vector *v); -void cpio_add(mode_t mode, const char *entry, const char *filename, vector *v); - // Utils void mmap_ro(const char *filename, unsigned char **buf, size_t *size); void mmap_rw(const char *filename, unsigned char **buf, size_t *size); diff --git a/jni/magiskboot/main.c b/jni/magiskboot/main.c index 7d55c9699..d25105cfc 100644 --- a/jni/magiskboot/main.c +++ b/jni/magiskboot/main.c @@ -5,36 +5,48 @@ *********************/ static void usage(char *arg0) { - fprintf(stderr, "\n"); fprintf(stderr, "%s --unpack \n", arg0); - fprintf(stderr, " Unpack to kernel, ramdisk.cpio, (second), (dtb) into the\n current directory\n\n"); + fprintf(stderr, " Unpack to kernel, ramdisk.cpio, (second), (dtb) into the\n current directory\n"); + fprintf(stderr, "\n"); fprintf(stderr, "%s --repack [outbootimg]\n", arg0); fprintf(stderr, " Repack kernel, ramdisk.cpio[.ext], second, dtb... from current directory\n"); fprintf(stderr, " to [outbootimg], or new-boot.img if not specified.\n"); fprintf(stderr, " It will compress ramdisk.cpio with the same method used in \n"); fprintf(stderr, " if exists, or attempt to find ramdisk.cpio.[ext], and repack\n"); - fprintf(stderr, " directly with the compressed ramdisk file\n\n"); + fprintf(stderr, " directly with the compressed ramdisk file\n"); + fprintf(stderr, "\n"); fprintf(stderr, "%s --hexpatch \n", arg0); - fprintf(stderr, " Search in , and replace with \n\n"); + fprintf(stderr, " Search in , and replace with \n"); + fprintf(stderr, "\n"); - fprintf(stderr, "%s --cpio- [flags...] [params...]\n", arg0); - fprintf(stderr, " Do cpio related cmds to and output to \n Supported commands:\n"); - fprintf(stderr, " --cpio-rm [-r] \n Remove entry from cpio, flag -r to remove recursively\n"); - fprintf(stderr, " --cpio-mkdir \n Create directory as an \n"); - fprintf(stderr, " --cpio-add \n Add as an ; will replace if already exists\n"); - fprintf(stderr, " e.g: the command to add /tmp/tmpfile as entry init.magisk.rc:\n"); - fprintf(stderr, " %s --cpio-add 0750 init.magisk.rc /tmp/tmpfile\n\n", arg0); + fprintf(stderr, "%s --cpio- [flags...] [params...]\n", arg0); + fprintf(stderr, " Do cpio related cmds to (modifications are done directly)\n Supported commands:\n"); + fprintf(stderr, " --cpio-rm [-r] \n Remove entry from cpio, flag -r to remove recursively\n"); + fprintf(stderr, " --cpio-mkdir \n Create directory as an \n"); + fprintf(stderr, " --cpio-add \n Add as an ; replaces if already exists\n"); + fprintf(stderr, " --cpio-extract \n Extract to \n"); + fprintf(stderr, " --cpio-test \n Return value: 0/not patched 1/Magisk 2/SuperSU\n"); + fprintf(stderr, " --cpio-patch-dmverity \n Remove dm-verity\n"); + fprintf(stderr, " --cpio-patch-forceencrypt \n Change forceencrypt flag to encryptable\n"); + fprintf(stderr, "\n"); fprintf(stderr, "%s --compress[=method] \n", arg0); - fprintf(stderr, " Compress with [method], or gzip if not specified.\n Supported methods: " SUP_LIST "\n\n"); + fprintf(stderr, " Compress with [method], or gzip if not specified.\n Supported methods: " SUP_LIST "\n"); + fprintf(stderr, "\n"); fprintf(stderr, "%s --decompress \n", arg0); - fprintf(stderr, " Auto check file type, and decompress accordingly\n Supported methods: " SUP_LIST "\n\n"); + fprintf(stderr, " Auto check file type, and decompress accordingly\n Supported methods: " SUP_LIST "\n"); + fprintf(stderr, "\n"); + + fprintf(stderr, "%s --sha1 \n", arg0); + fprintf(stderr, " Print the SHA1 checksum for \n"); + fprintf(stderr, "\n"); fprintf(stderr, "%s --cleanup\n", arg0); - fprintf(stderr, " Cleanup the current working directory\n\n"); + fprintf(stderr, " Cleanup the current working directory\n"); + fprintf(stderr, "\n"); exit(1); } @@ -49,10 +61,19 @@ void error(int rc, const char *msg, ...) { } int main(int argc, char *argv[]) { - printf("MagiskBoot (by topjohnwu) - Boot Image Modification Tool\n"); + printf("MagiskBoot (by topjohnwu) - Boot Image Modification Tool\n\n"); if (argc > 1 && strcmp(argv[1], "--cleanup") == 0) { cleanup(); + } else if (argc > 2 && strcmp(argv[1], "--sha1") == 0) { + char sha1[21], *buf; + size_t size; + mmap_ro(argv[2], (unsigned char **) &buf, &size); + SHA1(sha1, buf, size); + for (int i = 0; i < 20; ++i) + printf("%02x", sha1[i]); + printf("\n"); + munmap(buf, size); } else if (argc > 2 && strcmp(argv[1], "--unpack") == 0) { unpack(argv[2]); } else if (argc > 2 && strcmp(argv[1], "--repack") == 0) { @@ -67,47 +88,12 @@ int main(int argc, char *argv[]) { comp_file(method, argv[2]); } else if (argc > 4 && strcmp(argv[1], "--hexpatch") == 0) { hexpatch(argv[2], argv[3], argv[4]); - } else if (argc > 4 && strncmp(argv[1], "--cpio", 6) == 0) { - int recursive = 0; + } else if (argc > 2 && strncmp(argv[1], "--cpio", 6) == 0) { char *command; - command_t cmd; command = strchr(argv[1] + 2, '-'); if (command == NULL) usage(argv[0]); - else command++; - if (strcmp(command, "rm") == 0) { - cmd = RM; - if (argc > 5 && strcmp(argv[4], "-r") == 0) { - recursive = 1; - argv[4] = argv[5]; - argc--; - } - } else if (argc > 5 && strcmp(command, "mkdir") == 0) { - cmd = MKDIR; - } else if (argc > 6 && strcmp(command, "add") == 0) { - cmd = ADD; - } else { - cmd = NONE; - usage(argv[0]); - } - vector v; - vec_init(&v); - parse_cpio(argv[2], &v); - switch(cmd) { - case RM: - cpio_rm(recursive, argv[4], &v); - break; - case MKDIR: - cpio_mkdir(strtoul(argv[4], NULL, 8), argv[5], &v); - break; - case ADD: - cpio_add(strtoul(argv[4], NULL, 8), argv[5], argv[6], &v); - break; - default: - // Never happen - break; - } - dump_cpio(argv[3], &v); - cpio_vec_destroy(&v); + else ++command; + if (cpio_commands(command, argc - 2, argv + 2)) usage(argv[0]); } else { usage(argv[0]); } diff --git a/jni/magiskboot/repack.c b/jni/magiskboot/repack.c index b2ce58165..a4e6bc1cb 100644 --- a/jni/magiskboot/repack.c +++ b/jni/magiskboot/repack.c @@ -29,7 +29,7 @@ void repack(const char* orig_image, const char* out_image) { mmap_ro(orig_image, &orig, &size); // Parse original image - printf("\nParsing boot image: [%s]\n\n", orig_image); + printf("Parsing boot image: [%s]\n\n", orig_image); parse_img(orig, size); // Create new image @@ -105,7 +105,7 @@ void repack(const char* orig_image, const char* out_image) { } // Write header back - printf("\nRepack to boot image: [%s]\n\n", out_image); + printf("Repack to boot image: [%s]\n\n", out_image); print_info(); lseek(fd, 0, SEEK_SET); write(fd, &hdr, sizeof(hdr)); diff --git a/jni/magiskboot/sha1.c b/jni/magiskboot/sha1.c new file mode 100644 index 000000000..d49304984 --- /dev/null +++ b/jni/magiskboot/sha1.c @@ -0,0 +1,295 @@ +/* +SHA-1 in C +By Steve Reid +100% Public Domain + +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */ +/* #define SHA1HANDSOFF * Copies data before messing with it. */ + +#define SHA1HANDSOFF + +#include +#include + +/* for uint32_t */ +#include + +#include "sha1.h" + + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#elif BYTE_ORDER == BIG_ENDIAN +#define blk0(i) block->l[i] +#else +#error "Endianness not defined!" +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void SHA1Transform( + uint32_t state[5], + const unsigned char buffer[64] +) +{ + uint32_t a, b, c, d, e; + + typedef union + { + unsigned char c[64]; + uint32_t l[16]; + } CHAR64LONG16; + +#ifdef SHA1HANDSOFF + CHAR64LONG16 block[1]; /* use array to appear as a pointer */ + + memcpy(block, buffer, 64); +#else + /* The following had better never be used because it causes the + * pointer-to-const buffer to be cast into a pointer to non-const. + * And the result is written through. I threw a "const" in, hoping + * this will cause a diagnostic. + */ + CHAR64LONG16 *block = (const CHAR64LONG16 *) buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a, b, c, d, e, 0); + R0(e, a, b, c, d, 1); + R0(d, e, a, b, c, 2); + R0(c, d, e, a, b, 3); + R0(b, c, d, e, a, 4); + R0(a, b, c, d, e, 5); + R0(e, a, b, c, d, 6); + R0(d, e, a, b, c, 7); + R0(c, d, e, a, b, 8); + R0(b, c, d, e, a, 9); + R0(a, b, c, d, e, 10); + R0(e, a, b, c, d, 11); + R0(d, e, a, b, c, 12); + R0(c, d, e, a, b, 13); + R0(b, c, d, e, a, 14); + R0(a, b, c, d, e, 15); + R1(e, a, b, c, d, 16); + R1(d, e, a, b, c, 17); + R1(c, d, e, a, b, 18); + R1(b, c, d, e, a, 19); + R2(a, b, c, d, e, 20); + R2(e, a, b, c, d, 21); + R2(d, e, a, b, c, 22); + R2(c, d, e, a, b, 23); + R2(b, c, d, e, a, 24); + R2(a, b, c, d, e, 25); + R2(e, a, b, c, d, 26); + R2(d, e, a, b, c, 27); + R2(c, d, e, a, b, 28); + R2(b, c, d, e, a, 29); + R2(a, b, c, d, e, 30); + R2(e, a, b, c, d, 31); + R2(d, e, a, b, c, 32); + R2(c, d, e, a, b, 33); + R2(b, c, d, e, a, 34); + R2(a, b, c, d, e, 35); + R2(e, a, b, c, d, 36); + R2(d, e, a, b, c, 37); + R2(c, d, e, a, b, 38); + R2(b, c, d, e, a, 39); + R3(a, b, c, d, e, 40); + R3(e, a, b, c, d, 41); + R3(d, e, a, b, c, 42); + R3(c, d, e, a, b, 43); + R3(b, c, d, e, a, 44); + R3(a, b, c, d, e, 45); + R3(e, a, b, c, d, 46); + R3(d, e, a, b, c, 47); + R3(c, d, e, a, b, 48); + R3(b, c, d, e, a, 49); + R3(a, b, c, d, e, 50); + R3(e, a, b, c, d, 51); + R3(d, e, a, b, c, 52); + R3(c, d, e, a, b, 53); + R3(b, c, d, e, a, 54); + R3(a, b, c, d, e, 55); + R3(e, a, b, c, d, 56); + R3(d, e, a, b, c, 57); + R3(c, d, e, a, b, 58); + R3(b, c, d, e, a, 59); + R4(a, b, c, d, e, 60); + R4(e, a, b, c, d, 61); + R4(d, e, a, b, c, 62); + R4(c, d, e, a, b, 63); + R4(b, c, d, e, a, 64); + R4(a, b, c, d, e, 65); + R4(e, a, b, c, d, 66); + R4(d, e, a, b, c, 67); + R4(c, d, e, a, b, 68); + R4(b, c, d, e, a, 69); + R4(a, b, c, d, e, 70); + R4(e, a, b, c, d, 71); + R4(d, e, a, b, c, 72); + R4(c, d, e, a, b, 73); + R4(b, c, d, e, a, 74); + R4(a, b, c, d, e, 75); + R4(e, a, b, c, d, 76); + R4(d, e, a, b, c, 77); + R4(c, d, e, a, b, 78); + R4(b, c, d, e, a, 79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +#ifdef SHA1HANDSOFF + memset(block, '\0', sizeof(block)); +#endif +} + + +/* SHA1Init - Initialize new context */ + +void SHA1Init( + SHA1_CTX * context +) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void SHA1Update( + SHA1_CTX * context, + const unsigned char *data, + uint32_t len +) +{ + uint32_t i; + + uint32_t j; + + j = context->count[0]; + if ((context->count[0] += len << 3) < j) + context->count[1]++; + context->count[1] += (len >> 29); + j = (j >> 3) & 63; + if ((j + len) > 63) + { + memcpy(&context->buffer[j], data, (i = 64 - j)); + SHA1Transform(context->state, context->buffer); + for (; i + 63 < len; i += 64) + { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else + i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* Add padding and return the message digest. */ + +void SHA1Final( + unsigned char digest[20], + SHA1_CTX * context +) +{ + unsigned i; + + unsigned char finalcount[8]; + + unsigned char c; + +#if 0 /* untested "improvement" by DHR */ + /* Convert context->count to a sequence of bytes + * in finalcount. Second element first, but + * big-endian order within element. + * But we do it all backwards. + */ + unsigned char *fcp = &finalcount[8]; + + for (i = 0; i < 2; i++) + { + uint32_t t = context->count[i]; + + int j; + + for (j = 0; j < 4; t >>= 8, j++) + *--fcp = (unsigned char) t} +#else + for (i = 0; i < 8; i++) + { + finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ + } +#endif + c = 0200; + SHA1Update(context, &c, 1); + while ((context->count[0] & 504) != 448) + { + c = 0000; + SHA1Update(context, &c, 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + for (i = 0; i < 20; i++) + { + digest[i] = (unsigned char) + ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); + } + /* Wipe variables */ + memset(context, '\0', sizeof(*context)); + memset(&finalcount, '\0', sizeof(finalcount)); +} + +void SHA1( + char *hash_out, + const char *str, + int len) +{ + SHA1_CTX ctx; + unsigned int ii; + + SHA1Init(&ctx); + for (ii=0; ii + 100% Public Domain + */ + +#include "stdint.h" + +typedef struct +{ + uint32_t state[5]; + uint32_t count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +void SHA1Transform( + uint32_t state[5], + const unsigned char buffer[64] + ); + +void SHA1Init( + SHA1_CTX * context + ); + +void SHA1Update( + SHA1_CTX * context, + const unsigned char *data, + uint32_t len + ); + +void SHA1Final( + unsigned char digest[20], + SHA1_CTX * context + ); + +void SHA1( + char *hash_out, + const char *str, + int len); + +#endif /* SHA1_H */ diff --git a/jni/magiskboot/unpack.c b/jni/magiskboot/unpack.c index 28be1fc62..18c1c9de8 100644 --- a/jni/magiskboot/unpack.c +++ b/jni/magiskboot/unpack.c @@ -13,7 +13,7 @@ void unpack(const char* image) { mmap_ro(image, &orig, &size); // Parse image - printf("\nParsing boot image: [%s]\n\n", image); + printf("Parsing boot image: [%s]\n\n", image); parse_img(orig, size); if (boot_type == CHROMEOS) { diff --git a/jni/magiskboot/utils.c b/jni/magiskboot/utils.c index 8532b8861..3acc60eea 100644 --- a/jni/magiskboot/utils.c +++ b/jni/magiskboot/utils.c @@ -124,6 +124,7 @@ void print_info() { default: fprintf(stderr, "Unknown ramdisk format!\n"); } + printf("\n"); } void cleanup() { @@ -157,6 +158,10 @@ void vec_push_back(vector *v, void *p) { ++vec_size(v); } +void vec_sort(vector *v, int (*compar)(const void *, const void *)) { + qsort(vec_entry(v), vec_size(v), sizeof(void*), compar); +} + void vec_destroy(vector *v) { // Will not free each entry! // Manually free each entry, then call this function