Skip to content
Merged
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
76 changes: 52 additions & 24 deletions Src/IronPython.Modules/_ssl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using System.Linq;
using System.Net.Security;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Authentication;
using System.Security.Cryptography;
Expand Down Expand Up @@ -190,7 +191,11 @@ public void load_verify_locations(CodeContext context, object cafile = null, str
} else {
throw PythonOps.TypeError("cafile should be a valid filesystem path");
}
#if NET5_0_OR_GREATER
_cert_store.ImportFromPemFile(_cafile);
#else
_cert_store.Add(ReadCertificate(context, _cafile));
#endif
}

if (capath != null) {
Expand Down Expand Up @@ -631,8 +636,7 @@ public Bytes read(int size = -1) {
if (length < span.Length) {
buf = Bytes.Make(span.Slice(length).ToArray());
span = span.Slice(0, length);
}
else {
} else {
buf = null;
}
span.CopyTo(resSpan);
Expand Down Expand Up @@ -903,7 +907,13 @@ private static PythonTuple IssuerFieldToPython(CodeContext context, string p) {
return null;
}

private static X509Certificate2 ReadCertificate(CodeContext context, string filename) {
private static X509Certificate2 ReadCertificate(CodeContext context, string filename, bool readKey = false) {
#if NET5_0_OR_GREATER
if (readKey) {
return X509Certificate2.CreateFromPemFile(filename);
}
#endif

string[] lines;
try {
lines = File.ReadAllLines(filename);
Expand All @@ -923,14 +933,17 @@ private static X509Certificate2 ReadCertificate(CodeContext context, string file
} catch (Exception e) {
throw ErrorDecoding(context, filename, e);
}
if (!readKey) return cert;
} else if (lines[i] == "-----BEGIN RSA PRIVATE KEY-----") {
var keyStr = ReadToEnd(lines, ref i, "-----END RSA PRIVATE KEY-----");

try {
var keyBytes = Convert.FromBase64String(keyStr.ToString());
key = ParsePkcs1DerEncodedPrivateKey(context, filename, keyBytes);
} catch (Exception e) {
throw ErrorDecoding(context, filename, e);
if (readKey) {
try {
var keyBytes = Convert.FromBase64String(keyStr.ToString());
key = ParsePkcs1DerEncodedPrivateKey(context, filename, keyBytes);
} catch (Exception e) {
throw ErrorDecoding(context, filename, e);
}
}
}
}
Expand All @@ -941,9 +954,7 @@ private static X509Certificate2 ReadCertificate(CodeContext context, string file
if (cert != null) {
if (key != null) {
try {
#pragma warning disable SYSLIB0028 // Type or member is obsolete
cert.PrivateKey = key;
#pragma warning restore SYSLIB0028 // Type or member is obsolete
cert = cert.CopyWithPrivateKey(key);
} catch (CryptographicException e) {
throw ErrorDecoding(context, filename, "cert and private key are incompatible", e);
}
Expand All @@ -954,6 +965,23 @@ private static X509Certificate2 ReadCertificate(CodeContext context, string file
throw ErrorDecoding(context, filename, "certificate not found");
}

#if !NETCOREAPP && !NET472_OR_GREATER
#if NETSTANDARD
private static MethodInfo CopyWithPrivateKeyMethodInfo = typeof(RSACertificateExtensions).GetMethod("CopyWithPrivateKey", new Type[] { typeof(X509Certificate2), typeof(System.Security.Cryptography.RSA) });
#endif

private static X509Certificate2 CopyWithPrivateKey(this X509Certificate2 certificate, RSA privateKey) {
#if NETSTANDARD
if (CopyWithPrivateKeyMethodInfo is not null) {
return (X509Certificate2)CopyWithPrivateKeyMethodInfo.Invoke(null, new object[] { certificate, privateKey });
}
#endif
certificate.PrivateKey = privateKey;
return certificate;
}
#endif


#region Private Key Parsing

private const int ClassOffset = 6;
Expand All @@ -965,7 +993,7 @@ private static X509Certificate2 ReadCertificate(CodeContext context, string file

private const int NumberMask = 0x1f;

private const int UnivesalSequence = 0x10;
private const int UniversalSequence = 0x10;
private const int UniversalInteger = 0x02;
private const int UniversalOctetString = 0x04;

Expand All @@ -987,7 +1015,7 @@ private static RSACryptoServiceProvider ParsePkcs1DerEncodedPrivateKey(CodeConte
// read header for sequence
if ((x[0] & ClassMask) != ClassUniversal) {
throw ErrorDecoding(context, filename, "failed to find universal class");
} else if ((x[0] & NumberMask) != UnivesalSequence) {
} else if ((x[0] & NumberMask) != UniversalSequence) {
throw ErrorDecoding(context, filename, "failed to read sequence header");
}

Expand All @@ -996,7 +1024,7 @@ private static RSACryptoServiceProvider ParsePkcs1DerEncodedPrivateKey(CodeConte
ReadLength(x, ref offset);

// read version
int version = ReadUnivesalInt(x, ref offset);
int version = ReadUniversalInt(x, ref offset);
if (version != 0) {
// unsupported version
throw new InvalidOperationException(String.Format("bad vesion: {0}", version));
Expand All @@ -1006,20 +1034,20 @@ private static RSACryptoServiceProvider ParsePkcs1DerEncodedPrivateKey(CodeConte
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
RSAParameters parameters = new RSAParameters();

parameters.Modulus = ReadUnivesalIntAsBytes(x, ref offset);
parameters.Exponent = ReadUnivesalIntAsBytes(x, ref offset);
parameters.D = ReadUnivesalIntAsBytes(x, ref offset);
parameters.P = ReadUnivesalIntAsBytes(x, ref offset);
parameters.Q = ReadUnivesalIntAsBytes(x, ref offset);
parameters.DP = ReadUnivesalIntAsBytes(x, ref offset);
parameters.DQ = ReadUnivesalIntAsBytes(x, ref offset);
parameters.InverseQ = ReadUnivesalIntAsBytes(x, ref offset);
parameters.Modulus = ReadUniversalIntAsBytes(x, ref offset);
parameters.Exponent = ReadUniversalIntAsBytes(x, ref offset);
parameters.D = ReadUniversalIntAsBytes(x, ref offset);
parameters.P = ReadUniversalIntAsBytes(x, ref offset);
parameters.Q = ReadUniversalIntAsBytes(x, ref offset);
parameters.DP = ReadUniversalIntAsBytes(x, ref offset);
parameters.DQ = ReadUniversalIntAsBytes(x, ref offset);
parameters.InverseQ = ReadUniversalIntAsBytes(x, ref offset);

provider.ImportParameters(parameters);
return provider;
}

private static byte[] ReadUnivesalIntAsBytes(byte[] x, ref int offset) {
private static byte[] ReadUniversalIntAsBytes(byte[] x, ref int offset) {
ReadIntType(x, ref offset);

int bytes = ReadLength(x, ref offset);
Expand All @@ -1046,7 +1074,7 @@ private static void ReadIntType(byte[] x, ref int offset) {
throw new InvalidOperationException(String.Format("expected version, fonud {0}", versionType));
}
}
private static int ReadUnivesalInt(byte[] x, ref int offset) {
private static int ReadUniversalInt(byte[] x, ref int offset) {
ReadIntType(x, ref offset);

return ReadInt(x, ref offset);
Expand Down