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