Coverage Report

Created: 2024-07-27 06:30

/src/ibmswtpm2/src/CryptSym.c
Line
Count
Source (jump to first uncovered line)
1
/********************************************************************************/
2
/*                    */
3
/*           Symmetric block cipher modes     */
4
/*           Written by Ken Goldman       */
5
/*           IBM Thomas J. Watson Research Center     */
6
/*            $Id: CryptSym.c 1311 2018-08-23 21:39:29Z 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
/* 10.2.19 CryptSym.c */
63
/* 10.2.19.1 Introduction */
64
/* This file contains the implementation of the symmetric block cipher modes allowed for a
65
   TPM. These functions only use the single block encryption functions of the selected symmetric
66
   crypto library. */
67
/* 10.2.19.2 Includes, Defines, and Typedefs */
68
#include "Tpm.h"
69
#include "CryptSym.h"
70
/* 10.2.19.3.1  CryptSymInit() */
71
/* This function is called to do _TPM_Init() processing */
72
BOOL
73
CryptSymInit(
74
       void
75
       )
76
657
{
77
657
    return TRUE;
78
657
}
79
/* 10.2.19.3.2  CryptSymStartup() */
80
/* This function is called to do TPM2_Startup() processing */
81
BOOL
82
CryptSymStartup(
83
    void
84
    )
85
656
{
86
656
    return TRUE;
87
656
}
88
/* 10.2.20.4 Data Access Functions */
89
/* 10.2.20.4.1 CryptGetSymmetricBlockSize() */
90
/* This function returns the block size of the algorithm. */
91
/* Return Values Meaning */
92
/* <= 0 cipher not supported */
93
/* > 0 the cipher block size in bytes */
94
LIB_EXPORT INT16
95
CryptGetSymmetricBlockSize(
96
         TPM_ALG_ID      symmetricAlg,   // IN: the symmetric algorithm
97
         UINT16          keySizeInBits   // IN: the key size
98
         )
99
0
{
100
0
    switch(symmetricAlg)
101
0
  {
102
0
#if ALG_AES
103
0
    case ALG_AES_VALUE:
104
0
      switch(keySizeInBits)
105
0
    {
106
0
      case 128:
107
0
        return AES_128_BLOCK_SIZE_BYTES;
108
0
      case 192:
109
0
        return AES_192_BLOCK_SIZE_BYTES;
110
0
      case 256:
111
0
        return AES_256_BLOCK_SIZE_BYTES;
112
0
      default:
113
0
        break;
114
0
    }
115
0
      break;
116
0
#endif
117
#if ALG_SM4
118
    case ALG_SM4_VALUE:
119
      switch(keySizeInBits)
120
    {
121
      case 128:
122
        return SM4_128_BLOCK_SIZE_BYTES;
123
      default:
124
        break;
125
    }
126
#endif
127
#if ALG_CAMELLIA
128
    case ALG_CAMELLIA_VALUE:
129
      switch(keySizeInBits)
130
    {
131
      case 128:
132
        return CAMELLIA_128_BLOCK_SIZE_BYTES;
133
      case 192:
134
        return CAMELLIA_192_BLOCK_SIZE_BYTES;
135
      case 256:
136
        return CAMELLIA_256_BLOCK_SIZE_BYTES;
137
      default:
138
        break;
139
    }
140
#endif
141
#if ALG_TDES
142
    case ALG_TDES_VALUE:
143
      switch(keySizeInBits)
144
    {
145
      case 128:
146
        return TDES_128_BLOCK_SIZE_BYTES;
147
      case 192:
148
        return TDES_192_BLOCK_SIZE_BYTES;
149
      default:
150
        break;
151
    }
152
#endif
153
0
    default:
154
0
      break;
155
0
  }
156
0
    return 0;
157
0
}
158
/* 10.2.20.5 Symmetric Encryption */
159
/* This function performs symmetric encryption based on the mode. */
160
/* Error Returns Meaning */
161
/* TPM_RC_SUCCESS if success */
162
/* TPM_RC_SIZE dSize is not a multiple of the block size for an algorithm that requires it */
163
/* TPM_RC_FAILURE Fatal error */
164
LIB_EXPORT TPM_RC
165
CryptSymmetricEncrypt(
166
          BYTE                *dOut,          // OUT:
167
          TPM_ALG_ID           algorithm,     // IN: the symmetric algorithm
168
          UINT16               keySizeInBits, // IN: key size in bits
169
          const BYTE          *key,           // IN: key buffer. The size of this buffer
170
          //     in bytes is (keySizeInBits + 7) / 8
171
          TPM2B_IV            *ivInOut,       // IN/OUT: IV for decryption.
172
          TPM_ALG_ID           mode,          // IN: Mode to use
173
          INT32                dSize,         // IN: data size (may need to be a
174
          //     multiple of the blockSize)
175
          const BYTE          *dIn            // IN: data buffer
176
          )
177
0
{
178
0
    BYTE                *pIv;
179
0
    int                  i;
180
0
    BYTE                 tmp[MAX_SYM_BLOCK_SIZE];
181
0
    BYTE                *pT;
182
0
    tpmCryptKeySchedule_t        keySchedule;
183
0
    INT16                blockSize;
184
0
    TpmCryptSetSymKeyCall_t        encrypt;
185
0
    BYTE                *iv;
186
0
    BYTE                 defaultIv[MAX_SYM_BLOCK_SIZE] = {0};
187
    //
188
0
    pAssert(dOut != NULL && key != NULL && dIn != NULL);
189
0
    if(dSize == 0)
190
0
  return TPM_RC_SUCCESS;
191
0
    TEST(algorithm);
192
0
    blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits);
193
0
    if(blockSize == 0)
194
0
  return TPM_RC_FAILURE;
195
    // If the iv is provided, then it is expected to be block sized. In some cases,
196
    // the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE]
197
    // with no knowledge of the actual block size. This function will set it.
198
0
    if((ivInOut != NULL) && (mode != ALG_ECB_VALUE))
199
0
  {
200
0
      ivInOut->t.size = blockSize;
201
0
      iv = ivInOut->t.buffer;
202
0
  }
203
0
    else
204
0
  iv = defaultIv;
205
0
    pIv = iv;
206
    // Create encrypt key schedule and set the encryption function pointer.
207
0
    SELECT(ENCRYPT);
208
0
    switch(mode)
209
0
  {
210
0
#if ALG_CTR
211
0
    case ALG_CTR_VALUE:
212
0
      for(; dSize > 0; dSize -= blockSize)
213
0
    {
214
        // Encrypt the current value of the IV(counter)
215
0
        ENCRYPT(&keySchedule, iv, tmp);
216
        //increment the counter (counter is big-endian so start at end)
217
0
        for(i = blockSize - 1; i >= 0; i--)
218
0
      if((iv[i] += 1) != 0)
219
0
          break;
220
        // XOR the encrypted counter value with input and put into output
221
0
        pT = tmp;
222
0
        for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)
223
0
      *dOut++ = *dIn++ ^ *pT++;
224
0
    }
225
0
      break;
226
0
#endif
227
0
#if ALG_OFB
228
0
    case ALG_OFB_VALUE:
229
      // This is written so that dIn and dOut may be the same
230
0
      for(; dSize > 0; dSize -= blockSize)
231
0
    {
232
        // Encrypt the current value of the "IV"
233
0
        ENCRYPT(&keySchedule, iv, iv);
234
        // XOR the encrypted IV into dIn to create the cipher text (dOut)
235
0
        pIv = iv;
236
0
        for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)
237
0
      *dOut++ = (*pIv++ ^ *dIn++);
238
0
    }
239
0
      break;
240
0
#endif
241
0
#if ALG_CBC
242
0
    case ALG_CBC_VALUE:
243
      // For CBC the data size must be an even multiple of the
244
      // cipher block size
245
0
      if((dSize % blockSize) != 0)
246
0
    return TPM_RC_SIZE;
247
      // XOR the data block into the IV, encrypt the IV into the IV
248
      // and then copy the IV to the output
249
0
      for(; dSize > 0; dSize -= blockSize)
250
0
    {
251
0
        pIv = iv;
252
0
        for(i = blockSize; i > 0; i--)
253
0
      *pIv++ ^= *dIn++;
254
0
        ENCRYPT(&keySchedule, iv, iv);
255
0
        pIv = iv;
256
0
        for(i = blockSize; i > 0; i--)
257
0
      *dOut++ = *pIv++;
258
0
    }
259
0
      break;
260
0
#endif
261
      // CFB is not optional
262
0
    case ALG_CFB_VALUE:
263
      // Encrypt the IV into the IV, XOR in the data, and copy to output
264
0
      for(; dSize > 0; dSize -= blockSize)
265
0
    {
266
        // Encrypt the current value of the IV
267
0
        ENCRYPT(&keySchedule, iv, iv);
268
0
        pIv = iv;
269
0
        for(i = (int)(dSize < blockSize) ? dSize : blockSize; i > 0; i--)
270
      // XOR the data into the IV to create the cipher text
271
      // and put into the output
272
0
      *dOut++ = *pIv++ ^= *dIn++;
273
0
    }
274
      // If the inner loop (i loop) was smaller than blockSize, then dSize
275
      // would have been smaller than blockSize and it is now negative. If
276
      // it is negative, then it indicates how many bytes are needed to pad
277
      // out the IV for the next round.
278
0
      for(; dSize < 0; dSize++)
279
0
    *pIv++ = 0;
280
0
      break;
281
0
#if ALG_ECB
282
0
    case ALG_ECB_VALUE:
283
      // For ECB the data size must be an even multiple of the
284
      // cipher block size
285
0
      if((dSize % blockSize) != 0)
286
0
    return TPM_RC_SIZE;
287
      // Encrypt the input block to the output block
288
0
      for(; dSize > 0; dSize -= blockSize)
289
0
    {
290
0
        ENCRYPT(&keySchedule, dIn, dOut);
291
0
        dIn = &dIn[blockSize];
292
0
        dOut = &dOut[blockSize];
293
0
    }
294
0
      break;
295
0
#endif
296
0
    default:
297
0
      return TPM_RC_FAILURE;
298
0
  }
299
0
    return TPM_RC_SUCCESS;
300
0
}
301
/* 10.2.20.5.1 CryptSymmetricDecrypt() */
302
/* This function performs symmetric decryption based on the mode. */
303
/* Error Returns Meaning */
304
/* TPM_RC_FAILURE A fatal error */
305
/* TPM_RC_SUCCESS if success */
306
/* TPM_RCS_SIZE dSize is not a multiple of the block size for an algorithm that requires it */
307
LIB_EXPORT TPM_RC
308
CryptSymmetricDecrypt(
309
          BYTE                *dOut,          // OUT: decrypted data
310
          TPM_ALG_ID           algorithm,     // IN: the symmetric algorithm
311
          UINT16               keySizeInBits, // IN: key size in bits
312
          const BYTE          *key,           // IN: key buffer. The size of this buffer
313
          //     in bytes is (keySizeInBits + 7) / 8
314
          TPM2B_IV            *ivInOut,       // IN/OUT: IV for decryption.
315
          TPM_ALG_ID           mode,          // IN: Mode to use
316
          INT32                dSize,         // IN: data size (may need to be a
317
          //     multiple of the blockSize)
318
          const BYTE          *dIn            // IN: data buffer
319
          )
320
0
{
321
0
    BYTE                *pIv;
322
0
    int                  i;
323
0
    BYTE                 tmp[MAX_SYM_BLOCK_SIZE];
324
0
    BYTE                *pT;
325
0
    tpmCryptKeySchedule_t        keySchedule;
326
0
    INT16                blockSize;
327
0
    BYTE                *iv;
328
0
    TpmCryptSetSymKeyCall_t        encrypt;
329
0
    TpmCryptSetSymKeyCall_t        decrypt;
330
0
    BYTE                 defaultIv[MAX_SYM_BLOCK_SIZE] = {0};
331
    // These are used but the compiler can't tell because they are initialized
332
    // in case statements and it can't tell if they are always initialized
333
    // when needed, so... Comment these out if the compiler can tell or doesn't
334
    // care that these are initialized before use.
335
0
    encrypt = NULL;
336
0
    decrypt = NULL;
337
0
    pAssert(dOut != NULL && key != NULL && dIn != NULL);
338
0
    if(dSize == 0)
339
0
  return TPM_RC_SUCCESS;
340
0
    TEST(algorithm);
341
0
    blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits);
342
0
    if(blockSize == 0)
343
0
  return TPM_RC_FAILURE;
344
    // If the iv is provided, then it is expected to be block sized. In some cases,
345
    // the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE]
346
    // with no knowledge of the actual block size. This function will set it.
347
0
    if((ivInOut != NULL) && (mode != ALG_ECB_VALUE))
348
0
  {
349
0
      ivInOut->t.size = blockSize;
350
0
      iv = ivInOut->t.buffer;
351
0
  }
352
0
    else
353
0
  iv = defaultIv;
354
0
    pIv = iv;
355
    // Use the mode to select the key schedule to create. Encrypt always uses the
356
    // encryption schedule. Depending on the mode, decryption might use either
357
    // the decryption or encryption schedule.
358
0
    switch(mode)
359
0
  {
360
0
#if ALG_CBC || ALG_ECB
361
0
    case ALG_CBC_VALUE: // decrypt = decrypt
362
0
    case ALG_ECB_VALUE:
363
      // For ECB and CBC, the data size must be an even multiple of the
364
      // cipher block size
365
0
      if((dSize % blockSize) != 0)
366
0
    return TPM_RC_SIZE;
367
0
      SELECT(DECRYPT);
368
0
      break;
369
0
#endif
370
0
    default:
371
      // For the remaining stream ciphers, use encryption to decrypt
372
0
      SELECT(ENCRYPT);
373
0
      break;
374
0
  }
375
    // Now do the mode-dependent decryption
376
0
    switch(mode)
377
0
  {
378
0
#if ALG_CBC
379
0
    case ALG_CBC_VALUE:
380
      // Copy the input data to a temp buffer, decrypt the buffer into the
381
      // output, XOR in the IV, and copy the temp buffer to the IV and repeat.
382
0
      for(; dSize > 0; dSize -= blockSize)
383
0
    {
384
0
        pT = tmp;
385
0
        for(i = blockSize; i > 0; i--)
386
0
      *pT++ = *dIn++;
387
0
        DECRYPT(&keySchedule, tmp, dOut);
388
0
        pIv = iv;
389
0
        pT = tmp;
390
0
        for(i = blockSize; i > 0; i--)
391
0
      {
392
0
          *dOut++ ^= *pIv;
393
0
          *pIv++ = *pT++;
394
0
      }
395
0
    }
396
0
      break;
397
0
#endif
398
0
    case TPM_ALG_CFB:
399
0
      for(; dSize > 0; dSize -= blockSize)
400
0
    {
401
        // Encrypt the IV into the temp buffer
402
0
        ENCRYPT(&keySchedule, iv, tmp);
403
0
        pT = tmp;
404
0
        pIv = iv;
405
0
        for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)
406
      // Copy the current cipher text to IV, XOR
407
      // with the temp buffer and put into the output
408
0
      *dOut++ = *pT++ ^ (*pIv++ = *dIn++);
409
0
    }
410
      // If the inner loop (i loop) was smaller than blockSize, then dSize
411
      // would have been smaller than blockSize and it is now negative
412
      // If it is negative, then it indicates how may fill bytes
413
      // are needed to pad out the IV for the next round.
414
0
      for(; dSize < 0; dSize++)
415
0
    *pIv++ = 0;
416
0
      break;
417
0
#if ALG_CTR
418
0
    case ALG_CTR_VALUE:
419
0
      for(; dSize > 0; dSize -= blockSize)
420
0
    {
421
        // Encrypt the current value of the IV(counter)
422
0
        ENCRYPT(&keySchedule, iv, tmp);
423
        //increment the counter (counter is big-endian so start at end)
424
0
        for(i = blockSize - 1; i >= 0; i--)
425
0
      if((iv[i] += 1) != 0)
426
0
          break;
427
        // XOR the encrypted counter value with input and put into output
428
0
        pT = tmp;
429
0
        for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)
430
0
      *dOut++ = *dIn++ ^ *pT++;
431
0
    }
432
0
      break;
433
0
#endif
434
0
#if ALG_ECB
435
0
    case ALG_ECB_VALUE:
436
0
      for(; dSize > 0; dSize -= blockSize)
437
0
    {
438
0
        DECRYPT(&keySchedule, dIn, dOut);
439
0
        dIn = &dIn[blockSize];
440
0
        dOut = &dOut[blockSize];
441
0
    }
442
0
      break;
443
0
#endif
444
0
#if ALG_OFB
445
0
    case TPM_ALG_OFB:
446
      // This is written so that dIn and dOut may be the same
447
0
      for(; dSize > 0; dSize -= blockSize)
448
0
    {
449
        // Encrypt the current value of the "IV"
450
0
        ENCRYPT(&keySchedule, iv, iv);
451
        // XOR the encrypted IV into dIn to create the cipher text (dOut)
452
0
        pIv = iv;
453
0
        for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--)
454
0
      *dOut++ = (*pIv++ ^ *dIn++);
455
0
    }
456
0
      break;
457
0
#endif
458
0
    default:
459
0
      return TPM_RC_FAILURE;
460
0
  }
461
0
    return TPM_RC_SUCCESS;
462
0
}
463
/* 10.2.20.5.2 CryptSymKeyValidate() */
464
/* Validate that a provided symmetric key meets the requirements of the TPM */
465
/* Error Returns Meaning */
466
/* TPM_RC_KEY_SIZE Key size specifiers do not match */
467
/* TPM_RC_KEY Key is not allowed */
468
TPM_RC
469
CryptSymKeyValidate(
470
        TPMT_SYM_DEF_OBJECT *symDef,
471
        TPM2B_SYM_KEY       *key
472
        )
473
0
{
474
0
    if(key->t.size != BITS_TO_BYTES(symDef->keyBits.sym))
475
0
  return TPM_RCS_KEY_SIZE;
476
#if ALG_TDES
477
    if(symDef->algorithm == TPM_ALG_TDES && !CryptDesValidateKey(key))
478
  return TPM_RCS_KEY;
479
#endif // TPM_ALG_TDES
480
0
    return TPM_RC_SUCCESS;
481
0
}