18c2ecf20Sopenharmony_ci#!/usr/bin/env perl 28c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 38c2ecf20Sopenharmony_ci# 48c2ecf20Sopenharmony_ci# extract-mod-sig <part> <module-file> 58c2ecf20Sopenharmony_ci# 68c2ecf20Sopenharmony_ci# Reads the module file and writes out some or all of the signature 78c2ecf20Sopenharmony_ci# section to stdout. Part is the bit to be written and is one of: 88c2ecf20Sopenharmony_ci# 98c2ecf20Sopenharmony_ci# -0: The unsigned module, no signature data at all 108c2ecf20Sopenharmony_ci# -a: All of the signature data, including magic number 118c2ecf20Sopenharmony_ci# -d: Just the descriptor values as a sequence of numbers 128c2ecf20Sopenharmony_ci# -n: Just the signer's name 138c2ecf20Sopenharmony_ci# -k: Just the key ID 148c2ecf20Sopenharmony_ci# -s: Just the crypto signature or PKCS#7 message 158c2ecf20Sopenharmony_ci# 168c2ecf20Sopenharmony_ciuse warnings; 178c2ecf20Sopenharmony_ciuse strict; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cidie "Format: $0 -[0adnks] module-file >out\n" 208c2ecf20Sopenharmony_ci if ($#ARGV != 1); 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cimy $part = $ARGV[0]; 238c2ecf20Sopenharmony_cimy $modfile = $ARGV[1]; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cimy $magic_number = "~Module signature appended~\n"; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci# 288c2ecf20Sopenharmony_ci# Read the module contents 298c2ecf20Sopenharmony_ci# 308c2ecf20Sopenharmony_ciopen FD, "<$modfile" || die $modfile; 318c2ecf20Sopenharmony_cibinmode(FD); 328c2ecf20Sopenharmony_cimy @st = stat(FD); 338c2ecf20Sopenharmony_cidie "$modfile" unless (@st); 348c2ecf20Sopenharmony_cimy $buf = ""; 358c2ecf20Sopenharmony_cimy $len = sysread(FD, $buf, $st[7]); 368c2ecf20Sopenharmony_cidie "$modfile" unless (defined($len)); 378c2ecf20Sopenharmony_cidie "Short read on $modfile\n" unless ($len == $st[7]); 388c2ecf20Sopenharmony_ciclose(FD) || die $modfile; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ciprint STDERR "Read ", $len, " bytes from module file\n"; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cidie "The file is too short to have a sig magic number and descriptor\n" 438c2ecf20Sopenharmony_ci if ($len < 12 + length($magic_number)); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci# 468c2ecf20Sopenharmony_ci# Check for the magic number and extract the information block 478c2ecf20Sopenharmony_ci# 488c2ecf20Sopenharmony_cimy $p = $len - length($magic_number); 498c2ecf20Sopenharmony_cimy $raw_magic = substr($buf, $p); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cidie "Magic number not found at $len\n" 528c2ecf20Sopenharmony_ci if ($raw_magic ne $magic_number); 538c2ecf20Sopenharmony_ciprint STDERR "Found magic number at $len\n"; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci$p -= 12; 568c2ecf20Sopenharmony_cimy $raw_info = substr($buf, $p, 12); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cimy @info = unpack("CCCCCxxxN", $raw_info); 598c2ecf20Sopenharmony_cimy ($algo, $hash, $id_type, $name_len, $kid_len, $sig_len) = @info; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ciif ($id_type == 0) { 628c2ecf20Sopenharmony_ci print STDERR "Found PGP key identifier\n"; 638c2ecf20Sopenharmony_ci} elsif ($id_type == 1) { 648c2ecf20Sopenharmony_ci print STDERR "Found X.509 cert identifier\n"; 658c2ecf20Sopenharmony_ci} elsif ($id_type == 2) { 668c2ecf20Sopenharmony_ci print STDERR "Found PKCS#7/CMS encapsulation\n"; 678c2ecf20Sopenharmony_ci} else { 688c2ecf20Sopenharmony_ci print STDERR "Found unsupported identifier type $id_type\n"; 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci# 728c2ecf20Sopenharmony_ci# Extract the three pieces of info data 738c2ecf20Sopenharmony_ci# 748c2ecf20Sopenharmony_cidie "Insufficient name+kid+sig data in file\n" 758c2ecf20Sopenharmony_ci unless ($p >= $name_len + $kid_len + $sig_len); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci$p -= $sig_len; 788c2ecf20Sopenharmony_cimy $raw_sig = substr($buf, $p, $sig_len); 798c2ecf20Sopenharmony_ci$p -= $kid_len; 808c2ecf20Sopenharmony_cimy $raw_kid = substr($buf, $p, $kid_len); 818c2ecf20Sopenharmony_ci$p -= $name_len; 828c2ecf20Sopenharmony_cimy $raw_name = substr($buf, $p, $name_len); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cimy $module_len = $p; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ciif ($sig_len > 0) { 878c2ecf20Sopenharmony_ci print STDERR "Found $sig_len bytes of signature ["; 888c2ecf20Sopenharmony_ci my $n = $sig_len > 16 ? 16 : $sig_len; 898c2ecf20Sopenharmony_ci foreach my $i (unpack("C" x $n, substr($raw_sig, 0, $n))) { 908c2ecf20Sopenharmony_ci printf STDERR "%02x", $i; 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci print STDERR "]\n"; 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ciif ($kid_len > 0) { 968c2ecf20Sopenharmony_ci print STDERR "Found $kid_len bytes of key identifier ["; 978c2ecf20Sopenharmony_ci my $n = $kid_len > 16 ? 16 : $kid_len; 988c2ecf20Sopenharmony_ci foreach my $i (unpack("C" x $n, substr($raw_kid, 0, $n))) { 998c2ecf20Sopenharmony_ci printf STDERR "%02x", $i; 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci print STDERR "]\n"; 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ciif ($name_len > 0) { 1058c2ecf20Sopenharmony_ci print STDERR "Found $name_len bytes of signer's name [$raw_name]\n"; 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci# 1098c2ecf20Sopenharmony_ci# Produce the requested output 1108c2ecf20Sopenharmony_ci# 1118c2ecf20Sopenharmony_ciif ($part eq "-0") { 1128c2ecf20Sopenharmony_ci # The unsigned module, no signature data at all 1138c2ecf20Sopenharmony_ci binmode(STDOUT); 1148c2ecf20Sopenharmony_ci print substr($buf, 0, $module_len); 1158c2ecf20Sopenharmony_ci} elsif ($part eq "-a") { 1168c2ecf20Sopenharmony_ci # All of the signature data, including magic number 1178c2ecf20Sopenharmony_ci binmode(STDOUT); 1188c2ecf20Sopenharmony_ci print substr($buf, $module_len); 1198c2ecf20Sopenharmony_ci} elsif ($part eq "-d") { 1208c2ecf20Sopenharmony_ci # Just the descriptor values as a sequence of numbers 1218c2ecf20Sopenharmony_ci print join(" ", @info), "\n"; 1228c2ecf20Sopenharmony_ci} elsif ($part eq "-n") { 1238c2ecf20Sopenharmony_ci # Just the signer's name 1248c2ecf20Sopenharmony_ci print STDERR "No signer's name for PKCS#7 message type sig\n" 1258c2ecf20Sopenharmony_ci if ($id_type == 2); 1268c2ecf20Sopenharmony_ci binmode(STDOUT); 1278c2ecf20Sopenharmony_ci print $raw_name; 1288c2ecf20Sopenharmony_ci} elsif ($part eq "-k") { 1298c2ecf20Sopenharmony_ci # Just the key identifier 1308c2ecf20Sopenharmony_ci print STDERR "No key ID for PKCS#7 message type sig\n" 1318c2ecf20Sopenharmony_ci if ($id_type == 2); 1328c2ecf20Sopenharmony_ci binmode(STDOUT); 1338c2ecf20Sopenharmony_ci print $raw_kid; 1348c2ecf20Sopenharmony_ci} elsif ($part eq "-s") { 1358c2ecf20Sopenharmony_ci # Just the crypto signature or PKCS#7 message 1368c2ecf20Sopenharmony_ci binmode(STDOUT); 1378c2ecf20Sopenharmony_ci print $raw_sig; 1388c2ecf20Sopenharmony_ci} 139