xref: /OK3568_Linux_fs/kernel/scripts/extract-module-sig.pl (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/usr/bin/env perl
2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0
3*4882a593Smuzhiyun#
4*4882a593Smuzhiyun# extract-mod-sig <part> <module-file>
5*4882a593Smuzhiyun#
6*4882a593Smuzhiyun# Reads the module file and writes out some or all of the signature
7*4882a593Smuzhiyun# section to stdout.  Part is the bit to be written and is one of:
8*4882a593Smuzhiyun#
9*4882a593Smuzhiyun#  -0: The unsigned module, no signature data at all
10*4882a593Smuzhiyun#  -a: All of the signature data, including magic number
11*4882a593Smuzhiyun#  -d: Just the descriptor values as a sequence of numbers
12*4882a593Smuzhiyun#  -n: Just the signer's name
13*4882a593Smuzhiyun#  -k: Just the key ID
14*4882a593Smuzhiyun#  -s: Just the crypto signature or PKCS#7 message
15*4882a593Smuzhiyun#
16*4882a593Smuzhiyunuse warnings;
17*4882a593Smuzhiyunuse strict;
18*4882a593Smuzhiyun
19*4882a593Smuzhiyundie "Format: $0 -[0adnks] module-file >out\n"
20*4882a593Smuzhiyun    if ($#ARGV != 1);
21*4882a593Smuzhiyun
22*4882a593Smuzhiyunmy $part = $ARGV[0];
23*4882a593Smuzhiyunmy $modfile = $ARGV[1];
24*4882a593Smuzhiyun
25*4882a593Smuzhiyunmy $magic_number = "~Module signature appended~\n";
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun#
28*4882a593Smuzhiyun# Read the module contents
29*4882a593Smuzhiyun#
30*4882a593Smuzhiyunopen FD, "<$modfile" || die $modfile;
31*4882a593Smuzhiyunbinmode(FD);
32*4882a593Smuzhiyunmy @st = stat(FD);
33*4882a593Smuzhiyundie "$modfile" unless (@st);
34*4882a593Smuzhiyunmy $buf = "";
35*4882a593Smuzhiyunmy $len = sysread(FD, $buf, $st[7]);
36*4882a593Smuzhiyundie "$modfile" unless (defined($len));
37*4882a593Smuzhiyundie "Short read on $modfile\n" unless ($len == $st[7]);
38*4882a593Smuzhiyunclose(FD) || die $modfile;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyunprint STDERR "Read ", $len, " bytes from module file\n";
41*4882a593Smuzhiyun
42*4882a593Smuzhiyundie "The file is too short to have a sig magic number and descriptor\n"
43*4882a593Smuzhiyun    if ($len < 12 + length($magic_number));
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun#
46*4882a593Smuzhiyun# Check for the magic number and extract the information block
47*4882a593Smuzhiyun#
48*4882a593Smuzhiyunmy $p = $len - length($magic_number);
49*4882a593Smuzhiyunmy $raw_magic = substr($buf, $p);
50*4882a593Smuzhiyun
51*4882a593Smuzhiyundie "Magic number not found at $len\n"
52*4882a593Smuzhiyun    if ($raw_magic ne $magic_number);
53*4882a593Smuzhiyunprint STDERR "Found magic number at $len\n";
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun$p -= 12;
56*4882a593Smuzhiyunmy $raw_info = substr($buf, $p, 12);
57*4882a593Smuzhiyun
58*4882a593Smuzhiyunmy @info = unpack("CCCCCxxxN", $raw_info);
59*4882a593Smuzhiyunmy ($algo, $hash, $id_type, $name_len, $kid_len, $sig_len) = @info;
60*4882a593Smuzhiyun
61*4882a593Smuzhiyunif ($id_type == 0) {
62*4882a593Smuzhiyun    print STDERR "Found PGP key identifier\n";
63*4882a593Smuzhiyun} elsif ($id_type == 1) {
64*4882a593Smuzhiyun    print STDERR "Found X.509 cert identifier\n";
65*4882a593Smuzhiyun} elsif ($id_type == 2) {
66*4882a593Smuzhiyun    print STDERR "Found PKCS#7/CMS encapsulation\n";
67*4882a593Smuzhiyun} else {
68*4882a593Smuzhiyun    print STDERR "Found unsupported identifier type $id_type\n";
69*4882a593Smuzhiyun}
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun#
72*4882a593Smuzhiyun# Extract the three pieces of info data
73*4882a593Smuzhiyun#
74*4882a593Smuzhiyundie "Insufficient name+kid+sig data in file\n"
75*4882a593Smuzhiyun    unless ($p >= $name_len + $kid_len + $sig_len);
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun$p -= $sig_len;
78*4882a593Smuzhiyunmy $raw_sig = substr($buf, $p, $sig_len);
79*4882a593Smuzhiyun$p -= $kid_len;
80*4882a593Smuzhiyunmy $raw_kid = substr($buf, $p, $kid_len);
81*4882a593Smuzhiyun$p -= $name_len;
82*4882a593Smuzhiyunmy $raw_name = substr($buf, $p, $name_len);
83*4882a593Smuzhiyun
84*4882a593Smuzhiyunmy $module_len = $p;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyunif ($sig_len > 0) {
87*4882a593Smuzhiyun    print STDERR "Found $sig_len bytes of signature [";
88*4882a593Smuzhiyun    my $n = $sig_len > 16 ? 16 : $sig_len;
89*4882a593Smuzhiyun    foreach my $i (unpack("C" x $n, substr($raw_sig, 0, $n))) {
90*4882a593Smuzhiyun	printf STDERR "%02x", $i;
91*4882a593Smuzhiyun    }
92*4882a593Smuzhiyun    print STDERR "]\n";
93*4882a593Smuzhiyun}
94*4882a593Smuzhiyun
95*4882a593Smuzhiyunif ($kid_len > 0) {
96*4882a593Smuzhiyun    print STDERR "Found $kid_len bytes of key identifier [";
97*4882a593Smuzhiyun    my $n = $kid_len > 16 ? 16 : $kid_len;
98*4882a593Smuzhiyun    foreach my $i (unpack("C" x $n, substr($raw_kid, 0, $n))) {
99*4882a593Smuzhiyun	printf STDERR "%02x", $i;
100*4882a593Smuzhiyun    }
101*4882a593Smuzhiyun    print STDERR "]\n";
102*4882a593Smuzhiyun}
103*4882a593Smuzhiyun
104*4882a593Smuzhiyunif ($name_len > 0) {
105*4882a593Smuzhiyun    print STDERR "Found $name_len bytes of signer's name [$raw_name]\n";
106*4882a593Smuzhiyun}
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun#
109*4882a593Smuzhiyun# Produce the requested output
110*4882a593Smuzhiyun#
111*4882a593Smuzhiyunif ($part eq "-0") {
112*4882a593Smuzhiyun    # The unsigned module, no signature data at all
113*4882a593Smuzhiyun    binmode(STDOUT);
114*4882a593Smuzhiyun    print substr($buf, 0, $module_len);
115*4882a593Smuzhiyun} elsif ($part eq "-a") {
116*4882a593Smuzhiyun    # All of the signature data, including magic number
117*4882a593Smuzhiyun    binmode(STDOUT);
118*4882a593Smuzhiyun    print substr($buf, $module_len);
119*4882a593Smuzhiyun} elsif ($part eq "-d") {
120*4882a593Smuzhiyun    # Just the descriptor values as a sequence of numbers
121*4882a593Smuzhiyun    print join(" ", @info), "\n";
122*4882a593Smuzhiyun} elsif ($part eq "-n") {
123*4882a593Smuzhiyun    # Just the signer's name
124*4882a593Smuzhiyun    print STDERR "No signer's name for PKCS#7 message type sig\n"
125*4882a593Smuzhiyun	if ($id_type == 2);
126*4882a593Smuzhiyun    binmode(STDOUT);
127*4882a593Smuzhiyun    print $raw_name;
128*4882a593Smuzhiyun} elsif ($part eq "-k") {
129*4882a593Smuzhiyun    # Just the key identifier
130*4882a593Smuzhiyun    print STDERR "No key ID for PKCS#7 message type sig\n"
131*4882a593Smuzhiyun	if ($id_type == 2);
132*4882a593Smuzhiyun    binmode(STDOUT);
133*4882a593Smuzhiyun    print $raw_kid;
134*4882a593Smuzhiyun} elsif ($part eq "-s") {
135*4882a593Smuzhiyun    # Just the crypto signature or PKCS#7 message
136*4882a593Smuzhiyun    binmode(STDOUT);
137*4882a593Smuzhiyun    print $raw_sig;
138*4882a593Smuzhiyun}
139