1 //
2 // Pkits_4_03_VerifyingNameChaining.cs -
3 //	NUnit tests for Pkits 4.3 : Verifying Name Chaining
4 //
5 // Author:
6 //	Sebastien Pouliot  <sebastien@ximian.com>
7 //
8 // Copyright (C) 2006 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29 
30 
31 using NUnit.Framework;
32 
33 using System;
34 using System.Security.Cryptography.X509Certificates;
35 
36 namespace MonoTests.System.Security.Cryptography.X509Certificates {
37 
38 	/*
39 	 * Notes:
40 	 *
41 	 * [MS/XP][!RFC3280] It doesn't looks like any checks is done between the
42 	 * EE issuer and CA subject names.
43 	 *
44 	 * See PkitsTest.cs for more details
45 	 */
46 
47 	[TestFixture]
48 	[Category ("PKITS")]
49 	public class Pkits_4_03_VerifyingNameChaining: PkitsTest {
50 
51 		public X509Certificate2 NameOrderingCACert {
52 			get { return GetCertificate ("NameOrderingCACert.crt"); }
53 		}
54 
55 		public X509Certificate2 UIDCACert {
56 			get { return GetCertificate ("UIDCACert.crt"); }
57 		}
58 
59 		public X509Certificate2 RFC3280MandatoryAttributeTypesCACert {
60 			get { return GetCertificate ("RFC3280MandatoryAttributeTypesCACert.crt"); }
61 		}
62 
63 		public X509Certificate2 RFC3280OptionalAttributeTypesCACert {
64 			get { return GetCertificate ("RFC3280OptionalAttributeTypesCACert.crt"); }
65 		}
66 
67 		public X509Certificate2 UTF8StringEncodedNamesCACert {
68 			get { return GetCertificate ("UTF8StringEncodedNamesCACert.crt"); }
69 		}
70 
71 		public X509Certificate2 RolloverfromPrintableStringtoUTF8StringCACert {
72 			get { return GetCertificate ("RolloverfromPrintableStringtoUTF8StringCACert.crt"); }
73 		}
74 
75 		public X509Certificate2 UTF8StringCaseInsensitiveMatchCACert {
76 			get { return GetCertificate ("UTF8StringCaseInsensitiveMatchCACert.crt"); }
77 		}
78 
79 		[Test]
80 		[Category ("NotDotNet")] // test case is RFC3280 compliant
T01_InvalidNameChainingEE()81 		public void T01_InvalidNameChainingEE ()
82 		{
83 			X509Certificate2 ee = GetCertificate ("InvalidNameChainingTest1EE.crt");
84 			X509Chain chain = new X509Chain ();
85 			// INFO: different ee.issuer/ca.subject names
86 			// ee.IssuerName.Name		"CN=Good CA Root, O=Test Certificates, C=US"
87 			// GoodCACert.SubjectName.Name	"CN=Good CA, O=Test Certificates, C=US"
88 			Assert.IsFalse (chain.Build (ee), "Build");
89 			CheckChainStatus (X509ChainStatusFlags.InvalidNameConstraints, chain.ChainStatus, "ChainStatus");
90 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
91 			CheckChainStatus (X509ChainStatusFlags.InvalidNameConstraints, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
92 			Assert.AreEqual (GoodCACert, chain.ChainElements[1].Certificate, "GoodCACert");
93 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "GoodCACert.Status");
94 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
95 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
96 		}
97 
98 		[Test]
99 		[Category ("NotWorking")] // WONTFIX - this isn't RFC3280 compliant
T01_InvalidNameChainingEE_MS()100 		public void T01_InvalidNameChainingEE_MS ()
101 		{
102 			X509Certificate2 ee = GetCertificate ("InvalidNameChainingTest1EE.crt");
103 			X509Chain chain = new X509Chain ();
104 
105 			// MS-BAD / this is NOT valid wrt RFC3280
106 			// I don't like this result. MS builds the chain (using AKI/SKI) then can't find
107 			// the CRL (based on the wrong CA name?) which isn't what the test looks for.
108 
109 			Assert.IsFalse (chain.Build (ee), "Build");
110 			CheckChainStatus (X509ChainStatusFlags.RevocationStatusUnknown, chain.ChainStatus, "ChainStatus");
111 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
112 			CheckChainStatus (X509ChainStatusFlags.RevocationStatusUnknown, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
113 			Assert.AreEqual (GoodCACert, chain.ChainElements[1].Certificate, "GoodCACert");
114 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "GoodCACert.Status");
115 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
116 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
117 
118 			// Here's a proof of this, disabling the revocation check for the end-entity results in
119 			// a success
120 
121 			chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreEndRevocationUnknown;
122 			Assert.IsTrue (chain.Build (ee), "Build-Bug");
123 		}
124 
125 		[Test]
126 		[Category ("NotDotNet")] // test case is RFC3280 compliant
T02_InvalidNameChainingOrder()127 		public void T02_InvalidNameChainingOrder ()
128 		{
129 			X509Certificate2 ee = GetCertificate ("InvalidNameChainingOrderTest2EE.crt");
130 			X509Chain chain = new X509Chain ();
131 			// INFO: different (order) ee.issuer/ca.subject names
132 			// ee.Issuer			"CN=Name Ordering CA, OU=Organizational Unit Name 1, OU=Organizational Unit Name 2, O=Test Certificates, C=US"
133 			// NameOrderingCACert.Subject	"CN=Name Ordering CA, OU=Organizational Unit Name 2, OU=Organizational Unit Name 1, O=Test Certificates, C=US"
134 			Assert.IsFalse (chain.Build (ee), "Build");
135 			CheckChainStatus (X509ChainStatusFlags.RevocationStatusUnknown | X509ChainStatusFlags.InvalidNameConstraints, chain.ChainStatus, "ChainStatus");
136 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
137 			CheckChainStatus (X509ChainStatusFlags.RevocationStatusUnknown | X509ChainStatusFlags.InvalidNameConstraints, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
138 			Assert.AreEqual (NameOrderingCACert, chain.ChainElements[1].Certificate, "NameOrderingCACert");
139 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "NameOrderingCACert.Status");
140 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
141 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
142 		}
143 
144 		[Test]
145 		[Category ("NotWorking")] // WONTFIX - this isn't RFC3280 compliant
T02_InvalidNameChainingOrder_MS()146 		public void T02_InvalidNameChainingOrder_MS ()
147 		{
148 			X509Certificate2 ee = GetCertificate ("InvalidNameChainingOrderTest2EE.crt");
149 			X509Chain chain = new X509Chain ();
150 
151 			// MS-BAD / this is NOT valid wrt RFC3280
152 			// I don't like this result. MS builds the chain (using AKI/SKI) then can't find
153 			// the CRL (based on the wrong CA name?) which isn't what the test looks for.
154 
155 			Assert.IsFalse (chain.Build (ee), "Build");
156 			CheckChainStatus (X509ChainStatusFlags.RevocationStatusUnknown, chain.ChainStatus, "ChainStatus");
157 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
158 			CheckChainStatus (X509ChainStatusFlags.RevocationStatusUnknown, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
159 			Assert.AreEqual (NameOrderingCACert, chain.ChainElements[1].Certificate, "NameOrderingCACert");
160 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "NameOrderingCACert.Status");
161 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
162 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
163 
164 			// Here's a proof of this, disabling the revocation check for the end-entity results in
165 			// a success
166 
167 			chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreEndRevocationUnknown;
168 			Assert.IsTrue (chain.Build (ee), "Build-Bug");
169 		}
170 
171 		[Test]
172 		[Category ("NotDotNet")] // test case is RFC3280 compliant
T03_ValidNameChainingWhitespace()173 		public void T03_ValidNameChainingWhitespace ()
174 		{
175 			X509Certificate2 ee = GetCertificate ("ValidNameChainingWhitespaceTest3EE.crt");
176 			X509Chain chain = new X509Chain ();
177 			// INFO: different (spaces) ee.issuer/ca.subject names
178 			// ee.Issuer		"CN=Good     CA, O=Test  Certificates, C=US"
179 			// GoodCACert.Subject	"CN=Good CA, O=Test Certificates, C=US"
180 			Assert.IsTrue (chain.Build (ee), "Build");
181 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainStatus, "ChainStatus");
182 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
183 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
184 			Assert.AreEqual (GoodCACert, chain.ChainElements[1].Certificate, "GoodCACert");
185 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "GoodCACert.Status");
186 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
187 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
188 		}
189 
190 		[Test]
191 		[Category ("NotWorking")] // WONTFIX - this isn't RFC3280 compliant
T03_ValidNameChainingWhitespace_MS()192 		public void T03_ValidNameChainingWhitespace_MS ()
193 		{
194 			X509Certificate2 ee = GetCertificate ("ValidNameChainingWhitespaceTest3EE.crt");
195 			X509Chain chain = new X509Chain ();
196 
197 			// MS-BAD / this is valid wrt RFC3280
198 			// MS doesn't support internal whitespace compression. It seems MS builds the chain
199 			// (using AKI/SKI) then can't find the CRL (which isn't what the test looks for).
200 
201 			Assert.IsFalse (chain.Build (ee), "Build");
202 			CheckChainStatus (X509ChainStatusFlags.RevocationStatusUnknown, chain.ChainStatus, "ChainStatus");
203 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
204 			CheckChainStatus (X509ChainStatusFlags.RevocationStatusUnknown, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
205 			Assert.AreEqual (GoodCACert, chain.ChainElements[1].Certificate, "GoodCACert");
206 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "GoodCACert.Status");
207 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
208 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
209 
210 			// Here's a proof of this, disabling the revocation check for the end-entity results in
211 			// a success
212 
213 			chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreEndRevocationUnknown;
214 			Assert.IsTrue (chain.Build (ee), "Build-Bug");
215 		}
216 
217 		[Test]
218 		[Category ("NotDotNet")] // test case is RFC3280 compliant
T04_ValidNameChainingWhitespace()219 		public void T04_ValidNameChainingWhitespace ()
220 		{
221 			X509Certificate2 ee = GetCertificate ("ValidNameChainingWhitespaceTest4EE.crt");
222 			X509Chain chain = new X509Chain ();
223 			// INFO: different (spaces) ee.issuer/ca.subject names
224 			// ee.Issuer		"CN=\"   Good CA\", O=\"Test Certificates   \", C=US"
225 			// GoodCACert.Subject	"CN=Good CA, O=Test Certificates, C=US"
226 			Assert.IsTrue (chain.Build (ee), "Build");
227 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainStatus, "ChainStatus");
228 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
229 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
230 			Assert.AreEqual (GoodCACert, chain.ChainElements[1].Certificate, "GoodCACert");
231 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "GoodCACert.Status");
232 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
233 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
234 		}
235 
236 		[Test]
237 		[Category ("NotWorking")] // WONTFIX - this isn't RFC3280 compliant
T04_ValidNameChainingWhitespace_MS()238 		public void T04_ValidNameChainingWhitespace_MS ()
239 		{
240 			X509Certificate2 ee = GetCertificate ("ValidNameChainingWhitespaceTest4EE.crt");
241 			X509Chain chain = new X509Chain ();
242 
243 			// MS-BAD / this is valid wrt RFC3280
244 			// MS doesn't support internal whitespace compression. It seems MS builds the chain
245 			// (using AKI/SKI) then can't find the CRL (which isn't what the test looks for).
246 
247 			Assert.IsFalse (chain.Build (ee), "Build");
248 			CheckChainStatus (X509ChainStatusFlags.RevocationStatusUnknown, chain.ChainStatus, "ChainStatus");
249 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
250 			CheckChainStatus (X509ChainStatusFlags.RevocationStatusUnknown, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
251 			Assert.AreEqual (GoodCACert, chain.ChainElements[1].Certificate, "GoodCACert");
252 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "GoodCACert.Status");
253 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
254 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
255 
256 			// Here's a proof of this, disabling the revocation check for the end-entity results in
257 			// a success
258 
259 			chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreEndRevocationUnknown;
260 			Assert.IsTrue (chain.Build (ee), "Build-Bug");
261 		}
262 
263 		[Test]
264 		[Category ("NotDotNet")] // test case is RFC3280 compliant
T05_ValidNameChainingCapitalization()265 		public void T05_ValidNameChainingCapitalization ()
266 		{
267 			X509Certificate2 ee = GetCertificate ("ValidNameChainingCapitalizationTest5EE.crt");
268 			X509Chain chain = new X509Chain ();
269 			// INFO: different (capitalization) ee.issuer/ca.subject names
270 			// ee.Issuer		"CN=GOOD CA, O=Test Certificates, C=US"
271 			// GoodCACert.Subject	"CN=Good CA, O=Test Certificates, C=US"
272 			Assert.IsTrue (chain.Build (ee), "Build");
273 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainStatus, "ChainStatus");
274 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
275 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
276 			Assert.AreEqual (GoodCACert, chain.ChainElements[1].Certificate, "GoodCACert");
277 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "GoodCACert.Status");
278 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
279 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
280 		}
281 
282 		[Test]
283 		[Category ("NotWorking")] // WONTFIX - this isn't RFC3280 compliant
T05_ValidNameChainingCapitalization_MS()284 		public void T05_ValidNameChainingCapitalization_MS ()
285 		{
286 			X509Certificate2 ee = GetCertificate ("ValidNameChainingCapitalizationTest5EE.crt");
287 			X509Chain chain = new X509Chain ();
288 
289 			// MS-BAD / this is valid wrt RFC3280
290 			// NOTE: X509FindType.FindBySubjectDistinguishedName deals (correctly) with capitalization
291 			// issues. However it seems MS can't find the CRL based on the name with a different
292 			// capitalization so FALSE is returned
293 
294 			Assert.IsFalse (chain.Build (ee), "Build");
295 			CheckChainStatus (X509ChainStatusFlags.RevocationStatusUnknown, chain.ChainStatus, "ChainStatus");
296 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
297 			CheckChainStatus (X509ChainStatusFlags.RevocationStatusUnknown, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
298 			Assert.AreEqual (GoodCACert, chain.ChainElements[1].Certificate, "GoodCACert");
299 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "GoodCACert.Status");
300 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
301 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
302 
303 			// Here's a proof of this, disabling the revocation check for the end-entity results in
304 			// a success
305 
306 			chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreEndRevocationUnknown;
307 			Assert.IsTrue (chain.Build (ee), "Build-Bug");
308 		}
309 
310 		[Test]
T06_ValidNameChainingUIDs()311 		public void T06_ValidNameChainingUIDs ()
312 		{
313 			X509Certificate2 ee = GetCertificate ("ValidNameUIDsTest6EE.crt");
314 			X509Chain chain = new X509Chain ();
315 			Assert.IsTrue (chain.Build (ee), "Build");
316 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainStatus, "ChainStatus");
317 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
318 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
319 			Assert.AreEqual (UIDCACert, chain.ChainElements[1].Certificate, "UIDCACert");
320 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "UIDCACert.Status");
321 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
322 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
323 		}
324 
325 		[Test]
T07_ValidRFC3280MandatoryAttributeTypes()326 		public void T07_ValidRFC3280MandatoryAttributeTypes ()
327 		{
328 			X509Certificate2 ee = GetCertificate ("ValidRFC3280MandatoryAttributeTypesTest7EE.crt");
329 			X509Chain chain = new X509Chain ();
330 			Assert.IsTrue (chain.Build (ee), "Build");
331 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainStatus, "ChainStatus");
332 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
333 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
334 			Assert.AreEqual (RFC3280MandatoryAttributeTypesCACert, chain.ChainElements[1].Certificate, "RFC3280MandatoryAttributeTypesCACert");
335 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "RFC3280MandatoryAttributeTypesCACert.Status");
336 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
337 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
338 		}
339 
340 		[Test]
T08_ValidRFC3280OptionalAttributeTypes()341 		public void T08_ValidRFC3280OptionalAttributeTypes ()
342 		{
343 			X509Certificate2 ee = GetCertificate ("ValidRFC3280OptionalAttributeTypesTest8EE.crt");
344 			X509Chain chain = new X509Chain ();
345 			Assert.IsTrue (chain.Build (ee), "Build");
346 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainStatus, "ChainStatus");
347 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
348 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
349 			Assert.AreEqual (RFC3280OptionalAttributeTypesCACert, chain.ChainElements[1].Certificate, "RFC3280OptionalAttributeTypesCACert");
350 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "RFC3280OptionalAttributeTypesCACert.Status");
351 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
352 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
353 		}
354 
355 		[Test]
T09_ValidUTF8StringEncodedNames()356 		public void T09_ValidUTF8StringEncodedNames ()
357 		{
358 			X509Certificate2 ee = GetCertificate ("ValidUTF8StringEncodedNamesTest9EE.crt");
359 			X509Chain chain = new X509Chain ();
360 			Assert.IsTrue (chain.Build (ee), "Build");
361 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainStatus, "ChainStatus");
362 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
363 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
364 			Assert.AreEqual (UTF8StringEncodedNamesCACert, chain.ChainElements[1].Certificate, "UTF8StringEncodedNamesCACert");
365 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "UTF8StringEncodedNamesCACert.Status");
366 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
367 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
368 		}
369 
370 		[Test]
T10_ValidRolloverFromPrintableStringToUTF8String()371 		public void T10_ValidRolloverFromPrintableStringToUTF8String ()
372 		{
373 			X509Certificate2 ee = GetCertificate ("ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt");
374 			X509Chain chain = new X509Chain ();
375 			Assert.IsTrue (chain.Build (ee), "Build");
376 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainStatus, "ChainStatus");
377 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
378 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
379 			Assert.AreEqual (RolloverfromPrintableStringtoUTF8StringCACert, chain.ChainElements[1].Certificate, "RolloverfromPrintableStringtoUTF8StringCACert");
380 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "RolloverfromPrintableStringtoUTF8StringCACert.Status");
381 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
382 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
383 		}
384 
385 		[Test]
386 		[Category ("NotDotNet")] // test case is RFC3280 compliant
T11_ValidUTF8StringCaseInsensitiveMatch()387 		public void T11_ValidUTF8StringCaseInsensitiveMatch ()
388 		{
389 			X509Certificate2 ee = GetCertificate ("ValidUTF8StringCaseInsensitiveMatchTest11EE.crt");
390 			X509Chain chain = new X509Chain ();
391 			// INFO: different ee.issuer/ca.subject names (spaces & cases)
392 			// ee.Issuer					"CN=utf8string case  insensitive match CA, O=\"  test certificates  \", C=US"
393 			// UTF8StringCaseInsensitiveMatchCACert.Subject	"CN=UTF8String Case Insensitive Match CA, O=Test Certificates, C=US"
394 			Assert.IsTrue (chain.Build (ee), "Build");
395 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainStatus, "ChainStatus");
396 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
397 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
398 			Assert.AreEqual (UTF8StringCaseInsensitiveMatchCACert, chain.ChainElements[1].Certificate, "UTF8StringCaseInsensitiveMatchCACert");
399 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "UTF8StringCaseInsensitiveMatchCACert.Status");
400 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
401 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
402 		}
403 
404 		[Test]
405 		[Category ("NotWorking")] // WONTFIX - this isn't RFC3280 compliant
T11_ValidUTF8StringCaseInsensitiveMatch_MS()406 		public void T11_ValidUTF8StringCaseInsensitiveMatch_MS ()
407 		{
408 			X509Certificate2 ee = GetCertificate ("ValidUTF8StringCaseInsensitiveMatchTest11EE.crt");
409 			X509Chain chain = new X509Chain ();
410 			// MS-BAD / this is valid wrt RFC3280
411 			Assert.IsFalse (chain.Build (ee), "Build");
412 			CheckChainStatus (X509ChainStatusFlags.RevocationStatusUnknown, chain.ChainStatus, "ChainStatus");
413 			Assert.AreEqual (ee, chain.ChainElements[0].Certificate, "EndEntity");
414 			CheckChainStatus (X509ChainStatusFlags.RevocationStatusUnknown, chain.ChainElements[0].ChainElementStatus, "EndEntity.Status");
415 			Assert.AreEqual (UTF8StringCaseInsensitiveMatchCACert, chain.ChainElements[1].Certificate, "UTF8StringCaseInsensitiveMatchCACert");
416 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[1].ChainElementStatus, "UTF8StringCaseInsensitiveMatchCACert.Status");
417 			Assert.AreEqual (TrustAnchorRoot, chain.ChainElements[2].Certificate, "TrustAnchorRoot");
418 			CheckChainStatus (X509ChainStatusFlags.NoError, chain.ChainElements[2].ChainElementStatus, "TrustAnchorRoot.Status");
419 		}
420 	}
421 }
422 
423