Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 683853a

Browse files
committed
Merge pull request #2196 from bartonjs/X509Chain-Submit
Initial implementation of X509Chain for Unix.
2 parents 655a3ca + 4aa6b8e commit 683853a

File tree

20 files changed

+1531
-76
lines changed

20 files changed

+1531
-76
lines changed

src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.NativeCrypto.cs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using System;
5+
using System.Diagnostics;
56
using System.Runtime.InteropServices;
67
using System.Security.Cryptography;
7-
using System.Security.Cryptography.X509Certificates;
88

99
using Microsoft.Win32.SafeHandles;
1010

@@ -51,6 +51,33 @@ internal static partial class NativeCrypto
5151
[DllImport(Libraries.CryptoInterop)]
5252
private static extern int GetAsn1StringBytes(IntPtr asn1, byte[] buf, int cBuf);
5353

54+
[DllImport(Libraries.CryptoInterop)]
55+
internal static extern int GetX509StackFieldCount(SafeX509StackHandle stack);
56+
57+
/// <summary>
58+
/// Gets a pointer to a certificate within a STACK_OF(X509). This pointer will later
59+
/// be freed, so it should be cloned via new X509Certificate2(IntPtr)
60+
/// </summary>
61+
[DllImport(Libraries.CryptoInterop)]
62+
internal static extern IntPtr GetX509StackField(SafeX509StackHandle stack, int loc);
63+
64+
[DllImport(Libraries.CryptoInterop)]
65+
internal static extern void RecursiveFreeX509Stack(IntPtr stack);
66+
67+
[DllImport(Libraries.CryptoInterop, CharSet = CharSet.Ansi)]
68+
internal static extern string GetX509RootStorePath();
69+
70+
[DllImport(Libraries.CryptoInterop)]
71+
private static extern int SetX509ChainVerifyTime(
72+
SafeX509StoreCtxHandle ctx,
73+
int year,
74+
int month,
75+
int day,
76+
int hour,
77+
int minute,
78+
int second,
79+
[MarshalAs(UnmanagedType.Bool)] bool isDst);
80+
5481
internal static byte[] GetAsn1StringBytes(IntPtr asn1)
5582
{
5683
int negativeSize = GetAsn1StringBytes(asn1, null, 0);
@@ -71,5 +98,29 @@ internal static byte[] GetAsn1StringBytes(IntPtr asn1)
7198

7299
return bytes;
73100
}
101+
102+
internal static void SetX509ChainVerifyTime(SafeX509StoreCtxHandle ctx, DateTime verifyTime)
103+
{
104+
// Let Unspecified mean Local, so only convert if the source was UTC.
105+
if (verifyTime.Kind == DateTimeKind.Utc)
106+
{
107+
verifyTime = verifyTime.ToLocalTime();
108+
}
109+
110+
int succeeded = SetX509ChainVerifyTime(
111+
ctx,
112+
verifyTime.Year,
113+
verifyTime.Month,
114+
verifyTime.Day,
115+
verifyTime.Hour,
116+
verifyTime.Minute,
117+
verifyTime.Second,
118+
verifyTime.IsDaylightSavingTime());
119+
120+
if (succeeded != 1)
121+
{
122+
throw new CryptographicException();
123+
}
124+
}
74125
}
75126
}

src/Common/src/Interop/Unix/libcrypto/Interop.BIO.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ internal static partial class libcrypto
2828
[DllImport(Libraries.LibCrypto, CharSet = CharSet.Ansi)]
2929
internal static extern int BIO_gets(SafeBioHandle b, StringBuilder buf, int size);
3030

31+
[DllImport(Libraries.LibCrypto)]
32+
internal static extern int BIO_write(SafeBioHandle b, byte[] data, int len);
33+
3134
[DllImport(Libraries.LibCrypto)]
3235
private static extern NativeLong BIO_ctrl(SafeBioHandle bio, int cmd, NativeLong larg, IntPtr parg);
3336

src/Common/src/Interop/Unix/libcrypto/Interop.Initialization.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
// Copyright (c) Microsoft. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4-
using System;
5-
using System.Diagnostics;
64
using System.Runtime.InteropServices;
75
using System.Security.Cryptography;
8-
using System.Threading;
96

107
internal static partial class Interop
118
{
@@ -21,8 +18,15 @@ static libcrypto()
2118
throw new CryptographicException();
2219
}
2320

21+
// Load the SHA-2 hash algorithms, and anything else not in the default
22+
// support set.
23+
OPENSSL_add_all_algorithms_conf();
24+
2425
// Ensure that the error message table is loaded.
25-
Interop.libcrypto.ERR_load_crypto_strings();
26+
ERR_load_crypto_strings();
2627
}
28+
29+
[DllImport(Libraries.LibCrypto)]
30+
private static extern void OPENSSL_add_all_algorithms_conf();
2731
}
2832
}

src/Common/src/Interop/Unix/libcrypto/Interop.X509.cs

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33

44
using System;
55
using System.Runtime.InteropServices;
6-
using System.Security.Cryptography;
76

87
using Microsoft.Win32.SafeHandles;
98

9+
using NativeLong=System.IntPtr;
1010
using NativeULong=System.UIntPtr;
1111

1212
internal static partial class Interop
@@ -22,6 +22,12 @@ internal static partial class libcrypto
2222
[DllImport(Libraries.LibCrypto)]
2323
internal static extern unsafe int i2d_X509(SafeX509Handle x, byte** @out);
2424

25+
[DllImport(Libraries.LibCrypto)]
26+
internal static extern SafeX509Handle X509_dup(IntPtr handle);
27+
28+
[DllImport(Libraries.LibCrypto)]
29+
internal static extern SafeX509Handle PEM_read_bio_X509_AUX(SafeBioHandle bio, IntPtr zero, IntPtr zero1, IntPtr zero2);
30+
2531
[DllImport(Libraries.LibCrypto)]
2632
internal static extern IntPtr X509_get_serialNumber(SafeX509Handle x);
2733

@@ -44,6 +50,9 @@ internal static partial class libcrypto
4450
[return: MarshalAs(UnmanagedType.Bool)]
4551
internal static extern bool X509_check_purpose(SafeX509Handle x, int id, int ca);
4652

53+
[DllImport(Libraries.LibCrypto)]
54+
internal static extern int X509_check_issued(SafeX509Handle issuer, SafeX509Handle subject);
55+
4756
[DllImport(Libraries.LibCrypto)]
4857
internal static extern int X509_get_ext_count(SafeX509Handle x);
4958

@@ -63,5 +72,88 @@ internal static partial class libcrypto
6372
[DllImport(Libraries.LibCrypto)]
6473
[return: MarshalAs(UnmanagedType.Bool)]
6574
internal static extern bool X509_EXTENSION_get_critical(IntPtr ex);
75+
76+
[DllImport(Libraries.LibCrypto)]
77+
internal static extern SafeX509StoreHandle X509_STORE_new();
78+
79+
[DllImport(Libraries.LibCrypto)]
80+
internal static extern void X509_STORE_free(IntPtr v);
81+
82+
[DllImport(Libraries.LibCrypto)]
83+
[return: MarshalAs(UnmanagedType.Bool)]
84+
internal static extern bool X509_STORE_add_cert(SafeX509StoreHandle ctx, SafeX509Handle x);
85+
86+
[DllImport(Libraries.LibCrypto)]
87+
internal static extern SafeX509StoreCtxHandle X509_STORE_CTX_new();
88+
89+
[DllImport(Libraries.LibCrypto)]
90+
internal static extern void X509_STORE_CTX_free(IntPtr v);
91+
92+
[DllImport(Libraries.LibCrypto)]
93+
[return: MarshalAs(UnmanagedType.Bool)]
94+
internal static extern bool X509_STORE_CTX_init(SafeX509StoreCtxHandle ctx, SafeX509StoreHandle store, SafeX509Handle x509, IntPtr zero);
95+
96+
[DllImport(Libraries.LibCrypto)]
97+
internal static extern int X509_verify_cert(SafeX509StoreCtxHandle ctx);
98+
99+
[DllImport(Libraries.LibCrypto)]
100+
internal static extern SafeX509StackHandle X509_STORE_CTX_get1_chain(SafeX509StoreCtxHandle ctx);
101+
102+
[DllImport(Libraries.LibCrypto)]
103+
internal static extern X509VerifyStatusCode X509_STORE_CTX_get_error(SafeX509StoreCtxHandle ctx);
104+
105+
[DllImport(Libraries.LibCrypto)]
106+
internal static extern int X509_STORE_CTX_get_error_depth(SafeX509StoreCtxHandle ctx);
107+
108+
[DllImport(Libraries.LibCrypto)]
109+
internal static extern string X509_verify_cert_error_string(X509VerifyStatusCode n);
110+
111+
internal enum X509VerifyStatusCode
112+
{
113+
X509_V_OK = 0,
114+
X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 2,
115+
X509_V_ERR_UNABLE_TO_GET_CRL = 3,
116+
X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE = 4,
117+
X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE = 5,
118+
X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY = 6,
119+
X509_V_ERR_CERT_SIGNATURE_FAILURE = 7,
120+
X509_V_ERR_CRL_SIGNATURE_FAILURE = 8,
121+
X509_V_ERR_CERT_NOT_YET_VALID = 9,
122+
X509_V_ERR_CERT_HAS_EXPIRED = 10,
123+
X509_V_ERR_CRL_NOT_YET_VALID = 11,
124+
X509_V_ERR_CRL_HAS_EXPIRED = 12,
125+
X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 13,
126+
X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 14,
127+
X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD = 15,
128+
X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 16,
129+
X509_V_ERR_OUT_OF_MEM = 17,
130+
X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT = 18,
131+
X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN = 19,
132+
X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 20,
133+
X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = 21,
134+
X509_V_ERR_CERT_CHAIN_TOO_LONG = 22,
135+
X509_V_ERR_CERT_REVOKED = 23,
136+
X509_V_ERR_INVALID_CA = 24,
137+
X509_V_ERR_PATH_LENGTH_EXCEEDED = 25,
138+
X509_V_ERR_INVALID_PURPOSE = 26,
139+
X509_V_ERR_CERT_UNTRUSTED = 27,
140+
X509_V_ERR_CERT_REJECTED = 28,
141+
X509_V_ERR_AKID_SKID_MISMATCH = 30,
142+
X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH = 31,
143+
X509_V_ERR_KEYUSAGE_NO_CERTSIGN = 32,
144+
X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER = 33,
145+
X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION = 34,
146+
X509_V_ERR_KEYUSAGE_NO_CRL_SIGN = 35,
147+
X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION = 36,
148+
X509_V_ERR_INVALID_NON_CA = 37,
149+
X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED = 38,
150+
X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE = 39,
151+
X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED = 40,
152+
X509_V_ERR_INVALID_EXTENSION = 41,
153+
X509_V_ERR_INVALID_POLICY_EXTENSION = 42,
154+
X509_V_ERR_NO_EXPLICIT_POLICY = 43,
155+
X509_V_ERR_UNNESTED_RESOURCE = 44,
156+
X509_V_ERR_APPLICATION_VERIFICATION = 50,
157+
}
66158
}
67159
}

src/Common/src/Microsoft/Win32/SafeHandles/SafeX509Handle.Unix.cs

Lines changed: 0 additions & 32 deletions
This file was deleted.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Security;
6+
using System.Runtime.InteropServices;
7+
8+
namespace Microsoft.Win32.SafeHandles
9+
{
10+
[SecurityCritical]
11+
internal sealed class SafeX509Handle : SafeHandle
12+
{
13+
private SafeX509Handle() :
14+
base(IntPtr.Zero, ownsHandle: true)
15+
{
16+
}
17+
18+
[SecurityCritical]
19+
protected override bool ReleaseHandle()
20+
{
21+
Interop.libcrypto.X509_free(handle);
22+
SetHandle(IntPtr.Zero);
23+
return true;
24+
}
25+
26+
public override bool IsInvalid
27+
{
28+
[SecurityCritical]
29+
get { return handle == IntPtr.Zero; }
30+
}
31+
}
32+
[SecurityCritical]
33+
internal sealed class SafeX509StoreHandle : SafeHandle
34+
{
35+
private SafeX509StoreHandle() :
36+
base(IntPtr.Zero, ownsHandle: true)
37+
{
38+
}
39+
40+
protected override bool ReleaseHandle()
41+
{
42+
Interop.libcrypto.X509_STORE_free(handle);
43+
SetHandle(IntPtr.Zero);
44+
return true;
45+
}
46+
47+
public override bool IsInvalid
48+
{
49+
get { return handle == IntPtr.Zero; }
50+
}
51+
}
52+
[SecurityCritical]
53+
internal sealed class SafeX509StoreCtxHandle : SafeHandle
54+
{
55+
private SafeX509StoreCtxHandle() :
56+
base(IntPtr.Zero, ownsHandle: true)
57+
{
58+
}
59+
60+
protected override bool ReleaseHandle()
61+
{
62+
Interop.libcrypto.X509_STORE_CTX_free(handle);
63+
SetHandle(IntPtr.Zero);
64+
return true;
65+
}
66+
67+
public override bool IsInvalid
68+
{
69+
get { return handle == IntPtr.Zero; }
70+
}
71+
}
72+
73+
[SecurityCritical]
74+
internal sealed class SafeX509StackHandle : SafeHandle
75+
{
76+
private SafeX509StackHandle() :
77+
base(IntPtr.Zero, ownsHandle: true)
78+
{
79+
}
80+
81+
protected override bool ReleaseHandle()
82+
{
83+
Interop.NativeCrypto.RecursiveFreeX509Stack(handle);
84+
SetHandle(IntPtr.Zero);
85+
return true;
86+
}
87+
88+
public override bool IsInvalid
89+
{
90+
get { return handle == IntPtr.Zero; }
91+
}
92+
}
93+
}

src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Oids.cs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,19 @@ namespace Internal.Cryptography
1414
//
1515
internal static class Oids
1616
{
17-
public const String BasicConstraints = "2.5.29.10";
18-
public const String SubjectKeyIdentifier = "2.5.29.14";
19-
public const String KeyUsage = "2.5.29.15";
20-
public const String BasicConstraints2 = "2.5.29.19";
21-
public const String CertPolicies = "2.5.29.32";
22-
public const String EnhancedKeyUsage = "2.5.29.37";
23-
public const String RsaRsa = "1.2.840.113549.1.1.1";
24-
public const String EnrollCertTypeExtension = "1.3.6.1.4.1.311.20.2";
25-
public const String CertificateTemplate = "1.3.6.1.4.1.311.21.7";
17+
public const string BasicConstraints = "2.5.29.10";
18+
public const string SubjectKeyIdentifier = "2.5.29.14";
19+
public const string KeyUsage = "2.5.29.15";
20+
public const string BasicConstraints2 = "2.5.29.19";
21+
public const string CertPolicies = "2.5.29.32";
22+
public const string AnyCertPolicy = "2.5.29.32.0";
23+
public const string CertPolicyMappings = "2.5.29.33";
24+
public const string CertPolicyConstraints = "2.5.29.36";
25+
public const string EnhancedKeyUsage = "2.5.29.37";
26+
public const string InhibitAnyPolicyExtension = "2.5.29.54";
27+
public const string RsaRsa = "1.2.840.113549.1.1.1";
28+
public const string EnrollCertTypeExtension = "1.3.6.1.4.1.311.20.2";
29+
public const string CertificateTemplate = "1.3.6.1.4.1.311.21.7";
30+
public const string ApplicationCertPolicies = "1.3.6.1.4.1.311.21.10";
2631
}
2732
}

0 commit comments

Comments
 (0)