Home | History | Annotate | Download | only in nist-pkits
      1 #!/usr/bin/env perl
      2 #
      3 # Copyright (C) 2012 The Android Open Source Project
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the "License");
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #      http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS IS" BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 #
     17 
     18 #
     19 # This script parses the NIST PKI Test Suite test descriptions document
     20 # and creates a .java file with test cases.
     21 #
     22 
     23 use strict;
     24 
     25 my $enabled = 0;
     26 my $readingPath = 0;
     27 my $sectionName;
     28 my $testNumber;
     29 my $testName;
     30 my $pathEntry = "";
     31 my $expectedOutcome;
     32 my @pathEntries;
     33 
     34 my @usedFiles = ();
     35 
     36 my $delimiter = "\x{2022}";
     37 utf8::encode($delimiter);
     38 
     39 if ($#ARGV != 2) {
     40     die "Usage: $0 <text-descriptions> <java-output> <used-files-output>";
     41 }
     42 
     43 open(DESC_FILE, "<", $ARGV[0]);
     44 open(OUTPUT_FILE, ">", $ARGV[1]);
     45 open(USED_FILES, ">", $ARGV[2]);
     46 
     47 sub trim($) {
     48     my $s = shift;
     49     $s =~ s/^\s+//g;
     50     $s =~ s/\s+$//g;
     51     return $s;
     52 }
     53 
     54 sub printTest() {
     55     my @certNames;
     56     my @crlNames;
     57 
     58     foreach my $entry (@pathEntries) {
     59         $entry =~ s/ //g;
     60         $entry =~ s/-//g;
     61         my @parts = split(/,/, $entry);
     62         for my $part (@parts) {
     63             if ($part =~ /CRL[0-9]*$/) {
     64                 my $crlName = $part . ".crl";
     65                 push(@crlNames, $crlName);
     66                 push(@usedFiles, "crls/" . $crlName);
     67             } else {
     68                 my $certName = $part . ".crt";
     69                 push(@certNames, $certName);
     70                 push(@usedFiles, "certs/" . $certName);
     71             }
     72         }
     73     }
     74 
     75     print OUTPUT_FILE <<EOF;
     76     /** NIST PKITS test ${testNumber} */
     77     public void test${sectionName}_${testName}() throws Exception {
     78 EOF
     79     print OUTPUT_FILE " " x 8 . "String trustAnchor = \"" . (shift @certNames) . "\";\n";
     80 
     81     print OUTPUT_FILE <<EOF;
     82 
     83         String[] certs = {
     84 EOF
     85 
     86     # Print the CertPath in reverse order.
     87     for (0..$#certNames) {
     88         print OUTPUT_FILE " " x 16 . "\"${certNames[$#certNames - $_]}\",\n";
     89     }
     90     print OUTPUT_FILE <<EOF;
     91         };
     92 
     93         String[] crls = {
     94 EOF
     95     foreach my $crlName (@crlNames) {
     96         print OUTPUT_FILE " " x 16 . "\"${crlName}\",\n";
     97     }
     98     print OUTPUT_FILE <<EOF;
     99         };
    100 
    101 EOF
    102     if ($expectedOutcome) {
    103         print OUTPUT_FILE <<EOF;
    104         assertValidPath(trustAnchor, certs, crls);
    105 EOF
    106     } else {
    107         print OUTPUT_FILE <<EOF;
    108         assertInvalidPath(trustAnchor, certs, crls);
    109 EOF
    110     }
    111 
    112         print OUTPUT_FILE <<EOF;
    113     }
    114 
    115 EOF
    116 }
    117 
    118 sub stopReadingPath() {
    119     if ($readingPath) {
    120         if (defined($pathEntry) and $pathEntry ne "") {
    121             push(@pathEntries, $pathEntry);
    122             $pathEntry = "";
    123         }
    124 
    125         printTest();
    126         @pathEntries = ();
    127         $readingPath = 0;
    128     }
    129 }
    130 
    131 
    132 while (<DESC_FILE>) {
    133     chomp;
    134 
    135     if ($_ =~ /^\s*4 Certification Path Validation Tests$/) {
    136         $enabled = 1;
    137         next;
    138     }
    139 
    140     #
    141     # TODO: this script needs to be fixed to support the test cases in
    142     # 4.8 to 4.12
    143     #
    144 
    145     if ($_ =~ /^\s*4\.8 Certificate Policies\s*$/) {
    146         stopReadingPath();
    147         $enabled = 0;
    148 
    149         print OUTPUT_FILE " "x4 . "// skipping sections 4.8 to 4.12\n\n";
    150         next;
    151     }
    152 
    153     if ($_ =~ /^\s*4\.13 Name Constraints\s*$/) {
    154         $enabled = 1;
    155         next;
    156     }
    157 
    158     if ($_ =~ /^\s*5 Relationship to Previous Test Suite\s*[^.]/) {
    159         stopReadingPath();
    160         $enabled = 0;
    161         exit;
    162     }
    163 
    164     if (!$enabled) {
    165         next;
    166     }
    167 
    168     if ($_ =~ /^\s*4\.[0-9]+ (.*)$/) {
    169         stopReadingPath();
    170         $sectionName = $1;
    171         $sectionName =~ s/ //g;
    172         $sectionName =~ s/-//g;
    173     }
    174 
    175     if ($_ =~ /^\s*(4\.[0-9]+\.[0-9]+) (.*)$/) {
    176         stopReadingPath();
    177         $testNumber = $1;
    178         $testName = $2;
    179         $testName =~ s/ //g;
    180         $testName =~ s/-//g;
    181     }
    182 
    183     if ($_ =~ /Expected Result:.*(should validate|should not validate)/) {
    184         if ($1 eq "should validate") {
    185             $expectedOutcome = 1;
    186         } else {
    187             $expectedOutcome = 0;
    188         }
    189     } elsif ($_ =~ /Expected Result:/) {
    190         die "Can not determine expected result for test:\n\t${testName}";
    191     }
    192 
    193     if ($_ =~ /^\s*Certification Path:/) {
    194         $readingPath = 1;
    195         next;
    196     }
    197 
    198     if ($readingPath) {
    199         # Page number from the PDF
    200         if (trim($_) =~ /^[0-9]+$/) {
    201             do {
    202                 $_ = <DESC_FILE>;
    203                 if ($_ =~ /^\s*$/) {
    204                     next;
    205                 }
    206             } while (1);
    207         }
    208 
    209         if ($_ =~ /${delimiter}\s*(.*)$/u) {
    210             if (defined($pathEntry) and $pathEntry ne "") {
    211                 push(@pathEntries, $pathEntry);
    212             }
    213             $pathEntry = trim($1);
    214         } else {
    215             if ($_ =~ /The certification path is composed of the following objects:(.*)$/) {
    216                 $pathEntry = trim($1);
    217             } else {
    218                 $pathEntry .= trim($_);
    219             }
    220         }
    221     }
    222 }
    223 
    224 print USED_FILES join("\n", keys %{{map{$_ => 1} @usedFiles}});
    225 
    226 close(DESC_FILE);
    227 close(OUTPUT_FILE);
    228 close(USED_FILES);
    229