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;
+}