dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.19k stars 4.72k forks source link

.net core TLS server certificate with private key in TPM #109243

Open appcodr opened 17 hours ago

appcodr commented 17 hours ago

I'm trying to do an equivalent of this command in a .net core library for doing a TLS server where the private key is in TPM with a reference of 0x8100001:

openssl s_server -cert rsa.crt -key 0x8100002-keyform engine -engine tpm2tss -accept 8

im trying for this to be running in Ubuntu on .net core. In Windows this is abstracted well by the cert store with crypto provider but the same doesn't exist in Ubuntu.

Does anyone have an example of using a package that works in Ubuntu? The below is the equivalent in windows that we use to get from cert store(the cert store abstracts the TPM access)

X509Store store = new X509Store(storeName, StoreLocation.CurrentUser);  
store.Open(OpenFlags.ReadOnly);  
X509Certificate2Collection col = store.Certificates.Find(X509FindType.FindBySubjectName, commonName,false);

I also tried this example(https://github.com/dotnet/runtime/issues/94493) with the 0x8100002 reference but it fails as well

private static X509Certificate2 GetClientCert(string path, ???)
{
    using SafeEvpPKeyHandle keyHandle = ???;
    using RSAOpenSsl rsa = new RSAOpenSsl(keyHandle);
    using X509Certificate2 certOnly = new X509Certificate2(path);

    return certOnly.CopyWithPrivateKey(rsa);
}
dotnet-policy-service[bot] commented 17 hours ago

Tagging subscribers to this area: @dotnet/area-system-security, @bartonjs, @vcsjones See info in area-owners.md if you want to be subscribed.

bartonjs commented 16 hours ago

Since you're using an engine (and not a provider) you should be able to do it with .NET 8+

using (SafeEvpPKeyHandle keyHandle = SafeEvpPKeyHandle.OpenPrivateKeyFromEngine("tpm2tss", "0x8100002"))
using (RSA rsa = new RSAOpenSsl(keyHandle))
using (X509Certificate2 certOnly = new X509Certificate2(path))
{
    return certOnly.CopyWithPrivateKey(rsa);
}

If instead you need an OSSL_PROVIDER (instead of an ENGINE) then you need .NET 9+, where it would look like

using (SafeEvpPKeyHandle keyHandle = SafeEvpPKeyHandle.OpenKeyFromProvider("tpm2tss", "0x8100002"))
using (RSA rsa = new RSAOpenSsl(keyHandle))
using (X509Certificate2 certOnly = X509CertificateLoader.LoadCertificateFromFile(path))
{
    return certOnly.CopyWithPrivateKey(rsa);
}