Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.
Merged
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
4 changes: 2 additions & 2 deletions src/Kestrel.Tls/ListenOptionsTlsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ namespace Microsoft.AspNetCore.Hosting
{
public static class ListenOptionsTlsExtensions
{
public static ListenOptions UseTls(this ListenOptions listenOptions, string certificatePath, string privateKeyPath)
public static ListenOptions UseTls(this ListenOptions listenOptions, string certificatePath, string password)
{
return listenOptions.UseTls(new TlsConnectionAdapterOptions
{
CertificatePath = certificatePath,
PrivateKeyPath = privateKeyPath,
Password = password,
Protocols = listenOptions.Protocols
});
}
Expand Down
62 changes: 62 additions & 0 deletions src/Kestrel.Tls/OpenSsl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,41 @@ public static void SSL_CTX_free(IntPtr ctx)
NativeMethods.SSL_CTX_free(ctx);
}

public unsafe static int SSL_CTX_Set_Pfx(IntPtr ctx, string path, string password)
{
var pass = Marshal.StringToHGlobalAnsi(password);
var key = IntPtr.Zero;
var cert = IntPtr.Zero;
var ca = IntPtr.Zero;

try
{
var file = System.IO.File.ReadAllBytes(path);

fixed (void* f = file)
{
var buffer = (IntPtr)f;
var pkcs = NativeMethods.d2i_PKCS12(IntPtr.Zero, ref buffer, file.Length);
var result = NativeMethods.PKCS12_parse(pkcs, pass, ref key, ref cert, ref ca);
if (result != 1)
{
return -1;
}
if (NativeMethods.SSL_CTX_use_certificate(ctx, cert) != 1) return -1;
if (NativeMethods.SSL_CTX_use_PrivateKey(ctx, key) != 1) return -1;
if (NativeMethods.SSL_CTX_set1_chain(ctx, ca) != 1) return -1;
return 1;
}
}
finally
{
Marshal.FreeHGlobal(pass);
if (key != IntPtr.Zero) NativeMethods.EVP_PKEY_free(key);
if (cert != IntPtr.Zero) NativeMethods.X509_free(cert);
if (ca != IntPtr.Zero) NativeMethods.sk_X509_pop_free(ca);
}
}

public static int SSL_CTX_set_ecdh_auto(IntPtr ctx, int onoff)
{
return (int)NativeMethods.SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, IntPtr.Zero);
Expand Down Expand Up @@ -263,6 +298,33 @@ private class NativeMethods

[DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
public static extern void ERR_load_BIO_strings();

[DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr d2i_PKCS12(IntPtr unsused, ref IntPtr bufferPointer, long length);

[DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
public static extern int PKCS12_parse(IntPtr p12, IntPtr pass, ref IntPtr pkey, ref IntPtr cert, ref IntPtr ca);

[DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
public static extern void PKCS12_free(IntPtr p12);

[DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
public static extern void EVP_PKEY_free(IntPtr pkey);

[DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
public static extern void X509_free(IntPtr a);

[DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
public static extern void sk_X509_pop_free(IntPtr ca);

[DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
public static extern int SSL_CTX_set1_chain(IntPtr ctx, IntPtr sk);

[DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
public static extern int SSL_CTX_use_certificate(IntPtr ctx, IntPtr x509);

[DllImport("libssl", CallingConvention = CallingConvention.Cdecl)]
public static extern int SSL_CTX_use_PrivateKey(IntPtr ctx, IntPtr pkey);
}
}
}
6 changes: 3 additions & 3 deletions src/Kestrel.Tls/TlsConnectionAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ public TlsConnectionAdapter(TlsConnectionAdapterOptions options, ILoggerFactory
throw new ArgumentException("Certificate path must be non-null.", nameof(options));
}

if (options.PrivateKeyPath == null)
if (options.Password == null)
{
throw new ArgumentException("Private key path must be non-null.", nameof(options));
throw new ArgumentException("Password must be non-null.", nameof(options));
}

_options = options;
Expand Down Expand Up @@ -70,7 +70,7 @@ public Task<IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext conte

private async Task<IAdaptedConnection> InnerOnConnectionAsync(ConnectionAdapterContext context)
{
var tlsStream = new TlsStream(context.ConnectionStream, _options.CertificatePath, _options.PrivateKeyPath, _serverProtocols);
var tlsStream = new TlsStream(context.ConnectionStream, _options.CertificatePath, _options.Password, _serverProtocols);

try
{
Expand Down
2 changes: 1 addition & 1 deletion src/Kestrel.Tls/TlsConnectionAdapterOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class TlsConnectionAdapterOptions
{
public string CertificatePath { get; set; } = string.Empty;

public string PrivateKeyPath { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;

public HttpProtocols Protocols { get; set; }
}
Expand Down
15 changes: 5 additions & 10 deletions src/Kestrel.Tls/TlsStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ static TlsStream()
OpenSsl.OpenSSL_add_all_algorithms();
}

public TlsStream(Stream innerStream, string certificatePath, string privateKeyPath, IEnumerable<string> protocols)
public TlsStream(Stream innerStream, string certificatePath, string password, IEnumerable<string> protocols)
{
_innerStream = innerStream;
_protocols = ToWireFormat(protocols);
Expand All @@ -49,18 +49,13 @@ public TlsStream(Stream innerStream, string certificatePath, string privateKeyPa
throw new Exception("Unable to create SSL context.");
}

OpenSsl.SSL_CTX_set_ecdh_auto(_ctx, 1);

if (OpenSsl.SSL_CTX_use_certificate_file(_ctx, certificatePath, 1) != 1)
{
throw new Exception("Unable to load certificate file.");
}

if (OpenSsl.SSL_CTX_use_PrivateKey_file(_ctx, privateKeyPath, 1) != 1)
if(OpenSsl.SSL_CTX_Set_Pfx(_ctx, certificatePath, password) != 1)
{
throw new Exception("Unable to load private key file.");
throw new InvalidOperationException("Unable to load PFX");
}

OpenSsl.SSL_CTX_set_ecdh_auto(_ctx, 1);

OpenSsl.SSL_CTX_set_alpn_select_cb(_ctx, _alpnSelectCallback, GCHandle.ToIntPtr(_protocolsHandle));

_ssl = OpenSsl.SSL_new(_ctx);
Expand Down