blob: e05a4d13ddc23e3a22df92113a9b226b339d0050 [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//
Vadim Bendebury56797522015-05-20 10:32:25 -0700347// _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}
Vadim Bendeburybceae452015-05-29 12:58:51 -0700482#ifdef TPM_ALG_SM4
Vadim Bendebury56797522015-05-20 10:32:25 -0700483//
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//
Vadim Bendebury56797522015-05-20 10:32:25 -0700760// _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}
Vadim Bendebury56797522015-05-20 10:32:25 -0700895#endif //% TPM_ALG_SM4