parent
6a7d856339
commit
55e042f47c
@ -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
|
@ -0,0 +1,101 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="rewrite">
|
||||||
|
<UniqueIdentifier>{dfa2a449-d195-41f6-9061-1cddd0d53459}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="linux">
|
||||||
|
<UniqueIdentifier>{ff838198-8354-4f87-9c88-5d00dd0ae098}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="rewrite\Lib.SoulExtraction.rewrite.c">
|
||||||
|
<Filter>rewrite</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="linux\mscode_parser.c">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="linux\oid_registry.c">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="linux\pkcs7_parser.c">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="linux\public_key.c">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="linux\signature.c">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="linux\system_keyring.c">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="linux\verify_pefile.c">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="linux\x509_cert_parser.c">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="linux\x509_public_key.c">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="linux\asn1_decoder.c">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="linux\asymmetric_type.c">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Lib.SoulExtraction.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="rewrite\Lib.SoulExtraction.rewrite.h">
|
||||||
|
<Filter>rewrite</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="linux\errno-base.h">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="linux\key.h">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="linux\oid_registry.h">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="linux\pe.h">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="linux\pkcs7.h">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="linux\pkcs7_parser.h">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="linux\public_key.h">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="linux\verify_pefile.h">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="linux\x509_parser.h">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="linux\asn1.h">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="linux\asn1_ber_bytecode.h">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="linux\asn1_decoder.h">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="linux\asymmetric-type.h">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="linux\config.h">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="linux\errno.h">
|
||||||
|
<Filter>linux</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Lib.SoulExtraction.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,579 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#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
|
@ -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);
|
||||||
|
|
||||||
|
}
|
@ -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 */
|
@ -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 <linux/types.h>
|
||||||
|
//#endif
|
||||||
|
//#include <linux/asn1.h>
|
||||||
|
|
||||||
|
#include <fltKernel.h>
|
||||||
|
|
||||||
|
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 */
|
@ -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 <linux/export.h>
|
||||||
|
//#include <linux/kernel.h>
|
||||||
|
//#include <linux/errno.h>
|
||||||
|
//#include <linux/module.h>
|
||||||
|
//#include <linux/asn1_decoder.h>
|
||||||
|
//#include <linux/asn1_ber_bytecode.h>
|
||||||
|
|
||||||
|
#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");
|
@ -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 <linux/asn1.h>
|
||||||
|
|
||||||
|
#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 */
|
@ -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 <linux/key-type.h>
|
||||||
|
//#include <linux/verification.h>
|
||||||
|
|
||||||
|
#include <fltKernel.h>
|
||||||
|
|
||||||
|
// 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 */
|
@ -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 <keys/asymmetric-subtype.h>
|
||||||
|
//#include <keys/asymmetric-parser.h>
|
||||||
|
//#include <crypto/public_key.h>
|
||||||
|
//#include <linux/seq_file.h>
|
||||||
|
//#include <linux/module.h>
|
||||||
|
//#include <linux/slab.h>
|
||||||
|
//#include <linux/ctype.h>
|
||||||
|
//#include <keys/system_keyring.h>
|
||||||
|
//#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:<keyid>". */
|
||||||
|
// 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:<id>" - find a key by partial match on any available ID
|
||||||
|
* "ex:<id>" - 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);
|
@ -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
|
@ -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
|
@ -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
|
@ -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 <linux/types.h>
|
||||||
|
////#include <linux/list.h>
|
||||||
|
////#include <linux/rbtree.h>
|
||||||
|
////#include <linux/rcupdate.h>
|
||||||
|
////#include <linux/sysctl.h>
|
||||||
|
////#include <linux/rwsem.h>
|
||||||
|
////#include <linux/atomic.h>
|
||||||
|
////#include <linux/assoc_array.h>
|
||||||
|
////#include <linux/refcount.h>
|
||||||
|
////#include <linux/time64.h>
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////#ifdef __KERNEL__
|
||||||
|
////#include <linux/uidgid.h>
|
||||||
|
//
|
||||||
|
//#include <fltKernel.h>
|
||||||
|
//
|
||||||
|
//#include <stdint.h>
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////
|
||||||
|
//// 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 */
|
@ -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 <linux/kernel.h>
|
||||||
|
//#include <linux/slab.h>
|
||||||
|
//#include <linux/err.h>
|
||||||
|
//#include <linux/oid_registry.h>
|
||||||
|
//#include <crypto/pkcs7.h>
|
||||||
|
//#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;
|
||||||
|
}
|
@ -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);
|
@ -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 <fltKernel.h>
|
||||||
|
|
||||||
|
//#include <linux/types.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Author(s): Peter Jones <pjones@redhat.com>
|
||||||
|
*/
|
||||||
|
//#ifndef __LINUX_PE_H
|
||||||
|
//#define __LINUX_PE_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fltKernel.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
//#include <linux/types.h>
|
||||||
|
|
||||||
|
#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 */
|
@ -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 <linux/verification.h>
|
||||||
|
//#include <crypto/public_key.h>
|
||||||
|
|
||||||
|
#include "pkcs7_parser.h"
|
||||||
|
|
||||||
|
#include <fltKernel.h>
|
||||||
|
|
||||||
|
// 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 */
|
File diff suppressed because it is too large
Load Diff
@ -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 <linux/oid_registry.h>
|
||||||
|
//#include <crypto/pkcs7.h>
|
||||||
|
//#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) */
|
||||||
|
};
|
@ -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 <linux/module.h>
|
||||||
|
//#include <linux/export.h>
|
||||||
|
//#include <linux/kernel.h>
|
||||||
|
//#include <linux/slab.h>
|
||||||
|
//#include <linux/seq_file.h>
|
||||||
|
//#include <linux/scatterlist.h>
|
||||||
|
//#include <keys/asymmetric-subtype.h>
|
||||||
|
//#include <crypto/public_key.h>
|
||||||
|
//#include <crypto/akcipher.h>
|
||||||
|
//
|
||||||
|
// 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);
|
@ -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 <fltKernel.h>
|
||||||
|
|
||||||
|
#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 */
|
@ -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 <keys/asymmetric-subtype.h>
|
||||||
|
//#include <linux/export.h>
|
||||||
|
//#include <linux/err.h>
|
||||||
|
//#include <linux/slab.h>
|
||||||
|
//#include <crypto/public_key.h>
|
||||||
|
//#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);
|
@ -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 <linux/export.h>
|
||||||
|
////#include <linux/kernel.h>
|
||||||
|
////#include <linux/sched.h>
|
||||||
|
////#include <linux/cred.h>
|
||||||
|
////#include <linux/err.h>
|
||||||
|
////#include <linux/slab.h>
|
||||||
|
////#include <linux/verification.h>
|
||||||
|
////#include <keys/asymmetric-type.h>
|
||||||
|
////#include <keys/system_keyring.h>
|
||||||
|
////#include <crypto/pkcs7.h>
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//#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
|
@ -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 <linux/module.h>
|
||||||
|
//#include <linux/kernel.h>
|
||||||
|
//#include <linux/slab.h>
|
||||||
|
//#include <linux/err.h>
|
||||||
|
//#include <linux/pe.h>
|
||||||
|
//#include <linux/asn1.h>
|
||||||
|
//#include <linux/verification.h>
|
||||||
|
//#include <crypto/hash.h>
|
||||||
|
//#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;
|
||||||
|
}
|
@ -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 <crypto/pkcs7.h>
|
||||||
|
//#include <crypto/hash_info.h>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fltKernel.h>
|
||||||
|
|
||||||
|
#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);
|
File diff suppressed because it is too large
Load Diff
@ -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);
|
@ -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 <linux/module.h>
|
||||||
|
//#include <linux/kernel.h>
|
||||||
|
//#include <linux/slab.h>
|
||||||
|
//#include <keys/asymmetric-subtype.h>
|
||||||
|
//#include <keys/asymmetric-parser.h>
|
||||||
|
//#include <keys/system_keyring.h>
|
||||||
|
//#include <crypto/hash.h>
|
||||||
|
//#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");
|
@ -0,0 +1,180 @@
|
|||||||
|
#include "Lib.SoulExtraction.rewrite.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fltKernel.h>
|
||||||
|
|
||||||
|
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);
|
@ -0,0 +1,19 @@
|
|||||||
|
#include <fltKernel.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
Loading…
Reference in new issue