Skip to content
This repository has been archived by the owner on Jun 19, 2020. It is now read-only.

Add additional validations to SCT extension #41

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions lib/certlint/extensions/signedcertificatetimestamplist.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
# express or implied. See the License for the specific language governing
# permissions and limitations under the License.
require_relative 'asn1ext'
require 'openssl'
require 'date'

module CertLint
class ASN1Ext
Expand All @@ -22,8 +24,71 @@ def self.lint(content, cert, critical = false)
if critical
messages << 'E: SignedCertificateTimestampList must not be critical'
end
begin
asn1 = OpenSSL::ASN1.decode content
value = asn1.value
offset = 0

sct_list_len = unpack1(value[0..1], 'S>')
offset += 2
any_scts = false

while offset < value.length
sct_len = unpack1(value[offset..offset+1], 'S>')
offset += 2

messages.concat(parse_sct(value[offset..offset+sct_len-1]))
offset += sct_len
any_scts = true
end

messages << 'E: No SCTs were found in SignedCertificateTimestampList' if not any_scts
rescue
messages << 'E: Parse error occurred when parsing SignedCertificateTimestampList'
end

messages
end

private

def self.unpack1(value, fmt)
value.unpack(fmt)[0]
end

def self.parse_sct(sct_octets)
messages = []
offset = 0

version = sct_octets[offset].ord
offset += 1

if version != 0
messages << "I: SCT has a non-zero version value (#{version})"
else
# skip log ID
offset += 32

timestamp = DateTime.strptime(unpack1(sct_octets[offset..offset+7], 'Q>').to_s, '%Q')
offset += 8
messages << 'E: SCT timestamp is in the future' if timestamp > DateTime.now

ext_len = unpack1(sct_octets[offset..offset+1], 'S>')
offset += 2
messages << 'E: SCT extension length is non-zero' if ext_len != 0
offset += ext_len

# skip signature hash/signing algorithm
offset += 2

sig_len = unpack1(sct_octets[offset..offset+1], 'S>')
offset += 2

messages << 'E: SCT contains an incorrect signature length' if sig_len != (sct_octets.length - offset)
end

messages
end
end
end
end
Expand Down