diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 9f5d77b..8ccf7d2 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -36,7 +36,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: x86_64 - path: build/ + path: build/x86_64/ - name: build aarch64 bins run: ARCH=aarch64 make all @@ -45,7 +45,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: aarch64 - path: build/ + path: build/aarch64/ - name: build armv7 bins run: CC=arm-linux-gnueabihf-gcc ARCH=armv7 make all @@ -54,4 +54,4 @@ jobs: uses: actions/upload-artifact@v4 with: name: armv7 - path: build/ + path: build/armv7/ diff --git a/.vscode/settings.json b/.vscode/settings.json index ec8c142..3ec69ee 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,7 @@ { "files.associations": { - "stdio.h": "c" + "stdio.h": "c", + "types.h": "c" }, // this setting isn't "unknown", its just for troubleshooting, diff --git a/Makefile b/Makefile index 82618ee..ef09596 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,11 @@ KVSFLIST := \ src/KVS/main.c \ src/KVS/tpm.c \ src/KVS/rmasmoke.c \ - src/KVS/ui.c + src/KVS/ui.c \ + src/KVS/hex_utils.c + +TOOLS := \ + src/tools/is_ti50.c CFLAGS := \ -Iinclude \ @@ -28,26 +32,22 @@ TARGET = ${ARCH}-unknown-linux-${TOOLCHAIN} all: clean build kvs kvg -kvs: build build/bin/kvs-$(ARCH) -kvg: build build/bin/kvg-$(ARCH) -kvg-c: build build/bin/kvg-c +kvs: build build/$(ARCH)/bin/kvs +kvg: build build/$(ARCH)/bin/kvg +tools: build build/bin +kvg-c: build build/$(ARCH)bin/kvg-c build: - $(shell mkdir -p build/bin) + $(shell mkdir -p build/$(ARCH)/bin) -build/bin/kvs-$(ARCH): src/KVS/main.c - $(CC) $(KVSFLIST) -o build/bin/kvs-$(ARCH) $(CFLAGS) - chmod +rx build/bin/kvs-$(ARCH) +build/$(ARCH)/bin/kvs: src/KVS/main.c + $(CC) $(KVSFLIST) -o build/$(ARCH)/bin/kvs $(CFLAGS) + chmod +rx build/$(ARCH)/bin/kvs -build/bin/kvg-$(ARCH): src/KVG/main.rs +build/$(ARCH)/bin/kvg: src/KVG/main.rs cargo build --bin KVG --target=$(TARGET) --release - cp target/$(TARGET)/release/KVG build/bin/kvg-$(ARCH) - -# The C version of KVS, not normally built. -# Also guaranteed to be out-of-date. -build/bin/kvg-c: src/KVG/main.c - $(CC) src/KVG/main.c -o build/bin/kvg-c $(CFLAGS) - chmod +rx build/bin/kvg-c + cp target/$(TARGET)/release/KVG build/$(ARCH)/bin/kvg + chmod +rx build/$(ARCH)/bin/kvg install: cp -r build/* /usr/local/ diff --git a/include/arg_checks.h b/include/arg_checks.h index 9428402..30a214a 100644 --- a/include/arg_checks.h +++ b/include/arg_checks.h @@ -4,6 +4,7 @@ #define ARG_CHECKS_H #include +#include int gargc; diff --git a/include/hex_utils.h b/include/hex_utils.h index da3733a..877491c 100644 --- a/include/hex_utils.h +++ b/include/hex_utils.h @@ -4,31 +4,13 @@ #include #include #include +#include +#include +#include -uint32_t convert_to_uint32(const char *str) { - char *endptr; - unsigned long ul_value = strtoul(str, &endptr, 0); - - if (strlen(str) > 10){ - fprintf(stderr, "The entered kernver, %s, was longer than 10 characters (including 0x),\nplease refine the input and try again.", str); - exit(1); - } +uint32_t convert_to_uint32(const char *str); +bool is_valid_hex(const char *str); +void print_hex(const uint8_t *data, uint32_t size); +bool grep(char *string, const char *pattern); - return (uint32_t)ul_value; -} - -bool is_valid_hex(const char *str) { - if (strncmp(str, "0x", 2) == 0 || strncmp(str, "0X", 2) == 0) { - str += 2; - } - - return *str != '\0' && strspn(str, "0123456789abcdefABCDEF") == strlen(str); -} - -void print_hex(const uint8_t *data, uint32_t size) { - for (uint32_t i = 0; i < size; i++) { - printf("%02x ", data[i]); - } -} - -#endif \ No newline at end of file +#endif // HEX_UTILS_H diff --git a/include/kernver.h b/include/kernver.h new file mode 100644 index 0000000..c58fb37 --- /dev/null +++ b/include/kernver.h @@ -0,0 +1,6 @@ +#ifndef KERNVER_H +#define KERNVER_H + +extern const char *KERNVER_TYPE; + +#endif diff --git a/include/sysinfo.h b/include/sysinfo.h index cc4bc8f..13da56a 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -5,7 +5,11 @@ #include #include -#include "tpm.h" +#include "tpm.h" +#include "kernver.h" +#include "hex_utils.h" + +const char *KERNVER_TYPE = "N/A. This is an error, please report at https://github.com/kxtzownsu/KVS with a picture of the screen."; void trim_newline(char* str) { size_t len = strlen(str); @@ -17,6 +21,7 @@ void trim_newline(char* str) { const char* getFirmwareVersion(){ // note, may not work on all chromebooks + // I also don't wanna have to rely on the crossystem binary for it FILE *fptr; char stupidfile[] = "/sys/class/dmi/id/bios_version"; fptr = fopen(stupidfile, "r"); @@ -26,7 +31,7 @@ const char* getFirmwareVersion(){ printf("Error reading Firmware Version \n"); printf("Please report as a bug at https://github.com/kxtzownsu/KVS-private\n"); - sleep(86400); // sleep for 1d if error + sleep(86400); return "Error!"; } fgets(firmwareVersion, 100, fptr); @@ -37,10 +42,6 @@ const char* getFirmwareVersion(){ return firmwareVersion; } -// uint32_t getKernelVersion(){ -// } - -// this is kinda shitty, but until the TPM2 API is done, this is how we have to do it const char* getTpmVersion(){ char cmd[] = "tpmc tpmver"; static char output[5]; @@ -54,5 +55,82 @@ const char* getTpmVersion(){ return output; } +const char* getKernver() { + char cmd[] = "tpmc read 0x1008 9 2>"; + static char output[26]; + FILE* fp = popen(cmd, "r"); + fgets(output, sizeof(output), fp); + fclose(fp); + trim_newline(output); + + uint32_t kernver = 0; + static char kernver_str[18] = "0x00000000"; + + // ewwww yucky i hate this + + if (strncmp(output, "10", 2) == 0) { + printf("using v1.0\n"); + unsigned int b1, b2, b3, b4; + sscanf(output + 12, "%2x %2x %2x %2x", &b1, &b2, &b3, &b4); + kernver = b1 | (b2 << 8) | (b3 << 16) | (b4 << 24); + snprintf(kernver_str, sizeof(kernver_str), "0x%08x (v1.0)", kernver); + KERNVER_TYPE = "v1"; + } else if (strncmp(output, "2", 1) == 0) { + unsigned int b1, b2, b3, b4; + sscanf(output + 14, "%2x %2x %2x %2x", &b1, &b2, &b3, &b4); + kernver = b1 | (b2 << 8) | (b3 << 16) | (b4 << 24); + snprintf(kernver_str, sizeof(kernver_str), "0x%08x (v0.2)", kernver); + KERNVER_TYPE = "v0"; + } + + + return kernver_str; +} + +const char* getFWMPFlags(){ + // char cmd[] = "tpmc read 0x100A 5 2>/dev/null"; + // static char output[256]; + // FILE* fp = popen(cmd, "r"); + // fgets(output, sizeof(output), fp); + // fclose(fp); + // trim_newline(output); + static char output[256]; + output = ""' + + + if (strcmp(output, "") == 0) { + return "N/A (Most likely unenrolled)"; + } else { + uint8_t flags = 0; + static char flags_str[4]; + unsigned int b1; + sscanf(output + 12, "%2x", &b1); + flags = b1; + snprintf(flags_str, sizeof(flags_str), "0x%08x (v1.0)", flags); + return flags_str; + } +} + +const char* getGSCRWVersion(){ + char cmd[] = "gsctool -a -f | tail -n 1 | awk '{printf $2}'"; + static char output[8]; + FILE* fp = popen(cmd, "r"); + fgets(output, sizeof(output), fp); + fclose(fp); + trim_newline(output); + + return output; +} + +const char* getGSCType(){ + char cmd[] = "/opt/kvs/bin/is_ti50"; + static char output[7]; + FILE* fp = popen(cmd, "r"); + fgets(output, sizeof(output), fp); + fclose(fp); + trim_newline(output); + + return output; +} #endif \ No newline at end of file diff --git a/include/tpm.h b/include/tpm.h index 25960ca..55941b6 100644 --- a/include/tpm.h +++ b/include/tpm.h @@ -2,7 +2,7 @@ #define TPM_H #include -int tpm_nvwrite(char* index, char* bytes, char* offset, char* authType, char* indexPassword); -int tpm_nvread(char* index, char* size, char* offset, char* authType, char* indexPassword); +int tpm_nvwrite(char* index, char* bytes); +int tpm_nvread(char* index, char* size); #endif \ No newline at end of file diff --git a/include/ui.h b/include/ui.h index 8a7ac03..cf99433 100644 --- a/include/ui.h +++ b/include/ui.h @@ -2,6 +2,8 @@ #define UI_H void ui_flash(char* flashtype); -void ui_header(const char* fwver, char* kernver, const char* tpmver, char* fwmp, char* gscver, char* gsctype); +void ui_header(const char* fwver, const char* kernver, const char* tpmver, const char* fwmp, const char* gscver, const char* gsctype); +void show_credits(); +void troll(); #endif \ No newline at end of file diff --git a/src/KVG/main.c b/src/KVG/main.c deleted file mode 100644 index 1d15405..0000000 --- a/src/KVG/main.c +++ /dev/null @@ -1,168 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "arg_checks.h" -#include "hex_utils.h" - -uint32_t kvarg; - -// basically almost all of this code was pieced together -// using vboot_reference code, credits to Google -// for writing most of this code in a sense :3 - -#define VB2_SHA256_DIGEST_SIZE 32 - -struct vb2_secdata_kernel_v0 { - uint8_t struct_version; - uint32_t uid; - uint32_t kernver; - uint8_t reserved[3]; - uint8_t crc8; -} __attribute__((packed)); - -struct vb2_secdata_kernel_v1 { - uint8_t struct_version; /* 1.0 (or 0x10 in v0 format) */ - uint8_t struct_size; - uint8_t crc8; - uint8_t flags; - uint32_t kernver; - uint8_t ec_hash[VB2_SHA256_DIGEST_SIZE]; -}; - - -struct vb2_secdata_kernel_v0 secdata0; -struct vb2_secdata_kernel_v1 secdata1; - - -struct vb2_context { - void *secdata_kernel; -}; - -uint8_t vb2_crc8(const void *vptr, uint32_t size) -{ - const uint8_t *data = vptr; - unsigned crc = 0; - uint32_t i, j; - - for (j = size; j; j--, data++) { - crc ^= (*data << 8); - for(i = 8; i; i--) { - if (crc & 0x8000) - crc ^= (0x1070 << 3); - crc <<= 1; - } - } - - return (uint8_t)(crc >> 8); -} - -#define MAJOR_VER(x) (((x) & 0xf0) >> 4) -#define MINOR_VER(x) ((x) & 0x0f) - -static inline int is_v0(struct vb2_context *ctx) -{ - struct vb2_secdata_kernel_v1 *sec = (void *)ctx->secdata_kernel; - return MAJOR_VER(sec->struct_version) == 0; -} - -static uint8_t secdata_kernel_crc(struct vb2_context *ctx) -{ - size_t offset, size; - - if (is_v0(ctx)) { - offset = 0; - size = offsetof(struct vb2_secdata_kernel_v0, crc8); - } else { - struct vb2_secdata_kernel_v1 *sec - = (void *)ctx->secdata_kernel; - offset = offsetof(struct vb2_secdata_kernel_v1, flags); - size = sec->struct_size - offset; - } - - return vb2_crc8(ctx->secdata_kernel + offset, size); -} - - -int main(int argc, char *argv[]) { - gargc = argc; - gargv = argv; - char *version = fequals("--ver"); - - // if --help or no args are passsed - // print the usage and an example command - if (fbool("--help") || argc == 1){ - printf("USAGE: %s \n", argv[0]); - printf("e.g: %s 0x00010001 --raw\n", argv[0]); - printf("-=-=-=-=-=-=-\n"); - printf("--raw - prints the output as raw hex bytes\n"); - printf("--ver=<0/1> - specifies the kernver struct version to use, oldui boards use ver0 while newui boards use ver1\n"); - printf("--help - shows this message :3\n"); - printf("-=-=-=-=-=-=-\n"); - printf("KVG was created by kxtzownsu\n"); - printf("Credits go to Hannah for making the arg parsing system\n"); - exit(0); - } - - // make sure the user sends us a correct hex value, - // we dont want to just blindly trust that its correct - if (is_valid_hex(argv[1])) { - kvarg = convert_to_uint32(argv[1]); - } else { - printf("The entered kernver: %s, wasn't detected as valid hexadecimal, please try again.\n", argv[1]); - exit(1); - } - - if (strcmp(version, "0") != 0 && strcmp(version, "1") != 0) { - printf("The entered struct version: %s, wasn't a valid option (see --help). Please try again.\n", version); - exit(1); - } - - if (!strcmp(version, "0")){ - secdata0.struct_version = 0x02; - secdata0.uid = 0x4752574c; - secdata0.reserved[0] = 0x00; - secdata0.reserved[1] = 0x00; - secdata0.reserved[2] = 0x00; - secdata0.kernver = kvarg; - - struct vb2_context ctx; - ctx.secdata_kernel = (void *)&secdata0; - - secdata0.crc8 = secdata_kernel_crc(&ctx); - } - - if (!strcmp(version, "1")) { - secdata1.struct_version = 0x10; - secdata1.struct_size = sizeof(struct vb2_secdata_kernel_v1); - secdata1.flags = 0x0; - secdata1.kernver = kvarg; - - struct vb2_context ctx; - ctx.secdata_kernel = (void *)&secdata1; - secdata1.crc8 = secdata_kernel_crc(&ctx); - } - - // god i hate this nesting, TODO: find a better way to detect if we're specifying ver0 or ver1 - if (fbool("--raw")) { - if (!strcmp(version, "0")) { - fwrite(&secdata0, sizeof(secdata0), 1, stdout); - } - if (!strcmp(version, "1")) { - fwrite(&secdata1, sizeof(secdata1), 1, stdout); - } - } else { - if (!strcmp(version, "0")) { - print_hex((uint8_t *)&secdata0, sizeof(struct vb2_secdata_kernel_v0)); - } - if (!strcmp(version, "1")) { - print_hex((uint8_t *)&secdata1, sizeof(struct vb2_secdata_kernel_v1)); - } - } - - return 0; -} diff --git a/src/KVS/hex_utils.c b/src/KVS/hex_utils.c new file mode 100644 index 0000000..e953c9c --- /dev/null +++ b/src/KVS/hex_utils.c @@ -0,0 +1,32 @@ +#include "hex_utils.h" + +uint32_t convert_to_uint32(const char *str) { + char *endptr; + unsigned long ul_value = strtoul(str, &endptr, 0); + + if (strlen(str) > 10) { + fprintf(stderr, "The entered kernver, %s, was longer than 10 characters (including 0x),\nplease refine the input and try again.", str); + exit(1); + } + + return (uint32_t)ul_value; +} + +bool is_valid_hex(const char *str) { + if (strncmp(str, "0x", 2) == 0 || strncmp(str, "0X", 2) == 0) { + str += 2; // Skip the "0x" or "0X" prefix + } + + return *str != '\0' && strspn(str, "0123456789abcdefABCDEF") == strlen(str); +} + +void print_hex(const uint8_t *data, uint32_t size) { + for (uint32_t i = 0; i < size; i++) { + printf("%02x ", data[i]); + } + printf("\n"); +} + +bool grep(char *string, const char *pattern) { + return strstr(string, pattern) != NULL; +} diff --git a/src/KVS/main.c b/src/KVS/main.c index ef91842..58c8ab9 100644 --- a/src/KVS/main.c +++ b/src/KVS/main.c @@ -5,6 +5,19 @@ #include "ui.h" #include "sysinfo.h" +void kernver_faq(){ + printf( + "Basic kernver FAQ: \n" + "Updated: 12/28/24 1:46 PM EST\n" + "------------------------------------------\n" + "Kernver 0: All versions will boot\n" + "Kernver 1: All versions will boot\n" + "Kernver 2: Versions R112 and up will boot\n" + "Kernver 3: Versions R120 and up will boot\n" + "Kernver 4: Versions R125 and up will boot\n" + ); +}; + int main(int argc, char **argv) { if (geteuid() != 0){ printf("Please run KVS as root!\n"); @@ -13,39 +26,45 @@ int main(int argc, char **argv) { // example values for testing const char* fwver = getFirmwareVersion(); - char* kernver = "0x00010001"; + const char* kernver = getKernver(); const char* tpmver = getTpmVersion(); - char* fwmp = "0x1"; - char* gscver = "0.5.229"; - char* gsctype = "Cr50"; - + const char* fwmp = getFWMPFlags(); + const char* gscver = getGSCRWVersion(); + const char* gsctype = getGSCType(); + const char* requirement_flash = "[UNENROLLED]"; // only allow 2 characters (option & newline) char choice[3]; + while (true) { + ui_header(fwver, kernver, tpmver, fwmp, gscver, gsctype); + printf("%s 1) Flash new kernver \n", requirement_flash); + printf("2) Run KAUB (Kernver Automatic Update Blocker) \n"); + printf("3) Kernver FAQ \n"); + printf("4) Credits\n"); + printf("5) Shell\n"); + printf("6) Reboot\n"); + printf("> "); + fgets(choice, sizeof(choice), stdin); + if (choice[strlen(choice) - 1] == '\n') { + choice[strlen(choice) - 1] = '\0'; + } - ui_header(fwver, kernver, tpmver, fwmp, gscver, gsctype); - printf("1) Flash new kernver via /dev/tpm0 (REQ. UNENROLLED)\n"); - printf("2) Flash new kernver via RMASmoke (REQ. CR50 VER 0.5.229 OR LOWER)\n"); - printf("3) Make kernver index unwritable\n"); - printf("4) Shell\n"); - printf("5) Reboot\n"); - printf("> "); - fgets(choice, sizeof(choice), stdin); - if (choice[strlen(choice) - 1] == '\n') { - choice[strlen(choice) - 1] = '\0'; - } - - if (!strcmp(choice, "1")) { - ui_flash("tpm0"); - } else if (!strcmp(choice, "2")) { - ui_flash("rmasmoke"); - } else if (!strcmp(choice, "3")) { - printf("wip"); - } else if (!strcmp(choice, "4")) { - system("/bin/bash"); - } else if (!strcmp(choice, "5")) { - exit(1); + if (!strcmp(choice, "1")) { + ui_flash("tpm0"); + } else if (!strcmp(choice, "2")) { + printf("KAUB is not avaliable on v2.0.0. Please either update your shim or wait for KAUB to release on v2.1"); + } else if (!strcmp(choice, "3")) { + kernver_faq(); + } else if (!strcmp(choice, "4")) { + show_credits(); + } else if (!strcmp(choice, "4")) { + system("/bin/bash"); + } else if (!strcmp(choice, "6")) { + exit(1); + } else if (!strcmp(choice, "7")) { + troll(); + } } return 0; diff --git a/src/KVS/tpm.c b/src/KVS/tpm.c index 7af7788..8e34df9 100644 --- a/src/KVS/tpm.c +++ b/src/KVS/tpm.c @@ -1,15 +1,14 @@ #include +#include +// yeah kill me but this is just a `tpmc` wrapper :troll: /* ARGS: index = that what TPM2 index to read from, e.g: "0x1008" size = how many bytes should we read -offset = how far into the index should we start reading -authType = either owner, index, or platform -indexPassword = if index authType is chosen, enter your indexPassword, otherwise pass nothing */ -int tpm_nvwrite(char* index, char* bytes, char* offset, char* authType, char* indexPassword){ - printf ("wip, index: %s, bytes: '%s', offset: %s, authType: %s, indexPassword: %s", index, bytes, offset, authType, indexPassword); +int tpm_nvwrite(char* index, char* bytes){ + printf ("wip, index: %s, bytes: '%s'", index, bytes); return 0; } @@ -17,10 +16,8 @@ int tpm_nvwrite(char* index, char* bytes, char* offset, char* authType, char* in /* ARGS: index = that what TPM2 index to read from, e.g: "0x1008" size = how many bytes should we read -offset = how far into the index should we start reading -authType = either owner, index, or platform -indexPassword = if index authType is chosen, enter your indexPassword, otherwise pass nothing */ -int tpm_nvread(char* index, char* size, char* offset, char* authType, char* indexPassword){ - printf ("wip, index: %s, size: '%s', offset: %s, authType: %s, indexPassword: %s", index, size, offset, authType, indexPassword); +int tpm_nvread(char* index, char* size){ + printf ("wip, index: %s, size: '%s'", index, size); + return 0; } \ No newline at end of file diff --git a/src/KVS/ui.c b/src/KVS/ui.c index 780896e..676d0a3 100644 --- a/src/KVS/ui.c +++ b/src/KVS/ui.c @@ -8,6 +8,7 @@ #include "tpm.h" #include "hex_utils.h" +#include "kernver.h" void ui_flash(char* flashtype) { // i feel like this is some of the dirtiest C that @@ -19,7 +20,6 @@ void ui_flash(char* flashtype) { char kvgout_v1[V1_SIZE + 1]; char kerninput[12]; - char structtype[4]; printf("What kernver would you like to flash? \n"); printf("> "); @@ -33,28 +33,21 @@ void ui_flash(char* flashtype) { exit(1); } - printf("Does your device have lightmode (v0) or darkmode (v1) recovery? Please type either v0 or v1.\n"); - printf("> "); - fgets(structtype, sizeof(structtype), stdin); - if (structtype[strlen(structtype) - 1] == '\n') { - structtype[strlen(structtype) - 1] = '\0'; - } - // the output of strcmp if it fails is True - if (strcmp(structtype, "v0") && strcmp(structtype, "v1")){ - fprintf(stderr, "Invalid struct type %s, valid types are v0 and v1\n", structtype); + if (strcmp(KERNVER_TYPE, "v0") && strcmp(KERNVER_TYPE, "v1")){ + fprintf(stderr, KERNVER_TYPE); exit(1); } // we check if its *false* since strcmp returns true if failing - if (!strcmp(structtype, "v0")){ + if (!strcmp(KERNVER_TYPE, "v0")){ char cmd[128]; snprintf(cmd, sizeof(cmd), "kvg %s --ver=0", kerninput); FILE* fp = popen(cmd, "r"); fgets(kvgout_v0, sizeof(kvgout_v0), fp); fclose(fp); - } else if (!strcmp(structtype, "v1")) { + } else if (!strcmp(KERNVER_TYPE, "v1")) { char cmd[128]; snprintf(cmd, sizeof(cmd), "kvg %s --ver=1", kerninput); @@ -65,17 +58,17 @@ void ui_flash(char* flashtype) { if (flashtype == "tpm0"){ - if (!strcmp(structtype, "v0")) { - tpm_nvwrite("0x1008", kvgout_v0, "0", "platform", ""); - } else if (!strcmp(structtype, "v1")) { - tpm_nvwrite("0x1008", kvgout_v1, "0", "platform", ""); + if (!strcmp(KERNVER_TYPE, "v0")) { + tpm_nvwrite("0x1008", kvgout_v0); + } else if (!strcmp(KERNVER_TYPE, "v1")) { + tpm_nvwrite("0x1008", kvgout_v1); } } else if (flashtype == "rmasmoke"){ printf("using rmasmoke\n"); } } -void ui_header(const char* fwver, char* kernver, const char* tpmver, char* fwmp, char* gscver, char* gsctype){ +void ui_header(const char* fwver, const char* kernver, const char* tpmver, const char* fwmp, const char* gscver, const char* gsctype){ printf("KVS: Kernel Version Switcher (codename Maglev, bid: 2.0.0))\n"); printf("FW Version: %s\n", fwver); printf("Kernel Version: %s\n", kernver); @@ -86,8 +79,33 @@ void ui_header(const char* fwver, char* kernver, const char* tpmver, char* fwmp, printf("-=-=-=-=-=-=-=-=-=-=-=-=-\n"); } -void ui_credits(){ +void show_credits(){ printf("kxtzownsu - Writing KVS 1 and 2\n"); printf("Hannah/ZegLol - Helping with /dev/tpm0 flashing, rewriting RMASmoke.\n"); printf("Writable - Writing the RMASmoke vulnerability\n"); +} + +void troll(){ + while (true){ + printf("\033[H\033[J"); + printf( + " 333333333333333 \n" + " 3:::::::::::::::33 \n" + " 3::::::33333::::::3\n" + " 3333333 3:::::3\n" + " 3:::::3\n" + " :::::: 3:::::3\n" + " :::::: 33333333:::::3 \n" + " :::::: 3:::::::::::3 \n" + " 33333333:::::3 \n" + " 3:::::3\n" + " 3:::::3\n" + " :::::: 3:::::3\n" + " :::::: 3333333 3:::::3\n" + " :::::: 3::::::33333::::::3\n" + " 3:::::::::::::::33 \n" + " 333333333333333 \n" + ); + sleep(1); + } } \ No newline at end of file diff --git a/src/tools/is_ti50.c b/src/tools/is_ti50.c new file mode 100644 index 0000000..72f0ffe --- /dev/null +++ b/src/tools/is_ti50.c @@ -0,0 +1,160 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define VENDOR_CC_GET_AP_RO_STATUS 57 +static inline int MIN(int a, int b) { return a < b ? a : b; } +#define EXTENSION_FW_UPGRADE 4 +#define LAST_EXTENSION_COMMAND 15 +#define CONFIG_EXTENSION_COMMAND 0xbaccd00a +#define TPM_CC_VENDOR_BIT_MASK 0x20000000 +#define SIGNED_TRANSFER_SIZE 1024 +#define MAX_RX_BUF_SIZE 2048 +#define MAX_TX_BUF_SIZE (SIGNED_TRANSFER_SIZE + sizeof(struct tpm_pkt)) +#define VENDOR_RC_ERR 0x500 + +int tpm; + +struct tpm_pkt { + __be16 tag; + __be32 length; + __be32 ordinal; + __be16 subcmd; + union { + struct { + __be32 digest; + __be32 address; + char data[0]; + } upgrade; + struct { + char data[0]; + } command; + }; +} __attribute__((packed)); + + +static int send_payload(unsigned int digest, unsigned int addr, + const void *data, int size, uint16_t subcmd) +{ + static uint8_t outbuf[MAX_TX_BUF_SIZE]; + struct tpm_pkt *out = (struct tpm_pkt *)outbuf; + int len, done; + void *payload; + size_t header_size; + + out->tag = htobe16(0x8001); + out->subcmd = htobe16(subcmd); + + out->ordinal = htobe32((subcmd <= LAST_EXTENSION_COMMAND) ? CONFIG_EXTENSION_COMMAND : TPM_CC_VENDOR_BIT_MASK); + + if (subcmd == EXTENSION_FW_UPGRADE) { + out->upgrade.digest = digest; + out->upgrade.address = htobe32(addr); + header_size = offsetof(struct tpm_pkt, upgrade.data); + }else{ + header_size = offsetof(struct tpm_pkt, command.data); + } + + payload = outbuf + header_size; + len = size + header_size; + + out->length = htobe32(len); + memcpy(payload, data, size); + + done = write(tpm, out, len); + + if (done < 0) { + fprintf(stderr, "Error: Failed to write to TPM, %s.\n", strerror(errno)); + return 1; + }else if (done != len) { + fprintf(stderr, "Error: Expected to write %d bytes to TPM, instead wrote %d. %s\n", len, done, strerror(errno)); + return 1; + } + + return 0; +} + +static int read_response(void *response, size_t *response_size) +{ + static uint8_t raw_response[MAX_RX_BUF_SIZE + sizeof(struct tpm_pkt)]; + int response_offset = offsetof(struct tpm_pkt, command.data); + const size_t rx_size = sizeof(raw_response); + uint32_t rv; + + int read_count, len; + + len = 0; + do { + uint8_t *rx_buf = raw_response + len; + size_t rx_to_go = rx_size - len; + + read_count = read(tpm, rx_buf, rx_to_go); + + len += read_count; + } while (read_count); + + len = len - response_offset; + if (len < 0) { + fprintf(stderr, "Error: Problems reading from TPM, got %d bytes.\n", len + response_offset); + return 1; + } + + len = MIN(len, *response_size); + memcpy(response, raw_response + response_offset, len); + *response_size = len; + + memcpy(&rv, &((struct tpm_pkt *)raw_response)->ordinal, sizeof(rv)); + rv = be32toh(rv); + + if ((rv & VENDOR_RC_ERR) == VENDOR_RC_ERR) rv &= ~VENDOR_RC_ERR; + + return rv; +} + +bool is_ti50(int *rc) +{ + uint8_t resp; + size_t response_size = sizeof(resp); + + tpm = open("/dev/tpm0", O_RDWR); + + if (send_payload(0, 0, NULL, 0, VENDOR_CC_GET_AP_RO_STATUS) != 0) { + fprintf(stderr, "Error: Failed to write AP RO Status request to TPM.\n"); + return false; + } + if (read_response(&resp, &response_size) != 0) { + fprintf(stderr, "Error: Failed to read AP RO Status from TPM.\n"); + return false; + } + + if (resp == 0x01E) { + *rc = resp; + return false; + } + + return resp != 4; +} + +int main(){ + int rc; + + bool ti50 = is_ti50(&rc); + + if (rc == 0x01E){ + printf("TPM 1.2\n"); + } else if (!ti50){ + printf("Cr50\n"); + } else { + printf("Ti50\n"); + } + + return rc; +} \ No newline at end of file