Prepare v2024.10
[platform/kernel/u-boot.git] / lib / tpm-v2.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2023 Linaro Limited
4  * Copyright (c) 2018 Bootlin
5  * Author: Miquel Raynal <miquel.raynal@bootlin.com>
6  */
7
8 #include <dm.h>
9 #include <dm/of_access.h>
10 #include <tpm_api.h>
11 #include <tpm-common.h>
12 #include <tpm-v2.h>
13 #include <tpm_tcg2.h>
14 #include <u-boot/sha1.h>
15 #include <u-boot/sha256.h>
16 #include <u-boot/sha512.h>
17 #include <version_string.h>
18 #include <asm/io.h>
19 #include <linux/bitops.h>
20 #include <linux/unaligned/be_byteshift.h>
21 #include <linux/unaligned/generic.h>
22 #include <linux/unaligned/le_byteshift.h>
23
24 #include "tpm-utils.h"
25
26 u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
27 {
28         const u8 command_v2[12] = {
29                 tpm_u16(TPM2_ST_NO_SESSIONS),
30                 tpm_u32(12),
31                 tpm_u32(TPM2_CC_STARTUP),
32                 tpm_u16(mode),
33         };
34         int ret;
35
36         /*
37          * Note TPM2_Startup command will return RC_SUCCESS the first time,
38          * but will return RC_INITIALIZE otherwise.
39          */
40         ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
41         if (ret && ret != TPM2_RC_INITIALIZE)
42                 return ret;
43
44         return 0;
45 }
46
47 u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test)
48 {
49         const u8 command_v2[12] = {
50                 tpm_u16(TPM2_ST_NO_SESSIONS),
51                 tpm_u32(11),
52                 tpm_u32(TPM2_CC_SELF_TEST),
53                 full_test,
54         };
55
56         return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
57 }
58
59 u32 tpm2_auto_start(struct udevice *dev)
60 {
61         u32 rc;
62
63         rc = tpm2_self_test(dev, TPMI_YES);
64
65         if (rc == TPM2_RC_INITIALIZE) {
66                 rc = tpm2_startup(dev, TPM2_SU_CLEAR);
67                 if (rc)
68                         return rc;
69
70                 rc = tpm2_self_test(dev, TPMI_YES);
71         }
72
73         return rc;
74 }
75
76 u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
77                const ssize_t pw_sz)
78 {
79         /* Length of the message header, up to start of password */
80         uint offset = 27;
81         u8 command_v2[COMMAND_BUFFER_SIZE] = {
82                 tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
83                 tpm_u32(offset + pw_sz),        /* Length */
84                 tpm_u32(TPM2_CC_CLEAR),         /* Command code */
85
86                 /* HANDLE */
87                 tpm_u32(handle),                /* TPM resource handle */
88
89                 /* AUTH_SESSION */
90                 tpm_u32(9 + pw_sz),             /* Authorization size */
91                 tpm_u32(TPM2_RS_PW),            /* Session handle */
92                 tpm_u16(0),                     /* Size of <nonce> */
93                                                 /* <nonce> (if any) */
94                 0,                              /* Attributes: Cont/Excl/Rst */
95                 tpm_u16(pw_sz),                 /* Size of <hmac/password> */
96                 /* STRING(pw)                      <hmac/password> (if any) */
97         };
98         int ret;
99
100         /*
101          * Fill the command structure starting from the first buffer:
102          *     - the password (if any)
103          */
104         ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
105                                offset, pw, pw_sz);
106         offset += pw_sz;
107         if (ret)
108                 return TPM_LIB_ERROR;
109
110         return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
111 }
112
113 u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
114                          size_t space_size, u32 nv_attributes,
115                          const u8 *nv_policy, size_t nv_policy_size)
116 {
117         /*
118          * Calculate the offset of the nv_policy piece by adding each of the
119          * chunks below.
120          */
121         const int platform_len = sizeof(u32);
122         const int session_hdr_len = 13;
123         const int message_len = 14;
124         uint offset = TPM2_HDR_LEN + platform_len + session_hdr_len +
125                 message_len;
126         u8 command_v2[COMMAND_BUFFER_SIZE] = {
127                 /* header 10 bytes */
128                 tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
129                 tpm_u32(offset + nv_policy_size + 2),/* Length */
130                 tpm_u32(TPM2_CC_NV_DEFINE_SPACE),/* Command code */
131
132                 /* handles 4 bytes */
133                 tpm_u32(TPM2_RH_PLATFORM),      /* Primary platform seed */
134
135                 /* session header 13 bytes */
136                 tpm_u32(9),                     /* Header size */
137                 tpm_u32(TPM2_RS_PW),            /* Password authorisation */
138                 tpm_u16(0),                     /* nonce_size */
139                 0,                              /* session_attrs */
140                 tpm_u16(0),                     /* auth_size */
141
142                 /* message 14 bytes + policy */
143                 tpm_u16(message_len + nv_policy_size),  /* size */
144                 tpm_u32(space_index),
145                 tpm_u16(TPM2_ALG_SHA256),
146                 tpm_u32(nv_attributes),
147                 tpm_u16(nv_policy_size),
148                 /*
149                  * nv_policy
150                  * space_size
151                  */
152         };
153         int ret;
154
155         /*
156          * Fill the command structure starting from the first buffer:
157          *     - the password (if any)
158          */
159         ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
160                                offset, nv_policy, nv_policy_size,
161                                offset + nv_policy_size, space_size);
162         if (ret)
163                 return TPM_LIB_ERROR;
164
165         return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
166 }
167
168 u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
169                     const u8 *digest, u32 digest_len)
170 {
171         /* Length of the message header, up to start of digest */
172         uint offset = 33;
173         u8 command_v2[COMMAND_BUFFER_SIZE] = {
174                 tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
175                 tpm_u32(offset + digest_len),   /* Length */
176                 tpm_u32(TPM2_CC_PCR_EXTEND),    /* Command code */
177
178                 /* HANDLE */
179                 tpm_u32(index),                 /* Handle (PCR Index) */
180
181                 /* AUTH_SESSION */
182                 tpm_u32(9),                     /* Authorization size */
183                 tpm_u32(TPM2_RS_PW),            /* Session handle */
184                 tpm_u16(0),                     /* Size of <nonce> */
185                                                 /* <nonce> (if any) */
186                 0,                              /* Attributes: Cont/Excl/Rst */
187                 tpm_u16(0),                     /* Size of <hmac/password> */
188                                                 /* <hmac/password> (if any) */
189
190                 /* hashes */
191                 tpm_u32(1),                     /* Count (number of hashes) */
192                 tpm_u16(algorithm),     /* Algorithm of the hash */
193                 /* STRING(digest)                  Digest */
194         };
195         int ret;
196
197         if (!digest)
198                 return -EINVAL;
199
200         if (!tpm2_allow_extend(dev)) {
201                 log_err("Cannot extend PCRs if all the TPM enabled algorithms are not supported\n");
202                 return -EINVAL;
203         }
204         /*
205          * Fill the command structure starting from the first buffer:
206          *     - the digest
207          */
208         ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
209                                offset, digest, digest_len);
210         if (ret)
211                 return TPM_LIB_ERROR;
212
213         return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
214 }
215
216 u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
217 {
218         u8 command_v2[COMMAND_BUFFER_SIZE] = {
219                 /* header 10 bytes */
220                 tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
221                 tpm_u32(10 + 8 + 4 + 9 + 4),    /* Length */
222                 tpm_u32(TPM2_CC_NV_READ),       /* Command code */
223
224                 /* handles 8 bytes */
225                 tpm_u32(TPM2_RH_PLATFORM),      /* Primary platform seed */
226                 tpm_u32(HR_NV_INDEX + index),   /* Password authorisation */
227
228                 /* AUTH_SESSION */
229                 tpm_u32(9),                     /* Authorization size */
230                 tpm_u32(TPM2_RS_PW),            /* Session handle */
231                 tpm_u16(0),                     /* Size of <nonce> */
232                                                 /* <nonce> (if any) */
233                 0,                              /* Attributes: Cont/Excl/Rst */
234                 tpm_u16(0),                     /* Size of <hmac/password> */
235                                                 /* <hmac/password> (if any) */
236
237                 tpm_u16(count),                 /* Number of bytes */
238                 tpm_u16(0),                     /* Offset */
239         };
240         size_t response_len = COMMAND_BUFFER_SIZE;
241         u8 response[COMMAND_BUFFER_SIZE];
242         int ret;
243         u16 tag;
244         u32 size, code;
245
246         ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
247         if (ret)
248                 return log_msg_ret("read", ret);
249         if (unpack_byte_string(response, response_len, "wdds",
250                                0, &tag, 2, &size, 6, &code,
251                                16, data, count))
252                 return TPM_LIB_ERROR;
253
254         return 0;
255 }
256
257 u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
258                         u32 count)
259 {
260         struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
261         uint offset = 10 + 8 + 4 + 9 + 2;
262         uint len = offset + count + 2;
263         /* Use empty password auth if platform hierarchy is disabled */
264         u32 auth = priv->plat_hier_disabled ? HR_NV_INDEX + index :
265                 TPM2_RH_PLATFORM;
266         u8 command_v2[COMMAND_BUFFER_SIZE] = {
267                 /* header 10 bytes */
268                 tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
269                 tpm_u32(len),                   /* Length */
270                 tpm_u32(TPM2_CC_NV_WRITE),      /* Command code */
271
272                 /* handles 8 bytes */
273                 tpm_u32(auth),                  /* Primary platform seed */
274                 tpm_u32(HR_NV_INDEX + index),   /* Password authorisation */
275
276                 /* AUTH_SESSION */
277                 tpm_u32(9),                     /* Authorization size */
278                 tpm_u32(TPM2_RS_PW),            /* Session handle */
279                 tpm_u16(0),                     /* Size of <nonce> */
280                                                 /* <nonce> (if any) */
281                 0,                              /* Attributes: Cont/Excl/Rst */
282                 tpm_u16(0),                     /* Size of <hmac/password> */
283                                                 /* <hmac/password> (if any) */
284
285                 tpm_u16(count),
286         };
287         size_t response_len = COMMAND_BUFFER_SIZE;
288         u8 response[COMMAND_BUFFER_SIZE];
289         int ret;
290
291         ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
292                                offset, data, count,
293                                offset + count, 0);
294         if (ret)
295                 return TPM_LIB_ERROR;
296
297         return tpm_sendrecv_command(dev, command_v2, response, &response_len);
298 }
299
300 u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
301                   u16 algorithm, void *data, u32 digest_len,
302                   unsigned int *updates)
303 {
304         u8 idx_array_sz = max(idx_min_sz, DIV_ROUND_UP(idx, 8));
305         u8 command_v2[COMMAND_BUFFER_SIZE] = {
306                 tpm_u16(TPM2_ST_NO_SESSIONS),   /* TAG */
307                 tpm_u32(17 + idx_array_sz),     /* Length */
308                 tpm_u32(TPM2_CC_PCR_READ),      /* Command code */
309
310                 /* TPML_PCR_SELECTION */
311                 tpm_u32(1),                     /* Number of selections */
312                 tpm_u16(algorithm),             /* Algorithm of the hash */
313                 idx_array_sz,                   /* Array size for selection */
314                 /* bitmap(idx)                     Selected PCR bitmap */
315         };
316         size_t response_len = COMMAND_BUFFER_SIZE;
317         u8 response[COMMAND_BUFFER_SIZE];
318         unsigned int pcr_sel_idx = idx / 8;
319         u8 pcr_sel_bit = BIT(idx % 8);
320         unsigned int counter = 0;
321         int ret;
322
323         if (pack_byte_string(command_v2, COMMAND_BUFFER_SIZE, "b",
324                              17 + pcr_sel_idx, pcr_sel_bit))
325                 return TPM_LIB_ERROR;
326
327         ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
328         if (ret)
329                 return ret;
330
331         if (digest_len > response_len)
332                 return TPM_LIB_ERROR;
333
334         if (unpack_byte_string(response, response_len, "ds",
335                                10, &counter,
336                                response_len - digest_len, data,
337                                digest_len))
338                 return TPM_LIB_ERROR;
339
340         if (updates)
341                 *updates = counter;
342
343         return 0;
344 }
345
346 u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
347                         void *buf, size_t prop_count)
348 {
349         u8 command_v2[COMMAND_BUFFER_SIZE] = {
350                 tpm_u16(TPM2_ST_NO_SESSIONS),           /* TAG */
351                 tpm_u32(22),                            /* Length */
352                 tpm_u32(TPM2_CC_GET_CAPABILITY),        /* Command code */
353
354                 tpm_u32(capability),                    /* Capability */
355                 tpm_u32(property),                      /* Property */
356                 tpm_u32(prop_count),                    /* Property count */
357         };
358         u8 response[COMMAND_BUFFER_SIZE];
359         size_t response_len = COMMAND_BUFFER_SIZE;
360         unsigned int properties_off;
361         int ret;
362
363         ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
364         if (ret)
365                 return ret;
366
367         /*
368          * In the response buffer, the properties are located after the:
369          * tag (u16), response size (u32), response code (u32),
370          * YES/NO flag (u8), TPM_CAP (u32).
371          */
372         properties_off = sizeof(u16) + sizeof(u32) + sizeof(u32) +
373                          sizeof(u8) + sizeof(u32);
374         memcpy(buf, &response[properties_off], response_len - properties_off);
375
376         return 0;
377 }
378
379 static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
380 {
381         u8 response[(sizeof(struct tpms_capability_data) -
382                 offsetof(struct tpms_capability_data, data))];
383         u32 properties_offset =
384                 offsetof(struct tpml_tagged_tpm_property, tpm_property) +
385                 offsetof(struct tpms_tagged_property, value);
386         u32 ret;
387
388         memset(response, 0, sizeof(response));
389         ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
390                                   TPM2_PT_PCR_COUNT, response, 1);
391         if (ret)
392                 return ret;
393
394         *num_pcr = get_unaligned_be32(response + properties_offset);
395         if (*num_pcr > TPM2_MAX_PCRS) {
396                 printf("%s: too many pcrs: %u\n", __func__, *num_pcr);
397                 return -E2BIG;
398         }
399
400         return 0;
401 }
402
403 int tpm2_get_pcr_info(struct udevice *dev, struct tpml_pcr_selection *pcrs)
404 {
405         u8 response[(sizeof(struct tpms_capability_data) -
406                 offsetof(struct tpms_capability_data, data))];
407         u32 num_pcr;
408         size_t i;
409         u32 ret;
410
411         ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
412         if (ret)
413                 return ret;
414
415         pcrs->count = get_unaligned_be32(response);
416         /*
417          * We only support 4 algorithms for now so check against that
418          * instead of TPM2_NUM_PCR_BANKS
419          */
420         if (pcrs->count > 4 || pcrs->count < 1) {
421                 printf("%s: too many pcrs: %u\n", __func__, pcrs->count);
422                 return -EMSGSIZE;
423         }
424
425         ret = tpm2_get_num_pcr(dev, &num_pcr);
426         if (ret)
427                 return ret;
428
429         for (i = 0; i < pcrs->count; i++) {
430                 /*
431                  * Definition of TPMS_PCR_SELECTION Structure
432                  * hash: u16
433                  * size_of_select: u8
434                  * pcr_select: u8 array
435                  *
436                  * The offsets depend on the number of the device PCRs
437                  * so we have to calculate them based on that
438                  */
439                 u32 hash_offset = offsetof(struct tpml_pcr_selection, selection) +
440                         i * offsetof(struct tpms_pcr_selection, pcr_select) +
441                         i * ((num_pcr + 7) / 8);
442                 u32 size_select_offset =
443                         hash_offset + offsetof(struct tpms_pcr_selection,
444                                                size_of_select);
445                 u32 pcr_select_offset =
446                         hash_offset + offsetof(struct tpms_pcr_selection,
447                                                pcr_select);
448
449                 pcrs->selection[i].hash =
450                         get_unaligned_be16(response + hash_offset);
451                 pcrs->selection[i].size_of_select =
452                         __get_unaligned_be(response + size_select_offset);
453                 if (pcrs->selection[i].size_of_select > TPM2_PCR_SELECT_MAX) {
454                         printf("%s: pcrs selection too large: %u\n", __func__,
455                                pcrs->selection[i].size_of_select);
456                         return -ENOBUFS;
457                 }
458                 /* copy the array of pcr_select */
459                 memcpy(pcrs->selection[i].pcr_select, response + pcr_select_offset,
460                        pcrs->selection[i].size_of_select);
461         }
462
463         return 0;
464 }
465
466 u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz)
467 {
468         u8 command_v2[COMMAND_BUFFER_SIZE] = {
469                 tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
470                 tpm_u32(27 + pw_sz),            /* Length */
471                 tpm_u32(TPM2_CC_DAM_RESET),     /* Command code */
472
473                 /* HANDLE */
474                 tpm_u32(TPM2_RH_LOCKOUT),       /* TPM resource handle */
475
476                 /* AUTH_SESSION */
477                 tpm_u32(9 + pw_sz),             /* Authorization size */
478                 tpm_u32(TPM2_RS_PW),            /* Session handle */
479                 tpm_u16(0),                     /* Size of <nonce> */
480                                                 /* <nonce> (if any) */
481                 0,                              /* Attributes: Cont/Excl/Rst */
482                 tpm_u16(pw_sz),                 /* Size of <hmac/password> */
483                 /* STRING(pw)                      <hmac/password> (if any) */
484         };
485         unsigned int offset = 27;
486         int ret;
487
488         /*
489          * Fill the command structure starting from the first buffer:
490          *     - the password (if any)
491          */
492         ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
493                                offset, pw, pw_sz);
494         offset += pw_sz;
495         if (ret)
496                 return TPM_LIB_ERROR;
497
498         return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
499 }
500
501 u32 tpm2_dam_parameters(struct udevice *dev, const char *pw,
502                         const ssize_t pw_sz, unsigned int max_tries,
503                         unsigned int recovery_time,
504                         unsigned int lockout_recovery)
505 {
506         u8 command_v2[COMMAND_BUFFER_SIZE] = {
507                 tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
508                 tpm_u32(27 + pw_sz + 12),       /* Length */
509                 tpm_u32(TPM2_CC_DAM_PARAMETERS), /* Command code */
510
511                 /* HANDLE */
512                 tpm_u32(TPM2_RH_LOCKOUT),       /* TPM resource handle */
513
514                 /* AUTH_SESSION */
515                 tpm_u32(9 + pw_sz),             /* Authorization size */
516                 tpm_u32(TPM2_RS_PW),            /* Session handle */
517                 tpm_u16(0),                     /* Size of <nonce> */
518                                                 /* <nonce> (if any) */
519                 0,                              /* Attributes: Cont/Excl/Rst */
520                 tpm_u16(pw_sz),                 /* Size of <hmac/password> */
521                 /* STRING(pw)                      <hmac/password> (if any) */
522
523                 /* LOCKOUT PARAMETERS */
524                 /* tpm_u32(max_tries)              Max tries (0, always lock) */
525                 /* tpm_u32(recovery_time)          Recovery time (0, no lock) */
526                 /* tpm_u32(lockout_recovery)       Lockout recovery */
527         };
528         unsigned int offset = 27;
529         int ret;
530
531         /*
532          * Fill the command structure starting from the first buffer:
533          *     - the password (if any)
534          *     - max tries
535          *     - recovery time
536          *     - lockout recovery
537          */
538         ret = pack_byte_string(command_v2, sizeof(command_v2), "sddd",
539                                offset, pw, pw_sz,
540                                offset + pw_sz, max_tries,
541                                offset + pw_sz + 4, recovery_time,
542                                offset + pw_sz + 8, lockout_recovery);
543         offset += pw_sz + 12;
544         if (ret)
545                 return TPM_LIB_ERROR;
546
547         return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
548 }
549
550 int tpm2_change_auth(struct udevice *dev, u32 handle, const char *newpw,
551                      const ssize_t newpw_sz, const char *oldpw,
552                      const ssize_t oldpw_sz)
553 {
554         unsigned int offset = 27;
555         u8 command_v2[COMMAND_BUFFER_SIZE] = {
556                 tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
557                 tpm_u32(offset + oldpw_sz + 2 + newpw_sz), /* Length */
558                 tpm_u32(TPM2_CC_HIERCHANGEAUTH), /* Command code */
559
560                 /* HANDLE */
561                 tpm_u32(handle),                /* TPM resource handle */
562
563                 /* AUTH_SESSION */
564                 tpm_u32(9 + oldpw_sz),          /* Authorization size */
565                 tpm_u32(TPM2_RS_PW),            /* Session handle */
566                 tpm_u16(0),                     /* Size of <nonce> */
567                                                 /* <nonce> (if any) */
568                 0,                              /* Attributes: Cont/Excl/Rst */
569                 tpm_u16(oldpw_sz)               /* Size of <hmac/password> */
570                 /* STRING(oldpw)                   <hmac/password> (if any) */
571
572                 /* TPM2B_AUTH (TPM2B_DIGEST) */
573                 /* tpm_u16(newpw_sz)               Digest size, new pw length */
574                 /* STRING(newpw)                   Digest buffer, new pw */
575         };
576         int ret;
577
578         /*
579          * Fill the command structure starting from the first buffer:
580          *     - the old password (if any)
581          *     - size of the new password
582          *     - new password
583          */
584         ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
585                                offset, oldpw, oldpw_sz,
586                                offset + oldpw_sz, newpw_sz,
587                                offset + oldpw_sz + 2, newpw, newpw_sz);
588         offset += oldpw_sz + 2 + newpw_sz;
589         if (ret)
590                 return TPM_LIB_ERROR;
591
592         return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
593 }
594
595 u32 tpm2_pcr_setauthpolicy(struct udevice *dev, const char *pw,
596                            const ssize_t pw_sz, u32 index, const char *key)
597 {
598         u8 command_v2[COMMAND_BUFFER_SIZE] = {
599                 tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
600                 tpm_u32(35 + pw_sz + TPM2_DIGEST_LEN), /* Length */
601                 tpm_u32(TPM2_CC_PCR_SETAUTHPOL), /* Command code */
602
603                 /* HANDLE */
604                 tpm_u32(TPM2_RH_PLATFORM),      /* TPM resource handle */
605
606                 /* AUTH_SESSION */
607                 tpm_u32(9 + pw_sz),             /* Authorization size */
608                 tpm_u32(TPM2_RS_PW),            /* session handle */
609                 tpm_u16(0),                     /* Size of <nonce> */
610                                                 /* <nonce> (if any) */
611                 0,                              /* Attributes: Cont/Excl/Rst */
612                 tpm_u16(pw_sz)                  /* Size of <hmac/password> */
613                 /* STRING(pw)                      <hmac/password> (if any) */
614
615                 /* TPM2B_AUTH (TPM2B_DIGEST) */
616                 /* tpm_u16(TPM2_DIGEST_LEN)        Digest size length */
617                 /* STRING(key)                     Digest buffer (PCR key) */
618
619                 /* TPMI_ALG_HASH */
620                 /* tpm_u16(TPM2_ALG_SHA256)   Algorithm of the hash */
621
622                 /* TPMI_DH_PCR */
623                 /* tpm_u32(index),                 PCR Index */
624         };
625         unsigned int offset = 27;
626         int ret;
627
628         /*
629          * Fill the command structure starting from the first buffer:
630          *     - the password (if any)
631          *     - the PCR key length
632          *     - the PCR key
633          *     - the hash algorithm
634          *     - the PCR index
635          */
636         ret = pack_byte_string(command_v2, sizeof(command_v2), "swswd",
637                                offset, pw, pw_sz,
638                                offset + pw_sz, TPM2_DIGEST_LEN,
639                                offset + pw_sz + 2, key, TPM2_DIGEST_LEN,
640                                offset + pw_sz + 2 + TPM2_DIGEST_LEN,
641                                TPM2_ALG_SHA256,
642                                offset + pw_sz + 4 + TPM2_DIGEST_LEN, index);
643         offset += pw_sz + 2 + TPM2_DIGEST_LEN + 2 + 4;
644         if (ret)
645                 return TPM_LIB_ERROR;
646
647         return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
648 }
649
650 u32 tpm2_pcr_setauthvalue(struct udevice *dev, const char *pw,
651                           const ssize_t pw_sz, u32 index, const char *key,
652                           const ssize_t key_sz)
653 {
654         u8 command_v2[COMMAND_BUFFER_SIZE] = {
655                 tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
656                 tpm_u32(33 + pw_sz + TPM2_DIGEST_LEN), /* Length */
657                 tpm_u32(TPM2_CC_PCR_SETAUTHVAL), /* Command code */
658
659                 /* HANDLE */
660                 tpm_u32(index),                 /* Handle (PCR Index) */
661
662                 /* AUTH_SESSION */
663                 tpm_u32(9 + pw_sz),             /* Authorization size */
664                 tpm_u32(TPM2_RS_PW),            /* session handle */
665                 tpm_u16(0),                     /* Size of <nonce> */
666                                                 /* <nonce> (if any) */
667                 0,                              /* Attributes: Cont/Excl/Rst */
668                 tpm_u16(pw_sz),                 /* Size of <hmac/password> */
669                 /* STRING(pw)                      <hmac/password> (if any) */
670
671                 /* TPM2B_DIGEST */
672                 /* tpm_u16(key_sz)                 Key length */
673                 /* STRING(key)                     Key */
674         };
675         unsigned int offset = 27;
676         int ret;
677
678         /*
679          * Fill the command structure starting from the first buffer:
680          *     - the password (if any)
681          *     - the number of digests, 1 in our case
682          *     - the algorithm, sha256 in our case
683          *     - the digest (64 bytes)
684          */
685         ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
686                                offset, pw, pw_sz,
687                                offset + pw_sz, key_sz,
688                                offset + pw_sz + 2, key, key_sz);
689         offset += pw_sz + 2 + key_sz;
690         if (ret)
691                 return TPM_LIB_ERROR;
692
693         return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
694 }
695
696 u32 tpm2_get_random(struct udevice *dev, void *data, u32 count)
697 {
698         const u8 command_v2[10] = {
699                 tpm_u16(TPM2_ST_NO_SESSIONS),
700                 tpm_u32(12),
701                 tpm_u32(TPM2_CC_GET_RANDOM),
702         };
703         u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
704
705         const size_t data_size_offset = 10;
706         const size_t data_offset = 12;
707         size_t response_length = sizeof(response);
708         u32 data_size;
709         u8 *out = data;
710
711         while (count > 0) {
712                 u32 this_bytes = min((size_t)count,
713                                      sizeof(response) - data_offset);
714                 u32 err;
715
716                 if (pack_byte_string(buf, sizeof(buf), "sw",
717                                      0, command_v2, sizeof(command_v2),
718                                      sizeof(command_v2), this_bytes))
719                         return TPM_LIB_ERROR;
720                 err = tpm_sendrecv_command(dev, buf, response,
721                                            &response_length);
722                 if (err)
723                         return err;
724                 if (unpack_byte_string(response, response_length, "w",
725                                        data_size_offset, &data_size))
726                         return TPM_LIB_ERROR;
727                 if (data_size > this_bytes)
728                         return TPM_LIB_ERROR;
729                 if (unpack_byte_string(response, response_length, "s",
730                                        data_offset, out, data_size))
731                         return TPM_LIB_ERROR;
732
733                 count -= data_size;
734                 out += data_size;
735         }
736
737         return 0;
738 }
739
740 u32 tpm2_write_lock(struct udevice *dev, u32 index)
741 {
742         u8 command_v2[COMMAND_BUFFER_SIZE] = {
743                 /* header 10 bytes */
744                 tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
745                 tpm_u32(10 + 8 + 13), /* Length */
746                 tpm_u32(TPM2_CC_NV_WRITELOCK), /* Command code */
747
748                 /* handles 8 bytes */
749                 tpm_u32(TPM2_RH_PLATFORM),      /* Primary platform seed */
750                 tpm_u32(HR_NV_INDEX + index),   /* Password authorisation */
751
752                 /* session header 9 bytes */
753                 tpm_u32(9),                     /* Header size */
754                 tpm_u32(TPM2_RS_PW),            /* Password authorisation */
755                 tpm_u16(0),                     /* nonce_size */
756                 0,                              /* session_attrs */
757                 tpm_u16(0),                     /* auth_size */
758         };
759
760         return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
761 }
762
763 u32 tpm2_disable_platform_hierarchy(struct udevice *dev)
764 {
765         struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
766         u8 command_v2[COMMAND_BUFFER_SIZE] = {
767                 /* header 10 bytes */
768                 tpm_u16(TPM2_ST_SESSIONS),      /* TAG */
769                 tpm_u32(10 + 4 + 13 + 5),       /* Length */
770                 tpm_u32(TPM2_CC_HIER_CONTROL),  /* Command code */
771
772                 /* 4 bytes */
773                 tpm_u32(TPM2_RH_PLATFORM),      /* Primary platform seed */
774
775                 /* session header 9 bytes */
776                 tpm_u32(9),                     /* Header size */
777                 tpm_u32(TPM2_RS_PW),            /* Password authorisation */
778                 tpm_u16(0),                     /* nonce_size */
779                 0,                              /* session_attrs */
780                 tpm_u16(0),                     /* auth_size */
781
782                 /* payload 5 bytes */
783                 tpm_u32(TPM2_RH_PLATFORM),      /* Hierarchy to disable */
784                 0,                              /* 0=disable */
785         };
786         int ret;
787
788         ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
789         log_info("ret=%s, %x\n", dev->name, ret);
790         if (ret)
791                 return ret;
792
793         priv->plat_hier_disabled = true;
794
795         return 0;
796 }
797
798 u32 tpm2_submit_command(struct udevice *dev, const u8 *sendbuf,
799                         u8 *recvbuf, size_t *recv_size)
800 {
801         return tpm_sendrecv_command(dev, sendbuf, recvbuf, recv_size);
802 }
803
804 u32 tpm2_report_state(struct udevice *dev, uint vendor_cmd, uint vendor_subcmd,
805                       u8 *recvbuf, size_t *recv_size)
806 {
807         u8 command_v2[COMMAND_BUFFER_SIZE] = {
808                 /* header 10 bytes */
809                 tpm_u16(TPM2_ST_NO_SESSIONS),           /* TAG */
810                 tpm_u32(10 + 2),                        /* Length */
811                 tpm_u32(vendor_cmd),    /* Command code */
812
813                 tpm_u16(vendor_subcmd),
814         };
815         int ret;
816
817         ret = tpm_sendrecv_command(dev, command_v2, recvbuf, recv_size);
818         log_debug("ret=%s, %x\n", dev->name, ret);
819         if (ret)
820                 return ret;
821         if (*recv_size < 12)
822                 return -ENODATA;
823         *recv_size -= 12;
824         memcpy(recvbuf, recvbuf + 12, *recv_size);
825
826         return 0;
827 }
828
829 u32 tpm2_enable_nvcommits(struct udevice *dev, uint vendor_cmd,
830                           uint vendor_subcmd)
831 {
832         u8 command_v2[COMMAND_BUFFER_SIZE] = {
833                 /* header 10 bytes */
834                 tpm_u16(TPM2_ST_NO_SESSIONS),           /* TAG */
835                 tpm_u32(10 + 2),                        /* Length */
836                 tpm_u32(vendor_cmd),    /* Command code */
837
838                 tpm_u16(vendor_subcmd),
839         };
840         int ret;
841
842         ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
843         log_debug("ret=%s, %x\n", dev->name, ret);
844         if (ret)
845                 return ret;
846
847         return 0;
848 }
849
850 bool tpm2_is_active_pcr(struct tpms_pcr_selection *selection)
851 {
852         int i;
853
854         for (i = 0; i < selection->size_of_select; i++) {
855                 if (selection->pcr_select[i])
856                         return true;
857         }
858
859         return false;
860 }
861
862 enum tpm2_algorithms tpm2_name_to_algorithm(const char *name)
863 {
864         size_t i;
865
866         for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
867                 if (!strcasecmp(name, hash_algo_list[i].hash_name))
868                         return hash_algo_list[i].hash_alg;
869         }
870         printf("%s: unsupported algorithm %s\n", __func__, name);
871
872         return -EINVAL;
873 }
874
875 const char *tpm2_algorithm_name(enum tpm2_algorithms algo)
876 {
877         size_t i;
878
879         for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
880                 if (hash_algo_list[i].hash_alg == algo)
881                         return hash_algo_list[i].hash_name;
882         }
883
884         return "";
885 }
886
887 u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo)
888 {
889         size_t i;
890
891         for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
892                 if (hash_algo_list[i].hash_alg == algo)
893                         return hash_algo_list[i].hash_len;
894         }
895
896         return 0;
897 }
898
899 bool tpm2_allow_extend(struct udevice *dev)
900 {
901         struct tpml_pcr_selection pcrs;
902         size_t i;
903         int rc;
904
905         rc = tpm2_get_pcr_info(dev, &pcrs);
906         if (rc)
907                 return false;
908
909         for (i = 0; i < pcrs.count; i++) {
910                 if (tpm2_is_active_pcr(&pcrs.selection[i]) &&
911                     !tpm2_algorithm_to_len(pcrs.selection[i].hash))
912                         return false;
913         }
914
915         return true;
916 }