diff --git a/CMakeLists.txt b/CMakeLists.txt index 655e47923..46c656957 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -405,6 +405,7 @@ set(LIBFASTFETCH_SRC src/modules/terminalsize/terminalsize.c src/modules/theme/theme.c src/modules/title/title.c + src/modules/tpm/tpm.c src/modules/uptime/uptime.c src/modules/users/users.c src/modules/version/version.c @@ -495,6 +496,7 @@ if(LINUX) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/tpm/tpm_linux.c src/detection/uptime/uptime_linux.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_linux.c @@ -558,6 +560,7 @@ elseif(ANDROID) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_nosupport.c + src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_linux.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_nosupport.c @@ -638,6 +641,7 @@ elseif(FreeBSD) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_bsd.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_linux.c @@ -703,6 +707,7 @@ elseif(APPLE) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_nosupport.c + src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_bsd.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_apple.m @@ -770,6 +775,7 @@ elseif(WIN32) src/detection/terminalshell/terminalshell_windows.c src/detection/terminalsize/terminalsize_windows.c src/detection/theme/theme_nosupport.c + src/detection/tpm/tpm_windows.c src/detection/uptime/uptime_windows.c src/detection/users/users_windows.c src/detection/wallpaper/wallpaper_windows.c @@ -854,6 +860,7 @@ elseif(SunOS) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_sunos.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_linux.c @@ -1179,7 +1186,7 @@ elseif(APPLE) PRIVATE "-weak_framework Apple80211" ) elseif(WIN32) - target_compile_definitions(libfastfetch PRIVATE -D_WIN32_WINNT=0x0601) + target_compile_definitions(libfastfetch PRIVATE -D_WIN32_WINNT=0x0A00) target_link_libraries(libfastfetch PRIVATE "dwmapi" PRIVATE "gdi32" diff --git a/doc/json_schema.json b/doc/json_schema.json index 0ebda7d2c..04266e383 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -706,6 +706,7 @@ "terminaltheme", "title", "theme", + "tpm", "uptime", "users", "version", @@ -865,6 +866,10 @@ "const": "theme", "description": "Print current theme of desktop environment" }, + { + "const": "tpm", + "description": "Print info of Trusted Platform Module (TPM) Security Device" + }, { "const": "uptime", "description": "Print how long system has been running" diff --git a/src/common/modules.c b/src/common/modules.c index 232c555f0..4e8ae69e4 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -137,6 +137,7 @@ static FFModuleBaseInfo* T[] = { (void*) &instance.config.modules.terminalTheme, (void*) &instance.config.modules.title, (void*) &instance.config.modules.theme, + (void*) &instance.config.modules.tpm, NULL, }; diff --git a/src/detection/tpm/tpm.h b/src/detection/tpm/tpm.h new file mode 100644 index 000000000..d8bc72b54 --- /dev/null +++ b/src/detection/tpm/tpm.h @@ -0,0 +1,11 @@ +#pragma once + +#include "fastfetch.h" + +typedef struct FFTPMResult +{ + FFstrbuf version; + FFstrbuf interfaceType; +} FFTPMResult; + +const char* ffDetectTPM(FFTPMResult* result); diff --git a/src/detection/tpm/tpm_linux.c b/src/detection/tpm/tpm_linux.c new file mode 100644 index 000000000..14e8be369 --- /dev/null +++ b/src/detection/tpm/tpm_linux.c @@ -0,0 +1,22 @@ +#include "tpm.h" +#include "common/io/io.h" + +const char* ffDetectTPM(FF_MAYBE_UNUSED FFTPMResult* result) +{ + if (ffReadFileBuffer("/sys/class/tpm/tpm0/tpm_version_major", &result->version)) + { + ffStrbufTrimRightSpace(&result->version); + if (ffStrbufEqualS(&result->version, "2")) + ffStrbufSetStatic(&result->version, "2.0"); + + return NULL; + } + + if (ffPathExists("/sys/class/tpm/tpm0", FF_PATHTYPE_DIRECTORY)) + { + ffStrbufSetStatic(&result->version, "unknown"); + return NULL; + } + + return "TPM device is not found"; +} diff --git a/src/detection/tpm/tpm_nosupport.c b/src/detection/tpm/tpm_nosupport.c new file mode 100644 index 000000000..7865f70b5 --- /dev/null +++ b/src/detection/tpm/tpm_nosupport.c @@ -0,0 +1,6 @@ +#include "tpm.h" + +const char* ffDetectTPM(FF_MAYBE_UNUSED FFTPMResult* result) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/tpm/tpm_windows.c b/src/detection/tpm/tpm_windows.c new file mode 100644 index 000000000..2837822d8 --- /dev/null +++ b/src/detection/tpm/tpm_windows.c @@ -0,0 +1,82 @@ +#include "tpm.h" +#include "common/library.h" + +// #include + +#define TBS_SUCCESS 0u +#define TBS_E_INTERNAL_ERROR 0x80284001u +#define TBS_E_INVALID_CONTEXT 0x80284004u +typedef UINT32 TBS_RESULT; + +#define TPM_VERSION_UNKNOWN 0 +#define TPM_VERSION_12 1 +#define TPM_VERSION_20 2 + +#define TPM_IFTYPE_UNKNOWN 0 +#define TPM_IFTYPE_1 1 // for 1.2 - use I/O-port or MMIO +#define TPM_IFTYPE_TRUSTZONE 2 // 2.0: Trustzone +#define TPM_IFTYPE_HW 3 // 2.0: HW TPM +#define TPM_IFTYPE_EMULATOR 4 // 2.0: SW-emulator +#define TPM_IFTYPE_SPB 5 // 2.0: SPB attached + +typedef struct _TPM_DEVICE_INFO +{ + UINT32 structVersion; // = 1 for now + UINT32 tpmVersion; // 1.2 / 2.0 + UINT32 tpmInterfaceType; // HW, simulator, ... + UINT32 tpmImpRevision; // code-drop revision, + // implenmentation-specific +} TPM_DEVICE_INFO, *PTPM_DEVICE_INFO; +typedef const TPM_DEVICE_INFO *PCTPM_DEVICE_INFO; + +TBS_RESULT WINAPI +Tbsi_GetDeviceInfo( + _In_ UINT32 Size, + _Out_writes_bytes_(Size) PVOID Info); + +const char* ffDetectTPM(FFTPMResult* result) +{ + FF_LIBRARY_LOAD(tbs, "dlopen TBS" FF_LIBRARY_EXTENSION " failed", "TBS" FF_LIBRARY_EXTENSION, -1) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(tbs, Tbsi_GetDeviceInfo) + + TPM_DEVICE_INFO deviceInfo = {}; + TBS_RESULT code = ffTbsi_GetDeviceInfo(sizeof(deviceInfo), &deviceInfo); + if (code != TBS_SUCCESS) + return code == (TBS_RESULT) TBS_E_INVALID_CONTEXT ? "TPM device is not found" : "Tbsi_GetDeviceInfo() failed"; + + switch (deviceInfo.tpmVersion) + { + case TPM_VERSION_12: + ffStrbufSetStatic(&result->version, "1.2"); + break; + case TPM_VERSION_20: + ffStrbufSetStatic(&result->version, "2.0"); + break; + default: + ffStrbufSetStatic(&result->version, "unknown"); + break; + } + + switch (deviceInfo.tpmInterfaceType) + { + case TPM_IFTYPE_1: + ffStrbufSetStatic(&result->interfaceType, "I/O-port or MMIO"); + break; + case TPM_IFTYPE_TRUSTZONE: + ffStrbufSetStatic(&result->interfaceType, "Trustzone"); + break; + case TPM_IFTYPE_HW: + ffStrbufSetStatic(&result->interfaceType, "HW TPM"); + break; + case TPM_IFTYPE_EMULATOR: + ffStrbufSetStatic(&result->interfaceType, "SW-emulator"); + break; + case TPM_IFTYPE_SPB: + ffStrbufSetStatic(&result->interfaceType, "SPB attached"); + break; + default: + break; + } + + return NULL; +} diff --git a/src/modules/modules.h b/src/modules/modules.h index 84d9e6fcb..4f9fa7a40 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -62,6 +62,7 @@ #include "modules/terminaltheme/terminaltheme.h" #include "modules/theme/theme.h" #include "modules/title/title.h" +#include "modules/tpm/tpm.h" #include "modules/uptime/uptime.h" #include "modules/users/users.h" #include "modules/version/version.h" diff --git a/src/modules/options.h b/src/modules/options.h index 2677d2515..783757d3a 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -62,6 +62,7 @@ #include "modules/terminaltheme/option.h" #include "modules/theme/option.h" #include "modules/title/option.h" +#include "modules/tpm/option.h" #include "modules/uptime/option.h" #include "modules/users/option.h" #include "modules/version/option.h" diff --git a/src/modules/tpm/option.h b/src/modules/tpm/option.h new file mode 100644 index 000000000..d98c21df2 --- /dev/null +++ b/src/modules/tpm/option.h @@ -0,0 +1,11 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFTPMOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; +} FFTPMOptions; diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c new file mode 100644 index 000000000..f9b7a1e5d --- /dev/null +++ b/src/modules/tpm/tpm.c @@ -0,0 +1,124 @@ +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "detection/tpm/tpm.h" +#include "modules/tpm/tpm.h" +#include "util/stringUtils.h" + +#define FF_TPM_NUM_FORMAT_ARGS 2 + +void ffPrintTPM(FFTPMOptions* options) +{ + FFTPMResult result = { + .version = ffStrbufCreate(), + .interfaceType = ffStrbufCreate() + }; + const char* error = ffDetectTPM(&result); + + if(error) + { + ffPrintError(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + return; + } + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffStrbufPutTo(&result.version, stdout); + } + else + { + FF_PRINT_FORMAT_CHECKED(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_TPM_NUM_FORMAT_ARGS, ((FFformatarg[]){ + FF_FORMAT_ARG(result.version, "version"), + FF_FORMAT_ARG(result.interfaceType, "interface-type"), + })); + } + + ffStrbufDestroy(&result.version); + ffStrbufDestroy(&result.interfaceType); +} + +bool ffParseTPMCommandOptions(FFTPMOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_TPM_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + return false; +} + +void ffParseTPMJsonObject(FFTPMOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + ffPrintError(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + } +} + +void ffGenerateTPMJsonConfig(FFTPMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + __attribute__((__cleanup__(ffDestroyTPMOptions))) FFTPMOptions defaultOptions; + ffInitTPMOptions(&defaultOptions); + + ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); +} + +void ffGenerateTPMJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFTPMResult result = { + .version = ffStrbufCreate(), + .interfaceType = ffStrbufCreate() + }; + const char* error = ffDetectTPM(&result); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "version", &result.version); + yyjson_mut_obj_add_strbuf(doc, obj, "interfaceType", &result.interfaceType); + + ffStrbufDestroy(&result.version); + ffStrbufDestroy(&result.interfaceType); +} + +void ffPrintTPMHelpFormat(void) +{ + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_TPM_MODULE_NAME, "{1} [{2}]", FF_TPM_NUM_FORMAT_ARGS, ((const char* []) { + "TPM device version - version", + "TPM interface type - interface-type", + })); +} + +void ffInitTPMOptions(FFTPMOptions* options) +{ + ffOptionInitModuleBaseInfo( + &options->moduleInfo, + FF_TPM_MODULE_NAME, + "Print info of Trusted Platform Module (TPM) Security Device", + ffParseTPMCommandOptions, + ffParseTPMJsonObject, + ffPrintTPM, + ffGenerateTPMJsonResult, + ffPrintTPMHelpFormat, + ffGenerateTPMJsonConfig + ); + ffOptionInitModuleArg(&options->moduleArgs, "󰔎"); +} + +void ffDestroyTPMOptions(FFTPMOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} diff --git a/src/modules/tpm/tpm.h b/src/modules/tpm/tpm.h new file mode 100644 index 000000000..3356a46dc --- /dev/null +++ b/src/modules/tpm/tpm.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_TPM_MODULE_NAME "TPM" + +void ffPrintTPM(FFTPMOptions* options); +void ffInitTPMOptions(FFTPMOptions* options); +void ffDestroyTPMOptions(FFTPMOptions* options); diff --git a/src/options/modules.c b/src/options/modules.c index 10b6fc627..cea3c7af0 100644 --- a/src/options/modules.c +++ b/src/options/modules.c @@ -63,6 +63,7 @@ void ffOptionsInitModules(FFOptionsModules* options) ffInitTerminalThemeOptions(&options->terminalTheme); ffInitThemeOptions(&options->theme); ffInitTitleOptions(&options->title); + ffInitTPMOptions(&options->tpm); ffInitUptimeOptions(&options->uptime); ffInitUsersOptions(&options->users); ffInitVersionOptions(&options->version); @@ -137,6 +138,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options) ffDestroyTerminalThemeOptions(&options->terminalTheme); ffDestroyThemeOptions(&options->theme); ffDestroyTitleOptions(&options->title); + ffDestroyTPMOptions(&options->tpm); ffDestroyUptimeOptions(&options->uptime); ffDestroyUsersOptions(&options->users); ffDestroyVersionOptions(&options->version); diff --git a/src/options/modules.h b/src/options/modules.h index 7f210be69..919d92408 100644 --- a/src/options/modules.h +++ b/src/options/modules.h @@ -64,6 +64,7 @@ typedef struct FFOptionsModules FFTerminalThemeOptions terminalTheme; FFThemeOptions theme; FFTitleOptions title; + FFTPMOptions tpm; FFUptimeOptions uptime; FFUsersOptions users; FFVersionOptions version;