pcpaesauthcmacca.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  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 "pcpcmac.h"
  34. #include "pcpaesm.h"
  35. #include "pcptool.h"
  36. #include "pcprijtables.h"
  37. /*F*
  38. // Name: ippsAES_CMACGetSize
  39. //
  40. // Purpose: Returns size of AES-CMAC context (in bytes).
  41. //
  42. // Returns: Reason:
  43. // ippStsNullPtrErr pSzie == NULL
  44. // ippStsNoErr no errors
  45. //
  46. // Parameters:
  47. // pSize pointer to the AES-CMAC size of context
  48. //
  49. *F*/
  50. static int cpSizeofCtx_AESCMAC(void)
  51. {
  52. return sizeof(IppsAES_CMACState) + AESCMAC_ALIGNMENT-1;
  53. }
  54. IPPFUN(IppStatus, ippsAES_CMACGetSize,(int* pSize))
  55. {
  56. /* test size's pointer */
  57. IPP_BAD_PTR1_RET(pSize);
  58. *pSize = cpSizeofCtx_AESCMAC();
  59. return ippStsNoErr;
  60. }
  61. /*F*
  62. // Name: ippsAES_CMACInit
  63. //
  64. // Purpose: Init AES-CMAC context.
  65. //
  66. // Returns: Reason:
  67. // ippStsNullPtrErr pCtx == NULL
  68. // ippStsMemAllocErr size of buffer is not match fro operation
  69. // ippStsLengthErr keyLen != 16
  70. // keyLen != 24
  71. // keyLen != 32
  72. // ippStsNoErr no errors
  73. //
  74. // Parameters:
  75. // pKey pointer to the secret key
  76. // keyLen length of secret key
  77. // pCtx pointer to the CMAC context
  78. // ctxSize available size (in bytes) of buffer above
  79. //
  80. *F*/
  81. static
  82. void init(IppsAES_CMACState* pCtx)
  83. {
  84. /* buffer is empty */
  85. CMAC_INDX(pCtx) = 0;
  86. /* zeros MAC */
  87. PaddBlock(0, CMAC_MAC(pCtx), MBS_RIJ128);
  88. }
  89. static
  90. void LogicalLeftSift16(const Ipp8u* pSrc, Ipp8u* pDst)
  91. {
  92. Ipp32u carry = 0;
  93. int n;
  94. for(n=0; n<16; n++) {
  95. Ipp32u x = pSrc[16-1-n] + pSrc[16-1-n] + carry;
  96. pDst[16-1-n] = (Ipp8u)x;
  97. carry = (x>>8) & 0xFF;
  98. }
  99. }
  100. IPPFUN(IppStatus, ippsAES_CMACInit,(const Ipp8u* pKey, int keyLen, IppsAES_CMACState* pCtx, int ctxSize))
  101. {
  102. /* test pCtx pointer */
  103. IPP_BAD_PTR1_RET(pCtx);
  104. /* test available size of context buffer */
  105. IPP_BADARG_RET(ctxSize<cpSizeofCtx_AESCMAC(), ippStsMemAllocErr);
  106. /* use aligned context */
  107. pCtx = (IppsAES_CMACState*)( IPP_ALIGNED_PTR(pCtx, AESCMAC_ALIGNMENT) );
  108. {
  109. IppStatus sts;
  110. /* set context ID */
  111. CMAC_ID(pCtx) = idCtxCMAC;
  112. /* init internal buffer and DAC */
  113. init(pCtx);
  114. /* init AES cipher */
  115. sts = ippsAESInit(pKey, keyLen, &CMAC_CIPHER(pCtx), cpSizeofCtx_AES());
  116. if(ippStsNoErr==sts) {
  117. const IppsAESSpec* pAES = &CMAC_CIPHER(pCtx);
  118. /* setup encoder method */
  119. RijnCipher encoder = RIJ_ENCODER(pAES);
  120. int msb;
  121. encoder(CMAC_MAC(pCtx), CMAC_K1(pCtx), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox);
  122. /* precompute k1 subkey */
  123. msb = (CMAC_K1(pCtx))[0];
  124. LogicalLeftSift16(CMAC_K1(pCtx),CMAC_K1(pCtx));
  125. (CMAC_K1(pCtx))[MBS_RIJ128-1] ^= (Ipp8u)((0-(msb>>7)) & 0x87); /* ^ Rb changed for constant time execution */
  126. /* precompute k2 subkey */
  127. msb = (CMAC_K1(pCtx))[0];
  128. LogicalLeftSift16(CMAC_K1(pCtx),CMAC_K2(pCtx));
  129. (CMAC_K2(pCtx))[MBS_RIJ128-1] ^= (Ipp8u)((0-(msb>>7)) & 0x87); /* ^ Rb changed for constant time execution */
  130. }
  131. return sts;
  132. }
  133. }
  134. /*F*
  135. // Name: ippsAES_CMACUpdate
  136. //
  137. // Purpose: Updates intermadiate digest based on input stream.
  138. //
  139. // Returns: Reason:
  140. // ippStsNullPtrErr pSrc == NULL
  141. // pCtx == NULL
  142. // ippStsContextMatchErr !VALID_AESCMAC_ID()
  143. // ippStsLengthErr len <0
  144. // ippStsNoErr no errors
  145. //
  146. // Parameters:
  147. // pSrc pointer to the input stream
  148. // len input stream length
  149. // pCtx pointer to the CMAC context
  150. //
  151. *F*/
  152. static
  153. void AES_CMAC_processing(Ipp8u* pDigest, const Ipp8u* pSrc, int processedLen, const IppsAESSpec* pAES)
  154. {
  155. /* setup encoder method */
  156. RijnCipher encoder = RIJ_ENCODER(pAES);
  157. while(processedLen) {
  158. ((Ipp32u*)pDigest)[0] ^= ((Ipp32u*)pSrc)[0];
  159. ((Ipp32u*)pDigest)[1] ^= ((Ipp32u*)pSrc)[1];
  160. ((Ipp32u*)pDigest)[2] ^= ((Ipp32u*)pSrc)[2];
  161. ((Ipp32u*)pDigest)[3] ^= ((Ipp32u*)pSrc)[3];
  162. encoder(pDigest, pDigest, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox);
  163. pSrc += MBS_RIJ128;
  164. processedLen -= MBS_RIJ128;
  165. }
  166. }
  167. IPPFUN(IppStatus, ippsAES_CMACUpdate,(const Ipp8u* pSrc, int len, IppsAES_CMACState* pCtx))
  168. {
  169. int processedLen;
  170. /* test context pointer */
  171. IPP_BAD_PTR1_RET(pCtx);
  172. /* use aligned context */
  173. pCtx = (IppsAES_CMACState*)( IPP_ALIGNED_PTR(pCtx, AESCMAC_ALIGNMENT) );
  174. /* test ID */
  175. IPP_BADARG_RET(!VALID_AESCMAC_ID(pCtx), ippStsContextMatchErr);
  176. /* test input message and it's length */
  177. IPP_BADARG_RET((len<0 && pSrc), ippStsLengthErr);
  178. /* test source pointer */
  179. IPP_BADARG_RET((len && !pSrc), ippStsNullPtrErr);
  180. if(!len)
  181. return ippStsNoErr;
  182. {
  183. /*
  184. // test internal buffer filling
  185. */
  186. if(CMAC_INDX(pCtx)) {
  187. /* copy from input stream to the internal buffer as match as possible */
  188. processedLen = IPP_MIN(len, (MBS_RIJ128 - CMAC_INDX(pCtx)));
  189. CopyBlock(pSrc, CMAC_BUFF(pCtx)+CMAC_INDX(pCtx), processedLen);
  190. /* internal buffer filling */
  191. CMAC_INDX(pCtx) += processedLen;
  192. /* update message pointer and length */
  193. pSrc += processedLen;
  194. len -= processedLen;
  195. if(!len)
  196. return ippStsNoErr;
  197. /* update CMAC if buffer full but not the last */
  198. if(MBS_RIJ128==CMAC_INDX(pCtx) ) {
  199. const IppsAESSpec* pAES = &CMAC_CIPHER(pCtx);
  200. /* setup encoder method */
  201. RijnCipher encoder = RIJ_ENCODER(pAES);
  202. XorBlock16(CMAC_BUFF(pCtx), CMAC_MAC(pCtx), CMAC_MAC(pCtx));
  203. encoder(CMAC_MAC(pCtx), CMAC_MAC(pCtx), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox);
  204. CMAC_INDX(pCtx) = 0;
  205. }
  206. }
  207. /*
  208. // main part
  209. */
  210. processedLen = len & ~(MBS_RIJ128-1);
  211. if(!(len & (MBS_RIJ128-1)))
  212. processedLen -= MBS_RIJ128;
  213. if(processedLen) {
  214. const IppsAESSpec* pAES = &CMAC_CIPHER(pCtx);
  215. AES_CMAC_processing(CMAC_MAC(pCtx), pSrc, processedLen, pAES);
  216. /* update message pointer and length */
  217. pSrc += processedLen;
  218. len -= processedLen;
  219. }
  220. /*
  221. // remaind
  222. */
  223. if(len) {
  224. CopyBlock(pSrc, (Ipp8u*)(&CMAC_BUFF(pCtx)), len);
  225. /* update internal buffer filling */
  226. CMAC_INDX(pCtx) += len;
  227. }
  228. return ippStsNoErr;
  229. }
  230. }
  231. /*F*
  232. // Name: ippsAES_CMACFinal
  233. //
  234. // Purpose: Stop message digesting and return MD.
  235. //
  236. // Returns: Reason:
  237. // ippStsNullPtrErr pMD == NULL
  238. // pCtx == NULL
  239. // ippStsContextMatchErr !VALID_AESCMAC_ID()
  240. // ippStsLengthErr MBS_RIJ128 < mdLen <1
  241. // ippStsNoErr no errors
  242. //
  243. // Parameters:
  244. // pMD pointer to the output message digest
  245. // mdLen requested length of the message digest
  246. // pCtx pointer to the CMAC context
  247. //
  248. *F*/
  249. IPPFUN(IppStatus, ippsAES_CMACFinal,(Ipp8u* pMD, int mdLen, IppsAES_CMACState* pCtx))
  250. {
  251. /* test context pointer and ID */
  252. IPP_BAD_PTR1_RET(pCtx);
  253. /* use aligned context */
  254. pCtx = (IppsAES_CMACState*)( IPP_ALIGNED_PTR(pCtx, AESCMAC_ALIGNMENT) );
  255. IPP_BADARG_RET(!VALID_AESCMAC_ID(pCtx), ippStsContextMatchErr);
  256. /* test DAC pointer */
  257. IPP_BAD_PTR1_RET(pMD);
  258. IPP_BADARG_RET((mdLen<1)||(MBS_RIJ128<mdLen), ippStsLengthErr);
  259. {
  260. const IppsAESSpec* pAES = &CMAC_CIPHER(pCtx);
  261. /* setup encoder method */
  262. RijnCipher encoder = RIJ_ENCODER(pAES);
  263. /* message length is divided by MBS_RIJ128 */
  264. if(MBS_RIJ128==CMAC_INDX(pCtx)) {
  265. XorBlock16(CMAC_BUFF(pCtx), CMAC_K1(pCtx), CMAC_BUFF(pCtx));
  266. }
  267. /* message length isn't divided by MBS_RIJ128 */
  268. else {
  269. PaddBlock(0, CMAC_BUFF(pCtx)+CMAC_INDX(pCtx), MBS_RIJ128-CMAC_INDX(pCtx));
  270. CMAC_BUFF(pCtx)[CMAC_INDX(pCtx)] = 0x80;
  271. XorBlock16(CMAC_BUFF(pCtx), CMAC_K2(pCtx), CMAC_BUFF(pCtx));
  272. }
  273. XorBlock16(CMAC_BUFF(pCtx), CMAC_MAC(pCtx), CMAC_MAC(pCtx));
  274. encoder(CMAC_MAC(pCtx), CMAC_MAC(pCtx), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox);
  275. /* return truncated DAC */
  276. CopyBlock(CMAC_MAC(pCtx), pMD, mdLen);
  277. /* re-init context */
  278. init(pCtx);
  279. return ippStsNoErr;
  280. }
  281. }
  282. /*F*
  283. // Name: ippsAES_CMACGetTag
  284. //
  285. // Purpose: computes MD value and could contunue process.
  286. //
  287. // Returns: Reason:
  288. // ippStsNullPtrErr pMD == NULL
  289. // pCtx == NULL
  290. // ippStsContextMatchErr !VALID_AESCMAC_ID()
  291. // ippStsLengthErr MBS_RIJ128 < mdLen <1
  292. // ippStsNoErr no errors
  293. //
  294. // Parameters:
  295. // pMD pointer to the output message digest
  296. // mdLen requested length of the message digest
  297. // pCtx pointer to the CMAC context
  298. //
  299. *F*/
  300. IPPFUN(IppStatus, ippsAES_CMACGetTag,(Ipp8u* pMD, int mdLen, const IppsAES_CMACState* pCtx))
  301. {
  302. /* test context pointer and ID */
  303. IPP_BAD_PTR1_RET(pCtx);
  304. /* use aligned context */
  305. pCtx = (IppsAES_CMACState*)( IPP_ALIGNED_PTR(pCtx, AESCMAC_ALIGNMENT) );
  306. IPP_BADARG_RET(!VALID_AESCMAC_ID(pCtx), ippStsContextMatchErr);
  307. /* test DAC pointer */
  308. IPP_BAD_PTR1_RET(pMD);
  309. IPP_BADARG_RET((mdLen<1)||(MBS_RIJ128<mdLen), ippStsLengthErr);
  310. {
  311. const IppsAESSpec* pAES = &CMAC_CIPHER(pCtx);
  312. /* setup encoder method */
  313. RijnCipher encoder = RIJ_ENCODER(pAES);
  314. Ipp8u locBuffer[MBS_RIJ128];
  315. Ipp8u locMac[MBS_RIJ128];
  316. CopyBlock16(CMAC_BUFF(pCtx), locBuffer);
  317. CopyBlock16(CMAC_MAC(pCtx), locMac);
  318. /* message length is divided by MBS_RIJ128 */
  319. if(MBS_RIJ128==CMAC_INDX(pCtx)) {
  320. XorBlock16(locBuffer, CMAC_K1(pCtx), locBuffer);
  321. }
  322. /* message length isn't divided by MBS_RIJ128 */
  323. else {
  324. PaddBlock(0, locBuffer+CMAC_INDX(pCtx), MBS_RIJ128-CMAC_INDX(pCtx));
  325. locBuffer[CMAC_INDX(pCtx)] = 0x80;
  326. XorBlock16(locBuffer, CMAC_K2(pCtx), locBuffer);
  327. }
  328. XorBlock16(locBuffer, locMac, locMac);
  329. encoder(locMac, locMac, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox);
  330. /* return truncated DAC */
  331. CopyBlock(locMac, pMD, mdLen);
  332. return ippStsNoErr;
  333. }
  334. }