cros-boot-keys 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. #!/usr/bin/env bash
  2. # Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr>
  3. #
  4. # This program is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation, either version 3 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. REGEXP="\([^[:space:]]*\)[[:space:]]\(.*\)"
  17. KEYBLOCK="keyblock"
  18. VBPRIVK="vbprivk"
  19. VBPUBK="vbpubk"
  20. KEYB="keyb"
  21. PEM="pem"
  22. CRT="crt"
  23. KEYS="ec_root_key ec_data_key root_key firmware_data_key kernel_subkey kernel_data_key recovery_key recovery_kernel_data_key installer_kernel_data_key"
  24. KEYBLOCKS="firmware ec recovery_kernel kernel installer_kernel"
  25. SUBKEYS="firmware_data_key root_key ec_data_key ec_root_key recovery_kernel_data_key recovery_key kernel_data_key kernel_subkey installer_kernel_data_key recovery_key"
  26. ALGORITHMS="7 7 11 7 7 4 11 11 11"
  27. MODES="7 7 11 7 10"
  28. usage() {
  29. printf '%s\n' "$executable [action]" >&2
  30. printf '\n%s\n' 'Actions:' >&2
  31. printf '%s\n' ' generate - Generate a set of keys' >&2
  32. printf '%s\n' ' verify - Verify keyblocks' >&2
  33. printf '\n%s\n' 'Environment variables:' >&2
  34. printf '%s\n' ' KEYS_VERSION - Version to give the keys' >&2
  35. printf '%s\n' ' VBOOT_KEYS_PATH - Path to the vboot keys' >&2
  36. printf '%s\n' ' VBOOT_TOOLS_PATH - Path to vboot tools' >&2
  37. }
  38. keys_override_confirm() {
  39. local override=0
  40. local confirm
  41. for key in $KEYS
  42. do
  43. if [ -f "$VBOOT_KEYS_PATH/$key.$VBPUBK" ] || [ -f "$VBOOT_KEYS_PATH/$key.$VBPRIVK" ]
  44. then
  45. override=1
  46. fi
  47. done
  48. for keyblock in $KEYBLOCKS
  49. do
  50. if [ -f "$VBOOT_KEYS_PATH/$keyblock.$KEYBLOCK" ]
  51. then
  52. override=1
  53. fi
  54. done
  55. if [ $override -ne 1 ]
  56. then
  57. return 0
  58. fi
  59. printf '%s\n' 'This is going to override keys stored in the following directory:'
  60. printf '%s\n' " $VBOOT_KEYS_PATH"
  61. printf '%s' 'Press enter to confirm: '
  62. read confirm
  63. }
  64. generate() {
  65. local algorithms=$ALGORITHMS
  66. local subkeys=$SUBKEYS
  67. local modes=$MODES
  68. local keyblock
  69. local algorithm
  70. local pubkey
  71. local privkey
  72. local mode
  73. keys_override_confirm
  74. for key in $KEYS
  75. do
  76. algorithm=$( printf '%s\n' "$algorithms" | sed "s/$REGEXP/\1/g" )
  77. algorithms=$( printf '%s\n' "$algorithms" | sed "s/$REGEXP/\2/g" )
  78. key_length=$(( 1 << (10 + ($algorithm / 3)) ))
  79. openssl genrsa -F4 -out "$VBOOT_KEYS_PATH/$key.$PEM" "$key_length"
  80. openssl req -batch -new -x509 -key "$VBOOT_KEYS_PATH/$key.$PEM"
  81. openssl req -batch -new -x509 -key "$VBOOT_KEYS_PATH/$key.$PEM" -out "$VBOOT_KEYS_PATH/$key.$CRT"
  82. dumpRSAPublicKey -cert "$VBOOT_KEYS_PATH/$key.$CRT" > "$VBOOT_KEYS_PATH/$key.$KEYB"
  83. futility vbutil_key --pack "$VBOOT_KEYS_PATH/$key.$VBPUBK" --key "$VBOOT_KEYS_PATH/$key.$KEYB" --version "$KEYS_VERSION" --algorithm "$algorithm"
  84. futility vbutil_key --pack "$VBOOT_KEYS_PATH/$key.$VBPRIVK" --key "$VBOOT_KEYS_PATH/$key.$PEM" --algorithm "$algorithm"
  85. rm -f "$VBOOT_KEYS_PATH/$key.$PEM" "$VBOOT_KEYS_PATH/$key.$CRT" "$VBOOT_KEYS_PATH/$key.$KEYB"
  86. done
  87. printf '\n%s\n' "Generated keys $KEYS"
  88. for keyblock in $KEYBLOCKS
  89. do
  90. pubkey=$( printf '%s\n' "$subkeys" | sed "s/$REGEXP/\1/g" )
  91. subkeys=$( printf '%s\n' "$subkeys" | sed "s/$REGEXP/\2/g" )
  92. privkey=$( printf '%s\n' "$subkeys" | sed "s/$REGEXP/\1/g" )
  93. subkeys=$( printf '%s\n' "$subkeys" | sed "s/$REGEXP/\2/g" )
  94. mode=$( printf '%s\n' "$modes" | sed "s/$REGEXP/\1/g" )
  95. modes=$( printf '%s\n' "$modes" | sed "s/$REGEXP/\2/g" )
  96. futility vbutil_keyblock --pack "$VBOOT_KEYS_PATH/$keyblock.$KEYBLOCK" --flags "$mode" --datapubkey "$VBOOT_KEYS_PATH/$pubkey.$VBPUBK" --signprivate "$VBOOT_KEYS_PATH/$privkey.$VBPRIVK"
  97. futility vbutil_keyblock --unpack "$VBOOT_KEYS_PATH/$keyblock.$KEYBLOCK" --signpubkey "$VBOOT_KEYS_PATH/$privkey.$VBPUBK"
  98. done
  99. printf '\n%s\n' "Generated keyblocks $KEYBLOCKS"
  100. }
  101. verify() {
  102. local subkeys=$SUBKEYS
  103. local pubkey
  104. local privkey
  105. for keyblock in $KEYBLOCKS
  106. do
  107. pubkey=$( printf '%s\n' "$subkeys" | sed "s/$REGEXP/\1/g" )
  108. subkeys=$( printf '%s\n' "$subkeys" | sed "s/$REGEXP/\2/g" )
  109. privkey=$( printf '%s\n' "$subkeys" | sed "s/$REGEXP/\1/g" )
  110. subkeys=$( printf '%s\n' "$subkeys" | sed "s/$REGEXP/\2/g" )
  111. futility vbutil_keyblock --unpack "$VBOOT_KEYS_PATH/$keyblock.$KEYBLOCK" --signpubkey "$VBOOT_KEYS_PATH/$privkey.$VBPUBK"
  112. done
  113. printf '\n%s\n' "Verified keyblocks $KEYBLOCKS"
  114. }
  115. requirements() {
  116. local requirement
  117. local requirement_path
  118. for requirement in "$@"
  119. do
  120. requirement_path=$( which "$requirement" || true )
  121. if [ -z "$requirement_path" ]
  122. then
  123. printf '%s\n' "Missing requirement: $requirement" >&2
  124. exit 1
  125. fi
  126. done
  127. }
  128. setup() {
  129. root=$(readlink -f "$( dirname "$0" )" )
  130. executable=$( basename "$0" )
  131. if [ -z "$KEYS_VERSION" ]
  132. then
  133. KEYS_VERSION=1
  134. fi
  135. if ! [ -z "$VBOOT_TOOLS_PATH" ]
  136. then
  137. PATH="$PATH:$VBOOT_TOOLS_PATH"
  138. fi
  139. if [ -z "$VBOOT_KEYS_PATH" ]
  140. then
  141. VBOOT_KEYS_PATH="$root/keys"
  142. mkdir -p "$VBOOT_KEYS_PATH"
  143. fi
  144. }
  145. cros_boot_keys() {
  146. local action=$1
  147. set -e
  148. setup "$@"
  149. if [ -z "$action" ]
  150. then
  151. usage
  152. exit 1
  153. fi
  154. case $action in
  155. "generate")
  156. requirements "openssl" "dumpRSAPublicKey" "futility"
  157. generate
  158. ;;
  159. "verify")
  160. requirements "futility"
  161. verify
  162. ;;
  163. *)
  164. usage
  165. exit 1
  166. ;;
  167. esac
  168. }
  169. cros_boot_keys "$@"