summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2023-04-11 18:58:02 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2023-04-11 18:58:02 +0700
commit7b744590df675b09e7773e2b2af3d2b1f8c528d5 (patch)
tree2884492600e4f286ffe22d11014aefd6904aecff
parentFix static method references (diff)
downloadBouncyCastle.NET-ed25519-7b744590df675b09e7773e2b2af3d2b1f8c528d5.tar.xz
X509: Refactor stream calculator usage
-rw-r--r--crypto/src/cmp/ProtectedPkiMessage.cs8
-rw-r--r--crypto/src/cmp/ProtectedPkiMessageBuilder.cs18
-rw-r--r--crypto/src/crmf/CertificateRequestMessage.cs34
-rw-r--r--crypto/src/crmf/ProofOfPossessionSigningKeyBuilder.cs51
-rw-r--r--crypto/src/ocsp/BasicOCSPRespGenerator.cs24
-rw-r--r--crypto/src/pkcs/Pkcs10CertificationRequest.cs25
-rw-r--r--crypto/src/x509/X509Utilities.cs59
-rw-r--r--crypto/src/x509/X509V1CertificateGenerator.cs18
-rw-r--r--crypto/src/x509/X509V3CertificateGenerator.cs57
9 files changed, 119 insertions, 175 deletions
diff --git a/crypto/src/cmp/ProtectedPkiMessage.cs b/crypto/src/cmp/ProtectedPkiMessage.cs
index fdcdeb90d..79394094d 100644
--- a/crypto/src/cmp/ProtectedPkiMessage.cs
+++ b/crypto/src/cmp/ProtectedPkiMessage.cs
@@ -139,12 +139,8 @@ namespace Org.BouncyCastle.Cmp
 
         private TResult Process<TResult>(IStreamCalculator<TResult> streamCalculator)
         {
-            using (var s = streamCalculator.Stream)
-            {
-                new DerSequence(m_pkiMessage.Header, m_pkiMessage.Body).EncodeTo(s, Asn1Encodable.Der);
-            }
-
-            return streamCalculator.GetResult();
+            var asn1Encodable = new DerSequence(m_pkiMessage.Header, m_pkiMessage.Body);
+            return X509Utilities.CalculateResult(streamCalculator, asn1Encodable);
         }
     }
 }
diff --git a/crypto/src/cmp/ProtectedPkiMessageBuilder.cs b/crypto/src/cmp/ProtectedPkiMessageBuilder.cs
index 508b00ff5..a3070ee56 100644
--- a/crypto/src/cmp/ProtectedPkiMessageBuilder.cs
+++ b/crypto/src/cmp/ProtectedPkiMessageBuilder.cs
@@ -97,14 +97,12 @@ namespace Org.BouncyCastle.Cmp
             if (null == body)
                 throw new InvalidOperationException("body must be set before building");
 
-            var calculator = signatureFactory.CreateCalculator();
-
             if (!(signatureFactory.AlgorithmDetails is AlgorithmIdentifier algorithmDetails))
                 throw new ArgumentException("AlgorithmDetails is not AlgorithmIdentifier");
 
             FinalizeHeader(algorithmDetails);
             PkiHeader header = m_hdrBuilder.Build();
-            DerBitString protection = new DerBitString(CalculateSignature(calculator, header, body));
+            DerBitString protection = X509Utilities.GenerateSignature(signatureFactory, new DerSequence(header, body));
             return FinalizeMessage(header, protection);
         }
 
@@ -113,14 +111,12 @@ namespace Org.BouncyCastle.Cmp
             if (null == body)
                 throw new InvalidOperationException("body must be set before building");
 
-            var calculator = macFactory.CreateCalculator();
-
             if (!(macFactory.AlgorithmDetails is AlgorithmIdentifier algorithmDetails))
                 throw new ArgumentException("AlgorithmDetails is not AlgorithmIdentifier");
 
             FinalizeHeader(algorithmDetails);
             PkiHeader header = m_hdrBuilder.Build();
-            DerBitString protection = new DerBitString(CalculateSignature(calculator, header, body));
+            DerBitString protection = X509Utilities.GenerateMac(macFactory, new DerSequence(header, body));
             return FinalizeMessage(header, protection);
         }
 
@@ -146,15 +142,5 @@ namespace Org.BouncyCastle.Cmp
 
             return new ProtectedPkiMessage(new PkiMessage(header, body, protection, cmpCertificates));
         }
-
-        private byte[] CalculateSignature(IStreamCalculator<IBlockResult> signer, PkiHeader header, PkiBody body)
-        {
-            using (var s = signer.Stream)
-            {
-                new DerSequence(header, body).EncodeTo(s);
-            }
-
-            return signer.GetResult().Collect();
-        }
     }
 }
diff --git a/crypto/src/crmf/CertificateRequestMessage.cs b/crypto/src/crmf/CertificateRequestMessage.cs
index 0a246aaa4..36149c791 100644
--- a/crypto/src/crmf/CertificateRequestMessage.cs
+++ b/crypto/src/crmf/CertificateRequestMessage.cs
@@ -178,43 +178,25 @@ namespace Org.BouncyCastle.Crmf
             {
                 PopoSigningKey popoSign = PopoSigningKey.GetInstance(pop.Object);
                 if (popoSign.PoposkInput != null && popoSign.PoposkInput.PublicKeyMac != null)
-                {
                     throw new InvalidOperationException("verification requires password check");
-                }
-                return verifySignature(verifierProvider, popoSign);
+
+                return VerifySignature(verifierProvider, popoSign);
             }
 
             throw new InvalidOperationException("not Signing Key type of proof of possession");
         }
 
-        private bool verifySignature(IVerifierFactoryProvider verifierFactoryProvider, PopoSigningKey signKey)
+        private bool VerifySignature(IVerifierFactoryProvider verifierFactoryProvider, PopoSigningKey signKey)
         {
-            IVerifierFactory verifer;
-            IStreamCalculator<IVerifier> calculator;
-            try
-            {
-                verifer = verifierFactoryProvider.CreateVerifierFactory(signKey.AlgorithmIdentifier);
-                calculator = verifer.CreateCalculator();
-            }
-            catch (Exception ex)
-            {
-                throw new CrmfException("unable to create verifier: " + ex.Message, ex);
-            }
+            var verifierFactory = verifierFactoryProvider.CreateVerifierFactory(signKey.AlgorithmIdentifier);
 
-            if (signKey.PoposkInput != null)
+            Asn1Encodable asn1Encodable = signKey.PoposkInput;
+            if (asn1Encodable == null)
             {
-                byte[] b = signKey.GetDerEncoded();
-                calculator.Stream.Write(b, 0, b.Length);
+                asn1Encodable = certReqMsg.CertReq;
             }
-            else
-            {
-                byte[] b = certReqMsg.CertReq.GetDerEncoded();
-                calculator.Stream.Write(b, 0, b.Length);
-            }
-
-            IVerifier result = calculator.GetResult();
 
-            return result.IsVerified(signKey.Signature.GetBytes());
+            return X509.X509Utilities.VerifySignature(verifierFactory, asn1Encodable, signKey.Signature);
         }
 
         /// <summary>
diff --git a/crypto/src/crmf/ProofOfPossessionSigningKeyBuilder.cs b/crypto/src/crmf/ProofOfPossessionSigningKeyBuilder.cs
index 8d2ea0bac..02af74924 100644
--- a/crypto/src/crmf/ProofOfPossessionSigningKeyBuilder.cs
+++ b/crypto/src/crmf/ProofOfPossessionSigningKeyBuilder.cs
@@ -1,12 +1,11 @@
 using System;
 using System.IO;
+using System.Net.Security;
 
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Crmf;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Operators;
-using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Crmf
 {
@@ -55,43 +54,33 @@ namespace Org.BouncyCastle.Crmf
                 throw new InvalidOperationException("name and publicKeyMAC cannot both be set.");
 
             PopoSigningKeyInput popo;
+            Asn1Encodable asn1Encodable;
 
-            IStreamCalculator<IBlockResult> calc = signer.CreateCalculator();
-            using (Stream sigStream = calc.Stream)
+            if (_certRequest != null)
             {
-                if (_certRequest != null)
-                {
-                    popo = null;
-                    _certRequest.EncodeTo(sigStream, Asn1Encodable.Der);
-                }
-                else if (_name != null)
-                {
-                    popo = new PopoSigningKeyInput(_name, _pubKeyInfo);
-                    popo.EncodeTo(sigStream, Asn1Encodable.Der);
-                }
-                else
-                {
-                    popo = new PopoSigningKeyInput(_publicKeyMAC, _pubKeyInfo);
-                    popo.EncodeTo(sigStream, Asn1Encodable.Der);
-                }
+                popo = null;
+                asn1Encodable = _certRequest;
+            }
+            else if (_name != null)
+            {
+                popo = new PopoSigningKeyInput(_name, _pubKeyInfo);
+                asn1Encodable = popo;
+            }
+            else
+            {
+                popo = new PopoSigningKeyInput(_publicKeyMAC, _pubKeyInfo);
+                asn1Encodable = popo;
             }
 
-            var signature = calc.GetResult().Collect();
+            var signature = X509.X509Utilities.GenerateSignature(signer, asn1Encodable);
 
-            return new PopoSigningKey(popo, (AlgorithmIdentifier)signer.AlgorithmDetails, new DerBitString(signature));
+            return new PopoSigningKey(popo, (AlgorithmIdentifier)signer.AlgorithmDetails, signature);
         }
 
-        private ProofOfPossessionSigningKeyBuilder ImplSetPublicKeyMac(IMacFactory fact)
+        private ProofOfPossessionSigningKeyBuilder ImplSetPublicKeyMac(IMacFactory macFactory)
         {
-            IStreamCalculator<IBlockResult> calc = fact.CreateCalculator();
-            using (var stream = calc.Stream)
-            {
-                _pubKeyInfo.EncodeTo(stream, Asn1Encodable.Der);
-            }
-
-            var mac = calc.GetResult().Collect();
-
-            this._publicKeyMAC = new PKMacValue((AlgorithmIdentifier)fact.AlgorithmDetails, new DerBitString(mac));
+            var macValue = X509.X509Utilities.GenerateMac(macFactory, _pubKeyInfo);
+            this._publicKeyMAC = new PKMacValue((AlgorithmIdentifier)macFactory.AlgorithmDetails, macValue);
             return this;
         }
     }
diff --git a/crypto/src/ocsp/BasicOCSPRespGenerator.cs b/crypto/src/ocsp/BasicOCSPRespGenerator.cs
index ff7ae33d3..3d89dfd38 100644
--- a/crypto/src/ocsp/BasicOCSPRespGenerator.cs
+++ b/crypto/src/ocsp/BasicOCSPRespGenerator.cs
@@ -164,12 +164,10 @@ namespace Org.BouncyCastle.Ocsp
 			this.responseExtensions = responseExtensions;
 		}
 
-		private BasicOcspResp GenerateResponse(
-			ISignatureFactory    signatureCalculator,
-			X509Certificate[]		chain,
-			DateTime				producedAt)
+		private BasicOcspResp GenerateResponse(ISignatureFactory signatureFactory, X509Certificate[] chain,
+			DateTime producedAt)
 		{
-            AlgorithmIdentifier signingAlgID = (AlgorithmIdentifier)signatureCalculator.AlgorithmDetails;
+            AlgorithmIdentifier signingAlgID = (AlgorithmIdentifier)signatureFactory.AlgorithmDetails;
             DerObjectIdentifier signingAlgorithm = signingAlgID.Algorithm;
 
 			Asn1EncodableVector responses = new Asn1EncodableVector();
@@ -186,26 +184,20 @@ namespace Org.BouncyCastle.Ocsp
 				}
 			}
 
-			ResponseData tbsResp = new ResponseData(responderID.ToAsn1Object(), new Asn1GeneralizedTime(producedAt),
+			var responseData = new ResponseData(responderID.ToAsn1Object(), new Asn1GeneralizedTime(producedAt),
 				new DerSequence(responses), responseExtensions);
-			DerBitString bitSig;
 
+			DerBitString bitSig;
 			try
 			{
-                IStreamCalculator<IBlockResult> streamCalculator = signatureCalculator.CreateCalculator();
-				using (Stream sigStream = streamCalculator.Stream)
-				{
-					tbsResp.EncodeTo(sigStream, Asn1Encodable.Der);
-				}
-
-				bitSig = new DerBitString(streamCalculator.GetResult().Collect());
+				bitSig = X509.X509Utilities.GenerateSignature(signatureFactory, responseData);
 			}
 			catch (Exception e)
 			{
 				throw new OcspException("exception processing TBSRequest: " + e, e);
 			}
 
-			AlgorithmIdentifier sigAlgId = OcspUtilities.GetSigAlgID(signingAlgorithm);
+			AlgorithmIdentifier sigAlgID = OcspUtilities.GetSigAlgID(signingAlgorithm);
 
 			DerSequence chainSeq = null;
 			if (chain != null && chain.Length > 0)
@@ -230,7 +222,7 @@ namespace Org.BouncyCastle.Ocsp
 				chainSeq = new DerSequence(v);
 			}
 
-			return new BasicOcspResp(new BasicOcspResponse(tbsResp, sigAlgId, bitSig, chainSeq));
+			return new BasicOcspResp(new BasicOcspResponse(responseData, sigAlgID, bitSig, chainSeq));
 		}
 
 		public BasicOcspResp Generate(
diff --git a/crypto/src/pkcs/Pkcs10CertificationRequest.cs b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
index dbaaa34f6..c3e21f8ed 100644
--- a/crypto/src/pkcs/Pkcs10CertificationRequest.cs
+++ b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
@@ -269,10 +269,7 @@ namespace Org.BouncyCastle.Pkcs
             Init(signatureFactory, subject, publicKey, attributes);
         }
 
-        private void Init(
-            ISignatureFactory signatureFactory,
-            X509Name subject,
-            AsymmetricKeyParameter publicKey,
+        private void Init(ISignatureFactory signatureFactory, X509Name subject, AsymmetricKeyParameter publicKey,
             Asn1Set attributes)
         {
             this.sigAlgId = (AlgorithmIdentifier)signatureFactory.AlgorithmDetails;
@@ -281,14 +278,7 @@ namespace Org.BouncyCastle.Pkcs
 
             this.reqInfo = new CertificationRequestInfo(subject, pubInfo, attributes);
 
-            IStreamCalculator<IBlockResult> streamCalculator = signatureFactory.CreateCalculator();
-            using (Stream sigStream = streamCalculator.Stream)
-            {
-                reqInfo.EncodeTo(sigStream, Der);
-            }
-
-            // Generate Signature.
-            sigBits = new DerBitString(streamCalculator.GetResult().Collect());
+            sigBits = X509.X509Utilities.GenerateSignature(signatureFactory, reqInfo);
         }
 
         //        internal Pkcs10CertificationRequest(
@@ -337,18 +327,11 @@ namespace Org.BouncyCastle.Pkcs
             return Verify(verifierProvider.CreateVerifierFactory(sigAlgId));
         }
 
-        public bool Verify(
-            IVerifierFactory verifier)
+        public bool Verify(IVerifierFactory verifier)
         {
             try
             {
-                IStreamCalculator<IVerifier> streamCalculator = verifier.CreateCalculator();
-                using (var stream = streamCalculator.Stream)
-                {
-                    reqInfo.EncodeTo(stream, Asn1Encodable.Der);
-                }
-
-                return streamCalculator.GetResult().IsVerified(sigBits.GetOctets());
+                return X509.X509Utilities.VerifySignature(verifier, reqInfo, sigBits);
             }
             catch (Exception e)
             {
diff --git a/crypto/src/x509/X509Utilities.cs b/crypto/src/x509/X509Utilities.cs
index bb9b7155f..3ab6b926c 100644
--- a/crypto/src/x509/X509Utilities.cs
+++ b/crypto/src/x509/X509Utilities.cs
@@ -14,7 +14,7 @@ using Org.BouncyCastle.Utilities.Collections;
 
 namespace Org.BouncyCastle.X509
 {
-	internal class X509Utilities
+    internal static class X509Utilities
 	{
         private static readonly Dictionary<string, DerObjectIdentifier> m_algorithms =
 			new Dictionary<string, DerObjectIdentifier>(StringComparer.OrdinalIgnoreCase);
@@ -126,7 +126,17 @@ namespace Org.BouncyCastle.X509
 			m_exParams.Add("SHA512WITHRSAANDMGF1", CreatePssParams(sha512AlgId, 64));
 		}
 
-		private static RsassaPssParameters CreatePssParams(
+        internal static TResult CalculateResult<TResult>(IStreamCalculator<TResult> streamCalculator,
+            Asn1Encodable asn1Encodable)
+        {
+            using (var stream = streamCalculator.Stream)
+            {
+                asn1Encodable.EncodeTo(stream, Asn1Encodable.Der);
+            }
+            return streamCalculator.GetResult();
+        }
+
+        private static RsassaPssParameters CreatePssParams(
 			AlgorithmIdentifier	hashAlgId,
 			int					saltSize)
 		{
@@ -137,7 +147,23 @@ namespace Org.BouncyCastle.X509
 				new DerInteger(1));
 		}
 
-		internal static DerObjectIdentifier GetAlgorithmOid(string algorithmName)
+        internal static DerBitString CollectDerBitString(IBlockResult result)
+        {
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            var maxResultLength = result.GetMaxResultLength();
+            Span<byte> data = maxResultLength <= 512
+                ? stackalloc byte[maxResultLength]
+                : new byte[maxResultLength];
+            int resultLength = result.Collect(data);
+            data = data[..resultLength];
+#else
+            var data = result.Collect();
+#endif
+
+            return new DerBitString(data);
+        }
+
+        internal static DerObjectIdentifier GetAlgorithmOid(string algorithmName)
 		{
 			if (m_algorithms.TryGetValue(algorithmName, out var oid))
 				return oid;
@@ -161,16 +187,29 @@ namespace Org.BouncyCastle.X509
 			return CollectionUtilities.Proxy(m_algorithms.Keys);
 		}
 
+        internal static DerBitString GenerateBitString(IStreamCalculator<IBlockResult> streamCalculator,
+			Asn1Encodable asn1Encodable)
+        {
+            var result = CalculateResult(streamCalculator, asn1Encodable);
+            return CollectDerBitString(result);
+        }
+
+        internal static DerBitString GenerateMac(IMacFactory macFactory, Asn1Encodable asn1Encodable)
+        {
+			return GenerateBitString(macFactory.CreateCalculator(), asn1Encodable);
+        }
+
         internal static DerBitString GenerateSignature(ISignatureFactory signatureFactory, Asn1Encodable asn1Encodable)
         {
-			var result = CalculateResult(signatureFactory.CreateCalculator(), asn1Encodable);
-            return new DerBitString(result.Collect());
+            return GenerateBitString(signatureFactory.CreateCalculator(), asn1Encodable);
         }
 
         internal static bool VerifySignature(IVerifierFactory verifierFactory, Asn1Encodable asn1Encodable,
 			DerBitString signature)
         {
             var result = CalculateResult(verifierFactory.CreateCalculator(), asn1Encodable);
+
+			// TODO[api] Use GetOctetsSpan() once IsVerified(ReadOnlySpan<byte>) is available
 			return result.IsVerified(signature.GetOctets());
         }
 
@@ -190,15 +229,5 @@ namespace Org.BouncyCastle.X509
 
             return new DerTaggedObject(true, tagNo, new DerSequence(extV));
         }
-
-		private static TResult CalculateResult<TResult>(IStreamCalculator<TResult> streamCalculator,
-			Asn1Encodable asn1Encodable)
-		{
-            using (var stream = streamCalculator.Stream)
-            {
-                asn1Encodable.EncodeTo(stream, Asn1Encodable.Der);
-            }
-            return streamCalculator.GetResult();
-        }
     }
 }
diff --git a/crypto/src/x509/X509V1CertificateGenerator.cs b/crypto/src/x509/X509V1CertificateGenerator.cs
index 93ec03ea3..2fc53ec7c 100644
--- a/crypto/src/x509/X509V1CertificateGenerator.cs
+++ b/crypto/src/x509/X509V1CertificateGenerator.cs
@@ -122,26 +122,16 @@ namespace Org.BouncyCastle.X509
 
 			tbsGen.SetSignature(sigAlgID);
 
-			TbsCertificateStructure tbsCert = tbsGen.GenerateTbsCertificate();
+			var tbsCertificate = tbsGen.GenerateTbsCertificate();
 
-			IStreamCalculator<IBlockResult> streamCalculator = signatureFactory.CreateCalculator();
-			using (var sigStream = streamCalculator.Stream)
-			{
-				tbsCert.EncodeTo(sigStream, Asn1Encodable.Der);
-			}
-
-			var signature = streamCalculator.GetResult().Collect();
+            var signature = X509Utilities.GenerateSignature(signatureFactory, tbsCertificate);
 
-			return new X509Certificate(
-				new X509CertificateStructure(tbsCert, sigAlgID, new DerBitString(signature)));
+            return new X509Certificate(new X509CertificateStructure(tbsCertificate, sigAlgID, signature));
 		}
 
 		/// <summary>
 		/// Allows enumeration of the signature names supported by the generator.
 		/// </summary>
-		public IEnumerable<string> SignatureAlgNames
-		{
-			get { return X509Utilities.GetAlgNames(); }
-		}
+		public IEnumerable<string> SignatureAlgNames => X509Utilities.GetAlgNames();
 	}
 }
diff --git a/crypto/src/x509/X509V3CertificateGenerator.cs b/crypto/src/x509/X509V3CertificateGenerator.cs
index 65e3c9177..1dd1776be 100644
--- a/crypto/src/x509/X509V3CertificateGenerator.cs
+++ b/crypto/src/x509/X509V3CertificateGenerator.cs
@@ -143,7 +143,7 @@ namespace Org.BouncyCastle.X509
 		public void SetSubjectUniqueID(
 			bool[] uniqueID)
 		{
-			tbsGen.SetSubjectUniqueID(booleanToBitString(uniqueID));
+			tbsGen.SetSubjectUniqueID(BooleanToBitString(uniqueID));
 		}
 
 		/// <summary>
@@ -153,30 +153,7 @@ namespace Org.BouncyCastle.X509
 		public void SetIssuerUniqueID(
 			bool[] uniqueID)
 		{
-			tbsGen.SetIssuerUniqueID(booleanToBitString(uniqueID));
-		}
-
-		private DerBitString booleanToBitString(
-			bool[] id)
-		{
-			byte[] bytes = new byte[(id.Length + 7) / 8];
-
-			for (int i = 0; i != id.Length; i++)
-			{
-				if (id[i])
-				{
-					bytes[i / 8] |= (byte)(1 << ((7 - (i % 8))));
-				}
-			}
-
-			int pad = id.Length % 8;
-
-			if (pad == 0)
-			{
-				return new DerBitString(bytes);
-			}
-
-			return new DerBitString(bytes, 8 - pad);
+			tbsGen.SetIssuerUniqueID(BooleanToBitString(uniqueID));
 		}
 
 		/// <summary>
@@ -327,9 +304,29 @@ namespace Org.BouncyCastle.X509
 		/// <summary>
 		/// Allows enumeration of the signature names supported by the generator.
 		/// </summary>
-		public IEnumerable<string> SignatureAlgNames
-		{
-			get { return X509Utilities.GetAlgNames(); }
-		}
-	}
+		public IEnumerable<string> SignatureAlgNames => X509Utilities.GetAlgNames();
+
+        private static DerBitString BooleanToBitString(bool[] id)
+        {
+            int byteLength = (id.Length + 7) / 8;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            Span<byte> bytes = byteLength <= 512
+                ? stackalloc byte[byteLength]
+                : new byte[byteLength];
+#else
+			byte[] bytes = new byte[byteLength];
+#endif
+
+            for (int i = 0; i != id.Length; i++)
+            {
+                if (id[i])
+                {
+                    bytes[i >> 3] |= (byte)(0x80 >> (i & 7));
+                }
+            }
+
+            return new DerBitString(bytes, (8 - id.Length) & 7);
+        }
+    }
 }