Home | History | Annotate | Download | only in tpm2
      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 {
     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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    896