From: Yongkui Han <yonhan@cisco.com>
To: linux-kernel@vger.kernel.org
Cc: Mehmet Kayaalp <mkayaalp@linux.vnet.ibm.com>,
David Howells <dhowells@redhat.com>,
Yongkui Han <yonhan@cisco.com>
Subject: [PATCH] Brute-force binary-scanning method to extract certificates
Date: Tue, 30 Apr 2019 14:30:26 -0400 [thread overview]
Message-ID: <20190430183026.31982-1-yonhan@cisco.com> (raw)
Hi Mehmet, David,
I came up with an enhancement to the scripts/extract-sys-certs.pl script
in Linux kernel source, so that the system certificates can be extracted
without debugging symbols or System.map file.
The idea is that the DER-format kernel X509 certificate follows some fixed
pattern. So we can search this fixed pattern to find the location of the
system certificate.
Specifically, below is the pattern I used:
($type0, $len0, $type1, $len1, $ver_attr) =
unpack "nnnnN", substr($fb, $start, 12);
if ($type0 == 0x3082 && $type1 == 0x3082 && $ver_attr == 0xa0030201) {
my $certsize = $len0 + 4;
printf "Have %u bytes of certificate at file offset 0x%x\n",
$certsize, $start;
That is, in the first 12 bytes, two 2-bytes must be 0x3082, and one 4-bytes
must be 0xa0030201. The length of the certificate is also in one of the
2-bytes of the first 12 bytes array.
The script works by scanning the vmlinux file to find this fixed pattern,
and extract the certificate. I think it can be optimized to only scan the
.init* section, instead of the whole vmlinux file. However, the current
approach seems already sufficient.
I have tested with different vmlinux files, and the script works well.
The new script output is like below:
[ bxb-ads-339 ] ./extract-sys-certs.pl vmlinux sys_cert.x509
Have 33 sections
No symbols available, will try brute-force approach.
Length of vmlinux is: 21354392
Have 1063 bytes of certificate at file offset 0x12f99b8
Have 1070 bytes of certificate at file offset 0x12f9ddf
Have 851 bytes of certificate at file offset 0x12fa20d
Have 1188 bytes of certificate at file offset 0x12fa560
Length of extracted certificate is: 4172
[ bxb-ads-339 ]
There is no change if vmlinux contains debugging symbols or System.map
file is provided.
Enclosed please find the git diff output. I can also send you the patch
with “git format-patch” and “git send-email” for you to review.
If possible, can you also try the enhanced script with a few kernel
vmlinux files to test it?
Your review/comments are greatly appreciated.
Thanks,
Yongkui
Signed-off-by: Yongkui Han <yonhan@cisco.com>
---
| 44 +++++++++++++++++++++++++++++++++---
1 file changed, 41 insertions(+), 3 deletions(-)
--git a/scripts/extract-sys-certs.pl b/scripts/extract-sys-certs.pl
index fa8ab15118cc..06f515b4dcd6 100755
--- a/scripts/extract-sys-certs.pl
+++ b/scripts/extract-sys-certs.pl
@@ -86,6 +86,44 @@ if ($nr_symbols == 0 && $sysmap ne "") {
parse_symbols(@lines);
}
+my $buf = "";
+my $len= 0;
+my $size = 0;
+
+if ($nr_symbols == 0 && $sysmap eq "") {
+ print "No symbols available, will try brute-force approach\n";
+
+ my $filesize = -s $vmlinux;
+ open FD, "<$vmlinux" || die $vmlinux;
+ binmode(FD);
+ my $fb;
+ my $len = sysread(FD, $fb, $filesize);
+ die "$vmlinux" if (!defined($len));
+ die "Short read on $vmlinux\n" if ($len != $filesize);
+ close(FD) || die $vmlinux;
+ printf "Length of vmlinux is: %d\n", length($fb);
+
+ my ($type0, $len0, $type1, $len1, $ver_attr) = (0,0,0,0,0);
+ my $start = 0;
+ while ($start < $filesize - 256) {
+ ($type0, $len0, $type1, $len1, $ver_attr) =
+ unpack "nnnnN", substr($fb, $start, 12);
+ if ($type0 == 0x3082 && $type1 == 0x3082 && $ver_attr == 0xa0030201) {
+ my $certsize = $len0 + 4;
+ printf "Have %u bytes of certificate at file offset 0x%x\n",
+ $certsize, $start;
+ $buf .= substr($fb, $start, $certsize);
+ $start += $certsize;
+ } else {
+ $start += 1;
+ }
+ }
+
+ $size = length($buf);
+ printf "Length of extracted certificate is: %d\n", $size ;
+}
+else {
+
die "No symbols available\n"
if ($nr_symbols == 0);
@@ -97,7 +135,6 @@ die "Can't find system certificate list"
my $start = Math::BigInt->new($symbols{"__cert_list_start"});
my $end;
-my $size;
my $size_sym = Math::BigInt->new($symbols{"system_certificate_list_size"});
open FD, "<$vmlinux" || die $vmlinux;
@@ -145,12 +182,13 @@ my $foff = $start - $s->{vma} + $s->{foff};
printf "Certificate list at file offset 0x%x\n", $foff;
die $vmlinux if (!defined(sysseek(FD, $foff, SEEK_SET)));
-my $buf = "";
-my $len = sysread(FD, $buf, $size);
+$len = sysread(FD, $buf, $size);
die "$vmlinux" if (!defined($len));
die "Short read on $vmlinux\n" if ($len != $size);
close(FD) || die $vmlinux;
+} ### end of ($nr_symbols == 0 && $sysmap eq "") else block
+
open FD, ">$keyring" || die $keyring;
binmode(FD);
$len = syswrite(FD, $buf, $size);
--
2.19.1
reply other threads:[~2019-04-30 18:38 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190430183026.31982-1-yonhan@cisco.com \
--to=yonhan@cisco.com \
--cc=dhowells@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mkayaalp@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®