[PATCH 1/2] MODSIGN: perlify sign-file and merge in x509keyid [ver #3]

2012-10-19 Thread David Howells
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]

2012-10-19 Thread David Howells
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($$@)
+{