1cb77f0d6SKamil Rytarowski#!/usr/bin/env perl 2*b2441318SGreg Kroah-Hartman# SPDX-License-Identifier: GPL-2.0 34adc605eSDavid Howells# 44adc605eSDavid Howells# extract-mod-sig <part> <module-file> 54adc605eSDavid Howells# 64adc605eSDavid Howells# Reads the module file and writes out some or all of the signature 74adc605eSDavid Howells# section to stdout. Part is the bit to be written and is one of: 84adc605eSDavid Howells# 94adc605eSDavid Howells# -0: The unsigned module, no signature data at all 104adc605eSDavid Howells# -a: All of the signature data, including magic number 114adc605eSDavid Howells# -d: Just the descriptor values as a sequence of numbers 124adc605eSDavid Howells# -n: Just the signer's name 134adc605eSDavid Howells# -k: Just the key ID 144adc605eSDavid Howells# -s: Just the crypto signature or PKCS#7 message 154adc605eSDavid Howells# 16cb77f0d6SKamil Rytarowskiuse warnings; 174adc605eSDavid Howellsuse strict; 184adc605eSDavid Howells 194adc605eSDavid Howellsdie "Format: $0 -[0adnks] module-file >out\n" 204adc605eSDavid Howells if ($#ARGV != 1); 214adc605eSDavid Howells 224adc605eSDavid Howellsmy $part = $ARGV[0]; 234adc605eSDavid Howellsmy $modfile = $ARGV[1]; 244adc605eSDavid Howells 254adc605eSDavid Howellsmy $magic_number = "~Module signature appended~\n"; 264adc605eSDavid Howells 274adc605eSDavid Howells# 284adc605eSDavid Howells# Read the module contents 294adc605eSDavid Howells# 304adc605eSDavid Howellsopen FD, "<$modfile" || die $modfile; 314adc605eSDavid Howellsbinmode(FD); 324adc605eSDavid Howellsmy @st = stat(FD); 334adc605eSDavid Howellsdie "$modfile" unless (@st); 344adc605eSDavid Howellsmy $buf = ""; 354adc605eSDavid Howellsmy $len = sysread(FD, $buf, $st[7]); 364adc605eSDavid Howellsdie "$modfile" unless (defined($len)); 374adc605eSDavid Howellsdie "Short read on $modfile\n" unless ($len == $st[7]); 384adc605eSDavid Howellsclose(FD) || die $modfile; 394adc605eSDavid Howells 404adc605eSDavid Howellsprint STDERR "Read ", $len, " bytes from module file\n"; 414adc605eSDavid Howells 424adc605eSDavid Howellsdie "The file is too short to have a sig magic number and descriptor\n" 434adc605eSDavid Howells if ($len < 12 + length($magic_number)); 444adc605eSDavid Howells 454adc605eSDavid Howells# 464adc605eSDavid Howells# Check for the magic number and extract the information block 474adc605eSDavid Howells# 484adc605eSDavid Howellsmy $p = $len - length($magic_number); 494adc605eSDavid Howellsmy $raw_magic = substr($buf, $p); 504adc605eSDavid Howells 514adc605eSDavid Howellsdie "Magic number not found at $len\n" 524adc605eSDavid Howells if ($raw_magic ne $magic_number); 534adc605eSDavid Howellsprint STDERR "Found magic number at $len\n"; 544adc605eSDavid Howells 554adc605eSDavid Howells$p -= 12; 564adc605eSDavid Howellsmy $raw_info = substr($buf, $p, 12); 574adc605eSDavid Howells 584adc605eSDavid Howellsmy @info = unpack("CCCCCxxxN", $raw_info); 594adc605eSDavid Howellsmy ($algo, $hash, $id_type, $name_len, $kid_len, $sig_len) = @info; 604adc605eSDavid Howells 614adc605eSDavid Howellsif ($id_type == 0) { 624adc605eSDavid Howells print STDERR "Found PGP key identifier\n"; 634adc605eSDavid Howells} elsif ($id_type == 1) { 644adc605eSDavid Howells print STDERR "Found X.509 cert identifier\n"; 654adc605eSDavid Howells} elsif ($id_type == 2) { 664adc605eSDavid Howells print STDERR "Found PKCS#7/CMS encapsulation\n"; 674adc605eSDavid Howells} else { 684adc605eSDavid Howells print STDERR "Found unsupported identifier type $id_type\n"; 694adc605eSDavid Howells} 704adc605eSDavid Howells 714adc605eSDavid Howells# 724adc605eSDavid Howells# Extract the three pieces of info data 734adc605eSDavid Howells# 744adc605eSDavid Howellsdie "Insufficient name+kid+sig data in file\n" 754adc605eSDavid Howells unless ($p >= $name_len + $kid_len + $sig_len); 764adc605eSDavid Howells 774adc605eSDavid Howells$p -= $sig_len; 784adc605eSDavid Howellsmy $raw_sig = substr($buf, $p, $sig_len); 794adc605eSDavid Howells$p -= $kid_len; 804adc605eSDavid Howellsmy $raw_kid = substr($buf, $p, $kid_len); 814adc605eSDavid Howells$p -= $name_len; 824adc605eSDavid Howellsmy $raw_name = substr($buf, $p, $name_len); 834adc605eSDavid Howells 844adc605eSDavid Howellsmy $module_len = $p; 854adc605eSDavid Howells 864adc605eSDavid Howellsif ($sig_len > 0) { 874adc605eSDavid Howells print STDERR "Found $sig_len bytes of signature ["; 884adc605eSDavid Howells my $n = $sig_len > 16 ? 16 : $sig_len; 894adc605eSDavid Howells foreach my $i (unpack("C" x $n, substr($raw_sig, 0, $n))) { 904adc605eSDavid Howells printf STDERR "%02x", $i; 914adc605eSDavid Howells } 924adc605eSDavid Howells print STDERR "]\n"; 934adc605eSDavid Howells} 944adc605eSDavid Howells 954adc605eSDavid Howellsif ($kid_len > 0) { 964adc605eSDavid Howells print STDERR "Found $kid_len bytes of key identifier ["; 974adc605eSDavid Howells my $n = $kid_len > 16 ? 16 : $kid_len; 984adc605eSDavid Howells foreach my $i (unpack("C" x $n, substr($raw_kid, 0, $n))) { 994adc605eSDavid Howells printf STDERR "%02x", $i; 1004adc605eSDavid Howells } 1014adc605eSDavid Howells print STDERR "]\n"; 1024adc605eSDavid Howells} 1034adc605eSDavid Howells 1044adc605eSDavid Howellsif ($name_len > 0) { 1054adc605eSDavid Howells print STDERR "Found $name_len bytes of signer's name [$raw_name]\n"; 1064adc605eSDavid Howells} 1074adc605eSDavid Howells 1084adc605eSDavid Howells# 1094adc605eSDavid Howells# Produce the requested output 1104adc605eSDavid Howells# 1114adc605eSDavid Howellsif ($part eq "-0") { 1124adc605eSDavid Howells # The unsigned module, no signature data at all 1134adc605eSDavid Howells binmode(STDOUT); 1144adc605eSDavid Howells print substr($buf, 0, $module_len); 1154adc605eSDavid Howells} elsif ($part eq "-a") { 1164adc605eSDavid Howells # All of the signature data, including magic number 1174adc605eSDavid Howells binmode(STDOUT); 1184adc605eSDavid Howells print substr($buf, $module_len); 1194adc605eSDavid Howells} elsif ($part eq "-d") { 1204adc605eSDavid Howells # Just the descriptor values as a sequence of numbers 1214adc605eSDavid Howells print join(" ", @info), "\n"; 1224adc605eSDavid Howells} elsif ($part eq "-n") { 1234adc605eSDavid Howells # Just the signer's name 1244adc605eSDavid Howells print STDERR "No signer's name for PKCS#7 message type sig\n" 1254adc605eSDavid Howells if ($id_type == 2); 1264adc605eSDavid Howells binmode(STDOUT); 1274adc605eSDavid Howells print $raw_name; 1284adc605eSDavid Howells} elsif ($part eq "-k") { 1294adc605eSDavid Howells # Just the key identifier 1304adc605eSDavid Howells print STDERR "No key ID for PKCS#7 message type sig\n" 1314adc605eSDavid Howells if ($id_type == 2); 1324adc605eSDavid Howells binmode(STDOUT); 1334adc605eSDavid Howells print $raw_kid; 1344adc605eSDavid Howells} elsif ($part eq "-s") { 1354adc605eSDavid Howells # Just the crypto signature or PKCS#7 message 1364adc605eSDavid Howells binmode(STDOUT); 1374adc605eSDavid Howells print $raw_sig; 1384adc605eSDavid Howells} 139