1 /* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  *
5  * Tests for misc library
6  */
7 
8 #include <stdio.h>
9 
10 #include "2sysincludes.h"
11 #include "2api.h"
12 #include "2common.h"
13 #include "2misc.h"
14 #include "2nvstorage.h"
15 #include "2rsa.h"
16 #include "2secdata.h"
17 #include "test_common.h"
18 
19 /* Common context for tests */
20 static uint8_t workbuf[VB2_WORKBUF_RECOMMENDED_SIZE]
21 	__attribute__ ((aligned (VB2_WORKBUF_ALIGN)));
22 static struct vb2_context cc;
23 static struct vb2_shared_data *sd;
24 
25 const char mock_body[320] = "Mock body";
26 const int mock_body_size = sizeof(mock_body);
27 const int mock_algorithm = VB2_ALG_RSA2048_SHA256;
28 const int mock_hash_alg = VB2_HASH_SHA256;
29 static const uint8_t mock_hwid_digest[VB2_GBB_HWID_DIGEST_SIZE] = {
30 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
31 	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
32 	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
33 	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
34 };
35 
36 /* Mocked function data */
37 
38 static int retval_vb2_fw_parse_gbb;
39 static int retval_vb2_check_dev_switch;
40 static int retval_vb2_check_tpm_clear;
41 static int retval_vb2_select_fw_slot;
42 
43 /* Type of test to reset for */
44 enum reset_type {
45 	FOR_MISC,
46 };
47 
reset_common_data(enum reset_type t)48 static void reset_common_data(enum reset_type t)
49 {
50 	memset(workbuf, 0xaa, sizeof(workbuf));
51 
52 	memset(&cc, 0, sizeof(cc));
53 	cc.workbuf = workbuf;
54 	cc.workbuf_size = sizeof(workbuf);
55 
56 	vb2_init_context(&cc);
57 	sd = vb2_get_sd(&cc);
58 
59 	vb2_nv_init(&cc);
60 
61 	vb2_secdata_create(&cc);
62 	vb2_secdata_init(&cc);
63 
64 	retval_vb2_fw_parse_gbb = VB2_SUCCESS;
65 	retval_vb2_check_dev_switch = VB2_SUCCESS;
66 	retval_vb2_check_tpm_clear = VB2_SUCCESS;
67 	retval_vb2_select_fw_slot = VB2_SUCCESS;
68 
69 	memcpy(sd->gbb_hwid_digest, mock_hwid_digest,
70 	       sizeof(sd->gbb_hwid_digest));
71 };
72 
73 /* Mocked functions */
74 
vb2_fw_parse_gbb(struct vb2_context * ctx)75 int vb2_fw_parse_gbb(struct vb2_context *ctx)
76 {
77 	return retval_vb2_fw_parse_gbb;
78 }
79 
vb2_check_dev_switch(struct vb2_context * ctx)80 int vb2_check_dev_switch(struct vb2_context *ctx)
81 {
82 	return retval_vb2_check_dev_switch;
83 }
84 
vb2_check_tpm_clear(struct vb2_context * ctx)85 int vb2_check_tpm_clear(struct vb2_context *ctx)
86 {
87 	return retval_vb2_check_tpm_clear;
88 }
89 
vb2_select_fw_slot(struct vb2_context * ctx)90 int vb2_select_fw_slot(struct vb2_context *ctx)
91 {
92 	return retval_vb2_select_fw_slot;
93 }
94 
95 /* Tests */
96 
misc_tests(void)97 static void misc_tests(void)
98 {
99 	/* Test secdata passthru functions */
100 	reset_common_data(FOR_MISC);
101 	/* Corrupt secdata so initial check will fail */
102 	cc.secdata[0] ^= 0x42;
103 	TEST_EQ(vb2api_secdata_check(&cc), VB2_ERROR_SECDATA_CRC,
104 		"secdata check");
105 	TEST_SUCC(vb2api_secdata_create(&cc), "secdata create");
106 	TEST_SUCC(vb2api_secdata_check(&cc), "secdata check 2");
107 
108 	/* Test fail passthru */
109 	reset_common_data(FOR_MISC);
110 	vb2api_fail(&cc, 12, 34);
111 	TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST),
112 		12, "vb2api_fail request");
113 	TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_SUBCODE),
114 		34, "vb2api_fail subcode");
115 }
116 
phase1_tests(void)117 static void phase1_tests(void)
118 {
119 	reset_common_data(FOR_MISC);
120 	TEST_SUCC(vb2api_fw_phase1(&cc), "phase1 good");
121 	TEST_EQ(sd->recovery_reason, 0, "  not recovery");
122 	TEST_EQ(cc.flags & VB2_CONTEXT_RECOVERY_MODE, 0, "  recovery flag");
123 	TEST_EQ(cc.flags & VB2_CONTEXT_CLEAR_RAM, 0, "  clear ram flag");
124 
125 	reset_common_data(FOR_MISC);
126 	retval_vb2_fw_parse_gbb = VB2_ERROR_GBB_MAGIC;
127 	TEST_EQ(vb2api_fw_phase1(&cc), VB2_ERROR_API_PHASE1_RECOVERY,
128 		"phase1 gbb");
129 	TEST_EQ(sd->recovery_reason, VB2_RECOVERY_GBB_HEADER,
130 		"  recovery reason");
131 	TEST_NEQ(cc.flags & VB2_CONTEXT_RECOVERY_MODE, 0, "  recovery flag");
132 	TEST_NEQ(cc.flags & VB2_CONTEXT_CLEAR_RAM, 0, "  clear ram flag");
133 
134 
135 	reset_common_data(FOR_MISC);
136 	retval_vb2_check_dev_switch = VB2_ERROR_MOCK;
137 	TEST_EQ(vb2api_fw_phase1(&cc), VB2_ERROR_API_PHASE1_RECOVERY,
138 		"phase1 dev switch");
139 	TEST_EQ(sd->recovery_reason, VB2_RECOVERY_DEV_SWITCH,
140 		"  recovery reason");
141 	TEST_NEQ(cc.flags & VB2_CONTEXT_RECOVERY_MODE, 0, "  recovery flag");
142 	TEST_NEQ(cc.flags & VB2_CONTEXT_CLEAR_RAM, 0, "  clear ram flag");
143 
144 	reset_common_data(FOR_MISC);
145 	cc.secdata[0] ^= 0x42;
146 	TEST_EQ(vb2api_fw_phase1(&cc), VB2_ERROR_API_PHASE1_RECOVERY,
147 		"phase1 secdata");
148 	TEST_EQ(sd->recovery_reason, VB2_RECOVERY_SECDATA_INIT,
149 		"  recovery reason");
150 	TEST_NEQ(cc.flags & VB2_CONTEXT_RECOVERY_MODE, 0, "  recovery flag");
151 	TEST_NEQ(cc.flags & VB2_CONTEXT_CLEAR_RAM, 0, "  clear ram flag");
152 }
153 
phase2_tests(void)154 static void phase2_tests(void)
155 {
156 	reset_common_data(FOR_MISC);
157 	TEST_SUCC(vb2api_fw_phase2(&cc), "phase2 good");
158 	TEST_EQ(cc.flags & VB2_CONTEXT_CLEAR_RAM, 0, "  clear ram flag");
159 
160 	reset_common_data(FOR_MISC);
161 	cc.flags |= VB2_CONTEXT_DEVELOPER_MODE;
162 	TEST_SUCC(vb2api_fw_phase2(&cc), "phase1 dev");
163 	TEST_NEQ(cc.flags & VB2_CONTEXT_CLEAR_RAM, 0, "  clear ram flag");
164 
165 	reset_common_data(FOR_MISC);
166 	retval_vb2_check_tpm_clear = VB2_ERROR_MOCK;
167 	TEST_EQ(vb2api_fw_phase2(&cc), VB2_ERROR_MOCK, "phase2 tpm clear");
168 	TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST),
169 		VB2_RECOVERY_TPM_CLEAR_OWNER, "  recovery reason");
170 
171 	reset_common_data(FOR_MISC);
172 	retval_vb2_select_fw_slot = VB2_ERROR_MOCK;
173 	TEST_EQ(vb2api_fw_phase2(&cc), VB2_ERROR_MOCK, "phase2 slot");
174 	TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST),
175 		VB2_RECOVERY_FW_SLOT, "  recovery reason");
176 }
177 
get_pcr_digest_tests(void)178 static void get_pcr_digest_tests(void)
179 {
180 	uint8_t digest[VB2_PCR_DIGEST_RECOMMENDED_SIZE];
181 	uint8_t digest_org[VB2_PCR_DIGEST_RECOMMENDED_SIZE];
182 	uint32_t digest_size;
183 
184 	reset_common_data(FOR_MISC);
185 	memset(digest_org, 0, sizeof(digest_org));
186 
187 	digest_size = sizeof(digest);
188 	memset(digest, 0, sizeof(digest));
189 	TEST_SUCC(vb2api_get_pcr_digest(
190 			&cc, BOOT_MODE_PCR, digest, &digest_size),
191 		  "BOOT_MODE_PCR");
192 	TEST_EQ(digest_size, VB2_SHA1_DIGEST_SIZE, "BOOT_MODE_PCR digest size");
193 	TEST_TRUE(memcmp(digest, digest_org, digest_size),
194 		  "BOOT_MODE_PCR digest");
195 
196 	digest_size = sizeof(digest);
197 	memset(digest, 0, sizeof(digest));
198 	TEST_SUCC(vb2api_get_pcr_digest(
199 			&cc, HWID_DIGEST_PCR, digest, &digest_size),
200 		  "HWID_DIGEST_PCR");
201 	TEST_EQ(digest_size, VB2_GBB_HWID_DIGEST_SIZE,
202 		"HWID_DIGEST_PCR digest size");
203 	TEST_FALSE(memcmp(digest, mock_hwid_digest, digest_size),
204 		   "HWID_DIGEST_PCR digest");
205 
206 	digest_size = 1;
207 	TEST_EQ(vb2api_get_pcr_digest(&cc, BOOT_MODE_PCR, digest, &digest_size),
208 		VB2_ERROR_API_PCR_DIGEST_BUF,
209 		"BOOT_MODE_PCR buffer too small");
210 
211 	TEST_EQ(vb2api_get_pcr_digest(
212 			&cc, HWID_DIGEST_PCR + 1, digest, &digest_size),
213 		VB2_ERROR_API_PCR_DIGEST,
214 		"invalid enum vb2_pcr_digest");
215 }
216 
main(int argc,char * argv[])217 int main(int argc, char* argv[])
218 {
219 	misc_tests();
220 	phase1_tests();
221 	phase2_tests();
222 
223 	get_pcr_digest_tests();
224 
225 	return gTestSuccess ? 0 : 255;
226 }
227