From 55e042f47cde7b3cf26d859a15db3cb1bdf8674c Mon Sep 17 00:00:00 2001 From: gmh5225 <2315157@qq.com> Date: Sun, 12 Feb 2023 18:52:50 +0800 Subject: [PATCH] Upload --- .clang-format | 101 ++ Driver-SoulExtraction.sln | 49 + Driver-SoulExtraction.vcxproj | 160 +++ Lib-SoulExtraction/Lib-SoulExtraction.vcxproj | 168 +++ .../Lib-SoulExtraction.vcxproj.filters | 101 ++ Lib-SoulExtraction/Lib.SoulExtraction.cpp | 579 ++++++++ Lib-SoulExtraction/Lib.SoulExtraction.h | 14 + Lib-SoulExtraction/linux/asn1.h | 71 + Lib-SoulExtraction/linux/asn1_ber_bytecode.h | 99 ++ Lib-SoulExtraction/linux/asn1_decoder.c | 600 ++++++++ Lib-SoulExtraction/linux/asn1_decoder.h | 24 + Lib-SoulExtraction/linux/asymmetric-type.h | 91 ++ Lib-SoulExtraction/linux/asymmetric_type.c | 635 +++++++++ Lib-SoulExtraction/linux/config.h | 21 + Lib-SoulExtraction/linux/errno-base.h | 40 + Lib-SoulExtraction/linux/errno.h | 157 ++ Lib-SoulExtraction/linux/key.h | 448 ++++++ Lib-SoulExtraction/linux/mscode_parser.c | 296 ++++ Lib-SoulExtraction/linux/oid_registry.c | 404 ++++++ Lib-SoulExtraction/linux/oid_registry.h | 102 ++ Lib-SoulExtraction/linux/pe.h | 478 +++++++ Lib-SoulExtraction/linux/pkcs7.h | 53 + Lib-SoulExtraction/linux/pkcs7_parser.c | 1270 +++++++++++++++++ Lib-SoulExtraction/linux/pkcs7_parser.h | 81 ++ Lib-SoulExtraction/linux/public_key.c | 193 +++ Lib-SoulExtraction/linux/public_key.h | 82 ++ Lib-SoulExtraction/linux/signature.c | 76 + Lib-SoulExtraction/linux/system_keyring.c | 338 +++++ Lib-SoulExtraction/linux/verify_pefile.c | 575 ++++++++ Lib-SoulExtraction/linux/verify_pefile.h | 73 + Lib-SoulExtraction/linux/x509_cert_parser.c | 1213 ++++++++++++++++ Lib-SoulExtraction/linux/x509_parser.h | 114 ++ Lib-SoulExtraction/linux/x509_public_key.c | 304 ++++ .../rewrite/Lib.SoulExtraction.rewrite.c | 180 +++ .../rewrite/Lib.SoulExtraction.rewrite.h | 41 + SoulExtraction.cpp | 19 + 36 files changed, 9250 insertions(+) create mode 100644 .clang-format create mode 100644 Driver-SoulExtraction.sln create mode 100644 Driver-SoulExtraction.vcxproj create mode 100644 Lib-SoulExtraction/Lib-SoulExtraction.vcxproj create mode 100644 Lib-SoulExtraction/Lib-SoulExtraction.vcxproj.filters create mode 100644 Lib-SoulExtraction/Lib.SoulExtraction.cpp create mode 100644 Lib-SoulExtraction/Lib.SoulExtraction.h create mode 100644 Lib-SoulExtraction/linux/asn1.h create mode 100644 Lib-SoulExtraction/linux/asn1_ber_bytecode.h create mode 100644 Lib-SoulExtraction/linux/asn1_decoder.c create mode 100644 Lib-SoulExtraction/linux/asn1_decoder.h create mode 100644 Lib-SoulExtraction/linux/asymmetric-type.h create mode 100644 Lib-SoulExtraction/linux/asymmetric_type.c create mode 100644 Lib-SoulExtraction/linux/config.h create mode 100644 Lib-SoulExtraction/linux/errno-base.h create mode 100644 Lib-SoulExtraction/linux/errno.h create mode 100644 Lib-SoulExtraction/linux/key.h create mode 100644 Lib-SoulExtraction/linux/mscode_parser.c create mode 100644 Lib-SoulExtraction/linux/oid_registry.c create mode 100644 Lib-SoulExtraction/linux/oid_registry.h create mode 100644 Lib-SoulExtraction/linux/pe.h create mode 100644 Lib-SoulExtraction/linux/pkcs7.h create mode 100644 Lib-SoulExtraction/linux/pkcs7_parser.c create mode 100644 Lib-SoulExtraction/linux/pkcs7_parser.h create mode 100644 Lib-SoulExtraction/linux/public_key.c create mode 100644 Lib-SoulExtraction/linux/public_key.h create mode 100644 Lib-SoulExtraction/linux/signature.c create mode 100644 Lib-SoulExtraction/linux/system_keyring.c create mode 100644 Lib-SoulExtraction/linux/verify_pefile.c create mode 100644 Lib-SoulExtraction/linux/verify_pefile.h create mode 100644 Lib-SoulExtraction/linux/x509_cert_parser.c create mode 100644 Lib-SoulExtraction/linux/x509_parser.h create mode 100644 Lib-SoulExtraction/linux/x509_public_key.c create mode 100644 Lib-SoulExtraction/rewrite/Lib.SoulExtraction.rewrite.c create mode 100644 Lib-SoulExtraction/rewrite/Lib.SoulExtraction.rewrite.h create mode 100644 SoulExtraction.cpp diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..4096055 --- /dev/null +++ b/.clang-format @@ -0,0 +1,101 @@ +AccessModifierOffset: -4 +AlignAfterOpenBracket: AlwaysBreak +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: DontAlign +AlignOperands: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: TopLevel +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: false + AfterStruct: true + AfterUnion: true + AfterExternBlock: false + BeforeCatch: true + BeforeElse: true +BreakBeforeBraces: Custom +BreakBeforeBinaryOperators: None +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: AfterColon +BreakStringLiterals: false +ColumnLimit: 120 +CommentPragmas: '^begin_wpp|^end_wpp|^FUNC |^USESUFFIX |^USESUFFIX ' +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +ExperimentalAutoDetectBinPacking: false +IndentCaseLabels: false +IndentPPDirectives: AfterHash +IndentWidth: 4 +KeepEmptyLinesAtTheStartOfBlocks: false +Language: Cpp +MacroBlockBegin: '^BEGIN_MODULE$|^BEGIN_TEST_CLASS$|^BEGIN_TEST_METHOD$' +MacroBlockEnd: '^END_MODULE$|^END_TEST_CLASS$|^END_TEST_METHOD$' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +PointerAlignment: Right +ReflowComments: true +SortIncludes: false +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +StatementMacros: [ + 'EXTERN_C', + 'PAGED', + 'PAGEDX', + 'NONPAGED', + 'PNPCODE', + 'INITCODE', + '_At_', + '_When_', + '_Success_', + '_Check_return_', + '_Must_inspect_result_', + '_IRQL_requires_', + '_IRQL_requires_max_', + '_IRQL_requires_min_', + '_IRQL_saves_', + '_IRQL_restores_', + '_IRQL_saves_global_', + '_IRQL_restores_global_', + '_IRQL_raises_', + '_IRQL_lowers_', + '_Acquires_lock_', + '_Releases_lock_', + '_Acquires_exclusive_lock_', + '_Releases_exclusive_lock_', + '_Acquires_shared_lock_', + '_Releases_shared_lock_', + '_Requires_lock_held_', + '_Use_decl_annotations_', + '_Guarded_by_', + '__drv_preferredFunction', + '__drv_allocatesMem', + '__drv_freesMem', + ] +TabWidth: '4' +UseTab: Never diff --git a/Driver-SoulExtraction.sln b/Driver-SoulExtraction.sln new file mode 100644 index 0000000..61b4b46 --- /dev/null +++ b/Driver-SoulExtraction.sln @@ -0,0 +1,49 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32929.385 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Drv-SoulExtraction", "Driver-SoulExtraction.vcxproj", "{D0686DC0-DACB-4F53-B1EC-5B25432A7E60}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Lib-SoulExtraction", "Lib-SoulExtraction\Lib-SoulExtraction.vcxproj", "{CD112165-BCF9-412E-8F79-3AABDB135A13}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D0686DC0-DACB-4F53-B1EC-5B25432A7E60}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {D0686DC0-DACB-4F53-B1EC-5B25432A7E60}.Debug|ARM64.Build.0 = Debug|ARM64 + {D0686DC0-DACB-4F53-B1EC-5B25432A7E60}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {D0686DC0-DACB-4F53-B1EC-5B25432A7E60}.Debug|x64.ActiveCfg = Debug|x64 + {D0686DC0-DACB-4F53-B1EC-5B25432A7E60}.Debug|x64.Build.0 = Debug|x64 + {D0686DC0-DACB-4F53-B1EC-5B25432A7E60}.Debug|x64.Deploy.0 = Debug|x64 + {D0686DC0-DACB-4F53-B1EC-5B25432A7E60}.Release|ARM64.ActiveCfg = Release|ARM64 + {D0686DC0-DACB-4F53-B1EC-5B25432A7E60}.Release|ARM64.Build.0 = Release|ARM64 + {D0686DC0-DACB-4F53-B1EC-5B25432A7E60}.Release|ARM64.Deploy.0 = Release|ARM64 + {D0686DC0-DACB-4F53-B1EC-5B25432A7E60}.Release|x64.ActiveCfg = Release|x64 + {D0686DC0-DACB-4F53-B1EC-5B25432A7E60}.Release|x64.Build.0 = Release|x64 + {D0686DC0-DACB-4F53-B1EC-5B25432A7E60}.Release|x64.Deploy.0 = Release|x64 + {CD112165-BCF9-412E-8F79-3AABDB135A13}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {CD112165-BCF9-412E-8F79-3AABDB135A13}.Debug|ARM64.Build.0 = Debug|ARM64 + {CD112165-BCF9-412E-8F79-3AABDB135A13}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {CD112165-BCF9-412E-8F79-3AABDB135A13}.Debug|x64.ActiveCfg = Debug|x64 + {CD112165-BCF9-412E-8F79-3AABDB135A13}.Debug|x64.Build.0 = Debug|x64 + {CD112165-BCF9-412E-8F79-3AABDB135A13}.Debug|x64.Deploy.0 = Debug|x64 + {CD112165-BCF9-412E-8F79-3AABDB135A13}.Release|ARM64.ActiveCfg = Release|ARM64 + {CD112165-BCF9-412E-8F79-3AABDB135A13}.Release|ARM64.Build.0 = Release|ARM64 + {CD112165-BCF9-412E-8F79-3AABDB135A13}.Release|ARM64.Deploy.0 = Release|ARM64 + {CD112165-BCF9-412E-8F79-3AABDB135A13}.Release|x64.ActiveCfg = Release|x64 + {CD112165-BCF9-412E-8F79-3AABDB135A13}.Release|x64.Build.0 = Release|x64 + {CD112165-BCF9-412E-8F79-3AABDB135A13}.Release|x64.Deploy.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4203A5A1-B37E-42A0-AA64-62B2184B7ABA} + EndGlobalSection +EndGlobal diff --git a/Driver-SoulExtraction.vcxproj b/Driver-SoulExtraction.vcxproj new file mode 100644 index 0000000..5a3cf42 --- /dev/null +++ b/Driver-SoulExtraction.vcxproj @@ -0,0 +1,160 @@ + + + + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + + + + {D0686DC0-DACB-4F53-B1EC-5B25432A7E60} + {1bc93793-694f-48fe-9372-81e2b05556fd} + v4.5 + 12.0 + Debug + x64 + Driver_SoulExtraction + Drv-SoulExtraction + $(LatestTargetPlatformVersion) + + + + Windows10 + true + LLVM-MSVC_v143_KernelMode + Driver + KMDF + Universal + false + + + Windows10 + false + LLVM-MSVC_v143_KernelMode + Driver + KMDF + Universal + false + + + Windows10 + true + LLVM-MSVC_v143_KernelMode + Driver + KMDF + Universal + + + Windows10 + false + LLVM-MSVC_v143_KernelMode + Driver + KMDF + Universal + + + + + + + + + + + DbgengKernelDebugger + $(SolutionDir)Output + obj_$(PlatformArchitecture)\$(ConfigurationName)\ + + + DbgengKernelDebugger + $(SolutionDir)Output + obj_$(PlatformArchitecture)\$(ConfigurationName)\ + + + DbgengKernelDebugger + + + DbgengKernelDebugger + + + + sha256 + + + false + + + false + Level3 + false + + + false + DriverEntry + + + + + sha256 + + + false + + + false + Level3 + false + + + false + DriverEntry + + + + + sha256 + + + false + + + false + Level3 + false + + + + + sha256 + + + false + + + false + Level3 + false + + + + + + + + + + + + \ No newline at end of file diff --git a/Lib-SoulExtraction/Lib-SoulExtraction.vcxproj b/Lib-SoulExtraction/Lib-SoulExtraction.vcxproj new file mode 100644 index 0000000..be1c8d7 --- /dev/null +++ b/Lib-SoulExtraction/Lib-SoulExtraction.vcxproj @@ -0,0 +1,168 @@ + + + + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + + + + {CD112165-BCF9-412E-8F79-3AABDB135A13} + {1bc93793-694f-48fe-9372-81e2b05556fd} + v4.5 + 12.0 + Debug + x64 + Lib_SoulExtraction + $(LatestTargetPlatformVersion) + + + + Windows10 + true + LLVM-MSVC_v143_KernelMode + StaticLibrary + KMDF + Universal + false + + + Windows10 + false + LLVM-MSVC_v143_KernelMode + StaticLibrary + KMDF + Universal + false + + + Windows10 + true + LLVM-MSVC_v143_KernelMode + StaticLibrary + KMDF + Universal + + + Windows10 + false + LLVM-MSVC_v143_KernelMode + StaticLibrary + KMDF + Universal + + + + + + + + + + + DbgengKernelDebugger + $(SolutionDir)Output + obj_$(PlatformArchitecture)\$(ConfigurationName)\ + $(TargetName.Replace(' ',''))_$(Configuration)_$(PlatformArchitecture) + + + DbgengKernelDebugger + $(SolutionDir)Output + obj_$(PlatformArchitecture)\$(ConfigurationName)\ + $(TargetName.Replace(' ',''))_$(Configuration)_$(PlatformArchitecture) + + + DbgengKernelDebugger + + + DbgengKernelDebugger + + + + sha256 + + + false + + + false + Level3 + false + + + + + sha256 + + + false + + + false + Level3 + false + + + + + sha256 + + + + + sha256 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Lib-SoulExtraction/Lib-SoulExtraction.vcxproj.filters b/Lib-SoulExtraction/Lib-SoulExtraction.vcxproj.filters new file mode 100644 index 0000000..fcf49ca --- /dev/null +++ b/Lib-SoulExtraction/Lib-SoulExtraction.vcxproj.filters @@ -0,0 +1,101 @@ + + + + + {dfa2a449-d195-41f6-9061-1cddd0d53459} + + + {ff838198-8354-4f87-9c88-5d00dd0ae098} + + + + + rewrite + + + linux + + + linux + + + linux + + + linux + + + linux + + + linux + + + linux + + + linux + + + linux + + + linux + + + linux + + + + + + rewrite + + + linux + + + linux + + + linux + + + linux + + + linux + + + linux + + + linux + + + linux + + + linux + + + linux + + + linux + + + linux + + + linux + + + linux + + + linux + + + + \ No newline at end of file diff --git a/Lib-SoulExtraction/Lib.SoulExtraction.cpp b/Lib-SoulExtraction/Lib.SoulExtraction.cpp new file mode 100644 index 0000000..19ebfc0 --- /dev/null +++ b/Lib-SoulExtraction/Lib.SoulExtraction.cpp @@ -0,0 +1,579 @@ +#include + +#include "Lib.SoulExtraction.h" +extern "C" { +#include "linux\verify_pefile.h" +} + +__forceinline size_t +_strlen_a(const char *s) +{ + char *s0 = (char *)s; + + if (s == 0) + return 0; + + while (*s != 0) + s++; + + return (s - s0); +} + +__forceinline size_t +_strlen_w(const wchar_t *s) +{ + wchar_t *s0 = (wchar_t *)s; + + if (s == 0) + return 0; + + while (*s != 0) + s++; + + return (s - s0); +} + +__forceinline size_t +ultostr_a(unsigned long x, char *s) +{ + unsigned long t = x; + size_t i, r = 1; + + while (t >= 10) + { + t /= 10; + r++; + } + + if (s == 0) + return r; + + for (i = r; i != 0; i--) + { + s[i - 1] = (char)(x % 10) + '0'; + x /= 10; + } + + s[r] = (char)0; + return r; +} + +__forceinline char * +_strcat_a(char *dest, const char *src) +{ + if ((dest == 0) || (src == 0)) + return dest; + + while (*dest != 0) + dest++; + + while (*src != 0) + { + *dest = *src; + dest++; + src++; + } + + *dest = 0; + return dest; +} + +__forceinline int +_isdigit_w(wchar_t x) +{ + return ((x >= L'0') && (x <= L'9')); +} + +__forceinline unsigned long long +strtou64_a(char *s) +{ + unsigned long long a = 0; + char c; + + if (s == 0) + return 0; + + while (*s != 0) + { + c = *s; + if (_isdigit_w(c)) + a = (a * 10) + (c - '0'); + else + break; + s++; + } + return a; +} + +namespace LibSoulExtraction { + +#define SIGN_NOT_3RDPARTY_TAG (19) // Non-third-party tag is 19. May not be correct +#define SIGN_MAIN_SIG_AKID_SIZE (24) // The size of the main signature is usually 24. It may not be right + +static bool +IsUTF8(char *Buffer, unsigned long Size, bool ExcludeAscii /*= true*/) +{ + bool b_utf8 = true; + bool b_ascii = true; + + unsigned char *start = (unsigned char *)Buffer; + unsigned char *end = (unsigned char *)Buffer + Size; + + while (start < end) + { + if ((*start & 0x80) != 0) + { + b_ascii = false; + } + + if (*start < 0x80) + { + start += 1; + } + else if (*start < (0xC0)) + { + b_utf8 = false; + + break; + } + else if (*start < (0xE0)) + { + if (start >= end - 1) + { + break; + } + + if ((start[1] & (0xC0)) != 0x80) + { + b_utf8 = false; + + break; + } + + start += 2; + } + else if (*start < (0xF0)) + { + if (start >= end - 2) + { + break; + } + + if ((start[1] & (0xC0)) != 0x80 || (start[2] & (0xC0)) != 0x80) + { + b_utf8 = false; + + break; + } + + start += 3; + } + else + { + b_utf8 = false; + + break; + } + } + + if (ExcludeAscii) + { + if (b_ascii) + { + b_utf8 = false; + } + } + + return b_utf8; +} + +unsigned long long +MakeTime(unsigned long Year, unsigned long Mon, unsigned long Day, unsigned long Hour, unsigned long Min) +{ + char c_year[5]; + char c_mon[5]; + char c_day[5]; + char c_hour[5]; + char c_min[5]; + + char c_all[20]; + + RtlSecureZeroMemory(c_year, sizeof(c_year)); + RtlSecureZeroMemory(c_mon, sizeof(c_mon)); + RtlSecureZeroMemory(c_day, sizeof(c_day)); + RtlSecureZeroMemory(c_hour, sizeof(c_hour)); + RtlSecureZeroMemory(c_min, sizeof(c_min)); + RtlSecureZeroMemory(c_all, sizeof(c_all)); + + ultostr_a(Year, c_year); + ultostr_a(Mon, c_mon); + ultostr_a(Day, c_day); + ultostr_a(Hour, c_hour); + ultostr_a(Min, c_min); + + if (c_mon[1] == 0) + { + c_mon[1] = c_mon[0]; + c_mon[0] = '0'; + } + + if (c_day[1] == 0) + { + c_day[1] = c_day[0]; + c_day[0] = '0'; + } + + if (c_hour[1] == 0) + { + c_hour[1] = c_hour[0]; + c_hour[0] = '0'; + } + + if (c_min[1] == 0) + { + c_min[1] = c_min[0]; + c_min[0] = '0'; + } + + _strcat_a(c_all, c_year); + _strcat_a(c_all, c_mon); + _strcat_a(c_all, c_day); + _strcat_a(c_all, c_hour); + _strcat_a(c_all, c_min); + + return strtou64_a(c_all); +} + +static NTSTATUS +UTF8ToUnicodeN(PWSTR uni_dest, ULONG uni_bytes_max, PULONG uni_bytes_written, PCCH utf8_src, ULONG utf8_bytes) +{ + NTSTATUS status; + ULONG i, j; + ULONG written; + ULONG ch; + ULONG utf8_trail_bytes; + WCHAR utf16_ch[3]; + ULONG utf16_ch_len; + + if (!utf8_src) + return STATUS_INVALID_PARAMETER_4; + if (!uni_bytes_written) + return STATUS_INVALID_PARAMETER; + + written = 0; + status = STATUS_SUCCESS; + + for (i = 0; i < utf8_bytes; i++) + { + /* read UTF-8 lead byte */ + ch = (unsigned char)utf8_src[i]; + utf8_trail_bytes = 0; + if (ch >= 0xf5) + { + ch = 0xfffd; + status = STATUS_SOME_NOT_MAPPED; + } + else if (ch >= 0xf0) + { + ch &= 0x07; + utf8_trail_bytes = 3; + } + else if (ch >= 0xe0) + { + ch &= 0x0f; + utf8_trail_bytes = 2; + } + else if (ch >= 0xc2) + { + ch &= 0x1f; + utf8_trail_bytes = 1; + } + else if (ch >= 0x80) + { + /* overlong or trail byte */ + ch = 0xfffd; + status = STATUS_SOME_NOT_MAPPED; + } + + /* read UTF-8 trail bytes */ + if (i + utf8_trail_bytes < utf8_bytes) + { + for (j = 0; j < utf8_trail_bytes; j++) + { + if ((utf8_src[i + 1] & 0xc0) == 0x80) + { + ch <<= 6; + ch |= utf8_src[i + 1] & 0x3f; + i++; + } + else + { + ch = 0xfffd; + utf8_trail_bytes = 0; + status = STATUS_SOME_NOT_MAPPED; + break; + } + } + } + else + { + ch = 0xfffd; + utf8_trail_bytes = 0; + status = STATUS_SOME_NOT_MAPPED; + i = utf8_bytes; + } + + /* encode ch as UTF-16 */ + if ((ch > 0x10ffff) || (ch >= 0xd800 && ch <= 0xdfff) || (utf8_trail_bytes == 2 && ch < 0x00800) || + (utf8_trail_bytes == 3 && ch < 0x10000)) + { + /* invalid codepoint or overlong encoding */ + utf16_ch[0] = 0xfffd; + utf16_ch[1] = 0xfffd; + utf16_ch[2] = 0xfffd; + utf16_ch_len = utf8_trail_bytes; + status = STATUS_SOME_NOT_MAPPED; + } + else if (ch >= 0x10000) + { + /* surrogate pair */ + ch -= 0x010000; + utf16_ch[0] = 0xd800 + (ch >> 10 & 0x3ff); + utf16_ch[1] = 0xdc00 + (ch >> 0 & 0x3ff); + utf16_ch_len = 2; + } + else + { + /* single unit */ + utf16_ch[0] = (WCHAR)ch; + utf16_ch_len = 1; + } + + if (!uni_dest) + { + written += utf16_ch_len; + continue; + } + + for (j = 0; j < utf16_ch_len; j++) + { + if (uni_bytes_max >= sizeof(WCHAR)) + { + *uni_dest++ = utf16_ch[j]; + uni_bytes_max -= sizeof(WCHAR); + written++; + } + else + { + uni_bytes_max = 0; + status = STATUS_BUFFER_TOO_SMALL; + } + } + } + + *uni_bytes_written = written * sizeof(WCHAR); + return status; +} + +static bool +IsMainCert( + /*IN*/ struct pkcs7_message *Pkcs7, + /*OUT*/ struct x509_certificate **MainCert) +{ + if (!Pkcs7 || !MainCert) + { + return false; + } + + bool b_ismain = false; + + // Up to 10 cycles, let's say up to 10 certificates + + auto cert = Pkcs7->certs; + for (int i = 0; i < 10; ++i) + { + if (cert && MmIsAddressValid(cert)) + { + auto subject_tag = cert->subject_tag; + if (subject_tag != SIGN_NOT_3RDPARTY_TAG) + { + b_ismain = true; + break; + } + cert = cert->next; + } + } + + if (b_ismain) + { + if (cert->subject && MmIsAddressValid(cert->subject)) + { + *MainCert = cert; + } + else + { + b_ismain = false; + } + } + else + { + // Get the maximum length of the X509 fingerprint ID is generally the main signature (the regular look out, may + // not be allowed) + + cert = Pkcs7->certs; + + struct x509_certificate *find_cert = NULL; + unsigned short max_idlen = 0; + for (int i = 0; i < 10; ++i) + { + if (cert && MmIsAddressValid(cert)) + { + auto idlen = cert->id->len; + if (idlen > max_idlen) + { + max_idlen = idlen; + find_cert = cert; + } + cert = cert->next; + } + } + + if (find_cert && MmIsAddressValid(find_cert)) + { + auto raw_akid_size = find_cert->raw_akid_size; + if (raw_akid_size == SIGN_MAIN_SIG_AKID_SIZE) + { + if (find_cert->subject && MmIsAddressValid(find_cert->subject)) + { + *MainCert = find_cert; + b_ismain = true; + } + } + } + } + + return b_ismain; +} + +bool +GetMainCertInfo( + /*IN*/ void *PeBuf, + /*IN*/ unsigned long PeBufLen, + /*OUT*/ char *CertName, + /*IN*/ unsigned long CertNameMaxSize, + /*OUT OPTIONAL*/ unsigned long long *ValidFromTime, + /*OUT OPTIONAL*/ unsigned long long *ValidToTime) +{ + if (!PeBuf || !CertName || !PeBufLen || !CertNameMaxSize) + { + return false; + } + + if (!MmIsAddressValid(PeBuf)) + { + return false; + } + + struct pefile_context ctx; + int ret; + + RtlSecureZeroMemory(&ctx, sizeof(ctx)); + + ret = pefile_parse_binary(PeBuf, PeBufLen, &ctx); + if (ret < 0) + { + return false; + } + + ret = pefile_strip_sig_wrapper(PeBuf, &ctx); + if (ret < 0) + { + return false; + } + + if (!ctx.sig_offset) + { + return false; + } + if (!ctx.sig_len) + { + return false; + } + + auto pstart = (PUCHAR)PeBuf + ctx.sig_offset; + if (!MmIsAddressValid(pstart)) + { + return false; + } + + auto pkcs7 = pkcs7_parse_message(pstart, ctx.sig_len); + if (!(pkcs7 && MmIsAddressValid(pkcs7))) + { + return false; + } + + struct x509_certificate *main_cert = NULL; + auto bret = IsMainCert(pkcs7, &main_cert); + do + { + if (!(bret && main_cert)) + { + break; + } + + auto subject = main_cert->subject; + auto subject_len = (unsigned long)strlen(subject); + if (IsUTF8(subject, subject_len, true)) + { + wchar_t utf16[_MAX_PATH + sizeof(wchar_t)]; + + RtlSecureZeroMemory(utf16, _MAX_PATH + sizeof(wchar_t)); + auto ns = UTF8ToUTF16(subject, subject_len, utf16, _MAX_PATH); + if (NT_SUCCESS(ns)) + { + char ascii[_MAX_PATH + sizeof(char)]; + auto utf16_len = (unsigned long)_strlen_w(utf16); + + RtlSecureZeroMemory(ascii, _MAX_PATH + sizeof(char)); + + ns = UTF16ToAscii(utf16, utf16_len, ascii, _MAX_PATH); + if (NT_SUCCESS(ns)) + { + auto ascii_len = (unsigned long)_strlen_a(ascii); + memcpy(CertName, ascii, min(ascii_len, CertNameMaxSize)); + } + } + } + else + { + memcpy(CertName, subject, min(subject_len, CertNameMaxSize)); + } + + if (ValidFromTime) + { + *ValidFromTime = MakeTime( + main_cert->valid_from_year, + main_cert->valid_from_mon, + main_cert->valid_from_day, + main_cert->valid_from_hour, + main_cert->valid_from_min); + } + + if (ValidToTime) + { + *ValidToTime = MakeTime( + main_cert->valid_to_year, + main_cert->valid_to_mon, + main_cert->valid_to_day, + main_cert->valid_to_hour, + main_cert->valid_to_min); + } + + } while (0); + + pkcs7_free_message(pkcs7); + + return bret; +} + +} // namespace LibSoulExtraction diff --git a/Lib-SoulExtraction/Lib.SoulExtraction.h b/Lib-SoulExtraction/Lib.SoulExtraction.h new file mode 100644 index 0000000..1b2ea42 --- /dev/null +++ b/Lib-SoulExtraction/Lib.SoulExtraction.h @@ -0,0 +1,14 @@ +#pragma once + +namespace LibSoulExtraction { + +bool +GetMainCertInfo( + /*IN*/ void *PeBuf, + /*IN*/ unsigned long PeBufLen, + /*OUT*/ char *CertName, + /*IN*/ unsigned long CertNameMaxSize, + /*OUT OPTIONAL*/ unsigned long long *ValidFromTime, + /*OUT OPTIONAL*/ unsigned long long *ValidToTime); + +} diff --git a/Lib-SoulExtraction/linux/asn1.h b/Lib-SoulExtraction/linux/asn1.h new file mode 100644 index 0000000..8177a3d --- /dev/null +++ b/Lib-SoulExtraction/linux/asn1.h @@ -0,0 +1,71 @@ +/* ASN.1 BER/DER/CER encoding definitions + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _LINUX_ASN1_H +#define _LINUX_ASN1_H + +/* Class */ +enum asn1_class +{ + ASN1_UNIV = 0, /* Universal */ + ASN1_APPL = 1, /* Application */ + ASN1_CONT = 2, /* Context */ + ASN1_PRIV = 3 /* Private */ +}; +#define ASN1_CLASS_BITS 0xc0 + +enum asn1_method +{ + ASN1_PRIM = 0, /* Primitive */ + ASN1_CONS = 1 /* Constructed */ +}; +#define ASN1_CONS_BIT 0x20 + +/* Tag */ +enum asn1_tag +{ + ASN1_EOC = 0, /* End Of Contents or N/A */ + ASN1_BOOL = 1, /* Boolean */ + ASN1_INT = 2, /* Integer */ + ASN1_BTS = 3, /* Bit String */ + ASN1_OTS = 4, /* Octet String */ + ASN1_NULL = 5, /* Null */ + ASN1_OID = 6, /* Object Identifier */ + ASN1_ODE = 7, /* Object Description */ + ASN1_EXT = 8, /* External */ + ASN1_REAL = 9, /* Real float */ + ASN1_ENUM = 10, /* Enumerated */ + ASN1_EPDV = 11, /* Embedded PDV */ + ASN1_UTF8STR = 12, /* UTF8 String */ + ASN1_RELOID = 13, /* Relative OID */ + /* 14 - Reserved */ + /* 15 - Reserved */ + ASN1_SEQ = 16, /* Sequence and Sequence of */ + ASN1_SET = 17, /* Set and Set of */ + ASN1_NUMSTR = 18, /* Numerical String */ + ASN1_PRNSTR = 19, /* Printable String */ + ASN1_TEXSTR = 20, /* T61 String / Teletext String */ + ASN1_VIDSTR = 21, /* Videotex String */ + ASN1_IA5STR = 22, /* IA5 String */ + ASN1_UNITIM = 23, /* Universal Time */ + ASN1_GENTIM = 24, /* General Time */ + ASN1_GRASTR = 25, /* Graphic String */ + ASN1_VISSTR = 26, /* Visible String */ + ASN1_GENSTR = 27, /* General String */ + ASN1_UNISTR = 28, /* Universal String */ + ASN1_CHRSTR = 29, /* Character String */ + ASN1_BMPSTR = 30, /* BMP String */ + ASN1_LONG_TAG = 31 /* Long form tag */ +}; + +#define ASN1_INDEFINITE_LENGTH 0x80 + +#endif /* _LINUX_ASN1_H */ diff --git a/Lib-SoulExtraction/linux/asn1_ber_bytecode.h b/Lib-SoulExtraction/linux/asn1_ber_bytecode.h new file mode 100644 index 0000000..e4c9877 --- /dev/null +++ b/Lib-SoulExtraction/linux/asn1_ber_bytecode.h @@ -0,0 +1,99 @@ +/* ASN.1 BER/DER/CER parsing state machine internal definitions + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _LINUX_ASN1_BER_BYTECODE_H +#define _LINUX_ASN1_BER_BYTECODE_H + +//#ifdef __KERNEL__ +//#include +//#endif +//#include + +#include + +typedef int (*asn1_action_t)( + void *context, + size_t hdrlen, /* In case of ANY type */ + unsigned char tag, /* In case of ANY type */ + const void *value, + size_t vlen); + +struct asn1_decoder +{ + const unsigned char *machine; + size_t machlen; + const asn1_action_t *actions; +}; + +enum asn1_opcode +{ +/* The tag-matching ops come first and the odd-numbered slots + * are for OR_SKIP ops. + */ +#define ASN1_OP_MATCH__SKIP 0x01 +#define ASN1_OP_MATCH__ACT 0x02 +#define ASN1_OP_MATCH__JUMP 0x04 +#define ASN1_OP_MATCH__ANY 0x08 +#define ASN1_OP_MATCH__COND 0x10 + + ASN1_OP_MATCH = 0x00, + ASN1_OP_MATCH_OR_SKIP = 0x01, + ASN1_OP_MATCH_ACT = 0x02, + ASN1_OP_MATCH_ACT_OR_SKIP = 0x03, + ASN1_OP_MATCH_JUMP = 0x04, + ASN1_OP_MATCH_JUMP_OR_SKIP = 0x05, + ASN1_OP_MATCH_ANY = 0x08, + ASN1_OP_MATCH_ANY_OR_SKIP = 0x09, + ASN1_OP_MATCH_ANY_ACT = 0x0a, + ASN1_OP_MATCH_ANY_ACT_OR_SKIP = 0x0b, + /* Everything before here matches unconditionally */ + + ASN1_OP_COND_MATCH_OR_SKIP = 0x11, + ASN1_OP_COND_MATCH_ACT_OR_SKIP = 0x13, + ASN1_OP_COND_MATCH_JUMP_OR_SKIP = 0x15, + ASN1_OP_COND_MATCH_ANY = 0x18, + ASN1_OP_COND_MATCH_ANY_OR_SKIP = 0x19, + ASN1_OP_COND_MATCH_ANY_ACT = 0x1a, + ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP = 0x1b, + +/* Everything before here will want a tag from the data */ +#define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP + + /* These are here to help fill up space */ + ASN1_OP_COND_FAIL = 0x1c, + ASN1_OP_COMPLETE = 0x1d, + ASN1_OP_ACT = 0x1e, + ASN1_OP_MAYBE_ACT = 0x1f, + + /* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */ + ASN1_OP_END_SEQ = 0x20, + ASN1_OP_END_SET = 0x21, + ASN1_OP_END_SEQ_OF = 0x22, + ASN1_OP_END_SET_OF = 0x23, + ASN1_OP_END_SEQ_ACT = 0x24, + ASN1_OP_END_SET_ACT = 0x25, + ASN1_OP_END_SEQ_OF_ACT = 0x26, + ASN1_OP_END_SET_OF_ACT = 0x27, +#define ASN1_OP_END__SET 0x01 +#define ASN1_OP_END__OF 0x02 +#define ASN1_OP_END__ACT 0x04 + + ASN1_OP_RETURN = 0x28, + + ASN1_OP__NR +}; + +#define _tag(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | ASN1_##TAG) +#define _tagn(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | TAG) +#define _jump_target(N) (N) +#define _action(N) (N) + +#endif /* _LINUX_ASN1_BER_BYTECODE_H */ diff --git a/Lib-SoulExtraction/linux/asn1_decoder.c b/Lib-SoulExtraction/linux/asn1_decoder.c new file mode 100644 index 0000000..d1069c3 --- /dev/null +++ b/Lib-SoulExtraction/linux/asn1_decoder.c @@ -0,0 +1,600 @@ +/* Decoder for ASN.1 BER/DER/CER encoded bytestream + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +//#include +//#include +//#include +//#include +//#include +//#include + +#include "errno.h" +#include "asn1_ber_bytecode.h" +#include "asn1.h" + +// +// macro +// + +//#define pr_debug DbgPrint +//#define pr_devel DbgPrint +//#define pr_err DbgPrint + +#define pr_debug +#define pr_devel +#define pr_err + +#define GFP_ATOMIC /*(__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)*/ 1 +#define GFP_KERNEL /*(__GFP_RECLAIM | __GFP_IO | __GFP_FS)*/ 2 +#define GFP_KERNEL_ACCOUNT /*(GFP_KERNEL | __GFP_ACCOUNT)*/ 3 +#define GFP_NOWAIT /*(__GFP_KSWAPD_RECLAIM)*/ 4 +#define GFP_NOIO /*(__GFP_RECLAIM)*/ 5 +#define GFP_NOFS /*(__GFP_RECLAIM | __GFP_IO)*/ 6 +#define GFP_USER /*(__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL)*/ 7 +#define GFP_DMA /*__GFP_DMA*/ 8 +#define GFP_DMA32 /*__GFP_DMA32*/ 9 +#define GFP_HIGHUSER /*(GFP_USER | __GFP_HIGHMEM)*/ 10 +#define GFP_HIGHUSER_MOVABLE /*(GFP_HIGHUSER | __GFP_MOVABLE)*/ 11 +#define GFP_TRANSHUGE_LIGHT 12 +#define GFP_TRANSHUGE /*(GFP_TRANSHUGE_LIGHT | __GFP_DIRECT_RECLAIM)*/ 13 + +#define unlikely(a) (a) + +static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { + /* OPC TAG JMP ACT */ + [ASN1_OP_MATCH] = 1 + 1, + [ASN1_OP_MATCH_OR_SKIP] = 1 + 1, + [ASN1_OP_MATCH_ACT] = 1 + 1 + 1, + [ASN1_OP_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, + [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1, + [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, + [ASN1_OP_MATCH_ANY] = 1, + [ASN1_OP_MATCH_ANY_OR_SKIP] = 1, + [ASN1_OP_MATCH_ANY_ACT] = 1 + 1, + [ASN1_OP_MATCH_ANY_ACT_OR_SKIP] = 1 + 1, + [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1, + [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, + [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, + [ASN1_OP_COND_MATCH_ANY] = 1, + [ASN1_OP_COND_MATCH_ANY_OR_SKIP] = 1, + [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1, + [ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP] = 1 + 1, + [ASN1_OP_COND_FAIL] = 1, + [ASN1_OP_COMPLETE] = 1, + [ASN1_OP_ACT] = 1 + 1, + [ASN1_OP_MAYBE_ACT] = 1 + 1, + [ASN1_OP_RETURN] = 1, + [ASN1_OP_END_SEQ] = 1, + [ASN1_OP_END_SEQ_OF] = 1 + 1, + [ASN1_OP_END_SET] = 1, + [ASN1_OP_END_SET_OF] = 1 + 1, + [ASN1_OP_END_SEQ_ACT] = 1 + 1, + [ASN1_OP_END_SEQ_OF_ACT] = 1 + 1 + 1, + [ASN1_OP_END_SET_ACT] = 1 + 1, + [ASN1_OP_END_SET_OF_ACT] = 1 + 1 + 1, +}; + +/* + * Find the length of an indefinite length object + * @data: The data buffer + * @datalen: The end of the innermost containing element in the buffer + * @_dp: The data parse cursor (updated before returning) + * @_len: Where to return the size of the element. + * @_errmsg: Where to return a pointer to an error message on error + */ +static int +asn1_find_indefinite_length(const unsigned char *data, size_t datalen, size_t *_dp, size_t *_len, const char **_errmsg) +{ + unsigned char tag, tmp; + size_t dp = *_dp, len, n; + int indef_level = 1; + +next_tag: + if (unlikely(datalen - dp < 2)) + { + if (datalen == dp) + goto missing_eoc; + goto data_overrun_error; + } + + /* Extract a tag from the data */ + tag = data[dp++]; + if (tag == ASN1_EOC) + { + /* It appears to be an EOC. */ + if (data[dp++] != 0) + goto invalid_eoc; + if (--indef_level <= 0) + { + *_len = dp - *_dp; + *_dp = dp; + return 0; + } + goto next_tag; + } + + if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) + { + do + { + if (unlikely(datalen - dp < 2)) + goto data_overrun_error; + tmp = data[dp++]; + } while (tmp & 0x80); + } + + /* Extract the length */ + len = data[dp++]; + if (len <= 0x7f) + goto check_length; + + if (unlikely(len == ASN1_INDEFINITE_LENGTH)) + { + /* Indefinite length */ + if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5)) + goto indefinite_len_primitive; + indef_level++; + goto next_tag; + } + + n = len - 0x80; + if (unlikely(n > sizeof(len) - 1)) + goto length_too_long; + if (unlikely(n > datalen - dp)) + goto data_overrun_error; + len = 0; + for (; n > 0; n--) + { + len <<= 8; + len |= data[dp++]; + } +check_length: + if (len > datalen - dp) + goto data_overrun_error; + dp += len; + goto next_tag; + +length_too_long: + /**_errmsg = "Unsupported length";*/ + *_errmsg = "UI"; + goto error; +indefinite_len_primitive: + /**_errmsg = "Indefinite len primitive not permitted";*/ + *_errmsg = "ILPNP"; + goto error; +invalid_eoc: + /**_errmsg = "Invalid length EOC";*/ + *_errmsg = "ILE"; + goto error; +data_overrun_error: + /**_errmsg = "Data overrun error";*/ + *_errmsg = "DOE"; + goto error; +missing_eoc: + /**_errmsg = "Missing EOC in indefinite len cons";*/ + *_errmsg = "MEIILC"; +error: + *_dp = dp; + return -1; +} + +/** + * asn1_ber_decoder - Decoder BER/DER/CER ASN.1 according to pattern + * @decoder: The decoder definition (produced by asn1_compiler) + * @context: The caller's context (to be passed to the action functions) + * @data: The encoded data + * @datalen: The size of the encoded data + * + * Decode BER/DER/CER encoded ASN.1 data according to a bytecode pattern + * produced by asn1_compiler. Action functions are called on marked tags to + * allow the caller to retrieve significant data. + * + * LIMITATIONS: + * + * To keep down the amount of stack used by this function, the following limits + * have been imposed: + * + * (1) This won't handle datalen > 65535 without increasing the size of the + * cons stack elements and length_too_long checking. + * + * (2) The stack of constructed types is 10 deep. If the depth of non-leaf + * constructed types exceeds this, the decode will fail. + * + * (3) The SET type (not the SET OF type) isn't really supported as tracking + * what members of the set have been seen is a pain. + */ +int +asn1_ber_decoder(const struct asn1_decoder *decoder, void *context, const unsigned char *data, size_t datalen) +{ + const unsigned char *machine = decoder->machine; + const asn1_action_t *actions = decoder->actions; + size_t machlen = decoder->machlen; + enum asn1_opcode op; + unsigned char tag = 0, csp = 0, jsp = 0, optag = 0, hdr = 0; + const char *errmsg; + size_t pc = 0, dp = 0, tdp = 0, len = 0; + int ret; + + unsigned char flags = 0; +#define FLAG_INDEFINITE_LENGTH 0x01 +#define FLAG_MATCHED 0x02 +#define FLAG_LAST_MATCHED 0x04 /* Last tag matched */ +#define FLAG_CONS \ + 0x20 /* Corresponds to CONS bit in the opcode tag \ + * - ie. whether or not we are going to parse \ + * a compound type. \ + */ + +#define NR_CONS_STACK 10 + unsigned short cons_dp_stack[NR_CONS_STACK]; + unsigned short cons_datalen_stack[NR_CONS_STACK]; + unsigned char cons_hdrlen_stack[NR_CONS_STACK]; +#define NR_JUMP_STACK 10 + unsigned char jump_stack[NR_JUMP_STACK]; + + if (datalen > 65535) + return -EMSGSIZE; + +next_op: + /*pr_debug("next_op: pc=\e[32m%zu\e[m/%zu dp=\e[33m%zu\e[m/%zu C=%d J=%d\n", + pc, machlen, dp, datalen, csp, jsp);*/ + if (unlikely(pc >= machlen)) + goto machine_overrun_error; + op = machine[pc]; + if (unlikely(pc + asn1_op_lengths[op] > machlen)) + goto machine_overrun_error; + + /* If this command is meant to match a tag, then do that before + * evaluating the command. + */ + if (op <= ASN1_OP__MATCHES_TAG) + { + unsigned char tmp; + + /* Skip conditional matches if possible */ + if ((op & ASN1_OP_MATCH__COND && flags & FLAG_MATCHED) || (op & ASN1_OP_MATCH__SKIP && dp == datalen)) + { + flags &= ~FLAG_LAST_MATCHED; + pc += asn1_op_lengths[op]; + goto next_op; + } + + flags = 0; + hdr = 2; + + /* Extract a tag from the data */ + if (unlikely(datalen - dp < 2)) + goto data_overrun_error; + tag = data[dp++]; + if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) + goto long_tag_not_supported; + + if (op & ASN1_OP_MATCH__ANY) + { + pr_debug("- any %02x\n", tag); + } + else + { + /* Extract the tag from the machine + * - Either CONS or PRIM are permitted in the data if + * CONS is not set in the op stream, otherwise CONS + * is mandatory. + */ + optag = machine[pc + 1]; + flags |= optag & FLAG_CONS; + + /* Determine whether the tag matched */ + tmp = optag ^ tag; + tmp &= ~(optag & ASN1_CONS_BIT); + pr_debug("- match? %02x %02x %02x\n", tag, optag, tmp); + if (tmp != 0) + { + /* All odd-numbered tags are MATCH_OR_SKIP. */ + if (op & ASN1_OP_MATCH__SKIP) + { + pc += asn1_op_lengths[op]; + dp--; + goto next_op; + } + goto tag_mismatch; + } + } + flags |= FLAG_MATCHED; + + len = data[dp++]; + if (len > 0x7f) + { + if (unlikely(len == ASN1_INDEFINITE_LENGTH)) + { + /* Indefinite length */ + if (unlikely(!(tag & ASN1_CONS_BIT))) + goto indefinite_len_primitive; + flags |= FLAG_INDEFINITE_LENGTH; + if (unlikely(2 > datalen - dp)) + goto data_overrun_error; + } + else + { + unsigned char n = (unsigned char)len - 0x80; + if (unlikely(n > 2)) + goto length_too_long; + if (unlikely(n > datalen - dp)) + goto data_overrun_error; + hdr += n; + for (len = 0; n > 0; n--) + { + len <<= 8; + len |= data[dp++]; + } + if (unlikely(len > datalen - dp)) + goto data_overrun_error; + } + } + else + { + if (unlikely(len > datalen - dp)) + goto data_overrun_error; + } + + if (flags & FLAG_CONS) + { + /* For expected compound forms, we stack the positions + * of the start and end of the data. + */ + if (unlikely(csp >= NR_CONS_STACK)) + goto cons_stack_overflow; + cons_dp_stack[csp] = dp; + cons_hdrlen_stack[csp] = hdr; + if (!(flags & FLAG_INDEFINITE_LENGTH)) + { + cons_datalen_stack[csp] = datalen; + datalen = dp + len; + } + else + { + cons_datalen_stack[csp] = 0; + } + csp++; + } + + pr_debug("- TAG: %02x %u %d %s\n", tag, len, flags & FLAG_CONS ? " CONS" : ""); + tdp = dp; + } + + /* Decide how to handle the operation */ + switch (op) + { + case ASN1_OP_MATCH: + case ASN1_OP_MATCH_OR_SKIP: + case ASN1_OP_MATCH_ACT: + case ASN1_OP_MATCH_ACT_OR_SKIP: + case ASN1_OP_MATCH_ANY: + case ASN1_OP_MATCH_ANY_OR_SKIP: + case ASN1_OP_MATCH_ANY_ACT: + case ASN1_OP_MATCH_ANY_ACT_OR_SKIP: + case ASN1_OP_COND_MATCH_OR_SKIP: + case ASN1_OP_COND_MATCH_ACT_OR_SKIP: + case ASN1_OP_COND_MATCH_ANY: + case ASN1_OP_COND_MATCH_ANY_OR_SKIP: + case ASN1_OP_COND_MATCH_ANY_ACT: + case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP: + + if (!(flags & FLAG_CONS)) + { + if (flags & FLAG_INDEFINITE_LENGTH) + { + size_t tmp = dp; + + ret = asn1_find_indefinite_length(data, datalen, &tmp, &len, &errmsg); + if (ret < 0) + goto error; + } + pr_debug("- LEAF: %zu\n", len); + } + + if (op & ASN1_OP_MATCH__ACT) + { + unsigned char act; + + if (op & ASN1_OP_MATCH__ANY) + act = machine[pc + 1]; + else + act = machine[pc + 2]; + ret = actions[act](context, hdr, tag, data + dp, len); + if (ret < 0) + return ret; + } + + if (!(flags & FLAG_CONS)) + dp += len; + pc += asn1_op_lengths[op]; + goto next_op; + + case ASN1_OP_MATCH_JUMP: + case ASN1_OP_MATCH_JUMP_OR_SKIP: + case ASN1_OP_COND_MATCH_JUMP_OR_SKIP: + pr_debug("- MATCH_JUMP\n"); + if (unlikely(jsp == NR_JUMP_STACK)) + goto jump_stack_overflow; + jump_stack[jsp++] = pc + asn1_op_lengths[op]; + pc = machine[pc + 2]; + goto next_op; + + case ASN1_OP_COND_FAIL: + if (unlikely(!(flags & FLAG_MATCHED))) + goto tag_mismatch; + pc += asn1_op_lengths[op]; + goto next_op; + + case ASN1_OP_COMPLETE: + if (unlikely(jsp != 0 || csp != 0)) + { + pr_err("ASN.1 decoder error: Stacks not empty at completion (%u, %u)\n", jsp, csp); + return -EBADMSG; + } + return 0; + + case ASN1_OP_END_SET: + case ASN1_OP_END_SET_ACT: + if (unlikely(!(flags & FLAG_MATCHED))) + goto tag_mismatch; + case ASN1_OP_END_SEQ: + case ASN1_OP_END_SET_OF: + case ASN1_OP_END_SEQ_OF: + case ASN1_OP_END_SEQ_ACT: + case ASN1_OP_END_SET_OF_ACT: + case ASN1_OP_END_SEQ_OF_ACT: + if (unlikely(csp <= 0)) + goto cons_stack_underflow; + csp--; + tdp = cons_dp_stack[csp]; + hdr = cons_hdrlen_stack[csp]; + len = datalen; + datalen = cons_datalen_stack[csp]; + pr_debug("- end cons t=%zu dp=%zu l=%zu/%zu\n", tdp, dp, len, datalen); + if (datalen == 0) + { + /* Indefinite length - check for the EOC. */ + datalen = len; + if (unlikely(datalen - dp < 2)) + goto data_overrun_error; + if (data[dp++] != 0) + { + if (op & ASN1_OP_END__OF) + { + dp--; + csp++; + pc = machine[pc + 1]; + pr_debug("- continue\n"); + goto next_op; + } + goto missing_eoc; + } + if (data[dp++] != 0) + goto invalid_eoc; + len = dp - tdp - 2; + } + else + { + if (dp < len && (op & ASN1_OP_END__OF)) + { + datalen = len; + csp++; + pc = machine[pc + 1]; + pr_debug("- continue\n"); + goto next_op; + } + if (dp != len) + goto cons_length_error; + len -= tdp; + pr_debug("- cons len l=%zu d=%zu\n", len, dp - tdp); + } + + if (op & ASN1_OP_END__ACT) + { + unsigned char act; + if (op & ASN1_OP_END__OF) + act = machine[pc + 2]; + else + act = machine[pc + 1]; + ret = actions[act](context, hdr, 0, data + tdp, len); + if (ret < 0) + return ret; + } + pc += asn1_op_lengths[op]; + goto next_op; + + case ASN1_OP_MAYBE_ACT: + if (!(flags & FLAG_LAST_MATCHED)) + { + pc += asn1_op_lengths[op]; + goto next_op; + } + case ASN1_OP_ACT: + ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len); + if (ret < 0) + return ret; + pc += asn1_op_lengths[op]; + goto next_op; + + case ASN1_OP_RETURN: + if (unlikely(jsp <= 0)) + goto jump_stack_underflow; + pc = jump_stack[--jsp]; + flags |= FLAG_MATCHED | FLAG_LAST_MATCHED; + goto next_op; + + default: + break; + } + + /* Shouldn't reach here */ + pr_err("ASN.1 decoder error: Found reserved opcode (%u) pc=%zu\n", op, pc); + return -EBADMSG; + +data_overrun_error: + /*errmsg = "Data overrun error";*/ + errmsg = "DOE"; + goto error; +machine_overrun_error: + /*errmsg = "Machine overrun error";*/ + errmsg = "MOE"; + goto error; +jump_stack_underflow: + /*errmsg = "Jump stack underflow";*/ + errmsg = "JSU"; + goto error; +jump_stack_overflow: + /*errmsg = "Jump stack overflow";*/ + errmsg = "JSO"; + goto error; +cons_stack_underflow: + /*errmsg = "Cons stack underflow";*/ + errmsg = "CSU"; + goto error; +cons_stack_overflow: + /*errmsg = "Cons stack overflow";*/ + errmsg = "CSO"; + goto error; +cons_length_error: + /*errmsg = "Cons length error";*/ + errmsg = "CLE"; + goto error; +missing_eoc: + /*errmsg = "Missing EOC in indefinite len cons";*/ + errmsg = "MEIILC"; + goto error; +invalid_eoc: + /*errmsg = "Invalid length EOC";*/ + errmsg = "ILE"; + goto error; +length_too_long: + /*errmsg = "Unsupported length";*/ + errmsg = "UL"; + goto error; +indefinite_len_primitive: + /*errmsg = "Indefinite len primitive not permitted";*/ + errmsg = "ILPNP"; + goto error; +tag_mismatch: + /*errmsg = "Unexpected tag";*/ + errmsg = "UT"; + goto error; +long_tag_not_supported: + /*errmsg = "Long tag not supported";*/ + errmsg = "LTNS"; +error: + pr_debug("\nASN1: %s [m=%zu d=%zu ot=%02x t=%02x l=%zu]\n", errmsg, pc, dp, optag, tag, len); + return -EBADMSG; +} +// EXPORT_SYMBOL_GPL(asn1_ber_decoder); + +// MODULE_LICENSE("GPL"); diff --git a/Lib-SoulExtraction/linux/asn1_decoder.h b/Lib-SoulExtraction/linux/asn1_decoder.h new file mode 100644 index 0000000..cc84a97 --- /dev/null +++ b/Lib-SoulExtraction/linux/asn1_decoder.h @@ -0,0 +1,24 @@ +/* ASN.1 decoder + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _LINUX_ASN1_DECODER_H +#define _LINUX_ASN1_DECODER_H + +//#include + +#include "asn1_ber_bytecode.h" + +// struct asn1_decoder; + +extern int +asn1_ber_decoder(const struct asn1_decoder *decoder, void *context, const unsigned char *data, size_t datalen); + +#endif /* _LINUX_ASN1_DECODER_H */ diff --git a/Lib-SoulExtraction/linux/asymmetric-type.h b/Lib-SoulExtraction/linux/asymmetric-type.h new file mode 100644 index 0000000..a751cd1 --- /dev/null +++ b/Lib-SoulExtraction/linux/asymmetric-type.h @@ -0,0 +1,91 @@ +/* Asymmetric Public-key cryptography key type interface + * + * See Documentation/security/asymmetric-keys.txt + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _KEYS_ASYMMETRIC_TYPE_H +#define _KEYS_ASYMMETRIC_TYPE_H + +//#include +//#include + +#include + +// extern struct key_type key_type_asymmetric; + +/* + * The key payload is four words. The asymmetric-type key uses them as + * follows: + */ +enum asymmetric_payload_bits +{ + asym_crypto, /* The data representing the key */ + asym_subtype, /* Pointer to an asymmetric_key_subtype struct */ + asym_key_ids, /* Pointer to an asymmetric_key_ids struct */ + asym_auth /* The key's authorisation (signature, parent key ID) */ +}; + +/* + * Identifiers for an asymmetric key ID. We have three ways of looking up a + * key derived from an X.509 certificate: + * + * (1) Serial Number & Issuer. Non-optional. This is the only valid way to + * map a PKCS#7 signature to an X.509 certificate. + * + * (2) Issuer & Subject Unique IDs. Optional. These were the original way to + * match X.509 certificates, but have fallen into disuse in favour of (3). + * + * (3) Auth & Subject Key Identifiers. Optional. SKIDs are only provided on + * CA keys that are intended to sign other keys, so don't appear in end + * user certificates unless forced. + * + * We could also support an PGP key identifier, which is just a SHA1 sum of the + * public key and certain parameters, but since we don't support PGP keys at + * the moment, we shall ignore those. + * + * What we actually do is provide a place where binary identifiers can be + * stashed and then compare against them when checking for an id match. + */ +struct asymmetric_key_id +{ + unsigned short len; + unsigned char data[1]; +}; + +struct asymmetric_key_ids +{ + void *id[2]; +}; + +extern unsigned char +asymmetric_key_id_same(const struct asymmetric_key_id *kid1, const struct asymmetric_key_id *kid2); + +// extern bool asymmetric_key_id_partial(const struct asymmetric_key_id *kid1, +// const struct asymmetric_key_id *kid2); + +extern struct asymmetric_key_id * +asymmetric_key_generate_id(const void *val_1, size_t len_1, const void *val_2, size_t len_2); +// static inline +// const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key) +//{ +// return key->payload.data[asym_key_ids]; +// } + +// extern struct key *find_asymmetric_key(struct key *keyring, +// const struct asymmetric_key_id *id_0, +// const struct asymmetric_key_id *id_1, +// bool partial); + +/* + * The payload is at the discretion of the subtype. + */ + +#endif /* _KEYS_ASYMMETRIC_TYPE_H */ diff --git a/Lib-SoulExtraction/linux/asymmetric_type.c b/Lib-SoulExtraction/linux/asymmetric_type.c new file mode 100644 index 0000000..d94b802 --- /dev/null +++ b/Lib-SoulExtraction/linux/asymmetric_type.c @@ -0,0 +1,635 @@ +/* Asymmetric public-key cryptography key type + * + * See Documentation/security/asymmetric-keys.txt + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include "asymmetric_keys.h" +// +// MODULE_LICENSE("GPL"); + +#include "asymmetric-type.h" +#include "errno.h" + +#include "../rewrite/Lib.SoulExtraction.rewrite.h" + +#include "config.h" + +#define GFP_ATOMIC /*(__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)*/ 1 +#define GFP_KERNEL /*(__GFP_RECLAIM | __GFP_IO | __GFP_FS)*/ 2 +#define GFP_KERNEL_ACCOUNT /*(GFP_KERNEL | __GFP_ACCOUNT)*/ 3 +#define GFP_NOWAIT /*(__GFP_KSWAPD_RECLAIM)*/ 4 +#define GFP_NOIO /*(__GFP_RECLAIM)*/ 5 +#define GFP_NOFS /*(__GFP_RECLAIM | __GFP_IO)*/ 6 +#define GFP_USER /*(__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL)*/ 7 +#define GFP_DMA /*__GFP_DMA*/ 8 +#define GFP_DMA32 /*__GFP_DMA32*/ 9 +#define GFP_HIGHUSER /*(GFP_USER | __GFP_HIGHMEM)*/ 10 +#define GFP_HIGHUSER_MOVABLE /*(GFP_HIGHUSER | __GFP_MOVABLE)*/ 11 +#define GFP_TRANSHUGE_LIGHT 12 +#define GFP_TRANSHUGE /*(GFP_TRANSHUGE_LIGHT | __GFP_DIRECT_RECLAIM)*/ 13 + +#define ERR_PTR(err) ((void *)((long)(err))) +#define PTR_ERR(ptr) ((long)(ptr)) +#define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000)) + +// const char *const key_being_used_for[NR__KEY_BEING_USED_FOR] = { +// [VERIFYING_MODULE_SIGNATURE] = "mod sig", +// [VERIFYING_FIRMWARE_SIGNATURE] = "firmware sig", +// [VERIFYING_KEXEC_PE_SIGNATURE] = "kexec PE sig", +// [VERIFYING_KEY_SIGNATURE] = "key sig", +// [VERIFYING_KEY_SELF_SIGNATURE] = "key self sig", +// [VERIFYING_UNSPECIFIED_SIGNATURE] = "unspec sig", +// }; +// EXPORT_SYMBOL_GPL(key_being_used_for); +// +// static LIST_HEAD(asymmetric_key_parsers); +// static DECLARE_RWSEM(asymmetric_key_parsers_sem); + +/** + * find_asymmetric_key - Find a key by ID. + * @keyring: The keys to search. + * @id_0: The first ID to look for or NULL. + * @id_1: The second ID to look for or NULL. + * @partial: Use partial match if true, exact if false. + * + * Find a key in the given keyring by identifier. The preferred identifier is + * the id_0 and the fallback identifier is the id_1. If both are given, the + * lookup is by the former, but the latter must also match. + */ +// struct key *find_asymmetric_key(struct key *keyring, +// const struct asymmetric_key_id *id_0, +// const struct asymmetric_key_id *id_1, +// bool partial) +//{ +// struct key *key; +// key_ref_t ref; +// const char *lookup; +// char *req, *p; +// int len; +// +// BUG_ON(!id_0 && !id_1); +// +// if (id_0) { +// lookup = id_0->data; +// len = id_0->len; +// } else { +// lookup = id_1->data; +// len = id_1->len; +// } +// +// /* Construct an identifier "id:". */ +// p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL); +// if (!req) +// return ERR_PTR(-ENOMEM); +// +// if (partial) { +// *p++ = 'i'; +// *p++ = 'd'; +// } else { +// *p++ = 'e'; +// *p++ = 'x'; +// } +// *p++ = ':'; +// p = bin2hex(p, lookup, len); +// *p = 0; +// +// pr_debug("Look up: \"%s\"\n", req); +// +// ref = keyring_search(make_key_ref(keyring, 1), +// &key_type_asymmetric, req); +// if (IS_ERR(ref)) +// pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref)); +// kfree(req); +// +// if (IS_ERR(ref)) { +// switch (PTR_ERR(ref)) { +// /* Hide some search errors */ +// case -EACCES: +// case -ENOTDIR: +// case -EAGAIN: +// return ERR_PTR(-ENOKEY); +// default: +// return ERR_CAST(ref); +// } +// } +// +// key = key_ref_to_ptr(ref); +// if (id_0 && id_1) { +// const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); +// +// if (!kids->id[1]) { +// pr_debug("First ID matches, but second is missing\n"); +// goto reject; +// } +// if (!asymmetric_key_id_same(id_1, kids->id[1])) { +// pr_debug("First ID matches, but second does not\n"); +// goto reject; +// } +// } +// +// pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key)); +// return key; +// +// reject: +// key_put(key); +// return ERR_PTR(-EKEYREJECTED); +// } +// EXPORT_SYMBOL_GPL(find_asymmetric_key); + +/** + * asymmetric_key_generate_id: Construct an asymmetric key ID + * @val_1: First binary blob + * @len_1: Length of first binary blob + * @val_2: Second binary blob + * @len_2: Length of second binary blob + * + * Construct an asymmetric key ID from a pair of binary blobs. + */ +struct asymmetric_key_id * +asymmetric_key_generate_id(const void *val_1, size_t len_1, const void *val_2, size_t len_2) +{ + struct asymmetric_key_id *kid; + + kid = kmalloc(sizeof(struct asymmetric_key_id) + len_1 + len_2, GFP_KERNEL); + if (!kid) + return ERR_PTR(-ENOMEM); + kid->len = len_1 + len_2; + memcpy(kid->data, val_1, len_1); + memcpy(kid->data + len_1, val_2, len_2); + return kid; +} +// EXPORT_SYMBOL_GPL(asymmetric_key_generate_id); + +/** + * asymmetric_key_id_same - Return true if two asymmetric keys IDs are the same. + * @kid_1, @kid_2: The key IDs to compare + */ +unsigned char +asymmetric_key_id_same(const struct asymmetric_key_id *kid1, const struct asymmetric_key_id *kid2) +{ + if (!kid1 || !kid2) + return FALSE; + if (kid1->len != kid2->len) + return FALSE; + return memcmp(kid1->data, kid2->data, kid1->len) == 0; +} +// EXPORT_SYMBOL_GPL(asymmetric_key_id_same); + +/** + * asymmetric_key_id_partial - Return true if two asymmetric keys IDs + * partially match + * @kid_1, @kid_2: The key IDs to compare + */ +// bool asymmetric_key_id_partial(const struct asymmetric_key_id *kid1, +// const struct asymmetric_key_id *kid2) +//{ +// if (!kid1 || !kid2) +// return false; +// if (kid1->len < kid2->len) +// return false; +// return memcmp(kid1->data + (kid1->len - kid2->len), +// kid2->data, kid2->len) == 0; +// } +// EXPORT_SYMBOL_GPL(asymmetric_key_id_partial); + +/** + * asymmetric_match_key_ids - Search asymmetric key IDs + * @kids: The list of key IDs to check + * @match_id: The key ID we're looking for + * @match: The match function to use + */ +// static bool asymmetric_match_key_ids( +// const struct asymmetric_key_ids *kids, +// const struct asymmetric_key_id *match_id, +// bool (*match)(const struct asymmetric_key_id *kid1, +// const struct asymmetric_key_id *kid2)) +//{ +// int i; +// +// if (!kids || !match_id) +// return false; +// for (i = 0; i < ARRAY_SIZE(kids->id); i++) +// if (match(kids->id[i], match_id)) +// return true; +// return false; +// } + +/* helper function can be called directly with pre-allocated memory */ +// inline int __asymmetric_key_hex_to_key_id(const char *id, +// struct asymmetric_key_id *match_id, +// size_t hexlen) +//{ +// match_id->len = hexlen; +// return hex2bin(match_id->data, id, hexlen); +// } + +/** + * asymmetric_key_hex_to_key_id - Convert a hex string into a key ID. + * @id: The ID as a hex string. + */ +// struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id) +//{ +// struct asymmetric_key_id *match_id; +// size_t asciihexlen; +// int ret; +// +// if (!*id) +// return ERR_PTR(-EINVAL); +// asciihexlen = strlen(id); +// if (asciihexlen & 1) +// return ERR_PTR(-EINVAL); +// +// match_id = kmalloc(sizeof(struct asymmetric_key_id) + asciihexlen / 2, +// GFP_KERNEL); +// if (!match_id) +// return ERR_PTR(-ENOMEM); +// ret = __asymmetric_key_hex_to_key_id(id, match_id, asciihexlen / 2); +// if (ret < 0) { +// kfree(match_id); +// return ERR_PTR(-EINVAL); +// } +// return match_id; +// } + +/* + * Match asymmetric keys by an exact match on an ID. + */ +// static bool asymmetric_key_cmp(const struct key *key, +// const struct key_match_data *match_data) +//{ +// const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); +// const struct asymmetric_key_id *match_id = match_data->preparsed; +// +// return asymmetric_match_key_ids(kids, match_id, +// asymmetric_key_id_same); +// } + +/* + * Match asymmetric keys by a partial match on an IDs. + */ +// static bool asymmetric_key_cmp_partial(const struct key *key, +// const struct key_match_data *match_data) +//{ +// const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); +// const struct asymmetric_key_id *match_id = match_data->preparsed; +// +// return asymmetric_match_key_ids(kids, match_id, +// asymmetric_key_id_partial); +// } + +/* + * Preparse the match criterion. If we don't set lookup_type and cmp, + * the default will be an exact match on the key description. + * + * There are some specifiers for matching key IDs rather than by the key + * description: + * + * "id:" - find a key by partial match on any available ID + * "ex:" - find a key by exact match on any available ID + * + * These have to be searched by iteration rather than by direct lookup because + * the key is hashed according to its description. + */ +// static int asymmetric_key_match_preparse(struct key_match_data *match_data) +//{ +// struct asymmetric_key_id *match_id; +// const char *spec = match_data->raw_data; +// const char *id; +// bool (*cmp)(const struct key *, const struct key_match_data *) = +// asymmetric_key_cmp; +// +// if (!spec || !*spec) +// return -EINVAL; +// if (spec[0] == 'i' && +// spec[1] == 'd' && +// spec[2] == ':') { +// id = spec + 3; +// cmp = asymmetric_key_cmp_partial; +// } else if (spec[0] == 'e' && +// spec[1] == 'x' && +// spec[2] == ':') { +// id = spec + 3; +// } else { +// goto default_match; +// } +// +// match_id = asymmetric_key_hex_to_key_id(id); +// if (IS_ERR(match_id)) +// return PTR_ERR(match_id); +// +// match_data->preparsed = match_id; +// match_data->cmp = cmp; +// match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE; +// return 0; +// +// default_match: +// return 0; +// } + +/* + * Free the preparsed the match criterion. + */ +// static void asymmetric_key_match_free(struct key_match_data *match_data) +//{ +// kfree(match_data->preparsed); +// } + +/* + * Describe the asymmetric key + */ +// static void asymmetric_key_describe(const struct key *key, struct seq_file *m) +//{ +// const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); +// const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); +// const struct asymmetric_key_id *kid; +// const unsigned char *p; +// int n; +// +// seq_puts(m, key->description); +// +// if (subtype) { +// seq_puts(m, ": "); +// subtype->describe(key, m); +// +// if (kids && kids->id[1]) { +// kid = kids->id[1]; +// seq_putc(m, ' '); +// n = kid->len; +// p = kid->data; +// if (n > 4) { +// p += n - 4; +// n = 4; +// } +// seq_printf(m, "%p", n, p); +// } +// +// seq_puts(m, " ["); +// /* put something here to indicate the key's capabilities */ +// seq_putc(m, ']'); +// } +// } + +/* + * Preparse a asymmetric payload to get format the contents appropriately for the + * internal payload to cut down on the number of scans of the data performed. + * + * We also generate a proposed description from the contents of the key that + * can be used to name the key if the user doesn't want to provide one. + */ +// static int asymmetric_key_preparse(struct key_preparsed_payload *prep) +//{ +// struct asymmetric_key_parser *parser; +// int ret; +// +// pr_devel("==>%s()\n", __func__); +// +// if (prep->datalen == 0) +// return -EINVAL; +// +// down_read(&asymmetric_key_parsers_sem); +// +// ret = -EBADMSG; +// list_for_each_entry(parser, &asymmetric_key_parsers, link) { +// pr_debug("Trying parser '%s'\n", parser->name); +// +// ret = parser->parse(prep); +// if (ret != -EBADMSG) { +// pr_debug("Parser recognised the format (ret %d)\n", +// ret); +// break; +// } +// } +// +// up_read(&asymmetric_key_parsers_sem); +// pr_devel("<==%s() = %d\n", __func__, ret); +// return ret; +// } + +/* + * Clean up the key ID list + */ +// static void asymmetric_key_free_kids(struct asymmetric_key_ids *kids) +//{ +// int i; +// +// if (kids) { +// for (i = 0; i < ARRAY_SIZE(kids->id); i++) +// kfree(kids->id[i]); +// kfree(kids); +// } +// } + +/* + * Clean up the preparse data + */ +// static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) +//{ +// struct asymmetric_key_subtype *subtype = prep->payload.data[asym_subtype]; +// struct asymmetric_key_ids *kids = prep->payload.data[asym_key_ids]; +// +// pr_devel("==>%s()\n", __func__); +// +// if (subtype) { +// subtype->destroy(prep->payload.data[asym_crypto], +// prep->payload.data[asym_auth]); +// module_put(subtype->owner); +// } +// asymmetric_key_free_kids(kids); +// kfree(prep->description); +// } + +/* + * dispose of the data dangling from the corpse of a asymmetric key + */ +// static void asymmetric_key_destroy(struct key *key) +//{ +// struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); +// struct asymmetric_key_ids *kids = key->payload.data[asym_key_ids]; +// void *data = key->payload.data[asym_crypto]; +// void *auth = key->payload.data[asym_auth]; +// +// key->payload.data[asym_crypto] = NULL; +// key->payload.data[asym_subtype] = NULL; +// key->payload.data[asym_key_ids] = NULL; +// key->payload.data[asym_auth] = NULL; +// +// if (subtype) { +// subtype->destroy(data, auth); +// module_put(subtype->owner); +// } +// +// asymmetric_key_free_kids(kids); +// } + +// static struct key_restriction *asymmetric_restriction_alloc( +// key_restrict_link_func_t check, +// struct key *key) +//{ +// struct key_restriction *keyres = +// kzalloc(sizeof(struct key_restriction), GFP_KERNEL); +// +// if (!keyres) +// return ERR_PTR(-ENOMEM); +// +// keyres->check = check; +// keyres->key = key; +// keyres->keytype = &key_type_asymmetric; +// +// return keyres; +// } + +/* + * look up keyring restrict functions for asymmetric keys + */ +// static struct key_restriction *asymmetric_lookup_restriction( +// const char *restriction) +//{ +// char *restrict_method; +// char *parse_buf; +// char *next; +// struct key_restriction *ret = ERR_PTR(-EINVAL); +// +// if (strcmp("builtin_trusted", restriction) == 0) +// return asymmetric_restriction_alloc( +// restrict_link_by_builtin_trusted, NULL); +// +// if (strcmp("builtin_and_secondary_trusted", restriction) == 0) +// return asymmetric_restriction_alloc( +// restrict_link_by_builtin_and_secondary_trusted, NULL); +// +// parse_buf = kstrndup(restriction, PAGE_SIZE, GFP_KERNEL); +// if (!parse_buf) +// return ERR_PTR(-ENOMEM); +// +// next = parse_buf; +// restrict_method = strsep(&next, ":"); +// +// if ((strcmp(restrict_method, "key_or_keyring") == 0) && next) { +// char *key_text; +// key_serial_t serial; +// struct key *key; +// key_restrict_link_func_t link_fn = +// restrict_link_by_key_or_keyring; +// bool allow_null_key = false; +// +// key_text = strsep(&next, ":"); +// +// if (next) { +// if (strcmp(next, "chain") != 0) +// goto out; +// +// link_fn = restrict_link_by_key_or_keyring_chain; +// allow_null_key = true; +// } +// +// if (kstrtos32(key_text, 0, &serial) < 0) +// goto out; +// +// if ((serial == 0) && allow_null_key) { +// key = NULL; +// } else { +// key = key_lookup(serial); +// if (IS_ERR(key)) { +// ret = ERR_CAST(key); +// goto out; +// } +// } +// +// ret = asymmetric_restriction_alloc(link_fn, key); +// if (IS_ERR(ret)) +// key_put(key); +// } +// +// out: +// kfree(parse_buf); +// return ret; +// } + +// struct key_type key_type_asymmetric = { +// .name = "asymmetric", +// .preparse = asymmetric_key_preparse, +// .free_preparse = asymmetric_key_free_preparse, +// .instantiate = generic_key_instantiate, +// .match_preparse = asymmetric_key_match_preparse, +// .match_free = asymmetric_key_match_free, +// .destroy = asymmetric_key_destroy, +// .describe = asymmetric_key_describe, +// .lookup_restriction = asymmetric_lookup_restriction, +// }; +// EXPORT_SYMBOL_GPL(key_type_asymmetric); + +/** + * register_asymmetric_key_parser - Register a asymmetric key blob parser + * @parser: The parser to register + */ +// int register_asymmetric_key_parser(struct asymmetric_key_parser *parser) +//{ +// struct asymmetric_key_parser *cursor; +// int ret; +// +// down_write(&asymmetric_key_parsers_sem); +// +// list_for_each_entry(cursor, &asymmetric_key_parsers, link) { +// if (strcmp(cursor->name, parser->name) == 0) { +// pr_err("Asymmetric key parser '%s' already registered\n", +// parser->name); +// ret = -EEXIST; +// goto out; +// } +// } +// +// list_add_tail(&parser->link, &asymmetric_key_parsers); +// +// pr_notice("Asymmetric key parser '%s' registered\n", parser->name); +// ret = 0; +// +// out: +// up_write(&asymmetric_key_parsers_sem); +// return ret; +// } +// EXPORT_SYMBOL_GPL(register_asymmetric_key_parser); + +/** + * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser + * @parser: The parser to unregister + */ +// void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser) +//{ +// down_write(&asymmetric_key_parsers_sem); +// list_del(&parser->link); +// up_write(&asymmetric_key_parsers_sem); +// +// pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name); +// } +// EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser); + +/* + * Module stuff + */ +// static int __init asymmetric_key_init(void) +//{ +// return register_key_type(&key_type_asymmetric); +// } +// +// static void __exit asymmetric_key_cleanup(void) +//{ +// unregister_key_type(&key_type_asymmetric); +// } +// +// module_init(asymmetric_key_init); +// module_exit(asymmetric_key_cleanup); diff --git a/Lib-SoulExtraction/linux/config.h b/Lib-SoulExtraction/linux/config.h new file mode 100644 index 0000000..a7dae64 --- /dev/null +++ b/Lib-SoulExtraction/linux/config.h @@ -0,0 +1,21 @@ +#pragma once + +//#define usedbg + +#ifdef usedbg + +# define pr_debug DbgPrint +# define pr_devel DbgPrint +# define pr_err DbgPrint +# define pr_warn DbgPrint +# define printk DbgPrint + +#else + +# define pr_debug +# define pr_devel +# define pr_err +# define pr_warn +# define printk + +#endif // usedbg diff --git a/Lib-SoulExtraction/linux/errno-base.h b/Lib-SoulExtraction/linux/errno-base.h new file mode 100644 index 0000000..e209919 --- /dev/null +++ b/Lib-SoulExtraction/linux/errno-base.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _ASM_GENERIC_ERRNO_BASE_H +#define _ASM_GENERIC_ERRNO_BASE_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ + +#endif diff --git a/Lib-SoulExtraction/linux/errno.h b/Lib-SoulExtraction/linux/errno.h new file mode 100644 index 0000000..aae9ba0 --- /dev/null +++ b/Lib-SoulExtraction/linux/errno.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _ALPHA_ERRNO_H +#define _ALPHA_ERRNO_H + +#include "errno-base.h" + +#undef EAGAIN /* 11 in errno-base.h */ + +#define EDEADLK 11 /* Resource deadlock would occur */ + +#define EAGAIN 35 /* Try again */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define EINPROGRESS 36 /* Operation now in progress */ +#define EALREADY 37 /* Operation already in progress */ +#define ENOTSOCK 38 /* Socket operation on non-socket */ +#define EDESTADDRREQ 39 /* Destination address required */ +#define EMSGSIZE 40 /* Message too long */ +#define EPROTOTYPE 41 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 42 /* Protocol not available */ +#define EPROTONOSUPPORT 43 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 44 /* Socket type not supported */ +#define EOPNOTSUPP 45 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 46 /* Protocol family not supported */ +#define EAFNOSUPPORT 47 /* Address family not supported by protocol */ +#define EADDRINUSE 48 /* Address already in use */ +#define EADDRNOTAVAIL 49 /* Cannot assign requested address */ +#define ENETDOWN 50 /* Network is down */ +#define ENETUNREACH 51 /* Network is unreachable */ +#define ENETRESET 52 /* Network dropped connection because of reset */ +#define ECONNABORTED 53 /* Software caused connection abort */ +#define ECONNRESET 54 /* Connection reset by peer */ +#define ENOBUFS 55 /* No buffer space available */ +#define EISCONN 56 /* Transport endpoint is already connected */ +#define ENOTCONN 57 /* Transport endpoint is not connected */ +#define ESHUTDOWN 58 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 59 /* Too many references: cannot splice */ +#define ETIMEDOUT 60 /* Connection timed out */ +#define ECONNREFUSED 61 /* Connection refused */ +#define ELOOP 62 /* Too many symbolic links encountered */ +#define ENAMETOOLONG 63 /* File name too long */ +#define EHOSTDOWN 64 /* Host is down */ +#define EHOSTUNREACH 65 /* No route to host */ +#define ENOTEMPTY 66 /* Directory not empty */ + +#define EUSERS 68 /* Too many users */ +#define EDQUOT 69 /* Quota exceeded */ +#define ESTALE 70 /* Stale file handle */ +#define EREMOTE 71 /* Object is remote */ + +#define ENOLCK 77 /* No record locks available */ +#define ENOSYS 78 /* Function not implemented */ + +#define ENOMSG 80 /* No message of desired type */ +#define EIDRM 81 /* Identifier removed */ +#define ENOSR 82 /* Out of streams resources */ +#define ETIME 83 /* Timer expired */ +#define EBADMSG 84 /* Not a data message */ +#define EPROTO 85 /* Protocol error */ +#define ENODATA 86 /* No data available */ +#define ENOSTR 87 /* Device not a stream */ + +#define ENOPKG 92 /* Package not installed */ + +#define EILSEQ 116 /* Illegal byte sequence */ + +/* The following are just random noise.. */ +#define ECHRNG 88 /* Channel number out of range */ +#define EL2NSYNC 89 /* Level 2 not synchronized */ +#define EL3HLT 90 /* Level 3 halted */ +#define EL3RST 91 /* Level 3 reset */ + +#define ELNRNG 93 /* Link number out of range */ +#define EUNATCH 94 /* Protocol driver not attached */ +#define ENOCSI 95 /* No CSI structure available */ +#define EL2HLT 96 /* Level 2 halted */ +#define EBADE 97 /* Invalid exchange */ +#define EBADR 98 /* Invalid request descriptor */ +#define EXFULL 99 /* Exchange full */ +#define ENOANO 100 /* No anode */ +#define EBADRQC 101 /* Invalid request code */ +#define EBADSLT 102 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 104 /* Bad font file format */ +#define ENONET 105 /* Machine is not on the network */ +#define ENOLINK 106 /* Link has been severed */ +#define EADV 107 /* Advertise error */ +#define ESRMNT 108 /* Srmount error */ +#define ECOMM 109 /* Communication error on send */ +#define EMULTIHOP 110 /* Multihop attempted */ +#define EDOTDOT 111 /* RFS specific error */ +#define EOVERFLOW 112 /* Value too large for defined data type */ +#define ENOTUNIQ 113 /* Name not unique on network */ +#define EBADFD 114 /* File descriptor in bad state */ +#define EREMCHG 115 /* Remote address changed */ + +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ + +#define ELIBACC 122 /* Can not access a needed shared library */ +#define ELIBBAD 123 /* Accessing a corrupted shared library */ +#define ELIBSCN 124 /* .lib section in a.out corrupted */ +#define ELIBMAX 125 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 126 /* Cannot exec a shared library directly */ +#define ERESTART 127 /* Interrupted system call should be restarted */ +#define ESTRPIPE 128 /* Streams pipe error */ + +#define ENOMEDIUM 129 /* No medium found */ +#define EMEDIUMTYPE 130 /* Wrong medium type */ +#define ECANCELED 131 /* Operation Cancelled */ +#define ENOKEY 132 /* Required key not available */ +#define EKEYEXPIRED 133 /* Key has expired */ +#define EKEYREVOKED 134 /* Key has been revoked */ +#define EKEYREJECTED 135 /* Key was rejected by service */ + +/* for robust mutexes */ +#define EOWNERDEAD 136 /* Owner died */ +#define ENOTRECOVERABLE 137 /* State not recoverable */ + +#define ERFKILL 138 /* Operation not possible due to RF-kill */ + +#define EHWPOISON 139 /* Memory page has hardware error */ + +//×·¼ÓµÄ + +/* + * These should never be seen by user programs. To return one of ERESTART* + * codes, signal_pending() MUST be set. Note that ptrace can observe these + * at syscall exit tracing, but they will never be left for the debugged user + * process to see. + */ +#define ERESTARTSYS 512 +#define ERESTARTNOINTR 513 +#define ERESTARTNOHAND 514 /* restart if no handler.. */ +#define ENOIOCTLCMD 515 /* No ioctl command */ +#define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */ +#define EPROBE_DEFER 517 /* Driver requests probe retry */ +#define EOPENSTALE 518 /* open found a stale dentry */ +#define ENOPARAM 519 /* Parameter not supported */ + +/* Defined for the NFSv3 protocol */ +#define EBADHANDLE 521 /* Illegal NFS file handle */ +#define ENOTSYNC 522 /* Update synchronization mismatch */ +#define EBADCOOKIE 523 /* Cookie is stale */ +#define ENOTSUPP 524 /* Operation is not supported */ +#define ETOOSMALL 525 /* Buffer or request is too small */ +#define ESERVERFAULT 526 /* An untranslatable error occurred */ +#define EBADTYPE 527 /* Type not supported by server */ +#define EJUKEBOX 528 /* Request initiated, but will not complete before timeout */ +#define EIOCBQUEUED 529 /* iocb queued, will get completion event */ +#define ERECALLCONFLICT 530 /* conflict with recalled state */ + +#endif diff --git a/Lib-SoulExtraction/linux/key.h b/Lib-SoulExtraction/linux/key.h new file mode 100644 index 0000000..f8b1c30 --- /dev/null +++ b/Lib-SoulExtraction/linux/key.h @@ -0,0 +1,448 @@ +///* Authentication token and access key management +// * +// * Copyright (C) 2004, 2007 Red Hat, Inc. All Rights Reserved. +// * Written by David Howells (dhowells@redhat.com) +// * +// * This program is free software; you can redistribute it and/or +// * modify it under the terms of the GNU General Public License +// * as published by the Free Software Foundation; either version +// * 2 of the License, or (at your option) any later version. +// * +// * +// * See Documentation/security/keys/core.rst for information on keys/keyrings. +// */ +// +//#pragma once +// +// //#ifndef _LINUX_KEY_H +////#define _LINUX_KEY_H +// +////#include +////#include +////#include +////#include +////#include +////#include +////#include +////#include +////#include +////#include +// +// +////#ifdef __KERNEL__ +////#include +// +//#include +// +//#include +// +// +// +// +// +//// +//// macro +//// +// +//#define CONFIG_KEYS +// +// +// +// +// +///* key handle serial number */ +// typedef int32_t key_serial_t; +// +///* key handle permissions mask */ +// typedef uint32_t key_perm_t; +// +// struct key; +// +//#ifdef CONFIG_KEYS +// +//#undef KEY_DEBUGGING +// +//#define KEY_POS_VIEW 0x01000000 /* possessor can view a key's attributes */ +//#define KEY_POS_READ 0x02000000 /* possessor can read key payload / view keyring */ +//#define KEY_POS_WRITE 0x04000000 /* possessor can update key payload / add link to keyring */ +//#define KEY_POS_SEARCH 0x08000000 /* possessor can find a key in search / search a keyring */ +//#define KEY_POS_LINK 0x10000000 /* possessor can create a link to a key/keyring */ +//#define KEY_POS_SETATTR 0x20000000 /* possessor can set key attributes */ +//#define KEY_POS_ALL 0x3f000000 +// +//#define KEY_USR_VIEW 0x00010000 /* user permissions... */ +//#define KEY_USR_READ 0x00020000 +//#define KEY_USR_WRITE 0x00040000 +//#define KEY_USR_SEARCH 0x00080000 +//#define KEY_USR_LINK 0x00100000 +//#define KEY_USR_SETATTR 0x00200000 +//#define KEY_USR_ALL 0x003f0000 +// +//#define KEY_GRP_VIEW 0x00000100 /* group permissions... */ +//#define KEY_GRP_READ 0x00000200 +//#define KEY_GRP_WRITE 0x00000400 +//#define KEY_GRP_SEARCH 0x00000800 +//#define KEY_GRP_LINK 0x00001000 +//#define KEY_GRP_SETATTR 0x00002000 +//#define KEY_GRP_ALL 0x00003f00 +// +//#define KEY_OTH_VIEW 0x00000001 /* third party permissions... */ +//#define KEY_OTH_READ 0x00000002 +//#define KEY_OTH_WRITE 0x00000004 +//#define KEY_OTH_SEARCH 0x00000008 +//#define KEY_OTH_LINK 0x00000010 +//#define KEY_OTH_SETATTR 0x00000020 +//#define KEY_OTH_ALL 0x0000003f +// +//#define KEY_PERM_UNDEF 0xffffffff +// +// struct seq_file; +// struct user_struct; +// struct signal_struct; +// struct cred; +// +// struct key_type; +// struct key_owner; +// struct keyring_list; +// struct keyring_name; +// +// struct keyring_index_key { +// struct key_type *type; +// const char *description; +// size_t desc_len; +// }; +// +// union key_payload { +// void __rcu *rcu_data0; +// void *data[4]; +// }; +// +///*****************************************************************************/ +///* +// * key reference with possession attribute handling +// * +// * NOTE! key_ref_t is a typedef'd pointer to a type that is not actually +// * defined. This is because we abuse the bottom bit of the reference to carry a +// * flag to indicate whether the calling process possesses that key in one of +// * its keyrings. +// * +// * the key_ref_t has been made a separate type so that the compiler can reject +// * attempts to dereference it without proper conversion. +// * +// * the three functions are used to assemble and disassemble references +// */ +// typedef struct __key_reference_with_attributes *key_ref_t; +// +// static inline key_ref_t make_key_ref(const struct key *key, +// bool possession) +//{ +// return (key_ref_t) ((unsigned long) key | possession); +//} +// +// static inline struct key *key_ref_to_ptr(const key_ref_t key_ref) +//{ +// return (struct key *) ((unsigned long) key_ref & ~1UL); +//} +// +// static inline bool is_key_possessed(const key_ref_t key_ref) +//{ +// return (unsigned long) key_ref & 1UL; +//} +// +// typedef int (*key_restrict_link_func_t)(struct key *dest_keyring, +// const struct key_type *type, +// const union key_payload *payload, +// struct key *restriction_key); +// +// struct key_restriction { +// key_restrict_link_func_t check; +// struct key *key; +// struct key_type *keytype; +//}; +// +// enum key_state { +// KEY_IS_UNINSTANTIATED, +// KEY_IS_POSITIVE, /* Positively instantiated */ +//}; +// +///*****************************************************************************/ +///* +// * authentication token / access credential / keyring +// * - types of key include: +// * - keyrings +// * - disk encryption IDs +// * - Kerberos TGTs and tickets +// */ +// struct key { +// refcount_t usage; /* number of references */ +// key_serial_t serial; /* key serial number */ +// union { +// struct list_head graveyard_link; +// struct rb_node serial_node; +// }; +// struct rw_semaphore sem; /* change vs change sem */ +// struct key_user *user; /* owner of this key */ +// void *security; /* security data for this key */ +// union { +// time64_t expiry; /* time at which key expires (or 0) */ +// time64_t revoked_at; /* time at which key was revoked */ +// }; +// time64_t last_used_at; /* last time used for LRU keyring discard */ +// kuid_t uid; +// kgid_t gid; +// key_perm_t perm; /* access permissions */ +// unsigned short quotalen; /* length added to quota */ +// unsigned short datalen; /* payload data length +// * - may not match RCU dereferenced payload +// * - payload should contain own length +// */ +// short state; /* Key state (+) or rejection error (-) */ +// +//#ifdef KEY_DEBUGGING +// unsigned magic; +//#define KEY_DEBUG_MAGIC 0x18273645u +//#endif +// +// unsigned long flags; /* status flags (change with bitops) */ +//#define KEY_FLAG_DEAD 0 /* set if key type has been deleted */ +//#define KEY_FLAG_REVOKED 1 /* set if key had been revoked */ +//#define KEY_FLAG_IN_QUOTA 2 /* set if key consumes quota */ +//#define KEY_FLAG_USER_CONSTRUCT 3 /* set if key is being constructed in userspace */ +//#define KEY_FLAG_ROOT_CAN_CLEAR 4 /* set if key can be cleared by root without permission */ +//#define KEY_FLAG_INVALIDATED 5 /* set if key has been invalidated */ +//#define KEY_FLAG_BUILTIN 6 /* set if key is built in to the kernel */ +//#define KEY_FLAG_ROOT_CAN_INVAL 7 /* set if key can be invalidated by root without permission */ +//#define KEY_FLAG_KEEP 8 /* set if key should not be removed */ +//#define KEY_FLAG_UID_KEYRING 9 /* set if key is a user or user session keyring */ +// +// /* the key type and key description string +// * - the desc is used to match a key against search criteria +// * - it should be a printable string +// * - eg: for krb5 AFS, this might be "afs@REDHAT.COM" +// */ +// union { +// struct keyring_index_key index_key; +// struct { +// struct key_type *type; /* type of key */ +// char *description; +// }; +// }; +// +// /* key data +// * - this is used to hold the data actually used in cryptography or +// * whatever +// */ +// union { +// union key_payload payload; +// struct { +// /* Keyring bits */ +// struct list_head name_link; +// struct assoc_array keys; +// }; +// }; +// +// /* This is set on a keyring to restrict the addition of a link to a key +// * to it. If this structure isn't provided then it is assumed that the +// * keyring is open to any addition. It is ignored for non-keyring +// * keys. Only set this value using keyring_restrict(), keyring_alloc(), +// * or key_alloc(). +// * +// * This is intended for use with rings of trusted keys whereby addition +// * to the keyring needs to be controlled. KEY_ALLOC_BYPASS_RESTRICTION +// * overrides this, allowing the kernel to add extra keys without +// * restriction. +// */ +// struct key_restriction *restrict_link; +//}; +// +// extern struct key *key_alloc(struct key_type *type, +// const char *desc, +// kuid_t uid, kgid_t gid, +// const struct cred *cred, +// key_perm_t perm, +// unsigned long flags, +// struct key_restriction *restrict_link); +// +// +//#define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */ +//#define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ +//#define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ +//#define KEY_ALLOC_BUILT_IN 0x0004 /* Key is built into kernel */ +//#define KEY_ALLOC_BYPASS_RESTRICTION 0x0008 /* Override the check on restricted keyrings */ +//#define KEY_ALLOC_UID_KEYRING 0x0010 /* allocating a user or user session keyring */ +// +// extern void key_revoke(struct key *key); +// extern void key_invalidate(struct key *key); +// extern void key_put(struct key *key); +// +// static inline struct key *__key_get(struct key *key) +//{ +// refcount_inc(&key->usage); +// return key; +//} +// +// static inline struct key *key_get(struct key *key) +//{ +// return key ? __key_get(key) : key; +//} +// +// static inline void key_ref_put(key_ref_t key_ref) +//{ +// key_put(key_ref_to_ptr(key_ref)); +//} +// +// extern struct key *request_key(struct key_type *type, +// const char *description, +// const char *callout_info); +// +// extern struct key *request_key_with_auxdata(struct key_type *type, +// const char *description, +// const void *callout_info, +// size_t callout_len, +// void *aux); +// +// extern struct key *request_key_async(struct key_type *type, +// const char *description, +// const void *callout_info, +// size_t callout_len); +// +// extern struct key *request_key_async_with_auxdata(struct key_type *type, +// const char *description, +// const void *callout_info, +// size_t callout_len, +// void *aux); +// +// extern int wait_for_key_construction(struct key *key, bool intr); +// +// extern int key_validate(const struct key *key); +// +// extern key_ref_t key_create_or_update(key_ref_t keyring, +// const char *type, +// const char *description, +// const void *payload, +// size_t plen, +// key_perm_t perm, +// unsigned long flags); +// +// extern int key_update(key_ref_t key, +// const void *payload, +// size_t plen); +// +// extern int key_link(struct key *keyring, +// struct key *key); +// +// extern int key_unlink(struct key *keyring, +// struct key *key); +// +// extern struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid, +// const struct cred *cred, +// key_perm_t perm, +// unsigned long flags, +// struct key_restriction *restrict_link, +// struct key *dest); +// +// extern int restrict_link_reject(struct key *keyring, +// const struct key_type *type, +// const union key_payload *payload, +// struct key *restriction_key); +// +// extern int keyring_clear(struct key *keyring); +// +// extern key_ref_t keyring_search(key_ref_t keyring, +// struct key_type *type, +// const char *description); +// +// extern int keyring_add_key(struct key *keyring, +// struct key *key); +// +// extern int keyring_restrict(key_ref_t keyring, const char *type, +// const char *restriction); +// +// extern struct key *key_lookup(key_serial_t id); +// +// static inline key_serial_t key_serial(const struct key *key) +//{ +// return key ? key->serial : 0; +//} +// +// extern void key_set_timeout(struct key *, unsigned); +// +// extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, +// key_perm_t perm); +// +///* +// * The permissions required on a key that we're looking up. +// */ +//#define KEY_NEED_VIEW 0x01 /* Require permission to view attributes */ +//#define KEY_NEED_READ 0x02 /* Require permission to read content */ +//#define KEY_NEED_WRITE 0x04 /* Require permission to update / modify */ +//#define KEY_NEED_SEARCH 0x08 /* Require permission to search (keyring) or find (key) */ +//#define KEY_NEED_LINK 0x10 /* Require permission to link */ +//#define KEY_NEED_SETATTR 0x20 /* Require permission to change attributes */ +//#define KEY_NEED_ALL 0x3f /* All the above permissions */ +// +////static inline short key_read_state(const struct key *key) +////{ +//// /* Barrier versus mark_key_instantiated(). */ +//// return smp_load_acquire(&key->state); +////} +// +///** +// * key_is_positive - Determine if a key has been positively instantiated +// * @key: The key to check. +// * +// * Return true if the specified key has been positively instantiated, false +// * otherwise. +// */ +// static inline bool key_is_positive(const struct key *key) +//{ +// return key_read_state(key) == KEY_IS_POSITIVE; +//} +// +// static inline bool key_is_negative(const struct key *key) +//{ +// return key_read_state(key) < 0; +//} +// +//#define dereference_key_rcu(KEY) \ +// (rcu_dereference((KEY)->payload.rcu_data0)) +// +//#define dereference_key_locked(KEY) \ +// (rcu_dereference_protected((KEY)->payload.rcu_data0, \ +// rwsem_is_locked(&((struct key *)(KEY))->sem))) +// +// #define rcu_assign_keypointer(KEY, PAYLOAD) \ +//do { \ +// rcu_assign_pointer((KEY)->payload.rcu_data0, (PAYLOAD)); \ +//} while (0) +// +//#ifdef CONFIG_SYSCTL +// extern struct ctl_table key_sysctls[]; +//#endif +///* +// * the userspace interface +// */ +// extern int install_thread_keyring_to_cred(struct cred *cred); +// extern void key_fsuid_changed(struct task_struct *tsk); +// extern void key_fsgid_changed(struct task_struct *tsk); +// extern void key_init(void); +// +//#else /* CONFIG_KEYS */ +// +//#define key_validate(k) 0 +//#define key_serial(k) 0 +//#define key_get(k) ({ NULL; }) +//#define key_revoke(k) do { } while(0) +//#define key_invalidate(k) do { } while(0) +//#define key_put(k) do { } while(0) +//#define key_ref_put(k) do { } while(0) +//#define make_key_ref(k, p) NULL +//#define key_ref_to_ptr(k) NULL +//#define is_key_possessed(k) 0 +//#define key_fsuid_changed(t) do { } while(0) +//#define key_fsgid_changed(t) do { } while(0) +//#define key_init() do { } while(0) +// +//#endif /* CONFIG_KEYS */ +////#endif /* __KERNEL__ */ +////#endif /* _LINUX_KEY_H */ diff --git a/Lib-SoulExtraction/linux/mscode_parser.c b/Lib-SoulExtraction/linux/mscode_parser.c new file mode 100644 index 0000000..b0133fa --- /dev/null +++ b/Lib-SoulExtraction/linux/mscode_parser.c @@ -0,0 +1,296 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Parse a Microsoft Individual Code Signing blob + * + * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +//#define pr_fmt(fmt) "MSCODE: "fmt +//#include +//#include +//#include +//#include +//#include +//#include "verify_pefile.h" +//#include "mscode.asn1.h" + +#include "verify_pefile.h" +#include "pkcs7.h" +#include "asn1.h" +#include "asn1_ber_bytecode.h" +#include "asn1_decoder.h" +#include "errno.h" +#include "oid_registry.h" + +#include "../rewrite/Lib.SoulExtraction.rewrite.h" + +#define pr_debug +#define pr_devel +#define pr_warn +#define pr_err +#define printk + +#define GFP_ATOMIC /*(__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)*/ 1 +#define GFP_KERNEL /*(__GFP_RECLAIM | __GFP_IO | __GFP_FS)*/ 2 +#define GFP_KERNEL_ACCOUNT /*(GFP_KERNEL | __GFP_ACCOUNT)*/ 3 +#define GFP_NOWAIT /*(__GFP_KSWAPD_RECLAIM)*/ 4 +#define GFP_NOIO /*(__GFP_RECLAIM)*/ 5 +#define GFP_NOFS /*(__GFP_RECLAIM | __GFP_IO)*/ 6 +#define GFP_USER /*(__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL)*/ 7 +#define GFP_DMA /*__GFP_DMA*/ 8 +#define GFP_DMA32 /*__GFP_DMA32*/ 9 +#define GFP_HIGHUSER /*(GFP_USER | __GFP_HIGHMEM)*/ 10 +#define GFP_HIGHUSER_MOVABLE /*(GFP_HIGHUSER | __GFP_MOVABLE)*/ 11 +#define GFP_TRANSHUGE_LIGHT 12 +#define GFP_TRANSHUGE /*(GFP_TRANSHUGE_LIGHT | __GFP_DIRECT_RECLAIM)*/ 13 + +#define ERR_PTR(err) ((void *)((long)(err))) +#define PTR_ERR(ptr) ((long)(ptr)) +#define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000)) + +// +// fun decla +// + +/* + * Check the content type OID + */ +int +mscode_note_content_type(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note the digest we're guaranteeing with this certificate + */ +int +mscode_note_digest(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note the digest algorithm OID + */ +int +mscode_note_digest_algo(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +// +// enum +// + +enum mscode_actions +{ + ACT_mscode_note_content_type = 0, + ACT_mscode_note_digest = 1, + ACT_mscode_note_digest_algo = 2, + NR__mscode_actions = 3 +}; + +// +// global +// + +static const asn1_action_t mscode_action_table[NR__mscode_actions] = { + mscode_note_content_type, + mscode_note_digest, + mscode_note_digest_algo, +}; + +static const unsigned char mscode_machine[] = { + // MSCode + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + ASN1_OP_MATCH, // type + _tag(UNIV, CONS, SEQ), + // ContentType + ASN1_OP_MATCH_ACT, + _tag(UNIV, PRIM, OID), + _action(ACT_mscode_note_content_type), + ASN1_OP_MATCH_ANY, // parameters + ASN1_OP_END_SEQ, + ASN1_OP_MATCH, // content + _tag(UNIV, CONS, SEQ), + // DigestAlgorithmIdentifier + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + ASN1_OP_MATCH_ACT, // algorithm + _tag(UNIV, PRIM, OID), + _action(ACT_mscode_note_digest_algo), + ASN1_OP_MATCH_ANY_OR_SKIP, // parameters + ASN1_OP_END_SEQ, + ASN1_OP_MATCH_ACT, // digest + _tag(UNIV, PRIM, OTS), + _action(ACT_mscode_note_digest), + ASN1_OP_END_SEQ, + ASN1_OP_END_SEQ, + ASN1_OP_COMPLETE, +}; + +const struct asn1_decoder mscode_decoder = { + mscode_machine, + sizeof(mscode_machine), + mscode_action_table, +}; + +/* + * Parse a Microsoft Individual Code Signing blob + */ +int +mscode_parse(void *_ctx, const void *content_data, size_t data_len, size_t asn1hdrlen) +{ + struct pefile_context *ctx = _ctx; + + content_data = (void *)((unsigned char *)content_data - asn1hdrlen); + data_len += asn1hdrlen; + pr_devel("Data: %zu [%*ph]\n", data_len, (unsigned)(data_len), content_data); + + return asn1_ber_decoder(&mscode_decoder, ctx, content_data, data_len); +} + +/* + * Check the content type OID + */ +int +mscode_note_content_type(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + enum OID oid; + + oid = look_up_OID(value, vlen); + if (oid == OID__NR) + { + char buffer[50]; + + sprint_oid(value, vlen, buffer, sizeof(buffer)); + pr_err("Unknown OID: %s\n", buffer); + return -EBADMSG; + } + + /* + * pesign utility had a bug where it was putting + * OID_msIndividualSPKeyPurpose instead of OID_msPeImageDataObjId + * So allow both OIDs. + */ + if (oid != OID_msPeImageDataObjId && oid != OID_msIndividualSPKeyPurpose) + { + pr_err("Unexpected content type OID %u\n", oid); + return -EBADMSG; + } + + return 0; +} + +/* + * Note the digest algorithm OID + */ +int +mscode_note_digest_algo(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + char tmp1[] = {// md4 + 'm', + 'd', + '4', + 0}; + + char tmp2[] = {// md5 + 'm', + 'd', + '5', + 0}; + + char tmp3[] = {// sha1 + 's', + 'h', + 'a', + '1', + 0}; + + char tmp4[] = {// sha256 + 's', + 'h', + 'a', + '2', + '5', + '6', + 0}; + + char tmp5[] = {// sha384 + 's', + 'h', + 'a', + '3', + '8', + '4', + 0}; + + char tmp6[] = {// sha512 + 's', + 'h', + 'a', + '5', + '1', + '2', + 0}; + + char tmp7[] = {// sha224 + 's', + 'h', + 'a', + '2', + '2', + '4', + 0}; + + struct pefile_context *ctx = context; + char buffer[50]; + enum OID oid; + + oid = look_up_OID(value, vlen); + switch (oid) + { + case OID_md4: + ctx->digest_algo = tmp1; + break; + case OID_md5: + ctx->digest_algo = tmp2; + break; + case OID_sha1: + ctx->digest_algo = tmp3; + break; + case OID_sha256: + ctx->digest_algo = tmp4; + break; + case OID_sha384: + ctx->digest_algo = tmp5; + break; + case OID_sha512: + ctx->digest_algo = tmp6; + break; + case OID_sha224: + ctx->digest_algo = tmp7; + break; + + case OID__NR: + sprint_oid(value, vlen, buffer, sizeof(buffer)); + pr_err("Unknown OID: %s\n", buffer); + return -EBADMSG; + + default: + pr_err("Unsupported content type: %u\n", oid); + return -ENOPKG; + } + + return 0; +} + +/* + * Note the digest we're guaranteeing with this certificate + */ +int +mscode_note_digest(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct pefile_context *ctx = context; + + ctx->digest = kmemdup(value, vlen, GFP_KERNEL); + if (!ctx->digest) + return -ENOMEM; + + ctx->digest_len = vlen; + + return 0; +} diff --git a/Lib-SoulExtraction/linux/oid_registry.c b/Lib-SoulExtraction/linux/oid_registry.c new file mode 100644 index 0000000..7ee19b3 --- /dev/null +++ b/Lib-SoulExtraction/linux/oid_registry.c @@ -0,0 +1,404 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* ASN.1 Object identifier (OID) registry + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include "oid_registry.h" +#include "errno.h" + +#include "../rewrite/Lib.SoulExtraction.rewrite.h" + +// +// struct +// + +struct t1 +{ + unsigned char hash; + enum OID oid : 8; +}; + +// global +static const unsigned char oid_data[381] = { + 42, 134, 72, 206, 46, 4, 3, // id_dsa_with_sha1 + 42, 134, 72, 206, 56, 4, 1, // id_dsa + 42, 134, 72, 206, 61, 4, 1, // id_ecdsa_with_sha1 + 42, 134, 72, 206, 61, 2, 1, // id_ecPublicKey + 42, 134, 72, 134, 247, 13, 1, 1, 1, // rsaEncryption + 42, 134, 72, 134, 247, 13, 1, 1, 2, // md2WithRSAEncryption + 42, 134, 72, 134, 247, 13, 1, 1, 3, // md3WithRSAEncryption + 42, 134, 72, 134, 247, 13, 1, 1, 4, // md4WithRSAEncryption + 42, 134, 72, 134, 247, 13, 1, 1, 5, // sha1WithRSAEncryption + 42, 134, 72, 134, 247, 13, 1, 1, 11, // sha256WithRSAEncryption + 42, 134, 72, 134, 247, 13, 1, 1, 12, // sha384WithRSAEncryption + 42, 134, 72, 134, 247, 13, 1, 1, 13, // sha512WithRSAEncryption + 42, 134, 72, 134, 247, 13, 1, 1, 14, // sha224WithRSAEncryption + 42, 134, 72, 134, 247, 13, 1, 7, 1, // data + 42, 134, 72, 134, 247, 13, 1, 7, 2, // signed_data + 42, 134, 72, 134, 247, 13, 1, 9, 1, // email_address + 42, 134, 72, 134, 247, 13, 1, 9, 3, // contentType + 42, 134, 72, 134, 247, 13, 1, 9, 4, // messageDigest + 42, 134, 72, 134, 247, 13, 1, 9, 5, // signingTime 2a864886f70d010905 + 42, 134, 72, 134, 247, 13, 1, 9, 15, // smimeCapabilites + 42, 134, 72, 134, 247, 13, 1, 9, 16, 2, 11, // smimeAuthenticatedAttrs + 42, 134, 72, 134, 247, 13, 2, 2, // md2 + 42, 134, 72, 134, 247, 13, 2, 4, // md4 + 42, 134, 72, 134, 247, 13, 2, 5, // md5 + 43, 6, 1, 4, 1, 130, 55, 2, 1, 4, // msIndirectData + 43, 6, 1, 4, 1, 130, 55, 2, 1, 11, // msStatementType + 43, 6, 1, 4, 1, 130, 55, 2, 1, 12, // msSpOpusInfo + 43, 6, 1, 4, 1, 130, 55, 2, 1, 15, // msPeImageDataObjId + 43, 6, 1, 4, 1, 130, 55, 2, 1, 21, // msIndividualSPKeyPurpose + 43, 6, 1, 4, 1, 130, 55, 16, 4, // msOutlookExpress + 43, 6, 1, 5, 5, 7, 1, 1, // certAuthInfoAccess + 43, 14, 3, 2, 26, // sha1 + 96, 134, 72, 1, 101, 3, 4, 2, 1, // sha256 + 96, 134, 72, 1, 101, 3, 4, 2, 2, // sha384 + 96, 134, 72, 1, 101, 3, 4, 2, 3, // sha512 + 96, 134, 72, 1, 101, 3, 4, 2, 4, // sha224 + 85, 4, 3, // commonName + 85, 4, 4, // surname 55040314 + 85, 4, 6, // countryName + 85, 4, 7, // locality + 85, 4, 8, // stateOrProvinceName + 85, 4, 10, // organizationName + 85, 4, 11, // organizationUnitName + 85, 4, 12, // title + 85, 4, 13, // description + 85, 4, 41, // name + 85, 4, 42, // givenName + 85, 4, 43, // initials + 85, 4, 44, // generationalQualifier + 85, 29, 14, // subjectKeyIdentifier + 85, 29, 15, // keyUsage + 85, 29, 17, // subjectAltName + 85, 29, 18, // issuerAltName + 85, 29, 19, // basicConstraints + 85, 29, 31, // crlDistributionPoints + 85, 29, 32, // certPolicies + 85, 29, 35, // authorityKeyIdentifier + 85, 29, 37, // extKeyUsage +}; + +unsigned short oid_index[OID__NR + 1] = { + [OID_id_dsa_with_sha1] = 0, + [OID_id_dsa] = 7, + [OID_id_ecdsa_with_sha1] = 14, + [OID_id_ecPublicKey] = 21, + [OID_rsaEncryption] = 28, + [OID_md2WithRSAEncryption] = 37, + [OID_md3WithRSAEncryption] = 46, + [OID_md4WithRSAEncryption] = 55, + [OID_sha1WithRSAEncryption] = 64, + [OID_sha256WithRSAEncryption] = 73, + [OID_sha384WithRSAEncryption] = 82, + [OID_sha512WithRSAEncryption] = 91, + [OID_sha224WithRSAEncryption] = 100, + [OID_data] = 109, + [OID_signed_data] = 118, + [OID_email_address] = 127, + [OID_contentType] = 136, + [OID_messageDigest] = 145, + [OID_signingTime] = 154, + [OID_smimeCapabilites] = 163, + [OID_smimeAuthenticatedAttrs] = 172, + [OID_md2] = 183, + [OID_md4] = 191, + [OID_md5] = 199, + [OID_msIndirectData] = 207, + [OID_msStatementType] = 217, + [OID_msSpOpusInfo] = 227, + [OID_msPeImageDataObjId] = 237, + [OID_msIndividualSPKeyPurpose] = 247, + [OID_msOutlookExpress] = 257, + [OID_certAuthInfoAccess] = 266, + [OID_sha1] = 274, + [OID_sha256] = 279, + [OID_sha384] = 288, + [OID_sha512] = 297, + [OID_sha224] = 306, + [OID_commonName] = 315, + [OID_surname] = 318, + [OID_countryName] = 321, + [OID_locality] = 324, + [OID_stateOrProvinceName] = 327, + [OID_organizationName] = 330, + [OID_organizationUnitName] = 333, + [OID_title] = 336, + [OID_description] = 339, + [OID_name] = 342, + [OID_givenName] = 345, + [OID_initials] = 348, + [OID_generationalQualifier] = 351, + [OID_subjectKeyIdentifier] = 354, + [OID_keyUsage] = 357, + [OID_subjectAltName] = 360, + [OID_issuerAltName] = 363, + [OID_basicConstraints] = 366, + [OID_crlDistributionPoints] = 369, + [OID_certPolicies] = 372, + [OID_authorityKeyIdentifier] = 375, + [OID_extKeyUsage] = 378, + [OID__NR] = 38, +}; + +static const struct t1 oid_search_table[OID__NR + 1] = { + {10, OID_title}, // 55040c + {23, OID_issuerAltName}, // 551d12 + {23, OID_initials}, // 55042b + {29, OID_md2WithRSAEncryption}, // 2a864886f70d010102 + {30, OID_md2}, // 2a864886f70d0202 + {32, OID_id_dsa_with_sha1}, // 2a8648ce2e0403 + {35, OID_contentType}, // 2a864886f70d010903 + {35, OID_sha256WithRSAEncryption}, // 2a864886f70d01010b + {36, OID_authorityKeyIdentifier}, // 551d23 + {37, OID_description}, // 55040d + {43, OID_id_dsa}, // 2a8648ce380401 + {51, OID_msIndividualSPKeyPurpose}, // 2b060104018237020115 + {54, OID_basicConstraints}, // 551d13 + {54, OID_generationalQualifier}, // 55042c + {60, OID_md3WithRSAEncryption}, // 2a864886f70d010103 + {64, OID_signed_data}, // 2a864886f70d010702 + {77, OID_countryName}, // 550406 + {77, OID_id_ecdsa_with_sha1}, // 2a8648ce3d0401 + {83, OID_sha256}, // 608648016503040201 + {85, OID_smimeCapabilites}, // 2a864886f70d01090f + {87, OID_sha1}, // 2b0e03021a + {97, OID_email_address}, // 2a864886f70d010901 + {106, OID_extKeyUsage}, // 551d25 + {106, OID_msPeImageDataObjId}, // 2b06010401823702010f + {110, OID_locality}, // 550407 + {126, OID_rsaEncryption}, // 2a864886f70d010101 + {132, OID_smimeAuthenticatedAttrs}, // 2a864886f70d010910020b + {142, OID_id_ecPublicKey}, // 2a8648ce3d0201 + {142, OID_sha224WithRSAEncryption}, // 2a864886f70d01010e + {143, OID_stateOrProvinceName}, // 550408 + {146, OID_subjectKeyIdentifier}, // 551d0e + {157, OID_sha512}, // 608648016503040203 + {160, OID_data}, // 2a864886f70d010701 + {161, OID_crlDistributionPoints}, // 551d1f + {173, OID_msOutlookExpress}, // 2b0601040182371004 + {178, OID_sha384}, // 608648016503040202 + {179, OID_keyUsage}, // 551d0f + {195, OID_md4WithRSAEncryption}, // 2a864886f70d010104 + {198, OID_certPolicies}, // 551d20 + {200, OID_msSpOpusInfo}, // 2b06010401823702010c + {201, OID_organizationName}, // 55040a + {204, OID_messageDigest}, // 2a864886f70d010904 + {204, OID_sha384WithRSAEncryption}, // 2a864886f70d01010c + {212, OID_name}, // 550429 + {213, OID_commonName}, // 550403 + {220, OID_md4}, // 2a864886f70d0204 + {226, OID_sha1WithRSAEncryption}, // 2a864886f70d010105 + {227, OID_md5}, // 2a864886f70d0205 + {228, OID_certAuthInfoAccess}, // 2b06010505070101 + {231, OID_msStatementType}, // 2b06010401823702010b + {234, OID_organizationUnitName}, // 55040b + {237, OID_signingTime}, // 2a864886f70d010905 + {237, OID_sha512WithRSAEncryption}, // 2a864886f70d01010d + {244, OID_surname}, // 550404 + {245, OID_subjectAltName}, // 551d11 + {245, OID_givenName}, // 55042a + {252, OID_sha224}, // 608648016503040204 + {255, OID_msIndirectData}, // 2b060104018237020104 + +}; + +/** + * look_up_OID - Find an OID registration for the specified data + * @data: Binary representation of the OID + * @datasize: Size of the binary representation + */ +enum OID +look_up_OID(const void *data, size_t datasize) +{ + const unsigned char *octets = data; + enum OID oid; + unsigned char xhash; + unsigned i, j, k, hash; + size_t len; + + /* Hash the OID data */ + hash = datasize - 1; + + for (i = 0; i < datasize; i++) + hash += octets[i] * 33; + hash = (hash >> 24) ^ (hash >> 16) ^ (hash >> 8) ^ hash; + hash &= 0xff; + + /* Binary search the OID registry. OIDs are stored in ascending order + * of hash value then ascending order of size and then in ascending + * order of reverse value. + */ + i = 0; + k = OID__NR; + while (i < k) + { + j = (i + k) / 2; + + xhash = oid_search_table[j].hash; + if (xhash > hash) + { + k = j; + continue; + } + if (xhash < hash) + { + i = j + 1; + continue; + } + + oid = oid_search_table[j].oid; + len = oid_index[oid + 1] - oid_index[oid]; + if (len > datasize) + { + k = j; + continue; + } + if (len < datasize) + { + i = j + 1; + continue; + } + + /* Variation is most likely to be at the tail end of the + * OID, so do the comparison in reverse. + */ + while (len > 0) + { + unsigned char a = oid_data[oid_index[oid] + --len]; + unsigned char b = octets[len]; + if (a > b) + { + k = j; + goto next; + } + if (a < b) + { + i = j + 1; + goto next; + } + } + return oid; + next:; + } + + return OID__NR; +} +// EXPORT_SYMBOL_GPL(look_up_OID); + +/* + * sprint_OID - Print an Object Identifier into a buffer + * @data: The encoded OID to print + * @datasize: The size of the encoded OID + * @buffer: The buffer to render into + * @bufsize: The size of the buffer + * + * The OID is rendered into the buffer in "a.b.c.d" format and the number of + * bytes is returned. -EBADMSG is returned if the data could not be intepreted + * and -ENOBUFS if the buffer was too small. + */ +int +sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize) +{ + char tmp1[] = {//%u.%u + '%', + 'u', + '.', + '%', + 'u', + 0}; + + char tmp2[] = {//.%lu + '.', + '%', + 'l', + 'u', + 0}; + + char tmp3[] = {//(bad) + '(', + 'b', + 'a', + 'd', + ')', + 0}; + + const unsigned char *v = data, *end = v + datasize; + unsigned long num; + unsigned char n; + size_t ret; + /*int*/ size_t count; + + if (v >= end) + goto bad; + + n = *v++; + /*ret = count = snprintf(buffer, bufsize, tmp1, n / 40, n % 40);*/ + count = (size_t)kmysnprintf(buffer, bufsize, tmp1, n / 40, n % 40); + ret = count; + + if (count >= bufsize) + return -ENOBUFS; + buffer += count; + bufsize -= count; + + while (v < end) + { + num = 0; + n = *v++; + if (!(n & 0x80)) + { + num = n; + } + else + { + num = n & 0x7f; + do + { + if (v >= end) + goto bad; + n = *v++; + num <<= 7; + num |= n & 0x7f; + } while (n & 0x80); + } + ret += count = kmysnprintf(buffer, bufsize, tmp2, num); + if (count >= bufsize) + return -ENOBUFS; + buffer += count; + bufsize -= count; + } + + return ret; + +bad: + kmysnprintf(buffer, bufsize, tmp3); + return -EBADMSG; +} +// EXPORT_SYMBOL_GPL(sprint_oid); + +/** + * sprint_OID - Print an Object Identifier into a buffer + * @oid: The OID to print + * @buffer: The buffer to render into + * @bufsize: The size of the buffer + * + * The OID is rendered into the buffer in "a.b.c.d" format and the number of + * bytes is returned. + */ +// int sprint_OID(enum OID oid, char *buffer, size_t bufsize) +//{ +// int ret; +// +// //BUG_ON(oid >= OID__NR); +// +// ret = sprint_oid(oid_data + oid_index[oid], +// oid_index[oid + 1] - oid_index[oid], +// buffer, bufsize); +// //BUG_ON(ret == -EBADMSG); +// return ret; +// } +// EXPORT_SYMBOL_GPL(sprint_OID); diff --git a/Lib-SoulExtraction/linux/oid_registry.h b/Lib-SoulExtraction/linux/oid_registry.h new file mode 100644 index 0000000..c31f9f9 --- /dev/null +++ b/Lib-SoulExtraction/linux/oid_registry.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* ASN.1 Object identifier (OID) registry + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#pragma once + +#include + +//#include + +/* + * OIDs are turned into these values if possible, or OID__NR if not held here. + * + * NOTE! Do not mess with the format of each line as this is read by + * build_OID_registry.pl to generate the data for look_up_OID(). + */ +enum OID +{ + OID_id_dsa_with_sha1, /* 1.2.840.10030.4.3 */ + OID_id_dsa, /* 1.2.840.10040.4.1 */ + OID_id_ecdsa_with_sha1, /* 1.2.840.10045.4.1 */ + OID_id_ecPublicKey, /* 1.2.840.10045.2.1 */ + + /* PKCS#1 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)} */ + OID_rsaEncryption, /* 1.2.840.113549.1.1.1 */ + OID_md2WithRSAEncryption, /* 1.2.840.113549.1.1.2 */ + OID_md3WithRSAEncryption, /* 1.2.840.113549.1.1.3 */ + OID_md4WithRSAEncryption, /* 1.2.840.113549.1.1.4 */ + OID_sha1WithRSAEncryption, /* 1.2.840.113549.1.1.5 */ + OID_sha256WithRSAEncryption, /* 1.2.840.113549.1.1.11 */ + OID_sha384WithRSAEncryption, /* 1.2.840.113549.1.1.12 */ + OID_sha512WithRSAEncryption, /* 1.2.840.113549.1.1.13 */ + OID_sha224WithRSAEncryption, /* 1.2.840.113549.1.1.14 */ + /* PKCS#7 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-7(7)} */ + OID_data, /* 1.2.840.113549.1.7.1 */ + OID_signed_data, /* 1.2.840.113549.1.7.2 */ + /* PKCS#9 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)} */ + OID_email_address, /* 1.2.840.113549.1.9.1 */ + OID_contentType, /* 1.2.840.113549.1.9.3 */ + OID_messageDigest, /* 1.2.840.113549.1.9.4 */ + OID_signingTime, /* 1.2.840.113549.1.9.5 */ + OID_smimeCapabilites, /* 1.2.840.113549.1.9.15 */ + OID_smimeAuthenticatedAttrs, /* 1.2.840.113549.1.9.16.2.11 */ + + /* {iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2)} */ + OID_md2, /* 1.2.840.113549.2.2 */ + OID_md4, /* 1.2.840.113549.2.4 */ + OID_md5, /* 1.2.840.113549.2.5 */ + + /* Microsoft Authenticode & Software Publishing */ + OID_msIndirectData, /* 1.3.6.1.4.1.311.2.1.4 */ + OID_msStatementType, /* 1.3.6.1.4.1.311.2.1.11 */ + OID_msSpOpusInfo, /* 1.3.6.1.4.1.311.2.1.12 */ + OID_msPeImageDataObjId, /* 1.3.6.1.4.1.311.2.1.15 */ + OID_msIndividualSPKeyPurpose, /* 1.3.6.1.4.1.311.2.1.21 */ + OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */ + + OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */ + OID_sha1, /* 1.3.14.3.2.26 */ + OID_sha256, /* 2.16.840.1.101.3.4.2.1 */ + OID_sha384, /* 2.16.840.1.101.3.4.2.2 */ + OID_sha512, /* 2.16.840.1.101.3.4.2.3 */ + OID_sha224, /* 2.16.840.1.101.3.4.2.4 */ + + /* Distinguished Name attribute IDs [RFC 2256] */ + OID_commonName, /* 2.5.4.3 */ + OID_surname, /* 2.5.4.4 */ + OID_countryName, /* 2.5.4.6 */ + OID_locality, /* 2.5.4.7 */ + OID_stateOrProvinceName, /* 2.5.4.8 */ + OID_organizationName, /* 2.5.4.10 */ + OID_organizationUnitName, /* 2.5.4.11 */ + OID_title, /* 2.5.4.12 */ + OID_description, /* 2.5.4.13 */ + OID_name, /* 2.5.4.41 */ + OID_givenName, /* 2.5.4.42 */ + OID_initials, /* 2.5.4.43 */ + OID_generationalQualifier, /* 2.5.4.44 */ + + /* Certificate extension IDs */ + OID_subjectKeyIdentifier, /* 2.5.29.14 */ + OID_keyUsage, /* 2.5.29.15 */ + OID_subjectAltName, /* 2.5.29.17 */ + OID_issuerAltName, /* 2.5.29.18 */ + OID_basicConstraints, /* 2.5.29.19 */ + OID_crlDistributionPoints, /* 2.5.29.31 */ + OID_certPolicies, /* 2.5.29.32 */ + OID_authorityKeyIdentifier, /* 2.5.29.35 */ + OID_extKeyUsage, /* 2.5.29.37 */ + + OID__NR +}; + +extern enum OID +look_up_OID(const void *data, size_t datasize); +extern int +sprint_oid(const void *, size_t, char *, size_t); +extern int +sprint_OID(enum OID, char *, size_t); diff --git a/Lib-SoulExtraction/linux/pe.h b/Lib-SoulExtraction/linux/pe.h new file mode 100644 index 0000000..cf42031 --- /dev/null +++ b/Lib-SoulExtraction/linux/pe.h @@ -0,0 +1,478 @@ +/* + * Copyright 2011 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Author(s): Peter Jones + */ +//#ifndef __LINUX_PE_H +//#define __LINUX_PE_H + +#pragma once + +#include + +#include + +//#include + +#define MZ_MAGIC 0x5a4d /* "MZ" */ + +#define PE_MAGIC 0x00004550 /* "PE\0\0" */ +#define PE_OPT_MAGIC_PE32 0x010b +#define PE_OPT_MAGIC_PE32_ROM 0x0107 +#define PE_OPT_MAGIC_PE32PLUS 0x020b + +/* machine type */ +#define IMAGE_FILE_MACHINE_UNKNOWN 0x0000 +#define IMAGE_FILE_MACHINE_AM33 0x01d3 +#define IMAGE_FILE_MACHINE_AMD64 0x8664 +#define IMAGE_FILE_MACHINE_ARM 0x01c0 +#define IMAGE_FILE_MACHINE_ARMV7 0x01c4 +#define IMAGE_FILE_MACHINE_ARM64 0xaa64 +#define IMAGE_FILE_MACHINE_EBC 0x0ebc +#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_IA64 0x0200 +#define IMAGE_FILE_MACHINE_M32R 0x9041 +#define IMAGE_FILE_MACHINE_MIPS16 0x0266 +#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 +#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 +#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 +#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 +#define IMAGE_FILE_MACHINE_R4000 0x0166 +#define IMAGE_FILE_MACHINE_SH3 0x01a2 +#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 +#define IMAGE_FILE_MACHINE_SH3E 0x01a4 +#define IMAGE_FILE_MACHINE_SH4 0x01a6 +#define IMAGE_FILE_MACHINE_SH5 0x01a8 +#define IMAGE_FILE_MACHINE_THUMB 0x01c2 +#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 + +/* flags */ +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 +#define IMAGE_FILE_AGGRESSIVE_WS_TRIM 0x0010 +#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 +#define IMAGE_FILE_16BIT_MACHINE 0x0040 +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 +#define IMAGE_FILE_32BIT_MACHINE 0x0100 +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 +#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 +#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 +#define IMAGE_FILE_SYSTEM 0x1000 +#define IMAGE_FILE_DLL 0x2000 +#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 + +#define IMAGE_FILE_OPT_ROM_MAGIC 0x107 +#define IMAGE_FILE_OPT_PE32_MAGIC 0x10b +#define IMAGE_FILE_OPT_PE32_PLUS_MAGIC 0x20b + +#define IMAGE_SUBSYSTEM_UNKNOWN 0 +#define IMAGE_SUBSYSTEM_NATIVE 1 +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 +#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 +#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 +#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 +#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 +#define IMAGE_SUBSYSTEM_EFI_ROM_IMAGE 13 +#define IMAGE_SUBSYSTEM_XBOX 14 + +#define IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE 0x0040 +#define IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY 0x0080 +#define IMAGE_DLL_CHARACTERISTICS_NX_COMPAT 0x0100 +#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200 +#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 +#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 +#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 +#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 + +/* they actually defined 0x00000000 as well, but I think we'll skip that one. */ +#define IMAGE_SCN_RESERVED_0 0x00000001 +#define IMAGE_SCN_RESERVED_1 0x00000002 +#define IMAGE_SCN_RESERVED_2 0x00000004 +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* don't pad - obsolete */ +#define IMAGE_SCN_RESERVED_3 0x00000010 +#define IMAGE_SCN_CNT_CODE 0x00000020 /* .text */ +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* .data */ +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* .bss */ +#define IMAGE_SCN_LNK_OTHER 0x00000100 /* reserved */ +#define IMAGE_SCN_LNK_INFO 0x00000200 /* .drectve comments */ +#define IMAGE_SCN_RESERVED_4 0x00000400 +#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* .o only - scn to be rm'd*/ +#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* .o only - COMDAT data */ +#define IMAGE_SCN_RESERVED_5 0x00002000 /* spec omits this */ +#define IMAGE_SCN_RESERVED_6 0x00004000 /* spec omits this */ +#define IMAGE_SCN_GPREL 0x00008000 /* global pointer referenced data */ +/* spec lists 0x20000 twice, I suspect they meant 0x10000 for one of them */ +#define IMAGE_SCN_MEM_PURGEABLE 0x00010000 /* reserved for "future" use */ +#define IMAGE_SCN_16BIT 0x00020000 /* reserved for "future" use */ +#define IMAGE_SCN_LOCKED 0x00040000 /* reserved for "future" use */ +#define IMAGE_SCN_PRELOAD 0x00080000 /* reserved for "future" use */ +/* and here they just stuck a 1-byte integer in the middle of a bitfield */ +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 /* it does what it says on the box */ +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 +#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 +#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 +#define IMAGE_SCN_ALIGN_512BYTES 0x00a00000 +#define IMAGE_SCN_ALIGN_1024BYTES 0x00b00000 +#define IMAGE_SCN_ALIGN_2048BYTES 0x00c00000 +#define IMAGE_SCN_ALIGN_4096BYTES 0x00d00000 +#define IMAGE_SCN_ALIGN_8192BYTES 0x00e00000 +#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* extended relocations */ +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 /* scn can be discarded */ +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* cannot be cached */ +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* not pageable */ +#define IMAGE_SCN_MEM_SHARED 0x10000000 /* can be shared */ +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 /* can be executed as code */ +#define IMAGE_SCN_MEM_READ 0x40000000 /* readable */ +#define IMAGE_SCN_MEM_WRITE 0x80000000 /* writeable */ + +#define IMAGE_DEBUG_TYPE_CODEVIEW 2 + +#ifndef __ASSEMBLY__ + +struct mz_hdr +{ + uint16_t magic; /* MZ_MAGIC */ + uint16_t lbsize; /* size of last used block */ + uint16_t blocks; /* pages in file, 0x3 */ + uint16_t relocs; /* relocations */ + uint16_t hdrsize; /* header size in "paragraphs" */ + uint16_t min_extra_pps; /* .bss */ + uint16_t max_extra_pps; /* runtime limit for the arena size */ + uint16_t ss; /* relative stack segment */ + uint16_t sp; /* initial %sp register */ + uint16_t checksum; /* word checksum */ + uint16_t ip; /* initial %ip register */ + uint16_t cs; /* initial %cs relative to load segment */ + uint16_t reloc_table_offset; /* offset of the first relocation */ + uint16_t overlay_num; /* overlay number. set to 0. */ + uint16_t reserved0[4]; /* reserved */ + uint16_t oem_id; /* oem identifier */ + uint16_t oem_info; /* oem specific */ + uint16_t reserved1[10]; /* reserved */ + uint32_t peaddr; /* address of pe header */ + char message[]; /* message to print */ +}; + +struct mz_reloc +{ + uint16_t offset; + uint16_t segment; +}; + +struct pe_hdr +{ + uint32_t magic; /* PE magic */ + uint16_t machine; /* machine type */ + uint16_t sections; /* number of sections */ + uint32_t timestamp; /* time_t */ + uint32_t symbol_table; /* symbol table offset */ + uint32_t symbols; /* number of symbols */ + uint16_t opt_hdr_size; /* size of optional header */ + uint16_t flags; /* flags */ +}; + +/* the fact that pe32 isn't padded where pe32+ is 64-bit means union won't + * work right. vomit. */ +struct pe32_opt_hdr +{ + /* "standard" header */ + uint16_t magic; /* file type */ + uint8_t ld_major; /* linker major version */ + uint8_t ld_minor; /* linker minor version */ + uint32_t text_size; /* size of text section(s) */ + uint32_t data_size; /* size of data section(s) */ + uint32_t bss_size; /* size of bss section(s) */ + uint32_t entry_point; /* file offset of entry point */ + uint32_t code_base; /* relative code addr in ram */ + uint32_t data_base; /* relative data addr in ram */ + /* "windows" header */ + uint32_t image_base; /* preferred load address */ + uint32_t section_align; /* alignment in bytes */ + uint32_t file_align; /* file alignment in bytes */ + uint16_t os_major; /* major OS version */ + uint16_t os_minor; /* minor OS version */ + uint16_t image_major; /* major image version */ + uint16_t image_minor; /* minor image version */ + uint16_t subsys_major; /* major subsystem version */ + uint16_t subsys_minor; /* minor subsystem version */ + uint32_t win32_version; /* reserved, must be 0 */ + uint32_t image_size; /* image size */ + uint32_t header_size; /* header size rounded up to + file_align */ + uint32_t csum; /* checksum */ + uint16_t subsys; /* subsystem */ + uint16_t dll_flags; /* more flags! */ + uint32_t stack_size_req; /* amt of stack requested */ + uint32_t stack_size; /* amt of stack required */ + uint32_t heap_size_req; /* amt of heap requested */ + uint32_t heap_size; /* amt of heap required */ + uint32_t loader_flags; /* reserved, must be 0 */ + uint32_t data_dirs; /* number of data dir entries */ +}; + +struct pe32plus_opt_hdr +{ + uint16_t magic; /* file type */ + uint8_t ld_major; /* linker major version */ + uint8_t ld_minor; /* linker minor version */ + uint32_t text_size; /* size of text section(s) */ + uint32_t data_size; /* size of data section(s) */ + uint32_t bss_size; /* size of bss section(s) */ + uint32_t entry_point; /* file offset of entry point */ + uint32_t code_base; /* relative code addr in ram */ + /* "windows" header */ + uint64_t image_base; /* preferred load address */ + uint32_t section_align; /* alignment in bytes */ + uint32_t file_align; /* file alignment in bytes */ + uint16_t os_major; /* major OS version */ + uint16_t os_minor; /* minor OS version */ + uint16_t image_major; /* major image version */ + uint16_t image_minor; /* minor image version */ + uint16_t subsys_major; /* major subsystem version */ + uint16_t subsys_minor; /* minor subsystem version */ + uint32_t win32_version; /* reserved, must be 0 */ + uint32_t image_size; /* image size */ + uint32_t header_size; /* header size rounded up to + file_align */ + uint32_t csum; /* checksum */ + uint16_t subsys; /* subsystem */ + uint16_t dll_flags; /* more flags! */ + uint64_t stack_size_req; /* amt of stack requested */ + uint64_t stack_size; /* amt of stack required */ + uint64_t heap_size_req; /* amt of heap requested */ + uint64_t heap_size; /* amt of heap required */ + uint32_t loader_flags; /* reserved, must be 0 */ + uint32_t data_dirs; /* number of data dir entries */ +}; + +struct data_dirent +{ + uint32_t virtual_address; /* relative to load address */ + uint32_t size; +}; + +struct data_directory +{ + struct data_dirent exports; /* .edata */ + struct data_dirent imports; /* .idata */ + struct data_dirent resources; /* .rsrc */ + struct data_dirent exceptions; /* .pdata */ + struct data_dirent certs; /* certs */ + struct data_dirent base_relocations; /* .reloc */ + struct data_dirent debug; /* .debug */ + struct data_dirent arch; /* reservered */ + struct data_dirent global_ptr; /* global pointer reg. Size=0 */ + struct data_dirent tls; /* .tls */ + struct data_dirent load_config; /* load configuration structure */ + struct data_dirent bound_imports; /* no idea */ + struct data_dirent import_addrs; /* import address table */ + struct data_dirent delay_imports; /* delay-load import table */ + struct data_dirent clr_runtime_hdr; /* .cor (object only) */ + struct data_dirent reserved; +}; + +struct section_header +{ + char name[8]; /* name or "/12\0" string tbl offset */ + uint32_t virtual_size; /* size of loaded section in ram */ + uint32_t virtual_address; /* relative virtual address */ + uint32_t raw_data_size; /* size of the section */ + uint32_t data_addr; /* file pointer to first page of sec */ + uint32_t relocs; /* file pointer to relocation entries */ + uint32_t line_numbers; /* line numbers! */ + uint16_t num_relocs; /* number of relocations */ + uint16_t num_lin_numbers; /* srsly. */ + uint32_t flags; +}; + +enum x64_coff_reloc_type +{ + IMAGE_REL_AMD64_ABSOLUTE = 0, + IMAGE_REL_AMD64_ADDR64, + IMAGE_REL_AMD64_ADDR32, + IMAGE_REL_AMD64_ADDR32N, + IMAGE_REL_AMD64_REL32, + IMAGE_REL_AMD64_REL32_1, + IMAGE_REL_AMD64_REL32_2, + IMAGE_REL_AMD64_REL32_3, + IMAGE_REL_AMD64_REL32_4, + IMAGE_REL_AMD64_REL32_5, + IMAGE_REL_AMD64_SECTION, + IMAGE_REL_AMD64_SECREL, + IMAGE_REL_AMD64_SECREL7, + IMAGE_REL_AMD64_TOKEN, + IMAGE_REL_AMD64_SREL32, + IMAGE_REL_AMD64_PAIR, + IMAGE_REL_AMD64_SSPAN32, +}; + +enum arm_coff_reloc_type +{ + IMAGE_REL_ARM_ABSOLUTE, + IMAGE_REL_ARM_ADDR32, + IMAGE_REL_ARM_ADDR32N, + IMAGE_REL_ARM_BRANCH2, + IMAGE_REL_ARM_BRANCH1, + IMAGE_REL_ARM_SECTION, + IMAGE_REL_ARM_SECREL, +}; + +enum sh_coff_reloc_type +{ + IMAGE_REL_SH3_ABSOLUTE, + IMAGE_REL_SH3_DIRECT16, + IMAGE_REL_SH3_DIRECT32, + IMAGE_REL_SH3_DIRECT8, + IMAGE_REL_SH3_DIRECT8_WORD, + IMAGE_REL_SH3_DIRECT8_LONG, + IMAGE_REL_SH3_DIRECT4, + IMAGE_REL_SH3_DIRECT4_WORD, + IMAGE_REL_SH3_DIRECT4_LONG, + IMAGE_REL_SH3_PCREL8_WORD, + IMAGE_REL_SH3_PCREL8_LONG, + IMAGE_REL_SH3_PCREL12_WORD, + IMAGE_REL_SH3_STARTOF_SECTION, + IMAGE_REL_SH3_SIZEOF_SECTION, + IMAGE_REL_SH3_SECTION, + IMAGE_REL_SH3_SECREL, + IMAGE_REL_SH3_DIRECT32_NB, + IMAGE_REL_SH3_GPREL4_LONG, + IMAGE_REL_SH3_TOKEN, + IMAGE_REL_SHM_PCRELPT, + IMAGE_REL_SHM_REFLO, + IMAGE_REL_SHM_REFHALF, + IMAGE_REL_SHM_RELLO, + IMAGE_REL_SHM_RELHALF, + IMAGE_REL_SHM_PAIR, + IMAGE_REL_SHM_NOMODE, +}; + +enum ppc_coff_reloc_type +{ + IMAGE_REL_PPC_ABSOLUTE, + IMAGE_REL_PPC_ADDR64, + IMAGE_REL_PPC_ADDR32, + IMAGE_REL_PPC_ADDR24, + IMAGE_REL_PPC_ADDR16, + IMAGE_REL_PPC_ADDR14, + IMAGE_REL_PPC_REL24, + IMAGE_REL_PPC_REL14, + IMAGE_REL_PPC_ADDR32N, + IMAGE_REL_PPC_SECREL, + IMAGE_REL_PPC_SECTION, + IMAGE_REL_PPC_SECREL16, + IMAGE_REL_PPC_REFHI, + IMAGE_REL_PPC_REFLO, + IMAGE_REL_PPC_PAIR, + IMAGE_REL_PPC_SECRELLO, + IMAGE_REL_PPC_GPREL, + IMAGE_REL_PPC_TOKEN, +}; + +enum x86_coff_reloc_type +{ + IMAGE_REL_I386_ABSOLUTE, + IMAGE_REL_I386_DIR16, + IMAGE_REL_I386_REL16, + IMAGE_REL_I386_DIR32, + IMAGE_REL_I386_DIR32NB, + IMAGE_REL_I386_SEG12, + IMAGE_REL_I386_SECTION, + IMAGE_REL_I386_SECREL, + IMAGE_REL_I386_TOKEN, + IMAGE_REL_I386_SECREL7, + IMAGE_REL_I386_REL32, +}; + +enum ia64_coff_reloc_type +{ + IMAGE_REL_IA64_ABSOLUTE, + IMAGE_REL_IA64_IMM14, + IMAGE_REL_IA64_IMM22, + IMAGE_REL_IA64_IMM64, + IMAGE_REL_IA64_DIR32, + IMAGE_REL_IA64_DIR64, + IMAGE_REL_IA64_PCREL21B, + IMAGE_REL_IA64_PCREL21M, + IMAGE_REL_IA64_PCREL21F, + IMAGE_REL_IA64_GPREL22, + IMAGE_REL_IA64_LTOFF22, + IMAGE_REL_IA64_SECTION, + IMAGE_REL_IA64_SECREL22, + IMAGE_REL_IA64_SECREL64I, + IMAGE_REL_IA64_SECREL32, + IMAGE_REL_IA64_DIR32NB, + IMAGE_REL_IA64_SREL14, + IMAGE_REL_IA64_SREL22, + IMAGE_REL_IA64_SREL32, + IMAGE_REL_IA64_UREL32, + IMAGE_REL_IA64_PCREL60X, + IMAGE_REL_IA64_PCREL60B, + IMAGE_REL_IA64_PCREL60F, + IMAGE_REL_IA64_PCREL60I, + IMAGE_REL_IA64_PCREL60M, + IMAGE_REL_IA64_IMMGPREL6, + IMAGE_REL_IA64_TOKEN, + IMAGE_REL_IA64_GPREL32, + IMAGE_REL_IA64_ADDEND, +}; + +struct coff_reloc +{ + uint32_t virtual_address; + uint32_t symbol_table_index; + union + { + enum x64_coff_reloc_type x64_type; + enum arm_coff_reloc_type arm_type; + enum sh_coff_reloc_type sh_type; + enum ppc_coff_reloc_type ppc_type; + enum x86_coff_reloc_type x86_type; + enum ia64_coff_reloc_type ia64_type; + uint16_t data; + }; +}; + +/* + * Definitions for the contents of the certs data block + */ +# define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002 +# define WIN_CERT_TYPE_EFI_OKCS115 0x0EF0 +# define WIN_CERT_TYPE_EFI_GUID 0x0EF1 + +# define WIN_CERT_REVISION_1_0 0x0100 +# define WIN_CERT_REVISION_2_0 0x0200 + +struct win_certificate +{ + uint32_t length; + uint16_t revision; + uint16_t cert_type; +}; + +#endif /* !__ASSEMBLY__ */ + +//#endif /* __LINUX_PE_H */ diff --git a/Lib-SoulExtraction/linux/pkcs7.h b/Lib-SoulExtraction/linux/pkcs7.h new file mode 100644 index 0000000..a5edd53 --- /dev/null +++ b/Lib-SoulExtraction/linux/pkcs7.h @@ -0,0 +1,53 @@ +/* PKCS#7 crypto data parser + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#pragma once + +//#ifndef _CRYPTO_PKCS7_H +//#define _CRYPTO_PKCS7_H + +//#include +//#include + +#include "pkcs7_parser.h" + +#include + +// struct key; +// struct pkcs7_message; + +/* + * pkcs7_parser.c + */ +extern struct pkcs7_message * +pkcs7_parse_message(const void *data, size_t datalen); +extern void +pkcs7_free_message(struct pkcs7_message *pkcs7); + +extern int +pkcs7_get_content_data(const struct pkcs7_message *pkcs7, const void **_data, size_t *_datalen, size_t *_headerlen); + +/* + * pkcs7_trust.c + */ +// extern int pkcs7_validate_trust(struct pkcs7_message *pkcs7, +// struct key *trust_keyring); + +/* + * pkcs7_verify.c + */ +// extern int pkcs7_verify(struct pkcs7_message *pkcs7, +// enum key_being_used_for usage); +// +// extern int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7, +// const void *data, size_t datalen); + +//#endif /* _CRYPTO_PKCS7_H */ diff --git a/Lib-SoulExtraction/linux/pkcs7_parser.c b/Lib-SoulExtraction/linux/pkcs7_parser.c new file mode 100644 index 0000000..e18897c --- /dev/null +++ b/Lib-SoulExtraction/linux/pkcs7_parser.c @@ -0,0 +1,1270 @@ +/* PKCS#7 parser + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +//#define pr_fmt(fmt) "PKCS7: "fmt +//#include +//#include +//#include +//#include +//#include +//#include +//#include "pkcs7_parser.h" +//#include "pkcs7-asn1.h" + +#include "pkcs7_parser.h" +#include "errno.h" +#include "asn1_ber_bytecode.h" +#include "asn1.h" +#include "asn1_decoder.h" +#include "config.h" + +#include "../rewrite/Lib.SoulExtraction.rewrite.h" + +#define GFP_ATOMIC /*(__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)*/ 1 +#define GFP_KERNEL /*(__GFP_RECLAIM | __GFP_IO | __GFP_FS)*/ 2 +#define GFP_KERNEL_ACCOUNT /*(GFP_KERNEL | __GFP_ACCOUNT)*/ 3 +#define GFP_NOWAIT /*(__GFP_KSWAPD_RECLAIM)*/ 4 +#define GFP_NOIO /*(__GFP_RECLAIM)*/ 5 +#define GFP_NOFS /*(__GFP_RECLAIM | __GFP_IO)*/ 6 +#define GFP_USER /*(__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL)*/ 7 +#define GFP_DMA /*__GFP_DMA*/ 8 +#define GFP_DMA32 /*__GFP_DMA32*/ 9 +#define GFP_HIGHUSER /*(GFP_USER | __GFP_HIGHMEM)*/ 10 +#define GFP_HIGHUSER_MOVABLE /*(GFP_HIGHUSER | __GFP_MOVABLE)*/ 11 +#define GFP_TRANSHUGE_LIGHT 12 +#define GFP_TRANSHUGE /*(GFP_TRANSHUGE_LIGHT | __GFP_DIRECT_RECLAIM)*/ 13 + +#define ERR_PTR(err) ((void *)((long)(err))) +#define PTR_ERR(ptr) ((long)(ptr)) +#define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000)) + +// +// enum +// + +enum pkcs7_actions +{ + ACT_pkcs7_check_content_type = 0, + ACT_pkcs7_extract_cert = 1, + ACT_pkcs7_note_OID = 2, + ACT_pkcs7_note_certificate_list = 3, + ACT_pkcs7_note_content = 4, + ACT_pkcs7_note_data = 5, + ACT_pkcs7_note_signed_info = 6, + ACT_pkcs7_note_signeddata_version = 7, + ACT_pkcs7_note_signerinfo_version = 8, + ACT_pkcs7_sig_note_authenticated_attr = 9, + ACT_pkcs7_sig_note_digest_algo = 10, + ACT_pkcs7_sig_note_issuer = 11, + ACT_pkcs7_sig_note_pkey_algo = 12, + ACT_pkcs7_sig_note_serial = 13, + ACT_pkcs7_sig_note_set_of_authattrs = 14, + ACT_pkcs7_sig_note_signature = 15, + ACT_pkcs7_sig_note_skid = 16, + NR__pkcs7_actions = 17 +}; + +// +// struct +// + +struct pkcs7_parse_context +{ + struct pkcs7_message *msg; /* Message being constructed */ + struct pkcs7_signed_info *sinfo; /* SignedInfo being constructed */ + struct pkcs7_signed_info **ppsinfo; + struct x509_certificate *certs; /* Certificate cache */ + struct x509_certificate **ppcerts; + unsigned long data; /* Start of data */ + enum OID last_oid; /* Last OID encountered */ + unsigned x509_index; + unsigned sinfo_index; + const void *raw_serial; + unsigned raw_serial_size; + unsigned raw_issuer_size; + const void *raw_issuer; + const void *raw_skid; + unsigned raw_skid_size; + /*bool*/ unsigned char expect_skid; +}; + +// func decl + +/* + * We only support signed data [RFC2315 sec 9]. + */ +int +pkcs7_check_content_type(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Extract a certificate and store it in the context. + */ +int +pkcs7_extract_cert(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note an OID when we find one for later processing when we know how + * to interpret it. + */ +int +pkcs7_note_OID(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Save the certificate list + */ +int +pkcs7_note_certificate_list(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note the content type. + */ +int +pkcs7_note_content(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Extract the data from the message and store that and its content type OID in + * the context. + */ +int +pkcs7_note_data(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note a signature information block + */ +int +pkcs7_note_signed_info(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note the SignedData version + */ +int +pkcs7_note_signeddata_version(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note the SignerInfo version + */ +int +pkcs7_note_signerinfo_version(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Parse authenticated attributes. + */ +int +pkcs7_sig_note_authenticated_attr(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note the digest algorithm for the signature. + */ +int +pkcs7_sig_note_digest_algo(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note the issuer's name + */ +int +pkcs7_sig_note_issuer(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note the public key algorithm for the signature. + */ +int +pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note the issuing certificate serial number + */ +int +pkcs7_sig_note_serial(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note the set of auth attributes for digestion purposes [RFC2315 sec 9.3] + */ +int +pkcs7_sig_note_set_of_authattrs(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note the signature data + */ +int +pkcs7_sig_note_signature(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note the issuing cert's subjectKeyIdentifier + */ +int +pkcs7_sig_note_skid(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +// +// global +// + +static const UCHAR pkcs7_machine[] = { + // PKCS7ContentInfo + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + // ContentType + ASN1_OP_MATCH_ACT, + _tag(UNIV, PRIM, OID), + _action(ACT_pkcs7_note_OID), + ASN1_OP_ACT, + _action(ACT_pkcs7_check_content_type), + ASN1_OP_MATCH_JUMP_OR_SKIP, // content + _tagn(CONT, CONS, 0), + _jump_target(12), + ASN1_OP_END_SEQ, + ASN1_OP_COMPLETE, + + // SignedData + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + ASN1_OP_MATCH_ACT, // version + _tag(UNIV, PRIM, INT), + _action(ACT_pkcs7_note_signeddata_version), + // DigestAlgorithmIdentifiers + ASN1_OP_MATCH_JUMP_OR_SKIP, // daSet + _tag(UNIV, CONS, SET), + _jump_target(61), + ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // daSequence + _tag(UNIV, CONS, SEQ), + _jump_target(67), + ASN1_OP_COND_FAIL, + // ContentInfo + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + // ContentType + ASN1_OP_MATCH_ACT, + _tag(UNIV, PRIM, OID), + _action(ACT_pkcs7_note_OID), + ASN1_OP_ACT, + _action(ACT_pkcs7_note_OID), + ASN1_OP_MATCH_JUMP_OR_SKIP, // content + _tagn(CONT, CONS, 0), + _jump_target(73), + ASN1_OP_END_SEQ, + ASN1_OP_ACT, + _action(ACT_pkcs7_note_content), + // ExtendedCertificatesAndCertificates + ASN1_OP_MATCH_JUMP_OR_SKIP, // certSet + _tagn(CONT, CONS, 0), + _jump_target(77), // --> ExtendedCertificatesAndCertificates + // Certificates + ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // certSequence + _tagn(CONT, CONS, 2), + _jump_target(85), // --> Certificates + ASN1_OP_ACT, + _action(ACT_pkcs7_note_certificate_list), + // CertificateRevocationLists + ASN1_OP_MATCH_JUMP_OR_SKIP, // crlSet + _tagn(CONT, CONS, 1), + _jump_target(90), // --> CertificateRevocationLists + // CRLSequence + ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // crlSequence + _tagn(CONT, CONS, 3), + _jump_target(96), // --> CRLSequence + // SignerInfos + ASN1_OP_MATCH_JUMP_OR_SKIP, // siSet + _tag(UNIV, CONS, SET), + _jump_target(102), + ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // siSequence + _tag(UNIV, CONS, SEQ), + _jump_target(108), + ASN1_OP_COND_FAIL, + ASN1_OP_END_SEQ, + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, + + // DigestAlgorithmIdentifier + ASN1_OP_MATCH_JUMP, + _tag(UNIV, CONS, SEQ), + _jump_target(114), // --> DigestAlgorithmIdentifier + ASN1_OP_END_SET_OF, + _jump_target(61), + ASN1_OP_RETURN, + + // DigestAlgorithmIdentifier + ASN1_OP_MATCH_JUMP, + _tag(UNIV, CONS, SEQ), + _jump_target(114), // --> DigestAlgorithmIdentifier + ASN1_OP_END_SEQ_OF, + _jump_target(67), + ASN1_OP_RETURN, + + // Data + ASN1_OP_MATCH_ANY_ACT, + _action(ACT_pkcs7_note_data), + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, + + // ExtendedCertificateOrCertificate + // Certificate + ASN1_OP_MATCH_ANY_ACT_OR_SKIP, + _action(ACT_pkcs7_extract_cert), + // ExtendedCertificate + // Certificate + ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP, + _action(ACT_pkcs7_extract_cert), + ASN1_OP_COND_FAIL, + ASN1_OP_END_SET_OF, + _jump_target(77), + ASN1_OP_RETURN, + + // Certificate + ASN1_OP_MATCH_ANY_ACT, + _action(ACT_pkcs7_extract_cert), + ASN1_OP_END_SEQ_OF, + _jump_target(85), + ASN1_OP_RETURN, + + // CertificateList + ASN1_OP_MATCH_JUMP, + _tag(UNIV, CONS, SEQ), + _jump_target(120), // --> CertificateList + ASN1_OP_END_SET_OF, + _jump_target(90), + ASN1_OP_RETURN, + + // CertificateList + ASN1_OP_MATCH_JUMP, + _tag(UNIV, CONS, SEQ), + _jump_target(120), // --> CertificateList + ASN1_OP_END_SEQ_OF, + _jump_target(96), + ASN1_OP_RETURN, + + // SignerInfo + ASN1_OP_MATCH_JUMP, + _tag(UNIV, CONS, SEQ), + _jump_target(125), // --> SignerInfo + ASN1_OP_END_SET_OF, + _jump_target(102), + ASN1_OP_RETURN, + + // SignerInfo + ASN1_OP_MATCH_JUMP, + _tag(UNIV, CONS, SEQ), + _jump_target(125), // --> SignerInfo + ASN1_OP_END_SEQ_OF, + _jump_target(108), + ASN1_OP_RETURN, + + ASN1_OP_MATCH_ACT, // algorithm + _tag(UNIV, PRIM, OID), + _action(ACT_pkcs7_note_OID), + ASN1_OP_MATCH_ANY_OR_SKIP, // parameters + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, + + // Certificate + ASN1_OP_MATCH_ANY_ACT, + _action(ACT_pkcs7_extract_cert), + ASN1_OP_END_SEQ_OF, + _jump_target(120), + ASN1_OP_RETURN, + + ASN1_OP_MATCH_ACT, // version + _tag(UNIV, PRIM, INT), + _action(ACT_pkcs7_note_signerinfo_version), + // SignerIdentifier + // IssuerAndSerialNumber + ASN1_OP_MATCH_JUMP_OR_SKIP, // issuerAndSerialNumber + _tag(UNIV, CONS, SEQ), + _jump_target(169), // --> IssuerAndSerialNumber + // SubjectKeyIdentifier + ASN1_OP_COND_MATCH_ACT_OR_SKIP, // subjectKeyIdentifier + _tagn(CONT, PRIM, 0), + _action(ACT_pkcs7_sig_note_skid), + ASN1_OP_COND_FAIL, + // DigestAlgorithmIdentifier + ASN1_OP_MATCH_JUMP, + _tag(UNIV, CONS, SEQ), + _jump_target(114), // --> DigestAlgorithmIdentifier + ASN1_OP_ACT, + _action(ACT_pkcs7_sig_note_digest_algo), + // SetOfAuthenticatedAttribute + ASN1_OP_MATCH_JUMP_OR_SKIP, // aaSet + _tagn(CONT, CONS, 0), + _jump_target(192), // --> SetOfAuthenticatedAttribute + ASN1_OP_MAYBE_ACT, + _action(ACT_pkcs7_sig_note_set_of_authattrs), + ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // aaSequence + _tagn(CONT, CONS, 2), + _jump_target(198), + // DigestEncryptionAlgorithmIdentifier + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + ASN1_OP_MATCH_ACT, // algorithm + _tag(UNIV, PRIM, OID), + _action(ACT_pkcs7_note_OID), + ASN1_OP_MATCH_ANY_OR_SKIP, // parameters + ASN1_OP_END_SEQ, + ASN1_OP_ACT, + _action(ACT_pkcs7_sig_note_pkey_algo), + // EncryptedDigest + ASN1_OP_MATCH_ACT, + _tag(UNIV, PRIM, OTS), + _action(ACT_pkcs7_sig_note_signature), + ASN1_OP_MATCH_JUMP_OR_SKIP, // uaSet + _tagn(CONT, CONS, 1), + _jump_target(207), + ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // uaSequence + _tagn(CONT, CONS, 3), + _jump_target(213), + ASN1_OP_END_SEQ_ACT, + _action(ACT_pkcs7_note_signed_info), + ASN1_OP_RETURN, + + // Name + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + // RelativeDistinguishedName + ASN1_OP_MATCH, + _tag(UNIV, CONS, SET), + // AttributeValueAssertion + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + ASN1_OP_MATCH_ACT, // attributeType + _tag(UNIV, PRIM, OID), + _action(ACT_pkcs7_note_OID), + ASN1_OP_MATCH_ANY, // attributeValue + ASN1_OP_END_SEQ, + ASN1_OP_END_SET_OF, + _jump_target(173), + ASN1_OP_END_SEQ_OF, + _jump_target(171), + ASN1_OP_ACT, + _action(ACT_pkcs7_sig_note_issuer), + // CertificateSerialNumber + ASN1_OP_MATCH, + _tag(UNIV, PRIM, INT), + ASN1_OP_ACT, + _action(ACT_pkcs7_sig_note_serial), + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, + + // AuthenticatedAttribute + ASN1_OP_MATCH_JUMP, + _tag(UNIV, CONS, SEQ), + _jump_target(219), // --> AuthenticatedAttribute + ASN1_OP_END_SET_OF, + _jump_target(192), + ASN1_OP_RETURN, + + ASN1_OP_MATCH, // aaSequence + _tag(UNIV, CONS, SEQ), + // AuthenticatedAttribute + ASN1_OP_MATCH_JUMP, + _tag(UNIV, CONS, SEQ), + _jump_target(219), // --> AuthenticatedAttribute + ASN1_OP_END_SEQ_OF, + _jump_target(200), + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, + + // UnauthenticatedAttribute + ASN1_OP_MATCH_JUMP, + _tag(UNIV, CONS, SEQ), + _jump_target(230), // --> UnauthenticatedAttribute + ASN1_OP_END_SET_OF, + _jump_target(207), + ASN1_OP_RETURN, + + // UnauthenticatedAttribute + ASN1_OP_MATCH_JUMP, + _tag(UNIV, CONS, SEQ), + _jump_target(230), // --> UnauthenticatedAttribute + ASN1_OP_END_SEQ_OF, + _jump_target(213), + ASN1_OP_RETURN, + + ASN1_OP_MATCH_ACT, // type + _tag(UNIV, PRIM, OID), + _action(ACT_pkcs7_note_OID), + ASN1_OP_MATCH, // values + _tag(UNIV, CONS, SET), + ASN1_OP_MATCH_ANY_ACT, + _action(ACT_pkcs7_sig_note_authenticated_attr), + ASN1_OP_END_SET_OF, + _jump_target(224), + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, + + ASN1_OP_MATCH, // type + _tag(UNIV, PRIM, OID), + ASN1_OP_MATCH, // values + _tag(UNIV, CONS, SET), + ASN1_OP_MATCH_ANY, + ASN1_OP_END_SET_OF, + _jump_target(234), + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, +}; + +static const asn1_action_t pkcs7_action_table[NR__pkcs7_actions] = { + pkcs7_check_content_type, + pkcs7_extract_cert, + pkcs7_note_OID, + pkcs7_note_certificate_list, + pkcs7_note_content, + pkcs7_note_data, + pkcs7_note_signed_info, + pkcs7_note_signeddata_version, + pkcs7_note_signerinfo_version, + pkcs7_sig_note_authenticated_attr, + pkcs7_sig_note_digest_algo, + pkcs7_sig_note_issuer, + pkcs7_sig_note_pkey_algo, + pkcs7_sig_note_serial, + pkcs7_sig_note_set_of_authattrs, + pkcs7_sig_note_signature, + pkcs7_sig_note_skid, +}; + +struct asn1_decoder pkcs7_decoder = { + pkcs7_machine, + sizeof(pkcs7_machine), + pkcs7_action_table, +}; + +/* + * Free a signed information block. + */ +static void +pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo) +{ + if (sinfo) + { + public_key_signature_free(sinfo->sig); + kfree(sinfo); + } +} + +/** + * pkcs7_free_message - Free a PKCS#7 message + * @pkcs7: The PKCS#7 message to free + */ +void +pkcs7_free_message(struct pkcs7_message *pkcs7) +{ + struct x509_certificate *cert; + struct pkcs7_signed_info *sinfo; + + if (pkcs7) + { + while (pkcs7->certs) + { + cert = pkcs7->certs; + pkcs7->certs = cert->next; + x509_free_certificate(cert); + } + while (pkcs7->crl) + { + cert = pkcs7->crl; + pkcs7->crl = cert->next; + x509_free_certificate(cert); + } + while (pkcs7->signed_infos) + { + sinfo = pkcs7->signed_infos; + pkcs7->signed_infos = sinfo->next; + pkcs7_free_signed_info(sinfo); + } + kfree(pkcs7); + } +} +// EXPORT_SYMBOL_GPL(pkcs7_free_message); + +/* + * Check authenticatedAttributes are provided or not provided consistently. + */ +static int +pkcs7_check_authattrs(struct pkcs7_message *msg) +{ + struct pkcs7_signed_info *sinfo; + /*bool*/ unsigned char want = /*false*/ FALSE; + + sinfo = msg->signed_infos; + if (!sinfo) + goto inconsistent; + + if (sinfo->authattrs) + { + want = /*true*/ TRUE; + msg->have_authattrs = /*true*/ TRUE; + } + + for (sinfo = sinfo->next; sinfo; sinfo = sinfo->next) + if (!!sinfo->authattrs != want) + goto inconsistent; + return 0; + +inconsistent: + pr_warn("Inconsistently supplied authAttrs\n"); + return -EINVAL; +} + +/** + * pkcs7_parse_message - Parse a PKCS#7 message + * @data: The raw binary ASN.1 encoded message to be parsed + * @datalen: The size of the encoded message + */ +struct pkcs7_message * +pkcs7_parse_message(const void *data, size_t datalen) +{ + struct pkcs7_parse_context *ctx; + struct pkcs7_message *msg = ERR_PTR(-ENOMEM); + int ret; + + ctx = kzalloc(sizeof(struct pkcs7_parse_context), GFP_KERNEL); + if (!ctx) + goto out_no_ctx; + ctx->msg = kzalloc(sizeof(struct pkcs7_message), GFP_KERNEL); + if (!ctx->msg) + goto out_no_msg; + ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL); + if (!ctx->sinfo) + goto out_no_sinfo; + ctx->sinfo->sig = kzalloc(sizeof(struct public_key_signature), GFP_KERNEL); + if (!ctx->sinfo->sig) + goto out_no_sig; + + /*ctx->data = (unsigned long)data;*/ + ctx->data = PtrToUlong(data); + ctx->ppcerts = &ctx->certs; + ctx->ppsinfo = &ctx->msg->signed_infos; + + /* Attempt to decode the signature */ + ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen); + if (ret < 0) + { + msg = ERR_PTR(ret); + goto out; + } + + ret = pkcs7_check_authattrs(ctx->msg); + if (ret < 0) + goto out; + + msg = ctx->msg; + ctx->msg = NULL; + +out: + while (ctx->certs) + { + struct x509_certificate *cert = ctx->certs; + ctx->certs = cert->next; + x509_free_certificate(cert); + } +out_no_sig: + pkcs7_free_signed_info(ctx->sinfo); +out_no_sinfo: + pkcs7_free_message(ctx->msg); +out_no_msg: + kfree(ctx); +out_no_ctx: + return msg; +} +// EXPORT_SYMBOL_GPL(pkcs7_parse_message); + +/** + * pkcs7_get_content_data - Get access to the PKCS#7 content + * @pkcs7: The preparsed PKCS#7 message to access + * @_data: Place to return a pointer to the data + * @_data_len: Place to return the data length + * @_headerlen: Size of ASN.1 header not included in _data + * + * Get access to the data content of the PKCS#7 message. The size of the + * header of the ASN.1 object that contains it is also provided and can be used + * to adjust *_data and *_data_len to get the entire object. + * + * Returns -ENODATA if the data object was missing from the message. + */ +int +pkcs7_get_content_data(const struct pkcs7_message *pkcs7, const void **_data, size_t *_data_len, size_t *_headerlen) +{ + if (!pkcs7->data) + return -ENODATA; + + *_data = pkcs7->data; + *_data_len = pkcs7->data_len; + if (_headerlen) + *_headerlen = pkcs7->data_hdrlen; + return 0; +} +// EXPORT_SYMBOL_GPL(pkcs7_get_content_data); + +/* + * Note an OID when we find one for later processing when we know how + * to interpret it. + */ +int +pkcs7_note_OID(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct pkcs7_parse_context *ctx = context; + + ctx->last_oid = look_up_OID(value, vlen); + if (ctx->last_oid == OID__NR) + { + char buffer[50]; + sprint_oid(value, vlen, buffer, sizeof(buffer)); + /*printk("PKCS7: Unknown OID: [%lu] %s\n", + (unsigned long)value - ctx->data, buffer);*/ + } + return 0; +} + +/* + * Note the digest algorithm for the signature. + */ +int +pkcs7_sig_note_digest_algo(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + char tmp1[] = {// md4 + 'm', + 'd', + '4', + 0}; + + char tmp2[] = {// md5 + 'm', + 'd', + '5', + 0}; + + char tmp3[] = {// sha1 + 's', + 'h', + 'a', + '1', + 0}; + + char tmp4[] = {// sha256 + 's', + 'h', + 'a', + '2', + '5', + '6', + 0}; + + char tmp5[] = {// sha384 + 's', + 'h', + 'a', + '3', + '8', + '4', + 0}; + + char tmp6[] = {// sha512 + 's', + 'h', + 'a', + '5', + '1', + '2', + 0}; + + char tmp7[] = {// sha224 + 's', + 'h', + 'a', + '2', + '2', + '4', + 0}; + + struct pkcs7_parse_context *ctx = context; + + switch (ctx->last_oid) + { + case OID_md4: + ctx->sinfo->sig->hash_algo = tmp1; + break; + case OID_md5: + ctx->sinfo->sig->hash_algo = tmp2; + break; + case OID_sha1: + ctx->sinfo->sig->hash_algo = tmp3; + break; + case OID_sha256: + ctx->sinfo->sig->hash_algo = tmp4; + break; + case OID_sha384: + ctx->sinfo->sig->hash_algo = tmp5; + break; + case OID_sha512: + ctx->sinfo->sig->hash_algo = tmp6; + break; + case OID_sha224: + ctx->sinfo->sig->hash_algo = tmp7; + break; + default: + printk("Unsupported digest algo: %u\n", ctx->last_oid); + return -ENOPKG; + } + return 0; +} + +/* + * Note the public key algorithm for the signature. + */ +int +pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + // char tmp1[] = { + // 's','a','r',0 + // }; + + struct pkcs7_parse_context *ctx = context; + + switch (ctx->last_oid) + { + case OID_rsaEncryption: + ctx->sinfo->sig->pkey_algo = "sar"; + break; + default: + printk("Unsupported pkey algo: %u\n", ctx->last_oid); + return -ENOPKG; + } + return 0; +} + +/* + * We only support signed data [RFC2315 sec 9]. + */ +int +pkcs7_check_content_type(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct pkcs7_parse_context *ctx = context; + + if (ctx->last_oid != OID_signed_data) + { + pr_warn("Only support pkcs7_signedData type\n"); + return -EINVAL; + } + + return 0; +} + +/* + * Note the SignedData version + */ +int +pkcs7_note_signeddata_version(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct pkcs7_parse_context *ctx = context; + unsigned version; + + if (vlen != 1) + goto unsupported; + + ctx->msg->version = version = *(const /*u8*/ unsigned char *)value; + switch (version) + { + case 1: + /* PKCS#7 SignedData [RFC2315 sec 9.1] + * CMS ver 1 SignedData [RFC5652 sec 5.1] + */ + break; + case 3: + /* CMS ver 3 SignedData [RFC2315 sec 5.1] */ + break; + default: + goto unsupported; + } + + return 0; + +unsupported: + pr_warn("Unsupported SignedData version\n"); + return -EINVAL; +} + +/* + * Note the SignerInfo version + */ +int +pkcs7_note_signerinfo_version(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct pkcs7_parse_context *ctx = context; + unsigned version; + + if (vlen != 1) + goto unsupported; + + version = *(const /*u8*/ unsigned char *)value; + switch (version) + { + case 1: + /* PKCS#7 SignerInfo [RFC2315 sec 9.2] + * CMS ver 1 SignerInfo [RFC5652 sec 5.3] + */ + if (ctx->msg->version != 1) + goto version_mismatch; + ctx->expect_skid = /*false*/ FALSE; + break; + case 3: + /* CMS ver 3 SignerInfo [RFC2315 sec 5.3] */ + if (ctx->msg->version == 1) + goto version_mismatch; + ctx->expect_skid = /*true*/ TRUE; + break; + default: + goto unsupported; + } + + return 0; + +unsupported: + pr_warn("Unsupported SignerInfo version\n"); + return -EINVAL; +version_mismatch: + pr_warn("SignedData-SignerInfo version mismatch\n"); + return -EBADMSG; +} + +/* + * Extract a certificate and store it in the context. + */ +int +pkcs7_extract_cert(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct pkcs7_parse_context *ctx = context; + struct x509_certificate *x509; + + if (tag != ((ASN1_UNIV << 6) | ASN1_CONS_BIT | ASN1_SEQ)) + { + pr_debug("Cert began with tag %02x at %p\n", tag, (ULONG_PTR)ctx - (ULONG_PTR)ctx->data); + return -EBADMSG; + } + + /* We have to correct for the header so that the X.509 parser can start + * from the beginning. Note that since X.509 stipulates DER, there + * probably shouldn't be an EOC trailer - but it is in PKCS#7 (which + * stipulates BER). + */ + value = (void *)((unsigned char *)value - hdrlen); + vlen += hdrlen; + + if (((unsigned char *)value)[1] == 0x80) + { + vlen += 2; /* Indefinite length - there should be an EOC */ + pr_debug("Indefinite length - there should be an EOC \n"); + } + + x509 = x509_cert_parse(value, vlen); + if (IS_ERR(PtrToUlong(x509))) + return PTR_ERR(PtrToUlong(x509)); + + x509->index = ++ctx->x509_index; + pr_debug("Got cert %u for %s,tag=%d\n", x509->index, x509->subject, tag); + pr_debug("len=%d fingerprint %p\n", x509->id->len, x509->id->data); + + *ctx->ppcerts = x509; + ctx->ppcerts = &x509->next; + return 0; +} + +/* + * Save the certificate list + */ +int +pkcs7_note_certificate_list(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct pkcs7_parse_context *ctx = context; + + pr_devel("Got cert list (0x%02x),subject=%s,ppcerts=%p\n", tag, ctx->certs->subject, (*(ctx->ppcerts))); + + *ctx->ppcerts = ctx->msg->certs; + ctx->msg->certs = ctx->certs; + ctx->certs = NULL; + ctx->ppcerts = &ctx->certs; + return 0; +} + +/* + * Note the content type. + */ +int +pkcs7_note_content(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct pkcs7_parse_context *ctx = context; + + if (ctx->last_oid != OID_data && ctx->last_oid != OID_msIndirectData) + { + pr_warn("Unsupported data type %d\n", ctx->last_oid); + return -EINVAL; + } + + ctx->msg->data_type = ctx->last_oid; + return 0; +} + +/* + * Extract the data from the message and store that and its content type OID in + * the context. + */ +int +pkcs7_note_data(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct pkcs7_parse_context *ctx = context; + + pr_debug("Got data\n"); + + ctx->msg->data = value; + ctx->msg->data_len = vlen; + ctx->msg->data_hdrlen = hdrlen; + return 0; +} + +/* + * Parse authenticated attributes. + */ +int +pkcs7_sig_note_authenticated_attr(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct pkcs7_parse_context *ctx = context; + struct pkcs7_signed_info *sinfo = ctx->sinfo; + enum OID content_type; + + pr_devel( + "AuthAttr: %02x %u [%p],last_oid=%d,sinfo->aa_set=%d,signing_time=%d\n", + tag, + vlen, + value, + ctx->last_oid, + sinfo->aa_set, + sinfo->signing_time); + + switch (ctx->last_oid) + { + case OID_contentType: + if (__test_and_set_bit(sinfo_has_content_type, &sinfo->aa_set)) + { + pr_debug("case OID_contentType:sinfo->aa_set=%d\n", sinfo->aa_set); + goto repeated; + } + + content_type = look_up_OID(value, vlen); + if (content_type != ctx->msg->data_type) + { + pr_warn( + "Mismatch between global data type (%d) and sinfo %u (%d)\n", + ctx->msg->data_type, + sinfo->index, + content_type); + return -EBADMSG; + } + return 0; + + case OID_signingTime: + if (__test_and_set_bit(sinfo_has_signing_time, &sinfo->aa_set)) + { + pr_debug("case OID_signingTime:sinfo->aa_set=%d\n", sinfo->aa_set); + goto repeated; + } + + /* Should we check that the signing time is consistent + * with the signer's X.509 cert? + */ + return x509_decode_time(ctx->msg->certs, FALSE, TRUE, &sinfo->signing_time, hdrlen, tag, value, vlen); + + case OID_messageDigest: + if (__test_and_set_bit(sinfo_has_message_digest, &sinfo->aa_set)) + { + pr_debug("case OID_messageDigest:sinfo->aa_set=%d\n", sinfo->aa_set); + goto repeated; + } + + if (tag != ASN1_OTS) + return -EBADMSG; + sinfo->msgdigest = value; + sinfo->msgdigest_len = vlen; + pr_debug("case OID_messageDigest:sinfo->msgdigest=%p,msgdigest_len=%d\n", value, vlen); + return 0; + + case OID_smimeCapabilites: + if (__test_and_set_bit(sinfo_has_smime_caps, &sinfo->aa_set)) + { + pr_debug("case OID_smimeCapabilites:sinfo->aa_set=%d\n", sinfo->aa_set); + goto repeated; + } + + if (ctx->msg->data_type != OID_msIndirectData) + { + pr_warn("S/MIME Caps only allowed with Authenticode\n"); + return -EKEYREJECTED; + } + return 0; + + /* Microsoft SpOpusInfo seems to be contain cont[0] 16-bit BE + * char URLs and cont[1] 8-bit char URLs. + * + * Microsoft StatementType seems to contain a list of OIDs that + * are also used as extendedKeyUsage types in X.509 certs. + */ + case OID_msSpOpusInfo: + if (__test_and_set_bit(sinfo_has_ms_opus_info, &sinfo->aa_set)) + { + pr_debug("case OID_smimeCapabilites:sinfo->aa_set=%d\n", sinfo->aa_set); + goto repeated; + } + + goto authenticode_check; + case OID_msStatementType: + if (__test_and_set_bit(sinfo_has_ms_statement_type, &sinfo->aa_set)) + { + pr_debug("case OID_smimeCapabilites:sinfo->aa_set=%d\n", sinfo->aa_set); + goto repeated; + } + + authenticode_check: + if (ctx->msg->data_type != OID_msIndirectData) + { + pr_warn("Authenticode AuthAttrs only allowed with Authenticode\n"); + return -EKEYREJECTED; + } + /* I'm not sure how to validate these */ + return 0; + default: + return 0; + } + +repeated: + /* We permit max one item per AuthenticatedAttribute and no repeats */ + pr_warn("Repeated/multivalue AuthAttrs not permitted\n"); + return -EKEYREJECTED; +} + +/* + * Note the set of auth attributes for digestion purposes [RFC2315 sec 9.3] + */ +int +pkcs7_sig_note_set_of_authattrs(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct pkcs7_parse_context *ctx = context; + struct pkcs7_signed_info *sinfo = ctx->sinfo; + + if (!test_bit(sinfo_has_content_type, &sinfo->aa_set) || !test_bit(sinfo_has_message_digest, &sinfo->aa_set)) + { + pr_warn("Missing required AuthAttr\n"); + return -EBADMSG; + } + + if (ctx->msg->data_type != OID_msIndirectData && test_bit(sinfo_has_ms_opus_info, &sinfo->aa_set)) + { + pr_warn("Unexpected Authenticode AuthAttr\n"); + return -EBADMSG; + } + + /* We need to switch the 'CONT 0' to a 'SET OF' when we digest */ + sinfo->authattrs = (void *)((unsigned char *)value - (hdrlen - 1)); + sinfo->authattrs_len = vlen + (hdrlen - 1); + return 0; +} + +/* + * Note the issuing certificate serial number + */ +int +pkcs7_sig_note_serial(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct pkcs7_parse_context *ctx = context; + ctx->raw_serial = value; + ctx->raw_serial_size = vlen; + return 0; +} + +/* + * Note the issuer's name + */ +int +pkcs7_sig_note_issuer(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct pkcs7_parse_context *ctx = context; + ctx->raw_issuer = value; + ctx->raw_issuer_size = vlen; + return 0; +} + +/* + * Note the issuing cert's subjectKeyIdentifier + */ +int +pkcs7_sig_note_skid(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct pkcs7_parse_context *ctx = context; + + pr_devel("SKID: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value); + + ctx->raw_skid = value; + ctx->raw_skid_size = vlen; + return 0; +} + +/* + * Note the signature data + */ +int +pkcs7_sig_note_signature(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct pkcs7_parse_context *ctx = context; + + ctx->sinfo->sig->s = kmemdup(value, vlen, GFP_KERNEL); + if (!ctx->sinfo->sig->s) + return -ENOMEM; + + ctx->sinfo->sig->s_size = vlen; + return 0; +} + +/* + * Note a signature information block + */ +int +pkcs7_note_signed_info(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct pkcs7_parse_context *ctx = context; + struct pkcs7_signed_info *sinfo = ctx->sinfo; + struct asymmetric_key_id *kid; + + if (ctx->msg->data_type == OID_msIndirectData && !sinfo->authattrs) + { + pr_warn("Authenticode requires AuthAttrs\n"); + return -EBADMSG; + } + + /* Generate cert issuer + serial number key ID */ + if (!ctx->expect_skid) + { + kid = asymmetric_key_generate_id(ctx->raw_serial, ctx->raw_serial_size, ctx->raw_issuer, ctx->raw_issuer_size); + } + else + { + kid = asymmetric_key_generate_id(ctx->raw_skid, ctx->raw_skid_size, "", 0); + } + if (IS_ERR(PtrToUlong(kid))) + return PTR_ERR(PtrToUlong(kid)); + + pr_devel("SINFO KID: %u [%p]\n", kid->len, kid->data); + + sinfo->sig->auth_ids[0] = kid; + sinfo->index = ++ctx->sinfo_index; + *ctx->ppsinfo = sinfo; + ctx->ppsinfo = &sinfo->next; + ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL); + if (!ctx->sinfo) + return -ENOMEM; + ctx->sinfo->sig = kzalloc(sizeof(struct public_key_signature), GFP_KERNEL); + if (!ctx->sinfo->sig) + return -ENOMEM; + return 0; +} diff --git a/Lib-SoulExtraction/linux/pkcs7_parser.h b/Lib-SoulExtraction/linux/pkcs7_parser.h new file mode 100644 index 0000000..ff29bfc --- /dev/null +++ b/Lib-SoulExtraction/linux/pkcs7_parser.h @@ -0,0 +1,81 @@ +/* PKCS#7 crypto data parser internal definitions + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#pragma once + +//#include +//#include +//#include "x509_parser.h" + +#include "pkcs7.h" +#include "x509_parser.h" +#include "public_key.h" +#include "oid_registry.h" + +//#define kenter(FMT, ...) \ +// pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__) +//#define kleave(FMT, ...) \ +// pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) + +#define kenter +#define kleave + +struct pkcs7_signed_info +{ + struct pkcs7_signed_info *next; + struct x509_certificate *signer; /* Signing certificate (in msg->certs) */ + unsigned index; + /*bool*/ unsigned char unsupported_crypto; /* T if not usable due to missing crypto */ + /*bool*/ unsigned char blacklisted; + + /* Message digest - the digest of the Content Data (or NULL) */ + const void *msgdigest; + unsigned msgdigest_len; + + /* Authenticated Attribute data (or NULL) */ + unsigned authattrs_len; + const void *authattrs; + unsigned long aa_set; +#define sinfo_has_content_type 0 +#define sinfo_has_signing_time 1 +#define sinfo_has_message_digest 2 +#define sinfo_has_smime_caps 3 +#define sinfo_has_ms_opus_info 4 +#define sinfo_has_ms_statement_type 5 + /*time64_t*/ long long signing_time; + + /* Message signature. + * + * This contains the generated digest of _either_ the Content Data or + * the Authenticated Attributes [RFC2315 9.3]. If the latter, one of + * the attributes contains the digest of the the Content Data within + * it. + * + * THis also contains the issuing cert serial number and issuer's name + * [PKCS#7 or CMS ver 1] or issuing cert's SKID [CMS ver 3]. + */ + struct public_key_signature *sig; +}; + +struct pkcs7_message +{ + struct x509_certificate *certs; /* Certificate list */ + struct x509_certificate *crl; /* Revocation list */ + struct pkcs7_signed_info *signed_infos; + /*u8*/ unsigned char version; /* Version of cert (1 -> PKCS#7 or CMS; 3 -> CMS) */ + /*bool*/ unsigned char have_authattrs; /* T if have authattrs */ + + /* Content Data (or NULL) */ + enum OID data_type; /* Type of Data */ + size_t data_len; /* Length of Data */ + size_t data_hdrlen; /* Length of Data ASN.1 header */ + const void *data; /* Content Data (or 0) */ +}; diff --git a/Lib-SoulExtraction/linux/public_key.c b/Lib-SoulExtraction/linux/public_key.c new file mode 100644 index 0000000..16ce47c --- /dev/null +++ b/Lib-SoulExtraction/linux/public_key.c @@ -0,0 +1,193 @@ +/* In-software asymmetric public-key crypto subtype + * + * See Documentation/crypto/asymmetric-keys.txt + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +//#define pr_fmt(fmt) "PKEY: "fmt +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +// +// MODULE_LICENSE("GPL"); + +#include "public_key.h" + +#include "../rewrite/Lib.SoulExtraction.rewrite.h" + +/* + * Provide a part of a description of the key for /proc/keys. + */ +// static void public_key_describe(const struct key *asymmetric_key, +// struct seq_file *m) +//{ +// struct public_key *key = asymmetric_key->payload.data[asym_crypto]; +// +// if (key) +// seq_printf(m, "%s.%s", key->id_type, key->pkey_algo); +// } + +/* + * Destroy a public key algorithm key. + */ +void +public_key_free(struct public_key *key) +{ + if (key) + { + kfree(key->key); + kfree(key); + } +} +// EXPORT_SYMBOL_GPL(public_key_free); + +/* + * Destroy a public key algorithm key. + */ +// static void public_key_destroy(void *payload0, void *payload3) +//{ +// public_key_free(payload0); +// public_key_signature_free(payload3); +// } + +// struct public_key_completion { +// struct completion completion; +// int err; +// }; +// +// static void public_key_verify_done(struct crypto_async_request *req, int err) +//{ +// struct public_key_completion *compl = req->data; +// +// if (err == -EINPROGRESS) +// return; +// +// compl->err = err; +// complete(&compl->completion); +// } + +/* + * Verify a signature using a public key. + */ +// int public_key_verify_signature(const struct public_key *pkey, +// const struct public_key_signature *sig) +//{ +// struct public_key_completion compl; +// struct crypto_akcipher *tfm; +// struct akcipher_request *req; +// struct scatterlist sig_sg, digest_sg; +// const char *alg_name; +// char alg_name_buf[CRYPTO_MAX_ALG_NAME]; +// void *output; +// unsigned int outlen; +// int ret = -ENOMEM; +// +// pr_devel("==>%s()\n", __func__); +// +// BUG_ON(!pkey); +// BUG_ON(!sig); +// BUG_ON(!sig->s); +// +// if (!sig->digest) +// return -ENOPKG; +// +// alg_name = sig->pkey_algo; +// if (strcmp(sig->pkey_algo, "rsa") == 0) { +// /* The data wangled by the RSA algorithm is typically padded +// * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447 +// * sec 8.2]. +// */ +// if (snprintf(alg_name_buf, CRYPTO_MAX_ALG_NAME, +// "pkcs1pad(rsa,%s)", sig->hash_algo +// ) >= CRYPTO_MAX_ALG_NAME) +// return -EINVAL; +// alg_name = alg_name_buf; +// } +// +// tfm = crypto_alloc_akcipher(alg_name, 0, 0); +// if (IS_ERR(tfm)) +// return PTR_ERR(tfm); +// +// req = akcipher_request_alloc(tfm, GFP_KERNEL); +// if (!req) +// goto error_free_tfm; +// +// ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen); +// if (ret) +// goto error_free_req; +// +// ret = -ENOMEM; +// outlen = crypto_akcipher_maxsize(tfm); +// output = kmalloc(outlen, GFP_KERNEL); +// if (!output) +// goto error_free_req; +// +// sg_init_one(&sig_sg, sig->s, sig->s_size); +// sg_init_one(&digest_sg, output, outlen); +// akcipher_request_set_crypt(req, &sig_sg, &digest_sg, sig->s_size, +// outlen); +// init_completion(&compl.completion); +// akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | +// CRYPTO_TFM_REQ_MAY_SLEEP, +// public_key_verify_done, &compl); +// +// /* Perform the verification calculation. This doesn't actually do the +// * verification, but rather calculates the hash expected by the +// * signature and returns that to us. +// */ +// ret = crypto_akcipher_verify(req); +// if ((ret == -EINPROGRESS) || (ret == -EBUSY)) { +// wait_for_completion(&compl.completion); +// ret = compl.err; +// } +// if (ret < 0) +// goto out_free_output; +// +// /* Do the actual verification step. */ +// if (req->dst_len != sig->digest_size || +// memcmp(sig->digest, output, sig->digest_size) != 0) +// ret = -EKEYREJECTED; +// +// out_free_output: +// kfree(output); +// error_free_req: +// akcipher_request_free(req); +// error_free_tfm: +// crypto_free_akcipher(tfm); +// pr_devel("<==%s() = %d\n", __func__, ret); +// return ret; +// } +// EXPORT_SYMBOL_GPL(public_key_verify_signature); +// +// static int public_key_verify_signature_2(const struct key *key, +// const struct public_key_signature *sig) +//{ +// const struct public_key *pk = key->payload.data[asym_crypto]; +// return public_key_verify_signature(pk, sig); +// } + +/* + * Public key algorithm asymmetric key subtype + */ +// struct asymmetric_key_subtype public_key_subtype = { +// .owner = THIS_MODULE, +// .name = "public_key", +// .name_len = sizeof("public_key") - 1, +// .describe = public_key_describe, +// .destroy = public_key_destroy, +// .verify_signature = public_key_verify_signature_2, +// }; +// EXPORT_SYMBOL_GPL(public_key_subtype); diff --git a/Lib-SoulExtraction/linux/public_key.h b/Lib-SoulExtraction/linux/public_key.h new file mode 100644 index 0000000..787c5a0 --- /dev/null +++ b/Lib-SoulExtraction/linux/public_key.h @@ -0,0 +1,82 @@ +/* Asymmetric public-key algorithm definitions + * + * See Documentation/crypto/asymmetric-keys.txt + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _LINUX_PUBLIC_KEY_H +#define _LINUX_PUBLIC_KEY_H + +#include + +#include "asymmetric-type.h" + +/* + * Cryptographic data for the public-key subtype of the asymmetric key type. + * + * Note that this may include private part of the key as well as the public + * part. + */ +struct public_key +{ + void *key; + /*u32*/ unsigned long keylen; + const char *id_type; + const char *pkey_algo; +}; + +extern void +public_key_free(struct public_key *key); + +/* + * Public key cryptography signature data + */ +struct public_key_signature +{ + struct asymmetric_key_id *auth_ids[2]; + /*u8*/ unsigned char *s; /* Signature */ + /*u32*/ unsigned long s_size; /* Number of bytes in signature */ + /*u8*/ unsigned char *digest; + /*u8*/ unsigned char digest_size; /* Number of bytes in digest */ + const char *pkey_algo; + const char *hash_algo; +}; + +extern void +public_key_signature_free(struct public_key_signature *sig); + +// extern struct asymmetric_key_subtype public_key_subtype; + +// struct key; +// struct key_type; +// union key_payload; + +// extern int restrict_link_by_signature(struct key *dest_keyring, +// const struct key_type *type, +// const union key_payload *payload, +// struct key *trust_keyring); + +// extern int restrict_link_by_key_or_keyring(struct key *dest_keyring, +// const struct key_type *type, +// const union key_payload *payload, +// struct key *trusted); + +// extern int restrict_link_by_key_or_keyring_chain(struct key *trust_keyring, +// const struct key_type *type, +// const union key_payload *payload, +// struct key *trusted); + +// extern int verify_signature(const struct key *key, +// const struct public_key_signature *sig); + +// int public_key_verify_signature(const struct public_key *pkey, +// const struct public_key_signature *sig); + +#endif /* _LINUX_PUBLIC_KEY_H */ diff --git a/Lib-SoulExtraction/linux/signature.c b/Lib-SoulExtraction/linux/signature.c new file mode 100644 index 0000000..d83793d --- /dev/null +++ b/Lib-SoulExtraction/linux/signature.c @@ -0,0 +1,76 @@ +/* Signature verification with an asymmetric key + * + * See Documentation/security/asymmetric-keys.txt + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +//#define pr_fmt(fmt) "SIG: "fmt +//#include +//#include +//#include +//#include +//#include +//#include "asymmetric_keys.h" + +#include "public_key.h" + +#include "../rewrite/Lib.SoulExtraction.rewrite.h" + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +/* + * Destroy a public key signature. + */ +void +public_key_signature_free(struct public_key_signature *sig) +{ + int i; + + if (sig) + { + for (i = 0; i < ARRAY_SIZE(sig->auth_ids); i++) + kfree(sig->auth_ids[i]); + kfree(sig->s); + kfree(sig->digest); + kfree(sig); + } +} +// EXPORT_SYMBOL_GPL(public_key_signature_free); + +/** + * verify_signature - Initiate the use of an asymmetric key to verify a signature + * @key: The asymmetric key to verify against + * @sig: The signature to check + * + * Returns 0 if successful or else an error. + */ +// int verify_signature(const struct key *key, +// const struct public_key_signature *sig) +//{ +// const struct asymmetric_key_subtype *subtype; +// int ret; +// +// pr_devel("==>%s()\n", __func__); +// +// if (key->type != &key_type_asymmetric) +// return -EINVAL; +// subtype = asymmetric_key_subtype(key); +// if (!subtype || +// !key->payload.data[0]) +// return -EINVAL; +// if (!subtype->verify_signature) +// return -ENOTSUPP; +// +// ret = subtype->verify_signature(key, sig); +// +// pr_devel("<==%s() = %d\n", __func__, ret); +// return ret; +// } +// EXPORT_SYMBOL_GPL(verify_signature); diff --git a/Lib-SoulExtraction/linux/system_keyring.c b/Lib-SoulExtraction/linux/system_keyring.c new file mode 100644 index 0000000..fc0f98a --- /dev/null +++ b/Lib-SoulExtraction/linux/system_keyring.c @@ -0,0 +1,338 @@ +//// SPDX-License-Identifier: GPL-2.0-or-later +///* System trusted keyring for trusted public keys +// * +// * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. +// * Written by David Howells (dhowells@redhat.com) +// */ +// +////#include +////#include +////#include +////#include +////#include +////#include +////#include +////#include +////#include +////#include +// +// +//#include "pkcs7.h" +//#include "errno.h" +// +// +//#include "../rewrite/lib_vsign_rewritefunc.h" +// +// +//// +//// macro +//// +// +// +////laji daima +//#define pr_debug +//#define pr_devel +//#define pr_warn +//#define pr_err +//#define printk +// +//#define GFP_ATOMIC /*(__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)*/1 +//#define GFP_KERNEL /*(__GFP_RECLAIM | __GFP_IO | __GFP_FS)*/2 +//#define GFP_KERNEL_ACCOUNT /*(GFP_KERNEL | __GFP_ACCOUNT)*/3 +//#define GFP_NOWAIT /*(__GFP_KSWAPD_RECLAIM)*/4 +//#define GFP_NOIO /*(__GFP_RECLAIM)*/5 +//#define GFP_NOFS /*(__GFP_RECLAIM | __GFP_IO)*/6 +//#define GFP_USER /*(__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL)*/7 +//#define GFP_DMA /*__GFP_DMA*/8 +//#define GFP_DMA32 /*__GFP_DMA32*/9 +//#define GFP_HIGHUSER /*(GFP_USER | __GFP_HIGHMEM)*/10 +//#define GFP_HIGHUSER_MOVABLE /*(GFP_HIGHUSER | __GFP_MOVABLE)*/11 +//#define GFP_TRANSHUGE_LIGHT 12 +//#define GFP_TRANSHUGE /*(GFP_TRANSHUGE_LIGHT | __GFP_DIRECT_RECLAIM)*/13 +// +// +//#define ERR_PTR(err) ((void *)((long)(err))) +//#define PTR_ERR(ptr) ((long)(ptr)) +//#define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000)) +// +// +//#define CONFIG_SECONDARY_TRUSTED_KEYRING +//#define CONFIG_INTEGRITY_PLATFORM_KEYRING +// +//#define CONFIG_SYSTEM_DATA_VERIFICATION +// +// +// +// +//static struct key *builtin_trusted_keys; +//#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING +//static struct key *secondary_trusted_keys; +//#endif +//#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING +//static struct key *platform_trusted_keys; +//#endif +// +////extern __initconst const u8 system_certificate_list[]; +////extern __initconst const unsigned long system_certificate_list_size; +// +// +///** +// * restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA +// * +// * Restrict the addition of keys into a keyring based on the key-to-be-added +// * being vouched for by a key in the built in system keyring. +// */ +//int restrict_link_by_builtin_trusted(struct key *dest_keyring, +// const struct key_type *type, +// const union key_payload *payload, +// struct key *restriction_key) +//{ +// return restrict_link_by_signature(dest_keyring, type, payload, +// builtin_trusted_keys); +//} +// +//#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING +///** +// * restrict_link_by_builtin_and_secondary_trusted - Restrict keyring +// * addition by both builtin and secondary keyrings +// * +// * Restrict the addition of keys into a keyring based on the key-to-be-added +// * being vouched for by a key in either the built-in or the secondary system +// * keyrings. +// */ +//int restrict_link_by_builtin_and_secondary_trusted( +// struct key *dest_keyring, +// const struct key_type *type, +// const union key_payload *payload, +// struct key *restrict_key) +//{ +// /* If we have a secondary trusted keyring, then that contains a link +// * through to the builtin keyring and the search will follow that link. +// */ +// if (type == &key_type_keyring && +// dest_keyring == secondary_trusted_keys && +// payload == &builtin_trusted_keys->payload) +// /* Allow the builtin keyring to be added to the secondary */ +// return 0; +// +// return restrict_link_by_signature(dest_keyring, type, payload, +// secondary_trusted_keys); +//} +// +///** +// * Allocate a struct key_restriction for the "builtin and secondary trust" +// * keyring. Only for use in system_trusted_keyring_init(). +// */ +//static __init struct key_restriction *get_builtin_and_secondary_restriction(void) +//{ +// struct key_restriction *restriction; +// +// restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL); +// +// if (!restriction) +// panic("Can't allocate secondary trusted keyring restriction\n"); +// +// restriction->check = restrict_link_by_builtin_and_secondary_trusted; +// +// return restriction; +//} +//#endif +// +///* +// * Create the trusted keyrings +// */ +////static __init int system_trusted_keyring_init(void) +////{ +//// pr_notice("Initialise system trusted keyrings\n"); +//// +//// builtin_trusted_keys = +//// keyring_alloc(".builtin_trusted_keys", +//// KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), +//// ((KEY_POS_ALL & ~KEY_POS_SETATTR) | +//// KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH), +//// KEY_ALLOC_NOT_IN_QUOTA, +//// NULL, NULL); +//// if (IS_ERR(builtin_trusted_keys)) +//// panic("Can't allocate builtin trusted keyring\n"); +//// +////#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING +//// secondary_trusted_keys = +//// keyring_alloc(".secondary_trusted_keys", +//// KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), +//// ((KEY_POS_ALL & ~KEY_POS_SETATTR) | +//// KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH | +//// KEY_USR_WRITE), +//// KEY_ALLOC_NOT_IN_QUOTA, +//// get_builtin_and_secondary_restriction(), +//// NULL); +//// if (IS_ERR(secondary_trusted_keys)) +//// panic("Can't allocate secondary trusted keyring\n"); +//// +//// if (key_link(secondary_trusted_keys, builtin_trusted_keys) < 0) +//// panic("Can't link trusted keyrings\n"); +////#endif +//// +//// return 0; +////} +// +///* +// * Must be initialised before we try and load the keys into the keyring. +// */ +////device_initcall(system_trusted_keyring_init); +//// +/////* +//// * Load the compiled-in list of X.509 certificates. +//// */ +////static __init int load_system_certificate_list(void) +////{ +//// key_ref_t key; +//// const u8 *p, *end; +//// size_t plen; +//// +//// pr_notice("Loading compiled-in X.509 certificates\n"); +//// +//// p = system_certificate_list; +//// end = p + system_certificate_list_size; +//// while (p < end) { +//// /* Each cert begins with an ASN.1 SEQUENCE tag and must be more +//// * than 256 bytes in size. +//// */ +//// if (end - p < 4) +//// goto dodgy_cert; +//// if (p[0] != 0x30 && +//// p[1] != 0x82) +//// goto dodgy_cert; +//// plen = (p[2] << 8) | p[3]; +//// plen += 4; +//// if (plen > end - p) +//// goto dodgy_cert; +//// +//// key = key_create_or_update(make_key_ref(builtin_trusted_keys, 1), +//// "asymmetric", +//// NULL, +//// p, +//// plen, +//// ((KEY_POS_ALL & ~KEY_POS_SETATTR) | +//// KEY_USR_VIEW | KEY_USR_READ), +//// KEY_ALLOC_NOT_IN_QUOTA | +//// KEY_ALLOC_BUILT_IN | +//// KEY_ALLOC_BYPASS_RESTRICTION); +//// if (IS_ERR(key)) { +//// pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", +//// PTR_ERR(key)); +//// } else { +//// pr_notice("Loaded X.509 cert '%s'\n", +//// key_ref_to_ptr(key)->description); +//// key_ref_put(key); +//// } +//// p += plen; +//// } +//// +//// return 0; +//// +////dodgy_cert: +//// pr_err("Problem parsing in-kernel X.509 certificate list\n"); +//// return 0; +////} +////late_initcall(load_system_certificate_list); +// +// +// +//#ifdef CONFIG_SYSTEM_DATA_VERIFICATION +// +///** +// * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data. +// * @data: The data to be verified (NULL if expecting internal data). +// * @len: Size of @data. +// * @raw_pkcs7: The PKCS#7 message that is the signature. +// * @pkcs7_len: The size of @raw_pkcs7. +// * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only, +// * (void *)1UL for all trusted keys). +// * @usage: The use to which the key is being put. +// * @view_content: Callback to gain access to content. +// * @ctx: Context for callback. +// */ +//int verify_pkcs7_signature(const void *data, size_t len, +// const void *raw_pkcs7, size_t pkcs7_len, +// struct key *trusted_keys, +// enum key_being_used_for usage, +// int (*view_content)(void *ctx, +// const void *data, size_t len, +// size_t asn1hdrlen), +// void *ctx) +//{ +// struct pkcs7_message *pkcs7; +// int ret; +// +// pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len); +// if (IS_ERR(pkcs7)) +// return PTR_ERR(pkcs7); +// +// /* The data should be detached - so we need to supply it. */ +// if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) { +// pr_err("PKCS#7 signature with non-detached data\n"); +// ret = -EBADMSG; +// goto error; +// } +// +// ret = pkcs7_verify(pkcs7, usage); +// if (ret < 0) +// goto error; +// +// if (!trusted_keys) { +// trusted_keys = builtin_trusted_keys; +// } else if (trusted_keys == VERIFY_USE_SECONDARY_KEYRING) { +//#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING +// trusted_keys = secondary_trusted_keys; +//#else +// trusted_keys = builtin_trusted_keys; +//#endif +// } else if (trusted_keys == VERIFY_USE_PLATFORM_KEYRING) { +//#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING +// trusted_keys = platform_trusted_keys; +//#else +// trusted_keys = NULL; +//#endif +// if (!trusted_keys) { +// ret = -ENOKEY; +// pr_devel("PKCS#7 platform keyring is not available\n"); +// goto error; +// } +// } +// ret = pkcs7_validate_trust(pkcs7, trusted_keys); +// if (ret < 0) { +// if (ret == -ENOKEY) +// pr_devel("PKCS#7 signature not signed with a trusted key\n"); +// goto error; +// } +// +// if (view_content) { +// size_t asn1hdrlen; +// +// ret = pkcs7_get_content_data(pkcs7, &data, &len, &asn1hdrlen); +// if (ret < 0) { +// if (ret == -ENODATA) +// pr_devel("PKCS#7 message does not contain data\n"); +// goto error; +// } +// +// ret = view_content(ctx, data, len, asn1hdrlen); +// } +// +//error: +// pkcs7_free_message(pkcs7); +// pr_devel("<==%s() = %d\n", __func__, ret); +// return ret; +//} +// +// +////EXPORT_SYMBOL_GPL(verify_pkcs7_signature); +// +//#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */ +// +////#ifdef CONFIG_INTEGRITY_PLATFORM_KEYRING +////void __init set_platform_trusted_keys(struct key *keyring) +////{ +//// platform_trusted_keys = keyring; +////} +////#endif diff --git a/Lib-SoulExtraction/linux/verify_pefile.c b/Lib-SoulExtraction/linux/verify_pefile.c new file mode 100644 index 0000000..9e98c0e --- /dev/null +++ b/Lib-SoulExtraction/linux/verify_pefile.c @@ -0,0 +1,575 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Parse a signed PE binary + * + * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +//#define pr_fmt(fmt) "PEFILE: "fmt +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include "verify_pefile.h" + +#include "verify_pefile.h" +#include "errno.h" +#include "asn1.h" + +#include "config.h" + +#include "pe.h" + +#include "../rewrite/Lib.SoulExtraction.rewrite.h" + +// +// macro +// + +#define GFP_ATOMIC /*(__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)*/ 1 +#define GFP_KERNEL /*(__GFP_RECLAIM | __GFP_IO | __GFP_FS)*/ 2 +#define GFP_KERNEL_ACCOUNT /*(GFP_KERNEL | __GFP_ACCOUNT)*/ 3 +#define GFP_NOWAIT /*(__GFP_KSWAPD_RECLAIM)*/ 4 +#define GFP_NOIO /*(__GFP_RECLAIM)*/ 5 +#define GFP_NOFS /*(__GFP_RECLAIM | __GFP_IO)*/ 6 +#define GFP_USER /*(__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL)*/ 7 +#define GFP_DMA /*__GFP_DMA*/ 8 +#define GFP_DMA32 /*__GFP_DMA32*/ 9 +#define GFP_HIGHUSER /*(GFP_USER | __GFP_HIGHMEM)*/ 10 +#define GFP_HIGHUSER_MOVABLE /*(GFP_HIGHUSER | __GFP_MOVABLE)*/ 11 +#define GFP_TRANSHUGE_LIGHT 12 +#define GFP_TRANSHUGE /*(GFP_TRANSHUGE_LIGHT | __GFP_DIRECT_RECLAIM)*/ 13 + +#define ERR_PTR(err) ((void *)((long)(err))) +#define PTR_ERR(ptr) ((long)(ptr)) +#define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000)) + +///* +// * This looks more complex than it should be. But we need to +// * get the type for the ~ right in round_down (it needs to be +// * as wide as the result!), and we want to evaluate the macro +// * arguments just once each. +// */ +//#define __round_mask(x, y) ((__typeof__(x))((y)-1)) +// +///** +// * round_up - round up to next specified power of 2 +// * @x: the value to round +// * @y: multiple to round up to (must be a power of 2) +// * +// * Rounds @x up to next multiple of @y (which must be a power of 2). +// * To perform arbitrary rounding up, use roundup() below. +// */ +//#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) +///** +//* round_up - round up to next specified power of 2 +//* @x: the value to round +//* @y: multiple to round up to (must be a power of 2) +//* +//* Rounds @x up to next multiple of @y (which must be a power of 2). +//* To perform arbitrary rounding up, use roundup() below. +//*/ +//#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) +///** +//* round_down - round down to next specified power of 2 +//* @x: the value to round +//* @y: multiple to round down to (must be a power of 2) +//* +//* Rounds @x down to next multiple of @y (which must be a power of 2). +//* To perform arbitrary rounding down, use rounddown() below. +//*/ +//#define round_down(x, y) ((x) & ~__round_mask(x, y)) + +/* n must be power of 2 */ +#define round_up(x, n) (((x) + (n)-1u) & ~((n)-1u)) + +/* + * Parse a PE binary. + */ +int +pefile_parse_binary(const void *pebuf, unsigned int pelen, struct pefile_context *ctx) +{ + const struct mz_hdr *mz = pebuf; + const struct pe_hdr *pe; + const struct pe32_opt_hdr *pe32; + const struct pe32plus_opt_hdr *pe64; + const struct data_directory *ddir; + const struct data_dirent *dde; + const struct section_header *secs, *sec; + size_t cursor, datalen = pelen; + + kenter(""); + +#define chkaddr(base, x, s) \ + do \ + { \ + if ((x) < base || (s) >= datalen || (x) > datalen - (s)) \ + return -ELIBBAD; \ + } while (0) + + // chkaddr(0, 0, sizeof(*mz)); + + if (sizeof(*mz) >= datalen) + return -ELIBBAD; + + if (mz->magic != MZ_MAGIC) + return -ELIBBAD; + cursor = sizeof(*mz); + + chkaddr(cursor, mz->peaddr, sizeof(*pe)); + pe = (struct pe_hdr *)((unsigned char *)pebuf + mz->peaddr); + if (pe->magic != PE_MAGIC) + return -ELIBBAD; + cursor = mz->peaddr + sizeof(*pe); + + // chkaddr(0, cursor, sizeof(pe32->magic)); + + if ((sizeof(pe32->magic)) >= datalen || cursor > datalen - sizeof(pe32->magic)) + return -ELIBBAD; + + pe32 = (struct pe32_opt_hdr *)((unsigned char *)pebuf + cursor); + pe64 = (struct pe32plus_opt_hdr *)((unsigned char *)pebuf + cursor); + + switch (pe32->magic) + { + case PE_OPT_MAGIC_PE32: + // chkaddr(0, cursor, sizeof(*pe32)); + if ((sizeof(*pe32)) >= datalen || cursor > datalen - sizeof(*pe32)) + return -ELIBBAD; + + ctx->image_checksum_offset = (unsigned)((unsigned char *)&pe32->csum - (unsigned char *)pebuf); + ctx->header_size = pe32->header_size; + cursor += sizeof(*pe32); + ctx->n_data_dirents = pe32->data_dirs; + break; + + case PE_OPT_MAGIC_PE32PLUS: + // chkaddr(0, cursor, sizeof(*pe64)); + if ((sizeof(*pe64)) >= datalen || cursor > datalen - sizeof(*pe64)) + return -ELIBBAD; + ctx->image_checksum_offset = (unsigned)((unsigned char *)&pe64->csum - (unsigned char *)pebuf); + ctx->header_size = pe64->header_size; + cursor += sizeof(*pe64); + ctx->n_data_dirents = pe64->data_dirs; + break; + + default: + pr_debug("Unknown PEOPT magic = %04hx\n", pe32->magic); + return -ELIBBAD; + } + + pr_debug("checksum @ %x\n", ctx->image_checksum_offset); + pr_debug("header size = %x\n", ctx->header_size); + + if (cursor >= ctx->header_size || ctx->header_size >= datalen) + return -ELIBBAD; + + if (ctx->n_data_dirents > (ctx->header_size - cursor) / sizeof(*dde)) + return -ELIBBAD; + + ddir = (struct data_directory *)((unsigned char *)pebuf + cursor); + cursor += sizeof(*dde) * ctx->n_data_dirents; + + ctx->cert_dirent_offset = (unsigned)((unsigned char *)&ddir->certs - (unsigned char *)pebuf); + ctx->certs_size = ddir->certs.size; + + if (!ddir->certs.virtual_address || !ddir->certs.size) + { + pr_debug("Unsigned PE binary\n"); + return -EKEYREJECTED; + } + + chkaddr(ctx->header_size, ddir->certs.virtual_address, ddir->certs.size); + ctx->sig_offset = ddir->certs.virtual_address; + ctx->sig_len = ddir->certs.size; + pr_debug( + "cert = %x @%x [%p]\n", ctx->sig_len, ctx->sig_offset, ctx->sig_len, (unsigned char *)pebuf + ctx->sig_offset); + + ctx->n_sections = pe->sections; + if (ctx->n_sections > (ctx->header_size - cursor) / sizeof(*sec)) + return -ELIBBAD; + ctx->secs = secs = (struct section_header *)((unsigned char *)pebuf + cursor); + + return 0; +} + +/* + * Check and strip the PE wrapper from around the signature and check that the + * remnant looks something like PKCS#7. + */ +int +pefile_strip_sig_wrapper(const void *pebuf, struct pefile_context *ctx) +{ + struct win_certificate wrapper; + const unsigned char *pkcs7; + unsigned len; + unsigned char pkcs7_1; + + if (ctx->sig_len < sizeof(wrapper)) + { + pr_debug("Signature wrapper too short\n"); + return -ELIBBAD; + } + + memcpy(&wrapper, (void *)((unsigned char *)pebuf + ctx->sig_offset), sizeof(wrapper)); + pr_debug("sig wrapper = { %x, %x, %x }\n", wrapper.length, wrapper.revision, wrapper.cert_type); + + /* Both pesign and sbsign round up the length of certificate table + * (in optional header data directories) to 8 byte alignment. + */ + if (round_up(wrapper.length, 8) != ctx->sig_len) + { + pr_debug("Signature wrapper len wrong\n"); + return -ELIBBAD; + } + + if (wrapper.revision != WIN_CERT_REVISION_2_0) + { + pr_debug("Signature is not revision 2.0\n"); + return -ENOTSUPP; + } + if (wrapper.cert_type != WIN_CERT_TYPE_PKCS_SIGNED_DATA) + { + pr_debug("Signature certificate type is not PKCS\n"); + return -ENOTSUPP; + } + + /* It looks like the pkcs signature length in wrapper->length and the + * size obtained from the data dir entries, which lists the total size + * of certificate table, are both aligned to an octaword boundary, so + * we may have to deal with some padding. + */ + ctx->sig_len = wrapper.length; + ctx->sig_offset += sizeof(wrapper); + ctx->sig_len -= sizeof(wrapper); + if (ctx->sig_len < 4) + { + pr_debug("Signature data missing\n"); + return -EKEYREJECTED; + } + + /* What's left should be a PKCS#7 cert */ + pkcs7 = (unsigned char *)((unsigned char *)pebuf + ctx->sig_offset); + if (pkcs7[0] != (ASN1_CONS_BIT | ASN1_SEQ)) + goto not_pkcs7; + + pkcs7_1 = pkcs7[1]; + if (pkcs7_1 >= 0 && pkcs7_1 <= 0x7f) + { + len = pkcs7[1] + 2; + goto check_len; + } + else if (pkcs7_1 == ASN1_INDEFINITE_LENGTH) + { + return 0; + } + else if (pkcs7_1 == 0x81) + { + len = pkcs7[2] + 3; + goto check_len; + } + else if (pkcs7_1 == 0x82) + { + len = ((pkcs7[2] << 8) | pkcs7[3]) + 4; + goto check_len; + } + else if (pkcs7_1 >= 0x83 && pkcs7_1 <= 0xff) + { + return -EMSGSIZE; + } + else + { + goto not_pkcs7; + } + + /*switch (pkcs7[1]) { + case 0 ... 0x7f: + len = pkcs7[1] + 2; + goto check_len; + case ASN1_INDEFINITE_LENGTH: + return 0; + case 0x81: + len = pkcs7[2] + 3; + goto check_len; + case 0x82: + len = ((pkcs7[2] << 8) | pkcs7[3]) + 4; + goto check_len; + case 0x83 ... 0xff: + return -EMSGSIZE; + default: + goto not_pkcs7; + }*/ + +check_len: + if (len <= ctx->sig_len) + { + /* There may be padding */ + ctx->sig_len = len; + return 0; + } +not_pkcs7: + pr_debug("Signature data not PKCS#7\n"); + return -ELIBBAD; +} + +/* + * Compare two sections for canonicalisation. + */ +// static int pefile_compare_shdrs(const void *a, const void *b) +//{ +// const struct section_header *shdra = a; +// const struct section_header *shdrb = b; +// int rc; +// +// if (shdra->data_addr > shdrb->data_addr) +// return 1; +// if (shdrb->data_addr > shdra->data_addr) +// return -1; +// +// if (shdra->virtual_address > shdrb->virtual_address) +// return 1; +// if (shdrb->virtual_address > shdra->virtual_address) +// return -1; +// +// rc = strcmp(shdra->name, shdrb->name); +// if (rc != 0) +// return rc; +// +// if (shdra->virtual_size > shdrb->virtual_size) +// return 1; +// if (shdrb->virtual_size > shdra->virtual_size) +// return -1; +// +// if (shdra->raw_data_size > shdrb->raw_data_size) +// return 1; +// if (shdrb->raw_data_size > shdra->raw_data_size) +// return -1; +// +// return 0; +// } + +/* + * Load the contents of the PE binary into the digest, leaving out the image + * checksum and the certificate data block. + */ +// static int pefile_digest_pe_contents(const void *pebuf, unsigned int pelen, +// struct pefile_context *ctx, +// struct shash_desc *desc) +//{ +// unsigned *canon, tmp, loop, i, hashed_bytes; +// int ret; +// +// /* Digest the header and data directory, but leave out the image +// * checksum and the data dirent for the signature. +// */ +// ret = crypto_shash_update(desc, pebuf, ctx->image_checksum_offset); +// if (ret < 0) +// return ret; +// +// tmp = ctx->image_checksum_offset + sizeof(uint32_t); +// ret = crypto_shash_update(desc, pebuf + tmp, +// ctx->cert_dirent_offset - tmp); +// if (ret < 0) +// return ret; +// +// tmp = ctx->cert_dirent_offset + sizeof(struct data_dirent); +// ret = crypto_shash_update(desc, pebuf + tmp, ctx->header_size - tmp); +// if (ret < 0) +// return ret; +// +// canon = kcalloc(ctx->n_sections, sizeof(unsigned), GFP_KERNEL); +// if (!canon) +// return -ENOMEM; +// +// /* We have to canonicalise the section table, so we perform an +// * insertion sort. +// */ +// canon[0] = 0; +// for (loop = 1; loop < ctx->n_sections; loop++) { +// for (i = 0; i < loop; i++) { +// if (pefile_compare_shdrs(&ctx->secs[canon[i]], +// &ctx->secs[loop]) > 0) { +// memmove(&canon[i + 1], &canon[i], +// (loop - i) * sizeof(canon[0])); +// break; +// } +// } +// canon[i] = loop; +// } +// +// hashed_bytes = ctx->header_size; +// for (loop = 0; loop < ctx->n_sections; loop++) { +// i = canon[loop]; +// if (ctx->secs[i].raw_data_size == 0) +// continue; +// ret = crypto_shash_update(desc, +// pebuf + ctx->secs[i].data_addr, +// ctx->secs[i].raw_data_size); +// if (ret < 0) { +// kfree(canon); +// return ret; +// } +// hashed_bytes += ctx->secs[i].raw_data_size; +// } +// kfree(canon); +// +// if (pelen > hashed_bytes) { +// tmp = hashed_bytes + ctx->certs_size; +// ret = crypto_shash_update(desc, +// pebuf + hashed_bytes, +// pelen - tmp); +// if (ret < 0) +// return ret; +// } +// +// return 0; +// } + +/* + * Digest the contents of the PE binary, leaving out the image checksum and the + * certificate data block. + */ +// static int pefile_digest_pe(const void *pebuf, unsigned int pelen, +// struct pefile_context *ctx) +//{ +// struct crypto_shash *tfm; +// struct shash_desc *desc; +// size_t digest_size, desc_size; +// void *digest; +// int ret; +// +// kenter(",%s", ctx->digest_algo); +// +// /* Allocate the hashing algorithm we're going to need and find out how +// * big the hash operational data will be. +// */ +// tfm = crypto_alloc_shash(ctx->digest_algo, 0, 0); +// if (IS_ERR(tfm)) +// return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); +// +// desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); +// digest_size = crypto_shash_digestsize(tfm); +// +// if (digest_size != ctx->digest_len) { +// pr_debug("Digest size mismatch (%zx != %x)\n", +// digest_size, ctx->digest_len); +// ret = -EBADMSG; +// goto error_no_desc; +// } +// pr_debug("Digest: desc=%zu size=%zu\n", desc_size, digest_size); +// +// ret = -ENOMEM; +// desc = kzalloc(desc_size + digest_size, GFP_KERNEL); +// if (!desc) +// goto error_no_desc; +// +// desc->tfm = tfm; +// ret = crypto_shash_init(desc); +// if (ret < 0) +// goto error; +// +// ret = pefile_digest_pe_contents(pebuf, pelen, ctx, desc); +// if (ret < 0) +// goto error; +// +// digest = (void *)desc + desc_size; +// ret = crypto_shash_final(desc, digest); +// if (ret < 0) +// goto error; +// +// pr_debug("Digest calc = [%*ph]\n", ctx->digest_len, digest); +// +// /* Check that the PE file digest matches that in the MSCODE part of the +// * PKCS#7 certificate. +// */ +// if (memcmp(digest, ctx->digest, ctx->digest_len) != 0) { +// pr_debug("Digest mismatch\n"); +// ret = -EKEYREJECTED; +// } else { +// pr_debug("The digests match!\n"); +// } +// +// error: +// kzfree(desc); +// error_no_desc: +// crypto_free_shash(tfm); +// kleave(" = %d", ret); +// return ret; +// } + +/** + * verify_pefile_signature - Verify the signature on a PE binary image + * @pebuf: Buffer containing the PE binary image + * @pelen: Length of the binary image + * @trust_keys: Signing certificate(s) to use as starting points + * @usage: The use to which the key is being put. + * + * Validate that the certificate chain inside the PKCS#7 message inside the PE + * binary image intersects keys we already know and trust. + * + * Returns, in order of descending priority: + * + * (*) -ELIBBAD if the image cannot be parsed, or: + * + * (*) -EKEYREJECTED if a signature failed to match for which we have a valid + * key, or: + * + * (*) 0 if at least one signature chain intersects with the keys in the trust + * keyring, or: + * + * (*) -ENOPKG if a suitable crypto module couldn't be found for a check on a + * chain. + * + * (*) -ENOKEY if we couldn't find a match for any of the signature chains in + * the message. + * + * May also return -ENOMEM. + */ +int +verify_pefile_signature(const void *pebuf, unsigned pelen, struct key *trusted_keys, enum key_being_used_for usage) +{ + struct pefile_context ctx; + int ret; + + kenter(""); + + memset(&ctx, 0, sizeof(ctx)); + ret = pefile_parse_binary(pebuf, pelen, &ctx); + if (ret < 0) + return ret; + + ret = pefile_strip_sig_wrapper(pebuf, &ctx); + if (ret < 0) + return ret; + + // we dont need this (gmh said) + /*ret = verify_pkcs7_signature(NULL, 0, + pebuf + ctx.sig_offset, ctx.sig_len, + trusted_keys, usage, + mscode_parse, &ctx); + if (ret < 0) + goto error; + + pr_debug("Digest: %u [%*ph]\n", + ctx.digest_len, ctx.digest_len, ctx.digest); + */ + + /* Generate the digest and check against the PKCS7 certificate + * contents. + */ + + // we dont need this (gmh said) + // ret = pefile_digest_pe(pebuf, pelen, &ctx); + + // error: + if (ctx.digest) + { + kzfree(ctx.digest); + } + + return ret; +} diff --git a/Lib-SoulExtraction/linux/verify_pefile.h b/Lib-SoulExtraction/linux/verify_pefile.h new file mode 100644 index 0000000..6a7c4d9 --- /dev/null +++ b/Lib-SoulExtraction/linux/verify_pefile.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* PE Binary parser bits + * + * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +//#include +//#include + +#pragma once + +#include + +#include "pkcs7.h" + +//#include "pe.h" + +struct section_header_x +{ + char name[8]; /* name or "/12\0" string tbl offset */ + unsigned long virtual_size; /* size of loaded section in ram */ + unsigned long virtual_address; /* relative virtual address */ + unsigned long raw_data_size; /* size of the section */ + unsigned long data_addr; /* file pointer to first page of sec */ + unsigned long relocs; /* file pointer to relocation entries */ + unsigned long line_numbers; /* line numbers! */ + unsigned long num_relocs; /* number of relocations */ + unsigned long num_lin_numbers; /* srsly. */ + unsigned long flags; +}; + +struct pefile_context +{ + unsigned header_size; + unsigned image_checksum_offset; + unsigned cert_dirent_offset; + unsigned n_data_dirents; + unsigned n_sections; + unsigned certs_size; + unsigned sig_offset; + unsigned sig_len; + const struct section_header_x *secs; + + /* PKCS#7 MS Individual Code Signing content */ + const void *digest; /* Digest */ + unsigned digest_len; /* Digest length */ + const char *digest_algo; /* Digest algorithm */ +}; + +//#define kenter(FMT, ...) \ +// pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__) +//#define kleave(FMT, ...) \ +// pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) + +/* + * Parse a PE binary. + */ +int +pefile_parse_binary(const void *pebuf, unsigned int pelen, struct pefile_context *ctx); + +/* + * Check and strip the PE wrapper from around the signature and check that the + * remnant looks something like PKCS#7. + */ +int +pefile_strip_sig_wrapper(const void *pebuf, struct pefile_context *ctx); + +/* + * mscode_parser.c + */ +extern int +mscode_parse(void *_ctx, const void *content_data, size_t data_len, size_t asn1hdrlen); diff --git a/Lib-SoulExtraction/linux/x509_cert_parser.c b/Lib-SoulExtraction/linux/x509_cert_parser.c new file mode 100644 index 0000000..5dd6805 --- /dev/null +++ b/Lib-SoulExtraction/linux/x509_cert_parser.c @@ -0,0 +1,1213 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* X.509 certificate parser + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#include + +#include "../rewrite/Lib.SoulExtraction.rewrite.h" + +#include "oid_registry.h" +#include "x509_parser.h" +#include "errno-base.h" +#include "asn1_ber_bytecode.h" +#include "asn1.h" +#include "asn1_decoder.h" +#include "errno.h" +#include "x509_parser.h" + +#include "config.h" + +// shoudong tianjia...ca +typedef unsigned char u8; +typedef unsigned short u16; + +// +// func decl +// + +/* + * Extract the data for the public key algorithm + */ +int +x509_extract_key_data(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note some of the name segments from which we'll fabricate a name. + */ +int +x509_extract_name_segment(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note an OID when we find one for later processing when we know how + * to interpret it. + */ +int +x509_note_OID(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +int +x509_note_issuer(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +int +x509_note_not_after(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +int +x509_note_not_before(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Record the public key algorithm + */ +int +x509_note_pkey_algo(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note the certificate serial number + */ +int +x509_note_serial(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note the whereabouts and type of the signature. + */ +int +x509_note_signature(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +int +x509_note_subject(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +int +x509_note_tbs_certificate(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Process certificate extensions that are used to qualify the certificate. + */ +int +x509_process_extension(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note a key identifier-based AuthorityKeyIdentifier + */ +int +x509_akid_note_kid(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +int +x509_akid_note_name(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +/* + * Note a serial number in an AuthorityKeyIdentifier + */ +int +x509_akid_note_serial(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen); + +// +// macro +// + +#define GFP_ATOMIC /*(__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)*/ 1 +#define GFP_KERNEL /*(__GFP_RECLAIM | __GFP_IO | __GFP_FS)*/ 2 +#define GFP_KERNEL_ACCOUNT /*(GFP_KERNEL | __GFP_ACCOUNT)*/ 3 +#define GFP_NOWAIT /*(__GFP_KSWAPD_RECLAIM)*/ 4 +#define GFP_NOIO /*(__GFP_RECLAIM)*/ 5 +#define GFP_NOFS /*(__GFP_RECLAIM | __GFP_IO)*/ 6 +#define GFP_USER /*(__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL)*/ 7 +#define GFP_DMA /*__GFP_DMA*/ 8 +#define GFP_DMA32 /*__GFP_DMA32*/ 9 +#define GFP_HIGHUSER /*(GFP_USER | __GFP_HIGHMEM)*/ 10 +#define GFP_HIGHUSER_MOVABLE /*(GFP_HIGHUSER | __GFP_MOVABLE)*/ 11 +#define GFP_TRANSHUGE_LIGHT 12 +#define GFP_TRANSHUGE /*(GFP_TRANSHUGE_LIGHT | __GFP_DIRECT_RECLAIM)*/ 13 + +#define ERR_PTR(err) ((void *)((LONG_PTR)(err))) +#define PTR_ERR(ptr) ((LONG_PTR)(ptr)) +#define IS_ERR(ptr) ((ULONG_PTR)(ptr) > (ULONG_PTR)(-1000)) + +// +// enum +// + +enum x509_actions +{ + ACT_x509_extract_key_data = 0, + ACT_x509_extract_name_segment = 1, + ACT_x509_note_OID = 2, + ACT_x509_note_issuer = 3, + ACT_x509_note_not_after = 4, + ACT_x509_note_not_before = 5, + ACT_x509_note_pkey_algo = 6, + ACT_x509_note_serial = 7, + ACT_x509_note_signature = 8, + ACT_x509_note_subject = 9, + ACT_x509_note_tbs_certificate = 10, + ACT_x509_process_extension = 11, + NR__x509_actions = 12 +}; + +enum x509_akid_actions +{ + ACT_x509_akid_note_kid1 = 0, + ACT_x509_akid_note_name1 = 1, + ACT_x509_akid_note_serial1 = 2, + ACT_x509_extract_name_segment1 = 3, + ACT_x509_note_OID1 = 4, + NR__x509_akid_actions1 = 5 +}; + +// +// global +// + +static const unsigned char x509_machine[] = { + // Certificate + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + // TBSCertificate + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + ASN1_OP_MATCH_JUMP_OR_SKIP, // version + _tagn(CONT, CONS, 0), + _jump_target(70), + // CertificateSerialNumber + ASN1_OP_MATCH, + _tag(UNIV, PRIM, INT), + ASN1_OP_ACT, + _action(ACT_x509_note_serial), + // AlgorithmIdentifier + ASN1_OP_MATCH_JUMP, + _tag(UNIV, CONS, SEQ), + _jump_target(74), // --> AlgorithmIdentifier + ASN1_OP_ACT, + _action(ACT_x509_note_pkey_algo), + // Name + ASN1_OP_MATCH_JUMP, + _tag(UNIV, CONS, SEQ), + _jump_target(80), // --> Name + ASN1_OP_ACT, + _action(ACT_x509_note_issuer), + // Validity + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + // Time + ASN1_OP_MATCH_OR_SKIP, // utcTime + _tag(UNIV, PRIM, UNITIM), + ASN1_OP_COND_MATCH_OR_SKIP, // generalTime + _tag(UNIV, PRIM, GENTIM), + ASN1_OP_COND_FAIL, + ASN1_OP_ACT, + _action(ACT_x509_note_not_before), + // Time + ASN1_OP_MATCH_OR_SKIP, // utcTime + _tag(UNIV, PRIM, UNITIM), + ASN1_OP_COND_MATCH_OR_SKIP, // generalTime + _tag(UNIV, PRIM, GENTIM), + ASN1_OP_COND_FAIL, + ASN1_OP_ACT, + _action(ACT_x509_note_not_after), + ASN1_OP_END_SEQ, + // Name + ASN1_OP_MATCH_JUMP, + _tag(UNIV, CONS, SEQ), + _jump_target(80), // --> Name + ASN1_OP_ACT, + _action(ACT_x509_note_subject), + // SubjectPublicKeyInfo + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + // AlgorithmIdentifier + ASN1_OP_MATCH_JUMP, + _tag(UNIV, CONS, SEQ), + _jump_target(74), // --> AlgorithmIdentifier + ASN1_OP_MATCH_ACT, // subjectPublicKey + _tag(UNIV, PRIM, BTS), + _action(ACT_x509_extract_key_data), + ASN1_OP_END_SEQ, + + // UniqueIdentifier + ASN1_OP_MATCH_OR_SKIP, // issuerUniqueID + _tagn(CONT, PRIM, 1), + // UniqueIdentifier + ASN1_OP_MATCH_OR_SKIP, // subjectUniqueID + _tagn(CONT, PRIM, 2), + ASN1_OP_MATCH_JUMP_OR_SKIP, // extensions + _tagn(CONT, CONS, 3), + _jump_target(95), + ASN1_OP_END_SEQ, + ASN1_OP_ACT, + _action(ACT_x509_note_tbs_certificate), + // AlgorithmIdentifier + ASN1_OP_MATCH_JUMP, + _tag(UNIV, CONS, SEQ), + _jump_target(74), // --> AlgorithmIdentifier + ASN1_OP_MATCH_ACT, // signature + _tag(UNIV, PRIM, BTS), + _action(ACT_x509_note_signature), + ASN1_OP_END_SEQ, + ASN1_OP_COMPLETE, + + // Version + ASN1_OP_MATCH, + _tag(UNIV, PRIM, INT), + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, + + ASN1_OP_MATCH_ACT, // algorithm + _tag(UNIV, PRIM, OID), + _action(ACT_x509_note_OID), + ASN1_OP_MATCH_ANY_OR_SKIP, // parameters + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, + + // RelativeDistinguishedName + ASN1_OP_MATCH, + _tag(UNIV, CONS, SET), + // AttributeValueAssertion + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + ASN1_OP_MATCH_ACT, // attributeType + _tag(UNIV, PRIM, OID), + _action(ACT_x509_note_OID), + ASN1_OP_MATCH_ANY_ACT, // attributeValue + _action(ACT_x509_extract_name_segment), + ASN1_OP_END_SEQ, + ASN1_OP_END_SET_OF, + _jump_target(82), + ASN1_OP_END_SEQ_OF, + _jump_target(80), + ASN1_OP_RETURN, + + // Extensions + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + // Extension + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + ASN1_OP_MATCH_ACT, // extnid + _tag(UNIV, PRIM, OID), + _action(ACT_x509_note_OID), + ASN1_OP_MATCH_OR_SKIP, // critical + _tag(UNIV, PRIM, BOOL), + ASN1_OP_MATCH_ACT, // extnValue + _tag(UNIV, PRIM, OTS), + _action(ACT_x509_process_extension), + ASN1_OP_END_SEQ, + ASN1_OP_END_SEQ_OF, + _jump_target(97), + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, +}; + +static const asn1_action_t x509_action_table[NR__x509_actions] = { + x509_extract_key_data, + x509_extract_name_segment, + x509_note_OID, + x509_note_issuer, + x509_note_not_after, + x509_note_not_before, + x509_note_pkey_algo, + x509_note_serial, + x509_note_signature, + x509_note_subject, + x509_note_tbs_certificate, + x509_process_extension, +}; + +struct asn1_decoder x509_decoder = { + x509_machine, + sizeof(x509_machine), + x509_action_table, +}; + +static const asn1_action_t x509_akid_action_table[NR__x509_akid_actions1] = { + x509_akid_note_kid, + x509_akid_note_name, + x509_akid_note_serial, + x509_extract_name_segment, + x509_note_OID, +}; + +static const UCHAR x509_akid_machine[] = { + // AuthorityKeyIdentifier + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + // KeyIdentifier + ASN1_OP_MATCH_ACT_OR_SKIP, // keyIdentifier + _tagn(CONT, PRIM, 0), + _action(ACT_x509_akid_note_kid1), + // GeneralNames + ASN1_OP_MATCH_JUMP_OR_SKIP, // authorityCertIssuer + _tagn(CONT, CONS, 1), + _jump_target(13), // --> GeneralNames + // CertificateSerialNumber + ASN1_OP_MATCH_ACT_OR_SKIP, // authorityCertSerialNumber + _tagn(CONT, PRIM, 2), + _action(ACT_x509_akid_note_serial1), + ASN1_OP_END_SEQ, + ASN1_OP_COMPLETE, + + // GeneralName + ASN1_OP_MATCH_JUMP_OR_SKIP, // otherName + _tagn(CONT, CONS, 0), + _jump_target(44), + ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // rfc822Name + _tagn(CONT, CONS, 1), + _jump_target(47), + ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // dNSName + _tagn(CONT, CONS, 2), + _jump_target(51), + ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // x400Address + _tagn(CONT, CONS, 3), + _jump_target(55), + ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // directoryName + _tagn(CONT, CONS, 4), + _jump_target(58), + ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // ediPartyName + _tagn(CONT, CONS, 5), + _jump_target(78), + ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // uniformResourceIdentifier + _tagn(CONT, CONS, 6), + _jump_target(81), + ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // iPAddress + _tagn(CONT, CONS, 7), + _jump_target(85), + ASN1_OP_COND_MATCH_JUMP_OR_SKIP, // registeredID + _tagn(CONT, CONS, 8), + _jump_target(89), + ASN1_OP_COND_FAIL, + ASN1_OP_END_SEQ_OF, + _jump_target(13), + ASN1_OP_RETURN, + + ASN1_OP_MATCH_ANY, // otherName + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, + + ASN1_OP_MATCH, // rfc822Name + _tag(UNIV, PRIM, IA5STR), + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, + + ASN1_OP_MATCH, // dNSName + _tag(UNIV, PRIM, IA5STR), + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, + + ASN1_OP_MATCH_ANY, // x400Address + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, + + // Name + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + // RelativeDistinguishedName + ASN1_OP_MATCH, + _tag(UNIV, CONS, SET), + // AttributeValueAssertion + ASN1_OP_MATCH, + _tag(UNIV, CONS, SEQ), + ASN1_OP_MATCH_ACT, // attributeType + _tag(UNIV, PRIM, OID), + _action(ACT_x509_note_OID), + ASN1_OP_MATCH_ANY_ACT, // attributeValue + _action(ACT_x509_extract_name_segment), + ASN1_OP_END_SEQ, + ASN1_OP_END_SET_OF, + _jump_target(62), + ASN1_OP_END_SEQ_OF, + _jump_target(60), + ASN1_OP_ACT, + _action(ACT_x509_akid_note_name1), + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, + + ASN1_OP_MATCH_ANY, // ediPartyName + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, + + ASN1_OP_MATCH, // uniformResourceIdentifier + _tag(UNIV, PRIM, IA5STR), + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, + + ASN1_OP_MATCH, // iPAddress + _tag(UNIV, PRIM, OTS), + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, + + ASN1_OP_MATCH, // registeredID + _tag(UNIV, PRIM, OID), + ASN1_OP_END_SEQ, + ASN1_OP_RETURN, +}; + +struct asn1_decoder x509_akid_decoder = { + x509_akid_machine, + sizeof(x509_akid_machine), + x509_akid_action_table, +}; + +/* + * Free an X.509 certificate + */ +void +x509_free_certificate(struct x509_certificate *cert) +{ + if (cert) + { + public_key_free(cert->pub); + public_key_signature_free(cert->sig); + kfree(cert->issuer); + kfree(cert->subject); + kfree(cert->id); + kfree(cert->skid); + kfree(cert); + } +} +// EXPORT_SYMBOL_GPL(x509_free_certificate); + +/* + * Parse an X.509 certificate + */ +struct x509_certificate * +x509_cert_parse(const void *data, size_t datalen) +{ + struct x509_certificate *cert; + struct x509_parse_context *ctx; + struct asymmetric_key_id *kid; + /*long*/ LONG_PTR ret; + + ret = -ENOMEM; + cert = kzalloc(sizeof(struct x509_certificate), GFP_KERNEL); + if (!cert) + goto error_no_cert; + cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL); + if (!cert->pub) + goto error_no_ctx; + cert->sig = kzalloc(sizeof(struct public_key_signature), GFP_KERNEL); + if (!cert->sig) + goto error_no_ctx; + ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL); + if (!ctx) + goto error_no_ctx; + + ctx->cert = cert; + /*ctx->data = (unsigned long)data;*/ + + ctx->data = (void *)data; + + /* Attempt to decode the certificate */ + ret = asn1_ber_decoder(&x509_decoder, ctx, data, datalen); + if (ret < 0) + goto error_decode; + + /* Decode the AuthorityKeyIdentifier */ + if (ctx->raw_akid) + { + cert->raw_akid_size = ctx->raw_akid_size; + + pr_devel("AKID: raw_akid_size=%u raw_akid=%p\n", ctx->raw_akid_size, ctx->raw_akid); + ret = asn1_ber_decoder(&x509_akid_decoder, ctx, ctx->raw_akid, ctx->raw_akid_size); + if (ret < 0) + { + pr_warn("Couldn't decode AuthKeyIdentifier\n"); + goto error_decode; + } + } + + ret = -ENOMEM; + cert->pub->key = kmemdup(ctx->key, ctx->key_size, GFP_KERNEL); + if (!cert->pub->key) + goto error_decode; + + cert->pub->keylen = ctx->key_size; + + /*cert->pub->params = (const void *)kmemdup(ctx->params, ctx->params_size, GFP_KERNEL); + if (!cert->pub->params) + goto error_decode; + + cert->pub->paramlen = ctx->params_size; + cert->pub->algo = ctx->key_algo;*/ + + /* Grab the signature bits */ + + /*ret = x509_get_sig_params(cert); + if (ret < 0) + goto error_decode;*/ + + /* Generate cert issuer + serial number key ID */ + kid = asymmetric_key_generate_id(cert->raw_serial, cert->raw_serial_size, cert->raw_issuer, cert->raw_issuer_size); + + if (IS_ERR(kid)) + { + ret = PTR_ERR(kid); + goto error_decode; + } + cert->id = kid; + + /* Detect self-signed certificates */ + + /*ret = x509_check_for_self_signed(cert); + if (ret < 0) + goto error_decode;*/ + + kfree(ctx); + return cert; + +error_decode: + kfree(ctx); +error_no_ctx: + x509_free_certificate(cert); +error_no_cert: + return ERR_PTR(ret); +} +// EXPORT_SYMBOL_GPL(x509_cert_parse); + +/* + * Note an OID when we find one for later processing when we know how + * to interpret it. + */ +int +x509_note_OID(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct x509_parse_context *ctx = context; + + ctx->last_oid = look_up_OID(value, vlen); + if (ctx->last_oid == OID__NR) + { + char buffer[50]; + sprint_oid(value, vlen, buffer, sizeof(buffer)); + pr_debug("Unknown OID: [%lu] %s\n", (ULONG_PTR)value - (ULONG_PTR)ctx->data, buffer); + } + return 0; +} + +/* + * Save the position of the TBS data so that we can check the signature over it + * later. + */ +int +x509_note_tbs_certificate(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct x509_parse_context *ctx = context; + + pr_debug( + "x509_note_tbs_certificate(,%u,%02x,%ld,%u)!\n", hdrlen, tag, (ULONG_PTR)value - (ULONG_PTR)ctx->data, vlen); + + ctx->cert->tbs = (const void *)((unsigned char *)value - hdrlen); + ctx->cert->tbs_size = vlen + hdrlen; + return 0; +} + +/* + * Record the public key algorithm + */ +int +x509_note_pkey_algo(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + char tmp1[] = {// md4 + 'm', + 'd', + '4', + 0}; + + char tmp2[] = {// rsa + 'r', + 's', + 'a', + 0}; + + char tmp3[] = {// sha1 + 's', + 'h', + 'a', + '1', + 0}; + + char tmp4[] = {// sha256 + 's', + 'h', + 'a', + '2', + '5', + '6', + 0}; + + char tmp5[] = {// sha384 + 's', + 'h', + 'a', + '3', + '8', + '4', + 0}; + + char tmp6[] = {// sha512 + 's', + 'h', + 'a', + '5', + '1', + '2', + 0}; + + char tmp7[] = {// sha224 + 's', + 'h', + 'a', + '2', + '2', + '4', + 0}; + + struct x509_parse_context *ctx = context; + + pr_debug("PubKey Algo: %u\n", ctx->last_oid); + + switch (ctx->last_oid) + { + case OID_md2WithRSAEncryption: + case OID_md3WithRSAEncryption: + default: + return -ENOPKG; /* Unsupported combination */ + + case OID_md4WithRSAEncryption: + ctx->cert->sig->hash_algo = tmp1; + ctx->cert->sig->pkey_algo = "sar"; + break; + + case OID_sha1WithRSAEncryption: + ctx->cert->sig->hash_algo = tmp3; + ctx->cert->sig->pkey_algo = "sar"; + break; + + case OID_sha256WithRSAEncryption: + ctx->cert->sig->hash_algo = tmp4; + ctx->cert->sig->pkey_algo = "sar"; + break; + + case OID_sha384WithRSAEncryption: + ctx->cert->sig->hash_algo = tmp5; + ctx->cert->sig->pkey_algo = "sar"; + break; + + case OID_sha512WithRSAEncryption: + ctx->cert->sig->hash_algo = tmp6; + ctx->cert->sig->pkey_algo = "sar"; + break; + + case OID_sha224WithRSAEncryption: + ctx->cert->sig->hash_algo = tmp7; + ctx->cert->sig->pkey_algo = "sar"; + break; + } + + ctx->algo_oid = ctx->last_oid; + return 0; +} + +/* + * Note the whereabouts and type of the signature. + */ +int +x509_note_signature(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + // char tmp1[] = {//rsa + // 'r','s','a',0 + // }; + + char tmp1[] = {// rsa + 's', + 'a', + 'r', + 0}; + + struct x509_parse_context *ctx = context; + + pr_debug("Signature type: %u size %zu\n", ctx->last_oid, vlen); + + if (ctx->last_oid != ctx->algo_oid) + { + pr_warn("Got cert with pkey (%u) and sig (%u) algorithm OIDs\n", ctx->algo_oid, ctx->last_oid); + return -EINVAL; + } + + if (strcmp(ctx->cert->sig->pkey_algo, tmp1) == 0) + { + /* Discard the BIT STRING metadata */ + if (vlen < 1 || *(const u8 *)value != 0) + return -EBADMSG; + + value = (void *)((unsigned char *)value + 1); + vlen--; + } + + ctx->cert->raw_sig = value; + ctx->cert->raw_sig_size = vlen; + return 0; +} + +/* + * Note the certificate serial number + */ +int +x509_note_serial(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct x509_parse_context *ctx = context; + ctx->cert->raw_serial = value; + ctx->cert->raw_serial_size = vlen; + return 0; +} + +/* + * Note some of the name segments from which we'll fabricate a name. + */ +int +x509_extract_name_segment(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct x509_parse_context *ctx = context; + + switch (ctx->last_oid) + { + case OID_commonName: + ctx->cn_size = vlen; + ctx->cn_offset = (u16)((ULONG_PTR)value - (ULONG_PTR)ctx->data); + break; + case OID_organizationName: + ctx->o_size = vlen; + ctx->o_offset = (u16)((ULONG_PTR)value - (ULONG_PTR)ctx->data); + break; + case OID_email_address: + ctx->email_size = vlen; + ctx->email_offset = (u16)((ULONG_PTR)value - (ULONG_PTR)ctx->data); + break; + default: + break; + } + + return 0; +} + +/* + * Fabricate and save the issuer and subject names + */ +static int +x509_fabricate_name(struct x509_parse_context *ctx, size_t hdrlen, unsigned char tag, char **_name, size_t vlen) +{ + const void *name, *data = (const void *)ctx->data; + size_t namesize; + char *buffer; + + if (*_name) + return -EINVAL; + + /* Empty name string if no material */ + if (!ctx->cn_size && !ctx->o_size && !ctx->email_size) + { + buffer = kmalloc(1, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + buffer[0] = 0; + goto done; + } + + if (ctx->cn_size && ctx->o_size) + { + /* Consider combining O and CN, but use only the CN if it is + * prefixed by the O, or a significant portion thereof. + */ + namesize = ctx->cn_size; + name = (void *)((unsigned char *)data + ctx->cn_offset); + if (ctx->cn_size >= ctx->o_size && memcmp( + (void *)((unsigned char *)data + ctx->cn_offset), + (void *)((unsigned char *)data + ctx->o_offset), + ctx->o_size) == 0) + goto single_component; + if (ctx->cn_size >= 7 && ctx->o_size >= 7 && + memcmp( + (void *)((unsigned char *)data + ctx->cn_offset), (void *)((unsigned char *)data + ctx->o_offset), 7) == + 0) + goto single_component; + + buffer = kmalloc(ctx->o_size + 2 + ctx->cn_size + 1, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + memcpy(buffer, (void *)((unsigned char *)data + ctx->o_offset), ctx->o_size); + buffer[ctx->o_size + 0] = ':'; + buffer[ctx->o_size + 1] = ' '; + memcpy(buffer + ctx->o_size + 2, (void *)((unsigned char *)data + ctx->cn_offset), ctx->cn_size); + buffer[ctx->o_size + 2 + ctx->cn_size] = 0; + goto done; + } + else if (ctx->cn_size) + { + namesize = ctx->cn_size; + name = (void *)((unsigned char *)data + ctx->cn_offset); + } + else if (ctx->o_size) + { + namesize = ctx->o_size; + name = (void *)((unsigned char *)data + ctx->o_offset); + } + else + { + namesize = ctx->email_size; + name = (void *)((unsigned char *)data + ctx->email_offset); + } + +single_component: + buffer = kmalloc(namesize + 1, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + memcpy(buffer, name, namesize); + buffer[namesize] = 0; + +done: + *_name = buffer; + pr_debug("x509_fabricate_name:name=%s,tag=%d\n", buffer, tag); + ctx->cn_size = 0; + ctx->o_size = 0; + ctx->email_size = 0; + return 0; +} + +int +x509_note_issuer(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct x509_parse_context *ctx = context; + ctx->cert->raw_issuer = value; + ctx->cert->raw_issuer_size = vlen; + ctx->cert->issuer_tag = tag; + pr_debug("x509_note_issuer:tag=%d,raw_issuer=%p\n", tag, value); + return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->issuer, vlen); +} + +int +x509_note_subject(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct x509_parse_context *ctx = context; + ctx->cert->raw_subject = value; + ctx->cert->raw_subject_size = vlen; + ctx->cert->subject_tag = tag; + pr_debug("x509_note_subject:tag=%d,raw_subject=%p\n", tag, value); + return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->subject, vlen); +} + +/* + * Extract the parameters for the public key + */ +// int x509_note_params(void *context, size_t hdrlen, +// unsigned char tag, +// const void *value, size_t vlen) +//{ +// struct x509_parse_context *ctx = context; +// +// /* +// * AlgorithmIdentifier is used three times in the x509, we should skip +// * first and ignore third, using second one which is after subject and +// * before subjectPublicKey. +// */ +// if (!ctx->cert->raw_subject || ctx->key) +// return 0; +// ctx->params = (void*)((unsigned char*)value - hdrlen); +// ctx->params_size = vlen + hdrlen; +// return 0; +// } + +/* + * Extract the data for the public key algorithm + */ +int +x509_extract_key_data(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + char tmp1[] = {'s', 'a', 'r', 0}; + + struct x509_parse_context *ctx = (struct x509_parse_context *)context; + + if (ctx->last_oid != OID_rsaEncryption) + return -EBADMSG; + + ctx->cert->pub->pkey_algo = tmp1; + + /* Discard the BIT STRING metadata */ + if (vlen < 1 || *(const UCHAR *)value != 0) + return -EBADMSG; + ctx->key = (void *)((unsigned char *)value + 1); + ctx->key_size = vlen - 1; + return 0; +} + +/* The keyIdentifier in AuthorityKeyIdentifier SEQUENCE is tag(CONT,PRIM,0) */ +#define SEQ_TAG_KEYID (ASN1_CONT << 6) + +/* + * Process certificate extensions that are used to qualify the certificate. + */ +int +x509_process_extension(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct x509_parse_context *ctx = context; + struct asymmetric_key_id *kid; + const unsigned char *v = value; + + pr_debug("Extension: %u\n", ctx->last_oid); + + if (ctx->last_oid == OID_subjectKeyIdentifier) + { + /* Get hold of the key fingerprint */ + if (ctx->cert->skid || vlen < 3) + return -EBADMSG; + if (v[0] != ASN1_OTS || v[1] != vlen - 2) + return -EBADMSG; + v += 2; + vlen -= 2; + + ctx->cert->raw_skid_size = vlen; + ctx->cert->raw_skid = v; + pr_debug("subjkeyid raw_skid_size=%d,raw_skid=%p\n", vlen, v); + + kid = asymmetric_key_generate_id(v, vlen, "", 0); + + if (IS_ERR(PtrToUlong(kid))) + return PTR_ERR(PtrToUlong(kid)); + ctx->cert->skid = kid; + pr_debug("subjkeyid %p\n", kid->len, kid->data); + return 0; + } + + if (ctx->last_oid == OID_authorityKeyIdentifier) + { + /* Get hold of the CA key fingerprint */ + ctx->raw_akid = v; + ctx->raw_akid_size = vlen; + return 0; + } + + return 0; +} + +/** + * x509_decode_time - Decode an X.509 time ASN.1 object + * @_t: The time to fill in + * @hdrlen: The length of the object header + * @tag: The object tag + * @value: The object value + * @vlen: The size of the object value + * + * Decode an ASN.1 universal time or generalised time field into a struct the + * kernel can handle and check it for validity. The time is decoded thus: + * + * [RFC5280 ¡ì4.1.2.5] + * CAs conforming to this profile MUST always encode certificate validity + * dates through the year 2049 as UTCTime; certificate validity dates in + * 2050 or later MUST be encoded as GeneralizedTime. Conforming + * applications MUST be able to process validity dates that are encoded in + * either UTCTime or GeneralizedTime. + */ +int +x509_decode_time( + struct x509_certificate *cert, + unsigned char isfrom, + unsigned char issign, + /*time64_t*/ long long *_t, + size_t hdrlen, + unsigned char tag, + const unsigned char *value, + size_t vlen) +{ + static const unsigned char month_lengths[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + unsigned char *p = (unsigned char *)value; + + unsigned year, mon, day, hour, min, sec, mon_len; + + //#define dec2bin(X) ({ unsigned char y = (X) - '0'; if (y > 9) goto invalid_time;}) + //#define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2;}) + + if (tag == ASN1_UNITIM) + { + /* UTCTime: YYMMDDHHMMSSZ */ + if (vlen != 13) + goto unsupported_time; + year = DD2bin(&p); + if (year == -1) + goto invalid_time; + if (year >= 50) + year += 1900; + else + year += 2000; + } + else if (tag == ASN1_GENTIM) + { + /* GenTime: YYYYMMDDHHMMSSZ */ + if (vlen != 15) + goto unsupported_time; + year = DD2bin(&p) * 100 + DD2bin(&p); + if (year == -1) + goto invalid_time; + if (year >= 1950 && year <= 2049) + goto invalid_time; + } + else + { + goto unsupported_time; + } + + mon = DD2bin(&p); + if (mon == -1) + goto invalid_time; + day = DD2bin(&p); + if (day == -1) + goto invalid_time; + hour = DD2bin(&p); + if (hour == -1) + goto invalid_time; + min = DD2bin(&p); + if (min == -1) + goto invalid_time; + sec = DD2bin(&p); + if (sec == -1) + goto invalid_time; + + if (*p != 'Z') + goto unsupported_time; + + if (year < 1970 || mon < 1 || mon > 12) + goto invalid_time; + + mon_len = month_lengths[mon - 1]; + if (mon == 2) + { + if (year % 4 == 0) + { + mon_len = 29; + if (year % 100 == 0) + { + mon_len = 28; + if (year % 400 == 0) + mon_len = 29; + } + } + } + + if (day < 1 || day > mon_len || hour > 24 || /* ISO 8601 permits 24:00:00 as midnight tomorrow */ + min > 59 || sec > 60) /* ISO 8601 permits leap seconds [X.680 46.3] */ + goto invalid_time; + + *_t = mktime64(year, mon, day, hour, min, sec); + + if (cert) + { + if (isfrom) + { + cert->valid_from_year = year; + cert->valid_from_mon = mon; + cert->valid_from_day = day; + cert->valid_from_hour = hour; + cert->valid_from_min = min; + } + else + { + cert->valid_to_year = year; + cert->valid_to_mon = mon; + cert->valid_to_day = day; + cert->valid_to_hour = hour; + cert->valid_to_min = min; + } + + if (issign) + { + cert->sign_time = *_t; + + cert->sign_time_year = year; + cert->sign_time_mon = mon; + cert->sign_time_day = day; + cert->sign_time_hour = hour; + cert->sign_time_min = min; + } + } + + pr_debug("x509_decode_time:yead=%d,mon=%d,day=%d,hour=%d,min=%d,sec=%d\n", year, mon, day, hour, min, sec); + return 0; + +unsupported_time: + pr_debug("Got unsupported time [tag %02x]: '%p'\n", tag, (int)vlen, value); + return -EBADMSG; +invalid_time: + pr_debug("Got invalid time [tag %02x]: '%p'\n", tag, (int)vlen, value); + return -EBADMSG; +} +// EXPORT_SYMBOL_GPL(x509_decode_time); + +int +x509_note_not_before(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct x509_parse_context *ctx = context; + return x509_decode_time(ctx->cert, TRUE, FALSE, &ctx->cert->valid_from, hdrlen, tag, value, vlen); +} + +int +x509_note_not_after(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct x509_parse_context *ctx = context; + return x509_decode_time(ctx->cert, FALSE, FALSE, &ctx->cert->valid_to, hdrlen, tag, value, vlen); +} + +/* + * Note a key identifier-based AuthorityKeyIdentifier + */ +int +x509_akid_note_kid(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct x509_parse_context *ctx = context; + struct asymmetric_key_id *kid; + + pr_debug("AKID: vlen:%d,keyid: %p\n", (int)vlen, value); + + if (ctx->cert->sig->auth_ids[1]) + return 0; + + kid = asymmetric_key_generate_id(value, vlen, "", 0); + if (IS_ERR(PtrToUlong(kid))) + return PTR_ERR(PtrToUlong(kid)); + pr_debug("len=%d,authkeyid %p\n", kid->len, kid->data); + ctx->cert->sig->auth_ids[1] = kid; + return 0; +} + +/* + * Note a directoryName in an AuthorityKeyIdentifier + */ +int +x509_akid_note_name(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct x509_parse_context *ctx = context; + + pr_debug("AKID: name: %p\n", (int)vlen, value); + + ctx->akid_raw_issuer = value; + ctx->akid_raw_issuer_size = vlen; + return 0; +} + +/* + * Note a serial number in an AuthorityKeyIdentifier + */ +int +x509_akid_note_serial(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) +{ + struct x509_parse_context *ctx = context; + struct asymmetric_key_id *kid; + + pr_debug("AKID: vlen=%d,serial: %p\n", (int)vlen, value); + + if (!ctx->akid_raw_issuer || ctx->cert->sig->auth_ids[0]) + return 0; + + kid = asymmetric_key_generate_id(value, vlen, ctx->akid_raw_issuer, ctx->akid_raw_issuer_size); + if (IS_ERR(PtrToUlong(kid))) + return PTR_ERR(PtrToUlong(kid)); + + pr_debug("authkeyid len:%d,data=%p\n", kid->len, kid->data); + ctx->cert->sig->auth_ids[0] = kid; + return 0; +} diff --git a/Lib-SoulExtraction/linux/x509_parser.h b/Lib-SoulExtraction/linux/x509_parser.h new file mode 100644 index 0000000..d16cb98 --- /dev/null +++ b/Lib-SoulExtraction/linux/x509_parser.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* X.509 certificate parser internal definitions + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#pragma once + +#include "public_key.h" + +struct x509_certificate +{ + struct x509_certificate *next; + struct x509_certificate *signer; /* Certificate that signed this one */ + struct public_key *pub; /* Public key details */ + struct public_key_signature *sig; /* Signature parameters */ + char *issuer; /* Name of certificate issuer */ + unsigned long issuer_tag; // Fix to 4 bytes by gmh + char *subject; /* Name of certificate subject */ + unsigned long subject_tag; // Fix to 4 bytes by gmh + + struct asymmetric_key_id *id; /* Issuer + Serial number */ + struct asymmetric_key_id *skid; /* Subject + subjectKeyId (optional) */ + /*time64_t*/ long long valid_from; + unsigned long valid_from_year; + unsigned long valid_from_mon; + unsigned long valid_from_day; + unsigned long valid_from_hour; + unsigned long valid_from_min; + + /*time64_t*/ long long valid_to; + unsigned long valid_to_year; + unsigned long valid_to_mon; + unsigned long valid_to_day; + unsigned long valid_to_hour; + unsigned long valid_to_min; + + /*time64_t*/ long long sign_time; + unsigned long sign_time_year; + unsigned long sign_time_mon; + unsigned long sign_time_day; + unsigned long sign_time_hour; + unsigned long sign_time_min; + + const void *tbs; /* Signed data */ + unsigned tbs_size; /* Size of signed data */ + unsigned raw_sig_size; /* Size of sigature */ + const void *raw_sig; /* Signature data */ + const void *raw_serial; /* Raw serial number in ASN.1 */ + unsigned raw_serial_size; + unsigned raw_issuer_size; + const void *raw_issuer; /* Raw issuer name in ASN.1 */ + const void *raw_subject; /* Raw subject name in ASN.1 */ + unsigned raw_subject_size; + unsigned raw_akid_size; // Fix to 4 bytes by gmh + unsigned raw_skid_size; + const void *raw_skid; /* Raw subjectKeyId in ASN.1 */ + unsigned index; + unsigned char /*BOOLEAN*/ seen; /* Infinite recursion prevention */ + unsigned char /*BOOLEAN*/ verified; + unsigned char /*BOOLEAN*/ self_signed; /* T if self-signed (check unsupported_sig too) */ + unsigned char /*BOOLEAN*/ unsupported_key; /* T if key uses unsupported crypto */ + unsigned char /*BOOLEAN*/ unsupported_sig; /* T if signature uses unsupported crypto */ + unsigned char /*BOOLEAN*/ blacklisted; +}; + +struct x509_parse_context +{ + struct x509_certificate *cert; /* Certificate being constructed */ + /*unsigned long*/ void *data; /* Start of data */ // Fix to void* by gmh + const void *cert_start; /* Start of cert content */ + const void *key; /* Key data */ + size_t key_size; /* Size of key data */ + enum OID last_oid; /* Last OID encountered */ + enum OID algo_oid; /* Algorithm OID */ + unsigned char nr_mpi; /* Number of MPIs stored */ + /*u8*/ unsigned char o_size; /* Size of organizationName (O) */ + /*u8*/ unsigned char cn_size; /* Size of commonName (CN) */ + /*u8*/ unsigned char email_size; /* Size of emailAddress */ + /*u16*/ unsigned short o_offset; /* Offset of organizationName (O) */ + /*u16*/ unsigned short cn_offset; /* Offset of commonName (CN) */ + /*u16*/ unsigned short email_offset; /* Offset of emailAddress */ + unsigned raw_akid_size; + const void *raw_akid; /* Raw authorityKeyId in ASN.1 */ + const void *akid_raw_issuer; /* Raw directoryName in authorityKeyId */ + unsigned akid_raw_issuer_size; +}; + +/* + * x509_cert_parser.c + */ +extern void +x509_free_certificate(struct x509_certificate *cert); +extern struct x509_certificate * +x509_cert_parse(const void *data, size_t datalen); +extern int +x509_decode_time( + struct x509_certificate *cert, + unsigned char isfrom, + unsigned char issign, + /*time64_t*/ long long *_t, + size_t hdrlen, + unsigned char tag, + const unsigned char *value, + size_t vlen); + +/* + * x509_public_key.c + */ +extern int +x509_get_sig_params(struct x509_certificate *cert); +extern int +x509_check_for_self_signed(struct x509_certificate *cert); diff --git a/Lib-SoulExtraction/linux/x509_public_key.c b/Lib-SoulExtraction/linux/x509_public_key.c new file mode 100644 index 0000000..2732abd --- /dev/null +++ b/Lib-SoulExtraction/linux/x509_public_key.c @@ -0,0 +1,304 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Instantiate a public key crypto key from an X.509 Certificate + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +//#define pr_fmt(fmt) "X.509: "fmt +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include "asymmetric_keys.h" +//#include "x509_parser.h" + +#include "x509_parser.h" +#include "errno.h" +#include "config.h" + +#include "../rewrite/Lib.SoulExtraction.rewrite.h" + +// +// macro +// + +/* + * Set up the signature parameters in an X.509 certificate. This involves + * digesting the signed data and extracting the signature. + */ +// int x509_get_sig_params(struct x509_certificate *cert) +//{ +// struct public_key_signature *sig = cert->sig; +// struct crypto_shash *tfm; +// struct shash_desc *desc; +// size_t desc_size; +// int ret; +// +// pr_devel("==>%s()\n", __func__); +// +// if (!cert->pub->pkey_algo) +// cert->unsupported_key = true; +// +// if (!sig->pkey_algo) +// cert->unsupported_sig = true; +// +// /* We check the hash if we can - even if we can't then verify it */ +// if (!sig->hash_algo) { +// cert->unsupported_sig = true; +// return 0; +// } +// +// sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL); +// if (!sig->s) +// return -ENOMEM; +// +// sig->s_size = cert->raw_sig_size; +// +// /* Allocate the hashing algorithm we're going to need and find out how +// * big the hash operational data will be. +// */ +// tfm = crypto_alloc_shash(sig->hash_algo, 0, 0); +// if (IS_ERR(tfm)) { +// if (PTR_ERR(tfm) == -ENOENT) { +// cert->unsupported_sig = true; +// return 0; +// } +// return PTR_ERR(tfm); +// } +// +// desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); +// sig->digest_size = crypto_shash_digestsize(tfm); +// +// ret = -ENOMEM; +// sig->digest = kmalloc(sig->digest_size, GFP_KERNEL); +// if (!sig->digest) +// goto error; +// +// desc = kzalloc(desc_size, GFP_KERNEL); +// if (!desc) +// goto error; +// +// desc->tfm = tfm; +// +// ret = crypto_shash_digest(desc, cert->tbs, cert->tbs_size, sig->digest); +// if (ret < 0) +// goto error_2; +// +// ret = is_hash_blacklisted(sig->digest, sig->digest_size, "tbs"); +// if (ret == -EKEYREJECTED) { +// pr_err("Cert %p is blacklisted\n", +// sig->digest_size, sig->digest); +// cert->blacklisted = true; +// ret = 0; +// } +// +// error_2: +// kfree(desc); +// error: +// crypto_free_shash(tfm); +// pr_devel("<==%s() = %d\n", __func__, ret); +// return ret; +// } + +/* + * Check for self-signedness in an X.509 cert and if found, check the signature + * immediately if we can. + */ +int +x509_check_for_self_signed(struct x509_certificate *cert) +{ + int ret = 0; + + pr_devel("==>%s()\n", __func__); + + pr_devel("raw_subject_size=%d,raw_issuer_size=%d\n", cert->raw_subject_size, cert->raw_issuer_size); + + /*if (cert->raw_subject_size != cert->raw_issuer_size || + memcmp(cert->raw_subject, cert->raw_issuer, + cert->raw_issuer_size) != 0) + { + + goto not_self_signed; + }*/ + + if (cert->sig->auth_ids[0] || cert->sig->auth_ids[1]) + { + /* If the AKID is present it may have one or two parts. If + * both are supplied, both must match. + */ + unsigned char a = asymmetric_key_id_same(cert->skid, cert->sig->auth_ids[1]); + unsigned char b = asymmetric_key_id_same(cert->id, cert->sig->auth_ids[0]); + + pr_devel( + "skid=%p,auth_ids[1]=%p,id=%p,auth_ids[0]=%p,a=%d,b=%d\n", + cert->skid, + cert->sig->auth_ids[1], + cert->id, + cert->sig->auth_ids[0], + a, + b); + + if (!a && !b) + { + pr_devel("232323232323\n"); + goto not_self_signed; + } + + ret = -EKEYREJECTED; + if (((a && !b) || (b && !a)) && cert->sig->auth_ids[0] && cert->sig->auth_ids[1]) + { + pr_devel("3.3333\n"); + goto out; + } + } + + ret = -EKEYREJECTED; + if (strcmp(cert->pub->pkey_algo, cert->sig->pkey_algo) != 0) + { + pr_devel("3.444\n"); + goto out; + } + + /*ret = public_key_verify_signature(cert->pub, cert->sig); + if (ret < 0) { + if (ret == -ENOPKG) { + cert->unsupported_sig = TRUE; + ret = 0; + } + goto out; + }*/ + + pr_devel("Cert Self-signature verified"); + cert->self_signed = TRUE; + +out: + pr_devel("<==%s() = %d\n", __func__, ret); + return ret; + +not_self_signed: + pr_devel("<==%s() = 0 [not]\n", __func__); + return 0; +} + +/* + * Attempt to parse a data blob for a key as an X509 certificate. + */ +// static int x509_key_preparse(struct key_preparsed_payload *prep) +//{ +// struct asymmetric_key_ids *kids; +// struct x509_certificate *cert; +// const char *q; +// size_t srlen, sulen; +// char *desc = NULL, *p; +// int ret; +// +// cert = x509_cert_parse(prep->data, prep->datalen); +// if (IS_ERR(cert)) +// return PTR_ERR(cert); +// +// pr_devel("Cert Issuer: %s\n", cert->issuer); +// pr_devel("Cert Subject: %s\n", cert->subject); +// +// if (cert->unsupported_key) { +// ret = -ENOPKG; +// goto error_free_cert; +// } +// +// pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo); +// pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to); +// +// cert->pub->id_type = "X509"; +// +// if (cert->unsupported_sig) { +// public_key_signature_free(cert->sig); +// cert->sig = NULL; +// } else { +// pr_devel("Cert Signature: %s + %s\n", +// cert->sig->pkey_algo, cert->sig->hash_algo); +// } +// +// /* Don't permit addition of blacklisted keys */ +// ret = -EKEYREJECTED; +// if (cert->blacklisted) +// goto error_free_cert; +// +// /* Propose a description */ +// sulen = strlen(cert->subject); +// if (cert->raw_skid) { +// srlen = cert->raw_skid_size; +// q = cert->raw_skid; +// } else { +// srlen = cert->raw_serial_size; +// q = cert->raw_serial; +// } +// +// ret = -ENOMEM; +// desc = kmalloc(sulen + 2 + srlen * 2 + 1, GFP_KERNEL); +// if (!desc) +// goto error_free_cert; +// p = memcpy(desc, cert->subject, sulen); +// p += sulen; +// *p++ = ':'; +// *p++ = ' '; +// p = bin2hex(p, q, srlen); +// *p = 0; +// +// kids = kmalloc(sizeof(struct asymmetric_key_ids), GFP_KERNEL); +// if (!kids) +// goto error_free_desc; +// kids->id[0] = cert->id; +// kids->id[1] = cert->skid; +// +// /* We're pinning the module by being linked against it */ +// __module_get(public_key_subtype.owner); +// prep->payload.data[asym_subtype] = &public_key_subtype; +// prep->payload.data[asym_key_ids] = kids; +// prep->payload.data[asym_crypto] = cert->pub; +// prep->payload.data[asym_auth] = cert->sig; +// prep->description = desc; +// prep->quotalen = 100; +// +// /* We've finished with the certificate */ +// cert->pub = NULL; +// cert->id = NULL; +// cert->skid = NULL; +// cert->sig = NULL; +// desc = NULL; +// ret = 0; +// +// error_free_desc: +// kfree(desc); +// error_free_cert: +// x509_free_certificate(cert); +// return ret; +// } + +// static struct asymmetric_key_parser x509_key_parser = { +// .owner = THIS_MODULE, +// .name = "x509", +// .parse = x509_key_preparse, +// }; + +/* + * Module stuff + */ +// static int __init x509_key_init(void) +//{ +// return register_asymmetric_key_parser(&x509_key_parser); +// } +// +// static void __exit x509_key_exit(void) +//{ +// unregister_asymmetric_key_parser(&x509_key_parser); +// } +// +// module_init(x509_key_init); +// module_exit(x509_key_exit); +// +// MODULE_DESCRIPTION("X.509 certificate parser"); +// MODULE_AUTHOR("Red Hat, Inc."); +// MODULE_LICENSE("GPL"); diff --git a/Lib-SoulExtraction/rewrite/Lib.SoulExtraction.rewrite.c b/Lib-SoulExtraction/rewrite/Lib.SoulExtraction.rewrite.c new file mode 100644 index 0000000..8dd419b --- /dev/null +++ b/Lib-SoulExtraction/rewrite/Lib.SoulExtraction.rewrite.c @@ -0,0 +1,180 @@ +#include "Lib.SoulExtraction.rewrite.h" +#include + +#define SOUL_POOL_TAG 'SOUL' + +typedef int(__cdecl *pfn_vsnprintf)( + char *const _Buffer, + size_t const _BufferCount, + char const *const _Format, + va_list _ArgList); + +pfn_vsnprintf g_vsnprintf2 = NULL; + +void * +kmalloc(size_t size, ULONG flags) +{ + void *p = ExAllocatePoolWithTag(NonPagedPool, size, SOUL_POOL_TAG); + if (p) + { + RtlSecureZeroMemory(p, size); + } + + return p; +} + +void * +kzalloc(size_t size, ULONG flags) +{ + return kmalloc(size, flags); +} + +void * +kmemdup(const void *src, size_t len, ULONG gfp) +{ + void *p = ExAllocatePoolWithTag(NonPagedPool, len + 1, SOUL_POOL_TAG); + if (p) + { + RtlSecureZeroMemory(p, len + 1); + if (src) + { + memcpy(p, src, len); + } + } + + return p; +} + +void +kfree(const void *block) +{ + if (!block) + { + return; + } + + ExFreePoolWithTag((void *)block, SOUL_POOL_TAG); +} + +void +kzfree(const void *p) +{ + kfree(p); +} + +int __cdecl kmysnprintf(char *s, size_t const sz, char const *const f, ...) +{ + int n = 0; + + va_list arg_list; + + if (g_vsnprintf2 == NULL) + { + UNICODE_STRING us; + + wchar_t wfunc[] = {//_vsnprintf + L'_', + L'v', + L's', + L'n', + L'p', + L'r', + L'i', + L'n', + L't', + L'f', + 0, + 0}; + + RtlInitUnicodeString(&us, wfunc); + g_vsnprintf2 = (pfn_vsnprintf)(MmGetSystemRoutineAddress(&us)); + } + + va_start(arg_list, f); + + if (g_vsnprintf2) + { + n = g_vsnprintf2(s, sz, f, arg_list); + } + + va_end(arg_list); + return n; +} + +long long +mktime64( + const unsigned int year0, + const unsigned int mon0, + const unsigned int day, + const unsigned int hour, + const unsigned int min, + const unsigned int sec) +{ + unsigned int mon = mon0, year = year0; + + /* 1..12 -> 11,12,1..10 */ + if (0 >= (int)(mon -= 2)) + { + mon += 12; /* Puts Feb last since it has leap day */ + year -= 1; + } + + return ((((long long)(year / 4 - year / 100 + year / 400 + 367 * mon / 12 + day) + year * 365 - 719499) * 24 + + hour /* now have hours - midnight tomorrow handled here */ + ) * 60 + + min /* now have minutes */ + ) * 60 + + sec; /* finally seconds */ +} + +// unsigned char y = (X) - '0'; if (y > 9) goto invalid_time; +unsigned char +dec2bin(unsigned char X) +{ + char y = (X) - '0'; + + if (y > 9) + { + return -1; + } + + return y; +} + +// DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; }) +unsigned +DD2bin(unsigned char **P) +{ + unsigned char a0 = dec2bin((*P)[0]); + unsigned char a1 = dec2bin((*P)[1]); + unsigned x = -1; + + if (a0 == -1 || a1 == -1) + { + goto _exit; + } + + x = (unsigned)(a0 * 10 + a1); + + (*P) += 2; + +_exit: + return x; +} + +int +__test_and_set_bit(unsigned long nr, volatile void *addr) +{ + unsigned long mask = 1 << (nr & 0x1f); + int *m = ((int *)addr) + (nr >> 5); + int old = *m; + + *m = old | mask; + return (old & mask) != 0; +} + +int +test_bit(int nr, const volatile void *addr) +{ + return (1UL & (((const int *)addr)[nr >> 5] >> (nr & 31))) != 0UL; +} \ No newline at end of file diff --git a/Lib-SoulExtraction/rewrite/Lib.SoulExtraction.rewrite.h b/Lib-SoulExtraction/rewrite/Lib.SoulExtraction.rewrite.h new file mode 100644 index 0000000..bab2a60 --- /dev/null +++ b/Lib-SoulExtraction/rewrite/Lib.SoulExtraction.rewrite.h @@ -0,0 +1,41 @@ +#pragma once + +#include + +void * +kzalloc(size_t size, ULONG flags); +void * +kmalloc(size_t size, ULONG flags); + +void * +kmemdup(const void *src, size_t len, ULONG gfp); + +void +kfree(const void *block); +void +kzfree(const void *p); + +int __cdecl kmysnprintf(char *s, size_t const sz, char const *const f, ...); + +long long +mktime64( + const unsigned int year0, + const unsigned int mon0, + const unsigned int day, + const unsigned int hour, + const unsigned int min, + const unsigned int sec); + +// unsigned char y = (X) - '0'; if (y > 9) goto invalid_time; +unsigned char +dec2bin(unsigned char X); + +// DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; }) +unsigned +DD2bin(unsigned char **P); + +int +__test_and_set_bit(unsigned long nr, volatile void *addr); + +int +test_bit(int nr, const volatile void *addr); diff --git a/SoulExtraction.cpp b/SoulExtraction.cpp new file mode 100644 index 0000000..516df82 --- /dev/null +++ b/SoulExtraction.cpp @@ -0,0 +1,19 @@ +#include + +#define dprintf(...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, __VA_ARGS__) + +void +DriverUnLoad(_In_ struct _DRIVER_OBJECT *DriverObject) +{ + dprintf("free world\n"); +} + +EXTERN_C +NTSTATUS +DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) +{ + dprintf("new world\n"); + DriverObject->DriverUnload = DriverUnLoad; + + return STATUS_SUCCESS; +}