From 1a0948bb47ba031a762e188cf92550fb60c6067b Mon Sep 17 00:00:00 2001
From: kxtzownsu <kxtzownsu@gmail.com>
Date: Wed, 6 Nov 2024 22:01:27 -0500
Subject: [PATCH] finish KVG, start KVS stuff

---
 Makefile                                  |   5 +-
 include/arg_checks.h                      |  10 ++
 include/ui.h                              |   7 ++
 src/KVS/kernver-utils.c => include/ver0.h |   0
 src/KVS/tpm-payload.c => include/ver1.h   |   0
 src/KVG/main.c                            | 116 +++++++++++++++++-----
 src/KVS/main.c                            |  36 +++++++
 src/KVS/rmasmoke.c                        |   0
 src/KVS/tpm.c                             |   0
 src/KVS/ui.c                              |  22 ++++
 10 files changed, 170 insertions(+), 26 deletions(-)
 create mode 100644 include/ui.h
 rename src/KVS/kernver-utils.c => include/ver0.h (100%)
 rename src/KVS/tpm-payload.c => include/ver1.h (100%)
 create mode 100644 src/KVS/rmasmoke.c
 create mode 100644 src/KVS/tpm.c

diff --git a/Makefile b/Makefile
index 8bb2667..83deb9a 100644
--- a/Makefile
+++ b/Makefile
@@ -2,8 +2,9 @@ CC ?= gcc
 SHELL ?= /bin/sh
 KVSFLIST := \
 	src/KVS/main.c \
-	src/KVS/ui.c \
-	src/KVS/kernver-utils.c
+	src/KVS/tpm.c \
+	src/KVS/rmasmoke.c \
+	src/KVS/ui.c 
 
 CFLAGS := \
 	-Iinclude \
diff --git a/include/arg_checks.h b/include/arg_checks.h
index 555ee08..1e22c5e 100644
--- a/include/arg_checks.h
+++ b/include/arg_checks.h
@@ -19,4 +19,14 @@ bool fbool(const char *arg)
 	}
 
 	return false;
+}
+
+char *fequals(const char *arg)
+{
+	for (int i = 0; i < gargc; i++) {
+		if (!memcmp(gargv[i], arg, strlen(arg) - 1)) 
+			return gargv[i] + strlen(arg) + 1;
+	}
+
+	return "";
 }
\ No newline at end of file
diff --git a/include/ui.h b/include/ui.h
new file mode 100644
index 0000000..97d6f9b
--- /dev/null
+++ b/include/ui.h
@@ -0,0 +1,7 @@
+#ifndef KVS2_UI_H
+#define KVS2_UI_H
+
+void ui_flash(char* flashtype);
+void ui_header(char* fwver, char* kernver, char* tpmver, char* fwmp, char* gscver, char* gsctype);
+
+#endif
\ No newline at end of file
diff --git a/src/KVS/kernver-utils.c b/include/ver0.h
similarity index 100%
rename from src/KVS/kernver-utils.c
rename to include/ver0.h
diff --git a/src/KVS/tpm-payload.c b/include/ver1.h
similarity index 100%
rename from src/KVS/tpm-payload.c
rename to include/ver1.h
diff --git a/src/KVG/main.c b/src/KVG/main.c
index a77ecfd..1d15405 100644
--- a/src/KVG/main.c
+++ b/src/KVG/main.c
@@ -9,19 +9,36 @@
 #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 kernel_versions;
+    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;
 };
@@ -44,17 +61,37 @@ uint8_t vb2_crc8(const void *vptr, uint32_t size)
     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;
-    offset = 0;
-    size = offsetof(struct vb2_secdata_kernel_v0, crc8);
-    return vb2_crc8(ctx->secdata_kernel + offset, size);
+	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
@@ -63,38 +100,69 @@ int main(int argc, char *argv[]) {
         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);
     }
 
-    struct vb2_secdata_kernel_v0 secdata;
-
-    secdata.struct_version = 0x02;
-    secdata.uid = 0x4752574c;
-    secdata.reserved[0] = 0x00;
-    secdata.reserved[1] = 0x00;
-    secdata.reserved[2] = 0x00;
-
     // 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])) {
-        uint32_t kvarg = convert_to_uint32(argv[1]);
-        secdata.kernel_versions = kvarg;
+        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);
     }
 
-    struct vb2_context ctx;
-    ctx.secdata_kernel = (void *)&secdata;
-
-    secdata.crc8 = secdata_kernel_crc(&ctx);
-    if (fbool("--raw")) {
-        fwrite(&secdata, sizeof(secdata), 1, stdout);
-    } else {
-        print_hex((uint8_t *)&secdata, sizeof(struct vb2_secdata_kernel_v0));
+    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;
-}
\ No newline at end of file
+}
diff --git a/src/KVS/main.c b/src/KVS/main.c
index e69de29..a73bd2f 100644
--- a/src/KVS/main.c
+++ b/src/KVS/main.c
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ui.h"
+
+int main(int argc, char **argv) {
+	// example values for testing
+	char* fwver = "Google_Grunt.11031.149.0";
+	char* kernver = "0x00010001";
+	char* tpmver = "2.0";
+	char* fwmp = "0x1";
+	char* gscver = "0.5.229";
+	char* gsctype = "Cr50";
+
+	// only allow 2 characters (option & newline)
+	char choice[2];
+
+	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';
+	}
+	printf("You entered: %s\n", choice);
+
+	if (strcmp(choice, "1") == 0) {
+		ui_flash("tpm0");
+	}
+
+	return 0;
+}
diff --git a/src/KVS/rmasmoke.c b/src/KVS/rmasmoke.c
new file mode 100644
index 0000000..e69de29
diff --git a/src/KVS/tpm.c b/src/KVS/tpm.c
new file mode 100644
index 0000000..e69de29
diff --git a/src/KVS/ui.c b/src/KVS/ui.c
index e69de29..b65f8fa 100644
--- a/src/KVS/ui.c
+++ b/src/KVS/ui.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+
+void ui_flash(char* flashtype) {
+	printf("wip\n");
+}
+
+void ui_header(char* fwver, char* kernver, char* tpmver, char* fwmp, char* gscver, 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);
+	printf("TPM: %s\n", tpmver);
+	printf("FWMP: %s\n", fwmp);
+	printf("GSC RW Version: %s\n", gscver);
+	printf("GSC Type: %s\n", gsctype);
+	printf("-=-=-=-=-=-=-=-=-=-=-=-=-\n");
+}
+
+void ui_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");
+}
\ No newline at end of file