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