@@ -18,7 +18,7 @@ TEST_CASE("Certificates_NoPinningSucceeds", "[certificates]")
1818 PinningDetails actual;
1919 actual.LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
2020
21- REQUIRE (expected.Validate (actual.GetCertificate ()));
21+ REQUIRE (CertificatePinningValidationResult::Accepted == expected.Validate (actual.GetCertificate (), CertificateChainPosition::Leaf ));
2222}
2323
2424TEST_CASE (" Certificates_PublicKeyMismatch" , " [certificates]" )
@@ -29,7 +29,7 @@ TEST_CASE("Certificates_PublicKeyMismatch", "[certificates]")
2929 PinningDetails actual;
3030 actual.LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
3131
32- REQUIRE (! expected.Validate (actual.GetCertificate ()));
32+ REQUIRE (CertificatePinningValidationResult::Rejected == expected.Validate (actual.GetCertificate (), CertificateChainPosition::Leaf ));
3333}
3434
3535TEST_CASE (" Certificates_PublicKeyMatch" , " [certificates]" )
@@ -40,7 +40,7 @@ TEST_CASE("Certificates_PublicKeyMatch", "[certificates]")
4040 PinningDetails actual;
4141 actual.LoadCertificate (IDX_CERTIFICATE_STORE_ROOT_2, CERTIFICATE_RESOURCE_TYPE);
4242
43- REQUIRE (expected.Validate (actual.GetCertificate ()));
43+ REQUIRE (CertificatePinningValidationResult::Accepted == expected.Validate (actual.GetCertificate (), CertificateChainPosition::Root ));
4444}
4545
4646TEST_CASE (" Certificates_SubjectMismatch" , " [certificates]" )
@@ -51,7 +51,7 @@ TEST_CASE("Certificates_SubjectMismatch", "[certificates]")
5151 PinningDetails actual;
5252 actual.LoadCertificate (IDX_CERTIFICATE_STORE_INTERMEDIATE_2, CERTIFICATE_RESOURCE_TYPE);
5353
54- REQUIRE (! expected.Validate (actual.GetCertificate ()));
54+ REQUIRE (CertificatePinningValidationResult::Rejected == expected.Validate (actual.GetCertificate (), CertificateChainPosition::Intermediate ));
5555}
5656
5757TEST_CASE (" Certificates_SubjectMatch" , " [certificates]" )
@@ -62,7 +62,7 @@ TEST_CASE("Certificates_SubjectMatch", "[certificates]")
6262 PinningDetails actual;
6363 actual.LoadCertificate (IDX_CERTIFICATE_STORE_INTERMEDIATE_2, CERTIFICATE_RESOURCE_TYPE);
6464
65- REQUIRE (expected.Validate (actual.GetCertificate ()));
65+ REQUIRE (CertificatePinningValidationResult::Accepted == expected.Validate (actual.GetCertificate (), CertificateChainPosition::Intermediate ));
6666}
6767
6868TEST_CASE (" Certificates_IssuerMismatch" , " [certificates]" )
@@ -73,7 +73,7 @@ TEST_CASE("Certificates_IssuerMismatch", "[certificates]")
7373 PinningDetails actual;
7474 actual.LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
7575
76- REQUIRE (! expected.Validate (actual.GetCertificate ()));
76+ REQUIRE (CertificatePinningValidationResult::Rejected == expected.Validate (actual.GetCertificate (), CertificateChainPosition::Leaf ));
7777}
7878
7979TEST_CASE (" Certificates_IssuerMatch" , " [certificates]" )
@@ -84,7 +84,7 @@ TEST_CASE("Certificates_IssuerMatch", "[certificates]")
8484 PinningDetails actual;
8585 actual.LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
8686
87- REQUIRE (expected.Validate (actual.GetCertificate ()));
87+ REQUIRE (CertificatePinningValidationResult::Accepted == expected.Validate (actual.GetCertificate (), CertificateChainPosition::Leaf ));
8888}
8989
9090TEST_CASE (" Certificates_ChainLengthDiffers" , " [certificates]" )
@@ -104,6 +104,122 @@ TEST_CASE("Certificates_ChainLengthDiffers", "[certificates]")
104104 REQUIRE (!config.Validate (details.GetCertificate ()));
105105}
106106
107+ TEST_CASE (" Certificates_ChainLengthDiffers_Partial" , " [certificates]" )
108+ {
109+ PinningChain chain;
110+ auto chainElement = chain.Root ();
111+ chainElement->LoadCertificate (IDX_CERTIFICATE_STORE_ROOT_2, CERTIFICATE_RESOURCE_TYPE).SetPinning (PinningVerificationType::PublicKey);
112+ chainElement = chainElement.Next ();
113+ chainElement->LoadCertificate (IDX_CERTIFICATE_STORE_INTERMEDIATE_2, CERTIFICATE_RESOURCE_TYPE).SetPinning (PinningVerificationType::Subject | PinningVerificationType::Issuer);
114+ chain.PartialChain ();
115+
116+ PinningConfiguration config;
117+ config.AddChain (chain);
118+
119+ PinningDetails details;
120+ details.LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
121+
122+ REQUIRE (config.Validate (details.GetCertificate ()));
123+ }
124+
125+ TEST_CASE (" CertificateChain_AnyIssuer_Intermediate" , " [certificates]" )
126+ {
127+ PinningChain chain;
128+ auto chainElement = chain.Root ();
129+ chainElement->LoadCertificate (IDX_CERTIFICATE_STORE_INTERMEDIATE_2, CERTIFICATE_RESOURCE_TYPE).SetPinning (PinningVerificationType::PublicKey | PinningVerificationType::AnyIssuer | PinningVerificationType::RequireNonLeaf);
130+ chain.PartialChain ();
131+
132+ PinningConfiguration config;
133+ config.AddChain (chain);
134+
135+ PinningDetails details;
136+ details.LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
137+
138+ REQUIRE (config.Validate (details.GetCertificate ()));
139+ }
140+
141+ TEST_CASE (" CertificateChain_AnyIssuer_IntermediateDiffers" , " [certificates]" )
142+ {
143+ PinningChain chain;
144+ auto chainElement = chain.Root ();
145+ chainElement->LoadCertificate (IDX_CERTIFICATE_STORE_INTERMEDIATE_1, CERTIFICATE_RESOURCE_TYPE).SetPinning (PinningVerificationType::PublicKey | PinningVerificationType::AnyIssuer | PinningVerificationType::RequireNonLeaf);
146+ chain.PartialChain ();
147+
148+ PinningConfiguration config;
149+ config.AddChain (chain);
150+
151+ PinningDetails details;
152+ details.LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
153+
154+ REQUIRE (!config.Validate (details.GetCertificate ()));
155+ }
156+
157+ TEST_CASE (" CertificateChain_AnyIssuer_IntermediateAndLeaf" , " [certificates]" )
158+ {
159+ PinningChain chain;
160+ auto chainElement = chain.Root ();
161+ chainElement->LoadCertificate (IDX_CERTIFICATE_STORE_INTERMEDIATE_2, CERTIFICATE_RESOURCE_TYPE).SetPinning (PinningVerificationType::PublicKey | PinningVerificationType::AnyIssuer | PinningVerificationType::RequireNonLeaf);
162+ chainElement = chainElement.Next ();
163+ chainElement->LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE).SetPinning (PinningVerificationType::Subject | PinningVerificationType::Issuer);
164+ chain.PartialChain ();
165+
166+ PinningConfiguration config;
167+ config.AddChain (chain);
168+
169+ PinningDetails details;
170+ details.LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
171+
172+ REQUIRE (config.Validate (details.GetCertificate ()));
173+ }
174+
175+ TEST_CASE (" CertificateChain_AnyIssuer_Leaf" , " [certificates]" )
176+ {
177+ PinningChain chain;
178+ auto chainElement = chain.Root ();
179+ chainElement->LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE).SetPinning (PinningVerificationType::PublicKey | PinningVerificationType::AnyIssuer);
180+ chain.PartialChain ();
181+
182+ PinningConfiguration config;
183+ config.AddChain (chain);
184+
185+ PinningDetails details;
186+ details.LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
187+
188+ REQUIRE (config.Validate (details.GetCertificate ()));
189+ }
190+
191+ TEST_CASE (" CertificateChain_AnyIssuer_LeafDiffers" , " [certificates]" )
192+ {
193+ PinningChain chain;
194+ auto chainElement = chain.Root ();
195+ chainElement->LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_1, CERTIFICATE_RESOURCE_TYPE).SetPinning (PinningVerificationType::PublicKey | PinningVerificationType::AnyIssuer);
196+ chain.PartialChain ();
197+
198+ PinningConfiguration config;
199+ config.AddChain (chain);
200+
201+ PinningDetails details;
202+ details.LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
203+
204+ REQUIRE (!config.Validate (details.GetCertificate ()));
205+ }
206+
207+ TEST_CASE (" CertificateChain_AnyIssuer_SameLeaf_RequireNonLeaf" , " [certificates]" )
208+ {
209+ PinningChain chain;
210+ auto chainElement = chain.Root ();
211+ chainElement->LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE).SetPinning (PinningVerificationType::PublicKey | PinningVerificationType::AnyIssuer | PinningVerificationType::RequireNonLeaf);
212+ chain.PartialChain ();
213+
214+ PinningConfiguration config;
215+ config.AddChain (chain);
216+
217+ PinningDetails details;
218+ details.LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
219+
220+ REQUIRE (!config.Validate (details.GetCertificate ()));
221+ }
222+
107223TEST_CASE (" Certificates_EmptyChainRejects" , " [certificates]" )
108224{
109225 PinningChain chain;
@@ -183,3 +299,47 @@ TEST_CASE("Certificates_MultipleChains_Success", "[certificates]")
183299
184300 REQUIRE (config.Validate (details.GetCertificate ()));
185301}
302+
303+ TEST_CASE (" CertificateChain_Position" , " [certificates]" )
304+ {
305+ CertificateChainPosition positions[3 ]{ CertificateChainPosition::Unknown, CertificateChainPosition::Unknown, CertificateChainPosition::Unknown };
306+
307+ PinningChain chain;
308+ auto chainElement = chain.Root ();
309+ chainElement->LoadCertificate (IDX_CERTIFICATE_STORE_ROOT_2, CERTIFICATE_RESOURCE_TYPE).SetCustomValidationFunction ([&](const PinningDetails&, PCCERT_CONTEXT, CertificateChainPosition position) { positions[0 ] = position; return true ; });
310+ chainElement = chainElement.Next ();
311+ chainElement->LoadCertificate (IDX_CERTIFICATE_STORE_INTERMEDIATE_2, CERTIFICATE_RESOURCE_TYPE).SetCustomValidationFunction ([&](const PinningDetails&, PCCERT_CONTEXT, CertificateChainPosition position) { positions[1 ] = position; return true ; });
312+ chainElement = chainElement.Next ();
313+ chainElement->LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE).SetCustomValidationFunction ([&](const PinningDetails&, PCCERT_CONTEXT, CertificateChainPosition position) { positions[2 ] = position; return true ; });
314+
315+ PinningConfiguration config;
316+ config.AddChain (chain);
317+
318+ PinningDetails details;
319+ details.LoadCertificate (IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
320+
321+ REQUIRE (config.Validate (details.GetCertificate ()));
322+
323+ REQUIRE (CertificateChainPosition::Root == positions[0 ]);
324+ REQUIRE (CertificateChainPosition::Intermediate == positions[1 ]);
325+ REQUIRE (CertificateChainPosition::Leaf == positions[2 ]);
326+ }
327+
328+ TEST_CASE (" CertificateChain_Position_SelfSigned" , " [certificates]" )
329+ {
330+ CertificateChainPosition positions[1 ]{ CertificateChainPosition::Unknown };
331+
332+ PinningChain chain;
333+ auto chainElement = chain.Root ();
334+ chainElement->LoadCertificate (IDX_CERTIFICATE_STORE_ROOT_2, CERTIFICATE_RESOURCE_TYPE).SetCustomValidationFunction ([&](const PinningDetails&, PCCERT_CONTEXT, CertificateChainPosition position) { positions[0 ] = position; return true ; });
335+
336+ PinningConfiguration config;
337+ config.AddChain (chain);
338+
339+ PinningDetails details;
340+ details.LoadCertificate (IDX_CERTIFICATE_STORE_ROOT_2, CERTIFICATE_RESOURCE_TYPE);
341+
342+ REQUIRE (config.Validate (details.GetCertificate ()));
343+
344+ REQUIRE ((CertificateChainPosition::Root | CertificateChainPosition::Leaf) == positions[0 ]);
345+ }
0 commit comments