wintun: extract inf driverver at compile time into C header

This requires us to make some insane conversions between INF date,
JavaScript time, and finally Windows file time. The point is to mimic
SystemTimeToFileTime, which is what SpInf.dll's pSetupStringToDriverDate
does on the YYYY-MM-DD from the INF.

The result is that we no longer have to parse an ancient text format in
C at runtime.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2020-11-03 17:06:20 +01:00
parent 55345ae386
commit 677ba8680f
4 changed files with 28 additions and 111 deletions

View File

@ -12,6 +12,7 @@
#include "ntdll.h"
#include "registry.h"
#include "resource.h"
#include "wintun-inf.h"
#include <Windows.h>
#include <winternl.h>
@ -950,109 +951,6 @@ cleanupTcpipAdapterRegKey:
return Result;
}
static const CHAR *
SkipWSpace(_In_ const CHAR *Beg, _In_ const CHAR *End)
{
for (; Beg < End && iswspace(*Beg); ++Beg)
;
return Beg;
}
static const CHAR *
SkipNonLF(_In_ const CHAR *Beg, _In_ const CHAR *End)
{
for (; Beg < End && *Beg != '\n'; ++Beg)
;
return Beg;
}
static WINTUN_STATUS
VersionOfInf(_Out_ FILETIME *DriverDate, _Out_ DWORDLONG *DriverVersion)
{
const VOID *LockedResource;
DWORD SizeResource;
DWORD Result = ResourceGetAddress(HaveWHQL() ? L"wintun-whql.inf" : L"wintun.inf", &LockedResource, &SizeResource);
if (Result != ERROR_SUCCESS)
return LOG(WINTUN_LOG_ERR, L"Failed to locate resource"), Result;
enum
{
SectNone,
SectUnknown,
SectVersion
} Section = SectNone;
for (const char *Inf = (const char *)LockedResource, *InfEnd = Inf + SizeResource; Inf < InfEnd; ++Inf)
{
if (*Inf == ';')
{
Inf = SkipNonLF(Inf + 1, InfEnd);
continue;
}
Inf = SkipWSpace(Inf, InfEnd);
if (*Inf == '[')
{
Section = Inf + 9 <= InfEnd && !_strnicmp(Inf, "[Version]", 9) ? SectVersion : SectUnknown;
}
else if (Section == SectVersion)
{
if (Inf + 9 <= InfEnd && !_strnicmp(Inf, "DriverVer", 9))
{
Inf = SkipWSpace(Inf + 9, InfEnd);
if (Inf < InfEnd && *Inf == '=')
{
Inf = SkipWSpace(Inf + 1, InfEnd);
/* Duplicate buffer, as resource is not zero-terminated. */
char Buffer[0x100];
size_t BufferLen = InfEnd - Inf;
if (BufferLen >= _countof(Buffer))
BufferLen = _countof(Buffer) - 1;
strncpy_s(Buffer, _countof(Buffer), Inf, BufferLen);
Buffer[BufferLen] = 0;
const char *Ptr = Buffer;
unsigned long Date[3] = { 0 };
for (size_t i = 0;; ++i, ++Ptr)
{
char *PtrNext;
Date[i] = strtoul(Ptr, &PtrNext, 10);
Ptr = PtrNext;
if (i >= _countof(Date) - 1)
break;
if (*Ptr != '/' && *Ptr != '-')
return LOG(WINTUN_LOG_ERR, L"Unexpected date delimiter"), ERROR_INVALID_DATA;
}
if (Date[0] < 1 || Date[0] > 12 || Date[1] < 1 || Date[1] > 31 || Date[2] < 1601 || Date[2] > 30827)
return LOG(WINTUN_LOG_ERR, L"Invalid date"), ERROR_INVALID_DATA;
const SYSTEMTIME SystemTime = { .wYear = (WORD)Date[2], .wMonth = (WORD)Date[0], .wDay = (WORD)Date[1] };
if (!SystemTimeToFileTime(&SystemTime, DriverDate))
return LOG_LAST_ERROR(L"Failed to convert system time to file time");
Ptr = SkipWSpace(Ptr, Buffer + BufferLen);
ULONGLONG Version[4] = { 0 };
if (*Ptr == ',')
{
Ptr = SkipWSpace(Ptr + 1, Buffer + BufferLen);
for (size_t i = 0;; ++i, ++Ptr)
{
char *PtrNext;
Version[i] = strtoul(Ptr, &PtrNext, 10);
if (Version[i] > 0xffff)
return LOG(WINTUN_LOG_ERR, L"Version field may not exceed 65535"), ERROR_INVALID_DATA;
Ptr = PtrNext;
if (i >= _countof(Version) - 1 || !*Ptr || *Ptr == ';' || iswspace(*Ptr))
break;
if (*Ptr != '.')
return LOG(WINTUN_LOG_ERR, L"Unexpected version delimiter"), ERROR_INVALID_DATA;
}
}
*DriverVersion = (Version[0] << 48) | (Version[1] << 32) | (Version[2] << 16) | (Version[3] << 0);
return ERROR_SUCCESS;
}
}
}
Inf = SkipNonLF(Inf, InfEnd);
}
LOG(WINTUN_LOG_ERR, L"DriverVer not found in INF resource");
return ERROR_FILE_NOT_FOUND;
}
static DWORD
VersionOfFile(_In_z_ const WCHAR *Filename)
{
@ -1164,17 +1062,12 @@ SelectDriver(
_Inout_ SP_DEVINSTALL_PARAMS_W *DevInstallParams,
_Inout_ BOOL *RebootRequired)
{
FILETIME OurDriverDate;
DWORDLONG OurDriverVersion;
DWORD Result = VersionOfInf(&OurDriverDate, &OurDriverVersion);
if (Result != ERROR_SUCCESS)
{
LOG(WINTUN_LOG_ERR, L"Failed to determine own driver version");
return Result;
}
static const FILETIME OurDriverDate = WINTUN_INF_FILETIME;
static const DWORDLONG OurDriverVersion = WINTUN_INF_VERSION;
HANDLE DriverInstallationLock = NamespaceTakeDriverInstallationMutex();
if (!DriverInstallationLock)
return LOG_LAST_ERROR(L"Failed to take driver installation mutex");
DWORD Result = ERROR_SUCCESS;
if (!SetupDiBuildDriverInfoList(DevInfo, DevInfoData, SPDIT_COMPATDRIVER))
{
Result = LOG_LAST_ERROR(L"Failed building driver info list");

View File

@ -106,6 +106,7 @@
<PreprocessorDefinitions>_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="Exists('$(OutDir)whql\')">HAVE_WHQL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/volatile:iso %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>..\$(Configuration)\$(WintunPlatform);..\$(Configuration);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ResourceCompile>
<AdditionalIncludeDirectories>..\$(Configuration)\$(WintunPlatform);..\$(Configuration);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

17
extract-driverver.js Normal file
View File

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0
*
* Copyright (C) 2018-2020 WireGuard LLC. All Rights Reserved.
*/
while (!WScript.StdIn.AtEndOfStream) {
var line = WScript.StdIn.ReadLine();
if (line.substr(0, 12) != "DriverVer = ")
continue;
var val = line.substr(12).split(",");
var date = val[0].split("/");
var ver = val[1].split(".");
var time = Date.UTC(date[2], date[0] - 1, date[1]).toString()
WScript.Echo("#define WINTUN_INF_FILETIME { (DWORD)((" + time + "ULL * 10000ULL + 116444736000000000ULL) & 0xffffffffU), (DWORD)((" + time + "ULL * 10000ULL + 116444736000000000ULL) >> 32) }")
WScript.Echo("#define WINTUN_INF_VERSION ((" + ver[0] + "ULL << 48) | (" + ver[1] + "ULL << 32) | (" + ver[2] + "ULL << 16) | (" + ver[3] + "ULL << 0))")
break;
}

View File

@ -139,6 +139,7 @@
<IntDir>$(ConfigurationName)\$(WintunPlatform)\</IntDir>
<OutDir>$(ConfigurationName)\$(WintunPlatform)\</OutDir>
<RunCodeAnalysis>true</RunCodeAnalysis>
<CustomBuildAfterTargets>StampInf</CustomBuildAfterTargets>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<CodeAnalysisRuleSet>$(WDKContentRoot)CodeAnalysis\DriverMustFixRules.ruleset</CodeAnalysisRuleSet>
@ -168,6 +169,11 @@
<DriverSign>
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
</DriverSign>
<CustomBuildStep>
<Command>cscript.exe /nologo "$(ProjectDir)\extract-driverver.js" &lt; "$(IntDir)wintun.inf" &gt; "$(IntDir)wintun-inf.h"</Command>
<Outputs>$(IntDir)wintun-inf.h</Outputs>
<Inputs>$(IntDir)wintun.inf</Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<Inf>