summary refs log tree commit diff
path: root/crypto/src/asn1/crmf/PopoPrivKey.cs
blob: 91b1ddba466084cdc7262947bbda03021d950839 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
using System;

using Org.BouncyCastle.Asn1.Cms;
using Org.BouncyCastle.Utilities;

namespace Org.BouncyCastle.Asn1.Crmf
{
    public class PopoPrivKey
        : Asn1Encodable, IAsn1Choice
    {
        public const int thisMessage = 0;
        public const int subsequentMessage = 1;
        public const int dhMAC = 2;
        public const int agreeMAC = 3;
        public const int encryptedKey = 4;

        public static PopoPrivKey GetInstance(object obj)
        {
            if (obj == null)
                return null;

            if (obj is Asn1Encodable element)
            {
                var result = GetOptional(element);
                if (result != null)
                    return result;
            }

            throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), nameof(obj));
        }

        public static PopoPrivKey GetInstance(Asn1TaggedObject tagged, bool isExplicit)
        {
            return Asn1Utilities.GetInstanceFromChoice(tagged, isExplicit, GetInstance);
        }

        public static PopoPrivKey GetOptional(Asn1Encodable element)
        {
            if (element == null)
                throw new ArgumentNullException(nameof(element));

            if (element is PopoPrivKey popoPrivKey)
                return popoPrivKey;

            if (element is Asn1TaggedObject taggedObject)
            {
                Asn1Encodable baseObject = GetOptionalBaseObject(taggedObject);
                if (baseObject != null)
                    return new PopoPrivKey(taggedObject.TagNo, baseObject);
            }

            return null;
        }

        private static Asn1Encodable GetOptionalBaseObject(Asn1TaggedObject taggedObject)
        {
            if (taggedObject.HasContextTag())
            {
                switch (taggedObject.TagNo)
                {
                case thisMessage:
                case dhMAC:
                    return DerBitString.GetInstance(taggedObject, false);
                case subsequentMessage:
                    return SubsequentMessage.ValueOf(DerInteger.GetInstance(taggedObject, false).IntValueExact);
                case agreeMAC:
                    return PKMacValue.GetInstance(taggedObject, false);
                case encryptedKey:
                    return EnvelopedData.GetInstance(taggedObject, false);

                }
            }
            return null;
        }

        private readonly int m_tagNo;
        private readonly Asn1Encodable m_obj;

        private PopoPrivKey(int tagNo, Asn1Encodable obj)
        {
            m_tagNo = tagNo;
            m_obj = obj ?? throw new ArgumentNullException(nameof(obj));
        }

        public PopoPrivKey(PKMacValue pkMacValue)
            : this(agreeMAC, pkMacValue)
        {
        }

        public PopoPrivKey(SubsequentMessage msg)
            : this(subsequentMessage, msg)
        {
        }

        public virtual int Type => m_tagNo;

        public virtual Asn1Encodable Value => m_obj;

        /**
         * <pre>
         * PopoPrivKey ::= CHOICE {
         *        thisMessage       [0] BIT STRING,         -- Deprecated
         *         -- possession is proven in this message (which contains the private
         *         -- key itself (encrypted for the CA))
         *        subsequentMessage [1] SubsequentMessage,
         *         -- possession will be proven in a subsequent message
         *        dhMAC             [2] BIT STRING,         -- Deprecated
         *        agreeMAC          [3] PKMACValue,
         *        encryptedKey      [4] EnvelopedData }
         * </pre>
         */
        public override Asn1Object ToAsn1Object() => new DerTaggedObject(false, m_tagNo, m_obj);
    }
}