universal8895: set blk loop min to 16
[GitHub/exynos8895/android_kernel_samsung_universal8895.git] / scripts / fips_kaslr_crypto_hmac.sh
1 #!/bin/bash
2
3 # fips_crypto_hmac.sh
4 #
5 # Author : Rohit Kothari (r.kothari@samsung.com)
6 # Created on : 14 Feb 2014
7 # Modified on: 22 Jun 2015 by Jia Ma (jia.ma@samsung.com) /* To adapt to KASLR change */
8 # Modified on: 09 Jul 2015 by Wenbo Shen (wenbo.s@samsung.com) /* To reduce the hmac generation time */
9 # Copyright (c) Samsung Electronics 2014
10
11 # Given a vmlinux file and a System.map, this scripts finds bytes belonging to
12 # Kernel Crypto within vmlinux file.(Under section .text, .init.text, .exit.text and .rodata)
13 # After collecting all the bytes, it calculates a hmac(sha256) on those bytes.
14 # Generated hmac is put back into a crypto rodata variable within vmlinux file itself.
15 # This makes the build time hmac available at runtime, for integrity check.
16 #
17 # To find crypto bytes, this scripts heavily relies on output of arm-eabi-readelf.
18 # If the output of arm-eabi-readelf changes in future, this script might need changes.
19 #
20 # Pre-conditions : $READELF, $HOSTCC variables are set.
21 #
22 #
23
24 # Here we want to seperate the oneshot code from the repeated code
25 ################ the repeated code ####################
26 kaslr_patch () {
27 index=$1
28 ./kaslr_fips $vmlinux_var $reloc_start_addr $reloc_end_addr $dynsym_addr $index $first_crypto_rodata $last_crypto_rodata $first_fmp_rodata $last_fmp_rodata $2
29 retval=$?
30 if [ $retval -ne 0 ]; then
31 echo "$0 : kaslr_fips : unable to patch the vmlinux"
32 exit 1
33 fi
34 }
35
36 hmac_patch() {
37 index=$1
38 offsets_sizes_file=$2
39
40 if [ "$3" == "crypto" ]; then
41 fips_utils=./fips_crypto_utils
42 hmac_offset=`expr $crypto_hmac_offset_base + $((32*$index)) `
43 elif [ "$3" == "fmp" ]; then
44 fips_utils=./fips_fmp_utils
45 hmac_offset=`expr $fmp_hmac_offset_base + $((32*$index)) `
46 fi
47
48 rm -f builtime_bytes.txt #used for debugging
49 rm -f builtime_bytes.bin #used for calculating hmac
50
51 date_var=`date`
52 echo "Created on : " $date_var > builtime_bytes.txt
53
54
55 #Using offsets_sizes.txt, dump crypto bytes from vmlinux file into builtime_bytes.bin
56 #Also gather printf's into builtime_bytes.txt, for debugging if required
57 while read args; do
58 $fips_utils -g $vmlinux_var $args builtime_bytes.bin >> builtime_bytes.txt
59 retval=$?
60 if [ $retval -ne 0 ]; then
61 echo "$0 : $fips_utils : unable to gather $3 bytes from vmlinux"
62 exit 1
63 fi
64 echo "" >> builtime_bytes.txt
65 done < $offsets_sizes_file
66
67
68 if [[ ! -f builtime_bytes.bin ]]; then
69 echo "$0 : builtime_bytes.bin does not exist"
70 exit 1
71 fi
72
73 #file_size=`cat builtime_bytes.bin| wc -c`
74
75 # Make sure that file size of crypto_hmac.bin is as expected
76 #if [ $total_bytes -ne $file_size ]; then
77 #echo "$0: Bytes mismatch"
78 #exit 1
79 #fi
80
81
82 key="The quick brown fox jumps over the lazy dog"
83
84 # Now, generate the hmac.
85 openssl dgst -sha256 -hmac "$key" -binary -out crypto_hmac.bin builtime_bytes.bin
86 retval=$?
87 if [ $retval -ne 0 ]; then
88 echo "$0 : openssl dgst command returned error"
89 exit 1
90 fi
91
92 # Just, for debugging, print the same hmac on console
93 #openssl dgst -sha256 -hmac "$key" builtime_bytes.bin
94
95 if [[ ! -f crypto_hmac.bin ]]; then
96 echo "$0 : crypto_hmac.bin does not exist"
97 exit 1
98 fi
99
100 file_size=`cat crypto_hmac.bin| wc -c`
101
102 # hmac(sha256) produces 32 bytes of hmac
103 if [ $file_size -ne 32 ]; then
104 echo "$0: Unexpected size of Hash file : " $file_size
105 exit 1
106 fi
107
108 # Now that we have the hmac, update this hmac into an rodata "builtime_crypto_hmac" varialble
109 # in vmlinux file.
110 # This variable has a place holder 32 bytes that will be over-written with generated hmac.
111 # This way, this build time hmac, will be available as a read-only variable at run-time.
112
113 if [[ $hmac_offset -le 0 ]]; then echo "$0 : hmac_offset invalid"; exit 1; fi
114
115 # This does the actual update of hmac into vmlinux file, at given offset
116 $fips_utils -u $vmlinux_var crypto_hmac.bin $hmac_offset
117 retval=$?
118 if [ $retval -ne 0 ]; then
119 echo "$0 : fips_crypto_utils : unable to update hmac in vmlinux"
120 exit 1
121 fi
122
123 rm -f crypto_hmac.bin
124 rm -f builtime_bytes.txt
125 rm -f builtime_bytes.bin
126 }
127
128 ################ the kaslr patch oneshot code ####################
129 # 1st parameter is the array, 2nd is the output file name
130 offsets_sizes_gen(){
131 name=$1[@]
132 array=("${!name}")
133
134 outfile=$2
135 rm -f $outfile
136
137 #Addresses retrieved must be a valid hex
138 reg='^[0-9A-Fa-f]+$'
139
140 #Total bytes of all crypto sections scanned. Used later for error checking
141 #total_bytes=0;
142
143 # For each type of Section :
144 # first_addr = Address of first_crypto_text, first_crypto_rodata, etc.
145 # last_addr = Address of last_crypto_text, last_crypto_rodata etc.
146 # start_addr = Starting Address of a section within vmlinux
147 # offset = Offset in vmlinux file where the section begins
148 # file_offset = Offset in vmlinux file where the crypto bytes begins.
149 # size = size of crypto bytes.
150
151 # Output is offsets_sizes.txt, of the format
152 # Section Name crypto_bytes_offset crypto_bytes_size
153 # (in decimal) (in decimal)
154 # .text 2531072 114576
155 # .rodata 9289648 55388
156 # : : :
157
158 for i in "${array[@]}"; do
159
160 var1=var2=var3=var4=var5=""
161 first_addr=last_addr=start_addr=offset=file_offset=size=""
162 k=1
163 #This loop creates var1, var2 etc and set them to individual strings of a row in array
164 for j in $i; do
165 export var$k=$j
166 let k+=1
167 done
168
169 first_addr=`cat $system_map_var|grep -w $var2|awk '{print $1}'`
170 if [[ ! $first_addr =~ $reg ]]; then echo "$0 : first_addr invalid"; exit 1; fi
171
172 last_addr=`cat $system_map_var|grep -w $var3|awk '{print $1}'`
173 if [[ ! $last_addr =~ $reg ]]; then echo "$0 : last_addr invalid"; exit 1; fi
174
175 start_addr=`cat vmlinux.elf |grep -w "$var1 "|grep PROGBITS|awk '{print '$var4'}'`
176 if [[ ! $start_addr =~ $reg ]]; then echo "$0 : start_addr invalid"; exit 1; fi
177
178 offset=`cat vmlinux.elf |grep -w "$var1 "|grep PROGBITS|awk '{print '$var5'}'`
179 if [[ ! $offset =~ $reg ]]; then echo "$0 : offset invalid"; exit 1; fi
180
181 if [[ $((16#$first_addr)) -lt $((16#$start_addr)) ]]; then echo "$0 : first_addr < start_addr"; exit 1; fi
182
183 if [[ $((16#$last_addr)) -le $((16#$first_addr)) ]]; then echo "$0 : last_addr <= first_addr"; exit 1; fi
184
185 file_offset=`expr $((16#$offset)) + $((16#$first_addr)) - $((16#$start_addr))`
186 if [[ $file_offset -le 0 ]]; then echo "$0 : file_offset invalid"; exit 1; fi
187
188 size=`expr $((16#$last_addr)) - $((16#$first_addr))`
189 if [[ $size -le 0 ]]; then echo "$0 : crypto section size invalid"; exit 1; fi
190
191 echo "$var1 " $file_offset " " $size >> $outfile
192
193 #let "total_bytes += `expr $((16#$last_addr)) - $((16#$first_addr))`"
194 done
195
196 if [[ ! -f $outfile ]]; then
197 echo "$0 : offset_sizes.txt does not exist"
198 exit 1
199 fi
200
201
202 }
203
204 cal_hmac_offset(){
205 first_addr=`cat $system_map_var|grep -w $1|awk '{print $1}' `
206 if [[ ! $first_addr =~ $reg ]]; then echo "$0 : first_addr of hmac variable invalid"; exit 1; fi
207
208 start_addr=`cat vmlinux.elf |grep -w $2|grep PROGBITS|awk '{print $5}' `
209 if [[ ! $start_addr =~ $reg ]]; then echo "$0 : start_addr of .rodata invalid"; exit 1; fi
210
211 offset=`cat vmlinux.elf |grep -w $2|grep PROGBITS| awk '{print $6}' `
212 if [[ ! $offset =~ $reg ]]; then echo "$0 : offset of .rodata invalid"; exit 1; fi
213
214 if [[ $((16#$first_addr)) -le $((16#$start_addr)) ]]; then echo "$0 : hmac var first_addr <= start_addr"; exit 1; fi
215
216 if [ "$1" == "builtime_crypto_hmac" ]; then
217 crypto_hmac_offset_base=`expr $((16#$offset)) + $((16#$first_addr)) - $((16#$start_addr)) `
218 elif [ "$1" == "builtime_fmp_hmac" ]; then
219 fmp_hmac_offset_base=`expr $((16#$offset)) + $((16#$first_addr)) - $((16#$start_addr)) `
220 fi
221 }
222
223 ################ Start Here ################
224
225 START_TIME=$SECONDS
226
227 if test $# -ne 2; then
228 echo "Usage: $0 vmlinux System.map"
229 exit 1
230 fi
231
232 vmlinux_var=$1
233 system_map_var=$2
234
235 if [[ -z "$vmlinux_var" || -z "$system_map_var" || -z "$READELF" || -z "$HOSTCC" ]]; then
236 echo "$0 : variables not set"
237 exit 1
238 fi
239
240 if [[ ! -f $vmlinux_var || ! -f $system_map_var ]]; then
241 echo "$0 : files does not exist"
242 exit 1
243 fi
244
245 rm -f vmlinux.elf
246 $READELF -S $vmlinux_var > vmlinux.elf
247
248 retval=$?
249 if [ $retval -ne 0 ]; then
250 echo "$0 : $READELF returned error"
251 exit 1
252 fi
253
254 #start patching vmlinux with static patcher, temporary put it here
255 rm -f kaslr_fips
256 $HOSTCC -o kaslr_fips $srctree/scripts/kaslr_fips.c
257 retval=$?
258 if [ $retval -ne 0 ]; then
259 echo "$0 : $HOSTCC returned error"
260 exit 1
261 fi
262
263 rm -f fips_crypto_utils
264 $HOSTCC -o fips_crypto_utils $srctree/scripts/fips_crypto_utils.c
265 retval=$?
266 if [ $retval -ne 0 ]; then
267 echo "$0 : $HOSTCC returned error"
268 exit 1
269 fi
270
271 rm -f fips_fmp_utils
272 $HOSTCC -o fips_fmp_utils $srctree/scripts/fips_fmp_utils.c
273 retval=$?
274 if [ $retval -ne 0 ]; then
275 echo "$0 : $HOSTCC returned error"
276 exit 1
277 fi
278
279 var="__reloc_start"
280 var1=`cat $system_map_var|grep -w $var|awk '{print $1}'`
281 var="__reloc_end"
282 var2=`cat $system_map_var|grep -w $var|awk '{print $1}'`
283 var="__dynsym_start"
284 var3=`cat $system_map_var|grep -w $var|awk '{print $1}'`
285
286 var="first_crypto_rodata"
287 var4=`cat $system_map_var|grep -w $var|awk '{print $1}'`
288 var="last_crypto_rodata"
289 var5=`cat $system_map_var|grep -w $var|awk '{print $1}'`
290
291 var="first_fmp_rodata"
292 var6=`cat $system_map_var|grep -w $var|awk '{print $1}'`
293 var="last_fmp_rodata"
294 var7=`cat $system_map_var|grep -w $var|awk '{print $1}'`
295
296 reloc_start_addr=`expr $((16#$var1))`
297 reloc_end_addr=`expr $((16#$var2))`
298 dynsym_addr=`expr $((16#$var3))`
299 first_crypto_rodata=`expr $((16#$var4))`
300 last_crypto_rodata=`expr $((16#$var5))`
301 first_fmp_rodata=`expr $((16#$var6))`
302 last_fmp_rodata=`expr $((16#$var7))`
303
304 ################# CRYPTO #######################
305 # FOR GENERIC CRYPTO FILES #awk fields to cut
306 fips_crypto[0]=".text first_crypto_text last_crypto_text \$5 \$6"
307 fips_crypto[1]=".rodata first_crypto_rodata last_crypto_rodata \$5 \$6"
308 fips_crypto[2]=".init.text first_crypto_init last_crypto_init \$4 \$5"
309
310 # # FOR ASM CRYPTO FILES
311 fips_crypto[3]=".text first_crypto_asm_text last_crypto_asm_text \$5 \$6"
312 fips_crypto[4]=".rodata first_crypto_asm_rodata last_crypto_asm_rodata \$5 \$6"
313 fips_crypto[5]=".init.text first_crypto_asm_init last_crypto_asm_init \$4 \$5"
314
315 offsets_sizes_crypto="offsets_sizes_crypto.txt"
316 offsets_sizes_gen fips_crypto $offsets_sizes_crypto
317
318 #find hmac_offset in vmlinux for updating
319 cal_hmac_offset builtime_crypto_hmac .rodata
320
321
322 ################# FMP #######################
323 fips_fmp[0]=".text first_fmp_text last_fmp_text \$5 \$6"
324 fips_fmp[1]=".rodata first_fmp_rodata last_fmp_rodata \$5 \$6"
325 fips_fmp[2]=".init.text first_fmp_init last_fmp_init \$4 \$5"
326
327 offsets_sizes_fmp="offsets_sizes_fmp.txt"
328 offsets_sizes_gen fips_fmp $offsets_sizes_fmp
329
330 #find hmac_offset in vmlinux for updating
331 cal_hmac_offset builtime_fmp_hmac .rodata
332
333 rodata_va_addr=`cat vmlinux.elf|grep -w '.rodata'|awk '{print $5}'`
334 rodata_file_addr=`cat vmlinux.elf|grep -w '.rodata'|awk '{print $6}'`
335 va_to_file=`expr $((16#$rodata_va_addr)) - $((16#$rodata_file_addr))`
336
337 # the loop
338 for index in {0..63}
339 do
340 kaslr_patch $index $va_to_file
341 hmac_patch $index $offsets_sizes_crypto crypto
342 hmac_patch $index $offsets_sizes_fmp fmp
343 done
344
345 rm -f kaslr_fips
346 rm -f fips_crypto_utils
347 rm -f fips_fmp_utils
348 rm -f vmlinux.elf
349 rm -f offsets_sizes*
350
351 ELAPSED_TIME=$(($SECONDS - $START_TIME))
352 echo ">>>>> Time used for generated all hashes is $(($ELAPSED_TIME)) sec"
353
354 # And we are done...