5 # Author : Rohit Kothari (r.kothari@samsung.com)
6 # Created on : 14 Feb 2014
7 # Copyright (c) Samsung Electronics 2014
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.
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.
18 # Pre-conditions : $READELF, $HOSTCC variables are set.
22 if test $# -ne 2; then
23 echo "Usage: $0 vmlinux System.map"
30 if [[ -z "$vmlinux_var" ||
-z "$system_map_var" ||
-z "$READELF" ||
-z "$HOSTCC" ]]; then
31 echo "$0 : variables not set"
35 if [[ ! -f $vmlinux_var ||
! -f $system_map_var ]]; then
36 echo "$0 : files does not exist"
41 $READELF -S $vmlinux_var > vmlinux.elf
44 if [ $retval -ne 0 ]; then
45 echo "$0 : $READELF returned error"
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 array
[3]=".exit.text first_fmp_exit last_fmp_exit \$4 \$5"
57 rm -f offsets_sizes.txt
59 #Addresses retrieved must be a valid hex
62 #Total bytes of all fmp sections scanned. Used later for error checking
65 # For each type of Section :
66 # first_addr = Address of first_fmp_text, first_fmp_rodata, etc.
67 # last_addr = Address of last_fmp_text, last_fmp_rodata etc.
68 # start_addr = Starting Address of a section within vmlinux
69 # offset = Offset in vmlinux file where the section begins
70 # file_offset = Offset in vmlinux file where the fmp bytes begins.
71 # size = size of fmp bytes.
73 # Output is offsets_sizes.txt, of the format
74 # Section Name fmp_bytes_offse fmp_bytes_size
75 # (in decimal) (in decimal)
76 # .text 2531072 114576
77 # .rodata 9289648 55388
80 for i
in "${array[@]}"; do
82 var1
=var2
=var3
=var4
=var5
=""
83 first_addr
=last_addr
=start_addr
=offset
=file_offset
=size
=""
85 #This loop creates var1, var2 etc and set them to individual strings of a row in array
91 first_addr
=`cat $system_map_var|grep -w $var2|awk '{print $1}'`
92 if [[ ! $first_addr =~
$reg ]]; then echo "$0 : first_addr invalid"; exit 1; fi
94 last_addr
=`cat $system_map_var|grep -w $var3|awk '{print $1}'`
95 if [[ ! $last_addr =~
$reg ]]; then echo "$0 : last_addr invalid"; exit 1; fi
97 start_addr
=`cat vmlinux.elf |grep -w "$var1 "|grep PROGBITS|awk '{print '$var4'}'`
98 if [[ ! $start_addr =~
$reg ]]; then echo "$0 : start_addr invalid"; exit 1; fi
100 offset
=`cat vmlinux.elf |grep -w "$var1 "|grep PROGBITS|awk '{print '$var5'}'`
101 if [[ ! $offset =~
$reg ]]; then echo "$0 : offset invalid"; exit 1; fi
103 if [[ $
((16#$first_addr)) -lt $((16#$start_addr)) ]]; then echo "$0 : first_addr < start_addr"; exit 1; fi
105 if [[ $
((16#$last_addr)) -le $((16#$first_addr)) ]]; then echo "$0 : last_addr <= first_addr"; exit 1; fi
107 file_offset
=`expr $((16#$offset)) + $((16#$first_addr)) - $((16#$start_addr))`
108 if [[ $file_offset -le 0 ]]; then echo "$0 : file_offset invalid"; exit 1; fi
110 size
=`expr $((16#$last_addr)) - $((16#$first_addr))`
111 if [[ $size -le 0 ]]; then echo "$0 : fmp section size invalid"; exit 1; fi
113 echo "$var1 " $file_offset " " $size >> offsets_sizes.txt
115 let "total_bytes += `expr $((16#$last_addr)) - $((16#$first_addr))`"
118 if [[ ! -f offsets_sizes.txt
]]; then
119 echo "$0 : offset_sizes.txt does not exist"
124 $HOSTCC -o fips_fmp_utils
$srctree/scripts
/fips_fmp_utils.c
126 if [ $retval -ne 0 ]; then
127 echo "$0 : $HOSTCC returned error"
131 rm -f builtime_bytes.txt
#used for debugging
132 rm -f builtime_bytes.bin
#used for calculating hmac
135 echo "Created on : " $date_var > builtime_bytes.txt
137 #Using offsets_sizes.txt, dump fmp bytes from vmlinux file into builtime_bytes.bin
138 #Also gather printf's into builtime_bytes.txt, for debugging if required
140 .
/fips_fmp_utils
-g $vmlinux_var $args builtime_bytes.bin
>> builtime_bytes.txt
142 if [ $retval -ne 0 ]; then
143 echo "$0 : fips_fmp_utils : unable to gather fmp bytes from vmlinux"
146 echo "" >> builtime_bytes.txt
147 done < offsets_sizes.txt
# <================== offsets_sizes.txt
149 if [[ ! -f builtime_bytes.bin
]]; then
150 echo "$0 : builtime_bytes.bin does not exist"
154 file_size
=`cat builtime_bytes.bin| wc -c`
156 # Make sure that file size of fmp_hmac.bin is as expected
157 if [ $total_bytes -ne $file_size ]; then
158 echo "$0: Bytes mismatch"
162 key
="The quick brown fox jumps over the lazy dog"
164 # Now, generate the hmac.
165 openssl dgst
-sha256 -hmac "$key" -binary -out fmp_hmac.bin builtime_bytes.bin
167 if [ $retval -ne 0 ]; then
168 echo "$0 : openssl dgst command returned error"
172 # Just, for debugging, print the same hmac on console
173 openssl dgst
-sha256 -hmac "$key" builtime_bytes.bin
175 if [ $retval -ne 0 ]; then
176 echo "$0 : openssl dgst command returned error"
180 if [[ ! -f fmp_hmac.bin
]]; then
181 echo "$0 : fmp_hmac.bin does not exist"
185 file_size
=`cat fmp_hmac.bin| wc -c`
187 # hmac(sha256) produces 32 bytes of hmac
188 if [ $file_size -ne 32 ]; then
189 echo "$0: Unexpected size of Hash file : " $file_size
194 # Now that we have the hmac, update this hmac into an rodata "builtime_fmp_hmac" varialble
196 # This variable has a place holder 32 bytes that will be over-written with generated hmac.
197 # This way, this build time hmac, will be available as a read-only variable at run-time.
199 first_addr
=`cat $system_map_var|grep -w "builtime_fmp_hmac"|awk '{print $1}' `
200 if [[ ! $first_addr =~
$reg ]]; then echo "$0 : first_addr of hmac variable invalid"; exit 1; fi
202 start_addr
=`cat vmlinux.elf |grep -w ".rodata"|grep PROGBITS|awk '{print $5}' `
203 if [[ ! $start_addr =~
$reg ]]; then echo "$0 : start_addr of .rodata invalid"; exit 1; fi
205 offset
=`cat vmlinux.elf |grep -w ".rodata"|grep PROGBITS| awk '{print $6}' `
206 if [[ ! $offset =~
$reg ]]; then echo "$0 : offset of .rodata invalid"; exit 1; fi
208 if [[ $
((16#$first_addr)) -le $((16#$start_addr)) ]]; then echo "$0 : hmac var first_addr <= start_addr"; exit 1; fi
210 hmac_offset
=`expr $((16#$offset)) + $((16#$first_addr)) - $((16#$start_addr))`
211 if [[ $hmac_offset -le 0 ]]; then echo "$0 : hmac_offset invalid"; exit 1; fi
213 # This does the actual update of hmac into vmlinux file, at given offset
214 .
/fips_fmp_utils
-u $vmlinux_var fmp_hmac.bin
$hmac_offset
216 if [ $retval -ne 0 ]; then
217 echo "$0 : fips_fmp_utils : unable to update hmac in vmlinux"
222 # rm -f builtime_bytes.txt
223 # rm -f builtime_bytes.bin
224 # rm -f fips_fmp_utils
226 # rm -f offsets_sizes.txt