test_gbb_utility.sh 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #!/bin/bash -eux
  2. # Copyright 2014 The Chromium OS Authors. All rights reserved.
  3. # Use of this source code is governed by a BSD-style license that can be
  4. # found in the LICENSE file.
  5. me=${0##*/}
  6. TMP="$me.tmp"
  7. # Work in scratch directory
  8. cd "$OUTDIR"
  9. # Helper utility to modify binary blobs
  10. REPLACE="${BUILD_RUN}/tests/futility/binary_editor"
  11. # First, let's test the basic functionality
  12. # For simplicity, we'll use the same size for all properties.
  13. ${FUTILITY} gbb_utility -c 16,0x10,16,0x10 ${TMP}.blob
  14. # Flags
  15. ${FUTILITY} gbb_utility -s --flags=0xdeadbeef ${TMP}.blob
  16. ${FUTILITY} gbb_utility -g --flags ${TMP}.blob | grep -i 0xdeadbeef
  17. # HWID length should include the terminating null - this is too long
  18. if ${FUTILITY} gbb_utility -s --hwid="0123456789ABCDEF" ${TMP}.blob; then
  19. false;
  20. fi
  21. # This works
  22. ${FUTILITY} gbb_utility -s --hwid="0123456789ABCDE" ${TMP}.blob
  23. # Read it back?
  24. ${FUTILITY} gbb_utility -g ${TMP}.blob | grep "0123456789ABCDE"
  25. # Same kind of tests for the other fields, but they need binary files.
  26. # too long
  27. dd if=/dev/urandom bs=17 count=1 of=${TMP}.data1.toolong
  28. dd if=/dev/urandom bs=17 count=1 of=${TMP}.data2.toolong
  29. dd if=/dev/urandom bs=17 count=1 of=${TMP}.data3.toolong
  30. if ${FUTILITY} gbb_utility -s --rootkey ${TMP}.data1.toolong ${TMP}.blob; then false; fi
  31. if ${FUTILITY} gbb_utility -s --recoverykey ${TMP}.data2.toolong ${TMP}.blob; then false; fi
  32. if ${FUTILITY} gbb_utility -s --bmpfv ${TMP}.data3.toolong ${TMP}.blob; then false; fi
  33. # shorter than max should be okay, though
  34. dd if=/dev/urandom bs=10 count=1 of=${TMP}.data1.short
  35. dd if=/dev/urandom bs=10 count=1 of=${TMP}.data2.short
  36. dd if=/dev/urandom bs=10 count=1 of=${TMP}.data3.short
  37. ${FUTILITY} gbb_utility -s \
  38. --rootkey ${TMP}.data1.short \
  39. --recoverykey ${TMP}.data2.short \
  40. --bmpfv ${TMP}.data3.short ${TMP}.blob
  41. # read 'em back
  42. ${FUTILITY} gbb_utility -g \
  43. --rootkey ${TMP}.read1 \
  44. --recoverykey ${TMP}.read2 \
  45. --bmpfv ${TMP}.read3 ${TMP}.blob
  46. # Verify (but remember, it's short)
  47. cmp -n 10 ${TMP}.data1.short ${TMP}.read1
  48. cmp -n 10 ${TMP}.data2.short ${TMP}.read2
  49. cmp -n 10 ${TMP}.data3.short ${TMP}.read3
  50. # Okay
  51. dd if=/dev/urandom bs=16 count=1 of=${TMP}.data1
  52. dd if=/dev/urandom bs=16 count=1 of=${TMP}.data2
  53. dd if=/dev/urandom bs=16 count=1 of=${TMP}.data3
  54. ${FUTILITY} gbb_utility -s --rootkey ${TMP}.data1 ${TMP}.blob
  55. ${FUTILITY} gbb_utility -s --recoverykey ${TMP}.data2 ${TMP}.blob
  56. ${FUTILITY} gbb_utility -s --bmpfv ${TMP}.data3 ${TMP}.blob
  57. # Read 'em back.
  58. ${FUTILITY} gbb_utility -g --rootkey ${TMP}.read1 ${TMP}.blob
  59. ${FUTILITY} gbb_utility -g --recoverykey ${TMP}.read2 ${TMP}.blob
  60. ${FUTILITY} gbb_utility -g --bmpfv ${TMP}.read3 ${TMP}.blob
  61. # Verify
  62. cmp ${TMP}.data1 ${TMP}.read1
  63. cmp ${TMP}.data2 ${TMP}.read2
  64. cmp ${TMP}.data3 ${TMP}.read3
  65. # Okay, creating GBB blobs seems to work. Now let's make sure that corrupted
  66. # blobs are rejected.
  67. # Danger Will Robinson! We assume that ${TMP}.blob has this binary struct:
  68. #
  69. # Field Offset Value
  70. #
  71. # signature: 0x0000 $GBB
  72. # major_version: 0x0004 0x0001
  73. # minor_version: 0x0006 0x0001
  74. # header_size: 0x0008 0x00000080
  75. # flags: 0x000c 0xdeadbeef
  76. # hwid_offset: 0x0010 0x00000080
  77. # hwid_size: 0x0014 0x00000010
  78. # rootkey_offset: 0x0018 0x00000090
  79. # rootkey_size: 0x001c 0x00000010
  80. # bmpfv_offset: 0x0020 0x000000a0
  81. # bmpfv_size: 0x0024 0x00000010
  82. # recovery_key_offset: 0x0028 0x000000b0
  83. # recovery_key_size: 0x002c 0x00000010
  84. # pad: 0x0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  85. # 0x0040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  86. # 0x0050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  87. # 0x0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  88. # 0x0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  89. # (HWID) 0x0080 30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 00
  90. # (rootkey) 0x0090 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
  91. # (bmpfv) 0x00a0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
  92. # (recovery_key) 0x00b0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
  93. # 0x00c0 <EOF>
  94. #
  95. # bad major_version
  96. cat ${TMP}.blob | ${REPLACE} 0x4 2 > ${TMP}.blob.bad
  97. if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
  98. # header size too large
  99. cat ${TMP}.blob | ${REPLACE} 0x8 0x81 > ${TMP}.blob.bad
  100. if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
  101. # header size too small
  102. cat ${TMP}.blob | ${REPLACE} 0x8 0x7f > ${TMP}.blob.bad
  103. if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
  104. # HWID not null-terminated is invalid
  105. cat ${TMP}.blob | ${REPLACE} 0x8f 0x41 > ${TMP}.blob.bad
  106. if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
  107. # HWID of length zero is okay
  108. cat ${TMP}.blob | ${REPLACE} 0x14 0x00 > ${TMP}.blob.ok
  109. ${FUTILITY} gbb_utility ${TMP}.blob.ok
  110. # And HWID of length 1 consisting only of '\0' is okay, too.
  111. cat ${TMP}.blob | ${REPLACE} 0x14 0x01 | ${REPLACE} 0x80 0x00 > ${TMP}.blob.ok
  112. ${FUTILITY} gbb_utility ${TMP}.blob.ok
  113. # zero-length HWID not null-terminated is invalid
  114. cat ${TMP}.blob | ${REPLACE} 0x8f 0x41 > ${TMP}.blob.bad
  115. if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
  116. # hwid_offset < GBB_HEADER_SIZE is invalid
  117. cat ${TMP}.blob | ${REPLACE} 0x10 0x7f > ${TMP}.blob.bad
  118. if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
  119. cat ${TMP}.blob | ${REPLACE} 0x10 0x00 > ${TMP}.blob.bad
  120. if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
  121. # rootkey_offset < GBB_HEADER_SIZE is invalid
  122. cat ${TMP}.blob | ${REPLACE} 0x18 0x7f > ${TMP}.blob.bad
  123. if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
  124. cat ${TMP}.blob | ${REPLACE} 0x18 0x00 > ${TMP}.blob.bad
  125. if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
  126. # bmpfv_offset < GBB_HEADER_SIZE is invalid
  127. cat ${TMP}.blob | ${REPLACE} 0x20 0x7f > ${TMP}.blob.bad
  128. if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
  129. cat ${TMP}.blob | ${REPLACE} 0x20 0x00 > ${TMP}.blob.bad
  130. if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
  131. # recovery_key_offset < GBB_HEADER_SIZE is invalid
  132. cat ${TMP}.blob | ${REPLACE} 0x28 0x7f > ${TMP}.blob.bad
  133. if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
  134. cat ${TMP}.blob | ${REPLACE} 0x28 0x00 > ${TMP}.blob.bad
  135. if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
  136. # hwid: offset + size == end of file is okay; beyond is invalid
  137. cat ${TMP}.blob | ${REPLACE} 0x14 0x40 > ${TMP}.blob.bad
  138. ${FUTILITY} gbb_utility -g ${TMP}.blob.bad
  139. cat ${TMP}.blob | ${REPLACE} 0x14 0x41 > ${TMP}.blob.bad
  140. if ${FUTILITY} gbb_utility -g ${TMP}.blob.bad; then false; fi
  141. # rootkey: offset + size == end of file is okay; beyond is invalid
  142. cat ${TMP}.blob | ${REPLACE} 0x1c 0x30 > ${TMP}.blob.bad
  143. ${FUTILITY} gbb_utility -g ${TMP}.blob.bad
  144. cat ${TMP}.blob | ${REPLACE} 0x1c 0x31 > ${TMP}.blob.bad
  145. if ${FUTILITY} gbb_utility -g ${TMP}.blob.bad; then false; fi
  146. # bmpfv: offset + size == end of file is okay; beyond is invalid
  147. cat ${TMP}.blob | ${REPLACE} 0x24 0x20 > ${TMP}.blob.bad
  148. ${FUTILITY} gbb_utility -g ${TMP}.blob.bad
  149. cat ${TMP}.blob | ${REPLACE} 0x24 0x21 > ${TMP}.blob.bad
  150. if ${FUTILITY} gbb_utility -g ${TMP}.blob.bad; then false; fi
  151. # recovery_key: offset + size == end of file is okay; beyond is invalid
  152. cat ${TMP}.blob | ${REPLACE} 0x2c 0x10 > ${TMP}.blob.bad
  153. ${FUTILITY} gbb_utility -g ${TMP}.blob.bad
  154. cat ${TMP}.blob | ${REPLACE} 0x2c 0x11 > ${TMP}.blob.bad
  155. if ${FUTILITY} gbb_utility -g ${TMP}.blob.bad; then false; fi
  156. # hwid_size == 0 doesn't complain, but can't be set
  157. cat ${TMP}.blob | ${REPLACE} 0x14 0x00 > ${TMP}.blob.bad
  158. ${FUTILITY} gbb_utility -g ${TMP}.blob.bad
  159. if ${FUTILITY} gbb_utility -s --hwid="A" ${TMP}.blob.bad; then false; fi
  160. # rootkey_size == 0 gives warning, gets nothing, can't be set
  161. cat ${TMP}.blob | ${REPLACE} 0x1c 0x00 > ${TMP}.blob.bad
  162. ${FUTILITY} gbb_utility -g --rootkey ${TMP}.read1 ${TMP}.blob.bad
  163. if ${FUTILITY} gbb_utility -s --rootkey ${TMP}.data1 ${TMP}.blob.bad; then false; fi
  164. # bmpfv_size == 0 gives warning, gets nothing, can't be set
  165. cat ${TMP}.blob | ${REPLACE} 0x24 0x00 > ${TMP}.blob.bad
  166. ${FUTILITY} gbb_utility -g --bmpfv ${TMP}.read3 ${TMP}.blob.bad
  167. if ${FUTILITY} gbb_utility -s --bmpfv ${TMP}.data3 ${TMP}.blob.bad; then false; fi
  168. # recovery_key_size == 0 gives warning, gets nothing, can't be set
  169. cat ${TMP}.blob | ${REPLACE} 0x2c 0x00 > ${TMP}.blob.bad
  170. ${FUTILITY} gbb_utility -g --recoverykey ${TMP}.read2 ${TMP}.blob.bad
  171. if ${FUTILITY} gbb_utility -s --recoverykey ${TMP}.data2 ${TMP}.blob.bad; then false; fi
  172. # GBB v1.2 adds a sha256 digest field in what was previously padding:
  173. #
  174. # hwid_digest: 0x0030 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
  175. # 0x0040 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
  176. # pad: 0x0050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  177. # 0x0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  178. # 0x0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  179. # (HWID) 0x0080 30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 00
  180. # See that the digest is updated properly.
  181. hwid="123456789ABCDEF"
  182. ${FUTILITY} gbb_utility -s --hwid=${hwid} ${TMP}.blob
  183. expect=$(echo -n "$hwid" | sha256sum | cut -d ' ' -f 1)
  184. [ $(echo -n ${expect} | wc -c) == "64" ]
  185. ${FUTILITY} gbb_utility -g --digest ${TMP}.blob | grep ${expect}
  186. # Garble the digest, see that it's noticed.
  187. # (assuming these zeros aren't present)
  188. cat ${TMP}.blob | ${REPLACE} 0x33 0x00 0x00 0x00 0x00 0x00 > ${TMP}.blob.bad
  189. ${FUTILITY} gbb_utility -g --digest ${TMP}.blob.bad | grep '0000000000'
  190. ${FUTILITY} gbb_utility -g --digest ${TMP}.blob.bad | grep 'invalid'
  191. # Garble the HWID. The digest is unchanged, but now invalid.
  192. cat ${TMP}.blob | ${REPLACE} 0x84 0x70 0x71 0x72 > ${TMP}.blob.bad
  193. ${FUTILITY} gbb_utility -g --digest ${TMP}.blob.bad | grep 'invalid'
  194. # cleanup
  195. rm -f ${TMP}*
  196. exit 0