File: | 3rdparty/vboot/futility/cmd_show.c |
Warning: | line 798, column 3 Address of stack memory associated with local variable 'pubk2' is still referred to by the global variable 'show_option' upon returning to the caller. This will be a dangling reference |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Copyright 2014 The ChromiumOS Authors | |||
2 | * Use of this source code is governed by a BSD-style license that can be | |||
3 | * found in the LICENSE file. | |||
4 | */ | |||
5 | ||||
6 | #include <openssl/rsa.h> | |||
7 | ||||
8 | #include <errno(*__errno_location ()).h> | |||
9 | #include <fcntl.h> | |||
10 | #include <getopt.h> | |||
11 | #include <inttypes.h> | |||
12 | #include <stddef.h> | |||
13 | #include <stdint.h> | |||
14 | #include <stdio.h> | |||
15 | #include <stdlib.h> | |||
16 | #include <string.h> | |||
17 | #include <sys/stat.h> | |||
18 | #include <sys/types.h> | |||
19 | #include <unistd.h> | |||
20 | ||||
21 | #include "2api.h" | |||
22 | #include "2common.h" | |||
23 | #include "2sha.h" | |||
24 | #include "2sysincludes.h" | |||
25 | #include "cbfstool.h" | |||
26 | #include "file_type_bios.h" | |||
27 | #include "file_type.h" | |||
28 | #include "fmap.h" | |||
29 | #include "futility.h" | |||
30 | #include "futility_options.h" | |||
31 | #include "host_common.h" | |||
32 | #include "host_key21.h" | |||
33 | #include "host_misc.h" | |||
34 | #include "util_misc.h" | |||
35 | #include "vb1_helper.h" | |||
36 | ||||
37 | /* Options */ | |||
38 | struct show_option_s show_option = { | |||
39 | .type = FILE_TYPE_UNKNOWN, | |||
40 | }; | |||
41 | ||||
42 | /* Shared work buffer */ | |||
43 | static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE(80 * 1024)] | |||
44 | __attribute__((aligned(VB2_WORKBUF_ALIGN8))); | |||
45 | static struct vb2_workbuf wb; | |||
46 | ||||
47 | void show_pubkey(const struct vb2_packed_key *pubkey, const char *sp) | |||
48 | { | |||
49 | // Clear out formatting if we are in parseable mode. | |||
50 | if (show_option.parseable) | |||
51 | sp = "\0"; | |||
52 | FT_PRINT("%sVboot API: 1.0\n", "%sapi::1.0\n", sp)do { do { if (!show_option.parseable) printf("%sVboot API: 1.0\n" , sp); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header ); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2 ); printf("%sapi::1.0\n", sp); } while (0); } while (0); | |||
53 | FT_PRINT("%sAlgorithm: %d %s\n",do { do { if (!show_option.parseable) printf("%sAlgorithm: %d %s\n" , sp, pubkey->algorithm, vb2_get_crypto_algorithm_name(pubkey ->algorithm)); } while (0); do { if (!show_option.parseable ) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header ); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2 ); printf("%salgorithm::%d::%s\n", sp, pubkey->algorithm, vb2_get_crypto_algorithm_name (pubkey->algorithm)); } while (0); } while (0) | |||
54 | "%salgorithm::%d::%s\n",do { do { if (!show_option.parseable) printf("%sAlgorithm: %d %s\n" , sp, pubkey->algorithm, vb2_get_crypto_algorithm_name(pubkey ->algorithm)); } while (0); do { if (!show_option.parseable ) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header ); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2 ); printf("%salgorithm::%d::%s\n", sp, pubkey->algorithm, vb2_get_crypto_algorithm_name (pubkey->algorithm)); } while (0); } while (0) | |||
55 | sp, pubkey->algorithm,do { do { if (!show_option.parseable) printf("%sAlgorithm: %d %s\n" , sp, pubkey->algorithm, vb2_get_crypto_algorithm_name(pubkey ->algorithm)); } while (0); do { if (!show_option.parseable ) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header ); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2 ); printf("%salgorithm::%d::%s\n", sp, pubkey->algorithm, vb2_get_crypto_algorithm_name (pubkey->algorithm)); } while (0); } while (0) | |||
56 | vb2_get_crypto_algorithm_name(pubkey->algorithm))do { do { if (!show_option.parseable) printf("%sAlgorithm: %d %s\n" , sp, pubkey->algorithm, vb2_get_crypto_algorithm_name(pubkey ->algorithm)); } while (0); do { if (!show_option.parseable ) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header ); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2 ); printf("%salgorithm::%d::%s\n", sp, pubkey->algorithm, vb2_get_crypto_algorithm_name (pubkey->algorithm)); } while (0); } while (0); | |||
57 | FT_PRINT("%sKey Version: %d\n", "%sversion::%d\n",do { do { if (!show_option.parseable) printf("%sKey Version: %d\n" , sp, pubkey->key_version); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("%sversion::%d\n", sp , pubkey->key_version); } while (0); } while (0) | |||
58 | sp, pubkey->key_version)do { do { if (!show_option.parseable) printf("%sKey Version: %d\n" , sp, pubkey->key_version); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("%sversion::%d\n", sp , pubkey->key_version); } while (0); } while (0); | |||
59 | FT_PRINT("%sKey sha1sum: %s\n", "%ssha1_sum::%s\n",do { do { if (!show_option.parseable) printf("%sKey sha1sum: %s\n" , sp, packed_key_sha1_string(pubkey)); } while (0); do { if ( !show_option.parseable) break; if (ft_print_header != ((void* )0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("%ssha1_sum::%s\n" , sp, packed_key_sha1_string(pubkey)); } while (0); } while ( 0) | |||
60 | sp, packed_key_sha1_string(pubkey))do { do { if (!show_option.parseable) printf("%sKey sha1sum: %s\n" , sp, packed_key_sha1_string(pubkey)); } while (0); do { if ( !show_option.parseable) break; if (ft_print_header != ((void* )0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("%ssha1_sum::%s\n" , sp, packed_key_sha1_string(pubkey)); } while (0); } while ( 0); | |||
61 | } | |||
62 | ||||
63 | static void show_keyblock(struct vb2_keyblock *keyblock, const char *print_name, | |||
64 | int sign_key, int good_sig) | |||
65 | { | |||
66 | if (print_name) | |||
67 | FT_READABLE_PRINT("Keyblock: %s\n", print_name)do { if (!show_option.parseable) printf("Keyblock: %s\n" , print_name); } while (0); | |||
68 | else | |||
69 | FT_READABLE_PRINT("Keyblock:\n")do { if (!show_option.parseable) printf("Keyblock:\n"); } while (0); | |||
70 | ||||
71 | FT_PRINT(" Signature: %s\n", "signature::%s\n",do { do { if (!show_option.parseable) printf(" Signature: %s\n" , sign_key ? (good_sig ? "valid" : "invalid") : "ignored"); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("signature::%s\n" , sign_key ? (good_sig ? "valid" : "invalid") : "ignored"); } while (0); } while (0) | |||
72 | sign_key ? (good_sig ? "valid" : "invalid") : "ignored")do { do { if (!show_option.parseable) printf(" Signature: %s\n" , sign_key ? (good_sig ? "valid" : "invalid") : "ignored"); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("signature::%s\n" , sign_key ? (good_sig ? "valid" : "invalid") : "ignored"); } while (0); } while (0); | |||
73 | FT_PRINT(" Size: %#x\n",do { do { if (!show_option.parseable) printf(" Size: %#x\n" , keyblock->keyblock_size); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("size::%d\n", keyblock ->keyblock_size); } while (0); } while (0) | |||
74 | "size::%d\n", keyblock->keyblock_size)do { do { if (!show_option.parseable) printf(" Size: %#x\n" , keyblock->keyblock_size); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("size::%d\n", keyblock ->keyblock_size); } while (0); } while (0); | |||
75 | FT_PRINT(" Flags: %d ",do { do { if (!show_option.parseable) printf(" Flags: %d " , keyblock->keyblock_flags); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("flags::%d:", keyblock ->keyblock_flags); } while (0); } while (0) | |||
76 | "flags::%d:", keyblock->keyblock_flags)do { do { if (!show_option.parseable) printf(" Flags: %d " , keyblock->keyblock_flags); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("flags::%d:", keyblock ->keyblock_flags); } while (0); } while (0); | |||
77 | if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_DEVELOPER_00x1) | |||
78 | FT_PRINT_RAW(" !DEV", ":!DEV")printf(show_option.parseable ? ":!DEV" : " !DEV"); | |||
79 | if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_DEVELOPER_10x2) | |||
80 | FT_PRINT_RAW(" DEV", ":DEV")printf(show_option.parseable ? ":DEV" : " DEV"); | |||
81 | if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_RECOVERY_00x4) | |||
82 | FT_PRINT_RAW(" !REC", ":!REC")printf(show_option.parseable ? ":!REC" : " !REC"); | |||
83 | if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_RECOVERY_10x8) | |||
84 | FT_PRINT_RAW(" REC", ":REC")printf(show_option.parseable ? ":REC" : " REC"); | |||
85 | if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_00x10) | |||
86 | FT_PRINT_RAW(" !MINIOS", ":!MINIOS")printf(show_option.parseable ? ":!MINIOS" : " !MINIOS"); | |||
87 | if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_10x20) | |||
88 | FT_PRINT_RAW(" MINIOS", ":MINIOS")printf(show_option.parseable ? ":MINIOS" : " MINIOS"); | |||
89 | printf("\n"); | |||
90 | ||||
91 | struct vb2_packed_key *data_key = &keyblock->data_key; | |||
92 | FT_PRINT(" Data key algorithm: %d %s\n",do { do { if (!show_option.parseable) printf(" Data key algorithm: %d %s\n" , data_key->algorithm, vb2_get_crypto_algorithm_name(data_key ->algorithm)); } while (0); do { if (!show_option.parseable ) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header ); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2 ); printf("data_key::algorithm::%d::%s\n", data_key->algorithm , vb2_get_crypto_algorithm_name(data_key->algorithm)); } while (0); } while (0) | |||
93 | "data_key::algorithm::%d::%s\n", data_key->algorithm,do { do { if (!show_option.parseable) printf(" Data key algorithm: %d %s\n" , data_key->algorithm, vb2_get_crypto_algorithm_name(data_key ->algorithm)); } while (0); do { if (!show_option.parseable ) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header ); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2 ); printf("data_key::algorithm::%d::%s\n", data_key->algorithm , vb2_get_crypto_algorithm_name(data_key->algorithm)); } while (0); } while (0) | |||
94 | vb2_get_crypto_algorithm_name(data_key->algorithm))do { do { if (!show_option.parseable) printf(" Data key algorithm: %d %s\n" , data_key->algorithm, vb2_get_crypto_algorithm_name(data_key ->algorithm)); } while (0); do { if (!show_option.parseable ) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header ); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2 ); printf("data_key::algorithm::%d::%s\n", data_key->algorithm , vb2_get_crypto_algorithm_name(data_key->algorithm)); } while (0); } while (0); | |||
95 | FT_PRINT(" Data key version: %d\n", "data_key::version::%d\n",do { do { if (!show_option.parseable) printf(" Data key version: %d\n" , data_key->key_version); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("data_key::version::%d\n" , data_key->key_version); } while (0); } while (0) | |||
96 | data_key->key_version)do { do { if (!show_option.parseable) printf(" Data key version: %d\n" , data_key->key_version); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("data_key::version::%d\n" , data_key->key_version); } while (0); } while (0); | |||
97 | FT_PRINT(" Data key sha1sum: %s\n", "data_key::sha1_sum::%s\n",do { do { if (!show_option.parseable) printf(" Data key sha1sum: %s\n" , packed_key_sha1_string(data_key)); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("data_key::sha1_sum::%s\n" , packed_key_sha1_string(data_key)); } while (0); } while (0) | |||
98 | packed_key_sha1_string(data_key))do { do { if (!show_option.parseable) printf(" Data key sha1sum: %s\n" , packed_key_sha1_string(data_key)); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("data_key::sha1_sum::%s\n" , packed_key_sha1_string(data_key)); } while (0); } while (0); | |||
99 | } | |||
100 | ||||
101 | int ft_show_pubkey(const char *fname) | |||
102 | { | |||
103 | int fd = -1; | |||
104 | struct vb2_packed_key *pubkey; | |||
105 | uint32_t len; | |||
106 | int rv = 0; | |||
107 | ||||
108 | if (futil_open_and_map_file(fname, &fd, FILE_RO, (uint8_t **)&pubkey, | |||
109 | &len)) | |||
110 | return 1; | |||
111 | ||||
112 | if (vb2_packed_key_looks_ok(pubkey, len)) { | |||
113 | ERROR("Invalid public key: %s\n", fname)fprintf(stderr, "ERROR: %s: " "Invalid public key: %s\n", __func__ , fname ); | |||
114 | rv = 1; | |||
115 | goto done; | |||
116 | } | |||
117 | FT_READABLE_PRINT("Public Key file: %s\n", fname)do { if (!show_option.parseable) printf("Public Key file: %s\n" , fname); } while (0); | |||
118 | ||||
119 | ft_print_header = "pubkey"; | |||
120 | show_pubkey(pubkey, " "); | |||
121 | ||||
122 | done: | |||
123 | futil_unmap_and_close_file(fd, FILE_RO, (uint8_t *)pubkey, len); | |||
124 | return rv; | |||
125 | } | |||
126 | ||||
127 | int ft_show_privkey(const char *fname) | |||
128 | { | |||
129 | int fd = -1; | |||
130 | int rv = 0; | |||
131 | struct vb2_packed_private_key *pkey = NULL((void*)0); | |||
132 | uint32_t len; | |||
133 | struct vb2_private_key key; | |||
134 | const unsigned char *start; | |||
135 | ||||
136 | if (futil_open_and_map_file(fname, &fd, FILE_RO, (uint8_t **)&pkey, | |||
137 | &len)) | |||
138 | return 1; | |||
139 | ||||
140 | start = pkey->key_data; | |||
141 | if (len <= sizeof(*pkey)) { | |||
142 | ERROR("Invalid private key: %s\n", fname)fprintf(stderr, "ERROR: %s: " "Invalid private key: %s\n", __func__ , fname ); | |||
143 | rv = 1; | |||
144 | goto done; | |||
145 | } | |||
146 | len -= sizeof(*pkey); | |||
147 | key.rsa_private_key = d2i_RSAPrivateKey(NULL((void*)0), &start, len); | |||
148 | ||||
149 | ||||
150 | ft_print_header = "prikey"; | |||
151 | FT_READABLE_PRINT("Private Key file: %s\n", fname)do { if (!show_option.parseable) printf("Private Key file: %s\n" , fname); } while (0); | |||
152 | FT_PRINT(" Vboot API: 1.0\n", "api::1.0\n")do { do { if (!show_option.parseable) printf(" Vboot API: 1.0\n" ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("api::1.0\n" ); } while (0); } while (0); | |||
153 | FT_PRINT(" Algorithm: %u %s\n",do { do { if (!show_option.parseable) printf(" Algorithm: %u %s\n" , pkey->algorithm, vb2_get_crypto_algorithm_name(pkey-> algorithm)); } while (0); do { if (!show_option.parseable) break ; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header ); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2 ); printf("algorithm::%d::%s\n", pkey->algorithm, vb2_get_crypto_algorithm_name (pkey->algorithm)); } while (0); } while (0) | |||
154 | "algorithm::%d::%s\n", pkey->algorithm,do { do { if (!show_option.parseable) printf(" Algorithm: %u %s\n" , pkey->algorithm, vb2_get_crypto_algorithm_name(pkey-> algorithm)); } while (0); do { if (!show_option.parseable) break ; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header ); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2 ); printf("algorithm::%d::%s\n", pkey->algorithm, vb2_get_crypto_algorithm_name (pkey->algorithm)); } while (0); } while (0) | |||
155 | vb2_get_crypto_algorithm_name(pkey->algorithm))do { do { if (!show_option.parseable) printf(" Algorithm: %u %s\n" , pkey->algorithm, vb2_get_crypto_algorithm_name(pkey-> algorithm)); } while (0); do { if (!show_option.parseable) break ; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header ); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2 ); printf("algorithm::%d::%s\n", pkey->algorithm, vb2_get_crypto_algorithm_name (pkey->algorithm)); } while (0); } while (0); | |||
156 | FT_PRINT(" Key sha1sum: %s\n", "sha1_sum::%s\n",do { do { if (!show_option.parseable) printf(" Key sha1sum: %s\n" , private_key_sha1_string(&key)); } while (0); do { if (! show_option.parseable) break; if (ft_print_header != ((void*) 0)) printf("%s::", ft_print_header); if (ft_print_header2 != ( (void*)0)) printf("%s::", ft_print_header2); printf("sha1_sum::%s\n" , private_key_sha1_string(&key)); } while (0); } while (0 ) | |||
157 | private_key_sha1_string(&key))do { do { if (!show_option.parseable) printf(" Key sha1sum: %s\n" , private_key_sha1_string(&key)); } while (0); do { if (! show_option.parseable) break; if (ft_print_header != ((void*) 0)) printf("%s::", ft_print_header); if (ft_print_header2 != ( (void*)0)) printf("%s::", ft_print_header2); printf("sha1_sum::%s\n" , private_key_sha1_string(&key)); } while (0); } while (0 ); | |||
158 | ||||
159 | done: | |||
160 | futil_unmap_and_close_file(fd, FILE_RO, (uint8_t *)pkey, len); | |||
161 | return rv; | |||
162 | } | |||
163 | ||||
164 | int ft_show_keyblock(const char *fname) | |||
165 | { | |||
166 | struct vb2_keyblock *block; | |||
167 | struct vb2_public_key *sign_key = show_option.k; | |||
168 | int good_sig = 0; | |||
169 | int retval = 0; | |||
170 | int fd = -1; | |||
171 | uint32_t len; | |||
172 | ||||
173 | if (futil_open_and_map_file(fname, &fd, FILE_RO, (uint8_t **)&block, &len)) | |||
174 | return 1; | |||
175 | ||||
176 | ft_print_header = "keyblock"; | |||
177 | ||||
178 | /* Check the hash only first */ | |||
179 | if (vb2_verify_keyblock_hash(block, len, &wb)) { | |||
180 | ERROR("%s is invalid\n", fname)fprintf(stderr, "ERROR: %s: " "%s is invalid\n", __func__, fname ); | |||
181 | FT_PARSEABLE_PRINT("invalid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("invalid\n" ); } while (0); | |||
182 | retval = 1; | |||
183 | goto done; | |||
184 | } else { | |||
185 | FT_PARSEABLE_PRINT("valid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("valid\n" ); } while (0); | |||
186 | } | |||
187 | ||||
188 | /* Check the signature if we have one */ | |||
189 | if (sign_key && | |||
190 | VB2_SUCCESS == vb2_verify_keyblock(block, len, sign_key, &wb)) | |||
191 | good_sig = 1; | |||
192 | else if (show_option.strict) | |||
193 | retval = 1; | |||
194 | ||||
195 | show_keyblock(block, fname, !!sign_key, good_sig); | |||
196 | ||||
197 | done: | |||
198 | futil_unmap_and_close_file(fd, FILE_RO, (uint8_t *)block, len); | |||
199 | return retval; | |||
200 | } | |||
201 | ||||
202 | static int fw_show_metadata_hash(const char *fname, enum bios_component body_c, | |||
203 | struct vb2_fw_preamble *pre) | |||
204 | { | |||
205 | struct vb2_hash real_hash; | |||
206 | struct vb2_hash *body_hash = | |||
207 | (struct vb2_hash *)vb2_signature_data(&pre->body_signature); | |||
208 | const uint32_t bhsize = vb2_digest_size(body_hash->algo); | |||
209 | ||||
210 | if (!bhsize || pre->body_signature.sig_size < | |||
211 | offsetof(struct vb2_hash, raw)__builtin_offsetof(struct vb2_hash, raw) + bhsize) { | |||
212 | ERROR("Body signature data is too small to fit metadata hash.\n")fprintf(stderr, "ERROR: %s: " "Body signature data is too small to fit metadata hash.\n" , __func__ ); | |||
213 | return 1; | |||
214 | } | |||
215 | ||||
216 | FT_READABLE_PRINT(" Body metadata hash: %s ",do { if (!show_option.parseable) printf(" Body metadata hash: %s " , vb2_get_hash_algorithm_name(body_hash->algo)); } while ( 0) | |||
217 | vb2_get_hash_algorithm_name(body_hash->algo))do { if (!show_option.parseable) printf(" Body metadata hash: %s " , vb2_get_hash_algorithm_name(body_hash->algo)); } while ( 0); | |||
218 | FT_PARSEABLE_PRINT("body::metadata_hash::algorithm::%d::%s\n",do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::metadata_hash::algorithm::%d::%s\n" , body_hash->algo, vb2_get_hash_algorithm_name(body_hash-> algo)); } while (0) | |||
219 | body_hash->algo,do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::metadata_hash::algorithm::%d::%s\n" , body_hash->algo, vb2_get_hash_algorithm_name(body_hash-> algo)); } while (0) | |||
220 | vb2_get_hash_algorithm_name(body_hash->algo))do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::metadata_hash::algorithm::%d::%s\n" , body_hash->algo, vb2_get_hash_algorithm_name(body_hash-> algo)); } while (0); | |||
221 | if (vb2_digest_size(body_hash->algo)) { | |||
222 | FT_PARSEABLE_PRINT("body::metadata_hash::hex::")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::metadata_hash::hex::" ); } while (0); | |||
223 | print_bytes((uint8_t *)body_hash->raw, | |||
224 | vb2_digest_size(body_hash->algo)); | |||
225 | putchar('\n'); | |||
226 | } | |||
227 | ||||
228 | if (cbfstool_get_metadata_hash(fname, fmap_name[body_c], &real_hash) != | |||
229 | VB2_SUCCESS || | |||
230 | real_hash.algo == VB2_HASH_INVALID) { | |||
231 | ERROR("Failed to get metadata hash. Firmware body is"fprintf(stderr, "ERROR: %s: " "Failed to get metadata hash. Firmware body is" " corrupted or is not a valid CBFS.\n", __func__ ) | |||
232 | " corrupted or is not a valid CBFS.\n")fprintf(stderr, "ERROR: %s: " "Failed to get metadata hash. Firmware body is" " corrupted or is not a valid CBFS.\n", __func__ ); | |||
233 | FT_PARSEABLE_PRINT("body::metadata_hash::invalid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::metadata_hash::invalid\n" ); } while (0); | |||
234 | FT_PARSEABLE_PRINT("body::signature::invalid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::signature::invalid\n" ); } while (0); | |||
235 | return 1; | |||
236 | } | |||
237 | ||||
238 | if (body_hash->algo != real_hash.algo || | |||
239 | !vb2_digest_size(body_hash->algo) || | |||
240 | memcmp(body_hash->raw, real_hash.raw, | |||
241 | vb2_digest_size(body_hash->algo))) { | |||
242 | FT_READABLE_PRINT(" MISMATCH! Real hash: %s:",do { if (!show_option.parseable) printf(" MISMATCH! Real hash: %s:" , vb2_get_hash_algorithm_name(real_hash.algo)); } while (0) | |||
243 | vb2_get_hash_algorithm_name(real_hash.algo))do { if (!show_option.parseable) printf(" MISMATCH! Real hash: %s:" , vb2_get_hash_algorithm_name(real_hash.algo)); } while (0); | |||
244 | FT_PARSEABLE_PRINT("body::metadata_hash::invalid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::metadata_hash::invalid\n" ); } while (0); | |||
245 | FT_PARSEABLE_PRINT(do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::metadata_hash::expected::algorithm::%d::%s\n" , real_hash.algo, vb2_get_hash_algorithm_name(real_hash.algo) ); } while (0) | |||
246 | "body::metadata_hash::expected::algorithm::%d::%s\n",do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::metadata_hash::expected::algorithm::%d::%s\n" , real_hash.algo, vb2_get_hash_algorithm_name(real_hash.algo) ); } while (0) | |||
247 | real_hash.algo,do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::metadata_hash::expected::algorithm::%d::%s\n" , real_hash.algo, vb2_get_hash_algorithm_name(real_hash.algo) ); } while (0) | |||
248 | vb2_get_hash_algorithm_name(real_hash.algo))do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::metadata_hash::expected::algorithm::%d::%s\n" , real_hash.algo, vb2_get_hash_algorithm_name(real_hash.algo) ); } while (0); | |||
249 | ||||
250 | FT_PARSEABLE_PRINT("body::metadata_hash::expected::hex::")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::metadata_hash::expected::hex::" ); } while (0); | |||
251 | ||||
252 | print_bytes(&real_hash.raw, vb2_digest_size(real_hash.algo)); | |||
253 | putchar('\n'); | |||
254 | ERROR("Signature hash does not match with"fprintf(stderr, "ERROR: %s: " "Signature hash does not match with" " real metadata hash.\n", __func__ ) | |||
255 | " real metadata hash.\n")fprintf(stderr, "ERROR: %s: " "Signature hash does not match with" " real metadata hash.\n", __func__ ); | |||
256 | ||||
257 | /* To balance out signature::valid otherwise printed by caller. */ | |||
258 | FT_PARSEABLE_PRINT("body::signature::invalid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::signature::invalid\n" ); } while (0); | |||
259 | return 1; | |||
260 | } else { | |||
261 | FT_PRINT(" Body metadata hash valid!\n",do { do { if (!show_option.parseable) printf(" Body metadata hash valid!\n" ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::metadata_hash::valid\n" ); } while (0); } while (0) | |||
262 | "body::metadata_hash::valid\n")do { do { if (!show_option.parseable) printf(" Body metadata hash valid!\n" ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::metadata_hash::valid\n" ); } while (0); } while (0); | |||
263 | } | |||
264 | return 0; | |||
265 | } | |||
266 | ||||
267 | int show_fw_preamble_buf(const char *fname, uint8_t *buf, uint32_t len, | |||
268 | struct bios_state_s *state) | |||
269 | { | |||
270 | const char *print_name = state ? fmap_name[state->c] : fname; | |||
271 | struct vb2_keyblock *keyblock = (struct vb2_keyblock *)buf; | |||
272 | struct vb2_public_key *sign_key = show_option.k; | |||
273 | uint8_t *fv_data = show_option.fv; | |||
274 | uint64_t fv_size = show_option.fv_size; | |||
275 | struct bios_area_s *fw_body_area = 0; | |||
276 | enum bios_component body_c = BIOS_FMAP_FW_MAIN_A; | |||
277 | int good_sig = 0; | |||
278 | int retval = 0; | |||
279 | ||||
280 | ft_print_header2 = "keyblock"; | |||
281 | /* Check the hash... */ | |||
282 | if (VB2_SUCCESS != vb2_verify_keyblock_hash(keyblock, len, &wb)) { | |||
283 | ERROR("%s keyblock component is invalid\n", print_name)fprintf(stderr, "ERROR: %s: " "%s keyblock component is invalid\n" , __func__, print_name ); | |||
284 | FT_PARSEABLE_PRINT("invalid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("invalid\n" ); } while (0); | |||
285 | return 1; | |||
286 | } else { | |||
287 | FT_PARSEABLE_PRINT("valid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("valid\n" ); } while (0); | |||
288 | } | |||
289 | ||||
290 | /* | |||
291 | * If we're being invoked while poking through a BIOS, we should | |||
292 | * be given the keys and data to verify as part of the state. If we | |||
293 | * have no state, then we're just looking at a standalone fw_preamble, | |||
294 | * so we'll have to get any keys or data from options. | |||
295 | */ | |||
296 | struct vb2_public_key root_key; | |||
297 | if (state) { | |||
298 | if (!sign_key && | |||
299 | state->rootkey.is_valid && | |||
300 | VB2_SUCCESS == vb2_unpack_key_buffer(&root_key, | |||
301 | state->rootkey.buf, | |||
302 | state->rootkey.len)) { | |||
303 | /* BIOS should have a rootkey in the GBB */ | |||
304 | sign_key = &root_key; | |||
305 | } | |||
306 | ||||
307 | /* Identify the firmware body for this VBLOCK */ | |||
308 | body_c = state->c == BIOS_FMAP_VBLOCK_A ? BIOS_FMAP_FW_MAIN_A | |||
309 | : BIOS_FMAP_FW_MAIN_B; | |||
310 | fw_body_area = &state->area[body_c]; | |||
311 | } | |||
312 | ||||
313 | /* If we have a key, check the signature too */ | |||
314 | if (sign_key && VB2_SUCCESS == | |||
315 | vb2_verify_keyblock(keyblock, len, sign_key, &wb)) | |||
316 | good_sig = 1; | |||
317 | else if (show_option.strict) | |||
318 | retval = 1; | |||
319 | ||||
320 | show_keyblock(keyblock, print_name, !!sign_key, good_sig); | |||
321 | ||||
322 | struct vb2_public_key data_key; | |||
323 | if (VB2_SUCCESS != vb2_unpack_key(&data_key, &keyblock->data_key)) { | |||
324 | ERROR("Parsing data key in %s\n", print_name)fprintf(stderr, "ERROR: %s: " "Parsing data key in %s\n", __func__ , print_name ); | |||
325 | FT_PARSEABLE_PRINT("data_key::invalid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("data_key::invalid\n" ); } while (0); | |||
326 | return 1; | |||
327 | } | |||
328 | ||||
329 | ft_print_header2 = "preamble"; | |||
330 | uint32_t more = keyblock->keyblock_size; | |||
331 | struct vb2_fw_preamble *pre2 = (struct vb2_fw_preamble *)(buf + more); | |||
332 | if (VB2_SUCCESS != vb2_verify_fw_preamble(pre2, len - more, | |||
333 | &data_key, &wb)) { | |||
334 | ERROR("%s is invalid\n", print_name)fprintf(stderr, "ERROR: %s: " "%s is invalid\n", __func__, print_name ); | |||
335 | FT_PARSEABLE_PRINT("invalid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("invalid\n" ); } while (0); | |||
336 | FT_PARSEABLE_PRINT("signature::invalid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("signature::invalid\n" ); } while (0); | |||
337 | return 1; | |||
338 | } else { | |||
339 | FT_PARSEABLE_PRINT("valid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("valid\n" ); } while (0); | |||
340 | FT_PARSEABLE_PRINT("signature::valid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("signature::valid\n" ); } while (0); | |||
341 | } | |||
342 | ||||
343 | uint32_t flags = pre2->flags; | |||
344 | if (pre2->header_version_minor < 1) | |||
345 | flags = 0; /* Old 2.0 structure didn't have flags */ | |||
346 | ||||
347 | FT_READABLE_PRINT("Firmware Preamble:\n")do { if (!show_option.parseable) printf("Firmware Preamble:\n" ); } while (0); | |||
348 | FT_PRINT(" Size: %d\n", "size::%d\n",do { do { if (!show_option.parseable) printf(" Size: %d\n" , pre2->preamble_size); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("size::%d\n", pre2-> preamble_size); } while (0); } while (0) | |||
349 | pre2->preamble_size)do { do { if (!show_option.parseable) printf(" Size: %d\n" , pre2->preamble_size); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("size::%d\n", pre2-> preamble_size); } while (0); } while (0); | |||
350 | FT_PRINT(" Header version: %d.%d\n",do { do { if (!show_option.parseable) printf(" Header version: %d.%d\n" , pre2->header_version_major, pre2->header_version_minor ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("header_version::%d.%d\n" , pre2->header_version_major, pre2->header_version_minor ); } while (0); } while (0) | |||
351 | "header_version::%d.%d\n",do { do { if (!show_option.parseable) printf(" Header version: %d.%d\n" , pre2->header_version_major, pre2->header_version_minor ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("header_version::%d.%d\n" , pre2->header_version_major, pre2->header_version_minor ); } while (0); } while (0) | |||
352 | pre2->header_version_major,do { do { if (!show_option.parseable) printf(" Header version: %d.%d\n" , pre2->header_version_major, pre2->header_version_minor ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("header_version::%d.%d\n" , pre2->header_version_major, pre2->header_version_minor ); } while (0); } while (0) | |||
353 | pre2->header_version_minor)do { do { if (!show_option.parseable) printf(" Header version: %d.%d\n" , pre2->header_version_major, pre2->header_version_minor ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("header_version::%d.%d\n" , pre2->header_version_major, pre2->header_version_minor ); } while (0); } while (0); | |||
354 | FT_PRINT(" Firmware version: %d\n", "firmware_version::%d\n",do { do { if (!show_option.parseable) printf(" Firmware version: %d\n" , pre2->firmware_version); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("firmware_version::%d\n" , pre2->firmware_version); } while (0); } while (0) | |||
355 | pre2->firmware_version)do { do { if (!show_option.parseable) printf(" Firmware version: %d\n" , pre2->firmware_version); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("firmware_version::%d\n" , pre2->firmware_version); } while (0); } while (0); | |||
356 | ||||
357 | struct vb2_packed_key *kernel_subkey = &pre2->kernel_subkey; | |||
358 | FT_PRINT(" Kernel key algorithm: %d %s\n",do { do { if (!show_option.parseable) printf(" Kernel key algorithm: %d %s\n" , kernel_subkey->algorithm, vb2_get_crypto_algorithm_name( kernel_subkey->algorithm)); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("kernel_subkey::algorithm::%d::%s\n" , kernel_subkey->algorithm, vb2_get_crypto_algorithm_name( kernel_subkey->algorithm)); } while (0); } while (0) | |||
359 | "kernel_subkey::algorithm::%d::%s\n",do { do { if (!show_option.parseable) printf(" Kernel key algorithm: %d %s\n" , kernel_subkey->algorithm, vb2_get_crypto_algorithm_name( kernel_subkey->algorithm)); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("kernel_subkey::algorithm::%d::%s\n" , kernel_subkey->algorithm, vb2_get_crypto_algorithm_name( kernel_subkey->algorithm)); } while (0); } while (0) | |||
360 | kernel_subkey->algorithm,do { do { if (!show_option.parseable) printf(" Kernel key algorithm: %d %s\n" , kernel_subkey->algorithm, vb2_get_crypto_algorithm_name( kernel_subkey->algorithm)); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("kernel_subkey::algorithm::%d::%s\n" , kernel_subkey->algorithm, vb2_get_crypto_algorithm_name( kernel_subkey->algorithm)); } while (0); } while (0) | |||
361 | vb2_get_crypto_algorithm_name(kernel_subkey->algorithm))do { do { if (!show_option.parseable) printf(" Kernel key algorithm: %d %s\n" , kernel_subkey->algorithm, vb2_get_crypto_algorithm_name( kernel_subkey->algorithm)); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("kernel_subkey::algorithm::%d::%s\n" , kernel_subkey->algorithm, vb2_get_crypto_algorithm_name( kernel_subkey->algorithm)); } while (0); } while (0); | |||
362 | if (kernel_subkey->algorithm >= VB2_ALG_COUNT) | |||
363 | retval = 1; | |||
364 | FT_PRINT(" Kernel key version: %d\n",do { do { if (!show_option.parseable) printf(" Kernel key version: %d\n" , kernel_subkey->key_version); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("kernel_subkey::version::%d\n" , kernel_subkey->key_version); } while (0); } while (0) | |||
365 | "kernel_subkey::version::%d\n",do { do { if (!show_option.parseable) printf(" Kernel key version: %d\n" , kernel_subkey->key_version); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("kernel_subkey::version::%d\n" , kernel_subkey->key_version); } while (0); } while (0) | |||
366 | kernel_subkey->key_version)do { do { if (!show_option.parseable) printf(" Kernel key version: %d\n" , kernel_subkey->key_version); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("kernel_subkey::version::%d\n" , kernel_subkey->key_version); } while (0); } while (0); | |||
367 | FT_PRINT(" Kernel key sha1sum: %s\n",do { do { if (!show_option.parseable) printf(" Kernel key sha1sum: %s\n" , packed_key_sha1_string(kernel_subkey)); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void *)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("kernel_subkey::sha1_sum::%s\n" , packed_key_sha1_string(kernel_subkey)); } while (0); } while (0) | |||
368 | "kernel_subkey::sha1_sum::%s\n",do { do { if (!show_option.parseable) printf(" Kernel key sha1sum: %s\n" , packed_key_sha1_string(kernel_subkey)); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void *)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("kernel_subkey::sha1_sum::%s\n" , packed_key_sha1_string(kernel_subkey)); } while (0); } while (0) | |||
369 | packed_key_sha1_string(kernel_subkey))do { do { if (!show_option.parseable) printf(" Kernel key sha1sum: %s\n" , packed_key_sha1_string(kernel_subkey)); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void *)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("kernel_subkey::sha1_sum::%s\n" , packed_key_sha1_string(kernel_subkey)); } while (0); } while (0); | |||
370 | FT_READABLE_PRINT(" Firmware body size: %d\n",do { if (!show_option.parseable) printf(" Firmware body size: %d\n" , pre2->body_signature.data_size); } while (0) | |||
371 | pre2->body_signature.data_size)do { if (!show_option.parseable) printf(" Firmware body size: %d\n" , pre2->body_signature.data_size); } while (0); | |||
372 | FT_PRINT(" Preamble flags: %d\n",do { do { if (!show_option.parseable) printf(" Preamble flags: %d\n" , flags); } while (0); do { if (!show_option.parseable) break ; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header ); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2 ); printf("flags::%d\n", flags); } while (0); } while (0) | |||
373 | "flags::%d\n", flags)do { do { if (!show_option.parseable) printf(" Preamble flags: %d\n" , flags); } while (0); do { if (!show_option.parseable) break ; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header ); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2 ); printf("flags::%d\n", flags); } while (0); } while (0); | |||
374 | ft_print_header2 = NULL((void*)0); | |||
375 | ||||
376 | FT_PARSEABLE_PRINT("body::size::%d\n", pre2->body_signature.data_size)do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::size::%d\n" , pre2->body_signature.data_size); } while (0); | |||
377 | ||||
378 | ||||
379 | if (flags & VB2_FIRMWARE_PREAMBLE_USE_RO_NORMAL0x00000001) { | |||
380 | FT_PRINT("Preamble requests USE_RO_NORMAL;"do { do { if (!show_option.parseable) printf("Preamble requests USE_RO_NORMAL;" " skipping body verification.\n"); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::signature::ignored\n" ); } while (0); } while (0) | |||
381 | " skipping body verification.\n",do { do { if (!show_option.parseable) printf("Preamble requests USE_RO_NORMAL;" " skipping body verification.\n"); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::signature::ignored\n" ); } while (0); } while (0) | |||
382 | "body::signature::ignored\n")do { do { if (!show_option.parseable) printf("Preamble requests USE_RO_NORMAL;" " skipping body verification.\n"); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::signature::ignored\n" ); } while (0); } while (0); | |||
383 | goto done; | |||
384 | } | |||
385 | ||||
386 | /* We'll need to get the firmware body from somewhere... */ | |||
387 | if (fw_body_area && fw_body_area->is_valid) { | |||
388 | fv_data = fw_body_area->buf; | |||
389 | fv_size = fw_body_area->len; | |||
390 | } | |||
391 | ||||
392 | if (!fv_data) { | |||
393 | FT_PRINT("No firmware body available to verify.\n",do { do { if (!show_option.parseable) printf("No firmware body available to verify.\n" ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::signature::ignored\n" ); } while (0); } while (0) | |||
394 | "body::signature::ignored\n")do { do { if (!show_option.parseable) printf("No firmware body available to verify.\n" ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::signature::ignored\n" ); } while (0); } while (0); | |||
395 | if (show_option.strict) | |||
396 | return 1; | |||
397 | return 0; | |||
398 | } | |||
399 | ||||
400 | if (pre2->body_signature.data_size) { | |||
401 | if (vb2_verify_data(fv_data, fv_size, &pre2->body_signature, | |||
402 | &data_key, &wb) != VB2_SUCCESS) { | |||
403 | ERROR("Verifying firmware body.\n")fprintf(stderr, "ERROR: %s: " "Verifying firmware body.\n", __func__ ); | |||
404 | FT_PARSEABLE_PRINT("body::signature::invalid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::signature::invalid\n" ); } while (0); | |||
405 | return show_option.strict ? 1 : 0; | |||
406 | } | |||
407 | } else if (state) { /* Only works if `fname` is a BIOS image */ | |||
408 | if (fw_show_metadata_hash(fname, body_c, pre2)) | |||
409 | return show_option.strict ? 1 : 0; | |||
410 | } else { | |||
411 | WARN("Metadata hash verification not supported.\n")fprintf(stderr, "WARNING: %s: " "Metadata hash verification not supported.\n" , __func__ ); | |||
412 | FT_PARSEABLE_PRINT("body::metadata_hash::ignored\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::metadata_hash::ignored\n" ); } while (0); | |||
413 | FT_PARSEABLE_PRINT("body::signature::ignored\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::signature::ignored\n" ); } while (0); | |||
414 | return show_option.strict ? 1 : 0; | |||
415 | } | |||
416 | ||||
417 | FT_PRINT("Body verification succeeded.\n",do { do { if (!show_option.parseable) printf("Body verification succeeded.\n" ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::signature::valid\n" ); } while (0); } while (0) | |||
418 | "body::signature::valid\n")do { do { if (!show_option.parseable) printf("Body verification succeeded.\n" ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::signature::valid\n" ); } while (0); } while (0); | |||
419 | ||||
420 | done: | |||
421 | /* Can't trust the BIOS unless everything is signed. */ | |||
422 | if (good_sig) { | |||
423 | if (state) | |||
424 | state->area[state->c].is_valid = 1; | |||
425 | FT_PARSEABLE_PRINT("verified\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("verified\n" ); } while (0); | |||
426 | } | |||
427 | ||||
428 | return retval; | |||
429 | } | |||
430 | ||||
431 | int ft_show_fw_preamble(const char *fname) | |||
432 | { | |||
433 | int rv = 0; | |||
434 | int fd = -1; | |||
435 | uint8_t *buf; | |||
436 | uint32_t len; | |||
437 | ||||
438 | if (futil_open_and_map_file(fname, &fd, FILE_RO, &buf, &len)) | |||
439 | return 1; | |||
440 | ft_print_header = "fw_pre"; | |||
441 | rv = show_fw_preamble_buf(fname, buf, len, NULL((void*)0)); | |||
442 | ||||
443 | futil_unmap_and_close_file(fd, FILE_RO, buf, len); | |||
444 | return rv; | |||
445 | } | |||
446 | ||||
447 | int ft_show_kernel_preamble(const char *fname) | |||
448 | { | |||
449 | struct vb2_keyblock *keyblock; | |||
450 | struct vb2_public_key *sign_key = show_option.k; | |||
451 | int retval = 0; | |||
452 | int fd = -1; | |||
453 | uint8_t *buf; | |||
454 | uint32_t len; | |||
455 | ||||
456 | if (futil_open_and_map_file(fname, &fd, FILE_RO, &buf, &len)) | |||
457 | return 1; | |||
458 | ||||
459 | keyblock = (struct vb2_keyblock *)buf; | |||
460 | ft_print_header = "kernel"; | |||
461 | ft_print_header2 = "keyblock"; | |||
462 | /* Check the hash... */ | |||
463 | if (VB2_SUCCESS != vb2_verify_keyblock_hash(keyblock, len, &wb)) { | |||
464 | ERROR("%s keyblock component is invalid\n", fname)fprintf(stderr, "ERROR: %s: " "%s keyblock component is invalid\n" , __func__, fname ); | |||
465 | FT_PARSEABLE_PRINT("invalid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("invalid\n" ); } while (0); | |||
466 | retval = 1; | |||
467 | goto done; | |||
468 | } else { | |||
469 | FT_PARSEABLE_PRINT("valid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("valid\n" ); } while (0); | |||
470 | } | |||
471 | ||||
472 | /* If we have a key, check the signature too */ | |||
473 | int good_sig = 0; | |||
474 | if (sign_key && VB2_SUCCESS == | |||
475 | vb2_verify_keyblock(keyblock, len, sign_key, &wb)) | |||
476 | good_sig = 1; | |||
477 | else if (show_option.strict) | |||
478 | retval = 1; | |||
479 | ||||
480 | FT_READABLE_PRINT("Kernel partition: %s\n", fname)do { if (!show_option.parseable) printf("Kernel partition: %s\n" , fname); } while (0); | |||
481 | show_keyblock(keyblock, NULL((void*)0), !!sign_key, good_sig); | |||
482 | ||||
483 | struct vb2_public_key data_key; | |||
484 | if (VB2_SUCCESS != vb2_unpack_key(&data_key, &keyblock->data_key)) { | |||
485 | ERROR("Parsing data key in %s\n", fname)fprintf(stderr, "ERROR: %s: " "Parsing data key in %s\n", __func__ , fname ); | |||
486 | retval = 1; | |||
487 | goto done; | |||
488 | } | |||
489 | ||||
490 | ft_print_header2 = NULL((void*)0); | |||
491 | uint32_t more = keyblock->keyblock_size; | |||
492 | struct vb2_kernel_preamble *pre2 = | |||
493 | (struct vb2_kernel_preamble *)(buf + more); | |||
494 | ||||
495 | if (VB2_SUCCESS != vb2_verify_kernel_preamble(pre2, len - more, | |||
496 | &data_key, &wb)) { | |||
497 | ERROR("%s is invalid\n", fname)fprintf(stderr, "ERROR: %s: " "%s is invalid\n", __func__, fname ); | |||
498 | FT_PARSEABLE_PRINT("preamble::invalid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("preamble::invalid\n" ); } while (0); | |||
499 | FT_PARSEABLE_PRINT("preamble::signature::invalid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("preamble::signature::invalid\n" ); } while (0); | |||
500 | retval = 1; | |||
501 | goto done; | |||
502 | } | |||
503 | ||||
504 | more += pre2->preamble_size; | |||
505 | FT_PARSEABLE_PRINT("preamble::valid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("preamble::valid\n" ); } while (0); | |||
506 | FT_PARSEABLE_PRINT("preamble::signature::valid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("preamble::signature::valid\n" ); } while (0); | |||
507 | FT_READABLE_PRINT("Kernel Preamble:\n")do { if (!show_option.parseable) printf("Kernel Preamble:\n") ; } while (0); | |||
508 | FT_PRINT(" Size: %#x\n",do { do { if (!show_option.parseable) printf(" Size: %#x\n" , pre2->preamble_size); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("preamble::size::%d\n" , pre2->preamble_size); } while (0); } while (0) | |||
509 | "preamble::size::%d\n", pre2->preamble_size)do { do { if (!show_option.parseable) printf(" Size: %#x\n" , pre2->preamble_size); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("preamble::size::%d\n" , pre2->preamble_size); } while (0); } while (0); | |||
510 | FT_PRINT(" Header version: %d.%d\n",do { do { if (!show_option.parseable) printf(" Header version: %d.%d\n" , pre2->header_version_major, pre2->header_version_minor ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("preamble::header_version::%d.%d\n" , pre2->header_version_major, pre2->header_version_minor ); } while (0); } while (0) | |||
511 | "preamble::header_version::%d.%d\n",do { do { if (!show_option.parseable) printf(" Header version: %d.%d\n" , pre2->header_version_major, pre2->header_version_minor ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("preamble::header_version::%d.%d\n" , pre2->header_version_major, pre2->header_version_minor ); } while (0); } while (0) | |||
512 | pre2->header_version_major,do { do { if (!show_option.parseable) printf(" Header version: %d.%d\n" , pre2->header_version_major, pre2->header_version_minor ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("preamble::header_version::%d.%d\n" , pre2->header_version_major, pre2->header_version_minor ); } while (0); } while (0) | |||
513 | pre2->header_version_minor)do { do { if (!show_option.parseable) printf(" Header version: %d.%d\n" , pre2->header_version_major, pre2->header_version_minor ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("preamble::header_version::%d.%d\n" , pre2->header_version_major, pre2->header_version_minor ); } while (0); } while (0); | |||
514 | FT_PRINT(" Kernel version: %u\n",do { do { if (!show_option.parseable) printf(" Kernel version: %u\n" , pre2->kernel_version); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("preamble::kernel_version::%u\n" , pre2->kernel_version); } while (0); } while (0) | |||
515 | "preamble::kernel_version::%u\n",do { do { if (!show_option.parseable) printf(" Kernel version: %u\n" , pre2->kernel_version); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("preamble::kernel_version::%u\n" , pre2->kernel_version); } while (0); } while (0) | |||
516 | pre2->kernel_version)do { do { if (!show_option.parseable) printf(" Kernel version: %u\n" , pre2->kernel_version); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("preamble::kernel_version::%u\n" , pre2->kernel_version); } while (0); } while (0); | |||
517 | FT_PRINT(" Flags: %#x\n",do { do { if (!show_option.parseable) printf(" Flags: %#x\n" , vb2_kernel_get_flags(pre2)); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("preamble::flags::%d\n" , vb2_kernel_get_flags(pre2)); } while (0); } while (0) | |||
518 | "preamble::flags::%d\n", vb2_kernel_get_flags(pre2))do { do { if (!show_option.parseable) printf(" Flags: %#x\n" , vb2_kernel_get_flags(pre2)); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("preamble::flags::%d\n" , vb2_kernel_get_flags(pre2)); } while (0); } while (0); | |||
519 | ||||
520 | FT_PRINT(" Body load address: 0x%" PRIx64 "\n",do { do { if (!show_option.parseable) printf(" Body load address: 0x%" "l" "x" "\n", pre2->body_load_address); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != (( void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::address::%" "l" "u" "\n", pre2->body_load_address); } while (0); } while (0) | |||
521 | "body::address::%" PRIu64 "\n",do { do { if (!show_option.parseable) printf(" Body load address: 0x%" "l" "x" "\n", pre2->body_load_address); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != (( void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::address::%" "l" "u" "\n", pre2->body_load_address); } while (0); } while (0) | |||
522 | pre2->body_load_address)do { do { if (!show_option.parseable) printf(" Body load address: 0x%" "l" "x" "\n", pre2->body_load_address); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != (( void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::address::%" "l" "u" "\n", pre2->body_load_address); } while (0); } while (0); | |||
523 | FT_PRINT(" Body size: %#x\n",do { do { if (!show_option.parseable) printf(" Body size: %#x\n" , pre2->body_signature.data_size); } while (0); do { if (! show_option.parseable) break; if (ft_print_header != ((void*) 0)) printf("%s::", ft_print_header); if (ft_print_header2 != ( (void*)0)) printf("%s::", ft_print_header2); printf("body::size::%d\n" , pre2->body_signature.data_size); } while (0); } while (0 ) | |||
524 | "body::size::%d\n",do { do { if (!show_option.parseable) printf(" Body size: %#x\n" , pre2->body_signature.data_size); } while (0); do { if (! show_option.parseable) break; if (ft_print_header != ((void*) 0)) printf("%s::", ft_print_header); if (ft_print_header2 != ( (void*)0)) printf("%s::", ft_print_header2); printf("body::size::%d\n" , pre2->body_signature.data_size); } while (0); } while (0 ) | |||
525 | pre2->body_signature.data_size)do { do { if (!show_option.parseable) printf(" Body size: %#x\n" , pre2->body_signature.data_size); } while (0); do { if (! show_option.parseable) break; if (ft_print_header != ((void*) 0)) printf("%s::", ft_print_header); if (ft_print_header2 != ( (void*)0)) printf("%s::", ft_print_header2); printf("body::size::%d\n" , pre2->body_signature.data_size); } while (0); } while (0 ); | |||
526 | FT_PRINT(" Bootloader address: 0x%" PRIx64 "\n",do { do { if (!show_option.parseable) printf(" Bootloader address: 0x%" "l" "x" "\n", pre2->bootloader_address); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != (( void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("bootloader::address::%" "l" "u" "\n", pre2->bootloader_address); } while (0); } while (0) | |||
527 | "bootloader::address::%" PRIu64 "\n",do { do { if (!show_option.parseable) printf(" Bootloader address: 0x%" "l" "x" "\n", pre2->bootloader_address); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != (( void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("bootloader::address::%" "l" "u" "\n", pre2->bootloader_address); } while (0); } while (0) | |||
528 | pre2->bootloader_address)do { do { if (!show_option.parseable) printf(" Bootloader address: 0x%" "l" "x" "\n", pre2->bootloader_address); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != (( void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("bootloader::address::%" "l" "u" "\n", pre2->bootloader_address); } while (0); } while (0); | |||
529 | FT_PRINT(" Bootloader size: %#x\n",do { do { if (!show_option.parseable) printf(" Bootloader size: %#x\n" , pre2->bootloader_size); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("bootloader::size::%d\n" , pre2->bootloader_size); } while (0); } while (0) | |||
530 | "bootloader::size::%d\n",do { do { if (!show_option.parseable) printf(" Bootloader size: %#x\n" , pre2->bootloader_size); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("bootloader::size::%d\n" , pre2->bootloader_size); } while (0); } while (0) | |||
531 | pre2->bootloader_size)do { do { if (!show_option.parseable) printf(" Bootloader size: %#x\n" , pre2->bootloader_size); } while (0); do { if (!show_option .parseable) break; if (ft_print_header != ((void*)0)) printf( "%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("bootloader::size::%d\n" , pre2->bootloader_size); } while (0); } while (0); | |||
532 | ||||
533 | uint64_t vmlinuz_header_address = 0; | |||
534 | uint32_t vmlinuz_header_size = 0; | |||
535 | vb2_kernel_get_vmlinuz_header(pre2, | |||
536 | &vmlinuz_header_address, | |||
537 | &vmlinuz_header_size); | |||
538 | if (vmlinuz_header_size) { | |||
539 | FT_PRINT(" Vmlinuz_header address: 0x%" PRIx64 "\n",do { do { if (!show_option.parseable) printf(" Vmlinuz_header address: 0x%" "l" "x" "\n", vmlinuz_header_address); } while (0); do { if ( !show_option.parseable) break; if (ft_print_header != ((void* )0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("vmlinuz_header::address::%" "l" "u" "\n", vmlinuz_header_address); } while (0); } while ( 0) | |||
540 | "vmlinuz_header::address::%" PRIu64 "\n",do { do { if (!show_option.parseable) printf(" Vmlinuz_header address: 0x%" "l" "x" "\n", vmlinuz_header_address); } while (0); do { if ( !show_option.parseable) break; if (ft_print_header != ((void* )0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("vmlinuz_header::address::%" "l" "u" "\n", vmlinuz_header_address); } while (0); } while ( 0) | |||
541 | vmlinuz_header_address)do { do { if (!show_option.parseable) printf(" Vmlinuz_header address: 0x%" "l" "x" "\n", vmlinuz_header_address); } while (0); do { if ( !show_option.parseable) break; if (ft_print_header != ((void* )0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("vmlinuz_header::address::%" "l" "u" "\n", vmlinuz_header_address); } while (0); } while ( 0); | |||
542 | FT_PRINT(" Vmlinuz header size: %#x\n",do { do { if (!show_option.parseable) printf(" Vmlinuz header size: %#x\n" , vmlinuz_header_size); } while (0); do { if (!show_option.parseable ) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header ); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2 ); printf("vmlinuz_header::size::%d\n", vmlinuz_header_size); } while (0); } while (0) | |||
543 | "vmlinuz_header::size::%d\n",do { do { if (!show_option.parseable) printf(" Vmlinuz header size: %#x\n" , vmlinuz_header_size); } while (0); do { if (!show_option.parseable ) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header ); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2 ); printf("vmlinuz_header::size::%d\n", vmlinuz_header_size); } while (0); } while (0) | |||
544 | vmlinuz_header_size)do { do { if (!show_option.parseable) printf(" Vmlinuz header size: %#x\n" , vmlinuz_header_size); } while (0); do { if (!show_option.parseable ) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header ); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2 ); printf("vmlinuz_header::size::%d\n", vmlinuz_header_size); } while (0); } while (0); | |||
545 | } | |||
546 | ||||
547 | /* Verify kernel body */ | |||
548 | uint8_t *kernel_blob; | |||
549 | uint64_t kernel_size; | |||
550 | if (show_option.fv) { | |||
551 | /* It's in a separate file, which we've already read in */ | |||
552 | kernel_blob = show_option.fv; | |||
553 | kernel_size = show_option.fv_size; | |||
554 | } else { | |||
555 | /* It should be at an offset within the input file. */ | |||
556 | kernel_blob = buf + more; | |||
557 | kernel_size = len - more; | |||
558 | } | |||
559 | ||||
560 | if (!kernel_size) { | |||
561 | FT_PRINT("No kernel blob available to verify.\n",do { do { if (!show_option.parseable) printf("No kernel blob available to verify.\n" ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::signature::ignored\n" ); } while (0); } while (0) | |||
562 | "body::signature::ignored\n")do { do { if (!show_option.parseable) printf("No kernel blob available to verify.\n" ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::signature::ignored\n" ); } while (0); } while (0); | |||
563 | if (show_option.strict) | |||
564 | retval = 1; | |||
565 | goto done; | |||
566 | } | |||
567 | ||||
568 | if (VB2_SUCCESS != | |||
569 | vb2_verify_data(kernel_blob, kernel_size, &pre2->body_signature, | |||
570 | &data_key, &wb)) { | |||
571 | ERROR("Verifying kernel body.\n")fprintf(stderr, "ERROR: %s: " "Verifying kernel body.\n", __func__ ); | |||
572 | FT_PARSEABLE_PRINT("body::signature::invalid\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::signature::invalid\n" ); } while (0); | |||
573 | if (show_option.strict) | |||
574 | retval = 1; | |||
575 | goto done; | |||
576 | } | |||
577 | ||||
578 | FT_PRINT("Body verification succeeded.\n",do { do { if (!show_option.parseable) printf("Body verification succeeded.\n" ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::signature::valid\n" ); } while (0); } while (0) | |||
579 | "body::signature::valid\n")do { do { if (!show_option.parseable) printf("Body verification succeeded.\n" ); } while (0); do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("body::signature::valid\n" ); } while (0); } while (0); | |||
580 | if (good_sig) | |||
581 | FT_PARSEABLE_PRINT("verified\n")do { if (!show_option.parseable) break; if (ft_print_header != ((void*)0)) printf("%s::", ft_print_header); if (ft_print_header2 != ((void*)0)) printf("%s::", ft_print_header2); printf("verified\n" ); } while (0); | |||
582 | ||||
583 | FT_READABLE_PRINT("Config:\n%s\n",do { if (!show_option.parseable) printf("Config:\n%s\n", kernel_blob + kernel_cmd_line_offset(pre2)); } while (0) | |||
584 | kernel_blob + kernel_cmd_line_offset(pre2))do { if (!show_option.parseable) printf("Config:\n%s\n", kernel_blob + kernel_cmd_line_offset(pre2)); } while (0); | |||
585 | ||||
586 | done: | |||
587 | futil_unmap_and_close_file(fd, FILE_RO, buf, len); | |||
588 | return retval; | |||
589 | } | |||
590 | ||||
591 | enum no_short_opts { | |||
592 | OPT_TYPE = 1000, | |||
593 | OPT_PUBKEY, | |||
594 | OPT_HELP, | |||
595 | }; | |||
596 | ||||
597 | static const char usage[] = "\n" | |||
598 | "Usage: " MYNAME"futility" " %s [OPTIONS] FILE [...]\n" | |||
599 | "\n" | |||
600 | "Where FILE could be\n" | |||
601 | "\n" | |||
602 | " a boot descriptor block (BDB)\n" | |||
603 | " a keyblock (.keyblock)\n" | |||
604 | " a firmware preamble signature (VBLOCK_A/B)\n" | |||
605 | " a firmware image (image.bin)\n" | |||
606 | " a kernel partition (/dev/sda2, /dev/mmcblk0p2)\n" | |||
607 | " keys in various formats (.vbpubk, .vbprivk, .pem)\n" | |||
608 | " several other file types related to verified boot\n" | |||
609 | "\n" | |||
610 | "Options:\n" | |||
611 | " -t Just show the type of each file\n" | |||
612 | " --type TYPE Override the detected file type\n" | |||
613 | " Use \"--type help\" for a list\n" | |||
614 | " -P|--parseable Machine friendly output format\n" | |||
615 | "Type-specific options:\n" | |||
616 | " -k|--publickey FILE.vbpubk Public key in vb1 format\n" | |||
617 | " --pubkey FILE.vpubk2 Public key in vb2 format\n" | |||
618 | " -f|--fv FILE Verify this payload (FW_MAIN_A/B)\n" | |||
619 | " --strict " | |||
620 | "Fail unless all signatures are valid\n" | |||
621 | "\n"; | |||
622 | ||||
623 | static void print_help(int argc, char *argv[]) | |||
624 | { | |||
625 | if (!strcmp(argv[0], "verify")) | |||
626 | printf("\nUsage: " MYNAME"futility" " %s [OPTIONS] FILE [...]\n\n" | |||
627 | "This is just an alias for\n\n" | |||
628 | " " MYNAME"futility" " show --strict\n\n", | |||
629 | argv[0]); | |||
630 | ||||
631 | printf(usage, "show"); | |||
632 | } | |||
633 | ||||
634 | static const struct option long_opts[] = { | |||
635 | /* name hasarg *flag val */ | |||
636 | {"publickey", 1, 0, 'k'}, | |||
637 | {"fv", 1, 0, 'f'}, | |||
638 | {"type", 1, NULL((void*)0), OPT_TYPE}, | |||
639 | {"strict", 0, &show_option.strict, 1}, | |||
640 | {"pubkey", 1, NULL((void*)0), OPT_PUBKEY}, | |||
641 | {"parseable", 0, NULL((void*)0), 'P'}, | |||
642 | {"help", 0, NULL((void*)0), OPT_HELP}, | |||
643 | {NULL((void*)0), 0, NULL((void*)0), 0}, | |||
644 | }; | |||
645 | static const char *short_opts = ":f:k:Pt"; | |||
646 | ||||
647 | ||||
648 | static int show_type(char *filename) | |||
649 | { | |||
650 | enum futil_file_err err; | |||
651 | enum futil_file_type type; | |||
652 | err = futil_file_type(filename, &type); | |||
653 | switch (err) { | |||
654 | case FILE_ERR_NONE: | |||
655 | printf("%s:\t%s\n", filename, futil_file_type_name(type)); | |||
656 | /* Only our recognized types return success */ | |||
657 | return 0; | |||
658 | case FILE_ERR_DIR: | |||
659 | printf("%s:\t%s\n", filename, "directory"); | |||
660 | break; | |||
661 | case FILE_ERR_CHR: | |||
662 | printf("%s:\t%s\n", filename, "character special"); | |||
663 | break; | |||
664 | case FILE_ERR_FIFO: | |||
665 | printf("%s:\t%s\n", filename, "FIFO"); | |||
666 | break; | |||
667 | case FILE_ERR_SOCK: | |||
668 | printf("%s:\t%s\n", filename, "socket"); | |||
669 | break; | |||
670 | default: | |||
671 | break; | |||
672 | } | |||
673 | /* Everything else is an error */ | |||
674 | return 1; | |||
675 | } | |||
676 | ||||
677 | static int load_publickey(const char *fname, uint8_t **buf_ptr, | |||
678 | struct vb2_public_key *pubkey) | |||
679 | { | |||
680 | uint32_t len = 0; | |||
681 | if (vb2_read_file(fname, buf_ptr, &len) != VB2_SUCCESS) { | |||
682 | ERROR("Reading publickey %s\n", fname)fprintf(stderr, "ERROR: %s: " "Reading publickey %s\n", __func__ , fname ); | |||
683 | return 1; | |||
684 | } | |||
685 | ||||
686 | struct vb2_keyblock *keyblock; | |||
687 | uint8_t *buf = *buf_ptr; | |||
688 | enum futil_file_type type = futil_file_type_buf(buf, len); | |||
689 | switch (type) { | |||
690 | case FILE_TYPE_FW_PREAMBLE: | |||
691 | keyblock = (struct vb2_keyblock *)buf; | |||
692 | if (vb2_check_keyblock(keyblock, len, &keyblock->keyblock_hash) | |||
693 | != VB2_SUCCESS) { | |||
694 | ERROR("Checking publickey keyblock\n")fprintf(stderr, "ERROR: %s: " "Checking publickey keyblock\n" , __func__ ); | |||
695 | return 1; | |||
696 | } | |||
697 | struct vb2_fw_preamble *pre = | |||
698 | (struct vb2_fw_preamble *)(buf + keyblock->keyblock_size); | |||
699 | if (vb2_unpack_key(pubkey, &pre->kernel_subkey) != VB2_SUCCESS) { | |||
700 | ERROR("Unpacking publickey from preamble %s\n", fname)fprintf(stderr, "ERROR: %s: " "Unpacking publickey from preamble %s\n" , __func__, fname ); | |||
701 | return 1; | |||
702 | } | |||
703 | break; | |||
704 | case FILE_TYPE_PUBKEY: | |||
705 | if (vb2_unpack_key_buffer(pubkey, buf, len) != VB2_SUCCESS) { | |||
706 | ERROR("Unpacking publickey %s\n", fname)fprintf(stderr, "ERROR: %s: " "Unpacking publickey %s\n", __func__ , fname ); | |||
707 | return 1; | |||
708 | } | |||
709 | break; | |||
710 | default: | |||
711 | ERROR("Unsupported file type '%s' for publickey %s\n",fprintf(stderr, "ERROR: %s: " "Unsupported file type '%s' for publickey %s\n" , __func__, futil_file_type_name(type), fname ) | |||
712 | futil_file_type_name(type), fname)fprintf(stderr, "ERROR: %s: " "Unsupported file type '%s' for publickey %s\n" , __func__, futil_file_type_name(type), fname ); | |||
713 | return 1; | |||
714 | } | |||
715 | ||||
716 | return 0; | |||
717 | } | |||
718 | ||||
719 | static int do_show(int argc, char *argv[]) | |||
720 | { | |||
721 | uint8_t *pubkbuf = NULL((void*)0); | |||
722 | struct vb2_public_key pubk2; | |||
723 | char *infile = 0; | |||
724 | int i; | |||
725 | int errorcnt = 0; | |||
726 | int type_override = 0; | |||
727 | enum futil_file_type type; | |||
728 | ||||
729 | vb2_workbuf_init(&wb, workbuf, sizeof(workbuf)); | |||
730 | ||||
731 | opterr = 0; /* quiet, you */ | |||
732 | while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) { | |||
733 | switch (i) { | |||
734 | case 'f': | |||
735 | show_option.fv = ReadFile(optarg, | |||
736 | &show_option.fv_size); | |||
737 | if (!show_option.fv) { | |||
738 | ERROR("Reading %s: %s\n",fprintf(stderr, "ERROR: %s: " "Reading %s: %s\n", __func__, optarg , strerror((*__errno_location ())) ) | |||
739 | optarg, strerror(errno))fprintf(stderr, "ERROR: %s: " "Reading %s: %s\n", __func__, optarg , strerror((*__errno_location ())) ); | |||
740 | errorcnt++; | |||
741 | } | |||
742 | break; | |||
743 | case 'k': | |||
744 | if (load_publickey(optarg, &pubkbuf, &pubk2)) { | |||
745 | ERROR("Loading publickey %s\n", optarg)fprintf(stderr, "ERROR: %s: " "Loading publickey %s\n", __func__ , optarg ); | |||
746 | errorcnt++; | |||
747 | break; | |||
748 | } | |||
749 | show_option.k = &pubk2; | |||
750 | break; | |||
751 | case 't': | |||
752 | show_option.t_flag = 1; | |||
753 | break; | |||
754 | case 'P': | |||
755 | show_option.parseable = true1; | |||
756 | break; | |||
757 | case OPT_TYPE: | |||
758 | if (!futil_str_to_file_type(optarg, | |||
759 | &show_option.type)) { | |||
760 | if (!strcasecmp("help", optarg)) | |||
761 | print_file_types_and_exit(errorcnt); | |||
762 | ERROR("Invalid --type \"%s\"\n", optarg)fprintf(stderr, "ERROR: %s: " "Invalid --type \"%s\"\n", __func__ , optarg ); | |||
763 | errorcnt++; | |||
764 | } | |||
765 | type_override = 1; | |||
766 | break; | |||
767 | case OPT_PUBKEY: | |||
768 | if (vb21_packed_key_read(&show_option.pkey, optarg)) { | |||
769 | ERROR("Reading %s\n", optarg)fprintf(stderr, "ERROR: %s: " "Reading %s\n", __func__, optarg ); | |||
770 | errorcnt++; | |||
771 | } | |||
772 | break; | |||
773 | case OPT_HELP: | |||
774 | print_help(argc, argv); | |||
775 | return !!errorcnt; | |||
776 | ||||
777 | case '?': | |||
778 | if (optopt) | |||
779 | ERROR("Unrecognized option: -%c\n",fprintf(stderr, "ERROR: %s: " "Unrecognized option: -%c\n", __func__ , optopt ) | |||
780 | optopt)fprintf(stderr, "ERROR: %s: " "Unrecognized option: -%c\n", __func__ , optopt ); | |||
781 | else | |||
782 | ERROR("Unrecognized option\n")fprintf(stderr, "ERROR: %s: " "Unrecognized option\n", __func__ ); | |||
783 | errorcnt++; | |||
784 | break; | |||
785 | case ':': | |||
786 | ERROR("Missing argument to -%c\n", optopt)fprintf(stderr, "ERROR: %s: " "Missing argument to -%c\n", __func__ , optopt ); | |||
787 | errorcnt++; | |||
788 | break; | |||
789 | case 0: /* handled option */ | |||
790 | break; | |||
791 | default: | |||
792 | FATAL("Unrecognized getopt output: %d\n", i)do { fprintf(stderr, "FATAL: %s: " "Unrecognized getopt output: %d\n" , __func__, i ); exit(1); } while (0); | |||
793 | } | |||
794 | } | |||
795 | ||||
796 | if (errorcnt
| |||
797 | print_help(argc, argv); | |||
798 | return 1; | |||
| ||||
799 | } | |||
800 | ||||
801 | if (argc - optind < 1) { | |||
802 | ERROR("Missing input filename\n")fprintf(stderr, "ERROR: %s: " "Missing input filename\n", __func__ ); | |||
803 | print_help(argc, argv); | |||
804 | return 1; | |||
805 | } | |||
806 | ||||
807 | if (show_option.t_flag) { | |||
808 | for (i = optind; i < argc; i++) | |||
809 | errorcnt += show_type(argv[i]); | |||
810 | goto done; | |||
811 | } | |||
812 | ||||
813 | for (i = optind; i < argc; i++) { | |||
814 | infile = argv[i]; | |||
815 | ||||
816 | /* Allow the user to override the type */ | |||
817 | if (type_override) | |||
818 | type = show_option.type; | |||
819 | else | |||
820 | futil_file_type(infile, &type); | |||
821 | ||||
822 | errorcnt += futil_file_type_show(type, infile); | |||
823 | } | |||
824 | ||||
825 | done: | |||
826 | if (pubkbuf) | |||
827 | free(pubkbuf); | |||
828 | if (show_option.fv) | |||
829 | free(show_option.fv); | |||
830 | ||||
831 | return !!errorcnt; | |||
832 | } | |||
833 | ||||
834 | DECLARE_FUTIL_COMMAND(show, do_show, VBOOT_VERSION_ALL,const struct futil_cmd_t __cmd_show = { .name = "show", .handler = do_show, .version = VBOOT_VERSION_ALL, .shorthelp = "Display the content of various binary components" , } | |||
835 | "Display the content of various binary components")const struct futil_cmd_t __cmd_show = { .name = "show", .handler = do_show, .version = VBOOT_VERSION_ALL, .shorthelp = "Display the content of various binary components" , }; | |||
836 | ||||
837 | static int do_verify(int argc, char *argv[]) | |||
838 | { | |||
839 | show_option.strict = 1; | |||
840 | return do_show(argc, argv); | |||
| ||||
841 | } | |||
842 | ||||
843 | DECLARE_FUTIL_COMMAND(verify, do_verify,const struct futil_cmd_t __cmd_verify = { .name = "verify", . handler = do_verify, .version = VBOOT_VERSION_ALL, .shorthelp = "Verify the signatures of various binary components. " "This does not verify GSCVD contents." , } | |||
844 | VBOOT_VERSION_ALL,const struct futil_cmd_t __cmd_verify = { .name = "verify", . handler = do_verify, .version = VBOOT_VERSION_ALL, .shorthelp = "Verify the signatures of various binary components. " "This does not verify GSCVD contents." , } | |||
845 | "Verify the signatures of various binary components. "const struct futil_cmd_t __cmd_verify = { .name = "verify", . handler = do_verify, .version = VBOOT_VERSION_ALL, .shorthelp = "Verify the signatures of various binary components. " "This does not verify GSCVD contents." , } | |||
846 | "This does not verify GSCVD contents.")const struct futil_cmd_t __cmd_verify = { .name = "verify", . handler = do_verify, .version = VBOOT_VERSION_ALL, .shorthelp = "Verify the signatures of various binary components. " "This does not verify GSCVD contents." , }; |