From 30fb1724a80b84f1ac560882016866ca4d3ccf4f Mon Sep 17 00:00:00 2001 From: Bart de Water Date: Sun, 20 Oct 2019 16:17:07 -0400 Subject: [PATCH 1/2] Separate cert generation and issuance test helpers --- test/utils.rb | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/test/utils.rb b/test/utils.rb index 126cb85df..36aeda055 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -60,11 +60,10 @@ def file_path(category, name) module_function - def issue_cert(dn, key, serial, extensions, issuer, issuer_key, - not_before: nil, not_after: nil, digest: "sha256") + def generate_cert(dn, key, serial, issuer, + not_before: nil, not_after: nil) cert = OpenSSL::X509::Certificate.new issuer = cert unless issuer - issuer_key = key unless issuer_key cert.version = 2 cert.serial = serial cert.subject = dn @@ -73,6 +72,16 @@ def issue_cert(dn, key, serial, extensions, issuer, issuer_key, now = Time.now cert.not_before = not_before || now - 3600 cert.not_after = not_after || now + 3600 + cert + end + + + def issue_cert(dn, key, serial, extensions, issuer, issuer_key, + not_before: nil, not_after: nil, digest: "sha256") + cert = generate_cert(dn, key, serial, issuer, + not_before: not_before, not_after: not_after) + issuer = cert unless issuer + issuer_key = key unless issuer_key ef = OpenSSL::X509::ExtensionFactory.new ef.subject_certificate = cert ef.issuer_certificate = issuer From 0410c6ff776433ddcb71f18214d35a28b5e4cc86 Mon Sep 17 00:00:00 2001 From: Bart de Water Date: Sun, 20 Oct 2019 16:18:08 -0400 Subject: [PATCH 2/2] Add helper to retrieve CRL URIs from a certificate --- lib/openssl/x509.rb | 34 ++++++++++++++++++++++++++++++++++ test/test_x509cert.rb | 16 ++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/lib/openssl/x509.rb b/lib/openssl/x509.rb index 4f3a4337f..ac216155f 100644 --- a/lib/openssl/x509.rb +++ b/lib/openssl/x509.rb @@ -113,6 +113,39 @@ def authority_key_identifier key_id.nil? ? nil : key_id.value end end + + module CRLDistributionPoints + include Helpers + + # Get the distributionPoint fullName URI from the certificate's CRL + # distribution points extension, as described in RFC5280 Section + # 4.2.1.13 + # + # Returns an array of strings or nil or raises ASN1::ASN1Error. + def crl_uris + ext = find_extension("crlDistributionPoints") + return nil if ext.nil? + + cdp_asn1 = ASN1.decode(ext.value_der) + if cdp_asn1.tag_class != :UNIVERSAL || cdp_asn1.tag != ASN1::SEQUENCE + raise ASN1::ASN1Error "invalid extension" + end + + crl_uris = cdp_asn1.map do |crl_distribution_point| + distribution_point = crl_distribution_point.value.find do |v| + v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0 + end + full_name = distribution_point&.value&.find do |v| + v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0 + end + full_name&.value&.find do |v| + v.tag_class == :CONTEXT_SPECIFIC && v.tag == 6 # uniformResourceIdentifier + end + end + + crl_uris&.map(&:value) + end + end end class Name @@ -234,6 +267,7 @@ def cleanup class Certificate include Extension::SubjectKeyIdentifier include Extension::AuthorityKeyIdentifier + include Extension::CRLDistributionPoints def pretty_print(q) q.object_group(self) { diff --git a/test/test_x509cert.rb b/test/test_x509cert.rb index a490ccfc7..ec8b2ea73 100644 --- a/test/test_x509cert.rb +++ b/test/test_x509cert.rb @@ -97,6 +97,22 @@ def test_extension assert_equal(ee1_exts[i].first, ext.oid) assert_equal(ee1_exts[i].last, ext.critical?) } + assert_nil(ee1_cert.crl_uris) + + ef = OpenSSL::X509::ExtensionFactory.new + ef.config = OpenSSL::Config.parse(<<~_cnf_) + [crlDistPts] + URI.1 = http://www.example.com/crl + URI.2 = ldap://ldap.example.com/cn=ca?certificateRevocationList;binary + _cnf_ + cdp_cert = generate_cert(@ee1, @rsa1024, 3, ca_cert) + ef.subject_certificate = cdp_cert + cdp_cert.add_extension(ef.create_extension("crlDistributionPoints", "@crlDistPts")) + cdp_cert.sign(@rsa2048, "sha256") + assert_equal( + ["http://www.example.com/crl", "ldap://ldap.example.com/cn=ca?certificateRevocationList;binary"], + cdp_cert.crl_uris + ) no_exts_cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil) assert_equal nil, no_exts_cert.authority_key_identifier