winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

Certificates.cpp (15469B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "TestCommon.h"
      5 #include <winget/Certificates.h>
      6 #include <CertificateResources.h>
      7 
      8 using namespace TestCommon;
      9 using namespace AppInstaller;
     10 using namespace AppInstaller::Certificates;
     11 
     12 
     13 TEST_CASE("Certificates_NoPinningSucceeds", "[certificates]")
     14 {
     15     PinningDetails expected;
     16     expected.LoadCertificate(IDX_CERTIFICATE_STORE_ROOT_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::None);
     17 
     18     PinningDetails actual;
     19     actual.LoadCertificate(IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
     20 
     21     REQUIRE(CertificatePinningValidationResult::Accepted == expected.Validate(actual.GetCertificate(), CertificateChainPosition::Leaf));
     22 }
     23 
     24 TEST_CASE("Certificates_PublicKeyMismatch", "[certificates]")
     25 {
     26     PinningDetails expected;
     27     expected.LoadCertificate(IDX_CERTIFICATE_STORE_ROOT_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::PublicKey);
     28 
     29     PinningDetails actual;
     30     actual.LoadCertificate(IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
     31 
     32     REQUIRE(CertificatePinningValidationResult::Rejected == expected.Validate(actual.GetCertificate(), CertificateChainPosition::Leaf));
     33 }
     34 
     35 TEST_CASE("Certificates_PublicKeyMatch", "[certificates]")
     36 {
     37     PinningDetails expected;
     38     expected.LoadCertificate(IDX_CERTIFICATE_STORE_ROOT_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::PublicKey);
     39 
     40     PinningDetails actual;
     41     actual.LoadCertificate(IDX_CERTIFICATE_STORE_ROOT_2, CERTIFICATE_RESOURCE_TYPE);
     42 
     43     REQUIRE(CertificatePinningValidationResult::Accepted == expected.Validate(actual.GetCertificate(), CertificateChainPosition::Root));
     44 }
     45 
     46 TEST_CASE("Certificates_SubjectMismatch", "[certificates]")
     47 {
     48     PinningDetails expected;
     49     expected.LoadCertificate(IDX_CERTIFICATE_STORE_ROOT_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::Subject);
     50 
     51     PinningDetails actual;
     52     actual.LoadCertificate(IDX_CERTIFICATE_STORE_INTERMEDIATE_2, CERTIFICATE_RESOURCE_TYPE);
     53 
     54     REQUIRE(CertificatePinningValidationResult::Rejected == expected.Validate(actual.GetCertificate(), CertificateChainPosition::Intermediate));
     55 }
     56 
     57 TEST_CASE("Certificates_SubjectMatch", "[certificates]")
     58 {
     59     PinningDetails expected;
     60     expected.LoadCertificate(IDX_CERTIFICATE_STORE_INTERMEDIATE_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::Subject);
     61 
     62     PinningDetails actual;
     63     actual.LoadCertificate(IDX_CERTIFICATE_STORE_INTERMEDIATE_2, CERTIFICATE_RESOURCE_TYPE);
     64 
     65     REQUIRE(CertificatePinningValidationResult::Accepted == expected.Validate(actual.GetCertificate(), CertificateChainPosition::Intermediate));
     66 }
     67 
     68 TEST_CASE("Certificates_IssuerMismatch", "[certificates]")
     69 {
     70     PinningDetails expected;
     71     expected.LoadCertificate(IDX_CERTIFICATE_STORE_INTERMEDIATE_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::Issuer);
     72 
     73     PinningDetails actual;
     74     actual.LoadCertificate(IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
     75 
     76     REQUIRE(CertificatePinningValidationResult::Rejected == expected.Validate(actual.GetCertificate(), CertificateChainPosition::Leaf));
     77 }
     78 
     79 TEST_CASE("Certificates_IssuerMatch", "[certificates]")
     80 {
     81     PinningDetails expected;
     82     expected.LoadCertificate(IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::Issuer);
     83 
     84     PinningDetails actual;
     85     actual.LoadCertificate(IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
     86 
     87     REQUIRE(CertificatePinningValidationResult::Accepted == expected.Validate(actual.GetCertificate(), CertificateChainPosition::Leaf));
     88 }
     89 
     90 TEST_CASE("Certificates_ChainLengthDiffers", "[certificates]")
     91 {
     92     PinningChain chain;
     93     auto chainElement = chain.Root();
     94     chainElement->LoadCertificate(IDX_CERTIFICATE_STORE_ROOT_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::PublicKey);
     95     chainElement = chainElement.Next();
     96     chainElement->LoadCertificate(IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::Subject | PinningVerificationType::Issuer);
     97 
     98     PinningConfiguration config;
     99     config.AddChain(chain);
    100 
    101     PinningDetails details;
    102     details.LoadCertificate(IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
    103 
    104     REQUIRE(!config.Validate(details.GetCertificate()));
    105 }
    106 
    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 
    223 TEST_CASE("Certificates_EmptyChainRejects", "[certificates]")
    224 {
    225     PinningChain chain;
    226 
    227     PinningConfiguration config;
    228     config.AddChain(chain);
    229 
    230     PinningDetails details;
    231     details.LoadCertificate(IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
    232 
    233     REQUIRE(!config.Validate(details.GetCertificate()));
    234 }
    235 
    236 TEST_CASE("Certificates_ChainOrderDiffers", "[certificates]")
    237 {
    238     PinningChain chain;
    239     auto chainElement = chain.Root();
    240     chainElement->LoadCertificate(IDX_CERTIFICATE_STORE_ROOT_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::PublicKey);
    241     chainElement = chainElement.Next();
    242     chainElement->LoadCertificate(IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::Subject | PinningVerificationType::Issuer);
    243     chainElement = chainElement.Next();
    244     chainElement->LoadCertificate(IDX_CERTIFICATE_STORE_INTERMEDIATE_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::Subject | PinningVerificationType::Issuer);
    245 
    246     PinningConfiguration config;
    247     config.AddChain(chain);
    248 
    249     PinningDetails details;
    250     details.LoadCertificate(IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
    251 
    252     REQUIRE(!config.Validate(details.GetCertificate()));
    253 }
    254 
    255 TEST_CASE("Certificates_StoreChain_BuiltInTest", "[certificates]")
    256 {
    257     PinningChain chain;
    258     auto chainElement = chain.Root();
    259     chainElement->LoadCertificate(IDX_CERTIFICATE_STORE_ROOT_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::PublicKey);
    260     chainElement = chainElement.Next();
    261     chainElement->LoadCertificate(IDX_CERTIFICATE_STORE_INTERMEDIATE_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::Subject | PinningVerificationType::Issuer);
    262     chainElement = chainElement.Next();
    263     chainElement->LoadCertificate(IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::Subject | PinningVerificationType::Issuer);
    264 
    265     PinningConfiguration config;
    266     config.AddChain(chain);
    267 
    268     PinningDetails details;
    269     details.LoadCertificate(IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
    270 
    271     REQUIRE(config.Validate(details.GetCertificate()));
    272 }
    273 
    274 TEST_CASE("Certificates_MultipleChains_Success", "[certificates]")
    275 {
    276     PinningChain chainOutOfOrder;
    277     auto chainElement = chainOutOfOrder.Root();
    278     chainElement->LoadCertificate(IDX_CERTIFICATE_STORE_ROOT_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::PublicKey);
    279     chainElement = chainElement.Next();
    280     chainElement->LoadCertificate(IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::Subject | PinningVerificationType::Issuer);
    281     chainElement = chainElement.Next();
    282     chainElement->LoadCertificate(IDX_CERTIFICATE_STORE_INTERMEDIATE_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::Subject | PinningVerificationType::Issuer);
    283 
    284     PinningConfiguration config;
    285     config.AddChain(chainOutOfOrder);
    286 
    287     PinningChain chain;
    288     chainElement = chain.Root();
    289     chainElement->LoadCertificate(IDX_CERTIFICATE_STORE_ROOT_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::PublicKey);
    290     chainElement = chainElement.Next();
    291     chainElement->LoadCertificate(IDX_CERTIFICATE_STORE_INTERMEDIATE_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::Subject | PinningVerificationType::Issuer);
    292     chainElement = chainElement.Next();
    293     chainElement->LoadCertificate(IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE).SetPinning(PinningVerificationType::Subject | PinningVerificationType::Issuer);
    294 
    295     config.AddChain(chain);
    296 
    297     PinningDetails details;
    298     details.LoadCertificate(IDX_CERTIFICATE_STORE_LEAF_2, CERTIFICATE_RESOURCE_TYPE);
    299 
    300     REQUIRE(config.Validate(details.GetCertificate()));
    301 }
    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 }