]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-tpm2.c
Merge pull request #32205 from YHNdnzj/bless-boot
[thirdparty/systemd.git] / src / test / test-tpm2.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include "hexdecoct.h"
4 #include "macro.h"
5 #include "tests.h"
6 #include "tpm2-util.h"
7 #include "virt.h"
8
9 TEST(tpm2_pcr_index_from_string) {
10 assert_se(tpm2_pcr_index_from_string("platform-code") == 0);
11 assert_se(tpm2_pcr_index_from_string("0") == 0);
12 assert_se(tpm2_pcr_index_from_string("platform-config") == 1);
13 assert_se(tpm2_pcr_index_from_string("1") == 1);
14 assert_se(tpm2_pcr_index_from_string("external-code") == 2);
15 assert_se(tpm2_pcr_index_from_string("2") == 2);
16 assert_se(tpm2_pcr_index_from_string("external-config") == 3);
17 assert_se(tpm2_pcr_index_from_string("3") == 3);
18 assert_se(tpm2_pcr_index_from_string("boot-loader-code") == 4);
19 assert_se(tpm2_pcr_index_from_string("4") == 4);
20 assert_se(tpm2_pcr_index_from_string("boot-loader-config") == 5);
21 assert_se(tpm2_pcr_index_from_string("5") == 5);
22 assert_se(tpm2_pcr_index_from_string("secure-boot-policy") == 7);
23 assert_se(tpm2_pcr_index_from_string("7") == 7);
24 assert_se(tpm2_pcr_index_from_string("kernel-initrd") == 9);
25 assert_se(tpm2_pcr_index_from_string("9") == 9);
26 assert_se(tpm2_pcr_index_from_string("ima") == 10);
27 assert_se(tpm2_pcr_index_from_string("10") == 10);
28 assert_se(tpm2_pcr_index_from_string("kernel-boot") == 11);
29 assert_se(tpm2_pcr_index_from_string("11") == 11);
30 assert_se(tpm2_pcr_index_from_string("kernel-config") == 12);
31 assert_se(tpm2_pcr_index_from_string("12") == 12);
32 assert_se(tpm2_pcr_index_from_string("sysexts") == 13);
33 assert_se(tpm2_pcr_index_from_string("13") == 13);
34 assert_se(tpm2_pcr_index_from_string("shim-policy") == 14);
35 assert_se(tpm2_pcr_index_from_string("14") == 14);
36 assert_se(tpm2_pcr_index_from_string("system-identity") == 15);
37 assert_se(tpm2_pcr_index_from_string("15") == 15);
38 assert_se(tpm2_pcr_index_from_string("debug") == 16);
39 assert_se(tpm2_pcr_index_from_string("16") == 16);
40 assert_se(tpm2_pcr_index_from_string("application-support") == 23);
41 assert_se(tpm2_pcr_index_from_string("23") == 23);
42 assert_se(tpm2_pcr_index_from_string("hello") == -EINVAL);
43 assert_se(tpm2_pcr_index_from_string("8") == 8);
44 assert_se(tpm2_pcr_index_from_string("44") == -EINVAL);
45 assert_se(tpm2_pcr_index_from_string("-5") == -EINVAL);
46 assert_se(tpm2_pcr_index_from_string("24") == -EINVAL);
47 }
48
49 TEST(tpm2_util_pbkdf2_hmac_sha256) {
50
51 /*
52 * The test vectors from RFC 6070 [1] are for dkLen of 20 as it's SHA1
53 * other RFCs I bumped into had various differing dkLen and iter counts,
54 * so this was generated using Python's hmacmodule.
55 *
56 * 1. https://www.rfc-editor.org/rfc/rfc6070.html#page-2
57 */
58 static const struct {
59 const uint8_t pass[256];
60 size_t passlen;
61 const uint8_t salt[256];
62 size_t saltlen;
63 uint8_t expected[SHA256_DIGEST_SIZE];
64 } test_vectors[] = {
65 { .pass={'f', 'o', 'o', 'p', 'a', 's', 's'}, .passlen=7, .salt={'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5'}, .saltlen=16, .expected={0xCB, 0xEA, 0x27, 0x23, 0x9A, 0x65, 0x99, 0xF6, 0x8C, 0x26, 0x54, 0x80, 0x5C, 0x63, 0x61, 0xD2, 0x91, 0x0A, 0x60, 0x3F, 0xC2, 0xF5, 0xF0, 0xAB, 0x55, 0x8B, 0x46, 0x07, 0x60, 0x93, 0xAB, 0xCB} },
66 { .pass={'f', 'o', 'o', 'p', 'a', 's', 's'}, .passlen=7, .salt={0x00, 'h', 'f', 's', 'd', 'j', 'h', 'f', 'd', 'j', 'h', 'j', 'd', 'f', 's'}, .saltlen=15, .expected={0x2B, 0xDF, 0x52, 0x29, 0x48, 0x3F, 0x98, 0x25, 0x01, 0x19, 0xB4, 0x42, 0xBC, 0xA7, 0x38, 0x5D, 0xCD, 0x08, 0xBD, 0xDC, 0x33, 0xBF, 0x32, 0x5E, 0x31, 0x87, 0x54, 0xFF, 0x2C, 0x23, 0x68, 0xFF} },
67 { .pass={'f', 'o', 'o', 'p', 'a', 's', 's'}, .passlen=7, .salt={'m', 'y', 's', 'a', 0x00, 'l', 't'}, .saltlen=7, .expected={0x7C, 0x24, 0xB4, 0x4D, 0x30, 0x11, 0x53, 0x24, 0x87, 0x56, 0x24, 0x10, 0xBA, 0x9F, 0xF2, 0x4E, 0xBB, 0xF5, 0x03, 0x56, 0x2B, 0xB1, 0xA1, 0x92, 0x8B, 0x5F, 0x32, 0x02, 0x23, 0x1F, 0x79, 0xE6} },
68 { .pass={'p', 'a', 's', 's', 'w', 'i', 't', 'h', 'n', 'u', 'l', 'l', 0x00, 'p', 'a', 's', 's', 'w', 'o', 'r', 'd'}, .passlen=21, .salt={'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5'}, .saltlen=16, .expected={0xE9, 0x53, 0xB7, 0x1D, 0xAB, 0xD1, 0xC1, 0xF3, 0xC4, 0x7F, 0x18, 0x96, 0xDD, 0xD7, 0x6B, 0xC6, 0x6A, 0xBD, 0xFB, 0x12, 0x7C, 0xF8, 0x68, 0xDC, 0x6E, 0xEF, 0x29, 0xCC, 0x1B, 0x30, 0x5B, 0x74} },
69 { .pass={'p', 'a', 's', 's', 'w', 'i', 't', 'h', 'n', 'u', 'l', 'l', 0x00, 'p', 'a', 's', 's', 'w', 'o', 'r', 'd'}, .passlen=21, .salt={0x00, 'h', 'f', 's', 'd', 'j', 'h', 'f', 'd', 'j', 'h', 'j', 'd', 'f', 's'}, .saltlen=15, .expected={0x51, 0xA3, 0x82, 0xA5, 0x2F, 0x48, 0x84, 0xB3, 0x02, 0x0D, 0xC2, 0x42, 0x9A, 0x8F, 0x86, 0xCC, 0x66, 0xFD, 0x65, 0x87, 0x89, 0x07, 0x2B, 0x07, 0x82, 0x42, 0xD6, 0x6D, 0x43, 0xB8, 0xFD, 0xCF} },
70 { .pass={'p', 'a', 's', 's', 'w', 'i', 't', 'h', 'n', 'u', 'l', 'l', 0x00, 'p', 'a', 's', 's', 'w', 'o', 'r', 'd'}, .passlen=21, .salt={'m', 'y', 's', 'a', 0x00, 'l', 't'}, .saltlen=7, .expected={0xEC, 0xFB, 0x5D, 0x5F, 0xF6, 0xA6, 0xE0, 0x79, 0x50, 0x64, 0x36, 0x64, 0xA3, 0x9A, 0x5C, 0xF3, 0x7A, 0x87, 0x0B, 0x64, 0x51, 0x59, 0x75, 0x64, 0x8B, 0x78, 0x2B, 0x62, 0x8F, 0x68, 0xD9, 0xCC} },
71 { .pass={0x00, 'p', 'a', 's', 's'}, .passlen=5, .salt={'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5'}, .saltlen=16, .expected={0x8A, 0x9A, 0x47, 0x9A, 0x91, 0x22, 0x2F, 0x56, 0x29, 0x4F, 0x26, 0x00, 0xE7, 0xB3, 0xEB, 0x63, 0x6D, 0x51, 0xF2, 0x60, 0x17, 0x08, 0x20, 0x70, 0x82, 0x8F, 0xA3, 0xD7, 0xBE, 0x2B, 0xD5, 0x5D} },
72 { .pass={0x00, 'p', 'a', 's', 's'}, .passlen=5, .salt={0x00, 'h', 'f', 's', 'd', 'j', 'h', 'f', 'd', 'j', 'h', 'j', 'd', 'f', 's'}, .saltlen=15, .expected={0x72, 0x3A, 0xF5, 0xF7, 0xCD, 0x6C, 0x12, 0xDD, 0x53, 0x28, 0x46, 0x0C, 0x19, 0x0E, 0xF2, 0x91, 0xDE, 0xEA, 0xF9, 0x6F, 0x74, 0x32, 0x34, 0x3F, 0x84, 0xED, 0x8D, 0x2A, 0xDE, 0xC9, 0xC6, 0x34} },
73 { .pass={0x00, 'p', 'a', 's', 's'}, .passlen=5, .salt={'m', 'y', 's', 'a', 0x00, 'l', 't'}, .saltlen=7, .expected={0xE3, 0x07, 0x12, 0xBE, 0xEE, 0xF5, 0x5D, 0x18, 0x72, 0xF4, 0xCF, 0xF1, 0x20, 0x6B, 0xD6, 0x66, 0xCD, 0x7C, 0xE7, 0x4F, 0xC2, 0x16, 0x70, 0x5B, 0x9B, 0x2F, 0x7D, 0xE2, 0x3B, 0x42, 0x3A, 0x1B} },
74 };
75
76 uint8_t res[SHA256_DIGEST_SIZE];
77 for (size_t i = 0; i < sizeof(test_vectors)/sizeof(test_vectors[0]); i++) {
78
79 int rc = tpm2_util_pbkdf2_hmac_sha256(
80 test_vectors[i].pass,
81 test_vectors[i].passlen,
82 test_vectors[i].salt,
83 test_vectors[i].saltlen,
84 res);
85 assert_se(rc == 0);
86 assert_se(memcmp(test_vectors[i].expected, res, SHA256_DIGEST_SIZE) == 0);
87 }
88 }
89
90 #if HAVE_TPM2
91
92 #define POISON(type) \
93 ({ \
94 type _p; \
95 memset(&_p, 0xaa, sizeof(_p)); \
96 _p; \
97 })
98 #define POISON_TPML POISON(TPML_PCR_SELECTION)
99 #define POISON_TPMS POISON(TPMS_PCR_SELECTION)
100 #define POISON_U32 POISON(uint32_t)
101
102 static void assert_tpms_pcr_selection_eq(TPMS_PCR_SELECTION *a, TPMS_PCR_SELECTION *b) {
103 assert_se(a);
104 assert_se(b);
105
106 assert_se(a->hash == b->hash);
107 assert_se(a->sizeofSelect == b->sizeofSelect);
108
109 for (size_t i = 0; i < a->sizeofSelect; i++)
110 assert_se(a->pcrSelect[i] == b->pcrSelect[i]);
111 }
112
113 static void assert_tpml_pcr_selection_eq(TPML_PCR_SELECTION *a, TPML_PCR_SELECTION *b) {
114 assert_se(a);
115 assert_se(b);
116
117 assert_se(a->count == b->count);
118 for (size_t i = 0; i < a->count; i++)
119 assert_tpms_pcr_selection_eq(&a->pcrSelections[i], &b->pcrSelections[i]);
120 }
121
122 static void verify_tpms_pcr_selection(TPMS_PCR_SELECTION *s, uint32_t mask, TPMI_ALG_HASH hash) {
123 assert_se(s->hash == hash);
124 assert_se(s->sizeofSelect == 3);
125 assert_se(s->pcrSelect[0] == (mask & 0xff));
126 assert_se(s->pcrSelect[1] == ((mask >> 8) & 0xff));
127 assert_se(s->pcrSelect[2] == ((mask >> 16) & 0xff));
128 assert_se(s->pcrSelect[3] == 0);
129
130 assert_se(tpm2_tpms_pcr_selection_to_mask(s) == mask);
131 }
132
133 static void verify_tpml_pcr_selection(TPML_PCR_SELECTION *l, TPMS_PCR_SELECTION s[], size_t count) {
134 assert_se(l->count == count);
135 for (size_t i = 0; i < count; i++) {
136 assert_tpms_pcr_selection_eq(&s[i], &l->pcrSelections[i]);
137
138 TPMI_ALG_HASH hash = l->pcrSelections[i].hash;
139 verify_tpms_pcr_selection(&l->pcrSelections[i], tpm2_tpml_pcr_selection_to_mask(l, hash), hash);
140 }
141 }
142
143 static void _test_pcr_selection_mask_hash(uint32_t mask, TPMI_ALG_HASH hash) {
144 TPMS_PCR_SELECTION s = POISON_TPMS;
145 tpm2_tpms_pcr_selection_from_mask(mask, hash, &s);
146 verify_tpms_pcr_selection(&s, mask, hash);
147
148 TPML_PCR_SELECTION l = POISON_TPML;
149 tpm2_tpml_pcr_selection_from_mask(mask, hash, &l);
150 verify_tpml_pcr_selection(&l, &s, 1);
151 verify_tpms_pcr_selection(&l.pcrSelections[0], mask, hash);
152
153 uint32_t test_masks[] = {
154 0x0, 0x1, 0x100, 0x10000, 0xf0f0f0, 0xaaaaaa, 0xffffff,
155 };
156 for (unsigned i = 0; i < ELEMENTSOF(test_masks); i++) {
157 uint32_t test_mask = test_masks[i];
158
159 TPMS_PCR_SELECTION a = POISON_TPMS, b = POISON_TPMS, test_s = POISON_TPMS;
160 tpm2_tpms_pcr_selection_from_mask(test_mask, hash, &test_s);
161
162 a = s;
163 b = test_s;
164 tpm2_tpms_pcr_selection_add(&a, &b);
165 verify_tpms_pcr_selection(&a, UPDATE_FLAG(mask, test_mask, true), hash);
166 verify_tpms_pcr_selection(&b, test_mask, hash);
167
168 a = s;
169 b = test_s;
170 tpm2_tpms_pcr_selection_sub(&a, &b);
171 verify_tpms_pcr_selection(&a, UPDATE_FLAG(mask, test_mask, false), hash);
172 verify_tpms_pcr_selection(&b, test_mask, hash);
173
174 a = s;
175 b = test_s;
176 tpm2_tpms_pcr_selection_move(&a, &b);
177 verify_tpms_pcr_selection(&a, UPDATE_FLAG(mask, test_mask, true), hash);
178 verify_tpms_pcr_selection(&b, 0, hash);
179 }
180 }
181
182 TEST(tpms_pcr_selection_mask_and_hash) {
183 TPMI_ALG_HASH HASH_ALGS[] = { TPM2_ALG_SHA1, TPM2_ALG_SHA256, };
184
185 for (unsigned i = 0; i < ELEMENTSOF(HASH_ALGS); i++)
186 for (uint32_t m2 = 0; m2 <= 0xffffff; m2 += 0x50000)
187 for (uint32_t m1 = 0; m1 <= 0xffff; m1 += 0x500)
188 for (uint32_t m0 = 0; m0 <= 0xff; m0 += 0x5)
189 _test_pcr_selection_mask_hash(m0 | m1 | m2, HASH_ALGS[i]);
190 }
191
192 static void _test_tpms_sw(
193 TPMI_ALG_HASH hash,
194 uint32_t mask,
195 const char *expected_str,
196 size_t expected_weight) {
197
198 TPMS_PCR_SELECTION s = POISON_TPMS;
199 tpm2_tpms_pcr_selection_from_mask(mask, hash, &s);
200
201 _cleanup_free_ char *tpms_str = tpm2_tpms_pcr_selection_to_string(&s);
202 assert_se(streq(tpms_str, expected_str));
203
204 assert_se(tpm2_tpms_pcr_selection_weight(&s) == expected_weight);
205 assert_se(tpm2_tpms_pcr_selection_is_empty(&s) == (expected_weight == 0));
206 }
207
208 TEST(tpms_pcr_selection_string_and_weight) {
209 TPMI_ALG_HASH sha1 = TPM2_ALG_SHA1, sha256 = TPM2_ALG_SHA256;
210
211 _test_tpms_sw(sha1, 0, "sha1()", 0);
212 _test_tpms_sw(sha1, 1, "sha1(0)", 1);
213 _test_tpms_sw(sha1, 0xf, "sha1(0+1+2+3)", 4);
214 _test_tpms_sw(sha1, 0x00ff00, "sha1(8+9+10+11+12+13+14+15)", 8);
215 _test_tpms_sw(sha1, 0xffffff, "sha1(0+1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+21+22+23)", 24);
216 _test_tpms_sw(sha256, 0, "sha256()", 0);
217 _test_tpms_sw(sha256, 1, "sha256(0)", 1);
218 _test_tpms_sw(sha256, 7, "sha256(0+1+2)", 3);
219 _test_tpms_sw(sha256, 0xf00000, "sha256(20+21+22+23)", 4);
220 _test_tpms_sw(sha256, 0xffffff, "sha256(0+1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+21+22+23)", 24);
221 }
222
223 static void _tpml_pcr_selection_add_tpms(TPMS_PCR_SELECTION s[], size_t count, TPML_PCR_SELECTION *ret) {
224 for (size_t i = 0; i < count; i++)
225 tpm2_tpml_pcr_selection_add_tpms_pcr_selection(ret, &s[i]);
226 }
227
228 static void _tpml_pcr_selection_sub_tpms(TPMS_PCR_SELECTION s[], size_t count, TPML_PCR_SELECTION *ret) {
229 for (size_t i = 0; i < count; i++)
230 tpm2_tpml_pcr_selection_sub_tpms_pcr_selection(ret, &s[i]);
231 }
232
233 static void _test_tpml_sw(
234 TPMS_PCR_SELECTION s[],
235 size_t count,
236 size_t expected_count,
237 const char *expected_str,
238 size_t expected_weight) {
239
240 TPML_PCR_SELECTION l = {};
241 _tpml_pcr_selection_add_tpms(s, count, &l);
242 assert_se(l.count == expected_count);
243
244 _cleanup_free_ char *tpml_str = tpm2_tpml_pcr_selection_to_string(&l);
245 assert_se(streq(tpml_str, expected_str));
246
247 assert_se(tpm2_tpml_pcr_selection_weight(&l) == expected_weight);
248 assert_se(tpm2_tpml_pcr_selection_is_empty(&l) == (expected_weight == 0));
249 }
250
251 TEST(tpml_pcr_selection_string_and_weight) {
252 size_t size = 0xaa;
253 TPMI_ALG_HASH sha1 = TPM2_ALG_SHA1,
254 sha256 = TPM2_ALG_SHA256,
255 sha384 = TPM2_ALG_SHA384,
256 sha512 = TPM2_ALG_SHA512;
257 TPMS_PCR_SELECTION s[4] = { POISON_TPMS, POISON_TPMS, POISON_TPMS, POISON_TPMS, };
258
259 size = 0;
260 tpm2_tpms_pcr_selection_from_mask(0x000002, sha1 , &s[size++]);
261 tpm2_tpms_pcr_selection_from_mask(0x0080f0, sha384, &s[size++]);
262 tpm2_tpms_pcr_selection_from_mask(0x010100, sha512, &s[size++]);
263 tpm2_tpms_pcr_selection_from_mask(0xff0000, sha256, &s[size++]);
264 _test_tpml_sw(s,
265 size,
266 /* expected_count= */ 4,
267 "[sha1(1),sha384(4+5+6+7+15),sha512(8+16),sha256(16+17+18+19+20+21+22+23)]",
268 /* expected_weight= */ 16);
269
270 size = 0;
271 tpm2_tpms_pcr_selection_from_mask(0x0403aa, sha512, &s[size++]);
272 tpm2_tpms_pcr_selection_from_mask(0x0080f0, sha256, &s[size++]);
273 _test_tpml_sw(s,
274 size,
275 /* expected_count= */ 2,
276 "[sha512(1+3+5+7+8+9+18),sha256(4+5+6+7+15)]",
277 /* expected_weight= */ 12);
278
279 size = 0;
280 /* Empty hashes should be ignored */
281 tpm2_tpms_pcr_selection_from_mask(0x0300ce, sha384, &s[size++]);
282 tpm2_tpms_pcr_selection_from_mask(0xffffff, sha512, &s[size++]);
283 tpm2_tpms_pcr_selection_from_mask(0x000000, sha1 , &s[size++]);
284 tpm2_tpms_pcr_selection_from_mask(0x330010, sha256, &s[size++]);
285 _test_tpml_sw(s,
286 size,
287 /* expected_count= */ 3,
288 "[sha384(1+2+3+6+7+16+17),sha512(0+1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+21+22+23),sha256(4+16+17+20+21)]",
289 /* expected_weight= */ 36);
290
291 size = 0;
292 /* Verify same-hash entries are properly combined. */
293 tpm2_tpms_pcr_selection_from_mask(0x000001, sha1 , &s[size++]);
294 tpm2_tpms_pcr_selection_from_mask(0x000001, sha256, &s[size++]);
295 tpm2_tpms_pcr_selection_from_mask(0x000010, sha1 , &s[size++]);
296 tpm2_tpms_pcr_selection_from_mask(0x000010, sha256, &s[size++]);
297 _test_tpml_sw(s,
298 size,
299 /* expected_count= */ 2,
300 "[sha1(0+4),sha256(0+4)]",
301 /* expected_weight= */ 4);
302 }
303
304 /* Test tpml add/sub by changing the tpms individually */
305 static void _test_tpml_addsub_tpms(
306 TPML_PCR_SELECTION *start,
307 TPMS_PCR_SELECTION add[],
308 size_t add_count,
309 TPMS_PCR_SELECTION expected1[],
310 size_t expected1_count,
311 TPMS_PCR_SELECTION sub[],
312 size_t sub_count,
313 TPMS_PCR_SELECTION expected2[],
314 size_t expected2_count) {
315
316 TPML_PCR_SELECTION l = *start;
317
318 _tpml_pcr_selection_add_tpms(add, add_count, &l);
319 verify_tpml_pcr_selection(&l, expected1, expected1_count);
320
321 _tpml_pcr_selection_sub_tpms(sub, sub_count, &l);
322 verify_tpml_pcr_selection(&l, expected2, expected2_count);
323 }
324
325 /* Test tpml add/sub by creating new tpmls */
326 static void _test_tpml_addsub_tpml(
327 TPML_PCR_SELECTION *start,
328 TPMS_PCR_SELECTION add[],
329 size_t add_count,
330 TPMS_PCR_SELECTION expected1[],
331 size_t expected1_count,
332 TPMS_PCR_SELECTION sub[],
333 size_t sub_count,
334 TPMS_PCR_SELECTION expected2[],
335 size_t expected2_count) {
336
337 TPML_PCR_SELECTION l = {};
338 tpm2_tpml_pcr_selection_add(&l, start);
339 assert_tpml_pcr_selection_eq(&l, start);
340
341 TPML_PCR_SELECTION addl = {};
342 _tpml_pcr_selection_add_tpms(add, add_count, &addl);
343 tpm2_tpml_pcr_selection_add(&l, &addl);
344
345 TPML_PCR_SELECTION e1 = {};
346 _tpml_pcr_selection_add_tpms(expected1, expected1_count, &e1);
347 assert_tpml_pcr_selection_eq(&l, &e1);
348
349 TPML_PCR_SELECTION subl = {};
350 _tpml_pcr_selection_add_tpms(sub, sub_count, &subl);
351 tpm2_tpml_pcr_selection_sub(&l, &subl);
352
353 TPML_PCR_SELECTION e2 = {};
354 _tpml_pcr_selection_add_tpms(expected2, expected2_count, &e2);
355 assert_tpml_pcr_selection_eq(&l, &e2);
356 }
357
358 #define _test_tpml_addsub(...) \
359 ({ \
360 _test_tpml_addsub_tpms(__VA_ARGS__); \
361 _test_tpml_addsub_tpml(__VA_ARGS__); \
362 })
363
364 TEST(tpml_pcr_selection_add_sub) {
365 size_t add_count = 0xaa, expected1_count = 0xaa, sub_count = 0xaa, expected2_count = 0xaa;
366 TPMI_ALG_HASH sha1 = TPM2_ALG_SHA1,
367 sha256 = TPM2_ALG_SHA256,
368 sha384 = TPM2_ALG_SHA384,
369 sha512 = TPM2_ALG_SHA512;
370 TPML_PCR_SELECTION l = POISON_TPML;
371 TPMS_PCR_SELECTION add[4] = { POISON_TPMS, POISON_TPMS, POISON_TPMS, POISON_TPMS, },
372 sub[4] = { POISON_TPMS, POISON_TPMS, POISON_TPMS, POISON_TPMS, },
373 expected1[4] = { POISON_TPMS, POISON_TPMS, POISON_TPMS, POISON_TPMS, },
374 expected2[4] = { POISON_TPMS, POISON_TPMS, POISON_TPMS, POISON_TPMS, };
375
376 l = (TPML_PCR_SELECTION){};
377 add_count = 0;
378 expected1_count = 0;
379 sub_count = 0;
380 expected2_count = 0;
381 tpm2_tpms_pcr_selection_from_mask(0x010101, sha256, &add[add_count++]);
382 tpm2_tpms_pcr_selection_from_mask(0x101010, sha256, &add[add_count++]);
383 tpm2_tpms_pcr_selection_from_mask(0x0000ff, sha512, &add[add_count++]);
384 tpm2_tpms_pcr_selection_from_mask(0x111111, sha256, &expected1[expected1_count++]);
385 tpm2_tpms_pcr_selection_from_mask(0x0000ff, sha512, &expected1[expected1_count++]);
386 tpm2_tpms_pcr_selection_from_mask(0x000001, sha256, &sub[sub_count++]);
387 tpm2_tpms_pcr_selection_from_mask(0xff0000, sha512, &sub[sub_count++]);
388 tpm2_tpms_pcr_selection_from_mask(0x111110, sha256, &expected2[expected2_count++]);
389 tpm2_tpms_pcr_selection_from_mask(0x0000ff, sha512, &expected2[expected2_count++]);
390 _test_tpml_addsub(&l,
391 add, add_count,
392 expected1, expected1_count,
393 sub, sub_count,
394 expected2, expected2_count);
395
396 l = (TPML_PCR_SELECTION){
397 .count = 1,
398 .pcrSelections[0].hash = sha1,
399 .pcrSelections[0].sizeofSelect = 3,
400 .pcrSelections[0].pcrSelect[0] = 0xf0,
401 };
402 add_count = 0;
403 expected1_count = 0;
404 sub_count = 0;
405 expected2_count = 0;
406 tpm2_tpms_pcr_selection_from_mask(0xff0000, sha256, &add[add_count++]);
407 tpm2_tpms_pcr_selection_from_mask(0xffff00, sha384, &add[add_count++]);
408 tpm2_tpms_pcr_selection_from_mask(0x0000ff, sha512, &add[add_count++]);
409 tpm2_tpms_pcr_selection_from_mask(0xf00000, sha1 , &add[add_count++]);
410 tpm2_tpms_pcr_selection_from_mask(0xf000f0, sha1 , &expected1[expected1_count++]);
411 tpm2_tpms_pcr_selection_from_mask(0xff0000, sha256, &expected1[expected1_count++]);
412 tpm2_tpms_pcr_selection_from_mask(0xffff00, sha384, &expected1[expected1_count++]);
413 tpm2_tpms_pcr_selection_from_mask(0x0000ff, sha512, &expected1[expected1_count++]);
414 tpm2_tpms_pcr_selection_from_mask(0x00ffff, sha256, &sub[sub_count++]);
415 tpm2_tpms_pcr_selection_from_mask(0xf000f0, sha1 , &expected2[expected2_count++]);
416 tpm2_tpms_pcr_selection_from_mask(0xff0000, sha256, &expected2[expected2_count++]);
417 tpm2_tpms_pcr_selection_from_mask(0xffff00, sha384, &expected2[expected2_count++]);
418 tpm2_tpms_pcr_selection_from_mask(0x0000ff, sha512, &expected2[expected2_count++]);
419 _test_tpml_addsub(&l,
420 add, add_count,
421 expected1, expected1_count,
422 sub, sub_count,
423 expected2, expected2_count);
424 }
425
426 static bool digest_check(const TPM2B_DIGEST *digest, const char *expect) {
427 _cleanup_free_ char *h = NULL;
428
429 assert_se(digest);
430 assert_se(expect);
431
432 h = hexmem(digest->buffer, digest->size);
433 assert_se(h);
434
435 return strcaseeq(expect, h);
436 }
437
438 static void digest_init(TPM2B_DIGEST *digest, const char *hash) {
439 assert_se(strlen(hash) <= sizeof(digest->buffer) * 2);
440
441 DEFINE_HEX_PTR(h, hash);
442
443 /* Make sure the length matches a known hash algorithm */
444 assert_se(IN_SET(h_len, TPM2_SHA1_DIGEST_SIZE, TPM2_SHA256_DIGEST_SIZE, TPM2_SHA384_DIGEST_SIZE, TPM2_SHA512_DIGEST_SIZE));
445
446 *digest = TPM2B_DIGEST_MAKE(h, h_len);
447
448 assert_se(digest_check(digest, hash));
449 }
450
451 TEST(digest_many) {
452 TPM2B_DIGEST d, d0, d1, d2, d3, d4;
453
454 digest_init(&d0, "0000000000000000000000000000000000000000000000000000000000000000");
455 digest_init(&d1, "17b7703d9d00776310ba032e88c1a8c2a9c630ebdd799db622f6631530789175");
456 digest_init(&d2, "12998c017066eb0d2a70b94e6ed3192985855ce390f321bbdb832022888bd251");
457 digest_init(&d3, "c3a65887fedd3fb4f5d0047e906dff830bcbd1293160909eb4b05f485e7387ad");
458 digest_init(&d4, "6491fb4bc08fc0b2ef47fc63db57e249917885e69d8c0d99667df83a59107a33");
459
460 /* tpm2_digest_init, tpm2_digest_rehash */
461 d = (TPM2B_DIGEST){ .size = 1, .buffer = { 2, }, };
462 assert_se(tpm2_digest_init(TPM2_ALG_SHA256, &d) == 0);
463 assert_se(digest_check(&d, "0000000000000000000000000000000000000000000000000000000000000000"));
464 assert_se(tpm2_digest_rehash(TPM2_ALG_SHA256, &d) == 0);
465 assert_se(digest_check(&d, "66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925"));
466
467 d = d1;
468 assert_se(tpm2_digest_rehash(TPM2_ALG_SHA256, &d) == 0);
469 assert_se(digest_check(&d, "ab55014b5ace12ba70c3acc887db571585a83539aad3633d252a710f268f405c"));
470 assert_se(tpm2_digest_init(TPM2_ALG_SHA256, &d) == 0);
471 assert_se(digest_check(&d, "0000000000000000000000000000000000000000000000000000000000000000"));
472
473 /* tpm2_digest_many_digests */
474 assert_se(tpm2_digest_many_digests(TPM2_ALG_SHA256, &d, &d2, 1, false) == 0);
475 assert_se(digest_check(&d, "56571a1be3fbeab18d215f549095915a004b5788ca0d535be668559129a76f25"));
476 assert_se(tpm2_digest_many_digests(TPM2_ALG_SHA256, &d, &d2, 1, true) == 0);
477 assert_se(digest_check(&d, "99dedaee8f4d8d10a8be184399fde8740d5e17ff783ee5c288a4486e4ce3a1fe"));
478
479 const TPM2B_DIGEST da1[] = { d2, d3, };
480 assert_se(tpm2_digest_many_digests(TPM2_ALG_SHA256, &d, da1, ELEMENTSOF(da1), false) == 0);
481 assert_se(digest_check(&d, "525aa13ef9a61827778ec3acf16fbb23b65ae8770b8fb2684d3a33f9457dd6d8"));
482 assert_se(tpm2_digest_many_digests(TPM2_ALG_SHA256, &d, da1, ELEMENTSOF(da1), true) == 0);
483 assert_se(digest_check(&d, "399ca2aa98963d1bd81a2b58a7e5cda24bba1be88fb4da9aa73d97706846566b"));
484
485 const TPM2B_DIGEST da2[] = { d3, d2, d0 };
486 assert_se(tpm2_digest_many_digests(TPM2_ALG_SHA256, &d, da2, ELEMENTSOF(da2), false) == 0);
487 assert_se(digest_check(&d, "b26fd22db74d4cd896bff01c61aa498a575e4a553a7fb5a322a5fee36954313e"));
488 assert_se(tpm2_digest_many_digests(TPM2_ALG_SHA256, &d, da2, ELEMENTSOF(da2), true) == 0);
489 assert_se(digest_check(&d, "091e79a5b09d4048df49a680f966f3ff67910afe185c3baf9704c9ca45bcf259"));
490
491 const TPM2B_DIGEST da3[] = { d4, d4, d4, d4, d3, d4, d4, d4, d4, };
492 assert_se(tpm2_digest_many_digests(TPM2_ALG_SHA256, &d, da3, ELEMENTSOF(da3), false) == 0);
493 assert_se(digest_check(&d, "8eca947641b6002df79dfb571a7f78b7d0a61370a366f722386dfbe444d18830"));
494 assert_se(tpm2_digest_many_digests(TPM2_ALG_SHA256, &d, da3, ELEMENTSOF(da3), true) == 0);
495 assert_se(digest_check(&d, "f9ba17bc0bbe8794e9bcbf112e4d59a11eb68fffbcd5516a746e4857829dff04"));
496
497 /* tpm2_digest_buffer */
498 const uint8_t b1[] = { 1, 2, 3, 4, };
499 assert_se(tpm2_digest_buffer(TPM2_ALG_SHA256, &d, b1, ELEMENTSOF(b1), false) == 0);
500 assert_se(digest_check(&d, "9f64a747e1b97f131fabb6b447296c9b6f0201e79fb3c5356e6c77e89b6a806a"));
501 assert_se(tpm2_digest_buffer(TPM2_ALG_SHA256, &d, b1, ELEMENTSOF(b1), true) == 0);
502 assert_se(digest_check(&d, "ff3bd307b287e9b29bb572f6ccfd19deb0106d0c4c3c5cfe8a1d03a396092ed4"));
503
504 const void *b2 = d2.buffer;
505 assert_se(tpm2_digest_buffer(TPM2_ALG_SHA256, &d, b2, d2.size, false) == 0);
506 assert_se(digest_check(&d, "56571a1be3fbeab18d215f549095915a004b5788ca0d535be668559129a76f25"));
507 assert_se(tpm2_digest_buffer(TPM2_ALG_SHA256, &d, b2, d2.size, true) == 0);
508 assert_se(digest_check(&d, "99dedaee8f4d8d10a8be184399fde8740d5e17ff783ee5c288a4486e4ce3a1fe"));
509
510 /* tpm2_digest_many */
511 const struct iovec iov1[] = {
512 IOVEC_MAKE((void*) b1, ELEMENTSOF(b1)),
513 IOVEC_MAKE(d2.buffer, d2.size),
514 IOVEC_MAKE(d3.buffer, d3.size),
515 };
516 assert_se(tpm2_digest_many(TPM2_ALG_SHA256, &d, iov1, ELEMENTSOF(iov1), false) == 0);
517 assert_se(digest_check(&d, "cd7bde4a047af976b6f1b282309976229be59f96a78aa186de32a1aee488ab09"));
518 assert_se(tpm2_digest_many(TPM2_ALG_SHA256, &d, iov1, ELEMENTSOF(iov1), true) == 0);
519 assert_se(digest_check(&d, "02ecb0628264235111e0053e271092981c8b15d59cd46617836bee3149a4ecb0"));
520 }
521
522 static void check_parse_pcr_argument(
523 const char *arg,
524 const Tpm2PCRValue *prev_values,
525 size_t n_prev_values,
526 const Tpm2PCRValue *expected_values,
527 size_t n_expected_values) {
528
529 _cleanup_free_ Tpm2PCRValue *values = NULL;
530 size_t n_values = 0;
531
532 if (n_prev_values > 0) {
533 assert_se(GREEDY_REALLOC_APPEND(values, n_values, prev_values, n_prev_values));
534 assert_se(tpm2_parse_pcr_argument_append(arg, &values, &n_values) == 0);
535 } else
536 assert_se(tpm2_parse_pcr_argument(arg, &values, &n_values) == 0);
537
538 assert_se(n_values == n_expected_values);
539 for (size_t i = 0; i < n_values; i++) {
540 const Tpm2PCRValue *v = &values[i], *e = &expected_values[i];
541 //tpm2_log_debug_pcr_value(e, "Expected value");
542 //tpm2_log_debug_pcr_value(v, "Actual value");
543
544 assert_se(v->index == e->index);
545 assert_se(v->hash == e->hash);
546 assert_se(v->value.size == e->value.size);
547 assert_se(memcmp(v->value.buffer, e->value.buffer, e->value.size) == 0);
548 }
549
550 size_t hash_count;
551 assert_se(tpm2_pcr_values_hash_count(expected_values, n_expected_values, &hash_count) == 0);
552 if (hash_count == 1) {
553 uint32_t mask = UINT32_MAX, expected_mask = 0;
554
555 if (n_prev_values > 0)
556 assert_se(tpm2_pcr_values_to_mask(prev_values, n_prev_values, prev_values[0].hash, &mask) == 0);
557
558 assert_se(tpm2_pcr_values_to_mask(expected_values, n_expected_values, expected_values[0].hash, &expected_mask) == 0);
559
560 assert_se(tpm2_parse_pcr_argument_to_mask(arg, &mask) == 0);
561 assert_se(mask == expected_mask);
562 }
563
564 size_t old_n_values = n_values;
565 assert_se(tpm2_parse_pcr_argument_append("", &values, &n_values) == 0);
566 assert_se(values);
567 assert_se(n_values == old_n_values);
568 }
569
570 static void check_parse_pcr_argument_to_mask(const char *arg, int mask) {
571 uint32_t m = 0;
572 int r = tpm2_parse_pcr_argument_to_mask(arg, &m);
573
574 if (mask < 0)
575 assert_se(mask == r);
576 else
577 assert_se((uint32_t) mask == m);
578 }
579
580 TEST(parse_pcr_argument) {
581 _cleanup_free_ Tpm2PCRValue *t0p = NULL;
582 size_t n_t0p;
583 assert_se(tpm2_parse_pcr_argument("", &t0p, &n_t0p) == 0);
584 assert_se(n_t0p == 0);
585 assert_se(tpm2_parse_pcr_argument_append("", &t0p, &n_t0p) == 0);
586 assert_se(n_t0p == 0);
587 uint32_t m0 = 0xf;
588 assert_se(tpm2_parse_pcr_argument_to_mask("", &m0) == 0);
589 assert_se(m0 == 0);
590 assert_se(tpm2_parse_pcr_argument_to_mask("", &m0) == 0);
591 assert_se(m0 == 0);
592
593 Tpm2PCRValue t1[] = {
594 TPM2_PCR_VALUE_MAKE(0, 0, {}),
595 TPM2_PCR_VALUE_MAKE(4, 0, {}),
596 TPM2_PCR_VALUE_MAKE(7, 0, {}),
597 TPM2_PCR_VALUE_MAKE(11, 0, {}),
598 };
599 check_parse_pcr_argument("0,4,7,11", NULL, 0, t1, ELEMENTSOF(t1));
600 check_parse_pcr_argument("11,4,7,0", NULL, 0, t1, ELEMENTSOF(t1));
601 check_parse_pcr_argument("7,4,0,11", NULL, 0, t1, ELEMENTSOF(t1));
602 check_parse_pcr_argument("11,7,4,0", NULL, 0, t1, ELEMENTSOF(t1));
603 check_parse_pcr_argument("0+4+7+11", NULL, 0, t1, ELEMENTSOF(t1));
604 check_parse_pcr_argument("0,4+7,11", NULL, 0, t1, ELEMENTSOF(t1));
605
606 Tpm2PCRValue t2[] = {
607 TPM2_PCR_VALUE_MAKE(0, TPM2_ALG_SHA1, {}),
608 TPM2_PCR_VALUE_MAKE(4, TPM2_ALG_SHA1, {}),
609 TPM2_PCR_VALUE_MAKE(7, TPM2_ALG_SHA1, {}),
610 TPM2_PCR_VALUE_MAKE(11, TPM2_ALG_SHA1, {}),
611 };
612 check_parse_pcr_argument("0:sha1,4,7,11", NULL, 0, t2, ELEMENTSOF(t2));
613 check_parse_pcr_argument("11,4,7,0:sha1", NULL, 0, t2, ELEMENTSOF(t2));
614 check_parse_pcr_argument("7,4:sha1,0,11", NULL, 0, t2, ELEMENTSOF(t2));
615 check_parse_pcr_argument("0:sha1,4:sha1,7:sha1,11:sha1", NULL, 0, t2, ELEMENTSOF(t2));
616 check_parse_pcr_argument("0:sha1+4:sha1,11:sha1+7:sha1", NULL, 0, t2, ELEMENTSOF(t2));
617
618 Tpm2PCRValue t3[] = {
619 TPM2_PCR_VALUE_MAKE(0, TPM2_ALG_SHA1, {}),
620 TPM2_PCR_VALUE_MAKE(1, TPM2_ALG_SHA1, {}),
621 TPM2_PCR_VALUE_MAKE(2, TPM2_ALG_SHA1, {}),
622 TPM2_PCR_VALUE_MAKE(3, TPM2_ALG_SHA1, {}),
623 TPM2_PCR_VALUE_MAKE(4, TPM2_ALG_SHA1, {}),
624 TPM2_PCR_VALUE_MAKE(7, TPM2_ALG_SHA1, {}),
625 TPM2_PCR_VALUE_MAKE(11, TPM2_ALG_SHA1, {}),
626 TPM2_PCR_VALUE_MAKE(12, TPM2_ALG_SHA1, {}),
627 };
628 check_parse_pcr_argument("1,2,3,12", t2, ELEMENTSOF(t2), t3, ELEMENTSOF(t3));
629 check_parse_pcr_argument("12,2,3,1", t2, ELEMENTSOF(t2), t3, ELEMENTSOF(t3));
630 check_parse_pcr_argument("1,2,3,12:sha1", t1, ELEMENTSOF(t1), t3, ELEMENTSOF(t3));
631 check_parse_pcr_argument("1,2,3,12:sha1", t2, ELEMENTSOF(t2), t3, ELEMENTSOF(t3));
632 check_parse_pcr_argument("1:sha1,2,3,12", t1, ELEMENTSOF(t1), t3, ELEMENTSOF(t3));
633 check_parse_pcr_argument("1:sha1,2,3,12", t2, ELEMENTSOF(t2), t3, ELEMENTSOF(t3));
634 check_parse_pcr_argument("1:sha1,2:sha1,3:sha1,12:sha1", t1, ELEMENTSOF(t1), t3, ELEMENTSOF(t3));
635 check_parse_pcr_argument("1:sha1,2:sha1,3:sha1,12:sha1", t2, ELEMENTSOF(t2), t3, ELEMENTSOF(t3));
636
637 TPM2B_DIGEST d4;
638 digest_init(&d4, "FCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2");
639 Tpm2PCRValue t4[] = {
640 TPM2_PCR_VALUE_MAKE(0, TPM2_ALG_SHA256, {}),
641 TPM2_PCR_VALUE_MAKE(1, TPM2_ALG_SHA256, d4),
642 TPM2_PCR_VALUE_MAKE(2, TPM2_ALG_SHA256, {}),
643 TPM2_PCR_VALUE_MAKE(3, TPM2_ALG_SHA256, {}),
644 TPM2_PCR_VALUE_MAKE(4, TPM2_ALG_SHA256, {}),
645 TPM2_PCR_VALUE_MAKE(7, TPM2_ALG_SHA256, {}),
646 TPM2_PCR_VALUE_MAKE(11, TPM2_ALG_SHA256, {}),
647 TPM2_PCR_VALUE_MAKE(12, TPM2_ALG_SHA256, {}),
648 };
649 check_parse_pcr_argument("1:sha256=0xFCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2,2,3,12", t1, ELEMENTSOF(t1), t4, ELEMENTSOF(t4));
650 check_parse_pcr_argument("12,2,3,1:sha256=FCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2", t1, ELEMENTSOF(t1), t4, ELEMENTSOF(t4));
651 check_parse_pcr_argument("12,2,3,1:sha256=0xFCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2", t1, ELEMENTSOF(t1), t4, ELEMENTSOF(t4));
652 check_parse_pcr_argument("1:sha256=0xFCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2,2,3,12:SHA256", t1, ELEMENTSOF(t1), t4, ELEMENTSOF(t4));
653 check_parse_pcr_argument("1:sha256=0xFCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2,2,3,12", t1, ELEMENTSOF(t1), t4, ELEMENTSOF(t4));
654 check_parse_pcr_argument("1:sha256=FCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2,2:sha256,3:sha256,12:sha256", t1, ELEMENTSOF(t1), t4, ELEMENTSOF(t4));
655 check_parse_pcr_argument("1:sha256=0xFCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2,2:sha256,3:sha256,12:sha256", t1, ELEMENTSOF(t1), t4, ELEMENTSOF(t4));
656
657 TPM2B_DIGEST d5;
658 digest_init(&d5, "0F21EADB7F27377668E3C8069BE88D116491FBEE");
659 Tpm2PCRValue t5[] = {
660 TPM2_PCR_VALUE_MAKE(1, TPM2_ALG_SHA1, d5),
661 TPM2_PCR_VALUE_MAKE(0, TPM2_ALG_SHA256, {}),
662 TPM2_PCR_VALUE_MAKE(1, TPM2_ALG_SHA256, d4),
663 TPM2_PCR_VALUE_MAKE(2, TPM2_ALG_SHA256, {}),
664 TPM2_PCR_VALUE_MAKE(3, TPM2_ALG_SHA256, {}),
665 TPM2_PCR_VALUE_MAKE(4, TPM2_ALG_SHA256, {}),
666 TPM2_PCR_VALUE_MAKE(7, TPM2_ALG_SHA256, {}),
667 TPM2_PCR_VALUE_MAKE(11, TPM2_ALG_SHA256, {}),
668 TPM2_PCR_VALUE_MAKE(12, TPM2_ALG_SHA256, {}),
669 TPM2_PCR_VALUE_MAKE(5, TPM2_ALG_SHA384, {}),
670 TPM2_PCR_VALUE_MAKE(6, TPM2_ALG_SHA512, {}),
671 };
672 check_parse_pcr_argument("0,1:sha256=0xFCE7F1083082B16CFE2B085DD7858BB11A37C09B78E36C79E5A2FD529353C4E2,1:sha1=0F21EADB7F27377668E3C8069BE88D116491FBEE,2,3,4,7,11,12,5:sha384,6:sha512", NULL, 0, t5, ELEMENTSOF(t5));
673 check_parse_pcr_argument("1:sha1=0F21EADB7F27377668E3C8069BE88D116491FBEE,6:sha512,5:sha384", t4, ELEMENTSOF(t4), t5, ELEMENTSOF(t5));
674
675 Tpm2PCRValue *v = NULL;
676 size_t n_v = 0;
677 assert_se(tpm2_parse_pcr_argument("1,100", &v, &n_v) < 0);
678 assert_se(tpm2_parse_pcr_argument("1,2=123456abc", &v, &n_v) < 0);
679 assert_se(tpm2_parse_pcr_argument("1,2:invalid", &v, &n_v) < 0);
680 assert_se(tpm2_parse_pcr_argument("1:sha1=invalid", &v, &n_v) < 0);
681 ASSERT_NULL(v);
682 assert_se(n_v == 0);
683
684 check_parse_pcr_argument_to_mask("", 0x0);
685 check_parse_pcr_argument_to_mask("0", 0x1);
686 check_parse_pcr_argument_to_mask("1", 0x2);
687 check_parse_pcr_argument_to_mask("0,1", 0x3);
688 check_parse_pcr_argument_to_mask("0+1", 0x3);
689 check_parse_pcr_argument_to_mask("0-1", -EINVAL);
690 check_parse_pcr_argument_to_mask("foo", -EINVAL);
691 check_parse_pcr_argument_to_mask("0,1,2", 0x7);
692 check_parse_pcr_argument_to_mask("0+1+2", 0x7);
693 check_parse_pcr_argument_to_mask("0+1,2", 0x7);
694 check_parse_pcr_argument_to_mask("0,1+2", 0x7);
695 check_parse_pcr_argument_to_mask("0,2", 0x5);
696 check_parse_pcr_argument_to_mask("0+2", 0x5);
697 check_parse_pcr_argument_to_mask("7+application-support", 0x800080);
698 check_parse_pcr_argument_to_mask("8+boot-loader-code", 0x110);
699 check_parse_pcr_argument_to_mask("7,shim-policy,4", 0x4090);
700 check_parse_pcr_argument_to_mask("sysexts,shim-policy+kernel-boot", 0x6800);
701 check_parse_pcr_argument_to_mask("sysexts,shim+kernel-boot", -EINVAL);
702 check_parse_pcr_argument_to_mask("sysexts+17+23", 0x822000);
703 check_parse_pcr_argument_to_mask("6+boot-loader-code,44", -EINVAL);
704 check_parse_pcr_argument_to_mask("debug+24", -EINVAL);
705 }
706
707 static const TPMT_PUBLIC test_rsa_template = {
708 .type = TPM2_ALG_RSA,
709 .nameAlg = TPM2_ALG_SHA256,
710 .objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
711 .parameters.rsaDetail = {
712 .symmetric = {
713 .algorithm = TPM2_ALG_AES,
714 .keyBits.aes = 128,
715 .mode.aes = TPM2_ALG_CFB,
716 },
717 .scheme.scheme = TPM2_ALG_NULL,
718 .keyBits = 2048,
719 },
720 };
721
722 static const TPMT_PUBLIC test_ecc_template = {
723 .type = TPM2_ALG_ECC,
724 .nameAlg = TPM2_ALG_SHA256,
725 .objectAttributes = TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH,
726 .parameters.eccDetail = {
727 .symmetric = {
728 .algorithm = TPM2_ALG_AES,
729 .keyBits.aes = 128,
730 .mode.aes = TPM2_ALG_CFB,
731 },
732 .scheme.scheme = TPM2_ALG_NULL,
733 .curveID = TPM2_ECC_NIST_P256,
734 .kdf.scheme = TPM2_ALG_NULL,
735 },
736 };
737
738 static const TPMT_PUBLIC *test_templates[] = {
739 &test_rsa_template,
740 &test_ecc_template,
741 };
742
743 static void tpm2b_public_rsa_init(TPM2B_PUBLIC *public, const char *rsa_n) {
744 TPMT_PUBLIC tpmt = test_rsa_template;
745
746 DEFINE_HEX_PTR(key, rsa_n);
747 tpmt.unique.rsa = TPM2B_PUBLIC_KEY_RSA_MAKE(key, key_len);
748
749 public->size = sizeof(tpmt);
750 public->publicArea = tpmt;
751 }
752
753 static void tpm2b_public_ecc_init(TPM2B_PUBLIC *public, TPMI_ECC_CURVE curve, const char *x, const char *y) {
754 TPMT_PUBLIC tpmt = test_ecc_template;
755 tpmt.parameters.eccDetail.curveID = curve;
756
757 DEFINE_HEX_PTR(buf_x, x);
758 tpmt.unique.ecc.x = TPM2B_ECC_PARAMETER_MAKE(buf_x, buf_x_len);
759
760 DEFINE_HEX_PTR(buf_y, y);
761 tpmt.unique.ecc.y = TPM2B_ECC_PARAMETER_MAKE(buf_y, buf_y_len);
762
763 public->size = sizeof(tpmt);
764 public->publicArea = tpmt;
765 }
766
767 #if HAVE_OPENSSL
768 TEST(tpm2b_public_to_openssl_pkey) {
769 DEFINE_HEX_PTR(msg, "edc64c6523778961fe9ba03ab7d624b27ca1dd5b01e7734cc6c891d50db04269");
770 TPM2B_PUBLIC public;
771
772 /* RSA */
773 tpm2b_public_rsa_init(&public, "d71cff5bba2173f0434a389171048e7da8cf8409b892c62946481cc383089bc754324620967fea3d00a02a717cdda4bfe1525ad957d294b88434e0a3933e86fb40f234e4935fd2ba27eb1d21da87efa466b74eb4ad18d26059904643441cf402ee933d138a2151f40459c49d87fef59e2cb822768b2d8689a9b58f82bf9a37e70693f2b2d40dfa388d365c1b1f029a14c4fc8dadb68978ef377d20ff2ca24e7078464c705eab42f531557c9c6dc0df66b506d0c26ef604f8110c64867099267453c71871e7ed22505a09daf102afc34355209ca7680eccc0ed368d148f402fa58cbb6c9d52351f535f09e4e24ad805e149f130edaa2f5e7efed3a4d2d03adb85");
774 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey_rsa = NULL;
775 assert_se(tpm2_tpm2b_public_to_openssl_pkey(&public, &pkey_rsa) >= 0);
776
777 _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx_rsa = EVP_PKEY_CTX_new((EVP_PKEY*) pkey_rsa, NULL);
778 assert_se(ctx_rsa);
779 assert_se(EVP_PKEY_verify_init(ctx_rsa) == 1);
780 assert_se(EVP_PKEY_CTX_set_signature_md(ctx_rsa, EVP_sha256()) > 0);
781
782 DEFINE_HEX_PTR(sig_rsa, "9f70a9e68911be3ec464cae91126328307bf355872127e042d6c61e0a80982872c151033bcf727abfae5fc9500c923120011e7ef4aa5fc690a59a034697b6022c141b4b209e2df6f4b282288cd9181073fbe7158ce113c79d87623423c1f3996ff931e59cc91db74f8e8656215b1436fc93ddec0f1f8fa8510826e674b250f047e6cba94c95ff98072a286baca94646b577974a1e00d56c21944e38960d8ee90511a2f938e5cf1ac7b7cc7ff8e3ac001d321254d3e4f988b90e9f6f873c26ecd0a12a626b3474833cdbb9e9f793238f6c97ee5b75a1a89bb7a7858d34ecfa6d34ac58d95085e6c4fbbebd47a4364be2725c2c6b3fa15d916f3c0b62a66fe76ae");
783 assert_se(EVP_PKEY_verify(ctx_rsa, sig_rsa, sig_rsa_len, (unsigned char*) msg, msg_len) == 1);
784
785 /* ECC */
786 tpm2b_public_ecc_init(&public, TPM2_ECC_NIST_P256, "6fc0ecf3645c673ab7e86d1ec5b315afb950257c5f68ab23296160006711fac2", "8dd2ef7a2c9ecede91493ba98c8fb3f893aff325c6a1e0f752c657b2d6ca1413");
787 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey_ecc = NULL;
788 assert_se(tpm2_tpm2b_public_to_openssl_pkey(&public, &pkey_ecc) >= 0);
789
790 _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx_ecc = EVP_PKEY_CTX_new((EVP_PKEY*) pkey_ecc, NULL);
791 assert_se(ctx_ecc);
792 assert_se(EVP_PKEY_verify_init(ctx_ecc) == 1);
793
794 DEFINE_HEX_PTR(sig_ecc, "304602210092447ac0b5b32e90923f79bb4aba864b9c546a9900cf193a83243d35d189a2110221009a8b4df1dfa85e225eff9c606694d4d205a7a3968c9552f50bc2790209a90001");
795 assert_se(EVP_PKEY_verify(ctx_ecc, sig_ecc, sig_ecc_len, (unsigned char*) msg, msg_len) == 1);
796 }
797
798 static void get_tpm2b_public_from_pem(const void *pem, size_t pem_size, TPM2B_PUBLIC *ret) {
799 _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
800 TPM2B_PUBLIC p1 = {}, p2 = {};
801
802 assert(pem);
803 assert(ret);
804
805 assert_se(openssl_pkey_from_pem(pem, pem_size, &pkey) >= 0);
806 assert_se(tpm2_tpm2b_public_from_openssl_pkey(pkey, &p1) >= 0);
807 assert_se(tpm2_tpm2b_public_from_pem(pem, pem_size, &p2) >= 0);
808 assert_se(memcmp_nn(&p1, sizeof(p1), &p2, sizeof(p2)) == 0);
809
810 *ret = p1;
811 }
812
813 static void check_tpm2b_public_fingerprint(const TPM2B_PUBLIC *public, const char *hexfp) {
814 DEFINE_HEX_PTR(expected, hexfp);
815 _cleanup_free_ void *fp = NULL;
816 size_t fp_size;
817
818 assert_se(tpm2_tpm2b_public_to_fingerprint(public, &fp, &fp_size) >= 0);
819 assert_se(memcmp_nn(fp, fp_size, expected, expected_len) == 0);
820 }
821
822 static void check_tpm2b_public_name(const TPM2B_PUBLIC *public, const char *hexname) {
823 DEFINE_HEX_PTR(expected, hexname);
824 TPM2B_NAME name = {};
825
826 assert_se(tpm2_calculate_pubkey_name(&public->publicArea, &name) >= 0);
827 assert_se(memcmp_nn(name.name, name.size, expected, expected_len) == 0);
828 }
829
830 static void check_tpm2b_public_from_ecc_pem(const char *pem, const char *hexx, const char *hexy, const char *hexfp, const char *hexname) {
831 TPM2B_PUBLIC public = {};
832 TPMT_PUBLIC *p = &public.publicArea;
833
834 DEFINE_HEX_PTR(key, pem);
835 get_tpm2b_public_from_pem(key, key_len, &public);
836
837 assert_se(p->type == TPM2_ALG_ECC);
838 assert_se(p->parameters.eccDetail.curveID == TPM2_ECC_NIST_P256);
839
840 DEFINE_HEX_PTR(expected_x, hexx);
841 assert_se(memcmp_nn(p->unique.ecc.x.buffer, p->unique.ecc.x.size, expected_x, expected_x_len) == 0);
842
843 DEFINE_HEX_PTR(expected_y, hexy);
844 assert_se(memcmp_nn(p->unique.ecc.y.buffer, p->unique.ecc.y.size, expected_y, expected_y_len) == 0);
845
846 check_tpm2b_public_fingerprint(&public, hexfp);
847 check_tpm2b_public_name(&public, hexname);
848 }
849
850 static void check_tpm2b_public_from_rsa_pem(const char *pem, const char *hexn, uint32_t exponent, const char *hexfp, const char *hexname) {
851 TPM2B_PUBLIC public = {};
852 TPMT_PUBLIC *p = &public.publicArea;
853
854 DEFINE_HEX_PTR(key, pem);
855 get_tpm2b_public_from_pem(key, key_len, &public);
856
857 assert_se(p->type == TPM2_ALG_RSA);
858
859 DEFINE_HEX_PTR(expected_n, hexn);
860 assert_se(memcmp_nn(p->unique.rsa.buffer, p->unique.rsa.size, expected_n, expected_n_len) == 0);
861
862 assert_se(p->parameters.rsaDetail.keyBits == expected_n_len * 8);
863
864 assert_se(p->parameters.rsaDetail.exponent == exponent);
865
866 check_tpm2b_public_fingerprint(&public, hexfp);
867 check_tpm2b_public_name(&public, hexname);
868 }
869
870 TEST(tpm2b_public_from_openssl_pkey) {
871 /* standard ECC key */
872 check_tpm2b_public_from_ecc_pem("2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a30444151634451674145726a6e4575424c73496c3972687068777976584e50686a346a426e500a44586e794a304b395579724e6764365335413532542b6f5376746b436a365a726c34685847337741515558706f426c532b7448717452714c35513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a",
873 "ae39c4b812ec225f6b869870caf5cd3e18f88c19cf0d79f22742bd532acd81de",
874 "92e40e764fea12bed9028fa66b9788571b7c004145e9a01952fad1eab51a8be5",
875 "cd3373293b62a52b48c12100e80ea9bfd806266ce76893a5ec31cb128052d97c",
876 "000b5c127e4dbaf8fb7bac641e8db25a84a48db876ca7ee3bd317ae1a4554ff72f17");
877
878 /* standard RSA key */
879 check_tpm2b_public_from_rsa_pem("2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494942496a414e42676b71686b6947397730424151454641414f43415138414d49494243674b4341514541795639434950652f505852337a436f63787045300a6a575262546c3568585844436b472f584b79374b6d2f4439584942334b734f5a31436a5937375571372f674359363170697838697552756a73413464503165380a593445336c68556d374a332b6473766b626f4b64553243626d52494c2f6675627771694c4d587a41673342575278747234547545443533527a373634554650640a307a70304b68775231496230444c67772f344e67566f314146763378784b4d6478774d45683567676b73733038326332706c354a504e32587677426f744e6b4d0a5471526c745a4a35355244436170696e7153334577376675646c4e735851357746766c7432377a7637344b585165616d704c59433037584f6761304c676c536b0a79754774586b6a50542f735542544a705374615769674d5a6f714b7479563463515a58436b4a52684459614c47587673504233687a766d5671636e6b47654e540a65774944415141420a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a",
880 "c95f4220f7bf3d7477cc2a1cc691348d645b4e5e615d70c2906fd72b2eca9bf0fd5c80772ac399d428d8efb52aeff80263ad698b1f22b91ba3b00e1d3f57bc638137961526ec9dfe76cbe46e829d53609b99120bfdfb9bc2a88b317cc0837056471b6be13b840f9dd1cfbeb85053ddd33a742a1c11d486f40cb830ff8360568d4016fdf1c4a31dc7030487982092cb34f36736a65e493cdd97bf0068b4d90c4ea465b59279e510c26a98a7a92dc4c3b7ee76536c5d0e7016f96ddbbcefef829741e6a6a4b602d3b5ce81ad0b8254a4cae1ad5e48cf4ffb140532694ad6968a0319a2a2adc95e1c4195c29094610d868b197bec3c1de1cef995a9c9e419e3537b",
881 0x10001,
882 "d9186d13a7fd5b3644cee05448f49ad3574e82a2942ff93cf89598d36cca78a9",
883 "000be1bd75c7976e7a30e9e82223b81a9eff0d42c30618e588db592ed5da94455e81");
884
885 /* RSA key with non-default (i.e. not 0x10001) exponent */
886 check_tpm2b_public_from_rsa_pem("2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d494942496a414e42676b71686b6947397730424151454641414f43415138414d49494243674b434151454179566c7551664b75565171596a5a71436a657a760a364e4a6f58654c736f702f72765375666330773769544d4f73566741557462515452505451725874397065537a4370524467634378656b6a544144577279304b0a6d59786a7a3634776c6a7030463959383068636a6b6b4b3759414d333054664c4648656c2b377574427370777142467a6e2b385a6659567353434b397354706f0a316c61376e5347514e7451576f36444a366c525a336a676d6d584f61544654416145304a432b7046584273564471736d46326438362f314e51714a755a5154520a575852636954704e58357649792f37766b6c5a6a685569526c78764e594f4e3070636476534a37364e74496e447a3048506f775a38705a454f4d2f4a454f59780a617a4c4a6a644936446b355279593578325a7949375074566a3057537242524f4d696f2b674c6556457a43343456336438315a38445138564e334c69625130330a70514944415141460a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a",
887 "c9596e41f2ae550a988d9a828decefe8d2685de2eca29febbd2b9f734c3b89330eb1580052d6d04d13d342b5edf69792cc2a510e0702c5e9234c00d6af2d0a998c63cfae30963a7417d63cd217239242bb600337d137cb1477a5fbbbad06ca70a811739fef197d856c4822bdb13a68d656bb9d219036d416a3a0c9ea5459de382699739a4c54c0684d090bea455c1b150eab2617677cebfd4d42a26e6504d159745c893a4d5f9bc8cbfeef925663854891971bcd60e374a5c76f489efa36d2270f3d073e8c19f2964438cfc910e6316b32c98dd23a0e4e51c98e71d99c88ecfb558f4592ac144e322a3e80b7951330b8e15dddf3567c0d0f153772e26d0d37a5",
888 0x10005,
889 "c8ca80a687d5972e1d961aaa2cfde2ff2e7a20d85e3ea0382804e70e013d65af",
890 "000beb8974d36d8cf58fdc87460dda00319e10c94c1b9f222ac9ce29d1c4776246cc");
891 }
892 #endif
893
894 static void check_name(const TPM2B_NAME *name, const char *expect) {
895 assert_se(name->size == SHA256_DIGEST_SIZE + 2);
896
897 DEFINE_HEX_PTR(e, expect);
898 assert_se(name->size == e_len);
899 assert_se(memcmp(name->name, e, e_len) == 0);
900 }
901
902 TEST(calculate_pubkey_name) {
903 TPM2B_PUBLIC public;
904 TPM2B_NAME name;
905
906 /* RSA */
907 tpm2b_public_rsa_init(&public, "9ec7341c52093ac40a1965a5df10432513c539adcf905e30577ab6ebc88ffe53cd08cef12ed9bec6125432f4fada3629b8b96d31b8f507aa35029188fe396da823fcb236027f7fbb01b0da3d87be7f999390449ced604bdf7e26c48657cc0671000f1147da195c3861c96642e54427cb7a11572e07567ec3fd6316978abc4bd92b27bb0a0e4958e599804eeb41d682b3b7fc1f960209f80a4fb8a1b64abfd96bf5d554e73cdd6ad1c8becb4fcf5e8f0c3e621d210e5e2f308f6520ad9a966779231b99f06c5989e5a23a9415c8808ab89ce81117632e2f8461cd4428bded40979236aeadafe8de3f51660a45e1dbc87694e6a36360201cca3ff9e7263e712727");
908 assert_se(tpm2_calculate_pubkey_name(&public.publicArea, &name) >= 0);
909 check_name(&name, "000be78f74a470dd92e979ca067cdb2293a35f075e8560b436bd2ccea5da21486a07");
910
911 /* ECC */
912 tpm2b_public_ecc_init(&public, TPM2_ECC_NIST_P256, "238e02ee4fd5598add6b502429f1815418515e4b0d6551c8e816b38cb15451d1", "70c2d491769775ec43ccd5a571c429233e9d30cf0f486c2e01acd6cb32ba93b6");
913 assert_se(tpm2_calculate_pubkey_name(&public.publicArea, &name) >= 0);
914 check_name(&name, "000b302787187ba19c82011c987bd2dcdbb652b3a543ccc5cb0b49c33d4caae604a6");
915 }
916
917 TEST(calculate_policy_auth_value) {
918 TPM2B_DIGEST d;
919
920 digest_init(&d, "0000000000000000000000000000000000000000000000000000000000000000");
921 assert_se(tpm2_calculate_policy_auth_value(&d) == 0);
922 assert_se(digest_check(&d, "8fcd2169ab92694e0c633f1ab772842b8241bbc20288981fc7ac1eddc1fddb0e"));
923 assert_se(tpm2_calculate_policy_auth_value(&d) == 0);
924 assert_se(digest_check(&d, "759ebd5ed65100e0b4aa2d04b4b789c2672d92ecc9cdda4b5fa16a303132e008"));
925 }
926
927 TEST(calculate_policy_authorize) {
928 TPM2B_PUBLIC public;
929 TPM2B_DIGEST d;
930
931 /* RSA */
932 tpm2b_public_rsa_init(&public, "9ec7341c52093ac40a1965a5df10432513c539adcf905e30577ab6ebc88ffe53cd08cef12ed9bec6125432f4fada3629b8b96d31b8f507aa35029188fe396da823fcb236027f7fbb01b0da3d87be7f999390449ced604bdf7e26c48657cc0671000f1147da195c3861c96642e54427cb7a11572e07567ec3fd6316978abc4bd92b27bb0a0e4958e599804eeb41d682b3b7fc1f960209f80a4fb8a1b64abfd96bf5d554e73cdd6ad1c8becb4fcf5e8f0c3e621d210e5e2f308f6520ad9a966779231b99f06c5989e5a23a9415c8808ab89ce81117632e2f8461cd4428bded40979236aeadafe8de3f51660a45e1dbc87694e6a36360201cca3ff9e7263e712727");
933 digest_init(&d, "0000000000000000000000000000000000000000000000000000000000000000");
934 assert_se(tpm2_calculate_policy_authorize(&public, NULL, &d) == 0);
935 assert_se(digest_check(&d, "95213a3784eaab04f427bc7e8851c2f1df0903be8e42428ec25dcefd907baff1"));
936 assert_se(tpm2_calculate_policy_authorize(&public, NULL, &d) == 0);
937 assert_se(digest_check(&d, "95213a3784eaab04f427bc7e8851c2f1df0903be8e42428ec25dcefd907baff1"));
938
939 /* ECC */
940 tpm2b_public_ecc_init(&public, TPM2_ECC_NIST_P256, "423a89da6f0998f510489ab9682706e762031ef8f9faef2a185eff67065a187e", "996f73291670cef9e303d6cd9fa19ddf2c9c1fb1e283324ca9acca07c405c8d0");
941 digest_init(&d, "0000000000000000000000000000000000000000000000000000000000000000");
942 assert_se(tpm2_calculate_policy_authorize(&public, NULL, &d) == 0);
943 assert_se(digest_check(&d, "2a5b705e83f949c27ac4d2e79e54fb5fb0a60f0b37bbd54a0ee1022ba00d3628"));
944 assert_se(tpm2_calculate_policy_authorize(&public, NULL, &d) == 0);
945 assert_se(digest_check(&d, "2a5b705e83f949c27ac4d2e79e54fb5fb0a60f0b37bbd54a0ee1022ba00d3628"));
946 }
947
948 TEST(calculate_policy_pcr) {
949 TPM2B_DIGEST d, dN[16];
950
951 digest_init(&dN[ 0], "2124793cbbe60c3a8637d3b84a5d054e87c351e1469a285acc04755e8b204dec");
952 digest_init(&dN[ 1], "bf7592f18adcfdc549fc0b94939f5069a24697f9cff4a0dca29014767b97559d");
953 digest_init(&dN[ 2], "4b00cff9dee3a364979b2dc241b34568a8ad49fcf2713df259e47dff8875feed");
954 digest_init(&dN[ 3], "3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969");
955 digest_init(&dN[ 4], "368f85b3013041dfe203faaa364f00b07c5da7b1e5f1dbf2efb06fa6b9bd92de");
956 digest_init(&dN[ 5], "c97c40369691c8e4aa78fb3a52655cd193b780a838b8e23f5f476576919db5e5");
957 digest_init(&dN[ 6], "3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969");
958 digest_init(&dN[ 7], "aa1154c9e0a774854ccbed4c8ce7e9b906b3d700a1a8db1772d0341a62dbe51b");
959 digest_init(&dN[ 8], "cfde439a2c06af3479ca6bdc60429b90553d65300c5cfcc40004a08c6b5ad81a");
960 digest_init(&dN[ 9], "9c2bac22ef5ec84fcdb71c3ebf776cba1247e5da980e5ee08e45666a2edf0b8b");
961 digest_init(&dN[10], "9885873f4d7348199ad286f8f2476d4f866940950f6f9fb9f945ed352dbdcbd2");
962 digest_init(&dN[11], "42400ab950d21aa79d12cc4fdef67d1087a39ad64900619831c0974dbae54e44");
963 digest_init(&dN[12], "767d064382e56ca1ad3bdcc6bc596112e6c2008b593d3570d24c2bfa64c4628c");
964 digest_init(&dN[13], "30c16133175959408c9745d8dafadef5daf4b39cb2be04df0d60089bd46d3cc4");
965 digest_init(&dN[14], "e3991b7ddd47be7e92726a832d6874c5349b52b789fa0db8b558c69fea29574e");
966 digest_init(&dN[15], "852dae3ecb992bdeb13d6002fefeeffdd90feca8b378d56681ef2c885d0e5137");
967
968 digest_init(&d, "0000000000000000000000000000000000000000000000000000000000000000");
969 Tpm2PCRValue v1[] = {
970 TPM2_PCR_VALUE_MAKE(4, TPM2_ALG_SHA256, dN[4]),
971 TPM2_PCR_VALUE_MAKE(7, TPM2_ALG_SHA256, dN[7]),
972 TPM2_PCR_VALUE_MAKE(8, TPM2_ALG_SHA256, dN[8]),
973 };
974 assert_se(tpm2_calculate_policy_pcr(v1, ELEMENTSOF(v1), &d) == 0);
975 assert_se(digest_check(&d, "76532a0e16f7e6bf6b02918c11f75d99d729fab0cc81d0df2c4284a2c4fe6e05"));
976 assert_se(tpm2_calculate_policy_pcr(v1, ELEMENTSOF(v1), &d) == 0);
977 assert_se(digest_check(&d, "97e64bcabb64c1fa4b726528644926c8029f5b4458b0575c98c04fe225629a0b"));
978
979 digest_init(&d, "0000000000000000000000000000000000000000000000000000000000000000");
980 Tpm2PCRValue v2[] = {
981 TPM2_PCR_VALUE_MAKE( 0, TPM2_ALG_SHA256, dN[ 0]),
982 TPM2_PCR_VALUE_MAKE( 1, TPM2_ALG_SHA256, dN[ 1]),
983 TPM2_PCR_VALUE_MAKE( 2, TPM2_ALG_SHA256, dN[ 2]),
984 TPM2_PCR_VALUE_MAKE( 3, TPM2_ALG_SHA256, dN[ 3]),
985 TPM2_PCR_VALUE_MAKE( 4, TPM2_ALG_SHA256, dN[ 4]),
986 TPM2_PCR_VALUE_MAKE( 5, TPM2_ALG_SHA256, dN[ 5]),
987 TPM2_PCR_VALUE_MAKE( 6, TPM2_ALG_SHA256, dN[ 6]),
988 TPM2_PCR_VALUE_MAKE( 7, TPM2_ALG_SHA256, dN[ 7]),
989 TPM2_PCR_VALUE_MAKE( 8, TPM2_ALG_SHA256, dN[ 8]),
990 TPM2_PCR_VALUE_MAKE( 9, TPM2_ALG_SHA256, dN[ 9]),
991 TPM2_PCR_VALUE_MAKE(10, TPM2_ALG_SHA256, dN[10]),
992 TPM2_PCR_VALUE_MAKE(11, TPM2_ALG_SHA256, dN[11]),
993 TPM2_PCR_VALUE_MAKE(12, TPM2_ALG_SHA256, dN[12]),
994 TPM2_PCR_VALUE_MAKE(13, TPM2_ALG_SHA256, dN[13]),
995 TPM2_PCR_VALUE_MAKE(14, TPM2_ALG_SHA256, dN[14]),
996 TPM2_PCR_VALUE_MAKE(15, TPM2_ALG_SHA256, dN[15]),
997 };
998 assert_se(tpm2_calculate_policy_pcr(v2, ELEMENTSOF(v2), &d) == 0);
999 assert_se(digest_check(&d, "22be4f1674f792d6345cea9427701068f0e8d9f42755dcc0e927e545a68f9c13"));
1000 assert_se(tpm2_calculate_policy_pcr(v2, ELEMENTSOF(v2), &d) == 0);
1001 assert_se(digest_check(&d, "7481fd1b116078eb3ac2456e4ad542c9b46b9b8eb891335771ca8e7c8f8e4415"));
1002 }
1003
1004 static void check_srk_rsa_template(TPMT_PUBLIC *template) {
1005 assert_se(template->type == TPM2_ALG_RSA);
1006 assert_se(template->nameAlg == TPM2_ALG_SHA256);
1007 assert_se(template->objectAttributes == 0x30472);
1008 assert_se(template->parameters.rsaDetail.symmetric.algorithm == TPM2_ALG_AES);
1009 assert_se(template->parameters.rsaDetail.symmetric.keyBits.sym == 128);
1010 assert_se(template->parameters.rsaDetail.symmetric.mode.sym == TPM2_ALG_CFB);
1011 assert_se(template->parameters.rsaDetail.scheme.scheme == TPM2_ALG_NULL);
1012 assert_se(template->parameters.rsaDetail.keyBits == 2048);
1013 }
1014
1015 static void check_srk_ecc_template(TPMT_PUBLIC *template) {
1016 assert_se(template->type == TPM2_ALG_ECC);
1017 assert_se(template->nameAlg == TPM2_ALG_SHA256);
1018 assert_se(template->objectAttributes == 0x30472);
1019 assert_se(template->parameters.eccDetail.symmetric.algorithm == TPM2_ALG_AES);
1020 assert_se(template->parameters.eccDetail.symmetric.keyBits.sym == 128);
1021 assert_se(template->parameters.eccDetail.symmetric.mode.sym == TPM2_ALG_CFB);
1022 assert_se(template->parameters.eccDetail.scheme.scheme == TPM2_ALG_NULL);
1023 assert_se(template->parameters.eccDetail.kdf.scheme == TPM2_ALG_NULL);
1024 assert_se(template->parameters.eccDetail.curveID == TPM2_ECC_NIST_P256);
1025 }
1026
1027 TEST(tpm2_get_srk_template) {
1028 TPMT_PUBLIC template;
1029
1030 assert_se(tpm2_get_srk_template(TPM2_ALG_RSA, &template) >= 0);
1031 check_srk_rsa_template(&template);
1032
1033 assert_se(tpm2_get_srk_template(TPM2_ALG_ECC, &template) >= 0);
1034 check_srk_ecc_template(&template);
1035 }
1036
1037 static void check_best_srk_template(Tpm2Context *c) {
1038 TEST_LOG_FUNC();
1039
1040 TPMT_PUBLIC template;
1041 assert_se(tpm2_get_best_srk_template(c, &template) >= 0);
1042
1043 assert_se(IN_SET(template.type, TPM2_ALG_ECC, TPM2_ALG_RSA));
1044
1045 if (template.type == TPM2_ALG_RSA)
1046 check_srk_rsa_template(&template);
1047 else
1048 check_srk_ecc_template(&template);
1049 }
1050
1051 static void check_test_parms(Tpm2Context *c) {
1052 assert(c);
1053
1054 TEST_LOG_FUNC();
1055
1056 TPMU_PUBLIC_PARMS parms = {
1057 .symDetail.sym = {
1058 .algorithm = TPM2_ALG_AES,
1059 .keyBits.aes = 128,
1060 .mode.aes = TPM2_ALG_CFB,
1061 },
1062 };
1063
1064 /* Test with invalid parms */
1065 assert_se(!tpm2_test_parms(c, TPM2_ALG_CFB, &parms));
1066
1067 TPMU_PUBLIC_PARMS invalid_parms = parms;
1068 invalid_parms.symDetail.sym.keyBits.aes = 1;
1069 assert_se(!tpm2_test_parms(c, TPM2_ALG_SYMCIPHER, &invalid_parms));
1070
1071 /* Test with valid parms */
1072 assert_se(tpm2_test_parms(c, TPM2_ALG_SYMCIPHER, &parms));
1073 }
1074
1075 static void check_supports_alg(Tpm2Context *c) {
1076 assert(c);
1077
1078 TEST_LOG_FUNC();
1079
1080 /* Test invalid algs */
1081 assert_se(!tpm2_supports_alg(c, TPM2_ALG_ERROR));
1082 assert_se(!tpm2_supports_alg(c, TPM2_ALG_LAST + 1));
1083
1084 /* Test valid algs */
1085 assert_se(tpm2_supports_alg(c, TPM2_ALG_RSA));
1086 assert_se(tpm2_supports_alg(c, TPM2_ALG_AES));
1087 assert_se(tpm2_supports_alg(c, TPM2_ALG_CFB));
1088 }
1089
1090 static void check_supports_command(Tpm2Context *c) {
1091 assert(c);
1092
1093 TEST_LOG_FUNC();
1094
1095 /* Test invalid commands. TPM specification Part 2 ("Structures") section "TPM_CC (Command Codes)"
1096 * states bits 31:30 and 28:16 are reserved and must be 0. */
1097 assert_se(!tpm2_supports_command(c, UINT32_C(0x80000000)));
1098 assert_se(!tpm2_supports_command(c, UINT32_C(0x40000000)));
1099 assert_se(!tpm2_supports_command(c, UINT32_C(0x00100000)));
1100 assert_se(!tpm2_supports_command(c, UINT32_C(0x80000144)));
1101 assert_se(!tpm2_supports_command(c, UINT32_C(0x40000144)));
1102 assert_se(!tpm2_supports_command(c, UINT32_C(0x00100144)));
1103
1104 /* Test valid commands. We should be able to expect all TPMs support these. */
1105 assert_se(tpm2_supports_command(c, TPM2_CC_Startup));
1106 assert_se(tpm2_supports_command(c, TPM2_CC_StartAuthSession));
1107 assert_se(tpm2_supports_command(c, TPM2_CC_Create));
1108 assert_se(tpm2_supports_command(c, TPM2_CC_CreatePrimary));
1109 assert_se(tpm2_supports_command(c, TPM2_CC_Unseal));
1110 }
1111
1112 static void check_get_or_create_srk(Tpm2Context *c) {
1113 TEST_LOG_FUNC();
1114
1115 _cleanup_free_ TPM2B_PUBLIC *public = NULL;
1116 _cleanup_free_ TPM2B_NAME *name = NULL, *qname = NULL;
1117 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
1118 assert_se(tpm2_get_or_create_srk(c, NULL, &public, &name, &qname, &handle) >= 0);
1119 assert_se(public && name && qname && handle);
1120
1121 _cleanup_free_ TPM2B_PUBLIC *public2 = NULL;
1122 _cleanup_free_ TPM2B_NAME *name2 = NULL, *qname2 = NULL;
1123 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle2 = NULL;
1124 assert_se(tpm2_get_srk(c, NULL, &public2, &name2, &qname2, &handle2) >= 0);
1125 assert_se(public2 && name2 && qname2 && handle2);
1126
1127 assert_se(memcmp_nn(public, sizeof(*public), public2, sizeof(*public2)) == 0);
1128 assert_se(memcmp_nn(name->name, name->size, name2->name, name2->size) == 0);
1129 assert_se(memcmp_nn(qname->name, qname->size, qname2->name, qname2->size) == 0);
1130 }
1131
1132 #if HAVE_OPENSSL && OPENSSL_VERSION_MAJOR >= 3
1133 static void calculate_seal_and_unseal(
1134 Tpm2Context *c,
1135 TPM2_HANDLE parent_index,
1136 const TPM2B_PUBLIC *parent_public) {
1137
1138 _cleanup_free_ char *secret_string = NULL;
1139 assert_se(asprintf(&secret_string, "The classified documents are in room %x", parent_index) > 0);
1140 size_t secret_size = strlen(secret_string) + 1;
1141
1142 _cleanup_(iovec_done) struct iovec blob = {}, serialized_parent = {};
1143 assert_se(tpm2_calculate_seal(
1144 parent_index,
1145 parent_public,
1146 /* attributes= */ NULL,
1147 &IOVEC_MAKE(secret_string, secret_size),
1148 /* policy= */ NULL,
1149 /* pin= */ NULL,
1150 /* ret_secret= */ NULL,
1151 &blob,
1152 &serialized_parent) >= 0);
1153
1154 _cleanup_(iovec_done) struct iovec unsealed_secret = {};
1155 assert_se(tpm2_unseal(
1156 c,
1157 /* hash_pcr_mask= */ 0,
1158 /* pcr_bank= */ 0,
1159 /* pubkey= */ NULL,
1160 /* pubkey_pcr_mask= */ 0,
1161 /* signature= */ NULL,
1162 /* pin= */ NULL,
1163 /* pcrlock_policy= */ NULL,
1164 /* primary_alg= */ 0,
1165 &blob,
1166 /* known_policy_hash= */ NULL,
1167 &serialized_parent,
1168 &unsealed_secret) >= 0);
1169
1170 assert_se(memcmp_nn(secret_string, secret_size, unsealed_secret.iov_base, unsealed_secret.iov_len) == 0);
1171
1172 char unsealed_string[unsealed_secret.iov_len];
1173 assert_se(snprintf(unsealed_string, unsealed_secret.iov_len, "%s", (char*) unsealed_secret.iov_base) == (int) unsealed_secret.iov_len - 1);
1174 log_debug("Unsealed secret is: %s", unsealed_string);
1175 }
1176
1177 static int check_calculate_seal(Tpm2Context *c) {
1178 assert(c);
1179 int r;
1180
1181 if (detect_virtualization() == VIRTUALIZATION_NONE && !slow_tests_enabled()) {
1182 log_notice("Skipping slow calculate seal TPM2 tests. Physical system detected, and slow tests disabled.");
1183 return 0;
1184 }
1185
1186 TEST_LOG_FUNC();
1187
1188 _cleanup_free_ TPM2B_PUBLIC *srk_public = NULL;
1189 assert_se(tpm2_get_srk(c, NULL, &srk_public, NULL, NULL, NULL) >= 0);
1190 calculate_seal_and_unseal(c, TPM2_SRK_HANDLE, srk_public);
1191
1192 TPMI_ALG_ASYM test_algs[] = { TPM2_ALG_RSA, TPM2_ALG_ECC, };
1193 for (unsigned i = 0; i < ELEMENTSOF(test_algs); i++) {
1194 TPMI_ALG_ASYM alg = test_algs[i];
1195
1196 TPM2B_PUBLIC template = { .size = sizeof(TPMT_PUBLIC), };
1197 assert_se(tpm2_get_srk_template(alg, &template.publicArea) >= 0);
1198
1199 _cleanup_free_ TPM2B_PUBLIC *public = NULL;
1200 _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
1201 assert_se(tpm2_create_primary(c, NULL, &template, NULL, &public, &handle) >= 0);
1202
1203 /* Once our minimum libtss2-esys version is 2.4.0 or later, this can assume
1204 * tpm2_index_from_handle() should always work. */
1205 TPM2_HANDLE index;
1206 r = tpm2_index_from_handle(c, handle, &index);
1207 if (r == -EOPNOTSUPP)
1208 return log_tests_skipped("libtss2-esys version too old to support tpm2_index_from_handle()");
1209 assert_se(r >= 0);
1210
1211 calculate_seal_and_unseal(c, index, public);
1212 }
1213
1214 return 0;
1215 }
1216 #endif /* HAVE_OPENSSL && OPENSSL_VERSION_MAJOR >= 3 */
1217
1218 static void check_seal_unseal_for_handle(Tpm2Context *c, TPM2_HANDLE handle) {
1219 TPM2B_DIGEST policy = TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE);
1220
1221 assert(c);
1222
1223 log_debug("Check seal/unseal for handle 0x%" PRIx32, handle);
1224
1225 _cleanup_(iovec_done) struct iovec secret = {}, blob = {}, srk = {}, unsealed_secret = {};
1226 assert_se(tpm2_seal(
1227 c,
1228 handle,
1229 &policy,
1230 /* pin= */ NULL,
1231 &secret,
1232 &blob,
1233 /* ret_primary_alg= */ NULL,
1234 &srk) >= 0);
1235
1236 assert_se(tpm2_unseal(
1237 c,
1238 /* hash_pcr_mask= */ 0,
1239 /* pcr_bank= */ 0,
1240 /* pubkey= */ NULL,
1241 /* pubkey_pcr_mask= */ 0,
1242 /* signature= */ NULL,
1243 /* pin= */ NULL,
1244 /* pcrlock_policy= */ NULL,
1245 /* primary_alg= */ 0,
1246 &blob,
1247 /* policy_hash= */ NULL,
1248 &srk,
1249 &unsealed_secret) >= 0);
1250
1251 assert_se(iovec_memcmp(&secret, &unsealed_secret) == 0);
1252 }
1253
1254 static void check_seal_unseal(Tpm2Context *c) {
1255 int r;
1256
1257 assert(c);
1258
1259 if (detect_virtualization() == VIRTUALIZATION_NONE && !slow_tests_enabled()) {
1260 log_notice("Skipping slow seal/unseal TPM2 tests. Physical system detected, and slow tests disabled.");
1261 return;
1262 }
1263
1264 TEST_LOG_FUNC();
1265
1266 check_seal_unseal_for_handle(c, 0);
1267 check_seal_unseal_for_handle(c, TPM2_SRK_HANDLE);
1268
1269 FOREACH_ARRAY(template, test_templates, ELEMENTSOF(test_templates)) {
1270 TPM2B_PUBLIC public = {
1271 .publicArea = **template,
1272 .size = sizeof(**template),
1273 };
1274 _cleanup_(tpm2_handle_freep) Tpm2Handle *transient_handle = NULL;
1275 assert_se(tpm2_create_primary(
1276 c,
1277 /* session= */ NULL,
1278 &public,
1279 /* sensitive= */ NULL,
1280 /* ret_public= */ NULL,
1281 &transient_handle) >= 0);
1282
1283 TPMI_DH_PERSISTENT transient_handle_index;
1284 r = tpm2_index_from_handle(c, transient_handle, &transient_handle_index);
1285 if (r == -EOPNOTSUPP) {
1286 /* libesys too old */
1287 log_tests_skipped("libesys too old for tpm2_index_from_handle");
1288 return;
1289 }
1290 assert_se(r >= 0);
1291
1292 check_seal_unseal_for_handle(c, transient_handle_index);
1293 }
1294 }
1295
1296 TEST_RET(tests_which_require_tpm) {
1297 _cleanup_(tpm2_context_unrefp) Tpm2Context *c = NULL;
1298 int r = 0;
1299
1300 if (tpm2_context_new(NULL, &c) < 0)
1301 return log_tests_skipped("Could not find TPM");
1302
1303 check_test_parms(c);
1304 check_supports_alg(c);
1305 check_supports_command(c);
1306 check_best_srk_template(c);
1307 check_get_or_create_srk(c);
1308 check_seal_unseal(c);
1309
1310 #if HAVE_OPENSSL && OPENSSL_VERSION_MAJOR >= 3 /* calculating sealed object requires openssl >= 3 */
1311 r = check_calculate_seal(c);
1312 #endif
1313
1314 return r;
1315 }
1316
1317 #endif /* HAVE_TPM2 */
1318
1319 DEFINE_TEST_MAIN(LOG_DEBUG);