extract-module-sig.pl 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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. die "Format: $0 -[0adnks] module-file >out\n"
  17. if ($#ARGV != 1);
  18. my $part = $ARGV[0];
  19. my $modfile = $ARGV[1];
  20. my $magic_number = "~Module signature appended~\n";
  21. #
  22. # Read the module contents
  23. #
  24. open FD, "<$modfile" || die $modfile;
  25. binmode(FD);
  26. my @st = stat(FD);
  27. die "$modfile" unless (@st);
  28. my $buf = "";
  29. my $len = sysread(FD, $buf, $st[7]);
  30. die "$modfile" unless (defined($len));
  31. die "Short read on $modfile\n" unless ($len == $st[7]);
  32. close(FD) || die $modfile;
  33. print STDERR "Read ", $len, " bytes from module file\n";
  34. die "The file is too short to have a sig magic number and descriptor\n"
  35. if ($len < 12 + length($magic_number));
  36. #
  37. # Check for the magic number and extract the information block
  38. #
  39. my $p = $len - length($magic_number);
  40. my $raw_magic = substr($buf, $p);
  41. die "Magic number not found at $len\n"
  42. if ($raw_magic ne $magic_number);
  43. print STDERR "Found magic number at $len\n";
  44. $p -= 12;
  45. my $raw_info = substr($buf, $p, 12);
  46. my @info = unpack("CCCCCxxxN", $raw_info);
  47. my ($algo, $hash, $id_type, $name_len, $kid_len, $sig_len) = @info;
  48. if ($id_type == 0) {
  49. print STDERR "Found PGP key identifier\n";
  50. } elsif ($id_type == 1) {
  51. print STDERR "Found X.509 cert identifier\n";
  52. } elsif ($id_type == 2) {
  53. print STDERR "Found PKCS#7/CMS encapsulation\n";
  54. } else {
  55. print STDERR "Found unsupported identifier type $id_type\n";
  56. }
  57. #
  58. # Extract the three pieces of info data
  59. #
  60. die "Insufficient name+kid+sig data in file\n"
  61. unless ($p >= $name_len + $kid_len + $sig_len);
  62. $p -= $sig_len;
  63. my $raw_sig = substr($buf, $p, $sig_len);
  64. $p -= $kid_len;
  65. my $raw_kid = substr($buf, $p, $kid_len);
  66. $p -= $name_len;
  67. my $raw_name = substr($buf, $p, $name_len);
  68. my $module_len = $p;
  69. if ($sig_len > 0) {
  70. print STDERR "Found $sig_len bytes of signature [";
  71. my $n = $sig_len > 16 ? 16 : $sig_len;
  72. foreach my $i (unpack("C" x $n, substr($raw_sig, 0, $n))) {
  73. printf STDERR "%02x", $i;
  74. }
  75. print STDERR "]\n";
  76. }
  77. if ($kid_len > 0) {
  78. print STDERR "Found $kid_len bytes of key identifier [";
  79. my $n = $kid_len > 16 ? 16 : $kid_len;
  80. foreach my $i (unpack("C" x $n, substr($raw_kid, 0, $n))) {
  81. printf STDERR "%02x", $i;
  82. }
  83. print STDERR "]\n";
  84. }
  85. if ($name_len > 0) {
  86. print STDERR "Found $name_len bytes of signer's name [$raw_name]\n";
  87. }
  88. #
  89. # Produce the requested output
  90. #
  91. if ($part eq "-0") {
  92. # The unsigned module, no signature data at all
  93. binmode(STDOUT);
  94. print substr($buf, 0, $module_len);
  95. } elsif ($part eq "-a") {
  96. # All of the signature data, including magic number
  97. binmode(STDOUT);
  98. print substr($buf, $module_len);
  99. } elsif ($part eq "-d") {
  100. # Just the descriptor values as a sequence of numbers
  101. print join(" ", @info), "\n";
  102. } elsif ($part eq "-n") {
  103. # Just the signer's name
  104. print STDERR "No signer's name for PKCS#7 message type sig\n"
  105. if ($id_type == 2);
  106. binmode(STDOUT);
  107. print $raw_name;
  108. } elsif ($part eq "-k") {
  109. # Just the key identifier
  110. print STDERR "No key ID for PKCS#7 message type sig\n"
  111. if ($id_type == 2);
  112. binmode(STDOUT);
  113. print $raw_kid;
  114. } elsif ($part eq "-s") {
  115. # Just the crypto signature or PKCS#7 message
  116. binmode(STDOUT);
  117. print $raw_sig;
  118. }