• 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 /// 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