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