blob: 755a036bca396fd72edcbff1cc12c45dcfca218c [file] [log] [blame]
Vadim Bendebury56797522015-05-20 10:32:25 -07001// 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__AESDecryptCTR()
348//
349// Counter mode decryption uses the same algorithm as encryption. The _cpri__AESDecryptCTR() function
350// is implemented as a macro call to _cpri__AESEncryptCTR(). (skip)
351//
352//% #define _cpri__AESDecryptCTR(dOut, keySize, key, iv, dInSize, dIn) \
353//% _cpri__AESEncryptCTR( \
354//% ((BYTE *)dOut), \
355//% ((UINT32)keySize), \
356//% ((BYTE *)key), \
357//% ((BYTE *)iv), \
358//% ((UINT32)dInSize), \
359//% ((BYTE *)dIn) \
360//% )
361//%
362// The //% is used by the prototype extraction program to cause it to include the
363// line in the prototype file after removing the //%. Need an extra line with
364//
365// nothing on it so that a blank line will separate this macro from the next definition.
366//
367// _cpri__AESEncryptECB()
368//
369// AES encryption in ECB mode. The data buffer is modified to contain the cipher text.
370//
371// Return Value Meaning
372//
373// CRYPT_SUCCESS no non-fatal errors
374//
375LIB_EXPORT CRYPT_RESULT
376_cpri__AESEncryptECB(
377 BYTE *dOut, // OUT: encrypted data
378 UINT32 keySizeInBits, // IN: key size in bit
379 BYTE *key, // IN: key buffer. The size of this buffer in
380 // bytes is (keySizeInBits + 7) / 8
381 UINT32 dInSize, // IN: data size
382 BYTE *dIn // IN: clear text buffer
383 )
384{
385 AES_KEY AesKey;
386 INT32 dSize;
387 pAssert(dOut != NULL && key != NULL && dIn != NULL);
388 if(dInSize == 0)
389 return CRYPT_SUCCESS;
390 pAssert(dInSize <= INT32_MAX);
391 dSize = (INT32)dInSize;
392 // For ECB, the data size must be an even multiple of the
393 // cipher block size
394 if((dSize % 16) != 0)
395 return CRYPT_PARAMETER;
396 // Create AES encrypting key schedule
397 if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
398 FAIL(FATAL_ERROR_INTERNAL);
399 for(; dSize > 0; dSize -= 16)
400 {
401 AES_encrypt(dIn, dOut, &AesKey);
402 dIn = &dIn[16];
403 dOut = &dOut[16];
404 }
405 return CRYPT_SUCCESS;
406}
407//
408//
409// _cpri__AESDecryptECB()
410//
411// This function performs AES decryption using ECB (not recommended). The cipher text dIn is decrypted
412// into dOut.
413//
414// Return Value Meaning
415//
416// CRYPT_SUCCESS no non-fatal errors
417//
418LIB_EXPORT CRYPT_RESULT
419_cpri__AESDecryptECB(
420 BYTE *dOut, // OUT: the clear text data
421 UINT32 keySizeInBits, // IN: key size in bit
422 BYTE *key, // IN: key buffer. The size of this buffer in
423 // bytes is (keySizeInBits + 7) / 8
424 UINT32 dInSize, // IN: data size
425 BYTE *dIn // IN: cipher text buffer
426 )
427{
428 AES_KEY AesKey;
429 INT32 dSize;
430 pAssert(dOut != NULL && key != NULL && dIn != NULL);
431 if(dInSize == 0)
432 return CRYPT_SUCCESS;
433 pAssert(dInSize <= INT32_MAX);
434 dSize = (INT32)dInSize;
435 // For ECB, the data size must be an even multiple of the
436 // cipher block size
437 if((dSize % 16) != 0)
438 return CRYPT_PARAMETER;
439 // Create AES decryption key schedule
440 if (AES_set_decrypt_key(key, keySizeInBits, &AesKey) != 0)
441 FAIL(FATAL_ERROR_INTERNAL);
442 for(; dSize > 0; dSize -= 16)
443 {
444 AES_decrypt(dIn, dOut, &AesKey);
445 dIn = &dIn[16];
446 dOut = &dOut[16];
447 }
448 return CRYPT_SUCCESS;
449}
450//
451//
452// _cpri__AESEncryptOFB()
453//
454// This function performs AES encryption/decryption in OFB chain mode. The dIn buffer is modified to
455// contain the encrypted/decrypted text.
456// The input iv buffer is assumed to have a size equal to the block size (16 bytes). The returned value of iv
457// will be the nth encryption of the IV, where n is the number of blocks (full or partial) in the data stream.
458//
459//
460//
461//
462// Return Value Meaning
463//
464// CRYPT_SUCCESS no non-fatal errors
465//
466LIB_EXPORT CRYPT_RESULT
467_cpri__AESEncryptOFB(
468 BYTE *dOut, // OUT: the encrypted/decrypted data
469 UINT32 keySizeInBits, // IN: key size in bit
470 BYTE *key, // IN: key buffer. The size of this buffer in
471 // bytes is (keySizeInBits + 7) / 8
472 BYTE *iv, // IN/OUT: IV for decryption. The size of this
473 // buffer is 16 byte
474 UINT32 dInSize, // IN: data size
475 BYTE *dIn // IN: data buffer
476 )
477{
478 BYTE *pIv;
479 AES_KEY AesKey;
480 INT32 dSize;
481 int i;
482 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
483 if(dInSize == 0)
484 return CRYPT_SUCCESS;
485 pAssert(dInSize <= INT32_MAX);
486 dSize = (INT32)dInSize;
487 // Create AES key schedule
488 if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
489 FAIL(FATAL_ERROR_INTERNAL);
490 // This is written so that dIn and dOut may be the same
491 for(; dSize > 0; dSize -= 16)
492 {
493 // Encrypt the current value of the "IV"
494 AES_encrypt(iv, iv, &AesKey);
495 // XOR the encrypted IV into dIn to create the cipher text (dOut)
496 pIv = iv;
497 for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
498 *dOut++ = (*pIv++ ^ *dIn++);
499 }
500 return CRYPT_SUCCESS;
501}
502//
503//
504// _cpri__AESDecryptOFB()
505//
506// OFB encryption and decryption use the same algorithms for both. The _cpri__AESDecryptOFB() function
507// is implemented as a macro call to _cpri__AESEncrytOFB(). (skip)
508//
509//%#define _cpri__AESDecryptOFB(dOut,keySizeInBits, key, iv, dInSize, dIn) \
510//% _cpri__AESEncryptOFB ( \
511//% ((BYTE *)dOut), \
512//% ((UINT32)keySizeInBits), \
513//% ((BYTE *)key), \
514//% ((BYTE *)iv), \
515//% ((UINT32)dInSize), \
516//% ((BYTE *)dIn) \
517//% )
518//%
519//
520#ifdef TPM_ALG_SM4 //%
521//
522//
523// SM4 Encryption
524//
525// _cpri__SM4EncryptCBC()
526//
527// This function performs SM4 encryption in CBC chain mode. The input dIn buffer is encrypted into dOut.
528// The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to
529// be a multiple of the block size.
530//
531// Return Value Meaning
532//
533// CRYPT_SUCCESS if success
534// CRYPT_PARAMETER dInSize is not a multiple of the block size
535//
536LIB_EXPORT CRYPT_RESULT
537_cpri__SM4EncryptCBC(
538 BYTE *dOut, // OUT:
539 UINT32 keySizeInBits, // IN: key size in bit
540 BYTE *key, // IN: key buffer. The size of this buffer in
541 // bytes is (keySizeInBits + 7) / 8
542 BYTE *iv, // IN/OUT: IV for decryption.
543 UINT32 dInSize, // IN: data size (is required to be a multiple
544 // of 16 bytes)
545 BYTE *dIn // IN: data buffer
546 )
547{
548 SM4_KEY Sm4Key;
549 BYTE *pIv;
550 INT32 dSize; // Need a signed version
551 int i;
552 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
553 if(dInSize == 0)
554 return CRYPT_SUCCESS;
555 pAssert(dInSize <= INT32_MAX);
556 dSize = (INT32)dInSize;
557 // For CBC, the data size must be an even multiple of the
558 // cipher block size
559 if((dSize % 16) != 0)
560 return CRYPT_PARAMETER;
561 // Create SM4 encrypt key schedule
562 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
563 FAIL(FATAL_ERROR_INTERNAL);
564 // XOR the data block into the IV, encrypt the IV into the IV
565 // and then copy the IV to the output
566 for(; dSize > 0; dSize -= 16)
567 {
568 pIv = iv;
569 for(i = 16; i > 0; i--)
570 *pIv++ ^= *dIn++;
571 SM4_encrypt(iv, iv, &Sm4Key);
572 pIv = iv;
573 for(i = 16; i > 0; i--)
574 *dOut++ = *pIv++;
575 }
576 return CRYPT_SUCCESS;
577}
578//
579//
580// _cpri__SM4DecryptCBC()
581//
582// This function performs SM4 decryption in CBC chain mode. The input dIn buffer is decrypted into dOut.
583// The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to
584// be a multiple of the block size.
585//
586// Return Value Meaning
587//
588// CRYPT_SUCCESS if success
589// CRYPT_PARAMETER dInSize is not a multiple of the block size
590//
591LIB_EXPORT CRYPT_RESULT
592_cpri__SM4DecryptCBC(
593 BYTE *dOut, // OUT: the decrypted data
594 UINT32 keySizeInBits, // IN: key size in bit
595 BYTE *key, // IN: key buffer. The size of this buffer in
596 // bytes is (keySizeInBits + 7) / 8
597 BYTE *iv, // IN/OUT: IV for decryption. The size of this
598 // buffer is 16 byte
599 UINT32 dInSize, // IN: data size
600 BYTE *dIn // IN: data buffer
601 )
602{
603 SM4_KEY Sm4Key;
604 BYTE *pIv;
605 int i;
606 BYTE tmp[16];
607 BYTE *pT = NULL;
608 INT32 dSize;
609 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
610 if(dInSize == 0)
611 return CRYPT_SUCCESS;
612 pAssert(dInSize <= INT32_MAX);
613 dSize = (INT32)dInSize;
614 // For CBC, the data size must be an even multiple of the
615 // cipher block size
616 if((dSize % 16) != 0)
617 return CRYPT_PARAMETER;
618 // Create SM4 key schedule
619 if (SM4_set_decrypt_key(key, keySizeInBits, &Sm4Key) != 0)
620 FAIL(FATAL_ERROR_INTERNAL);
621 // Copy the input data to a temp buffer, decrypt the buffer into the output;
622 // XOR in the IV, and copy the temp buffer to the IV and repeat.
623 for(; dSize > 0; dSize -= 16)
624 {
625 pT = tmp;
626 for(i = 16; i> 0; i--)
627 *pT++ = *dIn++;
628 SM4_decrypt(tmp, dOut, &Sm4Key);
629 pIv = iv;
630 pT = tmp;
631 for(i = 16; i> 0; i--)
632 {
633 *dOut++ ^= *pIv;
634//
635 *pIv++ = *pT++;
636 }
637 }
638 return CRYPT_SUCCESS;
639}
640//
641//
642// _cpri__SM4EncryptCFB()
643//
644// This function performs SM4 encryption in CFB chain mode. The dOut buffer receives the values
645// encrypted dIn. The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will
646// be modified to contain the last encrypted block.
647//
648// Return Value Meaning
649//
650// CRYPT_SUCCESS no non-fatal errors
651//
652LIB_EXPORT CRYPT_RESULT
653_cpri__SM4EncryptCFB(
654 BYTE *dOut, // OUT: the encrypted
655 UINT32 keySizeInBits, // IN: key size in bit
656 BYTE *key, // IN: key buffer. The size of this buffer in
657 // bytes is (keySizeInBits + 7) / 8
658 BYTE *iv, // IN/OUT: IV for decryption.
659 UINT32 dInSize, // IN: data size
660 BYTE *dIn // IN: data buffer
661 )
662{
663 BYTE *pIv;
664 SM4_KEY Sm4Key;
665 INT32 dSize; // Need a signed version of dInSize
666 int i;
667 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
668 if(dInSize == 0)
669 return CRYPT_SUCCESS;
670 pAssert(dInSize <= INT32_MAX);
671 dSize = (INT32)dInSize;
672 // Create SM4 encryption key schedule
673 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
674 FAIL(FATAL_ERROR_INTERNAL);
675 // Encrypt the IV into the IV, XOR in the data, and copy to output
676 for(; dSize > 0; dSize -= 16)
677 {
678 // Encrypt the current value of the IV
679 SM4_encrypt(iv, iv, &Sm4Key);
680 pIv = iv;
681 for(i = (int)(dSize < 16) ? dSize : 16; i > 0; i--)
682 // XOR the data into the IV to create the cipher text
683 // and put into the output
684 *dOut++ = *pIv++ ^= *dIn++;
685 }
686 return CRYPT_SUCCESS;
687}
688//
689//
690// _cpri__SM4DecryptCFB()
691//
692// This function performs SM4 decrypt in CFB chain mode. The dOut buffer receives the values decrypted
693// from dIn.
694//
695// The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will be modified to
696// contain the last decoded block, padded with zeros
697//
698// Return Value Meaning
699//
700// CRYPT_SUCCESS no non-fatal errors
701//
702LIB_EXPORT CRYPT_RESULT
703_cpri__SM4DecryptCFB(
704 BYTE *dOut, // OUT: the decrypted data
705 UINT32 keySizeInBits, // IN: key size in bit
706 BYTE *key, // IN: key buffer. The size of this buffer in
707 // bytes is (keySizeInBits + 7) / 8
708 BYTE *iv, // IN/OUT: IV for decryption.
709 UINT32 dInSize, // IN: data size
710 BYTE *dIn // IN: data buffer
711 )
712{
713 BYTE *pIv;
714 BYTE tmp[16];
715 int i;
716 BYTE *pT;
717 SM4_KEY Sm4Key;
718 INT32 dSize;
719 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
720 if(dInSize == 0)
721 return CRYPT_SUCCESS;
722 pAssert(dInSize <= INT32_MAX);
723 dSize = (INT32)dInSize;
724 // Create SM4 encryption key schedule
725 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
726 FAIL(FATAL_ERROR_INTERNAL);
727 for(; dSize > 0; dSize -= 16)
728 {
729 // Encrypt the IV into the temp buffer
730 SM4_encrypt(iv, tmp, &Sm4Key);
731 pT = tmp;
732 pIv = iv;
733 for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
734 // Copy the current cipher text to IV, XOR
735 // with the temp buffer and put into the output
736 *dOut++ = *pT++ ^ (*pIv++ = *dIn++);
737 }
738 // If the inner loop (i loop) was smaller than 16, then dSize
739 // would have been smaller than 16 and it is now negative
740 // If it is negative, then it indicates how may fill bytes
741 // are needed to pad out the IV for the next round.
742 for(; dSize < 0; dSize++)
743 *iv++ = 0;
744 return CRYPT_SUCCESS;
745}
746//
747//
748// _cpri__SM4EncryptCTR()
749//
750// This function performs SM4 encryption/decryption in CTR chain mode. The dIn buffer is encrypted into
751// dOut. The input iv buffer is assumed to have a size equal to the SM4 block size (16 bytes). The iv will be
752// incremented by the number of blocks (full and partial) that were encrypted.
753//
754// Return Value Meaning
755//
756// CRYPT_SUCCESS no non-fatal errors
757//
758LIB_EXPORT CRYPT_RESULT
759_cpri__SM4EncryptCTR(
760 BYTE *dOut, // OUT: the encrypted data
761 UINT32 keySizeInBits, // IN: key size in bit
762 BYTE *key, // IN: key buffer. The size of this buffer in
763 // bytes is (keySizeInBits + 7) / 8
764 BYTE *iv, // IN/OUT: IV for decryption.
765 UINT32 dInSize, // IN: data size
766 BYTE *dIn // IN: data buffer
767 )
768{
769 BYTE tmp[16];
770 BYTE *pT;
771 SM4_KEY Sm4Key;
772 int i;
773 INT32 dSize;
774 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
775 if(dInSize == 0)
776 return CRYPT_SUCCESS;
777 pAssert(dInSize <= INT32_MAX);
778 dSize = (INT32)dInSize;
779 // Create SM4 encryption schedule
780 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
781 FAIL(FATAL_ERROR_INTERNAL);
782 for(; dSize > 0; dSize--)
783 {
784 // Encrypt the current value of the IV(counter)
785 SM4_encrypt(iv, (BYTE *)tmp, &Sm4Key);
786 //increment the counter
787 for(i = 0; i < 16; i++)
788 if((iv[i] += 1) != 0)
789 break;
790 // XOR the encrypted counter value with input and put into output
791 pT = tmp;
792 for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
793 *dOut++ = *dIn++ ^ *pT++;
794 }
795 return CRYPT_SUCCESS;
796}
797//
798//
799// _cpri__SM4DecryptCTR()
800//
801// Counter mode decryption uses the same algorithm as encryption. The _cpri__SM4DecryptCTR() function
802// is implemented as a macro call to _cpri__SM4EncryptCTR(). (skip)
803//
804//% #define _cpri__SM4DecryptCTR(dOut, keySize, key, iv, dInSize, dIn) \
805//% _cpri__SM4EncryptCTR( \
806//% ((BYTE *)dOut), \
807//% ((UINT32)keySize), \
808//% ((BYTE *)key), \
809//% ((BYTE *)iv), \
810//% ((UINT32)dInSize), \
811//
812//% ((BYTE *)dIn) \
813//% )
814//%
815// The //% is used by the prototype extraction program to cause it to include the
816// line in the prototype file after removing the //%. Need an extra line with
817//
818// nothing on it so that a blank line will separate this macro from the next definition.
819//
820// _cpri__SM4EncryptECB()
821//
822// SM4 encryption in ECB mode. The data buffer is modified to contain the cipher text.
823//
824// Return Value Meaning
825//
826// CRYPT_SUCCESS no non-fatal errors
827//
828LIB_EXPORT CRYPT_RESULT
829_cpri__SM4EncryptECB(
830 BYTE *dOut, // OUT: encrypted data
831 UINT32 keySizeInBits, // IN: key size in bit
832 BYTE *key, // IN: key buffer. The size of this buffer in
833 // bytes is (keySizeInBits + 7) / 8
834 UINT32 dInSize, // IN: data size
835 BYTE *dIn // IN: clear text buffer
836 )
837{
838 SM4_KEY Sm4Key;
839 INT32 dSize;
840 pAssert(dOut != NULL && key != NULL && dIn != NULL);
841 if(dInSize == 0)
842 return CRYPT_SUCCESS;
843 pAssert(dInSize <= INT32_MAX);
844 dSize = (INT32)dInSize;
845 // For ECB, the data size must be an even multiple of the
846 // cipher block size
847 if((dSize % 16) != 0)
848 return CRYPT_PARAMETER;
849 // Create SM4 encrypting key schedule
850 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
851 FAIL(FATAL_ERROR_INTERNAL);
852 for(; dSize > 0; dSize -= 16)
853 {
854 SM4_encrypt(dIn, dOut, &Sm4Key);
855 dIn = &dIn[16];
856 dOut = &dOut[16];
857 }
858 return CRYPT_SUCCESS;
859}
860//
861//
862// _cpri__SM4DecryptECB()
863//
864// This function performs SM4 decryption using ECB (not recommended). The cipher text dIn is decrypted
865// into dOut.
866//
867//
868//
869//
870// Return Value Meaning
871//
872// CRYPT_SUCCESS no non-fatal errors
873//
874LIB_EXPORT CRYPT_RESULT
875_cpri__SM4DecryptECB(
876 BYTE *dOut, // OUT: the clear text data
877 UINT32 keySizeInBits, // IN: key size in bit
878 BYTE *key, // IN: key buffer. The size of this buffer in
879 // bytes is (keySizeInBits + 7) / 8
880 UINT32 dInSize, // IN: data size
881 BYTE *dIn // IN: cipher text buffer
882 )
883{
884 SM4_KEY Sm4Key;
885 INT32 dSize;
886 pAssert(dOut != NULL && key != NULL && dIn != NULL);
887 if(dInSize == 0)
888 return CRYPT_SUCCESS;
889 pAssert(dInSize <= INT32_MAX);
890 dSize = (INT32)dInSize;
891 // For ECB, the data size must be an even multiple of the
892 // cipher block size
893 if((dSize % 16) != 0)
894 return CRYPT_PARAMETER;
895 // Create SM4 decryption key schedule
896 if (SM4_set_decrypt_key(key, keySizeInBits, &Sm4Key) != 0)
897 FAIL(FATAL_ERROR_INTERNAL);
898 for(; dSize > 0; dSize -= 16)
899 {
900 SM4_decrypt(dIn, dOut, &Sm4Key);
901 dIn = &dIn[16];
902 dOut = &dOut[16];
903 }
904 return CRYPT_SUCCESS;
905}
906//
907//
908// _cpri__SM4EncryptOFB()
909//
910// This function performs SM4 encryption/decryption in OFB chain mode. The dIn buffer is modified to
911// contain the encrypted/decrypted text.
912// The input iv buffer is assumed to have a size equal to the block size (16 bytes). The returned value of iv
913// will be the nth encryption of the IV, where n is the number of blocks (full or partial) in the data stream.
914//
915// Return Value Meaning
916//
917// CRYPT_SUCCESS no non-fatal errors
918//
919LIB_EXPORT CRYPT_RESULT
920_cpri__SM4EncryptOFB(
921 BYTE *dOut, // OUT: the encrypted/decrypted data
922 UINT32 keySizeInBits, // IN: key size in bit
923 BYTE *key, // IN: key buffer. The size of this buffer in
924 // bytes is (keySizeInBits + 7) / 8
925 BYTE *iv, // IN/OUT: IV for decryption. The size of this
926 // buffer is 16 byte
927 UINT32 dInSize, // IN: data size
928 BYTE *dIn // IN: data buffer
929 )
930{
931 BYTE *pIv;
932 SM4_KEY Sm4Key;
933 INT32 dSize;
934 int i;
935 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
936 if(dInSize == 0)
937 return CRYPT_SUCCESS;
938 pAssert(dInSize <= INT32_MAX);
939 dSize = (INT32)dInSize;
940 // Create SM4 key schedule
941 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
942 FAIL(FATAL_ERROR_INTERNAL);
943 // This is written so that dIn and dOut may be the same
944 for(; dSize > 0; dSize -= 16)
945 {
946 // Encrypt the current value of the "IV"
947 SM4_encrypt(iv, iv, &Sm4Key);
948 // XOR the encrypted IV into dIn to create the cipher text (dOut)
949 pIv = iv;
950 for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
951 *dOut++ = (*pIv++ ^ *dIn++);
952 }
953 return CRYPT_SUCCESS;
954}
955//
956//
957// _cpri__SM4DecryptOFB()
958//
959// OFB encryption and decryption use the same algorithms for both. The _cpri__SM4DecryptOFB() function
960// is implemented as a macro call to _cpri__SM4EncrytOFB(). (skip)
961//
962//%#define _cpri__SM4DecryptOFB(dOut,keySizeInBits, key, iv, dInSize, dIn) \
963//% _cpri__SM4EncryptOFB ( \
964//% ((BYTE *)dOut), \
965//% ((UINT32)keySizeInBits), \
966//% ((BYTE *)key), \
967//% ((BYTE *)iv), \
968//% ((UINT32)dInSize), \
969//% ((BYTE *)dIn) \
970//% )
971//%
972#endif //% TPM_ALG_SM4