summaryrefslogtreecommitdiff
path: root/buildscripts/fipsld
blob: f03713dd74eabf8d43dab5f8c361bfd5ff769827 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#!/bin/sh -e
#
# Copyright (c) 2005-2011 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.

#set -x

# Note: edit this to point to your copy of g++ if this is not correct.
CC="/usr/bin/g++"

# 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" -a "x$1" != "x-E" ]; do shift; done;
    [ $# -ge 1 ]
) && exec ${CC} "$@"

TARGET=`(while [ "x$1" != "x" -a "x$1" != "x-o" ]; do shift; done; echo $2)`

# If using an auto-tooled (autoconf/automake/libtool) project,
# configure will fail when testing the compiler or even performing
# simple checks. Pass-through to compiler directly if application is
# is not being linked with libcrypto, allowing auto-tooled applications
# to utilize fipsld (e.g. CC=/usr/local/ssl/bin/fipsld FIPSLD_CC=gcc
# ./configure && make). But keep in mind[!] that if certified code
# resides in a shared library, then fipsld *may not* be used and
# end-developer should not modify application configuration and build
# procedures. This is because in-core fingerprint and associated
# procedures are already embedded into and executed in shared library
# context.
case `basename "${TARGET}"` in
libcrypto*|libfips*|*.dll)		;;
*)	case "$*" in
	*libcrypto.a*|*-lcrypto*|*fipscanister.o*)	;;
	*)	exec ${CC} "$@"		;;
	esac
esac

[ -n "${TARGET}" ] || { echo 'no -o specified'; exit 1; }

# Turn on debugging output?
(   while [ "x$1" != "x" -a "x$1" != "x-DDEBUG_FINGERPRINT_PREMAIN" ]; do shift; done;
    [ $# -ge 1 ]
) && set -x

THERE="`echo $0 | sed -e 's|[^/]*$||'`"..

# fipscanister.o can appear in command line
CANISTER_O=`(while [ "x$1" != "x" ]; do case "$1" in *fipscanister.o) echo $1; exit;; esac; shift; done)`
if [ -z "${CANISTER_O}" ]; then
	# If set, FIPSLIBDIR is location of installed validated FIPS module
	if [ -n "${FIPSLIBDIR}" ]; then
		CANISTER_O="${FIPSLIBDIR}/fipscanister.o"
	elif [ -f "${THERE}/fips/fipscanister.o" ]; then
		CANISTER_O="${THERE}/fips/fipscanister.o"
	elif [ -f "${THERE}/lib/fipscanister.o" ]; then
		CANISTER_O="${THERE}/lib/fipscanister.o"
	fi
	CANISTER_O_CMD="${CANISTER_O}"
fi
[ -f ${CANISTER_O} ] || { echo "unable to find ${CANISTER_O}"; exit 1; }

PREMAIN_C=`dirname "${CANISTER_O}"`/fips_premain.c
PREMAIN_O=`dirname "${CANISTER_O}"`/fips_premain.o

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,-bnoobjreorder";;
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 `basename "${TARGET}"` in
lib*|*.dll)	# must be linking a shared lib...
	# Shared lib creation can be taking place in the source
	# directory only, but fipscanister.o can reside elsewhere...

	if [ -x "${THERE}/fips/fips_standalone_sha1" ]; then
		FINGERTYPE="${THERE}/fips/fips_standalone_sha1"
		PREMAIN_DSO="${THERE}/fips/fips_premain_dso"
	elif [ -x "${THERE}/bin/fips_standalone_sha1" ]; then
		FINGERTYPE="${THERE}/bin/fips_standalone_sha1"
		PREMAIN_DSO="./fips_premain_dso"
	fi

	# verify fipspremain.c against its detached signature...
	${FINGERTYPE} "${PREMAIN_C}" | sed "s/(.*\//(/" | \
		diff -w "${PREMAIN_C}.sha1" - || \
	{ echo "${PREMAIN_C} fingerprint mismatch"; exit 1; }
	# verify fipscanister.o against its detached signature...
	${FINGERTYPE} "${CANISTER_O}" | sed "s/(.*\//(/" | \
		diff -w "${CANISTER_O}.sha1" - || \
	{ echo "${CANISTER_O} fingerprint mismatch"; exit 1; }

	[ -z "${FIPSLD_LIBCRYPTO}" -a -f "${THERE}/libcrypto.a" ] && \
		FIPSLD_LIBCRYPTO="${THERE}/libcrypto.a"
		

	# Temporarily remove fipscanister.o from libcrypto.a!
	# We are required to use the standalone copy...
	if [ -n  "${FIPSLD_LIBCRYPTO}" ]; then
	    if ar d "${FIPSLD_LIBCRYPTO}" fipscanister.o; then
		(ranlib "${FIPSLD_LIBCRYPTO}") 2>/dev/null || :
		trap	'ar r "${FIPSLD_LIBCRYPTO}" "${CANISTER_O}";
			 (ranlib "${FIPSLD_LIBCRYPTO}") 2>/dev/null || :;
			 sleep 1;
			 touch -c "${TARGET}"' 0
	    fi
	fi

	/bin/rm -f "${TARGET}"
        ${CC} -x c "${PREMAIN_C}" -c -o "${PREMAIN_O}"
	${CC}	${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \
		"${PREMAIN_O}" \
		${_WL_PREMAIN} "$@"

	if [ "x${FIPS_SIG}" != "x" ]; then
		# embed signature
		"${FIPS_SIG}" "${TARGET}"
		[ $? -ne 42 ] && exit $?
	fi

	# generate signature...
	SIG=`"${PREMAIN_DSO}" "${TARGET}"`

	/bin/rm -f "${TARGET}"
	if [ -z "${SIG}" ]; then
	   echo "unable to collect signature"; exit 1
	fi

	# recompile with signature...
        ${CC} -x c -DHMAC_SHA1_SIG=\"${SIG}\" "${PREMAIN_C}" -c -o "${PREMAIN_O}"
	${CC}	${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \
		-DHMAC_SHA1_SIG=\"${SIG}\" "${PREMAIN_O}" \
		${_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/fips_standalone_sha1" ]; then
		FINGERTYPE="${THERE}/fips/fips_standalone_sha1"
	elif [ -x "${THERE}/bin/fips_standalone_sha1" ]; then
		FINGERTYPE="${THERE}/bin/fips_standalone_sha1"
	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="openssl sha1 -hmac ${HMAC_KEY}"
	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 detached signature...
	${FINGERTYPE} "${PREMAIN_C}" | sed "s/(.*\//(/" | \
		diff -w "${PREMAIN_C}.sha1" - || \
	{ echo "${PREMAIN_C} fingerprint mismatch"; exit 1; }

	/bin/rm -f "${TARGET}"
        ${CC} -x c "${PREMAIN_C}" -c -o "${PREMAIN_O}"
	${CC}	${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \
		"${PREMAIN_O}" \
		${_WL_PREMAIN} "$@"
	
	if [ "x${FIPS_SIG}" != "x" ]; then
		# embed signature
		"${FIPS_SIG}" "${TARGET}"
		[ $? -ne 42 ] && exit $?
	fi

	# generate signature...
	SIG=`"${TARGET}"`

	/bin/rm -f "${TARGET}"
	if [ -z "${SIG}" ]; then
	   echo "unable to collect signature"; exit 1
	fi

	# recompile with signature...
        ${CC} -x c -DHMAC_SHA1_SIG=\"${SIG}\" "${PREMAIN_C}" -c -o "${PREMAIN_O}"
	${CC}	${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \
		-DHMAC_SHA1_SIG=\"${SIG}\" "${PREMAIN_O}" \
		${_WL_PREMAIN} "$@"
	;;
esac