pcpaesauthgcmca.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. /*
  2. * Copyright (C) 2016 Intel Corporation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in
  12. * the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Intel Corporation nor the names of its
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. */
  31. #include "owndefs.h"
  32. #include "owncp.h"
  33. #include "pcpaesauthgcm.h"
  34. #include "pcptool.h"
  35. #include "pcprijtables.h"
  36. /*F*
  37. // Name: ippsAES_GCMGetSize
  38. //
  39. // Purpose: Returns size of AES_GCM state (in bytes).
  40. //
  41. // Returns: Reason:
  42. // ippStsNullPtrErr pSize == NULL
  43. // ippStsNoErr no errors
  44. //
  45. // Parameters:
  46. // pSize pointer to size of context
  47. //
  48. *F*/
  49. static int cpSizeofCtx_AESGCM(void)
  50. {
  51. int precomp_size;
  52. precomp_size = PRECOMP_DATA_SIZE_FAST2K;
  53. /* decrease precomp_size as soon as BLOCK_SIZE bytes already reserved in context */
  54. precomp_size -= BLOCK_SIZE;
  55. return sizeof(IppsAES_GCMState)
  56. +precomp_size
  57. +AESGCM_ALIGNMENT-1;
  58. }
  59. IPPFUN(IppStatus, ippsAES_GCMGetSize,(int* pSize))
  60. {
  61. /* test size's pointer */
  62. IPP_BAD_PTR1_RET(pSize);
  63. *pSize = cpSizeofCtx_AESGCM();
  64. return ippStsNoErr;
  65. }
  66. /*F*
  67. // Name: ippsAES_GCMReset
  68. //
  69. // Purpose: Resets AES_GCM context.
  70. //
  71. // Returns: Reason:
  72. // ippStsNullPtrErr pState== NULL
  73. // ippStsContextMatchErr pState points on invalid context
  74. // ippStsNoErr no errors
  75. //
  76. // Parameters:
  77. // pState pointer to the context
  78. //
  79. *F*/
  80. IPPFUN(IppStatus, ippsAES_GCMReset,(IppsAES_GCMState* pState))
  81. {
  82. /* test pState pointer */
  83. IPP_BAD_PTR1_RET(pState);
  84. /* use aligned context */
  85. pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) );
  86. /* test context validity */
  87. IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr);
  88. /* reset GCM */
  89. AESGCM_STATE(pState) = GcmInit;
  90. AESGCM_IV_LEN(pState) = CONST_64(0);
  91. AESGCM_AAD_LEN(pState) = CONST_64(0);
  92. AESGCM_TXT_LEN(pState) = CONST_64(0);
  93. AESGCM_BUFLEN(pState) = 0;
  94. PaddBlock(0, AESGCM_COUNTER(pState), BLOCK_SIZE);
  95. PaddBlock(0, AESGCM_ECOUNTER(pState), BLOCK_SIZE);
  96. PaddBlock(0, AESGCM_ECOUNTER0(pState), BLOCK_SIZE);
  97. PaddBlock(0, AESGCM_GHASH(pState), BLOCK_SIZE);
  98. return ippStsNoErr;
  99. }
  100. /*F*
  101. // Name: ippsAES_GCMInit
  102. //
  103. // Purpose: Init AES_GCM context for future usage.
  104. //
  105. // Returns: Reason:
  106. // ippStsNullPtrErr pState == NULL
  107. // ippStsMemAllocErr size of buffer is not match fro operation
  108. // ippStsLengthErr keyLen != 16 &&
  109. // != 24 &&
  110. // != 32
  111. // ippStsNoErr no errors
  112. //
  113. // Parameters:
  114. // pKey pointer to the secret key
  115. // keyLen length of secret key
  116. // pState pointer to the AES-GCM context
  117. // ctxSize available size (in bytes) of buffer above
  118. //
  119. *F*/
  120. IPPFUN(IppStatus, ippsAES_GCMInit,(const Ipp8u* pKey, int keyLen, IppsAES_GCMState* pState, int ctxSize))
  121. {
  122. /* test pCtx pointer */
  123. IPP_BAD_PTR1_RET(pState);
  124. /* test available size of context buffer */
  125. IPP_BADARG_RET(ctxSize<cpSizeofCtx_AESGCM(), ippStsMemAllocErr);
  126. /* use aligned context */
  127. pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) );
  128. /* set and clear GCM context */
  129. AESGCM_ID(pState) = idCtxAESGCM;
  130. ippsAES_GCMReset(pState);
  131. /* init cipher */
  132. {
  133. IppStatus sts = ippsAESInit(pKey, keyLen, AESGCM_CIPHER(pState), cpSizeofCtx_AES());
  134. if(ippStsNoErr!=sts)
  135. return sts;
  136. }
  137. /* set up:
  138. // - ghash function
  139. // - authentication function
  140. */
  141. AESGCM_HASH(pState) = AesGcmMulGcm_table2K;
  142. AESGCM_AUTH(pState) = AesGcmAuth_table2K;
  143. AESGCM_ENC(pState) = wrpAesGcmEnc_table2K;
  144. AESGCM_DEC(pState) = wrpAesGcmDec_table2K;
  145. /* precomputations (for constant multiplier(s)) */
  146. {
  147. IppsAESSpec* pAES = AESGCM_CIPHER(pState);
  148. RijnCipher encoder = RIJ_ENCODER(pAES);
  149. /* multiplier c = Enc({0}) */
  150. PaddBlock(0, AESGCM_HKEY(pState), BLOCK_SIZE);
  151. encoder(AESGCM_HKEY(pState), AESGCM_HKEY(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox);
  152. }
  153. AesGcmPrecompute_table2K(AES_GCM_MTBL(pState), AESGCM_HKEY(pState));
  154. return ippStsNoErr;
  155. }
  156. /*F*
  157. // Name: ippsAES_GCMProcessIV
  158. //
  159. // Purpose: IV processing.
  160. //
  161. // Returns: Reason:
  162. // ippStsNullPtrErr pState == NULL
  163. // pIV ==NULL && ivLen>0
  164. // ippStsContextMatchErr !AESGCM_VALID_ID()
  165. // ippStsLengthErr ivLen <0
  166. // ippStsBadArgErr illegal sequence call
  167. // ippStsNoErr no errors
  168. //
  169. // Parameters:
  170. // pIV pointer to the IV
  171. // ivLen length of IV (it could be 0)
  172. // pState pointer to the context
  173. //
  174. *F*/
  175. IPPFUN(IppStatus, ippsAES_GCMProcessIV,(const Ipp8u* pIV, int ivLen, IppsAES_GCMState* pState))
  176. {
  177. /* test pState pointer */
  178. IPP_BAD_PTR1_RET(pState);
  179. /* test IV pointer and length */
  180. IPP_BADARG_RET(ivLen && !pIV, ippStsNullPtrErr);
  181. IPP_BADARG_RET(ivLen<0, ippStsLengthErr);
  182. /* use aligned context */
  183. pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) );
  184. /* test context validity */
  185. IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr);
  186. IPP_BADARG_RET(!(GcmInit==AESGCM_STATE(pState) || GcmIVprocessing==AESGCM_STATE(pState)), ippStsBadArgErr);
  187. /* switch IVprocessing on */
  188. AESGCM_STATE(pState) = GcmIVprocessing;
  189. /* test if buffer is not empty */
  190. if(AESGCM_BUFLEN(pState)) {
  191. int locLen = IPP_MIN(ivLen, BLOCK_SIZE-AESGCM_BUFLEN(pState));
  192. XorBlock(pIV, AESGCM_COUNTER(pState)+AESGCM_BUFLEN(pState), AESGCM_COUNTER(pState)+AESGCM_BUFLEN(pState), locLen);
  193. AESGCM_BUFLEN(pState) += locLen;
  194. /* if buffer full */
  195. if(BLOCK_SIZE==AESGCM_BUFLEN(pState)) {
  196. MulGcm_ ghashFunc = AESGCM_HASH(pState);
  197. ghashFunc(AESGCM_COUNTER(pState), AESGCM_HKEY(pState), AesGcmConst_table);
  198. AESGCM_BUFLEN(pState) = 0;
  199. }
  200. AESGCM_IV_LEN(pState) += locLen;
  201. pIV += locLen;
  202. ivLen -= locLen;
  203. }
  204. /* process main part of IV */
  205. {
  206. int lenBlks = ivLen & (-BLOCK_SIZE);
  207. if(lenBlks) {
  208. Auth_ authFunc = AESGCM_AUTH(pState);
  209. authFunc(AESGCM_COUNTER(pState), pIV, lenBlks, AESGCM_HKEY(pState), AesGcmConst_table);
  210. AESGCM_IV_LEN(pState) += lenBlks;
  211. pIV += lenBlks;
  212. ivLen -= lenBlks;
  213. }
  214. }
  215. /* copy the rest of IV into the buffer */
  216. if(ivLen) {
  217. XorBlock(pIV, AESGCM_COUNTER(pState), AESGCM_COUNTER(pState), ivLen);
  218. AESGCM_IV_LEN(pState) += ivLen;
  219. AESGCM_BUFLEN(pState) += ivLen;
  220. }
  221. return ippStsNoErr;
  222. }
  223. /*F*
  224. // Name: ippsAES_GCMProcessAAD
  225. //
  226. // Purpose: AAD processing.
  227. //
  228. // Returns: Reason:
  229. // ippStsNullPtrErr pState == NULL
  230. // pAAD == NULL, aadLen>0
  231. // ippStsContextMatchErr !AESGCM_VALID_ID()
  232. // ippStsLengthErr aadLen <0
  233. // ippStsBadArgErr illegal sequence call
  234. // ippStsNoErr no errors
  235. //
  236. // Parameters:
  237. // pAAD pointer to the AAD
  238. // aadlen length of AAD (it could be 0)
  239. // pState pointer to the context
  240. //
  241. *F*/
  242. IPPFUN(IppStatus, ippsAES_GCMProcessAAD,(const Ipp8u* pAAD, int aadLen, IppsAES_GCMState* pState))
  243. {
  244. /* test pState pointer */
  245. IPP_BAD_PTR1_RET(pState);
  246. /* use aligned context */
  247. pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) );
  248. /* test if context is valid */
  249. IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr);
  250. /* test AAD pointer and length */
  251. IPP_BADARG_RET(aadLen && !pAAD, ippStsNullPtrErr);
  252. IPP_BADARG_RET(aadLen<0, ippStsLengthErr);
  253. IPP_BADARG_RET(!(GcmIVprocessing==AESGCM_STATE(pState) || GcmAADprocessing==AESGCM_STATE(pState)), ippStsBadArgErr);
  254. {
  255. /* get method */
  256. MulGcm_ hashFunc = AESGCM_HASH(pState);
  257. if( GcmIVprocessing==AESGCM_STATE(pState) ) {
  258. IPP_BADARG_RET(0==AESGCM_IV_LEN(pState), ippStsBadArgErr);
  259. /* complete IV processing */
  260. if(CTR_POS==AESGCM_IV_LEN(pState)) {
  261. /* apply special format if IV length is 12 bytes */
  262. AESGCM_COUNTER(pState)[12] = 0;
  263. AESGCM_COUNTER(pState)[13] = 0;
  264. AESGCM_COUNTER(pState)[14] = 0;
  265. AESGCM_COUNTER(pState)[15] = 1;
  266. }
  267. else {
  268. /* process the rest of IV */
  269. if(AESGCM_BUFLEN(pState))
  270. hashFunc(AESGCM_COUNTER(pState), AESGCM_HKEY(pState), AesGcmConst_table);
  271. /* add IV bit length */
  272. {
  273. Ipp64u ivBitLen = AESGCM_IV_LEN(pState)*BYTESIZE;
  274. Ipp8u tmp[BLOCK_SIZE];
  275. PaddBlock(0, tmp, BLOCK_SIZE-8);
  276. U32_TO_HSTRING(tmp+8, HIDWORD(ivBitLen));
  277. U32_TO_HSTRING(tmp+12, LODWORD(ivBitLen));
  278. XorBlock16(tmp, AESGCM_COUNTER(pState), AESGCM_COUNTER(pState));
  279. hashFunc(AESGCM_COUNTER(pState), AESGCM_HKEY(pState), AesGcmConst_table);
  280. }
  281. }
  282. /* prepare initial counter */
  283. {
  284. IppsAESSpec* pAES = AESGCM_CIPHER(pState);
  285. RijnCipher encoder = RIJ_ENCODER(pAES);
  286. encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER0(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox);
  287. }
  288. /* switch mode and init counters */
  289. AESGCM_STATE(pState) = GcmAADprocessing;
  290. AESGCM_AAD_LEN(pState) = CONST_64(0);
  291. AESGCM_BUFLEN(pState) = 0;
  292. }
  293. /*
  294. // AAD processing
  295. */
  296. /* test if buffer is not empty */
  297. if(AESGCM_BUFLEN(pState)) {
  298. int locLen = IPP_MIN(aadLen, BLOCK_SIZE-AESGCM_BUFLEN(pState));
  299. XorBlock(pAAD, AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), locLen);
  300. AESGCM_BUFLEN(pState) += locLen;
  301. /* if buffer full */
  302. if(BLOCK_SIZE==AESGCM_BUFLEN(pState)) {
  303. hashFunc(AESGCM_GHASH(pState), AESGCM_HKEY(pState), AesGcmConst_table);
  304. AESGCM_BUFLEN(pState) = 0;
  305. }
  306. AESGCM_AAD_LEN(pState) += locLen;
  307. pAAD += locLen;
  308. aadLen -= locLen;
  309. }
  310. /* process main part of AAD */
  311. {
  312. int lenBlks = aadLen & (-BLOCK_SIZE);
  313. if(lenBlks) {
  314. Auth_ authFunc = AESGCM_AUTH(pState);
  315. authFunc(AESGCM_GHASH(pState), pAAD, lenBlks, AESGCM_HKEY(pState), AesGcmConst_table);
  316. AESGCM_AAD_LEN(pState) += lenBlks;
  317. pAAD += lenBlks;
  318. aadLen -= lenBlks;
  319. }
  320. }
  321. /* copy the rest of AAD into the buffer */
  322. if(aadLen) {
  323. XorBlock(pAAD, AESGCM_GHASH(pState), AESGCM_GHASH(pState), aadLen);
  324. AESGCM_AAD_LEN(pState) += aadLen;
  325. AESGCM_BUFLEN(pState) = aadLen;
  326. }
  327. return ippStsNoErr;
  328. }
  329. }
  330. /*F*
  331. // Name: ippsAES_GCMStart
  332. //
  333. // Purpose: Start the process of encryption or decryption and authentication tag generation.
  334. //
  335. // Returns: Reason:
  336. // ippStsNullPtrErr pState == NULL
  337. // pIV == NULL, ivLen>0
  338. // pAAD == NULL, aadLen>0
  339. // ippStsContextMatchErr !AESGCM_VALID_ID()
  340. // ippStsLengthErr ivLen < 0
  341. // aadLen < 0
  342. // ippStsNoErr no errors
  343. //
  344. // Parameters:
  345. // pIV pointer to the IV (nonce)
  346. // ivLen length of the IV in bytes
  347. // pAAD pointer to the Addition Authenticated Data (header)
  348. // aadLen length of the AAD in bytes
  349. // pState pointer to the AES-GCM state
  350. //
  351. *F*/
  352. IPPFUN(IppStatus, ippsAES_GCMStart,(const Ipp8u* pIV, int ivLen,
  353. const Ipp8u* pAAD, int aadLen,
  354. IppsAES_GCMState* pState))
  355. {
  356. IppStatus sts = ippsAES_GCMReset(pState);
  357. if(ippStsNoErr==sts)
  358. sts = ippsAES_GCMProcessIV(pIV, ivLen, pState);
  359. if(ippStsNoErr==sts)
  360. sts = ippsAES_GCMProcessAAD(pAAD, aadLen, pState);
  361. return sts;
  362. }
  363. /*F*
  364. // Name: ippsAES_GCMEncrypt
  365. //
  366. // Purpose: Encrypts a data buffer in the GCM mode.
  367. //
  368. // Returns: Reason:
  369. // ippStsNullPtrErr pSrc == NULL
  370. // pDst == NULL
  371. // pState == NULL
  372. // ippStsContextMatchErr !AESGCM_VALID_ID()
  373. // ippStsLengthErr txtLen<0
  374. // ippStsNoErr no errors
  375. //
  376. // Parameters:
  377. // pSrc Pointer to plaintext.
  378. // pDst Pointer to ciphertext.
  379. // len Length of the plaintext and ciphertext in bytes
  380. // pState pointer to the context
  381. //
  382. *F*/
  383. IPPFUN(IppStatus, ippsAES_GCMEncrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int txtLen,
  384. IppsAES_GCMState* pState))
  385. {
  386. /* test pState pointer */
  387. IPP_BAD_PTR1_RET(pState);
  388. /* use aligned context */
  389. pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) );
  390. /* test state ID */
  391. IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr);
  392. /* test context validity */
  393. IPP_BADARG_RET(!(GcmAADprocessing==AESGCM_STATE(pState) || GcmTXTprocessing==AESGCM_STATE(pState)), ippStsBadArgErr);
  394. /* test text pointers and length */
  395. IPP_BAD_PTR2_RET(pSrc, pDst);
  396. IPP_BADARG_RET(txtLen<0, ippStsLengthErr);
  397. {
  398. /* get method */
  399. IppsAESSpec* pAES = AESGCM_CIPHER(pState);
  400. RijnCipher encoder = RIJ_ENCODER(pAES);
  401. MulGcm_ hashFunc = AESGCM_HASH(pState);
  402. if( GcmAADprocessing==AESGCM_STATE(pState) ) {
  403. /* complete AAD processing */
  404. if(AESGCM_BUFLEN(pState))
  405. hashFunc(AESGCM_GHASH(pState), AESGCM_HKEY(pState), AesGcmConst_table);
  406. /* increment counter block */
  407. IncrementCounter32(AESGCM_COUNTER(pState));
  408. /* and encrypt counter */
  409. encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox);
  410. /* switch mode and init counters */
  411. AESGCM_STATE(pState) = GcmTXTprocessing;
  412. AESGCM_TXT_LEN(pState) = CONST_64(0);
  413. AESGCM_BUFLEN(pState) = 0;
  414. }
  415. /*
  416. // process text (encrypt and authenticate)
  417. */
  418. /* process partial block */
  419. if(AESGCM_BUFLEN(pState)) {
  420. int locLen = IPP_MIN(txtLen, BLOCK_SIZE-AESGCM_BUFLEN(pState));
  421. /* ctr encryption */
  422. XorBlock(pSrc, AESGCM_ECOUNTER(pState)+AESGCM_BUFLEN(pState), pDst, locLen);
  423. /* authentication */
  424. XorBlock(pDst, AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), locLen);
  425. AESGCM_BUFLEN(pState) += locLen;
  426. AESGCM_TXT_LEN(pState) += locLen;
  427. pSrc += locLen;
  428. pDst += locLen;
  429. txtLen -= locLen;
  430. /* if buffer full */
  431. if(BLOCK_SIZE==AESGCM_BUFLEN(pState)) {
  432. /* hash buffer */
  433. hashFunc(AESGCM_GHASH(pState), AESGCM_HKEY(pState), AesGcmConst_table);
  434. AESGCM_BUFLEN(pState) = 0;
  435. /* increment counter block */
  436. IncrementCounter32(AESGCM_COUNTER(pState));
  437. /* and encrypt counter */
  438. encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox);
  439. }
  440. }
  441. /* process the main part of text */
  442. {
  443. int lenBlks = txtLen & (-BLOCK_SIZE);
  444. if(lenBlks) {
  445. Encrypt_ encFunc = AESGCM_ENC(pState);
  446. encFunc(pDst, pSrc, lenBlks, pState);
  447. AESGCM_TXT_LEN(pState) += lenBlks;
  448. pSrc += lenBlks;
  449. pDst += lenBlks;
  450. txtLen -= lenBlks;
  451. }
  452. }
  453. /* process the rest of text */
  454. if(txtLen) {
  455. XorBlock(pSrc, AESGCM_ECOUNTER(pState)+AESGCM_BUFLEN(pState), pDst, txtLen);
  456. XorBlock(pDst, AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), txtLen);
  457. AESGCM_BUFLEN(pState) += txtLen;
  458. AESGCM_TXT_LEN(pState) += txtLen;
  459. }
  460. return ippStsNoErr;
  461. }
  462. }
  463. /*F*
  464. // Name: ippsAES_GCMDecrypt
  465. //
  466. // Purpose: Decrypts a data buffer in the GCM mode.
  467. //
  468. // Returns: Reason:
  469. // ippStsNullPtrErr pSrc == NULL
  470. // pDst == NULL
  471. // pState == NULL
  472. // ippStsContextMatchErr !AESGCM_VALID_ID()
  473. // ippStsLengthErr txtLen<0
  474. // ippStsNoErr no errors
  475. //
  476. // Parameters:
  477. // pSrc Pointer to ciphertext.
  478. // pDst Pointer to plaintext.
  479. // len Length of the plaintext and ciphertext in bytes
  480. // pState pointer to the context
  481. //
  482. *F*/
  483. IPPFUN(IppStatus, ippsAES_GCMDecrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int txtLen, IppsAES_GCMState* pState))
  484. {
  485. /* test pState pointer */
  486. IPP_BAD_PTR1_RET(pState);
  487. /* use aligned context */
  488. pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) );
  489. /* test state ID */
  490. IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr);
  491. /* test context validity */
  492. IPP_BADARG_RET(!(GcmAADprocessing==AESGCM_STATE(pState) || GcmTXTprocessing==AESGCM_STATE(pState)), ippStsBadArgErr);
  493. /* test text pointers and length */
  494. IPP_BAD_PTR2_RET(pSrc, pDst);
  495. IPP_BADARG_RET(txtLen<0, ippStsLengthErr);
  496. {
  497. /* get method */
  498. IppsAESSpec* pAES = AESGCM_CIPHER(pState);
  499. RijnCipher encoder = RIJ_ENCODER(pAES);
  500. MulGcm_ hashFunc = AESGCM_HASH(pState);
  501. if( GcmAADprocessing==AESGCM_STATE(pState) ) {
  502. /* complete AAD processing */
  503. if(AESGCM_BUFLEN(pState))
  504. hashFunc(AESGCM_GHASH(pState), AESGCM_HKEY(pState), AesGcmConst_table);
  505. /* increment counter block */
  506. IncrementCounter32(AESGCM_COUNTER(pState));
  507. /* and encrypt counter */
  508. encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox);
  509. /* switch mode and init counters */
  510. AESGCM_BUFLEN(pState) = 0;
  511. AESGCM_TXT_LEN(pState) = CONST_64(0);
  512. AESGCM_STATE(pState) = GcmTXTprocessing;
  513. }
  514. /*
  515. // process text (authenticate and decrypt )
  516. */
  517. /* process partial block */
  518. if(AESGCM_BUFLEN(pState)) {
  519. int locLen = IPP_MIN(txtLen, BLOCK_SIZE-AESGCM_BUFLEN(pState));
  520. /* authentication */
  521. XorBlock(pSrc, AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), locLen);
  522. /* ctr decryption */
  523. XorBlock(pSrc, AESGCM_ECOUNTER(pState)+AESGCM_BUFLEN(pState), pDst, locLen);
  524. AESGCM_BUFLEN(pState) += locLen;
  525. AESGCM_TXT_LEN(pState) += locLen;
  526. pSrc += locLen;
  527. pDst += locLen;
  528. txtLen -= locLen;
  529. /* if buffer full */
  530. if(BLOCK_SIZE==AESGCM_BUFLEN(pState)) {
  531. /* hash buffer */
  532. hashFunc(AESGCM_GHASH(pState), AESGCM_HKEY(pState), AesGcmConst_table);
  533. AESGCM_BUFLEN(pState) = 0;
  534. /* increment counter block */
  535. IncrementCounter32(AESGCM_COUNTER(pState));
  536. /* and encrypt counter */
  537. encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox);
  538. }
  539. }
  540. /* process the main part of text */
  541. {
  542. int lenBlks = txtLen & (-BLOCK_SIZE);
  543. if(lenBlks) {
  544. Decrypt_ decFunc = AESGCM_DEC(pState);
  545. decFunc(pDst, pSrc, lenBlks, pState);
  546. AESGCM_TXT_LEN(pState) += lenBlks;
  547. pSrc += lenBlks;
  548. pDst += lenBlks;
  549. txtLen -= lenBlks;
  550. }
  551. }
  552. /* process the rest of text */
  553. if(txtLen) {
  554. /* ctr encryption */
  555. XorBlock(pSrc, AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), txtLen);
  556. XorBlock(pSrc, AESGCM_ECOUNTER(pState)+AESGCM_BUFLEN(pState), pDst, txtLen);
  557. AESGCM_BUFLEN(pState) += txtLen;
  558. AESGCM_TXT_LEN(pState) += txtLen;
  559. }
  560. return ippStsNoErr;
  561. }
  562. }
  563. /*F*
  564. // Name: ippsAES_GCMGetTag
  565. //
  566. // Purpose: Generates authentication tag in the GCM mode.
  567. //
  568. // Returns: Reason:
  569. // ippStsNullPtrErr pDstTag == NULL
  570. // pState == NULL
  571. // ippStsLengthErr tagLen<=0 || tagLen>16
  572. // ippStsContextMatchErr !AESGCM_VALID_ID()
  573. // ippStsNoErr no errors
  574. //
  575. // Parameters:
  576. // pDstTag pointer to the authentication tag.
  577. // tagLen length of the authentication tag *pDstTag in bytes
  578. // pState pointer to the context
  579. //
  580. *F*/
  581. IPPFUN(IppStatus, ippsAES_GCMGetTag,(Ipp8u* pTag, int tagLen, const IppsAES_GCMState* pState))
  582. {
  583. /* test State pointer */
  584. IPP_BAD_PTR1_RET(pState);
  585. /* use aligned context */
  586. pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) );
  587. /* test state ID */
  588. IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr);
  589. /* test tag pointer and length */
  590. IPP_BAD_PTR1_RET(pTag);
  591. IPP_BADARG_RET(tagLen<=0 || tagLen>BLOCK_SIZE, ippStsLengthErr);
  592. {
  593. /* get method */
  594. MulGcm_ hashFunc = AESGCM_HASH(pState);
  595. __ALIGN16 Ipp8u tmpHash[BLOCK_SIZE];
  596. Ipp8u tmpCntr[BLOCK_SIZE];
  597. /* local copy of AAD and text counters (in bits) */
  598. Ipp64u aadBitLen = AESGCM_AAD_LEN(pState)*BYTESIZE;
  599. Ipp64u txtBitLen = AESGCM_TXT_LEN(pState)*BYTESIZE;
  600. /* do local copy of ghash */
  601. CopyBlock16(AESGCM_GHASH(pState), tmpHash);
  602. /* complete text processing */
  603. if(AESGCM_BUFLEN(pState)) {
  604. hashFunc(tmpHash, AESGCM_HKEY(pState), AesGcmConst_table);
  605. }
  606. /* process lengths of AAD and text */
  607. U32_TO_HSTRING(tmpCntr, HIDWORD(aadBitLen));
  608. U32_TO_HSTRING(tmpCntr+4, LODWORD(aadBitLen));
  609. U32_TO_HSTRING(tmpCntr+8, HIDWORD(txtBitLen));
  610. U32_TO_HSTRING(tmpCntr+12,LODWORD(txtBitLen));
  611. XorBlock16(tmpHash, tmpCntr, tmpHash);
  612. hashFunc(tmpHash, AESGCM_HKEY(pState), AesGcmConst_table);
  613. /* add encrypted initial counter */
  614. XorBlock16(tmpHash, AESGCM_ECOUNTER0(pState), tmpHash);
  615. /* return tag of required lenth */
  616. CopyBlock(tmpHash, pTag, tagLen);
  617. return ippStsNoErr;
  618. }
  619. }