pcphashca.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  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 "pcphash.h"
  34. #include "pcptool.h"
  35. /*F*
  36. // Name: ippsHashGetSize
  37. //
  38. // Purpose: Returns size (bytes) of IppsHashState state.
  39. //
  40. // Returns: Reason:
  41. // ippStsNullPtrErr pSize == NULL
  42. // ippStsNoErr no errors
  43. //
  44. // Parameters:
  45. // pSize pointer to state size
  46. //
  47. *F*/
  48. IPPFUN(IppStatus, ippsHashGetSize,(int* pSize))
  49. {
  50. /* test pointers */
  51. IPP_BAD_PTR1_RET(pSize);
  52. *pSize = sizeof(IppsHashState);
  53. return ippStsNoErr;
  54. }
  55. /*F*
  56. // Name: ippsHashInit
  57. //
  58. // Purpose: Init Hash state.
  59. //
  60. // Returns: Reason:
  61. // ippStsNullPtrErr pState == NULL
  62. // ippStsNotSupportedModeErr if algID is not match to supported hash alg
  63. // ippStsNoErr no errors
  64. //
  65. // Parameters:
  66. // pCtx pointer to the Hash state
  67. // algID hash alg ID
  68. //
  69. *F*/
  70. int cpReInitHash(IppsHashState* pCtx, IppHashAlgId algID)
  71. {
  72. int hashIvSize = cpHashIvSize(algID);
  73. const Ipp8u* iv = cpHashIV[algID];
  74. HASH_LENLO(pCtx) = CONST_64(0);
  75. HASH_LENHI(pCtx) = CONST_64(0);
  76. HAHS_BUFFIDX(pCtx) = 0;
  77. CopyBlock(iv, HASH_VALUE(pCtx), hashIvSize);
  78. return hashIvSize;
  79. }
  80. /*
  81. // hash alg default processing functions and opt argument
  82. */
  83. static cpHashProc cpHashProcFunc[] = {
  84. (cpHashProc)NULL,
  85. UpdateSHA1,
  86. UpdateSHA256,
  87. UpdateSHA256,
  88. UpdateSHA512,
  89. UpdateSHA512,
  90. UpdateMD5,
  91. UpdateSHA512,
  92. UpdateSHA512,
  93. };
  94. int cpInitHash(IppsHashState* pCtx, IppHashAlgId algID)
  95. {
  96. /* setup default processing function */
  97. HASH_FUNC(pCtx) = cpHashProcFunc[algID];
  98. /* setup optional agr of processing function */
  99. HASH_FUNC_PAR(pCtx) = cpHashProcFuncOpt[algID];
  100. return cpReInitHash(pCtx, algID);
  101. }
  102. IPPFUN(IppStatus, ippsHashInit,(IppsHashState* pCtx, IppHashAlgId algID))
  103. {
  104. /* get algorithm id */
  105. algID = cpValidHashAlg(algID);
  106. /* test hash alg */
  107. IPP_BADARG_RET(ippHashAlg_Unknown==algID, ippStsNotSupportedModeErr);
  108. /* test ctx pointer */
  109. IPP_BAD_PTR1_RET(pCtx);
  110. /* test hash alg */
  111. /* set ctx ID */
  112. HASH_CTX_ID(pCtx) = idCtxHash;
  113. HASH_ALG_ID(pCtx) = algID;
  114. /* init context */
  115. cpInitHash(pCtx, algID);
  116. return ippStsNoErr;
  117. }
  118. /*F*
  119. // Name: ippsHashUpdate
  120. //
  121. // Purpose: Updates intermediate hash value based on input stream.
  122. //
  123. // Returns: Reason:
  124. // ippStsNullPtrErr pCtx == NULL
  125. // ippStsNullPtrErr pSrc==0 but len!=0
  126. // ippStsContextMatchErr pCtx->idCtx != idCtxHash
  127. // ippStsLengthErr len <0
  128. // ippStsNoErr no errors
  129. //
  130. // Parameters:
  131. // pSrc pointer to the input stream
  132. // len input stream length
  133. // pCtx pointer to the Hash context
  134. //
  135. *F*/
  136. __INLINE int IsExceedMsgLen(Ipp64u maxLo, Ipp64u maxHi, Ipp64u lenLo, Ipp64u lenHi)
  137. {
  138. int isExceed = lenLo > maxLo;
  139. isExceed = (lenHi+isExceed) > maxHi;
  140. return isExceed;
  141. }
  142. IPPFUN(IppStatus, ippsHashUpdate,(const Ipp8u* pSrc, int len, IppsHashState* pCtx))
  143. {
  144. /* test state pointer and ID */
  145. IPP_BAD_PTR1_RET(pCtx);
  146. /* test the context */
  147. IPP_BADARG_RET(!HASH_VALID_ID(pCtx), ippStsContextMatchErr);
  148. /* test input length */
  149. IPP_BADARG_RET((len<0 && pSrc), ippStsLengthErr);
  150. /* test source pointer */
  151. IPP_BADARG_RET((len && !pSrc), ippStsNullPtrErr);
  152. /* handle non empty input */
  153. if(len) {
  154. const cpHashAttr* pAttr = &cpHashAlgAttr[HASH_ALG_ID(pCtx)];
  155. /* test if size of message is being processed not exceeded yet */
  156. Ipp64u lenLo = HASH_LENLO(pCtx);
  157. Ipp64u lenHi = HASH_LENHI(pCtx);
  158. lenLo += len;
  159. if(lenLo < HASH_LENLO(pCtx)) lenHi++;
  160. if(IsExceedMsgLen(pAttr->msgLenMax[0],pAttr->msgLenMax[1], lenLo,lenHi))
  161. IPP_ERROR_RET(ippStsLengthErr);
  162. else {
  163. cpHashProc hashFunc = HASH_FUNC(pCtx); /* processing function */
  164. const void* pParam = HASH_FUNC_PAR(pCtx); /* and it's addition params */
  165. int mbs = pAttr->msgBlkSize; /* data block size */
  166. /*
  167. // processing
  168. */
  169. {
  170. int procLen;
  171. /* test if internal buffer is not empty */
  172. int n = HAHS_BUFFIDX(pCtx);
  173. if(n) {
  174. procLen = IPP_MIN(len, (mbs-n));
  175. CopyBlock(pSrc, HASH_BUFF(pCtx)+n, procLen);
  176. HAHS_BUFFIDX(pCtx) = n += procLen;
  177. /* block processing */
  178. if(mbs==n) {
  179. hashFunc(HASH_VALUE(pCtx), HASH_BUFF(pCtx), mbs, pParam);
  180. HAHS_BUFFIDX(pCtx) = 0;
  181. }
  182. /* update message pointer and length */
  183. pSrc += procLen;
  184. len -= procLen;
  185. }
  186. /* main processing part */
  187. procLen = len & ~(mbs-1);
  188. if(procLen) {
  189. hashFunc(HASH_VALUE(pCtx), pSrc, procLen, pParam);
  190. pSrc += procLen;
  191. len -= procLen;
  192. }
  193. /* rest of input message */
  194. if(len) {
  195. CopyBlock(pSrc, HASH_BUFF(pCtx), len);
  196. HAHS_BUFFIDX(pCtx) += len;
  197. }
  198. }
  199. /* update length of processed message */
  200. HASH_LENLO(pCtx) = lenLo;
  201. HASH_LENHI(pCtx) = lenHi;
  202. return ippStsNoErr;
  203. }
  204. }
  205. return ippStsNoErr;
  206. }
  207. static void cpComputeDigest(Ipp8u* pHashTag, int hashTagLen, const IppsHashState* pCtx)
  208. {
  209. /* hash alg and parameters */
  210. cpHashProc hashFunc = HASH_FUNC(pCtx); /* processing function */
  211. const void* pParam = HASH_FUNC_PAR(pCtx); /* and it's addition params */
  212. /* attributes */
  213. const cpHashAttr* pAttr = &cpHashAlgAttr[HASH_ALG_ID(pCtx)];
  214. int mbs = pAttr->msgBlkSize; /* data block size */
  215. int ivSize = pAttr->ivSize; /* size of hash's IV */
  216. int msgLenRepSize = pAttr->msgLenRepSize; /* length of the message representation */
  217. /* number of bytes in context buffer */
  218. int n = HAHS_BUFFIDX(pCtx);
  219. /* buffer and it actual length */
  220. Ipp8u buffer[MBS_HASH_MAX*2];
  221. int bufferLen = n < (mbs-msgLenRepSize)? mbs : mbs*2;
  222. /* copy current hash value */
  223. cpHash hash;
  224. CopyBlock(HASH_VALUE(pCtx), hash, ivSize);
  225. /* copy of state's buffer */
  226. CopyBlock(HASH_BUFF(pCtx), buffer, bufferLen);
  227. /* end of message bit */
  228. buffer[n++] = 0x80;
  229. /* padd buffer */
  230. PaddBlock(0, buffer+n, bufferLen-n-msgLenRepSize);
  231. /* message length representation in bits (remember about big endian) */
  232. {
  233. /* convert processed message length bytes ->bits */
  234. Ipp64u lo = HASH_LENLO(pCtx);
  235. Ipp64u hi = HASH_LENHI(pCtx);
  236. hi = LSL64(hi,3) | LSR64(lo,63-3);
  237. lo = LSL64(lo,3);
  238. if(msgLenRepSize>(int)(sizeof(Ipp64u))) {
  239. #if (IPP_ENDIAN == IPP_BIG_ENDIAN)
  240. ((Ipp64u*)(buffer+bufferLen))[-2] = hi;
  241. #else
  242. ((Ipp64u*)(buffer+bufferLen))[-2] = ENDIANNESS64(hi);
  243. #endif
  244. }
  245. /* recall about MD5 specific */
  246. if(ippHashAlg_MD5!=HASH_ALG_ID(pCtx)) {
  247. #if (IPP_ENDIAN == IPP_BIG_ENDIAN)
  248. ((Ipp64u*)(buffer+bufferLen))[-1] = lo;
  249. #else
  250. ((Ipp64u*)(buffer+bufferLen))[-1] = ENDIANNESS64(lo);
  251. #endif
  252. }
  253. else {
  254. #if (IPP_ENDIAN == IPP_BIG_ENDIAN)
  255. ((Ipp64u*)(buffer+bufferLen))[-1] = ENDIANNESS64(lo);
  256. #else
  257. ((Ipp64u*)(buffer+bufferLen))[-1] = lo;
  258. #endif
  259. }
  260. }
  261. /* copmplete hash computation */
  262. hashFunc(hash, buffer, bufferLen, pParam);
  263. /* store digest into the user buffer (remember digest in big endian) */
  264. if(msgLenRepSize>(int)(sizeof(Ipp64u))) {
  265. /* ippHashAlg_SHA384, ippHashAlg_SHA512, ippHashAlg_SHA512_224 and ippHashAlg_SHA512_256 */
  266. hash[0] = ENDIANNESS64(hash[0]);
  267. hash[1] = ENDIANNESS64(hash[1]);
  268. hash[2] = ENDIANNESS64(hash[2]);
  269. hash[3] = ENDIANNESS64(hash[3]);
  270. hash[4] = ENDIANNESS64(hash[4]);
  271. hash[5] = ENDIANNESS64(hash[5]);
  272. hash[6] = ENDIANNESS64(hash[6]);
  273. hash[7] = ENDIANNESS64(hash[7]);
  274. }
  275. else if(ippHashAlg_MD5!=HASH_ALG_ID(pCtx)) {
  276. ((Ipp32u*)hash)[0] = ENDIANNESS32(((Ipp32u*)hash)[0]);
  277. ((Ipp32u*)hash)[1] = ENDIANNESS32(((Ipp32u*)hash)[1]);
  278. ((Ipp32u*)hash)[2] = ENDIANNESS32(((Ipp32u*)hash)[2]);
  279. ((Ipp32u*)hash)[3] = ENDIANNESS32(((Ipp32u*)hash)[3]);
  280. ((Ipp32u*)hash)[4] = ENDIANNESS32(((Ipp32u*)hash)[4]);
  281. if(ippHashAlg_SHA1!=HASH_ALG_ID(pCtx)) {
  282. ((Ipp32u*)hash)[5] = ENDIANNESS32(((Ipp32u*)hash)[5]);
  283. ((Ipp32u*)hash)[6] = ENDIANNESS32(((Ipp32u*)hash)[6]);
  284. ((Ipp32u*)hash)[7] = ENDIANNESS32(((Ipp32u*)hash)[7]);
  285. }
  286. }
  287. CopyBlock(hash, pHashTag, hashTagLen);
  288. }
  289. /*F*
  290. // Name: ippsHashGetTag
  291. //
  292. // Purpose: Compute digest based on current state.
  293. // Note, that futher digest update is possible
  294. //
  295. // Returns: Reason:
  296. // ippStsNullPtrErr pTag == NULL
  297. // pCtx == NULL
  298. // ippStsContextMatchErr pCtx->idCtx != idCtxHash
  299. // ippStsLengthErr hashSize < tagLen <1
  300. // ippStsNoErr no errors
  301. //
  302. // Parameters:
  303. // pTag address of the output digest
  304. // tagLen length of digest
  305. // pCtx pointer to the SHS state
  306. //
  307. *F*/
  308. IPPFUN(IppStatus, ippsHashGetTag,(Ipp8u* pTag, int tagLen, const IppsHashState* pCtx))
  309. {
  310. /* test state pointer and ID */
  311. IPP_BAD_PTR2_RET(pTag, pCtx);
  312. /* test the context */
  313. IPP_BADARG_RET(!HASH_VALID_ID(pCtx), ippStsContextMatchErr);
  314. {
  315. /* size of hash */
  316. int hashSize = cpHashAlgAttr[HASH_ALG_ID(pCtx)].hashSize;
  317. if(tagLen<1||hashSize<tagLen) IPP_ERROR_RET(ippStsLengthErr);
  318. cpComputeDigest(pTag, tagLen, pCtx);
  319. return ippStsNoErr;
  320. }
  321. }
  322. /*F*
  323. // Name: ippsHashFinal
  324. //
  325. // Purpose: Complete message digesting and return digest.
  326. //
  327. // Returns: Reason:
  328. // ippStsNullPtrErr pMD == NULL
  329. // pCtx == NULL
  330. // ippStsContextMatchErr pCtx->idCtx != idCtxHash
  331. // ippStsNoErr no errors
  332. //
  333. // Parameters:
  334. // pMD address of the output digest
  335. // pCtx pointer to the SHS state
  336. //
  337. *F*/
  338. IPPFUN(IppStatus, ippsHashFinal,(Ipp8u* pMD, IppsHashState* pCtx))
  339. {
  340. /* test state pointer and ID */
  341. IPP_BAD_PTR2_RET(pMD, pCtx);
  342. /* test the context */
  343. IPP_BADARG_RET(!HASH_VALID_ID(pCtx), ippStsContextMatchErr);
  344. {
  345. IppHashAlgId algID = HASH_ALG_ID(pCtx);
  346. int hashSize = cpHashAlgAttr[algID].hashSize;
  347. cpComputeDigest(pMD, hashSize, pCtx);
  348. cpReInitHash(pCtx, algID);
  349. return ippStsNoErr;
  350. }
  351. }
  352. /*F*
  353. // Name: ippsHashMessage
  354. //
  355. // Purpose: Hash of the whole message.
  356. //
  357. // Returns: Reason:
  358. // ippStsNullPtrErr pMD == NULL
  359. // pMsg == NULL but msgLen!=0
  360. // ippStsLengthErr msgLen <0
  361. // ippStsNotSupportedModeErr if algID is not match to supported hash alg
  362. // ippStsNoErr no errors
  363. //
  364. // Parameters:
  365. // pMsg pointer to the input message
  366. // msgLen input message length
  367. // pMD address of the output digest
  368. // algID hash alg ID
  369. //
  370. *F*/
  371. IPPFUN(IppStatus, ippsHashMessage,(const Ipp8u* pMsg, int msgLen, Ipp8u* pMD, IppHashAlgId algID))
  372. {
  373. /* get algorithm id */
  374. algID = cpValidHashAlg(algID);
  375. /* test hash alg */
  376. IPP_BADARG_RET(ippHashAlg_Unknown==algID, ippStsNotSupportedModeErr);
  377. /* test digest pointer */
  378. IPP_BAD_PTR1_RET(pMD);
  379. /* test message length */
  380. IPP_BADARG_RET((msgLen<0), ippStsLengthErr);
  381. /* test message pointer */
  382. IPP_BADARG_RET((msgLen && !pMsg), ippStsNullPtrErr);
  383. {
  384. /* processing function and parameter */
  385. cpHashProc hashFunc = cpHashProcFunc[algID];
  386. const void* pParam = cpHashProcFuncOpt[algID];
  387. /* attributes */
  388. const cpHashAttr* pAttr = &cpHashAlgAttr[algID];
  389. int mbs = pAttr->msgBlkSize; /* data block size */
  390. int ivSize = pAttr->ivSize; /* size of hash's IV */
  391. int hashSize = pAttr->hashSize; /* hash size */
  392. int msgLenRepSize = pAttr->msgLenRepSize; /* length of the message representation */
  393. /* message bitlength representation */
  394. Ipp64u msgLenBits = (Ipp64u)msgLen*8;
  395. /* length of main message part */
  396. int msgLenBlks = msgLen & (-mbs);
  397. /* rest of message length */
  398. int msgLenRest = msgLen - msgLenBlks;
  399. /* end of message buffer */
  400. Ipp8u buffer[MBS_HASH_MAX*2];
  401. int bufferLen = (msgLenRest < (mbs-msgLenRepSize))? mbs : mbs*2;
  402. /* init hash */
  403. cpHash hash;
  404. const Ipp8u* iv = cpHashIV[algID];
  405. CopyBlock(iv, hash, ivSize);
  406. /*construct last messge block(s) */
  407. #define MSG_LEN_REP (sizeof(Ipp64u))
  408. /* copy end of message */
  409. CopyBlock(pMsg+msgLen-msgLenRest, buffer, msgLenRest);
  410. /* end of message bit */
  411. buffer[msgLenRest++] = 0x80;
  412. /* padd buffer */
  413. PaddBlock(0, buffer+msgLenRest, bufferLen-msgLenRest-MSG_LEN_REP);
  414. /* copy message bitlength representation */
  415. if(ippHashAlg_MD5!=algID)
  416. msgLenBits = ENDIANNESS64(msgLenBits);
  417. ((Ipp64u*)(buffer+bufferLen))[-1] = msgLenBits;
  418. #undef MSG_LEN_REP
  419. /* message processing */
  420. if(msgLenBlks)
  421. hashFunc(hash, pMsg, msgLenBlks, pParam);
  422. hashFunc(hash, buffer, bufferLen, pParam);
  423. /* store digest into the user buffer (remember digest in big endian) */
  424. if(msgLenRepSize > (int)(sizeof(Ipp64u))) {
  425. /* ippHashAlg_SHA384, ippHashAlg_SHA512, ippHashAlg_SHA512_224 and ippHashAlg_SHA512_256 */
  426. hash[0] = ENDIANNESS64(hash[0]);
  427. hash[1] = ENDIANNESS64(hash[1]);
  428. hash[2] = ENDIANNESS64(hash[2]);
  429. hash[3] = ENDIANNESS64(hash[3]);
  430. hash[4] = ENDIANNESS64(hash[4]);
  431. hash[5] = ENDIANNESS64(hash[5]);
  432. hash[6] = ENDIANNESS64(hash[6]);
  433. hash[7] = ENDIANNESS64(hash[7]);
  434. }
  435. else if(ippHashAlg_MD5!=algID) {
  436. /* ippHashAlg_SHA1, ippHashAlg_SHA224, ippHashAlg_SHA256 and ippHashAlg_SM3 */
  437. ((Ipp32u*)hash)[0] = ENDIANNESS32(((Ipp32u*)hash)[0]);
  438. ((Ipp32u*)hash)[1] = ENDIANNESS32(((Ipp32u*)hash)[1]);
  439. ((Ipp32u*)hash)[2] = ENDIANNESS32(((Ipp32u*)hash)[2]);
  440. ((Ipp32u*)hash)[3] = ENDIANNESS32(((Ipp32u*)hash)[3]);
  441. ((Ipp32u*)hash)[4] = ENDIANNESS32(((Ipp32u*)hash)[4]);
  442. ((Ipp32u*)hash)[5] = ENDIANNESS32(((Ipp32u*)hash)[5]);
  443. ((Ipp32u*)hash)[6] = ENDIANNESS32(((Ipp32u*)hash)[6]);
  444. ((Ipp32u*)hash)[7] = ENDIANNESS32(((Ipp32u*)hash)[7]);
  445. }
  446. CopyBlock(hash, pMD, hashSize);
  447. return ippStsNoErr;
  448. }
  449. }