1#!/usr/local/bin/perl 2 3print "1..26\n"; 4 5BEGIN { require './t/funcs.pl' } 6 7use Convert::ASN1; 8 9my $t = 1; 10 11my $asn = Convert::ASN1->new; 12btest $t++, $asn->prepare(<<ASN1); 13-- ASN.1 from RFC2459 and X.509(2001) 14-- Adapted for use with Convert::ASN1 15-- Id: x509decode,v 1.1 2002/02/10 16:41:28 gbarr Exp 16 17-- attribute data types -- 18 19Attribute ::= SEQUENCE { 20 type AttributeType, 21 values SET OF AttributeValue 22 -- at least one value is required -- 23 } 24 25AttributeType ::= OBJECT IDENTIFIER 26 27AttributeValue ::= DirectoryString --ANY 28 29AttributeTypeAndValue ::= SEQUENCE { 30 type AttributeType, 31 value AttributeValue 32 } 33 34 35-- naming data types -- 36 37Name ::= CHOICE { -- only one possibility for now 38 rdnSequence RDNSequence 39 } 40 41RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 42 43DistinguishedName ::= RDNSequence 44 45RelativeDistinguishedName ::= 46 SET OF AttributeTypeAndValue --SET SIZE (1 .. MAX) OF 47 48 49-- Directory string type -- 50 51DirectoryString ::= CHOICE { 52 teletexString TeletexString, --(SIZE (1..MAX)), 53 printableString PrintableString, --(SIZE (1..MAX)), 54 bmpString BMPString, --(SIZE (1..MAX)), 55 universalString UniversalString, --(SIZE (1..MAX)), 56 utf8String UTF8String, --(SIZE (1..MAX)), 57 ia5String IA5String, --added for EmailAddress, 58 integer INTEGER 59 } 60 61 62-- certificate and CRL specific structures begin here 63 64Certificate ::= SEQUENCE { 65 tbsCertificate TBSCertificate, 66 signatureAlgorithm AlgorithmIdentifier, 67 signature BIT STRING 68 } 69 70TBSCertificate ::= SEQUENCE { 71 version [0] EXPLICIT Version OPTIONAL, --DEFAULT v1 72 serialNumber CertificateSerialNumber, 73 signature AlgorithmIdentifier, 74 issuer Name, 75 validity Validity, 76 subject Name, 77 subjectPublicKeyInfo SubjectPublicKeyInfo, 78 issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, 79 -- If present, version shall be v2 or v3 80 subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, 81 -- If present, version shall be v2 or v3 82 extensions [3] EXPLICIT Extensions OPTIONAL 83 -- If present, version shall be v3 84 } 85 86Version ::= INTEGER --{ v1(0), v2(1), v3(2) } 87 88CertificateSerialNumber ::= INTEGER 89 90Validity ::= SEQUENCE { 91 notBefore Time, 92 notAfter Time 93 } 94 95Time ::= CHOICE { 96 utcTime UTCTime, 97 generalTime GeneralizedTime 98 } 99 100UniqueIdentifier ::= BIT STRING 101 102SubjectPublicKeyInfo ::= SEQUENCE { 103 algorithm AlgorithmIdentifier, 104 subjectPublicKey BIT STRING 105 } 106 107 108RSAPubKeyInfo ::= SEQUENCE { 109 modulus INTEGER, 110 exponent INTEGER 111 } 112 113Extensions ::= SEQUENCE OF Extension --SIZE (1..MAX) OF Extension 114 115Extension ::= SEQUENCE { 116 extnID OBJECT IDENTIFIER, 117 critical BOOLEAN OPTIONAL, --DEFAULT FALSE, 118 extnValue OCTET STRING 119 } 120 121AlgorithmIdentifier ::= SEQUENCE { 122 algorithm OBJECT IDENTIFIER, 123 parameters ANY OPTIONAL 124 } 125 126 127--extensions 128 129AuthorityKeyIdentifier ::= SEQUENCE { 130 keyIdentifier [0] KeyIdentifier OPTIONAL, 131 authorityCertIssuer [1] GeneralNames OPTIONAL, 132 authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } 133 -- authorityCertIssuer and authorityCertSerialNumber shall both 134 -- be present or both be absent 135 136KeyIdentifier ::= OCTET STRING 137 138SubjectKeyIdentifier ::= KeyIdentifier 139 140-- key usage extension OID and syntax 141 142-- id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } 143 144KeyUsage ::= BIT STRING --{ 145-- digitalSignature (0), 146-- nonRepudiation (1), 147-- keyEncipherment (2), 148-- dataEncipherment (3), 149-- keyAgreement (4), 150-- keyCertSign (5), 151-- cRLSign (6), 152-- encipherOnly (7), 153-- decipherOnly (8) } 154 155 156-- private key usage period extension OID and syntax 157 158-- id-ce-privateKeyUsagePeriod OBJECT IDENTIFIER ::= { id-ce 16 } 159 160PrivateKeyUsagePeriod ::= SEQUENCE { 161 notBefore [0] GeneralizedTime OPTIONAL, 162 notAfter [1] GeneralizedTime OPTIONAL } 163 -- either notBefore or notAfter shall be present 164 165-- certificate policies extension OID and syntax 166-- id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } 167 168CertificatePolicies ::= SEQUENCE OF PolicyInformation 169 170PolicyInformation ::= SEQUENCE { 171 policyIdentifier CertPolicyId, 172 policyQualifiers SEQUENCE OF 173 PolicyQualifierInfo OPTIONAL } 174 175CertPolicyId ::= OBJECT IDENTIFIER 176 177PolicyQualifierInfo ::= SEQUENCE { 178 policyQualifierId PolicyQualifierId, 179 qualifier ANY } --DEFINED BY policyQualifierId } 180 181-- Implementations that recognize additional policy qualifiers shall 182-- augment the following definition for PolicyQualifierId 183 184PolicyQualifierId ::= 185 OBJECT IDENTIFIER --( id-qt-cps | id-qt-unotice ) 186 187-- CPS pointer qualifier 188 189CPSuri ::= IA5String 190 191-- user notice qualifier 192 193UserNotice ::= SEQUENCE { 194 noticeRef NoticeReference OPTIONAL, 195 explicitText DisplayText OPTIONAL} 196 197NoticeReference ::= SEQUENCE { 198 organization DisplayText, 199 noticeNumbers SEQUENCE OF INTEGER } 200 201DisplayText ::= CHOICE { 202 visibleString VisibleString , 203 bmpString BMPString , 204 utf8String UTF8String } 205 206 207-- policy mapping extension OID and syntax 208-- id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } 209 210PolicyMappings ::= SEQUENCE OF SEQUENCE { 211 issuerDomainPolicy CertPolicyId, 212 subjectDomainPolicy CertPolicyId } 213 214 215-- subject alternative name extension OID and syntax 216-- id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } 217 218SubjectAltName ::= GeneralNames 219 220GeneralNames ::= SEQUENCE OF GeneralName 221 222GeneralName ::= CHOICE { 223 otherName [0] AnotherName, 224 rfc822Name [1] IA5String, 225 dNSName [2] IA5String, 226 x400Address [3] ANY, --ORAddress, 227 directoryName [4] Name, 228 ediPartyName [5] EDIPartyName, 229 uniformResourceIdentifier [6] IA5String, 230 iPAddress [7] OCTET STRING, 231 registeredID [8] OBJECT IDENTIFIER } 232 233EntrustVersionInfo ::= SEQUENCE { 234 entrustVers GeneralString, 235 entrustInfoFlags EntrustInfoFlags } 236 237EntrustInfoFlags::= BIT STRING --{ 238-- keyUpdateAllowed 239-- newExtensions (1), -- not used 240-- pKIXCertificate (2) } -- certificate created by pkix 241 242-- AnotherName replaces OTHER-NAME ::= TYPE-IDENTIFIER, as 243-- TYPE-IDENTIFIER is not supported in the 88 ASN.1 syntax 244 245AnotherName ::= SEQUENCE { 246 type OBJECT IDENTIFIER, 247 value [0] EXPLICIT ANY } --DEFINED BY type-id } 248 249EDIPartyName ::= SEQUENCE { 250 nameAssigner [0] DirectoryString OPTIONAL, 251 partyName [1] DirectoryString } 252 253 254-- issuer alternative name extension OID and syntax 255-- id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } 256 257IssuerAltName ::= GeneralNames 258 259 260-- id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } 261 262SubjectDirectoryAttributes ::= SEQUENCE OF Attribute 263 264 265-- basic constraints extension OID and syntax 266-- id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } 267 268BasicConstraints ::= SEQUENCE { 269 cA BOOLEAN OPTIONAL, --DEFAULT FALSE, 270 pathLenConstraint INTEGER OPTIONAL } 271 272 273-- name constraints extension OID and syntax 274-- id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } 275 276NameConstraints ::= SEQUENCE { 277 permittedSubtrees [0] GeneralSubtrees OPTIONAL, 278 excludedSubtrees [1] GeneralSubtrees OPTIONAL } 279 280GeneralSubtrees ::= SEQUENCE OF GeneralSubtree 281 282GeneralSubtree ::= SEQUENCE { 283 base GeneralName, 284 minimum [0] BaseDistance OPTIONAL, --DEFAULT 0, 285 maximum [1] BaseDistance OPTIONAL } 286 287BaseDistance ::= INTEGER 288 289 290-- policy constraints extension OID and syntax 291-- id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } 292 293PolicyConstraints ::= SEQUENCE { 294 requireExplicitPolicy [0] SkipCerts OPTIONAL, 295 inhibitPolicyMapping [1] SkipCerts OPTIONAL } 296 297SkipCerts ::= INTEGER 298 299 300-- CRL distribution points extension OID and syntax 301-- id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= {id-ce 31} 302 303cRLDistributionPoints ::= SEQUENCE OF DistributionPoint 304 305DistributionPoint ::= SEQUENCE { 306 distributionPoint [0] DistributionPointName OPTIONAL, 307 reasons [1] ReasonFlags OPTIONAL, 308 cRLIssuer [2] GeneralNames OPTIONAL } 309 310DistributionPointName ::= CHOICE { 311 fullName [0] GeneralNames, 312 nameRelativeToCRLIssuer [1] RelativeDistinguishedName } 313 314ReasonFlags ::= BIT STRING --{ 315-- unused (0), 316-- keyCompromise (1), 317-- cACompromise (2), 318-- affiliationChanged (3), 319-- superseded (4), 320-- cessationOfOperation (5), 321-- certificateHold (6), 322-- privilegeWithdrawn (7), 323-- aACompromise (8) } 324 325 326-- extended key usage extension OID and syntax 327-- id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37} 328 329ExtKeyUsageSyntax ::= SEQUENCE OF KeyPurposeId 330 331KeyPurposeId ::= OBJECT IDENTIFIER 332 333-- extended key purpose OIDs 334-- id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } 335-- id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } 336-- id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } 337-- id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } 338-- id-kp-ipsecEndSystem OBJECT IDENTIFIER ::= { id-kp 5 } 339-- id-kp-ipsecTunnel OBJECT IDENTIFIER ::= { id-kp 6 } 340-- id-kp-ipsecUser OBJECT IDENTIFIER ::= { id-kp 7 } 341-- id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } 342 343-- authority info access 344 345-- id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 } 346 347AuthorityInfoAccessSyntax ::= 348 SEQUENCE OF AccessDescription --SIZE (1..MAX) OF AccessDescription 349 350AccessDescription ::= SEQUENCE { 351 accessMethod OBJECT IDENTIFIER, 352 accessLocation GeneralName } 353 354-- subject info access 355 356-- id-pe-subjectInfoAccess OBJECT IDENTIFIER ::= { id-pe 11 } 357 358SubjectInfoAccessSyntax ::= 359 SEQUENCE OF AccessDescription --SIZE (1..MAX) OF AccessDescription 360 361-- pgp creation time 362 363PGPExtension ::= SEQUENCE { 364 version Version, -- DEFAULT v1(0) 365 keyCreation Time 366} 367ASN1 368 369btest $t++, my $parser = $asn->find('Certificate'); 370btest $t++, my $crlp = $asn->find('cRLDistributionPoints'); 371 372my %certs = ( 373 't/aj.cer' => ["http://rootca.allianz.com/ad-ca/ad-ca.crl"], 374 't/aj2.cer' => ["http://rootca.allianz.com/sc-ad-ca/sc-ad-ca.crl"], 375 't/allianz_root.cer' => ["http://rootca.allianz.com/rootca.crl"], 376 't/pgpextension.der' => ["http://ca.mayfirst.org/mfpl.crl"], 377 't/subca_2.cer' => [ 378 "ldap://ldap.treas.gov/cn=CRL1,ou=US%20Treasury%20Root%20CA,ou=Certification%20Authorities,ou=Department%20of%20the%20Treasury,o=U.S.%20Government,c=US?authorityRevocationList" 379 ], 380 't/dsacert.der' => undef, 381 't/new_root_ca.cer' => undef, 382 't/telesec_799972029.crt' => undef, 383 't/verisign.der' => undef, 384); 385 386for my $file (sort keys %certs) { 387 print "# $file\n"; 388 my $cert = loadcert($file); 389 btest $t++, my $data = $parser->decode($cert); 390 $data ||= {}; 391 my $extns = $data->{tbsCertificate}{extensions} || []; 392 393 my ($ext) = grep { $_->{'extnID'} eq '2.5.29.31' } @$extns; 394 if ($ext) { 395 my $points = $crlp->decode($ext->{'extnValue'}); # decode the value 396 $points = $points && $points->[0]->{'distributionPoint'}->{'fullName'}; 397 btest $t++, !$crlp->error or warn($crlp->error); 398 my @points = grep $_, map { $_->{'uniformResourceIdentifier'} } @{$points || []}; 399 rtest $t++, $certs{$file}, \@points; 400 } 401 else { 402 btest $t++, !$certs{$file}; 403 } 404} 405 406sub loadcert { 407 my $file = shift; 408 open FILE, $file || die "cannot load test certificate" . $file . "\n"; 409 binmode FILE; # HELLO Windows, dont fuss with this 410 my $holdTerminator = $/; 411 undef $/; # using slurp mode to read the DER-encoded binary certificate 412 my $cert = <FILE>; 413 $/ = $holdTerminator; 414 close FILE; 415 return $cert; 416} 417