summary refs log tree commit diff
path: root/crypto/src/asn1/cmp/KemOtherInfo.cs
blob: 3185495fc07e255d9174e1a4948c99b9f3c5d62f (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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
using System;

using Org.BouncyCastle.Asn1.X509;

namespace Org.BouncyCastle.Asn1.Cmp
{
    /*
     * <pre>
     * KemOtherInfo ::= SEQUENCE {
     *   staticString      PKIFreeText,  -- MUST be "CMP-KEM"
     *   transactionID [0] OCTET STRING     OPTIONAL,
     *   senderNonce   [1] OCTET STRING     OPTIONAL,
     *   recipNonce    [2] OCTET STRING     OPTIONAL,
     *   len               INTEGER (1..MAX),
     *   mac               AlgorithmIdentifier{MAC-ALGORITHM, {...}}
     *   ct                OCTET STRING
     * }
     * </pre>
     */
    public class KemOtherInfo
        : Asn1Encodable
    {
        public static KemOtherInfo GetInstance(object obj)
        {
            if (obj == null)
                return null;
            if (obj is KemOtherInfo kemOtherInfo)
                return kemOtherInfo;
            return new KemOtherInfo(Asn1Sequence.GetInstance(obj));
        }

        public static KemOtherInfo GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
            new KemOtherInfo(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));

        private static readonly PkiFreeText DEFAULT_staticString = new PkiFreeText("CMP-KEM");

        private readonly PkiFreeText m_staticString;
        private readonly Asn1OctetString m_transactionID;
        private readonly Asn1OctetString m_senderNonce;
        private readonly Asn1OctetString m_recipNonce;
        private readonly DerInteger m_len;
        private readonly AlgorithmIdentifier m_mac;
        private readonly Asn1OctetString m_ct;

        public KemOtherInfo(Asn1OctetString transactionID, Asn1OctetString senderNonce, Asn1OctetString recipNonce,
            DerInteger len, AlgorithmIdentifier mac, Asn1OctetString ct)
        {
            m_staticString = DEFAULT_staticString;
            m_transactionID = transactionID;
            m_senderNonce = senderNonce;
            m_recipNonce = recipNonce;
            m_len = len;
            m_mac = mac;
            m_ct = ct;
        }

        public KemOtherInfo(Asn1OctetString transactionID, Asn1OctetString senderNonce, Asn1OctetString recipNonce,
            long len, AlgorithmIdentifier mac, Asn1OctetString ct)
            : this(transactionID, senderNonce, recipNonce, new DerInteger(len), mac, ct)
        {
        }

        private KemOtherInfo(Asn1Sequence seq)
        {
            if (seq.Count < 4 || seq.Count > 7)
                throw new ArgumentException("sequence size should be between 4 and 7 inclusive", nameof(seq));

            int seqPos = 0;

            m_staticString = PkiFreeText.GetInstance(seq[seqPos]);
            if (!DEFAULT_staticString.Equals(m_staticString))
                throw new ArgumentException("staticString field should be " + DEFAULT_staticString);

            Asn1TaggedObject tagged = seq[++seqPos] as Asn1TaggedObject;

            if (tagged != null &&
                Asn1Utilities.TryGetContextBaseUniversal(tagged, 0, true, Asn1Tags.OctetString, out var transactionID))
            {
                m_transactionID = (Asn1OctetString)transactionID;
                tagged = seq[++seqPos] as Asn1TaggedObject;
            }

            if (tagged != null &&
                Asn1Utilities.TryGetContextBaseUniversal(tagged, 1, true, Asn1Tags.OctetString, out var senderNonce))
            {
                m_senderNonce = (Asn1OctetString)senderNonce;
                tagged = seq[++seqPos] as Asn1TaggedObject;
            }

            if (tagged != null &&
                Asn1Utilities.TryGetContextBaseUniversal(tagged, 2, true, Asn1Tags.OctetString, out var recipNonce))
            {
                m_recipNonce = (Asn1OctetString)recipNonce;
                tagged = seq[++seqPos] as Asn1TaggedObject;
            }

            if (tagged != null)
                throw new ArgumentException("unknown tag: " + Asn1Utilities.GetTagText(tagged));

            m_len = DerInteger.GetInstance(seq[seqPos]);
            m_mac = AlgorithmIdentifier.GetInstance(seq[++seqPos]);
            m_ct = Asn1OctetString.GetInstance(seq[++seqPos]);

            if (++seqPos != seq.Count)
                throw new ArgumentException("unexpected data at end of sequence", nameof(seq));
        }

        public virtual Asn1OctetString TransactionID => m_transactionID;

        public virtual Asn1OctetString SenderNonce => m_senderNonce;

        public virtual Asn1OctetString RecipNonce => m_recipNonce;

        public virtual DerInteger Len => m_len;

        public virtual AlgorithmIdentifier Mac => m_mac;

        public virtual Asn1OctetString Ct => m_ct;

        /**
         * <pre>
         * KemOtherInfo ::= SEQUENCE {
         *   staticString      PKIFreeText,   -- MUST be "CMP-KEM"
         *   transactionID [0] OCTET STRING     OPTIONAL,
         *   senderNonce   [1] OCTET STRING     OPTIONAL,
         *   recipNonce    [2] OCTET STRING     OPTIONAL,
         *   len               INTEGER (1..MAX),
         *   mac               AlgorithmIdentifier{MAC-ALGORITHM, {...}}
         *   ct                OCTET STRING
         * }
         * </pre>
         *
         * @return a basic ASN.1 object representation.
         */
        public override Asn1Object ToAsn1Object()
        {
            Asn1EncodableVector v = new Asn1EncodableVector(7);

            v.Add(m_staticString);
            v.AddOptionalTagged(true, 0, m_transactionID);
            v.AddOptionalTagged(true, 1, m_senderNonce);
            v.AddOptionalTagged(true, 2, m_recipNonce);
            v.Add(m_len);
            v.Add(m_mac);
            v.Add(m_ct);

            return new DerSequence(v);
        }
    }
}