diff --git a/kernel/base/predata.c b/kernel/base/predata.c index 584dea27..757b3815 100644 --- a/kernel/base/predata.c +++ b/kernel/base/predata.c @@ -34,7 +34,7 @@ int auth_superkey(const char *key) sha256_init(&ctx); sha256_update(&ctx, (const BYTE *)key, lib_strnlen(key, SUPER_KEY_LEN)); sha256_final(&ctx, hash); - int len = SHA256_BLOCK_SIZE > SUPER_KEY_HASH_LEN ? SUPER_KEY_HASH_LEN : SHA256_BLOCK_SIZE; + int len = SHA256_BLOCK_SIZE > ROOT_SUPER_KEY_HASH_LEN ? ROOT_SUPER_KEY_HASH_LEN : SHA256_BLOCK_SIZE; rc = lib_memcmp(superkey_hash, hash, len); return rc; diff --git a/kernel/base/setup1.S b/kernel/base/setup1.S index 2f4a8e36..ba2b15ab 100644 --- a/kernel/base/setup1.S +++ b/kernel/base/setup1.S @@ -103,10 +103,10 @@ start_prepare: mov x2, #SUPER_KEY_LEN bl memcpy8 - // memcpy(start_preset.superkey_hash, setup_preset.superkey_hash, SUPER_KEY_HASH_LEN); + // memcpy(start_preset.superkey_hash, setup_preset.superkey_hash, ROOT_SUPER_KEY_HASH_LEN); add x0, x11, #start_superkey_hash_offset; add x1, x10, #setup_superkey_hash_offset - mov x2, #SUPER_KEY_HASH_LEN + mov x2, #ROOT_SUPER_KEY_HASH_LEN bl memcpy8 // memcpy(&start_preset.patch_symbol, &setup_preset.patch_symbol, sizeof(header.patch_symbol)); diff --git a/kernel/base/start.h b/kernel/base/start.h index e48b9b68..48f510b3 100644 --- a/kernel/base/start.h +++ b/kernel/base/start.h @@ -23,7 +23,7 @@ typedef struct int64_t map_backup_len; uint8_t map_backup[MAP_MAX_SIZE]; uint8_t superkey[SUPER_KEY_LEN]; - uint8_t superkey_hash[SUPER_KEY_HASH_LEN]; + uint8_t superkey_hash[ROOT_SUPER_KEY_HASH_LEN]; patch_symbol_t patch_symbol; } start_preset_t; #else @@ -39,7 +39,7 @@ typedef struct #define start_map_backup_offset (start_map_backup_len_offset + 8) #define start_superkey_offset (start_map_backup_offset + MAP_MAX_SIZE) #define start_superkey_hash_offset (start_superkey_offset + SUPER_KEY_LEN) -#define start_patch_symbol_offset (start_superkey_hash_offset + SUPER_KEY_HASH_LEN) +#define start_patch_symbol_offset (start_superkey_hash_offset + ROOT_SUPER_KEY_HASH_LEN) #define start_patch_extra_offset_offset (start_patch_symbol_offset + PATCH_SYMBOL_LEN) #define start_patch_extra_size_offset (start_patch_extra_offset_offset + 8) #define start_end (start_patch_extra_size_offset + 8) diff --git a/kernel/include/preset.h b/kernel/include/preset.h index 79cb056d..4acba211 100644 --- a/kernel/include/preset.h +++ b/kernel/include/preset.h @@ -14,7 +14,7 @@ #define MAGIC_LEN 0x8 #define KP_HEADER_SIZE 0x40 #define SUPER_KEY_LEN 0x40 -#define SUPER_KEY_HASH_LEN 0x20 +#define ROOT_SUPER_KEY_HASH_LEN 0x20 #define SETUP_PRESERVE_LEN 0x40 #define HDR_BACKUP_SIZE 0x8 #define COMPILE_TIME_LEN 0x18 @@ -234,7 +234,7 @@ typedef struct _setup_preset_t map_symbol_t map_symbol; uint8_t header_backup[HDR_BACKUP_SIZE]; uint8_t superkey[SUPER_KEY_LEN]; - uint8_t superkey_hash[SUPER_KEY_HASH_LEN]; + uint8_t superkey_hash[ROOT_SUPER_KEY_HASH_LEN]; uint8_t __[SETUP_PRESERVE_LEN]; patch_symbol_t patch_symbol; char additional[ADDITIONAL_LEN]; @@ -257,7 +257,7 @@ typedef struct _setup_preset_t #define setup_header_backup_offset (setup_map_symbol_offset + MAP_SYMBOL_SIZE) #define setup_superkey_offset (setup_header_backup_offset + HDR_BACKUP_SIZE) #define setup_superkey_hash_offset (setup_superkey_offset + SUPER_KEY_LEN) -#define setup_patch_symbol_offset (setup_superkey_hash_offset + SUPER_KEY_HASH_LEN + SETUP_PRESERVE_LEN) +#define setup_patch_symbol_offset (setup_superkey_hash_offset + ROOT_SUPER_KEY_HASH_LEN + SETUP_PRESERVE_LEN) #define setup_end (setup_patch_symbol_offset + PATCH_SYMBOL_LEN) #endif diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index 96112011..2d04598b 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -173,7 +173,7 @@ static long supercall(long cmd, long arg1, long arg2, long arg3, long arg4) break; case SUPERCALL_SKEY_RAND: break; - case SUPERCALL_SKEY_TRY_HASH_AUTH: + case SUPERCALL_SKEY_ROOT_ENABLE: break; } diff --git a/kernel/patch/include/uapi/scdefs.h b/kernel/patch/include/uapi/scdefs.h index 070abe34..7662b5a6 100644 --- a/kernel/patch/include/uapi/scdefs.h +++ b/kernel/patch/include/uapi/scdefs.h @@ -29,7 +29,7 @@ static inline long hash_key(const char *key) #define SUPERCALL_SKEY_GET 0x100a #define SUPERCALL_SKEY_SET 0x100b #define SUPERCALL_SKEY_RAND 0x100c -#define SUPERCALL_SKEY_TRY_HASH_AUTH 0x100d +#define SUPERCALL_SKEY_ROOT_ENABLE 0x100d #define SUPERCALL_SU 0x1010 #define SUPERCALL_SU_TASK 0x1011 // syscall(__NR_gettid) diff --git a/tools/kptools.c b/tools/kptools.c index 57ef8d90..af14d8d2 100644 --- a/tools/kptools.c +++ b/tools/kptools.c @@ -51,7 +51,7 @@ void print_usage(char **argv) " -i, --image PATH Kernel image path.\n" " -k, --kpimg PATH KernelPatch image path.\n" " -s, --skey KEY Set the superkey and save it directly in the boot.img.\n" - " -S, --skey-hash KEY Consistent with (-s), but store the hash value of skey.\n" + " -S, --root-skey KEY Set the root-superkey that uses hash verification, and the superkey can be changed dynamically.\n" " -o, --out PATH Patched image path.\n" " -a --addition KEY=VALUE Add additional information.\n" @@ -106,7 +106,7 @@ int main(int argc, char *argv[]) char *out_path = NULL; char *superkey = NULL; char *kpatch_path = NULL; - bool do_hash_key = false; + bool root_skey = false; int additional_num = 0; const char *additional[16] = { 0 }; @@ -138,7 +138,7 @@ int main(int argc, char *argv[]) kpimg_path = optarg; break; case 'S': - do_hash_key = true; + root_skey = true; case 's': superkey = optarg; break; @@ -190,7 +190,7 @@ int main(int argc, char *argv[]) else fprintf(stdout, "%x\n", version); } else if (cmd == 'p') { - ret = patch_update_img(kimg_path, kpimg_path, out_path, superkey, do_hash_key, additional, kpatch_path, + ret = patch_update_img(kimg_path, kpimg_path, out_path, superkey, root_skey, additional, kpatch_path, extra_configs, extra_config_num); } else if (cmd == 'd') { ret = dump_kallsym(kimg_path); diff --git a/tools/patch.c b/tools/patch.c index 47e112ff..1d38e253 100644 --- a/tools/patch.c +++ b/tools/patch.c @@ -150,8 +150,8 @@ void print_preset_info(preset_t *preset) // todo: remove compat version if (ver_num > 0xa04) { - char *hexstr = bytes_to_hexstr(setup->superkey_hash, SUPER_KEY_HASH_LEN); - fprintf(stdout, "superkey_hash=%s\n", hexstr); + char *hexstr = bytes_to_hexstr(setup->superkey_hash, ROOT_SUPER_KEY_HASH_LEN); + fprintf(stdout, "root_superkey=%s\n", hexstr); free(hexstr); } @@ -159,7 +159,7 @@ void print_preset_info(preset_t *preset) char *addition = setup->additional; // todo: remove compat version if (ver_num <= 0xa04) { - addition -= (SUPER_KEY_HASH_LEN + SETUP_PRESERVE_LEN); + addition -= (ROOT_SUPER_KEY_HASH_LEN + SETUP_PRESERVE_LEN); } char *pos = addition; while (pos < addition + ADDITIONAL_LEN) { @@ -337,7 +337,7 @@ static void extra_append(char *kimg, const void *data, int len, int *offset) } int patch_update_img(const char *kimg_path, const char *kpimg_path, const char *out_path, const char *superkey, - bool hash_key, const char **additional, const char *kpatch_path, extra_config_t *extra_configs, + bool root_key, const char **additional, const char *kpatch_path, extra_config_t *extra_configs, int extra_config_num) { set_log_enable(true); @@ -547,11 +547,11 @@ int patch_update_img(const char *kimg_path, const char *kpimg_path, const char * fillin_patch_symbol(&kallsym, kallsym_kimg, ori_kimg_len, &setup->patch_symbol, kinfo->is_be, 0); // superkey - if (!hash_key) { + if (!root_key) { tools_logi("superkey: %s\n", superkey); strncpy((char *)setup->superkey, superkey, SUPER_KEY_LEN - 1); } else { - int len = SHA256_BLOCK_SIZE > SUPER_KEY_HASH_LEN ? SUPER_KEY_HASH_LEN : SHA256_BLOCK_SIZE; + int len = SHA256_BLOCK_SIZE > ROOT_SUPER_KEY_HASH_LEN ? ROOT_SUPER_KEY_HASH_LEN : SHA256_BLOCK_SIZE; BYTE buf[SHA256_BLOCK_SIZE]; SHA256_CTX ctx; sha256_init(&ctx); @@ -559,7 +559,7 @@ int patch_update_img(const char *kimg_path, const char *kpimg_path, const char * sha256_final(&ctx, buf); memcpy(setup->superkey_hash, buf, len); char *hexstr = bytes_to_hexstr(setup->superkey_hash, len); - tools_logi("superkey hash: %s\n", hexstr); + tools_logi("root superkey hash: %s\n", hexstr); free(hexstr); } diff --git a/tools/patch.h b/tools/patch.h index 0a43bdbe..d2443e67 100644 --- a/tools/patch.h +++ b/tools/patch.h @@ -69,7 +69,7 @@ uint32_t get_kpimg_version(const char *kpimg_path); int extra_str_type(const char *extra_str); const char *extra_type_str(extra_item_type extra_type); int patch_update_img(const char *kimg_path, const char *kpimg_path, const char *out_path, const char *superkey, - bool hash_key, const char **additional, const char *kpatch_path, extra_config_t *extra_configs, + bool root_skey, const char **additional, const char *kpatch_path, extra_config_t *extra_configs, int extra_config_num); int unpatch_img(const char *kimg_path, const char *out_path); int reset_key(const char *kimg_path, const char *out_path, const char *key); diff --git a/user/kpatch.c b/user/kpatch.c index 33d8ae7d..2325ce38 100644 --- a/user/kpatch.c +++ b/user/kpatch.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "supercall.h" @@ -59,3 +60,83 @@ int __test(const char *key) // return __sc_test(key, 0, 0, 0); return sc_pid_virt_to_phys(key, getpid(), (unsigned long)__test); } + +extern const char program_name[]; +extern const char *key; + +static void usage(int status) +{ + if (status != EXIT_SUCCESS) + fprintf(stderr, "Try `%s help' for more information.\n", program_name); + else { + printf("Usage: %s [ARG]...\n\n", program_name); + fprintf(stdout, "" + "KernelPatch SuperKey manager.\n" + "\n" + "help Print this help message. \n" + "get Print current superkey.\n" + "set Set current superkey.\n" + "rand Randomize current superkey.\n" + "root [enable|disable] Whether to use hash to verify the root superkey.\n" + ""); + } + exit(status); +} + +int skey_main(int argc, char **argv) +{ + if (argc < 2) usage(EXIT_FAILURE); + + const char *scmd = argv[1]; + int cmd = -1; + + struct + { + const char *scmd; + int cmd; + } cmd_arr[] = { + { "get", SUPERCALL_SKEY_GET }, + { "set", SUPERCALL_SKEY_SET }, + { "rand", SUPERCALL_SKEY_RAND }, + { "root", SUPERCALL_SKEY_ROOT_ENABLE }, + { "help", 0 }, + }; + + for (int i = 0; i < sizeof(cmd_arr) / sizeof(cmd_arr[0]); i++) { + if (strcmp(scmd, cmd_arr[i].scmd)) continue; + cmd = cmd_arr[i].cmd; + break; + } + + if (cmd < 0) usage(EXIT_FAILURE); + char out_buf[SUPERCALL_KEY_MAX_LEN] = { '\0' }; + + switch (cmd) { + case SUPERCALL_SKEY_GET: + sc_skey_get(key, out_buf, sizeof(out_buf)); + fprintf(stdout, "%s\n", out_buf); + break; + case SUPERCALL_SKEY_SET: + if (argc < 3) error(-EINVAL, 0, "no new superkey"); + const char *new_key = argv[2]; + return sc_skey_set(key, new_key); + case SUPERCALL_SKEY_RAND: + return sc_skey_rand(key); + case SUPERCALL_SKEY_ROOT_ENABLE: + if (argc < 3) error(-EINVAL, 0, "no enable or disable specified"); + if (!strcmp("enable", argv[2])) { + sc_skey_root_enable(key, true); + } else if (!strcmp("disable", argv[2])) { + sc_skey_root_enable(key, false); + } else { + error(-EINVAL, 0, "no enable or disable specified"); + } + break; + case 0: + usage(EXIT_SUCCESS); + default: + usage(EXIT_FAILURE); + } + + return 0; +} \ No newline at end of file diff --git a/user/kpatch.h b/user/kpatch.h index e97d9f52..fd7b44c3 100644 --- a/user/kpatch.h +++ b/user/kpatch.h @@ -21,6 +21,8 @@ extern "C" void kpv(const char *key); void kv(const char *key); + int skey_main(int argc, char **argv); + void bootlog(const char *key); void panic(const char *key); int __test(const char *key); diff --git a/user/main.c b/user/main.c index d8cf2b40..5b8e99fc 100644 --- a/user/main.c +++ b/user/main.c @@ -47,6 +47,7 @@ static void usage(int status) "hello If KernelPatch installed, '%s' will echoed.\n" "kpver Print KernelPatch version.\n" "kver Print Kernel version.\n" + "key Manager the superkey.\n" "su KernelPatch Substitute User.\n" "kpm KernelPatch Module manager.\n" #ifdef ANDROID @@ -58,6 +59,7 @@ static void usage(int status) exit(status); } +// todo: refactor int main(int argc, char **argv) { strcat(program_name, argv[0]); @@ -93,6 +95,7 @@ int main(int argc, char **argv) { "hello", SUPERCALL_HELLO }, { "kpver", SUPERCALL_KERNELPATCH_VER }, { "kver", SUPERCALL_KERNEL_VER }, + { "key", 'K' }, { "su", 's' }, { "kpm", 'k' }, @@ -131,6 +134,9 @@ int main(int argc, char **argv) case 's': strcat(program_name, " su"); return su_main(argc - 2, argv + 2); + case 'K': + strcat(program_name, " key"); + return skey_main(argc - 2, argv + 2); case 'k': strcat(program_name, " kpm"); return kpm_main(argc - 2, argv + 2); diff --git a/user/supercall.h b/user/supercall.h index 6d2a7c03..65d81378 100644 --- a/user/supercall.h +++ b/user/supercall.h @@ -56,6 +56,36 @@ static inline uint32_t sc_k_ver(const char *key) return (uint32_t)ret; } +static inline uint32_t sc_skey_get(const char *key, char *out_key, int outlen) +{ + if (!key || !key[0]) return -EINVAL; + if (outlen < SUPERCALL_KEY_MAX_LEN) return -EINVAL; + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SKEY_GET), out_key, outlen); + return (uint32_t)ret; +} + +static inline uint32_t sc_skey_set(const char *key, const char *new_key) +{ + if (!key || !key[0]) return -EINVAL; + if (!new_key || !new_key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SKEY_SET), new_key); + return (uint32_t)ret; +} + +static inline uint32_t sc_skey_rand(const char *key) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SKEY_RAND)); + return (uint32_t)ret; +} + +static inline uint32_t sc_skey_root_enable(const char *key, bool enable) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SKEY_ROOT_ENABLE), (long)enable); + return (uint32_t)ret; +} + static inline long sc_su(const char *key, struct su_profile *profile) { if (!key || !key[0]) return -EINVAL;