File Coverage

blib/lib/Crypt/X509/CRL.pm
Criterion Covered Total %
statement 73 284 25.7
branch 14 100 14.0
condition 4 6 66.6
subroutine 16 40 40.0
pod 30 30 100.0
total 137 460 29.7


line stmt bran cond sub pod time code
1             package Crypt::X509::CRL;
2            
3 3     3   143920 use 5.006;
  3         20  
4 3     3   17 use Carp;
  3         8  
  3         192  
5 3     3   33 use strict;
  3         6  
  3         87  
6 3     3   16 use warnings;
  3         5  
  3         107  
7 3     3   1656 use Convert::ASN1 qw(:io :debug);
  3         113399  
  3         10683  
8            
9             require Exporter;
10            
11             our @ISA = qw(Exporter);
12             our %EXPORT_TAGS = ( 'all' => [qw()] );
13             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
14             our @EXPORT = qw( error new this_update next_update );
15             our $VERSION = '0.4';
16            
17             my $parser = undef;
18             my $asn = undef;
19             my $error = undef;
20            
21             my %oid2enchash= (
22             '1.2.840.113549.1.1.1' => {'enc' => 'RSA'},
23             '1.2.840.113549.1.1.2' => {'enc' => 'RSA', 'hash' => 'MD2'},
24             '1.2.840.113549.1.1.3' => {'enc' => 'RSA', 'hash' => 'MD4'},
25             '1.2.840.113549.1.1.4' => {'enc' => 'RSA', 'hash' => 'MD5'},
26             '1.2.840.113549.1.1.5' => {'enc' => 'RSA', 'hash' => 'SHA1'},
27             '1.2.840.113549.1.1.6' => {'enc' => 'OAEP'}
28             );
29            
30             my %oid2attr = (
31             "2.5.4.3" => "CN",
32             "2.5.4.6" => "C",
33             "2.5.4.7" => "l",
34             "2.5.4.8" => "S",
35             "2.5.4.10" => "O",
36             "2.5.4.11" => "OU",
37             "1.2.840.113549.1.9.1" => "E",
38             "0.9.2342.19200300.100.1.1" => "UID",
39             "0.9.2342.19200300.100.1.25" => "DC"
40             );
41            
42            
43            
44            
45             sub new {
46 3     3 1 2573 my ( $class , %args ) = @_;
47            
48 3 100 66     22 if ( !defined ( $parser ) || $parser->error ) {
49 2         7 $parser = _init();
50             }
51            
52 3         27 my $self = $parser->decode( $args{'crl'} );
53            
54 3         151010 $self->{'_error'} = $parser->error;
55 3         31 bless ( $self , $class );
56            
57 3         18 return $self;
58             }
59            
60            
61             sub error {
62 3     3 1 863 my $self = shift;
63 3         37 return $self->{'_error'};
64             }
65            
66            
67             sub version {
68 0     0 1 0 my $self = shift;
69            
70 0 0       0 return undef if not exists $self->{'tbsCertList'}{'version'};
71            
72 0         0 return $self->{'tbsCertList'}{'version'};
73             }
74            
75            
76             sub version_string {
77 0     0 1 0 my $self = shift;
78            
79 0 0       0 return undef if not exists $self->{'tbsCertList'}{'version'};
80            
81 0         0 my $v = $self->{'tbsCertList'}{'version'};
82 0 0       0 return "v1" if $v == 0;
83 0 0       0 return "v2" if $v == 1;
84 0 0       0 return "v3" if $v == 2;
85             }
86            
87            
88             sub this_update {
89 1     1 1 4 my $self = shift;
90 1 50       6 if ( exists $self->{'tbsCertList'}{'thisUpdate'}{'utcTime'} ) {
    0          
91 1         6 return $self->{'tbsCertList'}{'thisUpdate'}{'utcTime'};
92             } elsif ( exists $self->{'tbsCertList'}{'thisUpdate'}{'generalTime'} ) {
93 0         0 return $self->{'tbsCertList'}{'thisUpdate'}{'generalTime'};
94             } else {
95 0         0 return undef;
96             }
97             }
98            
99            
100             sub next_update {
101 1     1 1 4 my $self = shift;
102 1 50       5 if ( exists $self->{'tbsCertList'}{'nextUpdate'}{'utcTime'} ) {
    0          
103 1         6 return $self->{'tbsCertList'}{'nextUpdate'}{'utcTime'};
104             } elsif ( $self->{'tbsCertList'}{'nextUpdate'}{'generalTime'} ) {
105 0         0 return $self->{'tbsCertList'}{'nextUpdate'}{'generalTime'};
106             } else {
107 0         0 return undef;
108             }
109             }
110            
111            
112             sub signature {
113 0     0 1 0 my $self = shift;
114 0         0 return $self->{'signatureValue'}[0];
115             }
116            
117            
118             sub signature_length {
119 1     1 1 3 my $self = shift;
120 1         6 return $self->{'signatureValue'}[1];
121             }
122            
123            
124             sub signature_algorithm {
125 1     1 1 3 my $self = shift;
126 1         7 return $self->{'tbsCertList'}{'signature'}{'algorithm'};
127             }
128            
129            
130             sub SigEncAlg {
131 1     1 1 3 my $self = shift;
132 1         8 return $oid2enchash{ $self->{'tbsCertList'}{'signature'}->{'algorithm'} }->{'enc'};
133             }
134            
135             sub SigHashAlg {
136 1     1 1 3 my $self = shift;
137 1         7 return $oid2enchash{ $self->{'tbsCertList'}{'signature'}->{'algorithm'} }->{'hash'};
138             }
139            
140            
141             #########################################################################
142             # accessors - issuer
143             #########################################################################
144            
145             sub Issuer {
146 1     1 1 3 my $self = shift;
147 1         3 my ( $i , $type );
148 1         4 my $issuerdn = $self->{'tbsCertList'}->{'issuer'}->{'rdnSequence'};
149            
150 1         3 $self->{'tbsCertList'}->{'issuer'}->{'dn'} = [];
151            
152 1         3 my $issuedn = $self->{'tbsCertList'}->{'issuer'}->{'dn'};
153            
154 1         2 for my $issue ( @{ $issuerdn } ) {
  1         3  
155 5         7 $i = @{ $issue }[0];
  5         11  
156 5 50       15 if ( $oid2attr{ $i->{'type'} } ) {
157 5         10 $type = $oid2attr{ $i->{'type'} };
158             } else {
159 0         0 $type = $i->{'type'};
160             }
161 5         7 my @key = keys ( %{ $i->{'value'} } );
  5         15  
162 5         8 push @{ $issuedn } , $type . "=" . $i->{'value'}->{ $key[0] };
  5         15  
163             }
164 1         8 return $issuedn;
165             }
166            
167             sub _issuer_part {
168 0     0   0 my $self = shift;
169 0         0 my $oid = shift;
170 0         0 my $issuerrdn = $self->{'tbsCertList'}->{'issuer'}->{'rdnSequence'};
171 0         0 for my $issue ( @{ $issuerrdn } ) {
  0         0  
172 0         0 my $i = @{ $issue }[0];
  0         0  
173 0 0       0 if ( $i->{'type'} eq $oid ) {
174 0         0 my @key = keys ( %{ $i->{'value'} } );
  0         0  
175 0         0 return $i->{'value'}->{ $key[0] };
176             }
177             }
178 0         0 return undef;
179             }
180            
181            
182             sub issuer_cn {
183 0     0 1 0 my $self = shift;
184 0         0 return _issuer_part( $self , '2.5.4.3' );
185             }
186            
187            
188            
189             sub issuer_country {
190 0     0 1 0 my $self = shift;
191 0         0 return _issuer_part( $self , '2.5.4.6' );
192             }
193            
194            
195             sub issuer_state {
196 0     0 1 0 my $self = shift;
197 0         0 return _issuer_part( $self , '2.5.4.8' );
198             }
199            
200            
201             sub issuer_locality {
202 0     0 1 0 my $self = shift;
203 0         0 return _issuer_part( $self , '2.5.4.7' );
204             }
205            
206            
207             sub issuer_org {
208 0     0 1 0 my $self = shift;
209 0         0 return _issuer_part( $self , '2.5.4.10' );
210             }
211            
212            
213             sub issuer_email {
214 0     0 1 0 my $self = shift;
215 0         0 return _issuer_part( $self , '1.2.840.113549.1.9.1' );
216             }
217            
218            
219             #########################################################################
220             #
221             # ------- EXTENSIONS -------
222             #
223             # valid RFC 3280 extensions:
224             # Authority Key Identifier (implemented)
225             # CRL Number (implemented)
226             # Issuing Distribution Point (implemented)
227             # Issuer Alternative Name
228             # Delta CRL Indicator
229             # Freshest CRL (a.k.a. Delta CRL Distribution Point)
230             #
231             #########################################################################
232            
233            
234             sub key_identifier {
235 0     0 1 0 my $self = shift;
236 0 0       0 if ( defined $self->_AuthorityKeyIdentifier ) { return ( $self->_AuthorityKeyIdentifier )->{keyIdentifier}; }
  0         0  
237 0         0 return undef;
238             }
239            
240             # _AuthorityKeyIdentifier
241             sub _AuthorityKeyIdentifier {
242 0     0   0 my $self = shift;
243 0         0 my $extensions = $self->{'tbsCertList'}->{'crlExtensions'};
244            
245 0 0       0 if ( not defined $extensions ) { return undef; } # no extensions in certificate
  0         0  
246            
247 0 0       0 if ( defined $self->{'tbsCertList'}{'AuthorityKeyIdentifier'} ) {
248 0         0 return ( $self->{'tbsCertList'}{'AuthorityKeyIdentifier'} );
249             }
250            
251 0         0 for my $extension ( @{ $extensions } ) {
  0         0  
252 0 0       0 if ( $extension->{'extnID'} eq '2.5.29.35' ) { # OID for AuthorityKeyIdentifier
253 0         0 my $parser = _init('AuthorityKeyIdentifier');
254 0         0 $self->{'tbsCertList'}{'AuthorityKeyIdentifier'} = $parser->decode( $extension->{'extnValue'} );
255 0 0       0 if ( $parser->error ) {
256 0         0 $self->{"_error"} = $parser->error;
257 0         0 return undef;
258             }
259 0         0 return $self->{'tbsCertList'}{'AuthorityKeyIdentifier'};
260             }
261             }
262 0         0 return undef;
263             }
264            
265            
266             sub authorityCertIssuer {
267 0     0 1 0 my $self = shift;
268 0         0 my ( $i , $type );
269 0         0 my $rdn = _AuthorityKeyIdentifier( $self );
270 0 0       0 if ( not defined ( $rdn ) ) {
271 0         0 return (undef); # we do not have that extension
272             } else {
273 0         0 $rdn = $rdn->{'authorityCertIssuer'}[0]->{'directoryName'};
274             }
275 0         0 $rdn->{'dn'} = [];
276 0         0 my $dn = $rdn->{'dn'};
277 0         0 $rdn = $rdn->{'rdnSequence'};
278 0         0 for my $r ( @{ $rdn } ) {
  0         0  
279 0         0 $i = @{ $r }[0];
  0         0  
280 0 0       0 if ( $oid2attr{ $i->{'type'} } ) {
281 0         0 $type = $oid2attr{ $i->{'type'} };
282             } else {
283 0         0 $type = $i->{'type'};
284             }
285 0         0 my @key = keys ( %{ $i->{'value'} } );
  0         0  
286 0         0 push @{ $dn } , $type . "=" . $i->{'value'}->{ $key[0] };
  0         0  
287             }
288 0         0 return $dn;
289             }
290            
291             sub _authcert_part {
292 0     0   0 my $self = shift;
293 0         0 my $oid = shift;
294 0         0 my $rdn = _AuthorityKeyIdentifier( $self );
295 0 0       0 if ( not defined ( $rdn ) ) {
296 0         0 return (undef); # we do not have that extension
297             } else {
298 0         0 $rdn = $rdn->{'authorityCertIssuer'}[0]->{'directoryName'}->{'rdnSequence'};
299             }
300 0         0 for my $r ( @{ $rdn } ) {
  0         0  
301 0         0 my $i = @{ $r }[0];
  0         0  
302 0 0       0 if ( $i->{'type'} eq $oid ) {
303 0         0 my @key = keys ( %{ $i->{'value'} } );
  0         0  
304 0         0 return $i->{'value'}->{ $key[0] };
305             }
306             }
307 0         0 return undef;
308             }
309            
310            
311             sub authority_serial {
312 0     0 1 0 my $self = shift;
313 0         0 return ( $self->_AuthorityKeyIdentifier )->{authorityCertSerialNumber};
314             }
315            
316            
317             sub authority_cn {
318 0     0 1 0 my $self = shift;
319 0         0 return _authcert_part( $self , '2.5.4.3' );
320             }
321            
322            
323             sub authority_country {
324 0     0 1 0 my $self = shift;
325 0         0 return _authcert_part( $self , '2.5.4.6' );
326             }
327            
328            
329             sub authority_state {
330 0     0 1 0 my $self = shift;
331 0         0 return _authcert_part( $self , '2.5.4.8' );
332            
333             }
334            
335            
336             sub authority_locality {
337 0     0 1 0 my $self = shift;
338 0         0 return _authcert_part( $self , '2.5.4.7' );
339             }
340            
341            
342             sub authority_org {
343 0     0 1 0 my $self = shift;
344 0         0 return _authcert_part( $self , '2.5.4.10' );
345             }
346            
347            
348             sub authority_email {
349 0     0 1 0 my $self = shift;
350 0         0 return _authcert_part( $self , '1.2.840.113549.1.9.1' );
351             }
352            
353            
354             # crl_number (another extension)
355             sub crl_number {
356 1     1 1 3 my $self = shift;
357 1         3 my $extension;
358 1         3 my $extensions = $self->{'tbsCertList'}->{'crlExtensions'};
359            
360 1 50       5 if ( defined $self->{'tbsCertList'}{'cRLNumber'} ) {
361 0         0 return ( $self->{'tbsCertList'}{'cRLNumber'} );
362             }
363            
364 1 50       7 if ( not defined $extensions ) { return undef; } # no extensions in certificate
  0         0  
365            
366 1         2 for $extension ( @{ $extensions } ) {
  1         4  
367 2 100       8 if ( $extension->{'extnID'} eq '2.5.29.20' ) { # OID for CRLNumber
368 1         5 my $parser = _init('cRLNumber'); # get a parser for this
369 1         5 $self->{'tbsCertList'}{'cRLNumber'} = $parser->decode( $extension->{'extnValue'} ); # decode the value
370 1 50       95 if ( $parser->error ) {
371 0         0 $self->{"_error"} = $parser->error;
372 0         0 return undef;
373             }
374 1         13 return $self->{'tbsCertList'}{'cRLNumber'};
375             }
376             }
377 0         0 return undef;
378             }
379            
380            
381             # IDPs
382             sub IDPs {
383 0     0 1 0 my $self = shift;
384 0         0 my $extension;
385 0         0 my $extensions = $self->{'tbsCertList'}->{'crlExtensions'};
386            
387 0 0       0 if ( defined $self->{'tbsCertList'}{'idp'} ) {
388 0         0 return ( $self->{'tbsCertList'}{'idp'} );
389             }
390            
391 0 0       0 if ( not defined $extensions ) { return undef; } # no extensions in certificate
  0         0  
392            
393 0         0 for $extension ( @{ $extensions } ) {
  0         0  
394 0 0       0 if ( $extension->{'extnID'} eq '2.5.29.28' ) { # OID for issuingDistributionPoint
395 0         0 my $parser = _init('issuingDistributionPoint'); # get a parser for this
396 0         0 my $idps = $parser->decode( $extension->{'extnValue'} ); # decode the value
397 0 0       0 if ( $parser->error ) {
398 0         0 $self->{"_error"} = $parser->error;
399 0         0 return undef;
400             }
401            
402             # set the critical flag
403 0 0       0 if ( exists $extension->{'critical'} ) {
404 0         0 $self->{'tbsCertList'}{'idp'}{'critical'} = $extension->{'critical'};
405             } else {
406 0         0 $self->{'tbsCertList'}{'idp'}{'critical'} = 0;
407             }
408            
409             # set the onlyContainsUserCerts flag
410 0 0       0 if ( exists $idps->{'onlyContainsUserCerts'} ) {
411 0         0 $self->{'tbsCertList'}{'idp'}{'onlyUserCerts'} = $idps->{'onlyContainsUserCerts'};
412             } else {
413 0         0 $self->{'tbsCertList'}{'idp'}{'onlyUserCerts'} = 0;
414             }
415            
416             # set the onlyContainsCACerts flag
417 0 0       0 if ( exists $idps->{'onlyContainsCACerts'} ) {
418 0         0 $self->{'tbsCertList'}{'idp'}{'onlyCaCerts'} = $idps->{'onlyContainsCACerts'};
419             } else {
420 0         0 $self->{'tbsCertList'}{'idp'}{'onlyCaCerts'} = 0;
421             }
422            
423             # set the onlyContainsAttributeCerts flag
424 0 0       0 if ( exists $idps->{'onlyContainsAttributeCerts'} ) {
425 0         0 $self->{'tbsCertList'}{'idp'}{'onlyAttribCerts'} = $idps->{'onlyContainsAttributeCerts'}
426             } else {
427 0         0 $self->{'tbsCertList'}{'idp'}{'onlyAttribCerts'} = 0;
428             }
429            
430             # set the indirectCRL flag
431 0 0       0 if ( exists $idps->{'indirectCRL'} ) {
432 0         0 $self->{'tbsCertList'}{'idp'}{'indirectCRL'} = $idps->{'indirectCRL'}
433             } else {
434 0         0 $self->{'tbsCertList'}{'idp'}{'indirectCRL'} = 0
435             }
436            
437             # set the defaults for directory_addr and url
438 0         0 $self->{'tbsCertList'}{'idp'}{'directory_addr'} = undef;
439 0         0 $self->{'tbsCertList'}{'idp'}{'url'} = undef;
440            
441             # set the directory_addr and/or URL values
442 0         0 for my $each_fullName ( @{ $idps->{'distributionPoint'}->{'fullName'} } ) { # this loops through multiple "fullName" values
  0         0  
443 0 0       0 if ( exists $each_fullName->{directoryName} ) {
    0          
444             # found a rdnSequence
445             $self->{'tbsCertList'}{'idp'}{'directory_addr'} =
446 0         0 join( ', ' , reverse @{ _IDP_rdn( $each_fullName->{directoryName}->{rdnSequence} ) } );
  0         0  
447             } elsif ( exists $each_fullName->{uniformResourceIdentifier} ) {
448             # found a URI
449 0         0 $self->{'tbsCertList'}{'idp'}{'url'} = $each_fullName->{uniformResourceIdentifier};
450             } else {
451             # found some other type of IDP value
452             # return undef;
453             }
454             }
455            
456             # set the reason flags BIT STRING
457 0 0       0 if ( exists $idps->{'onlySomeReasons'} ) {
458 0         0 $self->{'tbsCertList'}{'idp'}{'reasonFlags'} = $idps->{'onlySomeReasons'};
459             } else {
460 0         0 $self->{'tbsCertList'}{'idp'}{'reasonFlags'} = undef;
461             }
462            
463 0         0 return $self->{'tbsCertList'}{'idp'};
464             }
465             }
466 0         0 return undef;
467             }
468            
469             # internal function for parsing the rdn sequence parts
470             sub _IDP_rdn {
471 0     0   0 my $crl_rdn = shift; # this should be the passed in 'rdnSequence' array
472 0         0 my ( $i ,$type );
473 0         0 my $crl_dn = [];
474 0         0 for my $part ( @{$crl_rdn} ) {
  0         0  
475 0         0 $i = @{$part}[0];
  0         0  
476 0 0       0 if ( $oid2attr{ $i->{'type'} } ) {
477 0         0 $type = $oid2attr{ $i->{'type'} };
478             } else {
479 0         0 $type = $i->{'type'};
480             }
481 0         0 my @key = keys ( %{ $i->{'value'} } );
  0         0  
482 0         0 push @{ $crl_dn } , $type . "=" . $i->{'value'}->{ $key[0] };
  0         0  
483             }
484 0         0 return $crl_dn;
485             }
486            
487             #########################################################################
488             #
489             # ------- CRL ENTRY EXTENSIONS -------
490             #
491             # valid RFC 3280 CRL Entry Extensions:
492             # Reason Code
493             # Hold Instruction Code
494             # Invalidity Date
495             # Certificate Issuer
496             #
497             #########################################################################
498            
499            
500             # revocation_list
501             sub revocation_list {
502 0     0 1 0 my $self = shift;
503 0         0 my @crl_reason = qw(unspecified keyCompromise cACompromise affiliationChanged superseded
504             cessationOfOperation certificateHold removeFromCRL privilegeWithdrawn
505             aACompromise);
506 0         0 my %hold_codes = (
507             '1.2.840.10040.2.1' => 'holdinstruction-none',
508             '1.2.840.10040.2.2' => 'holdinstruction-callissuer',
509             '1.2.840.10040.2.3' => 'holdinstruction-reject',
510             );
511            
512 0 0       0 if ( defined $self->{'tbsCertList'}{'rl'} ) {
513 0         0 return ( $self->{'tbsCertList'}{'rl'} );
514             }
515            
516 0         0 my $rls = $self->{'tbsCertList'}->{'revokedCertificates'};
517 0 0       0 if ( not defined $rls ) { # no revoked certs in this CRL
518 0         0 $self->{'tbsCertList'}{'rl'} = undef;
519 0         0 return $self->{'tbsCertList'}{'rl'};
520             }
521            
522 0         0 for my $rl ( @{ $rls } ) {
  0         0  
523             # the below assignment of 'utcTime' is based on the RFC of dates through the
524             # year 2049, after which the RFC calls for dates to be listed as
525             # 'GeneralizedTime' or in the ASN1 below for Time as 'generalTime'.
526 0 0       0 if ( exists $rl->{'revocationDate'}{'utcTime'} ) {
    0          
527             $self->{'tbsCertList'}{'rl'}{ $rl->{'userCertificate'} }{'revocationDate'} =
528 0         0 $rl->{'revocationDate'}{'utcTime'};
529             } elsif ( exists $rl->{'revocationDate'}{'generalTime'} ) {
530             $self->{'tbsCertList'}{'rl'}{ $rl->{'userCertificate'} }{'revocationDate'} =
531 0         0 $rl->{'revocationDate'}{'generalTime'};
532             } else {
533 0         0 $self->{'tbsCertList'}{'rl'}{ $rl->{'userCertificate'} }{'revocationDate'} = undef;
534             }
535            
536 0         0 for my $extension ( @{ $rl->{'crlEntryExtensions'} } ) {
  0         0  
537 0 0       0 if ( $extension->{'extnID'} eq '2.5.29.21' ) { # OID for crlReason
    0          
    0          
538 0         0 my $parser = _init('CRLReason'); # get a parser for this
539 0         0 my $reason = $parser->decode( $extension->{'extnValue'} ); # decode the value
540 0 0       0 if ( $parser->error ) {
541 0         0 $self->{"_error"} = $parser->error;
542 0         0 return undef;
543             }
544 0         0 $self->{'tbsCertList'}{'rl'}{ $rl->{'userCertificate'} }{'crlReason'} =
545             $crl_reason[ $reason ];
546            
547             } elsif ( $extension->{'extnID'} eq '2.5.29.24' ) { # OID for invalidityDate
548 0         0 my $parser = _init('invalidityDate');
549 0         0 my $invalid_date = $parser->decode( $extension->{'extnValue'} );
550 0 0       0 if ( $parser->error ) {
551 0         0 $self->{"_error"} = $parser->error;
552 0         0 return undef;
553             }
554 0         0 $self->{'tbsCertList'}{'rl'}{ $rl->{'userCertificate'} }{'invalidityDate'} =
555             $invalid_date;
556            
557             } elsif ( $extension->{'extnID'} eq '2.5.29.23' ) { # OID for holdInstructionCode
558 0         0 my $parser = _init('holdInstructionCode');
559 0         0 my $hold_code = $parser->decode( $extension->{'extnValue'} );
560 0 0       0 if ( $parser->error ) {
561 0         0 $self->{"_error"} = $parser->error;
562 0         0 return undef;
563             }
564             $self->{'tbsCertList'}{'rl'}{ $rl->{'userCertificate'} }{'holdInstructionCode'} =
565 0         0 $hold_codes{ $hold_code };
566            
567             } else {
568             # unimplemented OID(s) found
569             $self->{'tbsCertList'}{'rl'}{ $rl->{'userCertificate'} }{ $extension->{'extnID'} } =
570 0         0 $extension->{'extnValue'};
571             }
572             }
573             }
574 0         0 return $self->{'tbsCertList'}{'rl'};
575             }
576            
577            
578             #######################################################################
579             # internal function
580             #######################################################################
581            
582             # _init is the initialzation function and is also used for subsequent
583             # decoding of the inner parts of the object.
584             sub _init {
585 3     3   7 my $what = shift;
586 3 100 66     17 if ( ( not defined $what ) or ( '' eq $what ) ) { $what = 'CertificateList' }
  2         6  
587 3 100       10 if ( not defined $asn) {
588 2         25 $asn = Convert::ASN1->new;
589 2         97 $asn->prepare(<
590             -- ASN.1 from RFC 3280 and X509 (April 2002)
591             -- Adapted for use with Convert::ASN1
592            
593            
594             -- attribute data types --
595            
596             Attribute ::= SEQUENCE {
597             type AttributeType,
598             values SET OF AttributeValue
599             -- at least one value is required --
600             }
601            
602             AttributeType ::= OBJECT IDENTIFIER
603            
604             AttributeValue ::= DirectoryString --ANY
605            
606             AttributeTypeAndValue ::= SEQUENCE {
607             type AttributeType,
608             value AttributeValue
609             }
610            
611            
612             -- naming data types --
613            
614             Name ::= CHOICE { -- only one possibility for now
615             rdnSequence RDNSequence
616             }
617            
618             RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
619            
620             RelativeDistinguishedName ::=
621             SET OF AttributeTypeAndValue --SET SIZE (1 .. MAX) OF
622            
623            
624             -- Directory string type --
625            
626             DirectoryString ::= CHOICE {
627             teletexString TeletexString, --(SIZE (1..MAX)),
628             printableString PrintableString, --(SIZE (1..MAX)),
629             bmpString BMPString, --(SIZE (1..MAX)),
630             universalString UniversalString, --(SIZE (1..MAX)),
631             utf8String UTF8String, --(SIZE (1..MAX)),
632             ia5String IA5String, --added for EmailAddress,
633             integer INTEGER
634             }
635            
636            
637             -- CRL specific structures begin here
638            
639             CertificateList ::= SEQUENCE {
640             tbsCertList TBSCertList,
641             signatureAlgorithm AlgorithmIdentifier,
642             signatureValue BIT STRING
643             }
644            
645            
646             TBSCertList ::= SEQUENCE {
647             version Version OPTIONAL, -- if present, MUST be v2
648             signature AlgorithmIdentifier,
649             issuer Name,
650             thisUpdate Time,
651             nextUpdate Time OPTIONAL,
652            
653             revokedCertificates RevokedCertificates OPTIONAL,
654             crlExtensions [0] EXPLICIT Extensions OPTIONAL
655             }
656            
657             RevokedCertificates ::= SEQUENCE OF RevokedCerts
658            
659             RevokedCerts ::= SEQUENCE {
660             userCertificate CertificateSerialNumber,
661             revocationDate Time,
662             crlEntryExtensions Extensions OPTIONAL
663             }
664            
665             -- Version, Time, CertificateSerialNumber, and Extensions
666             -- are all defined in the ASN.1 in section 4.1
667            
668             -- AlgorithmIdentifier is defined in section 4.1.1.2
669            
670             Version ::= INTEGER --{ v1(0), v2(1), v3(2) }
671            
672             CertificateSerialNumber ::= INTEGER
673            
674             AlgorithmIdentifier ::= SEQUENCE {
675             algorithm OBJECT IDENTIFIER,
676             parameters ANY
677             }
678            
679            
680             Name ::= CHOICE { -- only one possibility for now
681             rdnSequence RDNSequence
682             }
683            
684            
685             Time ::= CHOICE {
686             utcTime UTCTime,
687             generalTime GeneralizedTime
688             }
689            
690             --extensions
691            
692             Extensions ::= SEQUENCE OF Extension --SIZE (1..MAX) OF Extension
693            
694             Extension ::= SEQUENCE {
695             extnID OBJECT IDENTIFIER,
696             critical BOOLEAN OPTIONAL, --DEFAULT FALSE,
697             extnValue OCTET STRING
698             }
699            
700             AuthorityKeyIdentifier ::= SEQUENCE {
701             keyIdentifier [0] KeyIdentifier OPTIONAL,
702             authorityCertIssuer [1] GeneralNames OPTIONAL,
703             authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
704             -- authorityCertIssuer and authorityCertSerialNumber shall both
705             -- be present or both be absent
706            
707             KeyIdentifier ::= OCTET STRING
708            
709             GeneralNames ::= SEQUENCE OF GeneralName
710            
711             GeneralName ::= CHOICE {
712             otherName [0] AnotherName,
713             rfc822Name [1] IA5String,
714             dNSName [2] IA5String,
715             x400Address [3] ANY, --ORAddress,
716             directoryName [4] Name,
717             ediPartyName [5] EDIPartyName,
718             uniformResourceIdentifier [6] IA5String,
719             iPAddress [7] OCTET STRING,
720             registeredID [8] OBJECT IDENTIFIER }
721            
722             -- AnotherName replaces OTHER-NAME ::= TYPE-IDENTIFIER, as
723             -- TYPE-IDENTIFIER is not supported in the 88 ASN.1 syntax
724            
725             AnotherName ::= SEQUENCE {
726             type OBJECT IDENTIFIER,
727             value [0] EXPLICIT ANY } --DEFINED BY type-id }
728            
729             EDIPartyName ::= SEQUENCE {
730             nameAssigner [0] DirectoryString OPTIONAL,
731             partyName [1] DirectoryString }
732            
733             -- id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 }
734            
735             issuingDistributionPoint ::= SEQUENCE {
736             distributionPoint [0] DistributionPointName OPTIONAL,
737             onlyContainsUserCerts [1] BOOLEAN OPTIONAL, --DEFAULT FALSE,
738             onlyContainsCACerts [2] BOOLEAN OPTIONAL, --DEFAULT FALSE,
739             onlySomeReasons [3] ReasonFlags OPTIONAL,
740             indirectCRL [4] BOOLEAN OPTIONAL, --DEFAULT FALSE,
741             onlyContainsAttributeCerts [5] BOOLEAN OPTIONAL --DEFAULT FALSE
742             }
743            
744             DistributionPointName ::= CHOICE {
745             fullName [0] GeneralNames,
746             nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
747            
748             ReasonFlags ::= BIT STRING --{
749             -- unused (0),
750             -- keyCompromise (1),
751             -- cACompromise (2),
752             -- affiliationChanged (3),
753             -- superseded (4),
754             -- cessationOfOperation (5),
755             -- certificateHold (6),
756             -- privilegeWithdrawn (7),
757             -- aACompromise (8) }
758            
759             -- id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 }
760            
761             cRLNumber ::= INTEGER --(0..MAX)
762            
763             -- id-ce-cRLReason OBJECT IDENTIFIER ::= { id-ce 21 }
764            
765             -- reasonCode ::= { CRLReason }
766            
767             CRLReason ::= ENUMERATED {
768             unspecified (0),
769             keyCompromise (1),
770             cACompromise (2),
771             affiliationChanged (3),
772             superseded (4),
773             cessationOfOperation (5),
774             certificateHold (6),
775             removeFromCRL (8),
776             privilegeWithdrawn (9),
777             aACompromise (10) }
778            
779             -- id-ce-holdInstructionCode OBJECT IDENTIFIER ::= { id-ce 23 }
780            
781             holdInstructionCode ::= OBJECT IDENTIFIER
782            
783             -- holdInstruction OBJECT IDENTIFIER ::=
784             -- { iso(1) member-body(2) us(840) x9-57(10040) 2 }
785             --
786             -- id-holdinstruction-none OBJECT IDENTIFIER ::= {holdInstruction 1}
787             -- id-holdinstruction-callissuer
788             -- OBJECT IDENTIFIER ::= {holdInstruction 2}
789             -- id-holdinstruction-reject OBJECT IDENTIFIER ::= {holdInstruction 3}
790            
791             -- id-ce-invalidityDate OBJECT IDENTIFIER ::= { id-ce 24 }
792            
793             invalidityDate ::= GeneralizedTime
794            
795             -- id-ce-certificateIssuer OBJECT IDENTIFIER ::= { id-ce 29 }
796            
797             certificateIssuer ::= GeneralNames
798            
799             ASN1
800             }
801 3         73411 my $self = $asn->find( $what );
802 3         68 return $self;
803             }
804            
805            
806            
807             1;
808            
809             __DATA__