Coverage Report

Created: 2025-07-12 06:35

/src/ibmswtpm2/src/SymmetricCommands.c
Line
Count
Source (jump to first uncovered line)
1
/********************************************************************************/
2
/*                    */
3
/*            Symmetric Commands        */
4
/*           Written by Ken Goldman       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*            $Id: SymmetricCommands.c 1259 2018-07-10 19:11:09Z kgoldman $ */
7
/*                    */
8
/*  Licenses and Notices              */
9
/*                    */
10
/*  1. Copyright Licenses:              */
11
/*                    */
12
/*  - Trusted Computing Group (TCG) grants to the user of the source code in  */
13
/*    this specification (the "Source Code") a worldwide, irrevocable,    */
14
/*    nonexclusive, royalty free, copyright license to reproduce, create  */
15
/*    derivative works, distribute, display and perform the Source Code and */
16
/*    derivative works thereof, and to grant others the rights granted herein.  */
17
/*                    */
18
/*  - The TCG grants to the user of the other parts of the specification  */
19
/*    (other than the Source Code) the rights to reproduce, distribute,   */
20
/*    display, and perform the specification solely for the purpose of    */
21
/*    developing products based on such documents.        */
22
/*                    */
23
/*  2. Source Code Distribution Conditions:         */
24
/*                    */
25
/*  - Redistributions of Source Code must retain the above copyright licenses,  */
26
/*    this list of conditions and the following disclaimers.      */
27
/*                    */
28
/*  - Redistributions in binary form must reproduce the above copyright   */
29
/*    licenses, this list of conditions and the following disclaimers in the  */
30
/*    documentation and/or other materials provided with the distribution.  */
31
/*                    */
32
/*  3. Disclaimers:               */
33
/*                    */
34
/*  - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
35
/*  LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
36
/*  RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
37
/*  THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.   */
38
/*  Contact TCG Administration (admin@trustedcomputinggroup.org) for    */
39
/*  information on specification licensing rights available through TCG   */
40
/*  membership agreements.              */
41
/*                    */
42
/*  - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED   */
43
/*    WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR   */
44
/*    FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR    */
45
/*    NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY    */
46
/*    OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE.   */
47
/*                    */
48
/*  - Without limitation, TCG and its members and licensors disclaim all  */
49
/*    liability, including liability for infringement of any proprietary  */
50
/*    rights, relating to use of information in this specification and to the */
51
/*    implementation of this specification, and TCG disclaims all liability for */
52
/*    cost of procurement of substitute goods or services, lost profits, loss   */
53
/*    of use, loss of data or any incidental, consequential, direct, indirect,  */
54
/*    or special damages, whether under contract, tort, warranty or otherwise,  */
55
/*    arising in any way out of use or reliance upon this specification or any  */
56
/*    information herein.             */
57
/*                    */
58
/*  (c) Copyright IBM Corp. and others, 2016 - 2018       */
59
/*                    */
60
/********************************************************************************/
61
62
#include "Tpm.h"
63
#include "EncryptDecrypt_fp.h"
64
#if CC_EncryptDecrypt2
65
#include  "EncryptDecrypt_spt_fp.h"
66
#endif
67
#if CC_EncryptDecrypt  // Conditional expansion of this file
68
TPM_RC
69
TPM2_EncryptDecrypt(
70
        EncryptDecrypt_In   *in,            // IN: input parameter list
71
        EncryptDecrypt_Out  *out            // OUT: output parameter list
72
        )
73
0
{
74
0
#if CC_EncryptDecrypt2
75
0
    return EncryptDecryptShared(in->keyHandle, in->decrypt, in->mode,
76
0
        &in->ivIn, &in->inData, out);
77
#else
78
    OBJECT              *symKey;
79
    UINT16               keySize;
80
    UINT16               blockSize;
81
    BYTE                *key;
82
    TPM_ALG_ID           alg;
83
    TPM_ALG_ID           mode;
84
    TPM_RC               result;
85
    BOOL                 OK;
86
    TPMA_OBJECT          attributes;
87
    // Input Validation
88
    symKey = HandleToObject(in->keyHandle);
89
    mode = symKey->publicArea.parameters.symDetail.sym.mode.sym;
90
    attributes = symKey->publicArea.objectAttributes;
91
    // The input key should be a symmetric key
92
    if(symKey->publicArea.type != TPM_ALG_SYMCIPHER)
93
  return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle; 
94
    // The key must be unrestricted and allow the selected operation
95
    OK = IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)
96
     if(YES == in->decrypt)
97
   OK = OK && IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt);
98
     else
99
   OK = OK && IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign);
100
    if(!OK)
101
  return TPM_RCS_ATTRIBUTES + RC_EncryptDecrypt_keyHandle;
102
    // If the key mode is not TPM_ALG_NULL...
103
    // or TPM_ALG_NULL
104
    if(mode != TPM_ALG_NULL)
105
  {
106
      // then the input mode has to be TPM_ALG_NULL or the same as the key
107
      if((in->mode != TPM_ALG_NULL) && (in->mode != mode))
108
    return TPM_RCS_MODE + RC_EncryptDecrypt_mode;
109
  }
110
    else
111
  {
112
      // if the key mode is null, then the input can't be null
113
      if(in->mode == TPM_ALG_NULL)
114
    return TPM_RCS_MODE + RC_EncryptDecrypt_mode;
115
      mode = in->mode;
116
  }
117
    // The input iv for ECB mode should be an Empty Buffer.  All the other modes
118
    // should have an iv size same as encryption block size
119
    keySize = symKey->publicArea.parameters.symDetail.sym.keyBits.sym;
120
    alg = symKey->publicArea.parameters.symDetail.sym.algorithm;
121
    blockSize = CryptGetSymmetricBlockSize(alg, keySize);
122
    // reverify the algorithm. This is mainly to keep static analysis tools happy
123
    if(blockSize == 0)
124
  return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle;
125
    // Note: When an algorithm is not supported by a TPM, the TPM_ALG_xxx for that
126
    // algorithm is not defined. However, it is assumed that the ALG_xxx_VALUE for
127
    // the algorithm is always defined. Both have the same numeric value.
128
    // ALG_xxx_VALUE is used here so that the code does not get cluttered with
129
    // #ifdef's. Having this check does not mean that the algorithm is supported.
130
    // If it was not supported the unmarshaling code would have rejected it before
131
    // this function were called. This means that, depending on the implementation,
132
    // the check could be redundant but it doesn't hurt.
133
    if(((mode == ALG_ECB_VALUE) && (in->ivIn.t.size != 0))
134
       || ((mode != ALG_ECB_VALUE) && (in->ivIn.t.size != blockSize)))
135
  return TPM_RCS_SIZE + RC_EncryptDecrypt_ivIn;
136
    // The input data size of CBC mode or ECB mode must be an even multiple of
137
    // the symmetric algorithm's block size
138
    if(((mode == ALG_CBC_VALUE) || (mode == ALG_ECB_VALUE))
139
       && ((in->inData.t.size % blockSize) != 0))
140
  return TPM_RCS_SIZE + RC_EncryptDecrypt_inData;
141
    // Copy IV
142
    // Note: This is copied here so that the calls to the encrypt/decrypt functions
143
    // will modify the output buffer, not the input buffer
144
    out->ivOut = in->ivIn;
145
    // Command Output
146
    key = symKey->sensitive.sensitive.sym.t.buffer;
147
    // For symmetric encryption, the cipher data size is the same as plain data
148
    // size.
149
    out->outData.t.size = in->inData.t.size;
150
    if(in->decrypt == YES)
151
  {
152
      // Decrypt data to output
153
      result = CryptSymmetricDecrypt(out->outData.t.buffer, alg, keySize, key,
154
             &(out->ivOut), mode, in->inData.t.size,
155
             in->inData.t.buffer);
156
  }
157
    else
158
  {
159
      // Encrypt data to output
160
      result = CryptSymmetricEncrypt(out->outData.t.buffer, alg, keySize, key,
161
             &(out->ivOut), mode, in->inData.t.size,
162
             in->inData.t.buffer);
163
  }
164
    return result;
165
#endif // CC_EncryptDecrypt2
166
0
}
167
#endif // CC_EncryptDecrypt
168
#include "Tpm.h"
169
#include "EncryptDecrypt2_fp.h"
170
#include "EncryptDecrypt_spt_fp.h"
171
#if CC_EncryptDecrypt2  // Conditional expansion of this file
172
TPM_RC
173
TPM2_EncryptDecrypt2(
174
         EncryptDecrypt2_In   *in,            // IN: input parameter list
175
         EncryptDecrypt2_Out  *out            // OUT: output parameter list
176
         )
177
0
{
178
0
    TPM_RC                result;
179
    // EncryptDecyrptShared() performs the operations as shown in
180
    // TPM2_EncrypDecrypt
181
0
    result = EncryptDecryptShared(in->keyHandle, in->decrypt, in->mode,
182
0
          &in->ivIn, &in->inData,
183
0
          (EncryptDecrypt_Out *)out);
184
    // Handle response code swizzle.
185
0
    switch(result)
186
0
  {
187
0
    case TPM_RCS_MODE + RC_EncryptDecrypt_mode:
188
0
      result = TPM_RCS_MODE + RC_EncryptDecrypt2_mode;
189
0
      break;
190
0
    case TPM_RCS_SIZE + RC_EncryptDecrypt_ivIn:
191
0
      result = TPM_RCS_SIZE + RC_EncryptDecrypt2_ivIn;
192
0
      break;
193
0
    case TPM_RCS_SIZE + RC_EncryptDecrypt_inData:
194
0
      result = TPM_RCS_SIZE + RC_EncryptDecrypt2_inData;
195
0
      break;
196
0
    default:
197
0
      break;
198
0
  }
199
0
    return result;
200
0
}
201
#endif // CC_EncryptDecrypt2
202
#include "Tpm.h"
203
#include "Hash_fp.h"
204
#if CC_Hash  // Conditional expansion of this file
205
TPM_RC
206
TPM2_Hash(
207
    Hash_In         *in,            // IN: input parameter list
208
    Hash_Out        *out            // OUT: output parameter list
209
    )
210
0
{
211
0
    HASH_STATE          hashState;
212
    // Command Output
213
    // Output hash
214
    // Start hash stack
215
0
    out->outHash.t.size = CryptHashStart(&hashState, in->hashAlg);
216
    // Adding hash data
217
0
    CryptDigestUpdate2B(&hashState, &in->data.b);
218
    // Complete hash
219
0
    CryptHashEnd2B(&hashState, &out->outHash.b);
220
    // Output ticket
221
0
    out->validation.tag = TPM_ST_HASHCHECK;
222
0
    out->validation.hierarchy = in->hierarchy;
223
0
    if(in->hierarchy == TPM_RH_NULL)
224
0
  {
225
      // Ticket is not required
226
0
      out->validation.hierarchy = TPM_RH_NULL;
227
0
      out->validation.digest.t.size = 0;
228
0
  }
229
0
    else if(in->data.t.size >= sizeof(TPM_GENERATED)
230
0
      && !TicketIsSafe(&in->data.b))
231
0
  {
232
      // Ticket is not safe
233
0
      out->validation.hierarchy = TPM_RH_NULL;
234
0
      out->validation.digest.t.size = 0;
235
0
  }
236
0
    else
237
0
  {
238
      // Compute ticket
239
0
      TicketComputeHashCheck(in->hierarchy, in->hashAlg,
240
0
           &out->outHash, &out->validation);
241
0
  }
242
0
    return TPM_RC_SUCCESS;
243
0
}
244
#endif // CC_Hash
245
#include "Tpm.h"
246
#include "HMAC_fp.h"
247
#if CC_HMAC  // Conditional expansion of this file
248
TPM_RC
249
TPM2_HMAC(
250
    HMAC_In         *in,            // IN: input parameter list
251
    HMAC_Out        *out            // OUT: output parameter list
252
    )
253
{
254
    HMAC_STATE               hmacState;
255
    OBJECT                  *hmacObject;
256
    TPMI_ALG_HASH            hashAlg;
257
    TPMT_PUBLIC             *publicArea;
258
    // Input Validation
259
    // Get HMAC key object and public area pointers
260
    hmacObject = HandleToObject(in->handle);
261
    publicArea = &hmacObject->publicArea;
262
    // Make sure that the key is an HMAC key
263
    if(publicArea->type != TPM_ALG_KEYEDHASH)
264
  return TPM_RCS_TYPE + RC_HMAC_handle;
265
    // and that it is unrestricted
266
    if (IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
267
  return TPM_RCS_ATTRIBUTES + RC_HMAC_handle;
268
    // and that it is a signing key
269
    if (!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
270
  return TPM_RCS_KEY + RC_HMAC_handle;
271
    // See if the key has a default
272
    if(publicArea->parameters.keyedHashDetail.scheme.scheme == TPM_ALG_NULL)
273
  // it doesn't so use the input value
274
  hashAlg = in->hashAlg;
275
    else
276
  {
277
      // key has a default so use it
278
      hashAlg
279
    = publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg;
280
      // and verify that the input was either the  TPM_ALG_NULL or the default
281
      if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg)
282
    hashAlg = TPM_ALG_NULL;
283
  }
284
    // if we ended up without a hash algorithm then return an error
285
    if(hashAlg == TPM_ALG_NULL)
286
  return TPM_RCS_VALUE + RC_HMAC_hashAlg;
287
    // Command Output
288
    // Start HMAC stack
289
    out->outHMAC.t.size = CryptHmacStart2B(&hmacState, hashAlg,
290
             &hmacObject->sensitive.sensitive.bits.b);
291
    // Adding HMAC data
292
    CryptDigestUpdate2B(&hmacState.hashState, &in->buffer.b);
293
    // Complete HMAC
294
    CryptHmacEnd2B(&hmacState, &out->outHMAC.b);
295
    return TPM_RC_SUCCESS;
296
}
297
#endif // CC_HMAC
298
299
#include "Tpm.h"
300
#include "MAC_fp.h"
301
#if CC_MAC  // Conditional expansion of this file
302
/* Error Returns Meaning */
303
/* TPM_RC_ATTRIBUTES key referenced by handle is a restricted key */
304
/* TPM_RC_KEY handle does not reference a signing key */
305
/* TPM_RC_TYPE key referenced by handle is not an HMAC key */
306
/* TPM_RC_VALUE hashAlg is not compatible with the hash algorithm of the scheme of the object
307
   referenced by handle */
308
TPM_RC
309
TPM2_MAC(
310
   MAC_In         *in,            // IN: input parameter list
311
   MAC_Out        *out            // OUT: output parameter list
312
   )
313
0
{
314
0
    OBJECT                  *keyObject;
315
0
    HMAC_STATE               state;
316
0
    TPMT_PUBLIC             *publicArea;
317
0
    TPM_RC                   result;
318
    // Input Validation
319
    // Get MAC key object and public area pointers
320
0
    keyObject = HandleToObject(in->handle);
321
0
    publicArea = &keyObject->publicArea;
322
    // If the key is not able to do a MAC, indicate that the handle selects an
323
    // object that can't do a MAC
324
0
    result = CryptSelectMac(publicArea, &in->inScheme);
325
0
    if(result == TPM_RCS_TYPE)
326
0
  return TPM_RCS_TYPE + RC_MAC_handle;
327
    // If there is another error type, indicate that the scheme and key are not
328
    // compatible
329
0
    if(result != TPM_RC_SUCCESS)
330
0
  return RcSafeAddToResult(result, RC_MAC_inScheme);
331
    // Make sure that the key is not restricted
332
0
    if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted))
333
0
  return TPM_RCS_ATTRIBUTES + RC_MAC_handle;
334
    // and that it is a signing key
335
0
    if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))
336
0
  return TPM_RCS_KEY + RC_MAC_handle;
337
    // Command Output
338
0
    out->outMAC.t.size = CryptMacStart(&state, &publicArea->parameters,
339
0
               in->inScheme,
340
0
               &keyObject->sensitive.sensitive.any.b);
341
    // If the mac can't start, treat it as a fatal error
342
0
    if(out->outMAC.t.size == 0)
343
0
  return TPM_RC_FAILURE;
344
0
    CryptDigestUpdate2B(&state.hashState, &in->buffer.b);
345
    // If the MAC result is not what was expected, it is a fatal error
346
0
    if(CryptHmacEnd2B(&state, &out->outMAC.b) != out->outMAC.t.size)
347
0
  return TPM_RC_FAILURE;
348
0
    return TPM_RC_SUCCESS;
349
0
}
350
#endif // CC_MAC