diff options
author | James Morris <james.l.morris@oracle.com> | 2015-10-22 21:07:52 -0400 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2015-10-22 21:07:52 -0400 |
commit | ba94c3ff20c9c179f2a80f0e4c71e1571ebbf5c7 (patch) | |
tree | 8f94d0fcb68cdcff0d00a7911ddb494705cf7c72 /scripts | |
parent | a47c7a6c8aff0563c0ef4adf299268f3c27af0f6 (diff) | |
parent | 146aa8b1453bd8f1ff2304ffb71b4ee0eb9acdcc (diff) |
Merge tag 'keys-next-20151021' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs into next
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/extract-module-sig.pl | 136 | ||||
-rwxr-xr-x | scripts/extract-sys-certs.pl | 144 |
2 files changed, 280 insertions, 0 deletions
diff --git a/scripts/extract-module-sig.pl b/scripts/extract-module-sig.pl new file mode 100755 index 000000000000..faac6f2e377f --- /dev/null +++ b/scripts/extract-module-sig.pl | |||
@@ -0,0 +1,136 @@ | |||
1 | #!/usr/bin/perl -w | ||
2 | # | ||
3 | # extract-mod-sig <part> <module-file> | ||
4 | # | ||
5 | # Reads the module file and writes out some or all of the signature | ||
6 | # section to stdout. Part is the bit to be written and is one of: | ||
7 | # | ||
8 | # -0: The unsigned module, no signature data at all | ||
9 | # -a: All of the signature data, including magic number | ||
10 | # -d: Just the descriptor values as a sequence of numbers | ||
11 | # -n: Just the signer's name | ||
12 | # -k: Just the key ID | ||
13 | # -s: Just the crypto signature or PKCS#7 message | ||
14 | # | ||
15 | use strict; | ||
16 | |||
17 | die "Format: $0 -[0adnks] module-file >out\n" | ||
18 | if ($#ARGV != 1); | ||
19 | |||
20 | my $part = $ARGV[0]; | ||
21 | my $modfile = $ARGV[1]; | ||
22 | |||
23 | my $magic_number = "~Module signature appended~\n"; | ||
24 | |||
25 | # | ||
26 | # Read the module contents | ||
27 | # | ||
28 | open FD, "<$modfile" || die $modfile; | ||
29 | binmode(FD); | ||
30 | my @st = stat(FD); | ||
31 | die "$modfile" unless (@st); | ||
32 | my $buf = ""; | ||
33 | my $len = sysread(FD, $buf, $st[7]); | ||
34 | die "$modfile" unless (defined($len)); | ||
35 | die "Short read on $modfile\n" unless ($len == $st[7]); | ||
36 | close(FD) || die $modfile; | ||
37 | |||
38 | print STDERR "Read ", $len, " bytes from module file\n"; | ||
39 | |||
40 | die "The file is too short to have a sig magic number and descriptor\n" | ||
41 | if ($len < 12 + length($magic_number)); | ||
42 | |||
43 | # | ||
44 | # Check for the magic number and extract the information block | ||
45 | # | ||
46 | my $p = $len - length($magic_number); | ||
47 | my $raw_magic = substr($buf, $p); | ||
48 | |||
49 | die "Magic number not found at $len\n" | ||
50 | if ($raw_magic ne $magic_number); | ||
51 | print STDERR "Found magic number at $len\n"; | ||
52 | |||
53 | $p -= 12; | ||
54 | my $raw_info = substr($buf, $p, 12); | ||
55 | |||
56 | my @info = unpack("CCCCCxxxN", $raw_info); | ||
57 | my ($algo, $hash, $id_type, $name_len, $kid_len, $sig_len) = @info; | ||
58 | |||
59 | if ($id_type == 0) { | ||
60 | print STDERR "Found PGP key identifier\n"; | ||
61 | } elsif ($id_type == 1) { | ||
62 | print STDERR "Found X.509 cert identifier\n"; | ||
63 | } elsif ($id_type == 2) { | ||
64 | print STDERR "Found PKCS#7/CMS encapsulation\n"; | ||
65 | } else { | ||
66 | print STDERR "Found unsupported identifier type $id_type\n"; | ||
67 | } | ||
68 | |||
69 | # | ||
70 | # Extract the three pieces of info data | ||
71 | # | ||
72 | die "Insufficient name+kid+sig data in file\n" | ||
73 | unless ($p >= $name_len + $kid_len + $sig_len); | ||
74 | |||
75 | $p -= $sig_len; | ||
76 | my $raw_sig = substr($buf, $p, $sig_len); | ||
77 | $p -= $kid_len; | ||
78 | my $raw_kid = substr($buf, $p, $kid_len); | ||
79 | $p -= $name_len; | ||
80 | my $raw_name = substr($buf, $p, $name_len); | ||
81 | |||
82 | my $module_len = $p; | ||
83 | |||
84 | if ($sig_len > 0) { | ||
85 | print STDERR "Found $sig_len bytes of signature ["; | ||
86 | my $n = $sig_len > 16 ? 16 : $sig_len; | ||
87 | foreach my $i (unpack("C" x $n, substr($raw_sig, 0, $n))) { | ||
88 | printf STDERR "%02x", $i; | ||
89 | } | ||
90 | print STDERR "]\n"; | ||
91 | } | ||
92 | |||
93 | if ($kid_len > 0) { | ||
94 | print STDERR "Found $kid_len bytes of key identifier ["; | ||
95 | my $n = $kid_len > 16 ? 16 : $kid_len; | ||
96 | foreach my $i (unpack("C" x $n, substr($raw_kid, 0, $n))) { | ||
97 | printf STDERR "%02x", $i; | ||
98 | } | ||
99 | print STDERR "]\n"; | ||
100 | } | ||
101 | |||
102 | if ($name_len > 0) { | ||
103 | print STDERR "Found $name_len bytes of signer's name [$raw_name]\n"; | ||
104 | } | ||
105 | |||
106 | # | ||
107 | # Produce the requested output | ||
108 | # | ||
109 | if ($part eq "-0") { | ||
110 | # The unsigned module, no signature data at all | ||
111 | binmode(STDOUT); | ||
112 | print substr($buf, 0, $module_len); | ||
113 | } elsif ($part eq "-a") { | ||
114 | # All of the signature data, including magic number | ||
115 | binmode(STDOUT); | ||
116 | print substr($buf, $module_len); | ||
117 | } elsif ($part eq "-d") { | ||
118 | # Just the descriptor values as a sequence of numbers | ||
119 | print join(" ", @info), "\n"; | ||
120 | } elsif ($part eq "-n") { | ||
121 | # Just the signer's name | ||
122 | print STDERR "No signer's name for PKCS#7 message type sig\n" | ||
123 | if ($id_type == 2); | ||
124 | binmode(STDOUT); | ||
125 | print $raw_name; | ||
126 | } elsif ($part eq "-k") { | ||
127 | # Just the key identifier | ||
128 | print STDERR "No key ID for PKCS#7 message type sig\n" | ||
129 | if ($id_type == 2); | ||
130 | binmode(STDOUT); | ||
131 | print $raw_kid; | ||
132 | } elsif ($part eq "-s") { | ||
133 | # Just the crypto signature or PKCS#7 message | ||
134 | binmode(STDOUT); | ||
135 | print $raw_sig; | ||
136 | } | ||
diff --git a/scripts/extract-sys-certs.pl b/scripts/extract-sys-certs.pl new file mode 100755 index 000000000000..d476e7d1fd88 --- /dev/null +++ b/scripts/extract-sys-certs.pl | |||
@@ -0,0 +1,144 @@ | |||
1 | #!/usr/bin/perl -w | ||
2 | # | ||
3 | use strict; | ||
4 | use Math::BigInt; | ||
5 | use Fcntl "SEEK_SET"; | ||
6 | |||
7 | die "Format: $0 [-s <systemmap-file>] <vmlinux-file> <keyring-file>\n" | ||
8 | if ($#ARGV != 1 && $#ARGV != 3 || | ||
9 | $#ARGV == 3 && $ARGV[0] ne "-s"); | ||
10 | |||
11 | my $sysmap = ""; | ||
12 | if ($#ARGV == 3) { | ||
13 | shift; | ||
14 | $sysmap = $ARGV[0]; | ||
15 | shift; | ||
16 | } | ||
17 | |||
18 | my $vmlinux = $ARGV[0]; | ||
19 | my $keyring = $ARGV[1]; | ||
20 | |||
21 | # | ||
22 | # Parse the vmlinux section table | ||
23 | # | ||
24 | open FD, "objdump -h $vmlinux |" || die $vmlinux; | ||
25 | my @lines = <FD>; | ||
26 | close(FD) || die $vmlinux; | ||
27 | |||
28 | my @sections = (); | ||
29 | |||
30 | foreach my $line (@lines) { | ||
31 | chomp($line); | ||
32 | if ($line =~ /\s*([0-9]+)\s+(\S+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+2[*][*]([0-9]+)/ | ||
33 | ) { | ||
34 | my $seg = $1; | ||
35 | my $name = $2; | ||
36 | my $len = Math::BigInt->new("0x" . $3); | ||
37 | my $vma = Math::BigInt->new("0x" . $4); | ||
38 | my $lma = Math::BigInt->new("0x" . $5); | ||
39 | my $foff = Math::BigInt->new("0x" . $6); | ||
40 | my $align = 2 ** $7; | ||
41 | |||
42 | push @sections, { name => $name, | ||
43 | vma => $vma, | ||
44 | len => $len, | ||
45 | foff => $foff }; | ||
46 | } | ||
47 | } | ||
48 | |||
49 | print "Have $#sections sections\n"; | ||
50 | |||
51 | # | ||
52 | # Try and parse the vmlinux symbol table. If the vmlinux file has been created | ||
53 | # from a vmlinuz file with extract-vmlinux then the symbol table will be empty. | ||
54 | # | ||
55 | open FD, "nm $vmlinux 2>/dev/null |" || die $vmlinux; | ||
56 | @lines = <FD>; | ||
57 | close(FD) || die $vmlinux; | ||
58 | |||
59 | my %symbols = (); | ||
60 | my $nr_symbols = 0; | ||
61 | |||
62 | sub parse_symbols(@) { | ||
63 | foreach my $line (@_) { | ||
64 | chomp($line); | ||
65 | if ($line =~ /([0-9a-f]+)\s([a-zA-Z])\s(\S+)/ | ||
66 | ) { | ||
67 | my $addr = "0x" . $1; | ||
68 | my $type = $2; | ||
69 | my $name = $3; | ||
70 | |||
71 | $symbols{$name} = $addr; | ||
72 | $nr_symbols++; | ||
73 | } | ||
74 | } | ||
75 | } | ||
76 | parse_symbols(@lines); | ||
77 | |||
78 | if ($nr_symbols == 0 && $sysmap ne "") { | ||
79 | print "No symbols in vmlinux, trying $sysmap\n"; | ||
80 | |||
81 | open FD, "<$sysmap" || die $sysmap; | ||
82 | @lines = <FD>; | ||
83 | close(FD) || die $sysmap; | ||
84 | parse_symbols(@lines); | ||
85 | } | ||
86 | |||
87 | die "No symbols available\n" | ||
88 | if ($nr_symbols == 0); | ||
89 | |||
90 | print "Have $nr_symbols symbols\n"; | ||
91 | |||
92 | die "Can't find system certificate list" | ||
93 | unless (exists($symbols{"__cert_list_start"}) && | ||
94 | exists($symbols{"__cert_list_end"})); | ||
95 | |||
96 | my $start = Math::BigInt->new($symbols{"__cert_list_start"}); | ||
97 | my $end = Math::BigInt->new($symbols{"__cert_list_end"}); | ||
98 | my $size = $end - $start; | ||
99 | |||
100 | printf "Have %u bytes of certs at VMA 0x%x\n", $size, $start; | ||
101 | |||
102 | my $s = undef; | ||
103 | foreach my $sec (@sections) { | ||
104 | my $s_name = $sec->{name}; | ||
105 | my $s_vma = $sec->{vma}; | ||
106 | my $s_len = $sec->{len}; | ||
107 | my $s_foff = $sec->{foff}; | ||
108 | my $s_vend = $s_vma + $s_len; | ||
109 | |||
110 | next unless ($start >= $s_vma); | ||
111 | next if ($start >= $s_vend); | ||
112 | |||
113 | die "Cert object partially overflows section $s_name\n" | ||
114 | if ($end > $s_vend); | ||
115 | |||
116 | die "Cert object in multiple sections: ", $s_name, " and ", $s->{name}, "\n" | ||
117 | if ($s); | ||
118 | $s = $sec; | ||
119 | } | ||
120 | |||
121 | die "Cert object not inside a section\n" | ||
122 | unless ($s); | ||
123 | |||
124 | print "Certificate list in section ", $s->{name}, "\n"; | ||
125 | |||
126 | my $foff = $start - $s->{vma} + $s->{foff}; | ||
127 | |||
128 | printf "Certificate list at file offset 0x%x\n", $foff; | ||
129 | |||
130 | open FD, "<$vmlinux" || die $vmlinux; | ||
131 | binmode(FD); | ||
132 | die $vmlinux if (!defined(sysseek(FD, $foff, SEEK_SET))); | ||
133 | my $buf = ""; | ||
134 | my $len = sysread(FD, $buf, $size); | ||
135 | die "$vmlinux" if (!defined($len)); | ||
136 | die "Short read on $vmlinux\n" if ($len != $size); | ||
137 | close(FD) || die $vmlinux; | ||
138 | |||
139 | open FD, ">$keyring" || die $keyring; | ||
140 | binmode(FD); | ||
141 | $len = syswrite(FD, $buf, $size); | ||
142 | die "$keyring" if (!defined($len)); | ||
143 | die "Short write on $keyring\n" if ($len != $size); | ||
144 | close(FD) || die $keyring; | ||