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
_cpri__SymStartup(void)25 _cpri__SymStartup(
26       void
27 )
28 {
29       return TRUE;
30 }
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
_cpri__GetSymmetricBlockSize(TPM_ALG_ID symmetricAlg,UINT16 keySizeInBits)43 _cpri__GetSymmetricBlockSize(
44       TPM_ALG_ID         symmetricAlg,        // IN: the symmetric algorithm
45       UINT16             keySizeInBits        // IN: the key size
46       )
47 {
48    switch (symmetricAlg)
49    {
50 #ifdef TPM_ALG_AES
51    case TPM_ALG_AES:
52 #endif
53 #ifdef TPM_ALG_SM4 // Both AES and SM4 use the same block size
54    case TPM_ALG_SM4:
55 #endif
56        if(keySizeInBits != 0) // This is mostly to have a reference to
57               // keySizeInBits for the compiler
58               return 16;
59          else
60              return 0;
61          break;
62     default:
63         return 0;
64     }
65 }
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
_cpri__AESEncryptCBC(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)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 {
93     AES_KEY         AesKey;
94     BYTE           *pIv;
95     INT32           dSize;              // Need a signed version
96     int             i;
97     pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
98     if(dInSize == 0)
99         return CRYPT_SUCCESS;
100     pAssert(dInSize <= INT32_MAX);
101     dSize = (INT32)dInSize;
102     // For CBC, the data size must be an even multiple of the
103     // cipher block size
104     if((dSize % 16) != 0)
105         return CRYPT_PARAMETER;
106     // Create AES encrypt key schedule
107     if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
108         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     for(; dSize > 0; dSize -= 16)
112     {
113          pIv = iv;
114          for(i = 16; i > 0; i--)
115              *pIv++ ^= *dIn++;
116          AES_encrypt(iv, iv, &AesKey);
117          pIv = iv;
118          for(i = 16; i > 0; i--)
119              *dOut++ = *pIv++;
120     }
121     return CRYPT_SUCCESS;
122 }
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
_cpri__AESDecryptCBC(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)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 {
148     AES_KEY         AesKey;
149     BYTE           *pIv;
150     int             i;
151     BYTE            tmp[16];
152     BYTE           *pT = NULL;
153     INT32           dSize;
154     pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
155     if(dInSize == 0)
156         return CRYPT_SUCCESS;
157     pAssert(dInSize <= INT32_MAX);
158     dSize = (INT32)dInSize;
159     // For CBC, the data size must be an even multiple of the
160     // cipher block size
161     if((dSize % 16) != 0)
162         return CRYPT_PARAMETER;
163     // Create AES key schedule
164     if (AES_set_decrypt_key(key, keySizeInBits, &AesKey) != 0)
165         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     for(; dSize > 0; dSize -= 16)
169     {
170 //
171         pT = tmp;
172         for(i = 16; i> 0; i--)
173             *pT++ = *dIn++;
174         AES_decrypt(tmp, dOut, &AesKey);
175         pIv = iv;
176         pT = tmp;
177         for(i = 16; i> 0; i--)
178         {
179             *dOut++ ^= *pIv;
180             *pIv++ = *pT++;
181         }
182    }
183    return CRYPT_SUCCESS;
184 }
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
_cpri__AESEncryptCFB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)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 {
208    BYTE           *pIv = NULL;
209    AES_KEY         AesKey;
210    INT32           dSize;               // Need a signed version of dInSize
211    int             i;
212    pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
213    if(dInSize == 0)
214        return CRYPT_SUCCESS;
215    pAssert(dInSize <= INT32_MAX);
216    dSize = (INT32)dInSize;
217    // Create AES encryption key schedule
218    if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
219        FAIL(FATAL_ERROR_INTERNAL);
220    // Encrypt the IV into the IV, XOR in the data, and copy to output
221    for(; dSize > 0; dSize -= 16)
222    {
223        // Encrypt the current value of the IV
224        AES_encrypt(iv, iv, &AesKey);
225        pIv = iv;
226        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            *dOut++ = *pIv++ ^= *dIn++;
230    }
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    for(; dSize < 0; dSize++)
235        *pIv++ = 0;
236    return CRYPT_SUCCESS;
237 }
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
_cpri__AESDecryptCFB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)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 {
262    BYTE           *pIv = NULL;
263    BYTE            tmp[16];
264    int             i;
265    BYTE           *pT;
266    AES_KEY         AesKey;
267    INT32           dSize;
268    pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
269    if(dInSize == 0)
270        return CRYPT_SUCCESS;
271    pAssert(dInSize <= INT32_MAX);
272    dSize = (INT32)dInSize;
273    // Create AES encryption key schedule
274    if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
275        FAIL(FATAL_ERROR_INTERNAL);
276    for(; dSize > 0; dSize -= 16)
277    {
278        // Encrypt the IV into the temp buffer
279        AES_encrypt(iv, tmp, &AesKey);
280        pT = tmp;
281        pIv = iv;
282        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            *dOut++ = *pT++ ^ (*pIv++ = *dIn++);
286    }
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    for(; dSize < 0; dSize++)
292        *pIv++ = 0;
293    return CRYPT_SUCCESS;
294 }
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
_cpri__AESEncryptCTR(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)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 {
318    BYTE            tmp[16];
319    BYTE           *pT;
320    AES_KEY         AesKey;
321    int             i;
322    INT32           dSize;
323    pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
324    if(dInSize == 0)
325        return CRYPT_SUCCESS;
326    pAssert(dInSize <= INT32_MAX);
327    dSize = (INT32)dInSize;
328    // Create AES encryption schedule
329    if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
330        FAIL(FATAL_ERROR_INTERNAL);
331    for(; dSize > 0; dSize -= 16)
332    {
333        // Encrypt the current value of the IV(counter)
334        AES_encrypt(iv, (BYTE *)tmp, &AesKey);
335         //increment the counter (counter is big-endian so start at end)
336         for(i = 15; i >= 0; i--)
337             if((iv[i] += 1) != 0)
338                 break;
339         // XOR the encrypted counter value with input and put into output
340         pT = tmp;
341         for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
342             *dOut++ = *dIn++ ^ *pT++;
343    }
344    return CRYPT_SUCCESS;
345 }
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
_cpri__AESEncryptECB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,UINT32 dInSize,BYTE * dIn)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 {
365     AES_KEY          AesKey;
366     INT32            dSize;
367     pAssert(dOut != NULL && key != NULL && dIn != NULL);
368     if(dInSize == 0)
369         return CRYPT_SUCCESS;
370     pAssert(dInSize <= INT32_MAX);
371     dSize = (INT32)dInSize;
372     // For ECB, the data size must be an even multiple of the
373     // cipher block size
374     if((dSize % 16) != 0)
375         return CRYPT_PARAMETER;
376     // Create AES encrypting key schedule
377     if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
378         FAIL(FATAL_ERROR_INTERNAL);
379     for(; dSize > 0; dSize -= 16)
380     {
381         AES_encrypt(dIn, dOut, &AesKey);
382         dIn = &dIn[16];
383         dOut = &dOut[16];
384     }
385    return CRYPT_SUCCESS;
386 }
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
_cpri__AESDecryptECB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,UINT32 dInSize,BYTE * dIn)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 {
408    AES_KEY         AesKey;
409    INT32           dSize;
410    pAssert(dOut != NULL && key != NULL && dIn != NULL);
411    if(dInSize == 0)
412        return CRYPT_SUCCESS;
413    pAssert(dInSize <= INT32_MAX);
414    dSize = (INT32)dInSize;
415    // For ECB, the data size must be an even multiple of the
416    // cipher block size
417    if((dSize % 16) != 0)
418        return CRYPT_PARAMETER;
419    // Create AES decryption key schedule
420    if (AES_set_decrypt_key(key, keySizeInBits, &AesKey) != 0)
421        FAIL(FATAL_ERROR_INTERNAL);
422    for(; dSize > 0; dSize -= 16)
423    {
424        AES_decrypt(dIn, dOut, &AesKey);
425        dIn = &dIn[16];
426        dOut = &dOut[16];
427    }
428    return CRYPT_SUCCESS;
429 }
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
_cpri__AESEncryptOFB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)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 {
458    BYTE           *pIv;
459    AES_KEY         AesKey;
460    INT32           dSize;
461    int             i;
462    pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
463    if(dInSize == 0)
464        return CRYPT_SUCCESS;
465    pAssert(dInSize <= INT32_MAX);
466    dSize = (INT32)dInSize;
467    // Create AES key schedule
468    if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
469        FAIL(FATAL_ERROR_INTERNAL);
470    // This is written so that dIn and dOut may be the same
471    for(; dSize > 0; dSize -= 16)
472    {
473        // Encrypt the current value of the "IV"
474        AES_encrypt(iv, iv, &AesKey);
475         // XOR the encrypted IV into dIn to create the cipher text (dOut)
476         pIv = iv;
477         for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
478             *dOut++ = (*pIv++ ^ *dIn++);
479    }
480    return CRYPT_SUCCESS;
481 }
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
_cpri__SM4EncryptCBC(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)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
_cpri__SM4DecryptCBC(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)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
_cpri__SM4EncryptCFB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)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
_cpri__SM4DecryptCFB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)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
_cpri__SM4EncryptCTR(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)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
_cpri__SM4EncryptECB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,UINT32 dInSize,BYTE * dIn)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
_cpri__SM4DecryptECB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,UINT32 dInSize,BYTE * dIn)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
_cpri__SM4EncryptOFB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)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
896