OLD | NEW |
1 #!/bin/sh | 1 #!/bin/sh |
2 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. | 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 | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 # | 5 # |
6 # Derived from dev_debug_vboot. | 6 # Derived from dev_debug_vboot. |
7 # | 7 # |
8 # This script checks if system firmware and SSD images are ready for verified | 8 # This script checks if system firmware and SSD images are ready for verified |
9 # booting. | 9 # booting. |
10 # | 10 # |
11 | 11 |
| 12 alert() { |
| 13 echo "$*" 1>&2 |
| 14 } |
| 15 |
12 if [ "$#" != "2" ]; then | 16 if [ "$#" != "2" ]; then |
13 echo "ERROR: Usage: $0 kernel_device main_firmware" 1>&2 | 17 alert "ERROR: Usage: $0 kernel_device main_firmware" |
14 exit 1 | 18 exit 1 |
15 fi | 19 fi |
16 | 20 |
| 21 DEVKEYS="/usr/share/vboot/devkeys" |
17 TMPDIR="$(mktemp -d)" | 22 TMPDIR="$(mktemp -d)" |
18 KERN_DEV="$(readlink -f "$1")" | 23 KERN_DEV="$(readlink -f "$1")" |
19 FIRMWARE_IMAGE="$(readlink -f "$2")" | 24 FIRMWARE_IMAGE="$(readlink -f "$2")" |
20 RETURN=0 | 25 RETURN=0 |
21 | 26 |
22 invoke() { | 27 invoke() { |
23 # Usage: invoke "message" "shell-command" | 28 # Usage: invoke "message" "shell-command" |
24 result=0 | 29 result=0 |
25 message="$1" | 30 message="$1" |
26 shift | 31 shift |
27 eval "$@" >_stdout 2>_stderr || result=$? | 32 eval "$@" >_stdout 2>_stderr || result=$? |
28 if [ "$result" != 0 ]; then | 33 if [ "$result" != 0 ]; then |
29 echo "ERROR: Failed to $message" 1>&2 | 34 alert "ERROR: Failed to $message" |
30 echo "Command detail: $@" 1>&2 | 35 alert "Command detail: $@" |
31 cat _stdout _stderr 1>&2 | 36 cat _stdout _stderr 1>&2 |
32 RETURN=1 | 37 RETURN=1 |
33 fi | 38 fi |
34 } | 39 } |
35 | 40 |
36 detect_section_name() { | 41 detect_section_name() { |
37 # Usage: detect_section_name official_name alias_name | 42 # Usage: detect_section_name official_name alias_name |
38 if [ -f "$2" ]; then | 43 if [ -f "$2" ]; then |
39 echo "$2" | 44 echo "$2" |
40 else | 45 else |
41 echo "$1" | 46 echo "$1" |
42 fi | 47 fi |
43 } | 48 } |
44 | 49 |
45 verify_keys() { | 50 verify_keys() { |
46 # Usage: verify_keys kernel_device main_firmware | 51 # Usage: verify_keys kernel_device main_firmware |
47 | 52 |
48 # Define section names | 53 # Define section names |
49 GBB="$(detect_section_name GBB GBB_Area)" | 54 GBB="$(detect_section_name GBB GBB_Area)" |
50 FW_MAIN_A="$(detect_section_name FW_MAIN_A Firmware_A_Data)" | 55 FW_MAIN_A="$(detect_section_name FW_MAIN_A Firmware_A_Data)" |
51 FW_MAIN_B="$(detect_section_name FW_MAIN_B Firmware_B_Data)" | 56 FW_MAIN_B="$(detect_section_name FW_MAIN_B Firmware_B_Data)" |
52 VBLOCK_A="$(detect_section_name VBLOCK_A Firmware_A_Key)" | 57 VBLOCK_A="$(detect_section_name VBLOCK_A Firmware_A_Key)" |
53 VBLOCK_B="$(detect_section_name VBLOCK_B Firmware_B_Key)" | 58 VBLOCK_B="$(detect_section_name VBLOCK_B Firmware_B_Key)" |
54 | 59 |
55 invoke "dump kernel" dd if="$1" bs=1M count=64 of=hd_kern.blob | 60 invoke "dump kernel" dd if="$1" bs=1M count=64 of=hd_kern.blob |
56 invoke "extract firmware" dump_fmap -x "$2" | 61 invoke "extract firmware" dump_fmap -x "$2" |
57 invoke "get keys from firmware" \ | 62 invoke "get keys from firmware" \ |
58 gbb_utility -g --rootkey rootkey.vbpubk "$GBB" | 63 gbb_utility -g --rootkey rootkey.vbpubk \ |
| 64 --recoverykey recoverykey.vbpubk "$GBB" |
59 invoke "unpack rootkey" \ | 65 invoke "unpack rootkey" \ |
60 vbutil_key --unpack rootkey.vbpubk | 66 vbutil_key --unpack rootkey.vbpubk |
| 67 invoke "unpack recovery key" \ |
| 68 vbutil_key --unpack recoverykey.vbpubk |
| 69 |
| 70 # check if rootkey is developer key. 130 is the magic number for DEV key |
| 71 local key |
| 72 local rootkey_hash="$(od "rootkey.vbpubk" | |
| 73 head -130 | |
| 74 md5sum | |
| 75 sed 's/ .*$//' 2>/dev/null || true)" |
| 76 if [ "$rootkey_hash" = "a13642246ef93daaf75bd791446fec9b" ]; then |
| 77 alert "ERROR: YOU ARE TRYING TO FINALIZE WITH DEV ROOTKEY." |
| 78 fi |
61 | 79 |
62 # Verify firmware A/B with root key | 80 # Verify firmware A/B with root key |
63 invoke "verify VBLOCK_A with FW_MAIN_A" \ | 81 invoke "verify VBLOCK_A with FW_MAIN_A" \ |
64 vbutil_firmware --verify "$VBLOCK_A" --signpubkey rootkey.vbpubk \ | 82 vbutil_firmware --verify "$VBLOCK_A" --signpubkey rootkey.vbpubk \ |
65 --fv "$FW_MAIN_A" --kernelkey kernel_subkey_a.vbpubk | 83 --fv "$FW_MAIN_A" --kernelkey kernel_subkey_a.vbpubk |
66 invoke "verify VBLOCK_B with FW_MAIN_B" \ | 84 invoke "verify VBLOCK_B with FW_MAIN_B" \ |
67 vbutil_firmware --verify "$VBLOCK_B" --signpubkey rootkey.vbpubk \ | 85 vbutil_firmware --verify "$VBLOCK_B" --signpubkey rootkey.vbpubk \ |
68 --fv "$FW_MAIN_B" --kernelkey kernel_subkey_b.vbpubk | 86 --fv "$FW_MAIN_B" --kernelkey kernel_subkey_b.vbpubk |
69 | 87 |
70 # Unpack keys and keyblocks | 88 # Unpack keys and keyblocks |
71 for key in kernel_subkey_a.vbpubk kernel_subkey_b.vbpubk; do | 89 for key in kernel_subkey_a.vbpubk kernel_subkey_b.vbpubk; do |
72 invoke "unpack $key" vbutil_key --unpack $key | 90 invoke "unpack $key" vbutil_key --unpack $key |
73 done | 91 done |
74 for keyblock in *kern*.blob; do | 92 for keyblock in *kern*.blob; do |
75 invoke "unpack $keyblock" vbutil_keyblock --unpack $keyblock | 93 invoke "unpack $keyblock" vbutil_keyblock --unpack $keyblock |
76 done | 94 done |
77 | 95 |
78 # Test each kernel by each key | 96 # Test each kernel by each key |
79 for key in kernel_subkey_a.vbpubk kernel_subkey_b.vbpubk | 97 for key in kernel_subkey_a.vbpubk kernel_subkey_b.vbpubk |
80 do | 98 do |
81 for kern in *kern*.blob; do | 99 for kern in *kern*.blob; do |
82 invoke "verify $kern by $key" \ | 100 invoke "verify $kern by $key" \ |
83 vbutil_kernel --verify $kern --signpubkey $key | 101 vbutil_kernel --verify $kern --signpubkey $key |
84 done | 102 done |
85 done | 103 done |
| 104 |
| 105 if [ "$RETURN" != "0" ]; then |
| 106 # Error encountered. Let's try if we can provide more information. |
| 107 key="recoverykey.vbpubk" |
| 108 vbutil_kernel --verify "$kern" --signpubkey "$key" >/dev/null 2>&1 && |
| 109 alert "ERROR: YOU ARE USING A RECOVERY KEY SIGNED IMAGE." || |
| 110 true |
| 111 for key in recovery_key.vbpubk kernel_subkey.vbpubk; do |
| 112 if [ -f "$DEVKEYS/$key" ]; then |
| 113 vbutil_kernel --verify "$kern" \ |
| 114 --signpubkey "$DEVKEYS/$key" >/dev/null 2>&1 && |
| 115 alert "ERROR: YOU ARE FINALIZING WITH DEV-SIGNED IMAGE ($key)." || |
| 116 true |
| 117 fi |
| 118 done |
| 119 fi |
| 120 |
86 return $RETURN | 121 return $RETURN |
87 } | 122 } |
88 | 123 |
89 # verify_keys is run inside a sub-shell, so we need to check its return value | 124 # verify_keys is run inside a sub-shell, so we need to check its return value |
90 # instead of reading the global variable RETURN. | 125 # instead of reading the global variable RETURN. |
91 ( cd "$TMPDIR" | 126 ( cd "$TMPDIR" |
92 verify_keys "$KERN_DEV" "$FIRMWARE_IMAGE" ) || RETURN=1 | 127 verify_keys "$KERN_DEV" "$FIRMWARE_IMAGE" ) || RETURN=1 |
93 /bin/rm -rf "$TMPDIR" | 128 /bin/rm -rf "$TMPDIR" |
94 exit $RETURN | 129 exit $RETURN |
95 | 130 |
OLD | NEW |