summary refs log tree commit diff
path: root/crypto/src/asn1/crmf/ProofOfPossession.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/asn1/crmf/ProofOfPossession.cs')
-rw-r--r--crypto/src/asn1/crmf/ProofOfPossession.cs99
1 files changed, 60 insertions, 39 deletions
diff --git a/crypto/src/asn1/crmf/ProofOfPossession.cs b/crypto/src/asn1/crmf/ProofOfPossession.cs
index 6ef62efda..0e6a64dac 100644
--- a/crypto/src/asn1/crmf/ProofOfPossession.cs
+++ b/crypto/src/asn1/crmf/ProofOfPossession.cs
@@ -1,5 +1,6 @@
 using System;
 
+using Org.BouncyCastle.Tls;
 using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Asn1.Crmf
@@ -12,53 +13,79 @@ namespace Org.BouncyCastle.Asn1.Crmf
         public const int TYPE_KEY_ENCIPHERMENT = 2;
         public const int TYPE_KEY_AGREEMENT = 3;
 
-        private readonly int tagNo;
-        private readonly Asn1Encodable obj;
-
-        private ProofOfPossession(Asn1TaggedObject tagged)
+        public static ProofOfPossession GetInstance(object obj)
         {
-            tagNo = tagged.TagNo;
-            switch (tagNo)
+            if (obj == null)
+                return null;
+
+            if (obj is Asn1Encodable element)
             {
-            case 0:
-                obj = DerNull.Instance;
-                break;
-            case 1:
-                obj = PopoSigningKey.GetInstance(tagged, false);
-                break;
-            case 2:
-            case 3:
-                // CHOICE so explicit
-                obj = PopoPrivKey.GetInstance(tagged, true);
-                break;
-            default:
-                throw new ArgumentException("unknown tag: " + tagNo, "tagged");
+                var result = GetOptional(element);
+                if (result != null)
+                    return result;
             }
+
+            throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), nameof(obj));
         }
 
-        public static ProofOfPossession GetInstance(object obj)
+        public static ProofOfPossession GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
         {
-            if (obj is ProofOfPossession proofOfPossession)
+            return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
+        }
+
+        public static ProofOfPossession GetOptional(Asn1Encodable element)
+        {
+            if (element == null)
+                throw new ArgumentNullException(nameof(element));
+            if (element is ProofOfPossession proofOfPossession)
                 return proofOfPossession;
+            if (element is Asn1TaggedObject taggedObject)
+            {
+                Asn1Encodable baseObject = GetOptionalBaseObject(taggedObject);
+                if (baseObject != null)
+                    return new ProofOfPossession(taggedObject.TagNo, baseObject);
+            }
+            return null;
+        }
 
-            if (obj is Asn1TaggedObject taggedObject)
-                return new ProofOfPossession(taggedObject);
+        private static Asn1Encodable GetOptionalBaseObject(Asn1TaggedObject taggedObject)
+        {
+            if (taggedObject.HasContextTag())
+            {
+                switch (taggedObject.TagNo)
+                {
+                case 0:
+                    return DerNull.GetInstance(taggedObject, false);
+                case 1:
+                    return PopoSigningKey.GetInstance(taggedObject, false);
+                case 2:
+                case 3:
+                    // CHOICE so explicit
+                    return PopoPrivKey.GetInstance(taggedObject, true);
+                }
+            }
+            return null;
+        }
+
+        private readonly int m_tagNo;
+        private readonly Asn1Encodable m_obj;
 
-            throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), "obj");
+        private ProofOfPossession(int tagNo, Asn1Encodable obj)
+        {
+            m_tagNo = tagNo;
+            m_obj = obj ?? throw new ArgumentNullException(nameof(obj));
         }
 
         /** Creates a ProofOfPossession with type raVerified. */
         public ProofOfPossession()
+            : this(TYPE_RA_VERIFIED, DerNull.Instance)
         {
-            tagNo = TYPE_RA_VERIFIED;
-            obj = DerNull.Instance;
         }
 
         /** Creates a ProofOfPossession for a signing key. */
         public ProofOfPossession(PopoSigningKey Poposk)
+            : this(TYPE_SIGNING_KEY, Poposk)
         {
-            tagNo = TYPE_SIGNING_KEY;
-            obj = Poposk;
         }
 
         /**
@@ -66,20 +93,13 @@ namespace Org.BouncyCastle.Asn1.Crmf
          * @param type one of TYPE_KEY_ENCIPHERMENT or TYPE_KEY_AGREEMENT
          */
         public ProofOfPossession(int type, PopoPrivKey privkey)
+            : this(type, (Asn1Encodable)privkey)
         {
-            tagNo = type;
-            obj = privkey;
         }
 
-        public virtual int Type
-        {
-            get { return tagNo; }
-        }
+        public virtual int Type => m_tagNo;
 
-        public virtual Asn1Encodable Object
-        {
-            get { return obj; }
-        }
+        public virtual Asn1Encodable Object => m_obj;
 
         /**
          * <pre>
@@ -95,7 +115,8 @@ namespace Org.BouncyCastle.Asn1.Crmf
          */
         public override Asn1Object ToAsn1Object()
         {
-            return new DerTaggedObject(false, tagNo, obj);
+            // NOTE: Explicit tagging automatically applied for PopoPrivKey (a CHOICE)
+            return new DerTaggedObject(false, m_tagNo, m_obj);
         }
     }
 }