• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2004 IBM Corporation
4  * Copyright (C) 2014 Intel Corporation
5  */
6 
7 #include <linux/string.h>
8 #include <linux/err.h>
9 #include <linux/tpm.h>
10 #include <linux/tpm_command.h>
11 
12 #include <keys/trusted-type.h>
13 #include <keys/trusted_tpm.h>
14 
15 static struct tpm2_hash tpm2_hash_map[] = {
16 	{HASH_ALGO_SHA1, TPM_ALG_SHA1},
17 	{HASH_ALGO_SHA256, TPM_ALG_SHA256},
18 	{HASH_ALGO_SHA384, TPM_ALG_SHA384},
19 	{HASH_ALGO_SHA512, TPM_ALG_SHA512},
20 	{HASH_ALGO_SM3_256, TPM_ALG_SM3_256},
21 };
22 
23 /**
24  * tpm_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer.
25  *
26  * @buf: an allocated tpm_buf instance
27  * @session_handle: session handle
28  * @nonce: the session nonce, may be NULL if not used
29  * @nonce_len: the session nonce length, may be 0 if not used
30  * @attributes: the session attributes
31  * @hmac: the session HMAC or password, may be NULL if not used
32  * @hmac_len: the session HMAC or password length, maybe 0 if not used
33  */
tpm2_buf_append_auth(struct tpm_buf * buf,u32 session_handle,const u8 * nonce,u16 nonce_len,u8 attributes,const u8 * hmac,u16 hmac_len)34 static void tpm2_buf_append_auth(struct tpm_buf *buf, u32 session_handle,
35 				 const u8 *nonce, u16 nonce_len,
36 				 u8 attributes,
37 				 const u8 *hmac, u16 hmac_len)
38 {
39 	tpm_buf_append_u32(buf, 9 + nonce_len + hmac_len);
40 	tpm_buf_append_u32(buf, session_handle);
41 	tpm_buf_append_u16(buf, nonce_len);
42 
43 	if (nonce && nonce_len)
44 		tpm_buf_append(buf, nonce, nonce_len);
45 
46 	tpm_buf_append_u8(buf, attributes);
47 	tpm_buf_append_u16(buf, hmac_len);
48 
49 	if (hmac && hmac_len)
50 		tpm_buf_append(buf, hmac, hmac_len);
51 }
52 
53 /**
54  * tpm2_seal_trusted() - seal the payload of a trusted key
55  *
56  * @chip: TPM chip to use
57  * @payload: the key data in clear and encrypted form
58  * @options: authentication values and other options
59  *
60  * Return: < 0 on error and 0 on success.
61  */
tpm2_seal_trusted(struct tpm_chip * chip,struct trusted_key_payload * payload,struct trusted_key_options * options)62 int tpm2_seal_trusted(struct tpm_chip *chip,
63 		      struct trusted_key_payload *payload,
64 		      struct trusted_key_options *options)
65 {
66 	unsigned int blob_len;
67 	struct tpm_buf buf;
68 	u32 hash;
69 	int i;
70 	int rc;
71 
72 	for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) {
73 		if (options->hash == tpm2_hash_map[i].crypto_id) {
74 			hash = tpm2_hash_map[i].tpm_id;
75 			break;
76 		}
77 	}
78 
79 	if (i == ARRAY_SIZE(tpm2_hash_map))
80 		return -EINVAL;
81 
82 	rc = tpm_try_get_ops(chip);
83 	if (rc)
84 		return rc;
85 
86 	rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
87 	if (rc) {
88 		tpm_put_ops(chip);
89 		return rc;
90 	}
91 
92 	tpm_buf_append_u32(&buf, options->keyhandle);
93 	tpm2_buf_append_auth(&buf, TPM2_RS_PW,
94 			     NULL /* nonce */, 0,
95 			     0 /* session_attributes */,
96 			     options->keyauth /* hmac */,
97 			     TPM_DIGEST_SIZE);
98 
99 	/* sensitive */
100 	tpm_buf_append_u16(&buf, 4 + options->blobauth_len + payload->key_len + 1);
101 
102 	tpm_buf_append_u16(&buf, options->blobauth_len);
103 	if (options->blobauth_len)
104 		tpm_buf_append(&buf, options->blobauth, options->blobauth_len);
105 
106 	tpm_buf_append_u16(&buf, payload->key_len + 1);
107 	tpm_buf_append(&buf, payload->key, payload->key_len);
108 	tpm_buf_append_u8(&buf, payload->migratable);
109 
110 	/* public */
111 	tpm_buf_append_u16(&buf, 14 + options->policydigest_len);
112 	tpm_buf_append_u16(&buf, TPM_ALG_KEYEDHASH);
113 	tpm_buf_append_u16(&buf, hash);
114 
115 	/* policy */
116 	if (options->policydigest_len) {
117 		tpm_buf_append_u32(&buf, 0);
118 		tpm_buf_append_u16(&buf, options->policydigest_len);
119 		tpm_buf_append(&buf, options->policydigest,
120 			       options->policydigest_len);
121 	} else {
122 		tpm_buf_append_u32(&buf, TPM2_OA_USER_WITH_AUTH);
123 		tpm_buf_append_u16(&buf, 0);
124 	}
125 
126 	/* public parameters */
127 	tpm_buf_append_u16(&buf, TPM_ALG_NULL);
128 	tpm_buf_append_u16(&buf, 0);
129 
130 	/* outside info */
131 	tpm_buf_append_u16(&buf, 0);
132 
133 	/* creation PCR */
134 	tpm_buf_append_u32(&buf, 0);
135 
136 	if (buf.flags & TPM_BUF_OVERFLOW) {
137 		rc = -E2BIG;
138 		goto out;
139 	}
140 
141 	rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data");
142 	if (rc)
143 		goto out;
144 
145 	blob_len = be32_to_cpup((__be32 *) &buf.data[TPM_HEADER_SIZE]);
146 	if (blob_len > MAX_BLOB_SIZE) {
147 		rc = -E2BIG;
148 		goto out;
149 	}
150 	if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + 4 + blob_len) {
151 		rc = -EFAULT;
152 		goto out;
153 	}
154 
155 	memcpy(payload->blob, &buf.data[TPM_HEADER_SIZE + 4], blob_len);
156 	payload->blob_len = blob_len;
157 
158 out:
159 	tpm_buf_destroy(&buf);
160 
161 	if (rc > 0) {
162 		if (tpm2_rc_value(rc) == TPM2_RC_HASH)
163 			rc = -EINVAL;
164 		else
165 			rc = -EPERM;
166 	}
167 
168 	tpm_put_ops(chip);
169 	return rc;
170 }
171 
172 /**
173  * tpm2_load_cmd() - execute a TPM2_Load command
174  *
175  * @chip: TPM chip to use
176  * @payload: the key data in clear and encrypted form
177  * @options: authentication values and other options
178  * @blob_handle: returned blob handle
179  *
180  * Return: 0 on success.
181  *        -E2BIG on wrong payload size.
182  *        -EPERM on tpm error status.
183  *        < 0 error from tpm_send.
184  */
tpm2_load_cmd(struct tpm_chip * chip,struct trusted_key_payload * payload,struct trusted_key_options * options,u32 * blob_handle)185 static int tpm2_load_cmd(struct tpm_chip *chip,
186 			 struct trusted_key_payload *payload,
187 			 struct trusted_key_options *options,
188 			 u32 *blob_handle)
189 {
190 	struct tpm_buf buf;
191 	unsigned int private_len;
192 	unsigned int public_len;
193 	unsigned int blob_len;
194 	int rc;
195 
196 	private_len = be16_to_cpup((__be16 *) &payload->blob[0]);
197 	if (private_len > (payload->blob_len - 2))
198 		return -E2BIG;
199 
200 	public_len = be16_to_cpup((__be16 *) &payload->blob[2 + private_len]);
201 	blob_len = private_len + public_len + 4;
202 	if (blob_len > payload->blob_len)
203 		return -E2BIG;
204 
205 	rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
206 	if (rc)
207 		return rc;
208 
209 	tpm_buf_append_u32(&buf, options->keyhandle);
210 	tpm2_buf_append_auth(&buf, TPM2_RS_PW,
211 			     NULL /* nonce */, 0,
212 			     0 /* session_attributes */,
213 			     options->keyauth /* hmac */,
214 			     TPM_DIGEST_SIZE);
215 
216 	tpm_buf_append(&buf, payload->blob, blob_len);
217 
218 	if (buf.flags & TPM_BUF_OVERFLOW) {
219 		rc = -E2BIG;
220 		goto out;
221 	}
222 
223 	rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob");
224 	if (!rc)
225 		*blob_handle = be32_to_cpup(
226 			(__be32 *) &buf.data[TPM_HEADER_SIZE]);
227 
228 out:
229 	tpm_buf_destroy(&buf);
230 
231 	if (rc > 0)
232 		rc = -EPERM;
233 
234 	return rc;
235 }
236 
237 /**
238  * tpm2_unseal_cmd() - execute a TPM2_Unload command
239  *
240  * @chip: TPM chip to use
241  * @payload: the key data in clear and encrypted form
242  * @options: authentication values and other options
243  * @blob_handle: blob handle
244  *
245  * Return: 0 on success
246  *         -EPERM on tpm error status
247  *         < 0 error from tpm_send
248  */
tpm2_unseal_cmd(struct tpm_chip * chip,struct trusted_key_payload * payload,struct trusted_key_options * options,u32 blob_handle)249 static int tpm2_unseal_cmd(struct tpm_chip *chip,
250 			   struct trusted_key_payload *payload,
251 			   struct trusted_key_options *options,
252 			   u32 blob_handle)
253 {
254 	struct tpm_buf buf;
255 	u16 data_len;
256 	u8 *data;
257 	int rc;
258 
259 	rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
260 	if (rc)
261 		return rc;
262 
263 	tpm_buf_append_u32(&buf, blob_handle);
264 	tpm2_buf_append_auth(&buf,
265 			     options->policyhandle ?
266 			     options->policyhandle : TPM2_RS_PW,
267 			     NULL /* nonce */, 0,
268 			     TPM2_SA_CONTINUE_SESSION,
269 			     options->blobauth /* hmac */,
270 			     options->blobauth_len);
271 
272 	rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing");
273 	if (rc > 0)
274 		rc = -EPERM;
275 
276 	if (!rc) {
277 		data_len = be16_to_cpup(
278 			(__be16 *) &buf.data[TPM_HEADER_SIZE + 4]);
279 		if (data_len < MIN_KEY_SIZE ||  data_len > MAX_KEY_SIZE + 1) {
280 			rc = -EFAULT;
281 			goto out;
282 		}
283 
284 		if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + 6 + data_len) {
285 			rc = -EFAULT;
286 			goto out;
287 		}
288 		data = &buf.data[TPM_HEADER_SIZE + 6];
289 
290 		memcpy(payload->key, data, data_len - 1);
291 		payload->key_len = data_len - 1;
292 		payload->migratable = data[data_len - 1];
293 	}
294 
295 out:
296 	tpm_buf_destroy(&buf);
297 	return rc;
298 }
299 
300 /**
301  * tpm2_unseal_trusted() - unseal the payload of a trusted key
302  *
303  * @chip: TPM chip to use
304  * @payload: the key data in clear and encrypted form
305  * @options: authentication values and other options
306  *
307  * Return: Same as with tpm_send.
308  */
tpm2_unseal_trusted(struct tpm_chip * chip,struct trusted_key_payload * payload,struct trusted_key_options * options)309 int tpm2_unseal_trusted(struct tpm_chip *chip,
310 			struct trusted_key_payload *payload,
311 			struct trusted_key_options *options)
312 {
313 	u32 blob_handle;
314 	int rc;
315 
316 	rc = tpm_try_get_ops(chip);
317 	if (rc)
318 		return rc;
319 
320 	rc = tpm2_load_cmd(chip, payload, options, &blob_handle);
321 	if (rc)
322 		goto out;
323 
324 	rc = tpm2_unseal_cmd(chip, payload, options, blob_handle);
325 	tpm2_flush_context(chip, blob_handle);
326 
327 out:
328 	tpm_put_ops(chip);
329 
330 	return rc;
331 }
332