/*############################################################################ # Copyright 2017 Intel Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ############################################################################*/ /*! * \file * \brief TPM2_LoadExternal command implementation. */ #include "epid/member/tpm2/load_external.h" #include "epid/common/math/ecgroup.h" #include "epid/common/src/epid2params.h" #include "epid/common/src/memory.h" #include "epid/member/tpm2/ibm_tss/conversion.h" #include "epid/member/tpm2/ibm_tss/printtss.h" #include "epid/member/tpm2/ibm_tss/state.h" #include "tss2/TPM_Types.h" #include "tss2/tss.h" /// Handle Intel(R) EPID Error with Break #define BREAK_ON_EPID_ERROR(ret) \ if (kEpidNoErr != (ret)) { \ break; \ } EpidStatus Tpm2LoadExternal(Tpm2Ctx* ctx, FpElemStr const* f_str) { EpidStatus sts = kEpidErr; TPM_RC rc = TPM_RC_SUCCESS; EcPoint* pub = NULL; FfElement* f = NULL; TPMI_ALG_HASH tpm_hash_alg = TPM_ALG_NULL; if (!ctx || !ctx->epid2_params || !f_str) { return kEpidBadArgErr; } do { LoadExternal_In in = {0}; LoadExternal_Out out; G1ElemStr pub_str = {0}; TPMS_ECC_PARMS* ecc_details = &in.inPublic.publicArea.parameters.eccDetail; EcGroup* G1 = ctx->epid2_params->G1; EcPoint* g1 = ctx->epid2_params->g1; sts = NewFfElement(ctx->epid2_params->Fp, &f); BREAK_ON_EPID_ERROR(sts); // verify that f is valid sts = ReadFfElement(ctx->epid2_params->Fp, f_str, sizeof(*f_str), f); BREAK_ON_EPID_ERROR(sts); if (ctx->key_handle) { FlushContext_In in_fc; in_fc.flushHandle = ctx->key_handle; TSS_Execute(ctx->tss, NULL, (COMMAND_PARAMETERS*)&in_fc, NULL, TPM_CC_FlushContext, TPM_RH_NULL, NULL, 0); if (rc != TPM_RC_SUCCESS) { print_tpm2_response_code("TPM2_FlushContext", rc); } ctx->key_handle = 0; } sts = NewEcPoint(G1, &pub); BREAK_ON_EPID_ERROR(sts); sts = EcExp(G1, g1, (BigNumStr const*)f_str, pub); BREAK_ON_EPID_ERROR(sts); sts = WriteEcPoint(G1, pub, &pub_str, sizeof(pub_str)); BREAK_ON_EPID_ERROR(sts); tpm_hash_alg = EpidtoTpm2HashAlg(ctx->hash_alg); if (tpm_hash_alg == TPM_ALG_NULL) { sts = kEpidHashAlgorithmNotSupported; break; } in.hierarchy = TPM_RH_NULL; in.inPublic.size = sizeof(TPM2B_PUBLIC); in.inPublic.publicArea.type = TPM_ALG_ECC; in.inPublic.publicArea.nameAlg = tpm_hash_alg; in.inPublic.publicArea.objectAttributes.val = TPMA_OBJECT_NODA | TPMA_OBJECT_USERWITHAUTH | TPMA_OBJECT_SIGN; in.inPublic.publicArea.authPolicy.t.size = 0; ecc_details->symmetric.algorithm = TPM_ALG_NULL; ecc_details->scheme.scheme = TPM_ALG_ECDAA; ecc_details->scheme.details.ecdaa.hashAlg = tpm_hash_alg; ecc_details->scheme.details.ecdaa.count = 0; ecc_details->curveID = TPM_ECC_BN_P256; ecc_details->kdf.scheme = TPM_ALG_NULL; sts = ReadTpm2FfElement(&pub_str.x.data, &in.inPublic.publicArea.unique.ecc.x); BREAK_ON_EPID_ERROR(sts); sts = ReadTpm2FfElement(&pub_str.y.data, &in.inPublic.publicArea.unique.ecc.y); BREAK_ON_EPID_ERROR(sts); in.inPrivate.t.size = sizeof(in.inPrivate.t.sensitiveArea); in.inPrivate.t.sensitiveArea.sensitiveType = TPM_ALG_ECC; sts = ReadTpm2FfElement(&f_str->data, &in.inPrivate.t.sensitiveArea.sensitive.ecc); BREAK_ON_EPID_ERROR(sts); rc = TSS_Execute(ctx->tss, (RESPONSE_PARAMETERS*)&out, (COMMAND_PARAMETERS*)&in, NULL, TPM_CC_LoadExternal, TPM_RH_NULL, NULL, 0); if (rc != TPM_RC_SUCCESS) { print_tpm2_response_code("TPM2_LoadExternal", rc); if (TPM_RC_BINDING == rc || TPM_RC_ECC_POINT == rc || TPM_RC_KEY_SIZE == rc) sts = kEpidBadArgErr; else sts = kEpidErr; break; } ctx->key_handle = out.objectHandle; } while (0); DeleteEcPoint(&pub); DeleteFfElement(&f); return sts; }