diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.DSA.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.DSA.cs index adef3197785863..85e72a887a5e26 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.DSA.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.DSA.cs @@ -71,31 +71,34 @@ internal override bool VerifySignature( return false; } - DSAParameters dsaParameters = dsa.ExportParameters(false); - int bufSize = 2 * dsaParameters.Q!.Length; + using (dsa) + { + DSAParameters dsaParameters = dsa.ExportParameters(false); + int bufSize = 2 * dsaParameters.Q!.Length; #if NET || NETSTANDARD2_1 - byte[] rented = CryptoPool.Rent(bufSize); - Span ieee = new Span(rented, 0, bufSize); + byte[] rented = CryptoPool.Rent(bufSize); + Span ieee = new Span(rented, 0, bufSize); - try - { + try + { #else - byte[] ieee = new byte[bufSize]; + byte[] ieee = new byte[bufSize]; #endif - if (!DsaDerToIeee(signature, ieee)) - { - return false; - } + if (!DsaDerToIeee(signature, ieee)) + { + return false; + } - return dsa.VerifySignature(valueHash, ieee); + return dsa.VerifySignature(valueHash, ieee); #if NET || NETSTANDARD2_1 - } - finally - { - CryptoPool.Return(rented, bufSize); - } + } + finally + { + CryptoPool.Return(rented, bufSize); + } #endif + } } protected override bool Sign( @@ -115,71 +118,75 @@ protected override bool Sign( Debug.Assert(Helpers.IsDSASupported); signatureParameters = null; - // If there's no private key, fall back to the public key for a "no private key" exception. - DSA? dsa = key as DSA ?? - PkcsPal.Instance.GetPrivateKeyForSigning(certificate, silent) ?? - certificate.GetDSAPublicKey(); - - if (dsa == null) + using (GetSigningKey(key, certificate, silent, DSACertificateExtensions.GetDSAPublicKey, out DSA? dsa)) { - signatureAlgorithm = null; - signatureValue = null; - return false; - } + if (dsa == null) + { + signatureAlgorithm = null; + signatureValue = null; + return false; + } - string? oidValue = - hashAlgorithmOid switch + string? oidValue = + hashAlgorithmOid switch + { + Oids.Sha1 => Oids.DsaWithSha1, + Oids.Sha256 => Oids.DsaWithSha256, + Oids.Sha384 => Oids.DsaWithSha384, + Oids.Sha512 => Oids.DsaWithSha512, + _ => null + }; + + if (oidValue == null) { - Oids.Sha1 => Oids.DsaWithSha1, - Oids.Sha256 => Oids.DsaWithSha256, - Oids.Sha384 => Oids.DsaWithSha384, - Oids.Sha512 => Oids.DsaWithSha512, - _ => null - }; - - if (oidValue == null) - { - signatureAlgorithm = null; - signatureValue = null; - return false; - } + signatureAlgorithm = null; + signatureValue = null; + return false; + } - signatureAlgorithm = oidValue; + signatureAlgorithm = oidValue; #if NET || NETSTANDARD2_1 - // The Q size cannot be bigger than the KeySize. - byte[] rented = CryptoPool.Rent(dsa.KeySize / 8); - int bytesWritten = 0; + // The Q size cannot be bigger than the KeySize. + byte[] rented = CryptoPool.Rent(dsa.KeySize / 8); + int bytesWritten = 0; - try - { - if (dsa.TryCreateSignature(dataHash, rented, out bytesWritten)) + try { - var signature = new ReadOnlySpan(rented, 0, bytesWritten); - - if (key != null && !certificate.GetDSAPublicKey()!.VerifySignature(dataHash, signature)) + if (dsa.TryCreateSignature(dataHash, rented, out bytesWritten)) { - // key did not match certificate - signatureValue = null; - return false; + var signature = new ReadOnlySpan(rented, 0, bytesWritten); + + if (key != null) + { + using (DSA certKey = certificate.GetDSAPublicKey()!) + { + if (!certKey.VerifySignature(dataHash, signature)) + { + // key did not match certificate + signatureValue = null; + return false; + } + } + } + + signatureValue = DsaIeeeToDer(signature); + return true; } - - signatureValue = DsaIeeeToDer(signature); - return true; } - } - finally - { - CryptoPool.Return(rented, bytesWritten); - } + finally + { + CryptoPool.Return(rented, bytesWritten); + } - signatureValue = null; - return false; + signatureValue = null; + return false; #else - byte[] signature = dsa.CreateSignature(dataHash); - signatureValue = DsaIeeeToDer(new ReadOnlySpan(signature)); - return true; + byte[] signature = dsa.CreateSignature(dataHash); + signatureValue = DsaIeeeToDer(new ReadOnlySpan(signature)); + return true; #endif + } } } } diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.ECDsa.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.ECDsa.cs index 0541974cd8b107..4f3a76b44b2293 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.ECDsa.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.ECDsa.cs @@ -71,36 +71,39 @@ internal override bool VerifySignature( return false; } - int bufSize; - checked + using (key) { - // fieldSize = ceil(KeySizeBits / 8); - int fieldSize = (key.KeySize + 7) / 8; - bufSize = 2 * fieldSize; - } + int bufSize; + checked + { + // fieldSize = ceil(KeySizeBits / 8); + int fieldSize = (key.KeySize + 7) / 8; + bufSize = 2 * fieldSize; + } #if NET || NETSTANDARD2_1 - byte[] rented = CryptoPool.Rent(bufSize); - Span ieee = new Span(rented, 0, bufSize); + byte[] rented = CryptoPool.Rent(bufSize); + Span ieee = new Span(rented, 0, bufSize); - try - { + try + { #else - byte[] ieee = new byte[bufSize]; + byte[] ieee = new byte[bufSize]; #endif - if (!DsaDerToIeee(signature, ieee)) - { - return false; - } + if (!DsaDerToIeee(signature, ieee)) + { + return false; + } - return key.VerifyHash(valueHash, ieee); + return key.VerifyHash(valueHash, ieee); #if NET || NETSTANDARD2_1 - } - finally - { - CryptoPool.Return(rented, bufSize); - } + } + finally + { + CryptoPool.Return(rented, bufSize); + } #endif + } } protected override bool Sign( @@ -111,92 +114,96 @@ protected override bool Sign( #endif string? hashAlgorithmOid, X509Certificate2 certificate, - object? certKey, + object? privateKey, bool silent, [NotNullWhen(true)] out string? signatureAlgorithm, [NotNullWhen(true)] out byte[]? signatureValue, out byte[]? signatureParameters) { signatureParameters = null; - // If there's no private key, fall back to the public key for a "no private key" exception. - ECDsa? key = certKey as ECDsa ?? - PkcsPal.Instance.GetPrivateKeyForSigning(certificate, silent) ?? - certificate.GetECDsaPublicKey(); - - if (key == null) + using (GetSigningKey(privateKey, certificate, silent, ECDsaCertificateExtensions.GetECDsaPublicKey, out ECDsa? key)) { - signatureAlgorithm = null; - signatureValue = null; - return false; - } - - string? oidValue = - hashAlgorithmOid switch + if (key == null) { - Oids.Sha1 => Oids.ECDsaWithSha1, - Oids.Sha256 => Oids.ECDsaWithSha256, - Oids.Sha384 => Oids.ECDsaWithSha384, - Oids.Sha512 => Oids.ECDsaWithSha512, + signatureAlgorithm = null; + signatureValue = null; + return false; + } + + string? oidValue = + hashAlgorithmOid switch + { + Oids.Sha1 => Oids.ECDsaWithSha1, + Oids.Sha256 => Oids.ECDsaWithSha256, + Oids.Sha384 => Oids.ECDsaWithSha384, + Oids.Sha512 => Oids.ECDsaWithSha512, #if NET8_0_OR_GREATER - Oids.Sha3_256 => Oids.ECDsaWithSha3_256, - Oids.Sha3_384 => Oids.ECDsaWithSha3_384, - Oids.Sha3_512 => Oids.ECDsaWithSha3_512, + Oids.Sha3_256 => Oids.ECDsaWithSha3_256, + Oids.Sha3_384 => Oids.ECDsaWithSha3_384, + Oids.Sha3_512 => Oids.ECDsaWithSha3_512, #endif - _ => null, - }; + _ => null, + }; - if (oidValue == null) - { - signatureAlgorithm = null; - signatureValue = null; - return false; - } + if (oidValue == null) + { + signatureAlgorithm = null; + signatureValue = null; + return false; + } - signatureAlgorithm = oidValue; + signatureAlgorithm = oidValue; #if NET || NETSTANDARD2_1 - int bufSize; - checked - { - // fieldSize = ceil(KeySizeBits / 8); - int fieldSize = (key.KeySize + 7) / 8; - bufSize = 2 * fieldSize; - } + int bufSize; + checked + { + // fieldSize = ceil(KeySizeBits / 8); + int fieldSize = (key.KeySize + 7) / 8; + bufSize = 2 * fieldSize; + } - byte[] rented = CryptoPool.Rent(bufSize); - int bytesWritten = 0; + byte[] rented = CryptoPool.Rent(bufSize); + int bytesWritten = 0; - try - { - if (key.TrySignHash(dataHash, rented, out bytesWritten)) + try { - var signedHash = new ReadOnlySpan(rented, 0, bytesWritten); - - if (key != null && !certificate.GetECDsaPublicKey()!.VerifyHash(dataHash, signedHash)) + if (key.TrySignHash(dataHash, rented, out bytesWritten)) { - // key did not match certificate - signatureValue = null; - return false; + var signedHash = new ReadOnlySpan(rented, 0, bytesWritten); + + if (key != null) + { + using (ECDsa certKey = certificate.GetECDsaPublicKey()!) + { + if (!certKey.VerifyHash(dataHash, signedHash)) + { + // key did not match certificate + signatureValue = null; + return false; + } + } + } + + signatureValue = DsaIeeeToDer(signedHash); + return true; } - - signatureValue = DsaIeeeToDer(signedHash); - return true; } - } - finally - { - CryptoPool.Return(rented, bytesWritten); - } + finally + { + CryptoPool.Return(rented, bytesWritten); + } #endif - signatureValue = DsaIeeeToDer(key.SignHash( + signatureValue = DsaIeeeToDer(key.SignHash( #if NET || NETSTANDARD2_1 - dataHash.ToArray() + dataHash.ToArray() #else - dataHash + dataHash #endif - )); - return true; + )); + return true; + } } } } diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.RSA.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.RSA.cs index 9d4d237172e8a0..44c20006bfd6f7 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.RSA.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.RSA.cs @@ -78,15 +78,18 @@ internal override bool VerifySignature( return false; } - return publicKey.VerifyHash( - valueHash, + using (publicKey) + { + return publicKey.VerifyHash( + valueHash, #if NET || NETSTANDARD2_1 - signature.Span, + signature.Span, #else - signature, + signature, #endif - digestAlgorithmName, - padding); + digestAlgorithmName, + padding); + } } protected abstract RSASignaturePadding GetSignaturePadding( @@ -108,60 +111,68 @@ private protected static bool SignCore( RSASignaturePadding signaturePadding, [NotNullWhen(true)] out byte[]? signatureValue) { - RSA certPublicKey = certificate.GetRSAPublicKey()!; - - // If there's no private key, fall back to the public key for a "no private key" exception. - RSA? privateKey = key as RSA ?? - PkcsPal.Instance.GetPrivateKeyForSigning(certificate, silent) ?? - certPublicKey; - - if (privateKey is null) + using (GetSigningKey(key, certificate, silent, RSACertificateExtensions.GetRSAPublicKey, out RSA? privateKey)) { - signatureValue = null; - return false; - } + if (privateKey is null) + { + signatureValue = null; + return false; + } #if NET || NETSTANDARD2_1 - byte[] signature = new byte[privateKey.KeySize / 8]; + byte[] signature = new byte[privateKey.KeySize / 8]; - bool signed = privateKey.TrySignHash( - dataHash, - signature, - hashAlgorithmName, - signaturePadding, - out int bytesWritten); - - if (signed && signature.Length == bytesWritten) - { - signatureValue = signature; + bool signed = privateKey.TrySignHash( + dataHash, + signature, + hashAlgorithmName, + signaturePadding, + out int bytesWritten); - if (key is not null && !certPublicKey.VerifyHash(dataHash, signatureValue, hashAlgorithmName, signaturePadding)) + if (signed && signature.Length == bytesWritten) { - // key did not match certificate - signatureValue = null; - return false; + signatureValue = signature; + + if (key is not null) + { + using (RSA certKey = certificate.GetRSAPublicKey()!) + { + if (!certKey.VerifyHash(dataHash, signatureValue, hashAlgorithmName, signaturePadding)) + { + // key did not match certificate + signatureValue = null; + return false; + } + } + } + + return true; } - - return true; - } #endif - signatureValue = privateKey.SignHash( + signatureValue = privateKey.SignHash( #if NET || NETSTANDARD2_1 - dataHash.ToArray(), + dataHash.ToArray(), #else - dataHash, + dataHash, #endif - hashAlgorithmName, - signaturePadding); + hashAlgorithmName, + signaturePadding); - if (key is not null && !certPublicKey.VerifyHash(dataHash, signatureValue, hashAlgorithmName, signaturePadding)) - { - // key did not match certificate - signatureValue = null; - return false; - } + if (key is not null) + { + using (RSA certKey = certificate.GetRSAPublicKey()!) + { + if (!certKey.VerifyHash(dataHash, signatureValue, hashAlgorithmName, signaturePadding)) + { + // key did not match certificate + signatureValue = null; + return false; + } + } + } - return true; + return true; + } } } diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.SlhDsa.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.SlhDsa.cs index 940b565030ae08..8001c7da6cc38f 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.SlhDsa.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.SlhDsa.cs @@ -100,26 +100,16 @@ protected override bool Sign( // not enforce them here. It is up to the caller to choose an appropriate hash. signatureParameters = null; + signatureAlgorithm = _signatureAlgorithm; - SlhDsa? signingKey = key as SlhDsa; - IDisposable? signingKeyResources = null; - - if (signingKey is null) + using (GetSigningKey(key, certificate, silent, static cert => cert.GetSlhDsaPublicKey(), out SlhDsa? signingKey)) { - // If there's no private key, fall back to the public key for a "no private key" exception. - signingKeyResources = signingKey = - PkcsPal.Instance.GetPrivateKeyForSigning(certificate, silent) ?? certificate.GetSlhDsaPublicKey(); - if (signingKey is null) { - signatureAlgorithm = null; signatureValue = null; return false; } - } - using (signingKeyResources) - { // Don't pool because we will likely return this buffer to the caller. byte[] signature = new byte[signingKey.Algorithm.SignatureSizeInBytes]; signingKey.SignData(dataHash, signature); @@ -130,7 +120,6 @@ protected override bool Sign( { if (!certKey.VerifyData(dataHash, signature)) { - signatureAlgorithm = null; signatureValue = null; return false; } @@ -138,7 +127,6 @@ protected override bool Sign( } signatureValue = signature; - signatureAlgorithm = _signatureAlgorithm; return true; } } diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.cs index ac08a6c975df92..f4546932eae69f 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.cs @@ -7,6 +7,7 @@ using System.Formats.Asn1; using System.Numerics; using System.Security.Cryptography.X509Certificates; +using Internal.Cryptography; namespace System.Security.Cryptography.Pkcs { @@ -142,6 +143,27 @@ internal bool Sign( return signed; } + private static IDisposable? GetSigningKey( + object? privateKey, + X509Certificate2 certificate, + bool silent, + Func getCertPublicKey, + out T? signingKey) + where T : class, IDisposable + { + signingKey = privateKey as T; + IDisposable? signingKeyResources = null; + + if (signingKey is null) + { + // If there's no private key, fall back to the public key for a "no private key" exception. + signingKeyResources = signingKey = + PkcsPal.Instance.GetPrivateKeyForSigning(certificate, silent) ?? getCertPublicKey(certificate); + } + + return signingKeyResources; + } + private static bool DsaDerToIeee( ReadOnlyMemory derSignature, Span ieeeSignature)