common.sh 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. #!/bin/bash
  2. # Copyright (c) 2011 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. # Common key generation functions.
  6. SCRIPT_DIR="$(dirname "$(readlink -f -- "$0")")"
  7. # Algorithm ID mappings:
  8. RSA1024_SHA1_ALGOID=0
  9. RSA1024_SHA256_ALGOID=1
  10. RSA1024_SHA512_ALGOID=2
  11. RSA2048_SHA1_ALGOID=3
  12. RSA2048_SHA256_ALGOID=4
  13. RSA2048_SHA512_ALGOID=5
  14. RSA4096_SHA1_ALGOID=6
  15. RSA4096_SHA256_ALGOID=7
  16. RSA4096_SHA512_ALGOID=8
  17. RSA8192_SHA1_ALGOID=9
  18. RSA8192_SHA256_ALGOID=10
  19. RSA8192_SHA512_ALGOID=11
  20. alg_to_keylen() {
  21. echo $(( 1 << (10 + ($1 / 3)) ))
  22. }
  23. # Default algorithms.
  24. EC_ROOT_KEY_ALGOID=${RSA4096_SHA256_ALGOID}
  25. EC_DATAKEY_ALGOID=${RSA4096_SHA256_ALGOID}
  26. ROOT_KEY_ALGOID=${RSA8192_SHA512_ALGOID}
  27. RECOVERY_KEY_ALGOID=${RSA8192_SHA512_ALGOID}
  28. FIRMWARE_DATAKEY_ALGOID=${RSA4096_SHA256_ALGOID}
  29. DEV_FIRMWARE_DATAKEY_ALGOID=${RSA4096_SHA256_ALGOID}
  30. RECOVERY_KERNEL_ALGOID=${RSA8192_SHA512_ALGOID}
  31. INSTALLER_KERNEL_ALGOID=${RSA8192_SHA512_ALGOID}
  32. KERNEL_SUBKEY_ALGOID=${RSA4096_SHA256_ALGOID}
  33. KERNEL_DATAKEY_ALGOID=${RSA2048_SHA256_ALGOID}
  34. # Keyblock modes determine which boot modes a signing key is valid for use
  35. # in verification.
  36. EC_KEYBLOCK_MODE=7 # Only allow RW EC firmware in non-recovery.
  37. FIRMWARE_KEYBLOCK_MODE=7 # Only allow RW firmware in non-recovery.
  38. DEV_FIRMWARE_KEYBLOCK_MODE=6 # Only allow in dev mode.
  39. RECOVERY_KERNEL_KEYBLOCK_MODE=11 # Only in recovery mode.
  40. KERNEL_KEYBLOCK_MODE=7 # Only allow in non-recovery.
  41. INSTALLER_KERNEL_KEYBLOCK_MODE=10 # Only allow in Dev + Recovery.
  42. # Emit .vbpubk and .vbprivk using given basename and algorithm
  43. # NOTE: This function also appears in ../../utility/dev_make_keypair. Making
  44. # the two implementations the same would require some common.sh, which is more
  45. # likely to cause problems than just keeping an eye out for any differences. If
  46. # you feel the need to change this file, check the history of that other file
  47. # to see what may need updating here too.
  48. make_pair() {
  49. local base=$1
  50. local alg=$2
  51. local key_version=${3:-1}
  52. local len=$(alg_to_keylen $alg)
  53. echo "creating $base keypair (version = $key_version)..."
  54. # make the RSA keypair
  55. openssl genrsa -F4 -out "${base}_${len}.pem" $len
  56. # create a self-signed certificate
  57. openssl req -batch -new -x509 -key "${base}_${len}.pem" \
  58. -out "${base}_${len}.crt"
  59. # generate pre-processed RSA public key
  60. dumpRSAPublicKey -cert "${base}_${len}.crt" > "${base}_${len}.keyb"
  61. # wrap the public key
  62. vbutil_key \
  63. --pack "${base}.vbpubk" \
  64. --key "${base}_${len}.keyb" \
  65. --version "${key_version}" \
  66. --algorithm $alg
  67. # wrap the private key
  68. vbutil_key \
  69. --pack "${base}.vbprivk" \
  70. --key "${base}_${len}.pem" \
  71. --algorithm $alg
  72. # remove intermediate files
  73. rm -f "${base}_${len}.pem" "${base}_${len}.crt" "${base}_${len}.keyb"
  74. }
  75. # Emit a .keyblock containing flags and a public key, signed by a private key
  76. # flags are the bitwise OR of these (passed in decimal, though)
  77. # 0x01 Developer switch off
  78. # 0x02 Developer switch on
  79. # 0x04 Not recovery mode
  80. # 0x08 Recovery mode
  81. make_keyblock() {
  82. local base=$1
  83. local flags=$2
  84. local pubkey=$3
  85. local signkey=$4
  86. echo "creating $base keyblock..."
  87. # create it
  88. vbutil_keyblock \
  89. --pack "${base}.keyblock" \
  90. --flags $flags \
  91. --datapubkey "${pubkey}.vbpubk" \
  92. --signprivate "${signkey}.vbprivk"
  93. # verify it
  94. vbutil_keyblock \
  95. --unpack "${base}.keyblock" \
  96. --signpubkey "${signkey}.vbpubk"
  97. }
  98. # File to read current versions from.
  99. VERSION_FILE="key.versions"
  100. # ARGS: <VERSION_TYPE> [VERSION_FILE]
  101. get_version() {
  102. local key="$1"
  103. local file="${2:-${VERSION_FILE}}"
  104. awk -F= -vkey="${key}" '$1 == key { print $NF }' "${file}"
  105. }
  106. # Loads the current versions prints them to stdout and sets the global version
  107. # variables: CURR_FIRMKEY_VER CURR_FIRM_VER CURR_KERNKEY_VER CURR_KERN_VER
  108. load_current_versions() {
  109. local key_dir=$1
  110. local VERSION_FILE="${key_dir}/${VERSION_FILE}"
  111. if [[ ! -f ${VERSION_FILE} ]]; then
  112. return 1
  113. fi
  114. CURR_FIRMKEY_VER=$(get_version "firmware_key_version")
  115. # Firmware version is the kernel subkey version.
  116. CURR_FIRM_VER=$(get_version "firmware_version")
  117. # Kernel data key version is the kernel key version.
  118. CURR_KERNKEY_VER=$(get_version "kernel_key_version")
  119. CURR_KERN_VER=$(get_version "kernel_version")
  120. cat <<EOF
  121. Current Firmware key version: ${CURR_FIRMKEY_VER}
  122. Current Firmware version: ${CURR_FIRM_VER}
  123. Current Kernel key version: ${CURR_KERNKEY_VER}
  124. Current Kernel version: ${CURR_KERN_VER}
  125. EOF
  126. }
  127. # Make backups of existing kernel subkeys and keyblocks that will be revved.
  128. # Backup format:
  129. # for keyblocks: <keyblock_name>.v<datakey version>.v<subkey version>.keyblock
  130. # Args: SUBKEY_VERSION DATAKEY_VERSION
  131. backup_existing_kernel_keyblock() {
  132. if [[ ! -e kernel.keyblock ]]; then
  133. return
  134. fi
  135. mv --no-clobber kernel.{keyblock,"v$2.v$1.keyblock"}
  136. }
  137. # Make backups of existing kernel subkeys and keyblocks that will be revved.
  138. # Backup format:
  139. # for keys: <key_name>.v<version>.vb{pub|priv}k
  140. # for keyblocks: <keyblock_name>.v<datakey version>.v<subkey version>.keyblock
  141. # Args: SUBKEY_VERSION DATAKEY_VERSION
  142. backup_existing_kernel_subkeys() {
  143. local subkey_ver=$1
  144. local datakey_ver=$2
  145. # --no-clobber to prevent accidentally overwriting existing
  146. # backups.
  147. mv --no-clobber kernel_subkey.{vbprivk,"v${subkey_ver}.vbprivk"}
  148. mv --no-clobber kernel_subkey.{vbpubk,"v${subkey_ver}.vbpubk"}
  149. backup_existing_kernel_keyblock ${subkey_ver} ${datakey_ver}
  150. }
  151. # Make backups of existing kernel data keys and keyblocks that will be revved.
  152. # Backup format:
  153. # for keys: <key_name>.v<version>.vb{pub|priv}k
  154. # for keyblocks: <keyblock_name>.v<datakey version>.v<subkey version>.keyblock
  155. # Args: SUBKEY_VERSION DATAKEY_VERSION
  156. backup_existing_kernel_data_keys() {
  157. local subkey_ver=$1
  158. local datakey_ver=$2
  159. # --no-clobber to prevent accidentally overwriting existing
  160. # backups.
  161. mv --no-clobber kernel_data_key.{vbprivk,"v${datakey_ver}.vbprivk"}
  162. mv --no-clobber kernel_data_key.{vbpubk,"v${datakey_ver}.vbpubk"}
  163. backup_existing_kernel_keyblock ${subkey_ver} ${datakey_ver}
  164. }
  165. # Make backups of existing firmware keys and keyblocks that will be revved.
  166. # Backup format:
  167. # for keys: <key_name>.v<version>.vb{pub|priv}k
  168. # for keyblocks: <keyblock_name>.v<datakey version>.v<subkey version>.keyblock
  169. # Args: SUBKEY_VERSION DATAKEY_VERSION
  170. backup_existing_firmware_keys() {
  171. local subkey_ver=$1
  172. local datakey_ver=$2
  173. mv --no-clobber firmware_data_key.{vbprivk,"v${subkey_ver}.vbprivk"}
  174. mv --no-clobber firmware_data_key.{vbpubk,"v${subkey_ver}.vbpubk"}
  175. mv --no-clobber firmware.{keyblock,"v${datakey_ver}.v${subkey_ver}.keyblock"}
  176. }
  177. # Write new key version file with the updated key versions.
  178. # Args: FIRMWARE_KEY_VERSION FIRMWARE_VERSION KERNEL_KEY_VERSION
  179. # KERNEL_VERSION
  180. write_updated_version_file() {
  181. local firmware_key_version=$1
  182. local firmware_version=$2
  183. local kernel_key_version=$3
  184. local kernel_version=$4
  185. cat > ${VERSION_FILE} <<EOF
  186. firmware_key_version=${firmware_key_version}
  187. firmware_version=${firmware_version}
  188. kernel_key_version=${kernel_key_version}
  189. kernel_version=${kernel_version}
  190. EOF
  191. }
  192. # Returns the incremented version number of the passed in key from the version
  193. # file. The options are "firmware_key_version", "firmware_version",
  194. # "kernel_key_version", or "kernel_version".
  195. # ARGS: KEY_DIR <key_name>
  196. increment_version() {
  197. local key_dir=$1
  198. local VERSION_FILE="${key_dir}/${VERSION_FILE}"
  199. local old_version=$(get_version $2)
  200. local new_version=$(( ${old_version} + 1 ))
  201. if [[ ${new_version} -gt 0xffff ]]; then
  202. echo "Version overflow!" >&2
  203. return 1
  204. fi
  205. echo ${new_version}
  206. }