1 // This file was extracted from the TCG Published
2 // Trusted Platform Module Library
3 // Part 4: Supporting Routines
4 // Family "2.0"
5 // Level 00 Revision 01.16
6 // October 30, 2014
7
8 #include "OsslCryptoEngine.h"
9 //
10 // The following sets of defines are used to allow use of the SM4 algorithm identifier while waiting for the
11 // SM4 implementation code to appear.
12 //
13 typedef AES_KEY SM4_KEY;
14 #define SM4_set_encrypt_key AES_set_encrypt_key
15 #define SM4_set_decrypt_key AES_set_decrypt_key
16 #define SM4_decrypt AES_decrypt
17 #define SM4_encrypt AES_encrypt
18 //
19 //
20 // Utility Functions
21 //
22 // _cpri_SymStartup()
23 //
24 LIB_EXPORT BOOL
_cpri__SymStartup(void)25 _cpri__SymStartup(
26 void
27 )
28 {
29 return TRUE;
30 }
31 //
32 //
33 // _cpri__GetSymmetricBlockSize()
34 //
35 // This function returns the block size of the algorithm.
36 //
37 // Return Value Meaning
38 //
39 // <= 0 cipher not supported
40 // >0 the cipher block size in bytes
41 //
42 LIB_EXPORT INT16
_cpri__GetSymmetricBlockSize(TPM_ALG_ID symmetricAlg,UINT16 keySizeInBits)43 _cpri__GetSymmetricBlockSize(
44 TPM_ALG_ID symmetricAlg, // IN: the symmetric algorithm
45 UINT16 keySizeInBits // IN: the key size
46 )
47 {
48 switch (symmetricAlg)
49 {
50 #ifdef TPM_ALG_AES
51 case TPM_ALG_AES:
52 #endif
53 #ifdef TPM_ALG_SM4 // Both AES and SM4 use the same block size
54 case TPM_ALG_SM4:
55 #endif
56 if(keySizeInBits != 0) // This is mostly to have a reference to
57 // keySizeInBits for the compiler
58 return 16;
59 else
60 return 0;
61 break;
62 default:
63 return 0;
64 }
65 }
66 //
67 //
68 // AES Encryption
69 //
70 // _cpri__AESEncryptCBC()
71 //
72 // This function performs AES encryption in CBC chain mode. The input dIn buffer is encrypted into dOut.
73 // The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to
74 // be a multiple of the block size.
75 //
76 // Return Value Meaning
77 //
78 // CRYPT_SUCCESS if success
79 // CRYPT_PARAMETER dInSize is not a multiple of the block size
80 //
81 LIB_EXPORT CRYPT_RESULT
_cpri__AESEncryptCBC(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)82 _cpri__AESEncryptCBC(
83 BYTE *dOut, // OUT:
84 UINT32 keySizeInBits, // IN: key size in bit
85 BYTE *key, // IN: key buffer. The size of this buffer in
86 // bytes is (keySizeInBits + 7) / 8
87 BYTE *iv, // IN/OUT: IV for decryption.
88 UINT32 dInSize, // IN: data size (is required to be a multiple
89 // of 16 bytes)
90 BYTE *dIn // IN: data buffer
91 )
92 {
93 AES_KEY AesKey;
94 BYTE *pIv;
95 INT32 dSize; // Need a signed version
96 int i;
97 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
98 if(dInSize == 0)
99 return CRYPT_SUCCESS;
100 pAssert(dInSize <= INT32_MAX);
101 dSize = (INT32)dInSize;
102 // For CBC, the data size must be an even multiple of the
103 // cipher block size
104 if((dSize % 16) != 0)
105 return CRYPT_PARAMETER;
106 // Create AES encrypt key schedule
107 if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
108 FAIL(FATAL_ERROR_INTERNAL);
109 // XOR the data block into the IV, encrypt the IV into the IV
110 // and then copy the IV to the output
111 for(; dSize > 0; dSize -= 16)
112 {
113 pIv = iv;
114 for(i = 16; i > 0; i--)
115 *pIv++ ^= *dIn++;
116 AES_encrypt(iv, iv, &AesKey);
117 pIv = iv;
118 for(i = 16; i > 0; i--)
119 *dOut++ = *pIv++;
120 }
121 return CRYPT_SUCCESS;
122 }
123 //
124 //
125 // _cpri__AESDecryptCBC()
126 //
127 // This function performs AES decryption in CBC chain mode. The input dIn buffer is decrypted into dOut.
128 // The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to
129 // be a multiple of the block size.
130 //
131 // Return Value Meaning
132 //
133 // CRYPT_SUCCESS if success
134 // CRYPT_PARAMETER dInSize is not a multiple of the block size
135 //
136 LIB_EXPORT CRYPT_RESULT
_cpri__AESDecryptCBC(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)137 _cpri__AESDecryptCBC(
138 BYTE *dOut, // OUT: the decrypted data
139 UINT32 keySizeInBits, // IN: key size in bit
140 BYTE *key, // IN: key buffer. The size of this buffer in
141 // bytes is (keySizeInBits + 7) / 8
142 BYTE *iv, // IN/OUT: IV for decryption. The size of this
143 // buffer is 16 byte
144 UINT32 dInSize, // IN: data size
145 BYTE *dIn // IN: data buffer
146 )
147 {
148 AES_KEY AesKey;
149 BYTE *pIv;
150 int i;
151 BYTE tmp[16];
152 BYTE *pT = NULL;
153 INT32 dSize;
154 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
155 if(dInSize == 0)
156 return CRYPT_SUCCESS;
157 pAssert(dInSize <= INT32_MAX);
158 dSize = (INT32)dInSize;
159 // For CBC, the data size must be an even multiple of the
160 // cipher block size
161 if((dSize % 16) != 0)
162 return CRYPT_PARAMETER;
163 // Create AES key schedule
164 if (AES_set_decrypt_key(key, keySizeInBits, &AesKey) != 0)
165 FAIL(FATAL_ERROR_INTERNAL);
166 // Copy the input data to a temp buffer, decrypt the buffer into the output;
167 // XOR in the IV, and copy the temp buffer to the IV and repeat.
168 for(; dSize > 0; dSize -= 16)
169 {
170 //
171 pT = tmp;
172 for(i = 16; i> 0; i--)
173 *pT++ = *dIn++;
174 AES_decrypt(tmp, dOut, &AesKey);
175 pIv = iv;
176 pT = tmp;
177 for(i = 16; i> 0; i--)
178 {
179 *dOut++ ^= *pIv;
180 *pIv++ = *pT++;
181 }
182 }
183 return CRYPT_SUCCESS;
184 }
185 //
186 //
187 // _cpri__AESEncryptCFB()
188 //
189 // This function performs AES encryption in CFB chain mode. The dOut buffer receives the values
190 // encrypted dIn. The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will
191 // be modified to contain the last encrypted block.
192 //
193 // Return Value Meaning
194 //
195 // CRYPT_SUCCESS no non-fatal errors
196 //
197 LIB_EXPORT CRYPT_RESULT
_cpri__AESEncryptCFB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)198 _cpri__AESEncryptCFB(
199 BYTE *dOut, // OUT: the encrypted
200 UINT32 keySizeInBits, // IN: key size in bit
201 BYTE *key, // IN: key buffer. The size of this buffer in
202 // bytes is (keySizeInBits + 7) / 8
203 BYTE *iv, // IN/OUT: IV for decryption.
204 UINT32 dInSize, // IN: data size
205 BYTE *dIn // IN: data buffer
206 )
207 {
208 BYTE *pIv = NULL;
209 AES_KEY AesKey;
210 INT32 dSize; // Need a signed version of dInSize
211 int i;
212 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
213 if(dInSize == 0)
214 return CRYPT_SUCCESS;
215 pAssert(dInSize <= INT32_MAX);
216 dSize = (INT32)dInSize;
217 // Create AES encryption key schedule
218 if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
219 FAIL(FATAL_ERROR_INTERNAL);
220 // Encrypt the IV into the IV, XOR in the data, and copy to output
221 for(; dSize > 0; dSize -= 16)
222 {
223 // Encrypt the current value of the IV
224 AES_encrypt(iv, iv, &AesKey);
225 pIv = iv;
226 for(i = (int)(dSize < 16) ? dSize : 16; i > 0; i--)
227 // XOR the data into the IV to create the cipher text
228 // and put into the output
229 *dOut++ = *pIv++ ^= *dIn++;
230 }
231 // If the inner loop (i loop) was smaller than 16, then dSize would have been
232 // smaller than 16 and it is now negative. If it is negative, then it indicates
233 // how many bytes are needed to pad out the IV for the next round.
234 for(; dSize < 0; dSize++)
235 *pIv++ = 0;
236 return CRYPT_SUCCESS;
237 }
238 //
239 //
240 // _cpri__AESDecryptCFB()
241 //
242 // This function performs AES decrypt in CFB chain mode. The dOut buffer receives the values decrypted
243 // from dIn.
244 // The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will be modified to
245 // contain the last decoded block, padded with zeros
246 //
247 // Return Value Meaning
248 //
249 // CRYPT_SUCCESS no non-fatal errors
250 //
251 LIB_EXPORT CRYPT_RESULT
_cpri__AESDecryptCFB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)252 _cpri__AESDecryptCFB(
253 BYTE *dOut, // OUT: the decrypted data
254 UINT32 keySizeInBits, // IN: key size in bit
255 BYTE *key, // IN: key buffer. The size of this buffer in
256 // bytes is (keySizeInBits + 7) / 8
257 BYTE *iv, // IN/OUT: IV for decryption.
258 UINT32 dInSize, // IN: data size
259 BYTE *dIn // IN: data buffer
260 )
261 {
262 BYTE *pIv = NULL;
263 BYTE tmp[16];
264 int i;
265 BYTE *pT;
266 AES_KEY AesKey;
267 INT32 dSize;
268 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
269 if(dInSize == 0)
270 return CRYPT_SUCCESS;
271 pAssert(dInSize <= INT32_MAX);
272 dSize = (INT32)dInSize;
273 // Create AES encryption key schedule
274 if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
275 FAIL(FATAL_ERROR_INTERNAL);
276 for(; dSize > 0; dSize -= 16)
277 {
278 // Encrypt the IV into the temp buffer
279 AES_encrypt(iv, tmp, &AesKey);
280 pT = tmp;
281 pIv = iv;
282 for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
283 // Copy the current cipher text to IV, XOR
284 // with the temp buffer and put into the output
285 *dOut++ = *pT++ ^ (*pIv++ = *dIn++);
286 }
287 // If the inner loop (i loop) was smaller than 16, then dSize
288 // would have been smaller than 16 and it is now negative
289 // If it is negative, then it indicates how may fill bytes
290 // are needed to pad out the IV for the next round.
291 for(; dSize < 0; dSize++)
292 *pIv++ = 0;
293 return CRYPT_SUCCESS;
294 }
295 //
296 //
297 // _cpri__AESEncryptCTR()
298 //
299 // This function performs AES encryption/decryption in CTR chain mode. The dIn buffer is encrypted into
300 // dOut. The input iv buffer is assumed to have a size equal to the AES block size (16 bytes). The iv will be
301 // incremented by the number of blocks (full and partial) that were encrypted.
302 //
303 // Return Value Meaning
304 //
305 // CRYPT_SUCCESS no non-fatal errors
306 //
307 LIB_EXPORT CRYPT_RESULT
_cpri__AESEncryptCTR(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)308 _cpri__AESEncryptCTR(
309 BYTE *dOut, // OUT: the encrypted data
310 UINT32 keySizeInBits, // IN: key size in bit
311 BYTE *key, // IN: key buffer. The size of this buffer in
312 // bytes is (keySizeInBits + 7) / 8
313 BYTE *iv, // IN/OUT: IV for decryption.
314 UINT32 dInSize, // IN: data size
315 BYTE *dIn // IN: data buffer
316 )
317 {
318 BYTE tmp[16];
319 BYTE *pT;
320 AES_KEY AesKey;
321 int i;
322 INT32 dSize;
323 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
324 if(dInSize == 0)
325 return CRYPT_SUCCESS;
326 pAssert(dInSize <= INT32_MAX);
327 dSize = (INT32)dInSize;
328 // Create AES encryption schedule
329 if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
330 FAIL(FATAL_ERROR_INTERNAL);
331 for(; dSize > 0; dSize -= 16)
332 {
333 // Encrypt the current value of the IV(counter)
334 AES_encrypt(iv, (BYTE *)tmp, &AesKey);
335 //increment the counter (counter is big-endian so start at end)
336 for(i = 15; i >= 0; i--)
337 if((iv[i] += 1) != 0)
338 break;
339 // XOR the encrypted counter value with input and put into output
340 pT = tmp;
341 for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
342 *dOut++ = *dIn++ ^ *pT++;
343 }
344 return CRYPT_SUCCESS;
345 }
346 //
347 // _cpri__AESEncryptECB()
348 //
349 // AES encryption in ECB mode. The data buffer is modified to contain the cipher text.
350 //
351 // Return Value Meaning
352 //
353 // CRYPT_SUCCESS no non-fatal errors
354 //
355 LIB_EXPORT CRYPT_RESULT
_cpri__AESEncryptECB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,UINT32 dInSize,BYTE * dIn)356 _cpri__AESEncryptECB(
357 BYTE *dOut, // OUT: encrypted data
358 UINT32 keySizeInBits, // IN: key size in bit
359 BYTE *key, // IN: key buffer. The size of this buffer in
360 // bytes is (keySizeInBits + 7) / 8
361 UINT32 dInSize, // IN: data size
362 BYTE *dIn // IN: clear text buffer
363 )
364 {
365 AES_KEY AesKey;
366 INT32 dSize;
367 pAssert(dOut != NULL && key != NULL && dIn != NULL);
368 if(dInSize == 0)
369 return CRYPT_SUCCESS;
370 pAssert(dInSize <= INT32_MAX);
371 dSize = (INT32)dInSize;
372 // For ECB, the data size must be an even multiple of the
373 // cipher block size
374 if((dSize % 16) != 0)
375 return CRYPT_PARAMETER;
376 // Create AES encrypting key schedule
377 if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
378 FAIL(FATAL_ERROR_INTERNAL);
379 for(; dSize > 0; dSize -= 16)
380 {
381 AES_encrypt(dIn, dOut, &AesKey);
382 dIn = &dIn[16];
383 dOut = &dOut[16];
384 }
385 return CRYPT_SUCCESS;
386 }
387 //
388 //
389 // _cpri__AESDecryptECB()
390 //
391 // This function performs AES decryption using ECB (not recommended). The cipher text dIn is decrypted
392 // into dOut.
393 //
394 // Return Value Meaning
395 //
396 // CRYPT_SUCCESS no non-fatal errors
397 //
398 LIB_EXPORT CRYPT_RESULT
_cpri__AESDecryptECB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,UINT32 dInSize,BYTE * dIn)399 _cpri__AESDecryptECB(
400 BYTE *dOut, // OUT: the clear text data
401 UINT32 keySizeInBits, // IN: key size in bit
402 BYTE *key, // IN: key buffer. The size of this buffer in
403 // bytes is (keySizeInBits + 7) / 8
404 UINT32 dInSize, // IN: data size
405 BYTE *dIn // IN: cipher text buffer
406 )
407 {
408 AES_KEY AesKey;
409 INT32 dSize;
410 pAssert(dOut != NULL && key != NULL && dIn != NULL);
411 if(dInSize == 0)
412 return CRYPT_SUCCESS;
413 pAssert(dInSize <= INT32_MAX);
414 dSize = (INT32)dInSize;
415 // For ECB, the data size must be an even multiple of the
416 // cipher block size
417 if((dSize % 16) != 0)
418 return CRYPT_PARAMETER;
419 // Create AES decryption key schedule
420 if (AES_set_decrypt_key(key, keySizeInBits, &AesKey) != 0)
421 FAIL(FATAL_ERROR_INTERNAL);
422 for(; dSize > 0; dSize -= 16)
423 {
424 AES_decrypt(dIn, dOut, &AesKey);
425 dIn = &dIn[16];
426 dOut = &dOut[16];
427 }
428 return CRYPT_SUCCESS;
429 }
430 //
431 //
432 // _cpri__AESEncryptOFB()
433 //
434 // This function performs AES encryption/decryption in OFB chain mode. The dIn buffer is modified to
435 // contain the encrypted/decrypted text.
436 // The input iv buffer is assumed to have a size equal to the block size (16 bytes). The returned value of iv
437 // will be the nth encryption of the IV, where n is the number of blocks (full or partial) in the data stream.
438 //
439 //
440 //
441 //
442 // Return Value Meaning
443 //
444 // CRYPT_SUCCESS no non-fatal errors
445 //
446 LIB_EXPORT CRYPT_RESULT
_cpri__AESEncryptOFB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)447 _cpri__AESEncryptOFB(
448 BYTE *dOut, // OUT: the encrypted/decrypted data
449 UINT32 keySizeInBits, // IN: key size in bit
450 BYTE *key, // IN: key buffer. The size of this buffer in
451 // bytes is (keySizeInBits + 7) / 8
452 BYTE *iv, // IN/OUT: IV for decryption. The size of this
453 // buffer is 16 byte
454 UINT32 dInSize, // IN: data size
455 BYTE *dIn // IN: data buffer
456 )
457 {
458 BYTE *pIv;
459 AES_KEY AesKey;
460 INT32 dSize;
461 int i;
462 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
463 if(dInSize == 0)
464 return CRYPT_SUCCESS;
465 pAssert(dInSize <= INT32_MAX);
466 dSize = (INT32)dInSize;
467 // Create AES key schedule
468 if (AES_set_encrypt_key(key, keySizeInBits, &AesKey) != 0)
469 FAIL(FATAL_ERROR_INTERNAL);
470 // This is written so that dIn and dOut may be the same
471 for(; dSize > 0; dSize -= 16)
472 {
473 // Encrypt the current value of the "IV"
474 AES_encrypt(iv, iv, &AesKey);
475 // XOR the encrypted IV into dIn to create the cipher text (dOut)
476 pIv = iv;
477 for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
478 *dOut++ = (*pIv++ ^ *dIn++);
479 }
480 return CRYPT_SUCCESS;
481 }
482 #ifdef TPM_ALG_SM4
483 //
484 //
485 // SM4 Encryption
486 //
487 // _cpri__SM4EncryptCBC()
488 //
489 // This function performs SM4 encryption in CBC chain mode. The input dIn buffer is encrypted into dOut.
490 // The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to
491 // be a multiple of the block size.
492 //
493 // Return Value Meaning
494 //
495 // CRYPT_SUCCESS if success
496 // CRYPT_PARAMETER dInSize is not a multiple of the block size
497 //
498 LIB_EXPORT CRYPT_RESULT
_cpri__SM4EncryptCBC(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)499 _cpri__SM4EncryptCBC(
500 BYTE *dOut, // OUT:
501 UINT32 keySizeInBits, // IN: key size in bit
502 BYTE *key, // IN: key buffer. The size of this buffer in
503 // bytes is (keySizeInBits + 7) / 8
504 BYTE *iv, // IN/OUT: IV for decryption.
505 UINT32 dInSize, // IN: data size (is required to be a multiple
506 // of 16 bytes)
507 BYTE *dIn // IN: data buffer
508 )
509 {
510 SM4_KEY Sm4Key;
511 BYTE *pIv;
512 INT32 dSize; // Need a signed version
513 int i;
514 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
515 if(dInSize == 0)
516 return CRYPT_SUCCESS;
517 pAssert(dInSize <= INT32_MAX);
518 dSize = (INT32)dInSize;
519 // For CBC, the data size must be an even multiple of the
520 // cipher block size
521 if((dSize % 16) != 0)
522 return CRYPT_PARAMETER;
523 // Create SM4 encrypt key schedule
524 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
525 FAIL(FATAL_ERROR_INTERNAL);
526 // XOR the data block into the IV, encrypt the IV into the IV
527 // and then copy the IV to the output
528 for(; dSize > 0; dSize -= 16)
529 {
530 pIv = iv;
531 for(i = 16; i > 0; i--)
532 *pIv++ ^= *dIn++;
533 SM4_encrypt(iv, iv, &Sm4Key);
534 pIv = iv;
535 for(i = 16; i > 0; i--)
536 *dOut++ = *pIv++;
537 }
538 return CRYPT_SUCCESS;
539 }
540 //
541 //
542 // _cpri__SM4DecryptCBC()
543 //
544 // This function performs SM4 decryption in CBC chain mode. The input dIn buffer is decrypted into dOut.
545 // The input iv buffer is required to have a size equal to the block size (16 bytes). The dInSize is required to
546 // be a multiple of the block size.
547 //
548 // Return Value Meaning
549 //
550 // CRYPT_SUCCESS if success
551 // CRYPT_PARAMETER dInSize is not a multiple of the block size
552 //
553 LIB_EXPORT CRYPT_RESULT
_cpri__SM4DecryptCBC(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)554 _cpri__SM4DecryptCBC(
555 BYTE *dOut, // OUT: the decrypted data
556 UINT32 keySizeInBits, // IN: key size in bit
557 BYTE *key, // IN: key buffer. The size of this buffer in
558 // bytes is (keySizeInBits + 7) / 8
559 BYTE *iv, // IN/OUT: IV for decryption. The size of this
560 // buffer is 16 byte
561 UINT32 dInSize, // IN: data size
562 BYTE *dIn // IN: data buffer
563 )
564 {
565 SM4_KEY Sm4Key;
566 BYTE *pIv;
567 int i;
568 BYTE tmp[16];
569 BYTE *pT = NULL;
570 INT32 dSize;
571 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
572 if(dInSize == 0)
573 return CRYPT_SUCCESS;
574 pAssert(dInSize <= INT32_MAX);
575 dSize = (INT32)dInSize;
576 // For CBC, the data size must be an even multiple of the
577 // cipher block size
578 if((dSize % 16) != 0)
579 return CRYPT_PARAMETER;
580 // Create SM4 key schedule
581 if (SM4_set_decrypt_key(key, keySizeInBits, &Sm4Key) != 0)
582 FAIL(FATAL_ERROR_INTERNAL);
583 // Copy the input data to a temp buffer, decrypt the buffer into the output;
584 // XOR in the IV, and copy the temp buffer to the IV and repeat.
585 for(; dSize > 0; dSize -= 16)
586 {
587 pT = tmp;
588 for(i = 16; i> 0; i--)
589 *pT++ = *dIn++;
590 SM4_decrypt(tmp, dOut, &Sm4Key);
591 pIv = iv;
592 pT = tmp;
593 for(i = 16; i> 0; i--)
594 {
595 *dOut++ ^= *pIv;
596 //
597 *pIv++ = *pT++;
598 }
599 }
600 return CRYPT_SUCCESS;
601 }
602 //
603 //
604 // _cpri__SM4EncryptCFB()
605 //
606 // This function performs SM4 encryption in CFB chain mode. The dOut buffer receives the values
607 // encrypted dIn. The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will
608 // be modified to contain the last encrypted block.
609 //
610 // Return Value Meaning
611 //
612 // CRYPT_SUCCESS no non-fatal errors
613 //
614 LIB_EXPORT CRYPT_RESULT
_cpri__SM4EncryptCFB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)615 _cpri__SM4EncryptCFB(
616 BYTE *dOut, // OUT: the encrypted
617 UINT32 keySizeInBits, // IN: key size in bit
618 BYTE *key, // IN: key buffer. The size of this buffer in
619 // bytes is (keySizeInBits + 7) / 8
620 BYTE *iv, // IN/OUT: IV for decryption.
621 UINT32 dInSize, // IN: data size
622 BYTE *dIn // IN: data buffer
623 )
624 {
625 BYTE *pIv;
626 SM4_KEY Sm4Key;
627 INT32 dSize; // Need a signed version of dInSize
628 int i;
629 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
630 if(dInSize == 0)
631 return CRYPT_SUCCESS;
632 pAssert(dInSize <= INT32_MAX);
633 dSize = (INT32)dInSize;
634 // Create SM4 encryption key schedule
635 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
636 FAIL(FATAL_ERROR_INTERNAL);
637 // Encrypt the IV into the IV, XOR in the data, and copy to output
638 for(; dSize > 0; dSize -= 16)
639 {
640 // Encrypt the current value of the IV
641 SM4_encrypt(iv, iv, &Sm4Key);
642 pIv = iv;
643 for(i = (int)(dSize < 16) ? dSize : 16; i > 0; i--)
644 // XOR the data into the IV to create the cipher text
645 // and put into the output
646 *dOut++ = *pIv++ ^= *dIn++;
647 }
648 return CRYPT_SUCCESS;
649 }
650 //
651 //
652 // _cpri__SM4DecryptCFB()
653 //
654 // This function performs SM4 decrypt in CFB chain mode. The dOut buffer receives the values decrypted
655 // from dIn.
656 //
657 // The input iv is assumed to be the size of an encryption block (16 bytes). The iv buffer will be modified to
658 // contain the last decoded block, padded with zeros
659 //
660 // Return Value Meaning
661 //
662 // CRYPT_SUCCESS no non-fatal errors
663 //
664 LIB_EXPORT CRYPT_RESULT
_cpri__SM4DecryptCFB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)665 _cpri__SM4DecryptCFB(
666 BYTE *dOut, // OUT: the decrypted data
667 UINT32 keySizeInBits, // IN: key size in bit
668 BYTE *key, // IN: key buffer. The size of this buffer in
669 // bytes is (keySizeInBits + 7) / 8
670 BYTE *iv, // IN/OUT: IV for decryption.
671 UINT32 dInSize, // IN: data size
672 BYTE *dIn // IN: data buffer
673 )
674 {
675 BYTE *pIv;
676 BYTE tmp[16];
677 int i;
678 BYTE *pT;
679 SM4_KEY Sm4Key;
680 INT32 dSize;
681 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
682 if(dInSize == 0)
683 return CRYPT_SUCCESS;
684 pAssert(dInSize <= INT32_MAX);
685 dSize = (INT32)dInSize;
686 // Create SM4 encryption key schedule
687 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
688 FAIL(FATAL_ERROR_INTERNAL);
689 for(; dSize > 0; dSize -= 16)
690 {
691 // Encrypt the IV into the temp buffer
692 SM4_encrypt(iv, tmp, &Sm4Key);
693 pT = tmp;
694 pIv = iv;
695 for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
696 // Copy the current cipher text to IV, XOR
697 // with the temp buffer and put into the output
698 *dOut++ = *pT++ ^ (*pIv++ = *dIn++);
699 }
700 // If the inner loop (i loop) was smaller than 16, then dSize
701 // would have been smaller than 16 and it is now negative
702 // If it is negative, then it indicates how may fill bytes
703 // are needed to pad out the IV for the next round.
704 for(; dSize < 0; dSize++)
705 *iv++ = 0;
706 return CRYPT_SUCCESS;
707 }
708 //
709 //
710 // _cpri__SM4EncryptCTR()
711 //
712 // This function performs SM4 encryption/decryption in CTR chain mode. The dIn buffer is encrypted into
713 // dOut. The input iv buffer is assumed to have a size equal to the SM4 block size (16 bytes). The iv will be
714 // incremented by the number of blocks (full and partial) that were encrypted.
715 //
716 // Return Value Meaning
717 //
718 // CRYPT_SUCCESS no non-fatal errors
719 //
720 LIB_EXPORT CRYPT_RESULT
_cpri__SM4EncryptCTR(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)721 _cpri__SM4EncryptCTR(
722 BYTE *dOut, // OUT: the encrypted data
723 UINT32 keySizeInBits, // IN: key size in bit
724 BYTE *key, // IN: key buffer. The size of this buffer in
725 // bytes is (keySizeInBits + 7) / 8
726 BYTE *iv, // IN/OUT: IV for decryption.
727 UINT32 dInSize, // IN: data size
728 BYTE *dIn // IN: data buffer
729 )
730 {
731 BYTE tmp[16];
732 BYTE *pT;
733 SM4_KEY Sm4Key;
734 int i;
735 INT32 dSize;
736 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
737 if(dInSize == 0)
738 return CRYPT_SUCCESS;
739 pAssert(dInSize <= INT32_MAX);
740 dSize = (INT32)dInSize;
741 // Create SM4 encryption schedule
742 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
743 FAIL(FATAL_ERROR_INTERNAL);
744 for(; dSize > 0; dSize--)
745 {
746 // Encrypt the current value of the IV(counter)
747 SM4_encrypt(iv, (BYTE *)tmp, &Sm4Key);
748 //increment the counter
749 for(i = 0; i < 16; i++)
750 if((iv[i] += 1) != 0)
751 break;
752 // XOR the encrypted counter value with input and put into output
753 pT = tmp;
754 for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
755 *dOut++ = *dIn++ ^ *pT++;
756 }
757 return CRYPT_SUCCESS;
758 }
759 //
760 // _cpri__SM4EncryptECB()
761 //
762 // SM4 encryption in ECB mode. The data buffer is modified to contain the cipher text.
763 //
764 // Return Value Meaning
765 //
766 // CRYPT_SUCCESS no non-fatal errors
767 //
768 LIB_EXPORT CRYPT_RESULT
_cpri__SM4EncryptECB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,UINT32 dInSize,BYTE * dIn)769 _cpri__SM4EncryptECB(
770 BYTE *dOut, // OUT: encrypted data
771 UINT32 keySizeInBits, // IN: key size in bit
772 BYTE *key, // IN: key buffer. The size of this buffer in
773 // bytes is (keySizeInBits + 7) / 8
774 UINT32 dInSize, // IN: data size
775 BYTE *dIn // IN: clear text buffer
776 )
777 {
778 SM4_KEY Sm4Key;
779 INT32 dSize;
780 pAssert(dOut != NULL && key != NULL && dIn != NULL);
781 if(dInSize == 0)
782 return CRYPT_SUCCESS;
783 pAssert(dInSize <= INT32_MAX);
784 dSize = (INT32)dInSize;
785 // For ECB, the data size must be an even multiple of the
786 // cipher block size
787 if((dSize % 16) != 0)
788 return CRYPT_PARAMETER;
789 // Create SM4 encrypting key schedule
790 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
791 FAIL(FATAL_ERROR_INTERNAL);
792 for(; dSize > 0; dSize -= 16)
793 {
794 SM4_encrypt(dIn, dOut, &Sm4Key);
795 dIn = &dIn[16];
796 dOut = &dOut[16];
797 }
798 return CRYPT_SUCCESS;
799 }
800 //
801 //
802 // _cpri__SM4DecryptECB()
803 //
804 // This function performs SM4 decryption using ECB (not recommended). The cipher text dIn is decrypted
805 // into dOut.
806 //
807 //
808 //
809 //
810 // Return Value Meaning
811 //
812 // CRYPT_SUCCESS no non-fatal errors
813 //
814 LIB_EXPORT CRYPT_RESULT
_cpri__SM4DecryptECB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,UINT32 dInSize,BYTE * dIn)815 _cpri__SM4DecryptECB(
816 BYTE *dOut, // OUT: the clear text data
817 UINT32 keySizeInBits, // IN: key size in bit
818 BYTE *key, // IN: key buffer. The size of this buffer in
819 // bytes is (keySizeInBits + 7) / 8
820 UINT32 dInSize, // IN: data size
821 BYTE *dIn // IN: cipher text buffer
822 )
823 {
824 SM4_KEY Sm4Key;
825 INT32 dSize;
826 pAssert(dOut != NULL && key != NULL && dIn != NULL);
827 if(dInSize == 0)
828 return CRYPT_SUCCESS;
829 pAssert(dInSize <= INT32_MAX);
830 dSize = (INT32)dInSize;
831 // For ECB, the data size must be an even multiple of the
832 // cipher block size
833 if((dSize % 16) != 0)
834 return CRYPT_PARAMETER;
835 // Create SM4 decryption key schedule
836 if (SM4_set_decrypt_key(key, keySizeInBits, &Sm4Key) != 0)
837 FAIL(FATAL_ERROR_INTERNAL);
838 for(; dSize > 0; dSize -= 16)
839 {
840 SM4_decrypt(dIn, dOut, &Sm4Key);
841 dIn = &dIn[16];
842 dOut = &dOut[16];
843 }
844 return CRYPT_SUCCESS;
845 }
846 //
847 //
848 // _cpri__SM4EncryptOFB()
849 //
850 // This function performs SM4 encryption/decryption in OFB chain mode. The dIn buffer is modified to
851 // contain the encrypted/decrypted text.
852 // The input iv buffer is assumed to have a size equal to the block size (16 bytes). The returned value of iv
853 // will be the nth encryption of the IV, where n is the number of blocks (full or partial) in the data stream.
854 //
855 // Return Value Meaning
856 //
857 // CRYPT_SUCCESS no non-fatal errors
858 //
859 LIB_EXPORT CRYPT_RESULT
_cpri__SM4EncryptOFB(BYTE * dOut,UINT32 keySizeInBits,BYTE * key,BYTE * iv,UINT32 dInSize,BYTE * dIn)860 _cpri__SM4EncryptOFB(
861 BYTE *dOut, // OUT: the encrypted/decrypted data
862 UINT32 keySizeInBits, // IN: key size in bit
863 BYTE *key, // IN: key buffer. The size of this buffer in
864 // bytes is (keySizeInBits + 7) / 8
865 BYTE *iv, // IN/OUT: IV for decryption. The size of this
866 // buffer is 16 byte
867 UINT32 dInSize, // IN: data size
868 BYTE *dIn // IN: data buffer
869 )
870 {
871 BYTE *pIv;
872 SM4_KEY Sm4Key;
873 INT32 dSize;
874 int i;
875 pAssert(dOut != NULL && key != NULL && iv != NULL && dIn != NULL);
876 if(dInSize == 0)
877 return CRYPT_SUCCESS;
878 pAssert(dInSize <= INT32_MAX);
879 dSize = (INT32)dInSize;
880 // Create SM4 key schedule
881 if (SM4_set_encrypt_key(key, keySizeInBits, &Sm4Key) != 0)
882 FAIL(FATAL_ERROR_INTERNAL);
883 // This is written so that dIn and dOut may be the same
884 for(; dSize > 0; dSize -= 16)
885 {
886 // Encrypt the current value of the "IV"
887 SM4_encrypt(iv, iv, &Sm4Key);
888 // XOR the encrypted IV into dIn to create the cipher text (dOut)
889 pIv = iv;
890 for(i = (dSize < 16) ? dSize : 16; i > 0; i--)
891 *dOut++ = (*pIv++ ^ *dIn++);
892 }
893 return CRYPT_SUCCESS;
894 }
895 #endif //% TPM_ALG_SM4
896