Add extra utilities from FIPS branch.
authorDr. Stephen Henson <steve@openssl.org>
Thu, 18 Sep 2008 11:20:08 +0000 (11:20 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Thu, 18 Sep 2008 11:20:08 +0000 (11:20 +0000)
ms/segrenam.pl [new file with mode: 0644]
util/fipslink.pl [new file with mode: 0644]
util/mksdef.pl [new file with mode: 0644]

diff --git a/ms/segrenam.pl b/ms/segrenam.pl
new file mode 100644 (file)
index 0000000..2ab22a0
--- /dev/null
@@ -0,0 +1,65 @@
+#!/usr/bin/env perl
+
+my $quiet = 1;
+
+unpack("L",pack("N",1))!=1 || die "only little-endian hosts are supported";
+
+# first argument can specify custom suffix...
+$suffix=(@ARGV[0]=~/^\$/) ? shift(@ARGV) : "\$m";
+#################################################################
+# rename segments in COFF modules according to %map table below        #
+%map=( ".text" => "fipstx$suffix",                             #
+       ".text\$"=> "fipstx$suffix",                            #
+       ".rdata"=> "fipsrd$suffix",                             #
+       ".data" => "fipsda$suffix"      );                      #
+#################################################################
+
+# collect file list
+foreach (@ARGV) {
+    if (/\*/)  { push(@files,glob($_)); }
+    else       { push(@files,$_);       }
+}
+
+use Fcntl;
+use Fcntl ":seek";
+
+foreach (@files) {
+    $file=$_;
+    print "processing $file\n" unless $quiet;
+
+    sysopen(FD,$file,O_RDWR|O_BINARY) || die "sysopen($file): $!";
+
+    # read IMAGE_DOS_HEADER
+    sysread(FD,$mz,64)==64 || die "$file is too short";
+    @dos_header=unpack("a2C58I",$mz);
+    if (@dos_header[0] eq "MZ") {
+       $e_lfanew=pop(@dos_header);
+       sysseek(FD,$e_lfanew,SEEK_SET)  || die "$file is too short";
+       sysread(FD,$Magic,4)==4         || die "$file is too short";
+       unpack("I",$Magic)==0x4550      || die "$file is not COFF image";
+    } elsif ($file =~ /\.obj$/i) {
+       # .obj files have no IMAGE_DOS_HEADER
+       sysseek(FD,0,SEEK_SET)          || die "unable to rewind $file";
+    } else { next; }
+
+    # read IMAGE_FILE_HEADER
+    sysread(FD,$coff,20)==20 || die "$file is too short";
+    ($Machine,$NumberOfSections,$TimeDateStamp,
+     $PointerToSymbolTable,$NumberOfSysmbols,
+     $SizeOfOptionalHeader,$Characteristics)=unpack("SSIIISS",$coff);
+
+    # skip over IMAGE_OPTIONAL_HEADER
+    sysseek(FD,$SizeOfOptionalHeader,SEEK_CUR) || die "$file is too short";
+
+    # traverse IMAGE_SECTION_HEADER table
+    for($i=0;$i<$NumberOfSections;$i++) {
+       sysread(FD,$SectionHeader,40)==40 || die "$file is too short";
+       ($Name,@opaque)=unpack("Z8C*",$SectionHeader);
+       if ($map{$Name}) {
+           sysseek(FD,-40,SEEK_CUR) || die "unable to rewind $file";
+           syswrite(FD,pack("a8C*",$map{$Name},@opaque))==40 || die "syswrite failed: $!";
+           printf "    %-8s -> %.8s\n",$Name,$map{$Name} unless $quiet;
+       }
+    }
+    close(FD);
+}
diff --git a/util/fipslink.pl b/util/fipslink.pl
new file mode 100644 (file)
index 0000000..3597bc1
--- /dev/null
@@ -0,0 +1,78 @@
+#!/usr/bin/perl
+
+sub check_env
+       {
+       my @ret;
+       foreach (@_)
+               {
+               die "Environment variable $_ not defined!\n" unless exists $ENV{$_};
+               push @ret, $ENV{$_};
+               }
+       return @ret;
+       }
+
+
+my ($fips_cc,$fips_cc_args, $fips_link,$fips_target, $fips_libdir, $sha1_exe)
+        = check_env("FIPS_CC", "FIPS_CC_ARGS", "FIPS_LINK", "FIPS_TARGET",
+               "FIPSLIB_D", "FIPS_SHA1_EXE");
+
+
+
+if (exists $ENV{"PREMAIN_DSO_EXE"})
+       {
+       $fips_premain_dso = $ENV{"PREMAIN_DSO_EXE"};
+       }
+       else
+       {
+       $fips_premain_dso = "";
+       }
+
+check_hash($sha1_exe, "fips_premain.c");
+check_hash($sha1_exe, "fipscanister.lib");
+
+
+print "Integrity check OK\n";
+
+print "$fips_cc $fips_cc_args $fips_libdir/fips_premain.c\n";
+system "$fips_cc $fips_cc_args $fips_libdir/fips_premain.c";
+die "First stage Compile failure" if $? != 0;
+
+print "$fips_link @ARGV\n";
+system "$fips_link @ARGV";
+die "First stage Link failure" if $? != 0;
+
+
+print "$fips_premain_dso $fips_target\n";
+$fips_hash=`$fips_premain_dso $fips_target`;
+chomp $fips_hash;
+die "Get hash failure" if $? != 0;
+
+
+print "$fips_cc -DHMAC_SHA1_SIG=\\\"$fips_hash\\\" $fips_cc_args $fips_libdir/fips_premain.c\n";
+system "$fips_cc -DHMAC_SHA1_SIG=\\\"$fips_hash\\\" $fips_cc_args $fips_libdir/fips_premain.c";
+die "Second stage Compile failure" if $? != 0;
+
+
+print "$fips_link @ARGV\n";
+system "$fips_link @ARGV";
+die "Second stage Link failure" if $? != 0;
+
+sub check_hash
+       {
+       my ($sha1_exe, $filename) = @_;
+       my ($hashfile, $hashval);
+
+       open(IN, "${fips_libdir}/${filename}.sha1") || die "Cannot open file hash file ${fips_libdir}/${filename}.sha1";
+       $hashfile = <IN>;
+       close IN;
+       $hashval = `$sha1_exe ${fips_libdir}/$filename`;
+       chomp $hashfile;
+       chomp $hashval;
+       $hashfile =~ s/^.*=\s+//;
+       $hashval =~ s/^.*=\s+//;
+       die "Invalid hash syntax in file" if (length($hashfile) != 40);
+       die "Invalid hash received for file" if (length($hashval) != 40);
+       die "***HASH VALUE MISMATCH FOR FILE $filename ***" if ($hashval ne $hashfile); 
+       }
+
+
diff --git a/util/mksdef.pl b/util/mksdef.pl
new file mode 100644 (file)
index 0000000..065dc67
--- /dev/null
@@ -0,0 +1,87 @@
+
+# Perl script to split libeay32.def into two distinct DEF files for use in
+# fipdso mode. It works out symbols in each case by running "link" command and
+# parsing the output to find the list of missing symbols then splitting
+# libeay32.def based on the result.
+
+
+# Get list of unknown symbols
+
+my @deferr = `link @ARGV`;
+
+my $preamble = "";
+my @fipsdll;
+my @fipsrest;
+my %nosym;
+
+# Add symbols to a hash for easy lookup
+
+foreach (@deferr)
+       {
+       if (/^.*symbol (\S+)$/)
+               {
+               $nosym{$1} = 1;
+               }
+       }
+
+open (IN, "ms/libeay32.def") || die "Can't Open DEF file for spliting";
+
+my $started = 0;
+
+# Parse libeay32.def into two arrays depending on whether the symbol matches
+# the missing list.
+
+
+foreach (<IN>)
+       {
+       if (/^\s*(\S+)\s*(\@\S+)\s*$/)
+               {
+               $started = 1;
+               if (exists $nosym{$1})
+                       {
+                       push @fipsrest, $_;
+                       }
+               else
+                       {
+                       my $imptmp = sprintf "     %-39s %s\n",
+                                       "$1=libosslfips.$1", $2;
+                       push @fipsrest, $imptmp;
+                       push @fipsdll, "\t$1\n";
+                       }
+               }
+       $preamble .= $_ unless $started;
+       }
+
+close IN;
+
+# Hack! Add some additional exports needed for libcryptofips.dll
+#
+
+push @fipsdll, "\tOPENSSL_showfatal\n";
+push @fipsdll, "\tOPENSSL_cpuid_setup\n";
+
+# Write out DEF files for each array
+
+write_def("ms/libosslfips.def", "LIBOSSLFIPS", $preamble, \@fipsdll);
+write_def("ms/libeayfips.def", "", $preamble, \@fipsrest);
+
+
+sub write_def
+       {
+       my ($fnam, $defname, $preamble, $rdefs) = @_;
+       open (OUT, ">$fnam") || die "Can't Open DEF file $fnam for Writing\n";
+
+       if ($defname ne "")
+               {
+               $preamble =~ s/LIBEAY32/$defname/g;
+               $preamble =~ s/LIBEAY/$defname/g;
+               }
+       print OUT $preamble;
+       foreach (@$rdefs)
+               {
+               print OUT $_;
+               }
+       close OUT;
+       }
+
+