Skip to content

Commit

Permalink
Use correctly and validate certificate ECDSA signature hash algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
mrsuciu committed Dec 16, 2024
1 parent 0777bbd commit d1c8751
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 5 deletions.
12 changes: 8 additions & 4 deletions Libraries/Opc.Ua.Configuration/ApplicationInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright (c) 2005-2021 The OPC Foundation, Inc. All rights reserved.
*
* OPC Foundation MIT License 1.00
*
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
Expand All @@ -11,7 +11,7 @@
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Expand Down Expand Up @@ -499,7 +499,7 @@ public async Task<bool> CheckApplicationInstanceCertificates(

#region Private Methods
/// <summary>
///
///
/// </summary>
/// <param name="id"></param>
/// <param name="silent"></param>
Expand Down Expand Up @@ -715,7 +715,7 @@ await configuration.CertificateValidator.ValidateAsync(
configuration.CertificateValidator.CertificateValidation -= certValidator.OnCertificateValidation;
}

// check key size
// check key size
int keySize = X509Utils.GetPublicKeySize(certificate);
if (minimumKeySize > keySize)
{
Expand Down Expand Up @@ -911,6 +911,7 @@ private static async Task<X509Certificate2> CreateApplicationInstanceCertificate
throw new ServiceResultException(StatusCodes.BadConfigurationError, "The Ecc certificate type is not supported.");
#else
ECCurve curve = default(ECCurve);
HashAlgorithmName hashAlgorithm = HashAlgorithmName.SHA256;
if (id.CertificateType == ObjectTypeIds.EccApplicationCertificateType ||
id.CertificateType == ObjectTypeIds.EccNistP256ApplicationCertificateType)
{
Expand All @@ -919,6 +920,7 @@ private static async Task<X509Certificate2> CreateApplicationInstanceCertificate
else if (id.CertificateType == ObjectTypeIds.EccNistP384ApplicationCertificateType)
{
curve = ECCurve.NamedCurves.nistP384;
hashAlgorithm = HashAlgorithmName.SHA384;
}
else if (id.CertificateType == ObjectTypeIds.EccBrainpoolP256r1ApplicationCertificateType)
{
Expand All @@ -927,6 +929,7 @@ private static async Task<X509Certificate2> CreateApplicationInstanceCertificate
else if (id.CertificateType == ObjectTypeIds.EccBrainpoolP384r1ApplicationCertificateType)
{
curve = ECCurve.NamedCurves.brainpoolP384r1;
hashAlgorithm = HashAlgorithmName.SHA384;
}
#if CURVE25519
else if (id.CertificateType == ObjectTypeIds.EccCurve25519ApplicationCertificateType)
Expand All @@ -944,6 +947,7 @@ private static async Task<X509Certificate2> CreateApplicationInstanceCertificate
}

id.Certificate = builder
.SetHashAlgorithm(hashAlgorithm)
.SetECCurve(curve)
.CreateForECDsa();

Expand Down
20 changes: 19 additions & 1 deletion Stack/Opc.Ua.Core/Security/Certificates/CertificateValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace Opc.Ua
/// </summary>
public class CertificateValidator : ICertificateValidator
{
// default number of rejected certificates for history
// default number of rejected certificates for history
const int kDefaultMaxRejectedCertificates = 5;

#region Constructors
Expand Down Expand Up @@ -1414,6 +1414,24 @@ protected virtual async Task InternalValidateAsync(X509Certificate2Collection ce
null, null, "SHA1 signed certificates are not trusted.", null, sresult);
}

// check if certificate signature algorithm length is sufficient
if (isECDsaSignature)
{
int publicKeySize = X509Utils.GetPublicKeySize(certificate);
bool isInvalid = (certificate.SignatureAlgorithm.Value == Oids.ECDsaWithSha256 &&
publicKeySize < 256) ||
(certificate.SignatureAlgorithm.Value == Oids.ECDsaWithSha384 &&
publicKeySize < 384) ||
(certificate.SignatureAlgorithm.Value == Oids.ECDsaWithSha512 &&
publicKeySize < 512);

if (isInvalid)
{
sresult = new ServiceResult(StatusCodes.BadCertificatePolicyCheckFailed,
null, null, "Certificate doesn't meet minimum key length requirement.", null, sresult);
}
}

if (!isECDsaSignature)
{
int keySize = X509Utils.GetRSAPublicKeySize(certificate);
Expand Down

0 comments on commit d1c8751

Please sign in to comment.