Skip to content

Commit 1390dcc

Browse files
Merge pull request #26 from corporate-gadfly/crl-extension-update
fix CRL extension update by using ASN.1 INTEGER
2 parents 92b3db6 + 06dccc5 commit 1390dcc

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed

lib/puppetserver/ca/action/prune.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,13 @@ def update_pruned_CRL(crl, pkey)
145145

146146
extensions.each do |ext|
147147
if ext.oid == "crlNumber"
148+
next_value = OpenSSL::ASN1::Integer.new(ext.value.to_i + 1)
148149
if RUBY_ENGINE == "jruby"
149-
# Creating a crlNumber extension without an ExtensionFactory produce incorrect result on jruby
150-
crl.add_extension(ef.create_extension("crlNumber", ext.value.next))
150+
# Creating a crlNumber extension without an ExtensionFactory produces an incorrect result on jruby
151+
crl.add_extension(ef.create_extension("crlNumber", next_value))
151152
else
152-
# Creating a crlNumber extension with an ExtensionFactory rais on exception on MRI
153-
crl.add_extension(OpenSSL::X509::Extension.new("crlNumber", ext.value.next))
153+
# Creating a crlNumber extension with an ExtensionFactory raises an exception on MRI
154+
crl.add_extension(OpenSSL::X509::Extension.new("crlNumber", next_value))
154155
end
155156
else
156157
crl.add_extension(ext)

spec/puppetserver/ca/action/prune_spec.rb

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@
421421
end
422422

423423
describe 'update' do
424+
DER_INTEGER_TAG = 0x02
424425
it 'bumps CRL number up by 1' do
425426
ca_key = OpenSSL::PKey::RSA.new(512)
426427
ca_cert = create_cert(ca_key, "Bazzup")
@@ -433,9 +434,49 @@
433434

434435
subject.update_pruned_CRL(ca_crl, ca_key)
435436

436-
extensions_after = ca_crl.extensions.select { |ext| ext.oid == "crlNumber"}
437-
extensions_after.each do |ext|
438-
expect(ext.value.to_i).to eq(1)
437+
extensions_after = ca_crl.extensions.find { |ext| ext.oid == "crlNumber" }
438+
expect(extensions_after).not_to be_nil
439+
440+
raw_bytes = OpenSSL::ASN1::decode(extensions_after.to_der)
441+
.value[1] # index 1 is the extnValue OCTET STRING
442+
.value # unwrap the OCTET STRING to get DER bytes
443+
444+
# The first byte must be 0x02 (DER INTEGER tag)
445+
expect(raw_bytes.bytes.first).to eq(DER_INTEGER_TAG),
446+
"Expected CRL number extension value to be a DER INTEGER (tag #{DER_INTEGER_TAG}) " \
447+
"but got tag 0x#{raw_bytes.bytes.first.to_s(16)}"
448+
449+
parsed = OpenSSL::ASN1.decode(raw_bytes)
450+
expect(parsed).to be_a(OpenSSL::ASN1::Integer)
451+
expect(parsed.value).to eq(OpenSSL::BN.new(1))
452+
end
453+
454+
it 'correctly encodes CRL number as DER INTEGER after multiple prune operations' do
455+
number_of_iterations = 3
456+
ca_key = OpenSSL::PKey::RSA.new(512)
457+
ca_cert = create_cert(ca_key, "Bazzup")
458+
revoked_cert = create_cert(ca_key, 'revoked')
459+
ca_crl = create_crl(ca_cert, ca_key, Array.new(number_of_iterations, revoked_cert))
460+
461+
initial_crl_number = OpenSSL::BN.new(
462+
ca_crl.extensions.find { |ext| ext.oid == "crlNumber" }.value
463+
)
464+
465+
number_of_iterations.times do |iteration|
466+
subject.prune_CRL(ca_crl) if iteration == 0
467+
subject.update_pruned_CRL(ca_crl, ca_key)
468+
469+
crl_number_ext = ca_crl.extensions.find { |ext| ext.oid == "crlNumber" }
470+
raw_bytes = OpenSSL::ASN1.decode(crl_number_ext.to_der)
471+
.value[1] # index 1 is the extnValue OCTET STRING
472+
.value # unwrap the OCTET STRING to get DER bytes
473+
474+
expect(raw_bytes.bytes.first).to eq(DER_INTEGER_TAG),
475+
"After #{iteration + 1} update(s), CRL number tag was 0x#{raw_bytes.bytes.first.to_s(16)} " \
476+
"instead of #{DER_INTEGER_TAG} (DER INTEGER)"
477+
478+
parsed = OpenSSL::ASN1.decode(raw_bytes)
479+
expect(parsed.value).to eq(initial_crl_number + OpenSSL::BN.new(iteration + 1))
439480
end
440481
end
441482
end

0 commit comments

Comments
 (0)