#! /usr/bin/env perl
# Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License").  You may not use
# this file except in compliance with the License.  You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html

# Perl utility to run PKITS tests for RFC3280 compliance.

my $ossl_path;

if ( -f "../apps/openssl" ) {
    $ossl_path = "../util/shlib_wrap.sh ../apps/openssl";
}
elsif ( -f "..\\out32dll\\openssl.exe" ) {
    $ossl_path = "..\\out32dll\\openssl.exe";
}
elsif ( -f "..\\out32\\openssl.exe" ) {
    $ossl_path = "..\\out32\\openssl.exe";
}
else {
    die "Can't find OpenSSL executable";
}

my $pkitsdir = "pkits/smime";
my $pkitsta = "pkits/certs/TrustAnchorRootCertificate.crt";

die "Can't find PKITS test data" if !-d $pkitsdir;

my $nist1 = "2.16.840.1.101.3.2.1.48.1";
my $nist2 = "2.16.840.1.101.3.2.1.48.2";
my $nist3 = "2.16.840.1.101.3.2.1.48.3";
my $nist4 = "2.16.840.1.101.3.2.1.48.4";
my $nist5 = "2.16.840.1.101.3.2.1.48.5";
my $nist6 = "2.16.840.1.101.3.2.1.48.6";

my $apolicy = "X509v3 Any Policy";

# This table contains the chapter headings of the accompanying PKITS
# document. They provide useful informational output and their names
# can be converted into the filename to test.

my @testlists = (
    [ "4.1", "Signature Verification" ],
    [ "4.1.1", "Valid Signatures Test1",                        0 ],
    [ "4.1.2", "Invalid CA Signature Test2",                    7 ],
    [ "4.1.3", "Invalid EE Signature Test3",                    7 ],
    [ "4.1.4", "Valid DSA Signatures Test4",                    0 ],
    [ "4.1.5", "Valid DSA Parameter Inheritance Test5",         0 ],
    [ "4.1.6", "Invalid DSA Signature Test6",                   7 ],
    [ "4.2",   "Validity Periods" ],
    [ "4.2.1", "Invalid CA notBefore Date Test1",               9 ],
    [ "4.2.2", "Invalid EE notBefore Date Test2",               9 ],
    [ "4.2.3", "Valid pre2000 UTC notBefore Date Test3",        0 ],
    [ "4.2.4", "Valid GeneralizedTime notBefore Date Test4",    0 ],
    [ "4.2.5", "Invalid CA notAfter Date Test5",                10 ],
    [ "4.2.6", "Invalid EE notAfter Date Test6",                10 ],
    [ "4.2.7", "Invalid pre2000 UTC EE notAfter Date Test7",    10 ],
    [ "4.2.8", "Valid GeneralizedTime notAfter Date Test8",     0 ],
    [ "4.3",   "Verifying Name Chaining" ],
    [ "4.3.1", "Invalid Name Chaining EE Test1",                20 ],
    [ "4.3.2", "Invalid Name Chaining Order Test2",             20 ],
    [ "4.3.3", "Valid Name Chaining Whitespace Test3",          0 ],
    [ "4.3.4", "Valid Name Chaining Whitespace Test4",          0 ],
    [ "4.3.5", "Valid Name Chaining Capitalization Test5",      0 ],
    [ "4.3.6", "Valid Name Chaining UIDs Test6",                0 ],
    [ "4.3.7", "Valid RFC3280 Mandatory Attribute Types Test7", 0 ],
    [ "4.3.8", "Valid RFC3280 Optional Attribute Types Test8",  0 ],
    [ "4.3.9", "Valid UTF8String Encoded Names Test9",          0 ],
    [ "4.3.10", "Valid Rollover from PrintableString to UTF8String Test10", 0 ],
    [ "4.3.11", "Valid UTF8String Case Insensitive Match Test11",           0 ],
    [ "4.4",    "Basic Certificate Revocation Tests" ],
    [ "4.4.1",  "Missing CRL Test1",                                        3 ],
    [ "4.4.2", "Invalid Revoked CA Test2",          23 ],
    [ "4.4.3", "Invalid Revoked EE Test3",          23 ],
    [ "4.4.4", "Invalid Bad CRL Signature Test4",   8 ],
    [ "4.4.5", "Invalid Bad CRL Issuer Name Test5", 3 ],
    [ "4.4.6", "Invalid Wrong CRL Test6",           3 ],
    [ "4.4.7", "Valid Two CRLs Test7",              0 ],

    # The test document suggests these should return certificate revoked...
    # Subsequent discussion has concluded they should not due to unhandle
    # critical CRL extensions.
    [ "4.4.8", "Invalid Unknown CRL Entry Extension Test8", 36 ],
    [ "4.4.9", "Invalid Unknown CRL Extension Test9",       36 ],

    [ "4.4.10", "Invalid Unknown CRL Extension Test10",             36 ],
    [ "4.4.11", "Invalid Old CRL nextUpdate Test11",                12 ],
    [ "4.4.12", "Invalid pre2000 CRL nextUpdate Test12",            12 ],
    [ "4.4.13", "Valid GeneralizedTime CRL nextUpdate Test13",      0 ],
    [ "4.4.14", "Valid Negative Serial Number Test14",              0 ],
    [ "4.4.15", "Invalid Negative Serial Number Test15",            23 ],
    [ "4.4.16", "Valid Long Serial Number Test16",                  0 ],
    [ "4.4.17", "Valid Long Serial Number Test17",                  0 ],
    [ "4.4.18", "Invalid Long Serial Number Test18",                23 ],
    [ "4.4.19", "Valid Separate Certificate and CRL Keys Test19",   0 ],
    [ "4.4.20", "Invalid Separate Certificate and CRL Keys Test20", 23 ],

    # CRL path is revoked so get a CRL path validation error
    [ "4.4.21", "Invalid Separate Certificate and CRL Keys Test21",      54 ],
    [ "4.5",    "Verifying Paths with Self-Issued Certificates" ],
    [ "4.5.1",  "Valid Basic Self-Issued Old With New Test1",            0 ],
    [ "4.5.2",  "Invalid Basic Self-Issued Old With New Test2",          23 ],
    [ "4.5.3",  "Valid Basic Self-Issued New With Old Test3",            0 ],
    [ "4.5.4",  "Valid Basic Self-Issued New With Old Test4",            0 ],
    [ "4.5.5",  "Invalid Basic Self-Issued New With Old Test5",          23 ],
    [ "4.5.6",  "Valid Basic Self-Issued CRL Signing Key Test6",         0 ],
    [ "4.5.7",  "Invalid Basic Self-Issued CRL Signing Key Test7",       23 ],
    [ "4.5.8",  "Invalid Basic Self-Issued CRL Signing Key Test8",       20 ],
    [ "4.6",    "Verifying Basic Constraints" ],
    [ "4.6.1",  "Invalid Missing basicConstraints Test1",                24 ],
    [ "4.6.2",  "Invalid cA False Test2",                                24 ],
    [ "4.6.3",  "Invalid cA False Test3",                                24 ],
    [ "4.6.4",  "Valid basicConstraints Not Critical Test4",             0 ],
    [ "4.6.5",  "Invalid pathLenConstraint Test5",                       25 ],
    [ "4.6.6",  "Invalid pathLenConstraint Test6",                       25 ],
    [ "4.6.7",  "Valid pathLenConstraint Test7",                         0 ],
    [ "4.6.8",  "Valid pathLenConstraint Test8",                         0 ],
    [ "4.6.9",  "Invalid pathLenConstraint Test9",                       25 ],
    [ "4.6.10", "Invalid pathLenConstraint Test10",                      25 ],
    [ "4.6.11", "Invalid pathLenConstraint Test11",                      25 ],
    [ "4.6.12", "Invalid pathLenConstraint Test12",                      25 ],
    [ "4.6.13", "Valid pathLenConstraint Test13",                        0 ],
    [ "4.6.14", "Valid pathLenConstraint Test14",                        0 ],
    [ "4.6.15", "Valid Self-Issued pathLenConstraint Test15",            0 ],
    [ "4.6.16", "Invalid Self-Issued pathLenConstraint Test16",          25 ],
    [ "4.6.17", "Valid Self-Issued pathLenConstraint Test17",            0 ],
    [ "4.7",    "Key Usage" ],
    [ "4.7.1",  "Invalid keyUsage Critical keyCertSign False Test1",     20 ],
    [ "4.7.2",  "Invalid keyUsage Not Critical keyCertSign False Test2", 20 ],
    [ "4.7.3",  "Valid keyUsage Not Critical Test3",                     0 ],
    [ "4.7.4",  "Invalid keyUsage Critical cRLSign False Test4",         35 ],
    [ "4.7.5",  "Invalid keyUsage Not Critical cRLSign False Test5",     35 ],

    # Certificate policy tests need special handling. They can have several
    # sub tests and we need to check the outputs are correct.

    [ "4.8", "Certificate Policies" ],
    [
        "4.8.1.1",
        "All Certificates Same Policy Test1",
        "-policy anyPolicy -explicit_policy",
        "True", $nist1, $nist1, 0
    ],
    [
        "4.8.1.2",
        "All Certificates Same Policy Test1",
        "-policy $nist1 -explicit_policy",
        "True", $nist1, $nist1, 0
    ],
    [
        "4.8.1.3",
        "All Certificates Same Policy Test1",
        "-policy $nist2 -explicit_policy",
        "True", $nist1, "<empty>", 43
    ],
    [
        "4.8.1.4",
        "All Certificates Same Policy Test1",
        "-policy $nist1 -policy $nist2 -explicit_policy",
        "True", $nist1, $nist1, 0
    ],
    [
        "4.8.2.1",
        "All Certificates No Policies Test2",
        "-policy anyPolicy",
        "False", "<empty>", "<empty>", 0
    ],
    [
        "4.8.2.2",
        "All Certificates No Policies Test2",
        "-policy anyPolicy -explicit_policy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.8.3.1",
        "Different Policies Test3",
        "-policy anyPolicy",
        "False", "<empty>", "<empty>", 0
    ],
    [
        "4.8.3.2",
        "Different Policies Test3",
        "-policy anyPolicy -explicit_policy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.8.3.3",
        "Different Policies Test3",
        "-policy $nist1 -policy $nist2 -explicit_policy",
        "True", "<empty>", "<empty>", 43
    ],

    [
        "4.8.4",
        "Different Policies Test4",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.8.5",
        "Different Policies Test5",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.8.6.1",
        "Overlapping Policies Test6",
        "-policy anyPolicy",
        "True", $nist1, $nist1, 0
    ],
    [
        "4.8.6.2",
        "Overlapping Policies Test6",
        "-policy $nist1",
        "True", $nist1, $nist1, 0
    ],
    [
        "4.8.6.3",
        "Overlapping Policies Test6",
        "-policy $nist2",
        "True", $nist1, "<empty>", 43
    ],
    [
        "4.8.7",
        "Different Policies Test7",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.8.8",
        "Different Policies Test8",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.8.9",
        "Different Policies Test9",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.8.10.1",
        "All Certificates Same Policies Test10",
        "-policy $nist1",
        "True", "$nist1:$nist2", "$nist1", 0
    ],
    [
        "4.8.10.2",
        "All Certificates Same Policies Test10",
        "-policy $nist2",
        "True", "$nist1:$nist2", "$nist2", 0
    ],
    [
        "4.8.10.3",
        "All Certificates Same Policies Test10",
        "-policy anyPolicy",
        "True", "$nist1:$nist2", "$nist1:$nist2", 0
    ],
    [
        "4.8.11.1",
        "All Certificates AnyPolicy Test11",
        "-policy anyPolicy",
        "True", "$apolicy", "$apolicy", 0
    ],
    [
        "4.8.11.2",
        "All Certificates AnyPolicy Test11",
        "-policy $nist1",
        "True", "$apolicy", "$nist1", 0
    ],
    [
        "4.8.12",
        "Different Policies Test12",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.8.13.1",
        "All Certificates Same Policies Test13",
        "-policy $nist1",
        "True", "$nist1:$nist2:$nist3", "$nist1", 0
    ],
    [
        "4.8.13.2",
        "All Certificates Same Policies Test13",
        "-policy $nist2",
        "True", "$nist1:$nist2:$nist3", "$nist2", 0
    ],
    [
        "4.8.13.3",
        "All Certificates Same Policies Test13",
        "-policy $nist3",
        "True", "$nist1:$nist2:$nist3", "$nist3", 0
    ],
    [
        "4.8.14.1",       "AnyPolicy Test14",
        "-policy $nist1", "True",
        "$nist1",         "$nist1",
        0
    ],
    [
        "4.8.14.2",       "AnyPolicy Test14",
        "-policy $nist2", "True",
        "$nist1",         "<empty>",
        43
    ],
    [
        "4.8.15",
        "User Notice Qualifier Test15",
        "-policy anyPolicy",
        "False", "$nist1", "$nist1", 0
    ],
    [
        "4.8.16",
        "User Notice Qualifier Test16",
        "-policy anyPolicy",
        "False", "$nist1", "$nist1", 0
    ],
    [
        "4.8.17",
        "User Notice Qualifier Test17",
        "-policy anyPolicy",
        "False", "$nist1", "$nist1", 0
    ],
    [
        "4.8.18.1",
        "User Notice Qualifier Test18",
        "-policy $nist1",
        "True", "$nist1:$nist2", "$nist1", 0
    ],
    [
        "4.8.18.2",
        "User Notice Qualifier Test18",
        "-policy $nist2",
        "True", "$nist1:$nist2", "$nist2", 0
    ],
    [
        "4.8.19",
        "User Notice Qualifier Test19",
        "-policy anyPolicy",
        "False", "$nist1", "$nist1", 0
    ],
    [
        "4.8.20",
        "CPS Pointer Qualifier Test20",
        "-policy anyPolicy -explicit_policy",
        "True", "$nist1", "$nist1", 0
    ],
    [ "4.9", "Require Explicit Policy" ],
    [
        "4.9.1",
        "Valid RequireExplicitPolicy Test1",
        "-policy anyPolicy",
        "False", "<empty>", "<empty>", 0
    ],
    [
        "4.9.2",
        "Valid RequireExplicitPolicy Test2",
        "-policy anyPolicy",
        "False", "<empty>", "<empty>", 0
    ],
    [
        "4.9.3",
        "Invalid RequireExplicitPolicy Test3",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.9.4",
        "Valid RequireExplicitPolicy Test4",
        "-policy anyPolicy",
        "True", "$nist1", "$nist1", 0
    ],
    [
        "4.9.5",
        "Invalid RequireExplicitPolicy Test5",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.9.6",
        "Valid Self-Issued requireExplicitPolicy Test6",
        "-policy anyPolicy",
        "False", "<empty>", "<empty>", 0
    ],
    [
        "4.9.7",
        "Invalid Self-Issued requireExplicitPolicy Test7",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.9.8",
        "Invalid Self-Issued requireExplicitPolicy Test8",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [ "4.10", "Policy Mappings" ],
    [
        "4.10.1.1",
        "Valid Policy Mapping Test1",
        "-policy $nist1",
        "True", "$nist1", "$nist1", 0
    ],
    [
        "4.10.1.2",
        "Valid Policy Mapping Test1",
        "-policy $nist2",
        "True", "$nist1", "<empty>", 43
    ],
    [
        "4.10.1.3",
        "Valid Policy Mapping Test1",
        "-policy anyPolicy -inhibit_map",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.10.2.1",
        "Invalid Policy Mapping Test2",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.10.2.2",
        "Invalid Policy Mapping Test2",
        "-policy anyPolicy -inhibit_map",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.10.3.1",
        "Valid Policy Mapping Test3",
        "-policy $nist1",
        "True", "$nist2", "<empty>", 43
    ],
    [
        "4.10.3.2",
        "Valid Policy Mapping Test3",
        "-policy $nist2",
        "True", "$nist2", "$nist2", 0
    ],
    [
        "4.10.4",
        "Invalid Policy Mapping Test4",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.10.5.1",
        "Valid Policy Mapping Test5",
        "-policy $nist1",
        "True", "$nist1", "$nist1", 0
    ],
    [
        "4.10.5.2",
        "Valid Policy Mapping Test5",
        "-policy $nist6",
        "True", "$nist1", "<empty>", 43
    ],
    [
        "4.10.6.1",
        "Valid Policy Mapping Test6",
        "-policy $nist1",
        "True", "$nist1", "$nist1", 0
    ],
    [
        "4.10.6.2",
        "Valid Policy Mapping Test6",
        "-policy $nist6",
        "True", "$nist1", "<empty>", 43
    ],
    [ "4.10.7", "Invalid Mapping From anyPolicy Test7", 42 ],
    [ "4.10.8", "Invalid Mapping To anyPolicy Test8",   42 ],
    [
        "4.10.9",
        "Valid Policy Mapping Test9",
        "-policy anyPolicy",
        "True", "$nist1", "$nist1", 0
    ],
    [
        "4.10.10",
        "Invalid Policy Mapping Test10",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.10.11",
        "Valid Policy Mapping Test11",
        "-policy anyPolicy",
        "True", "$nist1", "$nist1", 0
    ],

    # TODO: check notice display
    [
        "4.10.12.1",
        "Valid Policy Mapping Test12",
        "-policy $nist1",
        "True", "$nist1:$nist2", "$nist1", 0
    ],

    # TODO: check notice display
    [
        "4.10.12.2",
        "Valid Policy Mapping Test12",
        "-policy $nist2",
        "True", "$nist1:$nist2", "$nist2", 0
    ],
    [
        "4.10.13",
        "Valid Policy Mapping Test13",
        "-policy anyPolicy",
        "True", "$nist1", "$nist1", 0
    ],

    # TODO: check notice display
    [
        "4.10.14",
        "Valid Policy Mapping Test14",
        "-policy anyPolicy",
        "True", "$nist1", "$nist1", 0
    ],
    [ "4.11", "Inhibit Policy Mapping" ],
    [
        "4.11.1",
        "Invalid inhibitPolicyMapping Test1",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.11.2",
        "Valid inhibitPolicyMapping Test2",
        "-policy anyPolicy",
        "True", "$nist1", "$nist1", 0
    ],
    [
        "4.11.3",
        "Invalid inhibitPolicyMapping Test3",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.11.4",
        "Valid inhibitPolicyMapping Test4",
        "-policy anyPolicy",
        "True", "$nist2", "$nist2", 0
    ],
    [
        "4.11.5",
        "Invalid inhibitPolicyMapping Test5",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.11.6",
        "Invalid inhibitPolicyMapping Test6",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.11.7",
        "Valid Self-Issued inhibitPolicyMapping Test7",
        "-policy anyPolicy",
        "True", "$nist1", "$nist1", 0
    ],
    [
        "4.11.8",
        "Invalid Self-Issued inhibitPolicyMapping Test8",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.11.9",
        "Invalid Self-Issued inhibitPolicyMapping Test9",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.11.10",
        "Invalid Self-Issued inhibitPolicyMapping Test10",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.11.11",
        "Invalid Self-Issued inhibitPolicyMapping Test11",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [ "4.12", "Inhibit Any Policy" ],
    [
        "4.12.1",
        "Invalid inhibitAnyPolicy Test1",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.12.2",
        "Valid inhibitAnyPolicy Test2",
        "-policy anyPolicy",
        "True", "$nist1", "$nist1", 0
    ],
    [
        "4.12.3.1",
        "inhibitAnyPolicy Test3",
        "-policy anyPolicy",
        "True", "$nist1", "$nist1", 0
    ],
    [
        "4.12.3.2",
        "inhibitAnyPolicy Test3",
        "-policy anyPolicy -inhibit_any",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.12.4",
        "Invalid inhibitAnyPolicy Test4",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.12.5",
        "Invalid inhibitAnyPolicy Test5",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [
        "4.12.6",
        "Invalid inhibitAnyPolicy Test6",
        "-policy anyPolicy",
        "True", "<empty>", "<empty>", 43
    ],
    [ "4.12.7",  "Valid Self-Issued inhibitAnyPolicy Test7",      0 ],
    [ "4.12.8",  "Invalid Self-Issued inhibitAnyPolicy Test8",    43 ],
    [ "4.12.9",  "Valid Self-Issued inhibitAnyPolicy Test9",      0 ],
    [ "4.12.10", "Invalid Self-Issued inhibitAnyPolicy Test10",   43 ],
    [ "4.13",    "Name Constraints" ],
    [ "4.13.1",  "Valid DN nameConstraints Test1",                0 ],
    [ "4.13.2",  "Invalid DN nameConstraints Test2",              47 ],
    [ "4.13.3",  "Invalid DN nameConstraints Test3",              47 ],
    [ "4.13.4",  "Valid DN nameConstraints Test4",                0 ],
    [ "4.13.5",  "Valid DN nameConstraints Test5",                0 ],
    [ "4.13.6",  "Valid DN nameConstraints Test6",                0 ],
    [ "4.13.7",  "Invalid DN nameConstraints Test7",              48 ],
    [ "4.13.8",  "Invalid DN nameConstraints Test8",              48 ],
    [ "4.13.9",  "Invalid DN nameConstraints Test9",              48 ],
    [ "4.13.10", "Invalid DN nameConstraints Test10",             48 ],
    [ "4.13.11", "Valid DN nameConstraints Test11",               0 ],
    [ "4.13.12", "Invalid DN nameConstraints Test12",             47 ],
    [ "4.13.13", "Invalid DN nameConstraints Test13",             47 ],
    [ "4.13.14", "Valid DN nameConstraints Test14",               0 ],
    [ "4.13.15", "Invalid DN nameConstraints Test15",             48 ],
    [ "4.13.16", "Invalid DN nameConstraints Test16",             48 ],
    [ "4.13.17", "Invalid DN nameConstraints Test17",             48 ],
    [ "4.13.18", "Valid DN nameConstraints Test18",               0 ],
    [ "4.13.19", "Valid Self-Issued DN nameConstraints Test19",   0 ],
    [ "4.13.20", "Invalid Self-Issued DN nameConstraints Test20", 47 ],
    [ "4.13.21", "Valid RFC822 nameConstraints Test21",           0 ],
    [ "4.13.22", "Invalid RFC822 nameConstraints Test22",         47 ],
    [ "4.13.23", "Valid RFC822 nameConstraints Test23",           0 ],
    [ "4.13.24", "Invalid RFC822 nameConstraints Test24",         47 ],
    [ "4.13.25", "Valid RFC822 nameConstraints Test25",           0 ],
    [ "4.13.26", "Invalid RFC822 nameConstraints Test26",         48 ],
    [ "4.13.27", "Valid DN and RFC822 nameConstraints Test27",    0 ],
    [ "4.13.28", "Invalid DN and RFC822 nameConstraints Test28",  47 ],
    [ "4.13.29", "Invalid DN and RFC822 nameConstraints Test29",  47 ],
    [ "4.13.30", "Valid DNS nameConstraints Test30",              0 ],
    [ "4.13.31", "Invalid DNS nameConstraints Test31",            47 ],
    [ "4.13.32", "Valid DNS nameConstraints Test32",              0 ],
    [ "4.13.33", "Invalid DNS nameConstraints Test33",            48 ],
    [ "4.13.34", "Valid URI nameConstraints Test34",              0 ],
    [ "4.13.35", "Invalid URI nameConstraints Test35",            47 ],
    [ "4.13.36", "Valid URI nameConstraints Test36",              0 ],
    [ "4.13.37", "Invalid URI nameConstraints Test37",            48 ],
    [ "4.13.38", "Invalid DNS nameConstraints Test38",            47 ],
    [ "4.14",    "Distribution Points" ],
    [ "4.14.1",  "Valid distributionPoint Test1",                 0 ],
    [ "4.14.2",  "Invalid distributionPoint Test2",               23 ],
    [ "4.14.3",  "Invalid distributionPoint Test3",               44 ],
    [ "4.14.4",  "Valid distributionPoint Test4",                 0 ],
    [ "4.14.5",  "Valid distributionPoint Test5",                 0 ],
    [ "4.14.6",  "Invalid distributionPoint Test6",               23 ],
    [ "4.14.7",  "Valid distributionPoint Test7",                 0 ],
    [ "4.14.8",  "Invalid distributionPoint Test8",               44 ],
    [ "4.14.9",  "Invalid distributionPoint Test9",               44 ],
    [ "4.14.10", "Valid No issuingDistributionPoint Test10",      0 ],
    [ "4.14.11", "Invalid onlyContainsUserCerts CRL Test11",      44 ],
    [ "4.14.12", "Invalid onlyContainsCACerts CRL Test12",        44 ],
    [ "4.14.13", "Valid onlyContainsCACerts CRL Test13",          0 ],
    [ "4.14.14", "Invalid onlyContainsAttributeCerts Test14",     44 ],
    [ "4.14.15", "Invalid onlySomeReasons Test15",                23 ],
    [ "4.14.16", "Invalid onlySomeReasons Test16",                23 ],
    [ "4.14.17", "Invalid onlySomeReasons Test17",                3 ],
    [ "4.14.18", "Valid onlySomeReasons Test18",                  0 ],
    [ "4.14.19", "Valid onlySomeReasons Test19",                  0 ],
    [ "4.14.20", "Invalid onlySomeReasons Test20",                23 ],
    [ "4.14.21", "Invalid onlySomeReasons Test21",                23 ],
    [ "4.14.22", "Valid IDP with indirectCRL Test22",             0 ],
    [ "4.14.23", "Invalid IDP with indirectCRL Test23",           23 ],
    [ "4.14.24", "Valid IDP with indirectCRL Test24",             0 ],
    [ "4.14.25", "Valid IDP with indirectCRL Test25",             0 ],
    [ "4.14.26", "Invalid IDP with indirectCRL Test26",           44 ],
    [ "4.14.27", "Invalid cRLIssuer Test27",                      3 ],
    [ "4.14.28", "Valid cRLIssuer Test28",                        0 ],
    [ "4.14.29", "Valid cRLIssuer Test29",                        0 ],

    # Although this test is valid it has a circular dependency. As a result
    # an attempt is made to recursively checks a CRL path and rejected due to
    # a CRL path validation error. PKITS notes suggest this test does not
    # need to be run due to this issue.
    [ "4.14.30", "Valid cRLIssuer Test30",                                 54 ],
    [ "4.14.31", "Invalid cRLIssuer Test31",                               23 ],
    [ "4.14.32", "Invalid cRLIssuer Test32",                               23 ],
    [ "4.14.33", "Valid cRLIssuer Test33",                                 0 ],
    [ "4.14.34", "Invalid cRLIssuer Test34",                               23 ],
    [ "4.14.35", "Invalid cRLIssuer Test35",                               44 ],
    [ "4.15",    "Delta-CRLs" ],
    [ "4.15.1",  "Invalid deltaCRLIndicator No Base Test1",                3 ],
    [ "4.15.2",  "Valid delta-CRL Test2",                                  0 ],
    [ "4.15.3",  "Invalid delta-CRL Test3",                                23 ],
    [ "4.15.4",  "Invalid delta-CRL Test4",                                23 ],
    [ "4.15.5",  "Valid delta-CRL Test5",                                  0 ],
    [ "4.15.6",  "Invalid delta-CRL Test6",                                23 ],
    [ "4.15.7",  "Valid delta-CRL Test7",                                  0 ],
    [ "4.15.8",  "Valid delta-CRL Test8",                                  0 ],
    [ "4.15.9",  "Invalid delta-CRL Test9",                                23 ],
    [ "4.15.10", "Invalid delta-CRL Test10",                               12 ],
    [ "4.16",    "Private Certificate Extensions" ],
    [ "4.16.1",  "Valid Unknown Not Critical Certificate Extension Test1", 0 ],
    [ "4.16.2",  "Invalid Unknown Critical Certificate Extension Test2",   34 ],
);

my $verbose = 1;

my $numtest = 0;
my $numfail = 0;

my $ossl = "ossl/apps/openssl";

my $ossl_cmd = "$ossl_path cms -verify -verify_retcode ";
$ossl_cmd .= "-CAfile pkitsta.pem -crl_check_all -x509_strict ";

# Check for expiry of trust anchor
system "$ossl_path x509 -inform DER -in $pkitsta -checkend 0";
if ($? == 256)
	{
	print STDERR "WARNING: using older expired data\n";
	$ossl_cmd .= "-attime 1291940972 ";
	}

$ossl_cmd .= "-policy_check -extended_crl -use_deltas -out /dev/null 2>&1 ";

system "$ossl_path x509 -inform DER -in $pkitsta -out pkitsta.pem";

die "Can't create trust anchor file" if $?;

print "Running PKITS tests:\n" if $verbose;

foreach (@testlists) {
    my $argnum = @$_;
    if ( $argnum == 2 ) {
        my ( $tnum, $title ) = @$_;
        print "$tnum $title\n" if $verbose;
    }
    elsif ( $argnum == 3 ) {
        my ( $tnum, $title, $exp_ret ) = @$_;
        my $filename = $title;
        $exp_ret += 32 if $exp_ret;
        $filename =~ tr/ -//d;
        $filename = "Signed${filename}.eml";
        if ( !-f "$pkitsdir/$filename" ) {
            print "\"$filename\" not found\n";
        }
        else {
            my $ret;
            my $test_fail = 0;
            my $errmsg    = "";
            my $cmd       = $ossl_cmd;
            $cmd .= "-in $pkitsdir/$filename -policy anyPolicy";
            my $cmdout = `$cmd`;
            $ret = $? >> 8;
            if ( $? & 0xff ) {
                $errmsg .= "Abnormal OpenSSL termination\n";
                $test_fail = 1;
            }
            if ( $exp_ret != $ret ) {
                $errmsg .= "Return code:$ret, ";
                $errmsg .= "expected $exp_ret\n";
                $test_fail = 1;
            }
            if ($test_fail) {
                print "$tnum $title : Failed!\n";
                print "Filename: $pkitsdir/$filename\n";
                print $errmsg;
                print "Command output:\n$cmdout\n";
                $numfail++;
            }
            $numtest++;
        }
    }
    elsif ( $argnum == 7 ) {
        my ( $tnum, $title, $exargs, $exp_epol, $exp_aset, $exp_uset, $exp_ret )
          = @$_;
        my $filename = $title;
        $exp_ret += 32 if $exp_ret;
        $filename =~ tr/ -//d;
        $filename = "Signed${filename}.eml";
        if ( !-f "$pkitsdir/$filename" ) {
            print "\"$filename\" not found\n";
        }
        else {
            my $ret;
            my $cmdout    = "";
            my $errmsg    = "";
            my $epol      = "";
            my $aset      = "";
            my $uset      = "";
            my $pol       = -1;
            my $test_fail = 0;
            my $cmd       = $ossl_cmd;
            $cmd .= "-in $pkitsdir/$filename $exargs -policy_print";
            @oparr = `$cmd`;
            $ret   = $? >> 8;

            if ( $? & 0xff ) {
                $errmsg .= "Abnormal OpenSSL termination\n";
                $test_fail = 1;
            }
            foreach (@oparr) {
                my $test_failed = 0;
                $cmdout .= $_;
                if (/^Require explicit Policy: (.*)$/) {
                    $epol = $1;
                }
                if (/^Authority Policies/) {
                    if (/empty/) {
                        $aset = "<empty>";
                    }
                    else {
                        $pol = 1;
                    }
                }
                $test_fail = 1 if (/leak/i);
                if (/^User Policies/) {
                    if (/empty/) {
                        $uset = "<empty>";
                    }
                    else {
                        $pol = 2;
                    }
                }
                if (/\s+Policy: (.*)$/) {
                    if ( $pol == 1 ) {
                        $aset .= ":" if $aset ne "";
                        $aset .= $1;
                    }
                    elsif ( $pol == 2 ) {
                        $uset .= ":" if $uset ne "";
                        $uset .= $1;
                    }
                }
            }

            if ( $epol ne $exp_epol ) {
                $errmsg .= "Explicit policy:$epol, ";
                $errmsg .= "expected $exp_epol\n";
                $test_fail = 1;
            }
            if ( $aset ne $exp_aset ) {
                $errmsg .= "Authority policy set :$aset, ";
                $errmsg .= "expected $exp_aset\n";
                $test_fail = 1;
            }
            if ( $uset ne $exp_uset ) {
                $errmsg .= "User policy set :$uset, ";
                $errmsg .= "expected $exp_uset\n";
                $test_fail = 1;
            }

            if ( $exp_ret != $ret ) {
                print "Return code:$ret, expected $exp_ret\n";
                $test_fail = 1;
            }

            if ($test_fail) {
                print "$tnum $title : Failed!\n";
                print "Filename: $pkitsdir/$filename\n";
                print "Command output:\n$cmdout\n";
                $numfail++;
            }
            $numtest++;
        }
    }
}

if ($numfail) {
    print "$numfail tests failed out of $numtest\n";
}
else {
    print "All Tests Successful.\n";
}

unlink "pkitsta.pem";


#! /usr/bin/env perl
# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License").  You may not use
# this file except in compliance with the License.  You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html

use strict;
use warnings;

# Recognise VERBOSE and V which is common on other projects.
BEGIN {
    $ENV{HARNESS_VERBOSE} = "yes" if $ENV{VERBOSE} || $ENV{V};
}

use File::Spec::Functions qw/catdir catfile curdir abs2rel rel2abs/;
use File::Basename;
use FindBin;
use lib "$FindBin::Bin/../util/perl";
use OpenSSL::Glob;

my $TAP_Harness = eval { require TAP::Harness } ? "TAP::Harness"
                                                : "OpenSSL::TAP::Harness";

my $srctop = $ENV{SRCTOP} || $ENV{TOP};
my $bldtop = $ENV{BLDTOP} || $ENV{TOP};
my $recipesdir = catdir($srctop, "test", "recipes");
my $libdir = rel2abs(catdir($srctop, "util", "perl"));

$ENV{OPENSSL_CONF} = catdir($srctop, "apps", "openssl.cnf");

my %tapargs =
    ( verbosity => $ENV{VERBOSE} || $ENV{V} || $ENV{HARNESS_VERBOSE} ? 1 : 0,
      lib       => [ $libdir ],
      switches  => '-w',
      merge     => 1
    );

my @alltests = find_matching_tests("*");
my %tests = ();

my $initial_arg = 1;
foreach my $arg (@ARGV ? @ARGV : ('alltests')) {
    if ($arg eq 'list') {
	foreach (@alltests) {
	    (my $x = basename($_)) =~ s|^[0-9][0-9]-(.*)\.t$|$1|;
	    print $x,"\n";
	}
	exit 0;
    }
    if ($arg eq 'alltests') {
	warn "'alltests' encountered, ignoring everything before that...\n"
	    unless $initial_arg;
	%tests = map { $_ => 1 } @alltests;
    } elsif ($arg =~ m/^(-?)(.*)/) {
	my $sign = $1;
	my $test = $2;
	my @matches = find_matching_tests($test);

	# If '-foo' is the first arg, it's short for 'alltests -foo'
	if ($sign eq '-' && $initial_arg) {
	    %tests = map { $_ => 1 } @alltests;
	}

	if (scalar @matches == 0) {
	    warn "Test $test found no match, skipping ",
		($sign eq '-' ? "removal" : "addition"),
		"...\n";
	} else {
	    foreach $test (@matches) {
		if ($sign eq '-') {
		    delete $tests{$test};
		} else {
		    $tests{$test} = 1;
		}
	    }
	}
    } else {
	warn "I don't know what '$arg' is about, ignoring...\n";
    }

    $initial_arg = 0;
}

my $harness = $TAP_Harness->new(\%tapargs);
my $ret = $harness->runtests(map { abs2rel($_, rel2abs(curdir())); }
                                 sort keys %tests);

# $ret->has_errors may be any number, not just 0 or 1.  On VMS, numbers
# from 2 and on are used as is as VMS statuses, which has severity encoded
# in the lower 3 bits.  0 and 1, on the other hand, generate SUCCESS and
# FAILURE, so for correct reporting on all platforms, we make sure the only
# exit codes are 0 and 1.  Double-bang is the trick to do so.
exit !!$ret->has_errors if (ref($ret) eq "TAP::Parser::Aggregator");

# If this isn't a TAP::Parser::Aggregator, it's the pre-TAP test harness,
# which simply dies at the end if any test failed, so we don't need to bother
# with any exit code in that case.

sub find_matching_tests {
    my ($glob) = @_;

    if ($glob =~ m|^[\d\[\]\?\-]+$|) {
        return glob(catfile($recipesdir,"$glob-*.t"));
    }
    return glob(catfile($recipesdir,"*-$glob.t"));
}

# Fake TAP::Harness in case it's not loaded
use Test::Harness;
package OpenSSL::TAP::Harness;

sub new {
    my $class = shift;
    my %args = %{ shift() };

    return bless { %args }, $class;
}

sub runtests {
    my $self = shift;

    my @switches = ();
    if ($self->{switches}) {
	push @switches, $self->{switches};
    }
    if ($self->{lib}) {
	foreach (@{$self->{lib}}) {
	    my $l = $_;

	    # It seems that $switches is getting interpreted with 'eval' or
	    # something like that, and that we need to take care of backslashes
	    # or they will disappear along the way.
	    $l =~ s|\\|\\\\|g if $^O eq "MSWin32";
	    push @switches, "-I$l";
	}
    }

    $Test::Harness::switches = join(' ', @switches);
    Test::Harness::runtests(@_);
}


#! /usr/bin/env perl
# Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License").  You may not use
# this file except in compliance with the License.  You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html

use strict;
use warnings;

use File::Compare qw/compare_text/;
use File::Copy;
use OpenSSL::Test qw/:DEFAULT/;

my %conversionforms = (
    # Default conversion forms.  Other series may be added with
    # specific test types as key.
    "*"		=> [ "d", "p" ],
    "msb"	=> [ "d", "p", "msblob" ],
    );
sub tconversion {
    my $testtype = shift;
    my $t = shift;
    my @conversionforms =
	defined($conversionforms{$testtype}) ?
	@{$conversionforms{$testtype}} :
	@{$conversionforms{"*"}};
    my @openssl_args = @_;
    if (!@openssl_args) { @openssl_args = ($testtype); }

    my $n = scalar @conversionforms;
    my $totaltests =
	1			# for initializing
	+ $n			# initial conversions from p to all forms (A)
	+ $n*$n			# conversion from result of A to all forms (B)
	+ 1			# comparing original test file to p form of A
	+ $n*($n-1);		# comparing first conversion to each fom in A with B
    $totaltests-- if ($testtype eq "p7d"); # no comparison of original test file
    plan tests => $totaltests;

    my @cmd = ("openssl", @openssl_args);

    my $init;
    if (scalar @openssl_args > 0 && $openssl_args[0] eq "pkey") {
	$init = ok(run(app([@cmd, "-in", $t, "-out", "$testtype-fff.p"])),
		   'initializing');
    } else {
	$init = ok(copy($t, "$testtype-fff.p"), 'initializing');
    }
    if (!$init) {
	diag("Trying to copy $t to $testtype-fff.p : $!");
    }

  SKIP: {
      skip "Not initialized, skipping...", 22 unless $init;

      foreach my $to (@conversionforms) {
	  ok(run(app([@cmd,
		      "-in", "$testtype-fff.p",
		      "-inform", "p",
		      "-out", "$testtype-f.$to",
		      "-outform", $to])),
	     "p -> $to");
      }

      foreach my $to (@conversionforms) {
	  foreach my $from (@conversionforms) {
	      ok(run(app([@cmd,
			  "-in", "$testtype-f.$from",
			  "-inform", $from,
			  "-out", "$testtype-ff.$from$to",
			  "-outform", $to])),
		 "$from -> $to");
	  }
      }

      if ($testtype ne "p7d") {
	  is(cmp_text("$testtype-fff.p", "$testtype-f.p"), 0,
	     'comparing orig to p');
      }

      foreach my $to (@conversionforms) {
	  next if $to eq "d";
	  foreach my $from (@conversionforms) {
	      is(cmp_text("$testtype-f.$to", "$testtype-ff.$from$to"), 0,
		 "comparing $to to $from$to");
	  }
      }
    }
    unlink glob "$testtype-f.*";
    unlink glob "$testtype-ff.*";
    unlink glob "$testtype-fff.*";
}

sub cmp_text {
    return compare_text(@_, sub {
        $_[0] =~ s/\R//g;
        $_[1] =~ s/\R//g;
        return $_[0] ne $_[1];
    });
}

1;


#! /usr/bin/env perl
# Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License").  You may not use
# this file except in compliance with the License.  You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html

use strict;
use warnings;

use lib '.';
use configdata;

use File::Spec::Functions qw(:DEFAULT rel2abs);
use File::Compare qw(compare_text);
use feature 'state';

# When using stat() on Windows, we can get it to perform better by avoid some
# data.  This doesn't affect the mtime field, so we're not losing anything...
${^WIN32_SLOPPY_STAT} = 1;

my $debug = $ENV{ADD_DEPENDS_DEBUG};
my $buildfile = $config{build_file};
my $build_mtime = (stat($buildfile))[9];
my $rebuild = 0;
my $depext = $target{dep_extension} || ".d";
my @depfiles =
    sort
    grep {
        # This grep has side effects.  Not only does if check the existence
        # of the dependency file given in $_, but it also checks if it's
        # newer than the build file, and if it is, sets $rebuild.
        my @st = stat($_);
        $rebuild = 1 if @st && $st[9] > $build_mtime;
        scalar @st > 0;         # Determines the grep result
    }
    map { (my $x = $_) =~ s|\.o$|$depext|; $x; }
    ( ( grep { $unified_info{sources}->{$_}->[0] =~ /\.cc?$/ }
            keys %{$unified_info{sources}} ),
      ( grep { $unified_info{shared_sources}->{$_}->[0] =~ /\.cc?$/ }
            keys %{$unified_info{shared_sources}} ) );

exit 0 unless $rebuild;

# Ok, primary checks are done, time to do some real work

my $producer = shift @ARGV;
die "Producer not given\n" unless $producer;

my $srcdir = $config{sourcedir};
my $blddir = $config{builddir};
my $abs_srcdir = rel2abs($srcdir);
my $abs_blddir = rel2abs($blddir);

# Convenient cache of absolute to relative map.  We start with filling it
# with mappings for the known generated header files.  They are relative to
# the current working directory, so that's an easy task.
# NOTE: there's more than C header files that are generated.  They will also
# generate entries in this map.  We could of course deal with C header files
# only, but in case we decide to handle more than just C files in the future,
# we already have the mechanism in place here.
# NOTE2: we lower case the index to make it searchable without regard for
# character case.  That could seem dangerous, but as long as we don't have
# files we depend on in the same directory that only differ by character case,
# we're fine.
my %depconv_cache =
    map { catfile($abs_blddir, $_) => $_ }
    keys %{$unified_info{generate}};

my %procedures = (
    'gcc' => undef,             # gcc style dependency files needs no mods
    'makedepend' =>
        sub {
            # makedepend, in its infinite wisdom, wants to have the object file
            # in the same directory as the source file.  This doesn't work too
            # well with out-of-source-tree builds, so we must resort to tricks
            # to get things right.  Fortunately, the .d files are always placed
            # parallel with the object files, so all we need to do is construct
            # the object file name from the dep file name.
            (my $objfile = shift) =~ s|\.d$|.o|i;
            my $line = shift;

            # Discard comments
            return undef if $line =~ /^(#.*|\s*)$/;

            # Remove the original object file
            $line =~ s|^.*\.o: | |;
            # Also, remove any dependency that starts with a /, because those
            # are typically system headers
            $line =~ s/\s+\/(\\.|\S)*//g;
            # Finally, discard all empty lines
            return undef if $line =~ /^\s*$/;

            # All we got now is a dependency, just shave off surrounding spaces
            $line =~ s/^\s+//;
            $line =~ s/\s+$//;
            return ($objfile, $line);
        },
    'VMS C' =>
        sub {
            state $abs_srcdir_shaved = undef;
            state $srcdir_shaved = undef;

            unless (defined $abs_srcdir_shaved) {
                ($abs_srcdir_shaved = $abs_srcdir) =~ s|[>\]]$||;
                ($srcdir_shaved = $srcdir) =~ s|[>\]]$||;
            }

            # current versions of DEC / Compaq / HP / VSI C strips away all
            # directory information from the object file, so we must insert it
            # back.  To make life simpler, we simply replace it with the
            # corresponding .D file that's had its extension changed.  Since
            # .D files are always written parallel to the object files, we
            # thereby get the directory information for free.
            (my $objfile = shift) =~ s|\.D$|.OBJ|i;
            my $line = shift;

            # Shave off the target.
            #
            # The pattern for target and dependencies will always take this
            # form:
            #
            #   target SPACE : SPACE deps
            #
            # This is so a volume delimiter (a : without any spaces around it)
            # won't get mixed up with the target / deps delimiter.  We use this
            # to easily identify what needs to be removed.
            m|\s:\s|; $line = $';

            # We know that VMS has system header files in text libraries,
            # extension .TLB.  We also know that our header files aren't stored
            # in text libraries.  Finally, we know that VMS C produces exactly
            # one dependency per line, so we simply discard any line ending with
            # .TLB.
            return undef if /\.TLB\s*$/;

            # All we got now is a dependency, just shave off surrounding spaces
            $line =~ s/^\s+//;
            $line =~ s/\s+$//;

            # VMS C gives us absolute paths, always.  Let's see if we can
            # make them relative instead.
            $line = canonpath($line);

            unless (defined $depconv_cache{$line}) {
                my $dep = $line;
                # Since we have already pre-populated the cache with
                # mappings for generated headers, we only need to deal
                # with the source tree.
                if ($dep =~ s|^\Q$abs_srcdir_shaved\E([\.>\]])?|$srcdir_shaved$1|i) {
                    $depconv_cache{$line} = $dep;
                }
            }
            return ($objfile, $depconv_cache{$line})
                if defined $depconv_cache{$line};
            print STDERR "DEBUG[VMS C]: ignoring $objfile <- $line\n"
                if $debug;

            return undef;
        },
    'VC' =>
        sub {
            # For the moment, we only support Visual C on native Windows, or
            # compatible compilers.  With those, the flags /Zs /showIncludes
            # give us the necessary output to be able to create dependencies
            # that nmake (or any 'make' implementation) should be able to read,
            # with a bit of help.  The output we're interested in looks like
            # this (it always starts the same)
            #
            #   Note: including file: {whatever header file}
            #
            # Since there's no object file name at all in that information,
            # we must construct it ourselves.

            (my $objfile = shift) =~ s|\.d$|.obj|i;
            my $line = shift;

            # There are also other lines mixed in, for example compiler
            # warnings, so we simply discard anything that doesn't start with
            # the Note:

            if (/^Note: including file: */) {
                (my $tail = $') =~ s/\s*\R$//;

                # VC gives us absolute paths for all include files, so to
                # remove system header dependencies, we need to check that
                # they don't match $abs_srcdir or $abs_blddir.
                $tail = canonpath($tail);

                unless (defined $depconv_cache{$tail}) {
                    my $dep = $tail;
                    # Since we have already pre-populated the cache with
                    # mappings for generated headers, we only need to deal
                    # with the source tree.
                    if ($dep =~ s|^\Q$abs_srcdir\E\\|\$(SRCDIR)\\|i) {
                        $depconv_cache{$tail} = $dep;
                    }
                }
                return ($objfile, '"'.$depconv_cache{$tail}.'"')
                    if defined $depconv_cache{$tail};
                print STDERR "DEBUG[VC]: ignoring $objfile <- $tail\n"
                    if $debug;
            }

            return undef;
        },
);
my %continuations = (
    'gcc' => undef,
    'makedepend' => "\\",
    'VMS C' => "-",
    'VC' => "\\",
);

die "Producer unrecognised: $producer\n"
    unless exists $procedures{$producer} && exists $continuations{$producer};

my $procedure = $procedures{$producer};
my $continuation = $continuations{$producer};

my $buildfile_new = "$buildfile-$$";

my %collect = ();
if (defined $procedure) {
    foreach my $depfile (@depfiles) {
        open IDEP,$depfile or die "Trying to read $depfile: $!\n";
        while (<IDEP>) {
            s|\R$||;                # The better chomp
            my ($target, $deps) = $procedure->($depfile, $_);
            $collect{$target}->{$deps} = 1 if defined $target;
        }
        close IDEP;
    }
}

open IBF, $buildfile or die "Trying to read $buildfile: $!\n";
open OBF, '>', $buildfile_new or die "Trying to write $buildfile_new: $!\n";
while (<IBF>) {
    last if /^# DO NOT DELETE THIS LINE/;
    print OBF or die "$!\n";
}
close IBF;

print OBF "# DO NOT DELETE THIS LINE -- make depend depends on it.\n";

if (defined $procedure) {
    foreach my $target (sort keys %collect) {
        my $prefix = $target . ' :';
        my @deps = sort keys %{$collect{$target}};

        while (@deps) {
            my $buf = $prefix;
            $prefix = '';

            while (@deps && ($buf eq ''
                                 || length($buf) + length($deps[0]) <= 77)) {
                $buf .= ' ' . shift @deps;
            }
            $buf .= ' '.$continuation if @deps;

            print OBF $buf,"\n" or die "Trying to print: $!\n"
        }
    }
} else {
    foreach my $depfile (@depfiles) {
        open IDEP,$depfile or die "Trying to read $depfile: $!\n";
        while (<IDEP>) {
            print OBF or die "Trying to print: $!\n";
        }
        close IDEP;
    }
}

close OBF;

if (compare_text($buildfile_new, $buildfile) != 0) {
    rename $buildfile_new, $buildfile
        or die "Trying to rename $buildfile_new -> $buildfile: $!\n";
}

END {
    # On VMS, we want to remove all generations of this file, in case there
    # are more than one, so we loop.
    if (defined $buildfile_new) {
        while (unlink $buildfile_new) {}
    }
}


#! /usr/bin/env perl
# Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the Apache License 2.0 (the "License").  You may not use
# this file except in compliance with the License.  You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html

#Convert CCM CAVS test vectors to a format suitable for evp_test

use strict;
use warnings;

my $alg;
my $mode;
my $keylen;
my $key = "";
my $iv = "";
my $aad = "";
my $ct = "";
my $pt = "";
my $tag = "";
my $aadlen = 0;
my $ptlen = 0;
my $taglen = 0;
my $res = "";
my $intest = 0;
my $fixediv = 0;

while (<STDIN>)
{
    chomp;

    # Pull out the cipher mode from the comment at the beginning of the file
    if(/^#\s*"([^-]+)-\w+" information/) {
        $mode = lc($1);
    # Pull out the key length from the comment at the beginning of the file
    } elsif(/^#\s*(\w+) Keylen: (\d+)/) {
        $alg = lc($1);
        $keylen = $2;
    # Some parameters common to many tests appear as a list in square brackets
    # so parse these
    } elsif(/\[(.*)\]/) {
        my @pairs = split(/, /, $1);
        foreach my $pair (@pairs) {
            $pair =~ /(\w+)\s*=\s*(\d+)/;
            # AAD Length
            if ($1 eq "Alen") {
                $aadlen = $2;
            # Plaintext length
            } elsif ($1 eq "Plen") {
                $ptlen = $2;
            # Tag length
            } elsif ($1 eq "Tlen") {
                $taglen = $2;
            }
        }
    # Key/Value pair
    } elsif (/^\s*(\w+)\s*=\s*(\S.*)\r/) {
        if ($1 eq "Key") {
            $key = $2;
        } elsif ($1 eq "Nonce") {
            $iv = $2;
            if ($intest == 0) {
                $fixediv = 1;
            } else {
                $fixediv = 0;
            }
        } elsif ($1 eq "Adata") {
            $aad = $2;
        } elsif ($1 eq "CT") {
            $ct = substr($2, 0, length($2) - ($taglen * 2));
            $tag = substr($2, $taglen * -2);
        } elsif ($1 eq "Payload") {
            $pt = $2;
        } elsif ($1 eq "Result") {
            if ($2 =~ /Fail/) {
                $res = "CIPHERUPDATE_ERROR";
            }
        } elsif ($1 eq "Count") {
            $intest = 1;
        } elsif ($1 eq "Plen") {
            $ptlen = $2;
        } elsif ($1 eq "Tlen") {
            $taglen = $2;
        } elsif ($1 eq "Alen") {
            $aadlen = $2;
        }
    # Something else - probably just a blank line
    } elsif ($intest) {
        print "Cipher = $alg-$keylen-$mode\n";
        print "Key = $key\n";
        print "IV = $iv\n";
        print "AAD =";
        if ($aadlen > 0) {
            print " $aad";
        }
        print "\nTag =";
        if ($taglen > 0) {
            print " $tag";
        }
        print "\nPlaintext =";
        if ($ptlen > 0) {
            print " $pt";
        }
        print "\nCiphertext = $ct\n";
        if ($res ne "") {
            print "Operation = DECRYPT\n";
            print "Result = $res\n";
        }
        print "\n";
        $res = "";
        if ($fixediv == 0) {
            $iv = "";
        }
        $aad = "";
        $tag = "";
        $pt = "";
        $intest = 0;
    }
}


#! /usr/bin/env perl
# Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License").  You may not use
# this file except in compliance with the License.  You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html

# This is just a quick script to scan for cases where the 'error'
# function name in a XXXerr() macro is wrong.
#
# Run in the top level by going
# perl util/ck_errf.pl */*.c */*/*.c
#

use strict;
use warnings;

my $config;
my $err_strict = 0;
my $debug      = 0;
my $internal   = 0;

sub help
{
    print STDERR <<"EOF";
mkerr.pl [options] [files...]

Options:

    -conf FILE  Use the named config file FILE instead of the default.

    -debug      Verbose output debugging on stderr.

    -internal   Generate code that is to be built as part of OpenSSL itself.
                Also scans internal list of files.

    -strict     If any error was found, fail with exit code 1, otherwise 0.

    -help       Show this help text.

    ...         Additional arguments are added to the file list to scan,
                if '-internal' was NOT specified on the command line.

EOF
}

while ( @ARGV ) {
    my $arg = $ARGV[0];
    last unless $arg =~ /-.*/;
    $arg = $1 if $arg =~ /-(-.*)/;
    if ( $arg eq "-conf" ) {
        $config = $ARGV[1];
        shift @ARGV;
    } elsif ( $arg eq "-debug" ) {
        $debug = 1;
    } elsif ( $arg eq "-internal" ) {
        $internal = 1;
    } elsif ( $arg eq "-strict" ) {
        $err_strict = 1;
    } elsif ( $arg =~ /-*h(elp)?/ ) {
        &help();
        exit;
    } elsif ( $arg =~ /-.*/ ) {
        die "Unknown option $arg; use -h for help.\n";
    }
    shift @ARGV;
}

my @source;
if ( $internal ) {
    die "Extra parameters given.\n" if @ARGV;
    $config = "crypto/err/openssl.ec" unless defined $config;
    @source = ( glob('crypto/*.c'), glob('crypto/*/*.c'),
                glob('ssl/*.c'), glob('ssl/*/*.c') );
} else {
    die "Configuration file not given.\nSee '$0 -help' for information\n"
        unless defined $config;
    @source = @ARGV;
}

# To detect if there is any error generation for a libcrypto/libssl libs
# we don't know, we need to find out what libs we do know.  That list is
# readily available in crypto/err/openssl.ec, in form of lines starting
# with "L ".  Note that we always rely on the modules SYS and ERR to be
# generally available.
my %libs       = ( SYS => 1, ERR => 1 );
open my $cfh, $config or die "Trying to read $config: $!\n";
while (<$cfh>) {
    s|\R$||;                    # Better chomp
    next unless m|^L ([0-9A-Z_]+)\s|;
    next if $1 eq "NONE";
    $libs{$1} = 1;
}

my $bad = 0;
foreach my $file (@source) {
    open( IN, "<$file" ) || die "Can't open $file, $!";
    my $func = "";
    while (<IN>) {
        if ( !/;$/ && /^\**([a-zA-Z_].*[\s*])?([A-Za-z_0-9]+)\(.*([),]|$)/ ) {
            /^([^()]*(\([^()]*\)[^()]*)*)\(/;
            $1 =~ /([A-Za-z_0-9]*)$/;
            $func = $1;
            $func =~ tr/A-Z/a-z/;
        }
        if ( /([A-Z0-9_]+[A-Z0-9])err\(([^,]+)/ && !/ckerr_ignore/ ) {
            my $errlib = $1;
            my $n      = $2;

            unless ( $libs{$errlib} ) {
                print "$file:$.:$errlib not listed in $config\n";
                $libs{$errlib} = 1; # To not display it again
                $bad = 1;
            }

            if ( $func eq "" ) {
                print "$file:$.:???:$n\n";
                $bad = 1;
                next;
            }

            if ( $n !~ /^(.+)_F_(.+)$/ ) {
                #print "check -$file:$.:$func:$n\n";
                next;
            }
            my $lib = $1;
            $n   = $2;

            if ( $lib ne $errlib ) {
                print "$file:$.:$func:$n [${errlib}err]\n";
                $bad = 1;
                next;
            }

            $n =~ tr/A-Z/a-z/;
            if ( $n ne $func && $errlib ne "SYS" ) {
                print "$file:$.:$func:$n\n";
                $bad = 1;
                next;
            }

            #		print "$func:$1\n";
        }
    }
    close(IN);
}

if ( $bad && $err_strict ) {
    print STDERR "FATAL: error discrepancy\n";
    exit 1;
}


#! /usr/bin/env perl
# Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License").  You may not use
# this file except in compliance with the License.  You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html

use Fcntl;

# copy.pl

# Perl script 'copy' comment. On Windows the built in "copy" command also
# copies timestamps: this messes up Makefile dependencies.

my $stripcr = 0;

my $arg;
my @excludes = ();

foreach $arg (@ARGV) {
	if ($arg eq "-stripcr")
		{
		$stripcr = 1;
		next;
		}
	if ($arg =~ /^-exclude_re=(.*)$/)
		{
		push @excludes, $1;
		next;
		}
	$arg =~ s|\\|/|g;	# compensate for bug/feature in cygwin glob...
	$arg = qq("$arg") if ($arg =~ /\s/);	# compensate for bug in 5.10...
	foreach my $f (glob $arg)
		{
		push @filelist, $f unless grep { $f =~ /$_/ } @excludes;
		}
}

$fnum = @filelist;

if ($fnum <= 1)
	{
	die "Need at least two filenames";
	}

$dest = pop @filelist;

if ($fnum > 2 && ! -d $dest)
	{
	die "Destination must be a directory";
	}

foreach (@filelist)
	{
	if (-d $dest)
		{
		$dfile = $_;
		$dfile =~ s|^.*[/\\]([^/\\]*)$|$1|;
		$dfile = "$dest/$dfile";
		}
	else
		{
		$dfile = $dest;
		}
	sysopen(IN, $_, O_RDONLY|O_BINARY) || die "Can't Open $_";
	sysopen(OUT, $dfile, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY)
					|| die "Can't Open $dfile";
	while (sysread IN, $buf, 10240)
		{
		if ($stripcr)
			{
			$buf =~ tr/\015//d;
			}
		syswrite(OUT, $buf, length($buf));
		}
	close(IN);
	close(OUT);
	print "Copying: $_ to $dfile\n";
	}


#! /usr/bin/env perl
# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License").  You may not use
# this file except in compliance with the License.  You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html

# Reads one or more template files and runs it through Text::Template
#
# It is assumed that this scripts is called with -Mconfigdata, a module
# that holds configuration data in %config

use strict;
use warnings;

use FindBin;
use Getopt::Std;

# We actually expect to get the following hash tables from configdata:
#
#    %config
#    %target
#    %withargs
#    %unified_info
#
# We just do a minimal test to see that we got what we expected.
# $config{target} must exist as an absolute minimum.
die "You must run this script with -Mconfigdata\n" if !exists($config{target});

# Make a subclass of Text::Template to override append_text_to_result,
# as recommended here:
#
# http://search.cpan.org/~mjd/Text-Template-1.46/lib/Text/Template.pm#Automatic_postprocessing_of_template_hunks

package OpenSSL::Template;

# Because we know that Text::Template isn't a core Perl module, we use
# a fallback in case it's not installed on the system
use File::Basename;
use File::Spec::Functions;
use lib "$FindBin::Bin/perl";
use with_fallback "Text::Template 1.46";

#use parent qw/Text::Template/;
use vars qw/@ISA/;
push @ISA, qw/Text::Template/;

# Override constructor
sub new {
    my ($class) = shift;

    # Call the constructor of the parent class, Person.
    my $self = $class->SUPER::new( @_ );
    # Add few more attributes
    $self->{_output_off}   = 0;	# Default to output hunks
    bless $self, $class;
    return $self;
}

sub append_text_to_output {
    my $self = shift;

    if ($self->{_output_off} == 0) {
	$self->SUPER::append_text_to_output(@_);
    }

    return;
}

sub output_reset_on {
    my $self = shift;
    $self->{_output_off} = 0;
}

sub output_on {
    my $self = shift;
    if (--$self->{_output_off} < 0) {
	$self->{_output_off} = 0;
    }
}

sub output_off {
    my $self = shift;
    $self->{_output_off}++;
}

# Come back to main

package main;

# Helper functions for the templates #################################

# It might be practical to quotify some strings and have them protected
# from possible harm.  These functions primarily quote things that might
# be interpreted wrongly by a perl eval.

# quotify1 STRING
# This adds quotes (") around the given string, and escapes any $, @, \,
# " and ' by prepending a \ to them.
sub quotify1 {
    my $s = shift @_;
    $s =~ s/([\$\@\\"'])/\\$1/g;
    '"'.$s.'"';
}

# quotify_l LIST
# For each defined element in LIST (i.e. elements that aren't undef), have
# it quotified with 'quotify1'
sub quotify_l {
    map {
        if (!defined($_)) {
            ();
        } else {
            quotify1($_);
        }
    } @_;
}

# Error reporter #####################################################

# The error reporter uses %lines to figure out exactly which file the
# error happened and at what line.  Not that the line number may be
# the start of a perl snippet rather than the exact line where it
# happened.  Nothing we can do about that here.

my %lines = ();
sub broken {
    my %args = @_;
    my $filename = "<STDIN>";
    my $deducelines = 0;
    foreach (sort keys %lines) {
        $filename = $lines{$_};
        last if ($_ > $args{lineno});
        $deducelines += $_;
    }
    print STDERR $args{error}," in $filename, fragment starting at line ",$args{lineno}-$deducelines;
    undef;
}

# Check options ######################################################

my %opts = ();

# -o ORIGINATOR
#		declares ORIGINATOR as the originating script.
getopt('o', \%opts);

my @autowarntext = ("WARNING: do not edit!",
		    "Generated"
		    . (defined($opts{o}) ? " by ".$opts{o} : "")
		    . (scalar(@ARGV) > 0 ? " from ".join(", ",@ARGV) : ""));

# Template reading ###################################################

# Read in all the templates into $text, while keeping track of each
# file and its size in lines, to try to help report errors with the
# correct file name and line number.

my $prev_linecount = 0;
my $text =
    @ARGV
    ? join("", map { my $x = Text::Template::_load_text($_);
                     if (!defined($x)) {
                         die $Text::Template::ERROR, "\n";
                     }
                     $x = "{- output_reset_on() -}" . $x;
                     my $linecount = $x =~ tr/\n//;
                     $prev_linecount = ($linecount += $prev_linecount);
                     $lines{$linecount} = $_;
                     $x } @ARGV)
    : join("", <STDIN>);

# Engage! ############################################################

# Load the full template (combination of files) into Text::Template
# and fill it up with our data.  Output goes directly to STDOUT

my $template =
    OpenSSL::Template->new(TYPE => 'STRING',
                           SOURCE => $text,
                           PREPEND => qq{use lib "$FindBin::Bin/perl";});

sub output_reset_on {
    $template->output_reset_on();
    "";
}
sub output_on {
    $template->output_on();
    "";
}
sub output_off {
    $template->output_off();
    "";
}

$template->fill_in(OUTPUT => \*STDOUT,
                   HASH => { config => \%config,
                             target => \%target,
                             disabled => \%disabled,
                             withargs => \%withargs,
                             unified_info => \%unified_info,
                             autowarntext => \@autowarntext,
                             quotify1 => \&quotify1,
                             quotify_l => \&quotify_l,
                             output_reset_on => \&output_reset_on,
                             output_on => \&output_on,
                             output_off => \&output_off },
                   DELIMITERS => [ "{-", "-}" ],
                   BROKEN => \&broken);


#! /usr/bin/perl

use strict;
use warnings;
use Getopt::Std;

our $opt_n = 0;

getopts('n') or die "Invalid option: $!\n";

print join(' ', @ARGV);
print "\n" unless $opt_n;


#! /usr/bin/env perl
# Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License").  You may not use
# this file except in compliance with the License.  You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html

use strict;
use warnings;

my ($cflags, $platform) = @ARGV;
$cflags = "compiler: $cflags";

my $date = gmtime($ENV{'SOURCE_DATE_EPOCH'} || time()) . " UTC";

print <<"END_OUTPUT";
/*
 * WARNING: do not edit!
 * Generated by util/mkbuildinf.pl
 *
 * Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#define PLATFORM "platform: $platform"
#define DATE "built on: $date"

/*
 * Generate compiler_flags as an array of individual characters. This is a
 * workaround for the situation where CFLAGS gets too long for a C90 string
 * literal
 */
static const char compiler_flags[] = {
END_OUTPUT

my $ctr = 0;
foreach my $c (split //, $cflags) {
    $c =~ s|([\\'])|\\$1|;
    # Max 16 characters per line
    if  (($ctr++ % 16) == 0) {
        if ($ctr != 1) {
            print "\n";
        }
        print "    ";
    }
    print "'$c',";
}
print <<"END_OUTPUT";
'\\0'
};
END_OUTPUT