Skip to content

Commit 4cd1fd1

Browse files
authored
Enable support for FIDO2/U2F security keys (#541)
1 parent 991465e commit 4cd1fd1

17 files changed

+851
-21
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ tags
4646
/config.h
4747
/contrib/win32/openssh/LibreSSL
4848
/contrib/win32/openssh/ZLib
49+
/contrib/win32/openssh/libfido2
4950
## Ignore Visual Studio temporary files, build results, and
5051
## files generated by popular Visual Studio add-ons.
5152

contrib/win32/openssh/GetFIDO2.ps1

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
param (
2+
[string] $paths_target_file_path,
3+
[string] $destDir,
4+
[switch] $override
5+
)
6+
7+
# Workaround that $PSScriptRoot is not support on ps version 2
8+
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
9+
10+
if([string]::IsNullOrEmpty($paths_target_file_path))
11+
{
12+
$paths_target_file_path = Join-Path $PSScriptRoot "paths.targets"
13+
}
14+
15+
if([string]::IsNullOrEmpty($destDir))
16+
{
17+
$destDir = $PSScriptRoot
18+
}
19+
20+
if($override)
21+
{
22+
Remove-Item (join-path $destDir "libfido2") -Recurse -Force -ErrorAction SilentlyContinue
23+
}
24+
elseif (Test-Path (Join-Path $destDir "libfido2") -PathType Container)
25+
{
26+
return
27+
}
28+
29+
[xml] $buildConfig = Get-Content $paths_target_file_path
30+
$version = $buildConfig.Project.PropertyGroup.fido2Version
31+
32+
Write-Host "Downloading libfido2 version:$version"
33+
Write-Host "paths_target_file_path:$paths_target_file_path"
34+
Write-Host "destDir:$destDir"
35+
Write-Host "override:$override"
36+
37+
$zip_path = Join-Path $PSScriptRoot "libfido2.zip"
38+
39+
$release_url = "https://ambientworks.net/tmp/libfido2-1.10-b32020cc-win.zip"
40+
Write-Host "release_url:$release_url"
41+
42+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor `
43+
[Net.SecurityProtocolType]::Tls11 -bor `
44+
[Net.SecurityProtocolType]::Tls
45+
46+
Remove-Item $zip_path -Force -ErrorAction SilentlyContinue
47+
Invoke-WebRequest -Uri $release_url -OutFile $zip_path -UseBasicParsing
48+
if(-not (Test-Path $zip_path))
49+
{
50+
throw "failed to download libfido2 version:$version"
51+
}
52+
53+
# XXX check pgp sig?
54+
Expand-Archive -Path $zip_path -DestinationPath $destDir -Force -ErrorAction SilentlyContinue -ErrorVariable e
55+
if($e -ne $null)
56+
{
57+
throw "Error when expand zip file. libfido2 version:$version"
58+
}
59+
60+
Rename-Item -Path $destDir\libfido2-1.10-b32020cc-win -NewName libfido2
61+
Remove-Item $zip_path -Force -ErrorAction SilentlyContinue
62+
63+
Write-Host "Succesfully downloaded libfido2 version:$version"

contrib/win32/openssh/OpenSSHBuildHelper.psm1

+1-1
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ function Start-OpenSSHPackage
370370

371371
$buildDir = Join-Path $repositoryRoot ("bin\" + $folderName + "\" + $Configuration)
372372
$payload = "sshd.exe", "ssh.exe", "ssh-agent.exe", "ssh-add.exe", "sftp.exe"
373-
$payload += "sftp-server.exe", "scp.exe", "ssh-shellhost.exe", "ssh-keygen.exe", "ssh-keyscan.exe"
373+
$payload += "sftp-server.exe", "scp.exe", "ssh-shellhost.exe", "ssh-keygen.exe", "ssh-keyscan.exe", "ssh-sk-helper.exe"
374374
$payload += "sshd_config_default", "install-sshd.ps1", "uninstall-sshd.ps1"
375375
$payload += "FixHostFilePermissions.ps1", "FixUserFilePermissions.ps1", "OpenSSHUtils.psm1", "OpenSSHUtils.psd1"
376376
$payload += "openssh-events.man", "moduli", "LICENSE.txt"

contrib/win32/openssh/README.txt

+50
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,53 @@ OpenSSH-Lib-Path = The directory path of the location to which libra
1010
LibreSSL-x86-Path = The directory path of LibreSSL statically compiled for x86 platform.
1111
LibreSSL-x64-Path = The directory path of LibreSSL statically compiled for x64 platform.
1212

13+
Notes on FIDO2 support
14+
----------------------
15+
16+
* How to build:
17+
18+
- Open Windows PowerShell.
19+
20+
- Build OpenSSH for Windows:
21+
22+
$ cd \path\to\openssh-portable\..
23+
$ .\openssh-portable\contrib\win32\openssh\OpenSSH-build.ps1
24+
25+
* What has been tested:
26+
27+
* Using a Yubico Security Key.
28+
29+
- Create a new SSH key:
30+
31+
$ ssh-keygen.exe -t ecdsa-sk
32+
33+
* Save the key material in SSH's default paths without an associated passphrase.
34+
35+
- Add the SSH key to your GitHub account.
36+
37+
- Tell git to use our SSH build:
38+
39+
$ $Env:GIT_SSH = '\path\to\ssh.exe'
40+
41+
- Clone a repository using the SSH key for authentication:
42+
43+
$ git clone ssh://[email protected]/org/some-private-repo
44+
45+
* WSL2:
46+
47+
- Export GIT_SSH:
48+
49+
$ export GIT_SSH=/mnt/c/.../path/to/ssh.exe
50+
51+
- Optionally, alias ssh:
52+
53+
$ alias ssh=/mnt/c/.../path/to/ssh.exe
54+
55+
* Note: FIDO2 keys are supported by ssh-agent.
56+
57+
* What definitely doesn't work:
58+
59+
* ssh-keygen -O no-touch-required:
60+
- there does not appear to be a way to toggle user presence in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS.
61+
* ssh-keygen -K, ssh-add -K:
62+
- these use Credential Management to reconstruct the SSH private key.

contrib/win32/openssh/Win32-OpenSSH.sln

+25
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssh-keyscan", "ssh-keyscan.
156156
{0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
157157
EndProjectSection
158158
EndProject
159+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssh-sk-helper", "ssh-sk-helper.vcxproj", "{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}"
160+
ProjectSection(ProjectDependencies) = postProject
161+
{05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
162+
{8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}
163+
{DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
164+
{0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
165+
EndProjectSection
166+
EndProject
159167
Global
160168
GlobalSection(SolutionConfigurationPlatforms) = preSolution
161169
Debug|ARM = Debug|ARM
@@ -504,6 +512,22 @@ Global
504512
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCA}.Release|x64.Build.0 = Release|x64
505513
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCA}.Release|x86.ActiveCfg = Release|Win32
506514
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCA}.Release|x86.Build.0 = Release|Win32
515+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}.Debug|ARM.ActiveCfg = Debug|ARM
516+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}.Debug|ARM.Build.0 = Debug|ARM
517+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}.Debug|ARM64.ActiveCfg = Debug|ARM64
518+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}.Debug|ARM64.Build.0 = Debug|ARM64
519+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}.Debug|x64.ActiveCfg = Debug|x64
520+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}.Debug|x64.Build.0 = Debug|x64
521+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}.Debug|x86.ActiveCfg = Debug|Win32
522+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}.Debug|x86.Build.0 = Debug|Win32
523+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}.Release|ARM.ActiveCfg = Release|ARM
524+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}.Release|ARM.Build.0 = Release|ARM
525+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}.Release|ARM64.ActiveCfg = Release|ARM64
526+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}.Release|ARM64.Build.0 = Release|ARM64
527+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}.Release|x64.ActiveCfg = Release|x64
528+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}.Release|x64.Build.0 = Release|x64
529+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}.Release|x86.ActiveCfg = Release|Win32
530+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB}.Release|x86.Build.0 = Release|Win32
507531
EndGlobalSection
508532
GlobalSection(SolutionProperties) = preSolution
509533
HideSolutionNode = FALSE
@@ -530,6 +554,7 @@ Global
530554
{FC568FF0-60F2-4B2E-AF62-FD392EDBA1B9} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
531555
{484A8CDE-B949-4BDA-B447-74685C8E032F} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
532556
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCA} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E}
557+
{7D0A75FC-F366-4B60-B72F-B37C3EA07CCB} = {17322AAF-808F-4646-AD37-5B0EDDCB8F3E}
533558
EndGlobalSection
534559
GlobalSection(ExtensibilityGlobals) = postSolution
535560
SolutionGuid = {0AC224E8-C215-4270-954A-A2ACEE06DE58}

contrib/win32/openssh/config.h.vs

+14-1
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,19 @@
137137
/* Enable for PKCS#11 support */
138138
#define ENABLE_PKCS11 1
139139

140+
/* Enable for U2F/FIDO support */
141+
#define ENABLE_SK
142+
143+
/* Enable for built-in U2F/FIDO support */
144+
#define ENABLE_SK_INTERNAL
145+
146+
/* Define for discoverable credential support */
147+
#define HAVE_FIDO_CRED_PROT
148+
#define HAVE_FIDO_CRED_SET_PROT
149+
#define HAVE_FIDO_DEV_SUPPORTS_CRED_PROT
150+
#define HAVE_FIDO_DEV_GET_TOUCH_BEGIN
151+
#define HAVE_FIDO_DEV_GET_TOUCH_STATUS
152+
140153
/* File names may not contain backslash characters */
141154
/* #undef FILESYSTEM_NO_BACKSLASH */
142155

@@ -1715,4 +1728,4 @@
17151728
#define HAVE_LOCALTIME_R
17161729
#define HAVE_DECL_MEMMEM 0
17171730
#define WITH_ZLIB
1718-
#define _PATH_TTY "conin$"
1731+
#define _PATH_TTY "conin$"

contrib/win32/openssh/config.vcxproj

+9-1
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@
187187
</Link>
188188
<PreBuildEvent>
189189
<Command>powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)config.ps1" -Config_h_vs "$(SolutionDir)config.h.vs" -Config_h "$(OpenSSH-Src-Path)config.h" -VCIncludePath "$(VC_IncludePath)" -OutCRTHeader "$(OpenSSH-Src-Path)contrib\win32\win32compat\inc\crtheaders.h"
190+
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetFIDO2.ps1
190191
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetLibreSSL.ps1
191192
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetZlib.ps1"</Command>
192193
</PreBuildEvent>
@@ -224,6 +225,7 @@ copy /Y "$(SolutionDir)openssh-events.man" "$(OutDir)"</Command>
224225
</Link>
225226
<PreBuildEvent>
226227
<Command>powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)config.ps1" -Config_h_vs "$(SolutionDir)config.h.vs" -Config_h "$(OpenSSH-Src-Path)config.h" -VCIncludePath "$(VC_IncludePath)" -OutCRTHeader "$(OpenSSH-Src-Path)contrib\win32\win32compat\inc\crtheaders.h"
228+
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetFIDO2.ps1
227229
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetLibreSSL.ps1
228230
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetZlib.ps1"</Command>
229231
</PreBuildEvent>
@@ -261,6 +263,7 @@ copy /Y "$(SolutionDir)openssh-events.man" "$(OutDir)"</Command>
261263
</Link>
262264
<PreBuildEvent>
263265
<Command>powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)config.ps1" -Config_h_vs "$(SolutionDir)config.h.vs" -Config_h "$(OpenSSH-Src-Path)config.h" -VCIncludePath "$(VC_IncludePath)" -OutCRTHeader "$(OpenSSH-Src-Path)contrib\win32\win32compat\inc\crtheaders.h"
266+
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetFIDO2.ps1
264267
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetLibreSSL.ps1
265268
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetZlib.ps1"</Command>
266269
</PreBuildEvent>
@@ -298,6 +301,7 @@ copy /Y "$(SolutionDir)openssh-events.man" "$(OutDir)"</Command>
298301
</Link>
299302
<PreBuildEvent>
300303
<Command>powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)config.ps1" -Config_h_vs "$(SolutionDir)config.h.vs" -Config_h "$(OpenSSH-Src-Path)config.h" -VCIncludePath "$(VC_IncludePath)" -OutCRTHeader "$(OpenSSH-Src-Path)contrib\win32\win32compat\inc\crtheaders.h"
304+
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetFIDO2.ps1
301305
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetLibreSSL.ps1
302306
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetZlib.ps1"</Command>
303307
</PreBuildEvent>
@@ -339,6 +343,7 @@ copy /Y "$(SolutionDir)openssh-events.man" "$(OutDir)"</Command>
339343
</Link>
340344
<PreBuildEvent>
341345
<Command>powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)config.ps1" -Config_h_vs "$(SolutionDir)config.h.vs" -Config_h "$(OpenSSH-Src-Path)config.h" -VCIncludePath "$(VC_IncludePath)" -OutCRTHeader "$(OpenSSH-Src-Path)contrib\win32\win32compat\inc\crtheaders.h"
346+
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetFIDO2.ps1
342347
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetLibreSSL.ps1
343348
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetZlib.ps1"</Command>
344349
</PreBuildEvent>
@@ -380,6 +385,7 @@ copy /Y "$(SolutionDir)openssh-events.man" "$(OutDir)"</Command>
380385
</Link>
381386
<PreBuildEvent>
382387
<Command>powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)config.ps1" -Config_h_vs "$(SolutionDir)config.h.vs" -Config_h "$(OpenSSH-Src-Path)config.h" -VCIncludePath "$(VC_IncludePath)" -OutCRTHeader "$(OpenSSH-Src-Path)contrib\win32\win32compat\inc\crtheaders.h"
388+
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetFIDO2.ps1
383389
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetLibreSSL.ps1
384390
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetZlib.ps1"</Command>
385391
</PreBuildEvent>
@@ -421,6 +427,7 @@ copy /Y "$(SolutionDir)openssh-events.man" "$(OutDir)"</Command>
421427
</Link>
422428
<PreBuildEvent>
423429
<Command>powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)config.ps1" -Config_h_vs "$(SolutionDir)config.h.vs" -Config_h "$(OpenSSH-Src-Path)config.h" -VCIncludePath "$(VC_IncludePath)" -OutCRTHeader "$(OpenSSH-Src-Path)contrib\win32\win32compat\inc\crtheaders.h"
430+
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetFIDO2.ps1
424431
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetLibreSSL.ps1
425432
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetZlib.ps1"</Command>
426433
</PreBuildEvent>
@@ -462,6 +469,7 @@ copy /Y "$(SolutionDir)openssh-events.man" "$(OutDir)"</Command>
462469
</Link>
463470
<PreBuildEvent>
464471
<Command>powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)config.ps1" -Config_h_vs "$(SolutionDir)config.h.vs" -Config_h "$(OpenSSH-Src-Path)config.h" -VCIncludePath "$(VC_IncludePath)" -OutCRTHeader "$(OpenSSH-Src-Path)contrib\win32\win32compat\inc\crtheaders.h"
472+
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetFIDO2.ps1
465473
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetLibreSSL.ps1
466474
powershell.exe -Executionpolicy Bypass -File "$(SolutionDir)GetZlib.ps1"</Command>
467475
</PreBuildEvent>
@@ -486,4 +494,4 @@ copy /Y "$(SolutionDir)openssh-events.man" "$(OutDir)"</Command>
486494
<Target Name="BeforeClean">
487495
<Delete Files="$(OpenSSH-Src-Path)contrib\win32\win32compat\inc\crtheaders.h" />
488496
</Target>
489-
</Project>
497+
</Project>

contrib/win32/openssh/paths.targets

+7-1
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,17 @@
66
<OpenSSH-Lib-Path>$(SolutionDir)lib\</OpenSSH-Lib-Path>
77
<LibreSSLVersion>3.3.3.0</LibreSSLVersion>
88
<ZLibVersion>1.2.11</ZLibVersion>
9+
<fido2Version>1.9.0</fido2Version>
910
<LibreSSL-Path>$(SolutionDir)\LibreSSL\sdk\</LibreSSL-Path>
1011
<LibreSSL-x86-Path>$(SolutionDir)\LibreSSL\bin\desktop\x86\</LibreSSL-x86-Path>
1112
<LibreSSL-x64-Path>$(SolutionDir)\LibreSSL\bin\desktop\x64\</LibreSSL-x64-Path>
1213
<LibreSSL-arm64-Path>$(SolutionDir)\LibreSSL\bin\desktop\arm64\</LibreSSL-arm64-Path>
1314
<LibreSSL-arm-Path>$(SolutionDir)\LibreSSL\bin\desktop\arm\</LibreSSL-arm-Path>
15+
<fido2-Path>$(SolutionDir)\libfido2\</fido2-Path>
16+
<fido2-x86-Path>$(SolutionDir)\libfido2\Win32\Release\v143\static\</fido2-x86-Path>
17+
<fido2-x64-Path>$(SolutionDir)\libfido2\Win64\Release\v143\static\</fido2-x64-Path>
18+
<fido2-arm64-Path>$(SolutionDir)\libfido2\ARM64\Release\v143\static\</fido2-arm64-Path>
19+
<fido2-arm-Path>$(SolutionDir)\libfido2\ARM\Release\v143\static\</fido2-arm-Path>
1420
<ZLib-Path>$(SolutionDir)\ZLib\sdk\</ZLib-Path>
1521
<ZLib-x86-Path>$(SolutionDir)\ZLib\bin\x86\</ZLib-x86-Path>
1622
<ZLib-x64-Path>$(SolutionDir)\ZLib\bin\x64\</ZLib-x64-Path>
@@ -22,4 +28,4 @@
2228
<AdditionalDependentLibs>bcrypt.lib;Userenv.lib;Crypt32.lib;Ws2_32.lib;Secur32.lib;Shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Netapi32.lib;Rpcrt4.lib;ntdll.lib</AdditionalDependentLibs>
2329
<MinimalCoreWin>false</MinimalCoreWin>
2430
</PropertyGroup>
25-
</Project>
31+
</Project>

0 commit comments

Comments
 (0)