• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*############################################################################
2 # Copyright 2017 Intel Corporation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 ############################################################################*/
16 
17 /*!
18  * \file
19  * \brief TPM2_LoadExternal command implementation.
20  */
21 
22 #include "epid/member/tpm2/load_external.h"
23 
24 #include "epid/common/math/ecgroup.h"
25 #include "epid/common/src/epid2params.h"
26 #include "epid/common/src/memory.h"
27 #include "epid/member/tpm2/ibm_tss/conversion.h"
28 #include "epid/member/tpm2/ibm_tss/printtss.h"
29 #include "epid/member/tpm2/ibm_tss/state.h"
30 #include "tss2/TPM_Types.h"
31 #include "tss2/tss.h"
32 
33 /// Handle Intel(R) EPID Error with Break
34 #define BREAK_ON_EPID_ERROR(ret) \
35   if (kEpidNoErr != (ret)) {     \
36     break;                       \
37   }
38 
Tpm2LoadExternal(Tpm2Ctx * ctx,FpElemStr const * f_str)39 EpidStatus Tpm2LoadExternal(Tpm2Ctx* ctx, FpElemStr const* f_str) {
40   EpidStatus sts = kEpidErr;
41   TPM_RC rc = TPM_RC_SUCCESS;
42   EcPoint* pub = NULL;
43   FfElement* f = NULL;
44   TPMI_ALG_HASH tpm_hash_alg = TPM_ALG_NULL;
45 
46   if (!ctx || !ctx->epid2_params || !f_str) {
47     return kEpidBadArgErr;
48   }
49 
50   do {
51     LoadExternal_In in = {0};
52     LoadExternal_Out out;
53     G1ElemStr pub_str = {0};
54     TPMS_ECC_PARMS* ecc_details = &in.inPublic.publicArea.parameters.eccDetail;
55     EcGroup* G1 = ctx->epid2_params->G1;
56     EcPoint* g1 = ctx->epid2_params->g1;
57 
58     sts = NewFfElement(ctx->epid2_params->Fp, &f);
59     BREAK_ON_EPID_ERROR(sts);
60     // verify that f is valid
61     sts = ReadFfElement(ctx->epid2_params->Fp, f_str, sizeof(*f_str), f);
62     BREAK_ON_EPID_ERROR(sts);
63     if (ctx->key_handle) {
64       FlushContext_In in_fc;
65       in_fc.flushHandle = ctx->key_handle;
66       TSS_Execute(ctx->tss, NULL, (COMMAND_PARAMETERS*)&in_fc, NULL,
67                   TPM_CC_FlushContext, TPM_RH_NULL, NULL, 0);
68       if (rc != TPM_RC_SUCCESS) {
69         print_tpm2_response_code("TPM2_FlushContext", rc);
70       }
71       ctx->key_handle = 0;
72     }
73 
74     sts = NewEcPoint(G1, &pub);
75     BREAK_ON_EPID_ERROR(sts);
76 
77     sts = EcExp(G1, g1, (BigNumStr const*)f_str, pub);
78     BREAK_ON_EPID_ERROR(sts);
79 
80     sts = WriteEcPoint(G1, pub, &pub_str, sizeof(pub_str));
81     BREAK_ON_EPID_ERROR(sts);
82 
83     tpm_hash_alg = EpidtoTpm2HashAlg(ctx->hash_alg);
84     if (tpm_hash_alg == TPM_ALG_NULL) {
85       sts = kEpidHashAlgorithmNotSupported;
86       break;
87     }
88 
89     in.hierarchy = TPM_RH_NULL;
90     in.inPublic.size = sizeof(TPM2B_PUBLIC);
91     in.inPublic.publicArea.type = TPM_ALG_ECC;
92     in.inPublic.publicArea.nameAlg = tpm_hash_alg;
93     in.inPublic.publicArea.objectAttributes.val =
94         TPMA_OBJECT_NODA | TPMA_OBJECT_USERWITHAUTH | TPMA_OBJECT_SIGN;
95     in.inPublic.publicArea.authPolicy.t.size = 0;
96 
97     ecc_details->symmetric.algorithm = TPM_ALG_NULL;
98     ecc_details->scheme.scheme = TPM_ALG_ECDAA;
99     ecc_details->scheme.details.ecdaa.hashAlg = tpm_hash_alg;
100     ecc_details->scheme.details.ecdaa.count = 0;
101     ecc_details->curveID = TPM_ECC_BN_P256;
102     ecc_details->kdf.scheme = TPM_ALG_NULL;
103 
104     sts = ReadTpm2FfElement(&pub_str.x.data,
105                             &in.inPublic.publicArea.unique.ecc.x);
106     BREAK_ON_EPID_ERROR(sts);
107     sts = ReadTpm2FfElement(&pub_str.y.data,
108                             &in.inPublic.publicArea.unique.ecc.y);
109     BREAK_ON_EPID_ERROR(sts);
110 
111     in.inPrivate.t.size = sizeof(in.inPrivate.t.sensitiveArea);
112     in.inPrivate.t.sensitiveArea.sensitiveType = TPM_ALG_ECC;
113     sts = ReadTpm2FfElement(&f_str->data,
114                             &in.inPrivate.t.sensitiveArea.sensitive.ecc);
115     BREAK_ON_EPID_ERROR(sts);
116 
117     rc = TSS_Execute(ctx->tss, (RESPONSE_PARAMETERS*)&out,
118                      (COMMAND_PARAMETERS*)&in, NULL, TPM_CC_LoadExternal,
119                      TPM_RH_NULL, NULL, 0);
120     if (rc != TPM_RC_SUCCESS) {
121       print_tpm2_response_code("TPM2_LoadExternal", rc);
122       if (TPM_RC_BINDING == rc || TPM_RC_ECC_POINT == rc ||
123           TPM_RC_KEY_SIZE == rc)
124         sts = kEpidBadArgErr;
125       else
126         sts = kEpidErr;
127       break;
128     }
129 
130     ctx->key_handle = out.objectHandle;
131   } while (0);
132 
133   DeleteEcPoint(&pub);
134   DeleteFfElement(&f);
135 
136   return sts;
137 }
138