FROMLIST: [PATCH v5 07/12] arm: vdso: disable profiling
[GitHub/exynos8895/android_kernel_samsung_universal8895.git] / scripts / fips_fmp_hmac.sh
1 #!/bin/bash
2
3 # fips_fmp_hmac.sh
4 #
5 # Author : Rohit Kothari (r.kothari@samsung.com)
6 # Created on : 14 Feb 2014
7 # Copyright (c) Samsung Electronics 2014
8
9 # Given a vmlinux file and a System.map, this scripts finds bytes belonging to
10 # Kernel Crypto within vmlinux file.(Under section .text, .init.text, .exit.text and .rodata)
11 # After collecting all the bytes, it calculates a hmac(sha256) on those bytes.
12 # Generated hmac is put back into a fmp rodata variable within vmlinux file itself.
13 # This makes the build time hmac available at runtime, for integrity check.
14 #
15 # To find fmp bytes, this scripts heavily relies on output of arm-eabi-readelf.
16 # If the output of arm-eabi-readelf changes in future, this script might need changes.
17 #
18 # Pre-conditions : $READELF, $HOSTCC variables are set.
19 #
20 #
21
22 if test $# -ne 2; then
23 echo "Usage: $0 vmlinux System.map"
24 exit 1
25 fi
26
27 vmlinux_var=$1
28 system_map_var=$2
29
30 if [[ -z "$vmlinux_var" || -z "$system_map_var" || -z "$READELF" || -z "$HOSTCC" ]]; then
31 echo "$0 : variables not set"
32 exit 1
33 fi
34
35 if [[ ! -f $vmlinux_var || ! -f $system_map_var ]]; then
36 echo "$0 : files does not exist"
37 exit 1
38 fi
39
40 rm -f vmlinux.elf
41 $READELF -S $vmlinux_var > vmlinux.elf
42
43 retval=$?
44 if [ $retval -ne 0 ]; then
45 echo "$0 : $READELF returned error"
46 exit 1
47 fi
48
49 declare -A array
50
51 # FOR GENERIC CRYPTO FILES #awk fields to cut
52 array[0]=".text first_fmp_text last_fmp_text \$5 \$6"
53 array[1]=".rodata first_fmp_rodata last_fmp_rodata \$5 \$6"
54 array[2]=".init.text first_fmp_init last_fmp_init \$4 \$5"
55
56 rm -f offsets_sizes.txt
57
58 #Addresses retrieved must be a valid hex
59 reg='^[0-9A-Fa-f]+$'
60
61 #Total bytes of all fmp sections scanned. Used later for error checking
62 total_bytes=0;
63
64 # For each type of Section :
65 # first_addr = Address of first_fmp_text, first_fmp_rodata, etc.
66 # last_addr = Address of last_fmp_text, last_fmp_rodata etc.
67 # start_addr = Starting Address of a section within vmlinux
68 # offset = Offset in vmlinux file where the section begins
69 # file_offset = Offset in vmlinux file where the fmp bytes begins.
70 # size = size of fmp bytes.
71
72 # Output is offsets_sizes.txt, of the format
73 # Section Name fmp_bytes_offse fmp_bytes_size
74 # (in decimal) (in decimal)
75 # .text 2531072 114576
76 # .rodata 9289648 55388
77 # : : :
78
79 for i in "${array[@]}"; do
80
81 var1=var2=var3=var4=var5=""
82 first_addr=last_addr=start_addr=offset=file_offset=size=""
83 k=1
84 #This loop creates var1, var2 etc and set them to individual strings of a row in array
85 for j in $i; do
86 export var$k=$j
87 let k+=1
88 done
89
90 first_addr=`cat $system_map_var|grep -w $var2|awk '{print $1}'`
91 if [[ ! $first_addr =~ $reg ]]; then echo "$0 : first_addr invalid"; exit 1; fi
92
93 last_addr=`cat $system_map_var|grep -w $var3|awk '{print $1}'`
94 if [[ ! $last_addr =~ $reg ]]; then echo "$0 : last_addr invalid"; exit 1; fi
95
96 start_addr=`cat vmlinux.elf |grep -w "$var1 "|grep PROGBITS|awk '{print '$var4'}'`
97 if [[ ! $start_addr =~ $reg ]]; then echo "$0 : start_addr invalid"; exit 1; fi
98
99 offset=`cat vmlinux.elf |grep -w "$var1 "|grep PROGBITS|awk '{print '$var5'}'`
100 if [[ ! $offset =~ $reg ]]; then echo "$0 : offset invalid"; exit 1; fi
101
102 if [[ $((16#$first_addr)) -lt $((16#$start_addr)) ]]; then echo "$0 : first_addr < start_addr"; exit 1; fi
103
104 if [[ $((16#$last_addr)) -le $((16#$first_addr)) ]]; then echo "$0 : last_addr <= first_addr"; exit 1; fi
105
106 file_offset=`expr $((16#$offset)) + $((16#$first_addr)) - $((16#$start_addr))`
107 if [[ $file_offset -le 0 ]]; then echo "$0 : file_offset invalid"; exit 1; fi
108
109 size=`expr $((16#$last_addr)) - $((16#$first_addr))`
110 if [[ $size -le 0 ]]; then echo "$0 : fmp section size invalid"; exit 1; fi
111
112 echo "$var1 " $file_offset " " $size >> offsets_sizes.txt
113
114 let "total_bytes += `expr $((16#$last_addr)) - $((16#$first_addr))`"
115 done
116
117 if [[ ! -f offsets_sizes.txt ]]; then
118 echo "$0 : offset_sizes.txt does not exist"
119 exit 1
120 fi
121
122 rm -f fips_fmp_utils
123 $HOSTCC -o fips_fmp_utils $srctree/scripts/fips_fmp_utils.c
124 retval=$?
125 if [ $retval -ne 0 ]; then
126 echo "$0 : $HOSTCC returned error"
127 exit 1
128 fi
129
130 rm -f builtime_bytes.txt #used for debugging
131 rm -f builtime_bytes.bin #used for calculating hmac
132
133 date_var=`date`
134 echo "Created on : " $date_var > builtime_bytes.txt
135
136 #Using offsets_sizes.txt, dump fmp bytes from vmlinux file into builtime_bytes.bin
137 #Also gather printf's into builtime_bytes.txt, for debugging if required
138 while read args; do
139 ./fips_fmp_utils -g $vmlinux_var $args builtime_bytes.bin >> builtime_bytes.txt
140 retval=$?
141 if [ $retval -ne 0 ]; then
142 echo "$0 : fips_fmp_utils : unable to gather fmp bytes from vmlinux"
143 exit 1
144 fi
145 echo "" >> builtime_bytes.txt
146 done < offsets_sizes.txt # <================== offsets_sizes.txt
147
148 if [[ ! -f builtime_bytes.bin ]]; then
149 echo "$0 : builtime_bytes.bin does not exist"
150 exit 1
151 fi
152
153 file_size=`cat builtime_bytes.bin| wc -c`
154
155 # Make sure that file size of fmp_hmac.bin is as expected
156 if [ $total_bytes -ne $file_size ]; then
157 echo "$0: Bytes mismatch"
158 exit 1
159 fi
160
161 key="The quick brown fox jumps over the lazy dog"
162
163 # Now, generate the hmac.
164 openssl dgst -sha256 -hmac "$key" -binary -out fmp_hmac.bin builtime_bytes.bin
165 retval=$?
166 if [ $retval -ne 0 ]; then
167 echo "$0 : openssl dgst command returned error"
168 exit 1
169 fi
170
171 # Just, for debugging, print the same hmac on console
172 openssl dgst -sha256 -hmac "$key" builtime_bytes.bin
173 retval=$?
174 if [ $retval -ne 0 ]; then
175 echo "$0 : openssl dgst command returned error"
176 exit 1
177 fi
178
179 if [[ ! -f fmp_hmac.bin ]]; then
180 echo "$0 : fmp_hmac.bin does not exist"
181 exit 1
182 fi
183
184 file_size=`cat fmp_hmac.bin| wc -c`
185
186 # hmac(sha256) produces 32 bytes of hmac
187 if [ $file_size -ne 32 ]; then
188 echo "$0: Unexpected size of Hash file : " $file_size
189 exit 1
190 fi
191
192
193 # Now that we have the hmac, update this hmac into an rodata "builtime_fmp_hmac" varialble
194 # in vmlinux file.
195 # This variable has a place holder 32 bytes that will be over-written with generated hmac.
196 # This way, this build time hmac, will be available as a read-only variable at run-time.
197
198 first_addr=`cat $system_map_var|grep -w "builtime_fmp_hmac"|awk '{print $1}' `
199 if [[ ! $first_addr =~ $reg ]]; then echo "$0 : first_addr of hmac variable invalid"; exit 1; fi
200
201 start_addr=`cat vmlinux.elf |grep -w ".rodata"|grep PROGBITS|awk '{print $5}' `
202 if [[ ! $start_addr =~ $reg ]]; then echo "$0 : start_addr of .rodata invalid"; exit 1; fi
203
204 offset=`cat vmlinux.elf |grep -w ".rodata"|grep PROGBITS| awk '{print $6}' `
205 if [[ ! $offset =~ $reg ]]; then echo "$0 : offset of .rodata invalid"; exit 1; fi
206
207 if [[ $((16#$first_addr)) -le $((16#$start_addr)) ]]; then echo "$0 : hmac var first_addr <= start_addr"; exit 1; fi
208
209 hmac_offset=`expr $((16#$offset)) + $((16#$first_addr)) - $((16#$start_addr))`
210 if [[ $hmac_offset -le 0 ]]; then echo "$0 : hmac_offset invalid"; exit 1; fi
211
212 # This does the actual update of hmac into vmlinux file, at given offset
213 ./fips_fmp_utils -u $vmlinux_var fmp_hmac.bin $hmac_offset
214 retval=$?
215 if [ $retval -ne 0 ]; then
216 echo "$0 : fips_fmp_utils : unable to update hmac in vmlinux"
217 exit 1
218 fi
219
220 # rm -f fmp_hmac.bin
221 # rm -f builtime_bytes.txt
222 # rm -f builtime_bytes.bin
223 # rm -f fips_fmp_utils
224 # rm -f vmlinux.elf
225 # rm -f offsets_sizes.txt
226
227 # And we are done...