mirrored from https://www.bouncycastle.org/repositories/bc-csharp
-
Notifications
You must be signed in to change notification settings - Fork 602
Expand file tree
/
Copy pathCMSUtils.cs
More file actions
381 lines (312 loc) · 14.8 KB
/
Copy pathCMSUtils.cs
File metadata and controls
381 lines (312 loc) · 14.8 KB
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
using System;
using System.Collections.Generic;
using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Cms;
using Org.BouncyCastle.Asn1.CryptoPro;
using Org.BouncyCastle.Asn1.Ocsp;
using Org.BouncyCastle.Asn1.Oiw;
using Org.BouncyCastle.Asn1.Rosstandart;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.Utilities.IO;
using Org.BouncyCastle.X509;
namespace Org.BouncyCastle.Cms
{
internal static class CmsUtilities
{
private static readonly HashSet<DerObjectIdentifier> DesAlgorithms = new HashSet<DerObjectIdentifier>();
private static readonly HashSet<DerObjectIdentifier> ECAlgorithms = new HashSet<DerObjectIdentifier>();
private static readonly HashSet<DerObjectIdentifier> GostAlgorithms = new HashSet<DerObjectIdentifier>();
private static readonly HashSet<DerObjectIdentifier> MqvAlgorithms = new HashSet<DerObjectIdentifier>();
static CmsUtilities()
{
DesAlgorithms.Add(OiwObjectIdentifiers.DesCbc);
DesAlgorithms.Add(Asn1.Pkcs.PkcsObjectIdentifiers.DesEde3Cbc);
DesAlgorithms.Add(Asn1.Pkcs.PkcsObjectIdentifiers.IdAlgCms3DesWrap);
ECAlgorithms.Add(X9ObjectIdentifiers.DHSinglePassStdDHSha1KdfScheme);
ECAlgorithms.Add(SecObjectIdentifiers.dhSinglePass_stdDH_sha224kdf_scheme);
ECAlgorithms.Add(SecObjectIdentifiers.dhSinglePass_stdDH_sha256kdf_scheme);
ECAlgorithms.Add(SecObjectIdentifiers.dhSinglePass_stdDH_sha384kdf_scheme);
ECAlgorithms.Add(SecObjectIdentifiers.dhSinglePass_stdDH_sha512kdf_scheme);
ECAlgorithms.Add(X9ObjectIdentifiers.DHSinglePassCofactorDHSha1KdfScheme);
ECAlgorithms.Add(SecObjectIdentifiers.dhSinglePass_cofactorDH_sha224kdf_scheme);
ECAlgorithms.Add(SecObjectIdentifiers.dhSinglePass_cofactorDH_sha256kdf_scheme);
ECAlgorithms.Add(SecObjectIdentifiers.dhSinglePass_cofactorDH_sha384kdf_scheme);
ECAlgorithms.Add(SecObjectIdentifiers.dhSinglePass_cofactorDH_sha512kdf_scheme);
GostAlgorithms.Add(CryptoProObjectIdentifiers.GostR3410x2001CryptoProESDH);
GostAlgorithms.Add(RosstandartObjectIdentifiers.id_tc26_agreement_gost_3410_12_256);
GostAlgorithms.Add(RosstandartObjectIdentifiers.id_tc26_agreement_gost_3410_12_512);
MqvAlgorithms.Add(X9ObjectIdentifiers.MqvSinglePassSha1KdfScheme);
MqvAlgorithms.Add(SecObjectIdentifiers.mqvSinglePass_sha224kdf_scheme);
MqvAlgorithms.Add(SecObjectIdentifiers.mqvSinglePass_sha256kdf_scheme);
MqvAlgorithms.Add(SecObjectIdentifiers.mqvSinglePass_sha384kdf_scheme);
MqvAlgorithms.Add(SecObjectIdentifiers.mqvSinglePass_sha512kdf_scheme);
}
internal static byte[] GetByteArray(CmsProcessable content)
{
if (content == null)
return Array.Empty<byte>();
if (content is CmsProcessableByteArray byteArray)
return byteArray.GetByteArray();
using (var buf = new MemoryStream())
{
content.Write(buf);
return buf.ToArray();
}
}
internal static bool IsDes(DerObjectIdentifier oid) => DesAlgorithms.Contains(oid);
internal static bool IsEC(DerObjectIdentifier oid) => ECAlgorithms.Contains(oid);
internal static bool IsGost(DerObjectIdentifier oid) => GostAlgorithms.Contains(oid);
internal static bool IsMqv(DerObjectIdentifier oid) => MqvAlgorithms.Contains(oid);
internal static bool IsEquivalent(AlgorithmIdentifier algID1, AlgorithmIdentifier algID2)
{
if (algID1 == null || algID2 == null)
return false;
return X509Utilities.AreEquivalentAlgorithms(algID1, algID2);
}
internal static ContentInfo ReadContentInfo(byte[] input)
{
Asn1Object asn1Object;
try
{
asn1Object = Asn1Object.FromByteArray(input);
}
catch (CmsException)
{
throw;
}
catch (Exception e)
{
throw new CmsException("Exception reading content.", e);
}
if (asn1Object == null)
throw new CmsException("No content found.");
return SafeGetInstance(asn1Object, ContentInfo.GetInstance);
}
internal static ContentInfo ReadContentInfo(Stream input)
{
Asn1Object asn1Object;
try
{
asn1Object = Asn1Object.FromStream(input);
}
catch (CmsException)
{
throw;
}
catch (Exception e)
{
throw new CmsException("Exception reading content.", e);
}
if (asn1Object == null)
throw new CmsException("No content found.");
return SafeGetInstance(asn1Object, ContentInfo.GetInstance);
}
internal static byte[] StreamToByteArray(Stream inStream) => Streams.ReadAll(inStream);
internal static byte[] StreamToByteArray(Stream inStream, int limit) => Streams.ReadAllLimited(inStream, limit);
internal static void AddDigestAlgorithms(DigestAlgorithmsBuilder builder, SignerInformation signer)
{
builder.Add(signer.DigestAlgorithmID);
foreach (var counterSigner in signer.GetCounterSignatures())
{
builder.Add(counterSigner.DigestAlgorithmID);
}
}
internal static IssuerAndSerialNumber GetIssuerAndSerialNumber(TbsCertificateStructure c) =>
new IssuerAndSerialNumber(c.Issuer, c.SerialNumber);
internal static IssuerAndSerialNumber GetIssuerAndSerialNumber(X509CertificateStructure c) =>
GetIssuerAndSerialNumber(c.TbsCertificate);
internal static IssuerAndSerialNumber GetIssuerAndSerialNumber(X509Certificate c) =>
GetIssuerAndSerialNumber(c.TbsCertificate);
internal static SignerIdentifier GetSignerIdentifier(X509Certificate c) =>
new SignerIdentifier(GetIssuerAndSerialNumber(c));
internal static SignerIdentifier GetSignerIdentifier(byte[] subjectKeyIdentifier) =>
new SignerIdentifier(new SubjectKeyIdentifier(subjectKeyIdentifier));
internal static Asn1.Cms.AttributeTable ParseAttributeTable(Asn1SetParser parser)
{
Asn1EncodableVector v = new Asn1EncodableVector();
IAsn1Convertible o;
while ((o = parser.ReadObject()) != null)
{
Asn1SequenceParser seq = (Asn1SequenceParser)o;
v.Add(seq.ToAsn1Object());
}
return new Asn1.Cms.AttributeTable(v);
}
internal static void CollectAttributeCertificate(List<Asn1Encodable> result,
X509V2AttributeCertificate attrCert)
{
result.Add(new DerTaggedObject(false, 2, attrCert.AttributeCertificate));
}
internal static void CollectAttributeCertificates(List<Asn1Encodable> result,
IStore<X509V2AttributeCertificate> attrCertStore)
{
if (attrCertStore != null)
{
foreach (var attrCert in attrCertStore.EnumerateMatches(null))
{
CollectAttributeCertificate(result, attrCert);
}
}
}
internal static void CollectCertificate(List<Asn1Encodable> result, X509Certificate cert)
{
result.Add(cert.CertificateStructure);
}
internal static void CollectCertificates(List<Asn1Encodable> result, IStore<X509Certificate> certStore)
{
if (certStore != null)
{
foreach (var cert in certStore.EnumerateMatches(null))
{
CollectCertificate(result, cert);
}
}
}
internal static void CollectCrl(List<Asn1Encodable> result, X509Crl crl)
{
result.Add(crl.CertificateList);
}
internal static void CollectCrls(List<Asn1Encodable> result, IStore<X509Crl> crlStore)
{
if (crlStore != null)
{
foreach (var crl in crlStore.EnumerateMatches(null))
{
CollectCrl(result, crl);
}
}
}
internal static void CollectOtherRevocationInfo(List<Asn1Encodable> result,
OtherRevocationInfoFormat otherRevocationInfo)
{
ValidateOtherRevocationInfo(otherRevocationInfo);
result.Add(new DerTaggedObject(false, 1, otherRevocationInfo));
}
internal static void CollectOtherRevocationInfo(List<Asn1Encodable> result,
DerObjectIdentifier otherRevInfoFormat, Asn1Encodable otherRevInfo)
{
CollectOtherRevocationInfo(result, new OtherRevocationInfoFormat(otherRevInfoFormat, otherRevInfo));
}
internal static void CollectOtherRevocationInfos(List<Asn1Encodable> result,
IStore<OtherRevocationInfoFormat> otherRevocationInfoStore)
{
if (otherRevocationInfoStore != null)
{
foreach (var otherRevocationInfo in otherRevocationInfoStore.EnumerateMatches(null))
{
CollectOtherRevocationInfo(result, otherRevocationInfo);
}
}
}
internal static void CollectOtherRevocationInfos(List<Asn1Encodable> result,
DerObjectIdentifier otherRevInfoFormat, IStore<Asn1Encodable> otherRevInfoStore)
{
if (otherRevInfoStore != null && otherRevInfoFormat != null)
{
foreach (var otherRevInfo in otherRevInfoStore.EnumerateMatches(null))
{
CollectOtherRevocationInfo(result, otherRevInfoFormat, otherRevInfo);
}
}
}
internal static Asn1Set ToAsn1Set(this IReadOnlyCollection<Asn1Encodable> elements, bool useDer, bool useDL)
{
return useDer
? ToDerSet(elements)
: useDL
? ToDLSet(elements)
: ToBerSet(elements);
}
internal static Asn1Set ToAsn1SetOptional(this IReadOnlyCollection<Asn1Encodable> elements, bool useDer,
bool useDL)
{
return elements.Count < 1 ? null : ToAsn1Set(elements, useDer, useDL);
}
internal static Asn1Set ToBerSet(this IReadOnlyCollection<Asn1Encodable> elements) =>
BerSet.FromCollection(elements);
internal static Asn1Set ToDerSet(this IReadOnlyCollection<Asn1Encodable> elements) =>
DerSet.FromCollection(elements);
internal static Asn1Set ToDLSet(this IReadOnlyCollection<Asn1Encodable> elements) =>
DLSet.FromCollection(elements);
internal static void ValidateOtherRevocationInfo(OtherRevocationInfoFormat otherRevocationInfo)
{
if (CmsObjectIdentifiers.id_ri_ocsp_response.Equals(otherRevocationInfo.InfoFormat))
{
OcspResponse ocspResponse = OcspResponse.GetInstance(otherRevocationInfo.Info);
if (!ocspResponse.ResponseStatus.HasValue(OcspResponseStatus.Successful))
throw new ArgumentException("cannot add unsuccessful OCSP response to CMS SignedData");
}
}
internal static CmsTypedData BindTypedData(DerObjectIdentifier contentType, CmsProcessable processable)
{
if (processable == null)
return new CmsAbsentContent(contentType);
if (processable is CmsTypedData cmsTypedData && cmsTypedData.ContentType.Equals(contentType))
return cmsTypedData;
return new CmsTypedProcessable(contentType, processable);
}
internal static CmsTypedData GetTypedData(CmsProcessable processable) =>
GetTypedData(processable, CmsObjectIdentifiers.Data);
internal static CmsTypedData GetTypedData(CmsProcessable processable, DerObjectIdentifier defaultContentType)
{
if (processable == null)
return new CmsAbsentContent(defaultContentType);
if (processable is CmsTypedData cmsTypedData)
return cmsTypedData;
return new CmsTypedProcessable(defaultContentType, processable);
}
internal static void AddOriginatorInfoToGenerator(BerSequenceGenerator seqGen, OriginatorInfo originatorInfo)
{
if (originatorInfo != null)
{
seqGen.AddObject(new DerTaggedObject(false, 0, originatorInfo));
}
}
internal static void AddRecipientInfosToGenerator(BerSequenceGenerator authGen,
Asn1EncodableVector recipientInfos, bool berEncodeRecipientSet)
{
recipientInfos.ToAsn1Set(useDer: !berEncodeRecipientSet, useDL: false)
.EncodeTo(authGen.GetRawOutputStream());
}
/// <exception cref="CmsException"></exception>
internal static TResult SafeGetContent<TResult>(ContentInfo contentInfo,
Func<Asn1Encodable, TResult> getInstance)
{
var content = contentInfo.Content ?? throw new CmsException("Missing content.");
return SafeGetInstance(content, getInstance);
}
/// <exception cref="CmsException"></exception>
internal static Asn1OctetString SafeGetEncryptedContent(EncryptedContentInfo encryptedContentInfo) =>
encryptedContentInfo.EncryptedContent ?? throw new CmsException("Missing content.");
/// <exception cref="CmsException"></exception>
internal static TResult SafeGetInstance<T, TResult>(T obj, Func<T, TResult> getInstance)
{
try
{
return getInstance(obj);
}
catch (CmsException)
{
throw;
}
catch (Exception e)
{
throw new CmsException("Malformed content.", e);
}
}
internal static CmsProcessableByteArray ProcessContentOctetString(ContentInfo contentInfo)
{
Asn1OctetString content = CmsUtilities.SafeGetContent(contentInfo, Asn1OctetString.GetInstance);
return new CmsProcessableByteArray(contentInfo.ContentType, content.GetOctets());
}
internal static CmsProcessableByteArray ProcessEncryptedContent(EncryptedContentInfo encryptedContentInfo)
{
Asn1OctetString content = CmsUtilities.SafeGetEncryptedContent(encryptedContentInfo);
return new CmsProcessableByteArray(encryptedContentInfo.ContentType, content.GetOctets());
}
}
}