More cpio features

This commit is contained in:
topjohnwu 2017-03-10 04:08:17 +08:00
parent 1e3bcfc8cd
commit 3f3568d8af
11 changed files with 578 additions and 77 deletions

View File

@ -9,7 +9,7 @@ LOCAL_C_INCLUDES := \
jni/ndk-compression/lz4/lib/ \ jni/ndk-compression/lz4/lib/ \
jni/ndk-compression/bzip2/ 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 LOCAL_CFLAGS += -DZLIB_CONST
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)

View File

@ -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) { static void report(const int mode, const char* filename) {
switch(mode) { switch(mode) {
case 0: case 0:
printf("Decompressing to %s\n", filename); printf("Decompressing to [%s]\n\n", filename);
break; break;
default: default:
printf("Compressing to %s\n", filename); printf("Compressing to [%s]\n\n", filename);
break; break;
} }
} }

View File

@ -30,6 +30,9 @@ static void cpio_vec_insert(vector *v, cpio_file *n) {
t = f; t = f;
if (strcmp(f->filename, n->filename) == 0) { if (strcmp(f->filename, n->filename) == 0) {
// Replace, then all is done // Replace, then all is done
free(f->filename);
free(f->data);
free(f);
vec_entry(v)[_i] = n; vec_entry(v)[_i] = n;
return; return;
} else if (strcmp(f->filename, n->filename) > 0) { } 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); 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 // Parse cpio file to a vector of cpio_file
void parse_cpio(const char *filename, vector *v) { static void parse_cpio(const char *filename, vector *v) {
printf("\nLoading cpio: [%s]\n\n", filename); printf("Loading cpio: [%s]\n\n", filename);
int fd = open(filename, O_RDONLY); int fd = open(filename, O_RDONLY);
if (fd < 0) if (fd < 0)
error(1, "Cannot open %s", filename); error(1, "Cannot open %s", filename);
@ -68,6 +75,11 @@ void parse_cpio(const char *filename, vector *v) {
f->filename = malloc(f->namesize); f->filename = malloc(f->namesize);
read(fd, f->filename, f->namesize); read(fd, f->filename, f->namesize);
file_align(fd, 4, 0); file_align(fd, 4, 0);
if (strcmp(f->filename, "TRAILER!!!") == 0 || strcmp(f->filename, ".") == 0) {
free(f->filename);
free(f);
break;
}
if (f->filesize) { if (f->filesize) {
f->data = malloc(f->filesize); f->data = malloc(f->filesize);
read(fd, f->data, 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); vec_push_back(v, f);
} }
close(fd); close(fd);
// Sort by name
vec_sort(v, cpio_compare);
} }
void dump_cpio(const char *filename, vector *v) { static void dump_cpio(const char *filename, vector *v) {
printf("\nDump cpio: [%s]\n\n", filename); printf("Dump cpio: [%s]\n\n", filename);
int fd = open_new(filename); int fd = open_new(filename);
unsigned inode = 300000; unsigned inode = 300000;
char header[111]; char header[111];
@ -109,9 +123,14 @@ void dump_cpio(const char *filename, vector *v) {
file_align(fd, 4, 1); 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 // Free each cpio_file
cpio_file *f; cpio_file *f;
vec_for_each(v, f) { vec_for_each(v, f) {
@ -122,7 +141,7 @@ void cpio_vec_destroy(vector *v) {
vec_destroy(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; cpio_file *f;
vec_for_each(v, f) { vec_for_each(v, f) {
if ((recursive && strncmp(f->filename, entry, strlen(entry)) == 0) 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); cpio_file *f = calloc(sizeof(*f), 1);
f->mode = S_IFDIR | mode; f->mode = S_IFDIR | mode;
f->namesize = strlen(entry) + 1; 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); 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); int fd = open(filename, O_RDONLY);
if (fd < 0) if (fd < 0)
error(1, "Cannot open %s", filename); 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); read(fd, f->data, f->filesize);
cpio_vec_insert(v, f); 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;
}

View File

@ -18,7 +18,7 @@ typedef struct cpio_file {
uint32_t namesize; uint32_t namesize;
// uint32_t check; // uint32_t check;
char *filename; char *filename;
void *data; char *data;
int remove; int remove;
} cpio_file; } cpio_file;

View File

@ -14,6 +14,7 @@
#include <string.h> #include <string.h>
#include "bootimg.h" #include "bootimg.h"
#include "sha1.h"
#define windowBits 15 #define windowBits 15
#define ZLIB_GZIP 16 #define ZLIB_GZIP 16
@ -54,7 +55,11 @@ typedef enum {
NONE, NONE,
RM, RM,
MKDIR, MKDIR,
ADD ADD,
EXTRACT,
TEST,
DMVERITY,
FORCEENCRYPT
} command_t; } command_t;
extern char *SUP_EXT_LIST[SUP_NUM]; extern char *SUP_EXT_LIST[SUP_NUM];
@ -71,6 +76,7 @@ typedef struct vector {
} vector; } vector;
void vec_init(vector *v); void vec_init(vector *v);
void vec_push_back(vector *v, void *p); void vec_push_back(vector *v, void *p);
void vec_sort(vector *v, int (*compar)(const void *, const void *));
void vec_destroy(vector *v); void vec_destroy(vector *v);
#define vec_size(v) (v)->size #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 hexpatch(const char *image, const char *from, const char *to);
void error(int rc, const char *msg, ...); void error(int rc, const char *msg, ...);
void parse_img(unsigned char *orig, size_t size); void parse_img(unsigned char *orig, size_t size);
int cpio_commands(const char *command, int argc, char *argv[]);
void cleanup(); void cleanup();
// Compressions // 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); int decomp(file_t type, const char *to, const unsigned char *from, size_t size);
void decomp_file(char *from); 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 // Utils
void mmap_ro(const char *filename, unsigned char **buf, size_t *size); void mmap_ro(const char *filename, unsigned char **buf, size_t *size);
void mmap_rw(const char *filename, unsigned char **buf, size_t *size); void mmap_rw(const char *filename, unsigned char **buf, size_t *size);

View File

@ -5,36 +5,48 @@
*********************/ *********************/
static void usage(char *arg0) { static void usage(char *arg0) {
fprintf(stderr, "\n");
fprintf(stderr, "%s --unpack <bootimg>\n", arg0); fprintf(stderr, "%s --unpack <bootimg>\n", arg0);
fprintf(stderr, " Unpack <bootimg> to kernel, ramdisk.cpio, (second), (dtb) into the\n current directory\n\n"); fprintf(stderr, " Unpack <bootimg> to kernel, ramdisk.cpio, (second), (dtb) into the\n current directory\n");
fprintf(stderr, "\n");
fprintf(stderr, "%s --repack <origbootimg> [outbootimg]\n", arg0); fprintf(stderr, "%s --repack <origbootimg> [outbootimg]\n", arg0);
fprintf(stderr, " Repack kernel, ramdisk.cpio[.ext], second, dtb... from current directory\n"); 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, " to [outbootimg], or new-boot.img if not specified.\n");
fprintf(stderr, " It will compress ramdisk.cpio with the same method used in <origbootimg>\n"); fprintf(stderr, " It will compress ramdisk.cpio with the same method used in <origbootimg>\n");
fprintf(stderr, " if exists, or attempt to find ramdisk.cpio.[ext], and repack\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 <file> <hexpattern1> <hexpattern2>\n", arg0); fprintf(stderr, "%s --hexpatch <file> <hexpattern1> <hexpattern2>\n", arg0);
fprintf(stderr, " Search <hexpattern1> in <file>, and replace with <hexpattern2>\n\n"); fprintf(stderr, " Search <hexpattern1> in <file>, and replace with <hexpattern2>\n");
fprintf(stderr, "\n");
fprintf(stderr, "%s --cpio-<cmd> <incpio> <outcpio> [flags...] [params...]\n", arg0); fprintf(stderr, "%s --cpio-<cmd> <incpio> [flags...] [params...]\n", arg0);
fprintf(stderr, " Do cpio related cmds to <incpio> and output to <outcpio>\n Supported commands:\n"); fprintf(stderr, " Do cpio related cmds to <incpio> (modifications are done directly)\n Supported commands:\n");
fprintf(stderr, " --cpio-rm [-r] <entry>\n Remove entry from cpio, flag -r to remove recursively\n"); fprintf(stderr, " --cpio-rm <incpio> [-r] <entry>\n Remove entry from cpio, flag -r to remove recursively\n");
fprintf(stderr, " --cpio-mkdir <mode> <entry>\n Create directory as an <entry>\n"); fprintf(stderr, " --cpio-mkdir <incpio> <mode> <entry>\n Create directory as an <entry>\n");
fprintf(stderr, " --cpio-add <mode> <entry> <infile>\n Add <infile> as an <entry>; will replace <entry> if already exists\n"); fprintf(stderr, " --cpio-add <incpio> <mode> <entry> <infile>\n Add <infile> as an <entry>; replaces <entry> if already exists\n");
fprintf(stderr, " e.g: the command to add /tmp/tmpfile as entry init.magisk.rc:\n"); fprintf(stderr, " --cpio-extract <incpio> <entry> <outfile>\n Extract <entry> to <outfile>\n");
fprintf(stderr, " %s --cpio-add <incpio> <outcpio> 0750 init.magisk.rc /tmp/tmpfile\n\n", arg0); fprintf(stderr, " --cpio-test <incpio>\n Return value: 0/not patched 1/Magisk 2/SuperSU\n");
fprintf(stderr, " --cpio-patch-dmverity <incpio>\n Remove dm-verity\n");
fprintf(stderr, " --cpio-patch-forceencrypt <incpio>\n Change forceencrypt flag to encryptable\n");
fprintf(stderr, "\n");
fprintf(stderr, "%s --compress[=method] <file>\n", arg0); fprintf(stderr, "%s --compress[=method] <file>\n", arg0);
fprintf(stderr, " Compress <file> with [method], or gzip if not specified.\n Supported methods: " SUP_LIST "\n\n"); fprintf(stderr, " Compress <file> with [method], or gzip if not specified.\n Supported methods: " SUP_LIST "\n");
fprintf(stderr, "\n");
fprintf(stderr, "%s --decompress <file>\n", arg0); fprintf(stderr, "%s --decompress <file>\n", arg0);
fprintf(stderr, " Auto check file type, and decompress <file> accordingly\n Supported methods: " SUP_LIST "\n\n"); fprintf(stderr, " Auto check file type, and decompress <file> accordingly\n Supported methods: " SUP_LIST "\n");
fprintf(stderr, "\n");
fprintf(stderr, "%s --sha1 <file>\n", arg0);
fprintf(stderr, " Print the SHA1 checksum for <file>\n");
fprintf(stderr, "\n");
fprintf(stderr, "%s --cleanup\n", arg0); 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); exit(1);
} }
@ -49,10 +61,19 @@ void error(int rc, const char *msg, ...) {
} }
int main(int argc, char *argv[]) { 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) { if (argc > 1 && strcmp(argv[1], "--cleanup") == 0) {
cleanup(); 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) { } else if (argc > 2 && strcmp(argv[1], "--unpack") == 0) {
unpack(argv[2]); unpack(argv[2]);
} else if (argc > 2 && strcmp(argv[1], "--repack") == 0) { } else if (argc > 2 && strcmp(argv[1], "--repack") == 0) {
@ -67,47 +88,12 @@ int main(int argc, char *argv[]) {
comp_file(method, argv[2]); comp_file(method, argv[2]);
} else if (argc > 4 && strcmp(argv[1], "--hexpatch") == 0) { } else if (argc > 4 && strcmp(argv[1], "--hexpatch") == 0) {
hexpatch(argv[2], argv[3], argv[4]); hexpatch(argv[2], argv[3], argv[4]);
} else if (argc > 4 && strncmp(argv[1], "--cpio", 6) == 0) { } else if (argc > 2 && strncmp(argv[1], "--cpio", 6) == 0) {
int recursive = 0;
char *command; char *command;
command_t cmd;
command = strchr(argv[1] + 2, '-'); command = strchr(argv[1] + 2, '-');
if (command == NULL) usage(argv[0]); if (command == NULL) usage(argv[0]);
else command++; else ++command;
if (strcmp(command, "rm") == 0) { if (cpio_commands(command, argc - 2, argv + 2)) usage(argv[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 { } else {
usage(argv[0]); usage(argv[0]);
} }

View File

@ -29,7 +29,7 @@ void repack(const char* orig_image, const char* out_image) {
mmap_ro(orig_image, &orig, &size); mmap_ro(orig_image, &orig, &size);
// Parse original image // 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); parse_img(orig, size);
// Create new image // Create new image
@ -105,7 +105,7 @@ void repack(const char* orig_image, const char* out_image) {
} }
// Write header back // 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(); print_info();
lseek(fd, 0, SEEK_SET); lseek(fd, 0, SEEK_SET);
write(fd, &hdr, sizeof(hdr)); write(fd, &hdr, sizeof(hdr));

295
jni/magiskboot/sha1.c Normal file
View File

@ -0,0 +1,295 @@
/*
SHA-1 in C
By Steve Reid <steve@edmweb.com>
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 <stdio.h>
#include <string.h>
/* for uint32_t */
#include <stdint.h>
#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<len; ii+=1)
SHA1Update(&ctx, (const unsigned char*)str + ii, 1);
SHA1Final((unsigned char *)hash_out, &ctx);
hash_out[20] = '\0';
}

44
jni/magiskboot/sha1.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef SHA1_H
#define SHA1_H
/*
SHA-1 in C
By Steve Reid <steve@edmweb.com>
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 */

View File

@ -13,7 +13,7 @@ void unpack(const char* image) {
mmap_ro(image, &orig, &size); mmap_ro(image, &orig, &size);
// Parse image // Parse image
printf("\nParsing boot image: [%s]\n\n", image); printf("Parsing boot image: [%s]\n\n", image);
parse_img(orig, size); parse_img(orig, size);
if (boot_type == CHROMEOS) { if (boot_type == CHROMEOS) {

View File

@ -124,6 +124,7 @@ void print_info() {
default: default:
fprintf(stderr, "Unknown ramdisk format!\n"); fprintf(stderr, "Unknown ramdisk format!\n");
} }
printf("\n");
} }
void cleanup() { void cleanup() {
@ -157,6 +158,10 @@ void vec_push_back(vector *v, void *p) {
++vec_size(v); ++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) { void vec_destroy(vector *v) {
// Will not free each entry! // Will not free each entry!
// Manually free each entry, then call this function // Manually free each entry, then call this function