-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathtpm1_cmds.c
108 lines (86 loc) · 2.13 KB
/
tpm1_cmds.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*
* Copyright (c) 2019 Apertus Solutions, LLC
*
* Author(s):
* Daniel P. Smith <[email protected]>
*
* The code in this file is based on the article "Writing a TPM Device Driver"
* published on http://ptgmedia.pearsoncmg.com.
*
*/
#ifdef LINUX_KERNEL
#include <linux/string.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <asm/byteorder.h>
#elif defined LINUX_USERSPACE
#include <string.h>
#include <errno.h>
#endif
#include "tpm.h"
#include "tpmbuff.h"
#include "tis.h"
#include "tpm_common.h"
#include "tpm1.h"
int tpm1_pcr_extend(struct tpm *t, struct tpm_digest *d)
{
int ret = 0;
struct tpmbuff *b = t->buff;
struct tpm_header *hdr;
struct tpm_extend_cmd *cmd;
size_t size;
if (b == NULL) {
ret = -EINVAL;
goto out;
}
/* ensure buffer is free for use */
tpmb_free(b);
hdr = (struct tpm_header *)tpmb_reserve(b);
if (!hdr) {
ret = -ENOMEM;
goto out;
}
hdr->tag = cpu_to_be16(TPM_TAG_RQU_COMMAND);
hdr->code = cpu_to_be32(TPM_ORD_EXTEND);
cmd = (struct tpm_extend_cmd *)
tpmb_put(b, sizeof(struct tpm_extend_cmd));
if (cmd == NULL) {
ret = -ENOMEM;
goto free;
}
cmd->pcr_num = cpu_to_be32(d->pcr);
memcpy(&(cmd->digest), &(d->digest), sizeof(TPM_DIGEST));
hdr->size = cpu_to_be32(tpmb_size(b));
if (be32_to_cpu(hdr->size) != t->ops.send(b)) {
ret = -EAGAIN;
goto free;
}
/* Reset buffer for receive */
tpmb_trim(b, tpmb_size(b));
hdr = (struct tpm_header *)b->head;
tpmb_put(b, sizeof(struct tpm_header));
/*
* The extend receive operation returns a struct tpm_extend_resp
* but the current implementation ignores the returned PCR value.
*/
/* recv() will increase the buffer size */
size = t->ops.recv(t->family, b);
if (tpmb_size(b) != size) {
ret = -EAGAIN;
goto free;
}
/*
* On return, the code field is used for the return code out. Though
* the commands specifications section 16.1 implies there is an
* ordinal field, the return size and values point to this being
* incorrect.
*
* Also tis_recv() converts the header back to CPU endianness.
*/
if (hdr->code != TPM_SUCCESS)
ret = -EAGAIN;
free:
tpmb_free(b);
out:
return ret;
}