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 /// Tpm2Sign implementation.
17 /*! \file */
18
19 #include "epid/member/tpm2/sign.h"
20 #include <stddef.h>
21 #include <string.h>
22 #include <tss2/tss.h>
23 #include "epid/common/math/finitefield.h"
24 #include "epid/common/src/epid2params.h"
25 #include "epid/common/src/hashsize.h"
26 #include "epid/common/src/memory.h"
27 #include "epid/common/types.h"
28 #include "epid/member/tpm2/getrandom.h"
29 #include "epid/member/tpm2/ibm_tss/conversion.h"
30 #include "epid/member/tpm2/ibm_tss/printtss.h"
31 #include "epid/member/tpm2/ibm_tss/state.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
39 /// Bit 7 binary mask
40 #define BIT7 0x080
41 /// Binary 00011111
42 #define BITS0500 0x3f
43
Tpm2Sign(Tpm2Ctx * ctx,void const * digest,size_t digest_len,uint16_t counter,FfElement * k,FfElement * s)44 EpidStatus Tpm2Sign(Tpm2Ctx* ctx, void const* digest, size_t digest_len,
45 uint16_t counter, FfElement* k, FfElement* s) {
46 EpidStatus sts = kEpidErr;
47 TPM_RC rc = TPM_RC_SUCCESS;
48
49 if (!ctx || !ctx->epid2_params || !digest || !s) {
50 return kEpidBadArgErr;
51 }
52 if (0 == digest_len || EpidGetHashSize(ctx->hash_alg) != digest_len) {
53 return kEpidBadArgErr;
54 }
55 if (ctx->key_handle == 0) {
56 return kEpidBadArgErr;
57 }
58
59 do {
60 TPMI_SH_AUTH_SESSION sessionHandle0 = TPM_RS_PW;
61 unsigned int sessionAttributes0 = 0;
62 Sign_In in = {0};
63 Sign_Out out;
64 FiniteField* Fp = ctx->epid2_params->Fp;
65 FpElemStr k_str;
66 FpElemStr s_str;
67 in.keyHandle = ctx->key_handle;
68 if (0 != memcpy_S(in.digest.t.buffer, sizeof(in.digest.t.buffer), digest,
69 digest_len)) {
70 sts = kEpidErr;
71 break;
72 }
73 in.digest.t.size = (uint16_t)digest_len;
74 in.inScheme.scheme = TPM_ALG_ECDAA;
75 in.inScheme.details.ecdaa.hashAlg = EpidtoTpm2HashAlg(ctx->hash_alg);
76 in.inScheme.details.ecdaa.count = counter;
77 /* proof that digest was created by the TPM (NULL ticket) */
78 /* Table 91 - Definition of TPMT_TK_HASHCHECK Structure */
79 in.validation.tag = TPM_ST_HASHCHECK;
80 in.validation.hierarchy = TPM_RH_NULL;
81 in.validation.digest.t.size = 0;
82 rc =
83 TSS_Execute(ctx->tss, (RESPONSE_PARAMETERS*)&out,
84 (COMMAND_PARAMETERS*)&in, NULL, TPM_CC_Sign, sessionHandle0,
85 NULL, sessionAttributes0, TPM_RH_NULL, NULL, 0);
86 if (rc != TPM_RC_SUCCESS) {
87 print_tpm2_response_code("TPM2_Sign", rc);
88 // workaround based on Table 2:15 to filter response code format defining
89 // handle, session, or parameter number modifier if bit 7 is 1 error is
90 // RC_FMT1
91 if ((rc & BIT7) != 0) {
92 rc = rc & (BITS0500 | RC_FMT1);
93 if (TPM_RC_VALUE == rc) {
94 sts = kEpidBadArgErr;
95 }
96 } else {
97 sts = kEpidErr;
98 }
99 break;
100 }
101
102 if (k) {
103 sts = WriteTpm2FfElement(&out.signature.signature.ecdaa.signatureR,
104 (OctStr256*)&k_str);
105 BREAK_ON_EPID_ERROR(sts);
106 sts = ReadFfElement(Fp, &k_str, sizeof(k_str), k);
107 BREAK_ON_EPID_ERROR(sts);
108 }
109
110 sts = WriteTpm2FfElement(&out.signature.signature.ecdaa.signatureS,
111 (OctStr256*)&s_str);
112 BREAK_ON_EPID_ERROR(sts);
113 sts = ReadFfElement(Fp, &s_str, sizeof(s_str), s);
114 BREAK_ON_EPID_ERROR(sts);
115 } while (0);
116 return sts;
117 }
118
Tpm2ReleaseCounter(Tpm2Ctx * ctx,uint16_t counter)119 EpidStatus Tpm2ReleaseCounter(Tpm2Ctx* ctx, uint16_t counter) {
120 EpidStatus sts = kEpidErr;
121
122 if (!ctx) {
123 return kEpidBadArgErr;
124 }
125
126 do {
127 TPM_RC rc = TPM_RC_SUCCESS;
128 TPMI_SH_AUTH_SESSION sessionHandle0 = TPM_RS_PW;
129 unsigned int sessionAttributes0 = 0;
130 Sign_In in = {0};
131 Sign_Out out;
132 in.keyHandle = ctx->key_handle;
133
134 in.digest.t.size = (uint16_t)EpidGetHashSize(ctx->hash_alg);
135 memset(in.digest.t.buffer, 0x1, (size_t)in.digest.t.size);
136 in.inScheme.scheme = TPM_ALG_ECDAA;
137 in.inScheme.details.ecdaa.hashAlg = EpidtoTpm2HashAlg(ctx->hash_alg);
138 in.inScheme.details.ecdaa.count = counter;
139 in.validation.tag = TPM_ST_HASHCHECK;
140 in.validation.hierarchy = TPM_RH_NULL;
141 in.validation.digest.t.size = 0;
142 rc =
143 TSS_Execute(ctx->tss, (RESPONSE_PARAMETERS*)&out,
144 (COMMAND_PARAMETERS*)&in, NULL, TPM_CC_Sign, sessionHandle0,
145 NULL, sessionAttributes0, TPM_RH_NULL, NULL, 0);
146 if (rc != TPM_RC_SUCCESS && (rc & (BITS0500 | RC_FMT1)) != TPM_RC_VALUE) {
147 print_tpm2_response_code("Tpm2ReleaseCounter: TPM2_Sign", rc);
148 sts = kEpidErr;
149 break;
150 }
151 sts = kEpidNoErr;
152 } while (0);
153
154 return sts;
155 }
156