162306a36Sopenharmony_ci#!/usr/bin/env perl 262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 362306a36Sopenharmony_ci# 462306a36Sopenharmony_ci# extract-mod-sig <part> <module-file> 562306a36Sopenharmony_ci# 662306a36Sopenharmony_ci# Reads the module file and writes out some or all of the signature 762306a36Sopenharmony_ci# section to stdout. Part is the bit to be written and is one of: 862306a36Sopenharmony_ci# 962306a36Sopenharmony_ci# -0: The unsigned module, no signature data at all 1062306a36Sopenharmony_ci# -a: All of the signature data, including magic number 1162306a36Sopenharmony_ci# -d: Just the descriptor values as a sequence of numbers 1262306a36Sopenharmony_ci# -n: Just the signer's name 1362306a36Sopenharmony_ci# -k: Just the key ID 1462306a36Sopenharmony_ci# -s: Just the crypto signature or PKCS#7 message 1562306a36Sopenharmony_ci# 1662306a36Sopenharmony_ciuse warnings; 1762306a36Sopenharmony_ciuse strict; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cidie "Format: $0 -[0adnks] module-file >out\n" 2062306a36Sopenharmony_ci if ($#ARGV != 1); 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cimy $part = $ARGV[0]; 2362306a36Sopenharmony_cimy $modfile = $ARGV[1]; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cimy $magic_number = "~Module signature appended~\n"; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci# 2862306a36Sopenharmony_ci# Read the module contents 2962306a36Sopenharmony_ci# 3062306a36Sopenharmony_ciopen FD, "<$modfile" || die $modfile; 3162306a36Sopenharmony_cibinmode(FD); 3262306a36Sopenharmony_cimy @st = stat(FD); 3362306a36Sopenharmony_cidie "$modfile" unless (@st); 3462306a36Sopenharmony_cimy $buf = ""; 3562306a36Sopenharmony_cimy $len = sysread(FD, $buf, $st[7]); 3662306a36Sopenharmony_cidie "$modfile" unless (defined($len)); 3762306a36Sopenharmony_cidie "Short read on $modfile\n" unless ($len == $st[7]); 3862306a36Sopenharmony_ciclose(FD) || die $modfile; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ciprint STDERR "Read ", $len, " bytes from module file\n"; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cidie "The file is too short to have a sig magic number and descriptor\n" 4362306a36Sopenharmony_ci if ($len < 12 + length($magic_number)); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci# 4662306a36Sopenharmony_ci# Check for the magic number and extract the information block 4762306a36Sopenharmony_ci# 4862306a36Sopenharmony_cimy $p = $len - length($magic_number); 4962306a36Sopenharmony_cimy $raw_magic = substr($buf, $p); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cidie "Magic number not found at $len\n" 5262306a36Sopenharmony_ci if ($raw_magic ne $magic_number); 5362306a36Sopenharmony_ciprint STDERR "Found magic number at $len\n"; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci$p -= 12; 5662306a36Sopenharmony_cimy $raw_info = substr($buf, $p, 12); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cimy @info = unpack("CCCCCxxxN", $raw_info); 5962306a36Sopenharmony_cimy ($algo, $hash, $id_type, $name_len, $kid_len, $sig_len) = @info; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ciif ($id_type == 0) { 6262306a36Sopenharmony_ci print STDERR "Found PGP key identifier\n"; 6362306a36Sopenharmony_ci} elsif ($id_type == 1) { 6462306a36Sopenharmony_ci print STDERR "Found X.509 cert identifier\n"; 6562306a36Sopenharmony_ci} elsif ($id_type == 2) { 6662306a36Sopenharmony_ci print STDERR "Found PKCS#7/CMS encapsulation\n"; 6762306a36Sopenharmony_ci} else { 6862306a36Sopenharmony_ci print STDERR "Found unsupported identifier type $id_type\n"; 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci# 7262306a36Sopenharmony_ci# Extract the three pieces of info data 7362306a36Sopenharmony_ci# 7462306a36Sopenharmony_cidie "Insufficient name+kid+sig data in file\n" 7562306a36Sopenharmony_ci unless ($p >= $name_len + $kid_len + $sig_len); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci$p -= $sig_len; 7862306a36Sopenharmony_cimy $raw_sig = substr($buf, $p, $sig_len); 7962306a36Sopenharmony_ci$p -= $kid_len; 8062306a36Sopenharmony_cimy $raw_kid = substr($buf, $p, $kid_len); 8162306a36Sopenharmony_ci$p -= $name_len; 8262306a36Sopenharmony_cimy $raw_name = substr($buf, $p, $name_len); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cimy $module_len = $p; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ciif ($sig_len > 0) { 8762306a36Sopenharmony_ci print STDERR "Found $sig_len bytes of signature ["; 8862306a36Sopenharmony_ci my $n = $sig_len > 16 ? 16 : $sig_len; 8962306a36Sopenharmony_ci foreach my $i (unpack("C" x $n, substr($raw_sig, 0, $n))) { 9062306a36Sopenharmony_ci printf STDERR "%02x", $i; 9162306a36Sopenharmony_ci } 9262306a36Sopenharmony_ci print STDERR "]\n"; 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ciif ($kid_len > 0) { 9662306a36Sopenharmony_ci print STDERR "Found $kid_len bytes of key identifier ["; 9762306a36Sopenharmony_ci my $n = $kid_len > 16 ? 16 : $kid_len; 9862306a36Sopenharmony_ci foreach my $i (unpack("C" x $n, substr($raw_kid, 0, $n))) { 9962306a36Sopenharmony_ci printf STDERR "%02x", $i; 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci print STDERR "]\n"; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ciif ($name_len > 0) { 10562306a36Sopenharmony_ci print STDERR "Found $name_len bytes of signer's name [$raw_name]\n"; 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci# 10962306a36Sopenharmony_ci# Produce the requested output 11062306a36Sopenharmony_ci# 11162306a36Sopenharmony_ciif ($part eq "-0") { 11262306a36Sopenharmony_ci # The unsigned module, no signature data at all 11362306a36Sopenharmony_ci binmode(STDOUT); 11462306a36Sopenharmony_ci print substr($buf, 0, $module_len); 11562306a36Sopenharmony_ci} elsif ($part eq "-a") { 11662306a36Sopenharmony_ci # All of the signature data, including magic number 11762306a36Sopenharmony_ci binmode(STDOUT); 11862306a36Sopenharmony_ci print substr($buf, $module_len); 11962306a36Sopenharmony_ci} elsif ($part eq "-d") { 12062306a36Sopenharmony_ci # Just the descriptor values as a sequence of numbers 12162306a36Sopenharmony_ci print join(" ", @info), "\n"; 12262306a36Sopenharmony_ci} elsif ($part eq "-n") { 12362306a36Sopenharmony_ci # Just the signer's name 12462306a36Sopenharmony_ci print STDERR "No signer's name for PKCS#7 message type sig\n" 12562306a36Sopenharmony_ci if ($id_type == 2); 12662306a36Sopenharmony_ci binmode(STDOUT); 12762306a36Sopenharmony_ci print $raw_name; 12862306a36Sopenharmony_ci} elsif ($part eq "-k") { 12962306a36Sopenharmony_ci # Just the key identifier 13062306a36Sopenharmony_ci print STDERR "No key ID for PKCS#7 message type sig\n" 13162306a36Sopenharmony_ci if ($id_type == 2); 13262306a36Sopenharmony_ci binmode(STDOUT); 13362306a36Sopenharmony_ci print $raw_kid; 13462306a36Sopenharmony_ci} elsif ($part eq "-s") { 13562306a36Sopenharmony_ci # Just the crypto signature or PKCS#7 message 13662306a36Sopenharmony_ci binmode(STDOUT); 13762306a36Sopenharmony_ci print $raw_sig; 13862306a36Sopenharmony_ci} 139