kvs: optimize stuff
changelog: - make hex_utils includes work across C files - have Makefile use `build/$(ARCH)` instead of `build/bin/binary-$(ARCH)` - small bugfixes - add is_ti50.c & place for future tools - global KERNVER_TYPE variable (if kernver.h is included)
This commit is contained in:
parent
c0ffaa3967
commit
a0b118bbbb
6
.github/workflows/build.yaml
vendored
6
.github/workflows/build.yaml
vendored
@ -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/
|
||||
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -1,6 +1,7 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"stdio.h": "c"
|
||||
"stdio.h": "c",
|
||||
"types.h": "c"
|
||||
},
|
||||
|
||||
// this setting isn't "unknown", its just for troubleshooting,
|
||||
|
32
Makefile
32
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/
|
||||
|
@ -4,6 +4,7 @@
|
||||
#define ARG_CHECKS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
int gargc;
|
||||
|
@ -4,31 +4,13 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
uint32_t convert_to_uint32(const char *str) {
|
||||
char *endptr;
|
||||
unsigned long ul_value = strtoul(str, &endptr, 0);
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
#endif // HEX_UTILS_H
|
||||
|
6
include/kernver.h
Normal file
6
include/kernver.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef KERNVER_H
|
||||
#define KERNVER_H
|
||||
|
||||
extern const char *KERNVER_TYPE;
|
||||
|
||||
#endif
|
@ -6,6 +6,10 @@
|
||||
#include <stdlib.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
|
@ -2,7 +2,7 @@
|
||||
#define TPM_H
|
||||
#include <stddef.h>
|
||||
|
||||
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
|
@ -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
|
168
src/KVG/main.c
168
src/KVG/main.c
@ -1,168 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#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 <kernver> <optl. flags>\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;
|
||||
}
|
32
src/KVS/hex_utils.c
Normal file
32
src/KVS/hex_utils.c
Normal file
@ -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;
|
||||
}
|
@ -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;
|
||||
|
@ -1,15 +1,14 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// 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;
|
||||
}
|
54
src/KVS/ui.c
54
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);
|
||||
}
|
||||
}
|
160
src/tools/is_ti50.c
Normal file
160
src/tools/is_ti50.c
Normal file
@ -0,0 +1,160 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <endian.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
||||
#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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user