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