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// 13typedef 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// 24LIB_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// 42LIB_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// 81LIB_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// 136LIB_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// 197LIB_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// 251LIB_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// 307LIB_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// 355LIB_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// 398LIB_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// 446LIB_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// 498LIB_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// 553LIB_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// 614LIB_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// 664LIB_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// 720LIB_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// 768LIB_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// 814LIB_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// 859LIB_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