sshnet / SSH.NET

SSH.NET is a Secure Shell (SSH) library for .NET, optimized for parallelism.
http://sshnet.github.io/SSH.NET/
MIT License
3.94k stars 927 forks source link

A proposal to add TPM support #576

Open sadlame opened 5 years ago

sadlame commented 5 years ago

Hello,

I am not sure if this is the correct place to ask, so please point out if I am doing this wrong.

I have been working on a small PoC codebase forked from SSH.NET that supports private keys stored in TPM instead of the filesystem. The additional code talks to the TPM via a newer subset of CNG API, so it works only on some later versions of Windows 10, in which the API was first introduced.

The quality of the code is really low right now, and I don't think it could be suddenly made into a PR. Before I start working on this, I wanted to ask if anyone is interested in implementing TPM support. I don't want to waste time on a feature that nobody asked for...

Thank you in advance.

keithallenjackson commented 5 years ago

I would love that feature! I've been looking at smart card support for my work.

sadlame commented 5 years ago

@keithallenjackson Thank you for your comment! I'll start working. Unfortunately I cannot test SmartCard support because I do not have the device, but it should definitely be supported by just changing a few lines, designating SmartCard instead of TPM as the Key Storage Provider.

sadlame commented 5 years ago

@keithallenjackson I set up a repo here which contains all the extra code required to support TPM/Smartcard authentication as a separate library.

It includes a sample program which demonstrates how to use the additional functionalities, e.g. creating a persistent key in TPM/Smartcard, deleting them, exporting them to OpenSSH format, and most importantly, logging in to a remote host with the key via SSH.

The quality of the code still needs improvement and the library lacks some important functionalities like importing keys from external files, but I believe it is already self-contained as a proof of concept.

The change required in SSH.NET itself (#577) is not available from NuGet of course, so the repo includes the modified version of SSH.NET as a submodule. So before you build, you have to initialize the submodule so its content is recognized by Visual Studio.

The sample program is quite self-explanatory, and you would be able to discover how to deal with Smartcard as well as TPM I hope. Please note that it might require admin privilege to read from/write to these devices.

Please feel free to ask me any questions. Thank you.

darinkes commented 5 years ago

How about adding PKCS#11 to work with smartcards, too? It works with .NET Core on Linux and also on older Windows Versions.

Tested and used it with SSH.NET in a project which source I currently cannot publish.

sadlame commented 5 years ago

@darinkes Supporting PKCS#11 as a backend looks like a good (or maybe better) idea to me, but unfortunately I barely know anything about it. I just chose CNG because I'm not bright enough to comprehend anything more complex, honestly.

The main point of this issue along with #577, I believe, is to make a pluggable interface so that people can implement their own source of encryption, not how it is actually implemented. Once such an interface is made available, various encryption backends (CNG, CAPI, PKCS#11, TBSIP, ...) could be developed separately without bothering anyone or breaking anything here. My implementation is intended to show that there really is a need for such an interface and I thought it could be tolerated to use a less capable API.

Anyway, thank you for enlightening me. Learning about that interface would be fun.

darinkes commented 5 years ago

Yeah, I'm also not sure which auth-methods should be shipped with the library. Or if it just should always come with private-key auth and expose hooks to add your own auth methods.

AFAIK I also added (quite dirty) some hooks to pass data between my custom PKCS#11 interface and SSH.NET.

drieseng commented 5 years ago

Since this is a Windows-only feature, shouldn't we move this to a separate module (and package it separately)?

sadlame commented 5 years ago

@drieseng Yes, I think so too. I'm currently developing my CNG backend as a separate module (if you have time, please take a look at my repo).

The problem I want to address in #577 is that it is currently impossible to delegate the signing operation to an external module, as far as I understand. #577 is the least possible amount of change required in this repo to make this possible.

darinkes commented 5 years ago

Since this is a Windows-only feature, shouldn't we move this to a separate module (and package it separately)?

Uh! That would be generally a great idea I think. Once there is an defined Interface in SSH.NET to have optional Nuget-Packages in the end: