Skip to content

Commit d4cacb5

Browse files
committed
Added SMimeCapabilities extensions to generated unit test certificates
1 parent 9c2659f commit d4cacb5

File tree

8 files changed

+89
-3
lines changed

8 files changed

+89
-3
lines changed

MimeKit/Cryptography/BouncyCastleCertificateExtensions.cs

+6-2
Original file line numberDiff line numberDiff line change
@@ -423,8 +423,12 @@ public static EncryptionAlgorithm[] GetEncryptionAlgorithms (this X509Certificat
423423

424424
var capabilities = certificate.GetExtensionValue (SmimeAttributes.SmimeCapabilities);
425425

426-
if (capabilities != null)
427-
return DecodeEncryptionAlgorithms (capabilities.GetOctets ());
426+
if (capabilities != null) {
427+
var algorithms = DecodeEncryptionAlgorithms (capabilities.GetOctets ());
428+
429+
if (algorithms != null)
430+
return algorithms;
431+
}
428432

429433
return new EncryptionAlgorithm[] { EncryptionAlgorithm.TripleDes };
430434
}

UnitTests/Cryptography/X509CertificateGenerator.cs

+59-1
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,18 @@
2525
//
2626

2727
using System.Text;
28+
using System.Globalization;
2829

2930
using Org.BouncyCastle.Asn1;
31+
using Org.BouncyCastle.Asn1.Nist;
32+
using Org.BouncyCastle.Asn1.Ntt;
33+
using Org.BouncyCastle.Asn1.Misc;
34+
using Org.BouncyCastle.Asn1.Oiw;
35+
using Org.BouncyCastle.Asn1.Pkcs;
36+
using Org.BouncyCastle.Asn1.Kisa;
37+
using Org.BouncyCastle.Asn1.Smime;
3038
using Org.BouncyCastle.Asn1.X509;
39+
using Org.BouncyCastle.Asn1.X9;
3140
using Org.BouncyCastle.Crypto;
3241
using Org.BouncyCastle.Crypto.Digests;
3342
using Org.BouncyCastle.Crypto.Generators;
@@ -41,13 +50,13 @@
4150
using Org.BouncyCastle.Utilities;
4251
using Org.BouncyCastle.X509;
4352
using Org.BouncyCastle.X509.Extension;
44-
using Org.BouncyCastle.Asn1.X9;
4553

4654
using MimeKit;
4755

4856
namespace UnitTests.Cryptography {
4957
class X509CertificateGenerator
5058
{
59+
static readonly Dictionary<string, DerObjectIdentifier> SMimeCapabilityMapping;
5160
static readonly Dictionary<string, DerObjectIdentifier> X509NameOidMapping;
5261
static readonly Dictionary<string, int> X509SubjectAlternativeTagMapping;
5362
static readonly char[] EqualSign = new char[] { '=' };
@@ -102,6 +111,21 @@ static X509CertificateGenerator ()
102111
{ "Rfc822Name", GeneralName.Rfc822Name },
103112
{ "DnsName", GeneralName.DnsName },
104113
};
114+
115+
SMimeCapabilityMapping = new Dictionary<string, DerObjectIdentifier> (StringComparer.OrdinalIgnoreCase) {
116+
{ "AES128", NistObjectIdentifiers.IdAes128Cbc },
117+
{ "AES192", NistObjectIdentifiers.IdAes192Cbc },
118+
{ "AES256", NistObjectIdentifiers.IdAes256Cbc },
119+
{ "CAMELLIA128", NttObjectIdentifiers.IdCamellia128Cbc },
120+
{ "CAMELLIA192", NttObjectIdentifiers.IdCamellia192Cbc },
121+
{ "CAMELLIA256", NttObjectIdentifiers.IdCamellia256Cbc },
122+
{ "CAST5", MiscObjectIdentifiers.cast5CBC },
123+
{ "DES", OiwObjectIdentifiers.DesCbc },
124+
{ "3DES", PkcsObjectIdentifiers.DesEde3Cbc },
125+
{ "IDEA", MiscObjectIdentifiers.as_sys_sec_alg_ideaCBC },
126+
{ "RC2", PkcsObjectIdentifiers.RC2Cbc },
127+
{ "SEED", KisaObjectIdentifiers.IdSeedCbc }
128+
};
105129
}
106130

107131
static AsymmetricCipherKeyPair LoadAsymmetricCipherKeyPair (string fileName)
@@ -218,6 +242,8 @@ public CertificateOptions ()
218242

219243
internal List<GeneralName> SubjectAlternativeNames { get; private set; }
220244

245+
internal SmimeCapabilityVector SMimeCapabilities { get; private set; }
246+
221247
public void Add (DerObjectIdentifier oid, string value)
222248
{
223249
if (oid == X509Name.CN || oid == X509Name.E)
@@ -253,6 +279,26 @@ public void AddSubjectAlternativeName (string property, string value)
253279
break;
254280
}
255281
}
282+
283+
public void AddSMimeCapability (string capability)
284+
{
285+
var components = capability.Split (new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
286+
DerObjectIdentifier oid;
287+
288+
if (SMimeCapabilityMapping.TryGetValue (components[0], out oid) || DerObjectIdentifier.TryFromID (components[0], out oid)) {
289+
SMimeCapabilities ??= new SmimeCapabilityVector ();
290+
291+
if (components.Length > 1) {
292+
int value = int.Parse (components[1], NumberStyles.None, CultureInfo.InvariantCulture);
293+
294+
SMimeCapabilities.AddCapability (oid, value);
295+
} else {
296+
SMimeCapabilities.AddCapability (oid);
297+
}
298+
} else {
299+
throw new ArgumentException ($"Unknown S/MIME capability: {capability}", nameof (capability));
300+
}
301+
}
256302
}
257303

258304
public sealed class GeneratorOptions
@@ -409,6 +455,11 @@ public static X509Certificate[] Generate (GeneratorOptions options, PrivateKeyOp
409455
generator.AddExtension (X509Extensions.SubjectAlternativeName, false, altNames);
410456
}
411457

458+
if (certificateOptions.SMimeCapabilities != null) {
459+
var capabilities = certificateOptions.SMimeCapabilities.ToAsn1EncodableVector ();
460+
generator.AddExtension (SmimeAttributes.SmimeCapabilities, false, new DerSequence (capabilities));
461+
}
462+
412463
if (issuerCertificate != null)
413464
generator.AddExtension (X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure (issuerCertificate));
414465

@@ -554,6 +605,13 @@ public static X509Certificate[] Generate (string cfg)
554605
throw new FormatException ($"Unknown [SubjectAlternativeNames] property: {property}");
555606
}
556607
break;
608+
case "smimecapabilities":
609+
try {
610+
certificate.AddSMimeCapability (value);
611+
} catch (ArgumentException) {
612+
throw new FormatException ($"Unknown [SMimeCapabilities] value: {value}");
613+
}
614+
break;
557615
case "generator":
558616
switch (property.ToLowerInvariant ()) {
559617
case "basicconstraints":

UnitTests/TestData/smime/dsa/smime.cfg

+10
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@ LocalityName = Boston
1010
CommonName = MimeKit UnitTests
1111
EmailAddress = [email protected]
1212

13+
[SMimeCapabilities]
14+
capability.0 = AES256
15+
capability.1 = AES192
16+
capability.2 = AES128
17+
capability.3 = IDEA
18+
capability.4 = 3DES
19+
capability.5 = RC2-128
20+
capability.6 = RC2-64
21+
capability.7 = RC2-40
22+
1323
[Generator]
1424
BasicConstraints = critical, CA:false
1525
DaysValid = 3650
128 Bytes
Binary file not shown.

UnitTests/TestData/smime/ec/smime.cfg

+7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ LocalityName = Boston
1010
CommonName = MimeKit UnitTests
1111
EmailAddress = [email protected]
1212

13+
[SMimeCapabilities]
14+
capability.0 = AES256
15+
capability.1 = AES192
16+
capability.2 = AES128
17+
capability.3 = IDEA
18+
capability.4 = 3DES
19+
1320
[Generator]
1421
BasicConstraints = critical, CA:false
1522
DaysValid = 3650

UnitTests/TestData/smime/ec/smime.pfx

88 Bytes
Binary file not shown.

UnitTests/TestData/smime/rsa/smime.cfg

+7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ LocalityName = Boston
1010
CommonName = MimeKit UnitTests
1111
EmailAddress = [email protected]
1212

13+
[SMimeCapabilities]
14+
capability.0 = AES256
15+
capability.1 = AES192
16+
capability.2 = AES128
17+
capability.3 = IDEA
18+
capability.4 = 3DES
19+
1320
[Generator]
1421
BasicConstraints = critical, CA:false
1522
DaysValid = 3650
-2 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)