[PATCH 1/2] MODSIGN: perlify sign-file and merge in x509keyid [ver #3]
Turn sign-file into perl and merge in x509keyid. The latter doesn't need to be a separate script as it doesn't actually need to work out the SHA1 sum of the X.509 certificate itself, since it can get that from the X.509 certificate. Signed-off-by: David Howells --- Makefile |2 scripts/sign-file | 477 - scripts/x509keyid | 268 -- 3 files changed, 400 insertions(+), 347 deletions(-) mode change 100644 => 100755 scripts/sign-file delete mode 100755 scripts/x509keyid diff --git a/Makefile b/Makefile index 4fd82f7..14b9874 100644 --- a/Makefile +++ b/Makefile @@ -723,7 +723,7 @@ ifeq ($(CONFIG_MODULE_SIG),y) MODSECKEY = ./signing_key.priv MODPUBKEY = ./signing_key.x509 export MODPUBKEY -mod_sign_cmd = sh $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY) $(srctree)/scripts/x509keyid +mod_sign_cmd = perl $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY) else mod_sign_cmd = true endif diff --git a/scripts/sign-file b/scripts/sign-file old mode 100644 new mode 100755 index d014abd..c8a2e7c --- a/scripts/sign-file +++ b/scripts/sign-file @@ -1,108 +1,429 @@ -#!/bin/bash +#!/usr/bin/perl -w # # Sign a module file using the given key. # -# Format: sign-file +# Format: # +# ./scripts/sign-file [-v][] +# +# +use strict; +use FileHandle; +use IPC::Open2; + +my $verbose = 0; +if ($#ARGV >= 0 && $ARGV[0] eq "-v") { +$verbose = 1; +shift; +} + +die "Format: ./scripts/sign-file [-v][]\n" +if ($#ARGV != 2 && $#ARGV != 3); + +my $private_key = $ARGV[0]; +my $x509 = $ARGV[1]; +my $module = $ARGV[2]; +my $dest = ($#ARGV == 3) ? $ARGV[3] : $ARGV[2] . "~"; + +die "Can't read private key\n" unless (-r $private_key); +die "Can't read X.509 certificate\n" unless (-r $x509); +die "Can't read module\n" unless (-r $module); + +# +# Read the kernel configuration +# +my %config = ( +CONFIG_MODULE_SIG_SHA512 => 1 +); + +if (-r ".config") { +open(FD, "<.config") || die ".config"; +while () { + if ($_ =~ /^(CONFIG_.*)=[ym]/) { + $config{$1} = 1; + } +} +close(FD); +} -scripts=`dirname $0` +# +# Function to read the contents of a file into a variable. +# +sub read_file($) +{ +my ($file) = @_; +my $contents; +my $len; + +open(FD, "<$file") || die $file; +binmode FD; +my @st = stat(FD); +die $file if (!@st); +$len = read(FD, $contents, $st[7]) || die $file; +close(FD) || die $file; +die "$file: Wanted length ", $st[7], ", got ", $len, "\n" + if ($len != $st[7]); +return $contents; +} + +### +# +# First of all, we have to parse the X.509 certificate to find certain details +# about it. +# +# We read the DER-encoded X509 certificate and parse it to extract the Subject +# name and Subject Key Identifier. Theis provides the data we need to build +# the certificate identifier. +# +# The signer's name part of the identifier is fabricated from the commonName, +# the organizationName or the emailAddress components of the X.509 subject +# name. +# +# The subject key ID is used to select which of that signer's certificates +# we're intending to use to sign the module. +# +### +my $x509_certificate = read_file($x509); -CONFIG_MODULE_SIG_SHA512=y -if [ -r .config ] -then -. ./.config -fi +my $UNIV = 0 << 6; +my $APPL = 1 << 6; +my $CONT = 2 << 6; +my $PRIV = 3 << 6; -key="$1" -x509="$2" -keyid_script="$3" -mod="$4" +my $CONS = 0x20; -if [ ! -r "$key" ] -then -echo "Can't read private key" >&2 -exit 2 -fi +my $BOOLEAN= 0x01; +my $INTEGER= 0x02; +my $BIT_STRING = 0x03; +my $OCTET_STRING = 0x04; +my $NULL = 0x05; +my $OBJ_ID = 0x06; +my $UTF8String = 0x0c; +my $SEQUENCE = 0x10; +my $SET= 0x11; +my $UTCTime= 0x17; +my $GeneralizedTime = 0x18; -if [ ! -r "$x509" ] -then -echo "Can't read X.509 certificate" >&2 -exit 2 -fi +my %OIDs = ( +pack("CCC", 85, 4, 3) => "commonName", +pack("CCC", 85, 4, 6) => "countryName", +pack("CCC", 85, 4, 10) => "organizationName", +pack("CCC", 85, 4, 11) => "organizationUnitName", +pack("C", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", +pack("C", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", +pack("C", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", +pack("CCC", 85, 29, 35)=> "authorityKeyIdentifier", +pack("CCC", 85, 29, 14)=> "subjectKeyIdentifier", +pack("CCC", 85, 29, 19)=> "basicConstraints" +); + +### +# +# Extract an ASN.1 element from a string and return information about it. +#
[PATCH 1/2] MODSIGN: perlify sign-file and merge in x509keyid [ver #3]
Turn sign-file into perl and merge in x509keyid. The latter doesn't need to be a separate script as it doesn't actually need to work out the SHA1 sum of the X.509 certificate itself, since it can get that from the X.509 certificate. Signed-off-by: David Howells dhowe...@redhat.com --- Makefile |2 scripts/sign-file | 477 - scripts/x509keyid | 268 -- 3 files changed, 400 insertions(+), 347 deletions(-) mode change 100644 = 100755 scripts/sign-file delete mode 100755 scripts/x509keyid diff --git a/Makefile b/Makefile index 4fd82f7..14b9874 100644 --- a/Makefile +++ b/Makefile @@ -723,7 +723,7 @@ ifeq ($(CONFIG_MODULE_SIG),y) MODSECKEY = ./signing_key.priv MODPUBKEY = ./signing_key.x509 export MODPUBKEY -mod_sign_cmd = sh $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY) $(srctree)/scripts/x509keyid +mod_sign_cmd = perl $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY) else mod_sign_cmd = true endif diff --git a/scripts/sign-file b/scripts/sign-file old mode 100644 new mode 100755 index d014abd..c8a2e7c --- a/scripts/sign-file +++ b/scripts/sign-file @@ -1,108 +1,429 @@ -#!/bin/bash +#!/usr/bin/perl -w # # Sign a module file using the given key. # -# Format: sign-file key x509 keyid-script module +# Format: # +# ./scripts/sign-file [-v] key x509 module [dest] +# +# +use strict; +use FileHandle; +use IPC::Open2; + +my $verbose = 0; +if ($#ARGV = 0 $ARGV[0] eq -v) { +$verbose = 1; +shift; +} + +die Format: ./scripts/sign-file [-v] key x509 module [dest]\n +if ($#ARGV != 2 $#ARGV != 3); + +my $private_key = $ARGV[0]; +my $x509 = $ARGV[1]; +my $module = $ARGV[2]; +my $dest = ($#ARGV == 3) ? $ARGV[3] : $ARGV[2] . ~; + +die Can't read private key\n unless (-r $private_key); +die Can't read X.509 certificate\n unless (-r $x509); +die Can't read module\n unless (-r $module); + +# +# Read the kernel configuration +# +my %config = ( +CONFIG_MODULE_SIG_SHA512 = 1 +); + +if (-r .config) { +open(FD, .config) || die .config; +while (FD) { + if ($_ =~ /^(CONFIG_.*)=[ym]/) { + $config{$1} = 1; + } +} +close(FD); +} -scripts=`dirname $0` +# +# Function to read the contents of a file into a variable. +# +sub read_file($) +{ +my ($file) = @_; +my $contents; +my $len; + +open(FD, $file) || die $file; +binmode FD; +my @st = stat(FD); +die $file if (!@st); +$len = read(FD, $contents, $st[7]) || die $file; +close(FD) || die $file; +die $file: Wanted length , $st[7], , got , $len, \n + if ($len != $st[7]); +return $contents; +} + +### +# +# First of all, we have to parse the X.509 certificate to find certain details +# about it. +# +# We read the DER-encoded X509 certificate and parse it to extract the Subject +# name and Subject Key Identifier. Theis provides the data we need to build +# the certificate identifier. +# +# The signer's name part of the identifier is fabricated from the commonName, +# the organizationName or the emailAddress components of the X.509 subject +# name. +# +# The subject key ID is used to select which of that signer's certificates +# we're intending to use to sign the module. +# +### +my $x509_certificate = read_file($x509); -CONFIG_MODULE_SIG_SHA512=y -if [ -r .config ] -then -. ./.config -fi +my $UNIV = 0 6; +my $APPL = 1 6; +my $CONT = 2 6; +my $PRIV = 3 6; -key=$1 -x509=$2 -keyid_script=$3 -mod=$4 +my $CONS = 0x20; -if [ ! -r $key ] -then -echo Can't read private key 2 -exit 2 -fi +my $BOOLEAN= 0x01; +my $INTEGER= 0x02; +my $BIT_STRING = 0x03; +my $OCTET_STRING = 0x04; +my $NULL = 0x05; +my $OBJ_ID = 0x06; +my $UTF8String = 0x0c; +my $SEQUENCE = 0x10; +my $SET= 0x11; +my $UTCTime= 0x17; +my $GeneralizedTime = 0x18; -if [ ! -r $x509 ] -then -echo Can't read X.509 certificate 2 -exit 2 -fi +my %OIDs = ( +pack(CCC, 85, 4, 3) = commonName, +pack(CCC, 85, 4, 6) = countryName, +pack(CCC, 85, 4, 10) = organizationName, +pack(CCC, 85, 4, 11) = organizationUnitName, +pack(C, 42, 134, 72, 134, 247, 13, 1, 1, 1) = rsaEncryption, +pack(C, 42, 134, 72, 134, 247, 13, 1, 1, 5) = sha1WithRSAEncryption, +pack(C, 42, 134, 72, 134, 247, 13, 1, 9, 1) = emailAddress, +pack(CCC, 85, 29, 35)= authorityKeyIdentifier, +pack(CCC, 85, 29, 14)= subjectKeyIdentifier, +pack(CCC, 85, 29, 19)= basicConstraints +); + +### +# +# Extract an ASN.1 element from a string and return information about it. +# +### +sub asn1_extract($$@) +{