TPM_RESULT TPM_ReleaseTransportSigned(TPM_KEY_HANDLE keyHandle, TPM_NONCE *antiReplay, TPM_AUTH *auth1, TPM_AUTH *auth2, TPM_MODIFIER_INDICATOR *locality, TPM_CURRENT_TICKS *currentTicks, UINT32 *sigSize, BYTE **sig) { TPM_RESULT res; TPM_KEY_DATA *key; TPM_SESSION_DATA *session; BYTE buf[30 + 20]; info("TPM_ReleaseTransportSigned()"); /* get key */ key = tpm_get_key(keyHandle); if (key == NULL) return TPM_INVALID_KEYHANDLE; /* verify authorization */ if (auth2->authHandle != TPM_INVALID_HANDLE || key->authDataUsage != TPM_AUTH_NEVER) { res = tpm_verify_auth(auth1, key->usageAuth, keyHandle); if (res != TPM_SUCCESS) return res; session = tpm_get_transport(auth2->authHandle); if (session == NULL) return TPM_INVALID_AUTHHANDLE; res = tpm_verify_auth(auth2, session->transInternal.authData, TPM_INVALID_HANDLE); if (res != TPM_SUCCESS) return (res == TPM_AUTHFAIL) ? TPM_AUTH2FAIL : res; } else { session = tpm_get_transport(auth1->authHandle); if (session == NULL) return TPM_INVALID_AUTHHANDLE; res = tpm_verify_auth(auth1, session->transInternal.authData, TPM_INVALID_HANDLE); if (res != TPM_SUCCESS) return res; } /* invalidate transport session */ auth1->continueAuthSession = FALSE; /* logging must be enabled */ if (!(session->transInternal.transPublic.transAttributes & TPM_TRANSPORT_LOG)) return TPM_BAD_MODE; *locality = tpmData.stany.flags.localityModifier; memcpy(currentTicks, &tpmData.stany.data.currentTicks, sizeof(TPM_CURRENT_TICKS)); transport_log_out(auth1->digest, &session->transInternal.transDigest); /* setup a TPM_SIGN_INFO structure */ memcpy(&buf[0], (uint8_t*)"\x00\x05TRAN", 6); memcpy(&buf[6], antiReplay->nonce, 20); memcpy(&buf[26], (uint8_t*)"\x00\x00\x00\x14", 4); memcpy(&buf[30], session->transInternal.transDigest.digest, 20); /* sign info structure */ if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_SHA1) { tpm_sha1_ctx_t ctx; debug("TPM_SS_RSASSAPKCS1v15_SHA1"); tpm_sha1_init(&ctx); tpm_sha1_update(&ctx, buf, sizeof(buf)); tpm_sha1_final(&ctx, buf); res = tpm_sign(key, auth1, FALSE, buf, SHA1_DIGEST_LENGTH, sig, sigSize); } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_INFO) { debug("TPM_SS_RSASSAPKCS1v15_INFO"); res = tpm_sign(key, auth1, TRUE, buf, sizeof(buf), sig, sigSize); } else { debug("unsupported signature scheme: %02x", key->sigScheme); res = TPM_INVALID_KEYUSAGE; } return res; }
/* * Sign operation is performed with the private key in the TPM. */ static int tpm_key_sign(struct tpm_key *tk, struct kernel_pkey_params *params, const void *in, void *out) { struct tpm_buf *tb; uint32_t keyhandle; uint8_t srkauth[SHA1_DIGEST_SIZE]; uint8_t keyauth[SHA1_DIGEST_SIZE]; void *asn1_wrapped = NULL; uint32_t in_len = params->in_len; int r; pr_devel("==>%s()\n", __func__); if (strcmp(params->encoding, "pkcs1")) return -ENOPKG; if (params->hash_algo) { const struct asn1_template *asn1 = lookup_asn1(params->hash_algo); if (!asn1) return -ENOPKG; /* request enough space for the ASN.1 template + input hash */ asn1_wrapped = kzalloc(in_len + asn1->size, GFP_KERNEL); if (!asn1_wrapped) return -ENOMEM; /* Copy ASN.1 template, then the input */ memcpy(asn1_wrapped, asn1->data, asn1->size); memcpy(asn1_wrapped + asn1->size, in, in_len); in = asn1_wrapped; in_len += asn1->size; } if (in_len > tk->key_len / 8 - 11) { r = -EOVERFLOW; goto error_free_asn1_wrapped; } r = -ENOMEM; tb = kzalloc(sizeof(*tb), GFP_KERNEL); if (!tb) goto error_free_asn1_wrapped; /* TODO: Handle a non-all zero SRK authorization */ memset(srkauth, 0, sizeof(srkauth)); r = tpm_loadkey2(tb, SRKHANDLE, srkauth, tk->blob, tk->blob_len, &keyhandle); if (r < 0) { pr_devel("loadkey2 failed (%d)\n", r); goto error_free_tb; } /* TODO: Handle a non-all zero key authorization */ memset(keyauth, 0, sizeof(keyauth)); r = tpm_sign(tb, keyhandle, keyauth, in, in_len, out, params->out_len); if (r < 0) pr_devel("tpm_sign failed (%d)\n", r); if (tpm_flushspecific(tb, keyhandle) < 0) pr_devel("flushspecific failed (%d)\n", r); error_free_tb: kzfree(tb); error_free_asn1_wrapped: kfree(asn1_wrapped); pr_devel("<==%s() = %d\n", __func__, r); return r; }