summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2023-07-26 17:58:23 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2023-07-26 17:58:23 +0700
commit21bfdd9eb9683fcad861a5b528729d6afcbe6863 (patch)
tree5830f6f898b5eb7e3e096f488b192e3204ab1214
parentUpdate XML doc (diff)
downloadBouncyCastle.NET-ed25519-21bfdd9eb9683fcad861a5b528729d6afcbe6863.tar.xz
CMP updates from bc-java
-rw-r--r--crypto/src/asn1/cmp/CertStatus.cs9
-rw-r--r--crypto/src/cmp/CertificateConfirmationContentBuilder.cs38
-rw-r--r--crypto/src/cmp/CertificateStatus.cs18
-rw-r--r--crypto/src/cmp/ProtectedPkiMessage.cs25
-rw-r--r--crypto/src/cmp/ProtectedPkiMessageBuilder.cs65
-rw-r--r--crypto/src/cmp/RevocationDetails.cs1
-rw-r--r--crypto/src/x509/X509Certificate.cs4
-rw-r--r--crypto/src/x509/X509V3CertificateGenerator.cs23
8 files changed, 127 insertions, 56 deletions
diff --git a/crypto/src/asn1/cmp/CertStatus.cs b/crypto/src/asn1/cmp/CertStatus.cs
index b64a0fe84..29db607d7 100644
--- a/crypto/src/asn1/cmp/CertStatus.cs
+++ b/crypto/src/asn1/cmp/CertStatus.cs
@@ -52,10 +52,15 @@ namespace Org.BouncyCastle.Asn1.Cmp
 			}
 		}
 
-		public CertStatus(byte[] certHash, BigInteger certReqID)
+        public CertStatus(byte[] certHash, BigInteger certReqID)
+            : this(certHash, new DerInteger(certReqID))
+        {
+        }
+
+        public CertStatus(byte[] certHash, DerInteger certReqID)
 		{
 			m_certHash = new DerOctetString(certHash);
-			m_certReqID = new DerInteger(certReqID);
+			m_certReqID = certReqID;
             m_statusInfo = null;
             m_hashAlg = null;
         }
diff --git a/crypto/src/cmp/CertificateConfirmationContentBuilder.cs b/crypto/src/cmp/CertificateConfirmationContentBuilder.cs
index 32fef908b..b46c1ab0e 100644
--- a/crypto/src/cmp/CertificateConfirmationContentBuilder.cs
+++ b/crypto/src/cmp/CertificateConfirmationContentBuilder.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
 
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Cmp;
+using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Math;
 using Org.BouncyCastle.Operators.Utilities;
 using Org.BouncyCastle.Security;
@@ -13,8 +14,9 @@ namespace Org.BouncyCastle.Cmp
     public sealed class CertificateConfirmationContentBuilder
     {
         private readonly IDigestAlgorithmFinder m_digestAlgorithmFinder;
-        private readonly List<X509Certificate> m_acceptedCerts = new List<X509Certificate>();
-        private readonly List<BigInteger> m_acceptedReqIDs = new List<BigInteger>();
+        private readonly List<CmpCertificate> m_acceptedCerts = new List<CmpCertificate>();
+        private readonly List<AlgorithmIdentifier> m_acceptedSignatureAlgorithms = new List<AlgorithmIdentifier>();
+        private readonly List<DerInteger> m_acceptedReqIDs = new List<DerInteger>();
 
         public CertificateConfirmationContentBuilder()
             : this(DefaultDigestAlgorithmFinder.Instance)
@@ -32,11 +34,26 @@ namespace Org.BouncyCastle.Cmp
             m_digestAlgorithmFinder = digestAlgorithmFinder;
         }
 
+        // TODO[api] Rename parameters to 'cert', 'certReqID'
         public CertificateConfirmationContentBuilder AddAcceptedCertificate(X509Certificate certHolder,
             BigInteger certReqId)
         {
-            m_acceptedCerts.Add(certHolder);
-            m_acceptedReqIDs.Add(certReqId);
+            return AddAcceptedCertificate(certHolder, new DerInteger(certReqId));
+        }
+
+        public CertificateConfirmationContentBuilder AddAcceptedCertificate(X509Certificate cert, DerInteger certReqID)
+        {
+            return AddAcceptedCertificate(
+                new CmpCertificate(cert.CertificateStructure), cert.SignatureAlgorithm, certReqID);
+        }
+
+        public CertificateConfirmationContentBuilder AddAcceptedCertificate(CmpCertificate cmpCertificate,
+            AlgorithmIdentifier signatureAlgorithm, DerInteger certReqID)
+        {
+            m_acceptedCerts.Add(cmpCertificate);
+            m_acceptedSignatureAlgorithms.Add(signatureAlgorithm);
+            m_acceptedReqIDs.Add(certReqID);
+
             return this;
         }
 
@@ -45,16 +62,15 @@ namespace Org.BouncyCastle.Cmp
             Asn1EncodableVector v = new Asn1EncodableVector(m_acceptedCerts.Count);
             for (int i = 0; i != m_acceptedCerts.Count; i++)
             {
-                X509Certificate cert = m_acceptedCerts[i];
-                BigInteger reqID = m_acceptedReqIDs[i];
-
-                var sigAlgID = DefaultSignatureAlgorithmFinder.Instance.Find(cert.SigAlgName)
-                    ?? throw new CmpException("cannot find algorithm identifier for signature name");
+                CmpCertificate cmpCertificate = m_acceptedCerts[i];
+                AlgorithmIdentifier signatureAlgorithm = m_acceptedSignatureAlgorithms[i];
+                DerInteger reqID = m_acceptedReqIDs[i];
 
-                var digAlgID = m_digestAlgorithmFinder.Find(sigAlgID)
+                var digestAlgorithm = m_digestAlgorithmFinder.Find(signatureAlgorithm)
                     ?? throw new CmpException("cannot find algorithm for digest from signature");
 
-                byte[] digest = DigestUtilities.CalculateDigest(digAlgID.Algorithm, cert.GetEncoded());
+                byte[] digest = DigestUtilities.CalculateDigest(digestAlgorithm.Algorithm,
+                    cmpCertificate.GetEncoded(Asn1Encodable.Der));
 
                 v.Add(new CertStatus(digest, reqID));
             }
diff --git a/crypto/src/cmp/CertificateStatus.cs b/crypto/src/cmp/CertificateStatus.cs
index 55292329a..4df7e0cf5 100644
--- a/crypto/src/cmp/CertificateStatus.cs
+++ b/crypto/src/cmp/CertificateStatus.cs
@@ -1,5 +1,6 @@
 using System;
 
+using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.Cmp;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Math;
@@ -32,17 +33,16 @@ namespace Org.BouncyCastle.Cmp
 
         public virtual BigInteger CertRequestID => m_certStatus.CertReqID.Value;
 
-        public virtual bool IsVerified(X509Certificate cert)
-        {
-            var signatureName = cert.SigAlgName;
-
-            var signatureAlgorithm = DefaultSignatureAlgorithmFinder.Instance.Find(signatureName)
-                ?? throw new CmpException("cannot find algorithm identifier for signature name");
+        public virtual bool IsVerified(X509Certificate cert) =>
+            IsVerified(new CmpCertificate(cert.CertificateStructure), cert.SignatureAlgorithm);
 
-            var digestAlgorithm = m_digestAlgorithmFinder.Find(signatureAlgorithm)
-                ?? throw new CmpException("cannot find algorithm for digest from signature " + signatureName);
+        public virtual bool IsVerified(CmpCertificate cmpCertificate, AlgorithmIdentifier signatureAlgorithm)
+        {
+            AlgorithmIdentifier digestAlgorithm = m_digestAlgorithmFinder.Find(signatureAlgorithm)
+                ?? throw new CmpException("cannot find algorithm for digest from signature");
 
-            byte[] digest = DigestUtilities.CalculateDigest(digestAlgorithm.Algorithm, cert.GetEncoded());
+            byte[] digest = DigestUtilities.CalculateDigest(digestAlgorithm.Algorithm,
+                cmpCertificate.GetEncoded(Asn1Encodable.Der));
 
             return Arrays.FixedTimeEquals(m_certStatus.CertHash.GetOctets(), digest);
         }
diff --git a/crypto/src/cmp/ProtectedPkiMessage.cs b/crypto/src/cmp/ProtectedPkiMessage.cs
index 79394094d..03dd2327e 100644
--- a/crypto/src/cmp/ProtectedPkiMessage.cs
+++ b/crypto/src/cmp/ProtectedPkiMessage.cs
@@ -27,7 +27,7 @@ namespace Org.BouncyCastle.Cmp
             if (!pkiMessage.HasProtection)
                 throw new ArgumentException("GeneralPkiMessage not protected");
 
-            this.m_pkiMessage = pkiMessage.ToAsn1Structure();
+            m_pkiMessage = pkiMessage.ToAsn1Structure();
         }
 
         // TODO[cmp] Make internal? (Has test that uses it)
@@ -41,7 +41,7 @@ namespace Org.BouncyCastle.Cmp
             if (null == pkiMessage.Header.ProtectionAlg)
                 throw new ArgumentException("PkiMessage not protected");
 
-            this.m_pkiMessage = pkiMessage;
+            m_pkiMessage = pkiMessage;
         }
 
         /// <summary>Message header</summary>
@@ -66,6 +66,13 @@ namespace Org.BouncyCastle.Cmp
             get { return CmpObjectIdentifiers.passwordBasedMac.Equals(Header.ProtectionAlg.Algorithm); }
         }
 
+        /**
+         * Return the message's protection algorithm.
+         *
+         * @return the algorithm ID for the message's protection algorithm.
+         */
+        public virtual AlgorithmIdentifier ProtectionAlgorithm => m_pkiMessage.Header.ProtectionAlg;
+
         /// <summary>
         /// Return the extra certificates associated with this message.
         /// </summary>
@@ -76,12 +83,8 @@ namespace Org.BouncyCastle.Cmp
             if (null == certs)
                 return new X509Certificate[0];
 
-            X509Certificate[] result = new X509Certificate[certs.Length];
-            for (int t = 0; t < certs.Length; t++)
-            {
-                result[t] = new X509Certificate(certs[t].X509v3PKCert);
-            }
-            return result;
+            return Array.ConvertAll<CmpCertificate, X509Certificate>(certs,
+                cmpCertificate => new X509Certificate(cmpCertificate.X509v3PKCert));
         }
 
         /// <summary>
@@ -107,10 +110,12 @@ namespace Org.BouncyCastle.Cmp
         /// <exception cref="InvalidOperationException">if algorithm not MAC based, or an exception is thrown verifying the MAC.</exception>
         public virtual bool Verify(PKMacBuilder pkMacBuilder, char[] password)
         {
-            if (!CmpObjectIdentifiers.passwordBasedMac.Equals(m_pkiMessage.Header.ProtectionAlg.Algorithm))
+            var protectionAlgorithm = m_pkiMessage.Header.ProtectionAlg;
+
+            if (!CmpObjectIdentifiers.passwordBasedMac.Equals(protectionAlgorithm.Algorithm))
                 throw new InvalidOperationException("protection algorithm is not mac based");
 
-            PbmParameter parameter = PbmParameter.GetInstance(m_pkiMessage.Header.ProtectionAlg.Parameters);
+            PbmParameter parameter = PbmParameter.GetInstance(protectionAlgorithm.Parameters);
             pkMacBuilder.SetParameters(parameter);
 
             var macFactory = pkMacBuilder.Build(password);
diff --git a/crypto/src/cmp/ProtectedPkiMessageBuilder.cs b/crypto/src/cmp/ProtectedPkiMessageBuilder.cs
index a3070ee56..ff4af5573 100644
--- a/crypto/src/cmp/ProtectedPkiMessageBuilder.cs
+++ b/crypto/src/cmp/ProtectedPkiMessageBuilder.cs
@@ -12,9 +12,9 @@ namespace Org.BouncyCastle.Cmp
     public sealed class ProtectedPkiMessageBuilder
     {
         private readonly PkiHeaderBuilder m_hdrBuilder;
-        private PkiBody body;
-        private readonly List<InfoTypeAndValue> generalInfos = new List<InfoTypeAndValue>();
-        private readonly List<X509Certificate> extraCerts = new List<X509Certificate>();
+        private readonly List<InfoTypeAndValue> m_generalInfos = new List<InfoTypeAndValue>();
+        private readonly List<X509Certificate> m_extraCerts = new List<X509Certificate>();
+        private PkiBody m_body;
 
         public ProtectedPkiMessageBuilder(GeneralName sender, GeneralName recipient)
             : this(PkiHeader.CMP_2000, sender, recipient)
@@ -40,7 +40,7 @@ namespace Org.BouncyCastle.Cmp
 
         public ProtectedPkiMessageBuilder AddGeneralInfo(InfoTypeAndValue genInfo)
         {
-            generalInfos.Add(genInfo);
+            m_generalInfos.Add(genInfo);
             return this;
         }
 
@@ -82,19 +82,49 @@ namespace Org.BouncyCastle.Cmp
 
         public ProtectedPkiMessageBuilder SetBody(PkiBody body)
         {
-            this.body = body;
+            m_body = body;
+            return this;
+        }
+
+        // TODO[crmf] Add CertificateReqMessages
+        //public ProtectedPkiMessageBuilder SetBody(int bodyType, CertificateReqMessages certificateReqMessages)
+        //{
+        //    if (!CertificateReqMessages.IsCertificateRequestMessages(bodyType))
+        //        throw new ArgumentException("body type " + bodyType + " does not match CMP type CertReqMessages");
+
+        //    m_body = new PkiBody(bodyType, certificateReqMessages.ToAsn1Structure());
+        //    return this;
+        //}
+
+        // TODO[crmf] Add CertificateRepMessage
+        //public ProtectedPkiMessageBuilder SetBody(int bodyType, CertificateRepMessage certificateRepMessage)
+        //{
+        //    if (!CertificateRepMessage.IsCertificateRepMessage(bodyType))
+        //        throw new ArgumentException("body type " + bodyType + " does not match CMP type CertRepMessage");
+
+        //    m_body = new PkiBody(bodyType, certificateRepMessage.ToAsn1Structure());
+        //    return this;
+        //}
+
+        public ProtectedPkiMessageBuilder SetBody(int bodyType,
+            CertificateConfirmationContent certificateConfirmationContent)
+        {
+            if (!CertificateConfirmationContent.IsCertificateConfirmationContent(bodyType))
+                throw new ArgumentException("body type " + bodyType + " does not match CMP type CertConfirmContent");
+
+            m_body = new PkiBody(bodyType, certificateConfirmationContent.ToAsn1Structure());
             return this;
         }
 
         public ProtectedPkiMessageBuilder AddCmpCertificate(X509Certificate certificate)
         {
-            extraCerts.Add(certificate);
+            m_extraCerts.Add(certificate);
             return this;
         }
 
         public ProtectedPkiMessage Build(ISignatureFactory signatureFactory)
         {
-            if (null == body)
+            if (null == m_body)
                 throw new InvalidOperationException("body must be set before building");
 
             if (!(signatureFactory.AlgorithmDetails is AlgorithmIdentifier algorithmDetails))
@@ -102,13 +132,14 @@ namespace Org.BouncyCastle.Cmp
 
             FinalizeHeader(algorithmDetails);
             PkiHeader header = m_hdrBuilder.Build();
-            DerBitString protection = X509Utilities.GenerateSignature(signatureFactory, new DerSequence(header, body));
+            DerBitString protection = X509Utilities.GenerateSignature(signatureFactory,
+                new DerSequence(header, m_body));
             return FinalizeMessage(header, protection);
         }
 
         public ProtectedPkiMessage Build(IMacFactory macFactory)
         {
-            if (null == body)
+            if (null == m_body)
                 throw new InvalidOperationException("body must be set before building");
 
             if (!(macFactory.AlgorithmDetails is AlgorithmIdentifier algorithmDetails))
@@ -116,31 +147,31 @@ namespace Org.BouncyCastle.Cmp
 
             FinalizeHeader(algorithmDetails);
             PkiHeader header = m_hdrBuilder.Build();
-            DerBitString protection = X509Utilities.GenerateMac(macFactory, new DerSequence(header, body));
+            DerBitString protection = X509Utilities.GenerateMac(macFactory, new DerSequence(header, m_body));
             return FinalizeMessage(header, protection);
         }
 
         private void FinalizeHeader(AlgorithmIdentifier algorithmIdentifier)
         {
             m_hdrBuilder.SetProtectionAlg(algorithmIdentifier);
-            if (generalInfos.Count > 0)
+            if (m_generalInfos.Count > 0)
             {
-                m_hdrBuilder.SetGeneralInfo(generalInfos.ToArray());
+                m_hdrBuilder.SetGeneralInfo(m_generalInfos.ToArray());
             }
         }
 
         private ProtectedPkiMessage FinalizeMessage(PkiHeader header, DerBitString protection)
         {
-            if (extraCerts.Count < 1)
-                return new ProtectedPkiMessage(new PkiMessage(header, body, protection));
+            if (m_extraCerts.Count < 1)
+                return new ProtectedPkiMessage(new PkiMessage(header, m_body, protection));
 
-            CmpCertificate[] cmpCertificates = new CmpCertificate[extraCerts.Count];
+            CmpCertificate[] cmpCertificates = new CmpCertificate[m_extraCerts.Count];
             for (int i = 0; i < cmpCertificates.Length; i++)
             {
-                cmpCertificates[i] = new CmpCertificate(extraCerts[i].CertificateStructure);
+                cmpCertificates[i] = new CmpCertificate(m_extraCerts[i].CertificateStructure);
             }
 
-            return new ProtectedPkiMessage(new PkiMessage(header, body, protection, cmpCertificates));
+            return new ProtectedPkiMessage(new PkiMessage(header, m_body, protection, cmpCertificates));
         }
     }
 }
diff --git a/crypto/src/cmp/RevocationDetails.cs b/crypto/src/cmp/RevocationDetails.cs
index 6060c6575..e3ad73f28 100644
--- a/crypto/src/cmp/RevocationDetails.cs
+++ b/crypto/src/cmp/RevocationDetails.cs
@@ -19,6 +19,7 @@ namespace Org.BouncyCastle.Cmp
 
         public BigInteger SerialNumber => m_revDetails.CertDetails.SerialNumber.Value;
 
+        // TODO[api] Rename to 'ToAsn1Structure'
         public RevDetails ToASN1Structure() => m_revDetails;
     }
 }
diff --git a/crypto/src/x509/X509Certificate.cs b/crypto/src/x509/X509Certificate.cs
index b1307d90e..944b627b0 100644
--- a/crypto/src/x509/X509Certificate.cs
+++ b/crypto/src/x509/X509Certificate.cs
@@ -312,6 +312,9 @@ namespace Org.BouncyCastle.X509
             return Arrays.Clone(sigAlgParams);
         }
 
+        /// <summary>The signature algorithm.</summary>
+        public virtual AlgorithmIdentifier SignatureAlgorithm => c.SignatureAlgorithm;
+
         /// <summary>
         /// Get the issuers UID.
         /// </summary>
@@ -629,6 +632,7 @@ namespace Org.BouncyCastle.X509
             return buf.ToString();
         }
 
+        // TODO[api] Rename 'key' to 'publicKey'
         public virtual bool IsSignatureValid(AsymmetricKeyParameter key)
         {
             return CheckSignatureValid(new Asn1VerifierFactory(c.SignatureAlgorithm, key));
diff --git a/crypto/src/x509/X509V3CertificateGenerator.cs b/crypto/src/x509/X509V3CertificateGenerator.cs
index 1dd1776be..2df8d5409 100644
--- a/crypto/src/x509/X509V3CertificateGenerator.cs
+++ b/crypto/src/x509/X509V3CertificateGenerator.cs
@@ -156,13 +156,22 @@ namespace Org.BouncyCastle.X509
 			tbsGen.SetIssuerUniqueID(BooleanToBitString(uniqueID));
 		}
 
-		/// <summary>
-		/// Add a given extension field for the standard extensions tag (tag 3).
-		/// </summary>
-		/// <param name="oid">string containing a dotted decimal Object Identifier.</param>
-		/// <param name="critical">Is it critical.</param>
-		/// <param name="extensionValue">The value.</param>
-		public void AddExtension(
+        /// <summary>
+        /// Set the SubjectPublicKeyInfo for the public key that this certificate identifies.
+        /// </summary>
+        /// <param name="subjectPublicKeyInfo"/>
+        public void SetSubjectPublicKeyInfo(SubjectPublicKeyInfo subjectPublicKeyInfo)
+        {
+            tbsGen.SetSubjectPublicKeyInfo(subjectPublicKeyInfo);
+        }
+
+        /// <summary>
+        /// Add a given extension field for the standard extensions tag (tag 3).
+        /// </summary>
+        /// <param name="oid">string containing a dotted decimal Object Identifier.</param>
+        /// <param name="critical">Is it critical.</param>
+        /// <param name="extensionValue">The value.</param>
+        public void AddExtension(
 			string			oid,
 			bool			critical,
 			Asn1Encodable	extensionValue)