@@ -175,6 +175,8 @@ pub struct OwnedCertRevocationList {
175175 signed_data : OwnedSignedData ,
176176
177177 next_update : UnixTime ,
178+
179+ crl_number : Vec < u8 > ,
178180}
179181
180182#[ cfg( feature = "alloc" ) ]
@@ -225,6 +227,8 @@ pub struct BorrowedCertRevocationList<'a> {
225227 revoked_certs : untrusted:: Input < ' a > ,
226228
227229 next_update : UnixTime ,
230+
231+ crl_number : untrusted:: Input < ' a > ,
228232}
229233
230234impl < ' a > BorrowedCertRevocationList < ' a > {
@@ -263,6 +267,7 @@ impl<'a> BorrowedCertRevocationList<'a> {
263267 . map ( |idp| idp. as_slice_less_safe ( ) . to_vec ( ) ) ,
264268 revoked_certs,
265269 next_update : self . next_update ,
270+ crl_number : self . crl_number . as_slice_less_safe ( ) . to_vec ( ) ,
266271 } )
267272 }
268273
@@ -273,22 +278,26 @@ impl<'a> BorrowedCertRevocationList<'a> {
273278 match id {
274279 // id-ce-cRLNumber 2.5.29.20 - RFC 5280 §5.2.3
275280 Standard ( 20 ) => {
281+ // Duplicate cRLNumber extensions are invalid.
282+ if !self . crl_number . as_slice_less_safe ( ) . is_empty ( ) {
283+ return Err ( Error :: ExtensionValueInvalid ) ;
284+ }
285+
276286 // RFC 5280 §5.2.3:
277287 // CRL verifiers MUST be able to handle CRLNumber values
278288 // up to 20 octets. Conforming CRL issuers MUST NOT use CRLNumber
279289 // values longer than 20 octets.
280290 //
281- extension. value . read_all ( Error :: InvalidCrlNumber , |der| {
282- let crl_number = der:: nonnegative_integer ( der)
283- . map_err ( |_| Error :: InvalidCrlNumber ) ?
284- . as_slice_less_safe ( ) ;
285- if crl_number. len ( ) <= 20 {
291+ self . crl_number = extension. value . read_all ( Error :: InvalidCrlNumber , |der| {
292+ let crl_number =
293+ der:: nonnegative_integer ( der) . map_err ( |_| Error :: InvalidCrlNumber ) ?;
294+ if crl_number. as_slice_less_safe ( ) . len ( ) <= 20 {
286295 Ok ( crl_number)
287296 } else {
288297 Err ( Error :: InvalidCrlNumber )
289298 }
290299 } ) ?;
291- // We enforce the cRLNumber is sensible, but don't retain the value for use.
300+
292301 Ok ( ( ) )
293302 }
294303
@@ -408,6 +417,7 @@ impl<'a> FromDer<'a> for BorrowedCertRevocationList<'a> {
408417 revoked_certs,
409418 issuing_distribution_point : None ,
410419 next_update,
420+ crl_number : untrusted:: Input :: from ( & [ ] ) ,
411421 } ;
412422
413423 // RFC 5280 §5.1.2.7:
@@ -441,6 +451,13 @@ impl<'a> FromDer<'a> for BorrowedCertRevocationList<'a> {
441451 } ,
442452 ) ?;
443453
454+ // From RFC 5280, Section 5.2.3:
455+ // CRL issuers conforming to this profile MUST include this extension in all
456+ // CRLs and MUST mark this extension as non-critical.
457+ if crl. crl_number . as_slice_less_safe ( ) . is_empty ( ) {
458+ return Err ( Error :: MissingCrlNumber ) ;
459+ }
460+
444461 Ok ( crl)
445462 } ) ?;
446463
@@ -473,6 +490,7 @@ impl core::hash::Hash for BorrowedCertRevocationList<'_> {
473490 issuing_distribution_point,
474491 revoked_certs,
475492 next_update,
493+ crl_number,
476494 } = self ;
477495 signed_data. hash ( state) ;
478496 issuer. as_slice_less_safe ( ) . hash ( state) ;
@@ -481,6 +499,7 @@ impl core::hash::Hash for BorrowedCertRevocationList<'_> {
481499 . hash ( state) ;
482500 revoked_certs. as_slice_less_safe ( ) . hash ( state) ;
483501 next_update. hash ( state) ;
502+ crl_number. as_slice_less_safe ( ) . hash ( state) ;
484503 }
485504}
486505
@@ -1313,21 +1332,67 @@ mod tests {
13131332 assert ! ( OwnedCertRevocationList :: from_der( crl) . is_ok( ) )
13141333 }
13151334
1335+ #[ test]
1336+ fn test_crl_missing_crl_number ( ) {
1337+ assert_eq ! (
1338+ BorrowedCertRevocationList :: from_der( CRL_MISSING_CRL_NUMBER ) . err( ) ,
1339+ Some ( Error :: MissingCrlNumber )
1340+ ) ;
1341+ }
1342+
1343+ #[ test]
1344+ fn test_crl_duplicate_crl_number ( ) {
1345+ assert_eq ! (
1346+ BorrowedCertRevocationList :: from_der( CRL_DUPLICATE_CRL_NUMBER ) . err( ) ,
1347+ Some ( Error :: ExtensionValueInvalid )
1348+ ) ;
1349+ }
1350+
13161351 #[ test]
13171352 fn test_crl_issuing_distribution_point_illegal_bit_string ( ) {
1318- let crl = & [
1319- 0x30 , 0x65 , 0x30 , 0x50 , 0x02 , 0x01 , 0x01 , 0x30 , 0x0d , 0x06 , 0x09 , 0x2a , 0x86 , 0x48 ,
1320- 0x86 , 0xf7 , 0x0d , 0x01 , 0x01 , 0x0b , 0x05 , 0x00 , 0x30 , 0x0c , 0x31 , 0x0a , 0x30 , 0x08 ,
1321- 0x06 , 0x03 , 0x55 , 0x04 , 0x03 , 0x13 , 0x01 , 0x41 , 0x17 , 0x0d , 0x32 , 0x30 , 0x30 , 0x31 ,
1322- 0x30 , 0x31 , 0x30 , 0x30 , 0x30 , 0x30 , 0x30 , 0x30 , 0x5a , 0x17 , 0x0d , 0x32 , 0x31 , 0x30 ,
1323- 0x31 , 0x30 , 0x31 , 0x30 , 0x30 , 0x30 , 0x30 , 0x30 , 0x30 , 0x5a , 0xa0 , 0x10 , 0x30 , 0x0e ,
1324- 0x30 , 0x0c , 0x06 , 0x03 , 0x55 , 0x1d , 0x1c , 0x04 , 0x05 , 0x30 , 0x03 , 0x83 , 0x01 , 0x00 ,
1325- 0x30 , 0x0d , 0x06 , 0x09 , 0x2a , 0x86 , 0x48 , 0x86 , 0xf7 , 0x0d , 0x01 , 0x01 , 0x0b , 0x05 ,
1326- 0x00 , 0x03 , 0x02 , 0x00 , 0x00 ,
1327- ] ;
13281353 assert_eq ! (
1329- BorrowedCertRevocationList :: from_der( crl ) . err( ) ,
1354+ BorrowedCertRevocationList :: from_der( CRL_WITH_REASON_PARTITIONED_IDP ) . err( ) ,
13301355 Some ( Error :: UnsupportedRevocationReasonsPartitioning )
13311356 ) ;
13321357 }
1358+
1359+ const CRL_MISSING_CRL_NUMBER : & [ u8 ] = & [
1360+ 0x30 , 0x81 , 0xd0 , 0x30 , 0x79 , 0x02 , 0x01 , 0x01 , 0x30 , 0x0a , 0x06 , 0x08 , 0x2a , 0x86 , 0x48 ,
1361+ 0xce , 0x3d , 0x04 , 0x03 , 0x02 , 0x30 , 0x25 , 0x31 , 0x23 , 0x30 , 0x21 , 0x06 , 0x03 , 0x55 , 0x04 ,
1362+ 0x03 , 0x0c , 0x1a , 0x63 , 0x72 , 0x6c , 0x2d , 0x6d , 0x69 , 0x73 , 0x73 , 0x69 , 0x6e , 0x67 , 0x2d ,
1363+ 0x6e , 0x75 , 0x6d , 0x62 , 0x65 , 0x72 , 0x2e , 0x65 , 0x78 , 0x61 , 0x6d , 0x70 , 0x6c , 0x65 , 0x17 ,
1364+ 0x0d , 0x32 , 0x30 , 0x30 , 0x31 , 0x30 , 0x31 , 0x30 , 0x30 , 0x30 , 0x30 , 0x30 , 0x30 , 0x5a , 0x17 ,
1365+ 0x0d , 0x32 , 0x31 , 0x30 , 0x31 , 0x30 , 0x31 , 0x30 , 0x30 , 0x30 , 0x30 , 0x30 , 0x30 , 0x5a , 0xa0 ,
1366+ 0x23 , 0x30 , 0x21 , 0x30 , 0x1f , 0x06 , 0x03 , 0x55 , 0x1d , 0x23 , 0x04 , 0x18 , 0x30 , 0x16 , 0x80 ,
1367+ 0x14 , 0x40 , 0x0e , 0x46 , 0x72 , 0x43 , 0xeb , 0x8b , 0xac , 0x02 , 0xdd , 0x09 , 0xb6 , 0xcc , 0x9d ,
1368+ 0x98 , 0xe9 , 0x5c , 0x34 , 0xdc , 0xee , 0x30 , 0x0a , 0x06 , 0x08 , 0x2a , 0x86 , 0x48 , 0xce , 0x3d ,
1369+ 0x04 , 0x03 , 0x02 , 0x03 , 0x47 , 0x00 , 0x30 , 0x44 , 0x02 , 0x20 , 0x44 , 0xdb , 0x2f , 0x86 , 0xb9 ,
1370+ 0x9e , 0xb8 , 0x9d , 0x4a , 0x4b , 0x42 , 0xe3 , 0x37 , 0x97 , 0xb5 , 0x7a , 0x1f , 0x50 , 0x8a , 0xae ,
1371+ 0x8a , 0x5c , 0x55 , 0x29 , 0xba , 0x5a , 0x5c , 0x4d , 0x53 , 0x1d , 0x44 , 0xce , 0x02 , 0x20 , 0x10 ,
1372+ 0x13 , 0x77 , 0x62 , 0x16 , 0x7a , 0x89 , 0x69 , 0x2e , 0x76 , 0xed , 0xb7 , 0xde , 0x62 , 0x03 , 0x78 ,
1373+ 0xc9 , 0x50 , 0xfb , 0xe7 , 0xcd , 0xb8 , 0x12 , 0xa3 , 0x83 , 0x40 , 0x2f , 0xd6 , 0xf0 , 0x5c , 0xc1 ,
1374+ 0xb6 ,
1375+ ] ;
1376+
1377+ const CRL_DUPLICATE_CRL_NUMBER : & [ u8 ] = & [
1378+ 0x30 , 0x6f , 0x30 , 0x5a , 0x02 , 0x01 , 0x01 , 0x30 , 0x0d , 0x06 , 0x09 , 0x2a , 0x86 , 0x48 , 0x86 ,
1379+ 0xf7 , 0x0d , 0x01 , 0x01 , 0x0b , 0x05 , 0x00 , 0x30 , 0x0c , 0x31 , 0x0a , 0x30 , 0x08 , 0x06 , 0x03 ,
1380+ 0x55 , 0x04 , 0x03 , 0x13 , 0x01 , 0x41 , 0x17 , 0x0d , 0x32 , 0x30 , 0x30 , 0x31 , 0x30 , 0x31 , 0x30 ,
1381+ 0x30 , 0x30 , 0x30 , 0x30 , 0x30 , 0x5a , 0x17 , 0x0d , 0x32 , 0x31 , 0x30 , 0x31 , 0x30 , 0x31 , 0x30 ,
1382+ 0x30 , 0x30 , 0x30 , 0x30 , 0x30 , 0x5a , 0xa0 , 0x1a , 0x30 , 0x18 , 0x30 , 0x0a , 0x06 , 0x03 , 0x55 ,
1383+ 0x1d , 0x14 , 0x04 , 0x03 , 0x02 , 0x01 , 0x01 , 0x30 , 0x0a , 0x06 , 0x03 , 0x55 , 0x1d , 0x14 , 0x04 ,
1384+ 0x03 , 0x02 , 0x01 , 0x01 , 0x30 , 0x0d , 0x06 , 0x09 , 0x2a , 0x86 , 0x48 , 0x86 , 0xf7 , 0x0d , 0x01 ,
1385+ 0x01 , 0x0b , 0x05 , 0x00 , 0x03 , 0x02 , 0x00 , 0x00 ,
1386+ ] ;
1387+
1388+ const CRL_WITH_REASON_PARTITIONED_IDP : & [ u8 ] = & [
1389+ 0x30 , 0x71 , 0x30 , 0x5c , 0x02 , 0x01 , 0x01 , 0x30 , 0x0d , 0x06 , 0x09 , 0x2a , 0x86 , 0x48 , 0x86 ,
1390+ 0xf7 , 0x0d , 0x01 , 0x01 , 0x0b , 0x05 , 0x00 , 0x30 , 0x0c , 0x31 , 0x0a , 0x30 , 0x08 , 0x06 , 0x03 ,
1391+ 0x55 , 0x04 , 0x03 , 0x13 , 0x01 , 0x41 , 0x17 , 0x0d , 0x32 , 0x30 , 0x30 , 0x31 , 0x30 , 0x31 , 0x30 ,
1392+ 0x30 , 0x30 , 0x30 , 0x30 , 0x30 , 0x5a , 0x17 , 0x0d , 0x32 , 0x31 , 0x30 , 0x31 , 0x30 , 0x31 , 0x30 ,
1393+ 0x30 , 0x30 , 0x30 , 0x30 , 0x30 , 0x5a , 0xa0 , 0x1c , 0x30 , 0x1a , 0x30 , 0x0c , 0x06 , 0x03 , 0x55 ,
1394+ 0x1d , 0x1c , 0x04 , 0x05 , 0x30 , 0x03 , 0x83 , 0x01 , 0x00 , 0x30 , 0x0a , 0x06 , 0x03 , 0x55 , 0x1d ,
1395+ 0x14 , 0x04 , 0x03 , 0x02 , 0x01 , 0x01 , 0x30 , 0x0d , 0x06 , 0x09 , 0x2a , 0x86 , 0x48 , 0x86 , 0xf7 ,
1396+ 0x0d , 0x01 , 0x01 , 0x0b , 0x05 , 0x00 , 0x03 , 0x02 , 0x00 , 0x00 ,
1397+ ] ;
13331398}
0 commit comments