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 */ 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 */ 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_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE); 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 + TPM_DIGEST_SIZE + payload->key_len + 1); 101 102 tpm_buf_append_u16(&buf, TPM_DIGEST_SIZE); 103 tpm_buf_append(&buf, options->blobauth, TPM_DIGEST_SIZE); 104 tpm_buf_append_u16(&buf, payload->key_len + 1); 105 tpm_buf_append(&buf, payload->key, payload->key_len); 106 tpm_buf_append_u8(&buf, payload->migratable); 107 108 /* public */ 109 tpm_buf_append_u16(&buf, 14 + options->policydigest_len); 110 tpm_buf_append_u16(&buf, TPM_ALG_KEYEDHASH); 111 tpm_buf_append_u16(&buf, hash); 112 113 /* policy */ 114 if (options->policydigest_len) { 115 tpm_buf_append_u32(&buf, 0); 116 tpm_buf_append_u16(&buf, options->policydigest_len); 117 tpm_buf_append(&buf, options->policydigest, 118 options->policydigest_len); 119 } else { 120 tpm_buf_append_u32(&buf, TPM2_OA_USER_WITH_AUTH); 121 tpm_buf_append_u16(&buf, 0); 122 } 123 124 /* public parameters */ 125 tpm_buf_append_u16(&buf, TPM_ALG_NULL); 126 tpm_buf_append_u16(&buf, 0); 127 128 /* outside info */ 129 tpm_buf_append_u16(&buf, 0); 130 131 /* creation PCR */ 132 tpm_buf_append_u32(&buf, 0); 133 134 if (buf.flags & TPM_BUF_OVERFLOW) { 135 rc = -E2BIG; 136 goto out; 137 } 138 139 rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data"); 140 if (rc) 141 goto out; 142 143 blob_len = be32_to_cpup((__be32 *) &buf.data[TPM_HEADER_SIZE]); 144 if (blob_len > MAX_BLOB_SIZE) { 145 rc = -E2BIG; 146 goto out; 147 } 148 if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + 4 + blob_len) { 149 rc = -EFAULT; 150 goto out; 151 } 152 153 memcpy(payload->blob, &buf.data[TPM_HEADER_SIZE + 4], blob_len); 154 payload->blob_len = blob_len; 155 156 out: 157 tpm_buf_destroy(&buf); 158 159 if (rc > 0) { 160 if (tpm2_rc_value(rc) == TPM2_RC_HASH) 161 rc = -EINVAL; 162 else 163 rc = -EPERM; 164 } 165 166 tpm_put_ops(chip); 167 return rc; 168 } 169 170 /** 171 * tpm2_load_cmd() - execute a TPM2_Load command 172 * 173 * @chip: TPM chip to use 174 * @payload: the key data in clear and encrypted form 175 * @options: authentication values and other options 176 * @blob_handle: returned blob handle 177 * 178 * Return: 0 on success. 179 * -E2BIG on wrong payload size. 180 * -EPERM on tpm error status. 181 * < 0 error from tpm_send. 182 */ 183 static int tpm2_load_cmd(struct tpm_chip *chip, 184 struct trusted_key_payload *payload, 185 struct trusted_key_options *options, 186 u32 *blob_handle) 187 { 188 struct tpm_buf buf; 189 unsigned int private_len; 190 unsigned int public_len; 191 unsigned int blob_len; 192 int rc; 193 194 private_len = be16_to_cpup((__be16 *) &payload->blob[0]); 195 if (private_len > (payload->blob_len - 2)) 196 return -E2BIG; 197 198 public_len = be16_to_cpup((__be16 *) &payload->blob[2 + private_len]); 199 blob_len = private_len + public_len + 4; 200 if (blob_len > payload->blob_len) 201 return -E2BIG; 202 203 rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD); 204 if (rc) 205 return rc; 206 207 tpm_buf_append_u32(&buf, options->keyhandle); 208 tpm2_buf_append_auth(&buf, TPM2_RS_PW, 209 NULL /* nonce */, 0, 210 0 /* session_attributes */, 211 options->keyauth /* hmac */, 212 TPM_DIGEST_SIZE); 213 214 tpm_buf_append(&buf, payload->blob, blob_len); 215 216 if (buf.flags & TPM_BUF_OVERFLOW) { 217 rc = -E2BIG; 218 goto out; 219 } 220 221 rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob"); 222 if (!rc) 223 *blob_handle = be32_to_cpup( 224 (__be32 *) &buf.data[TPM_HEADER_SIZE]); 225 226 out: 227 tpm_buf_destroy(&buf); 228 229 if (rc > 0) 230 rc = -EPERM; 231 232 return rc; 233 } 234 235 /** 236 * tpm2_unseal_cmd() - execute a TPM2_Unload command 237 * 238 * @chip: TPM chip to use 239 * @payload: the key data in clear and encrypted form 240 * @options: authentication values and other options 241 * @blob_handle: blob handle 242 * 243 * Return: 0 on success 244 * -EPERM on tpm error status 245 * < 0 error from tpm_send 246 */ 247 static int tpm2_unseal_cmd(struct tpm_chip *chip, 248 struct trusted_key_payload *payload, 249 struct trusted_key_options *options, 250 u32 blob_handle) 251 { 252 struct tpm_buf buf; 253 u16 data_len; 254 u8 *data; 255 int rc; 256 257 rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL); 258 if (rc) 259 return rc; 260 261 tpm_buf_append_u32(&buf, blob_handle); 262 tpm2_buf_append_auth(&buf, 263 options->policyhandle ? 264 options->policyhandle : TPM2_RS_PW, 265 NULL /* nonce */, 0, 266 TPM2_SA_CONTINUE_SESSION, 267 options->blobauth /* hmac */, 268 TPM_DIGEST_SIZE); 269 270 rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing"); 271 if (rc > 0) 272 rc = -EPERM; 273 274 if (!rc) { 275 data_len = be16_to_cpup( 276 (__be16 *) &buf.data[TPM_HEADER_SIZE + 4]); 277 if (data_len < MIN_KEY_SIZE || data_len > MAX_KEY_SIZE + 1) { 278 rc = -EFAULT; 279 goto out; 280 } 281 282 if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + 6 + data_len) { 283 rc = -EFAULT; 284 goto out; 285 } 286 data = &buf.data[TPM_HEADER_SIZE + 6]; 287 288 memcpy(payload->key, data, data_len - 1); 289 payload->key_len = data_len - 1; 290 payload->migratable = data[data_len - 1]; 291 } 292 293 out: 294 tpm_buf_destroy(&buf); 295 return rc; 296 } 297 298 /** 299 * tpm2_unseal_trusted() - unseal the payload of a trusted key 300 * 301 * @chip: TPM chip to use 302 * @payload: the key data in clear and encrypted form 303 * @options: authentication values and other options 304 * 305 * Return: Same as with tpm_send. 306 */ 307 int tpm2_unseal_trusted(struct tpm_chip *chip, 308 struct trusted_key_payload *payload, 309 struct trusted_key_options *options) 310 { 311 u32 blob_handle; 312 int rc; 313 314 rc = tpm_try_get_ops(chip); 315 if (rc) 316 return rc; 317 318 rc = tpm2_load_cmd(chip, payload, options, &blob_handle); 319 if (rc) 320 goto out; 321 322 rc = tpm2_unseal_cmd(chip, payload, options, blob_handle); 323 tpm2_flush_context(chip, blob_handle); 324 325 out: 326 tpm_put_ops(chip); 327 328 return rc; 329 } 330