Skip to main content
Bounty Awarded with 100 reputation awarded by Mikhail Morfikov
added 6 characters in body
Source Link
user313992
user313992

YMMV. I've only tried this with a custom built kernel using sha512 signatures. This should be of course much better done by using the openssl libraries directly, instead of kludging together slow and fragile openssl x509 and, openssl asn1parse and rsautl invocations.

use strict; sub through { my ($cmd, $data, $cb) = @_; use IPC::Open2; my $pid = open2 my $from, my $to, ref $cmd ? @$cmd : $cmd; print $to $data; close $to; my $out; if($cb){ while(<$from>){ last if $out = $cb->($_) } } else { local $/; $out = <$from>; } waitpid ($pid, 0); die "status $?" if $? != 0; $out; } sub gethash { my ($d) = @_; my ($alg, $hash); through [qw(openssl asn1parse -inform der)], $d, sub { if(/(\d+):d=\d+ +hl= *(\d+) +l= *(\d+) +prim: +OCTET STRING/){ $hash = substr $d, $1 + $2, $3 }elsif(/prim: +OBJECT +:(sha\w+)/){ $alg = $1; } undef }; $alg, $hash } use File::Temp; my $tf = new File::Temp; my $pub_key; my @type = qw(PGP X509 PKCS7); my $r = 0; if((my $cert = shift) =~ /(\.x509)$|\.pem$/i){ $pub_key = $tf->filename; system qw(openssl x509 -pubkey -noout), '-inform', $1 ? 'der' : 'pem', '-in', $cert, '-out', $pub_key; die "status $?" if $? != 0; } die "no certificate/key file" unless $pub_key; for my $kof (@ARGV){ open my $ko, '<', $kof or die "open $kof: $!\n"; seek $ko, -4096, 2 or die "seek: $!"; read $ko, my $d, 4096 or die "read: $!"; my ($algo, $hash, $type, $signer_len, $key_id_len, $sig_len, $magic) = unpack 'C5x3Na*', substr $d, -40; die "no signature in $kof" unless $magic eq "~Module signature appended~\n"; die "this script only knows about PKCS7PKCS#7 signatures" unless $type[$type] eq 'PKCS7'; my $hash = gethash substr $d, - 40 - $sig_len, $sig_len; die "hash not found" unless $hash; my ($alg, $vhash) = gethash through [qw(openssl rsautl -verify -pubin -inkey), $pub_key], $hash; seek $ko, 0, 0 or die "seek: $!"; read $ko, my $d, (-s $ko) - $sig_len - 40 or die "read: $!"; use Digest::SHA; my $fhash = new Digest::SHA($alg)->add($d)->digest; if($fhash eq $vhash){ print "OK $kof\n"; }else{ print "**FAIL** $kof\n"; $r = 1; warn 'orig=', unpack('H*', $vhash), "\n"; warn 'file=', unpack('H*', $fhash), "\n"; } } exit $r; 

YMMV. I've only tried this with a custom built kernel using sha512 signatures. This should of course much better done by using the openssl libraries directly, instead of kludging together slow and fragile openssl x509 and openssl asn1parse invocations.

use strict; sub through { my ($cmd, $data, $cb) = @_; use IPC::Open2; my $pid = open2 my $from, my $to, ref $cmd ? @$cmd : $cmd; print $to $data; close $to; my $out; if($cb){ while(<$from>){ last if $out = $cb->($_) } } else { local $/; $out = <$from>; } waitpid ($pid, 0); die "status $?" if $? != 0; $out; } sub gethash { my ($d) = @_; my ($alg, $hash); through [qw(openssl asn1parse -inform der)], $d, sub { if(/(\d+):d=\d+ +hl= *(\d+) +l= *(\d+) +prim: +OCTET STRING/){ $hash = substr $d, $1 + $2, $3 }elsif(/prim: +OBJECT +:(sha\w+)/){ $alg = $1; } undef }; $alg, $hash } use File::Temp; my $tf = new File::Temp; my $pub_key; my @type = qw(PGP X509 PKCS7); my $r = 0; if((my $cert = shift) =~ /(\.x509)$|\.pem$/i){ $pub_key = $tf->filename; system qw(openssl x509 -pubkey -noout), '-inform', $1 ? 'der' : 'pem', '-in', $cert, '-out', $pub_key; die "status $?" if $? != 0; } die "no certificate/key file" unless $pub_key; for my $kof (@ARGV){ open my $ko, '<', $kof or die "open $kof: $!\n"; seek $ko, -4096, 2 or die "seek: $!"; read $ko, my $d, 4096 or die "read: $!"; my ($algo, $hash, $type, $signer_len, $key_id_len, $sig_len, $magic) = unpack 'C5x3Na*', substr $d, -40; die "no signature in $kof" unless $magic eq "~Module signature appended~\n"; die "this script only knows about PKCS7 signatures" unless $type[$type] eq 'PKCS7'; my $hash = gethash substr $d, - 40 - $sig_len, $sig_len; die "hash not found" unless $hash; my ($alg, $vhash) = gethash through [qw(openssl rsautl -verify -pubin -inkey), $pub_key], $hash; seek $ko, 0, 0 or die "seek: $!"; read $ko, my $d, (-s $ko) - $sig_len - 40 or die "read: $!"; use Digest::SHA; my $fhash = new Digest::SHA($alg)->add($d)->digest; if($fhash eq $vhash){ print "OK $kof\n"; }else{ print "**FAIL** $kof\n"; $r = 1; warn 'orig=', unpack('H*', $vhash), "\n"; warn 'file=', unpack('H*', $fhash), "\n"; } } exit $r; 

YMMV. I've only tried this with a custom built kernel using sha512 signatures. This should be of course much better done by using the openssl libraries directly, instead of kludging together slow and fragile openssl x509, asn1parse and rsautl invocations.

use strict; sub through { my ($cmd, $data, $cb) = @_; use IPC::Open2; my $pid = open2 my $from, my $to, ref $cmd ? @$cmd : $cmd; print $to $data; close $to; my $out; if($cb){ while(<$from>){ last if $out = $cb->($_) } } else { local $/; $out = <$from>; } waitpid ($pid, 0); die "status $?" if $? != 0; $out; } sub gethash { my ($d) = @_; my ($alg, $hash); through [qw(openssl asn1parse -inform der)], $d, sub { if(/(\d+):d=\d+ +hl= *(\d+) +l= *(\d+) +prim: +OCTET STRING/){ $hash = substr $d, $1 + $2, $3 }elsif(/prim: +OBJECT +:(sha\w+)/){ $alg = $1; } undef }; $alg, $hash } use File::Temp; my $tf = new File::Temp; my $pub_key; my @type = qw(PGP X509 PKCS7); my $r = 0; if((my $cert = shift) =~ /(\.x509)$|\.pem$/i){ $pub_key = $tf->filename; system qw(openssl x509 -pubkey -noout), '-inform', $1 ? 'der' : 'pem', '-in', $cert, '-out', $pub_key; die "status $?" if $? != 0; } die "no certificate/key file" unless $pub_key; for my $kof (@ARGV){ open my $ko, '<', $kof or die "open $kof: $!\n"; seek $ko, -4096, 2 or die "seek: $!"; read $ko, my $d, 4096 or die "read: $!"; my ($algo, $hash, $type, $signer_len, $key_id_len, $sig_len, $magic) = unpack 'C5x3Na*', substr $d, -40; die "no signature in $kof" unless $magic eq "~Module signature appended~\n"; die "this script only knows about PKCS#7 signatures" unless $type[$type] eq 'PKCS7'; my $hash = gethash substr $d, - 40 - $sig_len, $sig_len; die "hash not found" unless $hash; my ($alg, $vhash) = gethash through [qw(openssl rsautl -verify -pubin -inkey), $pub_key], $hash; seek $ko, 0, 0 or die "seek: $!"; read $ko, my $d, (-s $ko) - $sig_len - 40 or die "read: $!"; use Digest::SHA; my $fhash = new Digest::SHA($alg)->add($d)->digest; if($fhash eq $vhash){ print "OK $kof\n"; }else{ print "**FAIL** $kof\n"; $r = 1; warn 'orig=', unpack('H*', $vhash), "\n"; warn 'file=', unpack('H*', $fhash), "\n"; } } exit $r; 
deleted 31 characters in body
Source Link
user313992
user313992
use strict; sub through { my ($cmd, $data, $cb) = @_; use IPC::Open2; my $pid = open2 my $from, my $to, ref $cmd ? @$cmd : $cmd; print $to $data; close $to; my $out; if($cb){ while(<$from>){ last if $out = $cb->($_) } } else { local $/; $out = <$from>; } waitpid ($pid, 0); die "status $?" if $? != 0; $out; } sub gethash { my ($d) = @_; my ($alg, $hash); through [qw(openssl asn1parse -inform der)], $d, sub { if(/(\d+):d=\d+ +hl= *(\d+) +l= *(\d+) +prim: +OCTET STRING/){ $hash = substr $d, $1 + $2, $3 }elsif(/prim: +OBJECT +:(sha\w+)/){ $alg = $1; } undef }; $alg, $hash } use File::Temp; my $tf = new File::Temp; my $pub_key; my @type = qw(PGP X509 PKCS7); my $r = 0; if((my $cert = shift) =~ /(\.x509)$|\.pem$/i){ $pub_key = $tf->filename; system qw(openssl x509 -pubkey -noout), '-inform', $1 ? 'der' : 'pem', '-in', $cert, '-out', $pub_key; die "status $?" if $? != 0; } die "no certificate/key file" unless $pub_key; for my $kof (@ARGV){ open my $ko, '<', $kof or die "open $kof: $!\n"; seek $ko, -4096, 2 or die "seek: $!"; read $ko, my $d, 4096 or die "read: $!"; my ($algo, $hash, $type, $signer_len, $key_id_len, $sig_len, $magic) = unpack 'C5x3Na*', substr $d, -40; die "no signature in $kof" unless $magic eq "~Module signature appended~\n"; die "this script only knows about PKCS7 signatures" unless $type[$type] eq 'PKCS7'; my $hash = gethash substr $d, - 40 - $sig_len, $sig_len; die "hash not found" unless $hash; my ($alg, $vhash) = gethash through [qw(openssl rsautl -verify -pubin -inkey), $pub_key], $hash; seek $ko, 0, 0 or die "seek: $!"; read $ko, my $d, (-s $ko) - $sig_len - 40 or die "read: $!"; use Digest::SHA; my $fhash = new Digest::SHA($alg)->add($d)->digest; if($fhash eq $vhash){ printfprint "OK %s\n", $kof;$kof\n"; }else{ printfprint "**FAIL** %s\n", $kof;  flush STDOUT;$kof\n"; $r = 1; warn 'orig=', unpack('H*', $vhash), "\n"; warn 'file=', unpack('H*', $fhash), "\n"; } } exit $r; 
use strict; sub through { my ($cmd, $data, $cb) = @_; use IPC::Open2; my $pid = open2 my $from, my $to, ref $cmd ? @$cmd : $cmd; print $to $data; close $to; my $out; if($cb){ while(<$from>){ last if $out = $cb->($_) } } else { local $/; $out = <$from>; } waitpid ($pid, 0); die "status $?" if $? != 0; $out; } sub gethash { my ($d) = @_; my ($alg, $hash); through [qw(openssl asn1parse -inform der)], $d, sub { if(/(\d+):d=\d+ +hl= *(\d+) +l= *(\d+) +prim: +OCTET STRING/){ $hash = substr $d, $1 + $2, $3 }elsif(/prim: +OBJECT +:(sha\w+)/){ $alg = $1; } undef }; $alg, $hash } use File::Temp; my $tf = new File::Temp; my $pub_key; my @type = qw(PGP X509 PKCS7); my $r = 0; if((my $cert = shift) =~ /(\.x509)$|\.pem$/i){ $pub_key = $tf->filename; system qw(openssl x509 -pubkey -noout), '-inform', $1 ? 'der' : 'pem', '-in', $cert, '-out', $pub_key; die "status $?" if $? != 0; } die "no certificate/key file" unless $pub_key; for my $kof (@ARGV){ open my $ko, '<', $kof or die "open $kof: $!\n"; seek $ko, -4096, 2 or die "seek: $!"; read $ko, my $d, 4096 or die "read: $!"; my ($algo, $hash, $type, $signer_len, $key_id_len, $sig_len, $magic) = unpack 'C5x3Na*', substr $d, -40; die "no signature in $kof" unless $magic eq "~Module signature appended~\n"; die "this script only knows about PKCS7 signatures" unless $type[$type] eq 'PKCS7'; my $hash = gethash substr $d, - 40 - $sig_len, $sig_len; die "hash not found" unless $hash; my ($alg, $vhash) = gethash through [qw(openssl rsautl -verify -pubin -inkey), $pub_key], $hash; seek $ko, 0, 0 or die "seek: $!"; read $ko, my $d, (-s $ko) - $sig_len - 40 or die "read: $!"; use Digest::SHA; my $fhash = new Digest::SHA($alg)->add($d)->digest; if($fhash eq $vhash){ printf "OK %s\n", $kof; }else{ printf "**FAIL** %s\n", $kof;  flush STDOUT; $r = 1; warn 'orig=', unpack('H*', $vhash), "\n"; warn 'file=', unpack('H*', $fhash), "\n"; } } exit $r; 
use strict; sub through { my ($cmd, $data, $cb) = @_; use IPC::Open2; my $pid = open2 my $from, my $to, ref $cmd ? @$cmd : $cmd; print $to $data; close $to; my $out; if($cb){ while(<$from>){ last if $out = $cb->($_) } } else { local $/; $out = <$from>; } waitpid ($pid, 0); die "status $?" if $? != 0; $out; } sub gethash { my ($d) = @_; my ($alg, $hash); through [qw(openssl asn1parse -inform der)], $d, sub { if(/(\d+):d=\d+ +hl= *(\d+) +l= *(\d+) +prim: +OCTET STRING/){ $hash = substr $d, $1 + $2, $3 }elsif(/prim: +OBJECT +:(sha\w+)/){ $alg = $1; } undef }; $alg, $hash } use File::Temp; my $tf = new File::Temp; my $pub_key; my @type = qw(PGP X509 PKCS7); my $r = 0; if((my $cert = shift) =~ /(\.x509)$|\.pem$/i){ $pub_key = $tf->filename; system qw(openssl x509 -pubkey -noout), '-inform', $1 ? 'der' : 'pem', '-in', $cert, '-out', $pub_key; die "status $?" if $? != 0; } die "no certificate/key file" unless $pub_key; for my $kof (@ARGV){ open my $ko, '<', $kof or die "open $kof: $!\n"; seek $ko, -4096, 2 or die "seek: $!"; read $ko, my $d, 4096 or die "read: $!"; my ($algo, $hash, $type, $signer_len, $key_id_len, $sig_len, $magic) = unpack 'C5x3Na*', substr $d, -40; die "no signature in $kof" unless $magic eq "~Module signature appended~\n"; die "this script only knows about PKCS7 signatures" unless $type[$type] eq 'PKCS7'; my $hash = gethash substr $d, - 40 - $sig_len, $sig_len; die "hash not found" unless $hash; my ($alg, $vhash) = gethash through [qw(openssl rsautl -verify -pubin -inkey), $pub_key], $hash; seek $ko, 0, 0 or die "seek: $!"; read $ko, my $d, (-s $ko) - $sig_len - 40 or die "read: $!"; use Digest::SHA; my $fhash = new Digest::SHA($alg)->add($d)->digest; if($fhash eq $vhash){ print "OK $kof\n"; }else{ print "**FAIL** $kof\n"; $r = 1; warn 'orig=', unpack('H*', $vhash), "\n"; warn 'file=', unpack('H*', $fhash), "\n"; } } exit $r; 
added 6 characters in body
Source Link
user313992
user313992

FirstSecond, you have to extract the certificate and public key from the kernel; you can use the extract-sys-certs.pl script for that:

You can also extract the public key from the certs/signing_key.x509 or certs/signing_key.pem files from the linux kernel's build directory.

Having done that, you have all the data you need in /tmp/pubkeymodsig and /tmp/cert.x509 and can continue with the dozen or so steps necessary to verify a PKCS#7 signature.

YMMV. I've only tried this with a custom buildbuilt kernel using sha512 signatures. This should of course much better done by using the openssl libraries directly, instead of kludging together slow and fragile openssl x509 and openssl asn1parse invocations.

use strict; sub through { my ($cmd, $data, $cb) = @_; use IPC::Open2; my $pid = open2 my $from, my $to, ref $cmd ? @$cmd : $cmd; print $to $data; close $to; my $out; if($cb){ while(<$from>){ last if $out = $cb->($_) } } else { local $/; $out = <$from>; } waitpid ($pid, 0); die "status $?" if $? != 0; $out; } sub gethash { my ($d) = @_; my ($alg, $hash); through [qw(openssl asn1parse -inform der)], $d, sub { if(/(\d+):d=\d+ +hl= *(\d+) +l= *(\d+) +prim: +OCTET STRING/){ $hash = substr $d, $1 + $2, $3 }elsif(/prim: +OBJECT +:(sha\w+)/){ $alg = $1; } undef }; $alg, $hash } use File::Temp; my $tf = new File::Temp; my $pub_key; my @type = qw(PGP X509 PKCS7); my $r = 0; if((my $cert = shift) =~ /(\.x509)$|\.pem$/i){ $pub_key = $tf->filename; system qw(openssl x509 -pubkey -noout), '-inform', $1 ? 'der' : 'pem', '-in', $cert, '-out', $pub_key; die "status $?" if $? != 0; } die "no certificate/key file" unless $pub_key; for my $kof (@ARGV){ open my $ko, '<', $kof or die "open $kof: $!\n"; seek $ko, -4096, 2 or die "seek: $!"; read $ko, my $d, 4096 or die "read: $!"; my ($algo, $hash, $type, $signer_len, $key_id_len, $sig_len, $magic) = unpack 'C5x3Na*', substr $d, -40; die "no signature in $kof" unless $magic eq "~Module signature appended~\n"; die "this script only knows about PKCS7 signatures" unless $type[$type] eq 'PKCS7'; my $hash = gethash substr $d, - 40 - $sig_len, $sig_len; die "hash not found" unless $hash; my ($alg, $vhash) = gethash through [qw(openssl rsautl -verify -pubin -inkey), $pub_key], $hash; seek $ko, 0, 0 or die "seek: $!"; read $ko, my $d, (-s $ko) - $sig_len - 40 or die "read: $!"; use Digest::SHA; my $fhash = new Digest::SHA($alg)->add($d)->digest; if($fhash eq $vhash){ printf "OK %s\n", $kof; }else{ printf "FAIL"**FAIL** %s\n", $kof; flush STDOUT; $r = 1; warn 'orig=', unpack('H*', $vhash), "\n"; warn 'file=', unpack('H*', $fhash), "\n"; } } exit $r; 

First, you have to extract the certificate and public key from the kernel; you can use the extract-sys-certs.pl script for that:

You can also extract the public key from the certs/signing_key.x509 or certs/signing_key.pem from the linux kernel's build directory.

Having done that, you have all the data you need in /tmp/pubkey and /tmp/cert.x509 and can continue with the dozen or so steps necessary to verify a PKCS#7 signature.

YMMV. I've only tried this with a custom build kernel using sha512 signatures. This should of course much better done by using the openssl libraries directly, instead of kludging together slow and fragile openssl x509 and openssl asn1parse invocations.

use strict; sub through { my ($cmd, $data, $cb) = @_; use IPC::Open2; my $pid = open2 my $from, my $to, ref $cmd ? @$cmd : $cmd; print $to $data; close $to; my $out; if($cb){ while(<$from>){ last if $out = $cb->($_) } } else { local $/; $out = <$from>; } waitpid ($pid, 0); die "status $?" if $? != 0; $out; } sub gethash { my ($d) = @_; my ($alg, $hash); through [qw(openssl asn1parse -inform der)], $d, sub { if(/(\d+):d=\d+ +hl= *(\d+) +l= *(\d+) +prim: +OCTET STRING/){ $hash = substr $d, $1 + $2, $3 }elsif(/prim: +OBJECT +:(sha\w+)/){ $alg = $1; } undef }; $alg, $hash } use File::Temp; my $tf = new File::Temp; my $pub_key; my @type = qw(PGP X509 PKCS7); my $r = 0; if((my $cert = shift) =~ /(\.x509)$|\.pem$/i){ $pub_key = $tf->filename; system qw(openssl x509 -pubkey -noout), '-inform', $1 ? 'der' : 'pem', '-in', $cert, '-out', $pub_key; die "status $?" if $? != 0; } die "no certificate/key file" unless $pub_key; for my $kof (@ARGV){ open my $ko, '<', $kof or die "open $kof: $!\n"; seek $ko, -4096, 2 or die "seek: $!"; read $ko, my $d, 4096 or die "read: $!"; my ($algo, $hash, $type, $signer_len, $key_id_len, $sig_len, $magic) = unpack 'C5x3Na*', substr $d, -40; die "no signature in $kof" unless $magic eq "~Module signature appended~\n"; die "this script only knows about PKCS7 signatures" unless $type[$type] eq 'PKCS7'; my $hash = gethash substr $d, - 40 - $sig_len, $sig_len; die "hash not found" unless $hash; my ($alg, $vhash) = gethash through [qw(openssl rsautl -verify -pubin -inkey), $pub_key], $hash; seek $ko, 0, 0 or die "seek: $!"; read $ko, my $d, (-s $ko) - $sig_len - 40 or die "read: $!"; use Digest::SHA; my $fhash = new Digest::SHA($alg)->add($d)->digest; if($fhash eq $vhash){ printf "OK %s\n", $kof; }else{ printf "FAIL %s\n", $kof; flush STDOUT; $r = 1; warn 'orig=', unpack('H*', $vhash), "\n"; warn 'file=', unpack('H*', $fhash), "\n"; } } exit $r; 

Second, you have to extract the certificate and public key from the kernel; you can use the extract-sys-certs.pl script for that:

You can also extract the public key from the certs/signing_key.x509 or certs/signing_key.pem files from the linux kernel's build directory.

Having done that, you have all the data you need in /tmp/modsig and /tmp/cert.x509 and can continue with the dozen or so steps necessary to verify a PKCS#7 signature.

YMMV. I've only tried this with a custom built kernel using sha512 signatures. This should of course much better done by using the openssl libraries directly, instead of kludging together slow and fragile openssl x509 and openssl asn1parse invocations.

use strict; sub through { my ($cmd, $data, $cb) = @_; use IPC::Open2; my $pid = open2 my $from, my $to, ref $cmd ? @$cmd : $cmd; print $to $data; close $to; my $out; if($cb){ while(<$from>){ last if $out = $cb->($_) } } else { local $/; $out = <$from>; } waitpid ($pid, 0); die "status $?" if $? != 0; $out; } sub gethash { my ($d) = @_; my ($alg, $hash); through [qw(openssl asn1parse -inform der)], $d, sub { if(/(\d+):d=\d+ +hl= *(\d+) +l= *(\d+) +prim: +OCTET STRING/){ $hash = substr $d, $1 + $2, $3 }elsif(/prim: +OBJECT +:(sha\w+)/){ $alg = $1; } undef }; $alg, $hash } use File::Temp; my $tf = new File::Temp; my $pub_key; my @type = qw(PGP X509 PKCS7); my $r = 0; if((my $cert = shift) =~ /(\.x509)$|\.pem$/i){ $pub_key = $tf->filename; system qw(openssl x509 -pubkey -noout), '-inform', $1 ? 'der' : 'pem', '-in', $cert, '-out', $pub_key; die "status $?" if $? != 0; } die "no certificate/key file" unless $pub_key; for my $kof (@ARGV){ open my $ko, '<', $kof or die "open $kof: $!\n"; seek $ko, -4096, 2 or die "seek: $!"; read $ko, my $d, 4096 or die "read: $!"; my ($algo, $hash, $type, $signer_len, $key_id_len, $sig_len, $magic) = unpack 'C5x3Na*', substr $d, -40; die "no signature in $kof" unless $magic eq "~Module signature appended~\n"; die "this script only knows about PKCS7 signatures" unless $type[$type] eq 'PKCS7'; my $hash = gethash substr $d, - 40 - $sig_len, $sig_len; die "hash not found" unless $hash; my ($alg, $vhash) = gethash through [qw(openssl rsautl -verify -pubin -inkey), $pub_key], $hash; seek $ko, 0, 0 or die "seek: $!"; read $ko, my $d, (-s $ko) - $sig_len - 40 or die "read: $!"; use Digest::SHA; my $fhash = new Digest::SHA($alg)->add($d)->digest; if($fhash eq $vhash){ printf "OK %s\n", $kof; }else{ printf "**FAIL** %s\n", $kof; flush STDOUT; $r = 1; warn 'orig=', unpack('H*', $vhash), "\n"; warn 'file=', unpack('H*', $fhash), "\n"; } } exit $r; 
Source Link
user313992
user313992
Loading