u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle, const void *usage_auth, void *pubkey, size_t *pubkey_len) { const u8 command[14] = { 0x00, 0xc2, /* TPM_TAG */ 0x00, 0x00, 0x00, 0x00, /* parameter size */ 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */ 0x00, 0x00, 0x00, 0x00, /* key handle */ }; const size_t req_size_offset = 2; const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH; const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH; u8 request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH]; u8 response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH + TPM_RESPONSE_AUTH_LENGTH]; size_t response_length = sizeof(response); u32 err; if (!oiap_session.valid) { err = tpm_oiap(dev, NULL); if (err) return err; } if (pack_byte_string(request, sizeof(request), "sdd", 0, command, sizeof(command), req_size_offset, (u32)(sizeof(command) + TPM_REQUEST_AUTH_LENGTH), req_key_handle_offset, key_handle )) return TPM_LIB_ERROR; err = create_request_auth(request, sizeof(command), 4, &oiap_session, request + sizeof(command), usage_auth); if (err) return err; err = tpm_sendrecv_command(dev, request, response, &response_length); if (err) { if (err == TPM_AUTHFAIL) oiap_session.valid = 0; return err; } err = verify_response_auth(0x00000021, response, response_length - TPM_RESPONSE_AUTH_LENGTH, 0, &oiap_session, response + response_length - TPM_RESPONSE_AUTH_LENGTH, usage_auth); if (err) return err; if (pubkey) { if ((response_length - TPM_RESPONSE_HEADER_LENGTH - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len) return TPM_LIB_ERROR; *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH - TPM_RESPONSE_AUTH_LENGTH; memcpy(pubkey, response + res_pubkey_offset, response_length - TPM_RESPONSE_HEADER_LENGTH - TPM_RESPONSE_AUTH_LENGTH); } return 0; }
static uint32_t _tpm_wrap_unseal(uint32_t locality, const uint8_t *in_data, uint32_t *secret_size, uint8_t *secret) { uint32_t ret; tpm_nonce_t odd_osap, even_osap; tpm_nonce_t nonce_even, nonce_odd, nonce_even_d, nonce_odd_d; tpm_authhandle_t hauth, hauth_d; tpm_authdata_t shared_secret; tpm_authdata_t pub_auth, res_auth, pub_auth_d, res_auth_d; uint8_t cont_session = false, cont_session_d = false; tpm_key_handle_t hkey = TPM_KH_SRK; uint32_t offset; uint32_t ordinal = TPM_ORD_UNSEAL; tpm_digest_t digest; /* skip generate nonce for odd_osap, just use the random value in stack */ /* establish a osap session */ ret = tpm_osap(locality, TPM_ET_SRK, TPM_KH_SRK, &odd_osap, &hauth, &nonce_even, &even_osap); if ( ret != TPM_SUCCESS ) return ret; /* calculate the shared secret shared-secret = HMAC(auth, even_osap || odd_osap) */ offset = 0; UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &even_osap); UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &odd_osap); HMAC_SHA1((uint8_t *)&srk_authdata, sizeof(srk_authdata), WRAPPER_IN_BUF, offset, (uint8_t *)&shared_secret); /* establish a oiap session */ ret = tpm_oiap(locality, &hauth_d, &nonce_even_d); if ( ret != TPM_SUCCESS ) return ret; /* skip generate nonce_odd & nonce_odd_d, just use the random values */ /* calculate authdata */ /* in_param_digest = sha1(1S ~ 6S) */ offset = 0; UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, ordinal); UNLOAD_STORED_DATA12(WRAPPER_IN_BUF, offset, in_data); sha1_buffer(WRAPPER_IN_BUF, offset, (uint8_t *)&digest); /* authdata1 = hmac(key, in_param_digest || auth_params1) */ offset = 0; UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &digest); UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &nonce_even); UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &nonce_odd); UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, cont_session); HMAC_SHA1((uint8_t *)&shared_secret, sizeof(shared_secret), WRAPPER_IN_BUF, offset, (uint8_t *)&pub_auth); /* authdata2 = hmac(key, in_param_digest || auth_params2) */ offset = 0; UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &digest); UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &nonce_even_d); UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &nonce_odd_d); UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, cont_session_d); HMAC_SHA1((uint8_t *)&blob_authdata, sizeof(blob_authdata), WRAPPER_IN_BUF, offset, (uint8_t *)&pub_auth_d); /* call the simple seal function */ ret = _tpm_unseal(locality, hkey, in_data, hauth, &nonce_odd, &cont_session, (const tpm_authdata_t *)&pub_auth, hauth_d, &nonce_odd_d, &cont_session_d, (const tpm_authdata_t *)&pub_auth_d, secret_size, secret, &nonce_even, &res_auth, &nonce_even_d, &res_auth_d); /* skip check for res_auth */ return ret; }
u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key, size_t key_length, const void *parent_key_usage_auth, u32 *key_handle) { const u8 command[14] = { 0x00, 0xc2, /* TPM_TAG */ 0x00, 0x00, 0x00, 0x00, /* parameter size */ 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */ 0x00, 0x00, 0x00, 0x00, /* parent handle */ }; const size_t req_size_offset = 2; const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH; const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4; const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH; u8 request[sizeof(command) + TPM_KEY12_MAX_LENGTH + TPM_REQUEST_AUTH_LENGTH]; u8 response[COMMAND_BUFFER_SIZE]; size_t response_length = sizeof(response); u32 err; if (!oiap_session.valid) { err = tpm_oiap(dev, NULL); if (err) return err; } if (pack_byte_string(request, sizeof(request), "sdds", 0, command, sizeof(command), req_size_offset, sizeof(command) + key_length + TPM_REQUEST_AUTH_LENGTH, req_parent_handle_offset, parent_handle, req_key_offset, key, key_length )) return TPM_LIB_ERROR; err = create_request_auth(request, sizeof(command) + key_length, 4, &oiap_session, request + sizeof(command) + key_length, parent_key_usage_auth); if (err) return err; err = tpm_sendrecv_command(dev, request, response, &response_length); if (err) { if (err == TPM_AUTHFAIL) oiap_session.valid = 0; return err; } err = verify_response_auth(0x00000041, response, response_length - TPM_RESPONSE_AUTH_LENGTH, 4, &oiap_session, response + response_length - TPM_RESPONSE_AUTH_LENGTH, parent_key_usage_auth); if (err) return err; if (key_handle) { if (unpack_byte_string(response, response_length, "d", res_handle_offset, key_handle)) return TPM_LIB_ERROR; } return 0; }