summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2023-02-01 21:07:46 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2023-02-01 21:07:46 +0700
commitdb9b19e3f17a2aee8afcd673ef9327bb8646b87a (patch)
treea16cf94d902be26f7f00a5218cafa15fe28cf233
parentAdd GetInstanceFromChoice helper (diff)
downloadBouncyCastle.NET-ed25519-db9b19e3f17a2aee8afcd673ef9327bb8646b87a.tar.xz
Overhaul Asn1.Cmp
-rw-r--r--crypto/src/asn1/cmp/CAKeyUpdAnnContent.cs19
-rw-r--r--crypto/src/asn1/cmp/CertAnnContent.cs54
-rw-r--r--crypto/src/asn1/cmp/CertConfirmContent.cs27
-rw-r--r--crypto/src/asn1/cmp/CertOrEncCert.cs35
-rw-r--r--crypto/src/asn1/cmp/CertRepMessage.cs13
-rw-r--r--crypto/src/asn1/cmp/CertReqTemplateContent.cs11
-rw-r--r--crypto/src/asn1/cmp/CertResponse.cs15
-rw-r--r--crypto/src/asn1/cmp/CertStatus.cs15
-rw-r--r--crypto/src/asn1/cmp/CertifiedKeyPair.cs11
-rw-r--r--crypto/src/asn1/cmp/Challenge.cs24
-rw-r--r--crypto/src/asn1/cmp/CmpCertificate.cs91
-rw-r--r--crypto/src/asn1/cmp/CrlAnnContent.cs15
-rw-r--r--crypto/src/asn1/cmp/CrlSource.cs16
-rw-r--r--crypto/src/asn1/cmp/CrlStatus.cs11
-rw-r--r--crypto/src/asn1/cmp/DhbmParameter.cs11
-rw-r--r--crypto/src/asn1/cmp/ErrorMsgContent.cs11
-rw-r--r--crypto/src/asn1/cmp/GenMsgContent.cs15
-rw-r--r--crypto/src/asn1/cmp/GenRepContent.cs11
-rw-r--r--crypto/src/asn1/cmp/InfoTypeAndValue.cs30
-rw-r--r--crypto/src/asn1/cmp/KeyRecRepContent.cs25
-rw-r--r--crypto/src/asn1/cmp/NestedMessageContent.cs27
-rw-r--r--crypto/src/asn1/cmp/OobCert.cs46
-rw-r--r--crypto/src/asn1/cmp/OobCertHash.cs17
-rw-r--r--crypto/src/asn1/cmp/PKIBody.cs15
-rw-r--r--crypto/src/asn1/cmp/PKIConfirmContent.cs14
-rw-r--r--crypto/src/asn1/cmp/PKIHeader.cs29
-rw-r--r--crypto/src/asn1/cmp/PKIMessage.cs31
-rw-r--r--crypto/src/asn1/cmp/PKIMessages.cs26
-rw-r--r--crypto/src/asn1/cmp/PKIStatus.cs27
-rw-r--r--crypto/src/asn1/cmp/PKIStatusInfo.cs91
-rw-r--r--crypto/src/asn1/cmp/PbmParameter.cs11
-rw-r--r--crypto/src/asn1/cmp/PollRepContent.cs15
-rw-r--r--crypto/src/asn1/cmp/PollReqContent.cs37
-rw-r--r--crypto/src/asn1/cmp/PopoDecKeyChallContent.cs15
-rw-r--r--crypto/src/asn1/cmp/PopoDecKeyRespContent.cs15
-rw-r--r--crypto/src/asn1/cmp/ProtectedPart.cs15
-rw-r--r--crypto/src/asn1/cmp/RevAnnContent.cs15
-rw-r--r--crypto/src/asn1/cmp/RevDetails.cs15
-rw-r--r--crypto/src/asn1/cmp/RevRepContent.cs33
-rw-r--r--crypto/src/asn1/cmp/RevReqContent.cs19
-rw-r--r--crypto/src/asn1/cmp/RootCaKeyUpdateContent.cs20
-rw-r--r--crypto/src/asn1/x509/AttributeCertificate.cs41
-rw-r--r--crypto/src/tsp/TimeStampResponseGenerator.cs2
43 files changed, 508 insertions, 528 deletions
diff --git a/crypto/src/asn1/cmp/CAKeyUpdAnnContent.cs b/crypto/src/asn1/cmp/CAKeyUpdAnnContent.cs
index a3ec5e4df..d39c57bc9 100644
--- a/crypto/src/asn1/cmp/CAKeyUpdAnnContent.cs
+++ b/crypto/src/asn1/cmp/CAKeyUpdAnnContent.cs
@@ -1,7 +1,3 @@
-using System;
-
-using Org.BouncyCastle.Utilities;
-
 namespace Org.BouncyCastle.Asn1.Cmp
 {
 	public class CAKeyUpdAnnContent
@@ -9,13 +5,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static CAKeyUpdAnnContent GetInstance(object obj)
         {
-            if (obj is CAKeyUpdAnnContent content)
-                return content;
-
-            if (obj is Asn1Sequence seq)
-                return new CAKeyUpdAnnContent(seq);
+            if (obj == null)
+                return null;
+            if (obj is CAKeyUpdAnnContent caKeyUpdAnnContent)
+                return caKeyUpdAnnContent;
+            return new CAKeyUpdAnnContent(Asn1Sequence.GetInstance(obj));
+        }
 
-            throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), nameof(obj));
+        public static CAKeyUpdAnnContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly CmpCertificate m_oldWithNew;
diff --git a/crypto/src/asn1/cmp/CertAnnContent.cs b/crypto/src/asn1/cmp/CertAnnContent.cs
index 30b1fad2f..d41f48e2e 100644
--- a/crypto/src/asn1/cmp/CertAnnContent.cs
+++ b/crypto/src/asn1/cmp/CertAnnContent.cs
@@ -1,8 +1,6 @@
 using System;
-using System.IO;
 
 using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Asn1.Cmp
 {
@@ -14,56 +12,38 @@ namespace Org.BouncyCastle.Asn1.Cmp
     {
         public static new CertAnnContent GetInstance(object obj)
         {
-            // TODO[cmp]
             if (obj == null)
                 return null;
-
-            if (obj is CertAnnContent content)
-                return content;
-
+            if (obj is CertAnnContent certAnnContent)
+                return certAnnContent;
             if (obj is CmpCertificate cmpCertificate)
-                return GetInstance(cmpCertificate.GetEncoded());
-
-            if (obj is byte[] bs)
-            {
-                try
-                {
-                    obj = Asn1Object.FromByteArray(bs);
-                }
-                catch (IOException)
-                {
-                    throw new ArgumentException("Invalid encoding in CertAnnContent");
-                }
-            }
-
-            if (obj is Asn1Sequence)
-                return new CertAnnContent(X509CertificateStructure.GetInstance(obj));
-
-            // TODO[cmp]
+                return new CertAnnContent(cmpCertificate);
             if (obj is Asn1TaggedObject taggedObject)
-                return new CertAnnContent(taggedObject.TagNo, taggedObject.GetObject());
-
-            throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), nameof(obj));
+                return new CertAnnContent(taggedObject);
+            return new CertAnnContent(X509CertificateStructure.GetInstance(obj));
         }
 
         public static new CertAnnContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
         {
-            // TODO[cmp]
-            if (taggedObject == null)
-                return null;
-
-            if (!declaredExplicit)
-                throw new ArgumentException("tag must be explicit");
-
-            // TODO[cmp]
-            return GetInstance(taggedObject.GetObject());
+            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
         }
 
+        [Obsolete("Use 'GetInstance' from tagged object instead")]
         public CertAnnContent(int type, Asn1Object otherCert)
             : base(type, otherCert)
         {
         }
 
+        internal CertAnnContent(Asn1TaggedObject taggedObject)
+            : base(taggedObject)
+        {
+        }
+
+        internal CertAnnContent(CmpCertificate other)
+            : base(other)
+        {
+        }
+
         public CertAnnContent(X509CertificateStructure x509v3PKCert)
             : base(x509v3PKCert)
         {
diff --git a/crypto/src/asn1/cmp/CertConfirmContent.cs b/crypto/src/asn1/cmp/CertConfirmContent.cs
index 8e75dfbd0..e11826d6b 100644
--- a/crypto/src/asn1/cmp/CertConfirmContent.cs
+++ b/crypto/src/asn1/cmp/CertConfirmContent.cs
@@ -1,22 +1,21 @@
-using System;
-
-using Org.BouncyCastle.Utilities;
-
 namespace Org.BouncyCastle.Asn1.Cmp
 {
-	public class CertConfirmContent
+    public class CertConfirmContent
 		: Asn1Encodable
 	{
-		public static CertConfirmContent GetInstance(object obj)
-		{
-			if (obj is CertConfirmContent content)
-				return content;
-
-			if (obj is Asn1Sequence seq)
-				return new CertConfirmContent(seq);
+        public static CertConfirmContent GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is CertConfirmContent certConfirmContent)
+                return certConfirmContent;
+            return new CertConfirmContent(Asn1Sequence.GetInstance(obj));
+        }
 
-            throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), nameof(obj));
-		}
+        public static CertConfirmContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
 
         private readonly Asn1Sequence m_content;
 
diff --git a/crypto/src/asn1/cmp/CertOrEncCert.cs b/crypto/src/asn1/cmp/CertOrEncCert.cs
index e517b66ce..1423503d2 100644
--- a/crypto/src/asn1/cmp/CertOrEncCert.cs
+++ b/crypto/src/asn1/cmp/CertOrEncCert.cs
@@ -1,7 +1,6 @@
 using System;
 
 using Org.BouncyCastle.Asn1.Crmf;
-using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Asn1.Cmp
 {
@@ -10,13 +9,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static CertOrEncCert GetInstance(object obj)
         {
+			if (obj == null)
+				return null;
             if (obj is CertOrEncCert certOrEncCert)
                 return certOrEncCert;
+            return new CertOrEncCert(Asn1TaggedObject.GetInstance(obj));
+        }
 
-            if (obj is Asn1TaggedObject taggedObject)
-                return new CertOrEncCert(taggedObject);
-
-            throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), nameof(obj));
+        public static CertOrEncCert GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
         }
 
         private readonly CmpCertificate m_certificate;
@@ -40,26 +42,18 @@ namespace Org.BouncyCastle.Asn1.Cmp
 
 		public CertOrEncCert(CmpCertificate certificate)
 		{
-			if (certificate == null)
-				throw new ArgumentNullException(nameof(certificate));
-
-			m_certificate = certificate;
-		}
+			m_certificate = certificate ?? throw new ArgumentNullException(nameof(certificate));
+        }
 
 		public CertOrEncCert(EncryptedValue encryptedValue)
 		{
-			if (encryptedValue == null)
-				throw new ArgumentNullException(nameof(encryptedValue));
-
-			m_encryptedCert = new EncryptedKey(encryptedValue);
+			m_encryptedCert = new EncryptedKey(
+				encryptedValue ?? throw new ArgumentNullException(nameof(encryptedValue)));
 		}
 
         public CertOrEncCert(EncryptedKey encryptedKey)
         {
-            if (encryptedKey == null)
-                throw new ArgumentNullException(nameof(encryptedKey));
-
-            m_encryptedCert = encryptedKey;
+            m_encryptedCert = encryptedKey ?? throw new ArgumentNullException(nameof(encryptedKey));
         }
 
 		public virtual CmpCertificate Certificate => m_certificate;
@@ -79,8 +73,9 @@ namespace Org.BouncyCastle.Asn1.Cmp
 		{
 			if (m_certificate != null)
 				return new DerTaggedObject(true, 0, m_certificate);
-
-			return new DerTaggedObject(true, 1, m_encryptedCert);
+			if (m_encryptedCert != null)
+				return new DerTaggedObject(true, 1, m_encryptedCert);
+			throw new InvalidOperationException();
 		}
 	}
 }
diff --git a/crypto/src/asn1/cmp/CertRepMessage.cs b/crypto/src/asn1/cmp/CertRepMessage.cs
index 696cfde47..882816b86 100644
--- a/crypto/src/asn1/cmp/CertRepMessage.cs
+++ b/crypto/src/asn1/cmp/CertRepMessage.cs
@@ -1,7 +1,5 @@
 using System;
 
-using Org.BouncyCastle.Utilities;
-
 namespace Org.BouncyCastle.Asn1.Cmp
 {
 	public class CertRepMessage
@@ -9,13 +7,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static CertRepMessage GetInstance(object obj)
         {
+            if (obj == null)
+                return null;
             if (obj is CertRepMessage certRepMessage)
                 return certRepMessage;
+            return new CertRepMessage(Asn1Sequence.GetInstance(obj));
+        }
 
-            if (obj != null)
-				return new CertRepMessage(Asn1Sequence.GetInstance(obj));
-
-			return null;
+        public static CertRepMessage GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly Asn1Sequence m_caPubs;
diff --git a/crypto/src/asn1/cmp/CertReqTemplateContent.cs b/crypto/src/asn1/cmp/CertReqTemplateContent.cs
index c25c71ad1..c08a9a293 100644
--- a/crypto/src/asn1/cmp/CertReqTemplateContent.cs
+++ b/crypto/src/asn1/cmp/CertReqTemplateContent.cs
@@ -22,13 +22,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
     {
         public static CertReqTemplateContent GetInstance(object obj)
         {
+            if (obj == null)
+                return null;
             if (obj is CertReqTemplateContent certReqTemplateContent)
                 return certReqTemplateContent;
+            return new CertReqTemplateContent(Asn1Sequence.GetInstance(obj));
+        }
 
-            if (obj != null)
-                return new CertReqTemplateContent(Asn1Sequence.GetInstance(obj));
-
-            return null;
+        public static CertReqTemplateContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly CertTemplate m_certTemplate;
diff --git a/crypto/src/asn1/cmp/CertResponse.cs b/crypto/src/asn1/cmp/CertResponse.cs
index 72a44c93e..e70d6d388 100644
--- a/crypto/src/asn1/cmp/CertResponse.cs
+++ b/crypto/src/asn1/cmp/CertResponse.cs
@@ -7,13 +7,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static CertResponse GetInstance(object obj)
         {
-			if (obj is CertResponse certResponse)
-				return certResponse;
-
-			if (obj != null)
-				return new CertResponse(Asn1Sequence.GetInstance(obj));
+            if (obj == null)
+                return null;
+            if (obj is CertResponse certResponse)
+                return certResponse;
+            return new CertResponse(Asn1Sequence.GetInstance(obj));
+        }
 
-			return null;
+        public static CertResponse GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly DerInteger m_certReqId;
diff --git a/crypto/src/asn1/cmp/CertStatus.cs b/crypto/src/asn1/cmp/CertStatus.cs
index 6eb36c6fb..37f0c29e8 100644
--- a/crypto/src/asn1/cmp/CertStatus.cs
+++ b/crypto/src/asn1/cmp/CertStatus.cs
@@ -10,13 +10,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static CertStatus GetInstance(object obj)
         {
-			if (obj is CertStatus certStatus)
-				return certStatus;
-
-			if (obj != null)
-				return new CertStatus(Asn1Sequence.GetInstance(obj));
+            if (obj == null)
+                return null;
+            if (obj is CertStatus certStatus)
+                return certStatus;
+            return new CertStatus(Asn1Sequence.GetInstance(obj));
+        }
 
-			return null;
+        public static CertStatus GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly Asn1OctetString m_certHash;
diff --git a/crypto/src/asn1/cmp/CertifiedKeyPair.cs b/crypto/src/asn1/cmp/CertifiedKeyPair.cs
index ec60ce965..e26c5c629 100644
--- a/crypto/src/asn1/cmp/CertifiedKeyPair.cs
+++ b/crypto/src/asn1/cmp/CertifiedKeyPair.cs
@@ -9,13 +9,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static CertifiedKeyPair GetInstance(object obj)
         {
+            if (obj == null)
+                return null;
             if (obj is CertifiedKeyPair certifiedKeyPair)
                 return certifiedKeyPair;
+            return new CertifiedKeyPair(Asn1Sequence.GetInstance(obj));
+        }
 
-            if (obj != null)
-                return new CertifiedKeyPair(Asn1Sequence.GetInstance(obj));
-
-            return null;
+        public static CertifiedKeyPair GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly CertOrEncCert m_certOrEncCert;
diff --git a/crypto/src/asn1/cmp/Challenge.cs b/crypto/src/asn1/cmp/Challenge.cs
index ca3d06339..21958da67 100644
--- a/crypto/src/asn1/cmp/Challenge.cs
+++ b/crypto/src/asn1/cmp/Challenge.cs
@@ -35,13 +35,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static Challenge GetInstance(object obj)
         {
+            if (obj == null)
+                return null;
             if (obj is Challenge challenge)
                 return challenge;
+            return new Challenge(Asn1Sequence.GetInstance(obj));
+        }
 
-            if (obj != null)
-                return new Challenge(Asn1Sequence.GetInstance(obj));
-
-            return null;
+        public static Challenge GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly AlgorithmIdentifier m_owf;
@@ -122,13 +125,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
         {
             public static Rand GetInstance(object obj)
             {
+                if (obj == null)
+                    return null;
                 if (obj is Rand rand)
                     return rand;
+                return new Rand(Asn1Sequence.GetInstance(obj));
+            }
 
-                if (obj != null)
-                    return new Rand(Asn1Sequence.GetInstance(obj));
-
-                return null;
+            public static Rand GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+            {
+                return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
             }
 
             private readonly DerInteger m_intVal;
@@ -143,7 +149,7 @@ namespace Org.BouncyCastle.Asn1.Cmp
             public Rand(Asn1Sequence seq)
             {
                 if (seq.Count != 2)
-                    throw new ArgumentException("expected sequence size of 2");
+                    throw new ArgumentException("expected sequence size of 2", nameof(seq));
 
                 m_intVal = DerInteger.GetInstance(seq[0]);
                 m_sender = GeneralName.GetInstance(seq[1]);
diff --git a/crypto/src/asn1/cmp/CmpCertificate.cs b/crypto/src/asn1/cmp/CmpCertificate.cs
index af433ec4d..bc9844911 100644
--- a/crypto/src/asn1/cmp/CmpCertificate.cs
+++ b/crypto/src/asn1/cmp/CmpCertificate.cs
@@ -1,8 +1,6 @@
 using System;
-using System.IO;
 
 using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Asn1.Cmp
 {
@@ -11,64 +9,53 @@ namespace Org.BouncyCastle.Asn1.Cmp
     {
         public static CmpCertificate GetInstance(object obj)
         {
-            // TODO[cmp] Review this whole metho
-
             if (obj == null)
                 return null;
-
             if (obj is CmpCertificate cmpCertificate)
                 return cmpCertificate;
-
-            if (obj is byte[] bs)
-            {
-                try
-                {
-                    obj = Asn1Object.FromByteArray(bs);
-                }
-                catch (IOException)
-                {
-                    throw new ArgumentException("Invalid encoding in CmpCertificate");
-                }
-            }
-
-            if (obj is Asn1Sequence)
-                return new CmpCertificate(X509CertificateStructure.GetInstance(obj));
-
             if (obj is Asn1TaggedObject taggedObject)
-                return new CmpCertificate(taggedObject.TagNo, taggedObject.GetObject());
-
-            throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), nameof(obj));
+                return new CmpCertificate(taggedObject);
+            return new CmpCertificate(X509CertificateStructure.GetInstance(obj));
         }
 
         public static CmpCertificate GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
         {
-            // TODO[cmp]
-            if (taggedObject == null)
-                return null;
-
-            if (!declaredExplicit)
-                throw new ArgumentException("tag must be explicit");
-
-            // TODO[cmp]
-            return GetInstance(taggedObject.GetObject());
+            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
         }
 
         private readonly X509CertificateStructure m_x509v3PKCert;
 
-        private readonly int m_otherTagValue;
-        private readonly Asn1Encodable m_otherCert;
+        private readonly int m_otherTag;
+        private readonly Asn1Encodable m_otherObject;
 
-        /**
-         * Note: the addition of other certificates is a BC extension. If you use this constructor they
-         * will be added with an explicit tag value of type.
-         *
-         * @param type      the type of the certificate (used as a tag value).
-         * @param otherCert the object representing the certificate
-         */
+        [Obsolete("Use 'GetInstance' from tagged object instead")]
         public CmpCertificate(int type, Asn1Encodable otherCert)
         {
-            m_otherTagValue = type;
-            m_otherCert = otherCert;
+            m_otherTag = type;
+            m_otherObject = otherCert;
+        }
+
+        internal CmpCertificate(Asn1TaggedObject taggedObject)
+        {
+            Asn1Encodable otherCert;
+            if (taggedObject.HasContextTag(1))
+            {
+                otherCert = AttributeCertificate.GetInstance(taggedObject, true);
+            }
+            else
+            {
+                throw new ArgumentException("Invalid CHOICE element", nameof(taggedObject));
+            }
+
+            m_otherTag = taggedObject.TagNo;
+            m_otherObject = taggedObject.GetExplicitBaseObject();
+        }
+
+        internal CmpCertificate(CmpCertificate other)
+        {
+            m_x509v3PKCert = other.m_x509v3PKCert;
+            m_otherTag = other.m_otherTag;
+            m_otherObject = other.m_otherObject;
         }
 
         public CmpCertificate(X509CertificateStructure x509v3PKCert)
@@ -83,9 +70,9 @@ namespace Org.BouncyCastle.Asn1.Cmp
 
         public virtual X509CertificateStructure X509v3PKCert => m_x509v3PKCert;
 
-        public virtual int OtherCertTag => m_otherTagValue;
+        public virtual int OtherCertTag => m_otherTag;
 
-        public virtual Asn1Encodable OtherCert => m_otherCert;
+        public virtual Asn1Encodable OtherCert => m_otherObject;
 
         /**
          * <pre>
@@ -100,13 +87,11 @@ namespace Org.BouncyCastle.Asn1.Cmp
          */
         public override Asn1Object ToAsn1Object()
         {
-            if (m_otherCert != null)
-            {
-                // explicit following CMP conventions
-                return new DerTaggedObject(true, m_otherTagValue, m_otherCert);
-            }
-
-            return m_x509v3PKCert.ToAsn1Object();
+            if (m_otherObject != null)
+                return new DerTaggedObject(true, m_otherTag, m_otherObject);
+            if (m_x509v3PKCert != null)
+                return m_x509v3PKCert.ToAsn1Object();
+            throw new InvalidOperationException();
         }
     }
 }
diff --git a/crypto/src/asn1/cmp/CrlAnnContent.cs b/crypto/src/asn1/cmp/CrlAnnContent.cs
index 0da25cd0e..ac8fc0458 100644
--- a/crypto/src/asn1/cmp/CrlAnnContent.cs
+++ b/crypto/src/asn1/cmp/CrlAnnContent.cs
@@ -7,13 +7,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static CrlAnnContent GetInstance(object obj)
         {
-			if (obj is CrlAnnContent crlAnnContent)
-				return crlAnnContent;
-
-			if (obj != null)
-				return new CrlAnnContent(Asn1Sequence.GetInstance(obj));
+            if (obj == null)
+                return null;
+            if (obj is CrlAnnContent crlAnnContent)
+                return crlAnnContent;
+            return new CrlAnnContent(Asn1Sequence.GetInstance(obj));
+        }
 
-			return null;
+        public static CrlAnnContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly Asn1Sequence m_content;
diff --git a/crypto/src/asn1/cmp/CrlSource.cs b/crypto/src/asn1/cmp/CrlSource.cs
index 9e2526ec2..6203b17c7 100644
--- a/crypto/src/asn1/cmp/CrlSource.cs
+++ b/crypto/src/asn1/cmp/CrlSource.cs
@@ -19,13 +19,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
     {
         public static CrlSource GetInstance(object obj)
         {
+            if (obj == null)
+                return null;
             if (obj is CrlSource crlSource)
                 return crlSource;
+            return new CrlSource(Asn1TaggedObject.GetInstance(obj));
+        }
 
-            if (obj != null)
-                return new CrlSource(Asn1TaggedObject.GetInstance(obj));
-
-            return null;
+        public static CrlSource GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
         }
 
         private readonly DistributionPointName m_dpn;
@@ -65,8 +68,9 @@ namespace Org.BouncyCastle.Asn1.Cmp
         {
             if (m_dpn != null)
                 return new DerTaggedObject(true, 0, m_dpn);
-
-            return new DerTaggedObject(true, 1, m_issuer);
+            if (m_issuer != null)
+                return new DerTaggedObject(true, 1, m_issuer);
+            throw new InvalidOperationException();
         }
     }
 }
diff --git a/crypto/src/asn1/cmp/CrlStatus.cs b/crypto/src/asn1/cmp/CrlStatus.cs
index 5bacbbbcc..6cd01c945 100644
--- a/crypto/src/asn1/cmp/CrlStatus.cs
+++ b/crypto/src/asn1/cmp/CrlStatus.cs
@@ -14,13 +14,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
     {
         public static CrlStatus GetInstance(object obj)
         {
+            if (obj == null)
+                return null;
             if (obj is CrlStatus crlStatus)
                 return crlStatus;
+            return new CrlStatus(Asn1Sequence.GetInstance(obj));
+        }
 
-            if (obj != null)
-                return new CrlStatus(Asn1Sequence.GetInstance(obj));
-
-            return null;
+        public static CrlStatus GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly CrlSource m_source;
diff --git a/crypto/src/asn1/cmp/DhbmParameter.cs b/crypto/src/asn1/cmp/DhbmParameter.cs
index aaf71f70e..12b8d91d3 100644
--- a/crypto/src/asn1/cmp/DhbmParameter.cs
+++ b/crypto/src/asn1/cmp/DhbmParameter.cs
@@ -17,13 +17,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
     {
         public static DhbmParameter GetInstance(object obj)
         {
+            if (obj == null)
+                return null;
             if (obj is DhbmParameter dhbmParameter)
                 return dhbmParameter;
+            return new DhbmParameter(Asn1Sequence.GetInstance(obj));
+        }
 
-            if (obj != null)
-                return new DhbmParameter(Asn1Sequence.GetInstance(obj));
-
-            return null;
+        public static DhbmParameter GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly AlgorithmIdentifier m_owf;
diff --git a/crypto/src/asn1/cmp/ErrorMsgContent.cs b/crypto/src/asn1/cmp/ErrorMsgContent.cs
index fe8318aab..0937d85d4 100644
--- a/crypto/src/asn1/cmp/ErrorMsgContent.cs
+++ b/crypto/src/asn1/cmp/ErrorMsgContent.cs
@@ -18,13 +18,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static ErrorMsgContent GetInstance(object obj)
         {
+            if (obj == null)
+                return null;
             if (obj is ErrorMsgContent errorMsgContent)
                 return errorMsgContent;
+            return new ErrorMsgContent(Asn1Sequence.GetInstance(obj));
+        }
 
-            if (obj != null)
-                return new ErrorMsgContent(Asn1Sequence.GetInstance(obj));
-
-            return null;
+        public static ErrorMsgContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly PkiStatusInfo m_pkiStatusInfo;
diff --git a/crypto/src/asn1/cmp/GenMsgContent.cs b/crypto/src/asn1/cmp/GenMsgContent.cs
index b4673b76a..11c0c8b3b 100644
--- a/crypto/src/asn1/cmp/GenMsgContent.cs
+++ b/crypto/src/asn1/cmp/GenMsgContent.cs
@@ -8,13 +8,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static GenMsgContent GetInstance(object obj)
         {
-			if (obj is GenMsgContent genMsgContent)
-				return genMsgContent;
-
-			if (obj != null)
-				return new GenMsgContent(Asn1Sequence.GetInstance(obj));
+            if (obj == null)
+                return null;
+            if (obj is GenMsgContent genMsgContent)
+                return genMsgContent;
+            return new GenMsgContent(Asn1Sequence.GetInstance(obj));
+        }
 
-			return null;
+        public static GenMsgContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly Asn1Sequence m_content;
diff --git a/crypto/src/asn1/cmp/GenRepContent.cs b/crypto/src/asn1/cmp/GenRepContent.cs
index 38f91061c..1de37e094 100644
--- a/crypto/src/asn1/cmp/GenRepContent.cs
+++ b/crypto/src/asn1/cmp/GenRepContent.cs
@@ -5,13 +5,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static GenRepContent GetInstance(object obj)
         {
+            if (obj == null)
+                return null;
             if (obj is GenRepContent genRepContent)
                 return genRepContent;
+            return new GenRepContent(Asn1Sequence.GetInstance(obj));
+        }
 
-            if (obj != null)
-                return new GenRepContent(Asn1Sequence.GetInstance(obj));
-
-            return null;
+        public static GenRepContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly Asn1Sequence m_content;
diff --git a/crypto/src/asn1/cmp/InfoTypeAndValue.cs b/crypto/src/asn1/cmp/InfoTypeAndValue.cs
index 08ad68a42..ca6dc1fe5 100644
--- a/crypto/src/asn1/cmp/InfoTypeAndValue.cs
+++ b/crypto/src/asn1/cmp/InfoTypeAndValue.cs
@@ -50,6 +50,20 @@ namespace Org.BouncyCastle.Asn1.Cmp
     public class InfoTypeAndValue
         : Asn1Encodable
     {
+        public static InfoTypeAndValue GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is InfoTypeAndValue infoTypeAndValue)
+                return infoTypeAndValue;
+            return new InfoTypeAndValue(Asn1Sequence.GetInstance(obj));
+        }
+
+        public static InfoTypeAndValue GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
         private readonly DerObjectIdentifier m_infoType;
         private readonly Asn1Encodable m_infoValue;
 
@@ -63,17 +77,6 @@ namespace Org.BouncyCastle.Asn1.Cmp
             }
         }
 
-        public static InfoTypeAndValue GetInstance(object obj)
-        {
-            if (obj is InfoTypeAndValue infoTypeAndValue)
-                return infoTypeAndValue;
-
-            if (obj != null)
-                return new InfoTypeAndValue(Asn1Sequence.GetInstance(obj));
-
-            return null;
-        }
-
         public InfoTypeAndValue(DerObjectIdentifier infoType)
             : this(infoType, null)
         {
@@ -81,10 +84,7 @@ namespace Org.BouncyCastle.Asn1.Cmp
 
         public InfoTypeAndValue(DerObjectIdentifier infoType, Asn1Encodable infoValue)
         {
-            if (infoType == null)
-                throw new ArgumentNullException(nameof(infoType));
-
-            m_infoType = infoType;
+            m_infoType = infoType ?? throw new ArgumentNullException(nameof(infoType));
             m_infoValue = infoValue;
         }
 
diff --git a/crypto/src/asn1/cmp/KeyRecRepContent.cs b/crypto/src/asn1/cmp/KeyRecRepContent.cs
index 6c5ef62f2..880eb9895 100644
--- a/crypto/src/asn1/cmp/KeyRecRepContent.cs
+++ b/crypto/src/asn1/cmp/KeyRecRepContent.cs
@@ -7,13 +7,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static KeyRecRepContent GetInstance(object obj)
         {
-			if (obj is KeyRecRepContent keyRecRepContent)
-				return keyRecRepContent;
-
-			if (obj != null)
-				return new KeyRecRepContent(Asn1Sequence.GetInstance(obj));
+            if (obj == null)
+                return null;
+            if (obj is KeyRecRepContent keyRecRepContent)
+                return keyRecRepContent;
+            return new KeyRecRepContent(Asn1Sequence.GetInstance(obj));
+        }
 
-			return null;
+        public static KeyRecRepContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly PkiStatusInfo m_status;
@@ -52,18 +55,12 @@ namespace Org.BouncyCastle.Asn1.Cmp
 
 		public virtual CmpCertificate[] GetCACerts()
 		{
-			if (m_caCerts == null)
-				return null;
-
-			return m_caCerts.MapElements(CmpCertificate.GetInstance);
+			return m_caCerts?.MapElements(CmpCertificate.GetInstance);
 		}
 
 		public virtual CertifiedKeyPair[] GetKeyPairHist()
 		{
-			if (m_keyPairHist == null)
-				return null;
-
-			return m_keyPairHist.MapElements(CertifiedKeyPair.GetInstance);
+			return m_keyPairHist?.MapElements(CertifiedKeyPair.GetInstance);
 		}
 
 		/**
diff --git a/crypto/src/asn1/cmp/NestedMessageContent.cs b/crypto/src/asn1/cmp/NestedMessageContent.cs
index 0cb2c080b..b9e62e218 100644
--- a/crypto/src/asn1/cmp/NestedMessageContent.cs
+++ b/crypto/src/asn1/cmp/NestedMessageContent.cs
@@ -1,4 +1,6 @@
-namespace Org.BouncyCastle.Asn1.Cmp
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
 {
     /**
      * NestedMessageContent ::= PKIMessages
@@ -8,13 +10,22 @@
     {
         public static new NestedMessageContent GetInstance(object obj)
         {
+            if (obj == null)
+                return null;
             if (obj is NestedMessageContent nestedMessageContent)
                 return nestedMessageContent;
+            if (obj is PkiMessages pkiMessages)
+                return new NestedMessageContent(pkiMessages);
+#pragma warning disable CS0618 // Type or member is obsolete
+            return new NestedMessageContent(Asn1Sequence.GetInstance(obj));
+#pragma warning restore CS0618 // Type or member is obsolete
+        }
 
-            if (obj != null)
-                return new NestedMessageContent(Asn1Sequence.GetInstance(obj));
-
-            return null;
+        public static new NestedMessageContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+#pragma warning disable CS0618 // Type or member is obsolete
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+#pragma warning restore CS0618 // Type or member is obsolete
         }
 
         public NestedMessageContent(PkiMessage msg)
@@ -27,9 +38,15 @@
         {
         }
 
+        [Obsolete("Use 'GetInstance' instead")]
         public NestedMessageContent(Asn1Sequence seq)
             : base(seq)
         {
         }
+
+        internal NestedMessageContent(PkiMessages other)
+            : base(other)
+        {
+        }
     }
 }
diff --git a/crypto/src/asn1/cmp/OobCert.cs b/crypto/src/asn1/cmp/OobCert.cs
index 82d5afe55..6d60f6bb6 100644
--- a/crypto/src/asn1/cmp/OobCert.cs
+++ b/crypto/src/asn1/cmp/OobCert.cs
@@ -1,8 +1,6 @@
 using System;
-using System.IO;
 
 using Org.BouncyCastle.Asn1.X509;
-using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Asn1.Cmp
 {
@@ -16,50 +14,36 @@ namespace Org.BouncyCastle.Asn1.Cmp
         {
             if (obj == null)
                 return null;
-
             if (obj is OobCert oobCert)
                 return oobCert;
-
             if (obj is CmpCertificate cmpCertificate)
-                return GetInstance(cmpCertificate.GetEncoded());
-
-            if (obj is byte[] bs)
-            {
-                try
-                {
-                    obj = Asn1Object.FromByteArray(bs);
-                }
-                catch (IOException)
-                {
-                    throw new ArgumentException("Invalid encoding in OobCert");
-                }
-            }
-
-            if (obj is Asn1Sequence seq)
-                return new OobCert(X509CertificateStructure.GetInstance(obj));
-
+                return new OobCert(cmpCertificate);
             if (obj is Asn1TaggedObject taggedObject)
-                return new OobCert(taggedObject.TagNo, taggedObject.GetObject());
-
-            throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), nameof(obj));
+                return new OobCert(taggedObject);
+            return new OobCert(X509CertificateStructure.GetInstance(obj));
         }
 
         public static new OobCert GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
         {
-            if (taggedObject == null)
-                return null;
-
-            if (!declaredExplicit)
-                throw new ArgumentException("tag must be explicit");
-
-            return GetInstance(taggedObject.GetObject());
+            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
         }
 
+        [Obsolete("Use constructor from Asn1TaggedObject instead")]
         public OobCert(int type, Asn1Encodable otherCert)
             : base(type, otherCert)
         {
         }
 
+        internal OobCert(Asn1TaggedObject taggedObject)
+            : base(taggedObject)
+        {
+        }
+
+        internal OobCert(CmpCertificate other)
+            : base(other)
+        {
+        }
+
         public OobCert(X509CertificateStructure x509v3PKCert)
             : base(x509v3PKCert)
         {
diff --git a/crypto/src/asn1/cmp/OobCertHash.cs b/crypto/src/asn1/cmp/OobCertHash.cs
index a18ff300d..95cbe0cf2 100644
--- a/crypto/src/asn1/cmp/OobCertHash.cs
+++ b/crypto/src/asn1/cmp/OobCertHash.cs
@@ -22,13 +22,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static OobCertHash GetInstance(object obj)
         {
-			if (obj is OobCertHash oobCertHash)
-				return oobCertHash;
-
-			if (obj != null)
-				return new OobCertHash(Asn1Sequence.GetInstance(obj));
+            if (obj == null)
+                return null;
+            if (obj is OobCertHash oobCertHash)
+                return oobCertHash;
+            return new OobCertHash(Asn1Sequence.GetInstance(obj));
+        }
 
-			return null;
+        public static OobCertHash GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly AlgorithmIdentifier m_hashAlg;
@@ -76,7 +79,7 @@ namespace Org.BouncyCastle.Asn1.Cmp
 		 */
 		public override Asn1Object ToAsn1Object()
 		{
-			Asn1EncodableVector v = new Asn1EncodableVector();
+			Asn1EncodableVector v = new Asn1EncodableVector(3);
             v.AddOptionalTagged(true, 0, m_hashAlg);
             v.AddOptionalTagged(true, 1, m_certId);
 			v.Add(m_hashVal);
diff --git a/crypto/src/asn1/cmp/PKIBody.cs b/crypto/src/asn1/cmp/PKIBody.cs
index 68f63ab0b..2a92053b5 100644
--- a/crypto/src/asn1/cmp/PKIBody.cs
+++ b/crypto/src/asn1/cmp/PKIBody.cs
@@ -2,7 +2,6 @@ using System;
 
 using Org.BouncyCastle.Asn1.Crmf;
 using Org.BouncyCastle.Asn1.Pkcs;
-using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Asn1.Cmp
 {
@@ -72,14 +71,14 @@ namespace Org.BouncyCastle.Asn1.Cmp
         {
             if (obj == null)
                 return null;
+            if (obj is PkiBody crlSource)
+                return crlSource;
+            return new PkiBody(Asn1TaggedObject.GetInstance(obj));
+        }
 
-            if (obj is PkiBody pkiBody)
-                return pkiBody;
-
-            if (obj is Asn1TaggedObject taggedObject)
-                return new PkiBody(taggedObject);
-
-            throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), nameof(obj));
+        public static PkiBody GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
         }
 
         private readonly int m_tagNo;
diff --git a/crypto/src/asn1/cmp/PKIConfirmContent.cs b/crypto/src/asn1/cmp/PKIConfirmContent.cs
index ecebb22a8..34a66f3f7 100644
--- a/crypto/src/asn1/cmp/PKIConfirmContent.cs
+++ b/crypto/src/asn1/cmp/PKIConfirmContent.cs
@@ -1,7 +1,5 @@
 using System;
 
-using Org.BouncyCastle.Utilities;
-
 namespace Org.BouncyCastle.Asn1.Cmp
 {
     /**
@@ -14,16 +12,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 		{
 			if (obj == null)
 				return null;
-
 			if (obj is PkiConfirmContent pkiConfirmContent)
 				return pkiConfirmContent;
-
-			if (obj is Asn1Null asn1Null)
-				return new PkiConfirmContent(asn1Null);
-
-            throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), nameof(obj));
+			return new PkiConfirmContent(Asn1Null.GetInstance(obj));
 		}
 
+        public static PkiConfirmContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Null.GetInstance(taggedObject, declaredExplicit));
+        }
+
         private readonly Asn1Null m_val;
 
         public PkiConfirmContent()
diff --git a/crypto/src/asn1/cmp/PKIHeader.cs b/crypto/src/asn1/cmp/PKIHeader.cs
index 7db9cde1d..6914ae613 100644
--- a/crypto/src/asn1/cmp/PKIHeader.cs
+++ b/crypto/src/asn1/cmp/PKIHeader.cs
@@ -16,6 +16,20 @@ namespace Org.BouncyCastle.Asn1.Cmp
         public static readonly int CMP_1999 = 1;
         public static readonly int CMP_2000 = 2;
 
+        public static PkiHeader GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is PkiHeader pkiHeader)
+                return pkiHeader;
+            return new PkiHeader(Asn1Sequence.GetInstance(obj));
+        }
+
+        public static PkiHeader GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
         private readonly DerInteger pvno;
         private readonly GeneralName sender;
         private readonly GeneralName recipient;
@@ -37,7 +51,9 @@ namespace Org.BouncyCastle.Asn1.Cmp
 
             for (int pos = 3; pos < seq.Count; ++pos)
             {
-                Asn1TaggedObject tObj = (Asn1TaggedObject)seq[pos];
+                Asn1TaggedObject tObj = Asn1TaggedObject.GetInstance(seq[pos]);
+                if (Asn1Tags.ContextSpecific != tObj.TagClass)
+                    continue;
 
                 switch (tObj.TagNo)
                 {
@@ -74,17 +90,6 @@ namespace Org.BouncyCastle.Asn1.Cmp
             }
         }
 
-        public static PkiHeader GetInstance(object obj)
-        {
-            if (obj is PkiHeader pkiHeader)
-                return pkiHeader;
-
-            if (obj is Asn1Sequence asn1Sequence)
-                return new PkiHeader(asn1Sequence);
-
-            throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), nameof(obj));
-        }
-
         public PkiHeader(
             int pvno,
             GeneralName sender,
diff --git a/crypto/src/asn1/cmp/PKIMessage.cs b/crypto/src/asn1/cmp/PKIMessage.cs
index 9ac54b3da..2265dd9b2 100644
--- a/crypto/src/asn1/cmp/PKIMessage.cs
+++ b/crypto/src/asn1/cmp/PKIMessage.cs
@@ -5,6 +5,20 @@ namespace Org.BouncyCastle.Asn1.Cmp
     public class PkiMessage
         : Asn1Encodable
     {
+        public static PkiMessage GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is PkiMessage pkiMessage)
+                return pkiMessage;
+            return new PkiMessage(Asn1Sequence.GetInstance(obj));
+        }
+
+        public static PkiMessage GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
         private readonly PkiHeader header;
         private readonly PkiBody body;
         private readonly DerBitString protection;
@@ -17,30 +31,19 @@ namespace Org.BouncyCastle.Asn1.Cmp
 
             for (int pos = 2; pos < seq.Count; ++pos)
             {
-                Asn1TaggedObject tObj = (Asn1TaggedObject)seq[pos].ToAsn1Object();
+                Asn1TaggedObject tObj = Asn1TaggedObject.GetInstance(seq[pos]);
 
-                if (tObj.TagNo == 0)
+                if (tObj.HasContextTag(0))
                 {
                     protection = DerBitString.GetInstance(tObj, true);
                 }
-                else
+                else if (tObj.HasContextTag(1))
                 {
                     extraCerts = Asn1Sequence.GetInstance(tObj, true);
                 }
             }
         }
 
-        public static PkiMessage GetInstance(object obj)
-        {
-            if (obj is PkiMessage)
-                return (PkiMessage)obj;
-
-            if (obj != null)
-                return new PkiMessage(Asn1Sequence.GetInstance(obj));
-
-            return null;
-        }
-
         /**
          * Creates a new PkiMessage.
          *
diff --git a/crypto/src/asn1/cmp/PKIMessages.cs b/crypto/src/asn1/cmp/PKIMessages.cs
index 8e2e8a1ed..ea7550b9a 100644
--- a/crypto/src/asn1/cmp/PKIMessages.cs
+++ b/crypto/src/asn1/cmp/PKIMessages.cs
@@ -7,6 +7,20 @@ namespace Org.BouncyCastle.Asn1.Cmp
     public class PkiMessages
         : Asn1Encodable
     {
+        public static PkiMessages GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is PkiMessages pkiMessages)
+                return pkiMessages;
+            return new PkiMessages(Asn1Sequence.GetInstance(obj));
+        }
+
+        public static PkiMessages GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
         private Asn1Sequence m_content;
 
         internal PkiMessages(Asn1Sequence seq)
@@ -14,18 +28,12 @@ namespace Org.BouncyCastle.Asn1.Cmp
             m_content = seq;
         }
 
-        public static PkiMessages GetInstance(object obj)
+        internal PkiMessages(PkiMessages other)
         {
-            if (obj is PkiMessages pkiMessages)
-                return pkiMessages;
-
-            if (obj is Asn1Sequence asn1Sequence)
-                return new PkiMessages(asn1Sequence);
-
-            throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), nameof(obj));
+            m_content = other.m_content;
         }
 
-		public PkiMessages(params PkiMessage[] msgs)
+        public PkiMessages(params PkiMessage[] msgs)
         {
             m_content = new DerSequence(msgs);
         }
diff --git a/crypto/src/asn1/cmp/PKIStatus.cs b/crypto/src/asn1/cmp/PKIStatus.cs
index ba757dfcf..72b0c7403 100644
--- a/crypto/src/asn1/cmp/PKIStatus.cs
+++ b/crypto/src/asn1/cmp/PKIStatus.cs
@@ -27,7 +27,21 @@ namespace Org.BouncyCastle.Asn1.Cmp
 		public static readonly PkiStatusEncodable revocationNotification = new PkiStatusEncodable(PkiStatus.RevocationNotification);
 		public static readonly PkiStatusEncodable keyUpdateWaiting = new PkiStatusEncodable(PkiStatus.KeyUpdateWarning);
 
-		private readonly DerInteger status;
+        public static PkiStatusEncodable GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is PkiStatusEncodable pkiStatusEncodable)
+                return pkiStatusEncodable;
+            return new PkiStatusEncodable(DerInteger.GetInstance(obj));
+        }
+
+        public static PkiStatusEncodable GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(DerInteger.GetInstance(taggedObject, declaredExplicit));
+        }
+
+        private readonly DerInteger status;
 
 		private PkiStatusEncodable(PkiStatus status)
 			: this(new DerInteger((int)status))
@@ -39,17 +53,6 @@ namespace Org.BouncyCastle.Asn1.Cmp
 			this.status = status;
 		}
 
-		public static PkiStatusEncodable GetInstance(object obj)
-		{
-			if (obj is PkiStatusEncodable)
-				return (PkiStatusEncodable)obj;
-
-			if (obj is DerInteger)
-				return new PkiStatusEncodable((DerInteger)obj);
-
-            throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), "obj");
-		}
-
 		public virtual BigInteger Value
 		{
 			get { return status.Value; }
diff --git a/crypto/src/asn1/cmp/PKIStatusInfo.cs b/crypto/src/asn1/cmp/PKIStatusInfo.cs
index c9f64bfde..fe5cc718c 100644
--- a/crypto/src/asn1/cmp/PKIStatusInfo.cs
+++ b/crypto/src/asn1/cmp/PKIStatusInfo.cs
@@ -1,41 +1,36 @@
 using System;
 
 using Org.BouncyCastle.Math;
-using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Asn1.Cmp
 {
 	public class PkiStatusInfo
 		: Asn1Encodable
 	{
-		DerInteger      status;
-		PkiFreeText     statusString;
-		DerBitString    failInfo;
+        public static PkiStatusInfo GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is PkiStatusInfo pkiStatusInfo)
+                return pkiStatusInfo;
+#pragma warning disable CS0618 // Type or member is obsolete
+            return new PkiStatusInfo(Asn1Sequence.GetInstance(obj));
+#pragma warning restore CS0618 // Type or member is obsolete
+        }
 
-		public static PkiStatusInfo GetInstance(
-			Asn1TaggedObject obj,
-			bool isExplicit)
-		{
-			return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
-		}
-
-		public static PkiStatusInfo GetInstance(
-			object obj)
-		{
-			if (obj is PkiStatusInfo)
-			{
-				return (PkiStatusInfo)obj;
-			}
-			else if (obj is Asn1Sequence)
-			{
-				return new PkiStatusInfo((Asn1Sequence)obj);
-			}
+        public static PkiStatusInfo GetInstance(Asn1TaggedObject obj, bool isExplicit)
+        {
+#pragma warning disable CS0618 // Type or member is obsolete
+            return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+#pragma warning restore CS0618 // Type or member is obsolete
+        }
 
-            throw new ArgumentException("Unknown object in factory: " + Platform.GetTypeName(obj), "obj");
-		}
+		private readonly DerInteger status;
+		private readonly PkiFreeText statusString;
+		private readonly DerBitString failInfo;
 
-		public PkiStatusInfo(
-			Asn1Sequence seq)
+        [Obsolete("Use 'GetInstance' instead")]
+        public PkiStatusInfo(Asn1Sequence seq)
 		{
 			this.status = DerInteger.GetInstance(seq[0]);
 
@@ -61,59 +56,29 @@ namespace Org.BouncyCastle.Asn1.Cmp
 			}
 		}
 
-		/**
-		 * @param status
-		 */
 		public PkiStatusInfo(int status)
 		{
 			this.status = new DerInteger(status);
 		}
 
-		/**
-		 * @param status
-		 * @param statusString
-		 */
-		public PkiStatusInfo(
-			int			status,
-			PkiFreeText	statusString)
+		public PkiStatusInfo(int status, PkiFreeText statusString)
 		{
 			this.status = new DerInteger(status);
 			this.statusString = statusString;
 		}
 
-		public PkiStatusInfo(
-			int				status,
-			PkiFreeText		statusString,
-			PkiFailureInfo	failInfo)
-		{
-			this.status = new DerInteger(status);
+        public PkiStatusInfo(int status, PkiFreeText statusString, PkiFailureInfo failInfo)
+        {
+            this.status = new DerInteger(status);
 			this.statusString = statusString;
 			this.failInfo = failInfo;
 		}
 
-		public BigInteger Status
-		{
-			get
-			{
-				return status.Value;
-			}
-		}
+		public BigInteger Status => status.Value;
 
-		public PkiFreeText StatusString
-		{
-			get
-			{
-				return statusString;
-			}
-		}
+		public PkiFreeText StatusString => statusString;
 
-		public DerBitString FailInfo
-		{
-			get
-			{
-				return failInfo;
-			}
-		}
+		public DerBitString FailInfo => failInfo;
 
 		/**
 		 * <pre>
diff --git a/crypto/src/asn1/cmp/PbmParameter.cs b/crypto/src/asn1/cmp/PbmParameter.cs
index f4b702ed5..ae3fb5f8e 100644
--- a/crypto/src/asn1/cmp/PbmParameter.cs
+++ b/crypto/src/asn1/cmp/PbmParameter.cs
@@ -26,13 +26,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
     {
         public static PbmParameter GetInstance(object obj)
         {
+            if (obj == null)
+                return null;
             if (obj is PbmParameter pbmParameter)
                 return pbmParameter;
+            return new PbmParameter(Asn1Sequence.GetInstance(obj));
+        }
 
-            if (obj != null)
-                return new PbmParameter(Asn1Sequence.GetInstance(obj));
-
-            return null;
+        public static PbmParameter GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly Asn1OctetString m_salt;
diff --git a/crypto/src/asn1/cmp/PollRepContent.cs b/crypto/src/asn1/cmp/PollRepContent.cs
index 15f153a5d..e8af7b7e9 100644
--- a/crypto/src/asn1/cmp/PollRepContent.cs
+++ b/crypto/src/asn1/cmp/PollRepContent.cs
@@ -11,13 +11,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static PollRepContent GetInstance(object obj)
         {
-			if (obj is PollRepContent pollRepContent)
-				return pollRepContent;
-
-			if (obj != null)
-				return new PollRepContent(Asn1Sequence.GetInstance(obj));
+            if (obj == null)
+                return null;
+            if (obj is PollRepContent pollRepContent)
+                return pollRepContent;
+            return new PollRepContent(Asn1Sequence.GetInstance(obj));
+        }
 
-			return null;
+        public static PollRepContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly DerInteger[] m_certReqID;
diff --git a/crypto/src/asn1/cmp/PollReqContent.cs b/crypto/src/asn1/cmp/PollReqContent.cs
index 80a39348a..31320416e 100644
--- a/crypto/src/asn1/cmp/PollReqContent.cs
+++ b/crypto/src/asn1/cmp/PollReqContent.cs
@@ -7,13 +7,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static PollReqContent GetInstance(object obj)
         {
-			if (obj is PollReqContent pollReqContent)
-				return pollReqContent;
-
-			if (obj != null)
-				return new PollReqContent(Asn1Sequence.GetInstance(obj));
+            if (obj == null)
+                return null;
+            if (obj is PollReqContent pollReqContent)
+                return pollReqContent;
+            return new PollReqContent(Asn1Sequence.GetInstance(obj));
+        }
 
-			return null;
+        public static PollReqContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly Asn1Sequence m_content;
@@ -65,24 +68,13 @@ namespace Org.BouncyCastle.Asn1.Cmp
 
 		public virtual DerInteger[][] GetCertReqIDs()
 		{
-			DerInteger[][] result = new DerInteger[m_content.Count][];
-			for (int i = 0; i != result.Length; ++i)
-			{
-				result[i] = SequenceToDerIntegerArray((Asn1Sequence)m_content[i]);
-			}
-			return result;
+            return m_content.MapElements(
+				element => Asn1Sequence.GetInstance(element).MapElements(DerInteger.GetInstance));
 		}
 
         public virtual BigInteger[] GetCertReqIDValues()
         {
-            BigInteger[] result = new BigInteger[m_content.Count];
-
-            for (int i = 0; i != result.Length; i++)
-            {
-                result[i] = DerInteger.GetInstance(Asn1Sequence.GetInstance(m_content[i])[0]).Value;
-            }
-
-            return result;
+			return m_content.MapElements(element => DerInteger.GetInstance(Asn1Sequence.GetInstance(element)[0]).Value);
         }
 
         /**
@@ -98,11 +90,6 @@ namespace Org.BouncyCastle.Asn1.Cmp
 			return m_content;
 		}
 
-		private static DerInteger[] SequenceToDerIntegerArray(Asn1Sequence seq)
-		{
-			return seq.MapElements(DerInteger.GetInstance);
-		}
-
 		private static DerSequence[] IntsToSequence(DerInteger[] ids)
 		{
 			DerSequence[] result = new DerSequence[ids.Length];
diff --git a/crypto/src/asn1/cmp/PopoDecKeyChallContent.cs b/crypto/src/asn1/cmp/PopoDecKeyChallContent.cs
index 0bd1597c8..20dadd232 100644
--- a/crypto/src/asn1/cmp/PopoDecKeyChallContent.cs
+++ b/crypto/src/asn1/cmp/PopoDecKeyChallContent.cs
@@ -7,13 +7,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static PopoDecKeyChallContent GetInstance(object obj)
         {
-			if (obj is PopoDecKeyChallContent popoDecKeyChallContent)
-				return popoDecKeyChallContent;
-
-            if (obj != null)
-                return new PopoDecKeyChallContent(Asn1Sequence.GetInstance(obj));
+            if (obj == null)
+                return null;
+            if (obj is PopoDecKeyChallContent popoDecKeyChallContent)
+                return popoDecKeyChallContent;
+            return new PopoDecKeyChallContent(Asn1Sequence.GetInstance(obj));
+        }
 
-            return null;
+        public static PopoDecKeyChallContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly Asn1Sequence m_content;
diff --git a/crypto/src/asn1/cmp/PopoDecKeyRespContent.cs b/crypto/src/asn1/cmp/PopoDecKeyRespContent.cs
index 77d720271..8344e4ae9 100644
--- a/crypto/src/asn1/cmp/PopoDecKeyRespContent.cs
+++ b/crypto/src/asn1/cmp/PopoDecKeyRespContent.cs
@@ -5,13 +5,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static PopoDecKeyRespContent GetInstance(object obj)
         {
-			if (obj is PopoDecKeyRespContent popoDecKeyRespContent)
-				return popoDecKeyRespContent;
-
-			if (obj != null)
-				return new PopoDecKeyRespContent(Asn1Sequence.GetInstance(obj));
+            if (obj == null)
+                return null;
+            if (obj is PopoDecKeyRespContent popoDecKeyRespContent)
+                return popoDecKeyRespContent;
+            return new PopoDecKeyRespContent(Asn1Sequence.GetInstance(obj));
+        }
 
-			return null;
+        public static PopoDecKeyRespContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly Asn1Sequence m_content;
diff --git a/crypto/src/asn1/cmp/ProtectedPart.cs b/crypto/src/asn1/cmp/ProtectedPart.cs
index fc83ac6c6..863a85e17 100644
--- a/crypto/src/asn1/cmp/ProtectedPart.cs
+++ b/crypto/src/asn1/cmp/ProtectedPart.cs
@@ -5,13 +5,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static ProtectedPart GetInstance(object obj)
         {
-			if (obj is ProtectedPart protectedPart)
-				return protectedPart;
-
-			if (obj != null)
-				return new ProtectedPart(Asn1Sequence.GetInstance(obj));
+            if (obj == null)
+                return null;
+            if (obj is ProtectedPart popoDecKeyRespContent)
+                return popoDecKeyRespContent;
+            return new ProtectedPart(Asn1Sequence.GetInstance(obj));
+        }
 
-			return null;
+        public static ProtectedPart GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly PkiHeader m_header;
diff --git a/crypto/src/asn1/cmp/RevAnnContent.cs b/crypto/src/asn1/cmp/RevAnnContent.cs
index cdd26c39f..1d3957759 100644
--- a/crypto/src/asn1/cmp/RevAnnContent.cs
+++ b/crypto/src/asn1/cmp/RevAnnContent.cs
@@ -8,13 +8,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static RevAnnContent GetInstance(object obj)
         {
-			if (obj is RevAnnContent revAnnContent)
-				return revAnnContent;
-
-			if (obj != null)
-				return new RevAnnContent(Asn1Sequence.GetInstance(obj));
+            if (obj == null)
+                return null;
+            if (obj is RevAnnContent revAnnContent)
+                return revAnnContent;
+            return new RevAnnContent(Asn1Sequence.GetInstance(obj));
+        }
 
-			return null;
+        public static RevAnnContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly PkiStatusEncodable m_status;
diff --git a/crypto/src/asn1/cmp/RevDetails.cs b/crypto/src/asn1/cmp/RevDetails.cs
index 9472d7775..79b30044a 100644
--- a/crypto/src/asn1/cmp/RevDetails.cs
+++ b/crypto/src/asn1/cmp/RevDetails.cs
@@ -20,13 +20,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static RevDetails GetInstance(object obj)
         {
-			if (obj is RevDetails revDetails)
-				return revDetails;
-
-			if (obj != null)
-				return new RevDetails(Asn1Sequence.GetInstance(obj));
+            if (obj == null)
+                return null;
+            if (obj is RevDetails revDetails)
+                return revDetails;
+            return new RevDetails(Asn1Sequence.GetInstance(obj));
+        }
 
-			return null;
+        public static RevDetails GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly CertTemplate m_certDetails;
diff --git a/crypto/src/asn1/cmp/RevRepContent.cs b/crypto/src/asn1/cmp/RevRepContent.cs
index 841b3cf94..762df12cd 100644
--- a/crypto/src/asn1/cmp/RevRepContent.cs
+++ b/crypto/src/asn1/cmp/RevRepContent.cs
@@ -3,7 +3,7 @@ using Org.BouncyCastle.Asn1.X509;
 
 namespace Org.BouncyCastle.Asn1.Cmp
 {
-    /**
+	/**
      * <pre>
      * RevRepContent ::= SEQUENCE {
      *          status       SEQUENCE SIZE (1..MAX) OF PKIStatusInfo,
@@ -17,18 +17,21 @@ namespace Org.BouncyCastle.Asn1.Cmp
      *      }
      *</pre>
      */
-    public class RevRepContent
+	public class RevRepContent
 		: Asn1Encodable
 	{
         public static RevRepContent GetInstance(object obj)
         {
-			if (obj is RevRepContent revRepContent)
-				return revRepContent;
-
-			if (obj != null)
-				return new RevRepContent(Asn1Sequence.GetInstance(obj));
+            if (obj == null)
+                return null;
+            if (obj is RevRepContent revRepContent)
+                return revRepContent;
+            return new RevRepContent(Asn1Sequence.GetInstance(obj));
+        }
 
-			return null;
+        public static RevRepContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly Asn1Sequence m_status;
@@ -43,11 +46,11 @@ namespace Org.BouncyCastle.Asn1.Cmp
 			{
 				Asn1TaggedObject tObj = Asn1TaggedObject.GetInstance(seq[pos]);
 
-				if (tObj.TagNo == 0)
+				if (tObj.HasContextTag(0))
 				{
 					m_revCerts = Asn1Sequence.GetInstance(tObj, true);
 				}
-				else
+				else if (tObj.HasContextTag(1))
 				{
 					m_crls = Asn1Sequence.GetInstance(tObj, true);
 				}
@@ -61,18 +64,12 @@ namespace Org.BouncyCastle.Asn1.Cmp
 
 		public virtual CertId[] GetRevCerts()
 		{
-			if (m_revCerts == null)
-				return null;
-
-			return m_revCerts.MapElements(CertId.GetInstance);
+			return m_revCerts?.MapElements(CertId.GetInstance);
 		}
 
 		public virtual CertificateList[] GetCrls()
 		{
-			if (m_crls == null)
-				return null;
-
-			return m_crls.MapElements(CertificateList.GetInstance);
+			return m_crls?.MapElements(CertificateList.GetInstance);
 		}
 
 		/**
diff --git a/crypto/src/asn1/cmp/RevReqContent.cs b/crypto/src/asn1/cmp/RevReqContent.cs
index c390530a8..eea65869e 100644
--- a/crypto/src/asn1/cmp/RevReqContent.cs
+++ b/crypto/src/asn1/cmp/RevReqContent.cs
@@ -1,7 +1,3 @@
-using System;
-
-using Org.BouncyCastle.Utilities;
-
 namespace Org.BouncyCastle.Asn1.Cmp
 {
 	public class RevReqContent
@@ -9,13 +5,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
 	{
         public static RevReqContent GetInstance(object obj)
         {
-			if (obj is RevReqContent revReqContent)
-				return revReqContent;
-
-			if (obj != null)
-				return new RevReqContent(Asn1Sequence.GetInstance(obj));
+            if (obj == null)
+                return null;
+            if (obj is RevReqContent revReqContent)
+                return revReqContent;
+            return new RevReqContent(Asn1Sequence.GetInstance(obj));
+        }
 
-			return null;
+        public static RevReqContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly Asn1Sequence m_content;
diff --git a/crypto/src/asn1/cmp/RootCaKeyUpdateContent.cs b/crypto/src/asn1/cmp/RootCaKeyUpdateContent.cs
index 696b08b94..64da80d6c 100644
--- a/crypto/src/asn1/cmp/RootCaKeyUpdateContent.cs
+++ b/crypto/src/asn1/cmp/RootCaKeyUpdateContent.cs
@@ -22,13 +22,16 @@ namespace Org.BouncyCastle.Asn1.Cmp
     {
         public static RootCaKeyUpdateContent GetInstance(object obj)
         {
+            if (obj == null)
+                return null;
             if (obj is RootCaKeyUpdateContent rootCaKeyUpdateContent)
                 return rootCaKeyUpdateContent;
+            return new RootCaKeyUpdateContent(Asn1Sequence.GetInstance(obj));
+        }
 
-            if (obj != null)
-                return new RootCaKeyUpdateContent(Asn1Sequence.GetInstance(obj));
-
-            return null;
+        public static RootCaKeyUpdateContent GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
         private readonly CmpCertificate m_newWithNew;
@@ -50,20 +53,19 @@ namespace Org.BouncyCastle.Asn1.Cmp
             if (seq.Count < 1 || seq.Count > 3)
                 throw new ArgumentException("expected sequence of 1 to 3 elements only");
 
-            CmpCertificate newWithNew;
+            CmpCertificate newWithNew = CmpCertificate.GetInstance(seq[0]);
             CmpCertificate newWithOld = null;
             CmpCertificate oldWithNew = null;
 
-            newWithNew = CmpCertificate.GetInstance(seq[0]);
-
             for (int pos = 1; pos < seq.Count; ++pos)
             {
                 Asn1TaggedObject ato = Asn1TaggedObject.GetInstance(seq[pos]);
-                if (ato.TagNo == 0)
+
+                if (ato.HasContextTag(0))
                 {
                     newWithOld = CmpCertificate.GetInstance(ato, true);
                 }
-                else if (ato.TagNo == 1)
+                else if (ato.HasContextTag(1))
                 {
                     oldWithNew = CmpCertificate.GetInstance(ato, true);
                 }
diff --git a/crypto/src/asn1/x509/AttributeCertificate.cs b/crypto/src/asn1/x509/AttributeCertificate.cs
index 41893b6b4..7ec79cc4b 100644
--- a/crypto/src/asn1/x509/AttributeCertificate.cs
+++ b/crypto/src/asn1/x509/AttributeCertificate.cs
@@ -1,44 +1,37 @@
 using System;
 
-using Org.BouncyCastle.Asn1;
-
 namespace Org.BouncyCastle.Asn1.X509
 {
     public class AttributeCertificate
         : Asn1Encodable
     {
-        private readonly AttributeCertificateInfo	acinfo;
-        private readonly AlgorithmIdentifier		signatureAlgorithm;
-        private readonly DerBitString				signatureValue;
-
-		/**
-         * @param obj
-         * @return
-         */
-        public static AttributeCertificate GetInstance(
-			object obj)
+        public static AttributeCertificate GetInstance(object obj)
         {
-            if (obj is AttributeCertificate)
-                return (AttributeCertificate) obj;
+            if (obj == null)
+                return null;
+            if (obj is AttributeCertificate attributeCertificate)
+                return attributeCertificate;
+            return new AttributeCertificate(Asn1Sequence.GetInstance(obj));
+        }
 
-			if (obj != null)
-				return new AttributeCertificate(Asn1Sequence.GetInstance(obj));
+        public static AttributeCertificate GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+        {
+            return new AttributeCertificate(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
 
-			return null;
-		}
+        private readonly AttributeCertificateInfo acinfo;
+        private readonly AlgorithmIdentifier signatureAlgorithm;
+        private readonly DerBitString signatureValue;
 
-		public AttributeCertificate(
-            AttributeCertificateInfo	acinfo,
-            AlgorithmIdentifier			signatureAlgorithm,
-            DerBitString				signatureValue)
+        public AttributeCertificate(AttributeCertificateInfo acinfo, AlgorithmIdentifier signatureAlgorithm,
+            DerBitString signatureValue)
         {
             this.acinfo = acinfo;
             this.signatureAlgorithm = signatureAlgorithm;
             this.signatureValue = signatureValue;
         }
 
-		private AttributeCertificate(
-            Asn1Sequence seq)
+		private AttributeCertificate(Asn1Sequence seq)
         {
 			if (seq.Count != 3)
 				throw new ArgumentException("Bad sequence size: " + seq.Count);
diff --git a/crypto/src/tsp/TimeStampResponseGenerator.cs b/crypto/src/tsp/TimeStampResponseGenerator.cs
index 76b400d6e..cf298f936 100644
--- a/crypto/src/tsp/TimeStampResponseGenerator.cs
+++ b/crypto/src/tsp/TimeStampResponseGenerator.cs
@@ -80,7 +80,7 @@ namespace Org.BouncyCastle.Tsp
                 v.Add(new FailInfo(failInfo));
             }
 
-            return new PkiStatusInfo(new DerSequence(v));
+            return PkiStatusInfo.GetInstance(new DerSequence(v));
         }
 
         /**