aboutsummaryrefslogtreecommitdiff
path: root/src/crypto/internal/boring/build/build_in_chroot.sh
blob: 73597e11fded1bc23aa79b6dd1bd2a6abcd66558 (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
#!/bin/bash
# Copyright 2017 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.

set -e
echo running build_in_chroot.sh
id
date
export LANG=C
unset LANGUAGE

# Build BoringCrypto libcrypto.a.
# Following https://csrc.nist.gov/CSRC/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp3318.pdf page 19.
if ! [ -e ./boringssl/build/tool/bssl ]; then
	export PATH=$PATH:/usr/lib/go-1.10/bin:/clangbin

	# Go requires -fPIC for linux/amd64 cgo builds.
	# Setting -fPIC only affects the compilation of the non-module code in libcrypto.a,
	# because the FIPS module itself is already built with -fPIC.
	mkdir /clangbin
	echo '#!/bin/bash
	exec clang-6.0 -fPIC "$@"
	' >/clangbin/clang
	echo '#!/bin/bash
	exec clang++-6.0 -fPIC "$@"
	' >/clangbin/clang++
	chmod +x /clangbin/clang /clangbin/clang++

	rm -rf boringssl
	tar xJf ../boringssl-*z
	cd boringssl

	# Verbatim instructions from BoringCrypto build docs.
	printf "set(CMAKE_C_COMPILER \"clang\")\nset(CMAKE_CXX_COMPILER \"clang++\")\n" >${HOME}/toolchain
	mkdir build && cd build && cmake -GNinja -DCMAKE_TOOLCHAIN_FILE=${HOME}/toolchain -DFIPS=1 -DCMAKE_BUILD_TYPE=Release ..
	ninja
	ninja run_tests

	cd ../..
fi
if [ "$(./boringssl/build/tool/bssl isfips)" != 1 ]; then
	echo "NOT FIPS"
	exit 2
fi


# Build and run test C++ program to make sure goboringcrypto.h matches openssl/*.h.
# Also collect list of checked symbols in syms.txt
set -x
set -e
cd godriver
cat >goboringcrypto.cc <<'EOF'
#include <cassert>
#include "goboringcrypto0.h"
#include "goboringcrypto1.h"
#define check_size(t) if(sizeof(t) != sizeof(GO_ ## t)) {printf("sizeof(" #t ")=%d, but sizeof(GO_" #t ")=%d\n", (int)sizeof(t), (int)sizeof(GO_ ## t)); ret=1;}
#define check_func(f) { auto x = f; x = _goboringcrypto_ ## f ; }
#define check_value(n, v) if(n != v) {printf(#n "=%d, but goboringcrypto.h defines it as %d\n", (int)n, (int)v); ret=1;}
int main() {
int ret = 0;
#include "goboringcrypto.x"
return ret;
}
EOF

awk '
BEGIN {
	exitcode = 0
}

# Ignore comments, #includes, blank lines.
/^\/\// || /^#/ || NF == 0 { next }

# Ignore unchecked declarations.
/\/\*unchecked/ { next }

# Check enum values.
!enum && $1 == "enum" && $NF == "{" {
	enum = 1
	next
}
enum && $1 == "};" {
	enum = 0
	next
}
enum && NF == 3 && $2 == "=" {
	name = $1
	sub(/^GO_/, "", name)
	val = $3
	sub(/,$/, "", val)
	print "check_value(" name ", " val ")" > "goboringcrypto.x"
	next
}
enum {
	print FILENAME ":" NR ": unexpected line in enum: " $0 > "/dev/stderr"
	exitcode = 1
	next
}

# Check struct sizes.
/^typedef struct / && $NF ~ /^GO_/ {
	name = $NF
	sub(/^GO_/, "", name)
	sub(/;$/, "", name)
	print "check_size(" name ")" > "goboringcrypto.x"
	next
}

# Check function prototypes.
/^(const )?[^ ]+ \**_goboringcrypto_.*\(/ {
	name = $2
	if($1 == "const")
		name = $3
	sub(/^\**_goboringcrypto_/, "", name)
	sub(/\(.*/, "", name)
	print "check_func(" name ")" > "goboringcrypto.x"
	print name > "syms.txt"
	next
}

{
	print FILENAME ":" NR ": unexpected line: " $0 > "/dev/stderr"
	exitcode = 1
}

END {
	exit exitcode
}
' goboringcrypto.h

cat goboringcrypto.h | awk '
	/^\/\/ #include/ {sub(/\/\//, ""); print > "goboringcrypto0.h"; next}
	/typedef struct|enum ([a-z_]+ )?{|^[ \t]/ {print;next}
	{gsub(/GO_/, ""); gsub(/enum go_/, "enum "); print}
' >goboringcrypto1.h
clang++-6.0 -std=c++11 -fPIC -I../boringssl/include -O2 -o a.out  goboringcrypto.cc
./a.out || exit 2

# Prepare copy of libcrypto.a with only the checked functions renamed and exported.
# All other symbols are left alone and hidden.
echo BORINGSSL_bcm_power_on_self_test >>syms.txt
awk '{print "_goboringcrypto_" $0 }' syms.txt >globals.txt
awk '{print $0 " _goboringcrypto_" $0 }' syms.txt >renames.txt
objcopy --globalize-symbol=BORINGSSL_bcm_power_on_self_test ../boringssl/build/crypto/libcrypto.a libcrypto.a

# clang implements u128 % u128 -> u128 by calling __umodti3,
# which is in libgcc. To make the result self-contained even if linking
# against a different compiler version, link our own __umodti3 into the syso.
# This one is specialized so it only expects divisors below 2^64,
# which is all BoringCrypto uses. (Otherwise it will seg fault.)
cat >umod.s <<'EOF'
# tu_int __umodti3(tu_int x, tu_int y)
# x is rsi:rdi, y is rcx:rdx, return result is rdx:rax.
.globl __umodti3
__umodti3:
	# specialized to u128 % u64, so verify that
	test %rcx,%rcx
	jne 1f

	# save divisor
	movq %rdx, %r8

	# reduce top 64 bits mod divisor
	movq %rsi, %rax
	xorl %edx, %edx
	divq %r8

	# reduce full 128-bit mod divisor
	# quotient fits in 64 bits because top 64 bits have been reduced < divisor.
	# (even though we only care about the remainder, divq also computes
	# the quotient, and it will trap if the quotient is too large.)
	movq %rdi, %rax
	divq %r8

	# expand remainder to 128 for return
	movq %rdx, %rax
	xorl %edx, %edx
	ret

1:
	# crash - only want 64-bit divisor
	xorl %ecx, %ecx
	movl %ecx, 0(%ecx)
	jmp 1b

.section .note.GNU-stack,"",@progbits
EOF
clang-6.0 -c -o umod.o umod.s

ld -r -nostdlib --whole-archive -o goboringcrypto.o libcrypto.a umod.o
echo __umodti3 _goboringcrypto___umodti3 >>renames.txt
objcopy --redefine-syms=renames.txt goboringcrypto.o goboringcrypto2.o
objcopy --keep-global-symbols=globals.txt goboringcrypto2.o goboringcrypto_linux_amd64.syso

# Done!
ls -l goboringcrypto_linux_amd64.syso
sha256sum goboringcrypto_linux_amd64.syso