diff --git a/APDU/APDU.csproj b/APDU/APDU.csproj index 8f52771..620faaf 100644 --- a/APDU/APDU.csproj +++ b/APDU/APDU.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + net6.0 diff --git a/JustTest/JustTest.csproj b/JustTest/JustTest.csproj index f75bd4e..da17972 100644 --- a/JustTest/JustTest.csproj +++ b/JustTest/JustTest.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net6.0-windows7.0 diff --git a/README.md b/README.md index 7296e20..ccda82e 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,9 @@ We take the security of this project seriously. Report any security vulnerabilit The app runs in the background. When a site loaded in a U2F-compatible browser attempts to register or authenticate with the software token, you'll see a notification asking you to accept or reject the request. You can experiment on [Yubico's U2F demo site](https://demo.yubico.com/u2f). +### Command Line Arguments +- *--db-unprotected* - this will save the key pair into a separated sqlite db without the DPAPI protection, this can be useful if you want to back up the db for some reasons. when enabled, the data will be saved in to `db.unprotected.sqlite`. You can find the databases under `$HOME\AppData\Roaming\SoftU2FDaemon` + ### Registration ![Registration](https://user-images.githubusercontent.com/543405/59797397-e9ab4e80-9322-11e9-9f36-555b608f926d.png) diff --git a/SoftU2F.sln b/SoftU2F.sln index 50de4dc..ac36c79 100644 --- a/SoftU2F.sln +++ b/SoftU2F.sln @@ -12,9 +12,14 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "U2FLib", "U2FLib\U2FLib.csproj", "{A0BEBDF6-1D0D-4085-910F-60AE9111613E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SoftU2FDaemon", "SoftU2FDaemon\SoftU2FDaemon.csproj", "{DA6EEE3B-38E8-414B-BDBF-AD3B80BC5950}" + ProjectSection(ProjectDependencies) = postProject + {54A914C2-7CE1-4F25-9722-8B90D5641689} = {54A914C2-7CE1-4F25-9722-8B90D5641689} + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JustTest", "JustTest\JustTest.csproj", "{551530B9-2C88-430A-B669-06F481FBB658}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SoftU2FDriverPackage", "SoftU2FDriverPackage\SoftU2FDriverPackage.vcxproj", "{B13752F9-1180-4716-9B4B-2D801305F15E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -30,17 +35,19 @@ Global EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {54A914C2-7CE1-4F25-9722-8B90D5641689}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {54A914C2-7CE1-4F25-9722-8B90D5641689}.Debug|Any CPU.Build.0 = Debug|Win32 {54A914C2-7CE1-4F25-9722-8B90D5641689}.Debug|ARM.ActiveCfg = Debug|Win32 {54A914C2-7CE1-4F25-9722-8B90D5641689}.Debug|ARM64.ActiveCfg = Debug|Win32 - {54A914C2-7CE1-4F25-9722-8B90D5641689}.Debug|x64.ActiveCfg = Release|x64 - {54A914C2-7CE1-4F25-9722-8B90D5641689}.Debug|x64.Build.0 = Release|x64 + {54A914C2-7CE1-4F25-9722-8B90D5641689}.Debug|x64.ActiveCfg = Release|Win32 + {54A914C2-7CE1-4F25-9722-8B90D5641689}.Debug|x64.Build.0 = Release|Win32 {54A914C2-7CE1-4F25-9722-8B90D5641689}.Debug|x86.ActiveCfg = Debug|Win32 {54A914C2-7CE1-4F25-9722-8B90D5641689}.Debug|x86.Build.0 = Debug|Win32 - {54A914C2-7CE1-4F25-9722-8B90D5641689}.Release|Any CPU.ActiveCfg = Release|x64 + {54A914C2-7CE1-4F25-9722-8B90D5641689}.Release|Any CPU.ActiveCfg = Release|Win32 + {54A914C2-7CE1-4F25-9722-8B90D5641689}.Release|Any CPU.Build.0 = Release|Win32 {54A914C2-7CE1-4F25-9722-8B90D5641689}.Release|ARM.ActiveCfg = Release|Win32 {54A914C2-7CE1-4F25-9722-8B90D5641689}.Release|ARM64.ActiveCfg = Release|Win32 - {54A914C2-7CE1-4F25-9722-8B90D5641689}.Release|x64.ActiveCfg = Release|x64 - {54A914C2-7CE1-4F25-9722-8B90D5641689}.Release|x64.Build.0 = Release|x64 + {54A914C2-7CE1-4F25-9722-8B90D5641689}.Release|x64.ActiveCfg = Release|Win32 + {54A914C2-7CE1-4F25-9722-8B90D5641689}.Release|x64.Build.0 = Release|Win32 {54A914C2-7CE1-4F25-9722-8B90D5641689}.Release|x86.ActiveCfg = Release|Win32 {54A914C2-7CE1-4F25-9722-8B90D5641689}.Release|x86.Build.0 = Release|Win32 {011BE5F9-1916-4549-B307-779097C922AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -64,6 +71,7 @@ Global {011BE5F9-1916-4549-B307-779097C922AF}.Release|x86.ActiveCfg = Release|Any CPU {011BE5F9-1916-4549-B307-779097C922AF}.Release|x86.Build.0 = Release|Any CPU {6480AC5C-E1DE-4855-B9EA-AFA0243EFE88}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {6480AC5C-E1DE-4855-B9EA-AFA0243EFE88}.Debug|Any CPU.Build.0 = Debug|Win32 {6480AC5C-E1DE-4855-B9EA-AFA0243EFE88}.Debug|ARM.ActiveCfg = Debug|ARM {6480AC5C-E1DE-4855-B9EA-AFA0243EFE88}.Debug|ARM.Build.0 = Debug|ARM {6480AC5C-E1DE-4855-B9EA-AFA0243EFE88}.Debug|ARM.Deploy.0 = Debug|ARM @@ -76,8 +84,8 @@ Global {6480AC5C-E1DE-4855-B9EA-AFA0243EFE88}.Debug|x86.ActiveCfg = Debug|Win32 {6480AC5C-E1DE-4855-B9EA-AFA0243EFE88}.Debug|x86.Build.0 = Debug|Win32 {6480AC5C-E1DE-4855-B9EA-AFA0243EFE88}.Debug|x86.Deploy.0 = Debug|Win32 - {6480AC5C-E1DE-4855-B9EA-AFA0243EFE88}.Release|Any CPU.ActiveCfg = Release|x64 - {6480AC5C-E1DE-4855-B9EA-AFA0243EFE88}.Release|Any CPU.Build.0 = Release|x64 + {6480AC5C-E1DE-4855-B9EA-AFA0243EFE88}.Release|Any CPU.ActiveCfg = Release|Win32 + {6480AC5C-E1DE-4855-B9EA-AFA0243EFE88}.Release|Any CPU.Build.0 = Release|Win32 {6480AC5C-E1DE-4855-B9EA-AFA0243EFE88}.Release|ARM.ActiveCfg = Release|ARM {6480AC5C-E1DE-4855-B9EA-AFA0243EFE88}.Release|ARM.Build.0 = Release|ARM {6480AC5C-E1DE-4855-B9EA-AFA0243EFE88}.Release|ARM.Deploy.0 = Release|ARM @@ -150,6 +158,36 @@ Global {551530B9-2C88-430A-B669-06F481FBB658}.Release|x64.Build.0 = Release|Any CPU {551530B9-2C88-430A-B669-06F481FBB658}.Release|x86.ActiveCfg = Release|Any CPU {551530B9-2C88-430A-B669-06F481FBB658}.Release|x86.Build.0 = Release|Any CPU + {B13752F9-1180-4716-9B4B-2D801305F15E}.Debug|Any CPU.ActiveCfg = Debug|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Debug|Any CPU.Build.0 = Debug|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Debug|Any CPU.Deploy.0 = Debug|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Debug|ARM.ActiveCfg = Debug|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Debug|ARM.Build.0 = Debug|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Debug|ARM.Deploy.0 = Debug|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Debug|ARM64.Build.0 = Debug|ARM64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Debug|x64.ActiveCfg = Debug|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Debug|x64.Build.0 = Debug|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Debug|x64.Deploy.0 = Debug|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Debug|x86.ActiveCfg = Debug|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Debug|x86.Build.0 = Debug|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Debug|x86.Deploy.0 = Debug|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Release|Any CPU.ActiveCfg = Release|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Release|Any CPU.Build.0 = Release|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Release|Any CPU.Deploy.0 = Release|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Release|ARM.ActiveCfg = Release|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Release|ARM.Build.0 = Release|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Release|ARM.Deploy.0 = Release|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Release|ARM64.ActiveCfg = Release|ARM64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Release|ARM64.Build.0 = Release|ARM64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Release|ARM64.Deploy.0 = Release|ARM64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Release|x64.ActiveCfg = Release|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Release|x64.Build.0 = Release|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Release|x64.Deploy.0 = Release|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Release|x86.ActiveCfg = Release|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Release|x86.Build.0 = Release|x64 + {B13752F9-1180-4716-9B4B-2D801305F15E}.Release|x86.Deploy.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/SoftU2FDaemon/Program.cs b/SoftU2FDaemon/Program.cs index 06384a3..63d8646 100644 --- a/SoftU2FDaemon/Program.cs +++ b/SoftU2FDaemon/Program.cs @@ -3,6 +3,9 @@ namespace SoftU2FDaemon { + using Microsoft.EntityFrameworkCore; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Win32; using System; using System.Drawing; using System.IO; @@ -10,9 +13,6 @@ namespace SoftU2FDaemon using System.Runtime.InteropServices; using System.Threading; using System.Windows.Forms; - using Microsoft.EntityFrameworkCore; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.Win32; using U2FLib; using U2FLib.Storage; @@ -29,6 +29,11 @@ public App() SetupApplication(); InitializeTrayIcon(); InitializeBackgroundDaemon(); + + if (DiagnoseMode) + { + tryOutNotification(); + } } [STAThread] @@ -48,6 +53,11 @@ public static void Main() private static readonly string DBPath = Path.Combine( BinFolder, "db.sqlite"); + private static readonly string UnProtectedDBPath = Path.Combine(BinFolder, "db.unprotected.sqlite"); + + public static bool UnprotectedMode => Environment.GetCommandLineArgs().Contains("--db-unprotected"); + + public static bool DiagnoseMode => Environment.GetCommandLineArgs().Contains("--diagnose-mode"); #endregion @@ -115,8 +125,17 @@ private void ConfigureServices(IServiceCollection service) { service.AddLogging(); service.AddSingleton(); - service.AddDbContext(options => { options.UseSqlite($"Filename={DBPath}"); }); - Environment.SetEnvironmentVariable("DBPath", DBPath); // for DbContext outside container + + if (UnprotectedMode) + { + service.AddDbContext(options => { options.UseSqlite($"Filename={UnProtectedDBPath}"); }); + Environment.SetEnvironmentVariable("DBPath", UnProtectedDBPath); // for DbContext outside container + } + else + { + service.AddDbContext(options => { options.UseSqlite($"Filename={DBPath}"); }); + Environment.SetEnvironmentVariable("DBPath", DBPath); // for DbContext outside container + } } #endregion @@ -127,7 +146,7 @@ private void InitializeTrayIcon() { _trayMenu = new ContextMenu(); - var item = new MenuItem {Text = @"Auto Start", Checked = AutoStart()}; + var item = new MenuItem { Text = @"Auto Start", Checked = AutoStart() }; item.Click += OnAutoStartClick; _trayMenu.Items.Add(item); @@ -174,7 +193,7 @@ private void OnAutoStartClick(object sender, EventArgs e) key?.SetValue(BinName, "\"" + Application.ExecutablePath + "\""); } - var item = (MenuItem) sender; + var item = (MenuItem)sender; item.Checked = !item.Checked; } @@ -255,11 +274,16 @@ private Action UserPresenceCallback public void Send(string title, string message, Action userClicked) { if (_notificationOpen) return; - _trayIcon.ShowBalloonTip((int) TimeSpan.FromSeconds(10).TotalMilliseconds, title, message, + _trayIcon.ShowBalloonTip((int)TimeSpan.FromSeconds(10).TotalMilliseconds, title, message, ToolTipIcon.Info); UserPresenceCallback = userClicked; } + private void tryOutNotification() + { + _trayIcon.ShowBalloonTip((int)TimeSpan.FromSeconds(5).TotalMilliseconds, "Test Notification", "If you didn't see this, you'd probabaly have issue with handling authentication actions", ToolTipIcon.Info); + } + #endregion } } \ No newline at end of file diff --git a/SoftU2FDaemon/Properties/PublishProfiles/FolderProfile.pubxml b/SoftU2FDaemon/Properties/PublishProfiles/FolderProfile.pubxml index c8ace4a..649f37d 100644 --- a/SoftU2FDaemon/Properties/PublishProfiles/FolderProfile.pubxml +++ b/SoftU2FDaemon/Properties/PublishProfiles/FolderProfile.pubxml @@ -1,19 +1,17 @@  - + FileSystem Release - x64 - net5.0-windows - bin\Release\net5.0\publish\ + Any CPU + net6.0-windows + bin\Release\net6.0\publish\ true <_IsPortable>true win-x64 - True - True - True + true \ No newline at end of file diff --git a/SoftU2FDaemon/SoftU2FDaemon.csproj b/SoftU2FDaemon/SoftU2FDaemon.csproj index abdb991..7f58188 100644 --- a/SoftU2FDaemon/SoftU2FDaemon.csproj +++ b/SoftU2FDaemon/SoftU2FDaemon.csproj @@ -1,8 +1,8 @@ - + WinExe - net6.0-windows + net6.0-windows10.0.17763.0 true Resources\tray.ico SoftU2FDaemon.App @@ -35,6 +35,33 @@ + + + True + True + Resources.resx + + + True + True + Settings.settings + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + diff --git a/SoftU2FDriver/Device.c b/SoftU2FDriver/Device.c index e00c6e3..84e9f8c 100644 --- a/SoftU2FDriver/Device.c +++ b/SoftU2FDriver/Device.c @@ -158,11 +158,11 @@ Return Value: status = CreateRawPdo(device); if (!NT_SUCCESS(status)) { - KdPrint(("Failed to create Raw Pdo\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Failed to create Raw Pdo\n")); return status; } - KdPrint(("Driver installed and loaded")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Driver installed and loaded\n")); return status; } @@ -182,7 +182,7 @@ EvtDeviceSelfManagedIoInit( if (!NT_SUCCESS(status)) { - KdPrint(("VhfStart failed %d\n", status)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "VhfStart failed %d\n", status)); } return status; @@ -210,7 +210,7 @@ NTSTATUS RAWPDO_EvtDeviceSelfManagedIoInit( ) { NTSTATUS status = STATUS_SUCCESS; - KdPrint(("RawPdo started\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "RawPdo started\n")); return status; } @@ -222,7 +222,8 @@ HidWriteInputReport( _In_ PHID_XFER_PACKET HidTransferPacket ) { - KdPrint(("HidWriteInputReport called\n")); + // this is where the application started to request U2F conversation + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "HidWriteInputReport called\n")); NTSTATUS status; PDEVICE_CONTEXT deviceContext = (PDEVICE_CONTEXT)VhfClientContext; @@ -241,10 +242,10 @@ HidWriteInputReport( if (!NT_SUCCESS(status)) { - KdPrint(("WriteInput report respond failed with status %x\n", status)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "WriteInput report respond failed with status %x\n", status)); } else { - KdPrint(("WriteInput report responded\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "WriteInput report responded\n")); } } @@ -262,51 +263,51 @@ HidMessageRead( frame = (PU2FHID_FRAME)HidTransferPacket->reportBuffer; if (frame->cid == 0x0) { - KdPrint(("Frame with cid 0.\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Frame with cid 0.\n")); HidErrorMessageSend(deviceContext->VhfHandle, frame->cid, ERR_INVALID_CID); return; } message = MessageListFind(deviceContext, frame->cid); - KdPrint(("MessageListFind result for cid: %d, %d. cmd: %d, MessateListCount: %d", frame->cid, !!message, frame->init.cmd, MessageListCount(deviceContext))); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "MessageListFind result for cid: %d, %d. cmd: %d, MessateListCount: %d", frame->cid, !!message, frame->init.cmd, MessageListCount(deviceContext))); switch (FRAME_TYPE(*frame)) { case TYPE_INIT: if (message) { if (frame->init.cmd == U2FHID_INIT) { - KdPrint(("U2FHID_INIT while waiting for CONT. Resetting.\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "U2FHID_INIT while waiting for CONT. Resetting.\n")); MessageListRemove(deviceContext, message); } else { - KdPrint(("INIT frame out of order.Bailing.\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "INIT frame out of order.Bailing.\n")); HidErrorMessageSend(deviceContext->VhfHandle, frame->cid, ERR_INVALID_SEQ); MessageListRemove(deviceContext, message); return; } } else if (frame->init.cmd == U2FHID_SYNC) { - KdPrint(("SYNC frame out of order. Bailing.\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "SYNC frame out of order. Bailing.\n")); HidErrorMessageSend(deviceContext->VhfHandle, frame->cid, ERR_INVALID_CMD); return; } else if (frame->init.cmd != U2FHID_INIT && MessageListCount(deviceContext) > 0) { - KdPrint(("INIT frame while waiting for CONT on other CID.\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "INIT frame while waiting for CONT on other CID.\n")); HidErrorMessageSend(deviceContext->VhfHandle, frame->cid, ERR_CHANNEL_BUSY); return; } if (frame->cid == CID_BROADCAST && frame->init.cmd != U2FHID_INIT) { - KdPrint(("Non U2FHID_INIT message on broadcast CID.\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Non U2FHID_INIT message on broadcast CID.\n")); HidErrorMessageSend(deviceContext->VhfHandle, frame->cid, ERR_INVALID_CID); return; } - KdPrint(("got frame from channel: %d\n", frame->cid)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "got frame from channel: %d\n", frame->cid)); message = MessageListCreate(deviceContext); if (!message) @@ -322,7 +323,7 @@ HidMessageRead( // see maximum message length // https://fidoalliance.org/specs/fido-u2f-v1.0-ps-20141009/fido-u2f-hid-protocol-ps-20141009.html if (message->bcnt > MAX_BCNT) { - KdPrint(("BCNT too large (%u). Bailing.\n", message->bcnt)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "BCNT too large (%u). Bailing.\n", message->bcnt)); HidErrorMessageSend(deviceContext->VhfHandle, message->cid, ERR_INVALID_LEN); MessageListRemove(deviceContext, message); return; @@ -349,13 +350,13 @@ HidMessageRead( case TYPE_CONT: if (!message) { - KdPrint(("CONT frame out of order. Ignoring\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "CONT frame out of order. Ignoring\n")); return; } if (FRAME_SEQ(*frame) != message->lastSeq++) { - KdPrint(("Bad SEQ in CONT frame (%d). Bailing\n", FRAME_SEQ(*frame))); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Bad SEQ in CONT frame (%d). Bailing\n", FRAME_SEQ(*frame))); MessageListRemove(deviceContext, message); HidErrorMessageSend(deviceContext->VhfHandle, frame->cid, ERR_INVALID_SEQ); return; @@ -374,7 +375,7 @@ HidMessageRead( default: - KdPrint(("Unknow frame type: 0x%08x\n", FRAME_TYPE(*frame))); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Unknow frame type: 0x%08x\n", FRAME_TYPE(*frame))); return; } @@ -402,7 +403,7 @@ HidMessageHandle( if (HidMessageIsComplete(deviceContext, message)) { - KdPrint(("Message Complete, responding\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Message Complete, responding\n")); HidMessageFinalize(deviceContext, message); switch (message->cmd) { @@ -418,6 +419,8 @@ HidMessageHandle( case U2FHID_SYNC: U2FHandleMessageSync(deviceContext, message); break; + // all the above msg can be processed within kernel mode + // the below msg, we need to forward to user space case U2FHID_MSG: U2FHandleMessageMsg(deviceContext, message); break; @@ -427,12 +430,12 @@ HidMessageHandle( MessageListRemove(deviceContext, message); } else if (HidMessageIsTimeout(deviceContext, message)) { - KdPrint(("Message Timeout, sending ERR_MSG_TIMEOUT.\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Message Timeout, sending ERR_MSG_TIMEOUT.\n")); HidErrorMessageSend(deviceContext->VhfHandle, message->cid, ERR_MSG_TIMEOUT); MessageListRemove(deviceContext, message); } else { - KdPrint(("Message %d didn't complete, wainting for cont.\n", message->cid)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Message %d didn't complete, wainting for cont.\n", message->cid)); } } } @@ -483,7 +486,7 @@ U2FHandleMessageInit( if (!NT_SUCCESS(status)) { - KdPrint(("Failed to submit report\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Failed to submit report\n")); return; } } @@ -517,7 +520,7 @@ U2FHandleMessageWink( resp.bcnt = message->bcnt; resp.data = message->data; - HidMessageSend(deviceContext->VhfHandle, message); + HidMessageSend(deviceContext->VhfHandle, &resp); } VOID @@ -547,15 +550,16 @@ U2FHandleMessageMsg( ULONG_PTR bytesTransferred = 0; PIO_CTL_XFER_MESSAGE xferMessage; + // grap a pending inverted call request, so we use this to notify User Space status = WdfIoQueueRetrieveNextRequest(deviceContext->ManualQueue, ¬ifyRequest); if (!NT_SUCCESS(status)) { - KdPrint(("No pending req found\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "No pending req found\n")); return; } - KdPrint(("Message bcnt %d\n", message->bcnt)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Message bcnt %d\n", message->bcnt)); status = WdfRequestRetrieveOutputBuffer( notifyRequest, @@ -564,23 +568,23 @@ U2FHandleMessageMsg( NULL); if (!NT_SUCCESS(status)) { - KdPrint(("Cant retrive memory for request\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Cant retrive memory for request\n")); status = STATUS_MEMORY_NOT_ALLOCATED; goto FINISH; } - KdPrint(("Buffer retrived with len %d\n", sizeof(IO_CTL_XFER_MESSAGE) + message->bcnt)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Buffer retrived with len %d\n", sizeof(IO_CTL_XFER_MESSAGE) + message->bcnt)); xferMessage->cmd = message->cmd; xferMessage->cid = message->cid; xferMessage->bcnt = message->bcnt; RtlCopyMemory((PUCHAR)xferMessage + sizeof(IO_CTL_XFER_MESSAGE), message->data, message->bcnt); - KdPrint(("Respons built, sending\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Respons built, sending\n")); bytesTransferred = sizeof(IO_CTL_XFER_MESSAGE) + message->bcnt; - KdPrint(("Sending response %d\n", bytesTransferred)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Sending response %d\n", bytesTransferred)); FINISH: WdfRequestCompleteWithInformation(notifyRequest, status, bytesTransferred); @@ -618,7 +622,7 @@ CreateRawQueue( &queue); if (!NT_SUCCESS(status)) { - KdPrint(("WdfIoQueueCreate failed 0x%X\n", status)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "WdfIoQueueCreate failed 0x%X\n", status)); return status; } @@ -660,7 +664,7 @@ CreateManualQueue( ); if (!NT_SUCCESS(status)) { - KdPrint(("ManualQueue failed 0x%x\n", status)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "ManualQueue failed 0x%x\n", status)); return status; } @@ -703,7 +707,7 @@ CreateTimer( if (!NT_SUCCESS(status)) { - KdPrint(("Create timer failed")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Create timer failed")); return status; } @@ -733,7 +737,7 @@ CreateRawPdo( DECLARE_CONST_UNICODE_STRING(SDDL_MY_PERMISSIONS, L"D:P(A;; GA;;; SY)(A;; GA;;; BA)(A;; GA;;; WD)"); DECLARE_UNICODE_STRING_SIZE(buffer, MAX_ID_LEN); - KdPrint(("Creating RawPdo\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Creating RawPdo\n")); pDeviceInit = WdfPdoInitAllocate(Device); @@ -878,7 +882,7 @@ CreateRawPdo( &queue // pointer to default queue ); if (!NT_SUCCESS(status)) { - KdPrint(("WdfIoQueueCreate failed 0x%x\n", status)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "WdfIoQueueCreate failed 0x%x\n", status)); goto Cleanup; } @@ -917,7 +921,7 @@ CreateRawPdo( ); if (!NT_SUCCESS(status)) { - KdPrint(("WdfDeviceCreateDeviceInterface failed 0x%x\n", status)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "WdfDeviceCreateDeviceInterface failed 0x%x\n", status)); goto Cleanup; } @@ -940,7 +944,7 @@ CreateRawPdo( return STATUS_SUCCESS; Cleanup: - KdPrint(("CreateRawPdo failed %x\n", status)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "CreateRawPdo failed %x\n", status)); // // Call WdfDeviceInitFree if you encounter an error while initializing @@ -1133,7 +1137,7 @@ MessageAlloc message = (PU2FHID_MESSAGE)MmAllocateNonCachedMemory(sizeof(U2FHID_MESSAGE)); if (!message) { - KdPrint(("No memory for new message.\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "No memory for new message.\n")); return NULL; } @@ -1275,7 +1279,7 @@ EvtIoDeviceControlForRawPdo( UNREFERENCED_PARAMETER(InputBufferLength); pdoContext = GetRawPdoDeviceContext(parent); - KdPrint(("RawPdo got DeviceControl, ControlCode(%lu)\n", IoControlCode)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "RawPdo got DeviceControl, ControlCode(%lu)\n", IoControlCode)); switch (IoControlCode) { @@ -1317,7 +1321,7 @@ EvtIoDeviceControlForMainPdo( const size_t IO_CTL_XFER_MESSAGE_SIZE = MAX_BCNT + sizeof(IO_CTL_XFER_MESSAGE); - KdPrint(("Entered EvtIoDeviceControlForMainPdo, IoControlCode(%lu), InputBufferLength %d, OutputBufferLength %d\n", IoControlCode, InputBufferLength, OutputBufferLength)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Entered EvtIoDeviceControlForMainPdo, IoControlCode(%lu), InputBufferLength %d, OutputBufferLength %d\n", IoControlCode, InputBufferLength, OutputBufferLength)); device = WdfIoQueueGetDevice(Queue); deviceContext = GetDeviceContext(device); @@ -1329,32 +1333,34 @@ EvtIoDeviceControlForMainPdo( { status = STATUS_BUFFER_TOO_SMALL; nData = IO_CTL_XFER_MESSAGE_SIZE; - KdPrint(("OutputBuffer too small, required: %lu\n", nData)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "OutputBuffer too small, required: %lu\n", nData)); break; } - KdPrint(("BufferLen check passed %d, forwarding to manual queue\n", OutputBufferLength)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "BufferLen check passed %d, forwarding to manual queue\n", OutputBufferLength)); + + // supply the req to ManualQueue, so when a message received from kernel, the inverted call can use this request handle to notify user space. status = WdfRequestForwardToIoQueue(Request, deviceContext->ManualQueue); if (!NT_SUCCESS(status)) { - KdPrint(("Failed to forward to manual queue\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Failed to forward to manual queue\n")); break; } - // to see if we have a report ready + // to see if User Space replied with anything if (InputBufferLength >= sizeof(IO_CTL_XFER_MESSAGE) && InputBufferLength <= IO_CTL_XFER_MESSAGE_SIZE) { status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &requestInputBuffer, NULL); if (!NT_SUCCESS(status)) { - KdPrint(("Failed to retrive inputBuffer, NT_STATUS: %d, InputBufferLength: %d\n", status, InputBufferLength)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Failed to retrive inputBuffer, NT_STATUS: %d, InputBufferLength: %d\n", status, InputBufferLength)); return; } xferMessage = (PIO_CTL_XFER_MESSAGE)requestInputBuffer; if (xferMessage->bcnt > InputBufferLength - sizeof(IO_CTL_XFER_MESSAGE)) { - KdPrint(("message bcnt is out of bounds: %d\n", xferMessage->bcnt)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "message bcnt is out of bounds: %d\n", xferMessage->bcnt)); return; } @@ -1363,15 +1369,21 @@ EvtIoDeviceControlForMainPdo( response.bcnt = xferMessage->bcnt; response.data = (PUCHAR)xferMessage + sizeof(IO_CTL_XFER_MESSAGE); - KdPrint(("Response message built, sending cmd: %d, cid: %d, bcnt: %d\n", response.cmd, response.cid, response.bcnt)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Response message built, sending cmd: %d, cid: %d, bcnt: %d\n", response.cmd, response.cid, response.bcnt)); + + // if we got a response from User Space, submit it to HID VHF; status = HidMessageSend(deviceContext->VhfHandle, &response); if (!NT_SUCCESS(status)) { - KdPrint(("Response message send failed\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Response message send failed\n")); } - KdPrint(("Response message sent\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Response message sent\n")); } + else + { + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Invalid InputBufferLength %d \n", InputBufferLength)); + } return; diff --git a/SoftU2FDriver/Driver.c b/SoftU2FDriver/Driver.c index 8c6eb00..91a365d 100644 --- a/SoftU2FDriver/Driver.c +++ b/SoftU2FDriver/Driver.c @@ -128,7 +128,7 @@ Return Value: TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry"); - KdPrint(("SoftU2FCreateDevice called: %s", "OK")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "SoftU2FCreateDevice called: %s\n", "OK")); status = SoftU2FCreateDevice(DeviceInit); diff --git a/SoftU2FDriver/SoftU2F.vcxproj b/SoftU2FDriver/SoftU2F.vcxproj index 40cba03..248d9b6 100644 --- a/SoftU2FDriver/SoftU2F.vcxproj +++ b/SoftU2FDriver/SoftU2F.vcxproj @@ -61,6 +61,7 @@ Win32 SoftU2F SoftU2FDriver + 10.0.22621.0 @@ -210,6 +211,9 @@ $(DDK_LIB_PATH)VhfKm.lib;%(AdditionalDependencies) + + SHA256 + diff --git a/SoftU2FDriver/U2F.c b/SoftU2FDriver/U2F.c index 886d945..75634ba 100644 --- a/SoftU2FDriver/U2F.c +++ b/SoftU2FDriver/U2F.c @@ -5,38 +5,38 @@ void softu2f_debug_frame(U2FHID_FRAME *frame, BOOLEAN recv) { UINT16 dlen = 0; if (recv) { - KdPrint(("Received frame:\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Received frame:\n")); } else { - KdPrint(("Sending frame:\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "Sending frame:\n")); } - KdPrint(("\tCID: 0x%08x\n", frame->cid)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "\tCID: 0x%08x\n", frame->cid)); switch (FRAME_TYPE(*frame)) { case TYPE_INIT: - KdPrint(( "\tTYPE: INIT\n")); - KdPrint(("\tCMD: 0x%02x\n", frame->init.cmd & ~TYPE_MASK)); - KdPrint(("\tBCNTH: 0x%02x\n", frame->init.bcnth)); - KdPrint(("\tBCNTL: 0x%02x\n", frame->init.bcntl)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "\tTYPE: INIT\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "\tCMD: 0x%02x\n", frame->init.cmd & ~TYPE_MASK)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "\tBCNTH: 0x%02x\n", frame->init.bcnth)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "\tBCNTL: 0x%02x\n", frame->init.bcntl)); data = frame->init.data; dlen = HID_RPT_SIZE - 7; break; case TYPE_CONT: - KdPrint(("\tTYPE: CONT\n")); - KdPrint(("\tSEQ: 0x%02x\n", frame->cont.seq)); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "\tTYPE: CONT\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "\tSEQ: 0x%02x\n", frame->cont.seq)); data = frame->cont.data; dlen = HID_RPT_SIZE - 5; break; } - KdPrint(("\tDATA:")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "\tDATA:")); for (int i = 0; i < dlen; i++) { - KdPrint((" %02x", data[i])); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, " %02x", data[i])); } - KdPrint(("\n\n")); + KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "\n\n")); } diff --git a/SoftU2FDriverPackage/SoftU2FDriverPackage.vcxproj b/SoftU2FDriverPackage/SoftU2FDriverPackage.vcxproj new file mode 100644 index 0000000..143587d --- /dev/null +++ b/SoftU2FDriverPackage/SoftU2FDriverPackage.vcxproj @@ -0,0 +1,129 @@ + + + + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + + + + + {6480ac5c-e1de-4855-b9ea-afa0243efe88} + + + + {B13752F9-1180-4716-9B4B-2D801305F15E} + {4605da2c-74a5-4865-98e1-152ef136825f} + v4.5 + 12.0 + Debug + x64 + SoftU2FDriverPackage + + + + Windows10 + true + WindowsKernelModeDriver10.0 + Utility + Package + true + + + Windows10 + false + WindowsKernelModeDriver10.0 + Utility + Package + true + + + Windows10 + true + WindowsKernelModeDriver10.0 + Utility + Package + true + + + Windows10 + false + WindowsKernelModeDriver10.0 + Utility + Package + true + + + + + + + + + + + DbgengKernelDebugger + + + + False + False + True + + 133563 + true + + + DbgengKernelDebugger + + + + False + False + True + + 133563 + + + DbgengKernelDebugger + + + + False + False + True + + 133563 + + + DbgengKernelDebugger + + + + False + False + True + + 133563 + + + + SHA256 + + + + + + \ No newline at end of file diff --git a/SoftU2FDriverPackage/SoftU2FDriverPackage.vcxproj.filters b/SoftU2FDriverPackage/SoftU2FDriverPackage.vcxproj.filters new file mode 100644 index 0000000..e1b34f2 --- /dev/null +++ b/SoftU2FDriverPackage/SoftU2FDriverPackage.vcxproj.filters @@ -0,0 +1,9 @@ + + + + + {8E41214B-6785-4CFE-B992-037D68949A14} + inf;inv;inx;mof;mc; + + + \ No newline at end of file diff --git a/U2FLib/Storage/KeyPair.cs b/U2FLib/Storage/KeyPair.cs index f4d63c7..b359315 100644 --- a/U2FLib/Storage/KeyPair.cs +++ b/U2FLib/Storage/KeyPair.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel.DataAnnotations; +using System.Linq; using System.Security.Cryptography; using Org.BouncyCastle.Asn1.Nist; using Org.BouncyCastle.Asn1.X9; @@ -24,6 +25,7 @@ public class KeyPair private byte[] _privateKey; private byte[] _publicKey; + private bool dataProtected => !Environment.GetCommandLineArgs().Contains("--db-unprotected"); public KeyPair() { @@ -41,10 +43,11 @@ public KeyPair(string label) PrivateKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private).GetDerEncoded(); - var ecPublicKey = (ECPublicKeyParameters) keyPair.Public; + var ecPublicKey = (ECPublicKeyParameters)keyPair.Public; PublicKey = ecPublicKey.Q.GetEncoded(); KeyHandle = Convert.ToBase64String(sha512(PublicKey)); + } public string Label { get; set; } @@ -69,8 +72,10 @@ public byte[] PrivateKey set => _privateKey = Protect(value); } - private static byte[] Protect(byte[] data) + private byte[] Protect(byte[] data) { + if (!dataProtected) return data; + try { return ProtectedData.Protect(data, null, DataProtectionScope.CurrentUser); @@ -81,8 +86,10 @@ private static byte[] Protect(byte[] data) } } - private static byte[] UnProtect(byte[] data) + private byte[] UnProtect(byte[] data) { + if (!dataProtected) return data; + try { return ProtectedData.Unprotect(data, null, DataProtectionScope.CurrentUser); diff --git a/U2FLib/U2FBackgroundTask.cs b/U2FLib/U2FBackgroundTask.cs index ad71713..0f2b2e8 100644 --- a/U2FLib/U2FBackgroundTask.cs +++ b/U2FLib/U2FBackgroundTask.cs @@ -47,6 +47,7 @@ public void StartIoLoop(CancellationToken token) IO_CTL_XFER_MESSAGE replyTo = default; while (!token.IsCancellationRequested) { + // enter inverted call replyTo = SendInitRequest(out var nTransferred, out var data, response, replyTo); response = HandleRequest(data, replyTo); } diff --git a/U2FLib/U2FHIDDeviceCommunication.cs b/U2FLib/U2FHIDDeviceCommunication.cs index eb9d51f..33fa807 100644 --- a/U2FLib/U2FHIDDeviceCommunication.cs +++ b/U2FLib/U2FHIDDeviceCommunication.cs @@ -78,6 +78,7 @@ private IO_CTL_XFER_MESSAGE SendInitRequest(out uint nTransferred, out byte[] da inputBufferLen = (uint)inputBuffer.Length; } + // block on inverted call var result = DeviceIoControl( _device, IOCTL_SOFTU2F_FILTER_INIT, diff --git a/U2FLib/U2FLib.csproj b/U2FLib/U2FLib.csproj index e752d59..bf4fd28 100644 --- a/U2FLib/U2FLib.csproj +++ b/U2FLib/U2FLib.csproj @@ -1,7 +1,7 @@  - net6.0 + net6.0-windows