From ed457c6e1cb0b685d00c367d548ac9b205fa4ede Mon Sep 17 00:00:00 2001 From: Andy Polyakov Date: Sat, 21 Jan 2006 14:01:30 +0000 Subject: [PATCH] Replace detached signature with in-core fingerprinting. --- Configure | 1 + Makefile.org | 60 ++++--------- apps/Makefile | 18 +--- apps/openssl.c | 9 +- crypto/cryptlib.c | 6 ++ fips/Makefile | 64 +++++++++++--- fips/aes/Makefile | 4 +- fips/aes/fips_aesavs.c | 2 +- fips/des/Makefile | 4 +- fips/des/fips_desmovs.c | 2 +- fips/dh/Makefile | 4 +- fips/dsa/Makefile | 4 +- fips/dsa/fips_dsatest.c | 2 +- fips/dsa/fips_dssvs.c | 2 +- fips/fips.c | 179 ++++++++++++++------------------------ fips/fips.h | 17 ++-- fips/fips_canister.c | 171 ++++++++++++++++++++++++++++++++++++ fips/fips_err.h | 15 ++-- fips/fips_premain.c | 171 ++++++++++++++++++++++++++++++++++++ fips/fips_test_suite.c | 4 +- fips/fipshashes.c | 8 +- fips/fipsld | 136 +++++++++++++++++++++++++++++ fips/hmac/fips_hmactest.c | 2 +- fips/rand/Makefile | 4 +- fips/rand/fips_rngvs.c | 2 +- fips/rsa/Makefile | 4 +- fips/rsa/fips_rsagtest.c | 2 +- fips/rsa/fips_rsastest.c | 2 +- fips/rsa/fips_rsavtest.c | 2 +- fips/sha/Makefile | 4 +- fips/sha/fips_shatest.c | 2 +- ssl/ssltest.c | 3 +- test/Makefile | 9 +- 33 files changed, 669 insertions(+), 250 deletions(-) create mode 100644 fips/fips_canister.c create mode 100644 fips/fips_premain.c create mode 100755 fips/fipsld diff --git a/Configure b/Configure index 2a1366d37a..9feec9637c 100755 --- a/Configure +++ b/Configure @@ -1160,6 +1160,7 @@ if (!$no_shared) if ($shared_cflag ne "") { $cflags = "$shared_cflag -DOPENSSL_PIC $cflags"; + $shared_ldflag = "$shared_ldflag $shared_cflag" if($fips); } } diff --git a/Makefile.org b/Makefile.org index 24e3acdaf3..1b96b76440 100644 --- a/Makefile.org +++ b/Makefile.org @@ -180,7 +180,7 @@ LIBZLIB= # we might set SHLIB_MARK to '$(SHARED_LIBS)'. SHLIB_MARK= -DIRS= crypto fips ssl $(SHLIB_MARK) sigs apps test tools +DIRS= crypto fips ssl $(SHLIB_MARK) apps test tools SHLIBDIRS= crypto ssl # dirs in crypto to build @@ -210,7 +210,6 @@ ONEDIRS=out tmp EDIRS= times doc bugs util include certs ms shlib mt demos perl sf dep VMS WDIRS= windows LIBS= libcrypto.a libssl.a -SIGS= libcrypto.a.sha1 SHARED_CRYPTO=libcrypto$(SHLIB_EXT) SHARED_SSL=libssl$(SHLIB_EXT) SHARED_LIBS= @@ -230,13 +229,6 @@ HEADER= e_os.h all: Makefile sub_all openssl.pc -sigs: $(SIGS) -libcrypto.a.sha1: libcrypto.a - @if egrep 'define OPENSSL_FIPS' $(TOP)/include/openssl/opensslconf.h > /dev/null; then \ - $(RANLIB) libcrypto.a; \ - fips/sha/fips_standalone_sha1 libcrypto.a > libcrypto.a.sha1; \ - fi - sub_all: @for i in $(DIRS); \ do \ @@ -262,9 +254,6 @@ sub_target: libcrypto$(SHLIB_EXT): libcrypto.a @if [ "$(SHLIB_TARGET)" != "" ]; then \ $(MAKE) SHLIBDIRS=crypto build-shared; \ - if egrep 'define OPENSSL_FIPS' $(TOP)/include/openssl/opensslconf.h > /dev/null; then \ - fips/sha/fips_standalone_sha1 -binary $@ > $@.$${HMAC_EXT:-sha1}; \ - fi; \ else \ echo "There's no support for shared libraries on this platform" >&2; \ fi @@ -312,7 +301,7 @@ do_gnu-shared: if [ "${SHLIBDIRS}" = "ssl" -a -n "$(LIBKRB5)" ]; then \ libs="$(LIBKRB5) $$libs"; \ fi; \ - ( set -x; ${CC} ${SHARED_LDFLAGS} \ + ( set -x; $${FIPSLD:-${CC}} ${SHARED_LDFLAGS} \ -shared -o lib$$i.so.${SHLIB_MAJOR}.${SHLIB_MINOR} \ -Wl,-soname=lib$$i.so.${SHLIB_MAJOR}.${SHLIB_MINOR} \ -Wl,-Bsymbolic \ @@ -329,7 +318,7 @@ do_darwin-shared: if [ "${SHLIBDIRS}" = "ssl" -a -n "$(LIBKRB5)" ]; then \ libs="$(LIBKRB5) $$libs"; \ fi; \ - ( set -x; ${CC} ${SHARED_LDFLAGS} \ + ( set -x; $${FIPSLD:-${CC}} ${SHARED_LDFLAGS} \ --verbose -dynamiclib -o lib$$i${SHLIB_EXT} \ lib$$i.a $$libs -all_load -current_version ${SHLIB_MAJOR}.${SHLIB_MINOR} \ -compatibility_version ${SHLIB_MAJOR}.`echo ${SHLIB_MINOR} | cut -d. -f1` \ @@ -348,13 +337,14 @@ do_cygwin-shared: [ -f apps/$$shlib ] && rm apps/$$shlib; \ [ -f test/$$shlib ] && rm test/$$shlib; \ base=; [ $$i = "crypto" ] && base=-Wl,--image-base,0x63000000; \ - ( set -x; ${CC} ${SHARED_LDFLAGS} \ + ( set -x; $${FIPSLD:-${CC}} ${SHARED_LDFLAGS} \ -shared $$base -o $$shlib \ -Wl,-Bsymbolic \ -Wl,--whole-archive lib$$i.a \ -Wl,--out-implib,lib$$i.dll.a \ -Wl,--no-whole-archive $$libs ${EX_LIBS} ) || exit 1; \ cp -p $$shlib apps/; cp -p $$shlib test/; \ + touch -c lib$$i.dll.a; \ libs="-l$$i $$libs"; \ done @@ -367,7 +357,7 @@ do_alpha-osf1-shared: if [ "${SHLIBDIRS}" = "ssl" -a -n "$(LIBKRB5)" ]; then \ libs="$(LIBKRB5) $$libs"; \ fi; \ - ( set -x; ${CC} ${SHARED_LDFLAGS} \ + ( set -x; $${FIPSLD:-${CC}} ${SHARED_LDFLAGS} \ -shared -o lib$$i.so \ -set_version "${SHLIB_VERSION_HISTORY}${SHLIB_VERSION_NUMBER}" \ -all lib$$i.a -none $$libs ${EX_LIBS} ) || exit 1; \ @@ -386,7 +376,7 @@ do_tru64-shared: if [ "${SHLIBDIRS}" = "ssl" -a -n "$(LIBKRB5)" ]; then \ libs="$(LIBKRB5) $$libs"; \ fi; \ - ( set -x; ${CC} ${SHARED_LDFLAGS} \ + ( set -x; $${FIPSLD:-${CC}} ${SHARED_LDFLAGS} \ -shared -msym -o lib$$i.so \ -set_version "${SHLIB_VERSION_HISTORY}${SHLIB_VERSION_NUMBER}" \ -all lib$$i.a -none $$libs ${EX_LIBS} ) || exit 1; \ @@ -405,7 +395,7 @@ do_tru64-shared-rpath: if [ "${SHLIBDIRS}" = "ssl" -a -n "$(LIBKRB5)" ]; then \ libs="$(LIBKRB5) $$libs"; \ fi; \ - ( set -x; ${CC} ${SHARED_LDFLAGS} \ + ( set -x; $${FIPSLD:-${CC}} ${SHARED_LDFLAGS} \ -shared -msym -o lib$$i.so \ -rpath ${INSTALLTOP}/lib \ -set_version "${SHLIB_VERSION_HISTORY}${SHLIB_VERSION_NUMBER}" \ @@ -427,7 +417,7 @@ do_solaris-shared: ( PATH=/usr/ccs/bin:$$PATH ; export PATH; \ MINUSZ='-z '; \ (${CC} -v 2>&1 | grep gcc) > /dev/null && MINUSZ='-Wl,-z,'; \ - set -x; ${CC} ${SHARED_LDFLAGS} \ + set -x; $${FIPSLD:-${CC}} ${SHARED_LDFLAGS} \ -o lib$$i.so.${SHLIB_MAJOR}.${SHLIB_MINOR} \ -h lib$$i.so.${SHLIB_MAJOR}.${SHLIB_MINOR} \ -Wl,-Bsymbolic \ @@ -452,7 +442,7 @@ do_svr3-shared: for obj in `ar t lib$$i.a` ; do \ OBJS="$${OBJS} `grep /$$obj allobjs`" ; \ done ; \ - set -x; ${CC} ${SHARED_LDFLAGS} \ + set -x; $${FIPSLD:-${CC}} ${SHARED_LDFLAGS} \ -G -o lib$$i.so.${SHLIB_MAJOR}.${SHLIB_MINOR} \ -h lib$$i.so.${SHLIB_MAJOR}.${SHLIB_MINOR} \ $${OBJS} $$libs ${EX_LIBS} ) || exit 1; \ @@ -478,7 +468,7 @@ do_svr5-shared: OBJS="$${OBJS} `grep /$$obj allobjs`" ; \ done ; \ set -x; LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH \ - ${CC} ${SHARED_LDFLAGS} \ + $${FIPSLD:-${CC}} ${SHARED_LDFLAGS} \ $${SHARE_FLAG} -o lib$$i.so.${SHLIB_MAJOR}.${SHLIB_MINOR} \ -h lib$$i.so.${SHLIB_MAJOR}.${SHLIB_MINOR} \ $${OBJS} $$libs ${EX_LIBS} ) || exit 1; \ @@ -497,7 +487,7 @@ do_irix-shared: fi; \ ( WHOLELIB="-all lib$$i.a -none"; \ (${CC} -v 2>&1 | grep gcc) > /dev/null && WHOLELIB="-Wl,-all,lib$$i.a,-none"; \ - set -x; ${CC} ${SHARED_LDFLAGS} \ + set -x; $${FIPSLD:-${CC}} ${SHARED_LDFLAGS} \ -shared -o lib$$i.so.${SHLIB_MAJOR}.${SHLIB_MINOR} \ -Wl,-soname,lib$$i.so.${SHLIB_MAJOR}.${SHLIB_MINOR} \ $${WHOLELIB} $$libs ${EX_LIBS}) || exit 1; \ @@ -520,7 +510,7 @@ do_hpux-shared: [ -f $$shlib ] && rm -f $$shlib; \ ALLSYMSFLAGS='-Wl,-Fl'; \ expr $(PLATFORM) : 'hpux64' > /dev/null && ALLSYMSFLAGS='-Wl,+forceload'; \ - ( set -x; ${CC} ${SHARED_LDFLAGS} \ + ( set -x; $${FIPSLD:-${CC}} ${SHARED_LDFLAGS} \ -Wl,-B,symbolic,+vnocompatwarnings,-z,+h,$$shlib \ -o $$shlib $$ALLSYMSFLAGS,lib$$i.a -ldld ) || exit 1; \ chmod a=rx $$shlib; \ @@ -568,7 +558,7 @@ do_aix-shared: OBJECT_MODE=$${OBJECT_MODE:-32}; export OBJECT_MODE; \ ld -r -o lib$$i.o $(ALLSYMSFLAG) lib$$i.a && \ ( nm -Pg lib$$i.o | grep ' [BD] ' | cut -f1 -d' ' > lib$$i.exp; \ - $(SHAREDCMD) $(SHAREDFLAGS) \ + $${FIPSLD:-${CC}} $(SHAREDFLAGS) \ -o lib$$i.so.${SHLIB_MAJOR}.${SHLIB_MINOR} lib$$i.o \ $$libs ${EX_LIBS} ) ) \ || exit 1; \ @@ -584,7 +574,7 @@ do_reliantunix-shared: ( set -x; \ ( Opwd=`pwd` ; mkdir $$tmpdir || exit 1; \ cd $$tmpdir || exit 1 ; ar x $$Opwd/lib$$i.a ; \ - ${CC} -G -o lib$$i.so.${SHLIB_MAJOR}.${SHLIB_MINOR} *.o \ + $${FIPSLD:-${CC}} -G -o lib$$i.so.${SHLIB_MAJOR}.${SHLIB_MINOR} *.o \ ) || exit 1; \ cp $$tmpdir/lib$$i.so.${SHLIB_MAJOR}.${SHLIB_MINOR} . ; \ ) || exit 1; \ @@ -820,16 +810,7 @@ install_sw: if [ "$(PLATFORM)" != "Cygwin" ]; then \ cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/lib/$$i.new; \ chmod 555 $(INSTALL_PREFIX)$(INSTALLTOP)/lib/$$i.new; \ - mv -f $(INSTALL_PREFIX)$(INSTALLTOP)/lib/$$i.new \ - $(INSTALL_PREFIX)$(INSTALLTOP)/lib/$$i; \ - sig="$$i.$${HMAC_EXT:-sha1}"; \ - if [ -f $$sig ]; then \ - echo installing $$sig; \ - cp $$sig $(INSTALL_PREFIX)$(INSTALLTOP)/lib/$$sig.new; \ - chmod 444 $(INSTALL_PREFIX)$(INSTALLTOP)/lib/$$sig.new; \ - mv -f $(INSTALL_PREFIX)$(INSTALLTOP)/lib/$$sig.new \ - $(INSTALL_PREFIX)$(INSTALLTOP)/lib/$$sig; \ - fi; \ + mv -f $(INSTALL_PREFIX)$(INSTALLTOP)/lib/$$i.new $(INSTALL_PREFIX)$(INSTALLTOP)/lib/$$i; \ else \ c=`echo $$i | sed 's/^lib\(.*\)\.dll/cyg\1-$(SHLIB_VERSION_NUMBER).dll/'`; \ cp $$c $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$c.new; \ @@ -852,15 +833,6 @@ install_sw: sed -e '1,/^$$/d' doc/openssl-shared.txt; \ fi; \ fi - @for i in $(SIGS) ;\ - do \ - if [ -f "$$i" ]; then \ - ( echo installing $$i; \ - cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/lib/$$i.new; \ - chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/lib/$$i.new; \ - mv -f $(INSTALL_PREFIX)$(INSTALLTOP)/lib/$$i.new $(INSTALL_PREFIX)$(INSTALLTOP)/lib/$$i ); \ - fi; \ - done; cp openssl.pc $(INSTALL_PREFIX)$(INSTALLTOP)/lib/pkgconfig chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/lib/pkgconfig/openssl.pc diff --git a/apps/Makefile b/apps/Makefile index 5ca70480e7..1b65e2a13e 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -103,14 +103,6 @@ install: chmod 755 $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$i.new; \ mv -f $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$i.new \ $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$i; \ - sig="$$i.$${HMAC_EXT:-sha1}"; \ - if [ -f $$sig ]; then \ - echo installing $$sig; \ - cp $$sig $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$sig.new; \ - chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$sig.new; \ - mv -f $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$sig.new \ - $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$sig; \ - fi; \ ) done; @for i in $(SCRIPTS); \ do \ @@ -152,20 +144,18 @@ $(DLIBCRYPTO): $(EXE): progs.h $(E_OBJ) $(PROGRAM).o $(DLIBCRYPTO) $(DLIBSSL) $(RM) $(EXE) + @if egrep 'define OPENSSL_FIPS' $(TOP)/include/openssl/opensslconf.h > /dev/null; then \ + FIPSLD_CC=$(CC); CC=$(TOP)/fips/fipsld; export CC FIPSLD_CC; \ + fi; \ SHARED_LIBS="$(SHARED_LIBS)"; \ if [ "$(SHLIB_TARGET)" = "darwin-shared" ] ; then \ SHARED_LIBS=""; \ fi; \ - if [ -z "$(SHARED_LIBS)" ]; then \ + if [ -z "$$SHARED_LIBS" ]; then \ set -x; $${CC:-$(CC)} -o $(EXE) $(CFLAGS) $(PROGRAM).o $(E_OBJ) $(PEX_LIBS) $(DLIBSSL) $(LIBKRB5) $(DLIBCRYPTO) $(EX_LIBS) ; \ else \ set -x; LD_LIBRARY_PATH=..:$$LD_LIBRARY_PATH \ $(CC) -o $(EXE) $(CFLAGS) $(PROGRAM).o $(E_OBJ) $(PEX_LIBS) $(LIBSSL) $(LIBKRB5) $(LIBCRYPTO) $(EX_LIBS) ; \ - fi; \ - if [ -z "$$SHARED_LIBS" ]; then \ - if egrep 'define OPENSSL_FIPS' $(TOP)/include/openssl/opensslconf.h > /dev/null; then \ - TOP=$(TOP) $(TOP)/fips/openssl_fips_fingerprint $(TOP)/libcrypto.a $(EXE); \ - fi; \ fi -(cd ..; \ OPENSSL="`pwd`/util/opensslwrap.sh"; export OPENSSL; \ diff --git a/apps/openssl.c b/apps/openssl.c index 2080fa8816..cb6ee740e7 100644 --- a/apps/openssl.c +++ b/apps/openssl.c @@ -237,14 +237,7 @@ int main(int Argc, char *Argv[]) #ifdef OPENSSL_FIPS if(getenv("OPENSSL_FIPS")) { -#if defined(_WIN32) - char filename[MAX_PATH] = ""; - GetModuleFileNameA( NULL, filename, MAX_PATH) ; - p = filename; -#else - p = Argv[0]; -#endif - if (!FIPS_mode_set(1,p)) { + if (!FIPS_mode_set(1)) { ERR_load_crypto_strings(); ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE)); EXIT(1); diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c index f73eefc519..e63bbe8dba 100644 --- a/crypto/cryptlib.c +++ b/crypto/cryptlib.c @@ -734,5 +734,11 @@ int fips_clear_owning_thread(void) } return ret; } + +unsigned char *fips_signature_witness(void) + { + extern unsigned char FIPS_signature[]; + return FIPS_signature; + } #endif /* OPENSSL_FIPS */ diff --git a/fips/Makefile b/fips/Makefile index 4396664228..9b88ef5c6c 100644 --- a/fips/Makefile +++ b/fips/Makefile @@ -32,15 +32,15 @@ GENERAL=Makefile README fips-lib.com install.com LIB= $(TOP)/libcrypto.a SHARED_LIB= libcrypto$(SHLIB_EXT) -LIBSRC=fips.c fips_err_wrapper.c -LIBOBJ=fips.o fips_err_wrapper.o +LIBSRC=fips.c fips_err_wrapper.c fipshashes.c +LIBOBJ=fips.o fips_err_wrapper.o fipshashes.o +FIPS_OBJ_LISTS=sha/lib rand/lib des/lib aes/lib dsa/lib rsa/lib dh/lib SRC= $(LIBSRC) EXHEADER=fips.h HEADER=$(EXHEADER) fips_err.h -EXE=openssl_fips_fingerprint -TEST= fips_test_suite.c +EXE=fipsld ALL= $(GENERAL) $(SRC) $(HEADER) @@ -53,7 +53,48 @@ all: fi check: - $(PERL) ../util/checkhash.pl + $(PERL) ../util/checkhash.pl || (rm fipscanister.o* 2>/dev/null; exit 1) + +# Idea behind fipscanister.o is to "seize" the sequestered code between +# known symbols for fingerprinting purposes, which would be commonly +# done with ld -r start.o ... end.o. The latter however presents a minor +# challenge on multi-ABI platforms. As just implied, we'd rather use ld, +# but the trouble is that we don't generally know how ABI-selection +# compiler flag is translated to corresponding linker flag. All compiler +# drivers seem to recognize -r flag and pass it down to linker, but some +# of them, including gcc, erroneously add -lc, as well as run-time +# components, such as crt1.o and alike. Fortunately among those vendor +# compilers which were observed to misinterpret -r flag multi-ABI ones +# are equipped with smart linkers, which don't require any ABI-selection +# flag and simply assume that all objects are of the same type as first +# one in command line. So the idea is to identify gcc and deficient +# vendor compiler drivers... +fipscanister.o: fips_start.o $(LIBOBJ) $(FIPS_OBJ_LISTS) fips_end.o + @objs="fips_start.o $(LIBOBJ)"; \ + for i in $(FIPS_OBJ_LISTS); do \ + dir=`dirname $$i`; script="s|^|$$dir/|;s| | $$dir/|g"; \ + objs="$$objs `sed "$$script" $$i`"; \ + done; \ + objs="$$objs fips_end.o" ; \ + if [ -n "${FIPS_SITE_LD}" ]; then \ + set -x; ${FIPS_SITE_LD} -r -o $@ $$objs; \ + elif $(CC) -dumpversion >/dev/null 2>&1; then \ + set -x; $(CC) $(CFLAGS) -r -nostdlib -o $@ $$objs ; \ + else case "`(uname -s) 2>/dev/null`" in \ + HP-UX|OSF1|SunOS) set -x; /usr/ccs/bin/ld -r -o $@ $$objs ;; \ + *) set -x; $(CC) $(CFLAGS) -r -o $@ $$objs ;; \ + esac fi + sha/fips_standalone_sha1 fipscanister.o > fipscanister.o.sha1 +# If another exception is immediately required, assign approprite +# site-specific ld command to FIPS_SITE_LD environment variable. + +fips_start.o: fips_canister.c + $(CC) $(CFLAGS) -DFIPS_START -c -o $@ fips_canister.c +fips_end.o: fips_canister.c + $(CC) $(CFLAGS) -DFIPS_END -c -o $@ fips_canister.c +fips_premain_dso$(EXE_EXT): fips_premain.c + $(CC) $(CFLAGS) -DFINGERPRINT_PREMAIN_DSO_LOAD -o $@ fips_premain.c \ + ../libcrypto.a $(EX_LIBS) subdirs: @for i in $(FDIRS) ;\ @@ -85,14 +126,14 @@ links: $(MAKE) CC='$(CC)' INCLUDES='${INCLUDES}' CFLAG='${CFLAG}' INSTALLTOP='${INSTALLTOP}' PEX_LIBS='${PEX_LIBS}' EX_LIBS='${EX_LIBS}' BN_ASM='${BN_ASM}' DES_ENC='${DES_ENC}' FIPS_DES_ENC='${FIPS_DES_ENC}' SHA1_ASM_OBJ='${SHA1_ASM_OBJ}' FIPS_SHA1_ASM_OBJ='${FIPS_SHA1_ASM_OBJ}' MD5_ASM_OBJ='${MD5_ASM_OBJ}' RMD160_ASM_OBJ='${RMD160_ASM_OBJ}' BF_ENC='${BF_ENC}' CAST_ENC='${CAST_ENC}' RC4_ENC='${RC4_ENC}' RC5_ENC='${RC5_ENC}' AR='${AR}' PERL='${PERL}' links ); \ done; -lib: $(LIBOBJ) - $(AR) $(LIB) $(LIBOBJ) +lib: fipscanister.o + $(AR) $(LIB) fipscanister.o $(RANLIB) $(LIB) || echo Never mind. @touch lib -shared: +shared: fips_premain_dso$(EXE_EXT) if [ -n "$(SHARED_LIBS)" ]; then \ - (cd ..; $(MAKE) $(SHARED_LIB)); \ + (cd ..; $(MAKE) FIPSLD_CC=$(CC) FIPSLD=fips/fipsld $(SHARED_LIB)); \ fi libs: @@ -130,6 +171,9 @@ install: chmod 755 $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$i.new; \ mv -f $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$i.new $(INSTALL_PREFIX)$(INSTALLTOP)/bin/$$i; \ done + @cp -p -f fipscanister.o fipscanister.o.sha1 $(INSTALL_PREFIX)$(INSTALLTOP)/lib/; \ + chmod 0444 $(INSTALL_PREFIX)$(INSTALLTOP)/lib/fipscanister.o \ + $(INSTALL_PREFIX)$(INSTALLTOP)/lib/fipscanister.o.sha1 lint: @for i in $(FDIRS) ;\ @@ -149,7 +193,7 @@ depend: done; clean: - rm -f buildinf.h *.o */*.o *.obj lib tags core .pure .nfs* *.old *.bak fluff + rm -f buildinf.h *.o *.obj fips_premain_dso$(EXE_EXT) lib tags core .pure .nfs* *.old *.bak fluff @for i in $(FDIRS) ;\ do \ (cd $$i && echo "making clean in fips/$$i..." && \ diff --git a/fips/aes/Makefile b/fips/aes/Makefile index c81cd39f06..d1cf4e045d 100644 --- a/fips/aes/Makefile +++ b/fips/aes/Makefile @@ -41,9 +41,7 @@ top: all: lib lib: $(LIBOBJ) - $(AR) $(LIB) $(LIBOBJ) - $(RANLIB) $(LIB) || echo Never mind. - @sleep 2; touch lib + @echo $(LIBOBJ) > lib files: $(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO diff --git a/fips/aes/fips_aesavs.c b/fips/aes/fips_aesavs.c index 5fc2879067..6bb9b899c8 100644 --- a/fips/aes/fips_aesavs.c +++ b/fips/aes/fips_aesavs.c @@ -939,7 +939,7 @@ int main(int argc, char **argv) int f_opt = 0, d_opt = 1; #ifdef OPENSSL_FIPS - if(!FIPS_mode_set(1,argv[0])) + if(!FIPS_mode_set(1)) { ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE)); EXIT(1); diff --git a/fips/des/Makefile b/fips/des/Makefile index 2e6b9d8f39..e1b7e7616d 100644 --- a/fips/des/Makefile +++ b/fips/des/Makefile @@ -40,9 +40,7 @@ top: all: lib lib: $(LIBOBJ) - $(AR) $(LIB) $(LIBOBJ) - $(RANLIB) $(LIB) || echo Never mind. - @sleep 2; touch lib + @echo $(LIBOBJ) > lib files: $(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO diff --git a/fips/des/fips_desmovs.c b/fips/des/fips_desmovs.c index d1b60c1a40..5eb55726e3 100644 --- a/fips/des/fips_desmovs.c +++ b/fips/des/fips_desmovs.c @@ -766,7 +766,7 @@ int main(int argc, char **argv) int f_opt = 0, d_opt = 1; #ifdef OPENSSL_FIPS - if(!FIPS_mode_set(1,argv[0])) + if(!FIPS_mode_set(1)) { ERR_load_crypto_strings(); ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE)); diff --git a/fips/dh/Makefile b/fips/dh/Makefile index 590090d0ce..5c66fc6dcb 100644 --- a/fips/dh/Makefile +++ b/fips/dh/Makefile @@ -38,9 +38,7 @@ top: all: lib lib: $(LIBOBJ) - $(AR) $(LIB) $(LIBOBJ) - $(RANLIB) $(LIB) || echo Never mind. - @sleep 2; touch lib + @echo $(LIBOBJ) > lib files: $(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO diff --git a/fips/dsa/Makefile b/fips/dsa/Makefile index efe324e852..4b21c6d74a 100644 --- a/fips/dsa/Makefile +++ b/fips/dsa/Makefile @@ -38,9 +38,7 @@ top: all: lib lib: $(LIBOBJ) - $(AR) $(LIB) $(LIBOBJ) - $(RANLIB) $(LIB) || echo Never mind. - @sleep 2; touch lib + @echo $(LIBOBJ) > lib files: $(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO diff --git a/fips/dsa/fips_dsatest.c b/fips/dsa/fips_dsatest.c index 7215940ede..5970b201e9 100644 --- a/fips/dsa/fips_dsatest.c +++ b/fips/dsa/fips_dsatest.c @@ -147,7 +147,7 @@ int main(int argc, char **argv) bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); #ifdef OPENSSL_FIPS - if(!FIPS_mode_set(1,argv[0])) + if(!FIPS_mode_set(1)) { ERR_print_errors(bio_err); EXIT(1); diff --git a/fips/dsa/fips_dssvs.c b/fips/dsa/fips_dssvs.c index cbf0a81981..560d635981 100644 --- a/fips/dsa/fips_dssvs.c +++ b/fips/dsa/fips_dssvs.c @@ -292,7 +292,7 @@ int main(int argc,char **argv) fprintf(stderr,"%s [prime|pqg]\n",argv[0]); exit(1); } - if(!FIPS_mode_set(1,argv[0])) + if(!FIPS_mode_set(1)) { ERR_load_crypto_strings(); ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE)); diff --git a/fips/fips.c b/fips/fips.c index 0bdaddf82c..bb833bfa2c 100644 --- a/fips/fips.c +++ b/fips/fips.c @@ -145,135 +145,78 @@ int FIPS_selftest() && FIPS_selftest_dsa(); } -#ifndef HMAC_EXT -#define HMAC_EXT "sha1" -#endif +extern const void *FIPS_text_start(), *FIPS_text_end(); +extern const unsigned char FIPS_rodata_start[], FIPS_rodata_end[]; +unsigned char FIPS_signature [20] = { 0 }; +static const char FIPS_hmac_key[]="etaonrishdlcupfm"; -static char key[]="etaonrishdlcupfm"; +unsigned int FIPS_incore_fingerprint(unsigned char *sig,unsigned int len) + { + const unsigned char *p1 = FIPS_text_start(); + const unsigned char *p2 = FIPS_text_end(); + const unsigned char *p3 = FIPS_rodata_start; + const unsigned char *p4 = FIPS_rodata_end; + HMAC_CTX c; -#ifdef OPENSSL_PIC -int DSO_pathbyaddr(void *addr,char *path,int sz); + HMAC_CTX_init(&c); + HMAC_Init(&c,FIPS_hmac_key,strlen(FIPS_hmac_key),EVP_sha1()); -static int FIPS_check_dso() - { - unsigned char buf[1024]; - char path [512]; - unsigned char mdbuf[EVP_MAX_MD_SIZE]; - FILE *f; - HMAC_CTX hmac; - int len,n; - - len = DSO_pathbyaddr(NULL,path,sizeof(path)-sizeof(HMAC_EXT)); - if (len<=0) - { - FIPSerr(FIPS_F_FIPS_CHECK_DSO,FIPS_R_NO_DSO_PATH); - return 0; - } + /* detect overlapping regions */ + if (p1<=p3 && p2>=p3) + p3=p1, p4=p2>p4?p2:p4, p1=NULL, p2=NULL; + else if (p3<=p1 && p4>=p1) + p3=p3, p4=p2>p4?p2:p4, p1=NULL, p2=NULL; - f=fopen(path,"rb"); - if(!f) - { - FIPSerr(FIPS_F_FIPS_CHECK_EXE,FIPS_R_CANNOT_READ_EXE); - return 0; - } + if (p1) + HMAC_Update(&c,p1,(size_t)p2-(size_t)p1); - HMAC_Init(&hmac,key,strlen(key),EVP_sha1()); - while(!feof(f)) - { - n=fread(buf,1,sizeof buf,f); - if(ferror(f)) - { - clearerr(f); - fclose(f); - FIPSerr(FIPS_F_FIPS_CHECK_EXE,FIPS_R_CANNOT_READ_EXE); - return 0; - } - if (n) HMAC_Update(&hmac,buf,n); - } - fclose(f); - HMAC_Final(&hmac,mdbuf,&n); - HMAC_CTX_cleanup(&hmac); - - path[len-1]='.'; - strcpy(path+len,HMAC_EXT); - f=fopen(path,"rb"); - if(!f || fread(buf,1,20,f) != 20) - { - if (f) fclose(f); - FIPSerr(FIPS_F_FIPS_CHECK_EXE,FIPS_R_CANNOT_READ_EXE_DIGEST); - return 0; - } - fclose(f); - if(memcmp(buf,mdbuf,20)) + if (FIPS_signature>=p3 && FIPS_signature=FIPS_rodata_start && FIPS_signature +#if defined(__DECC) +# include +# pragma __nostandard +#endif + +#include "e_os.h" + +#if !defined(POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION) +# if (defined(__sun) && (defined(__sparc) || defined(__sparcv9))) || \ + (defined(__sgi) && (defined(__mips) || defined(mips))) || \ + (defined(__osf__) && defined(__alpha)) || \ + (defined(__linux) && (defined(__arm) || defined(__arm__))) || \ + (defined(__i386) || defined(__i386__)) || \ + (defined(__x86_64) || defined(__x86_64__)) || \ + (defined(vax) || defined(__vax__)) +# define POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION +# endif +#endif + +#ifdef FIPS_START +#define FIPS_ref_point FIPS_text_start +/* Some compilers put string literals into a separate segment. As we + * are mostly interested to hash AES tables in .rodata, we declare + * reference points accordingly. In case you wonder, the values are + * big-endian encoded variable names, just to prevent these arrays + * from being merged by linker. */ +const unsigned int FIPS_rodata_start[]= + { 0x46495053, 0x5f726f64, 0x6174615f, 0x73746172 }; +#else +#define FIPS_ref_point FIPS_text_end +const unsigned int FIPS_rodata_end[]= + { 0x46495053, 0x5f726f64, 0x6174615f, 0x656e645b }; +#endif + +/* + * I declare reference function as static in order to avoid certain + * pitfalls in -dynamic linker behaviour... + */ +static void *instruction_pointer(void) +{ void *ret=NULL; +/* These are ABI-neutral CPU-specific snippets. ABI-neutrality means + * that they are designed to work under any OS running on particular + * CPU, which is why you don't find any #ifdef THIS_OR_THAT_OS in + * this function. */ +#if defined(INSTRUCTION_POINTER_IMPLEMENTED) + INSTRUCTION_POINTER_IMPLEMENTED(ret); +#elif defined(__GNUC__) && __GNUC__>=2 +# if defined(__alpha) || defined(__alpha__) +# define INSTRUCTION_POINTER_IMPLEMENTED + __asm __volatile ( "br %0,1f\n1:" : "=r"(ret) ); +# elif defined(__i386) || defined(__i386__) +# define INSTRUCTION_POINTER_IMPLEMENTED + __asm __volatile ( "call 1f\n1: popl %0" : "=r"(ret) ); + ret = (void *)((size_t)ret&~3UL); /* align for better performance */ +# elif defined(__ia64) || defined(__ia64__) +# define INSTRUCTION_POINTER_IMPLEMENTED + __asm __volatile ( "mov %0=ip" : "=r"(ret) ); +# elif defined(__hppa) || defined(__hppa__) || defined(__pa_risc) +# define INSTRUCTION_POINTER_IMPLEMENTED + __asm __volatile ( "blr %%r0,%0\n\tnop" : "=r"(ret) ); + ret = (void *)((size_t)ret&~3UL); /* mask privilege level */ +# elif defined(__mips) || defined(__mips__) +# define INSTRUCTION_POINTER_IMPLEMENTED + void *scratch; + __asm __volatile ( "move %1,$31\n\t" /* save ra */ + "bal .+8; nop\n\t" + "move %0,$31\n\t" + "move $31,%1" /* restore ra */ + : "=r"(ret),"=r"(scratch) ); +# elif defined(__ppc__) || defined(__powerpc) || defined(__powerpc__) || \ + defined(__POWERPC__) || defined(_POWER) || defined(__PPC__) || \ + defined(__PPC64__) || defined(__powerpc64__) +# define INSTRUCTION_POINTER_IMPLEMENTED + void *scratch; + __asm __volatile ( "mfspr %1,8\n\t" /* save lr */ + "bl .+4\n\t" + "mfspr %0,8\n\t" /* mflr ret */ + "mtspr 8,%1" /* restore lr */ + : "=r"(ret),"=r"(scratch) ); +# elif defined(__sparc) || defined(__sparc__) || defined(__sparcv9) +# define INSTRUCTION_POINTER_IMPLEMENTED + void *scratch; + __asm __volatile ( "mov %%o7,%1\n\t" + "call .+8; nop\n\t" + "mov %%o7,%0\n\t" + "mov %1,%%o7" + : "=r"(ret),"=r"(scratch) ); +# elif defined(__x86_64) || defined(__x86_64__) +# define INSTRUCTION_POINTER_IMPLEMENTED + __asm __volatile ( "leaq 0(%%rip),%0" : "=r"(ret) ); + ret = (void *)((size_t)ret&~3UL); /* align for better performance */ +# endif +#elif defined(__DECC) && defined(__alpha) +# define INSTRUCTION_POINTER_IMPLEMENTED + ret = (void *)(size_t)asm("br %v0,1f\n1:"); +#elif defined(_MSC_VER) && defined(_M_IX86) +# undef INSTRUCTION_POINTER_IMPLEMENTED + void *scratch; + _asm { + call self + self: pop eax + mov scratch,eax + } + ret = (void *)((size_t)scratch&~3UL); +#endif + return ret; +} + +/* + * This function returns pointer to an instruction in the vicinity of + * its entry point, but not outside this object module. This guarantees + * that sequestered code is covered... + */ +void *FIPS_ref_point() +{ +#if defined(INSTRUCTION_POINTER_IMPLEMENTED) + return instruction_pointer(); +/* Below we essentially cover vendor compilers which do not support + * inline assembler... */ +#elif defined(_AIX) + struct { void *ip,*gp,*env; } *p = (void *)instruction_pointer; + return p->ip; +#elif defined(_HPUX_SOURCE) +# if defined(__hppa) || defined(__hppa__) + struct { void *i[4]; } *p = (void *)FIPS_ref_point; + + if (sizeof(p) == 8) /* 64-bit */ + return p->i[2]; + else if ((size_t)p & 2) + { p = (void *)((size_t)p&~3UL); + return p->i[0]; + } + else + return (void *)p; +# elif defined(__ia64) || defined(__ia64__) + struct { unsigned long long ip,gp; } *p=(void *)instruction_pointer; + return (void *)(size_t)p->ip; +# endif +#elif (defined(__VMS) || defined(VMS)) && !(defined(vax) || defined(__vax__)) + /* applies to both alpha and ia64 */ + struct { unsigned __int64 opaque,ip; } *p=(void *)instruction_pointer; + return (void *)(size_t)p->ip; +#elif defined(__VOS__) + /* applies to both pa-risc and ia32 */ + struct { void *dp,*ip,*gp; } *p = (void *)instruction_pointer; + return p->ip; +#elif defined(_WIN32) +# if defined(_WIN64) && defined(_M_IA64) + struct { void *ip,*gp; } *p = (void *)FIPS_ref_point; + return p->ip; +# else + return (void *)FIPS_ref_point; +# endif +/* + * In case you wonder why there is no #ifdef __linux. All Linux targets + * are GCC-based and therefore are covered by instruction_pointer above + * [well, some are covered by by the one below]... + */ +#elif defined(POINTER_TO_FUNCTION_IS_POINTER_TO_1ST_INSTRUCTION) + return (void *)instruction_pointer; +#else + return NULL; +#endif +} diff --git a/fips/fips_err.h b/fips/fips_err.h index f08bd060e0..c57aebf8a3 100644 --- a/fips/fips_err.h +++ b/fips/fips_err.h @@ -75,8 +75,8 @@ static ERR_STRING_DATA FIPS_str_functs[]= {ERR_FUNC(FIPS_F_DSA_DO_VERIFY), "DSA_do_verify"}, {ERR_FUNC(FIPS_F_DSA_GENERATE_PARAMETERS), "DSA_generate_parameters"}, {ERR_FUNC(FIPS_F_FIPS_CHECK_DSA), "FIPS_CHECK_DSA"}, -{ERR_FUNC(FIPS_F_FIPS_CHECK_DSO), "FIPS_CHECK_DSO"}, {ERR_FUNC(FIPS_F_FIPS_CHECK_EXE), "FIPS_CHECK_EXE"}, +{ERR_FUNC(FIPS_F_FIPS_CHECK_FINGERPRINT), "FIPS_CHECK_FINGERPRINT"}, {ERR_FUNC(FIPS_F_FIPS_CHECK_RSA), "FIPS_CHECK_RSA"}, {ERR_FUNC(FIPS_F_FIPS_DSA_CHECK), "FIPS_dsa_check"}, {ERR_FUNC(FIPS_F_FIPS_MODE_SET), "FIPS_mode_set"}, @@ -91,6 +91,7 @@ static ERR_STRING_DATA FIPS_str_functs[]= {ERR_FUNC(FIPS_F_RSA_GENERATE_KEY), "RSA_generate_key"}, {ERR_FUNC(FIPS_F_RSA_X931_GENERATE_KEY), "RSA_X931_generate_key"}, {ERR_FUNC(FIPS_F_SSLEAY_RAND_BYTES), "SSLEAY_RAND_BYTES"}, +{ERR_FUNC(FIPS_F_FIPS_CHECK_DSO), "FIPS_check_dso"}, {0,NULL} }; @@ -99,14 +100,18 @@ static ERR_STRING_DATA FIPS_str_reasons[]= {ERR_REASON(FIPS_R_CANNOT_READ_EXE) ,"cannot access executable object"}, {ERR_REASON(FIPS_R_CANNOT_READ_EXE_DIGEST),"cannot access detached digest"}, {ERR_REASON(FIPS_R_EXE_DIGEST_DOES_NOT_MATCH),"detached digest verification failed"}, +{ERR_REASON(FIPS_R_FINGERPRINT_DOES_NOT_MATCH),"fingerprint does not match"}, +{ERR_REASON(FIPS_R_FINGERPRINT_DOES_NOT_MATCH_NONPIC_RELOCATED),"fingerprint does not match, possibly because non-PIC was relocated"}, +{ERR_REASON(FIPS_R_FINGERPRINT_DOES_NOT_MATCH_SEGMENT_ALIASING),"fingerprint does not match, invalid segment aliasing"}, {ERR_REASON(FIPS_R_FIPS_MODE_ALREADY_SET),"fips mode already set"}, {ERR_REASON(FIPS_R_FIPS_SELFTEST_FAILED) ,"fips selftest failed"}, {ERR_REASON(FIPS_R_INVALID_KEY_LENGTH) ,"invalid key length"}, {ERR_REASON(FIPS_R_KEY_TOO_SHORT) ,"key too short"}, {ERR_REASON(FIPS_R_NON_FIPS_METHOD) ,"non fips method"}, -{ERR_REASON(FIPS_R_NO_DSO_PATH) ,"DSO path can't be determined"}, {ERR_REASON(FIPS_R_PAIRWISE_TEST_FAILED) ,"pairwise test failed"}, {ERR_REASON(FIPS_R_SELFTEST_FAILED) ,"selftest failed"}, +{ERR_REASON(FIPS_R_UNSUPPORTED_PLATFORM) ,"unsupported platform"}, +{ERR_REASON(FIPS_R_CONTRADICTING_EVIDENCE),"duplicate code detected, check your linking procedure"}, {0,NULL} }; @@ -114,11 +119,11 @@ static ERR_STRING_DATA FIPS_str_reasons[]= void ERR_load_FIPS_strings(void) { - static int init=1; + static int init; - if (init) + if (!init) { - init=0; + init=1; #ifndef OPENSSL_NO_ERR ERR_load_strings(0,FIPS_str_functs); ERR_load_strings(0,FIPS_str_reasons); diff --git a/fips/fips_premain.c b/fips/fips_premain.c new file mode 100644 index 0000000000..6a75d909eb --- /dev/null +++ b/fips/fips_premain.c @@ -0,0 +1,171 @@ +/* ==================================================================== + * Copyright (c) 2005 The OpenSSL Project. Rights for redistribution + * and usage in source and binary forms are granted according to the + * OpenSSL license. + */ + +#include +#include +#include +#if defined(__unix) || defined(__unix__) +#include +#endif + +#ifndef FINGERPRINT_PREMAIN_DSO_LOAD + +#if defined(__GNUC__) && __GNUC__>=2 + void FINGERPRINT_premain(void) __attribute__((constructor)); + /* Most commonly this results in pointer to premain to be dropped + * to .ctors segment, which is traversed by GCC crtbegin.o upon + * program startup. Except on a.out OpenBSD where it results in + * _GLOBAL_$I$premain() {premain();} being auto-generated by + * compiler... But one way or another this is believed to cover + * *all* GCC targets. */ +#elif defined(_MSC_VER) +# ifdef _WINDLL + __declspec(dllexport) /* this is essentially cosmetics... */ +# endif + void FINGERPRINT_premain(void); + static int premain_wrapper(void) { FINGERPRINT_premain(); return 0; } +# pragma data_seg(".CRT$XCU") + static int (*p)(void) = premain_wrapper; + /* This results in pointer to premain to appear in .CRT segment, + * which is traversed by Visual C run-time initialization code. + * This applies to both Win32 and [all flavors of] Win64. */ +# pragma data_seg() +#elif defined(__SUNPRO_C) + void FINGERPRINT_premain(void); +# pragma init(FINGERPRINT_premain) + /* This results in a call to premain to appear in .init segment. */ +#elif defined(__DECC) && (defined(__VMS) || defined(VMS)) + void FINGERPRINT_premain(void); +# pragma __nostandard + globaldef { "LIB$INITIALIZ" } readonly _align (LONGWORD) + int spare[8] = {0}; + globaldef { "LIB$INITIALIZE" } readonly _align (LONGWORD) + void (*x_FINGERPRINT_premain)(void) = FINGERPRINT_premain; + /* Refer to LIB$INITIALIZE to ensure it exists in the image. */ + int lib$initialize(); + globaldef int (*lib_init_ref)() = lib$initialize; +# pragma __standard +#elif 0 + The rest has to be taken care of through command line: + + -Wl,-init,FINGERPRINT_premain on OSF1 and IRIX + -Wl,+init,FINGERPRINT_premain on HP-UX + -Wl,-binitfini:FINGERPRINT_premain on AIX + + On ELF platforms this results in a call to premain to appear in + .init segment... +#endif + +#ifndef HMAC_SHA1_SIG +#define HMAC_SHA1_SIG "?have to make sure this string is unique" +#endif + +static const unsigned char FINGERPRINT_ascii_value[40] = HMAC_SHA1_SIG; + +#define atox(c) ((c)>='a'?((c)-'a'+10):((c)>='A'?(c)-'A'+10:(c)-'0')) + +extern const void *FIPS_text_start(), *FIPS_text_end(); +extern const unsigned char FIPS_rodata_start[], FIPS_rodata_end[]; +extern unsigned char FIPS_signature[20]; +extern unsigned int FIPS_incore_fingerprint(unsigned char *,unsigned int); + +/* + * As name suggests this code is executed prior main(). We use this + * opportunity to fingerprint sequestered code in virtual address + * space of target application. + */ +void FINGERPRINT_premain(void) +{ unsigned char sig[sizeof(FIPS_signature)]; + const unsigned char *p=FINGERPRINT_ascii_value; + unsigned int len=sizeof(sig),i; + + /* "volatilization" is done to disengage unwanted optimization... */ + if (*((volatile unsigned char *)p)=='?') + { if (FIPS_text_start()==NULL) + { fprintf(stderr,"FIPS_text_start() returns NULL\n"); + _exit(1); + } +#if defined(DEBUG_FINGERPRINT_PREMAIN) + fprintf(stderr,".text:%p+%d=%p\n",FIPS_text_start(), + (int)((size_t)FIPS_text_end()-(size_t)FIPS_text_start()), + FIPS_text_end()); + fprintf(stderr,".rodata:%p+%d=%p\n",FIPS_rodata_start, + (int)((size_t)FIPS_rodata_end-(size_t)FIPS_rodata_start), + FIPS_rodata_end); +#endif + + len=FIPS_incore_fingerprint(sig,sizeof(sig)); + + if (len!=sizeof(sig)) + { fprintf(stderr,"fingerprint length mismatch: %u\n",len); + _exit(1); + } + + for (i=0;i +#include +#include + +int main(int argc,char *argv[]) +{ DSO *dso; + DSO_FUNC_TYPE func; + BIO *bio_err; + + if (argc < 2) + { fprintf (stderr,"usage: %s libcrypto.dso\n",argv[0]); + return 1; + } + + if ((bio_err=BIO_new(BIO_s_file())) == NULL) + { fprintf (stderr,"unable to allocate BIO\n"); + return 1; + } + BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); + ERR_load_crypto_strings(); + + dso = DSO_load(NULL,argv[1],NULL,DSO_FLAG_NO_NAME_TRANSLATION); + if (dso == NULL) + { ERR_print_errors(bio_err); + return 1; + } + + /* This is not normally reached, because FINGERPRINT_premain should + * have executed and terminated application already upon DSO_load... */ + func = DSO_bind_func(dso,"FINGERPRINT_premain"); + if (func == NULL) + { ERR_print_errors(bio_err); + return 1; + } + + (*func)(); + + return 0; +} + +#endif diff --git a/fips/fips_test_suite.c b/fips/fips_test_suite.c index a127e79145..94895747e6 100644 --- a/fips/fips_test_suite.c +++ b/fips/fips_test_suite.c @@ -248,7 +248,7 @@ int main(int argc,char **argv) printf("Bad argument \"%s\"\n", argv[1]); exit(1); } - if (!FIPS_mode_set(1,argv[0])) + if (!FIPS_mode_set(1)) { ERR_load_crypto_strings(); ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE)); @@ -271,7 +271,7 @@ int main(int argc,char **argv) */ ERR_clear_error(); printf("2. Automatic power-up self test..."); - if (!FIPS_mode_set(1,argv[0])) + if (!FIPS_mode_set(1)) { ERR_load_crypto_strings(); ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE)); diff --git a/fips/fipshashes.c b/fips/fipshashes.c index a9b141938c..9d9dbef7dc 100644 --- a/fips/fipshashes.c +++ b/fips/fipshashes.c @@ -1,8 +1,10 @@ const char * const FIPS_source_hashes[] = { -"HMAC-SHA1(fips.c)= c5116c8f381d5981d840d240f66c8303b866f5f6", +"HMAC-SHA1(fips.c)= 3a2deb3c319512952bf5547ed92116a7e0db472b", "HMAC-SHA1(fips_err_wrapper.c)= d3e2be316062510312269e98f964cb87e7577898", -"HMAC-SHA1(fips.h)= c9f7bfc3cd78ef7bfcf863b92dcb6e477384e300", -"HMAC-SHA1(fips_err.h)= f124e9f93777ca7f5bc6edd8323ffbb36625d40b", +"HMAC-SHA1(fips.h)= 57d602d18efe0594f806fbcc64269e9440638ef4", +"HMAC-SHA1(fips_err.h)= e0649ee1d60c8162f7eeb293f89f3b63ac85202a", +"HMAC-SHA1(fips_canister.c)= da6d0f5daf9594881fd060773a5f3e057ba302ff", +"HMAC-SHA1(fips_premain.c)= 6a08d15c578f1258246181bf52134ae974aa5a80", "HMAC-SHA1(aes/fips_aes_core.c)= b70bbbd675efe0613da0d57055310926a0104d55", "HMAC-SHA1(aes/asm/fips-ax86-elf.s)= f797b524a79196e7f59458a5b223432fcfd4a868", "HMAC-SHA1(aes/fips_aes_selftest.c)= 98b01502221e7fe529fd981222f2cbb52eb4cbe0", diff --git a/fips/fipsld b/fips/fipsld new file mode 100755 index 0000000000..acb6f6542c --- /dev/null +++ b/fips/fipsld @@ -0,0 +1,136 @@ +#!/bin/sh -e +# +# Copyright (c) 2005 The OpenSSL Project. +# +# Depending on output file name, the script either embeds fingerprint +# into libcrypto.so or static application. "Static" refers to static +# libcrypto.a, not [necessarily] application per se. +# +# Even though this script is called fipsld, it expects C compiler +# command line syntax and $FIPSLD_CC or $CC environment variable set +# and can even be used to compile source files. + +CC=${FIPSLD_CC:-${CC}} +[ -n "${CC}" ] || { echo '$CC is not defined'; exit 1; } + +# Initially -c wasn't intended to be interpreted here, but it might +# make life easier for those who want to build FIPS-ified applications +# with minimal [if any] modifications to their Makefiles... +( while [ "x$1" != "x" -a "x$1" != "x-c" ]; do shift; done; + [ $# -ge 1 ] +) && exec ${CC} "$@" + +# Turn on debugging output? +( while [ "x$1" != "x" -a "x$1" != "x-DDEBUG_FINGERPRINT_PREMAIN" ]; do shift; done; + [ $# -ge 1 ] +) && set -x + +TARGET=`(while [ "x$1" != "x" -a "x$1" != "x-o" ]; do shift; done; echo $2)` +[ -n "${TARGET}" ] || { echo 'no -o specified'; exit 1; } + +THERE="`echo $0 | sed -e 's|[^/]*$||'`".. + +HMAC_KEY="etaonrishdlcupfm" + +case "`(uname -s) 2>/dev/null`" in +OSF1|IRIX*) _WL_PREMAIN="-Wl,-init,FINGERPRINT_premain" ;; +HP-UX) _WL_PREMAIN="-Wl,+init,FINGERPRINT_premain" ;; +AIX) _WL_PREMAIN="-Wl,-binitfini:FINGERPRINT_premain";; +Darwin) ( while [ "x$1" != "x" -a "x$1" != "x-dynamiclib" ]; do shift; done; + [ $# -ge 1 ] + ) && _WL_PREMAIN="-Wl,-init,_FINGERPRINT_premain" ;; +esac + +case "${TARGET}" in +[!/]*) TARGET=./${TARGET} ;; +esac + +case "${TARGET}" in +*libcrypto*|*.dll) # must be linking a shared lib... + # Shared lib creation can be taking place in the source + # directory only!!! + FINGERTYPE="${THERE}/fips/sha/fips_standalone_sha1" + CANISTER_O="${THERE}/fips/fipscanister.o" + PREMAIN_C="${THERE}/fips/fips_premain.c" + + # verify fipscanister.o against its detached signature... + ${FINGERTYPE} "${CANISTER_O}" | sed "s/(.*\//(/" | \ + diff -w "${CANISTER_O}.sha1" - || \ + { echo "${CANISTER_O} fingerprint mismatch"; exit 1; } + + # verify fips_premain.c against its signature embedded into + # fipscanister.o... + SIG=`${FINGERTYPE} "${PREMAIN_C}" | sed -n "s/(.*\//(/;/^./p"` + REF=`strings "${CANISTER_O}" | grep "HMAC-SHA1(fips_premain\\.c)"` + [ "${SIG}" = "${REF}" ] || \ + { echo "${PREMAIN_C} fingerprint mismatch"; exit 1; } + + # Temporarily remove fipscanister.o from libcrypto.a! + # We are required to use the standalone copy... + trap 'ar r "${THERE}/libcrypto.a" "${CANISTER_O}"; + (ranlib "${THERE}/libcrypto.a") 2>/dev/null; + sleep 1; + touch -c "${TARGET}"' 0 + + ar d "${THERE}/libcrypto.a" fipscanister.o 2>&1 > /dev/null || : + (ranlib "${THERE}/libcrypto.a") 2>/dev/null || : + + ${CC} "${CANISTER_O}" \ + "${PREMAIN_C}" \ + ${_WL_PREMAIN} "$@" + + # generate signature... + SIG=`("${THERE}/fips/fips_premain_dso" "${TARGET}" || rm "${TARGET}")` + if [ -z "${SIG}" ]; then + echo "unable to collect signature"; exit 1 + fi + + # recompile with signature... + ${CC} "${CANISTER_O}" \ + -DHMAC_SHA1_SIG=\"${SIG}\" "${PREMAIN_C}" \ + ${_WL_PREMAIN} "$@" + ;; + +*) # must be linking statically... + # Static linking can be taking place either in the source + # directory or off the installed binary target destination. + if [ -x "${THERE}/fips/sha/fips_standalone_sha1" ]; then + FINGERTYPE="${THERE}/fips/sha/fips_standalone_sha1" + CANISTER_O="${THERE}/fips/fipscanister.o" + PREMAIN_C="${THERE}/fips/fips_premain.c" + else # Installed tree is expected to contain + # lib/fipscanister.o, lib/fipscanister.o.sha1 and + # lib/fips_premain.c [not to mention bin/openssl]. + FINGERTYPE="${THERE}/bin/openssl sha1 -hmac ${HMAC_KEY}" + CANISTER_O="${THERE}/lib/fipscanister.o" + PREMAIN_C="${THERE}/lib/fips_premain.c" + fi + + # verify fipscanister.o against its detached signature... + ${FINGERTYPE} "${CANISTER_O}" | sed "s/(.*\//(/" | \ + diff -w "${CANISTER_O}.sha1" - || \ + { echo "${CANISTER_O} fingerprint mismatch"; exit 1; } + + # verify fips_premain.c against its signature embedded into + # fipscanister.o... + SIG=`${FINGERTYPE} "${PREMAIN_C}" | sed -n "s/(.*\//(/;/^./p"` + REF=`strings "${CANISTER_O}" | grep "HMAC-SHA1(fips_premain\\.c)"` + [ "${SIG}" = "${REF}" ] || \ + { echo "${PREMAIN_C} fingerprint mismatch"; exit 1; } + + ${CC} "${CANISTER_O}" \ + "${PREMAIN_C}" \ + ${_WL_PREMAIN} "$@" + + # generate signature... + SIG=`("${TARGET}" || /bin/rm "${TARGET}")` + if [ -z "${SIG}" ]; then + echo "unable to collect signature"; exit 1 + fi + + # recompile with signature... + ${CC} "${CANISTER_O}" \ + -DHMAC_SHA1_SIG=\"${SIG}\" "${PREMAIN_C}" \ + ${_WL_PREMAIN} "$@" + ;; +esac diff --git a/fips/hmac/fips_hmactest.c b/fips/hmac/fips_hmactest.c index a686a2258a..e26e33ee3f 100644 --- a/fips/hmac/fips_hmactest.c +++ b/fips/hmac/fips_hmactest.c @@ -96,7 +96,7 @@ int main(int argc, char **argv) goto end; } - if(!FIPS_mode_set(1,argv[0])) + if(!FIPS_mode_set(1)) { ERR_print_errors(err); goto end; diff --git a/fips/rand/Makefile b/fips/rand/Makefile index 8b97d26129..ecd9a63711 100644 --- a/fips/rand/Makefile +++ b/fips/rand/Makefile @@ -38,9 +38,7 @@ top: all: lib lib: $(LIBOBJ) - $(AR) $(LIB) $(LIBOBJ) - $(RANLIB) $(LIB) || echo Never mind. - @sleep 2; touch lib + @echo $(LIBOBJ) > lib files: $(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO diff --git a/fips/rand/fips_rngvs.c b/fips/rand/fips_rngvs.c index aebba3a72a..2c3fdbcca7 100644 --- a/fips/rand/fips_rngvs.c +++ b/fips/rand/fips_rngvs.c @@ -213,7 +213,7 @@ int main(int argc,char **argv) fprintf(stderr,"%s [mct|vst]\n",argv[0]); exit(1); } - if(!FIPS_mode_set(1,argv[0])) + if(!FIPS_mode_set(1)) { ERR_load_crypto_strings(); ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE)); diff --git a/fips/rsa/Makefile b/fips/rsa/Makefile index 03986beb29..810c28d300 100644 --- a/fips/rsa/Makefile +++ b/fips/rsa/Makefile @@ -38,9 +38,7 @@ top: all: lib lib: $(LIBOBJ) - $(AR) $(LIB) $(LIBOBJ) - $(RANLIB) $(LIB) || echo Never mind. - @sleep 2; touch lib + @echo $(LIBOBJ) > lib files: $(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO diff --git a/fips/rsa/fips_rsagtest.c b/fips/rsa/fips_rsagtest.c index f3b05aaec6..15d3225d53 100644 --- a/fips/rsa/fips_rsagtest.c +++ b/fips/rsa/fips_rsagtest.c @@ -103,7 +103,7 @@ int main(int argc, char **argv) goto end; } - if(!FIPS_mode_set(1,argv[0])) + if(!FIPS_mode_set(1)) { ERR_print_errors(err); goto end; diff --git a/fips/rsa/fips_rsastest.c b/fips/rsa/fips_rsastest.c index 7c5fa9c598..880dd636a7 100644 --- a/fips/rsa/fips_rsastest.c +++ b/fips/rsa/fips_rsastest.c @@ -94,7 +94,7 @@ int main(int argc, char **argv) goto end; } - if(!FIPS_mode_set(1,argv[0])) + if(!FIPS_mode_set(1)) { ERR_print_errors(err); goto end; diff --git a/fips/rsa/fips_rsavtest.c b/fips/rsa/fips_rsavtest.c index 1a3a1db5d1..7e2c40424d 100644 --- a/fips/rsa/fips_rsavtest.c +++ b/fips/rsa/fips_rsavtest.c @@ -98,7 +98,7 @@ int main(int argc, char **argv) goto end; } - if(!FIPS_mode_set(1,argv[0])) + if(!FIPS_mode_set(1)) { ERR_print_errors(err); goto end; diff --git a/fips/sha/Makefile b/fips/sha/Makefile index 026a81014c..4ed2ca2ad5 100644 --- a/fips/sha/Makefile +++ b/fips/sha/Makefile @@ -43,9 +43,7 @@ top: all: fips_standalone_sha1$(EXE_EXT) lib lib: $(LIBOBJ) - $(AR) $(LIB) $(LIBOBJ) - $(RANLIB) $(LIB) || echo Never mind. - @sleep 2; touch lib + @echo $(LIBOBJ) > lib fips_standalone_sha1$(EXE_EXT): fips_standalone_sha1.o fips_sha1dgst.o $(FIPS_SHA1_ASM_OBJ) $(CC) -o fips_standalone_sha1$(EXE_EXT) $(CFLAGS) \ diff --git a/fips/sha/fips_shatest.c b/fips/sha/fips_shatest.c index 2e42bdd21e..4896b467e4 100644 --- a/fips/sha/fips_shatest.c +++ b/fips/sha/fips_shatest.c @@ -96,7 +96,7 @@ int main(int argc, char **argv) goto end; } - if(!FIPS_mode_set(1,argv[0])) + if(!FIPS_mode_set(1)) { ERR_print_errors(err); goto end; diff --git a/ssl/ssltest.c b/ssl/ssltest.c index a246a76b91..9845ef99ed 100644 --- a/ssl/ssltest.c +++ b/ssl/ssltest.c @@ -391,7 +391,6 @@ int main(int argc, char *argv[]) COMP_METHOD *cm = NULL; #ifdef OPENSSL_FIPS int fips_mode=0; - const char *path=argv[0]; #endif verbose = 0; @@ -594,7 +593,7 @@ bad: #ifdef OPENSSL_FIPS if(fips_mode) { - if(!FIPS_mode_set(1,path)) + if(!FIPS_mode_set(1)) { ERR_load_crypto_strings(); ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE)); diff --git a/test/Makefile b/test/Makefile index 8d250327f3..43c323c18e 100644 --- a/test/Makefile +++ b/test/Makefile @@ -336,12 +336,9 @@ BUILD_CMD=SHARED_LIBS="$(SHARED_LIBS)"; \ $(CC) -o $$target$(EXE_EXT) $(CFLAGS) $$target.o $(PEX_LIBS) $(LIBSSL) $(LIBKRB5) $(LIBCRYPTO) $(EX_LIBS) ; \ fi -FIPS_BUILD_CMD=$(BUILD_CMD); \ - if [ -z "$$SHARED_LIBS" ]; then \ - if egrep 'define OPENSSL_FIPS' $(TOP)/include/openssl/opensslconf.h > /dev/null; then \ - TOP=$(TOP) $(TOP)/fips/openssl_fips_fingerprint $(TOP)/libcrypto.a $$target; \ - fi; \ - fi +FIPS_BUILD_CMD=if egrep 'define OPENSSL_FIPS' $(TOP)/include/openssl/opensslconf.h > /dev/null; then \ + FIPSLD_CC=$(CC); CC=$(TOP)/fips/fipsld; export CC FIPSLD_CC; \ + fi; $(BUILD_CMD) $(FIPS_AESTEST)$(EXE_EXT): $(FIPS_AESTEST).o $(DLIBCRYPTO) @target=$(FIPS_AESTEST); $(FIPS_BUILD_CMD) -- 2.25.1