Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial Yubikey support #35

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions GenerateEWTManifest/GenerateEWTManifest.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.1742" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\TameMyCerts\TameMyCerts.csproj" />
</ItemGroup>

<Target Name="GenerateManifest" AfterTargets="Build">
<Exec Command="$(TargetDir)\$(TargetName).exe" WorkingDirectory="$(TargetDir)"/>
</Target>

<Target Name="MessageCompiler" AfterTargets="Build" DependsOnTargets="GenerateManifest">
<Exec Command="&quot;$(NuGetPackageRoot)microsoft.windows.sdk.buildtools\10.0.26100.1742\bin\10.0.26100.0\x64\mc.exe&quot; &quot;TameMyCerts.Events.man&quot; -r ." WorkingDirectory="$(TargetDir)"/>
</Target>

<Target Name="ResourceCompiler" AfterTargets="Build" DependsOnTargets="MessageCompiler">
<Exec Command="&quot;$(NuGetPackageRoot)microsoft.windows.sdk.buildtools\10.0.26100.1742\bin\10.0.26100.0\x64\rc.exe&quot; &quot;TameMyCerts.Events.rc&quot;" WorkingDirectory="$(TargetDir)"/>
</Target>

<Target Name="BuildDll" AfterTargets="Build" DependsOnTargets="MessageCompiler">
<Exec Command="&quot;$(MSBuildSDKsPath)\..\Current\Bin\Roslyn\csc.exe&quot; /out:TameMyCerts.Events.dll /target:library /win32res:TameMyCerts.Events.res" WorkingDirectory="$(TargetDir)"/>
</Target>

</Project>
15 changes: 15 additions & 0 deletions GenerateEWTManifest/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Diagnostics.Tracing;
using TameMyCerts;

// Generate the manifest
string? manifest = EventSource.GenerateManifest(typeof(EWTLogger), "TameMyCerts.Events.dll");
// Save the manifest to a file
if (manifest is not null)
{
File.WriteAllText("TameMyCerts.Events.man", manifest);
Console.WriteLine("Manifest generated and saved to TameMyCerts.Events.man");
}
else
{
Console.WriteLine("Failed to generate manifest. The manifest content is null.");
}
22 changes: 22 additions & 0 deletions TameMyCerts.Tests/EWTLoggerListener.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using TameMyCerts;

namespace TameMyCerts.Tests
{
public class EWTLoggerListener : EventListener
{
private readonly List<EventWrittenEventArgs> events = new List<EventWrittenEventArgs>();
protected override void OnEventWritten(EventWrittenEventArgs eventData) { events.Add(eventData); }
public List<EventWrittenEventArgs> Events => events;
public void ClearEvents() { events.Clear(); }

protected override void OnEventSourceCreated(EventSource eventSource)
{
if (eventSource.Name == "TameMyCerts")
{
EnableEvents(eventSource, EventLevel.LogAlways, (EventKeywords)(-1));
}
}
}
}
2 changes: 1 addition & 1 deletion TameMyCerts.Tests/TameMyCerts.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<NoWarn>1701;1702;CA1416</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\TameMyCerts\TameMyCerts.csproj" />
<ProjectReference Include="..\TameMyCerts\TameMyCerts.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
Expand Down
639 changes: 639 additions & 0 deletions TameMyCerts.Tests/YubikeyValidatorTests.cs

Large diffs are not rendered by default.

13 changes: 11 additions & 2 deletions TameMyCerts.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32922.545
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TameMyCerts", "TameMyCerts\TameMyCerts.csproj", "{BB35A67E-8E22-48C3-B3F8-E852161ACB59}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TameMyCerts", "TameMyCerts\TameMyCerts.csproj", "{BB35A67E-8E22-48C3-B3F8-E852161ACB59}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TameMyCerts.Tests", "TameMyCerts.Tests\TameMyCerts.Tests.csproj", "{98F86AA9-4B95-4300-9A23-512C620D075C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TameMyCerts.Tests", "TameMyCerts.Tests\TameMyCerts.Tests.csproj", "{98F86AA9-4B95-4300-9A23-512C620D075C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GenerateEWTManifest", "GenerateEWTManifest\GenerateEWTManifest.csproj", "{DE4BCB41-0F46-450D-A5A6-F870C7A15E5C}"
ProjectSection(ProjectDependencies) = postProject
{BB35A67E-8E22-48C3-B3F8-E852161ACB59} = {BB35A67E-8E22-48C3-B3F8-E852161ACB59}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -21,6 +26,10 @@ Global
{98F86AA9-4B95-4300-9A23-512C620D075C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{98F86AA9-4B95-4300-9A23-512C620D075C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{98F86AA9-4B95-4300-9A23-512C620D075C}.Release|Any CPU.Build.0 = Release|Any CPU
{DE4BCB41-0F46-450D-A5A6-F870C7A15E5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE4BCB41-0F46-450D-A5A6-F870C7A15E5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE4BCB41-0F46-450D-A5A6-F870C7A15E5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE4BCB41-0F46-450D-A5A6-F870C7A15E5C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
161 changes: 161 additions & 0 deletions TameMyCerts/EWTLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TameMyCerts.Enums;
using TameMyCerts.Models;
using TameMyCerts.Validators;

namespace TameMyCerts
{
[EventSource(Name = "TameMyCerts", LocalizationResources = "TameMyCerts.LocalizedStrings")]
public sealed class EWTLogger : EventSource
{
public static EWTLogger Log = new EWTLogger();

public class Tasks
{
public const EventTask None = (EventTask)1;
public const EventTask TameMyCerts = (EventTask)2;
public const EventTask YubikeyValidator = (EventTask)10;
}

#region Tame My Certs
[Event(1, Level = EventLevel.Informational, Channel = EventChannel.Admin, Task = Tasks.TameMyCerts, Keywords = EventKeywords.None)]
public void TMC_1_PolicyModule_Success_Initiated(string policyModule, string version)
{
if (IsEnabled())
{
WriteEvent(1, policyModule, version);
}
}
[Event(2, Level = EventLevel.Error, Channel = EventChannel.Admin, Task = Tasks.TameMyCerts, Keywords = EventKeywords.None)]
public void TMC_2_PolicyModule_Failed_Initiated(string exception)
{
if (IsEnabled())
{
WriteEvent(2, exception);
}
}
[Event(4, Level = EventLevel.Error, Channel = EventChannel.Admin, Task = Tasks.TameMyCerts, Keywords = EventKeywords.None)]
public void TMC_4_PolicyModule_Default_Shutdown_Failed(string exception)
{
if (IsEnabled())
{
WriteEvent(4, exception);
}
}
[Event(5, Level = EventLevel.Informational, Channel = EventChannel.Analytic, Task = Tasks.TameMyCerts, Keywords = EventKeywords.None)]
public void TMC_5_Analytical_Audit_only_Deny(int requestID, string template, string reason)
{
if (IsEnabled())
{
WriteEvent(5, requestID, template, reason);
}
}
[Event(6, Level = EventLevel.Informational, Channel = EventChannel.Admin, Task = Tasks.TameMyCerts, Keywords = EventKeywords.None)]
public void TMC_6_Deny_Issuing_Request(int requestID, string template, string reason)
{
if (IsEnabled())
{
WriteEvent(6, requestID, template, reason);
}
}
[Event(12, Level = EventLevel.Informational, Channel = EventChannel.Admin, Task = Tasks.TameMyCerts, Keywords = EventKeywords.None)]
public void TMC_12_Success_Issued(int requestID, string template)
{
if (IsEnabled())
{
WriteEvent(12, requestID, template);
}
}
[Event(13, Level = EventLevel.Informational, Channel = EventChannel.Admin, Task = Tasks.TameMyCerts, Keywords = EventKeywords.None)]
public void TMC_13_Success_Pending(int requestID, string template)
{
if (IsEnabled())
{
WriteEvent(13, requestID, template);
}
}
/*
[Event(91, Level = EventLevel.Informational, Channel = EventChannel.Debug, Task = Tasks.TameMyCerts, Keywords = EventKeywords.None)]
public void TMC_91_Read_Policy(string templateName, string policy)
{
if (IsEnabled())
{
WriteEvent(13, templateName, policy);
}
}
*/
#endregion

#region Yubico Validator events 4201-4399
[Event(4201, Level = EventLevel.Warning, Channel = EventChannel.Operational, Task = Tasks.YubikeyValidator, Keywords = EventKeywords.None)]
public void YKVal_4201_Denied_by_Policy(string denyingPolicy, int requestID)
{
if (IsEnabled())
{
WriteEvent(4201, denyingPolicy, requestID);
}
}
[Event(4202, Level = EventLevel.Warning, Channel = EventChannel.Operational, Task = Tasks.YubikeyValidator, Keywords = EventKeywords.None)]
public void YKVal_4202_Denied_by_Policy(int requestID)
{
if (IsEnabled())
{
WriteEvent(4202, requestID);
}
}
[Event(4203, Level = EventLevel.Warning, Channel = EventChannel.Operational, Task = Tasks.YubikeyValidator, Keywords = EventKeywords.None)]
public void YKVal_4203_Denied_due_to_no_matching_policy_default_deny(int requestID)
{
if (IsEnabled())
{
WriteEvent(4203, requestID);
}
}
[Event(4204, Level = EventLevel.Verbose, Channel = EventChannel.Operational, Task = Tasks.YubikeyValidator, Keywords = EventKeywords.None)]
public void YKVal_4204_Matching_policy(string policy, int requestID)
{
if (IsEnabled())
{
WriteEvent(4204, policy, requestID);
}
}
[Event(4205, Level = EventLevel.Error, Channel = EventChannel.Operational, Task = Tasks.YubikeyValidator, Keywords = EventKeywords.None)]
public void YKVal_4205_Failed_to_extract_Yubikey_Attestion(int requestID)
{
if (IsEnabled())
{
WriteEvent(4205, requestID);
}
}
[Event(4206, Level = EventLevel.Warning, Channel = EventChannel.Debug, Task = Tasks.YubikeyValidator, Keywords = EventKeywords.None)]
public void YKVal_4206_Debug_failed_to_match_policy(int requestID, string policy)
{
if (IsEnabled())
{
WriteEvent(4206, requestID, policy);
}
}
[Event(4207, Level = EventLevel.Error, Channel = EventChannel.Operational, Task = Tasks.YubikeyValidator, Keywords = EventKeywords.None)]
public void YKVal_4207_Yubikey_Attestion_Missmatch_with_CSR(int requestID)
{
if (IsEnabled())
{
WriteEvent(4207, requestID);
}
}
[Event(4208, Level = EventLevel.Error, Channel = EventChannel.Operational, Task = Tasks.YubikeyValidator, Keywords = EventKeywords.None)]
public void YKVal_4208_Yubikey_Attestion_Failed_to_build(int requestID)
{
if (IsEnabled())
{
WriteEvent(4208, requestID);
}
}
#endregion
}
}
2 changes: 1 addition & 1 deletion TameMyCerts/Enums/KeyAlgorithmFamily.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

namespace TameMyCerts.Enums;

internal enum KeyAlgorithmFamily
public enum KeyAlgorithmFamily
{
UNKNOWN = 0,
RSA = 1,
Expand Down
78 changes: 78 additions & 0 deletions TameMyCerts/Enums/Yubikey.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright 2021-2023 Uwe Gradenegger <[email protected]>

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace TameMyCerts.Enums
{
/// <summary>
/// Constants from Yubico
/// https://developers.yubico.com/PIV/Introduction/PIV_attestation.html
/// </summary>
internal static class YubikeyX509Extensions
{
public const string FIRMWARE = "1.3.6.1.4.1.41482.3.3";
public const string SERIALNUMBER = "1.3.6.1.4.1.41482.3.7";
public const string PIN_TOUCH_POLICY = "1.3.6.1.4.1.41482.3.8";
public const string FORMFACTOR = "1.3.6.1.4.1.41482.3.9";
public const string FIPS_CERTIFIED = "1.3.6.1.4.1.41482.3.10";
public const string CPSN_CERTIFIED = "1.3.6.1.4.1.41482.3.11";
public const string ATTESTION_INTERMEDIATE = "1.3.6.1.4.1.41482.3.2";
public const string ATTESTION_DEVICE = "1.3.6.1.4.1.41482.3.11";
}

public enum YubikeyFormFactor
{
Unknown = 0,
UsbAKeychain = 1,
UsbANano = 2,
UsbCKeychain = 3,
UsbCNano = 4,
UsbCLightning = 5,
UsbABiometricKeychain = 6,
UsbCBiometricKeychain = 7,
}

public enum YubikeyTouchPolicy
{
None = 0,
Never = 1,
Always = 2,
Cached = 3,
Default = 32,
}

public enum YubikeyPinPolicy
{
None = 0,
Never = 1,
Once = 2,
Always = 3,
MatchOnce = 4,
MatchAlways = 5,
Default = 32,
}

public enum YubikeyPolicyAction
{
Allow,
Deny,
}

public enum YubikeyEdition
{
Normal,
FIPS,
CSPN,
}

}
Loading
Loading