pcpmontgomeryca.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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 "pcpbn.h"
  34. #include "pcpmontgomery.h"
  35. #include "pcptool.h"
  36. /*F*
  37. // Name: ippsMontGetSize
  38. //
  39. // Purpose: Specifies size of buffer in bytes.
  40. //
  41. // Returns: Reason:
  42. // ippStsNullPtrErr pCtxSize==NULL
  43. // ippStsLengthErr maxLen32 < 1
  44. // maxLen32 > BITS2WORD32_SIZE(BN_MAXBITSIZE)
  45. // ippStsNoErr no errors
  46. //
  47. // Parameters:
  48. // method selected exponential method (unused parameter)
  49. // maxLen32 max modulus length (in Ipp32u chunks)
  50. // pCtxSize size of context
  51. //
  52. // Notes: Function always use method=ippBinaryMethod,
  53. // so this parameter is ignored
  54. *F*/
  55. IPPFUN(IppStatus, ippsMontGetSize, (IppsExpMethod method, cpSize maxLen32, cpSize* pCtxSize))
  56. {
  57. IPP_BAD_PTR1_RET(pCtxSize);
  58. IPP_BADARG_RET(maxLen32<1 || maxLen32>BITS2WORD32_SIZE(BN_MAXBITSIZE), ippStsLengthErr);
  59. UNREFERENCED_PARAMETER(method);
  60. {
  61. /* convert modulus length to the number of BNU_CHUNK_T */
  62. cpSize modSize = INTERNAL_BNU_LENGTH(maxLen32);
  63. *pCtxSize= sizeof(IppsMontState)
  64. + modSize*sizeof(BNU_CHUNK_T) /* modulus */
  65. + modSize*sizeof(BNU_CHUNK_T) /* identity */
  66. + modSize*sizeof(BNU_CHUNK_T) /* square R */
  67. + modSize*sizeof(BNU_CHUNK_T) /* cube R */
  68. + modSize*sizeof(BNU_CHUNK_T) /* internal buffer */
  69. + modSize*sizeof(BNU_CHUNK_T) /* internal sscm buffer */
  70. + modSize*sizeof(BNU_CHUNK_T)*2 /* internal product */
  71. + MONT_ALIGNMENT-1;
  72. return ippStsNoErr;
  73. }
  74. }
  75. /*F*
  76. // Name: ippsMontInit
  77. //
  78. // Purpose: Initializes the symbolic data structure and partitions the
  79. // specified buffer space.
  80. //
  81. // Returns: Reason:
  82. // ippStsNullPtrErr pMont==NULL
  83. // ippStsLengthErr maxLen32 < 1
  84. // maxLen32 > BITS2WORD32_SIZE(BN_MAXBITSIZE)
  85. // ippStsNoErr no errors
  86. //
  87. // Parameters:
  88. // method selected exponential method (unused parameter)
  89. // maxLen32 max modulus length (in Ipp32u chunks)
  90. // pMont pointer to Montgomery context
  91. *F*/
  92. IPPFUN(IppStatus, ippsMontInit,(IppsExpMethod method, int maxLen32, IppsMontState* pMont))
  93. {
  94. IPP_BADARG_RET(maxLen32<1 || maxLen32>BITS2WORD32_SIZE(BN_MAXBITSIZE), ippStsLengthErr);
  95. IPP_BAD_PTR1_RET(pMont);
  96. pMont = (IppsMontState*)( IPP_ALIGNED_PTR(pMont, MONT_ALIGNMENT) );
  97. UNREFERENCED_PARAMETER(method);
  98. MNT_ID(pMont) = idCtxUnknown;
  99. MNT_ROOM(pMont) = INTERNAL_BNU_LENGTH(maxLen32);
  100. MNT_SIZE(pMont) = 0;
  101. MNT_HELPER(pMont) = 0;
  102. {
  103. Ipp8u* ptr = (Ipp8u*)pMont;
  104. /* convert modulus length to the number of BNU_CHUNK_T */
  105. cpSize modSize = MNT_ROOM(pMont);
  106. /* assign internal buffers */
  107. MNT_MODULUS(pMont) = (BNU_CHUNK_T*)( ptr += sizeof(IppsMontState) );
  108. MNT_1(pMont) = (BNU_CHUNK_T*)( ptr += modSize*sizeof(BNU_CHUNK_T) );
  109. MNT_SQUARE_R(pMont)= (BNU_CHUNK_T*)( ptr += modSize*sizeof(BNU_CHUNK_T) );
  110. MNT_CUBE_R(pMont) = (BNU_CHUNK_T*)( ptr += modSize*sizeof(BNU_CHUNK_T) );
  111. MNT_TBUFFER(pMont) = (BNU_CHUNK_T*)( ptr += modSize*sizeof(BNU_CHUNK_T) );
  112. MNT_SBUFFER(pMont) = (BNU_CHUNK_T*)( ptr += modSize*sizeof(BNU_CHUNK_T) );
  113. MNT_PRODUCT(pMont) = (BNU_CHUNK_T*)( ptr += modSize*sizeof(BNU_CHUNK_T) );
  114. MNT_KBUFFER(pMont) = (BNU_CHUNK_T*)NULL;
  115. /* init internal buffers */
  116. ZEXPAND_BNU(MNT_MODULUS(pMont), 0, modSize);
  117. ZEXPAND_BNU(MNT_1(pMont), 0, modSize);
  118. ZEXPAND_BNU(MNT_SQUARE_R(pMont), 0, modSize);
  119. ZEXPAND_BNU(MNT_CUBE_R(pMont), 0, modSize);
  120. MNT_ID(pMont) = idCtxMontgomery;
  121. return ippStsNoErr;
  122. }
  123. }
  124. /*F*
  125. // Name: ippsMontSet
  126. //
  127. // Purpose: Setup modulus value
  128. //
  129. // Returns: Reason:
  130. // ippStsNullPtrErr pMont==NULL
  131. // pModulus==NULL
  132. // ippStsContextMatchErr !MNT_VALID_ID()
  133. // ippStsLengthErr len32<1
  134. // ippStsNoErr no errors
  135. //
  136. // Parameters:
  137. // pModulus pointer to the modulus buffer
  138. // len32 length of the modulus (in Ipp32u chunks).
  139. // pMont pointer to the context
  140. *F*/
  141. static BNU_CHUNK_T cpMontHelper(BNU_CHUNK_T m0)
  142. {
  143. BNU_CHUNK_T y = 1;
  144. BNU_CHUNK_T x = 2;
  145. BNU_CHUNK_T mask = 2*x-1;
  146. int i;
  147. for(i=2; i<=BNU_CHUNK_BITS; i++, x<<=1) {
  148. BNU_CHUNK_T rH, rL;
  149. MUL_AB(rH, rL, m0, y);
  150. if( x < (rL & mask) ) /* x < ((m0*y) mod (2*x)) */
  151. y+=x;
  152. mask += mask + 1;
  153. }
  154. return 0-y;
  155. }
  156. IPPFUN(IppStatus, ippsMontSet,(const Ipp32u* pModulus, cpSize len32, IppsMontState* pMont))
  157. {
  158. IPP_BAD_PTR2_RET(pModulus, pMont);
  159. pMont = (IppsMontState*)(IPP_ALIGNED_PTR((pMont), MONT_ALIGNMENT));
  160. IPP_BADARG_RET(!MNT_VALID_ID(pMont), ippStsContextMatchErr);
  161. IPP_BADARG_RET(len32<1, ippStsLengthErr);
  162. /* modulus is not an odd number */
  163. IPP_BADARG_RET((pModulus[0] & 1) == 0, ippStsBadModulusErr);
  164. IPP_BADARG_RET(MNT_ROOM(pMont)<(int)(INTERNAL_BNU_LENGTH(len32)), ippStsOutOfRangeErr);
  165. {
  166. BNU_CHUNK_T m0;
  167. cpSize len;
  168. /* fix input modulus */
  169. FIX_BNU(pModulus, len32);
  170. /* store modulus */
  171. ZEXPAND_BNU(MNT_MODULUS(pMont), 0, MNT_ROOM(pMont));
  172. COPY_BNU((Ipp32u*)(MNT_MODULUS(pMont)), pModulus, len32);
  173. /* store modulus length */
  174. len = INTERNAL_BNU_LENGTH(len32);
  175. MNT_SIZE(pMont) = len;
  176. /* pre-compute helper m0, m0*m = -1 mod R */
  177. m0 = cpMontHelper(MNT_MODULUS(pMont)[0]);
  178. MNT_HELPER(pMont) = m0;
  179. /* setup identity */
  180. ZEXPAND_BNU(MNT_1(pMont), 0, len);
  181. MNT_1(pMont)[len] = 1;
  182. cpMod_BNU(MNT_1(pMont), len+1, MNT_MODULUS(pMont), len);
  183. /* setup square */
  184. ZEXPAND_BNU(MNT_SQUARE_R(pMont), 0, len);
  185. COPY_BNU(MNT_SQUARE_R(pMont)+len, MNT_1(pMont), len);
  186. cpMod_BNU(MNT_SQUARE_R(pMont), 2*len, MNT_MODULUS(pMont), len);
  187. /* setup cube */
  188. ZEXPAND_BNU(MNT_CUBE_R(pMont), 0, len);
  189. COPY_BNU(MNT_CUBE_R(pMont)+len, MNT_SQUARE_R(pMont), len);
  190. cpMod_BNU(MNT_CUBE_R(pMont), 2*len, MNT_MODULUS(pMont), len);
  191. /* clear buffers */
  192. ZEXPAND_BNU(MNT_TBUFFER(pMont), 0, len);
  193. ZEXPAND_BNU(MNT_SBUFFER(pMont), 0, len);
  194. ZEXPAND_BNU(MNT_PRODUCT(pMont), 0, 2*len);
  195. return ippStsNoErr;
  196. }
  197. }
  198. /*F*
  199. // Name: ippsMontMul
  200. //
  201. // Purpose: Computes Montgomery modular multiplication for positive big
  202. // number integers of Montgomery form. The following pseudocode
  203. // represents this function:
  204. // r <- ( a * b * R^(-1) ) mod m
  205. //
  206. // Returns: Reason:
  207. // ippStsNoErr Returns no error.
  208. // ippStsNullPtrErr Returns an error when pointers are null.
  209. // ippStsBadArgErr Returns an error when a or b is a negative integer.
  210. // ippStsScaleRangeErr Returns an error when a or b is more than m.
  211. // ippStsOutOfRangeErr Returns an error when IppsBigNumState *r is larger than
  212. // IppsMontState *m.
  213. // ippStsContextMatchErr Returns an error when the context parameter does
  214. // not match the operation.
  215. //
  216. // Parameters:
  217. // a Multiplicand within the range [0, m - 1].
  218. // b Multiplier within the range [0, m - 1].
  219. // m Modulus.
  220. // r Montgomery multiplication result.
  221. //
  222. // Notes: The size of IppsBigNumState *r should not be less than the data
  223. // length of the modulus m.
  224. *F*/
  225. IPPFUN(IppStatus, ippsMontMul, (const IppsBigNumState* pA, const IppsBigNumState* pB, IppsMontState* pMont, IppsBigNumState* pR))
  226. {
  227. IPP_BAD_PTR4_RET(pA, pB, pMont, pR);
  228. pMont = (IppsMontState*)(IPP_ALIGNED_PTR((pMont), MONT_ALIGNMENT));
  229. pA = (IppsBigNumState*)( IPP_ALIGNED_PTR(pA, BN_ALIGNMENT) );
  230. pB = (IppsBigNumState*)( IPP_ALIGNED_PTR(pB, BN_ALIGNMENT) );
  231. pR = (IppsBigNumState*)( IPP_ALIGNED_PTR(pR, BN_ALIGNMENT) );
  232. IPP_BADARG_RET(!MNT_VALID_ID(pMont), ippStsContextMatchErr);
  233. IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr);
  234. IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr);
  235. IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr);
  236. IPP_BADARG_RET(BN_NEGATIVE(pA) || BN_NEGATIVE(pB), ippStsBadArgErr);
  237. IPP_BADARG_RET(cpCmp_BNU(BN_NUMBER(pA), BN_SIZE(pA), MNT_MODULUS(pMont), MNT_SIZE(pMont)) >= 0, ippStsScaleRangeErr);
  238. IPP_BADARG_RET(cpCmp_BNU(BN_NUMBER(pB), BN_SIZE(pB), MNT_MODULUS(pMont), MNT_SIZE(pMont)) >= 0, ippStsScaleRangeErr);
  239. IPP_BADARG_RET(BN_ROOM(pR) < MNT_SIZE(pMont), ippStsOutOfRangeErr);
  240. {
  241. BNU_CHUNK_T* pDataR = BN_NUMBER(pR);
  242. cpSize nsM = MNT_SIZE(pMont);
  243. cpMontMul_BNU(pDataR,
  244. BN_NUMBER(pA), BN_SIZE(pA),
  245. BN_NUMBER(pB), BN_SIZE(pB),
  246. MNT_MODULUS(pMont), nsM,
  247. MNT_HELPER(pMont),
  248. MNT_PRODUCT(pMont), MNT_KBUFFER(pMont));
  249. FIX_BNU(pDataR, nsM);
  250. BN_SIZE(pR) = nsM;
  251. BN_SIGN(pR) = ippBigNumPOS;
  252. return ippStsNoErr;
  253. }
  254. }