@@ -327,6 +327,44 @@ ossl_x509crl_set_revoked(VALUE self, VALUE ary)
327327 return ary ;
328328}
329329
330+ /*
331+ * call-seq:
332+ * crl.by_serial(serial) -> OpenSSL::X509::Revoked or nil
333+ *
334+ * Looks up the certificate _serial_ (an Integer or OpenSSL::BN) in the CRL and
335+ * returns the matching OpenSSL::X509::Revoked entry, or +nil+ if that serial is
336+ * not listed.
337+ *
338+ * Unlike iterating over #revoked, this does not instantiate the entire
339+ * revocation list: it performs a sorted lookup (wrapping the OpenSSL function
340+ * +X509_CRL_get0_by_serial+), which is significantly faster and uses far less
341+ * memory for large CRLs.
342+ *
343+ * crl.by_serial(cert.serial) #=> #<OpenSSL::X509::Revoked> or nil
344+ * crl.by_serial(cert.serial)&.time #=> revocation time, if revoked
345+ */
346+ static VALUE
347+ ossl_x509crl_by_serial (VALUE self , VALUE serial )
348+ {
349+ X509_CRL * crl ;
350+ X509_REVOKED * rev = NULL ;
351+ ASN1_INTEGER * asn1_serial ;
352+ int found ;
353+
354+ GetX509CRL (self , crl );
355+ asn1_serial = num_to_asn1integer (serial , NULL );
356+
357+ /* 0 = not found, 1 = found, 2 = found with reason removeFromCRL */
358+ found = X509_CRL_get0_by_serial (crl , & rev , asn1_serial );
359+ ASN1_INTEGER_free (asn1_serial );
360+
361+ if (found == 0 )
362+ return Qnil ;
363+
364+ /* ossl_x509revoked_new dups, so the result outlives the CRL safely */
365+ return ossl_x509revoked_new (rev );
366+ }
367+
330368static VALUE
331369ossl_x509crl_add_revoked (VALUE self , VALUE revoked )
332370{
@@ -525,6 +563,7 @@ Init_ossl_x509crl(void)
525563 rb_define_method (cX509CRL , "next_update=" , ossl_x509crl_set_next_update , 1 );
526564 rb_define_method (cX509CRL , "revoked" , ossl_x509crl_get_revoked , 0 );
527565 rb_define_method (cX509CRL , "revoked=" , ossl_x509crl_set_revoked , 1 );
566+ rb_define_method (cX509CRL , "by_serial" , ossl_x509crl_by_serial , 1 );
528567 rb_define_method (cX509CRL , "add_revoked" , ossl_x509crl_add_revoked , 1 );
529568 rb_define_method (cX509CRL , "sign" , ossl_x509crl_sign , 2 );
530569 rb_define_method (cX509CRL , "verify" , ossl_x509crl_verify , 1 );
0 commit comments