summary refs log tree commit diff
path: root/crypto/src/asn1/cms/AuthEnvelopedData.cs
blob: 62d54b33e25ecbb487cb92c17508e5ca31b2053c (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
using System;

namespace Org.BouncyCastle.Asn1.Cms
{
    public class AuthEnvelopedData
		: Asn1Encodable
	{
        public static AuthEnvelopedData GetInstance(object obj)
        {
            if (obj == null)
                return null;
            if (obj is AuthEnvelopedData authEnvelopedData)
                return authEnvelopedData;
            return new AuthEnvelopedData(Asn1Sequence.GetInstance(obj));
        }

        public static AuthEnvelopedData GetInstance(Asn1TaggedObject obj, bool isExplicit)
        {
            return new AuthEnvelopedData(Asn1Sequence.GetInstance(obj, isExplicit));
        }

        private readonly DerInteger m_version;
        private readonly OriginatorInfo m_originatorInfo;
        private readonly Asn1Set m_recipientInfos;
        private readonly EncryptedContentInfo m_authEncryptedContentInfo;
        private readonly Asn1Set m_authAttrs;
        private readonly Asn1OctetString m_mac;
        private readonly Asn1Set m_unauthAttrs;

        public AuthEnvelopedData(OriginatorInfo originatorInfo, Asn1Set recipientInfos,
			EncryptedContentInfo authEncryptedContentInfo, Asn1Set authAttrs, Asn1OctetString mac,
			Asn1Set unauthAttrs)
        {
            m_version = DerInteger.Zero;
			m_originatorInfo = originatorInfo;
			m_recipientInfos = recipientInfos ?? throw new ArgumentNullException(nameof(recipientInfos));
			m_authEncryptedContentInfo = authEncryptedContentInfo ?? throw new ArgumentNullException(nameof(authEncryptedContentInfo));
            m_authAttrs = authAttrs;
			m_mac = mac ?? throw new ArgumentNullException(nameof(mac));
			m_unauthAttrs = unauthAttrs;

            Validate();
        }

        private AuthEnvelopedData(Asn1Sequence seq)
		{
            int count = seq.Count, pos = 0;
            if (count < 4 || count > 7)
                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));

            m_version = DerInteger.GetInstance(seq[pos++]);
            m_originatorInfo = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, OriginatorInfo.GetInstance);
            m_recipientInfos = Asn1Set.GetInstance(seq[pos++]);
            m_authEncryptedContentInfo = EncryptedContentInfo.GetInstance(seq[pos++]);
            m_authAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetInstance);
            m_mac = Asn1OctetString.GetInstance(seq[pos++]);
            m_unauthAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, false, Asn1Set.GetInstance);

            if (pos != count)
                throw new ArgumentException("Unexpected elements in sequence", nameof(seq));

            Validate();
		}

        private void Validate()
        {
            // "It MUST be set to 0."
            if (!m_version.HasValue(0))
                throw new ArgumentException("AuthEnvelopedData version number must be 0");

            // "There MUST be at least one element in the collection."
            if (m_recipientInfos.Count < 1)
                throw new ArgumentException("AuthEnvelopedData requires at least 1 RecipientInfo");

            // "The authAttrs MUST be present if the content type carried in EncryptedContentInfo is not id-data."
            if (!CmsObjectIdentifiers.Data.Equals(m_authEncryptedContentInfo.ContentType))
            {
                if (m_authAttrs == null || m_authAttrs.Count < 1)
                    throw new ArgumentException("authAttrs must be present with non-data content");
            }
        }

        public DerInteger Version => m_version;

		public OriginatorInfo OriginatorInfo => m_originatorInfo;

		public Asn1Set RecipientInfos => m_recipientInfos;

		public EncryptedContentInfo AuthEncryptedContentInfo => m_authEncryptedContentInfo;

		public Asn1Set AuthAttrs => m_authAttrs;

		public Asn1OctetString Mac => m_mac;

		public Asn1Set UnauthAttrs => m_unauthAttrs;

		/**
		 * Produce an object suitable for an Asn1OutputStream.
		 * <pre>
		 * AuthEnvelopedData ::= SEQUENCE {
		 *   version CMSVersion,
		 *   originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
		 *   recipientInfos RecipientInfos,
		 *   authEncryptedContentInfo EncryptedContentInfo,
		 *   authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
		 *   mac MessageAuthenticationCode,
		 *   unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }
		 * </pre>
		 */
	    public override Asn1Object ToAsn1Object()
		{
			Asn1EncodableVector v = new Asn1EncodableVector(7);
			v.Add(m_version);
            v.AddOptionalTagged(false, 0, m_originatorInfo);
			v.Add(m_recipientInfos, m_authEncryptedContentInfo);

			// "authAttrs optionally contains the authenticated attributes."
            // "AuthAttributes MUST be DER encoded, even if the rest of the
            // AuthEnvelopedData structure is BER encoded."
            v.AddOptionalTagged(false, 1, m_authAttrs);

            v.Add(m_mac);

            // "unauthAttrs optionally contains the unauthenticated attributes."
            v.AddOptionalTagged(false, 2, m_unauthAttrs);

            return new BerSequence(v);
		}
	}
}