Skip to content

Commit 6038a69

Browse files
authored
[ECC] Implicitly set CertificateType of Certificate Identifier & allow Revocation with ECC Issuer Certificate & fix VerifyECDsaKeyPair (#2924)
* implicitly set certificate type of certificate identifier extend CertificateFactory to allow Revocation with ECC Issuer Certificate * Add Crl tests for ECC * fix X509 PFXUtils VerifyECDsaKeyPair
1 parent b38406c commit 6038a69

File tree

5 files changed

+88
-14
lines changed

5 files changed

+88
-14
lines changed

Libraries/Opc.Ua.Security.Certificates/X509Certificate/X509PfxUtils.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,8 @@ public static bool VerifyECDsaKeyPair(
257257
bool throwOnError = false)
258258
{
259259
bool result = false;
260-
using (ECDsa ecdsaPublicKey = certWithPrivateKey.GetECDsaPublicKey())
261-
using (ECDsa ecdsaPrivateKey = certWithPublicKey.GetECDsaPrivateKey())
260+
using (ECDsa ecdsaPublicKey = certWithPublicKey.GetECDsaPublicKey())
261+
using (ECDsa ecdsaPrivateKey = certWithPrivateKey.GetECDsaPrivateKey())
262262
{
263263
try
264264
{

Stack/Opc.Ua.Core/Schema/ApplicationConfiguration.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3067,7 +3067,7 @@ public CertificateIdentifier()
30673067
public CertificateIdentifier(X509Certificate2 certificate)
30683068
{
30693069
Initialize();
3070-
m_certificate = certificate;
3070+
Certificate = certificate;
30713071
}
30723072

30733073
/// <summary>
@@ -3076,7 +3076,7 @@ public CertificateIdentifier(X509Certificate2 certificate)
30763076
public CertificateIdentifier(X509Certificate2 certificate, CertificateValidationOptions validationOptions)
30773077
{
30783078
Initialize();
3079-
m_certificate = certificate;
3079+
Certificate = certificate;
30803080
m_validationOptions = validationOptions;
30813081
}
30823082

@@ -3087,7 +3087,7 @@ public CertificateIdentifier(X509Certificate2 certificate, CertificateValidation
30873087
public CertificateIdentifier(byte[] rawData)
30883088
{
30893089
Initialize();
3090-
m_certificate = CertificateFactory.Create(rawData, true);
3090+
Certificate = CertificateFactory.Create(rawData, true);
30913091
}
30923092

30933093
/// <summary>
@@ -3324,6 +3324,7 @@ public byte[] RawData
33243324
m_certificate = CertificateFactory.Create(value, true);
33253325
m_subjectName = m_certificate.Subject;
33263326
m_thumbprint = m_certificate.Thumbprint;
3327+
m_certificateType = GetCertificateType(m_certificate);
33273328
}
33283329
}
33293330

Stack/Opc.Ua.Core/Security/Certificates/CertificateFactory.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,19 @@ DateTime nextUpdate
292292
.SetNextUpdate(nextUpdate)
293293
.AddCRLExtension(X509Extensions.BuildAuthorityKeyIdentifier(issuerCertificate))
294294
.AddCRLExtension(X509Extensions.BuildCRLNumber(crlSerialNumber + 1));
295-
return new X509CRL(crlBuilder.CreateForRSA(issuerCertificate));
295+
296+
if (X509PfxUtils.IsECDsaSignature(issuerCertificate))
297+
{
298+
#if ECC_SUPPORT
299+
return new X509CRL(crlBuilder.CreateForECDsa(issuerCertificate));
300+
#else
301+
throw new NotSupportedException("CRL can only be created for an RSA Certificate on this system");
302+
#endif
303+
}
304+
else
305+
{
306+
return new X509CRL(crlBuilder.CreateForRSA(issuerCertificate));
307+
}
296308
}
297309

298310
#if NETSTANDARD2_1 || NET472_OR_GREATER || NET5_0_OR_GREATER

Stack/Opc.Ua.Core/Security/Certificates/CertificateIdentifier.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,14 @@ public CertificateValidationOptions ValidationOptions
145145
public X509Certificate2 Certificate
146146
{
147147
get { return m_certificate; }
148-
set { m_certificate = value; }
148+
set
149+
{
150+
m_certificate = value;
151+
if (m_certificate != null)
152+
{
153+
m_certificateType = GetCertificateType(m_certificate);
154+
}
155+
}
149156
}
150157
#endregion
151158

Tests/Opc.Ua.Security.Certificates.Tests/CRLTests.cs

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
using System;
3232
using System.Globalization;
33+
using System.Runtime.InteropServices;
3334
using System.Security.Cryptography;
3435
using System.Security.Cryptography.X509Certificates;
3536
using System.Text;
@@ -44,6 +45,7 @@ namespace Opc.Ua.Security.Certificates.Tests
4445
/// </summary>
4546
[TestFixture, Category("CRL")]
4647
[Parallelizable]
48+
[TestFixtureSource(nameof(FixtureArgs))]
4749
[SetCulture("en-us")]
4850
public class CRLTests
4951
{
@@ -58,16 +60,48 @@ public class CRLTests
5860
{ 4096, HashAlgorithmName.SHA512 } }.ToArray();
5961
#endregion
6062

63+
/// <summary>
64+
/// store types to run the tests with
65+
/// </summary>
66+
public static readonly object[] FixtureArgs = {
67+
new object [] { nameof(Opc.Ua.ObjectTypeIds.RsaSha256ApplicationCertificateType)},
68+
new object [] { nameof(Opc.Ua.ObjectTypeIds.EccNistP256ApplicationCertificateType)}
69+
};
70+
71+
public CRLTests(string certificateType)
72+
{
73+
if (certificateType == CertificateStoreType.X509Store && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
74+
{
75+
Assert.Ignore("X509 Store with crls is only supported on Windows, skipping test run");
76+
}
77+
m_certifiateType = certificateType;
78+
}
79+
80+
6181
#region Test Setup
6282
/// <summary>
6383
/// Set up a Global Discovery Server and Client instance and connect the session
6484
/// </summary>
6585
[OneTimeSetUp]
6686
protected void OneTimeSetUp()
6787
{
68-
m_issuerCert = CertificateBuilder.Create("CN=Root CA, O=OPC Foundation")
69-
.SetCAConstraint()
70-
.CreateForRSA();
88+
if (m_certifiateType == nameof(Opc.Ua.ObjectTypeIds.RsaSha256ApplicationCertificateType))
89+
{
90+
m_issuerCert = CertificateBuilder.Create("CN=Root CA, O=OPC Foundation")
91+
.SetCAConstraint()
92+
.CreateForRSA();
93+
}
94+
else if (m_certifiateType == nameof(Opc.Ua.ObjectTypeIds.EccNistP256ApplicationCertificateType))
95+
{
96+
m_issuerCert = CertificateBuilder.Create("CN=Root CA, O=OPC Foundation")
97+
.SetCAConstraint()
98+
.SetECCurve(ECCurve.NamedCurves.nistP256)
99+
.CreateForECDsa();
100+
}
101+
else
102+
{
103+
throw new NotImplementedException();
104+
}
71105
}
72106

73107
/// <summary>
@@ -144,8 +178,16 @@ public void CrlBuilderTest(bool empty, bool noExtensions, KeyHashPair keyHashPai
144178
crlBuilder.CrlExtensions.Add(X509Extensions.BuildCRLNumber(1111));
145179
crlBuilder.CrlExtensions.Add(X509Extensions.BuildAuthorityKeyIdentifier(m_issuerCert));
146180
}
181+
IX509CRL i509Crl;
182+
if (X509PfxUtils.IsECDsaSignature(m_issuerCert))
183+
{
147184

148-
var i509Crl = crlBuilder.CreateForRSA(m_issuerCert);
185+
i509Crl = crlBuilder.CreateForECDsa(m_issuerCert);
186+
}
187+
else
188+
{
189+
i509Crl = crlBuilder.CreateForRSA(m_issuerCert);
190+
}
149191
X509CRL x509Crl = new X509CRL(i509Crl.RawData);
150192
Assert.NotNull(x509Crl);
151193
Assert.NotNull(x509Crl.CrlExtensions);
@@ -203,10 +245,21 @@ public void CrlBuilderTestWithSignatureGenerator(KeyHashPair keyHashPair)
203245
crlBuilder.CrlExtensions.Add(X509Extensions.BuildAuthorityKeyIdentifier(m_issuerCert));
204246

205247
IX509CRL ix509Crl;
206-
using (RSA rsa = m_issuerCert.GetRSAPrivateKey())
248+
if (X509PfxUtils.IsECDsaSignature(m_issuerCert))
207249
{
208-
X509SignatureGenerator generator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1);
209-
ix509Crl = crlBuilder.CreateSignature(generator);
250+
using (ECDsa ecdsa = m_issuerCert.GetECDsaPrivateKey())
251+
{
252+
X509SignatureGenerator generator = X509SignatureGenerator.CreateForECDsa(ecdsa);
253+
ix509Crl = crlBuilder.CreateSignature(generator);
254+
}
255+
}
256+
else
257+
{
258+
using (RSA rsa = m_issuerCert.GetRSAPrivateKey())
259+
{
260+
X509SignatureGenerator generator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1);
261+
ix509Crl = crlBuilder.CreateSignature(generator);
262+
}
210263
}
211264
X509CRL x509Crl = new X509CRL(ix509Crl);
212265
Assert.NotNull(x509Crl);
@@ -322,6 +375,7 @@ private void ValidateCRL(
322375

323376
#region Private Fields
324377
X509Certificate2 m_issuerCert;
378+
private string m_certifiateType;
325379
#endregion
326380
}
327381

0 commit comments

Comments
 (0)