Coverage Report

Created: 2025-09-05 06:38

/src/tpm2/CpriSym.c
Line
Count
Source (jump to first uncovered line)
1
// This file was extracted from the TCG Published
2
// Trusted Platform Module Library
3
// Part 4: Supporting Routines
4
// Family "2.0"
5
// Level 00 Revision 01.16
6
// October 30, 2014
7
8
#include       "OsslCryptoEngine.h"
9
//
10
//     The following sets of defines are used to allow use of the SM4 algorithm identifier while waiting for the
11
//     SM4 implementation code to appear.
12
//
13
typedef   AES_KEY SM4_KEY;
14
#define   SM4_set_encrypt_key            AES_set_encrypt_key
15
#define   SM4_set_decrypt_key            AES_set_decrypt_key
16
#define   SM4_decrypt                    AES_decrypt
17
#define   SM4_encrypt                    AES_encrypt
18
//
19
//
20
//      Utility Functions
21
//
22
//      _cpri_SymStartup()
23
//
24
LIB_EXPORT BOOL
25
_cpri__SymStartup(
26
      void
27
)
28
759
{
29
759
      return TRUE;
30
759
}
31
//
32
//
33
//      _cpri__GetSymmetricBlockSize()
34
//
35
//     This function returns the block size of the algorithm.
36
//
37
//     Return Value                      Meaning
38
//
39
//     <= 0                              cipher not supported
40
//     >0                                the cipher block size in bytes
41
//
42
LIB_EXPORT INT16
43
_cpri__GetSymmetricBlockSize(
44
      TPM_ALG_ID         symmetricAlg,        // IN: the symmetric algorithm
45
      UINT16             keySizeInBits        // IN: the key size
46
      )
47
0
{
48
0
   switch (symmetricAlg)
49
0
   {
50
0
#ifdef TPM_ALG_AES
51
0
   case TPM_ALG_AES:
52
0
#endif
53
#ifdef TPM_ALG_SM4 // Both AES and SM4 use the same block size
54
   case TPM_ALG_SM4:
55
#endif
56
0
       if(keySizeInBits != 0) // This is mostly to have a reference to
57
              // keySizeInBits for the compiler
58
0
              return 16;
59
0
         else
60
0
             return 0;
61
0
         break;
62
0
    default:
63
0
        return 0;
64
0
    }
65
0
}
66
//
67
//
68
//      AES Encryption
69
//
70
//      _cpri__AESEncryptCBC()
71
//
72
//     This function performs AES encryption in CBC chain mode. The input dIn buffer is encrypted into dOut.
73
//     The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to
74
//     be a multiple of the block size.
75
//
76
//     Return Value                      Meaning
77
//
78
//     CRYPT_SUCCESS                     if success
79
//     CRYPT_PARAMETER                   dInSize is not a multiple of the block size
80
//
81
LIB_EXPORT CRYPT_RESULT
82
_cpri__AESEncryptCBC(
83
    BYTE                *dOut,          // OUT:
84
    UINT32               keySizeInBits, // IN: key size in bit
85
    BYTE                *key,           // IN: key buffer. The size of this buffer in
86
                                        //      bytes is (keySizeInBits + 7) / 8
87
    BYTE                *iv,            // IN/OUT: IV for decryption.
88
    UINT32               dInSize,       // IN: data size (is required to be a multiple
89
                                        //      of 16 bytes)
90
    BYTE                *dIn            // IN: data buffer
91
    )
92
0
{
93
0
    AES_KEY         AesKey;
94
0
    BYTE           *pIv;
95
0
    INT32           dSize;              // Need a signed version
96
0
    int             i;
97
0
    pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
98
0
    if(dInSize == 0)
99
0
        return CRYPT_SUCCESS;
100
0
    pAssert(dInSize <= INT32_MAX);
101
0
    dSize = (INT32)dInSize;
102
    // For CBC, the data size must be an even multiple of the
103
    // cipher block size
104
0
    if((dSize % 16) != 0)
105
0
        return CRYPT_PARAMETER;
106
    // Create AES encrypt key schedule
107
0
    if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
108
0
        FAIL(FATAL_ERROR_INTERNAL);
109
    // XOR the data block into the IV, encrypt the IV into the IV
110
    // and then copy the IV to the output
111
0
    for(; dSize > 0; dSize -= 16)
112
0
    {
113
0
         pIv = iv;
114
0
         for(i = 16; i > 0; i--)
115
0
             *pIv++ ^= *dIn++;
116
0
         AES_encrypt(iv, iv, &AesKey);
117
0
         pIv = iv;
118
0
         for(i = 16; i > 0; i--)
119
0
             *dOut++ = *pIv++;
120
0
    }
121
0
    return CRYPT_SUCCESS;
122
0
}
123
//
124
//
125
//       _cpri__AESDecryptCBC()
126
//
127
//      This function performs AES decryption in CBC chain mode. The input dIn buffer is decrypted into dOut.
128
//      The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to
129
//      be a multiple of the block size.
130
//
131
//      Return Value                     Meaning
132
//
133
//      CRYPT_SUCCESS                    if success
134
//      CRYPT_PARAMETER                  dInSize is not a multiple of the block size
135
//
136
LIB_EXPORT CRYPT_RESULT
137
_cpri__AESDecryptCBC(
138
    BYTE                *dOut,          // OUT: the decrypted data
139
    UINT32               keySizeInBits, // IN: key size in bit
140
    BYTE                *key,           // IN: key buffer. The size of this buffer in
141
                                        //     bytes is (keySizeInBits + 7) / 8
142
    BYTE                *iv,            // IN/OUT: IV for decryption. The size of this
143
                                        //     buffer is 16 byte
144
    UINT32               dInSize,       // IN: data size
145
    BYTE                *dIn            // IN: data buffer
146
    )
147
0
{
148
0
    AES_KEY         AesKey;
149
0
    BYTE           *pIv;
150
0
    int             i;
151
0
    BYTE            tmp[16];
152
0
    BYTE           *pT = NULL;
153
0
    INT32           dSize;
154
0
    pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
155
0
    if(dInSize == 0)
156
0
        return CRYPT_SUCCESS;
157
0
    pAssert(dInSize <= INT32_MAX);
158
0
    dSize = (INT32)dInSize;
159
    // For CBC, the data size must be an even multiple of the
160
    // cipher block size
161
0
    if((dSize % 16) != 0)
162
0
        return CRYPT_PARAMETER;
163
    // Create AES key schedule
164
0
    if (AES_set_decrypt_key(key, keySizeInBits, &AesKey) != 0)
165
0
        FAIL(FATAL_ERROR_INTERNAL);
166
    // Copy the input data to a temp buffer, decrypt the buffer into the output;
167
    // XOR in the IV, and copy the temp buffer to the IV and repeat.
168
0
    for(; dSize > 0; dSize -= 16)
169
0
    {
170
//
171
0
        pT = tmp;
172
0
        for(i = 16; i> 0; i--)
173
0
            *pT++ = *dIn++;
174
0
        AES_decrypt(tmp, dOut, &AesKey);
175
0
        pIv = iv;
176
0
        pT = tmp;
177
0
        for(i = 16; i> 0; i--)
178
0
        {
179
0
            *dOut++ ^= *pIv;
180
0
            *pIv++ = *pT++;
181
0
        }
182
0
   }
183
0
   return CRYPT_SUCCESS;
184
0
}
185
//
186
//
187
//       _cpri__AESEncryptCFB()
188
//
189
//      This function performs AES encryption in CFB chain mode. The dOut buffer receives the values
190
//      encrypted dIn. The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will
191
//      be modified to contain the last encrypted block.
192
//
193
//      Return Value                      Meaning
194
//
195
//      CRYPT_SUCCESS                     no non-fatal errors
196
//
197
LIB_EXPORT CRYPT_RESULT
198
_cpri__AESEncryptCFB(
199
   BYTE                *dOut,          // OUT: the encrypted
200
   UINT32               keySizeInBits, // IN: key size in bit
201
   BYTE                *key,           // IN: key buffer. The size of this buffer in
202
                                       //     bytes is (keySizeInBits + 7) / 8
203
   BYTE                *iv,            // IN/OUT: IV for decryption.
204
   UINT32               dInSize,       // IN: data size
205
   BYTE                *dIn            // IN: data buffer
206
   )
207
0
{
208
0
   BYTE           *pIv = NULL;
209
0
   AES_KEY         AesKey;
210
0
   INT32           dSize;               // Need a signed version of dInSize
211
0
   int             i;
212
0
   pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
213
0
   if(dInSize == 0)
214
0
       return CRYPT_SUCCESS;
215
0
   pAssert(dInSize <= INT32_MAX);
216
0
   dSize = (INT32)dInSize;
217
   // Create AES encryption key schedule
218
0
   if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
219
0
       FAIL(FATAL_ERROR_INTERNAL);
220
   // Encrypt the IV into the IV, XOR in the data, and copy to output
221
0
   for(; dSize > 0; dSize -= 16)
222
0
   {
223
       // Encrypt the current value of the IV
224
0
       AES_encrypt(iv, iv, &AesKey);
225
0
       pIv = iv;
226
0
       for(i = (int)(dSize < 16) ? dSize : 16; i > 0; i--)
227
           // XOR the data into the IV to create the cipher text
228
           // and put into the output
229
0
           *dOut++ = *pIv++ ^= *dIn++;
230
0
   }
231
   // If the inner loop (i loop) was smaller than 16, then dSize would have been
232
   // smaller than 16 and it is now negative. If it is negative, then it indicates
233
   // how many bytes are needed to pad out the IV for the next round.
234
0
   for(; dSize < 0; dSize++)
235
0
       *pIv++ = 0;
236
0
   return CRYPT_SUCCESS;
237
0
}
238
//
239
//
240
//       _cpri__AESDecryptCFB()
241
//
242
//      This function performs AES decrypt in CFB chain mode. The dOut buffer receives the values decrypted
243
//      from dIn.
244
//      The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will be modified to
245
//      contain the last decoded block, padded with zeros
246
//
247
//      Return Value                    Meaning
248
//
249
//      CRYPT_SUCCESS                   no non-fatal errors
250
//
251
LIB_EXPORT CRYPT_RESULT
252
_cpri__AESDecryptCFB(
253
   BYTE                *dOut,          // OUT: the decrypted data
254
   UINT32               keySizeInBits, // IN: key size in bit
255
   BYTE                *key,           // IN: key buffer. The size of this buffer in
256
                                       //     bytes is (keySizeInBits + 7) / 8
257
   BYTE                *iv,            // IN/OUT: IV for decryption.
258
   UINT32               dInSize,       // IN: data size
259
   BYTE                *dIn            // IN: data buffer
260
   )
261
0
{
262
0
   BYTE           *pIv = NULL;
263
0
   BYTE            tmp[16];
264
0
   int             i;
265
0
   BYTE           *pT;
266
0
   AES_KEY         AesKey;
267
0
   INT32           dSize;
268
0
   pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
269
0
   if(dInSize == 0)
270
0
       return CRYPT_SUCCESS;
271
0
   pAssert(dInSize <= INT32_MAX);
272
0
   dSize = (INT32)dInSize;
273
   // Create AES encryption key schedule
274
0
   if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
275
0
       FAIL(FATAL_ERROR_INTERNAL);
276
0
   for(; dSize > 0; dSize -= 16)
277
0
   {
278
       // Encrypt the IV into the temp buffer
279
0
       AES_encrypt(iv, tmp, &AesKey);
280
0
       pT = tmp;
281
0
       pIv = iv;
282
0
       for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
283
           // Copy the current cipher text to IV, XOR
284
           // with the temp buffer and put into the output
285
0
           *dOut++ = *pT++ ^ (*pIv++ = *dIn++);
286
0
   }
287
   // If the inner loop (i loop) was smaller than 16, then dSize
288
   // would have been smaller than 16 and it is now negative
289
   // If it is negative, then it indicates how may fill bytes
290
   // are needed to pad out the IV for the next round.
291
0
   for(; dSize < 0; dSize++)
292
0
       *pIv++ = 0;
293
0
   return CRYPT_SUCCESS;
294
0
}
295
//
296
//
297
//       _cpri__AESEncryptCTR()
298
//
299
//      This function performs AES encryption/decryption in CTR chain mode. The dIn buffer is encrypted into
300
//      dOut. The input iv buffer is assumed to have a size equal to the AES block size (16 bytes). The iv will be
301
//      incremented by the number of blocks (full and partial) that were encrypted.
302
//
303
//      Return Value                      Meaning
304
//
305
//      CRYPT_SUCCESS                     no non-fatal errors
306
//
307
LIB_EXPORT CRYPT_RESULT
308
_cpri__AESEncryptCTR(
309
   BYTE                *dOut,          // OUT: the encrypted data
310
   UINT32               keySizeInBits, // IN: key size in bit
311
   BYTE                *key,           // IN: key buffer. The size of this buffer in
312
                                       //     bytes is (keySizeInBits + 7) / 8
313
   BYTE                *iv,            // IN/OUT: IV for decryption.
314
   UINT32               dInSize,       // IN: data size
315
   BYTE                *dIn            // IN: data buffer
316
   )
317
0
{
318
0
   BYTE            tmp[16];
319
0
   BYTE           *pT;
320
0
   AES_KEY         AesKey;
321
0
   int             i;
322
0
   INT32           dSize;
323
0
   pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
324
0
   if(dInSize == 0)
325
0
       return CRYPT_SUCCESS;
326
0
   pAssert(dInSize <= INT32_MAX);
327
0
   dSize = (INT32)dInSize;
328
   // Create AES encryption schedule
329
0
   if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
330
0
       FAIL(FATAL_ERROR_INTERNAL);
331
0
   for(; dSize > 0; dSize -= 16)
332
0
   {
333
       // Encrypt the current value of the IV(counter)
334
0
       AES_encrypt(iv, (BYTE *)tmp, &AesKey);
335
        //increment the counter (counter is big-endian so start at end)
336
0
        for(i = 15; i >= 0; i--)
337
0
            if((iv[i] += 1) != 0)
338
0
                break;
339
        // XOR the encrypted counter value with input and put into output
340
0
        pT = tmp;
341
0
        for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
342
0
            *dOut++ = *dIn++ ^ *pT++;
343
0
   }
344
0
   return CRYPT_SUCCESS;
345
0
}
346
//
347
//       _cpri__AESEncryptECB()
348
//
349
//      AES encryption in ECB mode. The data buffer is modified to contain the cipher text.
350
//
351
//      Return Value                      Meaning
352
//
353
//      CRYPT_SUCCESS                     no non-fatal errors
354
//
355
LIB_EXPORT CRYPT_RESULT
356
_cpri__AESEncryptECB(
357
    BYTE                *dOut,          // OUT: encrypted data
358
    UINT32               keySizeInBits, // IN: key size in bit
359
    BYTE                *key,           // IN: key buffer. The size of this buffer in
360
                                        //     bytes is (keySizeInBits + 7) / 8
361
    UINT32               dInSize,       // IN: data size
362
    BYTE                *dIn            // IN: clear text buffer
363
    )
364
0
{
365
0
    AES_KEY          AesKey;
366
0
    INT32            dSize;
367
0
    pAssert(dOut != NULL && key != NULL && dIn != NULL);
368
0
    if(dInSize == 0)
369
0
        return CRYPT_SUCCESS;
370
0
    pAssert(dInSize <= INT32_MAX);
371
0
    dSize = (INT32)dInSize;
372
    // For ECB, the data size must be an even multiple of the
373
    // cipher block size
374
0
    if((dSize % 16) != 0)
375
0
        return CRYPT_PARAMETER;
376
    // Create AES encrypting key schedule
377
0
    if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
378
0
        FAIL(FATAL_ERROR_INTERNAL);
379
0
    for(; dSize > 0; dSize -= 16)
380
0
    {
381
0
        AES_encrypt(dIn, dOut, &AesKey);
382
0
        dIn = &dIn[16];
383
0
        dOut = &dOut[16];
384
0
    }
385
0
   return CRYPT_SUCCESS;
386
0
}
387
//
388
//
389
//       _cpri__AESDecryptECB()
390
//
391
//      This function performs AES decryption using ECB (not recommended). The cipher text dIn is decrypted
392
//      into dOut.
393
//
394
//      Return Value                      Meaning
395
//
396
//      CRYPT_SUCCESS                     no non-fatal errors
397
//
398
LIB_EXPORT CRYPT_RESULT
399
_cpri__AESDecryptECB(
400
   BYTE                *dOut,          // OUT: the clear text data
401
   UINT32               keySizeInBits, // IN: key size in bit
402
   BYTE                *key,           // IN: key buffer. The size of this buffer in
403
                                       //     bytes is (keySizeInBits + 7) / 8
404
   UINT32               dInSize,       // IN: data size
405
   BYTE                *dIn            // IN: cipher text buffer
406
   )
407
0
{
408
0
   AES_KEY         AesKey;
409
0
   INT32           dSize;
410
0
   pAssert(dOut != NULL && key != NULL && dIn != NULL);
411
0
   if(dInSize == 0)
412
0
       return CRYPT_SUCCESS;
413
0
   pAssert(dInSize <= INT32_MAX);
414
0
   dSize = (INT32)dInSize;
415
   // For ECB, the data size must be an even multiple of the
416
   // cipher block size
417
0
   if((dSize % 16) != 0)
418
0
       return CRYPT_PARAMETER;
419
   // Create AES decryption key schedule
420
0
   if (AES_set_decrypt_key(key, keySizeInBits, &AesKey) != 0)
421
0
       FAIL(FATAL_ERROR_INTERNAL);
422
0
   for(; dSize > 0; dSize -= 16)
423
0
   {
424
0
       AES_decrypt(dIn, dOut, &AesKey);
425
0
       dIn = &dIn[16];
426
0
       dOut = &dOut[16];
427
0
   }
428
0
   return CRYPT_SUCCESS;
429
0
}
430
//
431
//
432
//       _cpri__AESEncryptOFB()
433
//
434
//      This function performs AES encryption/decryption in OFB chain mode. The dIn buffer is modified to
435
//      contain the encrypted/decrypted text.
436
//      The input iv buffer is assumed to have a size equal to the block size (16 bytes). The returned value of iv
437
//      will be the nth encryption of the IV, where n is the number of blocks (full or partial) in the data stream.
438
//
439
//
440
//
441
//
442
//      Return Value                  Meaning
443
//
444
//      CRYPT_SUCCESS                 no non-fatal errors
445
//
446
LIB_EXPORT CRYPT_RESULT
447
_cpri__AESEncryptOFB(
448
   BYTE               *dOut,          // OUT: the encrypted/decrypted data
449
   UINT32              keySizeInBits, // IN: key size in bit
450
   BYTE               *key,           // IN: key buffer. The size of this buffer in
451
                                      //     bytes is (keySizeInBits + 7) / 8
452
   BYTE               *iv,            // IN/OUT: IV for decryption. The size of this
453
                                      //     buffer is 16 byte
454
   UINT32              dInSize,       // IN: data size
455
   BYTE               *dIn            // IN: data buffer
456
   )
457
0
{
458
0
   BYTE           *pIv;
459
0
   AES_KEY         AesKey;
460
0
   INT32           dSize;
461
0
   int             i;
462
0
   pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
463
0
   if(dInSize == 0)
464
0
       return CRYPT_SUCCESS;
465
0
   pAssert(dInSize <= INT32_MAX);
466
0
   dSize = (INT32)dInSize;
467
   // Create AES key schedule
468
0
   if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
469
0
       FAIL(FATAL_ERROR_INTERNAL);
470
   // This is written so that dIn and dOut may be the same
471
0
   for(; dSize > 0; dSize -= 16)
472
0
   {
473
       // Encrypt the current value of the "IV"
474
0
       AES_encrypt(iv, iv, &AesKey);
475
        // XOR the encrypted IV into dIn to create the cipher text (dOut)
476
0
        pIv = iv;
477
0
        for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
478
0
            *dOut++ = (*pIv++ ^ *dIn++);
479
0
   }
480
0
   return CRYPT_SUCCESS;
481
0
}
482
#ifdef    TPM_ALG_SM4
483
//
484
//
485
//       SM4 Encryption
486
//
487
//       _cpri__SM4EncryptCBC()
488
//
489
//      This function performs SM4 encryption in CBC chain mode. The input dIn buffer is encrypted into dOut.
490
//      The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to
491
//      be a multiple of the block size.
492
//
493
//      Return Value                      Meaning
494
//
495
//      CRYPT_SUCCESS                     if success
496
//      CRYPT_PARAMETER                   dInSize is not a multiple of the block size
497
//
498
LIB_EXPORT CRYPT_RESULT
499
_cpri__SM4EncryptCBC(
500
    BYTE                *dOut,          // OUT:
501
    UINT32               keySizeInBits, // IN: key size in bit
502
    BYTE                *key,           // IN: key buffer. The size of this buffer in
503
                                        //      bytes is (keySizeInBits + 7) / 8
504
    BYTE                *iv,            // IN/OUT: IV for decryption.
505
    UINT32               dInSize,       // IN: data size (is required to be a multiple
506
                                        //      of 16 bytes)
507
    BYTE                *dIn            // IN: data buffer
508
    )
509
{
510
    SM4_KEY         Sm4Key;
511
    BYTE           *pIv;
512
    INT32           dSize;              // Need a signed version
513
    int             i;
514
    pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
515
    if(dInSize == 0)
516
        return CRYPT_SUCCESS;
517
    pAssert(dInSize <= INT32_MAX);
518
    dSize = (INT32)dInSize;
519
    // For CBC, the data size must be an even multiple of the
520
    // cipher block size
521
    if((dSize % 16) != 0)
522
        return CRYPT_PARAMETER;
523
    // Create SM4 encrypt key schedule
524
    if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
525
        FAIL(FATAL_ERROR_INTERNAL);
526
    // XOR the data block into the IV, encrypt the IV into the IV
527
    // and then copy the IV to the output
528
    for(; dSize > 0; dSize -= 16)
529
    {
530
        pIv = iv;
531
        for(i = 16; i > 0; i--)
532
            *pIv++ ^= *dIn++;
533
        SM4_encrypt(iv, iv, &Sm4Key);
534
        pIv = iv;
535
        for(i = 16; i > 0; i--)
536
            *dOut++ = *pIv++;
537
    }
538
    return CRYPT_SUCCESS;
539
}
540
//
541
//
542
//       _cpri__SM4DecryptCBC()
543
//
544
//      This function performs SM4 decryption in CBC chain mode. The input dIn buffer is decrypted into dOut.
545
//      The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to
546
//      be a multiple of the block size.
547
//
548
//      Return Value                     Meaning
549
//
550
//      CRYPT_SUCCESS                    if success
551
//      CRYPT_PARAMETER                  dInSize is not a multiple of the block size
552
//
553
LIB_EXPORT CRYPT_RESULT
554
_cpri__SM4DecryptCBC(
555
    BYTE                *dOut,          // OUT: the decrypted data
556
    UINT32               keySizeInBits, // IN: key size in bit
557
    BYTE                *key,           // IN: key buffer. The size of this buffer in
558
                                        //     bytes is (keySizeInBits + 7) / 8
559
    BYTE                *iv,            // IN/OUT: IV for decryption. The size of this
560
                                        //     buffer is 16 byte
561
    UINT32               dInSize,       // IN: data size
562
    BYTE                *dIn            // IN: data buffer
563
    )
564
{
565
    SM4_KEY         Sm4Key;
566
    BYTE           *pIv;
567
    int             i;
568
    BYTE            tmp[16];
569
    BYTE           *pT = NULL;
570
    INT32           dSize;
571
    pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
572
    if(dInSize == 0)
573
        return CRYPT_SUCCESS;
574
    pAssert(dInSize <= INT32_MAX);
575
    dSize = (INT32)dInSize;
576
    // For CBC, the data size must be an even multiple of the
577
    // cipher block size
578
    if((dSize % 16) != 0)
579
        return CRYPT_PARAMETER;
580
    // Create SM4 key schedule
581
    if (SM4_set_decrypt_key(key, keySizeInBits, &Sm4Key) != 0)
582
        FAIL(FATAL_ERROR_INTERNAL);
583
    // Copy the input data to a temp buffer, decrypt the buffer into the output;
584
    // XOR in the IV, and copy the temp buffer to the IV and repeat.
585
    for(; dSize > 0; dSize -= 16)
586
    {
587
        pT = tmp;
588
        for(i = 16; i> 0; i--)
589
            *pT++ = *dIn++;
590
        SM4_decrypt(tmp, dOut, &Sm4Key);
591
        pIv = iv;
592
        pT = tmp;
593
        for(i = 16; i> 0; i--)
594
        {
595
            *dOut++ ^= *pIv;
596
//
597
              *pIv++ = *pT++;
598
        }
599
   }
600
   return CRYPT_SUCCESS;
601
}
602
//
603
//
604
//       _cpri__SM4EncryptCFB()
605
//
606
//      This function performs SM4 encryption in CFB chain mode. The dOut buffer receives the values
607
//      encrypted dIn. The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will
608
//      be modified to contain the last encrypted block.
609
//
610
//      Return Value                      Meaning
611
//
612
//      CRYPT_SUCCESS                     no non-fatal errors
613
//
614
LIB_EXPORT CRYPT_RESULT
615
_cpri__SM4EncryptCFB(
616
   BYTE                *dOut,          // OUT: the encrypted
617
   UINT32               keySizeInBits, // IN: key size in bit
618
   BYTE                *key,           // IN: key buffer. The size of this buffer in
619
                                       //     bytes is (keySizeInBits + 7) / 8
620
   BYTE                *iv,            // IN/OUT: IV for decryption.
621
   UINT32               dInSize,       // IN: data size
622
   BYTE                *dIn            // IN: data buffer
623
   )
624
{
625
   BYTE           *pIv;
626
   SM4_KEY         Sm4Key;
627
   INT32           dSize;               // Need a signed version of dInSize
628
   int             i;
629
   pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
630
   if(dInSize == 0)
631
       return CRYPT_SUCCESS;
632
   pAssert(dInSize <= INT32_MAX);
633
   dSize = (INT32)dInSize;
634
   // Create SM4 encryption key schedule
635
   if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
636
       FAIL(FATAL_ERROR_INTERNAL);
637
   // Encrypt the IV into the IV, XOR in the data, and copy to output
638
   for(; dSize > 0; dSize -= 16)
639
   {
640
       // Encrypt the current value of the IV
641
       SM4_encrypt(iv, iv, &Sm4Key);
642
       pIv = iv;
643
       for(i = (int)(dSize < 16) ? dSize : 16; i > 0; i--)
644
           // XOR the data into the IV to create the cipher text
645
           // and put into the output
646
           *dOut++ = *pIv++ ^= *dIn++;
647
   }
648
   return CRYPT_SUCCESS;
649
}
650
//
651
//
652
//       _cpri__SM4DecryptCFB()
653
//
654
//      This function performs SM4 decrypt in CFB chain mode. The dOut buffer receives the values decrypted
655
//      from dIn.
656
//
657
//      The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will be modified to
658
//      contain the last decoded block, padded with zeros
659
//
660
//      Return Value                    Meaning
661
//
662
//      CRYPT_SUCCESS                   no non-fatal errors
663
//
664
LIB_EXPORT CRYPT_RESULT
665
_cpri__SM4DecryptCFB(
666
   BYTE                *dOut,          // OUT: the decrypted data
667
   UINT32               keySizeInBits, // IN: key size in bit
668
   BYTE                *key,           // IN: key buffer. The size of this buffer in
669
                                       //     bytes is (keySizeInBits + 7) / 8
670
   BYTE                *iv,            // IN/OUT: IV for decryption.
671
   UINT32               dInSize,       // IN: data size
672
   BYTE                *dIn            // IN: data buffer
673
   )
674
{
675
   BYTE           *pIv;
676
   BYTE            tmp[16];
677
   int             i;
678
   BYTE           *pT;
679
   SM4_KEY         Sm4Key;
680
   INT32           dSize;
681
   pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
682
   if(dInSize == 0)
683
       return CRYPT_SUCCESS;
684
   pAssert(dInSize <= INT32_MAX);
685
   dSize = (INT32)dInSize;
686
   // Create SM4 encryption key schedule
687
   if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
688
       FAIL(FATAL_ERROR_INTERNAL);
689
   for(; dSize > 0; dSize -= 16)
690
   {
691
       // Encrypt the IV into the temp buffer
692
       SM4_encrypt(iv, tmp, &Sm4Key);
693
       pT = tmp;
694
       pIv = iv;
695
       for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
696
           // Copy the current cipher text to IV, XOR
697
           // with the temp buffer and put into the output
698
           *dOut++ = *pT++ ^ (*pIv++ = *dIn++);
699
   }
700
   // If the inner loop (i loop) was smaller than 16, then dSize
701
   // would have been smaller than 16 and it is now negative
702
   // If it is negative, then it indicates how may fill bytes
703
   // are needed to pad out the IV for the next round.
704
   for(; dSize < 0; dSize++)
705
       *iv++ = 0;
706
   return CRYPT_SUCCESS;
707
}
708
//
709
//
710
//       _cpri__SM4EncryptCTR()
711
//
712
//      This function performs SM4 encryption/decryption in CTR chain mode. The dIn buffer is encrypted into
713
//      dOut. The input iv buffer is assumed to have a size equal to the SM4 block size (16 bytes). The iv will be
714
//      incremented by the number of blocks (full and partial) that were encrypted.
715
//
716
//      Return Value                      Meaning
717
//
718
//      CRYPT_SUCCESS                     no non-fatal errors
719
//
720
LIB_EXPORT CRYPT_RESULT
721
_cpri__SM4EncryptCTR(
722
   BYTE               *dOut,          // OUT: the encrypted data
723
   UINT32              keySizeInBits, // IN: key size in bit
724
   BYTE               *key,           // IN: key buffer. The size of this buffer in
725
                                      //     bytes is (keySizeInBits + 7) / 8
726
   BYTE               *iv,            // IN/OUT: IV for decryption.
727
   UINT32              dInSize,       // IN: data size
728
   BYTE               *dIn            // IN: data buffer
729
   )
730
{
731
   BYTE            tmp[16];
732
   BYTE           *pT;
733
   SM4_KEY         Sm4Key;
734
   int             i;
735
   INT32           dSize;
736
   pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
737
   if(dInSize == 0)
738
       return CRYPT_SUCCESS;
739
   pAssert(dInSize <= INT32_MAX);
740
   dSize = (INT32)dInSize;
741
   // Create SM4 encryption schedule
742
   if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
743
       FAIL(FATAL_ERROR_INTERNAL);
744
   for(; dSize > 0; dSize--)
745
   {
746
       // Encrypt the current value of the IV(counter)
747
       SM4_encrypt(iv, (BYTE *)tmp, &Sm4Key);
748
        //increment the counter
749
        for(i = 0; i < 16; i++)
750
            if((iv[i] += 1) != 0)
751
                break;
752
        // XOR the encrypted counter value with input and put into output
753
        pT = tmp;
754
        for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
755
            *dOut++ = *dIn++ ^ *pT++;
756
   }
757
   return CRYPT_SUCCESS;
758
}
759
//
760
//       _cpri__SM4EncryptECB()
761
//
762
//      SM4 encryption in ECB mode. The data buffer is modified to contain the cipher text.
763
//
764
//      Return Value                      Meaning
765
//
766
//      CRYPT_SUCCESS                     no non-fatal errors
767
//
768
LIB_EXPORT CRYPT_RESULT
769
_cpri__SM4EncryptECB(
770
    BYTE                *dOut,          // OUT: encrypted data
771
    UINT32               keySizeInBits, // IN: key size in bit
772
    BYTE                *key,           // IN: key buffer. The size of this buffer in
773
                                        //     bytes is (keySizeInBits + 7) / 8
774
    UINT32               dInSize,       // IN: data size
775
    BYTE                *dIn            // IN: clear text buffer
776
    )
777
{
778
    SM4_KEY          Sm4Key;
779
    INT32            dSize;
780
    pAssert(dOut != NULL && key != NULL && dIn != NULL);
781
    if(dInSize == 0)
782
        return CRYPT_SUCCESS;
783
    pAssert(dInSize <= INT32_MAX);
784
    dSize = (INT32)dInSize;
785
    // For ECB, the data size must be an even multiple of the
786
    // cipher block size
787
    if((dSize % 16) != 0)
788
        return CRYPT_PARAMETER;
789
    // Create SM4 encrypting key schedule
790
    if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
791
        FAIL(FATAL_ERROR_INTERNAL);
792
    for(; dSize > 0; dSize -= 16)
793
    {
794
        SM4_encrypt(dIn, dOut, &Sm4Key);
795
        dIn = &dIn[16];
796
        dOut = &dOut[16];
797
    }
798
    return CRYPT_SUCCESS;
799
}
800
//
801
//
802
//       _cpri__SM4DecryptECB()
803
//
804
//      This function performs SM4 decryption using ECB (not recommended). The cipher text dIn is decrypted
805
//      into dOut.
806
//
807
//
808
//
809
//
810
//      Return Value                      Meaning
811
//
812
//      CRYPT_SUCCESS                     no non-fatal errors
813
//
814
LIB_EXPORT CRYPT_RESULT
815
_cpri__SM4DecryptECB(
816
   BYTE                *dOut,          // OUT: the clear text data
817
   UINT32               keySizeInBits, // IN: key size in bit
818
   BYTE                *key,           // IN: key buffer. The size of this buffer in
819
                                       //     bytes is (keySizeInBits + 7) / 8
820
   UINT32               dInSize,       // IN: data size
821
   BYTE                *dIn            // IN: cipher text buffer
822
   )
823
{
824
   SM4_KEY         Sm4Key;
825
   INT32           dSize;
826
   pAssert(dOut != NULL && key != NULL && dIn != NULL);
827
   if(dInSize == 0)
828
       return CRYPT_SUCCESS;
829
   pAssert(dInSize <= INT32_MAX);
830
   dSize = (INT32)dInSize;
831
   // For ECB, the data size must be an even multiple of the
832
   // cipher block size
833
   if((dSize % 16) != 0)
834
       return CRYPT_PARAMETER;
835
   // Create SM4 decryption key schedule
836
   if (SM4_set_decrypt_key(key, keySizeInBits, &Sm4Key) != 0)
837
       FAIL(FATAL_ERROR_INTERNAL);
838
   for(; dSize > 0; dSize -= 16)
839
   {
840
       SM4_decrypt(dIn, dOut, &Sm4Key);
841
       dIn = &dIn[16];
842
       dOut = &dOut[16];
843
   }
844
   return CRYPT_SUCCESS;
845
}
846
//
847
//
848
//       _cpri__SM4EncryptOFB()
849
//
850
//      This function performs SM4 encryption/decryption in OFB chain mode. The dIn buffer is modified to
851
//      contain the encrypted/decrypted text.
852
//      The input iv buffer is assumed to have a size equal to the block size (16 bytes). The returned value of iv
853
//      will be the nth encryption of the IV, where n is the number of blocks (full or partial) in the data stream.
854
//
855
//      Return Value                      Meaning
856
//
857
//      CRYPT_SUCCESS                     no non-fatal errors
858
//
859
LIB_EXPORT CRYPT_RESULT
860
_cpri__SM4EncryptOFB(
861
   BYTE                *dOut,          // OUT: the encrypted/decrypted data
862
   UINT32               keySizeInBits, // IN: key size in bit
863
   BYTE                *key,           // IN: key buffer. The size of this buffer in
864
                                       //     bytes is (keySizeInBits + 7) / 8
865
   BYTE                *iv,            // IN/OUT: IV for decryption. The size of this
866
                                       //     buffer is 16 byte
867
   UINT32              dInSize,         // IN: data size
868
   BYTE               *dIn              // IN: data buffer
869
   )
870
{
871
   BYTE           *pIv;
872
   SM4_KEY         Sm4Key;
873
   INT32           dSize;
874
   int             i;
875
   pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
876
   if(dInSize == 0)
877
       return CRYPT_SUCCESS;
878
   pAssert(dInSize <= INT32_MAX);
879
   dSize = (INT32)dInSize;
880
   // Create SM4 key schedule
881
   if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
882
       FAIL(FATAL_ERROR_INTERNAL);
883
   // This is written so that dIn and dOut may be the same
884
   for(; dSize > 0; dSize -= 16)
885
   {
886
       // Encrypt the current value of the "IV"
887
       SM4_encrypt(iv, iv, &Sm4Key);
888
        // XOR the encrypted IV into dIn to create the cipher text (dOut)
889
        pIv = iv;
890
        for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
891
            *dOut++ = (*pIv++ ^ *dIn++);
892
   }
893
   return CRYPT_SUCCESS;
894
}
895
#endif      //% TPM_ALG_SM4